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,15 @@
1
+ module Nexmo
2
+ module OAS
3
+ module Renderer
4
+ module Filters
5
+ class PHPInliner < Banzai::Filter
6
+ def call(input)
7
+ input.gsub(/(```php)\n/) do
8
+ "#{$1}?start_inline=1\n"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module Nexmo
2
+ module OAS
3
+ module Renderer
4
+ module Filters
5
+ class Screenshot < Banzai::Filter
6
+ def call(input)
7
+ input.gsub(/```screenshot(.+?)```/m) do |_s|
8
+ config = YAML.safe_load($1)
9
+ if config['image'] && File.file?(config['image'])
10
+ "![Screenshot](#{config['image'].gsub('public', '')})"
11
+ else
12
+ <<~HEREDOC
13
+ ## Missing image
14
+ To fix this run:
15
+ ```
16
+ $ rake screenshots:update
17
+ ```
18
+ HEREDOC
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,250 @@
1
+ module Nexmo
2
+ module OAS
3
+ module Renderer
4
+ module Filters
5
+ class Tab < Banzai::Filter
6
+ def call(input)
7
+ input.gsub(/^(\s*)```tabbed_(examples|content)(.+?)```/m) do |_s|
8
+ @indentation = $1
9
+ @mode = $2
10
+ @config = YAML.safe_load($3)
11
+ validate_config
12
+ html
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def create_tabs(content)
19
+ tab = Nokogiri::XML::Element.new 'div', @document
20
+ tab['class'] = 'Vlt-tabs__link'
21
+ tab['class'] += ' Vlt-tabs__link_active' if content[:active]
22
+
23
+ if content[:language]
24
+ tab['data-language'] = content[:language].key
25
+ tab['data-language-type'] = content[:language].type
26
+ tab['data-language-linkable'] = content[:language].linkable?
27
+ end
28
+
29
+ if content[:platform]
30
+ tab['data-language'] = content[:platform].languages.map(&:key).join(',')
31
+ tab['data-platform'] = content[:platform].key
32
+ tab['data-platform-type'] = content[:platform].type
33
+ tab['data-platform-linkable'] = content[:platform].linkable?
34
+ end
35
+
36
+ tab_link = Nokogiri::XML::Element.new 'span', @document
37
+ if content[:language]
38
+ # We don't currently have icons for JSON/XML
39
+ if ['json', 'xml'].include? content[:language].key.downcase
40
+ tab_link.content = content[:tab_title]
41
+ elsif content[:language].key == 'objective_c' || content[:language].key == 'swift'
42
+ tab_link.inner_html = '<svg><use xlink:href="/assets/images/brands/ios.svg#ios" /></svg><span>' + content[:tab_title] + '</span>'
43
+ else
44
+ tab_link.inner_html = "<svg><use xlink:href=\"/assets/images/brands/#{content[:language].key}.svg##{content[:language].key}\" /></svg><span>" + content[:tab_title] + '</span>'
45
+ end
46
+ elsif content[:platform]
47
+ tab_link.inner_html = "<svg><use xlink:href=\"/assets/images/brands/#{content[:platform].key}.svg##{content[:platform].key}\" /></svg><span>" + content[:tab_title] + '</span>'
48
+ else
49
+ tab_link.content = content[:tab_title]
50
+ end
51
+
52
+ tab.add_child(tab_link)
53
+ @tabs.add_child(tab)
54
+ end
55
+
56
+ def create_content(content)
57
+ tabs_panel = Nokogiri::XML::Element.new 'div', @document
58
+ tabs_panel['class'] = 'Vlt-tabs__panel'
59
+ tabs_panel['class'] += ' Vlt-tabs__panel_active' if content[:active]
60
+
61
+ element = Nokogiri::XML::Element.new 'p', @document
62
+ element['aria-labelledby'] = "\"#{content[:id]}\""
63
+ element['aria-hidden'] = true
64
+ element.inner_html = content[:body]
65
+
66
+ tabs_panel.add_child(element)
67
+ @tabs_content.add_child(tabs_panel)
68
+ end
69
+
70
+ def tabbed_code_examples?
71
+ @mode == 'examples'
72
+ end
73
+
74
+ def tabbed_content?
75
+ @mode == 'content'
76
+ end
77
+
78
+ def html
79
+ html = <<~HEREDOC
80
+ <div class="Vlt-tabs">
81
+ <div class="Vlt-tabs__header Vlt-tabs__header--bordered"></div>
82
+ <div class="Vlt-tabs__content">
83
+ </div>
84
+ </div>
85
+ HEREDOC
86
+
87
+ @document = Nokogiri::HTML::DocumentFragment.parse(html)
88
+ @tabs = @document.at_css('.Vlt-tabs__header')
89
+ @tabs_content = @document.at_css('.Vlt-tabs__content')
90
+
91
+ contents.each do |content|
92
+ create_tabs(content)
93
+ create_content(content)
94
+ end
95
+
96
+ source = @document.to_html
97
+
98
+ "#{@indentation}FREEZESTART#{Base64.urlsafe_encode64(source)}FREEZEEND"
99
+ end
100
+
101
+ def contents
102
+ list = content_from_source if @config['source']
103
+ list = content_from_tabs if @config['tabs']
104
+
105
+ list ||= []
106
+
107
+ return list unless list.any?
108
+
109
+ list = resolve_language(list)
110
+
111
+ if tabbed_code_examples?
112
+ list = format_code(list)
113
+ list = resolve_code(list)
114
+ list = resolve_tab_title(list)
115
+ end
116
+
117
+ list = sort_contents(list)
118
+ resolve_active_tab(list)
119
+
120
+ list
121
+ end
122
+
123
+ def validate_config
124
+ return if @config && (@config['source'] || @config['tabs'])
125
+ raise 'Source or tabs must be present in this tabbed_example config'
126
+ end
127
+
128
+ def content_from_source
129
+ source_path = @config['source']
130
+ source_path += '/*' if tabbed_code_examples?
131
+ source_path += '/*.md' if tabbed_content?
132
+
133
+ files = Dir[source_path]
134
+ raise "Empty content_from_source file list in #{source_path}" if files.empty?
135
+ files.map do |content_path|
136
+ raise "Could not find content_from_source file: #{content_path}" unless File.exist? content_path
137
+ source = File.read(content_path)
138
+
139
+ content = {
140
+ id: SecureRandom.hex,
141
+ source: source,
142
+ }
143
+
144
+ if tabbed_code_examples?
145
+ language_key = File.basename(content_path, '.*').downcase
146
+ content[:language_key] = language_key
147
+ end
148
+
149
+ if tabbed_content?
150
+ content[:frontmatter] = YAML.safe_load(source)
151
+ content[:language_key] = content[:frontmatter]['language']
152
+ content[:platform_key] = content[:frontmatter]['platform']
153
+ content[:tab_title] = content[:frontmatter]['title']
154
+ content[:body] = MarkdownPipeline.new(options).call(source)
155
+ end
156
+
157
+ content
158
+ end
159
+ end
160
+
161
+ def content_from_tabs
162
+ @config['tabs'].map do |title, config|
163
+ file_path = config['source']
164
+ raise "Could not find content_from_tabs file: #{config['source']}" unless File.exist? file_path
165
+ source = File.read(file_path)
166
+
167
+ config.symbolize_keys.merge({
168
+ id: SecureRandom.hex,
169
+ source: source,
170
+ language_key: title.dup.downcase,
171
+ })
172
+ end
173
+ end
174
+
175
+ def resolve_language(contents)
176
+ contents.map do |content|
177
+ if content[:language_key]
178
+ content[:language] = CodeLanguageAPI.find(content[:language_key])
179
+ end
180
+
181
+ if content[:platform_key]
182
+ content[:platform] = CodeLanguageAPI.find(content[:platform_key])
183
+ end
184
+
185
+ content
186
+ end
187
+ end
188
+
189
+ def format_code(contents)
190
+ contents.each do |content|
191
+ if content[:from_line] || content[:to_line]
192
+ lines = content[:source].lines
193
+ total_lines = lines.count
194
+ from_line = (content[:from_line] || 1) - 1
195
+ to_line = (content[:to_line] || total_lines) - 1
196
+ content[:source] = lines[from_line..to_line].join
197
+ end
198
+
199
+ content[:source].unindent! if content[:unindent]
200
+ end
201
+ end
202
+
203
+ def resolve_code(contents)
204
+ contents.map do |content|
205
+ @formatter ||= Rouge::Formatters::HTML.new
206
+ lexer = content[:language].lexer
207
+ highlighted_source = @formatter.format(lexer.lex(content[:source]))
208
+ body = <<~HEREDOC
209
+ <pre class="highlight #{content[:language_key]}"><code>#{highlighted_source}</code></pre>
210
+ HEREDOC
211
+
212
+ content.merge!({ body: body })
213
+ end
214
+ end
215
+
216
+ def resolve_tab_title(contents)
217
+ contents.map do |content|
218
+ content.merge!({ tab_title: content[:language].label })
219
+ end
220
+ end
221
+
222
+ def sort_contents(contents)
223
+ contents.sort_by do |content|
224
+ next content[:language].weight if content[:language]
225
+ next content[:frontmatter]['menu_weight'] || 999 if content[:frontmatter]
226
+ 999
227
+ end
228
+ end
229
+
230
+ def resolve_active_tab(contents)
231
+ active_index = nil
232
+
233
+ if options[:code_language]
234
+ contents.each_with_index do |content, index|
235
+ %i[language_key platform_key].each do |key|
236
+ active_index = index if content[key] == options[:code_language].key
237
+ end
238
+ end
239
+ end
240
+
241
+ @tabs['data-has-initial-tab'] = active_index.present?
242
+ active_index ||= 0
243
+
244
+ contents[active_index][:active] = true
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,24 @@
1
+ module Nexmo
2
+ module OAS
3
+ module Renderer
4
+ module Filters
5
+ class Techio < Banzai::Filter
6
+ def call(input)
7
+ input.gsub(/```techio(.+?)```/m) do |_s|
8
+ config = YAML.safe_load($1)
9
+
10
+ techio = <<~HEREDOC
11
+ <div class="techio-container">
12
+ <iframe width="100%" frameborder="0" scrolling="no" allowtransparency="true" style="visibility: hidden" src="https://tech.io/playground-widget#{config['path']}/#{config['title']}"></iframe>
13
+ <script>if(typeof window.techioScriptInjected==="undefined"){window.techioScriptInjected=true;var d=document,s=d.createElement("script");s.src="https://files.codingame.com/codingame/iframe-v-1-4.js";(d.head||d.body).appendChild(s);}</script>
14
+ </div>
15
+ HEREDOC
16
+
17
+ "FREEZESTART#{Base64.urlsafe_encode64(techio)}FREEZEEND"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ module Nexmo
2
+ module OAS
3
+ module Renderer
4
+ module Filters
5
+ class Tooltip < Banzai::Filter
6
+ def call(input)
7
+ input.gsub(/\^\[([a-zA-Z0-9\s:\-]+)\]\((.+?)\)/) do
8
+ tooltip = <<~HEREDOC
9
+ <span class="Vlt-tooltip Vlt-tooltip--top" title="#{$2}" tabindex="0">
10
+ #{$1}&nbsp;
11
+ <svg class="Vlt-icon Vlt-icon--smaller Vlt-icon--text-bottom Vlt-blue" aria-hidden="true"><use xlink:href="/assets/symbol/volta-icons.svg#Vlt-icon-help-negative"/></svg>
12
+ </span>
13
+ HEREDOC
14
+
15
+ "FREEZESTART#{Base64.urlsafe_encode64(tooltip)}FREEZEEND"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ module Nexmo
2
+ module OAS
3
+ module Renderer
4
+ module Filters
5
+ class TutorialLink < Banzai::Filter
6
+ def call(input)
7
+ @input = input
8
+
9
+ document.css('a').each_with_index do |link, _index|
10
+ if link['href']&.start_with?('/tutorials/')
11
+ link['data-turbolinks'] = 'false'
12
+ end
13
+ end
14
+
15
+ @document.to_html
16
+ end
17
+
18
+ private
19
+
20
+ def document
21
+ @document ||= Nokogiri::HTML::DocumentFragment.parse(@input)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ require_relative '../models/tutorial'
2
+ require 'banzai'
3
+ require 'yaml'
4
+
5
+ module Nexmo
6
+ module OAS
7
+ module Renderer
8
+ module Filters
9
+ class Tutorials < Banzai::Filter
10
+ def call(input)
11
+ input.gsub(/```tutorials(.+?)```/m) do |_s|
12
+ config = YAML.safe_load($1)
13
+ @product = config['product']
14
+ @tutorials = Models::Tutorial.by_product(@product)
15
+
16
+ # Default to plain layout, but allow people to override it
17
+ config['layout'] = 'list/plain' unless config['layout']
18
+
19
+ erb = File.read("#{API.root}/views/tutorials/#{config['layout']}.html.erb")
20
+ html = ERB.new(erb).result(binding)
21
+ "FREEZESTART#{Base64.urlsafe_encode64(html)}FREEZEEND"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ module Nexmo
2
+ module OAS
3
+ module Renderer
4
+ module Filters
5
+ class Unfreeze < Banzai::Filter
6
+ def call(input)
7
+ input.gsub!('FREEZESTARTFREEZEEND', '')
8
+ input.gsub!('<p>FREEZESTART', 'FREEZESTART')
9
+ input.gsub!('FREEZEEND</p>', 'FREEZEEND')
10
+
11
+ input.gsub!(/FREEZESTART(.+?)FREEZEEND/m) do |_s|
12
+ Base64.urlsafe_decode64($1).force_encoding(Encoding::UTF_8)
13
+ end
14
+ input
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,43 @@
1
+ module Nexmo
2
+ module OAS
3
+ module Renderer
4
+ module Filters
5
+ class UserPersonalization < Banzai::Filter
6
+ def call(input)
7
+ return input unless options[:current_user]
8
+ return input if options[:current_user].api_key.blank?
9
+ return input if options[:current_user].api_secret.blank?
10
+
11
+ @input = input
12
+ document.css('pre code').each do |code|
13
+ html = code.to_s
14
+
15
+ html.gsub!(/(['|"])?NEXMO_API_(KEY|SECRET)['|"]?/) do
16
+ quote = $1 || "'"
17
+ value = (
18
+ case $2
19
+ when 'KEY' then options[:current_user].api_key
20
+ when 'SECRET' then options[:current_user].api_secret
21
+ end
22
+ )
23
+ "#{quote}#{value}#{quote}"
24
+ end
25
+
26
+ html.gsub!('NEXMO_API_SECRET', "'#{options[:current_user].api_secret}'")
27
+
28
+ code.replace(html)
29
+ end
30
+
31
+ @document.to_html
32
+ end
33
+
34
+ private
35
+
36
+ def document
37
+ @document ||= Nokogiri::HTML::DocumentFragment.parse(@input)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end