nexmo_markdown_renderer 0.0.2
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/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/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 +320 -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
|
+
"})"
|
|
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
|