isaac-malline 1.1.0
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.
- data/COPYING +674 -0
- data/COPYING.LESSER +165 -0
- data/History.txt +34 -0
- data/Manifest.txt +72 -0
- data/README +24 -0
- data/README.txt +33 -0
- data/Rakefile +74 -0
- data/bin/malline +20 -0
- data/github.rb +6 -0
- data/init.rb +2 -0
- data/lib/malline.rb +109 -0
- data/lib/malline/adapters/rails-2.0.rb +72 -0
- data/lib/malline/adapters/rails-2.1.rb +103 -0
- data/lib/malline/erb_out.rb +34 -0
- data/lib/malline/form_builder.rb +44 -0
- data/lib/malline/plugin.rb +34 -0
- data/lib/malline/plugins/xhtml.rb +77 -0
- data/lib/malline/rails.rb +46 -0
- data/lib/malline/template.rb +185 -0
- data/lib/malline/view_proxy.rb +87 -0
- data/lib/malline/view_wrapper.rb +95 -0
- data/malline.gemspec +34 -0
- data/scripts/html2mn.rb +93 -0
- data/test/examples/_action.mn +4 -0
- data/test/examples/_action.target +1 -0
- data/test/examples/_one.mn +1 -0
- data/test/examples/_one.target +1 -0
- data/test/examples/_partial.mn +2 -0
- data/test/examples/_partial.target +1 -0
- data/test/examples/_three.rhtml +2 -0
- data/test/examples/_two.mn +1 -0
- data/test/examples/_two.target +1 -0
- data/test/examples/capture.mn +13 -0
- data/test/examples/capture.target +1 -0
- data/test/examples/class.mn +6 -0
- data/test/examples/class.target +1 -0
- data/test/examples/escape.mn +4 -0
- data/test/examples/escape.target +1 -0
- data/test/examples/frontpage.mn +6 -0
- data/test/examples/frontpage.target +1 -0
- data/test/examples/hello_world.mn +2 -0
- data/test/examples/hello_world.target +1 -0
- data/test/examples/helper.mn +5 -0
- data/test/examples/helper.target +1 -0
- data/test/examples/helper2.mn +5 -0
- data/test/examples/helper2.target +1 -0
- data/test/examples/helper_shortcut.mn +5 -0
- data/test/examples/helper_shortcut.target +1 -0
- data/test/examples/id.mn +3 -0
- data/test/examples/id.target +1 -0
- data/test/examples/layout.mn +8 -0
- data/test/examples/layout.target +4 -0
- data/test/examples/lists.mn +13 -0
- data/test/examples/lists.target +1 -0
- data/test/examples/nested.mn +6 -0
- data/test/examples/nested.target +1 -0
- data/test/examples/options.mn +10 -0
- data/test/examples/options.target +1 -0
- data/test/examples/partials.mn +5 -0
- data/test/examples/partials.target +1 -0
- data/test/examples/self.mn +2 -0
- data/test/examples/self.target +1 -0
- data/test/examples/text.mn +4 -0
- data/test/examples/text.target +1 -0
- data/test/examples/whitespace.mn +9 -0
- data/test/examples/whitespace.target +1 -0
- data/test/examples/xhtml.mn +11 -0
- data/test/examples/xhtml.target +4 -0
- data/test/kernel.org.html +107 -0
- data/test/kernel.org.mn +657 -0
- data/test/malline_test.rb +171 -0
- data/test/malline_test_helpers.rb +82 -0
- metadata +136 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
# Copyright © 2007,2008 Riku Palomäki
|
2
|
+
#
|
3
|
+
# This file is part of Malline.
|
4
|
+
#
|
5
|
+
# Malline is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# Malline is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
16
|
+
# along with Malline. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module Malline
|
19
|
+
# Every tag returns a ViewProxy object that binds the tag to the template.
|
20
|
+
# ViewProxy also chains the process by returning itself.
|
21
|
+
#
|
22
|
+
# This Proxy object then makes possible the attribute syntax:
|
23
|
+
# div.foo.bar! { stuff }
|
24
|
+
#
|
25
|
+
# div returns new ViewProxy instance, so div.foo actually calls
|
26
|
+
# ViewProxy#foo, which is then generated to class="foo" -attribute to the
|
27
|
+
# original tag div. div.foo returns the same ViewProxy, and foo.bar! calls
|
28
|
+
# ViewProxy#bar!, which is interpreted as a id="bar" -attribute.
|
29
|
+
#
|
30
|
+
# Finally the given block { stuff } is evaluated the same way than it would
|
31
|
+
# be evaluated without the ViewProxy:
|
32
|
+
# div { stuff }
|
33
|
+
class ViewProxy
|
34
|
+
def initialize template, tag
|
35
|
+
@tpl = template
|
36
|
+
@tag = tag
|
37
|
+
end
|
38
|
+
|
39
|
+
# Allows to add new content to already closed tag, for example:
|
40
|
+
# t = div do
|
41
|
+
# _'text'
|
42
|
+
# end
|
43
|
+
# t.__yld :whitespace { stuff }
|
44
|
+
#
|
45
|
+
# Intended for internal use only
|
46
|
+
def __yld *args, &block
|
47
|
+
# div :title => 'data'
|
48
|
+
if args.last.is_a?(Hash)
|
49
|
+
@tag[:attrs].merge!(args.pop)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Modifiers
|
53
|
+
whitespace = @tpl.whitespace
|
54
|
+
@tpl.whitespace = true if args.delete(:whitespace)
|
55
|
+
|
56
|
+
# Rest is just content separated by a space
|
57
|
+
txt = args.flatten.join ' '
|
58
|
+
@tag[:children] << txt unless txt.empty?
|
59
|
+
|
60
|
+
# Block
|
61
|
+
@tpl.execute @tag[:children], &block if block_given?
|
62
|
+
|
63
|
+
# Restore modifiers
|
64
|
+
@tpl.whitespace = whitespace
|
65
|
+
|
66
|
+
# Chain the calls, for example: div.foo.bar!.yeah.boring
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
# Capture attribute definitions, special modifiers and blocks
|
71
|
+
def method_missing s, *args, &block
|
72
|
+
# div.id!
|
73
|
+
if /^(.*)!$/ =~ s.to_s
|
74
|
+
@tag[:attrs]['id'] = $1
|
75
|
+
elsif s
|
76
|
+
# div.class
|
77
|
+
if @tag[:attrs]['class']
|
78
|
+
@tag[:attrs]['class'] << " #{s}"
|
79
|
+
else
|
80
|
+
@tag[:attrs]['class'] = s.to_s
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
__yld *args, &block
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Copyright © 2007,2008 Riku Palomäki
|
2
|
+
#
|
3
|
+
# This file is part of Malline.
|
4
|
+
#
|
5
|
+
# Malline is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# Malline is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public License
|
16
|
+
# along with Malline. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module Malline
|
19
|
+
# ViewWrapper is extended into used view object, like ActiveView::Base.
|
20
|
+
# Every method in ViewWrapper will pollute the original namespace.
|
21
|
+
module ViewWrapper
|
22
|
+
# List of all methods that may override some custom view methods
|
23
|
+
# If is_malline?, then their _malline_ -prefix versions are called
|
24
|
+
@@malline_methods = %w{_erbout capture _ tag! << txt!}
|
25
|
+
|
26
|
+
# Initialize @@malline_methods
|
27
|
+
def init_malline_methods
|
28
|
+
@malline_methods_inited = true
|
29
|
+
@@malline_methods.each do |m|
|
30
|
+
mf = m.gsub('<', 'lt')
|
31
|
+
eval %{def #{m}(*x, &b) is_malline? ? _malline_#{mf}(*x, &b) : super; end}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a current Template instance, makes a new if called first time
|
36
|
+
# Can also be used to set options to Template by giving them as hash opts:
|
37
|
+
# malline :whitespace => true
|
38
|
+
def malline opts = nil
|
39
|
+
if @malline
|
40
|
+
@malline.options.merge!(opts) if opts.is_a?(Hash)
|
41
|
+
else
|
42
|
+
@malline = Template.new(self, opts || {})
|
43
|
+
end
|
44
|
+
init_malline_methods unless @malline_methods_inited
|
45
|
+
@malline
|
46
|
+
end
|
47
|
+
|
48
|
+
# erbout emulator
|
49
|
+
def _malline__erbout
|
50
|
+
@_erbout ||= ErbOut.new(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
# capture and return the output of the block
|
54
|
+
def _malline_capture &block
|
55
|
+
@malline.run &block
|
56
|
+
end
|
57
|
+
|
58
|
+
# _'escaped text'
|
59
|
+
def _malline__ *args
|
60
|
+
@malline.add_text(*args)
|
61
|
+
end
|
62
|
+
alias_method :_malline_txt!, :_malline__
|
63
|
+
|
64
|
+
# self << "<unescaped text>"
|
65
|
+
def _malline_ltlt *args
|
66
|
+
@malline.add_unescaped_text *args
|
67
|
+
end
|
68
|
+
|
69
|
+
# Define a new tag of call a helper (if _prefixed)
|
70
|
+
def method_missing s, *args, &block
|
71
|
+
return super unless is_malline?
|
72
|
+
if @malline.tags[s]
|
73
|
+
@malline.tag s, *args, &block
|
74
|
+
else
|
75
|
+
helper = ((s.to_s[0] == ?_) ? s.to_s[1..-1] : s).to_sym
|
76
|
+
if respond_to?(helper)
|
77
|
+
@malline.helper(helper, *args, &block)
|
78
|
+
else
|
79
|
+
return super if @malline.options[:strict]
|
80
|
+
_malline_tag! s, *args, &block
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Define a new tag
|
86
|
+
def _malline_tag! *args, &block
|
87
|
+
@malline.tag *args, &block
|
88
|
+
end
|
89
|
+
|
90
|
+
# Are we in a Malline template
|
91
|
+
def is_malline?
|
92
|
+
true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/malline.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{malline}
|
3
|
+
s.version = "1.1.0"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["Riku Palom\303\244ki"]
|
7
|
+
s.date = %q{2008-09-06}
|
8
|
+
s.default_executable = %q{malline}
|
9
|
+
s.description = %q{Malline is a full-featured template system designed to be a replacement for ERB views in Rails or any other framework. It also includes standalone bin/malline to compile Malline templates to XML in commandline. All Malline templates are pure Ruby, see http://www.malline.org/ for more info. See documentation on http://www.malline.org/ Copyright © 2007,2008 Riku Palomäki, riku@palomaki.fi Malline is released under GNU Lesser General Public License. Example Rails template file images.html.mn: xhtml do _render :partial => 'head' body do div.images! "There are some images:" do images.each do |im| a(:href => img_path(im)) { img :src => im.url } span.caption im.caption end _"No more images" end div.footer! { _render :partial => 'footer' } end end}
|
10
|
+
s.email = ["riku@palomaki.fi"]
|
11
|
+
s.executables = ["malline"]
|
12
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
13
|
+
s.files = ["COPYING", "COPYING.LESSER", "History.txt", "Manifest.txt", "README", "README.txt", "Rakefile", "bin/malline", "github.rb", "init.rb", "lib/malline.rb", "lib/malline/adapters/rails-2.0.rb", "lib/malline/adapters/rails-2.1.rb", "lib/malline/erb_out.rb", "lib/malline/form_builder.rb", "lib/malline/plugin.rb", "lib/malline/plugins/xhtml.rb", "lib/malline/rails.rb", "lib/malline/template.rb", "lib/malline/view_proxy.rb", "lib/malline/view_wrapper.rb", "malline.gemspec", "scripts/html2mn.rb", "test/examples/_action.mn", "test/examples/_action.target", "test/examples/_one.mn", "test/examples/_one.target", "test/examples/_partial.mn", "test/examples/_partial.target", "test/examples/_three.rhtml", "test/examples/_two.mn", "test/examples/_two.target", "test/examples/capture.mn", "test/examples/capture.target", "test/examples/class.mn", "test/examples/class.target", "test/examples/escape.mn", "test/examples/escape.target", "test/examples/frontpage.mn", "test/examples/frontpage.target", "test/examples/hello_world.mn", "test/examples/hello_world.target", "test/examples/helper.mn", "test/examples/helper.target", "test/examples/helper2.mn", "test/examples/helper2.target", "test/examples/helper_shortcut.mn", "test/examples/helper_shortcut.target", "test/examples/id.mn", "test/examples/id.target", "test/examples/layout.mn", "test/examples/layout.target", "test/examples/lists.mn", "test/examples/lists.target", "test/examples/nested.mn", "test/examples/nested.target", "test/examples/options.mn", "test/examples/options.target", "test/examples/partials.mn", "test/examples/partials.target", "test/examples/self.mn", "test/examples/self.target", "test/examples/text.mn", "test/examples/text.target", "test/examples/whitespace.mn", "test/examples/whitespace.target", "test/examples/xhtml.mn", "test/examples/xhtml.target", "test/kernel.org.html", "test/kernel.org.mn", "test/malline_test.rb", "test/malline_test_helpers.rb"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://www.malline.org/}
|
16
|
+
s.rdoc_options = ["--main", "README.txt"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{malline}
|
19
|
+
s.rubygems_version = %q{1.2.0}
|
20
|
+
s.summary = %q{Malline is a full-featured template system designed to be a replacement for ERB views in Rails or any other framework}
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 2
|
25
|
+
|
26
|
+
if current_version >= 3 then
|
27
|
+
s.add_runtime_dependency(%q<hoe>, [">= 1.5.3"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<hoe>, [">= 1.5.3"])
|
30
|
+
end
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<hoe>, [">= 1.5.3"])
|
33
|
+
end
|
34
|
+
end
|
data/scripts/html2mn.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright © 2007,2008 Riku Palomäki
|
3
|
+
#
|
4
|
+
# This file is part of Malline.
|
5
|
+
#
|
6
|
+
# Malline is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Malline is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with Malline. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require "rexml/document"
|
20
|
+
include REXML
|
21
|
+
|
22
|
+
def html_unescape str
|
23
|
+
str.to_s.gsub('&', '&').gsub('"', '"').gsub('>', '>').gsub('<', '<')
|
24
|
+
end
|
25
|
+
|
26
|
+
def esc str
|
27
|
+
if str =~ /["#]/ || !(str =~ /'/)
|
28
|
+
"'"+(str.split("'").join("\\'"))+"'"
|
29
|
+
else
|
30
|
+
"\"#{str}\""
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def attributes element
|
35
|
+
element.attributes.keys.collect {|k| "#{esc k} => #{esc html_unescape(element.attributes[k])}" }.join(', ')
|
36
|
+
end
|
37
|
+
|
38
|
+
def txtize txt
|
39
|
+
#txt.gsub(/(\s)\s*$/, '\1').gsub(/^(\s)\s*/, '\1')
|
40
|
+
txt.gsub(/\s*$/, '').gsub(/^\s*/, '')
|
41
|
+
end
|
42
|
+
|
43
|
+
def convert element, prefix=''
|
44
|
+
valid_method = /^[A-Za-z][\w_]*$/
|
45
|
+
output = ''
|
46
|
+
if element.is_a?(Array)
|
47
|
+
element.each {|e| output << convert(e) }
|
48
|
+
elsif element.is_a?(Element)
|
49
|
+
output << prefix << element.name
|
50
|
+
attrs = []
|
51
|
+
element.attributes['class'].to_s.split.uniq.each do |cl|
|
52
|
+
if valid_method =~ cl
|
53
|
+
output << ".#{cl}"
|
54
|
+
else
|
55
|
+
attrs << cl
|
56
|
+
end
|
57
|
+
end
|
58
|
+
element.attributes.delete('class')
|
59
|
+
element.attributes['class'] = attrs.join(' ') unless attrs.empty?
|
60
|
+
if element.attributes['id'].to_s =~ valid_method
|
61
|
+
output << ".#{element.attributes['id']}!"
|
62
|
+
element.attributes.delete('id')
|
63
|
+
end
|
64
|
+
txt = ''
|
65
|
+
children = element.children
|
66
|
+
unless children.empty?
|
67
|
+
if children.first.is_a?(Text)
|
68
|
+
txt = txtize children.shift.to_s
|
69
|
+
output << " #{esc html_unescape(txt)}" unless txt.empty?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
output << (txt.empty? ? ' ' : ', ') << attributes(element) if element.has_attributes?
|
74
|
+
unless children.empty?
|
75
|
+
output << " do\n"
|
76
|
+
children.each {|e| output << convert(e, prefix + "\t") }
|
77
|
+
output << prefix << "end"
|
78
|
+
end
|
79
|
+
output << "\n"
|
80
|
+
elsif element.is_a?(Text)
|
81
|
+
txt = txtize(element.to_s)
|
82
|
+
output << prefix << "txt! #{esc html_unescape(txt)}\n" unless txt.empty?
|
83
|
+
end
|
84
|
+
output
|
85
|
+
end
|
86
|
+
|
87
|
+
input = File.open(ARGV.shift, 'r') rescue $stdin
|
88
|
+
output = File.open(ARGV.shift, 'w') rescue $stdout
|
89
|
+
|
90
|
+
doc = Document.new input
|
91
|
+
|
92
|
+
|
93
|
+
output.puts convert(doc.children)
|
@@ -0,0 +1 @@
|
|
1
|
+
<ul id="data"><li>Data 0</li><li>Data 1</li><li>Data 2</li></ul>
|
@@ -0,0 +1 @@
|
|
1
|
+
span.one 'This is the first'
|
@@ -0,0 +1 @@
|
|
1
|
+
<span class="one">This is the first</span>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div>I always thought something was fundamentally wrong with the universe.</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
img :src => image_path('second')
|
@@ -0,0 +1 @@
|
|
1
|
+
<img src="/images/img"/>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div><h4>Captured</h4><div><img src="/images/image.png"/><br/><span class="caption">Taken at the location of the event</span></div>EOF</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div class="page"></div><div class="page"></div><div class="foo bar many"></div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<p title="2 < 5">Do you know, that 2 < 5?</p><p>Me & Myself & Malline</p>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div class="page"><h1>Header one</h1><ul id="list"><li><a href="/foo">Link to somewhere</a></li></ul></div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div title="Hello">Hello world</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div>frperg fghss</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div>secret stuff</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<p>linklink</p>
|
data/test/examples/id.mn
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
<div id="page"></div><div class="foo bar" id="page"></div>
|