rembrandt 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +29 -1
- data/lib/rembrandt/config.rb +39 -0
- data/lib/rembrandt/engines/pygments_known_languages.rb +9 -0
- data/lib/rembrandt/engines/web_service.rb +1 -0
- data/lib/rembrandt/formatters/formatted_code.rb +21 -0
- data/lib/rembrandt/formatters/table.rb +10 -0
- data/lib/rembrandt/formatters/templates/table.erb +24 -0
- data/lib/rembrandt/highlighter.rb +52 -6
- data/lib/rembrandt/language_normalizer.rb +29 -0
- data/lib/rembrandt/stores/fetchable.rb +18 -0
- data/lib/rembrandt/stores/file.rb +51 -0
- data/lib/rembrandt/stores/redis.rb +33 -0
- data/lib/rembrandt/version.rb +1 -1
- data/rembrandt.gemspec +3 -0
- data/test/rembrandt/formatters/formatted_code_test.rb +16 -0
- data/test/rembrandt/formatters/table_test.rb +27 -3
- data/test/rembrandt/highlighter_test.rb +45 -12
- data/test/rembrandt/language_normalizer_test.rb +22 -0
- data/test/rembrandt/stores/file_test.rb +45 -0
- data/test/rembrandt/stores/redis_test.rb +67 -0
- data/test/support/ruby_sample_2.rb +3 -0
- data/test/support/ruby_sample_2.rb.html +4 -0
- data/test/support/ruby_sample_2.rb.tableized.html +28 -0
- metadata +53 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4e5b88327738db6739926a9ac97b9b9d6fb2ac6
|
4
|
+
data.tar.gz: 80181d4b01d282d0323ba3cd54e0a861f47f6760
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad2e5d4336e996780f08aa5bd9eb0065add68477d71fad5a3de3227259ff4659fab4d11a0545f9848f623aae64935b50b3fe8ad7a323df54e138521dccc1732c
|
7
|
+
data.tar.gz: ca01834cba775497338a4e1b56b781f15aeefdfe2cd8c54f66139db81b639f6237e1c5f6fc0f4684dc0bfefa0429ff7a46ad176ab94984c1b5c1517de993f034
|
data/README.md
CHANGED
@@ -18,7 +18,31 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
### Basic Highlighting
|
22
|
+
|
23
|
+
```irb
|
24
|
+
> require 'rembrandt'
|
25
|
+
> highlighter = Rembrandt::Highlighter.new
|
26
|
+
> highlighter.highlight("class Sample\nend", "ruby")
|
27
|
+
```
|
28
|
+
|
29
|
+
### Highlighting Source in a File
|
30
|
+
|
31
|
+
```irb
|
32
|
+
> require 'rembrandt'
|
33
|
+
> highlighter = Rembrandt::Highlighter.new
|
34
|
+
> highlighter.highlight_file("./my_input_file.rb", "ruby")
|
35
|
+
```
|
36
|
+
|
37
|
+
### Using a Formatter
|
38
|
+
|
39
|
+
```irb
|
40
|
+
> require 'rembrandt'
|
41
|
+
> highlighter = Rembrandt::Highlighter.new
|
42
|
+
> formatter = Rembrandt::Formatters::Table.new
|
43
|
+
> code = highlighter.highlight("class Sample\nend", "ruby")
|
44
|
+
> table = formatter.format(code, "ruby")
|
45
|
+
```
|
22
46
|
|
23
47
|
## Contributing
|
24
48
|
|
@@ -27,3 +51,7 @@ TODO: Write usage instructions here
|
|
27
51
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
52
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
53
|
5. Create new Pull Request
|
54
|
+
|
55
|
+
### When Developing
|
56
|
+
|
57
|
+
It's expected that when developing that you have both Redis and Python/Pygmentize available on your machine. If you don't have Pygments installed, Rembrant's tests will try to use the HTTP highlight engine which is blocked by VCR.
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Rembrandt
|
2
|
+
class Config
|
3
|
+
def self.default_language=(input)
|
4
|
+
@default_language = input
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.default_language
|
8
|
+
@default_language ||= library_default_language
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.library_default_language
|
12
|
+
"ruby"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.engine_priority=(engines)
|
16
|
+
@engine_priority = engines
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.engine_priority
|
20
|
+
@engine_priority ||= library_default_engine_priority
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.library_default_engine_priority
|
24
|
+
[Engines::Pygmentize, Engines::WebService]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.file_store_directory
|
28
|
+
@file_store_directory ||= library_default_file_store_directory
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.library_default_file_store_directory
|
32
|
+
'./tmp/.rembrandt_cache'
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.file_store_directory=(input)
|
36
|
+
@file_store_directory = input
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Rembrandt
|
2
|
+
module Engines
|
3
|
+
module PygmentsKnownLanguages
|
4
|
+
def known_languages
|
5
|
+
['sourceslist', 'sources.list', 'delphi', 'pas', 'pascal', 'objectpascal', 'js+mako', 'javascript+mako', 'iex', 'psql', 'postgresql-console', 'postgres-console', 'brainfuck', 'bf', 'ceylon', 'js+django', 'javascript+django', 'js+jinja', 'javascript+jinja', 'html+evoque', 'numpy', 'modula2', 'm2', 'live-script', 'livescript', 'nimrod', 'nim', 'bash', 'sh', 'ksh', 'html+django', 'html+jinja', 'css+php', 'xml+lasso', 'vim', 'css+genshitext', 'css+genshi', 'fancy', 'fy', 'cfm', 'cfs', 'ssp', 'smarty', 'xml+evoque', 'hx', 'haXe', 'powershell', 'posh', 'ps1', 'tea', 'html+cheetah', 'html+spitfire', 'rbcon', 'irb', 'mason', 'django', 'jinja', 'jags', 'apacheconf', 'aconf', 'apache', 'dtd', 'dylan-console', 'dylan-repl', 'lighty', 'lighttpd', 'java', 'js+genshitext', 'js+genshi', 'javascript+genshitext', 'javascript+genshi', 'scheme', 'scm', 'nemerle', 'rhtml', 'html+erb', 'html+ruby', 'ragel-java', 'dpatch', 'puppet', 'octave', 'coffee-script', 'coffeescript', 'ragel-d', 'scilab', 'monkey', 'html+myghty', 'erl', 'css', 'js+smarty', 'javascript+smarty', 'io', 'cobolfree', 'asy', 'asymptote', 'vhdl', 'python3', 'py3', 'css+erb', 'css+ruby', 'fortran', 'd-objdump', 'mysql', 'rebol', 'cpp', 'c++', 'erb', 'cbmbas', 'befunge', 'julia', 'jl', 'moon', 'moonscript', 'rb', 'ruby', 'duby', 'xml+smarty', 'dylan', 'groovy', 'trac-wiki', 'moin', 'ahk', 'c', 'html', 'felix', 'flx', 'cmake', 'nsis', 'nsi', 'nsh', 'sp', 'mako', 'vgl', 'velocity', 'koka', 'cuda', 'cu', 'gnuplot', 'irc', 'prolog', 'python', 'py', 'sage', 'css+django', 'css+jinja', 'verilog', 'v', 'smalltalk', 'squeak', 'js+myghty', 'javascript+myghty', 'yaml', 'antlr-as', 'antlr-actionscript', 'xml+mako', 'xslt', 'urbiscript', 'scaml', 'SCAML', 'splus', 's', 'r', 'dylan-lid', 'lid', 'maql', 'sqlite3', 'boo', 'ocaml', 'ec', 'as', 'actionscript', 'vb.net', 'vbnet', 'squidconf', 'squid.conf', 'squid', 'xquery', 'xqy', 'xq', 'xql', 'xqm', 'd', 'fan', 'pot', 'po', 'logos', 'jlcon', 'lasso', 'lassoscript', 'scss', 'bbcode', 'haml', 'HAML', 'Clipper', 'XBase', 'py3tb', 'mupad', 'xml+erb', 'xml+ruby', 'dart', 'idl', 'dg', 'evoque', 'jade', 'JADE', 'c-objdump', 'kconfig', 'menuconfig', 'linux-config', 'kernel-config', 'jsp', 'registry', 'abap', 'xml+velocity', 'js+cheetah', 'javascript+cheetah', 'js+spitfire', 'javascript+spitfire', 'html+mako', 'ragel-ruby', 'ragel-rb', 'RobotFramework', 'robotframework', 'protobuf', 'cfengine3', 'cf3', 'ragel', 'glsl', 'cobol', 'ts', 'ada', 'ada95ada2005', 'postgresql', 'postgres', 'xtend', 'logtalk', 'objdump', 'css+mako', 'ca65', 'objective-c++', 'objectivec++', 'obj-c++', 'objc++', 'Cucumber', 'cucumber', 'Gherkin', 'gherkin', 'html+php', 'make', 'makefile', 'mf', 'bsdmake', 'postscript', 'haxeml', 'hxml', 'kotlin', 'plpgsql', 'vala', 'vapi', 'haskell', 'hs', 'bro', 'lua', 'pov', 'sass', 'SASS', 'antlr-java', 'tcl', 'antlr-objc', 'js+erb', 'javascript+erb', 'js+ruby', 'javascript+ruby', 'racket', 'rkt', 'aspectj', 'basemake', 'antlr-python', 'cpp-objdump', 'c++-objdumb', 'cxx-objdump', 'genshitext', 'ioke', 'ik', 'pypylog', 'pypy', 'croc', 'objective-j', 'objectivej', 'obj-j', 'objj', 'gas', 'bat', 'snobol', 'pycon', 'xml', 'antlr', 'opa', 'xml+cheetah', 'xml+spitfire', 'go', 'diff', 'udiff', 'minid', 'cython', 'pyx', 'ragel-c', 'erlang', 'control', 'aspx-vb', 'bugs', 'winbugs', 'openbugs', 'ragel-cpp', 'aspx-cs', 'matlabsession', 'properties', 'groff', 'nroff', 'man', 'clojure', 'clj', 'modelica', 'qml', 'Qt Meta Language', 'Qt modeling Language', 'js+lasso', 'javascript+lasso', 'antlr-perl', 'genshi', 'kid', 'xml+genshi', 'xml+kid', 'blitzmax', 'bmax', 'treetop', 'matlab', 'myghty', 'html+genshi', 'html+kid', 'duel', 'Duel Engine', 'Duel View', 'JBST', 'jbst', 'JsonML+BST', 'perl', 'pl', 'fsharp', 'rst', 'rest', 'restructuredtext', 'newlisp', 'scala', 'css+lasso', 'xml+php', 'stan', 'ini', 'cfg', 'moocode', 'shell-session', 'spec', 'newspeak', 'console', 'coq', 'raw', 'tcsh', 'csh', 'html+lasso', 'csharp', 'c#', 'gst', 'rconsole', 'rout', 'mxml', 'tex', 'latex', 'css+smarty', 'text', 'antlr-csharp', 'antlr-c#', 'openedge', 'abl', 'progress', 'cheetah', 'spitfire', 'smali', 'css+myghty', 'rd', 'llvm', 'sml', 'elixir', 'ex', 'exs', 'nginx', 'gooddata-cl', 'applescript', 'html+smarty', 'objective-c', 'objectivec', 'obj-c', 'objc', 'js', 'javascript', 'rust', 'common-lisp', 'cl', 'ragel-em', 'as3', 'actionscript3', 'systemverilog', 'sv', 'lhs', 'literate-haskell', 'pytb', 'php', 'php3', 'php4', 'php5', 'antlr-cpp', 'gosu', 'hybris', 'hy', 'js+php', 'javascript+php', 'factor', 'html+velocity', 'mscgen', 'msc', 'ooc', 'sql', 'http', 'ecl', 'redcode', 'ragel-objc', 'xml+django', 'xml+jinja', 'awk', 'gawk', 'mawk', 'nawk', 'json', 'nasm', 'antlr-ruby', 'antlr-rb', 'xml+myghty', 'autoit', 'Autoit']
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rembrandt
|
2
|
+
module Formatters
|
3
|
+
class FormattedCode
|
4
|
+
attr_reader :code, :language
|
5
|
+
|
6
|
+
def initialize(input_code, input_language)
|
7
|
+
@code = extract_code_from_html(input_code)
|
8
|
+
@language = input_language
|
9
|
+
end
|
10
|
+
|
11
|
+
def line_count
|
12
|
+
code.lines.count
|
13
|
+
end
|
14
|
+
|
15
|
+
def extract_code_from_html(input)
|
16
|
+
matches = input.match(/<pre>(.+)<\/pre>/m)
|
17
|
+
matches[1] if matches
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,7 +1,17 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'tilt'
|
3
|
+
require_relative 'formatted_code'
|
4
|
+
|
1
5
|
module Rembrandt
|
2
6
|
module Formatters
|
3
7
|
class Table
|
8
|
+
def format(input_code, input_language)
|
9
|
+
template.render FormattedCode.new(input_code, input_language)
|
10
|
+
end
|
4
11
|
|
12
|
+
def template
|
13
|
+
@template ||= Tilt.new('./lib/rembrandt/formatters/templates/table.erb', :trim => true)
|
14
|
+
end
|
5
15
|
end
|
6
16
|
end
|
7
17
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<div class="highlight">
|
2
|
+
<table>
|
3
|
+
<tr>
|
4
|
+
<td class="gutter">
|
5
|
+
<pre class="line-numbers">
|
6
|
+
<% line_count.times do |i| %>
|
7
|
+
<span class='line-number'><%= i + 1 %></span>
|
8
|
+
<% end %>
|
9
|
+
</pre>
|
10
|
+
</td>
|
11
|
+
<td class='code'>
|
12
|
+
<pre>
|
13
|
+
<code class='<%= language %>'>
|
14
|
+
<% code.lines.each do |line| %>
|
15
|
+
<span class='line'>
|
16
|
+
<%= line %>
|
17
|
+
</span>
|
18
|
+
<% end %>
|
19
|
+
</code>
|
20
|
+
</pre>
|
21
|
+
</td>
|
22
|
+
</tr>
|
23
|
+
</table>
|
24
|
+
</div>
|
@@ -1,23 +1,69 @@
|
|
1
1
|
require_relative 'engines/pygmentize'
|
2
|
+
require_relative 'engines/web_service'
|
3
|
+
require_relative 'stores/file'
|
4
|
+
require_relative 'stores/redis'
|
5
|
+
require_relative 'config'
|
6
|
+
require_relative 'language_normalizer'
|
2
7
|
|
3
8
|
module Rembrandt
|
4
9
|
class Highlighter
|
5
|
-
|
10
|
+
attr_writer :store
|
6
11
|
|
7
12
|
def initialize(input_engine = nil)
|
8
|
-
@engine =
|
13
|
+
@engine = input_engine.new if input_engine
|
14
|
+
end
|
15
|
+
|
16
|
+
def engine
|
17
|
+
@engine ||= autoselect_engine
|
18
|
+
end
|
19
|
+
|
20
|
+
def store
|
21
|
+
@store ||= autoselect_store
|
9
22
|
end
|
10
23
|
|
11
24
|
def default_language
|
12
|
-
|
25
|
+
Config.default_language
|
26
|
+
end
|
27
|
+
|
28
|
+
def autoselect_store
|
29
|
+
redis = Stores::Redis.new
|
30
|
+
if redis.available?
|
31
|
+
redis
|
32
|
+
else
|
33
|
+
Stores::File.new
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def engines
|
38
|
+
Config.engine_priority
|
13
39
|
end
|
14
40
|
|
15
41
|
def autoselect_engine
|
16
|
-
|
42
|
+
begin
|
43
|
+
engines.detect(&:available?).new
|
44
|
+
rescue
|
45
|
+
raise "Error: no highlight engine is available."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def highlight(input, input_language = default_language)
|
50
|
+
language = normalize_language(input_language)
|
51
|
+
store.fetch(input, language) do
|
52
|
+
engine.highlight(input, language)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def highlight_file(filename, language = default_language)
|
57
|
+
data = File.read(filename)
|
58
|
+
highlight(data, language)
|
59
|
+
end
|
60
|
+
|
61
|
+
def normalize_language(input)
|
62
|
+
language_normalizer.process(input)
|
17
63
|
end
|
18
64
|
|
19
|
-
def
|
20
|
-
|
65
|
+
def language_normalizer
|
66
|
+
@language_normalizer ||= LanguageNormalizer.new
|
21
67
|
end
|
22
68
|
end
|
23
69
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'engines/pygments_known_languages'
|
2
|
+
|
3
|
+
module Rembrandt
|
4
|
+
class LanguageNormalizer
|
5
|
+
include Engines::PygmentsKnownLanguages
|
6
|
+
|
7
|
+
def known_language?(input)
|
8
|
+
known_languages.detect{|lang| lang == input}
|
9
|
+
end
|
10
|
+
|
11
|
+
def known_variant?(input)
|
12
|
+
known_variants[input]
|
13
|
+
end
|
14
|
+
|
15
|
+
def known_variants
|
16
|
+
{'ru' => 'ruby',
|
17
|
+
'm' => 'objc',
|
18
|
+
'yml' => 'yaml'}
|
19
|
+
end
|
20
|
+
|
21
|
+
def process(input)
|
22
|
+
known_language?(input) || known_variant?(input) || raise_exception(input)
|
23
|
+
end
|
24
|
+
|
25
|
+
def raise_exception(input)
|
26
|
+
raise ArgumentError.new("Unknown language specifier: #{input}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rembrandt
|
2
|
+
module Stores
|
3
|
+
module Fetchable
|
4
|
+
def key_for(input, language)
|
5
|
+
Digest::MD5.hexdigest(input + language)
|
6
|
+
end
|
7
|
+
|
8
|
+
def fetch(input, language)
|
9
|
+
result = read key_for(input, language)
|
10
|
+
if result.nil? && block_given?
|
11
|
+
data_to_store = yield
|
12
|
+
write(key_for(input, language), data_to_store)
|
13
|
+
return data_to_store
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'digest/md5'
|
3
|
+
require_relative 'fetchable'
|
4
|
+
|
5
|
+
module Rembrandt
|
6
|
+
module Stores
|
7
|
+
class File
|
8
|
+
include Fetchable
|
9
|
+
attr_reader :output_directory
|
10
|
+
|
11
|
+
def initialize(directory = nil)
|
12
|
+
self.output_directory = directory || Config.file_store_directory
|
13
|
+
create_directory
|
14
|
+
end
|
15
|
+
|
16
|
+
def output_directory=(name)
|
17
|
+
name += '/' unless name.end_with?('/')
|
18
|
+
@output_directory = name
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_directory
|
22
|
+
FileUtils.mkdir_p output_directory
|
23
|
+
end
|
24
|
+
|
25
|
+
def write(key, data)
|
26
|
+
::File.open( filename_for(key), "w" ) do |f|
|
27
|
+
f.write(data)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def read(key)
|
32
|
+
filename = filename_for(key)
|
33
|
+
if ::File.exist?(filename)
|
34
|
+
::File.read(filename_for(key))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def filename_for(key)
|
39
|
+
output_directory + prefix + key
|
40
|
+
end
|
41
|
+
|
42
|
+
def prefix
|
43
|
+
'rembrandt_'
|
44
|
+
end
|
45
|
+
|
46
|
+
def flush
|
47
|
+
`rm -rf #{output_directory}/*` if Dir.exist?(output_directory)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'redis'
|
3
|
+
require_relative 'fetchable'
|
4
|
+
|
5
|
+
module Rembrandt
|
6
|
+
module Stores
|
7
|
+
class Redis
|
8
|
+
include Fetchable
|
9
|
+
attr_reader :database, :url
|
10
|
+
|
11
|
+
def initialize(url = nil)
|
12
|
+
@url = ENV['REMBRANDT_REDIS_URL']
|
13
|
+
@database = ::Redis.new(:url => url)
|
14
|
+
end
|
15
|
+
|
16
|
+
def available?
|
17
|
+
defined?(::Redis)
|
18
|
+
end
|
19
|
+
|
20
|
+
def write(key, data)
|
21
|
+
database.set(key, data)
|
22
|
+
end
|
23
|
+
|
24
|
+
def read(key)
|
25
|
+
database.get(key)
|
26
|
+
end
|
27
|
+
|
28
|
+
def flush
|
29
|
+
database.flushdb
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/rembrandt/version.rb
CHANGED
data/rembrandt.gemspec
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
require './test/test_helper'
|
2
|
+
require './lib/rembrandt/formatters/formatted_code'
|
3
|
+
|
4
|
+
class FormattedCodeTest < CodeHighlightTest
|
5
|
+
def test_it_counts_lines
|
6
|
+
input = File.read('./test/support/ruby_sample_1.rb.html')
|
7
|
+
code = Rembrandt::Formatters::FormattedCode.new(input, 'ruby')
|
8
|
+
assert_equal 5, code.line_count
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_it_stores_the_language
|
12
|
+
input = File.read('./test/support/python_sample_1.py.html')
|
13
|
+
code = Rembrandt::Formatters::FormattedCode.new("", 'python')
|
14
|
+
assert_equal 'python', code.language
|
15
|
+
end
|
16
|
+
end
|
@@ -1,9 +1,33 @@
|
|
1
|
-
require '
|
2
|
-
require 'minitest/pride'
|
1
|
+
require './test/test_helper'
|
3
2
|
require './lib/rembrandt/formatters/table'
|
4
3
|
|
5
|
-
class FormattersTableTest <
|
4
|
+
class FormattersTableTest < CodeHighlightTest
|
5
|
+
attr_reader :formatter
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@formatter = Rembrandt::Formatters::Table.new
|
9
|
+
end
|
10
|
+
|
6
11
|
def test_it_exists
|
7
12
|
assert Rembrandt::Formatters::Table.new
|
8
13
|
end
|
14
|
+
|
15
|
+
def test_it_tableizes
|
16
|
+
input = File.read('./test/support/ruby_sample_2.rb.html')
|
17
|
+
expected = File.read('./test/support/ruby_sample_2.rb.tableized.html')
|
18
|
+
#expected_doc = Nokogiri::HTML(expected)
|
19
|
+
output = formatter.format(input, 'ruby')
|
20
|
+
#output_doc = Nokogiri::HTML(output)
|
21
|
+
|
22
|
+
#assert (expected_doc == output_doc), html_diff(expected_doc, output_doc)
|
23
|
+
assert_equal expected, output
|
24
|
+
end
|
25
|
+
|
26
|
+
def html_diff(doc_1, doc_2)
|
27
|
+
doc_1.diff(doc_2).collect do |change,node|
|
28
|
+
if ["+", "-"].include?(change)
|
29
|
+
"#{change} #{node.to_html}".ljust(30) + node.parent.path
|
30
|
+
end
|
31
|
+
end.reject!(&:nil?).join("\n")
|
32
|
+
end
|
9
33
|
end
|
@@ -17,7 +17,8 @@ class HighlighterTest < CodeHighlightTest
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_highlight_takes_an_input_and_a_language
|
20
|
-
|
20
|
+
result = highlighter.highlight("Hello, World", 'ruby')
|
21
|
+
assert result, "Got: #{result}"
|
21
22
|
end
|
22
23
|
|
23
24
|
def test_highlight_properly_highlights_ruby
|
@@ -28,6 +29,16 @@ class HighlighterTest < CodeHighlightTest
|
|
28
29
|
assert_highlight 'python_sample_1.py', 'python'
|
29
30
|
end
|
30
31
|
|
32
|
+
def test_it_highlights_a_file_directly
|
33
|
+
input_filename = './test/support/ruby_sample_1.rb'
|
34
|
+
expected = File.read('./test/support/ruby_sample_1.rb.html')
|
35
|
+
assert_equal expected, highlighter.highlight_file(input_filename, 'ruby')
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_it_normalizes_unusual_language_abbreviations
|
39
|
+
assert_highlight 'ruby_sample_1.rb', 'ru'
|
40
|
+
end
|
41
|
+
|
31
42
|
class StubEngine
|
32
43
|
def highlight(text, language)
|
33
44
|
"stub highlight"
|
@@ -39,18 +50,40 @@ class HighlighterTest < CodeHighlightTest
|
|
39
50
|
assert_equal "stub highlight", stubbed_highlighter.highlight("hello", "ruby")
|
40
51
|
end
|
41
52
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
53
|
+
class StubStore
|
54
|
+
def write(key, data)
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
def fetch(input, language)
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def flush
|
63
|
+
true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_it_uses_a_datastore
|
68
|
+
lighter = Rembrandt::Highlighter.new(StubEngine)
|
69
|
+
store = StubStore.new
|
70
|
+
highlighter.store = store
|
71
|
+
store.expects(:fetch).once
|
72
|
+
highlighter.highlight("Hello, World")
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_it_uses_the_default_language_from_config
|
76
|
+
Rembrandt::Config.default_language = "python"
|
77
|
+
assert_equal "python", highlighter.default_language
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_it_uses_the_engine_prioritization_from_config
|
81
|
+
preferred = [Rembrandt::Engines::Pygmentize]
|
82
|
+
Rembrandt::Config.engine_priority = preferred
|
83
|
+
assert_equal preferred, highlighter.engines
|
47
84
|
end
|
48
85
|
|
49
|
-
def
|
50
|
-
|
51
|
-
Rembrandt::Engines::WebService.stubs(:available?).returns(true)
|
52
|
-
expected_engine = Rembrandt::Engines::WebService
|
53
|
-
lighter = Rembrandt::Highlighter.new
|
54
|
-
assert_equal expected_engine, lighter.engine.class
|
86
|
+
def teardown
|
87
|
+
highlighter.store.flush
|
55
88
|
end
|
56
89
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require './test/test_helper'
|
2
|
+
require './lib/rembrandt/language_normalizer'
|
3
|
+
|
4
|
+
class LanguageNormalizerTest < CodeHighlightTest
|
5
|
+
attr_reader :normalizer
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@normalizer = Rembrandt::LanguageNormalizer.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_it_processes_a_known_variant
|
12
|
+
assert_equal 'ruby', normalizer.process('ru')
|
13
|
+
assert_equal 'objc', normalizer.process('m')
|
14
|
+
assert_equal 'yaml', normalizer.process('yml')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_it_cannot_process_an_unknown_language
|
18
|
+
assert_raises(ArgumentError){
|
19
|
+
normalizer.process('asdf')
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require './test/test_helper'
|
2
|
+
require './lib/rembrandt/stores/file'
|
3
|
+
require './lib/rembrandt/config'
|
4
|
+
|
5
|
+
class StoresFileTest < CodeHighlightTest
|
6
|
+
attr_reader :store
|
7
|
+
|
8
|
+
def target
|
9
|
+
Rembrandt::Config.file_store_directory
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@store = Rembrandt::Stores::File.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_it_creates_the_storage_folder
|
17
|
+
`rm -rf #{target}` if Dir.exist?(target)
|
18
|
+
refute Dir.exist?(target), "Directory #{target} should not exist."
|
19
|
+
store = Rembrandt::Stores::File.new(target)
|
20
|
+
assert Dir.exist?(target), "Directory #{target} should exist."
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_it_fetches_data_from_a_file
|
24
|
+
sample = "Hello, World!"
|
25
|
+
key = "001"
|
26
|
+
store.write(key, sample)
|
27
|
+
fetched = store.read(key)
|
28
|
+
assert_equal sample, fetched
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_it_calculates_keys
|
32
|
+
sample = "Hello, World!"
|
33
|
+
assert store.key_for(sample, 'ruby')
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_it_uses_the_configured_output_directory
|
37
|
+
Rembrandt::Config.file_store_directory = './tmp/'
|
38
|
+
store2 = Rembrandt::Stores::File.new
|
39
|
+
assert_equal './tmp/', store2.output_directory
|
40
|
+
end
|
41
|
+
|
42
|
+
def teardown
|
43
|
+
store.flush
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require './test/test_helper'
|
2
|
+
require './lib/rembrandt/stores/redis'
|
3
|
+
|
4
|
+
class StoresRedisTest < CodeHighlightTest
|
5
|
+
attr_reader :store
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@store = Rembrandt::Stores::Redis.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_it_is_not_available_when_redis_is_not_loaded
|
12
|
+
Object.const_set('REAL_REDIS', Redis)
|
13
|
+
Object.send(:remove_const, :Redis)
|
14
|
+
refute store.available?
|
15
|
+
Object.const_set('Redis', REAL_REDIS)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_it_is_available_when_redis_is_loaded
|
19
|
+
assert store.available?, "Redis should be available when required"
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_it_fetches_data
|
23
|
+
sample = "Hello, World!"
|
24
|
+
key = "001"
|
25
|
+
store.write(key, sample)
|
26
|
+
fetched = store.read(key)
|
27
|
+
assert_equal sample, fetched
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_it_calculates_keys
|
31
|
+
sample = "Hello, World!"
|
32
|
+
assert store.key_for(sample, 'ruby')
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_it_flushes_the_database
|
36
|
+
store.write("002", "Hello")
|
37
|
+
assert store.read("002")
|
38
|
+
store.flush
|
39
|
+
refute store.read("002"), "All keys should be gone"
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_fetch_does_not_write_when_there_is_no_block
|
43
|
+
refute store.fetch("hello", "ruby"), "hello should not be found"
|
44
|
+
key = store.key_for("hello", "ruby")
|
45
|
+
refute store.read(key), "hello should not have been written"
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_fetch_writes_the_result_of_a_block
|
49
|
+
refute store.fetch("hello", "ruby")
|
50
|
+
result = store.fetch("hello", "ruby"){ "Hello, World" }
|
51
|
+
assert_equal "Hello, World", result
|
52
|
+
key = store.key_for("hello", "ruby")
|
53
|
+
assert_equal result, store.read(key)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_it_uses_a_redis_url_in_an_environment_variable
|
57
|
+
url = "redis://redisuser:redispassword@provider.example.com:9352/"
|
58
|
+
ENV['REMBRANDT_REDIS_URL'] = url
|
59
|
+
store2 = Rembrandt::Stores::Redis.new
|
60
|
+
assert_equal url, store2.url
|
61
|
+
ENV['REMBRANDT_REDIS_URL'] = ''
|
62
|
+
end
|
63
|
+
|
64
|
+
def teardown
|
65
|
+
store.flush
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<div class="highlight"><pre><span class="ss">Blogger</span><span class="p">:</span><span class="ss">:Application</span><span class="o">.</span><span class="n">routes</span><span class="o">.</span><span class="n">draw</span> <span class="k">do</span>
|
2
|
+
<span class="n">resources</span> <span class="ss">:articles</span>
|
3
|
+
<span class="k">end</span>
|
4
|
+
</pre></div>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<div class="highlight">
|
2
|
+
<table>
|
3
|
+
<tr>
|
4
|
+
<td class="gutter">
|
5
|
+
<pre class="line-numbers">
|
6
|
+
<span class='line-number'>1</span>
|
7
|
+
<span class='line-number'>2</span>
|
8
|
+
<span class='line-number'>3</span>
|
9
|
+
</pre>
|
10
|
+
</td>
|
11
|
+
<td class='code'>
|
12
|
+
<pre>
|
13
|
+
<code class='ruby'>
|
14
|
+
<span class='line'>
|
15
|
+
<span class="ss">Blogger</span><span class="p">:</span><span class="ss">:Application</span><span class="o">.</span><span class="n">routes</span><span class="o">.</span><span class="n">draw</span> <span class="k">do</span>
|
16
|
+
</span>
|
17
|
+
<span class='line'>
|
18
|
+
<span class="n">resources</span> <span class="ss">:articles</span>
|
19
|
+
</span>
|
20
|
+
<span class='line'>
|
21
|
+
<span class="k">end</span>
|
22
|
+
</span>
|
23
|
+
</code>
|
24
|
+
</pre>
|
25
|
+
</td>
|
26
|
+
</tr>
|
27
|
+
</table>
|
28
|
+
</div>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rembrandt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Casimir
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,6 +108,34 @@ dependencies:
|
|
108
108
|
- - '>='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: redis
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: tilt
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
description: A library for generating and storing syntax-highlighted code
|
112
140
|
email:
|
113
141
|
- jeff@casimircreative.com
|
@@ -122,20 +150,35 @@ files:
|
|
122
150
|
- README.md
|
123
151
|
- Rakefile
|
124
152
|
- lib/rembrandt.rb
|
153
|
+
- lib/rembrandt/config.rb
|
125
154
|
- lib/rembrandt/engines/pygmentize.rb
|
155
|
+
- lib/rembrandt/engines/pygments_known_languages.rb
|
126
156
|
- lib/rembrandt/engines/web_service.rb
|
157
|
+
- lib/rembrandt/formatters/formatted_code.rb
|
127
158
|
- lib/rembrandt/formatters/table.rb
|
159
|
+
- lib/rembrandt/formatters/templates/table.erb
|
128
160
|
- lib/rembrandt/highlighter.rb
|
161
|
+
- lib/rembrandt/language_normalizer.rb
|
162
|
+
- lib/rembrandt/stores/fetchable.rb
|
163
|
+
- lib/rembrandt/stores/file.rb
|
164
|
+
- lib/rembrandt/stores/redis.rb
|
129
165
|
- lib/rembrandt/version.rb
|
130
166
|
- rembrandt.gemspec
|
131
167
|
- test/rembrandt/engines/pygmentize_test.rb
|
132
168
|
- test/rembrandt/engines/web_service_test.rb
|
169
|
+
- test/rembrandt/formatters/formatted_code_test.rb
|
133
170
|
- test/rembrandt/formatters/table_test.rb
|
134
171
|
- test/rembrandt/highlighter_test.rb
|
172
|
+
- test/rembrandt/language_normalizer_test.rb
|
173
|
+
- test/rembrandt/stores/file_test.rb
|
174
|
+
- test/rembrandt/stores/redis_test.rb
|
135
175
|
- test/support/python_sample_1.py
|
136
176
|
- test/support/python_sample_1.py.html
|
137
177
|
- test/support/ruby_sample_1.rb
|
138
178
|
- test/support/ruby_sample_1.rb.html
|
179
|
+
- test/support/ruby_sample_2.rb
|
180
|
+
- test/support/ruby_sample_2.rb.html
|
181
|
+
- test/support/ruby_sample_2.rb.tableized.html
|
139
182
|
- test/support/vcr_cassettes/web_engine_highlights_ruby_sample_1.yml
|
140
183
|
- test/support/vcr_cassettes/web_engine_is_accessible.yml
|
141
184
|
- test/test_helper.rb
|
@@ -159,19 +202,26 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
202
|
version: '0'
|
160
203
|
requirements: []
|
161
204
|
rubyforge_project:
|
162
|
-
rubygems_version: 2.
|
205
|
+
rubygems_version: 2.0.6
|
163
206
|
signing_key:
|
164
207
|
specification_version: 4
|
165
208
|
summary: Powered by the amazing Pygments Python library.
|
166
209
|
test_files:
|
167
210
|
- test/rembrandt/engines/pygmentize_test.rb
|
168
211
|
- test/rembrandt/engines/web_service_test.rb
|
212
|
+
- test/rembrandt/formatters/formatted_code_test.rb
|
169
213
|
- test/rembrandt/formatters/table_test.rb
|
170
214
|
- test/rembrandt/highlighter_test.rb
|
215
|
+
- test/rembrandt/language_normalizer_test.rb
|
216
|
+
- test/rembrandt/stores/file_test.rb
|
217
|
+
- test/rembrandt/stores/redis_test.rb
|
171
218
|
- test/support/python_sample_1.py
|
172
219
|
- test/support/python_sample_1.py.html
|
173
220
|
- test/support/ruby_sample_1.rb
|
174
221
|
- test/support/ruby_sample_1.rb.html
|
222
|
+
- test/support/ruby_sample_2.rb
|
223
|
+
- test/support/ruby_sample_2.rb.html
|
224
|
+
- test/support/ruby_sample_2.rb.tableized.html
|
175
225
|
- test/support/vcr_cassettes/web_engine_highlights_ruby_sample_1.yml
|
176
226
|
- test/support/vcr_cassettes/web_engine_is_accessible.yml
|
177
227
|
- test/test_helper.rb
|