redcarpet-confluence 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/Gemfile +3 -0
- data/README.md +41 -0
- data/Rakefile +3 -0
- data/bin/md2conf +43 -0
- data/lib/redcarpet/confluence.rb +149 -0
- data/redcarpet-confluence.gemspec +18 -0
- data/spec/redcarpet/confluence_spec.rb +285 -0
- data/spec/smoke_spec.rb +20 -0
- data/spec/spec_helper.rb +11 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3010153521e4234b72df560c2001a60b31a92fb5
|
4
|
+
data.tar.gz: 569031b749cb8bd4a194601370c36ae07b98b76a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bde7e967394a83eca860460d9776acb1d5b275afb68b4d283ef0a4476116e56b34ad6b9e6ff8387018811d095264715f0e39b4325f429a6032f7c1a349815df0
|
7
|
+
data.tar.gz: 1a09e09be82a1c282eb9c0b353092e41f044cf1d593e426d1d6ff36d3c4b96d1031684c1206ca17c48fd6b78f01ec706f637bf5befc38e00b995a192d348052f
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# RedcarpetConfluence
|
2
|
+
|
3
|
+
A Redcarpet renderer to convert Markdown to Confluence syntax.
|
4
|
+
|
5
|
+
Assumes text is UTF-8.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
Call `md2conf` with the Markdown text to convert. Alternatively, pipe the text to `md2conf`.
|
10
|
+
|
11
|
+
md2conf README.md
|
12
|
+
cat README.md | md2conf
|
13
|
+
|
14
|
+
If you're on a Mac, pipe the output to `pbcopy` so you can paste it directly into Confluence.
|
15
|
+
|
16
|
+
md2conf README.md | pbcopy
|
17
|
+
|
18
|
+
### From code
|
19
|
+
|
20
|
+
Create a Markdown parser with the Confluence renderer.
|
21
|
+
|
22
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Confluence)
|
23
|
+
puts markdown.render(markdown_text)
|
24
|
+
|
25
|
+
## Installation
|
26
|
+
|
27
|
+
Add this line to your application's Gemfile:
|
28
|
+
|
29
|
+
gem 'redcarpet-confluence'
|
30
|
+
|
31
|
+
And then execute:
|
32
|
+
|
33
|
+
$ bundle
|
34
|
+
|
35
|
+
Or install it yourself as:
|
36
|
+
|
37
|
+
$ gem install redcarpet-confluence
|
38
|
+
|
39
|
+
and require it as:
|
40
|
+
|
41
|
+
require 'redcarpet/confluence'
|
data/Rakefile
ADDED
data/bin/md2conf
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby -s
|
2
|
+
|
3
|
+
# Converts the contents of the given file to Confluence syntax (or stdin) and prints the result to stdout.
|
4
|
+
#
|
5
|
+
# Automatically enables all the additional features provided by Redcarpet. Provide flags to disable features.
|
6
|
+
#
|
7
|
+
# Usage: md2conf [-noautolink] [-nofencedcode] [-intraemphasis] [-nostrikethrough] [-nosuperscript] [-notables] FILENAME
|
8
|
+
# md2conf -h
|
9
|
+
|
10
|
+
require 'redcarpet/confluence'
|
11
|
+
|
12
|
+
# == Helpers
|
13
|
+
|
14
|
+
def usage
|
15
|
+
"Usage: #{$0} [-noautolink] [-nofencedcode] [-intraemphasis] [-nostrikethrough] [-nosuperscript] [-notables] FILENAME"
|
16
|
+
end
|
17
|
+
|
18
|
+
def markdown_text
|
19
|
+
if ARGV[0]
|
20
|
+
File.read(ARGV[0])
|
21
|
+
else
|
22
|
+
$stdin.read
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# == Script
|
27
|
+
|
28
|
+
if $h
|
29
|
+
$stderr.puts usage
|
30
|
+
exit 0
|
31
|
+
end
|
32
|
+
|
33
|
+
markdown_options = {
|
34
|
+
autolink: $noautolink.nil?,
|
35
|
+
fenced_code_blocks: $nofencedcode.nil?,
|
36
|
+
no_intra_emphasis: $intraemphasis.nil?,
|
37
|
+
strikethrough: $nostrikethrough.nil?,
|
38
|
+
superscript: $nosuperscript.nil?,
|
39
|
+
tables: $notables.nil?
|
40
|
+
}
|
41
|
+
|
42
|
+
renderer = Redcarpet::Markdown.new(Redcarpet::Confluence, markdown_options)
|
43
|
+
$stdout.puts renderer.render(markdown_text)
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require 'redcarpet'
|
4
|
+
|
5
|
+
module Redcarpet
|
6
|
+
# Public: A Redcarpet renderer to convert Markdown to Confluence syntax.
|
7
|
+
class Confluence < Redcarpet::Render::Base
|
8
|
+
|
9
|
+
# Internal: Languages supported by the code macro.
|
10
|
+
CODE_MACRO_LANGUAGES = %w(
|
11
|
+
actionscript actionscript3 bash csharp coldfusion cpp css delphi diff erlang groovy html java javafx javascript
|
12
|
+
perl php powershell python ruby scala sql vb xhtml xml
|
13
|
+
)
|
14
|
+
# Internal: List item delimiters used by Confluence.
|
15
|
+
LIST_ITEM_DELIMITER = %w( # * )
|
16
|
+
# Internal: Reserved character sequences in Confluence that need to be escaped when not intended to be used.
|
17
|
+
RESERVED_SEQUENCES = %w( { } [ ] - + * _ ^ ~ ?? bq. )
|
18
|
+
|
19
|
+
def block_code(code, language)
|
20
|
+
supported_language = CODE_MACRO_LANGUAGES.find { |lang| lang == language }
|
21
|
+
macro(:code, code, lang: supported_language || :none)
|
22
|
+
end
|
23
|
+
|
24
|
+
def block_quote(text)
|
25
|
+
macro(:quote, text)
|
26
|
+
end
|
27
|
+
|
28
|
+
def codespan(code)
|
29
|
+
"{{#{escape_reserved_sequences(code)}}}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def double_emphasis(text)
|
33
|
+
"*#{text}*"
|
34
|
+
end
|
35
|
+
|
36
|
+
def emphasis(text)
|
37
|
+
"_#{text}_"
|
38
|
+
end
|
39
|
+
|
40
|
+
def header(title, level)
|
41
|
+
"\n\nh#{level}. #{title}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def hrule
|
45
|
+
"\n\n----"
|
46
|
+
end
|
47
|
+
|
48
|
+
def image(link, title, alt)
|
49
|
+
"!#{link}#{args_string(alt: escape_reserved_sequences(alt), title: escape_reserved_sequences(title))}!"
|
50
|
+
end
|
51
|
+
|
52
|
+
def linebreak
|
53
|
+
"\n"
|
54
|
+
end
|
55
|
+
|
56
|
+
def link(link, title, content)
|
57
|
+
link = "[#{content}|#{link}]"
|
58
|
+
link.insert(-2, "|#{escape_reserved_sequences(title)}") if title && !title.empty?
|
59
|
+
link
|
60
|
+
end
|
61
|
+
|
62
|
+
def list(content, list_type)
|
63
|
+
nested_list_prefix_regexp = /\n\n(?<matched_list_item_delimiter>#{LIST_ITEM_DELIMITER.map { |c| Regexp.escape(c) }.join('|')})/
|
64
|
+
nested_list_content = content.gsub(nested_list_prefix_regexp, '\k<matched_list_item_delimiter>')
|
65
|
+
"\n\n#{nested_list_content}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def list_item(content, list_type)
|
69
|
+
list_item_delimiter_regexp = /\n(?<matched_list_item_delimiter>#{LIST_ITEM_DELIMITER.map { |c| Regexp.escape(c) }.join('|')})/
|
70
|
+
list_item_delimiter = nil
|
71
|
+
case list_type
|
72
|
+
when :ordered
|
73
|
+
list_item_delimiter = '#'
|
74
|
+
when :unordered
|
75
|
+
list_item_delimiter = '*'
|
76
|
+
end
|
77
|
+
"#{list_item_delimiter} #{content.gsub(list_item_delimiter_regexp, "\n#{list_item_delimiter}\\k<matched_list_item_delimiter>")}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def normal_text(text)
|
81
|
+
escape_reserved_sequences(text)
|
82
|
+
end
|
83
|
+
|
84
|
+
def paragraph(text)
|
85
|
+
"\n\n#{text}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def strikethrough(text)
|
89
|
+
"-#{text}-"
|
90
|
+
end
|
91
|
+
|
92
|
+
def superscript(text)
|
93
|
+
" ^#{text}^ "
|
94
|
+
end
|
95
|
+
|
96
|
+
def table(header, body)
|
97
|
+
"\n#{header.gsub('|', '||')}#{body}"
|
98
|
+
end
|
99
|
+
|
100
|
+
def table_row(text)
|
101
|
+
"\n|#{text}"
|
102
|
+
end
|
103
|
+
|
104
|
+
def table_cell(text, align)
|
105
|
+
"#{text}|"
|
106
|
+
end
|
107
|
+
|
108
|
+
def triple_emphasis(text)
|
109
|
+
"_*#{text}*_"
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# Internal: Backslash-escapes all Confluence-reserved character sequences.
|
115
|
+
#
|
116
|
+
# Returns a copy of the text with all Confluence-reserved character sequences escaped with a backslash.
|
117
|
+
def escape_reserved_sequences(text)
|
118
|
+
reserved_sequences_regexp = /(?<reserved_sequence>#{RESERVED_SEQUENCES.map { |c| Regexp.escape(c) }.join('|')})/
|
119
|
+
text ? text.gsub(reserved_sequences_regexp, '\\\\\k<reserved_sequence>') : text
|
120
|
+
end
|
121
|
+
|
122
|
+
# Internal: Wraps content in the named macro.
|
123
|
+
#
|
124
|
+
# name - The name of the macro to use.
|
125
|
+
# content - The content to go between the macro tags. Nil will act the same as the empty string.
|
126
|
+
# args - Optional Hash of arguments to pass to the macro.
|
127
|
+
#
|
128
|
+
# Returns a string with the given content wrapped in the named macro.
|
129
|
+
def macro(name, content, args = {})
|
130
|
+
# separate the macro name from the argument list with a colon
|
131
|
+
arguments = args_string(args).sub('|', ':')
|
132
|
+
"\n\n{#{name}#{arguments}}#{content}{#{name}}"
|
133
|
+
end
|
134
|
+
|
135
|
+
# Internal: Creates an argument String meant for a macro.
|
136
|
+
#
|
137
|
+
# Arguments are key-value pairs preceded by and separated by a pipe ('|').
|
138
|
+
#
|
139
|
+
# Returns the argument String
|
140
|
+
def args_string(args)
|
141
|
+
# format macro arguments string
|
142
|
+
args_string = ''
|
143
|
+
args.each do |arg, value|
|
144
|
+
args_string << "|#{arg}=#{value}" if value && !value.empty?
|
145
|
+
end
|
146
|
+
args_string
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = 'redcarpet-confluence'
|
3
|
+
gem.version = '1.0.0'
|
4
|
+
gem.authors = ['Adam Stegman']
|
5
|
+
gem.email = ['me@adamstegman.com']
|
6
|
+
gem.summary = 'A Redcarpet renderer to convert Markdown to Confluence syntax.'
|
7
|
+
gem.description = "#{gem.summary}"
|
8
|
+
gem.homepage = 'https://github.com/adamstegman/redcarpet-confluence'
|
9
|
+
|
10
|
+
gem.executable = 'md2conf'
|
11
|
+
gem.files = Dir['lib/**/*.rb', 'Gemfile', 'README.md', 'Rakefile', 'redcarpet-confluence.gemspec']
|
12
|
+
gem.test_files = Dir['spec/**/*.rb']
|
13
|
+
gem.require_paths = ['lib']
|
14
|
+
|
15
|
+
gem.add_dependency 'redcarpet', '~> 2.0'
|
16
|
+
gem.add_development_dependency 'rake'
|
17
|
+
gem.add_development_dependency 'rspec'
|
18
|
+
end
|
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'redcarpet/confluence'
|
3
|
+
|
4
|
+
describe Redcarpet::Confluence do
|
5
|
+
let(:renderer) { described_class.new }
|
6
|
+
|
7
|
+
describe '#block_code(code, language)' do
|
8
|
+
it 'wraps the code in a code macro for the given language' do
|
9
|
+
expect(renderer.block_code("some normal freakin' code", 'java')).to(
|
10
|
+
eq("\n\n{code:lang=java}some normal freakin' code{code}")
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'uses the "none" language when given an unsupported language' do
|
15
|
+
expect(renderer.block_code('code', 'unsupported')).to eq("\n\n{code:lang=none}code{code}")
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'does not escape Confluence text effects' do
|
19
|
+
expect(renderer.block_code('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??', 'java')).to(
|
20
|
+
eq("\n\n{code:lang=java}bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??{code}")
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#block_quote(text)' do
|
26
|
+
it 'wraps the text in a quote macro' do
|
27
|
+
expect(renderer.block_quote("some normal freakin' text")).to(
|
28
|
+
eq("\n\n{quote}some normal freakin' text{quote}")
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'does not escape Confluence text effects' do
|
33
|
+
expect(renderer.block_quote('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
34
|
+
eq("\n\n{quote}bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??{quote}")
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#codespan(code)' do
|
40
|
+
it 'wraps the given code in double curly braces' do
|
41
|
+
expect(renderer.codespan("some normal freakin' code")).to eq("{{some normal freakin' code}}")
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'escapes Confluence text effects that should be added in other methods' do
|
45
|
+
expect(renderer.codespan('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
46
|
+
eq('{{\bq. \*some\* \_emphasized\_ \-text\- \+words\+\^like\^\~this\~ \{\{and this\}\} \??Stegman\??}}')
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#double_emphasis(text)' do
|
52
|
+
it 'wraps the given text in asterisks' do
|
53
|
+
expect(renderer.double_emphasis("some normal freakin' text")).to eq("*some normal freakin' text*")
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'does not escape Confluence text effects' do
|
57
|
+
expect(renderer.double_emphasis('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
58
|
+
eq('*bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??*')
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#emphasis(text)' do
|
64
|
+
it 'wraps the given text in underscores' do
|
65
|
+
expect(renderer.emphasis("some normal freakin' text")).to eq("_some normal freakin' text_")
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'does not escape Confluence text effects' do
|
69
|
+
expect(renderer.emphasis('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
70
|
+
eq('_bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??_')
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#header(title, level)' do
|
76
|
+
it 'prepends the header level to the given text' do
|
77
|
+
expect(renderer.header("some normal freakin' text", 5)).to eq("\n\nh5. some normal freakin' text")
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'does not escape Confluence text effects' do
|
81
|
+
expect(renderer.header('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??', 5)).to(
|
82
|
+
eq("\n\nh5. bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??")
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#hrule' do
|
88
|
+
it 'returns four hyphens' do
|
89
|
+
expect(renderer.hrule).to eq("\n\n----")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#image(link, title, alt)' do
|
94
|
+
it 'wraps the link in exclamation points' do
|
95
|
+
expect(renderer.image('http://google.com/', nil, nil)).to eq('!http://google.com/!')
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'passes the title and alt text to the image macro' do
|
99
|
+
expect(renderer.image('http://google.com/', 'title', 'alt text')).to(
|
100
|
+
eq('!http://google.com/|alt=alt text|title=title!')
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'escapes Confluence text effects that should be added in other methods' do
|
105
|
+
expect(renderer.image(
|
106
|
+
'http://google.com/',
|
107
|
+
'bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??',
|
108
|
+
'bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??'
|
109
|
+
)).to(
|
110
|
+
eq('!http://google.com/|alt=\bq. \*some\* \_emphasized\_ \-text\- \+words\+\^like\^\~this\~ \{\{and this\}\} \??Stegman\??|title=\bq. \*some\* \_emphasized\_ \-text\- \+words\+\^like\^\~this\~ \{\{and this\}\} \??Stegman\??!')
|
111
|
+
)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '#linebreak' do
|
116
|
+
it 'returns a newline' do
|
117
|
+
expect(renderer.linebreak).to eq("\n")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#link(link, title, content)' do
|
122
|
+
it 'wraps the link and content in brackets' do
|
123
|
+
expect(renderer.link('http://google.com/', nil, 'my link')).to eq('[my link|http://google.com/]')
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'does not include the title when empty' do
|
127
|
+
expect(renderer.link('http://google.com/', '', 'my link')).to eq('[my link|http://google.com/]')
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'includes the title when given' do
|
131
|
+
expect(renderer.link('http://google.com/', 'some title', 'my link')).to(
|
132
|
+
eq('[my link|http://google.com/|some title]')
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'escapes Confluence text effects in the title' do
|
137
|
+
expect(renderer.link('http://google.com/', 'bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??', 'bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
138
|
+
eq('[bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??|http://google.com/|\bq. \*some\* \_emphasized\_ \-text\- \+words\+\^like\^\~this\~ \{\{and this\}\} \??Stegman\??]')
|
139
|
+
)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#list(content, list_type)' do
|
144
|
+
it 'returns the given content' do
|
145
|
+
expect(renderer.list('* content', :whatever)).to eq("\n\n* content")
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns a nested list' do
|
149
|
+
expect(renderer.list("* content\n\n\n*# nested content\n* more content\n\n\n*# more nested", :whatever)).to eq("\n\n* content\n*# nested content\n* more content\n*# more nested")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#list_item(content, list_type)' do
|
154
|
+
context 'given an ordered list_type' do
|
155
|
+
it 'prepends an octothorpe to the content' do
|
156
|
+
expect(renderer.list_item('content', :ordered)).to eq("# content")
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'prepends an octothorpe to each existing list item in the content' do
|
160
|
+
expect(renderer.list_item("content\n* nested content\n* more nested", :ordered)).to eq("# content\n#* nested content\n#* more nested")
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'does not escape Confluence text effects' do
|
164
|
+
expect(renderer.list_item('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??', :ordered)).to(
|
165
|
+
eq('# bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')
|
166
|
+
)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'given an unordered list type' do
|
171
|
+
it 'prepends an asterisk to the content' do
|
172
|
+
expect(renderer.list_item('content', :unordered)).to eq("* content")
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'prepends an asterisk to each existing list item in the content' do
|
176
|
+
expect(renderer.list_item("content\n# nested content", :unordered)).to eq("* content\n*# nested content")
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'does not escape Confluence text effects' do
|
180
|
+
expect(renderer.list_item('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??', :unordered)).to(
|
181
|
+
eq('* bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')
|
182
|
+
)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '#normal_text(text)' do
|
188
|
+
it 'does not modify normal text' do
|
189
|
+
expect(renderer.normal_text("some normal freakin' text")).to eq("some normal freakin' text")
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'escapes Confluence text effects that should be added in other methods' do
|
193
|
+
expect(renderer.normal_text('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
194
|
+
eq('\bq. \*some\* \_emphasized\_ \-text\- \+words\+\^like\^\~this\~ \{\{and this\}\} \??Stegman\??')
|
195
|
+
)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe '#paragraph(text)' do
|
200
|
+
it 'appends two newlines to normal text' do
|
201
|
+
expect(renderer.paragraph("some normal freakin' text")).to eq("\n\nsome normal freakin' text")
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'does not escape Confluence text effects' do
|
205
|
+
expect(renderer.paragraph('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
206
|
+
eq("\n\nbq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??")
|
207
|
+
)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe '#strikethrough(text)' do
|
212
|
+
it 'wraps the given text in hyphens' do
|
213
|
+
expect(renderer.strikethrough("some normal freakin' text")).to eq("-some normal freakin' text-")
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'does not escape Confluence text effects' do
|
217
|
+
expect(renderer.strikethrough('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
218
|
+
eq('-bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??-')
|
219
|
+
)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe '#superscript(text)' do
|
224
|
+
it 'wraps the given text in hyphens' do
|
225
|
+
expect(renderer.superscript("some normal freakin' text")).to eq(" ^some normal freakin' text^ ")
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'does not escape Confluence text effects' do
|
229
|
+
expect(renderer.superscript('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
230
|
+
eq(' ^bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??^ ')
|
231
|
+
)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe '#table(header, body)' do
|
236
|
+
it 'appends the body to the formatted header' do
|
237
|
+
expect(renderer.table("\n|header|", "\n|body|")).to eq("\n\n||header||\n|body|")
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'does not escape Confluence text effects' do
|
241
|
+
expect(renderer.table(
|
242
|
+
"\n|bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??|",
|
243
|
+
"\n|bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??|"
|
244
|
+
)).to(
|
245
|
+
eq("\n\n||bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??||\n|bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??|")
|
246
|
+
)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe '#table_row(text)' do
|
251
|
+
it 'prepends a pipe to the text' do
|
252
|
+
expect(renderer.table_row('text|')).to eq("\n|text|")
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'does not escape Confluence text effects' do
|
256
|
+
expect(renderer.table_row('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??|')).to(
|
257
|
+
eq("\n|bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??|")
|
258
|
+
)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe '#table_cell(text, align)' do
|
263
|
+
it 'appends a pipe to the text' do
|
264
|
+
expect(renderer.table_cell('text', :ignored)).to eq('text|')
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'does not escape Confluence text effects' do
|
268
|
+
expect(renderer.table_cell('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??', :ignored)).to(
|
269
|
+
eq('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??|')
|
270
|
+
)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
describe '#triple_emphasis(text)' do
|
275
|
+
it 'wraps the given text in asterisks and underscores' do
|
276
|
+
expect(renderer.triple_emphasis("some normal freakin' text")).to eq("_*some normal freakin' text*_")
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'does not escape Confluence text effects' do
|
280
|
+
expect(renderer.triple_emphasis('bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??')).to(
|
281
|
+
eq('_*bq. *some* _emphasized_ -text- +words+^like^~this~ {{and this}} ??Stegman??*_')
|
282
|
+
)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
data/spec/smoke_spec.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'redcarpet/confluence'
|
3
|
+
|
4
|
+
describe 'Smoke Tests' do
|
5
|
+
let(:markdown_options) { {
|
6
|
+
autolink: true,
|
7
|
+
fenced_code_blocks: true,
|
8
|
+
no_intra_emphasis: true,
|
9
|
+
strikethrough: true,
|
10
|
+
superscript: true,
|
11
|
+
tables: true
|
12
|
+
} }
|
13
|
+
let(:renderer) { Redcarpet::Markdown.new(Redcarpet::Confluence, markdown_options) }
|
14
|
+
let(:markdown_text) { File.read(File.expand_path('../sample.md', __FILE__)).force_encoding('UTF-8') }
|
15
|
+
let(:confluence_text) { File.read(File.expand_path('../sample.confluence', __FILE__)).force_encoding('UTF-8') }
|
16
|
+
|
17
|
+
it 'renders the markdown into confluence correctly' do
|
18
|
+
expect(renderer.render(markdown_text)).to eq(confluence_text)
|
19
|
+
end
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
2
|
+
# in spec/support/ and its subdirectories.
|
3
|
+
Dir[File.join("support/**/*.rb")].each {|f| require f}
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
# Run specs in random order to surface order dependencies. If you find an
|
7
|
+
# order dependency and want to debug it, you can fix the order by providing
|
8
|
+
# the seed, which is printed after each run.
|
9
|
+
# --seed 1234
|
10
|
+
config.order = "random"
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redcarpet-confluence
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Stegman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-30 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: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A Redcarpet renderer to convert Markdown to Confluence syntax.
|
56
|
+
email:
|
57
|
+
- me@adamstegman.com
|
58
|
+
executables:
|
59
|
+
- md2conf
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- lib/redcarpet/confluence.rb
|
64
|
+
- Gemfile
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- redcarpet-confluence.gemspec
|
68
|
+
- spec/redcarpet/confluence_spec.rb
|
69
|
+
- spec/smoke_spec.rb
|
70
|
+
- spec/spec_helper.rb
|
71
|
+
- bin/md2conf
|
72
|
+
homepage: https://github.com/adamstegman/redcarpet-confluence
|
73
|
+
licenses: []
|
74
|
+
metadata: {}
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 2.0.3
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: A Redcarpet renderer to convert Markdown to Confluence syntax.
|
95
|
+
test_files:
|
96
|
+
- spec/redcarpet/confluence_spec.rb
|
97
|
+
- spec/smoke_spec.rb
|
98
|
+
- spec/spec_helper.rb
|
99
|
+
has_rdoc:
|