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