nagoro 2009.05

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/CHANGELOG +446 -0
  2. data/MANIFEST +51 -0
  3. data/README.markdown +189 -0
  4. data/Rakefile +29 -0
  5. data/bin/nagoro +83 -0
  6. data/doc/COPYING +56 -0
  7. data/doc/GPL +340 -0
  8. data/doc/LEGAL +2 -0
  9. data/example/element/Html.nage +8 -0
  10. data/example/hello.nag +3 -0
  11. data/example/morpher.nag +23 -0
  12. data/lib/nagoro.rb +22 -0
  13. data/lib/nagoro/binding.rb +8 -0
  14. data/lib/nagoro/element.rb +46 -0
  15. data/lib/nagoro/pipe.rb +12 -0
  16. data/lib/nagoro/pipe/base.rb +56 -0
  17. data/lib/nagoro/pipe/compile.rb +30 -0
  18. data/lib/nagoro/pipe/element.rb +70 -0
  19. data/lib/nagoro/pipe/include.rb +36 -0
  20. data/lib/nagoro/pipe/instruction.rb +64 -0
  21. data/lib/nagoro/pipe/localization.rb +60 -0
  22. data/lib/nagoro/pipe/morph.rb +95 -0
  23. data/lib/nagoro/pipe/tidy.rb +49 -0
  24. data/lib/nagoro/scanner.rb +97 -0
  25. data/lib/nagoro/template.rb +89 -0
  26. data/lib/nagoro/tidy.rb +49 -0
  27. data/lib/nagoro/version.rb +3 -0
  28. data/nagoro.gemspec +28 -0
  29. data/spec/core_extensions.rb +33 -0
  30. data/spec/example/hello.rb +13 -0
  31. data/spec/helper.rb +19 -0
  32. data/spec/nagoro/listener/base.rb +19 -0
  33. data/spec/nagoro/pipe/compile.rb +31 -0
  34. data/spec/nagoro/pipe/element.rb +46 -0
  35. data/spec/nagoro/pipe/include.rb +17 -0
  36. data/spec/nagoro/pipe/instruction.rb +32 -0
  37. data/spec/nagoro/pipe/morph.rb +47 -0
  38. data/spec/nagoro/pipe/tidy.rb +23 -0
  39. data/spec/nagoro/template.rb +105 -0
  40. data/spec/nagoro/template/full.nag +26 -0
  41. data/spec/nagoro/template/hello.nag +1 -0
  42. data/tasks/bacon.rake +49 -0
  43. data/tasks/changelog.rake +18 -0
  44. data/tasks/gem.rake +22 -0
  45. data/tasks/gem_installer.rake +76 -0
  46. data/tasks/grancher.rake +12 -0
  47. data/tasks/install_dependencies.rake +6 -0
  48. data/tasks/manifest.rake +4 -0
  49. data/tasks/rcov.rake +19 -0
  50. data/tasks/release.rake +52 -0
  51. data/tasks/reversion.rake +8 -0
  52. metadata +105 -0
@@ -0,0 +1,13 @@
1
+ require 'spec/helper'
2
+
3
+ describe "example/hello.nag" do
4
+ behaves_like 'xpath'
5
+
6
+ Nagoro.file_element('Html', 'example/element/Html.nage')
7
+
8
+ should 'render Hello, World!' do
9
+ file = 'example/hello.nag'
10
+ doc = Nagoro.compile(file, :pipes => [:Element]).compiled
11
+ xpath(doc, '//title').first.text.should == 'Hello, World!'
12
+ end
13
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'lib/nagoro'
2
+ require 'spec/core_extensions'
3
+
4
+ require 'stringio'
5
+ require 'rexml/document'
6
+ require 'rexml/xpath'
7
+ require 'pp'
8
+
9
+ require 'rubygems'
10
+ require 'bacon'
11
+
12
+ Bacon.summary_on_exit
13
+
14
+ shared 'xpath' do
15
+ def xpath(string, path)
16
+ doc = REXML::Document.new(string)
17
+ REXML::XPath.match(doc, path)
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec/helper'
2
+
3
+ describe "Nagoro::Listener::Base" do
4
+ def base(string)
5
+ nagoro = Nagoro::Template[:Base]
6
+ nagoro.pipeline(string)
7
+ end
8
+
9
+ should 'not fail on backslash' do
10
+ base('#{}').should == '#{}'
11
+ end
12
+
13
+ it 'should not stumble over HTML entities' do
14
+ %w[gt lt quot amp nbsp uuml].each do |entity|
15
+ str = "&#{entity};"
16
+ base(str).should == str
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec/helper'
2
+
3
+ describe "Nagoro::Pipe::Compile" do
4
+ def render(obj)
5
+ Nagoro::Template[Nagoro::Pipe::Compile].render(obj)
6
+ end
7
+
8
+ should 'compile normal string' do
9
+ render('Hello, World!').should == 'Hello, World!'
10
+ end
11
+
12
+ should 'compile ruby instructions' do
13
+ render('<?r a = 1 ?><?ro a ?>').should == '1'
14
+ render('<?r a = 1 ?><?ro a > 1 ?>').should == 'false'
15
+ render('<?r a = 1 ?><?ro a < 1 ?>').should == 'false'
16
+ end
17
+
18
+ should 'compile with compatiblity to Ezamar' do
19
+ render('<?r a = 1 ?>#{a}').should == '1'
20
+ render('<?r a = 1 ?>#{a > 1}').should == 'false'
21
+ render('<?r a = 1 ?>#{a < 1}').should == 'false'
22
+ end
23
+
24
+ should 'not fail on nested {} inside #{}' do
25
+ render('#{"Hello, {World}!"}').should == 'Hello, {World}!'
26
+ end
27
+
28
+ should 'not fail on > inside ruby instruction' do
29
+ render('#{{:hi => :there}[:hi]}').should == 'there'
30
+ end
31
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec/helper'
2
+
3
+ describe "Nagoro::Pipe::Element" do
4
+ behaves_like 'xpath'
5
+
6
+ def compile(obj)
7
+ Nagoro::Template[Nagoro::Pipe::Element].compile(obj).compiled
8
+ end
9
+
10
+ Nagoro.element('Page') do |content, attrs|
11
+ "(Page: #{content.dump})"
12
+ end
13
+
14
+ Nagoro.element('SideBar') do |content, attrs|
15
+ "(SideBar: #{content.dump})"
16
+ end
17
+
18
+ Nagoro.file_element('Html', 'example/element/Html.nage')
19
+
20
+ it 'should compile single element' do
21
+ compile('<Page />').
22
+ should == '(Page: "")'
23
+ end
24
+
25
+ it 'should compile two elements' do
26
+ compile('<Page /><Page />').
27
+ should == '(Page: "")(Page: "")'
28
+ end
29
+
30
+ it 'should compile nested elements' do
31
+ compile('<Page><Page /></Page>').
32
+ should == '(Page: "(Page: \\"\\")")'
33
+ end
34
+
35
+ it 'should compile different nested elements' do
36
+ compile('<Page><SideBar /></Page>').
37
+ should == '(Page: "(SideBar: \\"\\")")'
38
+ end
39
+
40
+ it 'should render file-elements' do
41
+ doc = compile(File.read('example/hello.nag'))
42
+ doc.should.not.be.empty
43
+ xpath(doc, '//title').first.text.should == 'Hello, World!'
44
+ xpath(doc, '//h1').first.text.should == 'Hello, World!'
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec/helper'
2
+
3
+ describe "Nagoro::Pipe::Include" do
4
+ def compile(obj)
5
+ Nagoro::Template[Nagoro::Pipe::Include].compile(obj).compiled
6
+ end
7
+
8
+ it 'should append included file with arguments src or href' do
9
+ path = __DIR__/'../template/hello.nag'
10
+
11
+ compile(%{<p id="text"><include src="#{path}" /></p>}).strip.
12
+ should == %{<p id="text">#{File.read(path).strip}</p>}
13
+
14
+ compile(%{<p id="text"><include href="#{path}" /></p>}).strip.
15
+ should == %{<p id="text">#{File.read(path).strip}</p>}
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec/helper'
2
+
3
+ describe "Nagoro::Pipe::Instruction" do
4
+ behaves_like 'xpath'
5
+ def compile(obj)
6
+ Nagoro::Template[Nagoro::Pipe::Instruction].compile(obj).compiled
7
+ end
8
+
9
+ it 'should expand <?js code ?>' do
10
+ compile('<?js alert("Hello, World!"); ?>').
11
+ should == '<script type="text/javascript"> alert("Hello, World!"); </script>'
12
+ end
13
+
14
+ it 'should expand <?js:src path?>' do
15
+ doc = compile('<?js:src /js/foo.js ?>')
16
+ scripts = xpath(doc, 'script[@type="text/javascript" @src="/js/foo.js"]')
17
+ scripts.size.should == 1
18
+ scripts.first.texts.should.be.empty
19
+ end
20
+
21
+ it 'should expand <?css styles ?>' do
22
+ compile('<?css body{ color: #eee; } ?>').
23
+ should == '<style type="text/css"> body{ color: #eee; } </style>'
24
+ end
25
+
26
+ it 'should expand <?css:src path ?>' do
27
+ doc = compile('<?css:src /css/foo.css ?>')
28
+ styles = xpath(doc, 'style[@type="text/css" @src="/css/foo.css"]')
29
+ styles.size.should == 1
30
+ styles.first.texts.should.be.empty
31
+ end
32
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec/helper'
2
+
3
+ describe "Nagoro::Pipe::Morph" do
4
+ def compile(obj)
5
+ Nagoro::Template[Nagoro::Pipe::Morph].compile(obj).compiled
6
+ end
7
+
8
+ it 'should morph single tag' do
9
+ compile('<a href="foo" if="1">bar</a>').
10
+ should == '<?r if 1 ?><a href="foo">bar</a><?r end ?>'
11
+ end
12
+
13
+ it 'should morph multiple tags' do
14
+ compile('<div if="2"><p if="1"></p></div>').
15
+ should == '<?r if 2 ?><div><?r if 1 ?><p></p><?r end ?></div><?r end ?>'
16
+ end
17
+
18
+ it 'should morph if' do
19
+ compile('<p if="1">x</p>').
20
+ should == '<?r if 1 ?><p>x</p><?r end ?>'
21
+ end
22
+
23
+ it 'should morph unless' do
24
+ compile('<p unless="1">x</p>').
25
+ should == '<?r unless 1 ?><p>x</p><?r end ?>'
26
+ end
27
+
28
+ it 'should morph foreach' do
29
+ compile('<p foreach="i in 1..10">#{i}</p>').
30
+ should == '<?r for i in 1..10 ?><p>#{i}</p><?r end ?>'
31
+ end
32
+
33
+ it 'should morph each' do
34
+ compile('<p each="1..10">#{_e}</p>').
35
+ should == '<?r 1..10.each do |_e| ?><p>#{_e}</p><?r end ?>'
36
+ end
37
+
38
+ it 'should morph times' do
39
+ compile('<p times="3">#{_t}</p>').
40
+ should == '<?r 3.times do |_t| ?><p>#{_t}</p><?r end ?>'
41
+ end
42
+
43
+ it 'should morph filter' do
44
+ compile('<p filter="my_filter">x</p>').
45
+ should == '<?o my_filter(%<<p>x</p>>) ?>'
46
+ end
47
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec/helper'
2
+ require 'nagoro/pipe/tidy'
3
+
4
+ describe "Nagoro::Pipe::Tidy" do
5
+ def compile(obj)
6
+ Nagoro::Template[Nagoro::Pipe::Tidy].compile(obj).compiled
7
+ end
8
+
9
+ it 'pipes the template through tidy' do
10
+ compile('<html></html>').strip.should ==
11
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
12
+ \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
13
+
14
+ <html xmlns=\"http://www.w3.org/1999/xhtml\">
15
+ <head>
16
+ <title></title>
17
+ </head>
18
+
19
+ <body>
20
+ </body>
21
+ </html>"
22
+ end
23
+ end
@@ -0,0 +1,105 @@
1
+ require 'spec/helper'
2
+
3
+ describe "Nagoro" do
4
+ should '::compile from filename' do
5
+ file = __DIR__/'template/hello.nag'
6
+ template = Nagoro.compile(file)
7
+ template.compiled.should == "_out_ = []; _out_ << %Q`Hello, World!\n`; _out_.join"
8
+ end
9
+
10
+ should '::compile' do
11
+ string = 'Hello, World!'
12
+ template = Nagoro.compile(string)
13
+ template.compiled.should == '_out_ = []; _out_ << %Q`Hello, World!`; _out_.join'
14
+ end
15
+
16
+ should 'compile <?end ?> to <?r end ?>' do
17
+ string = '<?end ?>'
18
+ template = Nagoro.compile(string)
19
+ template.compiled.should == '_out_ = []; _out_ << %Q``;end; _out_ << %Q``; _out_.join'
20
+ end
21
+
22
+ should '::render from filename' do
23
+ file = __DIR__/'template/hello.nag'
24
+ rendered = Nagoro.render(file)
25
+ rendered.should == File.read(file).strip
26
+ end
27
+
28
+ should '::render' do
29
+ string = 'Hello, World!'
30
+ rendered = Nagoro.render(string)
31
+ rendered.should == string
32
+ end
33
+
34
+ should '::render from IO' do
35
+ io = StringIO.new('Hello, World!')
36
+ rendered = Nagoro.render(io)
37
+ rendered.should == 'Hello, World!'
38
+ end
39
+
40
+ should 'render a full featured template with binding' do
41
+ file = __DIR__/'template/full.nag'
42
+ @title = 'Full template'
43
+
44
+ template = Nagoro.render(file, :binding => binding)
45
+
46
+ template.should =~ %r~<!DOCTYPE html PUBLIC~
47
+ template.should =~ %r~<title>Full template</title>~
48
+ template.should =~ %r~<h1>Full template</h1>~
49
+ end
50
+ end
51
+
52
+ describe "Nagoro::Template" do
53
+ should 'set up with ::[]' do
54
+ template = Nagoro::Template[]
55
+ template.pipes.should == []
56
+ template = Nagoro::Template[*Nagoro::DEFAULT_PIPES]
57
+ template.pipes.size.should == Nagoro::DEFAULT_PIPES.size
58
+ end
59
+
60
+ should 'set up with ::new' do
61
+ template = Nagoro::Template.new(:pipes => [])
62
+ template.pipes.should.be.empty
63
+ template = Nagoro::Template.new(:pipes => Nagoro::DEFAULT_PIPES)
64
+ template.pipes.size.should == Nagoro::DEFAULT_PIPES.size
65
+ end
66
+
67
+ should 'not open/close empty tags' do
68
+ %w[ img hr br link meta ].each do |tag|
69
+ tag = "<#{tag} />"
70
+ Nagoro.render(tag).should == tag
71
+ end
72
+ end
73
+
74
+ should 'render and pass result to tidy via #tidy_result' do
75
+ template = Nagoro::Template.new
76
+ template.compile('<html></html>').tidy_result.should ==
77
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
78
+ \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
79
+
80
+ <html xmlns=\"http://www.w3.org/1999/xhtml\">
81
+ <head>
82
+ <title></title>
83
+ </head>
84
+
85
+ <body>
86
+ </body>
87
+ </html>"
88
+ end
89
+
90
+ def noop(*args) end
91
+
92
+ it "doesn't get stuck when ruby contains double-quotes" do
93
+ tag = %q(<link href='#{ noop("some.thing") }' />)
94
+ Nagoro.render(tag, :binding => binding).should == "<link href='' />"
95
+ end
96
+
97
+ it "ignores comments" do
98
+ comment = '
99
+ <!--[if IE]>
100
+ <link rel="stylesheet" type="text/css" media="screen, projection" href="css/blueprint/ie.css">
101
+ <![endif]-->'.strip
102
+
103
+ Nagoro.render(comment).should == comment
104
+ end
105
+ end
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" ?>
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
3
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4
+ <html xmlns="http://www.w3.org/1999/xhtml">
5
+ <head>
6
+ <title>#{@title}</title>
7
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
8
+ <meta http-equiv="Content-Style-Type" content="text/css" />
9
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
10
+ <meta http-equiv="expires" content="0" />
11
+ <meta name="description" content="Description for search engines" />
12
+ <meta name="generator" content="Nagoro #{Nagoro::VERSION}" />
13
+ <meta name="keywords" content="Nagoro, Your own keywords" />
14
+ <meta name="author" content="Max Mustermann" />
15
+ <style type="text/css">
16
+ body { margin: 2em; }
17
+ #content { margin-left: 2em; }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <h1>#{@title}</h1>
22
+ <div id="content">
23
+ #{@content}
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1 @@
1
+ Hello, World!
data/tasks/bacon.rake ADDED
@@ -0,0 +1,49 @@
1
+ desc 'Run all bacon specs with pretty output'
2
+ task :bacon => :install_dependencies do
3
+ require 'open3'
4
+ require 'scanf'
5
+
6
+ specs = PROJECT_SPECS
7
+
8
+ some_failed = false
9
+ total = specs.size
10
+ len = specs.map{|s| s.size }.sort.last
11
+ tt = ta = tf = te = 0
12
+
13
+ red, yellow, green = "\e[31m%s\e[0m", "\e[33m%s\e[0m", "\e[32m%s\e[0m"
14
+ left_format = "%4d/%d: %-#{len + 11}s"
15
+ spec_format = "%d specifications (%d requirements), %d failures, %d errors"
16
+
17
+ specs.each_with_index do |spec, idx|
18
+ print(left_format % [idx + 1, total, spec])
19
+
20
+ Open3.popen3(RUBY, spec) do |sin, sout, serr|
21
+ out = sout.read
22
+ err = serr.read
23
+
24
+ ran = false
25
+
26
+ out.each_line do |line|
27
+ tests, assertions, failures, errors = all = line.scanf(spec_format)
28
+ next unless all.any?
29
+ ran = true
30
+ tt += tests; ta += assertions; tf += failures; te += errors
31
+
32
+ if tests == 0 || failures + errors > 0
33
+ puts((red % spec_format) % all)
34
+ puts out
35
+ puts err
36
+ else
37
+ puts((green % "%6d passed") % tests)
38
+ end
39
+
40
+ break
41
+ end
42
+
43
+ puts(yellow % " skipped") unless ran
44
+ end
45
+ end
46
+
47
+ puts(spec_format % [tt, ta, tf, te])
48
+ exit 1 if some_failed
49
+ end