nexmo-oas-renderer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +1 -0
  3. data/.gitignore +5 -0
  4. data/CHANGELOG.md +2 -0
  5. data/CONTRIBUTING.md +46 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +183 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +73 -0
  10. data/Rakefile +2 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/exe/nexmo-oas-renderer +5 -0
  14. data/lib/nexmo/oas/engine.rb +9 -0
  15. data/lib/nexmo/oas/renderer.rb +13 -0
  16. data/lib/nexmo/oas/renderer/app.rb +116 -0
  17. data/lib/nexmo/oas/renderer/config.ru +7 -0
  18. data/lib/nexmo/oas/renderer/config/code_languages.yml +138 -0
  19. data/lib/nexmo/oas/renderer/config/dynamic_content.yml +1 -0
  20. data/lib/nexmo/oas/renderer/config/redirects.yml +8 -0
  21. data/lib/nexmo/oas/renderer/constraints/open_api.rb +76 -0
  22. data/lib/nexmo/oas/renderer/constraints/redirector.rb +17 -0
  23. data/lib/nexmo/oas/renderer/decorators/response_parser_decorator.rb +55 -0
  24. data/lib/nexmo/oas/renderer/filters/anchor.rb +17 -0
  25. data/lib/nexmo/oas/renderer/filters/audio.rb +21 -0
  26. data/lib/nexmo/oas/renderer/filters/block_escape.rb +24 -0
  27. data/lib/nexmo/oas/renderer/filters/break.rb +13 -0
  28. data/lib/nexmo/oas/renderer/filters/code.rb +64 -0
  29. data/lib/nexmo/oas/renderer/filters/code_snippet.rb +194 -0
  30. data/lib/nexmo/oas/renderer/filters/code_snippet_list.rb +33 -0
  31. data/lib/nexmo/oas/renderer/filters/code_snippets.rb +158 -0
  32. data/lib/nexmo/oas/renderer/filters/collapsible.rb +27 -0
  33. data/lib/nexmo/oas/renderer/filters/columns.rb +50 -0
  34. data/lib/nexmo/oas/renderer/filters/concept_list.rb +33 -0
  35. data/lib/nexmo/oas/renderer/filters/dynamic_content.rb +30 -0
  36. data/lib/nexmo/oas/renderer/filters/external_link.rb +32 -0
  37. data/lib/nexmo/oas/renderer/filters/frontmatter.rb +14 -0
  38. data/lib/nexmo/oas/renderer/filters/heading.rb +61 -0
  39. data/lib/nexmo/oas/renderer/filters/icon.rb +22 -0
  40. data/lib/nexmo/oas/renderer/filters/indent.rb +20 -0
  41. data/lib/nexmo/oas/renderer/filters/inline_escape.rb +17 -0
  42. data/lib/nexmo/oas/renderer/filters/js_sequence_diagram.rb +21 -0
  43. data/lib/nexmo/oas/renderer/filters/label.rb +32 -0
  44. data/lib/nexmo/oas/renderer/filters/language.rb +15 -0
  45. data/lib/nexmo/oas/renderer/filters/markdown.rb +85 -0
  46. data/lib/nexmo/oas/renderer/filters/modal.rb +41 -0
  47. data/lib/nexmo/oas/renderer/filters/partial.rb +28 -0
  48. data/lib/nexmo/oas/renderer/filters/php_inliner.rb +15 -0
  49. data/lib/nexmo/oas/renderer/filters/screenshot.rb +26 -0
  50. data/lib/nexmo/oas/renderer/filters/tab.rb +250 -0
  51. data/lib/nexmo/oas/renderer/filters/techio.rb +24 -0
  52. data/lib/nexmo/oas/renderer/filters/tooltip.rb +22 -0
  53. data/lib/nexmo/oas/renderer/filters/tutorial_link.rb +27 -0
  54. data/lib/nexmo/oas/renderer/filters/tutorials.rb +28 -0
  55. data/lib/nexmo/oas/renderer/filters/unfreeze.rb +20 -0
  56. data/lib/nexmo/oas/renderer/filters/user_personalization.rb +43 -0
  57. data/lib/nexmo/oas/renderer/helpers/navigation.rb +66 -0
  58. data/lib/nexmo/oas/renderer/helpers/render.rb +24 -0
  59. data/lib/nexmo/oas/renderer/helpers/summary.rb +30 -0
  60. data/lib/nexmo/oas/renderer/helpers/url.rb +17 -0
  61. data/lib/nexmo/oas/renderer/lib/core_ext/string.rb +14 -0
  62. data/lib/nexmo/oas/renderer/lib/redcarpet.rb +14 -0
  63. data/lib/nexmo/oas/renderer/models/code_snippet.rb +75 -0
  64. data/lib/nexmo/oas/renderer/models/tutorial.rb +83 -0
  65. data/lib/nexmo/oas/renderer/pipelines/markdown_pipeline.rb +52 -0
  66. data/lib/nexmo/oas/renderer/presenters/api_specification.rb +42 -0
  67. data/lib/nexmo/oas/renderer/presenters/groups.rb +35 -0
  68. data/lib/nexmo/oas/renderer/presenters/navigation.rb +24 -0
  69. data/lib/nexmo/oas/renderer/presenters/open_api_specification.rb +68 -0
  70. data/lib/nexmo/oas/renderer/presenters/versions.rb +40 -0
  71. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Black.woff +0 -0
  72. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Black.woff2 +0 -0
  73. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Heavy.woff +0 -0
  74. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Heavy.woff2 +0 -0
  75. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Regular.woff +0 -0
  76. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Regular.woff2 +0 -0
  77. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Semibold.woff +0 -0
  78. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Semibold.woff2 +0 -0
  79. data/lib/nexmo/oas/renderer/public/assets/images/brands/android.svg +1 -0
  80. data/lib/nexmo/oas/renderer/public/assets/images/brands/curl.svg +1 -0
  81. data/lib/nexmo/oas/renderer/public/assets/images/brands/dotnet.svg +1 -0
  82. data/lib/nexmo/oas/renderer/public/assets/images/brands/ios.svg +1 -0
  83. data/lib/nexmo/oas/renderer/public/assets/images/brands/java.svg +1 -0
  84. data/lib/nexmo/oas/renderer/public/assets/images/brands/javascript.svg +1 -0
  85. data/lib/nexmo/oas/renderer/public/assets/images/brands/node.svg +1 -0
  86. data/lib/nexmo/oas/renderer/public/assets/images/brands/php.svg +1 -0
  87. data/lib/nexmo/oas/renderer/public/assets/images/brands/python.svg +11 -0
  88. data/lib/nexmo/oas/renderer/public/assets/images/brands/ruby.svg +1 -0
  89. data/lib/nexmo/oas/renderer/public/assets/images/lost.svg +37 -0
  90. data/lib/nexmo/oas/renderer/public/assets/javascripts/components/format.js +42 -0
  91. data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.accordion.js +249 -0
  92. data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.core.js +230 -0
  93. data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.modal.js +300 -0
  94. data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.tabs.js +139 -0
  95. data/lib/nexmo/oas/renderer/public/assets/stylesheets/api.css +95 -0
  96. data/lib/nexmo/oas/renderer/public/assets/stylesheets/buttons.css +80 -0
  97. data/lib/nexmo/oas/renderer/public/assets/stylesheets/core.css +79 -0
  98. data/lib/nexmo/oas/renderer/public/assets/stylesheets/mediaqueries.css +2 -0
  99. data/lib/nexmo/oas/renderer/public/assets/stylesheets/mediaqueries.css.map +7 -0
  100. data/lib/nexmo/oas/renderer/public/assets/stylesheets/navigation.css +79 -0
  101. data/lib/nexmo/oas/renderer/public/assets/stylesheets/nexmo.css +68 -0
  102. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/api.scss +147 -0
  103. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/core.scss +133 -0
  104. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/mediaqueries.scss +48 -0
  105. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/navigation.scss +106 -0
  106. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/nexmo.scss +61 -0
  107. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/style.scss +10 -0
  108. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/syntax.scss +63 -0
  109. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/typography.scss +248 -0
  110. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/variables.scss +91 -0
  111. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/volta-templates.scss +119 -0
  112. data/lib/nexmo/oas/renderer/public/assets/stylesheets/style.css +2 -0
  113. data/lib/nexmo/oas/renderer/public/assets/stylesheets/style.css.map +7 -0
  114. data/lib/nexmo/oas/renderer/public/assets/stylesheets/syntax.css +79 -0
  115. data/lib/nexmo/oas/renderer/public/assets/stylesheets/typography.css +86 -0
  116. data/lib/nexmo/oas/renderer/public/assets/stylesheets/variables.css +2 -0
  117. data/lib/nexmo/oas/renderer/public/assets/stylesheets/variables.css.map +7 -0
  118. data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta-templates.css +2 -0
  119. data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta-templates.css.map +7 -0
  120. data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta.min.css +1 -0
  121. data/lib/nexmo/oas/renderer/public/assets/symbol/volta-icons.svg +1 -0
  122. data/lib/nexmo/oas/renderer/public/favicon.ico +0 -0
  123. data/lib/nexmo/oas/renderer/services/code_language_api.rb +98 -0
  124. data/lib/nexmo/oas/renderer/services/oas_parser.rb +21 -0
  125. data/lib/nexmo/oas/renderer/services/open_api_definition_resolver.rb +33 -0
  126. data/lib/nexmo/oas/renderer/version.rb +7 -0
  127. data/lib/nexmo/oas/renderer/views/api/show.erb +1 -0
  128. data/lib/nexmo/oas/renderer/views/code_snippets/_application_messages_dispatch.html.erb +9 -0
  129. data/lib/nexmo/oas/renderer/views/code_snippets/_application_rtc.html.erb +41 -0
  130. data/lib/nexmo/oas/renderer/views/code_snippets/_application_voice.html.erb +24 -0
  131. data/lib/nexmo/oas/renderer/views/code_snippets/_code_only.html.erb +6 -0
  132. data/lib/nexmo/oas/renderer/views/code_snippets/_configure_client.html.erb +20 -0
  133. data/lib/nexmo/oas/renderer/views/code_snippets/_dependencies.html.erb +11 -0
  134. data/lib/nexmo/oas/renderer/views/code_snippets/_write_code.html.erb +13 -0
  135. data/lib/nexmo/oas/renderer/views/code_snippets/list/plain.html.erb +10 -0
  136. data/lib/nexmo/oas/renderer/views/concepts/list/plain.html.erb +5 -0
  137. data/lib/nexmo/oas/renderer/views/layouts/_head.erb +4 -0
  138. data/lib/nexmo/oas/renderer/views/layouts/_javascripts.erb +9 -0
  139. data/lib/nexmo/oas/renderer/views/layouts/api.erb +23 -0
  140. data/lib/nexmo/oas/renderer/views/layouts/open_api.erb +10 -0
  141. data/lib/nexmo/oas/renderer/views/open_api/_callback.erb +5 -0
  142. data/lib/nexmo/oas/renderer/views/open_api/_callback_endpoint.erb +48 -0
  143. data/lib/nexmo/oas/renderer/views/open_api/_code_examples.erb +16 -0
  144. data/lib/nexmo/oas/renderer/views/open_api/_endpoint.erb +156 -0
  145. data/lib/nexmo/oas/renderer/views/open_api/_model.erb +38 -0
  146. data/lib/nexmo/oas/renderer/views/open_api/_navigation.erb +80 -0
  147. data/lib/nexmo/oas/renderer/views/open_api/_parameter_groups.erb +50 -0
  148. data/lib/nexmo/oas/renderer/views/open_api/_parameters.erb +165 -0
  149. data/lib/nexmo/oas/renderer/views/open_api/_response_description_parameters.erb +61 -0
  150. data/lib/nexmo/oas/renderer/views/open_api/_response_descriptions.erb +41 -0
  151. data/lib/nexmo/oas/renderer/views/open_api/show.erb +104 -0
  152. data/lib/nexmo/oas/renderer/views/static/404.erb +6 -0
  153. data/lib/nexmo/oas/renderer/views/tutorials/_index.html.erb +32 -0
  154. data/lib/nexmo/oas/renderer/views/tutorials/index.html.erb +7 -0
  155. data/lib/nexmo/oas/renderer/views/tutorials/list/plain.html.erb +5 -0
  156. data/lib/nexmo/oas/renderer/views/tutorials/show.html.erb +8 -0
  157. data/nexmo-oas-renderer.gemspec +49 -0
  158. 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,14 @@
1
+ require 'redcarpet'
2
+ require 'rouge'
3
+ require 'rouge/plugins/redcarpet'
4
+
5
+
6
+ module Nexmo
7
+ module OAS
8
+ module Renderer
9
+ class HTML < Redcarpet::Render::HTML
10
+ include Rouge::Plugins::Redcarpet
11
+ end
12
+ end
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