mc_markdown 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/mc_markdown.rb +11 -0
- data/lib/mc_markdown/extensions.rb +10 -0
- data/lib/mc_markdown/formatters.rb +9 -0
- data/lib/mc_markdown/formatters/blockquote.rb +38 -0
- data/lib/mc_markdown/formatters/blocks.rb +47 -0
- data/lib/mc_markdown/formatters/common_misspellings.rb +26 -0
- data/lib/mc_markdown/formatters/escape_merge_tags.rb +21 -0
- data/lib/mc_markdown/formatters/header_with_id.rb +34 -0
- data/lib/mc_markdown/formatters/image.rb +55 -0
- data/lib/mc_markdown/formatters/links.rb +51 -0
- data/lib/mc_markdown/formatters/lists.rb +33 -0
- data/lib/mc_markdown/formatters/wistia.rb +64 -0
- data/lib/mc_markdown/parsers.rb +4 -0
- data/lib/mc_markdown/parsers/block_tag.rb +70 -0
- data/lib/mc_markdown/parsers/formatter.rb +17 -0
- data/lib/mc_markdown/parsers/frontmatter.rb +39 -0
- data/lib/mc_markdown/parsers/short_tag.rb +51 -0
- data/lib/mc_markdown/renderers.rb +46 -0
- data/lib/mc_markdown/renderers/base.rb +12 -0
- data/lib/mc_markdown/renderers/html.rb +5 -0
- data/lib/mc_markdown/version.rb +3 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bd77c3ac8d404a34b13fce0798dce8e0ecd703ef
|
4
|
+
data.tar.gz: 01143bd86643d7fcc301f47e56da0be1dc3ba361
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 343a2e49df1c68dc69479d67bd25c77a5d833e3c508d8f62dccc6467e3316d97c95c960276c6af980fba068d35f742d3d7b33f99b7ba0514de4faf4f315fb5a6
|
7
|
+
data.tar.gz: f94055d08e32929046ce2c8f81aca889818cb959601fae05fa69bb05def250ee8e1b261636545c061763c5f74faac8fd9d031e98884ac660b97a1b5c7ec3cd4e
|
data/lib/mc_markdown.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative 'formatters/common_misspellings'
|
2
|
+
require_relative 'formatters/header_with_id'
|
3
|
+
require_relative 'formatters/image'
|
4
|
+
require_relative 'formatters/links'
|
5
|
+
require_relative 'formatters/lists'
|
6
|
+
require_relative 'formatters/escape_merge_tags'
|
7
|
+
require_relative 'formatters/blockquote'
|
8
|
+
require_relative 'formatters/blocks'
|
9
|
+
require_relative 'formatters/wistia'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Formatter
|
3
|
+
module Blockquote
|
4
|
+
|
5
|
+
# http://rubular.com/r/9DaY7IwzEV
|
6
|
+
BLOCK_QUOTE_PATTERN = /(?<!>\n) (^>\s[^>].+)/x
|
7
|
+
|
8
|
+
def preprocess doc
|
9
|
+
doc.gsub!(BLOCK_QUOTE_PATTERN) do |match|
|
10
|
+
match.prepend "\n{{break_quote}}\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
if defined?(super)
|
14
|
+
return super(doc)
|
15
|
+
else
|
16
|
+
return doc
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def postprocess doc
|
21
|
+
doc.gsub! "\n<p>{{break_quote}}</p>", ""
|
22
|
+
|
23
|
+
if defined?(super)
|
24
|
+
return super(doc)
|
25
|
+
else
|
26
|
+
return doc
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def block_quote quote
|
31
|
+
quote = quote.strip.gsub( "<p>{{break_quote}} ", '</blockquote><blockquote><p>').gsub(/\n/, '')
|
32
|
+
|
33
|
+
"<blockquote>" << quote << "</blockquote>"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Formatter
|
3
|
+
module Blocks
|
4
|
+
|
5
|
+
def preprocess doc
|
6
|
+
doc.gsub!( Parser::BlockTag::Block.open_block ) do |match|
|
7
|
+
"\n\n#{match}\n\n"
|
8
|
+
end
|
9
|
+
|
10
|
+
doc.gsub!( Parser::BlockTag::Block.close_block ) do |match|
|
11
|
+
"\n\n#{match}\n\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
if defined?(super)
|
15
|
+
return super(doc)
|
16
|
+
else
|
17
|
+
return doc
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def postprocess doc
|
22
|
+
doc = Parser::BlockTag.new(doc, BlockFormatter).parsed
|
23
|
+
|
24
|
+
if defined?(super)
|
25
|
+
return super(doc)
|
26
|
+
else
|
27
|
+
return doc
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class BlockFormatter < Parser::Formatter
|
32
|
+
|
33
|
+
def notes attributes={}
|
34
|
+
content = attributes[:content]
|
35
|
+
"<div class=\"notes\">\n\n#{content}\n\n</div>"
|
36
|
+
end
|
37
|
+
|
38
|
+
def callout attributes={}
|
39
|
+
content = attributes[:content]
|
40
|
+
"<div class=\"callout\">\n\n#{content}\n\n</div>"
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Formatter
|
3
|
+
module CommonMisspellings
|
4
|
+
|
5
|
+
def preprocess doc
|
6
|
+
|
7
|
+
replacements = {
|
8
|
+
"(&ldqou;)" => "“",
|
9
|
+
"(&rdqou;)" => "”",
|
10
|
+
"(&rsqou;)" => "’"
|
11
|
+
}
|
12
|
+
|
13
|
+
replacements.each do |bad_regex, correction|
|
14
|
+
doc.gsub! /#{bad_regex}/xi, correction
|
15
|
+
end
|
16
|
+
|
17
|
+
if defined?(super)
|
18
|
+
return super(doc)
|
19
|
+
else
|
20
|
+
return doc
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Formatter
|
3
|
+
module EscapeMergeTags
|
4
|
+
ALLOWED_CHARACTERS = ['w', ':', '_', '<', '>', '/' ]
|
5
|
+
|
6
|
+
def emphasis text
|
7
|
+
characters = ALLOWED_CHARACTERS.map { |char| "\\#{char}" }.join("")
|
8
|
+
unless text.match /^\| .+ \|$/x
|
9
|
+
"<em>#{text}</em>"
|
10
|
+
else
|
11
|
+
"*#{convert_em_tags_to_underscores(text)}*"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def convert_em_tags_to_underscores string
|
16
|
+
string.gsub( /<\/?em>/, '_' )
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'slugity/extend_string'
|
2
|
+
|
3
|
+
module MCMarkdown
|
4
|
+
module Formatter
|
5
|
+
module HeaderWithID
|
6
|
+
|
7
|
+
def header text, header_level
|
8
|
+
header_levels = Array(header_options.fetch(:level, 1))
|
9
|
+
return "<h#{header_level}>#{text}</h#{header_level}>" unless header_levels.include?(header_level)
|
10
|
+
|
11
|
+
# add ids to all h1 headers (pray they're unique)
|
12
|
+
if header_options.fetch(:template_tag_headers, false)
|
13
|
+
namespace = "{{section_id}}"
|
14
|
+
else
|
15
|
+
namespace = "#{header_options.fetch(:slug, 'section')}-#{text.strip.to_slug}"
|
16
|
+
end
|
17
|
+
|
18
|
+
return "<h#{header_level} id='#{namespace}'>#{text}</h#{header_level}>"
|
19
|
+
end
|
20
|
+
|
21
|
+
def header_options
|
22
|
+
if defined?(extensions)
|
23
|
+
options = extensions.fetch(:header_with_id, {})
|
24
|
+
options[:template_tag_headers] = extensions.fetch(:template_tag_headers, false)
|
25
|
+
else
|
26
|
+
options = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
return options
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Formatter
|
3
|
+
module Image
|
4
|
+
|
5
|
+
# http://rubular.com/r/lss0C9HqoP
|
6
|
+
# $1 => alt
|
7
|
+
# $2 => class/attrs
|
8
|
+
IMG_ATTRIBUTES_PATTERN = /^ ([^_{}]+)? (?:{(.+?)})? \s?$/x
|
9
|
+
|
10
|
+
# add classes to images and render title as figure/figcaption
|
11
|
+
# ![alt {class}](/path/to/img.jpg "caption")
|
12
|
+
def image link, title, alt_text
|
13
|
+
return "![#{alt_text}](#{link}#{(title && !title.empty?) ? " \"#{title}\"" : ''})" if extensions[:no_images]
|
14
|
+
|
15
|
+
match_data = IMG_ATTRIBUTES_PATTERN.match (alt_text || "")
|
16
|
+
alt_text = match_data[1] || ""
|
17
|
+
attrs = match_data[2] || ""
|
18
|
+
|
19
|
+
# check for attrs in class field
|
20
|
+
if attrs.include? ':'
|
21
|
+
attrs = attrs.split(', ').each_with_object([]) do |frag, out|
|
22
|
+
frag = frag.split ':'
|
23
|
+
out.push "#{frag[0].strip}='#{frag[1].strip}'"
|
24
|
+
out
|
25
|
+
end.join(" ") + " "
|
26
|
+
elsif !attrs.empty?
|
27
|
+
classes = attrs
|
28
|
+
attrs = "class='#{attrs}' "
|
29
|
+
end
|
30
|
+
|
31
|
+
if title
|
32
|
+
return "<figure class='img #{classes}'>" +
|
33
|
+
"<img src='#{link}' alt='#{alt_text.strip}' />" +
|
34
|
+
"<figcaption>" + ::Redcarpet::Markdown.new( self ).render(title).strip + "</figcaption>" +
|
35
|
+
"</figure>"
|
36
|
+
else
|
37
|
+
return "<img src='#{link}' alt='#{alt_text.strip}' #{attrs}/>"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# need to strip paragraph tags from around
|
42
|
+
# figures, has potential to cause invalid markup
|
43
|
+
def postprocess doc
|
44
|
+
doc = doc.gsub( /<p><figure/, '<figure' ).gsub( /<\/figure><\/p>/, '</figure>' )
|
45
|
+
|
46
|
+
if defined?(super)
|
47
|
+
return super(doc)
|
48
|
+
else
|
49
|
+
return doc
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Formatter
|
3
|
+
module Links
|
4
|
+
|
5
|
+
# http://rubular.com/r/nVJvYdiGud
|
6
|
+
# $1 => text
|
7
|
+
# $2 => junk
|
8
|
+
# $3 => class/attrs
|
9
|
+
# $4 => target
|
10
|
+
LINK_ATTRIBUTES_PATTERN = /^ ([^_{}]+) ({(.+?)})? (\s\_[a-zA-Z]+)? \s?$/x
|
11
|
+
|
12
|
+
|
13
|
+
# add ability to add classes to links
|
14
|
+
# [Link Test {class} _target ](link)
|
15
|
+
def link link, title, content
|
16
|
+
return "[#{content}](#{link}#{(title && !title.empty?) ? " \"#{title}\"" : ''})" if extensions[:no_links]
|
17
|
+
|
18
|
+
match_data = LINK_ATTRIBUTES_PATTERN.match content
|
19
|
+
content = match_data[1]
|
20
|
+
attrs = match_data[3] || ""
|
21
|
+
target = match_data[4]
|
22
|
+
|
23
|
+
# check for attrs in class field
|
24
|
+
if attrs.include? ':'
|
25
|
+
attrs = attrs.split(', ').each_with_object([]) do |frag, out|
|
26
|
+
frag = frag.split ':'
|
27
|
+
out.push "#{frag[0].strip}='#{frag[1].strip}'"
|
28
|
+
out
|
29
|
+
end.join(" ")
|
30
|
+
elsif !attrs.empty?
|
31
|
+
attrs = "class='#{attrs}'"
|
32
|
+
end
|
33
|
+
|
34
|
+
if extensions[:xml]
|
35
|
+
link.encode!(xml: :text)
|
36
|
+
# content gets loosely encoded before it
|
37
|
+
# enters the formatter
|
38
|
+
end
|
39
|
+
|
40
|
+
# there is always a link
|
41
|
+
return_string = "<a href='#{link}'"
|
42
|
+
return_string << " " << attrs if !attrs.empty?
|
43
|
+
return_string << " target='#{target.strip}'" if target
|
44
|
+
return_string << ">#{content.strip}</a>"
|
45
|
+
|
46
|
+
return return_string
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Formatter
|
3
|
+
module Lists
|
4
|
+
|
5
|
+
def list content, list_type
|
6
|
+
tag = ( list_type == :ordered ) ? "ol" : "ul"
|
7
|
+
tag = (/\<dt\>/.match(content) ) ? "dl" : tag
|
8
|
+
|
9
|
+
"<#{tag} class='list markers'>#{content}</#{tag}>"
|
10
|
+
end
|
11
|
+
|
12
|
+
def list_item text, list_type
|
13
|
+
if /\n\:\s*\n/.match(text)
|
14
|
+
match_data = /^((.*)\n\:\s*\n)/.match(text)
|
15
|
+
title = "<p>" << match_data[2].gsub('<p>','') << "</p>"
|
16
|
+
|
17
|
+
# strip the title from the text, but leave <p> tags
|
18
|
+
text = text.gsub( match_data[1].gsub(/\<\/?p\>/,''), '')
|
19
|
+
|
20
|
+
# strip opening and closing p tags
|
21
|
+
text = text.strip.gsub( /(\A\<p\>|\<\/p\>\z)/, '' )
|
22
|
+
|
23
|
+
text = "<p>" << text << "</p>"
|
24
|
+
|
25
|
+
"<dt>#{title}</dt><dd>#{text}</dd>"
|
26
|
+
else
|
27
|
+
"<li>#{text.strip}</li>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Formatter
|
3
|
+
module Wistia
|
4
|
+
|
5
|
+
def preprocess doc
|
6
|
+
doc = Parser::ShortTag.new(doc, WistiaFormatter).parsed
|
7
|
+
|
8
|
+
if defined?(super)
|
9
|
+
return super(doc)
|
10
|
+
else
|
11
|
+
return doc
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class WistiaFormatter < Parser::Formatter
|
16
|
+
|
17
|
+
def video attributes={}
|
18
|
+
wistia_id = attributes.delete(:id)
|
19
|
+
options = defaults.merge(attributes)
|
20
|
+
|
21
|
+
query_params = options.map do |attr,value|
|
22
|
+
# camel case attribute names
|
23
|
+
camel_case = attr.to_s.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
|
24
|
+
"#{camel_case}=#{value}"
|
25
|
+
end
|
26
|
+
|
27
|
+
html_params = {
|
28
|
+
src: "http://fast.wistia.com/embed/iframe/#{wistia_id}?#{query_params.join('&')}",
|
29
|
+
allowtransparency: 'true',
|
30
|
+
frameborder: '0',
|
31
|
+
scrolling: 'no',
|
32
|
+
class: 'wistia_embed',
|
33
|
+
name: 'wistia_embed',
|
34
|
+
width: options[:video_width],
|
35
|
+
height: options[:video_height]
|
36
|
+
}
|
37
|
+
|
38
|
+
if wistia_id
|
39
|
+
"<iframe #{render_params( html_params )}></iframe>"
|
40
|
+
else
|
41
|
+
""
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def defaults
|
48
|
+
{
|
49
|
+
version: "v1",
|
50
|
+
video_width: 600,
|
51
|
+
video_height: 400,
|
52
|
+
controls_visible_on_load: true
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def render_params params
|
57
|
+
params.map { |attr, value| "#{attr}='#{value}'" }.join(' ')
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Parser
|
3
|
+
|
4
|
+
class BlockTag
|
5
|
+
|
6
|
+
attr_reader :content
|
7
|
+
attr_reader :formatter
|
8
|
+
|
9
|
+
def initialize content, formatter
|
10
|
+
@content = content
|
11
|
+
@formatter = formatter.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def parsed
|
15
|
+
content.gsub Block.pattern do |match|
|
16
|
+
tag = Block.new(match)
|
17
|
+
formatter.format(tag)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Block
|
22
|
+
class << self
|
23
|
+
def pattern
|
24
|
+
/ #{open_block} (.*?) #{close_block} /xm
|
25
|
+
end
|
26
|
+
|
27
|
+
def open_block
|
28
|
+
/ (?:#{open_tag})? \{\{(.+?)\}\} #{repeated_spaces} (?:#{close_tag})? /x
|
29
|
+
end
|
30
|
+
|
31
|
+
def close_block
|
32
|
+
/ (?:#{open_tag})? #{repeated_spaces} \{\{\/(.+?)\}\} (?:#{close_tag})? /x
|
33
|
+
end
|
34
|
+
|
35
|
+
def open_tag
|
36
|
+
/ < (?:\w+?) > /x
|
37
|
+
end
|
38
|
+
|
39
|
+
def close_tag
|
40
|
+
/ < (?:\/) (?:\w+?) > /x
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def repeated_spaces
|
46
|
+
/ (?:[\s\t]*) /x
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
attr_reader :orig
|
52
|
+
attr_reader :type
|
53
|
+
attr_reader :attributes
|
54
|
+
|
55
|
+
def initialize content
|
56
|
+
@orig = content
|
57
|
+
end
|
58
|
+
|
59
|
+
def type
|
60
|
+
@_type ||= @orig.match( Block.pattern )[1]
|
61
|
+
end
|
62
|
+
|
63
|
+
def attributes
|
64
|
+
@_attributes ||= { content: @orig.match( Block.pattern )[2].strip }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Parsers
|
3
|
+
|
4
|
+
class Frontmatter
|
5
|
+
attr_reader :content
|
6
|
+
|
7
|
+
def initialize content
|
8
|
+
@content = content
|
9
|
+
end
|
10
|
+
|
11
|
+
def parsed
|
12
|
+
match = content.match( frontmatter_regex )
|
13
|
+
raw_fm = match[1]
|
14
|
+
content = match[2]
|
15
|
+
|
16
|
+
if raw_fm && !raw_fm.empty?
|
17
|
+
frontmatter = SafeYAML.load raw_fm, safe: true,
|
18
|
+
deserialize_symbols: true,
|
19
|
+
raise_on_unknown_tag: true
|
20
|
+
else
|
21
|
+
frontmatter = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
[ frontmatter, content ]
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def frontmatter_regex
|
30
|
+
# http://rubular.com/r/tJ6VoFBuqK
|
31
|
+
# [1] => frontmatter || nil
|
32
|
+
# [2] => content
|
33
|
+
/(?:(?:\A-{3,}\s*\n+) (.+?) (?:-{3,}\s*\n+))? (.*)/mx
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Parser
|
3
|
+
|
4
|
+
class ShortTag
|
5
|
+
|
6
|
+
attr_reader :content
|
7
|
+
attr_reader :formatter
|
8
|
+
|
9
|
+
def initialize content, formatter
|
10
|
+
@content = content
|
11
|
+
@formatter = formatter.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def parsed
|
15
|
+
content.gsub Tag.pattern do |match|
|
16
|
+
tag = Tag.new(match)
|
17
|
+
formatter.format(tag)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Tag
|
22
|
+
|
23
|
+
def self.pattern
|
24
|
+
/\{\{ (.*?) \}\}/x
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :orig
|
28
|
+
attr_reader :type
|
29
|
+
attr_reader :attributes
|
30
|
+
|
31
|
+
def initialize matched_string
|
32
|
+
@orig = matched_string
|
33
|
+
@data = @orig.match( Tag.pattern )[1].strip.split(' ')
|
34
|
+
@type = @data.shift
|
35
|
+
@attributes = @data.map { |set| set.scan( attribute_pattern ) }.inject({}) do |out,pair|
|
36
|
+
out[ pair[0][0].to_sym ] = pair[0][1]
|
37
|
+
out
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def attribute_pattern
|
44
|
+
/ (\w+) = ['"](.+?)['"] /x
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
module Renderers
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def use renderer_class, options={}
|
6
|
+
fetch( { class: renderer_class, extensions: options.delete(:extensions), options: options } )
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def store
|
12
|
+
@_store ||= {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch renderer_key
|
16
|
+
store.fetch(renderer_key) { add(renderer_key) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def add renderer_key
|
20
|
+
extensions = renderer_key[:extensions] || {}
|
21
|
+
|
22
|
+
store[renderer_key] = Redcarpet::Markdown.new(
|
23
|
+
::MCMarkdown.const_get( renderer_key[:class].to_s.capitalize ).new( renderer_key[:options] ),
|
24
|
+
extensions
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.render input, renderer=:base, options={}
|
32
|
+
Renderers.use(renderer, options).render(input)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.render_with_frontmatter input, renderer=:base, options={}
|
36
|
+
require 'safe_yaml/load'
|
37
|
+
|
38
|
+
frontmatter, content = Parsers::Frontmatter.new(input).parsed
|
39
|
+
rendered_content = Renderers.use(renderer, options).render(content)
|
40
|
+
|
41
|
+
[ frontmatter, rendered_content ]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require_relative 'renderers/html'
|
46
|
+
require_relative 'renderers/base'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module MCMarkdown
|
2
|
+
class Base < Html
|
3
|
+
include ::MCMarkdown::Formatter::Lists
|
4
|
+
include ::MCMarkdown::Formatter::Image
|
5
|
+
include ::MCMarkdown::Formatter::Links
|
6
|
+
include ::MCMarkdown::Formatter::EscapeMergeTags
|
7
|
+
include ::MCMarkdown::Formatter::CommonMisspellings
|
8
|
+
include ::MCMarkdown::Formatter::Blockquote
|
9
|
+
include ::MCMarkdown::Formatter::Blocks
|
10
|
+
include ::MCMarkdown::Formatter::Wistia
|
11
|
+
end
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mc_markdown
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Steven Sloan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redcarpet
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: slugity
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: safe_yaml
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description: ' MailChimp flavoured markdown syntax using RedCarpet '
|
56
|
+
email:
|
57
|
+
- stevenosloan@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- lib/mc_markdown.rb
|
63
|
+
- lib/mc_markdown/extensions.rb
|
64
|
+
- lib/mc_markdown/formatters.rb
|
65
|
+
- lib/mc_markdown/formatters/blockquote.rb
|
66
|
+
- lib/mc_markdown/formatters/blocks.rb
|
67
|
+
- lib/mc_markdown/formatters/common_misspellings.rb
|
68
|
+
- lib/mc_markdown/formatters/escape_merge_tags.rb
|
69
|
+
- lib/mc_markdown/formatters/header_with_id.rb
|
70
|
+
- lib/mc_markdown/formatters/image.rb
|
71
|
+
- lib/mc_markdown/formatters/links.rb
|
72
|
+
- lib/mc_markdown/formatters/lists.rb
|
73
|
+
- lib/mc_markdown/formatters/wistia.rb
|
74
|
+
- lib/mc_markdown/parsers.rb
|
75
|
+
- lib/mc_markdown/parsers/block_tag.rb
|
76
|
+
- lib/mc_markdown/parsers/formatter.rb
|
77
|
+
- lib/mc_markdown/parsers/frontmatter.rb
|
78
|
+
- lib/mc_markdown/parsers/short_tag.rb
|
79
|
+
- lib/mc_markdown/renderers.rb
|
80
|
+
- lib/mc_markdown/renderers/base.rb
|
81
|
+
- lib/mc_markdown/renderers/html.rb
|
82
|
+
- lib/mc_markdown/version.rb
|
83
|
+
homepage: http://github.com/mailchimp/mc_markdown
|
84
|
+
licenses:
|
85
|
+
- New-BSD
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.4.5
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: MailChimp flavoured markdown syntax using RedCarpet
|
107
|
+
test_files: []
|