mc_markdown 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
# 
|
12
|
+
def image link, title, alt_text
|
13
|
+
return " ? " \"#{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: []
|