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,18 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class TooltipFilter < Banzai::Filter
|
4
|
+
def call(input)
|
5
|
+
input.gsub(/\^\[([a-zA-Z0-9\s:\-]+)\]\((.+?)\)/) do
|
6
|
+
tooltip = <<~HEREDOC
|
7
|
+
<span class="Vlt-tooltip Vlt-tooltip--top" title="#{$2}" tabindex="0">
|
8
|
+
#{$1}
|
9
|
+
<svg class="Vlt-icon Vlt-icon--smaller Vlt-icon--text-bottom Vlt-blue" aria-hidden="true"><use xlink:href="/symbol/volta-icons.svg#Vlt-icon-help-negative"/></svg>
|
10
|
+
</span>
|
11
|
+
HEREDOC
|
12
|
+
|
13
|
+
"FREEZESTART#{Base64.urlsafe_encode64(tooltip)}FREEZEEND"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class UnfreezeFilter < Banzai::Filter
|
4
|
+
def call(input)
|
5
|
+
input.gsub!('FREEZESTARTFREEZEEND', '')
|
6
|
+
input.gsub!('<p>FREEZESTART', 'FREEZESTART')
|
7
|
+
input.gsub!('FREEZEEND</p>', 'FREEZEEND')
|
8
|
+
|
9
|
+
input.gsub!(/FREEZESTART(.+?)FREEZEEND/m) do |_s|
|
10
|
+
Base64.urlsafe_decode64($1).force_encoding(Encoding::UTF_8)
|
11
|
+
end
|
12
|
+
input
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class UseCaseListFilter < Banzai::Filter
|
4
|
+
def call(input)
|
5
|
+
input.gsub(/```use_cases(.+?)```/m) do |_s|
|
6
|
+
config = YAML.safe_load($1)
|
7
|
+
@product = config['product']
|
8
|
+
@use_cases = Nexmo::Markdown::UseCase.by_product(@product)
|
9
|
+
|
10
|
+
# Default to plain layout, but allow people to override it
|
11
|
+
config['layout'] = 'list/plain' unless config['layout']
|
12
|
+
|
13
|
+
erb = File.read("#{GEM_ROOT}/lib/nexmo_markdown_renderer/views/use_case/#{config['layout']}.html.erb")
|
14
|
+
html = ERB.new(erb).result(binding)
|
15
|
+
"FREEZESTART#{Base64.urlsafe_encode64(html)}FREEZEEND"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class Renderer < Banzai::Pipeline
|
4
|
+
def initialize(options = {})
|
5
|
+
super(
|
6
|
+
# As Markdown
|
7
|
+
FrontmatterFilter,
|
8
|
+
PhpInlinerFilter,
|
9
|
+
InlineEscapeFilter,
|
10
|
+
BlockEscapeFilter,
|
11
|
+
ScreenshotFilter,
|
12
|
+
AnchorFilter,
|
13
|
+
AudioFilter,
|
14
|
+
DynamicContentFilter,
|
15
|
+
TooltipFilter,
|
16
|
+
CollapsibleFilter,
|
17
|
+
TabFilter.new(options),
|
18
|
+
CodeSnippetsFilter.new(options),
|
19
|
+
CodeSnippetFilter.new(options),
|
20
|
+
CodeFilter,
|
21
|
+
IndentFilter,
|
22
|
+
ModalFilter,
|
23
|
+
JsSequenceDiagramFilter,
|
24
|
+
MermaidFilter,
|
25
|
+
PartialFilter.new(options),
|
26
|
+
TechioFilter,
|
27
|
+
UseCaseListFilter,
|
28
|
+
CodeSnippetListFilter,
|
29
|
+
ConceptListFilter.new(options),
|
30
|
+
LanguageFilter,
|
31
|
+
ColumnsFilter,
|
32
|
+
MarkdownFilter.new(options),
|
33
|
+
|
34
|
+
# As HTML
|
35
|
+
HeadingFilter,
|
36
|
+
LabelFilter.new(options),
|
37
|
+
BreakFilter,
|
38
|
+
UnfreezeFilter,
|
39
|
+
IconFilter,
|
40
|
+
ExternalLinkFilter
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class CodeLanguage
|
4
|
+
include ActiveModel::Model
|
5
|
+
attr_accessor :key, :label, :type, :dependencies, :unindent, :icon, :run_command
|
6
|
+
attr_writer :weight, :linkable, :languages, :lexer
|
7
|
+
|
8
|
+
def weight
|
9
|
+
@weight || 999
|
10
|
+
end
|
11
|
+
|
12
|
+
def linkable?
|
13
|
+
return true if @linkable.nil?
|
14
|
+
@linkable
|
15
|
+
end
|
16
|
+
|
17
|
+
def lexer
|
18
|
+
return Rouge::Lexers::PHP.new({ start_inline: true }) if @lexer == 'php'
|
19
|
+
Rouge::Lexer.find(@lexer) || Rouge::Lexer.find('text')
|
20
|
+
end
|
21
|
+
|
22
|
+
def languages
|
23
|
+
@languages ||= []
|
24
|
+
@languages.map do |language|
|
25
|
+
self.class.find(language)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.languages
|
30
|
+
where_type('languages')
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.frameworks
|
34
|
+
where_type('platforms')
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.terminal_programs
|
38
|
+
where_type('terminal_programs')
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.data
|
42
|
+
where_type('data')
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.all
|
46
|
+
languages + frameworks + terminal_programs + data
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.exists?(key)
|
50
|
+
all.detect { |lang| lang.key == key }
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.find(key)
|
54
|
+
raise 'Key is missing' unless key
|
55
|
+
code_language = all.detect { |lang| lang.key == key }
|
56
|
+
raise "Language #{key} does not exist." unless code_language
|
57
|
+
code_language
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.linkable
|
61
|
+
all.select(&:linkable?)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.route_constraint
|
65
|
+
{ code_language: Regexp.new(linkable.map(&:key).compact.join('|')) }
|
66
|
+
end
|
67
|
+
|
68
|
+
private_class_method def self.where_type(type)
|
69
|
+
config[type].map do |key, attributes|
|
70
|
+
new(attributes.merge({ key: key, type: type }))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private_class_method def self.config
|
75
|
+
@config ||= YAML.load_file('./config/code_languages.yml')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class CodeSnippet
|
4
|
+
include ActiveModel::Model
|
5
|
+
attr_accessor :title, :product, :category, :navigation_weight, :document_path, :url
|
6
|
+
|
7
|
+
def self.by_product(product)
|
8
|
+
all.select do |block|
|
9
|
+
block.product == product
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.all
|
14
|
+
blocks = files.map do |document_path|
|
15
|
+
document = File.read(document_path)
|
16
|
+
product = extract_product(document_path)
|
17
|
+
|
18
|
+
frontmatter = YAML.safe_load(document)
|
19
|
+
|
20
|
+
Nexmo::Markdown::CodeSnippet.new({
|
21
|
+
title: frontmatter['title'],
|
22
|
+
navigation_weight: frontmatter['navigation_weight'] || 999,
|
23
|
+
product: product,
|
24
|
+
document_path: document_path,
|
25
|
+
category: extract_category(document_path),
|
26
|
+
url: generate_url(document_path),
|
27
|
+
})
|
28
|
+
end
|
29
|
+
|
30
|
+
blocks.sort_by(&:navigation_weight)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.generate_url(path)
|
34
|
+
'/' + path.gsub(%r{#{origin}/\w{2}/}, '').gsub('.md', '')
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.extract_product(path)
|
38
|
+
# Remove the prefix
|
39
|
+
path = path.gsub!(%r{#{origin}/\w{2}/}, '')
|
40
|
+
|
41
|
+
# Each file is in the form code-snippets/<title>.md, so let's remove everything after code-snippets
|
42
|
+
path = path.gsub(%r{/code-snippets/.*}, '')
|
43
|
+
|
44
|
+
path
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.extract_category(path)
|
48
|
+
# Remove the prefix
|
49
|
+
path = path.gsub(%r{#{origin}/\w{2}/}, '')
|
50
|
+
|
51
|
+
# Each file is in the form code-snippets/<title>.md, so let's capture everything after code-snippets
|
52
|
+
path = path.gsub(%r{.*/code-snippets/(.*)$}, '\1')
|
53
|
+
|
54
|
+
parts = path.split('/')
|
55
|
+
parts = parts[0...-1]
|
56
|
+
|
57
|
+
return nil if parts.empty?
|
58
|
+
|
59
|
+
parts.join('/').tr('-', ' ').humanize
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.files
|
63
|
+
Dir.glob("#{origin}/**/code-snippets/**/*.md")
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.origin
|
67
|
+
"#{ENV['DOCS_BASE_PATH']}/_documentation"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class Concept
|
4
|
+
include ActiveModel::Model
|
5
|
+
|
6
|
+
ORIGIN = "#{ENV['DOCS_BASE_PATH']}/_documentation".freeze
|
7
|
+
|
8
|
+
FILES = [
|
9
|
+
Dir.glob("#{ORIGIN}/#{::I18n.default_locale}/**/guides/**/*.md"),
|
10
|
+
Dir.glob("#{ORIGIN}/#{::I18n.default_locale}/**/concepts/**/*.md"),
|
11
|
+
].flatten
|
12
|
+
|
13
|
+
attr_accessor :title, :product, :description, :navigation_weight, :document_path, :url, :ignore_in_list
|
14
|
+
|
15
|
+
def self.by_name(names, language)
|
16
|
+
matches = all(language).select do |block|
|
17
|
+
concept = "#{block.product}/#{block.filename}"
|
18
|
+
match = names.include?(concept)
|
19
|
+
names.delete(concept) if match
|
20
|
+
match
|
21
|
+
end
|
22
|
+
|
23
|
+
raise "Could not find concepts: #{names.join(', ')}" unless names.empty?
|
24
|
+
matches
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.by_product(product, language)
|
28
|
+
all(language).select do |block|
|
29
|
+
block.product == product
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def filename
|
34
|
+
Pathname(document_path).basename.to_s.gsub('.md', '')
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.all(language)
|
38
|
+
blocks = files(language).map do |document_path|
|
39
|
+
document = File.read(document_path)
|
40
|
+
product = extract_product(document_path)
|
41
|
+
|
42
|
+
frontmatter = YAML.safe_load(document)
|
43
|
+
|
44
|
+
Nexmo::Markdown::Concept.new({
|
45
|
+
title: frontmatter['title'],
|
46
|
+
description: frontmatter['description'],
|
47
|
+
navigation_weight: frontmatter['navigation_weight'] || 999,
|
48
|
+
ignore_in_list: frontmatter['ignore_in_list'],
|
49
|
+
product: product,
|
50
|
+
document_path: document_path,
|
51
|
+
url: generate_url(document_path, language),
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
blocks.sort_by(&:navigation_weight)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.generate_url(path, language)
|
59
|
+
'/' + path.gsub("#{ORIGIN}/#{language}/", '').gsub('.md', '')
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.extract_product(path)
|
63
|
+
# Remove the prefix
|
64
|
+
path = path.gsub!(%r{#{ORIGIN}\/[a-z]{2}\/}, '')
|
65
|
+
|
66
|
+
# Each file is in the form guides/<title>.md, so let's remove the last two segments
|
67
|
+
parts = path.split('/')
|
68
|
+
parts = parts[0...-2]
|
69
|
+
|
70
|
+
# What's left once we remove the start and end of the path is our product name. This could be any number
|
71
|
+
# of parts, but it's generally 1-2
|
72
|
+
parts.join('/')
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.files(language)
|
76
|
+
FILES.each_with_object([]) do |file, array|
|
77
|
+
document = file.gsub("#{ORIGIN}/#{::I18n.default_locale}/", '')
|
78
|
+
array << Nexmo::Markdown::DocFinder.find(root: ORIGIN, document: document, language: language)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module Nexmo
|
2
|
+
module Markdown
|
3
|
+
class Tutorial
|
4
|
+
include ActiveModel::Model
|
5
|
+
attr_accessor :raw, :name, :current_step, :current_product, :title, :description, :products, :subtasks, :prerequisites
|
6
|
+
|
7
|
+
def content_for(step_name)
|
8
|
+
if ['introduction', 'conclusion'].include? step_name
|
9
|
+
raise "Invalid step: #{step_name}" unless raw[step_name]
|
10
|
+
|
11
|
+
return raw[step_name]['content']
|
12
|
+
end
|
13
|
+
|
14
|
+
path = Nexmo::Markdown::DocFinder.find(
|
15
|
+
root: self.class.task_content_path,
|
16
|
+
document: step_name,
|
17
|
+
language: ::I18n.locale
|
18
|
+
)
|
19
|
+
|
20
|
+
File.read(path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def first_step
|
24
|
+
subtasks.first['path']
|
25
|
+
end
|
26
|
+
|
27
|
+
def prerequisite?
|
28
|
+
prerequisites.pluck('path').include?(@current_step)
|
29
|
+
end
|
30
|
+
|
31
|
+
def next_step
|
32
|
+
current_task_index = subtasks.pluck('path').index(@current_step)
|
33
|
+
return nil unless current_task_index
|
34
|
+
|
35
|
+
subtasks[current_task_index + 1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def previous_step
|
39
|
+
current_task_index = subtasks.pluck('path').index(@current_step)
|
40
|
+
return nil unless current_task_index
|
41
|
+
return nil if current_task_index <= 0
|
42
|
+
|
43
|
+
subtasks[current_task_index - 1]
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.load(name, current_step, current_product = nil)
|
47
|
+
document_path = Nexmo::Markdown::DocFinder.find(
|
48
|
+
root: 'config/tutorials',
|
49
|
+
document: name,
|
50
|
+
language: ::I18n.default_locale,
|
51
|
+
format: 'yml'
|
52
|
+
)
|
53
|
+
config = YAML.safe_load(File.read(document_path))
|
54
|
+
current_product ||= config['products'].first
|
55
|
+
|
56
|
+
Nexmo::Markdown::Tutorial.new({
|
57
|
+
raw: config,
|
58
|
+
name: name,
|
59
|
+
current_step: current_step,
|
60
|
+
current_product: current_product,
|
61
|
+
title: config['title'],
|
62
|
+
description: config['description'],
|
63
|
+
products: config['products'],
|
64
|
+
prerequisites: load_prerequisites(config['prerequisites'], current_step),
|
65
|
+
subtasks: load_subtasks(config['introduction'], config['prerequisites'], config['tasks'], config['conclusion'], current_step),
|
66
|
+
})
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.load_prerequisites(prerequisites, current_step)
|
70
|
+
return [] unless prerequisites
|
71
|
+
|
72
|
+
prerequisites.map do |t|
|
73
|
+
t_path = Nexmo::Markdown::DocFinder.find(
|
74
|
+
root: task_content_path,
|
75
|
+
document: t,
|
76
|
+
language: ::I18n.locale
|
77
|
+
)
|
78
|
+
raise "Prerequisite not found: #{t}" unless File.exist? t_path
|
79
|
+
|
80
|
+
content = File.read(t_path)
|
81
|
+
prereq = YAML.safe_load(content)
|
82
|
+
{
|
83
|
+
'path' => t,
|
84
|
+
'title' => prereq['title'],
|
85
|
+
'description' => prereq['description'],
|
86
|
+
'is_active' => t == current_step,
|
87
|
+
'content' => content,
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.load_subtasks(introduction, prerequisites, tasks, conclusion, current_step)
|
93
|
+
tasks ||= []
|
94
|
+
|
95
|
+
tasks = tasks.map do |t|
|
96
|
+
t_path = Nexmo::Markdown::DocFinder.find(
|
97
|
+
root: task_content_path,
|
98
|
+
document: t,
|
99
|
+
language: ::I18n.locale
|
100
|
+
)
|
101
|
+
raise "Subtask not found: #{t}" unless File.exist? t_path
|
102
|
+
|
103
|
+
subtask_config = YAML.safe_load(File.read(t_path))
|
104
|
+
{
|
105
|
+
'path' => t,
|
106
|
+
'title' => subtask_config['title'],
|
107
|
+
'description' => subtask_config['description'],
|
108
|
+
'is_active' => t == current_step,
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
if prerequisites
|
113
|
+
tasks.unshift({
|
114
|
+
'path' => 'prerequisites',
|
115
|
+
'title' => 'Prerequisites',
|
116
|
+
'description' => 'Everything you need to complete this task',
|
117
|
+
'is_active' => current_step == 'prerequisites',
|
118
|
+
})
|
119
|
+
end
|
120
|
+
|
121
|
+
if introduction
|
122
|
+
tasks.unshift({
|
123
|
+
'path' => 'introduction',
|
124
|
+
'title' => introduction['title'],
|
125
|
+
'description' => introduction['description'],
|
126
|
+
'is_active' => current_step == 'introduction',
|
127
|
+
})
|
128
|
+
end
|
129
|
+
|
130
|
+
if conclusion
|
131
|
+
tasks.push({
|
132
|
+
'path' => 'conclusion',
|
133
|
+
'title' => conclusion['title'],
|
134
|
+
'description' => conclusion['description'],
|
135
|
+
'is_active' => current_step == 'conclusion',
|
136
|
+
})
|
137
|
+
end
|
138
|
+
|
139
|
+
tasks
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.task_content_path
|
143
|
+
"#{ENV['DOCS_BASE_PATH']}/_tutorials"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|