nexmo_markdown_renderer 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe1875b3974959e1290b19d8e480b455fa5259b78567b607a4b66b86634ccfad
4
- data.tar.gz: 9e33c425c055ef2b52ac3e9abf70c596bcf86ad92f0f8ea4f69ea7732f3001ed
3
+ metadata.gz: 746e034b9ef6f00f3004f92196e71c3b670cc677f931fa67cdf42252620fdc37
4
+ data.tar.gz: 680b76bcce7a745ee748cb4e6a5db8d2724a2727271651179a18d43dee0a1701
5
5
  SHA512:
6
- metadata.gz: 25002e68f5f4db9e9de3d9360a82b3d93c4de70e56a00bdffa6e09ed89a0967a115c50f5b13cd875cfc386c66bbc359b15d5d191619be4f0f3420d250c04786c
7
- data.tar.gz: c2b6fc824c865d72f523e50a56b74647393bb8fb98fe9e63f96d48435867511eeb141f6d856ac47c6eae2d8661fdbbeb5d53d557dab5307c5a5525da775291b2
6
+ metadata.gz: 10cfc564ff9a5544f522fcd98a77afdae52c9140846ae199db099615218ccc8be61360f27ba1c73b46fb0326c4a613ddf625b7bef19df45ba5564a022c1fb1ad
7
+ data.tar.gz: 31bd733108f5ebcb4608cc9bfbd7b7669902ce66cc94a922abd58a7819c6843d082a710307920efd1450b6b737b53490bcdf5c7f34ead2e07c9d2bdcb704618c
@@ -38,6 +38,7 @@ require_relative 'nexmo_markdown_renderer/models/tutorial/prerequisite'
38
38
  require_relative 'nexmo_markdown_renderer/models/tutorial/task'
39
39
  require_relative 'nexmo_markdown_renderer/models/use_case'
40
40
 
41
+ Dir[File.join(__dir__, 'nexmo_markdown_renderer/filters/concerns', '*.rb')].each { |file| require_relative file }
41
42
  Dir[File.join(__dir__, 'nexmo_markdown_renderer/filters', '*.rb')].each { |file| require_relative file }
42
43
  Dir[File.join(__dir__, 'nexmo_markdown_renderer/filters/i18n', '*.rb')].each { |file| require_relative file }
43
44
  require_relative 'nexmo_markdown_renderer/markdown_renderer'
@@ -1,6 +1,8 @@
1
1
  module Nexmo
2
2
  module Markdown
3
3
  class BlockEscapeFilter < Banzai::Filter
4
+ include Nexmo::Markdown::Concerns::PrismCodeSnippet
5
+
4
6
  def call(input)
5
7
  # Freeze to prevent Markdown formatting
6
8
  input.gsub(/````\n(.+?)````/m) do |_s|
@@ -8,9 +10,7 @@ module Nexmo
8
10
  formatter = Rouge::Formatters::HTML.new
9
11
  highlighted_source = formatter.format(lexer.lex($1))
10
12
 
11
- output = <<~HEREDOC
12
- <pre class="Vlt-prism--dark language-#{lexer.tag} Vlt-prism--copy-disabled"><code>#{highlighted_source}</code></pre>
13
- HEREDOC
13
+ output = code_snippet_body(lexer, highlighted_source)
14
14
 
15
15
  "FREEZESTART#{Base64.urlsafe_encode64(output)}FREEZEEND"
16
16
  end
@@ -1,43 +1,43 @@
1
1
  module Nexmo
2
2
  module Markdown
3
3
  class CodeFilter < Banzai::Filter
4
+ include Nexmo::Markdown::Concerns::PrismCodeSnippet
5
+
4
6
  def call(input)
5
7
  input.gsub(/(?!.*snippet)```code(.+?)```/m) do |_s|
6
8
  config = YAML.safe_load($1)
7
-
9
+
8
10
  if config['config']
9
11
  configs = YAML.load_file("#{Nexmo::Markdown::Config.docs_base_path}/config/code_examples.yml")
10
12
  config = config['config'].split('.').inject(configs) { |h, k| h[k] }
11
13
  end
12
-
14
+
13
15
  code = File.read("#{Nexmo::Markdown::Config.docs_base_path}/#{config['source']}")
