nexmo_markdown_renderer 0.3.0 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/code_languages.yml +9 -0
- data/config/locales/en.yml +1 -0
- data/lib/nexmo_markdown_renderer.rb +11 -0
- data/lib/nexmo_markdown_renderer/filters/block_escape_filter.rb +3 -3
- data/lib/nexmo_markdown_renderer/filters/code_filter.rb +17 -17
- data/lib/nexmo_markdown_renderer/filters/code_snippet/binding.rb +41 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet/create_application.rb +61 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet/import_dependencies.rb +38 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet/initialize_dependencies.rb +41 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet/install_dependencies.rb +39 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet/instructions.rb +46 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet/renderable.rb +64 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet/run.rb +29 -0
- data/lib/nexmo_markdown_renderer/filters/code_snippet_filter.rb +22 -159
- data/lib/nexmo_markdown_renderer/filters/code_snippets_filter.rb +2 -1
- data/lib/nexmo_markdown_renderer/filters/concerns/prism_code_snippet.rb +22 -0
- data/lib/nexmo_markdown_renderer/filters/markdown_filter.rb +13 -10
- data/lib/nexmo_markdown_renderer/filters/partial_filter.rb +1 -1
- data/lib/nexmo_markdown_renderer/filters/screenshot_filter.rb +1 -1
- data/lib/nexmo_markdown_renderer/filters/tab_filter.rb +73 -70
- data/lib/nexmo_markdown_renderer/filters/utils.rb +50 -0
- data/lib/nexmo_markdown_renderer/models/code_language.rb +7 -3
- data/lib/nexmo_markdown_renderer/models/tutorial.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/android.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/curl.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/dotnet.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/go.rb +23 -0
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/java.rb +4 -3
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/javascript.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/kotlin.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/objective_c.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/php.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/python.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/ruby.rb +1 -1
- data/lib/nexmo_markdown_renderer/services/doc_finder.rb +2 -2
- data/lib/nexmo_markdown_renderer/views/code_snippets/_application_rtc.html.erb +1 -1
- data/lib/nexmo_markdown_renderer/views/code_snippets/_application_voice.html.erb +1 -1
- data/lib/nexmo_markdown_renderer/views/code_snippets/_configure_client.html.erb +2 -2
- data/lib/nexmo_markdown_renderer/views/code_snippets/_import_dependencies.html.erb +18 -0
- data/lib/version.rb +1 -1
- metadata +16 -3
@@ -0,0 +1,29 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
module Filters
|
4
|
+
module CodeSnippet
|
5
|
+
class Run
|
6
|
+
include OcticonsHelper
|
7
|
+
include Renderable
|
8
|
+
|
9
|
+
def initialize(config, snippet)
|
10
|
+
@config = config
|
11
|
+
@snippet = snippet
|
12
|
+
end
|
13
|
+
|
14
|
+
def run_command
|
15
|
+
@run_command ||= begin
|
16
|
+
if @config['run_command']
|
17
|
+
@config['run_command'].gsub('{filename}', file_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def render
|
23
|
+
renderer.run_command(run_command, file_name, @config['code']['source']).to_s
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -5,183 +5,46 @@ module Nexmo
|
|
5
5
|
|
6
6
|
def call(input)
|
7
7
|
input.gsub(/```single_code_snippet(.+?)```/m) do |_s|
|
8
|
-
config = YAML.safe_load($1)
|
8
|
+
@config = YAML.safe_load($1)
|
9
|
+
@binding = ::Nexmo::Markdown::Filters::CodeSnippet::Binding.new(@config)
|
9
10
|
|
10
|
-
|
11
|
+
return instructions if @config['code_only']
|
11
12
|
|
12
|
-
|
13
|
-
|
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
|
13
|
+
"#{prerequisites}#{instructions}#{run}"
|
14
|
+
end
|
15
|
+
end
|
54
16
|
|
55
|
-
|
17
|
+
def prerequisites
|
18
|
+
@prerequisites ||= begin
|
19
|
+
prereqs = [application_html, install_dependencies, import_dependencies, initialize_dependencies].join.strip
|
56
20
|
prereqs = "<h2>#{::I18n.t('.filters.prerequisites')}</h2>#{prereqs}" unless prereqs.empty?
|
57
|
-
prereqs
|
21
|
+
prereqs
|
58
22
|
end
|
59
23
|
end
|
60
24
|
|
61
|
-
|
62
|
-
|
63
|
-
def highlight(source, lexer)
|
64
|
-
formatter = Rouge::Formatters::HTML.new
|
65
|
-
formatter.format(lexer.lex(source))
|
25
|
+
def application_html
|
26
|
+
@application_html ||= ::Nexmo::Markdown::Filters::CodeSnippet::CreateApplication.new(@config['application']).render
|
66
27
|
end
|
67
28
|
|
68
|
-
def
|
69
|
-
|
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)
|
29
|
+
def install_dependencies
|
30
|
+
@install_dependencies ||= ::Nexmo::Markdown::Filters::CodeSnippet::InstallDependencies.new(@config['dependencies'], @config['version'], @binding).render
|
86
31
|
end
|
87
32
|
|
88
|
-
def
|
89
|
-
|
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
|
33
|
+
def import_dependencies
|
34
|
+
@import_dependencies ||= ::Nexmo::Markdown::Filters::CodeSnippet::ImportDependencies.new(@config['import_dependencies'], @binding).render
|
118
35
|
end
|
119
36
|
|
120
|
-
def
|
121
|
-
|
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)
|
37
|
+
def initialize_dependencies
|
38
|
+
@initialize_dependencies ||= ::Nexmo::Markdown::Filters::CodeSnippet::InitializeDependencies.new(@config['client'], @binding).render
|
131
39
|
end
|
132
40
|
|
133
|
-
def
|
134
|
-
|
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)
|
41
|
+
def instructions
|
42
|
+
@instructions ||= ::Nexmo::Markdown::Filters::CodeSnippet::Instructions.new(@config, @binding).render
|
158
43
|
end
|
159
44
|
|
160
|
-
def
|
161
|
-
|
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
|
45
|
+
def run
|
46
|
+
@run ||= ::Nexmo::Markdown::Filters::CodeSnippet::Run.new(@config, @binding).render
|
183
47
|
end
|
184
48
|
end
|
185
|
-
|
186
49
|
end
|
187
50
|
end
|
@@ -116,7 +116,8 @@ module Nexmo
|
|
116
116
|
content['weight'] ||= defaults.weight
|
117
117
|
content['run_command'] ||= defaults.run_command
|
118
118
|
content['unindent'] = defaults.unindent || false
|
119
|
-
|
119
|
+
content['version'] ||= defaults.version
|
120
|
+
|
120
121
|
# If we don't have a file_name in config, use the one in the repo
|
121
122
|
content['file_name'] ||= File.basename(content['code']['source'])
|
122
123
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
module Concerns
|
4
|
+
module PrismCodeSnippet
|
5
|
+
def code_snippet_body(lexer, body)
|
6
|
+
<<~HEREDOC
|
7
|
+
<pre class="#{prism_css_classes(lexer)}"><code>#{body}</code></pre>
|
8
|
+
HEREDOC
|
9
|
+
end
|
10
|
+
|
11
|
+
def code_language_to_prism(code_language)
|
12
|
+
code_language == 'objective_c' && 'objectivec' || code_language
|
13
|
+
end
|
14
|
+
|
15
|
+
def prism_css_classes(lexer)
|
16
|
+
code_language = code_language_to_prism(lexer.tag)
|
17
|
+
"main-code Vlt-prism--dark language-#{code_language} Vlt-prism--copy-disabled"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,16 +1,17 @@
|
|
1
1
|
module Nexmo
|
2
2
|
module Markdown
|
3
3
|
class MarkdownFilter < Banzai::Filter
|
4
|
+
|
4
5
|
def call(input)
|
5
6
|
markdown.render(input)
|
6
7
|
end
|
7
|
-
|
8
|
+
|
8
9
|
private
|
9
|
-
|
10
|
+
|
10
11
|
def renderer
|
11
12
|
@renderer ||= VoltaRender.new(options)
|
12
13
|
end
|
13
|
-
|
14
|
+
|
14
15
|
def markdown
|
15
16
|
@markdown ||= Redcarpet::Markdown.new(renderer, {
|
16
17
|
no_intra_emphasis: true,
|
@@ -27,17 +28,19 @@ module Nexmo
|
|
27
28
|
end
|
28
29
|
|
29
30
|
class VoltaRender < HTML
|
31
|
+
include Nexmo::Markdown::Concerns::PrismCodeSnippet
|
32
|
+
|
30
33
|
def initialize(options)
|
31
34
|
@options = options
|
32
35
|
super(options)
|
33
36
|
end
|
34
|
-
|
37
|
+
|
35
38
|
def paragraph(text)
|
36
39
|
return text if @options[:skip_paragraph_surround]
|
37
|
-
|
40
|
+
|
38
41
|
"<p>#{text}</p>"
|
39
42
|
end
|
40
|
-
|
43
|
+
|
41
44
|
def table(header, body)
|
42
45
|
'<div class="Vlt-table Vlt-table--bordered">' \
|
43
46
|
'<table>' \
|
@@ -46,7 +49,7 @@ module Nexmo
|
|
46
49
|
'</table>' \
|
47
50
|
'</div>'
|
48
51
|
end
|
49
|
-
|
52
|
+
|
50
53
|
def block_quote(quote)
|
51
54
|
'<div class="Vlt-callout Vlt-callout--tip">' \
|
52
55
|
'<i></i>' \
|
@@ -55,7 +58,7 @@ module Nexmo
|
|
55
58
|
'</div>' \
|
56
59
|
'</div>'
|
57
60
|
end
|
58
|
-
|
61
|
+
|
59
62
|
def image(link, _title, _alt_text)
|
60
63
|
'<figure>' \
|
61
64
|
'<img src="'\
|
@@ -63,7 +66,7 @@ module Nexmo
|
|
63
66
|
'" alt="#{alt_text}">' \
|
64
67
|
'</figure>'
|
65
68
|
end
|
66
|
-
|
69
|
+
|
67
70
|
def list(contents, list_type)
|
68
71
|
if "#{list_type}" == 'unordered'
|
69
72
|
'<ul class="Vlt-list Vlt-list--simple">' \
|
@@ -86,7 +89,7 @@ module Nexmo
|
|
86
89
|
code.gsub! /^ /, "\t"
|
87
90
|
end
|
88
91
|
|
89
|
-
formatter = ::Rouge::Formatters::HTMLLegacy.new(:css_class =>
|
92
|
+
formatter = ::Rouge::Formatters::HTMLLegacy.new(:css_class => prism_css_classes(lexer))
|
90
93
|
formatter.format(lexer.lex(code))
|
91
94
|
end
|
92
95
|
end
|
@@ -5,7 +5,7 @@ module Nexmo
|
|
5
5
|
input.gsub(/```partial(.+?)```/m) do |_s|
|
6
6
|
config = YAML.safe_load($1)
|
7
7
|
file_path = if config['source'].starts_with? 'app/views'
|
8
|
-
config['source']
|
8
|
+
"#{Rails.root}/#{config['source']}"
|
9
9
|
else
|
10
10
|
"#{Nexmo::Markdown::Config.docs_base_path}/#{config['source']}"
|
11
11
|
end
|
@@ -4,7 +4,7 @@ module Nexmo
|
|
4
4
|
def call(input)
|
5
5
|
input.gsub(/```screenshot(.+?)```/m) do |_s|
|
6
6
|
config = YAML.safe_load($1)
|
7
|
-
if config['image'] && File.file?(config['image'])
|
7
|
+
if config['image'] && File.file?("#{Nexmo::Markdown::Config.docs_base_path}/#{config['image']}")
|
8
8
|
"![Screenshot](#{config['image'].gsub('public', '')})"
|
9
9
|
else
|
10
10
|
<<~HEREDOC
|
@@ -1,16 +1,18 @@
|
|
1
1
|
module Nexmo
|
2
2
|
module Markdown
|
3
3
|
class TabFilter < Banzai::Filter
|
4
|
+
include Nexmo::Markdown::Concerns::PrismCodeSnippet
|
5
|
+
|
4
6
|
def call(input)
|
5
7
|
input.gsub(/^(\s*)```tabbed_(examples|content|folder)(.+?)```/m) do |_s|
|
6
8
|
@indentation = $1
|
7
9
|
@mode = $2
|
8
10
|
@config = YAML.safe_load($3)
|
9
|
-
|
11
|
+
|
10
12
|
if tabbed_folder?
|
11
|
-
raise "#{@config['source']} is not a directory" unless File.directory? "#{
|
12
|
-
|
13
|
-
@tabbed_config = YAML.safe_load(File.read("#{
|
13
|
+
raise "#{@config['source']} is not a directory" unless File.directory? "#{@config['source']}"
|
14
|
+
|
15
|
+
@tabbed_config = YAML.safe_load(File.read("#{@config['source']}/.config.yml"))
|
14
16
|
@path = @config['source']
|
15
17
|
validate_folder_config
|
16
18
|
else
|
@@ -19,28 +21,28 @@ module Nexmo
|
|
19
21
|
html
|
20
22
|
end
|
21
23
|
end
|
22
|
-
|
24
|
+
|
23
25
|
private
|
24
|
-
|
26
|
+
|
25
27
|
def create_tabs(content)
|
26
28
|
tab = Nokogiri::XML::Element.new 'div', @document
|
27
29
|
tab['class'] = 'Vlt-tabs__link'
|
28
30
|
tab['class'] += ' Vlt-tabs__link_active' if content[:active]
|
29
31
|
tab['role'] = 'tab'
|
30
|
-
|
32
|
+
|
31
33
|
if content[:language]
|
32
34
|
tab['data-language'] = content[:language].key
|
33
35
|
tab['data-language-type'] = content[:language].type
|
34
36
|
tab['data-language-linkable'] = content[:language].linkable?
|
35
37
|
end
|
36
|
-
|
38
|
+
|
37
39
|
if content[:platform]
|
38
40
|
tab['data-language'] = content[:platform].languages.map(&:key).join(',')
|
39
41
|
tab['data-platform'] = content[:platform].key
|
40
42
|
tab['data-platform-type'] = content[:platform].type
|
41
43
|
tab['data-platform-linkable'] = content[:platform].linkable?
|
42
44
|
end
|
43
|
-
|
45
|
+
|
44
46
|
tab_link = Nokogiri::XML::Element.new 'span', @document
|
45
47
|
if content[:language]
|
46
48
|
# We don't currently have icons for JSON/XML
|
@@ -48,6 +50,8 @@ module Nexmo
|
|
48
50
|
tab_link.content = content[:tab_title]
|
49
51
|
elsif content[:language].key == 'objective_c' || content[:language].key == 'swift'
|
50
52
|
tab_link.inner_html = "<svg><use xlink:href=\"/assets/images/brands/ios.svg#ios\" /></svg><span>" + content[:tab_title] + '</span>'
|
53
|
+
elsif content[:language].key == 'kotlin'
|
54
|
+
tab_link.inner_html = "<img class=\"Vlt-icon Vlt-icon--small\" src=\"/assets/images/brands/kotlin.svg#kotlin\" /><span>" + content[:tab_title] + '</span>'
|
51
55
|
else
|
52
56
|
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
57
|
end
|
@@ -56,37 +60,37 @@ module Nexmo
|
|
56
60
|
else
|
57
61
|
tab_link.content = content[:tab_title]
|
58
62
|
end
|
59
|
-
|
63
|
+
|
60
64
|
tab.add_child(tab_link)
|
61
65
|
@tabs.add_child(tab)
|
62
66
|
end
|
63
|
-
|
67
|
+
|
64
68
|
def create_content(content)
|
65
69
|
tabs_panel = Nokogiri::XML::Element.new 'div', @document
|
66
70
|
tabs_panel['class'] = 'Vlt-tabs__panel'
|
67
71
|
tabs_panel['class'] += ' Vlt-tabs__panel_active' if content[:active]
|
68
|
-
|
72
|
+
|
69
73
|
element = Nokogiri::XML::Element.new 'p', @document
|
70
74
|
element['aria-labelledby'] = "\"#{content[:id]}\""
|
71
75
|
element['aria-hidden'] = true
|
72
76
|
element.inner_html = content[:body]
|
73
|
-
|
77
|
+
|
74
78
|
tabs_panel.add_child(element)
|
75
79
|
@tabs_content.add_child(tabs_panel)
|
76
80
|
end
|
77
|
-
|
81
|
+
|
78
82
|
def tabbed_code_examples?
|
79
83
|
@mode == 'examples'
|
80
84
|
end
|
81
|
-
|
85
|
+
|
82
86
|
def tabbed_content?
|
83
87
|
@mode == 'content'
|
84
88
|
end
|
85
|
-
|
89
|
+
|
86
90
|
def tabbed_folder?
|
87
91
|
@mode == 'folder'
|
88
92
|
end
|
89
|
-
|
93
|
+
|
90
94
|
def html
|
91
95
|
html = <<~HEREDOC
|
92
96
|
<div class="Vlt-tabs">
|
@@ -95,97 +99,97 @@ module Nexmo
|
|
95
99
|
</div>
|
96
100
|
</div>
|
97
101
|
HEREDOC
|
98
|
-
|
102
|
+
|
99
103
|
@document = Nokogiri::HTML::DocumentFragment.parse(html)
|
100
104
|
@tabs = @document.at_css('.Vlt-tabs__header')
|
101
105
|
@tabs_content = @document.at_css('.Vlt-tabs__content')
|
102
|
-
|
106
|
+
|
103
107
|
contents.each do |content|
|
104
108
|
create_tabs(content)
|
105
109
|
create_content(content)
|
106
110
|
end
|
107
|
-
|
111
|
+
|
108
112
|
source = @document.to_html
|
109
|
-
|
113
|
+
|
110
114
|
"#{@indentation}FREEZESTART#{Base64.urlsafe_encode64(source)}FREEZEEND"
|
111
115
|
end
|
112
|
-
|
116
|
+
|
113
117
|
def contents
|
114
118
|
list = content_from_folder if tabbed_folder?
|
115
119
|
list ||= content_from_source if @config['source']
|
116
120
|
list ||= content_from_tabs if @config['tabs']
|
117
|
-
|
121
|
+
|
118
122
|
list ||= []
|
119
|
-
|
123
|
+
|
120
124
|
return list unless list.any?
|
121
|
-
|
125
|
+
|
122
126
|
list = resolve_language(list)
|
123
|
-
|
127
|
+
|
124
128
|
if tabbed_code_examples?
|
125
129
|
list = format_code(list)
|
126
130
|
list = resolve_code(list)
|
127
131
|
list = resolve_tab_title(list)
|
128
132
|
end
|
129
|
-
|
133
|
+
|
130
134
|
list = sort_contents(list)
|
131
135
|
resolve_active_tab(list)
|
132
|
-
|
136
|
+
|
133
137
|
list
|
134
138
|
end
|
135
|
-
|
139
|
+
|
136
140
|
def validate_config
|
137
141
|
return if @config && (@config['source'] || @config['tabs'])
|
138
|
-
|
142
|
+
|
139
143
|
raise 'Source or tabs must be present in this tabbed_example config'
|
140
144
|
end
|
141
|
-
|
145
|
+
|
142
146
|
def validate_folder_config
|
143
147
|
return if @tabbed_config && @tabbed_config['tabbed'] == true
|
144
|
-
|
148
|
+
|
145
149
|
raise 'Tabbed must be set to true in the folder config YAML file'
|
146
150
|
end
|
147
|
-
|
151
|
+
|
148
152
|
def content_from_source
|
149
153
|
source_path = "#{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}"
|
150
154
|
source_path += '/*' if tabbed_code_examples?
|
151
155
|
source_path += '/*.md' if tabbed_content?
|
152
|
-
|
156
|
+
|
153
157
|
files = Dir.glob(source_path)
|
154
158
|
raise "Empty content_from_source file list in #{source_path}" if files.empty?
|
155
|
-
|
159
|
+
|
156
160
|
files.map do |content_path|
|
157
161
|
raise "Could not find content_from_source file: #{content_path}" unless File.exist? content_path
|
158
|
-
|
162
|
+
|
159
163
|
source = File.read(content_path)
|
160
|
-
|
164
|
+
|
161
165
|
next generate_tabbed_code_examples(source, content_path) if tabbed_code_examples?
|
162
|
-
|
166
|
+
|
163
167
|
generate_tabbed_content(source) if tabbed_content?
|
164
168
|
end
|
165
169
|
end
|
166
|
-
|
170
|
+
|
167
171
|
def content_from_folder
|
168
|
-
source_path = "#{
|
172
|
+
source_path = "#{@config['source']}"
|
169
173
|
source_path += '/*.md'
|
170
|
-
|
174
|
+
|
171
175
|
files = Dir.glob(source_path)
|
172
176
|
raise "Empty content_from_source file list in #{source_path}" if files.empty?
|
173
|
-
|
177
|
+
|
174
178
|
files.map do |content_path|
|
175
179
|
raise "Could not find content_from_source file: #{content_path}" unless File.exist? content_path
|
176
|
-
|
180
|
+
|
177
181
|
source = File.read(content_path)
|
178
|
-
|
182
|
+
|
179
183
|
generate_tabbed_content(source)
|
180
184
|
end
|
181
185
|
end
|
182
|
-
|
186
|
+
|
183
187
|
def content_from_tabs
|
184
188
|
@config['tabs'].map do |title, config|
|
185
189
|
raise "Could not find content_from_tabs file: #{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}" unless File.exist? "#{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}"
|
186
|
-
|
190
|
+
|
187
191
|
source = File.read("#{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}")
|
188
|
-
|
192
|
+
|
189
193
|
config.symbolize_keys.merge({
|
190
194
|
id: SecureRandom.hex,
|
191
195
|
source: source,
|
@@ -193,22 +197,22 @@ module Nexmo
|
|
193
197
|
})
|
194
198
|
end
|
195
199
|
end
|
196
|
-
|
200
|
+
|
197
201
|
def generate_tabbed_content(source)
|
198
202
|
content = {
|
199
203
|
id: SecureRandom.hex,
|
200
204
|
source: source,
|
201
205
|
}
|
202
|
-
|
206
|
+
|
203
207
|
content[:frontmatter] = YAML.safe_load(source)
|
204
208
|
content[:language_key] = content[:frontmatter]['language']
|
205
209
|
content[:platform_key] = content[:frontmatter]['platform']
|
206
210
|
content[:tab_title] = content[:frontmatter]['title']
|
207
211
|
content[:body] = Nexmo::Markdown::Renderer.new(options).call(source)
|
208
|
-
|
212
|
+
|
209
213
|
content
|
210
214
|
end
|
211
|
-
|
215
|
+
|
212
216
|
def generate_tabbed_code_examples(source, content_path)
|
213
217
|
content = {
|
214
218
|
id: SecureRandom.hex,
|
@@ -216,24 +220,24 @@ module Nexmo
|
|
216
220
|
}
|
217
221
|
language_key = File.basename(content_path, '.*').downcase
|
218
222
|
content[:language_key] = language_key
|
219
|
-
|
223
|
+
|
220
224
|
content
|
221
225
|
end
|
222
|
-
|
226
|
+
|
223
227
|
def resolve_language(contents)
|
224
228
|
contents.map do |content|
|
225
229
|
if content[:language_key]
|
226
230
|
content[:language] = CodeLanguage.find(content[:language_key])
|
227
231
|
end
|
228
|
-
|
232
|
+
|
229
233
|
if content[:platform_key]
|
230
234
|
content[:platform] = CodeLanguage.find(content[:platform_key])
|
231
235
|
end
|
232
|
-
|
236
|
+
|
233
237
|
content
|
234
238
|
end
|
235
239
|
end
|
236
|
-
|
240
|
+
|
237
241
|
def format_code(contents)
|
238
242
|
contents.each do |content|
|
239
243
|
if content[:from_line] || content[:to_line]
|
@@ -243,43 +247,42 @@ module Nexmo
|
|
243
247
|
to_line = (content[:to_line] || total_lines) - 1
|
244
248
|
content[:source] = lines[from_line..to_line].join
|
245
249
|
end
|
246
|
-
|
250
|
+
|
247
251
|
content[:source].unindent! if content[:unindent]
|
248
252
|
end
|
249
253
|
end
|
250
|
-
|
254
|
+
|
251
255
|
def resolve_code(contents)
|
252
256
|
contents.map do |content|
|
253
257
|
@formatter ||= Rouge::Formatters::HTML.new
|
254
258
|
lexer = content[:language].lexer
|
255
259
|
highlighted_source = @formatter.format(lexer.lex(content[:source]))
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
+
|
261
|
+
body = code_snippet_body(lexer, highlighted_source)
|
262
|
+
|
260
263
|
content.merge!({ body: body })
|
261
264
|
end
|
262
265
|
end
|
263
|
-
|
266
|
+
|
264
267
|
def resolve_tab_title(contents)
|
265
268
|
contents.map do |content|
|
266
269
|
content.merge!({ tab_title: content[:language].label })
|
267
270
|
end
|
268
271
|
end
|
269
|
-
|
272
|
+
|
270
273
|
def sort_contents(contents)
|
271
274
|
contents.sort_by do |content|
|
272
275
|
next content[:language].weight if content[:language]
|
273
|
-
|
276
|
+
|
274
277
|
next content[:frontmatter]['menu_weight'] || 999 if content[:frontmatter]
|
275
|
-
|
278
|
+
|
276
279
|
999
|
277
280
|
end
|
278
281
|
end
|
279
|
-
|
282
|
+
|
280
283
|
def resolve_active_tab(contents)
|
281
284
|
active_index = nil
|
282
|
-
|
285
|
+
|
283
286
|
if options[:code_language]
|
284
287
|
contents.each_with_index do |content, index|
|
285
288
|
%i[language_key platform_key].each do |key|
|
@@ -287,10 +290,10 @@ module Nexmo
|
|
287
290
|
end
|
288
291
|
end
|
289
292
|
end
|
290
|
-
|
293
|
+
|
291
294
|
@tabs['data-has-initial-tab'] = active_index.present?
|
292
295
|
active_index ||= 0
|
293
|
-
|
296
|
+
|
294
297
|
contents[active_index][:active] = true
|
295
298
|
end
|
296
299
|
end
|