Skip to content
Snippets Groups Projects
Commit aa60db6c authored by blackst0ne's avatar blackst0ne
Browse files

Add CommonMark markdown engine

parent b5075640
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -126,6 +126,7 @@ gem 'html-pipeline', '~> 1.11.0'
gem 'deckar01-task_list', '2.0.0'
gem 'gitlab-markup', '~> 1.6.2'
gem 'redcarpet', '~> 3.4'
gem 'commonmarker', '~> 0.17'
gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 4.2'
gem 'org-ruby', '~> 0.9.12'
Loading
Loading
Loading
Loading
@@ -131,6 +131,8 @@ GEM
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
colorize (0.7.7)
commonmarker (0.17.8)
ruby-enum (~> 0.5)
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
Loading
Loading
@@ -797,6 +799,8 @@ GEM
rubocop (>= 0.51)
rubocop-rspec (1.22.1)
rubocop (>= 0.52.1)
ruby-enum (0.7.2)
i18n
ruby-fogbugz (0.2.1)
crack (~> 0.4)
ruby-prof (0.16.2)
Loading
Loading
@@ -1019,6 +1023,7 @@ DEPENDENCIES
charlock_holmes (~> 0.7.5)
chronic (~> 0.10.2)
chronic_duration (~> 0.10.6)
commonmarker (~> 0.17)
concurrent-ruby (~> 1.0.5)
connection_pool (~> 2.0)
creole (~> 0.5.0)
Loading
Loading
---
title: Add CommonMark markdown engine (experimental)
merge_request: 14835
author: blackst0ne
type: added
Loading
Loading
@@ -94,6 +94,7 @@ def instrument_classes(instrumentation)
 
instrumentation.instrument_instance_methods(RepositoryCheck::SingleRepositoryWorker)
 
instrumentation.instrument_instance_methods(Rouge::Plugins::CommonMark)
instrumentation.instrument_instance_methods(Rouge::Plugins::Redcarpet)
instrumentation.instrument_instance_methods(Rouge::Formatters::HTMLGitlab)
 
Loading
Loading
# `CommonMark` markdown engine for GitLab's Banzai markdown filter.
# This module is used in Banzai::Filter::MarkdownFilter.
# Used gem is `commonmarker` which is a ruby wrapper for libcmark (CommonMark parser)
# including GitHub's GFM extensions.
# Homepage: https://github.com/gjtorikian/commonmarker
module Banzai
module Filter
module MarkdownEngines
class CommonMark
EXTENSIONS = [
:autolink, # provides support for automatically converting URLs to anchor tags.
:strikethrough, # provides support for strikethroughs.
:table, # provides support for tables.
:tagfilter # strips out several "unsafe" HTML tags from being used: https://github.github.com/gfm/#disallowed-raw-html-extension-
].freeze
PARSE_OPTIONS = [
:FOOTNOTES, # parse footnotes.
:STRIKETHROUGH_DOUBLE_TILDE, # parse strikethroughs by double tildes (as redcarpet does).
:VALIDATE_UTF8 # replace illegal sequences with the replacement character U+FFFD.
].freeze
# The `:GITHUB_PRE_LANG` option is not used intentionally because
# it renders a fence block with language as `<pre lang="LANG"><code>some code\n</code></pre>`
# while GitLab's syntax is `<pre><code lang="LANG">some code\n</code></pre>`.
# If in the future the syntax is about to be made GitHub-compatible, please, add `:GITHUB_PRE_LANG` render option below
# and remove `code_block` method from `lib/banzai/renderer/common_mark/html.rb`.
RENDER_OPTIONS = [
:DEFAULT # default rendering system. Nothing special.
].freeze
def initialize
@renderer = Banzai::Renderer::CommonMark::HTML.new(options: RENDER_OPTIONS)
end
def render(text)
doc = CommonMarker.render_doc(text, PARSE_OPTIONS, EXTENSIONS)
@renderer.render(doc)
end
end
end
end
end
# `Redcarpet` markdown engine for GitLab's Banzai markdown filter.
# This module is used in Banzai::Filter::MarkdownFilter.
# Used gem is `redcarpet` which is a ruby library for markdown processing.
# Homepage: https://github.com/vmg/redcarpet
module Banzai
module Filter
module MarkdownEngines
class Redcarpet
OPTIONS = {
fenced_code_blocks: true,
footnotes: true,
lax_spacing: true,
no_intra_emphasis: true,
space_after_headers: true,
strikethrough: true,
superscript: true,
tables: true
}.freeze
def initialize
html_renderer = Banzai::Renderer::Redcarpet::HTML.new
@renderer = ::Redcarpet::Markdown.new(html_renderer, OPTIONS)
end
def render(text)
@renderer.render(text)
end
end
end
end
end
module Banzai
module Filter
class MarkdownFilter < HTML::Pipeline::TextFilter
# https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
REDCARPET_OPTIONS = {
fenced_code_blocks: true,
footnotes: true,
lax_spacing: true,
no_intra_emphasis: true,
space_after_headers: true,
strikethrough: true,
superscript: true,
tables: true
}.freeze
def initialize(text, context = nil, result = nil)
super text, context, result
@text = @text.delete "\r"
super(text, context, result)
@renderer = renderer(context[:markdown_engine]).new
@text = @text.delete("\r")
end
 
