nexmo-oas-renderer 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile.lock +16 -7
  4. data/lib/nexmo/oas/renderer/app.rb +2 -4
  5. data/lib/nexmo/oas/renderer/presenters/api_specification.rb +1 -1
  6. data/lib/nexmo/oas/renderer/presenters/open_api_specification.rb +1 -1
  7. data/lib/nexmo/oas/renderer/public/assets/stylesheets/nexmo-oas-renderer.css +1 -1
  8. data/lib/nexmo/oas/renderer/version.rb +1 -1
  9. data/lib/nexmo/oas/renderer/views/open_api/_model.erb +1 -1
  10. data/lib/nexmo/oas/renderer/views/open_api/_parameter_groups.erb +7 -37
  11. data/lib/nexmo/oas/renderer/views/open_api/_tabbed_parameters.erb +53 -0
  12. data/nexmo-oas-renderer.gemspec +1 -0
  13. metadata +17 -53
  14. data/lib/nexmo/oas/renderer/filters/anchor.rb +0 -17
  15. data/lib/nexmo/oas/renderer/filters/audio.rb +0 -21
  16. data/lib/nexmo/oas/renderer/filters/block_escape.rb +0 -24
  17. data/lib/nexmo/oas/renderer/filters/break.rb +0 -13
  18. data/lib/nexmo/oas/renderer/filters/code.rb +0 -64
  19. data/lib/nexmo/oas/renderer/filters/code_snippet.rb +0 -194
  20. data/lib/nexmo/oas/renderer/filters/code_snippet_list.rb +0 -33
  21. data/lib/nexmo/oas/renderer/filters/code_snippets.rb +0 -158
  22. data/lib/nexmo/oas/renderer/filters/collapsible.rb +0 -27
  23. data/lib/nexmo/oas/renderer/filters/columns.rb +0 -50
  24. data/lib/nexmo/oas/renderer/filters/concept_list.rb +0 -33
  25. data/lib/nexmo/oas/renderer/filters/dynamic_content.rb +0 -30
  26. data/lib/nexmo/oas/renderer/filters/external_link.rb +0 -32
  27. data/lib/nexmo/oas/renderer/filters/frontmatter.rb +0 -14
  28. data/lib/nexmo/oas/renderer/filters/heading.rb +0 -61
  29. data/lib/nexmo/oas/renderer/filters/icon.rb +0 -22
  30. data/lib/nexmo/oas/renderer/filters/indent.rb +0 -20
  31. data/lib/nexmo/oas/renderer/filters/inline_escape.rb +0 -17
  32. data/lib/nexmo/oas/renderer/filters/js_sequence_diagram.rb +0 -21
  33. data/lib/nexmo/oas/renderer/filters/label.rb +0 -32
  34. data/lib/nexmo/oas/renderer/filters/language.rb +0 -15
  35. data/lib/nexmo/oas/renderer/filters/markdown.rb +0 -85
  36. data/lib/nexmo/oas/renderer/filters/modal.rb +0 -41
  37. data/lib/nexmo/oas/renderer/filters/partial.rb +0 -28
  38. data/lib/nexmo/oas/renderer/filters/php_inliner.rb +0 -15
  39. data/lib/nexmo/oas/renderer/filters/screenshot.rb +0 -26
  40. data/lib/nexmo/oas/renderer/filters/tab.rb +0 -250
  41. data/lib/nexmo/oas/renderer/filters/techio.rb +0 -24
  42. data/lib/nexmo/oas/renderer/filters/tooltip.rb +0 -22
  43. data/lib/nexmo/oas/renderer/filters/tutorial_link.rb +0 -27
  44. data/lib/nexmo/oas/renderer/filters/tutorials.rb +0 -28
  45. data/lib/nexmo/oas/renderer/filters/unfreeze.rb +0 -20
  46. data/lib/nexmo/oas/renderer/filters/user_personalization.rb +0 -43
  47. data/lib/nexmo/oas/renderer/lib/core_ext/string.rb +0 -14
  48. data/lib/nexmo/oas/renderer/lib/redcarpet.rb +0 -14
  49. data/lib/nexmo/oas/renderer/models/code_snippet.rb +0 -75
  50. data/lib/nexmo/oas/renderer/models/tutorial.rb +0 -83
  51. data/lib/nexmo/oas/renderer/pipelines/markdown_pipeline.rb +0 -52
  52. data/lib/nexmo/oas/renderer/services/code_language_api.rb +0 -98
  53. data/lib/nexmo/oas/renderer/views/code_snippets/_application_messages_dispatch.html.erb +0 -9
  54. data/lib/nexmo/oas/renderer/views/code_snippets/_application_rtc.html.erb +0 -41
  55. data/lib/nexmo/oas/renderer/views/code_snippets/_application_voice.html.erb +0 -24
  56. data/lib/nexmo/oas/renderer/views/code_snippets/_code_only.html.erb +0 -6
  57. data/lib/nexmo/oas/renderer/views/code_snippets/_configure_client.html.erb +0 -20
  58. data/lib/nexmo/oas/renderer/views/code_snippets/_dependencies.html.erb +0 -11
  59. data/lib/nexmo/oas/renderer/views/code_snippets/_write_code.html.erb +0 -13
  60. data/lib/nexmo/oas/renderer/views/code_snippets/list/plain.html.erb +0 -10
  61. data/lib/nexmo/oas/renderer/views/tutorials/_index.html.erb +0 -32
  62. data/lib/nexmo/oas/renderer/views/tutorials/index.html.erb +0 -7
  63. data/lib/nexmo/oas/renderer/views/tutorials/list/plain.html.erb +0 -5
  64. data/lib/nexmo/oas/renderer/views/tutorials/show.html.erb +0 -8
