nexmo-oas-renderer 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/.env.example +1 -0
- data/.gitignore +5 -0
- data/CHANGELOG.md +2 -0
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +183 -0
- data/LICENSE.txt +21 -0
- data/README.md +73 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/nexmo-oas-renderer +5 -0
- data/lib/nexmo/oas/engine.rb +9 -0
- data/lib/nexmo/oas/renderer.rb +13 -0
- data/lib/nexmo/oas/renderer/app.rb +116 -0
- data/lib/nexmo/oas/renderer/config.ru +7 -0
- data/lib/nexmo/oas/renderer/config/code_languages.yml +138 -0
- data/lib/nexmo/oas/renderer/config/dynamic_content.yml +1 -0
- data/lib/nexmo/oas/renderer/config/redirects.yml +8 -0
- data/lib/nexmo/oas/renderer/constraints/open_api.rb +76 -0
- data/lib/nexmo/oas/renderer/constraints/redirector.rb +17 -0
- data/lib/nexmo/oas/renderer/decorators/response_parser_decorator.rb +55 -0
- data/lib/nexmo/oas/renderer/filters/anchor.rb +17 -0
- data/lib/nexmo/oas/renderer/filters/audio.rb +21 -0
- data/lib/nexmo/oas/renderer/filters/block_escape.rb +24 -0
- data/lib/nexmo/oas/renderer/filters/break.rb +13 -0
- data/lib/nexmo/oas/renderer/filters/code.rb +64 -0
- data/lib/nexmo/oas/renderer/filters/code_snippet.rb +194 -0
- data/lib/nexmo/oas/renderer/filters/code_snippet_list.rb +33 -0
- data/lib/nexmo/oas/renderer/filters/code_snippets.rb +158 -0
- data/lib/nexmo/oas/renderer/filters/collapsible.rb +27 -0
- data/lib/nexmo/oas/renderer/filters/columns.rb +50 -0
- data/lib/nexmo/oas/renderer/filters/concept_list.rb +33 -0
- data/lib/nexmo/oas/renderer/filters/dynamic_content.rb +30 -0
- data/lib/nexmo/oas/renderer/filters/external_link.rb +32 -0
- data/lib/nexmo/oas/renderer/filters/frontmatter.rb +14 -0
- data/lib/nexmo/oas/renderer/filters/heading.rb +61 -0
- data/lib/nexmo/oas/renderer/filters/icon.rb +22 -0
- data/lib/nexmo/oas/renderer/filters/indent.rb +20 -0
- data/lib/nexmo/oas/renderer/filters/inline_escape.rb +17 -0
- data/lib/nexmo/oas/renderer/filters/js_sequence_diagram.rb +21 -0
- data/lib/nexmo/oas/renderer/filters/label.rb +32 -0
- data/lib/nexmo/oas/renderer/filters/language.rb +15 -0
- data/lib/nexmo/oas/renderer/filters/markdown.rb +85 -0
- data/lib/nexmo/oas/renderer/filters/modal.rb +41 -0
- data/lib/nexmo/oas/renderer/filters/partial.rb +28 -0
- data/lib/nexmo/oas/renderer/filters/php_inliner.rb +15 -0
- data/lib/nexmo/oas/renderer/filters/screenshot.rb +26 -0
- data/lib/nexmo/oas/renderer/filters/tab.rb +250 -0
- data/lib/nexmo/oas/renderer/filters/techio.rb +24 -0
- data/lib/nexmo/oas/renderer/filters/tooltip.rb +22 -0
- data/lib/nexmo/oas/renderer/filters/tutorial_link.rb +27 -0
- data/lib/nexmo/oas/renderer/filters/tutorials.rb +28 -0
- data/lib/nexmo/oas/renderer/filters/unfreeze.rb +20 -0
- data/lib/nexmo/oas/renderer/filters/user_personalization.rb +43 -0
- data/lib/nexmo/oas/renderer/helpers/navigation.rb +66 -0
- data/lib/nexmo/oas/renderer/helpers/render.rb +24 -0
- data/lib/nexmo/oas/renderer/helpers/summary.rb +30 -0
- data/lib/nexmo/oas/renderer/helpers/url.rb +17 -0
- data/lib/nexmo/oas/renderer/lib/core_ext/string.rb +14 -0
- data/lib/nexmo/oas/renderer/lib/redcarpet.rb +14 -0
- data/lib/nexmo/oas/renderer/models/code_snippet.rb +75 -0
- data/lib/nexmo/oas/renderer/models/tutorial.rb +83 -0
- data/lib/nexmo/oas/renderer/pipelines/markdown_pipeline.rb +52 -0
- data/lib/nexmo/oas/renderer/presenters/api_specification.rb +42 -0
- data/lib/nexmo/oas/renderer/presenters/groups.rb +35 -0
- data/lib/nexmo/oas/renderer/presenters/navigation.rb +24 -0
- data/lib/nexmo/oas/renderer/presenters/open_api_specification.rb +68 -0
- data/lib/nexmo/oas/renderer/presenters/versions.rb +40 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Black.woff +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Black.woff2 +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Heavy.woff +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Heavy.woff2 +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Regular.woff +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Regular.woff2 +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Semibold.woff +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Semibold.woff2 +0 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/android.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/curl.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/dotnet.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/ios.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/java.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/javascript.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/node.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/php.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/python.svg +11 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/ruby.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/lost.svg +37 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/components/format.js +42 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.accordion.js +249 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.core.js +230 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.modal.js +300 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.tabs.js +139 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/api.css +95 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/buttons.css +80 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/core.css +79 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/mediaqueries.css +2 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/mediaqueries.css.map +7 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/navigation.css +79 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/nexmo.css +68 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/api.scss +147 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/core.scss +133 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/mediaqueries.scss +48 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/navigation.scss +106 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/nexmo.scss +61 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/style.scss +10 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/syntax.scss +63 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/typography.scss +248 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/variables.scss +91 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/volta-templates.scss +119 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/style.css +2 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/style.css.map +7 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/syntax.css +79 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/typography.css +86 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/variables.css +2 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/variables.css.map +7 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta-templates.css +2 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta-templates.css.map +7 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta.min.css +1 -0
- data/lib/nexmo/oas/renderer/public/assets/symbol/volta-icons.svg +1 -0
- data/lib/nexmo/oas/renderer/public/favicon.ico +0 -0
- data/lib/nexmo/oas/renderer/services/code_language_api.rb +98 -0
- data/lib/nexmo/oas/renderer/services/oas_parser.rb +21 -0
- data/lib/nexmo/oas/renderer/services/open_api_definition_resolver.rb +33 -0
- data/lib/nexmo/oas/renderer/version.rb +7 -0
- data/lib/nexmo/oas/renderer/views/api/show.erb +1 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_application_messages_dispatch.html.erb +9 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_application_rtc.html.erb +41 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_application_voice.html.erb +24 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_code_only.html.erb +6 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_configure_client.html.erb +20 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_dependencies.html.erb +11 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_write_code.html.erb +13 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/list/plain.html.erb +10 -0
- data/lib/nexmo/oas/renderer/views/concepts/list/plain.html.erb +5 -0
- data/lib/nexmo/oas/renderer/views/layouts/_head.erb +4 -0
- data/lib/nexmo/oas/renderer/views/layouts/_javascripts.erb +9 -0
- data/lib/nexmo/oas/renderer/views/layouts/api.erb +23 -0
- data/lib/nexmo/oas/renderer/views/layouts/open_api.erb +10 -0
- data/lib/nexmo/oas/renderer/views/open_api/_callback.erb +5 -0
- data/lib/nexmo/oas/renderer/views/open_api/_callback_endpoint.erb +48 -0
- data/lib/nexmo/oas/renderer/views/open_api/_code_examples.erb +16 -0
- data/lib/nexmo/oas/renderer/views/open_api/_endpoint.erb +156 -0
- data/lib/nexmo/oas/renderer/views/open_api/_model.erb +38 -0
- data/lib/nexmo/oas/renderer/views/open_api/_navigation.erb +80 -0
- data/lib/nexmo/oas/renderer/views/open_api/_parameter_groups.erb +50 -0
- data/lib/nexmo/oas/renderer/views/open_api/_parameters.erb +165 -0
- data/lib/nexmo/oas/renderer/views/open_api/_response_description_parameters.erb +61 -0
- data/lib/nexmo/oas/renderer/views/open_api/_response_descriptions.erb +41 -0
- data/lib/nexmo/oas/renderer/views/open_api/show.erb +104 -0
- data/lib/nexmo/oas/renderer/views/static/404.erb +6 -0
- data/lib/nexmo/oas/renderer/views/tutorials/_index.html.erb +32 -0
- data/lib/nexmo/oas/renderer/views/tutorials/index.html.erb +7 -0
- data/lib/nexmo/oas/renderer/views/tutorials/list/plain.html.erb +5 -0
- data/lib/nexmo/oas/renderer/views/tutorials/show.html.erb +8 -0
- data/nexmo-oas-renderer.gemspec +49 -0
- metadata +399 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module OAS
|
3
|
+
module Renderer
|
4
|
+
module Helpers
|
5
|
+
module Navigation
|
6
|
+
|
7
|
+
HEADING_TAG_DEPTHS = {
|
8
|
+
'h0' => 0,
|
9
|
+
'h1' => 1,
|
10
|
+
'h2' => 2,
|
11
|
+
'h3' => 3,
|
12
|
+
'h4' => 4,
|
13
|
+
'h5' => 5,
|
14
|
+
'h6' => 6,
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def navigation_from_content(content:, title: nil)
|
18
|
+
content = "<h0 class='injected'>#{title}</h0>\n" + content if title
|
19
|
+
document = build_document(content)
|
20
|
+
|
21
|
+
nodes = ['<ul class="Vlt-sidemenu Vlt-sidemenu--rounded Vlt-sidemenu--flat navigation js-navigation">']
|
22
|
+
last_node = nil
|
23
|
+
|
24
|
+
document.css('.reveal').remove
|
25
|
+
|
26
|
+
document.css('h0,h2,h3,h4,h5,h6').each do |heading|
|
27
|
+
# If it's a header within tabbed content (including Code Snippets) we don't want to treat
|
28
|
+
# the header as a navigation item in the sidebar
|
29
|
+
next unless heading.ancestors('.Vlt-tabs').empty?
|
30
|
+
|
31
|
+
# Same with callouts
|
32
|
+
next unless heading.ancestors('.Vlt-callout').empty?
|
33
|
+
|
34
|
+
if last_node.nil? || heading.name == last_node.name
|
35
|
+
# Do nothing (cleaner than adding wrapping further conditions)
|
36
|
+
elsif heading.name >= last_node.name # e.g. h2 -> h3
|
37
|
+
nodes << '<ul>'
|
38
|
+
else # e.g. h4 -> h2
|
39
|
+
(HEADING_TAG_DEPTHS[last_node.name] - HEADING_TAG_DEPTHS[heading.name]).times do
|
40
|
+
nodes << '</li></ul>'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
nodes << <<~HEREDOC
|
45
|
+
<li>
|
46
|
+
<a class="Vlt-sidemenu__link" href="##{heading.attributes['id']}" data-scrollspy-id="#{heading['data-id']}">
|
47
|
+
#{heading.text}
|
48
|
+
</a>
|
49
|
+
HEREDOC
|
50
|
+
last_node = heading
|
51
|
+
end
|
52
|
+
nodes << '</li></ul>'
|
53
|
+
nodes.join("\n").html_safe
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def build_document(content)
|
59
|
+
Nokogiri::HTML::DocumentFragment.parse(content)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module OAS
|
3
|
+
module Renderer
|
4
|
+
module Helpers
|
5
|
+
module Render
|
6
|
+
|
7
|
+
def find_template(views, name, engine, &block)
|
8
|
+
Array(views).each do |v|
|
9
|
+
super(v, name, engine, &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(*args)
|
14
|
+
if args.length > 2
|
15
|
+
super
|
16
|
+
else
|
17
|
+
ApplicationController.renderer.render(*args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module OAS
|
3
|
+
module Renderer
|
4
|
+
module Helpers
|
5
|
+
module Summary
|
6
|
+
def normalize_summary_title(summary, operation_id)
|
7
|
+
# return summary early if provided
|
8
|
+
return summary unless summary.nil?
|
9
|
+
|
10
|
+
# If the operation ID is camelCase,
|
11
|
+
if operation_id.match?(/^[a-zA-Z]\w+(?:[A-Z]\w+){1,}/x)
|
12
|
+
# Use the rails `.underscore` method to convert someString to some_string
|
13
|
+
operation_id = operation_id.underscore
|
14
|
+
end
|
15
|
+
|
16
|
+
# Replace snake_case and kebab-case with spaces and titelize the string
|
17
|
+
operation_id = operation_id.gsub(/(_|-)/, ' ').titleize
|
18
|
+
|
19
|
+
# Some terms need to be capitalised all the time
|
20
|
+
uppercase_array = ['SMS', 'DTMF']
|
21
|
+
operation_id.split(' ').map do |c|
|
22
|
+
next c.upcase if uppercase_array.include?(c.upcase)
|
23
|
+
c
|
24
|
+
end.join(' ')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module OAS
|
3
|
+
module Renderer
|
4
|
+
module Helpers
|
5
|
+
module URL
|
6
|
+
def parameter_values(enum)
|
7
|
+
enum.map { |value| "<code>#{value}</code>" }.to_sentence(last_word_connector: ' or ', two_words_connector: ' or ')
|
8
|
+
end
|
9
|
+
|
10
|
+
def canonical_path
|
11
|
+
request.path.chomp("/#{params[:code_language]}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class String
|
2
|
+
def render_markdown(options = {})
|
3
|
+
Nexmo::OAS::Renderer::MarkdownPipeline.new(options).call(self).html_safe
|
4
|
+
end
|
5
|
+
|
6
|
+
def unindent
|
7
|
+
indent = squeeze("\n").lines.map { |line| line.index(/[^\s]/) }.compact.min || 0
|
8
|
+
gsub(/^[[:blank:]]{#{indent}}/, '')
|
9
|
+
end
|
10
|
+
|
11
|
+
def unindent!
|
12
|
+
replace(unindent)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module OAS
|
3
|
+
module Renderer
|
4
|
+
module Models
|
5
|
+
class CodeSnippet
|
6
|
+
include ActiveModel::Model
|
7
|
+
attr_accessor :title, :product, :category, :navigation_weight, :document_path, :url
|
8
|
+
|
9
|
+
def self.by_product(product)
|
10
|
+
all.select do |block|
|
11
|
+
block.product == product
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.all
|
16
|
+
blocks = files.map do |document_path|
|
17
|
+
document = File.read(document_path)
|
18
|
+
product = extract_product(document_path)
|
19
|
+
|
20
|
+
frontmatter = YAML.safe_load(document)
|
21
|
+
|
22
|
+
new({
|
23
|
+
title: frontmatter['title'],
|
24
|
+
navigation_weight: frontmatter['navigation_weight'] || 999,
|
25
|
+
product: product,
|
26
|
+
document_path: document_path,
|
27
|
+
category: extract_category(document_path),
|
28
|
+
url: generate_url(document_path),
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
blocks.sort_by(&:navigation_weight)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.generate_url(path)
|
36
|
+
'/' + path.gsub("#{origin}/", '').gsub('.md', '')
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.extract_product(path)
|
40
|
+
# Remove the prefix
|
41
|
+
path = path.gsub!("#{origin}/", '')
|
42
|
+
|
43
|
+
# Each file is in the form code-snippets/<title>.md, so let's remove everything after code-snippets
|
44
|
+
path = path.gsub(%r{/code-snippets/.*}, '')
|
45
|
+
|
46
|
+
path
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.extract_category(path)
|
50
|
+
# Remove the prefix
|
51
|
+
path = path.gsub("#{origin}/", '')
|
52
|
+
|
53
|
+
# Each file is in the form code-snippets/<title>.md, so let's capture everything after code-snippets
|
54
|
+
path = path.gsub(%r{.*/code-snippets/(.*)$}, '\1')
|
55
|
+
|
56
|
+
parts = path.split('/')
|
57
|
+
parts = parts[0...-1]
|
58
|
+
|
59
|
+
return nil if parts.empty?
|
60
|
+
|
61
|
+
parts.join('/').tr('-', ' ').humanize
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.files
|
65
|
+
Dir.glob("#{origin}/**/code-snippets/**/*.md")
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.origin
|
69
|
+
"_documentation"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module OAS
|
3
|
+
module Renderer
|
4
|
+
module Models
|
5
|
+
class Tutorial
|
6
|
+
|
7
|
+
include ActiveModel::Model
|
8
|
+
attr_accessor :title, :description, :external_link, :products, :document_path, :languages
|
9
|
+
|
10
|
+
def body
|
11
|
+
File.read(document_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def path
|
15
|
+
return external_link if external_link
|
16
|
+
"/tutorials/#{document_path.relative_path_from(self.class.origin)}".gsub('.md', '')
|
17
|
+
end
|
18
|
+
|
19
|
+
def subtitle
|
20
|
+
normalized_products = products.map do |product|
|
21
|
+
normalise_product_title(product)
|
22
|
+
end
|
23
|
+
|
24
|
+
normalized_products.sort.to_sentence
|
25
|
+
end
|
26
|
+
|
27
|
+
def normalise_product_title(product)
|
28
|
+
return 'SMS' if product == 'messaging/sms'
|
29
|
+
return 'Voice' if product == 'voice/voice-api'
|
30
|
+
return 'Number Insight' if product == 'number-insight'
|
31
|
+
return 'Messages' if product == 'messages'
|
32
|
+
return 'Dispatch' if product == 'dispatch'
|
33
|
+
return 'Client SDK' if product == 'client-sdk'
|
34
|
+
product.camelcase
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.by_product(product, tutorials = [])
|
38
|
+
tutorials = all if tutorials.empty?
|
39
|
+
tutorials.select do |tutorial|
|
40
|
+
tutorial.products.include? product
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.by_language(language, tutorials = [])
|
45
|
+
language = language.downcase
|
46
|
+
tutorials = all if tutorials.empty?
|
47
|
+
|
48
|
+
tutorials.select do |tutorial|
|
49
|
+
tutorial.languages.map(&:downcase).include? language
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.origin
|
54
|
+
Pathname.new("_tutorials")
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.all
|
58
|
+
files.map do |document_path|
|
59
|
+
document_path = Pathname.new(document_path)
|
60
|
+
document = File.read(document_path)
|
61
|
+
frontmatter = YAML.safe_load(document)
|
62
|
+
|
63
|
+
new({
|
64
|
+
title: frontmatter['title'],
|
65
|
+
description: frontmatter['description'],
|
66
|
+
external_link: frontmatter['external_link'],
|
67
|
+
products: frontmatter['products'].split(',').map(&:strip),
|
68
|
+
languages: frontmatter['languages'] || [],
|
69
|
+
document_path: document_path,
|
70
|
+
})
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
private_class_method def self.files
|
77
|
+
Dir.glob("#{origin}/**/*.md")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'banzai'
|
2
|
+
|
3
|
+
Dir[File.join(__dir__, '../filters', '*.rb')].each { |f| require_relative f }
|
4
|
+
|
5
|
+
module Nexmo
|
6
|
+
module OAS
|
7
|
+
module Renderer
|
8
|
+
class MarkdownPipeline < Banzai::Pipeline
|
9
|
+
def initialize(options = {})
|
10
|
+
super(
|
11
|
+
# As Markdown
|
12
|
+
Filters::Frontmatter,
|
13
|
+
Filters::PHPInliner,
|
14
|
+
Filters::InlineEscape,
|
15
|
+
Filters::BlockEscape,
|
16
|
+
Filters::Screenshot,
|
17
|
+
Filters::Anchor,
|
18
|
+
Filters::Audio,
|
19
|
+
Filters::DynamicContent,
|
20
|
+
Filters::Tooltip,
|
21
|
+
Filters::Collapsible,
|
22
|
+
Filters::Tab.new(options),
|
23
|
+
Filters::CodeSnippets.new(options),
|
24
|
+
Filters::CodeSnippet.new(options),
|
25
|
+
Filters::Code,
|
26
|
+
Filters::Indent,
|
27
|
+
Filters::Modal,
|
28
|
+
Filters::JsSequenceDiagram,
|
29
|
+
Filters::Partial.new(options),
|
30
|
+
Filters::Techio,
|
31
|
+
Filters::Tutorials,
|
32
|
+
Filters::CodeSnippetList,
|
33
|
+
Filters::ConceptList,
|
34
|
+
Filters::Language,
|
35
|
+
Filters::Columns,
|
36
|
+
Filters::Markdown.new(options),
|
37
|
+
|
38
|
+
# As HTML
|
39
|
+
Filters::UserPersonalization.new(options),
|
40
|
+
Filters::Heading,
|
41
|
+
Filters::Label.new(options),
|
42
|
+
Filters::Break,
|
43
|
+
Filters::Unfreeze,
|
44
|
+
Filters::Icon,
|
45
|
+
Filters::ExternalLink,
|
46
|
+
Filters::TutorialLink
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module OAS
|
3
|
+
module Renderer
|
4
|
+
module Presenters
|
5
|
+
class ApiSpecification
|
6
|
+
|
7
|
+
def initialize(document_name:)
|
8
|
+
@document_name = document_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def side_navigation
|
12
|
+
"api/#{@document_name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def document_path
|
16
|
+
"_api/#{@document_name}.md"
|
17
|
+
end
|
18
|
+
|
19
|
+
def document
|
20
|
+
@document ||= File.read(document_path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def frontmatter
|
24
|
+
@frontmatter ||= YAML.safe_load(document)
|
25
|
+
end
|
26
|
+
|
27
|
+
def side_navigation_title
|
28
|
+
@side_navigation_title ||= frontmatter.fetch('api')
|
29
|
+
end
|
30
|
+
|
31
|
+
def document_title
|
32
|
+
@document_title ||= "#{side_navigation_title} > #{frontmatter.fetch('title')}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def content
|
36
|
+
@content ||= MarkdownPipeline.new.call(document)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module OAS
|
3
|
+
module Renderer
|
4
|
+
module Presenters
|
5
|
+
class Groups
|
6
|
+
def initialize(definition)
|
7
|
+
@definition = definition
|
8
|
+
end
|
9
|
+
|
10
|
+
def groups
|
11
|
+
tags = @definition.raw['tags']
|
12
|
+
# For now we only use the first tag in the list as an equivalent for the old x-group functionality
|
13
|
+
@groups = @definition.endpoints.group_by do |endpoint|
|
14
|
+
next nil unless tags
|
15
|
+
endpoint.raw['tags']&.first
|
16
|
+
end
|
17
|
+
|
18
|
+
# We want to use the order in which the tags are defined in the definition, so iterate over the tags
|
19
|
+
# and store the index against the tag name. We'll use this later for sorting
|
20
|
+
ordering = {}
|
21
|
+
tags&.each_with_index do |tag, index|
|
22
|
+
ordering[tag['name'].capitalize] = index
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sort by the order in which they're defined in the definition
|
26
|
+
@groups = @groups.sort_by do |name, _|
|
27
|
+
next -1 if name.nil?
|
28
|
+
ordering[name.capitalize] || 999
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|