nagoro 2009.05

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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