14
16
  language = File.extname("#{Nexmo::Markdown::Config.docs_base_path}/#{config['source']}")[1..-1]
15
17
  lexer = language_to_lexer(language)
16
-
18
+
17
19
  total_lines = code.lines.count
18
-
20
+
19
21
  # Minus one since lines are not zero-indexed
20
22
  from_line = (config['from_line'] || 1) - 1
21
23
  to_line = (config['to_line'] || total_lines) - 1
22
-
24
+
23
25
  code = code.lines[from_line..to_line].join
24
26
  code.unindent! if config['unindent']
25
-
27
+
26
28
  highlighted_source = highlight(code, lexer)
27
-
28
- <<~HEREDOC
29
- <pre class="Vlt-prism--dark language-#{lexer.tag} Vlt-prism--copy-disabled"><code>#{highlighted_source}</code></pre>
30
- HEREDOC
29
+
30
+ code_snippet_body(lexer, highlighted_source)
31
31
  end
32
32
  end
33
-
33
+
34
34
  private
35
-
35
+
36
36
  def highlight(source, lexer)
37
37
  formatter = Rouge::Formatters::HTML.new
38
38
  formatter.format(lexer.lex(source))
39
39
  end
40
-
40
+
41
41
  def language_to_lexer_name(language)
42
42
  if language_configuration[language]
43
43
  language_configuration[language]['lexer']
@@ -45,18 +45,18 @@ module Nexmo
45
45
  language
46
46
  end
47
47
  end
48
-
48
+
49
49
  def language_to_lexer(language)
50
50
  language = language_to_lexer_name(language)
51
51
  return Rouge::Lexers::PHP.new({ start_inline: true }) if language == 'php'
52
-
52
+
53
53
  Rouge::Lexer.find(language.downcase) || Rouge::Lexer.find('text')
54
54
  end
55
-
55
+
56
56
  def language_configuration
57
57
  @language_configuration ||= YAML.load_file("#{GEM_ROOT}/config/code_languages.yml")
58
58
  end
59
59
  end
60
-
60
+
61
61
  end
62
62
  end
@@ -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 => "Vlt-prism--dark language-#{lexer.tag} Vlt-prism--copy-disabled")
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
@@ -1,15 +1,17 @@
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
13
  raise "#{@config['source']} is not a directory" unless File.directory? "#{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}"
12
-
14
+
13
15
  @tabbed_config = YAML.safe_load(File.read("#{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}/.config.yml"))
14
16
  @path = @config['source']
15
17
  validate_folder_config
@@ -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
@@ -56,37 +58,37 @@ module Nexmo
56
58
  else
57
59
  tab_link.content = content[:tab_title]
58
60
  end
59
-
61
+
60
62
  tab.add_child(tab_link)
61
63
  @tabs.add_child(tab)
62
64
  end
63
-
65
+
64
66
  def create_content(content)
65
67
  tabs_panel = Nokogiri::XML::Element.new 'div', @document
66
68
  tabs_panel['class'] = 'Vlt-tabs__panel'
67
69
  tabs_panel['class'] += ' Vlt-tabs__panel_active' if content[:active]
68
-
70
+
69
71
  element = Nokogiri::XML::Element.new 'p', @document
70
72
  element['aria-labelledby'] = "\"#{content[:id]}\""
71
73
  element['aria-hidden'] = true
72
74
  element.inner_html = content[:body]
73
-
75
+
74
76
  tabs_panel.add_child(element)
75
77
  @tabs_content.add_child(tabs_panel)
76
78
  end
77
-
79
+
78
80
  def tabbed_code_examples?
79
81
  @mode == 'examples'
80
82
  end
81
-
83
+
82
84
  def tabbed_content?
83
85
  @mode == 'content'
84
86
  end
85
-
87
+
86
88
  def tabbed_folder?
87
89
  @mode == 'folder'
88
90
  end
89
-
91
+
90
92
  def html
91
93
  html = <<~HEREDOC
92
94
  <div class="Vlt-tabs">
@@ -95,97 +97,97 @@ module Nexmo
95
97
  </div>
96
98
  </div>
97
99
  HEREDOC
98
-
100
+
99
101
  @document = Nokogiri::HTML::DocumentFragment.parse(html)
100
102
  @tabs = @document.at_css('.Vlt-tabs__header')
