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,72 @@
|
|
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
|
+
ActionView::Base.register_template_handler 'rb', Malline::Base
|
19
|
+
module ActionView
|
20
|
+
# We need to redefine some ActionView::Base methods, Since Rails 2.0 doesn't
|
21
|
+
# offer any better way to do some things.
|
22
|
+
class Base
|
23
|
+
alias_method :orig_render_template, :render_template
|
24
|
+
# We want to save the name of the current file to @current_tpl_path,
|
25
|
+
# because then the error backtrace from Rails will include the
|
26
|
+
# name of the file. I didn't find better way to get this
|
27
|
+
def render_template template_extension, template, file_path = nil, *rest
|
28
|
+
@current_tpl_path = file_path
|
29
|
+
orig_render_template(template_extension, template, file_path, *rest)
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :orig_compile_and_render_template, :compile_and_render_template
|
33
|
+
def compile_and_render_template handler, *rest
|
34
|
+
if self.respond_to? :is_malline?
|
35
|
+
old, @malline_is_active = is_malline?, false
|
36
|
+
output = orig_compile_and_render_template handler, *rest
|
37
|
+
@malline_is_active = old
|
38
|
+
output
|
39
|
+
else
|
40
|
+
@malline_is_active = false
|
41
|
+
orig_compile_and_render_template handler, *rest
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :orig_delegate_render, :delegate_render
|
46
|
+
# Update the current file to malline and tell Malline to be deactivated
|
47
|
+
# if there is a non-Malline partial inside Malline template.
|
48
|
+
def delegate_render(handler, template, local_assigns)
|
49
|
+
old = is_malline?
|
50
|
+
tmp = if handler == Malline::Base
|
51
|
+
h = handler.new(self)
|
52
|
+
h.path = @current_tpl_path if @current_tpl_path
|
53
|
+
@malline_is_active = true
|
54
|
+
h.render(template, local_assigns)
|
55
|
+
else
|
56
|
+
@malline_is_active = false
|
57
|
+
orig_delegate_render(handler, template, local_assigns)
|
58
|
+
end
|
59
|
+
@malline_is_active = old
|
60
|
+
tmp
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module Malline::ViewWrapper
|
66
|
+
# Activate Malline if we are not using ActionView::Base or if
|
67
|
+
# the current template is a Malline template
|
68
|
+
def is_malline?
|
69
|
+
@malline_is_active.nil? ? true : @malline_is_active
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,103 @@
|
|
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
|
+
# Malline template handler for Rails 2.1
|
20
|
+
#
|
21
|
+
# We use Compilable-interface, even though Malline templates really doesn't
|
22
|
+
# compile into anything, but at least template files won't always be re-read
|
23
|
+
# from files. Builder templates (.builder|.rxml) also use this interface.
|
24
|
+
class RailsHandler < ActionView::TemplateHandler
|
25
|
+
include ActionView::TemplateHandlers::Compilable
|
26
|
+
|
27
|
+
# We have three lines framework code before real template code in
|
28
|
+
# 'compiled code'
|
29
|
+
def self.line_offset
|
30
|
+
3
|
31
|
+
end
|
32
|
+
|
33
|
+
# Compiles the template, i.e. return a runnable ruby code that initializes
|
34
|
+
# a new Malline::Base objects and renders the template.
|
35
|
+
def compile template
|
36
|
+
path = template.path.gsub('\\', '\\\\\\').gsub("'", "\\\\'")
|
37
|
+
"__malline_handler = Malline::Base.new self
|
38
|
+
malline.path = '#{path}'
|
39
|
+
__malline_handler.render do
|
40
|
+
#{template.source}
|
41
|
+
end"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get the rendered fragment contents
|
45
|
+
def cache_fragment block, name = {}, options = nil
|
46
|
+
@view.fragment_for(block, name, options) do
|
47
|
+
eval("__malline_handler.rendered", block.binding)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module Malline::ViewWrapper
|
54
|
+
# Activate Malline if we are not using ActionView::Base or if
|
55
|
+
# the current template is a Malline template
|
56
|
+
def is_malline?
|
57
|
+
!(is_a?(ActionView::Base) && ActionView::Template.handler_class_for_extension(
|
58
|
+
current_render_extension) != Malline::RailsHandler)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Rails has a bug with current_render_extension, lets fix it
|
63
|
+
if ActionView.const_defined?('Renderer')
|
64
|
+
module ActionView::Renderer
|
65
|
+
alias_method :orig_render, :render
|
66
|
+
def render *args
|
67
|
+
out = orig_render *args
|
68
|
+
@view.current_render_extension = @prev_extension
|
69
|
+
out
|
70
|
+
end
|
71
|
+
|
72
|
+
alias_method :orig_prepare!, :prepare!
|
73
|
+
def prepare! *args
|
74
|
+
@prev_extension = @view.current_render_extension
|
75
|
+
orig_prepare! *args
|
76
|
+
end
|
77
|
+
end
|
78
|
+
else
|
79
|
+
class ActionView::Template
|
80
|
+
alias_method :orig_render, :render
|
81
|
+
def render *args
|
82
|
+
out = orig_render *args
|
83
|
+
@view.current_render_extension = @prev_extension
|
84
|
+
out
|
85
|
+
end
|
86
|
+
|
87
|
+
alias_method :orig_prepare!, :prepare!
|
88
|
+
def prepare! *args
|
89
|
+
@prev_extension = @view.current_render_extension
|
90
|
+
orig_prepare! *args
|
91
|
+
end
|
92
|
+
end
|
93
|
+
class ActionView::PartialTemplate
|
94
|
+
alias_method :orig_render, :render
|
95
|
+
def render *args
|
96
|
+
out = orig_render *args
|
97
|
+
@view.current_render_extension = @prev_extension
|
98
|
+
out
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
ActionView::Template.register_template_handler 'rb', Malline::RailsHandler
|
@@ -0,0 +1,34 @@
|
|
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
|
+
# Since some parts of Rails use ERB directly instead of current template
|
20
|
+
# handler, we have to capture all that data.
|
21
|
+
#
|
22
|
+
# In practice the erb buffer object (named ActiveView::Base.erb_variable)
|
23
|
+
# is a string, where data is simply concatted.
|
24
|
+
class ErbOut
|
25
|
+
def initialize view
|
26
|
+
@view = view
|
27
|
+
end
|
28
|
+
# Redirect all data to view
|
29
|
+
def concat value
|
30
|
+
@view << value
|
31
|
+
end
|
32
|
+
alias_method :<<, :concat
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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
|
+
# Capture form elements directly from FormBuilder, so that there is no
|
20
|
+
# need to specially render any elements.
|
21
|
+
# In other words, with our own FormBuilder-wrapper we can do this:
|
22
|
+
# form_for :comment, Comment.new, :url => edit_url do |f|
|
23
|
+
# f.text_field :name
|
24
|
+
# end
|
25
|
+
# instead of
|
26
|
+
# ..
|
27
|
+
# self << f.text_field(:name)
|
28
|
+
class FormBuilder
|
29
|
+
# Wrap the Rails FormBuilder in @builder
|
30
|
+
def initialize *args, &block
|
31
|
+
@view = eval('self', args.last)
|
32
|
+
@builder = ::ActionView::Helpers::FormBuilder.new(*args, &block)
|
33
|
+
end
|
34
|
+
# Render every f.foo -method to view, unless we aren't using
|
35
|
+
# Malline template now
|
36
|
+
def method_missing *args, &block
|
37
|
+
if @view && @view.is_malline?
|
38
|
+
@view << @builder.send(*args, &block)
|
39
|
+
else
|
40
|
+
@builder.send(*args, &block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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
|
+
# Malline very incomplete Plugin interface.
|
19
|
+
class Malline::Plugin
|
20
|
+
# Install a new plugin: Malline::WhatEverPlugin.install view
|
21
|
+
def self.install view
|
22
|
+
return if view.malline.plugins.include? self
|
23
|
+
self.do_install view
|
24
|
+
view.malline.plugins << self
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
def self.do_install view
|
29
|
+
raise NotImplementedError.new
|
30
|
+
end
|
31
|
+
def self.do_uninstall view
|
32
|
+
raise NotImplementedError.new("#{self} cannot be uninstalled")
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,77 @@
|
|
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
|
+
# Quite stupid plugin for XHTML, we should be able to do this only with a DTD
|
19
|
+
# or similar.
|
20
|
+
#
|
21
|
+
# Defines all usable tags, list which one can be self-close, defines a short
|
22
|
+
# cut tag *xhtml*. Also makes sure that there is some necessary elements in
|
23
|
+
# the document.
|
24
|
+
class Malline::XHTML < Malline::Plugin
|
25
|
+
CUSTOM_TAGS = %w{head title meta}
|
26
|
+
|
27
|
+
# grep ELEMENT xhtml1-transitional.dtd | cut -d' ' -f2 | tr "\n" " "
|
28
|
+
XHTML_TAGS = %w{html head title base meta link style script noscript iframe
|
29
|
+
noframes body div p h1 h2 h3 h4 h5 h6 ul ol menu dir li dl dt dd address
|
30
|
+
hr pre blockquote center ins del a span bdo br em strong dfn code samp
|
31
|
+
kbd var cite abbr acronym q sub sup tt i b big small u s strike basefont
|
32
|
+
font object param applet img map area form label input select optgroup
|
33
|
+
option textarea fieldset legend button isindex table caption thead tfoot
|
34
|
+
tbody colgroup col tr th td} - CUSTOM_TAGS
|
35
|
+
|
36
|
+
# grep 'ELEMENT.*EMPTY' xhtml1-transitional.dtd | cut -d' ' -f2 | tr "\n" " "
|
37
|
+
SHORT_TAG_EXCLUDES = XHTML_TAGS + CUSTOM_TAGS - %w{base meta link hr br
|
38
|
+
basefont param img area input isindex col}
|
39
|
+
|
40
|
+
module Tags
|
41
|
+
def xhtml *args, &block
|
42
|
+
attrs = { :xmlns => 'http://www.w3.org/1999/xhtml', 'xml:lang' => malline.options[:lang] }
|
43
|
+
attrs.merge!(args.pop) if args.last.is_a?(Hash)
|
44
|
+
|
45
|
+
self << "<?xml version=\"1.0\" encoding=\"#{malline.options[:encoding] || 'UTF-8'}\"?>\n"
|
46
|
+
self << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 #{malline.options[:xhtml_dtd] || 'Transitional'}//EN\"\n"
|
47
|
+
self << " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-#{(malline.options[:xhtml_dtd] || 'Transitional').downcase}.dtd\">\n"
|
48
|
+
|
49
|
+
tag! 'html', args.join(''), attrs, &block
|
50
|
+
end
|
51
|
+
|
52
|
+
def title *args, &block
|
53
|
+
@__xhtml_title = true
|
54
|
+
tag! 'title', *args, &block
|
55
|
+
end
|
56
|
+
|
57
|
+
def meta *args, &block
|
58
|
+
@__xhtml_meta = true
|
59
|
+
tag! 'meta', *args, &block
|
60
|
+
end
|
61
|
+
|
62
|
+
def head *args, &block
|
63
|
+
@__xhtml_title = false
|
64
|
+
proxy = tag! 'head', *args, &block
|
65
|
+
proxy.__yld { title } unless @__xhtml_title
|
66
|
+
proxy.__yld do
|
67
|
+
meta :content => "text/html; charset=#{malline.options[:encoding] || 'UTF-8'}", 'http-equiv' => 'Content-Type'
|
68
|
+
end unless @__xhtml_meta
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.do_install view
|
73
|
+
view.malline.definetags! XHTML_TAGS
|
74
|
+
view.malline.short_tag_excludes += SHORT_TAG_EXCLUDES
|
75
|
+
view.extend Tags
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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
|
+
require 'malline' unless Kernel.const_defined?('Malline')
|
19
|
+
require 'malline/form_builder.rb'
|
20
|
+
|
21
|
+
if Rails::VERSION::STRING <= "2.0.z"
|
22
|
+
require 'malline/adapters/rails-2.0'
|
23
|
+
else
|
24
|
+
require 'malline/adapters/rails-2.1'
|
25
|
+
end
|
26
|
+
|
27
|
+
# Activate our FormBuilder wrapper, so we can use forms more easily
|
28
|
+
ActionView::Base.default_form_builder = Malline::FormBuilder
|
29
|
+
|
30
|
+
module Malline::ViewWrapper
|
31
|
+
@@malline_methods << 'cache'
|
32
|
+
|
33
|
+
# Rails caching
|
34
|
+
def _malline_cache name = {}, options = {}, &block
|
35
|
+
return block.call unless @controller.perform_caching
|
36
|
+
cache = @controller.read_fragment(name, options)
|
37
|
+
|
38
|
+
unless cache
|
39
|
+
cache = _malline_capture { block.call }
|
40
|
+
@controller.write_fragment(name, cache, options)
|
41
|
+
end
|
42
|
+
@malline.add_unescaped_text cache
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
@@ -0,0 +1,185 @@
|
|
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
|
+
# This is the class that really evaluates the template and is accessible
|
20
|
+
# from the view by "malline", for example:
|
21
|
+
# malline.path = 'File name'
|
22
|
+
class Template
|
23
|
+
# Current options (like @@options in Base)
|
24
|
+
attr_accessor :options
|
25
|
+
# List of every tag that doesn't support self-closing syntax
|
26
|
+
attr_accessor :short_tag_excludes
|
27
|
+
# Current state of :whitespace-modifier (bool)
|
28
|
+
attr_accessor :whitespace
|
29
|
+
# Current file name
|
30
|
+
attr_accessor :path
|
31
|
+
# Every overriden (in definetags!) helper method (:name => method)
|
32
|
+
attr_accessor :helper_overrides
|
33
|
+
# Every available tag, excluding the specific methods (:name => bool)
|
34
|
+
attr_accessor :tags
|
35
|
+
# Render result of the last #render
|
36
|
+
attr_reader :rendered
|
37
|
+
# List all installed plugins
|
38
|
+
attr_accessor :plugins
|
39
|
+
|
40
|
+
def initialize view, opts
|
41
|
+
@view = view
|
42
|
+
@whitespace = false
|
43
|
+
@path = 'Malline template'
|
44
|
+
@options = opts
|
45
|
+
@short_tag_excludes = []
|
46
|
+
@helper_overrides = {}
|
47
|
+
@tags = {}
|
48
|
+
@plugins = []
|
49
|
+
@inited = false
|
50
|
+
end
|
51
|
+
|
52
|
+
# Install plugins and do every thing that cannot be done in initialize
|
53
|
+
# Plugin install will use @view.malline, that will create a duplicate
|
54
|
+
# Template instance, if it's called from initialize.
|
55
|
+
def init
|
56
|
+
return if @inited
|
57
|
+
XHTML.install @view if @options[:xhtml]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Stolen from ERB, © 1999-2000,2002,2003 Masatoshi SEKI
|
61
|
+
def self.html_escape(s)
|
62
|
+
s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<")
|
63
|
+
end
|
64
|
+
# Stolen from ERB, © 1999-2000,2002,2003 Masatoshi SEKI
|
65
|
+
def self.url_encode(s)
|
66
|
+
s.to_s.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
|
67
|
+
end
|
68
|
+
|
69
|
+
# Changes dom to active @dom, and executes tpl / block
|
70
|
+
def execute dom, tpl = nil, &block
|
71
|
+
tmp = @dom
|
72
|
+
@dom = dom
|
73
|
+
if block_given?
|
74
|
+
@view.instance_eval &block
|
75
|
+
else
|
76
|
+
@view.instance_eval tpl, @path
|
77
|
+
end
|
78
|
+
@dom = tmp
|
79
|
+
end
|
80
|
+
|
81
|
+
# Add escaped string to @dom
|
82
|
+
def add_text *values
|
83
|
+
@dom << ' ' if @whitespace
|
84
|
+
@dom << Template.html_escape(values.join(' '))
|
85
|
+
end
|
86
|
+
|
87
|
+
# Add unescaped string to @dom
|
88
|
+
def add_unescaped_text value
|
89
|
+
@dom << ' ' if @whitespace
|
90
|
+
@dom << value.to_s unless value.nil?
|
91
|
+
end
|
92
|
+
|
93
|
+
# Call a helper (a method defined outside malline whose
|
94
|
+
# output is stored to @dom)
|
95
|
+
def helper helper, *args, &block
|
96
|
+
helper = helper.to_sym
|
97
|
+
tmp = if h = @helper_overrides[helper]
|
98
|
+
h.call *args, &block
|
99
|
+
else
|
100
|
+
@view.send helper, *args, &block
|
101
|
+
end
|
102
|
+
@dom << ' ' if @whitespace
|
103
|
+
@dom << tmp.to_s
|
104
|
+
tmp
|
105
|
+
end
|
106
|
+
|
107
|
+
# Add a tag to @dom
|
108
|
+
def tag s, *args, &block
|
109
|
+
tag = { :name => s.to_s, :attrs => {}, :children => [] }
|
110
|
+
|
111
|
+
tag[:whitespace] = true if @whitespace
|
112
|
+
whitespace = @whitespace
|
113
|
+
@whitespace = true if args.delete(:whitespace)
|
114
|
+
|
115
|
+
if args.last.is_a?(Hash)
|
116
|
+
tag[:attrs].merge!(args.pop)
|
117
|
+
end
|
118
|
+
|
119
|
+
txt = args.flatten.join('')
|
120
|
+
tag[:children] << Template.html_escape(txt) unless txt.empty?
|
121
|
+
|
122
|
+
@dom << tag
|
123
|
+
execute tag[:children], &block if block_given?
|
124
|
+
@whitespace = whitespace
|
125
|
+
|
126
|
+
ViewProxy.new self, tag
|
127
|
+
end
|
128
|
+
|
129
|
+
# Render the XML tree at dom or @dom
|
130
|
+
def render dom = nil
|
131
|
+
@rendered = (dom || @dom).inject('') do |out, tag|
|
132
|
+
if tag.is_a?(String)
|
133
|
+
out << tag
|
134
|
+
else
|
135
|
+
out << ' ' if tag[:whitespace]
|
136
|
+
out << "<#{tag[:name]}"
|
137
|
+
out << tag[:attrs].inject(''){|s, a| s + " #{a.first}=\"#{Template.html_escape(a.last)}\""}
|
138
|
+
|
139
|
+
if tag[:children].empty?
|
140
|
+
if @short_tag_excludes.include?(tag[:name])
|
141
|
+
out << "></#{tag[:name]}>"
|
142
|
+
else
|
143
|
+
out << '/>'
|
144
|
+
end
|
145
|
+
else
|
146
|
+
out << '>'
|
147
|
+
out << render(tag[:children])
|
148
|
+
out << "</#{tag[:name]}>"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Execute and render a text or block
|
155
|
+
def run tpl = nil, &block
|
156
|
+
init
|
157
|
+
tmp = []
|
158
|
+
execute tmp, tpl, &block
|
159
|
+
render tmp
|
160
|
+
end
|
161
|
+
|
162
|
+
# Define tags as a methods, overriding all same named methods
|
163
|
+
def definetags! *tags
|
164
|
+
tags.flatten.each do |tag|
|
165
|
+
tag = tag.to_sym
|
166
|
+
@helper_overrides[tag] = @view.method(tag) if @view.respond_to?(tag)
|
167
|
+
define_tag! tag
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Marking tags as usable, but not overriding anything
|
172
|
+
def definetags *tags
|
173
|
+
tags.flatten.each{|tag| @tags[tag] = true }
|
174
|
+
end
|
175
|
+
|
176
|
+
# Define a method tag
|
177
|
+
def define_tag! tag
|
178
|
+
eval %{
|
179
|
+
def @view.#{tag}(*args, &block)
|
180
|
+
tag!('#{tag}', *args, &block)
|
181
|
+
end
|
182
|
+
}
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|