makeup 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +30 -0
- data/Rakefile +10 -0
- data/Readme.md +68 -0
- data/lib/makeup/code_block_parser.rb +85 -0
- data/lib/makeup/markup.rb +56 -0
- data/lib/makeup/syntax_highlighter.rb +94 -0
- data/lib/makeup.rb +28 -0
- data/makeup.gemspec +32 -0
- data/test/makeup/markup_test.rb +92 -0
- data/test/makeup/syntax_highlighter_test.rb +108 -0
- data/test/test_helper.rb +36 -0
- metadata +110 -7
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
makeup (0.1.0)
|
5
|
+
github-markup (~> 0.7)
|
6
|
+
htmlentities (~> 4.3)
|
7
|
+
pygments.rb (~> 0.2)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
github-markup (0.7.4)
|
13
|
+
htmlentities (4.3.1)
|
14
|
+
minitest (2.12.1)
|
15
|
+
posix-spawn (0.3.6)
|
16
|
+
pygments.rb (0.3.1)
|
17
|
+
posix-spawn (~> 0.3.6)
|
18
|
+
yajl-ruby (~> 1.1.0)
|
19
|
+
rake (0.9.2.2)
|
20
|
+
redcarpet (2.1.1)
|
21
|
+
yajl-ruby (1.1.0)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
makeup!
|
28
|
+
minitest (~> 2.0)
|
29
|
+
rake (~> 0.9)
|
30
|
+
redcarpet
|
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Makeup
|
2
|
+
|
3
|
+
Makeup provides markup rendering and syntax highlighting in one glorious
|
4
|
+
package. It can also syntax highlight "fenced code blocks" in markdown files.
|
5
|
+
|
6
|
+
`Makeup` does all its heavylifting through `GitHub::Markup` and `Pygments.rb`,
|
7
|
+
and combines the two for killer code blocks in markup files.
|
8
|
+
|
9
|
+
## Markup
|
10
|
+
|
11
|
+
Rendering markup is done through `Makeup::Markup`. For information about markup
|
12
|
+
formats, what gems to install for various format support etc see the
|
13
|
+
[`GitHub::Markup` docs](https://github.com/github/markup/).
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require "makeup"
|
17
|
+
|
18
|
+
Makeup::Markup.new.render("file.md", "# Some markdown")
|
19
|
+
```
|
20
|
+
|
21
|
+
`GitHub::Markup` uses the file name to decide what markup format to render the
|
22
|
+
contents with.
|
23
|
+
|
24
|
+
To extract and syntax highlight "fenced code blocks" with Pygments, give the
|
25
|
+
markup renderer a highlighter:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require "makeup"
|
29
|
+
|
30
|
+
highlighter = Makeup::SyntaxHighlighter.new
|
31
|
+
renderer = Makeup::Markup.new(:highlighter => highlighter)
|
32
|
+
renderer.render("file.md", <<MD)
|
33
|
+
# Documentation and examples
|
34
|
+
|
35
|
+
## s-trim `(s)`
|
36
|
+
|
37
|
+
Remove whitespace at the beginning and end of `s`.
|
38
|
+
|
39
|
+
\`\`\`cl
|
40
|
+
(s-trim "trim ") ;; => "trim"
|
41
|
+
(s-trim " this") ;; => "this"
|
42
|
+
(s-trim " only trims beg and end ") ;; => "only trims beg and end"
|
43
|
+
\`\`\`
|
44
|
+
MD
|
45
|
+
```
|
46
|
+
|
47
|
+
The fenced code block will be syntax highlighted with the common lisp lexer.
|
48
|
+
|
49
|
+
## Syntax highlighting
|
50
|
+
|
51
|
+
`Makeup` provides a very thin abstraction around `Pygments.rb` for syntax
|
52
|
+
highlighting:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
require "makeup"
|
56
|
+
|
57
|
+
highlighter = Makeup::SyntaxHighlighter.new
|
58
|
+
res = highlighter.highlight(person.rb", <<RUBY)
|
59
|
+
class Person
|
60
|
+
def speak
|
61
|
+
"Hello"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
RUBY
|
65
|
+
|
66
|
+
res.lexer # "ruby"
|
67
|
+
res.code # HTML-formatted syntax highlighted code
|
68
|
+
```
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# --
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Gitorious AS
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#++
|
25
|
+
|
26
|
+
module Makeup
|
27
|
+
class CodeBlockParser
|
28
|
+
attr_reader :lines
|
29
|
+
|
30
|
+
def self.parse(markup, &block)
|
31
|
+
new(markup).parse(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(markup)
|
35
|
+
@lines = markup.split("\n")
|
36
|
+
@current_code_bock = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse(&block)
|
40
|
+
result = []
|
41
|
+
|
42
|
+
while line = @lines.shift
|
43
|
+
if closes_code_block?(line)
|
44
|
+
result << block.call(*close_active_code_block)
|
45
|
+
elsif active_code_block?
|
46
|
+
append_active_code_block(line)
|
47
|
+
elsif starts_code_block?(line)
|
48
|
+
start_code_block(line)
|
49
|
+
else
|
50
|
+
result << line
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
result.join("\n")
|
55
|
+
end
|
56
|
+
|
57
|
+
def active_code_block?
|
58
|
+
!@current_code_bock.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
def starts_code_block?(line)
|
62
|
+
line.match(/^```.*/)
|
63
|
+
end
|
64
|
+
|
65
|
+
def closes_code_block?(line)
|
66
|
+
active_code_block? && line == "```"
|
67
|
+
end
|
68
|
+
|
69
|
+
def start_code_block(line)
|
70
|
+
m = line.match(/```([^\s]+)/)
|
71
|
+
@current_code_bock = [m && m[1], []]
|
72
|
+
end
|
73
|
+
|
74
|
+
def append_active_code_block(line)
|
75
|
+
@current_code_bock[1] << line
|
76
|
+
end
|
77
|
+
|
78
|
+
def close_active_code_block
|
79
|
+
lexer = @current_code_bock[0]
|
80
|
+
code = @current_code_bock[1].join("\n")
|
81
|
+
@current_code_bock = nil
|
82
|
+
[lexer, code]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# --
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Gitorious AS
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#++
|
25
|
+
require "github/markup"
|
26
|
+
require "makeup/code_block_parser"
|
27
|
+
require "makeup/syntax_highlighter"
|
28
|
+
|
29
|
+
module Makeup
|
30
|
+
class NoopHighlighter
|
31
|
+
def highlight(path, code, options = {})
|
32
|
+
lexer = options[:lexer] || path.split(".").last
|
33
|
+
CodeBlock.new(lexer, code)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Markup
|
38
|
+
def initialize(options = {})
|
39
|
+
@markup_class_name = options[:markup_class_name] || "prettyprint"
|
40
|
+
@highlighter = options[:highlighter] || NoopHighlighter.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def render(path, content)
|
44
|
+
content = highlight_code_blocks(path, content)
|
45
|
+
GitHub::Markup.render(path, content)
|
46
|
+
end
|
47
|
+
|
48
|
+
def highlight_code_blocks(path, markup)
|
49
|
+
return markup unless path =~ /\.(md|mkdn?|mdwn|mdown|markdown)$/
|
50
|
+
CodeBlockParser.parse(markup) do |lexer, code|
|
51
|
+
hb = @highlighter.highlight(path, code, { :lexer => lexer })
|
52
|
+
"<pre class=\"#{hb.lexer} #{@markup_class_name}\">#{hb.code}</pre>"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# --
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Gitorious AS
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#++
|
25
|
+
require "pygments"
|
26
|
+
require "htmlentities"
|
27
|
+
|
28
|
+
module Makeup
|
29
|
+
CodeBlock = Struct.new(:lexer, :code)
|
30
|
+
|
31
|
+
class SyntaxHighlighter
|
32
|
+
def initialize
|
33
|
+
@entities = HTMLEntities.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def highlight(path, code, options = {})
|
37
|
+
options[:lexer] ||= lexer(path, code)
|
38
|
+
lexer = Pygments::Lexer.find(options[:lexer])
|
39
|
+
CodeBlock.new(lexer && lexer.aliases.first,
|
40
|
+
Pygments.highlight(code, highlight_options(options)))
|
41
|
+
rescue MentosError => e
|
42
|
+
# "MentosError" is what Pyments.rb raises when an unknown lexer is
|
43
|
+
# attempted used
|
44
|
+
CodeBlock.new(nil, @entities.encode(code))
|
45
|
+
end
|
46
|
+
|
47
|
+
def lexer(path, code = nil)
|
48
|
+
self.class.lexer(path.split(".").pop, code)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.lexer(suffix, code = nil)
|
52
|
+
return @@lexer_aliases[suffix] if @@lexer_aliases[suffix]
|
53
|
+
lexer = Pygments::Lexer.find_by_extname(".#{suffix}")
|
54
|
+
return lexer.aliases.first || lexer.name if lexer
|
55
|
+
shebang_language(shebang(code)) || suffix
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.shebang(code)
|
59
|
+
first_line = (code || "").split("\n")[0]
|
60
|
+
first_line =~ /^#!/ ? first_line : nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.shebang_language(shebang)
|
64
|
+
shebang = @@lexer_shebangs.find { |s| (shebang || "") =~ s[:pattern] }
|
65
|
+
shebang && shebang[:lexer]
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.add_lexer_alias(extension, lexer)
|
69
|
+
@@lexer_aliases ||= {}
|
70
|
+
@@lexer_aliases[extension] = lexer
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.add_lexer_shebang(pattern, lexer)
|
74
|
+
@@lexer_shebangs ||= []
|
75
|
+
@@lexer_shebangs << { :pattern => pattern, :lexer => lexer }
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
def highlight_options(options = {})
|
80
|
+
options[:options] ||= {}
|
81
|
+
options[:options][:nowrap] = true
|
82
|
+
options[:options][:encoding] ||= "utf-8"
|
83
|
+
options
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Makeup::SyntaxHighlighter.add_lexer_alias("txt", "text")
|
89
|
+
Makeup::SyntaxHighlighter.add_lexer_alias("ru", "rb")
|
90
|
+
Makeup::SyntaxHighlighter.add_lexer_alias("Rakefile", "rb")
|
91
|
+
Makeup::SyntaxHighlighter.add_lexer_alias("Gemfile", "rb")
|
92
|
+
Makeup::SyntaxHighlighter.add_lexer_alias("Gemfile.lock", "yaml")
|
93
|
+
|
94
|
+
Makeup::SyntaxHighlighter.add_lexer_shebang(/\bruby\b/, "rb")
|
data/lib/makeup.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# --
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Gitorious AS
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#++
|
25
|
+
|
26
|
+
module Makeup
|
27
|
+
VERSION = "0.1.0"
|
28
|
+
end
|
data/makeup.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
dir = File.expand_path(File.dirname(__FILE__))
|
3
|
+
require File.join(dir, "lib", "makeup")
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "makeup"
|
7
|
+
s.version = Makeup::VERSION
|
8
|
+
s.authors = ["Christian Johansen"]
|
9
|
+
s.email = ["christian@gitorious.org"]
|
10
|
+
s.homepage = "http://gitorious.org/gitorious/makeup"
|
11
|
+
s.summary = %q{Pretty markup}
|
12
|
+
s.description = <<-DESC
|
13
|
+
Makeup provides markup rendering and code highlighting. It renders all kinds of
|
14
|
+
markup formats using GitHub::Markup, and implements "fenced code blocks" for
|
15
|
+
markdown files.
|
16
|
+
DESC
|
17
|
+
|
18
|
+
s.rubyforge_project = "makeup"
|
19
|
+
|
20
|
+
s.add_dependency "pygments.rb", "~>0.2"
|
21
|
+
s.add_dependency "github-markup", "~> 0.7"
|
22
|
+
s.add_dependency "htmlentities", "~> 4.3"
|
23
|
+
|
24
|
+
s.add_development_dependency "minitest", "~> 2.0"
|
25
|
+
s.add_development_dependency "rake", "~> 0.9"
|
26
|
+
s.add_development_dependency "redcarpet"
|
27
|
+
|
28
|
+
s.files = `git ls-files`.split("\n")
|
29
|
+
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
30
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
31
|
+
s.require_paths = ["lib"]
|
32
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# --
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Gitorious AS
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#++
|
25
|
+
require "test_helper"
|
26
|
+
require "makeup/markup"
|
27
|
+
|
28
|
+
describe Makeup::Markup do
|
29
|
+
before do
|
30
|
+
@highlighter = Makeup::SyntaxHighlighter.new
|
31
|
+
@renderer = Makeup::Markup.new(:highlighter => @highlighter)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#render" do
|
35
|
+
it "renders multi-line code blocks with syntax highlighting" do
|
36
|
+
html = @renderer.render("file.md", <<-MD)
|
37
|
+
```cl
|
38
|
+
(s-trim-left "trim ") ;; => "trim "
|
39
|
+
(s-trim-left " this") ;; => "this"
|
40
|
+
```
|
41
|
+
MD
|
42
|
+
|
43
|
+
assert_match "<pre class=\"common-lisp prettyprint\">", html
|
44
|
+
end
|
45
|
+
|
46
|
+
it "highlights multiple separate multi-line code blocks" do
|
47
|
+
html = @renderer.render("file.md", <<-MD)
|
48
|
+
# This stuff
|
49
|
+
|
50
|
+
```cl
|
51
|
+
(s-trim-left "trim ") ;; => "trim "
|
52
|
+
(s-trim-left " this") ;; => "this"
|
53
|
+
```
|
54
|
+
|
55
|
+
# And this stuff
|
56
|
+
|
57
|
+
```cl
|
58
|
+
(s-trim-left "trim ") ;; => "trim "
|
59
|
+
(s-trim-left " this") ;; => "this"
|
60
|
+
```
|
61
|
+
MD
|
62
|
+
|
63
|
+
assert_equal 2, html.scan(/common-lisp/).length
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#highlight_code_blocks" do
|
68
|
+
it "does not touch non-markdown files" do
|
69
|
+
content = "```cl\n(yup)\n```"
|
70
|
+
highlighted = @renderer.highlight_code_blocks("file.rst", content)
|
71
|
+
assert_equal content, highlighted
|
72
|
+
end
|
73
|
+
|
74
|
+
it "highlights one-line code block" do
|
75
|
+
content = "```cl\n(yup)\n```"
|
76
|
+
highlighted = @renderer.highlight_code_blocks("file.md", content)
|
77
|
+
assert_match "common-lisp", highlighted
|
78
|
+
end
|
79
|
+
|
80
|
+
it "highlights multi-line code block" do
|
81
|
+
content = "```cl\n(yup)\n(yessir-p t)\n```"
|
82
|
+
highlighted = @renderer.highlight_code_blocks("file.md", content)
|
83
|
+
assert_match "(</span><span class=\"nv\">yessir-p</span>", highlighted
|
84
|
+
end
|
85
|
+
|
86
|
+
it "preserves code block white-space" do
|
87
|
+
content = "```cl\n(yup\n (yessir-p t))\n```"
|
88
|
+
highlighted = @renderer.highlight_code_blocks("file.md", content)
|
89
|
+
assert_match "\n <span class=\"p\">(</span>", highlighted
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# --
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Gitorious AS
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#++
|
25
|
+
require "test_helper"
|
26
|
+
require "makeup/syntax_highlighter"
|
27
|
+
|
28
|
+
describe Makeup::SyntaxHighlighter do
|
29
|
+
include Makeup::Html
|
30
|
+
before { @highlighter = Makeup::SyntaxHighlighter.new }
|
31
|
+
|
32
|
+
def highlight(path, code)
|
33
|
+
@highlighter.highlight(path, code).code
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#highlight" do
|
37
|
+
it "returns code and lexer name" do
|
38
|
+
block = @highlighter.highlight("file.rb", "class File;")
|
39
|
+
|
40
|
+
assert_match "<span class=\"k\">class</span>", block.code
|
41
|
+
assert_equal "rb", block.lexer
|
42
|
+
end
|
43
|
+
|
44
|
+
it "highlights a Ruby file" do
|
45
|
+
html = highlight("file.rb", "class File\n attr_reader :path\nend")
|
46
|
+
|
47
|
+
assert_match "<span class=\"k\">class</span>", html
|
48
|
+
assert_match "<span class=\"nc\">File</span>", html
|
49
|
+
end
|
50
|
+
|
51
|
+
it "highlights a YAML file" do
|
52
|
+
html = highlight("file.yml", "something:\n is: true")
|
53
|
+
|
54
|
+
assert_match "<span class=\"l-Scalar-Plain\">something</span>", html
|
55
|
+
assert_match "<span class=\"p-Indicator\">:", html
|
56
|
+
end
|
57
|
+
|
58
|
+
it "highlights an .htm file" do
|
59
|
+
html = highlight("file.htm", "<h1>Hey</h1>")
|
60
|
+
|
61
|
+
assert_match "<span class=\"nt\"><h1></span>", html
|
62
|
+
assert_match "Hey<span class=\"nt\"></h1></span>", html
|
63
|
+
end
|
64
|
+
|
65
|
+
it "highlights file with custom suffix" do
|
66
|
+
Makeup::SyntaxHighlighter.add_lexer_alias("derp", "rb")
|
67
|
+
html = highlight("file.derp", "class File")
|
68
|
+
|
69
|
+
assert_match "<span class=\"k\">class</span>", html
|
70
|
+
assert_match "<span class=\"nc\">File</span>", html
|
71
|
+
end
|
72
|
+
|
73
|
+
it "skips highlighting if lexer is missing" do
|
74
|
+
html = highlight("file.trololol", "Yeah yeah yeah")
|
75
|
+
|
76
|
+
assert_equal "Yeah yeah yeah", html
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#lexer" do
|
81
|
+
it "uses known suffix" do
|
82
|
+
assert_equal "rb", @highlighter.lexer("file.rb")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "uses registered suffix" do
|
86
|
+
Makeup::SyntaxHighlighter.add_lexer_alias("blarg", "blarg")
|
87
|
+
assert_equal "blarg", @highlighter.lexer("file.blarg")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "uses registered lexer" do
|
91
|
+
Makeup::SyntaxHighlighter.add_lexer_alias("bg", "blarg")
|
92
|
+
assert_equal "blarg", @highlighter.lexer("file.bg")
|
93
|
+
end
|
94
|
+
|
95
|
+
it "uses known shebang" do
|
96
|
+
assert_equal "rb", @highlighter.lexer("some-binary", "#!/usr/bin/env ruby\n")
|
97
|
+
end
|
98
|
+
|
99
|
+
it "uses registered shebang" do
|
100
|
+
Makeup::SyntaxHighlighter.add_lexer_shebang(/\bnode\b/, "js")
|
101
|
+
assert_equal "js", @highlighter.lexer("some-binary", "#!/usr/bin/env node\n")
|
102
|
+
end
|
103
|
+
|
104
|
+
it "uses filename for unknown lexer" do
|
105
|
+
assert_equal "some-binary", @highlighter.lexer("some-binary", "class Person\nend")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# --
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2012 Gitorious AS
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#++
|
25
|
+
require "bundler/setup"
|
26
|
+
require "minitest/autorun"
|
27
|
+
|
28
|
+
Bundler.require(:default, :test)
|
29
|
+
|
30
|
+
module Makeup
|
31
|
+
module Html
|
32
|
+
def select(html, tag_name)
|
33
|
+
html.scan(/<#{tag_name}[^>]*>.*?<\/#{tag_name}>/m)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: makeup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.0
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Christian Johansen
|
@@ -17,9 +17,101 @@ cert_chain: []
|
|
17
17
|
|
18
18
|
date: 2012-10-05 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: pygments.rb
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 15
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 2
|
33
|
+
version: "0.2"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: github-markup
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 5
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 7
|
48
|
+
version: "0.7"
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: htmlentities
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 29
|
60
|
+
segments:
|
61
|
+
- 4
|
62
|
+
- 3
|
63
|
+
version: "4.3"
|
64
|
+
type: :runtime
|
65
|
+
version_requirements: *id003
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: minitest
|
68
|
+
prerelease: false
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ~>
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
75
|
+
segments:
|
76
|
+
- 2
|
77
|
+
- 0
|
78
|
+
version: "2.0"
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rake
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 25
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
- 9
|
93
|
+
version: "0.9"
|
94
|
+
type: :development
|
95
|
+
version_requirements: *id005
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: redcarpet
|
98
|
+
prerelease: false
|
99
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
hash: 3
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
version: "0"
|
108
|
+
type: :development
|
109
|
+
version_requirements: *id006
|
110
|
+
description: |
|
111
|
+
Makeup provides markup rendering and code highlighting. It renders all kinds of
|
112
|
+
markup formats using GitHub::Markup, and implements "fenced code blocks" for
|
113
|
+
markdown files.
|
21
114
|
|
22
|
-
description:
|
23
115
|
email:
|
24
116
|
- christian@gitorious.org
|
25
117
|
executables: []
|
@@ -28,8 +120,19 @@ extensions: []
|
|
28
120
|
|
29
121
|
extra_rdoc_files: []
|
30
122
|
|
31
|
-
files:
|
32
|
-
|
123
|
+
files:
|
124
|
+
- Gemfile
|
125
|
+
- Gemfile.lock
|
126
|
+
- Rakefile
|
127
|
+
- Readme.md
|
128
|
+
- lib/makeup.rb
|
129
|
+
- lib/makeup/code_block_parser.rb
|
130
|
+
- lib/makeup/markup.rb
|
131
|
+
- lib/makeup/syntax_highlighter.rb
|
132
|
+
- makeup.gemspec
|
133
|
+
- test/makeup/markup_test.rb
|
134
|
+
- test/makeup/syntax_highlighter_test.rb
|
135
|
+
- test/test_helper.rb
|
33
136
|
has_rdoc: true
|
34
137
|
homepage: http://gitorious.org/gitorious/makeup
|
35
138
|
licenses: []
|