nexmo_markdown_renderer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +54 -0
- data/config/code_languages.yml +138 -0
- data/config/dynamic_content.yml +1 -0
- data/config/locales/en.yml +176 -0
- data/lib/nexmo_markdown_renderer.rb +28 -0
- data/lib/nexmo_markdown_renderer/cli.rb +13 -0
- data/lib/nexmo_markdown_renderer/core_ext/html.rb +7 -0
- data/lib/nexmo_markdown_renderer/core_ext/string.rb +14 -0
- data/lib/nexmo_markdown_renderer/filters/anchor_filter.rb +14 -0
- data/lib/nexmo_markdown_renderer/filters/audio_filter.rb +18 -0
- data/lib/nexmo_markdown_renderer/filters/block_escape_filter.rb +21 -0
- data/lib/nexmo_markdown_renderer/filters/break_filter.rb +10 -0
- data/lib/nexmo_markdown_renderer/filters/code_filter.rb +62 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet_filter.rb +187 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet_list_filter.rb +26 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippets_filter.rb +170 -0
- data/lib/nexmo_markdown_renderer/filters/collapsible_filter.rb +27 -0
- data/lib/nexmo_markdown_renderer/filters/columns_filter.rb +47 -0
- data/lib/nexmo_markdown_renderer/filters/concept_list_filter.rb +30 -0
- data/lib/nexmo_markdown_renderer/filters/dynamic_content_filter.rb +28 -0
- data/lib/nexmo_markdown_renderer/filters/external_link_filter.rb +29 -0
- data/lib/nexmo_markdown_renderer/filters/frontmatter_filter.rb +11 -0
- data/lib/nexmo_markdown_renderer/filters/heading_filter.rb +57 -0
- data/lib/nexmo_markdown_renderer/filters/i18n/frontmatter_filter.rb +16 -0
- data/lib/nexmo_markdown_renderer/filters/i18n/smartling_converter_filter.rb +22 -0
- data/lib/nexmo_markdown_renderer/filters/icon_filter.rb +19 -0
- data/lib/nexmo_markdown_renderer/filters/indent_filter.rb +17 -0
- data/lib/nexmo_markdown_renderer/filters/inline_escape_filter.rb +14 -0
- data/lib/nexmo_markdown_renderer/filters/js_sequence_diagram_filter.rb +18 -0
- data/lib/nexmo_markdown_renderer/filters/label_filter.rb +29 -0
- data/lib/nexmo_markdown_renderer/filters/language_filter.rb +12 -0
- data/lib/nexmo_markdown_renderer/filters/markdown_filter.rb +81 -0
- data/lib/nexmo_markdown_renderer/filters/mermaid_filter.rb +29 -0
- data/lib/nexmo_markdown_renderer/filters/modal_filter.rb +37 -0
- data/lib/nexmo_markdown_renderer/filters/partial_filter.rb +29 -0
- data/lib/nexmo_markdown_renderer/filters/php_inliner_filter.rb +11 -0
- data/lib/nexmo_markdown_renderer/filters/screenshot_filter.rb +22 -0
- data/lib/nexmo_markdown_renderer/filters/tab_filter.rb +298 -0
- data/lib/nexmo_markdown_renderer/filters/techio_filter.rb +20 -0
- data/lib/nexmo_markdown_renderer/filters/tooltip_filter.rb +18 -0
- data/lib/nexmo_markdown_renderer/filters/unfreeze_filter.rb +16 -0
- data/lib/nexmo_markdown_renderer/filters/use_case_list_filter.rb +20 -0
- data/lib/nexmo_markdown_renderer/initializers/doc_finder.rb +5 -0
- data/lib/nexmo_markdown_renderer/initializers/i18n.rb +4 -0
- data/lib/nexmo_markdown_renderer/initializers/redcarpet.rb +7 -0
- data/lib/nexmo_markdown_renderer/markdown_renderer.rb +47 -0
- data/lib/nexmo_markdown_renderer/models/code_language.rb +79 -0
- data/lib/nexmo_markdown_renderer/models/code_snippet.rb +72 -0
- data/lib/nexmo_markdown_renderer/models/concept.rb +83 -0
- data/lib/nexmo_markdown_renderer/models/tutorial.rb +148 -0
- data/lib/nexmo_markdown_renderer/models/use_case.rb +81 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/android.rb +25 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/base.rb +12 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/curl.rb +29 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/dotnet.rb +23 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/java.rb +32 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/javascript.rb +23 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/kotlin.rb +25 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/objective_c.rb +25 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/php.rb +23 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/python.rb +23 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/ruby.rb +23 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/swift.rb +25 -0
- data/lib/nexmo_markdown_renderer/services/doc_finder.rb +119 -0
- data/lib/nexmo_markdown_renderer/views/code_snippets/_application_messages_dispatch.html.erb +9 -0
- data/lib/nexmo_markdown_renderer/views/code_snippets/_application_rtc.html.erb +28 -0
- data/lib/nexmo_markdown_renderer/views/code_snippets/_application_voice.html.erb +24 -0
- data/lib/nexmo_markdown_renderer/views/code_snippets/_code_only.html.erb +6 -0
- data/lib/nexmo_markdown_renderer/views/code_snippets/_configure_client.html.erb +20 -0
- data/lib/nexmo_markdown_renderer/views/code_snippets/_dependencies.html.erb +11 -0
- data/lib/nexmo_markdown_renderer/views/code_snippets/_write_code.html.erb +13 -0
- data/lib/nexmo_markdown_renderer/views/code_snippets/list/plain.html.erb +10 -0
- data/lib/nexmo_markdown_renderer/views/concepts/list/plain.html.erb +5 -0
- data/lib/nexmo_markdown_renderer/views/use_case/_index.html.erb +41 -0
- data/lib/nexmo_markdown_renderer/views/use_case/index.html.erb +48 -0
- data/lib/nexmo_markdown_renderer/views/use_case/list/plain.html.erb +5 -0
- data/lib/nexmo_markdown_renderer/views/use_case/show.html.erb +8 -0
- data/lib/version.rb +7 -0
- metadata +322 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class MermaidFilter < Banzai::Filter
|
4
|
+
TYPES = {
|
5
|
+
'mermaid' => '',
|
6
|
+
'sequence_diagram' => 'sequenceDiagram',
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
def call(input)
|
10
|
+
TYPES.each do |markdown, mermaid|
|
11
|
+
input = input.gsub(/```#{markdown}(.+?)```/m) do |_s|
|
12
|
+
render_mermaid(mermaid, $1)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
input
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_mermaid(type, content)
|
20
|
+
diagram = <<~HEREDOC
|
21
|
+
<div class="mermaid" style="color: transparent;">#{type} #{content.gsub('\\n', '<br />').strip}
|
22
|
+
</div>
|
23
|
+
HEREDOC
|
24
|
+
|
25
|
+
"FREEZESTART#{Base64.urlsafe_encode64(diagram)}FREEZEEND"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class ModalFilter < Banzai::Filter
|
4
|
+
def call(input)
|
5
|
+
modals = []
|
6
|
+
|
7
|
+
input.gsub!(/@\[(.+?)\]\((.+?)\)/) do |_s|
|
8
|
+
id = 'M' + SecureRandom.hex(12)
|
9
|
+
modals << { document: $2, id: id }
|
10
|
+
"<a href='javascript:void(0)' data-modal='#{id}' class='Vlt-modal-trigger Vlt-text-link'>#{$1}</a>"
|
11
|
+
end
|
12
|
+
|
13
|
+
modals = modals.map do |modal|
|
14
|
+
filename = "#{ENV['DOCS_BASE_PATH']}/#{modal[:document]}"
|
15
|
+
raise "Could not find modal #{filename}" unless File.exist? filename
|
16
|
+
|
17
|
+
document = File.read(filename)
|
18
|
+
output = Nexmo::Markdown::Renderer.new.call(document)
|
19
|
+
|
20
|
+
modal = <<~HEREDOC
|
21
|
+
<div class="Vlt-modal" id="#{modal[:id]}">
|
22
|
+
<div class="Vlt-modal__panel">
|
23
|
+
<div class="Vlt-modal__content">
|
24
|
+
#{output}
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
HEREDOC
|
29
|
+
|
30
|
+
"FREEZESTART#{Base64.urlsafe_encode64(modal)}FREEZEEND"
|
31
|
+
end
|
32
|
+
|
33
|
+
input + modals.join("\n")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class PartialFilter < Banzai::Filter
|
4
|
+
def call(input)
|
5
|
+
input.gsub(/```partial(.+?)```/m) do |_s|
|
6
|
+
config = YAML.safe_load($1)
|
7
|
+
file_path = if config['source'].starts_with? 'app/views'
|
8
|
+
config['source']
|
9
|
+
else
|
10
|
+
"#{ENV['DOCS_BASE_PATH']}/#{config['source']}"
|
11
|
+
end
|
12
|
+
content = File.read(file_path)
|
13
|
+
|
14
|
+
active = options[:code_language] ? options[:code_language].key == config['platform'] : false
|
15
|
+
|
16
|
+
if config['platform']
|
17
|
+
<<~HEREDOC
|
18
|
+
<div class="js-platform" data-platform="#{config['platform']}" data-active="#{active}">
|
19
|
+
#{content.render_markdown}
|
20
|
+
</div>
|
21
|
+
HEREDOC
|
22
|
+
else
|
23
|
+
content
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class ScreenshotFilter < Banzai::Filter
|
4
|
+
def call(input)
|
5
|
+
input.gsub(/```screenshot(.+?)```/m) do |_s|
|
6
|
+
config = YAML.safe_load($1)
|
7
|
+
if config['image'] && File.file?(config['image'])
|
8
|
+
"![Screenshot](#{config['image'].gsub('public', '')})"
|
9
|
+
else
|
10
|
+
<<~HEREDOC
|
11
|
+
## Missing image
|
12
|
+
To fix this run:
|
13
|
+
```
|
14
|
+
$ rake screenshots:update
|
15
|
+
```
|
16
|
+
HEREDOC
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class TabFilter < Banzai::Filter
|
4
|
+
def call(input)
|
5
|
+
input.gsub(/^(\s*)```tabbed_(examples|content|folder)(.+?)```/m) do |_s|
|
6
|
+
@indentation = $1
|
7
|
+
@mode = $2
|
8
|
+
@config = YAML.safe_load($3)
|
9
|
+
|
10
|
+
if tabbed_folder?
|
11
|
+
raise "#{@config['source']} is not a directory" unless File.directory? "#{ENV['DOCS_BASE_PATH']}/#{@config['source']}"
|
12
|
+
|
13
|
+
@tabbed_config = YAML.safe_load(File.read("#{ENV['DOCS_BASE_PATH']}/#{@config['source']}/.config.yml"))
|
14
|
+
@path = @config['source']
|
15
|
+
validate_folder_config
|
16
|
+
else
|
17
|
+
validate_config
|
18
|
+
end
|
19
|
+
html
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def create_tabs(content)
|
26
|
+
tab = Nokogiri::XML::Element.new 'div', @document
|
27
|
+
tab['class'] = 'Vlt-tabs__link'
|
28
|
+
tab['class'] += ' Vlt-tabs__link_active' if content[:active]
|
29
|
+
tab['role'] = 'tab'
|
30
|
+
|
31
|
+
if content[:language]
|
32
|
+
tab['data-language'] = content[:language].key
|
33
|
+
tab['data-language-type'] = content[:language].type
|
34
|
+
tab['data-language-linkable'] = content[:language].linkable?
|
35
|
+
end
|
36
|
+
|
37
|
+
if content[:platform]
|
38
|
+
tab['data-language'] = content[:platform].languages.map(&:key).join(',')
|
39
|
+
tab['data-platform'] = content[:platform].key
|
40
|
+
tab['data-platform-type'] = content[:platform].type
|
41
|
+
tab['data-platform-linkable'] = content[:platform].linkable?
|
42
|
+
end
|
43
|
+
|
44
|
+
tab_link = Nokogiri::XML::Element.new 'span', @document
|
45
|
+
if content[:language]
|
46
|
+
# We don't currently have icons for JSON/XML
|
47
|
+
if ['json', 'xml'].include? content[:language].key.downcase
|
48
|
+
tab_link.content = content[:tab_title]
|
49
|
+
elsif content[:language].key == 'objective_c' || content[:language].key == 'swift'
|
50
|
+
tab_link.inner_html = "<svg><use xlink:href=\"/assets/images/brands/ios.svg#ios\" /></svg><span>" + content[:tab_title] + '</span>'
|
51
|
+
else
|
52
|
+
tab_link.inner_html = "<svg><use xlink:href=\"/assets/images/brands/#{content[:language].key}.svg##{content[:language].key}\" /></svg><span>" + content[:tab_title] + '</span>'
|
53
|
+
end
|
54
|
+
elsif content[:platform]
|
55
|
+
tab_link.inner_html = "<svg><use xlink:href=\"/assets/images/brands/#{content[:platform].key}.svg##{content[:platform].key}\" /></svg><span>" + content[:tab_title] + '</span>'
|
56
|
+
else
|
57
|
+
tab_link.content = content[:tab_title]
|
58
|
+
end
|
59
|
+
|
60
|
+
tab.add_child(tab_link)
|
61
|
+
@tabs.add_child(tab)
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_content(content)
|
65
|
+
tabs_panel = Nokogiri::XML::Element.new 'div', @document
|
66
|
+
tabs_panel['class'] = 'Vlt-tabs__panel'
|
67
|
+
tabs_panel['class'] += ' Vlt-tabs__panel_active' if content[:active]
|
68
|
+
|
69
|
+
element = Nokogiri::XML::Element.new 'p', @document
|
70
|
+
element['aria-labelledby'] = "\"#{content[:id]}\""
|
71
|
+
element['aria-hidden'] = true
|
72
|
+
element.inner_html = content[:body]
|
73
|
+
|
74
|
+
tabs_panel.add_child(element)
|
75
|
+
@tabs_content.add_child(tabs_panel)
|
76
|
+
end
|
77
|
+
|
78
|
+
def tabbed_code_examples?
|
79
|
+
@mode == 'examples'
|
80
|
+
end
|
81
|
+
|
82
|
+
def tabbed_content?
|
83
|
+
@mode == 'content'
|
84
|
+
end
|
85
|
+
|
86
|
+
def tabbed_folder?
|
87
|
+
@mode == 'folder'
|
88
|
+
end
|
89
|
+
|
90
|
+
def html
|
91
|
+
html = <<~HEREDOC
|
92
|
+
<div class="Vlt-tabs">
|
93
|
+
<div class="Vlt-tabs__header Vlt-tabs__header--bordered"></div>
|
94
|
+
<div class="Vlt-tabs__content">
|
95
|
+
</div>
|
96
|
+
</div>
|
97
|
+
HEREDOC
|
98
|
+
|
99
|
+
@document = Nokogiri::HTML::DocumentFragment.parse(html)
|
100
|
+
@tabs = @document.at_css('.Vlt-tabs__header')
|
101
|
+
@tabs_content = @document.at_css('.Vlt-tabs__content')
|
102
|
+
|
103
|
+
contents.each do |content|
|
104
|
+
create_tabs(content)
|
105
|
+
create_content(content)
|
106
|
+
end
|
107
|
+
|
108
|
+
source = @document.to_html
|
109
|
+
|
110
|
+
"#{@indentation}FREEZESTART#{Base64.urlsafe_encode64(source)}FREEZEEND"
|
111
|
+
end
|
112
|
+
|
113
|
+
def contents
|
114
|
+
list = content_from_folder if tabbed_folder?
|
115
|
+
list ||= content_from_source if @config['source']
|
116
|
+
list ||= content_from_tabs if @config['tabs']
|
117
|
+
|
118
|
+
list ||= []
|
119
|
+
|
120
|
+
return list unless list.any?
|
121
|
+
|
122
|
+
list = resolve_language(list)
|
123
|
+
|
124
|
+
if tabbed_code_examples?
|
125
|
+
list = format_code(list)
|
126
|
+
list = resolve_code(list)
|
127
|
+
list = resolve_tab_title(list)
|
128
|
+
end
|
129
|
+
|
130
|
+
list = sort_contents(list)
|
131
|
+
resolve_active_tab(list)
|
132
|
+
|
133
|
+
list
|
134
|
+
end
|
135
|
+
|
136
|
+
def validate_config
|
137
|
+
return if @config && (@config['source'] || @config['tabs'])
|
138
|
+
|
139
|
+
raise 'Source or tabs must be present in this tabbed_example config'
|
140
|
+
end
|
141
|
+
|
142
|
+
def validate_folder_config
|
143
|
+
return if @tabbed_config && @tabbed_config['tabbed'] == true
|
144
|
+
|
145
|
+
raise 'Tabbed must be set to true in the folder config YAML file'
|
146
|
+
end
|
147
|
+
|
148
|
+
def content_from_source
|
149
|
+
source_path = "#{ENV['DOCS_BASE_PATH']}/#{@config['source']}"
|
150
|
+
source_path += '/*' if tabbed_code_examples?
|
151
|
+
source_path += '/*.md' if tabbed_content?
|
152
|
+
|
153
|
+
files = Dir.glob(source_path)
|
154
|
+
raise "Empty content_from_source file list in #{source_path}" if files.empty?
|
155
|
+
|
156
|
+
files.map do |content_path|
|
157
|
+
raise "Could not find content_from_source file: #{content_path}" unless File.exist? content_path
|
158
|
+
|
159
|
+
source = File.read(content_path)
|
160
|
+
|
161
|
+
next generate_tabbed_code_examples(source, content_path) if tabbed_code_examples?
|
162
|
+
|
163
|
+
generate_tabbed_content(source) if tabbed_content?
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def content_from_folder
|
168
|
+
source_path = "#{ENV['DOCS_BASE_PATH']}/#{@config['source']}"
|
169
|
+
source_path += '/*.md'
|
170
|
+
|
171
|
+
files = Dir.glob(source_path)
|
172
|
+
raise "Empty content_from_source file list in #{source_path}" if files.empty?
|
173
|
+
|
174
|
+
files.map do |content_path|
|
175
|
+
raise "Could not find content_from_source file: #{content_path}" unless File.exist? content_path
|
176
|
+
|
177
|
+
source = File.read(content_path)
|
178
|
+
|
179
|
+
generate_tabbed_content(source)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def content_from_tabs
|
184
|
+
@config['tabs'].map do |title, config|
|
185
|
+
raise "Could not find content_from_tabs file: #{ENV['DOCS_BASE_PATH']}/#{@config['source']}" unless File.exist? "#{ENV['DOCS_BASE_PATH']}/#{@config['source']}"
|
186
|
+
|
187
|
+
source = File.read("#{ENV['DOCS_BASE_PATH']}/#{@config['source']}")
|
188
|
+
|
189
|
+
config.symbolize_keys.merge({
|
190
|
+
id: SecureRandom.hex,
|
191
|
+
source: source,
|
192
|
+
language_key: title.dup.downcase,
|
193
|
+
})
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def generate_tabbed_content(source)
|
198
|
+
content = {
|
199
|
+
id: SecureRandom.hex,
|
200
|
+
source: source,
|
201
|
+
}
|
202
|
+
|
203
|
+
content[:frontmatter] = YAML.safe_load(source)
|
204
|
+
content[:language_key] = content[:frontmatter]['language']
|
205
|
+
content[:platform_key] = content[:frontmatter]['platform']
|
206
|
+
content[:tab_title] = content[:frontmatter]['title']
|
207
|
+
content[:body] = Nexmo::Markdown::Renderer.new(options).call(source)
|
208
|
+
|
209
|
+
content
|
210
|
+
end
|
211
|
+
|
212
|
+
def generate_tabbed_code_examples(source, content_path)
|
213
|
+
content = {
|
214
|
+
id: SecureRandom.hex,
|
215
|
+
source: source,
|
216
|
+
}
|
217
|
+
language_key = File.basename(content_path, '.*').downcase
|
218
|
+
content[:language_key] = language_key
|
219
|
+
|
220
|
+
content
|
221
|
+
end
|
222
|
+
|
223
|
+
def resolve_language(contents)
|
224
|
+
contents.map do |content|
|
225
|
+
if content[:language_key]
|
226
|
+
content[:language] = CodeLanguage.find(content[:language_key])
|
227
|
+
end
|
228
|
+
|
229
|
+
if content[:platform_key]
|
230
|
+
content[:platform] = CodeLanguage.find(content[:platform_key])
|
231
|
+
end
|
232
|
+
|
233
|
+
content
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def format_code(contents)
|
238
|
+
contents.each do |content|
|
239
|
+
if content[:from_line] || content[:to_line]
|
240
|
+
lines = content[:source].lines
|
241
|
+
total_lines = lines.count
|
242
|
+
from_line = (content[:from_line] || 1) - 1
|
243
|
+
to_line = (content[:to_line] || total_lines) - 1
|
244
|
+
content[:source] = lines[from_line..to_line].join
|
245
|
+
end
|
246
|
+
|
247
|
+
content[:source].unindent! if content[:unindent]
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def resolve_code(contents)
|
252
|
+
contents.map do |content|
|
253
|
+
@formatter ||= Rouge::Formatters::HTML.new
|
254
|
+
lexer = content[:language].lexer
|
255
|
+
highlighted_source = @formatter.format(lexer.lex(content[:source]))
|
256
|
+
body = <<~HEREDOC
|
257
|
+
<pre class="highlight #{content[:language_key]}"><code>#{highlighted_source}</code></pre>
|
258
|
+
HEREDOC
|
259
|
+
|
260
|
+
content.merge!({ body: body })
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def resolve_tab_title(contents)
|
265
|
+
contents.map do |content|
|
266
|
+
content.merge!({ tab_title: content[:language].label })
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def sort_contents(contents)
|
271
|
+
contents.sort_by do |content|
|
272
|
+
next content[:language].weight if content[:language]
|
273
|
+
|
274
|
+
next content[:frontmatter]['menu_weight'] || 999 if content[:frontmatter]
|
275
|
+
|
276
|
+
999
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def resolve_active_tab(contents)
|
281
|
+
active_index = nil
|
282
|
+
|
283
|
+
if options[:code_language]
|
284
|
+
contents.each_with_index do |content, index|
|
285
|
+
%i[language_key platform_key].each do |key|
|
286
|
+
active_index = index if content[key] == options[:code_language].key
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
@tabs['data-has-initial-tab'] = active_index.present?
|
292
|
+
active_index ||= 0
|
293
|
+
|
294
|
+
contents[active_index][:active] = true
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class TechioFilter < Banzai::Filter
|
4
|
+
def call(input)
|
5
|
+
input.gsub(/```techio(.+?)```/m) do |_s|
|
6
|
+
config = YAML.safe_load($1)
|
7
|
+
|
8
|
+
techio = <<~HEREDOC
|
9
|
+
<div class="techio-container">
|
10
|
+
<iframe width="100%" frameborder="0" scrolling="no" allowtransparency="true" style="visibility: hidden" src="https://tech.io/playground-widget#{config['path']}/#{config['title']}"></iframe>
|
11
|
+
<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>
|
12
|
+
</div>
|
13
|
+
HEREDOC
|
14
|
+
|
15
|
+
"FREEZESTART#{Base64.urlsafe_encode64(techio)}FREEZEEND"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|