require 'html/pipeline'
require 'yaml'
require 'extended-markdown-filter'
module GraphQLDocs
class Renderer
include Helpers
def initialize(options, parsed_schema)
@options = options
@parsed_schema = parsed_schema
unless @options[:templates][:default].nil?
@graphql_default_layout = ERB.new(File.read(@options[:templates][:default]))
end
@pipeline_config = @options[:pipeline_config]
filters = @pipeline_config[:pipeline].map do |f|
if filter?(f)
f
else
key = filter_key(f)
filter = HTML::Pipeline.constants.find { |c| c.downcase == key }
# possibly a custom filter
if filter.nil?
Kernel.const_get(f)
else
HTML::Pipeline.const_get(filter)
end
end
end
@pipeline = HTML::Pipeline.new(filters, @pipeline_config[:context])
end
def render(type, name, contents)
opts = { base_url: @options[:base_url] }.merge({ type: type, name: name}).merge(helper_methods)
if has_yaml?(contents)
# Split data
meta, contents = split_into_metadata_and_contents(contents)
opts = opts.merge(meta)
end
contents = @pipeline.to_html(contents)
return contents if @graphql_default_layout.nil?
opts[:content] = contents
@graphql_default_layout.result(OpenStruct.new(opts).instance_eval { binding })
end
def has_yaml?(contents)
contents =~ /\A-{3,5}\s*$/
end
def yaml_split(contents)
contents.split(/^(-{5}|-{3})[ \t]*\r?\n?/, 3)
end
def split_into_metadata_and_contents(contents)
opts = {}
pieces = yaml_split(contents)
if pieces.size < 4
raise RuntimeError.new(
"The file '#{content_filename}' appears to start with a metadata section (three or five dashes at the top) but it does not seem to be in the correct format.",
)
end
# Parse
begin
meta = YAML.load(pieces[2]) || {}
rescue Exception => e # rubocop:disable Lint/RescueException
raise "Could not parse YAML for #{name}: #{e.message}"
end
[meta, pieces[4]]
end
private
def filter_key(s)
s.downcase
end
def filter?(f)
f < HTML::Pipeline::Filter
rescue LoadError, ArgumentError
false
end
end
end