module Nexmo module OAS module Renderer module Filters class CodeSnippets < Banzai::Filter def call(input) input.gsub(/^(\s*)```code_snippets(.+?)```/m) do |_s| @indentation = $1 @config = YAML.safe_load($2) validate_config html end end private def create_tabs(content) tab = Nokogiri::XML::Element.new 'li', @document tab['class'] = 'Vlt-tabs__link' tab['class'] += ' Vlt-tabs__link_active' if content[:active] tab['aria-selected'] = 'true' if content[:active] if content['language'] tab['data-language'] = content['language'] tab['data-language-type'] = content['language_type'] tab['data-language-linkable'] = true end tab_link = Nokogiri::XML::Element.new 'a', @document tab_link.inner_html = "" + content['title'] + '' tab_link['class'] = 'tab-link' tab.add_child(tab_link) @tabs.add_child(tab) end def create_content(content) element = Nokogiri::XML::Element.new 'div', @document element['id'] = content['id'] element['class'] = 'Vlt-tabs__panel' element['class'] += ' Vlt-tabs__panel_active' if content[:active] element.inner_html = content[:body] @tabs_content.add_child(element) end def html html = <<~HEREDOC
HEREDOC @document = Nokogiri::HTML::DocumentFragment.parse(html) @tabs = @document.at_css('.Vlt-tabs__header--bordered') @tabs_content = @document.at_css('.Vlt-tabs__content') contents.each do |content| create_tabs(content) create_content(content) end source = @document.to_html "#{@indentation}FREEZESTART#{Base64.urlsafe_encode64(source)}FREEZEEND" end def contents list = content_from_source list ||= [] return list unless list.any? list = sort_contents(list) resolve_active_tab(list) list end def validate_config return if @config && @config['source'] raise 'A source key must be present in this building_blocks config' end def content_from_source source_path = "#{@config['source']}/*.yml" files = Dir[source_path] raise "No .yml files found for #{@config['source']} code snippets" if files.empty? files.map do |content_path| source = File.read(content_path) # Load the defaults for this language filename = File.basename(content_path, '.yml') defaults = CodeLanguageAPI.find(filename) content = YAML.safe_load(source) content['source'] = source content['id'] = SecureRandom.hex content['title'] ||= defaults.label content['language'] ||= defaults.key content['language_type'] ||= defaults.type content['dependencies'] ||= defaults.dependencies content['icon'] = defaults.icon content['weight'] ||= defaults.weight content['run_command'] ||= defaults.run_command content['unindent'] = defaults.unindent || false # If we don't have a file_name in config, use the one in the repo content['file_name'] ||= File.basename(content['code']['source']) parent_config = { 'code_only' => @config['code_only'], 'source' => @config['source'].gsub('_examples/', '') } if @config['application'] parent_config = parent_config.merge({ 'application' => @config['application'] }) end parent_config = parent_config.to_yaml.lines[1..-1].join source = <<~HEREDOC ```single_code_snippet #{content.to_yaml}\n#{parent_config} ``` HEREDOC content[:body] = MarkdownPipeline.new(options).call(source) content end end def sort_contents(contents) contents.sort_by do |content| content['weight'] end end def resolve_active_tab(contents) active_index = nil if options[:code_language] contents.each_with_index do |content, index| active_index = index if content['language'] == options[:code_language].key end end @tabs['data-has-initial-tab'] = active_index.present? @tabs['class'] += ' skip-pushstate' if @tabs['data-has-initial-tab'] active_index ||= 0 contents[active_index][:active] = true end end end end end end