101
103
  @tabs_content = @document.at_css('.Vlt-tabs__content')
102
-
104
+
103
105
  contents.each do |content|
104
106
  create_tabs(content)
105
107
  create_content(content)
106
108
  end
107
-
109
+
108
110
  source = @document.to_html
109
-
111
+
110
112
  "#{@indentation}FREEZESTART#{Base64.urlsafe_encode64(source)}FREEZEEND"
111
113
  end
112
-
114
+
113
115
  def contents
114
116
  list = content_from_folder if tabbed_folder?
115
117
  list ||= content_from_source if @config['source']
116
118
  list ||= content_from_tabs if @config['tabs']
117
-
119
+
118
120
  list ||= []
119
-
121
+
120
122
  return list unless list.any?
121
-
123
+
122
124
  list = resolve_language(list)
123
-
125
+
124
126
  if tabbed_code_examples?
125
127
  list = format_code(list)
126
128
  list = resolve_code(list)
127
129
  list = resolve_tab_title(list)
128
130
  end
129
-
131
+
130
132
  list = sort_contents(list)
131
133
  resolve_active_tab(list)
132
-
134
+
133
135
  list
134
136
  end
135
-
137
+
136
138
  def validate_config
137
139
  return if @config && (@config['source'] || @config['tabs'])
138
-
140
+
139
141
  raise 'Source or tabs must be present in this tabbed_example config'
140
142
  end
141
-
143
+
142
144
  def validate_folder_config
143
145
  return if @tabbed_config && @tabbed_config['tabbed'] == true
144
-
146
+
145
147
  raise 'Tabbed must be set to true in the folder config YAML file'
146
148
  end
147
-
149
+
148
150
  def content_from_source
149
151
  source_path = "#{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}"
150
152
  source_path += '/*' if tabbed_code_examples?
151
153
  source_path += '/*.md' if tabbed_content?
152
-
154
+
153
155
  files = Dir.glob(source_path)
154
156
  raise "Empty content_from_source file list in #{source_path}" if files.empty?
155
-
157
+
156
158
  files.map do |content_path|
157
159
  raise "Could not find content_from_source file: #{content_path}" unless File.exist? content_path
158
-
160
+
159
161
  source = File.read(content_path)
160
-
162
+
161
163
  next generate_tabbed_code_examples(source, content_path) if tabbed_code_examples?
162
-
164
+
163
165
  generate_tabbed_content(source) if tabbed_content?
164
166
  end
165
167
  end
166
-
168
+
167
169
  def content_from_folder
168
170
  source_path = "#{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}"
169
171
  source_path += '/*.md'
170
-
172
+
171
173
  files = Dir.glob(source_path)
172
174
  raise "Empty content_from_source file list in #{source_path}" if files.empty?
173
-
175
+
174
176
  files.map do |content_path|
175
177
  raise "Could not find content_from_source file: #{content_path}" unless File.exist? content_path
176
-
178
+
177
179
  source = File.read(content_path)
178
-
180
+
179
181
  generate_tabbed_content(source)
180
182
  end
181
183
  end
182
-
184
+
183
185
  def content_from_tabs
184
186
  @config['tabs'].map do |title, config|
185
187
  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
-
188
+
187
189
  source = File.read("#{Nexmo::Markdown::Config.docs_base_path}/#{@config['source']}")
188
-
190
+
189
191
  config.symbolize_keys.merge({
190
192
  id: SecureRandom.hex,
191
193
  source: source,
@@ -193,22 +195,22 @@ module Nexmo
193
195
  })
194
196
  end
195
197
  end
196
-
198
+
197
199
  def generate_tabbed_content(source)
198
200
  content = {
199
201
  id: SecureRandom.hex,
200
202
  source: source,
201
203
  }
202
-
204
+
203
205
  content[:frontmatter] = YAML.safe_load(source)
204
206
  content[:language_key] = content[:frontmatter]['language']
205
207
  content[:platform_key] = content[:frontmatter]['platform']
206
208
  content[:tab_title] = content[:frontmatter]['title']
207
209
  content[:body] = Nexmo::Markdown::Renderer.new(options).call(source)
208
-
210
+
209
211
  content
210
212
  end
211
-
213
+
212
214
  def generate_tabbed_code_examples(source, content_path)
