nexmo_markdown_renderer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +54 -0
  4. data/config/code_languages.yml +138 -0
  5. data/config/dynamic_content.yml +1 -0
  6. data/config/locales/en.yml +176 -0
  7. data/lib/nexmo_markdown_renderer.rb +28 -0
  8. data/lib/nexmo_markdown_renderer/cli.rb +13 -0
  9. data/lib/nexmo_markdown_renderer/core_ext/html.rb +7 -0
  10. data/lib/nexmo_markdown_renderer/core_ext/string.rb +14 -0
  11. data/lib/nexmo_markdown_renderer/filters/anchor_filter.rb +14 -0
  12. data/lib/nexmo_markdown_renderer/filters/audio_filter.rb +18 -0
  13. data/lib/nexmo_markdown_renderer/filters/block_escape_filter.rb +21 -0
  14. data/lib/nexmo_markdown_renderer/filters/break_filter.rb +10 -0
  15. data/lib/nexmo_markdown_renderer/filters/code_filter.rb +62 -0
  16. data/lib/nexmo_markdown_renderer/filters/code_snippet_filter.rb +187 -0
  17. data/lib/nexmo_markdown_renderer/filters/code_snippet_list_filter.rb +26 -0
  18. data/lib/nexmo_markdown_renderer/filters/code_snippets_filter.rb +170 -0
  19. data/lib/nexmo_markdown_renderer/filters/collapsible_filter.rb +27 -0
  20. data/lib/nexmo_markdown_renderer/filters/columns_filter.rb +47 -0
  21. data/lib/nexmo_markdown_renderer/filters/concept_list_filter.rb +30 -0
  22. data/lib/nexmo_markdown_renderer/filters/dynamic_content_filter.rb +28 -0
  23. data/lib/nexmo_markdown_renderer/filters/external_link_filter.rb +29 -0
  24. data/lib/nexmo_markdown_renderer/filters/frontmatter_filter.rb +11 -0
  25. data/lib/nexmo_markdown_renderer/filters/heading_filter.rb +57 -0
  26. data/lib/nexmo_markdown_renderer/filters/i18n/frontmatter_filter.rb +16 -0
  27. data/lib/nexmo_markdown_renderer/filters/i18n/smartling_converter_filter.rb +22 -0
  28. data/lib/nexmo_markdown_renderer/filters/icon_filter.rb +19 -0
  29. data/lib/nexmo_markdown_renderer/filters/indent_filter.rb +17 -0
  30. data/lib/nexmo_markdown_renderer/filters/inline_escape_filter.rb +14 -0
  31. data/lib/nexmo_markdown_renderer/filters/js_sequence_diagram_filter.rb +18 -0
  32. data/lib/nexmo_markdown_renderer/filters/label_filter.rb +29 -0
  33. data/lib/nexmo_markdown_renderer/filters/language_filter.rb +12 -0
  34. data/lib/nexmo_markdown_renderer/filters/markdown_filter.rb +81 -0
  35. data/lib/nexmo_markdown_renderer/filters/mermaid_filter.rb +29 -0
  36. data/lib/nexmo_markdown_renderer/filters/modal_filter.rb +37 -0
  37. data/lib/nexmo_markdown_renderer/filters/partial_filter.rb +29 -0
  38. data/lib/nexmo_markdown_renderer/filters/php_inliner_filter.rb +11 -0
  39. data/lib/nexmo_markdown_renderer/filters/screenshot_filter.rb +22 -0
  40. data/lib/nexmo_markdown_renderer/filters/tab_filter.rb +298 -0
  41. data/lib/nexmo_markdown_renderer/filters/techio_filter.rb +20 -0
  42. data/lib/nexmo_markdown_renderer/filters/tooltip_filter.rb +18 -0
  43. data/lib/nexmo_markdown_renderer/filters/unfreeze_filter.rb +16 -0
  44. data/lib/nexmo_markdown_renderer/filters/use_case_list_filter.rb +20 -0
  45. data/lib/nexmo_markdown_renderer/initializers/doc_finder.rb +5 -0
  46. data/lib/nexmo_markdown_renderer/initializers/i18n.rb +4 -0
  47. data/lib/nexmo_markdown_renderer/initializers/redcarpet.rb +7 -0
  48. data/lib/nexmo_markdown_renderer/markdown_renderer.rb +47 -0
  49. data/lib/nexmo_markdown_renderer/models/code_language.rb +79 -0
  50. data/lib/nexmo_markdown_renderer/models/code_snippet.rb +72 -0
  51. data/lib/nexmo_markdown_renderer/models/concept.rb +83 -0
  52. data/lib/nexmo_markdown_renderer/models/tutorial.rb +148 -0
  53. data/lib/nexmo_markdown_renderer/models/use_case.rb +81 -0
  54. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/android.rb +25 -0
  55. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/base.rb +12 -0
  56. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/curl.rb +29 -0
  57. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/dotnet.rb +23 -0
  58. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/java.rb +32 -0
  59. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/javascript.rb +23 -0
  60. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/kotlin.rb +25 -0
  61. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/objective_c.rb +25 -0
  62. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/php.rb +23 -0
  63. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/python.rb +23 -0
  64. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/ruby.rb +23 -0
  65. data/lib/nexmo_markdown_renderer/services/code_snippet_renderer/swift.rb +25 -0
  66. data/lib/nexmo_markdown_renderer/services/doc_finder.rb +119 -0
  67. data/lib/nexmo_markdown_renderer/views/code_snippets/_application_messages_dispatch.html.erb +9 -0
  68. data/lib/nexmo_markdown_renderer/views/code_snippets/_application_rtc.html.erb +28 -0
  69. data/lib/nexmo_markdown_renderer/views/code_snippets/_application_voice.html.erb +24 -0
  70. data/lib/nexmo_markdown_renderer/views/code_snippets/_code_only.html.erb +6 -0
  71. data/lib/nexmo_markdown_renderer/views/code_snippets/_configure_client.html.erb +20 -0
  72. data/lib/nexmo_markdown_renderer/views/code_snippets/_dependencies.html.erb +11 -0
  73. data/lib/nexmo_markdown_renderer/views/code_snippets/_write_code.html.erb +13 -0
  74. data/lib/nexmo_markdown_renderer/views/code_snippets/list/plain.html.erb +10 -0
  75. data/lib/nexmo_markdown_renderer/views/concepts/list/plain.html.erb +5 -0
  76. data/lib/nexmo_markdown_renderer/views/use_case/_index.html.erb +41 -0
  77. data/lib/nexmo_markdown_renderer/views/use_case/index.html.erb +48 -0
  78. data/lib/nexmo_markdown_renderer/views/use_case/list/plain.html.erb +5 -0
  79. data/lib/nexmo_markdown_renderer/views/use_case/show.html.erb +8 -0
  80. data/lib/version.rb +7 -0
  81. metadata +322 -0
