Class: Clickwrap::DocumentRenderers::Markdown
- Inherits:
-
Object
- Object
- Clickwrap::DocumentRenderers::Markdown
- Defined in:
- lib/clickwrap/document_renderers/markdown.rb
Overview
Optional Markdown rendering for the representation people are offered.
The reference renderer deliberately escapes Markdown into a
block:
faithful, dependency-free, and ugly for a forty-page Terms document. This
renderer produces real HTML instead, using whichever Markdown library the
application already bundles — it is opt-in and it adds no dependency:</p>
<pre><code>Clickwrap.configure do |config|
config.document_renderer = :markdown
end
Three engines are recognized, in order: Commonmarker (1.x and the older CommonMarker 0.x), Redcarpet, and Kramdown. An application whose Markdown dialect needs specific options can inject its own rendering instead and must name it, because the receipt records which renderer produced the offered bytes:
config.document_renderer = Clickwrap::DocumentRenderers::Markdown.new(
render_markdown_with: ->(markdown_text) { MyMarkdown.render(markdown_text) },
engine_name: "my_markdown",
engine_version: MyMarkdown::VERSION
)
A leading YAML front-matter block (the Jekyll/Sitepress convention) is
stripped from the RENDERED representation only — the source digest still
covers the exact file bytes, front matter included. Bundled engines'
output always passes through the same safe-list sanitizer as the
reference renderer, so a Markdown library's raw-HTML passthrough cannot
smuggle markup into an offer. A host-supplied render_markdown_with:
may additionally pass sanitize_rendered_html: false when its own pages
serve the renderer's output verbatim: re-sanitizing reparses the HTML
and changes its bytes, and a stored digest must describe exactly what
readers were shown. The provenance records which choice was made.
Non-Markdown documents delegate to the reference renderer unchanged.
Constant Summary collapse
- NAME =
"clickwrap_markdown_document_renderer"- VERSION =
"1"
Instance Attribute Summary collapse
-
#engine_name ⇒ Object
readonly
Returns the value of attribute engine_name.
-
#engine_version ⇒ Object
readonly
Returns the value of attribute engine_version.
Instance Method Summary collapse
- #call(bytes, definition) ⇒ Object
-
#initialize(render_markdown_with: nil, engine_name: nil, engine_version: nil, sanitize_rendered_html: true) ⇒ Markdown
constructor
A new instance of Markdown.
Constructor Details
#initialize(render_markdown_with: nil, engine_name: nil, engine_version: nil, sanitize_rendered_html: true) ⇒ Markdown
Returns a new instance of Markdown.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/clickwrap/document_renderers/markdown.rb', line 43 def initialize(render_markdown_with: nil, engine_name: nil, engine_version: nil, sanitize_rendered_html: true) @sanitize_rendered_html = sanitize_rendered_html != false if !@sanitize_rendered_html && render_markdown_with.nil? raise ConfigurationError, "sanitize_rendered_html: false is only available with your own " \ "render_markdown_with. Clickwrap's bundled engines always sanitize; skipping " \ "sanitization is a promise about a rendering pipeline YOU own — that its " \ "output is exactly what your own pages already serve to readers." end if render_markdown_with unless render_markdown_with.respond_to?(:call) raise ConfigurationError, "render_markdown_with must respond to call(markdown_text) and return HTML." end if engine_name.to_s.strip.empty? raise ConfigurationError, "A custom render_markdown_with needs an engine_name (and ideally an " \ "engine_version), because receipts record which renderer produced the " \ "bytes a person was offered." end @render_markdown = render_markdown_with @engine_name = engine_name.to_s @engine_version = engine_version.to_s.strip.empty? ? "unstated" : engine_version.to_s else @render_markdown, @engine_name, @engine_version = resolve_bundled_engine end @fallback = DocumentRenderer.new end |
Instance Attribute Details
#engine_name ⇒ Object (readonly)
Returns the value of attribute engine_name.
77 78 79 |
# File 'lib/clickwrap/document_renderers/markdown.rb', line 77 def engine_name @engine_name end |
#engine_version ⇒ Object (readonly)
Returns the value of attribute engine_version.
77 78 79 |
# File 'lib/clickwrap/document_renderers/markdown.rb', line 77 def engine_version @engine_version end |
Instance Method Details
#call(bytes, definition) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/clickwrap/document_renderers/markdown.rb', line 79 def call(bytes, definition) return @fallback.call(bytes, definition) unless definition.media_type == "text/markdown" text = utf8_text!(bytes, definition) html = @render_markdown.call(FrontMatter.strip(text)) if @sanitize_rendered_html { bytes: DocumentRenderer.sanitize_html(html), media_type: "text/html; charset=utf-8", renderer_name: NAME, renderer_version: "#{VERSION} (#{@engine_name} #{@engine_version})", sanitizer_name: DocumentRenderer::SANITIZER_NAME, sanitizer_version: DocumentRenderer::SANITIZER_VERSION } else # Byte parity with the host's own pages is the point: re-sanitizing # reparses and re-serializes the HTML, so the stored digest would # describe bytes nobody was ever shown. The provenance says plainly # that no sanitizer ran — the host's rendering pipeline owns safety. { bytes: html.to_s.dup.force_encoding(Encoding::UTF_8), media_type: "text/html; charset=utf-8", renderer_name: NAME, renderer_version: "#{VERSION} (#{@engine_name} #{@engine_version})", sanitizer_name: "none", sanitizer_version: "host_renderer_output_stored_verbatim" } end end |