Class: GraphQLDocs::Renderer

Inherits:
Object
  • Object
show all
Includes:
Helpers
Defined in:
lib/graphql-docs/renderer.rb

Overview

Renders documentation content into HTML.

The Renderer takes parsed schema content and converts it to HTML using html-pipeline. It applies markdown processing, emoji support, and other filters, then wraps the result in the default layout template.

Examples:

Basic usage

renderer = GraphQLDocs::Renderer.new(parsed_schema, options)
html = renderer.render(markdown_content, type: 'object', name: 'User')

Custom renderer

class MyRenderer < GraphQLDocs::Renderer
  def render(contents, type: nil, name: nil, filename: nil)
    # Custom rendering logic
    super
  end
end

Constant Summary

Constants included from Helpers

Helpers::SLUGIFY_PRETTY_REGEXP

Instance Attribute Summary collapse

Attributes included from Helpers

#templates

Instance Method Summary collapse

Methods included from Helpers

#graphql_directive_types, #graphql_enum_types, #graphql_input_object_types, #graphql_interface_types, #graphql_mutation_types, #graphql_object_types, #graphql_operation_types, #graphql_query_types, #graphql_root_types, #graphql_scalar_types, #graphql_union_types, #include, #markdownify, #slugify, #split_into_metadata_and_contents, #yaml?, #yaml_split

Constructor Details

#initialize(parsed_schema, options) ⇒ Renderer

Initializes a new Renderer instance.

Parameters:

  • parsed_schema (Hash)

    The parsed schema from Parser#parse

  • options (Hash)

    Configuration options

Options Hash (options):

  • :templates (Hash)

    Template file paths

  • :pipeline_config (Hash)

    html-pipeline configuration



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/graphql-docs/renderer.rb', line 39

def initialize(parsed_schema, options)
  @parsed_schema = parsed_schema
  @options = options

  @graphql_default_layout = ERB.new(File.read(@options[:templates][:default])) unless @options[:templates][:default].nil?

  @pipeline_config = @options[:pipeline_config] || {}
  context = @pipeline_config[:context] || {}

  # Convert context for html-pipeline 3
  @pipeline_context = {}
  @pipeline_context[:unsafe] = context[:unsafe] if context.key?(:unsafe)
  @pipeline_context[:asset_root] = context[:asset_root] if context.key?(:asset_root)

  # html-pipeline 3 uses a simplified API - we'll just use text-to-text processing
  # since markdown conversion is handled by commonmarker directly
  @pipeline = nil # We'll handle markdown conversion directly in to_html
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



31
32
33
# File 'lib/graphql-docs/renderer.rb', line 31

def options
  @options
end

Instance Method Details

#emojify(string) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Converts emoji shortcodes like :smile: to emoji characters

Parameters:

  • string (String)

    Text containing emoji shortcodes

Returns:

  • (String)

    Text with shortcodes replaced by emoji



126
127
128
129
130
131
# File 'lib/graphql-docs/renderer.rb', line 126

def emojify(string)
  string.gsub(/:([a-z0-9_+-]+):/) do |match|
    emoji = Emoji.find_by_alias(Regexp.last_match(1))
    emoji ? emoji.raw : match
  end
end

#render(contents, type: nil, name: nil, filename: nil) ⇒ String?

Renders content into complete HTML with layout.

This method converts the content through the html-pipeline filters and wraps it in the default layout template. If the method returns nil, no file will be written.

Examples:

html = renderer.render(markdown, type: 'object', name: 'User')

Parameters:

  • contents (String)

    Content to render (typically Markdown)

  • type (String, nil) (defaults to: nil)

    GraphQL type category (e.g., 'object', 'interface')

  • name (String, nil) (defaults to: nil)

    Name of the GraphQL type being rendered

  • filename (String, nil) (defaults to: nil)

    Output filename path

Returns:

  • (String, nil)

    Rendered HTML content, or nil to skip file generation



71
72
73
74
75
76
77
78
79
80
# File 'lib/graphql-docs/renderer.rb', line 71

def render(contents, type: nil, name: nil, filename: nil)
  # Include all options (like Generator does) to support YAML frontmatter variables like title
  opts = @options.merge({type: type, name: name, filename: filename}).merge(helper_methods)

  contents = to_html(contents, context: {filename: filename})
  return contents if @graphql_default_layout.nil?

  opts[:content] = contents
  @graphql_default_layout.result(OpenStruct.new(opts).instance_eval { binding })
end

#to_html(string, context: {}) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Converts a string to HTML using commonmarker with emoji support.

Parameters:

  • string (String)

    Content to convert

  • context (Hash) (defaults to: {})

    Additional context (unused, kept for compatibility)

Returns:

  • (String)

    HTML output



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/graphql-docs/renderer.rb', line 89

def to_html(string, context: {})
  return "" if string.nil?
  return "" if string.empty?

  begin
    # Replace emoji shortcodes before markdown processing
    string_with_emoji = emojify(string)

    # Commonmarker 2.x uses parse/render API
    # Parse with GitHub Flavored Markdown extensions enabled by default
    doc = ::Commonmarker.parse(string_with_emoji)

    # Convert to HTML - commonmarker 2.x automatically includes:
    # - GitHub Flavored Markdown (tables, strikethrough, etc.)
    # - Header anchors with IDs
    # - Safe HTML by default (unless unsafe mode is enabled)
    html = if @pipeline_context[:unsafe]
      doc.to_html(options: {render: {unsafe: true}})
    else
      doc.to_html
    end

    # Strip trailing newline that commonmarker adds
    html.chomp
  rescue => e
    # Log error and return safe fallback
    warn "Failed to parse markdown: #{e.message}"
    require "cgi" unless defined?(CGI)
    CGI.escapeHTML(string.to_s)
  end
end