213
215
  content = {
214
216
  id: SecureRandom.hex,
@@ -216,24 +218,24 @@ module Nexmo
216
218
  }
217
219
  language_key = File.basename(content_path, '.*').downcase
218
220
  content[:language_key] = language_key
219
-
221
+
220
222
  content
221
223
  end
222
-
224
+
223
225
  def resolve_language(contents)
224
226
  contents.map do |content|
225
227
  if content[:language_key]
226
228
  content[:language] = CodeLanguage.find(content[:language_key])
227
229
  end
228
-
230
+
229
231
  if content[:platform_key]
230
232
  content[:platform] = CodeLanguage.find(content[:platform_key])
231
233
  end
232
-
234
+
233
235
  content
234
236
  end
235
237
  end
236
-
238
+
237
239
  def format_code(contents)
238
240
  contents.each do |content|
239
241
  if content[:from_line] || content[:to_line]
@@ -243,43 +245,42 @@ module Nexmo
243
245
  to_line = (content[:to_line] || total_lines) - 1
244
246
  content[:source] = lines[from_line..to_line].join
245
247
  end
246
-
248
+
247
249
  content[:source].unindent! if content[:unindent]
248
250
  end
249
251
  end
250
-
252
+
251
253
  def resolve_code(contents)
252
254
  contents.map do |content|
253
255
  @formatter ||= Rouge::Formatters::HTML.new
254
256
  lexer = content[:language].lexer
255
257
  highlighted_source = @formatter.format(lexer.lex(content[:source]))
256
- body = <<~HEREDOC
257
- <pre class="Vlt-prism--dark language-#{lexer.tag} Vlt-prism--copy-disabled"><code>#{highlighted_source}</code></pre>
258
- HEREDOC
259
-
258
+
259
+ body = code_snippet_body(lexer, highlighted_source)
260
+
260
261
  content.merge!({ body: body })
261
262
  end
262
263
  end
263
-
264
+
264
265
  def resolve_tab_title(contents)
265
266
  contents.map do |content|
266
267
  content.merge!({ tab_title: content[:language].label })
267
268
  end
268
269
  end
269
-
270
+
270
271
  def sort_contents(contents)
271
272
  contents.sort_by do |content|
272
273
  next content[:language].weight if content[:language]
273
-
274
+
274
275
  next content[:frontmatter]['menu_weight'] || 999 if content[:frontmatter]
275
-
276
+
276
277
  999
277
278
  end
278
279
  end
279
-
280
+
280
281
  def resolve_active_tab(contents)
281
282
  active_index = nil
282
-
283
+
283
284
  if options[:code_language]
284
285
  contents.each_with_index do |content, index|
285
286
  %i[language_key platform_key].each do |key|
@@ -287,10 +288,10 @@ module Nexmo
287
288
  end
288
289
  end
289
290
  end
290
-
291
+
291
292
  @tabs['data-has-initial-tab'] = active_index.present?
292
293
  active_index ||= 0
293
-
294
+
294
295
  contents[active_index][:active] = true
295
296
  end
296
297
  end
@@ -63,7 +63,7 @@ module Nexmo
63
63
  end
64
64
 
65
65
  def first_step
66
- subtasks.first.name
66
+ subtasks.first&.name
67
67
  end
68
68
 
69
69
  def prerequisite?
data/lib/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # :nocov:
2
2
  module Nexmo
3
3
  module Markdown
4
- VERSION = '0.3.0'
4
+ VERSION = '0.3.1'
5
5
  end
6
6
  end
7
7
  # :nocov:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexmo_markdown_renderer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nexmo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-15 00:00:00.000000000 Z
11
+ date: 2020-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: banzai
@@ -246,6 +246,7 @@ files:
246
246
  - lib/nexmo_markdown_renderer/filters/collapsible_filter.rb
247
247
  - lib/nexmo_markdown_renderer/filters/columns_filter.rb
248
248
  - lib/nexmo_markdown_renderer/filters/concept_list_filter.rb
249
+ - lib/nexmo_markdown_renderer/filters/concerns/prism_code_snippet.rb
249
250
  - lib/nexmo_markdown_renderer/filters/dynamic_content_filter.rb
250
251
  - lib/nexmo_markdown_renderer/filters/external_link_filter.rb
251
252
  - lib/nexmo_markdown_renderer/filters/frontmatter_filter.rb