@@ -0,0 +1,27 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class CollapsibleFilter < Banzai::Filter
4
+ # Transforms matching input into a collapsible HTML element on NDP.
5
+ # Matching input example: | ## Heading\n|\nContent\n\n
6
+
7
+ def call(input)
8
+ input.gsub(/^\|\s(\#{1,6})(\s)?(.+?)\n^\|\n(.+?)\n\n/m) do |_s|
9
+ heading = $3
10
+ body = $4.gsub(/^\|\n/, "\n")
11
+ body = body.gsub(/^\|\s/, '')
12
+ parsed_body = Nexmo::Markdown::Renderer.new.call(body)
13
+
14
+ <<~HEREDOC
15
+ <div class="Vlt-accordion Vlt-box Vlt-box--lesspadding Nxd-accordion-emphasis">
16
+ <h5 class="Vlt-accordion__trigger" tabindex="0">#{heading}</h5>
17
+ <div class="Vlt-accordion__content Vlt-accordion__content--noborder">
18
+ #{parsed_body}
19
+ </div>
20
+ </div>
21
+ HEREDOC
22
+ end
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,47 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class ColumnsFilter < Banzai::Filter
4
+ def call(input)
5
+ input.gsub!(%r{{column\:([1-4])\/([1-4])}\n(.+?){end}}m) do
6
+ s = []
7
+ s << row_start if $1 == '1'
8
+ s << column_start($2)
9
+ s << $3
10
+ s << column_end
11
+ s << row_end if $1 == $2
12
+ s.join('')
13
+ end
14
+
15
+ input
16
+ end
17
+
18
+ private
19
+
20
+ def row_start
21
+ "FREEZESTART#{Base64.urlsafe_encode64('<div class="row">')}FREEZEEND\n"
22
+ end
23
+
24
+ def row_end
25
+ close_tag
26
+ end
27
+
28
+ def close_tag
29
+ "FREEZESTART#{Base64.urlsafe_encode64('</div>')}FREEZEEND"
30
+ end
31
+
32
+ def column_start(columns)
33
+ html = "<div class='column small-12 medium-#{part_size(columns)}'>"
34
+ "FREEZESTART#{Base64.urlsafe_encode64(html)}FREEZEEND\n"
35
+ end
36
+
37
+ def column_end
38
+ "FREEZESTART#{Base64.urlsafe_encode64('</div>')}FREEZEEND\n"
39
+ end
40
+
41
+ def part_size(columns)
42
+ 12 / Integer(columns)
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class ConceptListFilter < Banzai::Filter
4
+ def call(input)
5
+ input.gsub(/```concept_list(.+?)```/m) do |_s|
6
+ config = YAML.safe_load($1)
7
+
8
+ raise 'concept_list filter takes a YAML config' if config.nil?
9
+ raise "concept_list filter requires 'product' or 'concepts' key" unless config['product'] || config['concepts']
10
+
11
+ if config['product']
12
+ @product = config['product']
13
+ @concepts = Nexmo::Markdown::Concept.by_product(@product, @options[:language])
14
+ elsif config['concepts']
15
+ @concepts = Nexmo::Markdown::Concept.by_name(config['concepts'], @options[:language])
16
+ end
17
+
18
+ @concepts.reject!(&:ignore_in_list)
19
+
20
+ return '' if @concepts.empty?
21
+
22
+ erb = File.read("#{GEM_ROOT}/lib/nexmo_markdown_renderer/views/concepts/list/plain.html.erb")
23
+ html = ERB.new(erb).result(binding)
24
+ "FREEZESTART#{Base64.urlsafe_encode64(html)}FREEZEEND"
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class DynamicContentFilter < Banzai::Filter
4
+ def call(input)
5
+ input.gsub(/(\s|^)\[\~(.+?)\~\](\s|$)/) do
6
+ content = environment_value($2) || config_value($2) || "VALUE NOT SET: #{$2}"
7
+ "#{$1}#{content}#{$3}"
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def environment_value(key)
14
+ return nil unless ENV['DYNAMIC_CONTENT']
15
+
16
+ @environment_dynamic_content ||= YAML.safe_load(ENV['DYNAMIC_CONTENT'])
17
+ @environment_dynamic_content ||= YAML.safe_load(temp)
18
+ @environment_dynamic_content[key]
19
+ end
20
+
21
+ def config_value(key)
22
+ @config_dynamic_content ||= YAML.load_file("#{GEM_ROOT}/config/dynamic_content.yml")
23
+ @config_dynamic_content[key]
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class ExternalLinkFilter < Banzai::Filter
4
+ def call(input)
5
+ @input = input
6
+
7
+ document.css('a').each_with_index do |link, _index|
8
+ if link['href']&.start_with?('http') && link['class'] && !link['class'].include?('no-external-marker')
9
+ link['target'] = '_blank'
10
+ if link.css('svg').empty?
11
+ link.add_child <<~HEREDOC
12
+ &nbsp;<svg class="Vlt-icon Vlt-icon--smaller Vlt-icon--text-bottom Vlt-blue-dark"><use xlink:href="/symbol/volta-icons.svg#Vlt-icon-open"></use></svg>
13
+ HEREDOC
14
+ end
15
+ end
16
+ end
17
+
18
+ @document.to_html
19
+ end
20
+
21
+ private
22
+
23
+ def document
24
+ @document ||= Nokogiri::HTML::DocumentFragment.parse(@input)
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class FrontmatterFilter < Banzai::Filter
4
+ def call(input)
5
+ # Remove frontmatter from the input
6
+ input.gsub(/\A(---.+?---)/mo, '')
7
+ end
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,57 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class HeadingFilter < Banzai::Filter
4
+ def call(input)
5
+ @input = input
6
+ @headings = []
7
+ heading_tag_list = %w[h1 h2 h3 h4 h5 h6]
8
+ headings = document.children.select do |child|
9
+ heading_tag_list.include? child.name
10
+ end
11
+
12
+ headings.each do |heading|
13
+ parameterized_heading = parameterized_heading_without_collision(heading)
14
+ heading['id'] = parameterized_heading
15
+ heading['data-id'] = SecureRandom.hex
16
+ heading['class'] = heading[:class]
17
+ heading['class'] += ' Vlt-title--icon'
18
+
19
+ heading.prepend_child <<~HEREDOC
20
+ <a href="##{parameterized_heading}" class="heading-permalink">
21
+ <svg class="Vlt-grey"><use xlink:href=\"/symbol/volta-icons.svg#Vlt-icon-link\" /></svg>
22
+ </a>
23
+ HEREDOC
24
+ end
25
+
26
+ @document.to_html
27
+ end
28
+
29
+ private
30
+
31
+ def document
32
+ @document ||= Nokogiri::HTML::DocumentFragment.parse(@input)
33
+ end
34
+
35
+ def parameterized_heading_without_collision(heading)
36
+ parameterized_heading = nil
37
+ index = nil
38
+
39
+ loop do
40
+ if index
41
+ parameterized_heading = "#{heading.text.parameterize}-#{index}"
42
+ index += 1
43
+ else
44
+ parameterized_heading = heading.text.parameterize
45
+ index = 2
46
+ end
47
+
48
+ break if @headings.exclude? parameterized_heading
49
+ end
50
+
51
+ @headings << parameterized_heading
52
+ parameterized_heading
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,16 @@
1
+ module Nexmo
2
+ module Markdown
3
+ module I18n
4
+ class FrontmatterFilter < Banzai::Filter
5
+ def call(input)
6
+ input.gsub(/\A(---.+?---)/mo) do |frontmatter|
7
+ frontmatter.gsub(/(\w*:)/) do |_key|
8
+ "```#{$1}```"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ module Nexmo
2
+ module Markdown
3
+ module I18n
4
+ class SmartlingConverterFilter < Banzai::Filter
5
+ def call(input)
6
+ input = input.gsub(/\A\*\*\* \*\* \* \*\* \*\*\*\n*(.*)\n*------------------------------------------/m) do |_frontmatter|
7
+ front = $1.gsub(/`(.*):`(.*)/) do |_config|
8
+ "#{$1}:#{$2}"
9
+ end
10
+ <<~FRONTMATTER
11
+ ---
12
+ #{front}
13
+ ---
14
+ FRONTMATTER
15
+ end
16
+ input.gsub('\-', '-').gsub('\|', '|')
17
+ end
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class IconFilter < Banzai::Filter
4
+ def call(input)
5
+ input.gsub!('✅', '<svg class="Vlt-green Vlt-icon Vlt-icon--small"><use xlink:href="/symbol/volta-icons.svg#Vlt-icon-check" /></svg>')
6
+ input.gsub!('❌', '<svg class="Vlt-red Vlt-icon Vlt-icon--small"><use xlink:href="/symbol/volta-icons.svg#Vlt-icon-cross" /></svg>')
7
+
8
+ input.gsub!(/\[icon="(.+?)"\]/) do
9
+ <<~HEREDOC
10
+ <svg class="Vlt-green Vlt-icon Vlt-icon--small"><use xlink:href="/symbol/volta-icons.svg#Vlt-icon-#{$1}" /></svg>
11
+ HEREDOC
12
+ end
13
+
14
+ input
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class IndentFilter < Banzai::Filter
4
+ def call(input)
5
+ input.gsub(/^^\s{4}\-\>\s(.+?)$/) do
6
+ body = Nexmo::Markdown::Renderer.new.call($1)
7
+ <<~HEREDOC
8
+ <div class="indent">
9
+ #{body}
10
+ </div>
11
+ HEREDOC
12
+ end
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class InlineEscapeFilter < Banzai::Filter
4
+ def call(input)
5
+ # Freeze to prevent Markdown formatting
6
+ input.gsub(/``(.+?)``/) do |_s|
7
+ frozen_code = Base64.urlsafe_encode64("<code>#{$1}</code>")
8
+ "FREEZESTART#{frozen_code}FREEZEEND"
9
+ end
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class JsSequenceDiagramFilter < Banzai::Filter
4
+ def call(input)
5
+ input.gsub(/```js_sequence_diagram(.+?)```/m) do |_s|
6
+ diagram = <<~HEREDOC
7
+ <div class="js-diagram">
8
+ #{$1}
9
+ </div>
10
+ HEREDOC
11
+
12
+ "FREEZESTART#{Base64.urlsafe_encode64(diagram)}FREEZEEND"
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class LabelFilter < Banzai::Filter
4
+ def call(input)
5
+ input.gsub(/\[(GET|POST|PUT|DELETE|OPTIONS)\]/i) do |_s|
6
+ "<span class='Vlt-badge #{class_name($1)}'>#{$1}</span> "
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def class_name(text)
13
+ case text
14
+ when 'POST'
15
+ 'Vlt-badge--green'
16
+ when 'GET'
17
+ 'Vlt-badge--blue'
18
+ when 'DELETE'
19
+ 'Vlt-badge--red'
20
+ when 'PUT'
21
+ 'Vlt-badge--yellow'
22
+ when 'OPTIONS'
23
+ 'Vlt-badge--grey'
24
+ end
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class LanguageFilter < Banzai::Filter
4
+ def call(input)
5
+ input.gsub(/\[(.+?)\]\(lang:.+?(?:'(.+?)'|"(.+?)")\)/) do |_s|
6
+ "<span lang='#{$2}'>#{$1}</span>"
7
+ end
8
+ end
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,81 @@
1
+ module Nexmo
2
+ module Markdown
3
+ class MarkdownFilter < Banzai::Filter
4
+ def call(input)
5
+ markdown.render(input)
6
+ end
7
+
8
+ private
9
+
10
+ def renderer
11
+ @renderer ||= VoltaRender.new(options)
12
+ end
13
+
14
+ def markdown
15
+ @markdown ||= Redcarpet::Markdown.new(renderer, {
16
+ no_intra_emphasis: true,
17
+ tables: true,
18
+ strikethrough: true,
19
+ superscript: true,
20
+ underline: true,
21
+ highlight: true,
22
+ fenced_code_blocks: true,
23
+ disable_indented_code_blocks: true,
24
+ start_inline: true,
25
+ })
26
+ end
27
+ end
28
+
29
+ class VoltaRender < HTML
30
+ def initialize(options)
31
+ @options = options
32
+ super(options)
33
+ end
34
+
35
+ def paragraph(text)
36
+ return text if @options[:skip_paragraph_surround]
37
+
38
+ "<p>#{text}</p>"
39
+ end
40
+
41
+ def table(header, body)
42
+ '<div class="Vlt-table Vlt-table--data Vlt-table--bordered">' \
43
+ '<table>' \
44
+ "<thead>#{header}</thead>" \
45
+ "<tbody>#{body}</tbody>" \
46
+ '</table>' \
47
+ '</div>'
48
+ end
49
+
50
+ def block_quote(quote)
51
+ '<div class="Vlt-callout Vlt-callout--tip">' \
52
+ '<i></i>' \
53
+ '<div class="Vlt-callout__content">' \
54
+ "#{quote}" \
55
+ '</div>' \
56
+ '</div>'
57
+ end
58
+
59
+ def image(link, _title, _alt_text)
60
+ '<figure>' \
61
+ '<img src="'\
62
+ "#{link}"\
63
+ '" alt="#{alt_text}">' \
64
+ '</figure>'
65
+ end
66
+
67
+ def list(contents, list_type)
68
+ if "#{list_type}" == 'unordered'
69
+ '<ul class="Vlt-list Vlt-list--simple">' \
70
+ "#{contents}" \
71
+ '</ul>'
72
+ else
73
+ '<ol class="Vlt-list Vlt-list--simple">' \
74
+ "#{contents}" \
75
+ '</ol>' \
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+