@@ -1,13 +0,0 @@
1
- module Nexmo
2
- module OAS
3
- module Renderer
4
- module Filters
5
- class Break < Banzai::Filter
6
- def call(input)
7
- input.gsub('§', '<br>')
8
- end
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,64 +0,0 @@
1
- module Nexmo
2
- module OAS
3
- module Renderer
4
- module Filters
5
- class Code < Banzai::Filter
6
- def call(input)
7
- input.gsub(/(?!.*snippet)```code(.+?)```/m) do |_s|
8
- config = YAML.safe_load($1)
9
-
10
- if config['config']
11
- configs = YAML.load_file("#{API.root}/config/code_examples.yml")
12
- config = config['config'].split('.').inject(configs) { |h, k| h[k] }
13
- end
14
-
15
- code = File.read("#{API.root}/#{config['source']}")
16
- language = File.extname("#{API.root}/#{config['source']}")[1..-1]
17
- lexer = language_to_lexer(language)
18
-
19
- total_lines = code.lines.count
20
-
21
- # Minus one since lines are not zero-indexed
22
- from_line = (config['from_line'] || 1) - 1
23
- to_line = (config['to_line'] || total_lines) - 1
24
-
25
- code = code.lines[from_line..to_line].join
26
- code.unindent! if config['unindent']
27
-
28
- highlighted_source = highlight(code, lexer)
29
-
30
- <<~HEREDOC
31
- <pre class="highlight #{lexer.tag}"><code>#{highlighted_source}</code></pre>
32
- HEREDOC
33
- end
34
- end
35
-
36
- private
37
-
38
- def highlight(source, lexer)
39
- formatter = Rouge::Formatters::HTML.new
40
- formatter.format(lexer.lex(source))
41
- end
42
-
43
- def language_to_lexer_name(language)
44
- if language_configuration[language]
45
- language_configuration[language]['lexer']
46
- else
47
- language
48
- end
49
- end
50
-
51
- def language_to_lexer(language)
52
- language = language_to_lexer_name(language)
53
- return Rouge::Lexers::PHP.new({ start_inline: true }) if language == 'php'
54
- Rouge::Lexer.find(language.downcase) || Rouge::Lexer.find('text')
55
- end
56
-
57
- def language_configuration
58
- @language_configuration ||= YAML.load_file("#{API.root}/config/code_languages.yml")
59
- end
60
- end
61
- end
62
- end
63
- end
64
- end
@@ -1,194 +0,0 @@
1
- require 'octicons_helper'
2
-
3
- module Nexmo
4
- module OAS
5
- module Renderer
6
- module Filters
7
- class CodeSnippet < Banzai::Filter
8
- include OcticonsHelper
9
-
10
- def call(input)
11
- input.gsub(/```single_code_snippet(.+?)```/m) do |_s|
12
- config = YAML.safe_load($1)
13
-
14
- @renderer = get_renderer(config['language'])
15
-
16
- lexer = CodeLanguageAPI.find(config['language']).lexer
17
- lang = config['title'].delete('.')
18
-
19
- application_html = generate_application_block(config['application'])
20
-
21
- # Read the client
22
- if config['client']
23
- highlighted_client_source = generate_code_block(config['language'], config['client'], config['unindent'])
24
- end
25
-
26
- # Read the code
27
- highlighted_code_source = generate_code_block(config['language'], config['code'], config['unindent'])
28
-
29
- dependency_html = ''
30
- if config['dependencies']
31
- dependency_html = generate_dependencies(lexer.tag, config['dependencies'])
32
- end
33
-
34
- source_url = generate_source_url(config['code'])
35
-
36
- client_html = ''
37
- if highlighted_client_source
38
- client_url = generate_source_url(config['client'])
39
- id = SecureRandom.hex
40
- create_instructions = @renderer.create_instructions(config['file_name']).render_markdown
41
- erb = File.read("#{API.root}/views/code_snippets/_configure_client.html.erb")
42
- client_html = ERB.new(erb).result(binding)
43
- end
44
-
45
- add_instructions = @renderer.add_instructions(config['file_name']).render_markdown
46
- if config['code_only']
47
- erb = File.read("#{API.root}/views/code_snippets/_code_only.html.erb")
48
- else
49
- erb = File.read("#{API.root}/views/code_snippets/_write_code.html.erb")
50
- end
51
-
52
- code_html = ERB.new(erb).result(binding)
53
-
54
- return code_html if config['code_only']
55
-
56
- config['run_command'] = config['run_command'].gsub('{filename}', config['file_name']) if config['run_command']
57
- run_html = @renderer.run_command(config['run_command'], config['file_name'], config['code']['source']).to_s
58
-
59
- prereqs = (application_html + dependency_html + client_html).strip
60
- prereqs = "<h2>Prerequisites</h2>#{prereqs}" unless prereqs.empty?
61
- prereqs + code_html + run_html
62
- end
63
- end
64
-
65
- private
66
-
67
- def highlight(source, lexer)
68
- formatter = Rouge::Formatters::HTML.new
69
- formatter.format(lexer.lex(source))
70
- end
71
-
72
- def generate_code_block(language, input, unindent)
73
- filename = input['source']
74
- return '' unless input
75
- raise "CodeSnippetFilter - Could not load #{filename} for language #{language}" unless File.exist?(filename)
76
-
77
- code = File.read(filename)
78
- lexer = CodeLanguageAPI.find(language).lexer
79
-
80
- total_lines = code.lines.count
81
-
82
- # Minus one since lines are not zero-indexed
83
- from_line = (input['from_line'] || 1) - 1
84
- to_line = (input['to_line'] || total_lines) - 1
85
-
86
- code = code.lines[from_line..to_line].join
87
- code.unindent! if unindent
88
-
89
- highlight(code, lexer)
90
- end
91
-
92
- def get_renderer(language)
93
- language = 'dotnet' if language == 'csharp'
94
- case language
95
- when 'curl'
96
- CodeSnippetRenderer::Curl
97
- when 'node'
98
- CodeSnippetRenderer::Javascript
99
- when 'javascript'
100
- CodeSnippetRenderer::Javascript
101
- when 'java'
102
- CodeSnippetRenderer::Java
103
- when 'dotnet'
104
- CodeSnippetRenderer::Dotnet
105
- when 'python'
106
- CodeSnippetRenderer::Python
107
- when 'ruby'
108
- CodeSnippetRenderer::Ruby
109
- when 'php'
110
- CodeSnippetRenderer::Php
111
- when 'android'
112
- CodeSnippetRenderer::Android
113
- when 'kotlin'
114
- CodeSnippetRenderer::Kotlin
115
- when 'objective_c'
116
- CodeSnippetRenderer::ObjectiveC
117
- when 'swift'
118
- CodeSnippetRenderer::Swift
119
- else
120
- raise "Unknown language: #{language}"
121
- end
122
- end
123
-
124
- def generate_dependencies(language, dependencies)
125
- # The only valid dependency for curl examples is `JWT`
126
- dependencies = dependencies.map(&:upcase)
127
- if dependencies.include?('JWT')
128
- title = 'Generate your JWT'
129
- else
130
- title = 'Install dependencies'
131
- end
132
- deps = @renderer.dependencies(dependencies)
133
- id = SecureRandom.hex
134
- erb = File.read("#{API.root}/views/code_snippets/_dependencies.html.erb")
135
- ERB.new(erb).result(binding)
136
- end
137
-
138
- def generate_application_block(app)
139
- return '' unless app
140
-
141
- base_url = 'http://demo.ngrok.io'
142
- base_url = 'https://example.com' if app['disable_ngrok']
143
-
144
- app['name'] = 'ExampleProject' unless app['name']
145
-
146
- # We should remove this default once we're sure that all Code Snippets
147
- # have a type set e.g audit
148
- app['type'] ||= 'voice'
149
-
150
- if ['voice', 'rtc'].include? app['type']
151
- app['event_url'] = "#{base_url}/webhooks/events" unless app['event_url']
152
- app['answer_url'] = "#{base_url}/webhooks/answer" unless app['answer_url']
153
- erb = File.read("#{API.root}/views/code_snippets/_application_#{app['type']}.html.erb")
154
- elsif ['messages', 'dispatch'].include? app['type']
155
- erb = File.read("#{API.root}/views/code_snippets/_application_messages_dispatch.html.erb")
156
- else
157
- raise "Invalid application type when creating code snippet: '#{app['type']}'"
158
- end
159
-
160
- id = SecureRandom.hex
161
-
162
- ERB.new(erb).result(binding)
163
- end
164
-
165
- def generate_source_url(code)
166
- # Source example: .repos/nexmo/nexmo-java-code-snippets/ExampleClass.java
167
- # Direct link on GitHub is in form https://github.com/nexmo/nexmo-java-code-snippets/blob/master/ExampleClass.java
168
- start_section = 'https://github.com'
169
-
170
- # Insert "blob/master" and strip ".repos" - except dotnet that needs "blob/ASPNET" instead
171
- repo_path = '\\0blob/master/'
172
- repo_path = '\\0blob/ASPNET/' if code['source'].include?('dotnet')
173
- file_section = code['source'].sub('.repos', '').sub(%r{(-quickstart|-code-snippets|-code-snippets)/}, repo_path)
174
-
175
- # Line highlighting
176
- line_section = ''
177
- if code['from_line']
178
- line_section += "#L#{code['from_line']}"
179
- if code['to_line']
180
- # If we've provided a to_line, use that
181
- line_section += "-L#{code['to_line']}" if code['to_line']
182
- else
183
- # By default we read to the end of the file
184
- line_section += "-L#{File.read(code['source']).lines.count}"
185
- end
186
- end
187
-
188
- start_section + file_section + line_section
189
- end
190
- end
191
- end
192
- end
193
- end
194
- end
@@ -1,33 +0,0 @@
1
- require 'yaml'
2
- require 'banzai'
3
- require_relative '../models/code_snippet'
4
-
5
- module Nexmo
6
- module OAS
7
- module Renderer
8
- module Filters
9
- class CodeSnippetList < Banzai::Filter
10
- def call(input)
11
- input.gsub(/```code_snippet_list(.+?)```/m) do |_s|
12
- config = YAML.safe_load($1)
13
- @product = config['product']
14
- @blocks = Models::CodeSnippet.by_product(@product)
15
-
16
- # Top level blocks come before subfolder
17
- @blocks.sort_by! do |b|
18
- sort_array = []
19
- sort_array << (b.category ? 1 : 0)
20
- sort_array << b.navigation_weight
21
- sort_array
22
- end
23
-
24
- erb = File.read("#{API.root}/views/code_snippets/list/plain.html.erb")
25
- html = ERB.new(erb).result(binding)
26
- "FREEZESTART#{Base64.urlsafe_encode64(html)}FREEZEEND"
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,158 +0,0 @@
1
- module Nexmo
2
- module OAS
3
- module Renderer
4
- module Filters
5
- class CodeSnippets < Banzai::Filter
6
- def call(input)
7
- input.gsub(/^(\s*)```code_snippets(.+?)```/m) do |_s|
8
- @indentation = $1
9
- @config = YAML.safe_load($2)
10
- validate_config
11
- html
12
- end
13
- end
14
-
15
- private
16
-
17
- def create_tabs(content)
18
- tab = Nokogiri::XML::Element.new 'li', @document
19
- tab['class'] = 'Vlt-tabs__link'
20
- tab['class'] += ' Vlt-tabs__link_active' if content[:active]
21
- tab['aria-selected'] = 'true' if content[:active]
22
-
23
- if content['language']
24
- tab['data-language'] = content['language']
25
- tab['data-language-type'] = content['language_type']
26
- tab['data-language-linkable'] = true
27
- end
28
-
29
- tab_link = Nokogiri::XML::Element.new 'a', @document
30
- tab_link.inner_html = "<svg><use xlink:href=\"/assets/images/brands/#{content['icon']}.svg##{content['icon']}\" /></svg><span>" + content['title'] + '</span>'
31
- tab_link['class'] = 'tab-link'
32
-
33
- tab.add_child(tab_link)
34
- @tabs.add_child(tab)
35
- end
36
-
37
- def create_content(content)
38
- element = Nokogiri::XML::Element.new 'div', @document
39
- element['id'] = content['id']
40
- element['class'] = 'Vlt-tabs__panel'
41
- element['class'] += ' Vlt-tabs__panel_active' if content[:active]
42
- element.inner_html = content[:body]
43
-
44
- @tabs_content.add_child(element)
45
- end
46
-
47
- def html
48
- html = <<~HEREDOC
49
- <div class="Vlt-tabs">
50
- <div class="Vlt-tabs__header--bordered"></div>
51
- <div class="Vlt-tabs__content"></div>
52
- </div>
53
- HEREDOC
54
-
55
- @document = Nokogiri::HTML::DocumentFragment.parse(html)
56
- @tabs = @document.at_css('.Vlt-tabs__header--bordered')
57
- @tabs_content = @document.at_css('.Vlt-tabs__content')
58
-
59
- contents.each do |content|
60
- create_tabs(content)
61
- create_content(content)
62
- end
63
-
64
- source = @document.to_html
65
-
66
- "#{@indentation}FREEZESTART#{Base64.urlsafe_encode64(source)}FREEZEEND"
67
- end
68
-
69
- def contents
70
- list = content_from_source
71
- list ||= []
72
-
73
- return list unless list.any?
74
-
75
- list = sort_contents(list)
76
- resolve_active_tab(list)
77
-
78
- list
79
- end
80
-
81
- def validate_config
82
- return if @config && @config['source']
83
- raise 'A source key must be present in this building_blocks config'
84
- end
85
-
86
- def content_from_source
87
- source_path = "#{@config['source']}/*.yml"
88
-
89
- files = Dir[source_path]
90
- raise "No .yml files found for #{@config['source']} code snippets" if files.empty?
91
-
92
- files.map do |content_path|
93
- source = File.read(content_path)
94
-
95
- # Load the defaults for this language
96
- filename = File.basename(content_path, '.yml')
97
- defaults = CodeLanguageAPI.find(filename)
98
-
99
- content = YAML.safe_load(source)
100
- content['source'] = source
101
- content['id'] = SecureRandom.hex
102
- content['title'] ||= defaults.label
103
- content['language'] ||= defaults.key
104
- content['language_type'] ||= defaults.type
105
- content['dependencies'] ||= defaults.dependencies
106
- content['icon'] = defaults.icon
107
- content['weight'] ||= defaults.weight
108
- content['run_command'] ||= defaults.run_command
109
- content['unindent'] = defaults.unindent || false
110
-
111
- # If we don't have a file_name in config, use the one in the repo
112
- content['file_name'] ||= File.basename(content['code']['source'])
113
-
114
- parent_config = { 'code_only' => @config['code_only'], 'source' => @config['source'].gsub('_examples/', '') }
115
- if @config['application']
116
- parent_config = parent_config.merge({ 'application' => @config['application'] })
117
- end
118
-
119
- parent_config = parent_config.to_yaml.lines[1..-1].join
120
-
121
- source = <<~HEREDOC
122
- ```single_code_snippet
123
- #{content.to_yaml}\n#{parent_config}
124
- ```
125
- HEREDOC
126
-
127
- content[:body] = MarkdownPipeline.new(options).call(source)
128
-
129
- content
130
- end
131
- end
132
-
133
- def sort_contents(contents)
134
- contents.sort_by do |content|
135
- content['weight']
136
- end
137
- end
138
-
139
- def resolve_active_tab(contents)
140
- active_index = nil
141
-
142
- if options[:code_language]
143
- contents.each_with_index do |content, index|
144
- active_index = index if content['language'] == options[:code_language].key
145
- end
146
- end
147
-
148
- @tabs['data-has-initial-tab'] = active_index.present?
149
- @tabs['class'] += ' skip-pushstate' if @tabs['data-has-initial-tab']
150
- active_index ||= 0
151
-
152
- contents[active_index][:active] = true
153
- end
154
- end
155
- end
156
- end
157
- end
158
- end