def call
html = self.class.renderer.render(@text)
html.rstrip!
html
@renderer.render(@text).rstrip
end
private
DEFAULT_ENGINE = :redcarpet
def engine(engine_from_context)
engine_from_context ||= DEFAULT_ENGINE
engine_from_context.to_s.classify
end
 
def self.renderer
Thread.current[:banzai_markdown_renderer] ||= begin
renderer = Banzai::Renderer::HTML.new
Redcarpet::Markdown.new(renderer, REDCARPET_OPTIONS)
end
def renderer(engine_from_context)
"Banzai::Filter::MarkdownEngines::#{engine(engine_from_context)}".constantize
rescue NameError
raise NameError, "`#{engine_from_context}` is unknown markdown engine"
end
end
end
Loading
Loading
require 'rouge/plugins/common_mark'
require 'rouge/plugins/redcarpet'
 
module Banzai
Loading
Loading
module Banzai
module Renderer
module CommonMark
class HTML < CommonMarker::HtmlRenderer
def code_block(node)
block do
code = node.string_content
lang = node.fence_info
lang_attr = lang.present? ? %Q{ lang="#{lang}"} : ''
result =
"<pre>" \
"<code#{lang_attr}>#{html_escape(code)}</code>" \
"</pre>"
out(result)
end
end
end
end
end
end
module Banzai
module Renderer
class HTML < Redcarpet::Render::HTML
def block_code(code, lang)
lang_attr = lang ? %Q{ lang="#{lang}"} : ''
"\n<pre>" \
"<code#{lang_attr}>#{html_escape(code)}</code>" \
"</pre>"
end
end
end
end
module Banzai
module Renderer
module Redcarpet
class HTML < ::Redcarpet::Render::HTML
def block_code(code, lang)
lang_attr = lang ? %Q{ lang="#{lang}"} : ''
"\n<pre>" \
"<code#{lang_attr}>#{html_escape(code)}</code>" \
"</pre>"
end
end
end
end
end
# A rouge plugin for CommonMark markdown engine.
# Used to highlight code generated by CommonMark.
module Rouge
module Plugins
module CommonMark
def code_block(code, language)
lexer = Lexer.find_fancy(language, code) || Lexers::PlainText
formatter = rouge_formatter(lexer)
formatter.format(lexer.lex(code))
end
# override this method for custom formatting behavior
def rouge_formatter(lexer)
Formatters::HTMLLegacy.new(css_class: "highlight #{lexer.tag}")
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment