pax_global_header00006660000000000000000000000064113012540240014502gustar00rootroot0000000000000052 comment=62bc0c33cabd5b72f36c93ed8f3ff55700f1be5d amrita2-2.0.2+dfsg.1/000077500000000000000000000000001130125402400141205ustar00rootroot00000000000000amrita2-2.0.2+dfsg.1/README000066400000000000000000000055241130125402400150060ustar00rootroot00000000000000= Amrita2 - a xml/xhtml template library for Ruby == Summary Amrita2 is a a xml/xhtml template library for Ruby. It makes html documents from a template and a model data. === Key feature specify "XML template" do t = Amrita2::Template.new <<-END </head> <body> <h1 am:src="header_title" /> <p class="text" am:src="text"> <span am:src="template" /> is a html template library for <span am:src="lang" /> </p> </body> </html> END data = { :page_title=>'Amrita2', :header_title=>'Hello, Amrita2', :text=>{ :template => 'Amrita2', :lang => 'Ruby' } } expected = <<-END <html> <head> <title>Amrita2

Hello, Amrita2

Amrita2 is a html template library for Ruby

END # t.render_with(data).should_be_samexml_as(expected) t2 = Amrita2::Template.new <<-END <> <> <

> is a html template library for <<:lang>> END # t2.render_with(data).should_be_samexml_as(expected) end * The template for amrita2 is a pure html/xhtml document without no special tag like or <% .. %> * The template can be written by designers using almost any xhtml/xml Editor. * Need no change on Ruby code to change the view of _dynamic_ part (not only static part) of the template * The model data may be standard Ruby data, Hash, Array, String... or an instance of a classes you made. * The output is controlled by _data_ not by logic. So It's easy to write, test, debug code. (Good for eXtreamPrograming) Amrita2 mixes a template and model data up to a html document naturally matching the +id+ attribute of XML element to model data. === Current version and roadmap Current version is 2.0.2 . === Setup # gem install amrita2 == document Start spec/intro.rb or Amrita2 Wiki (http://retro.brain-tokyo.net/projects/amrita2/wiki/Amrita2) == support/developement * http://retro.brain-tokyo.net/projects/amrita2/blog == Download * http://rubyforge.org/projects/amrita2 == License Amrita2 is Copyright (c) 2008 Taku Nakajima . It is free software, and may be redistributed under the terms specified in the README file of the Ruby distribution. Sample source code under sample/depot is Amrita2 version of Depot Application of "Agile Web Development with Rails". http://www.pragprog.com/titles/rails2/source_code Sample source code under sample/login_engine is Amrita2 version of LoginEngine. http://rails-engines.org/news/2007/01/23/farewell-login_engine-/ amrita2-2.0.2+dfsg.1/Rakefile000066400000000000000000000034671130125402400155770ustar00rootroot00000000000000require 'rubygems' require 'rake' require 'rake/testtask' require 'rake/rdoctask' require 'spec/rake/spectask' require 'lib/amrita2/version' Gem.manage_gems TMP='/tmp' PACKAGE_NAME = "amrita2" PACKAGE_VERSION = Amrita2::Version::STRING package_name = "#{PACKAGE_NAME}-#{PACKAGE_VERSION}" package_dir = "pkg" package_dir_path = "#{package_dir}/#{package_name}" tar_file = "#{package_name}.tar.gz" gem_file = "#{package_name}.gem" ENV['RUBYLIB'] = "lib" task :default => [ :specs, :test_login_engine, :spec1 ] task :test => [ :specs ] desc "Run all specs" Spec::Rake::SpecTask.new('specs') do |t| t.spec_files = FileList['specs/**/*.rb'] t.spec_opts = %w(-Du) end desc "Run all specs one by one" task :spec1 do tmp = "/tmp/amrita_spec.out" Dir['specs/**/*.rb'].each do |f| begin sh %{spec #{f} > #{tmp} } sh %{spec -r amrita2/gettext #{f} > #{tmp} } rescue puts File::open(tmp).read raise end end end task :clean do Dir['**/*~'].each do |f| puts f FileUtils::rm_f f end Dir['docs'].each do |f| puts f FileUtils::rm_rf f end end task :test_login_engine do Dir::chdir("sample/login_engine") do Dir::mkdir "log" unless FileTest::directory?("log") sh %{rake test} end end desc "Generate documentation for the application" Rake::RDocTask.new("appdoc") { |rdoc| rdoc.rdoc_dir = 'docs/app' rdoc.title = "Amrita2 Documentation" rdoc.rdoc_files = Dir['lib/amrita2/*.rb'] rdoc.rdoc_files << 'README' } task :tar do Dir::chdir(TMP) do system 'rm -rf amrita2' system "svn export http://svn.brain-tokyo.net/amrita2/trunk/amrita2 #{package_name}" system "tar zcvf #{tar_file} #{package_name}" end end task :gem => :clean do spec = eval(File.read("amrita2.gemspec")) Gem::Builder.new(spec).build mv gem_file, "#{TMP}/#{gem_file}" end amrita2-2.0.2+dfsg.1/amrita2.gemspec000066400000000000000000000012261130125402400170250ustar00rootroot00000000000000require 'lib/amrita2/version' Gem::Specification.new do |s| s.name = 'amrita2' s.version = Amrita2::Version::STRING s.platform = Gem::Platform::RUBY s.summary = "Amrita2 is a a xml/xhtml template library for Ruby" s.files = Dir.glob("{lib,specs,sample}/**/*") << "README" << "Rakefile" << "init.rb" s.require_path = 'lib' s.homepage = 'http://retro.brain-tokyo.net/projects/amrita2/wiki/Amrita2' s.rubyforge_project = 'amrita2' s.has_rdoc=true s.rdoc_options << "--main" << "README" s.extra_rdoc_files = ["README"] s.add_dependency('hpricot', '>= 0.6.0') s.author = "Taku Nakajima" s.email = "tnakajima@brain-tokyo.jp" end amrita2-2.0.2+dfsg.1/init.rb000066400000000000000000000003221130125402400154050ustar00rootroot00000000000000# plugin init files for Ruby On Rails require 'amrita2/rails_bridge' ActionView::Base.register_template_handler "a2html", Amrita2View::Base ActionView::Base.register_template_handler "a2", Amrita2View::Base amrita2-2.0.2+dfsg.1/lib/000077500000000000000000000000001130125402400146665ustar00rootroot00000000000000amrita2-2.0.2+dfsg.1/lib/amrita2.rb000066400000000000000000000000651130125402400165530ustar00rootroot00000000000000require 'amrita2/template' require 'amrita2/version' amrita2-2.0.2+dfsg.1/lib/amrita2/000077500000000000000000000000001130125402400162255ustar00rootroot00000000000000amrita2-2.0.2+dfsg.1/lib/amrita2/gettext.rb000066400000000000000000000050671130125402400202460ustar00rootroot00000000000000require 'amrita2/template' require 'gettext/rgettext' module Amrita2 module Core class CompoundElement # :nodoc: all def get_erb_source @children.collect do |c| c.get_erb_source end.join("\n") end end class ErbNode # :nodoc: all def get_erb_source return @node.to_s end end class DynamicElement # :nodoc: all def get_erb_source @children.collect do |c| c.get_erb_source end.join("\n") end end class CommentNode # :nodoc: all def get_erb_source "" end end class RootElement < DynamicElement # :nodoc: all attr_accessor :text_domain compile_old = self.instance_method(:compile) define_method(:compile) do |cg| cg.code("bindtextdomain(#{@text_domain.inspect})") compile_old.bind(self).call(cg) end end class Template attr_accessor :text_domain def compile_for_gettext setup end def get_erb_source_for_gettext setup @root.get_erb_source end end end module GetTextBridge # :nodoc: all class TextNodeForGetText < Core::StaticNode def dynamic? true end def render_me(cg) #text = @node.to_s.strip # to keep   text = "" @node.output(text, :preserve=>true) text.strip! cg.put_string_expression("_(#{text.inspect}) % $_") if text != "" end def get_erb_source return "" end end end module Filters class GetTextFilter < Filters::Base def parse_node(de, node) case node when Hpricot::CData super when Hpricot::Text Amrita2::GetTextBridge::TextNodeForGetText.new(de, node) else super end end end end module GetTextParser # :nodoc: all include Amrita2 include Amrita2::GetTextBridge module_function def target?(file) File.extname(file) == '.a2html' || File.extname(file) == '.a2' end def parse(file, ary) t = Template.new(File::open(file).read) do |e, src, filters| filters << Filters::GetTextFilter.new end src = t.compile_for_gettext RubyParser.parse_lines(file, [src], ary) src = t.get_erb_source_for_gettext erb = ERB.new(src).src.split(/$/) RubyParser.parse_lines(file, erb, ary) ary.collect do |msgid, fnameandline| [msgid, fnameandline.gsub(/\d+$/, "-")] end end end end GetText::RGetText.add_parser(Amrita2::GetTextParser) amrita2-2.0.2+dfsg.1/lib/amrita2/macro.rb000066400000000000000000000077161130125402400176660ustar00rootroot00000000000000require 'amrita2/template' module Amrita2 class Core::Template def add_macro(m) @macros ||= [] @macros << m end alias use_macro add_macro compile_old = instance_method(:compile) define_method(:compile) do |*args| macros = @macros if macros and macros.size > 0 filter_setup do |e, name ,filters| filters << MacroFilter.new(*macros) end end compile_old.bind(self).call(*args) end end module Macro # :nodoc: all class Base def initialize @mt = Template.new(get_macro_template, :amrita_prefix=>"macro:", :inline_ruby=>true) @option = {} @option = self.class.const_get(:Option) if self.class.const_defined?(:Option) raise "Macro Option is not defined propery in #{self.class} #{@option.inspect}" unless @option.kind_of?(Hash) end def get_macro_template self.class.const_get(:TemplateText) end def get_element_name #self.class.const_get(:ElementName) @option[:tag] || underscore(self.class.name) end def process(de, element) preprocess_element(@mt, element) end def match_element(element) element.name == get_element_name.to_s end def macro_data(element) element.as_amrita_dictionary(@option) end def preprocess_element(mt, element) if @option[:trace] mt.set_trace(@option[:trace]) @option[:trace] << (macro_data(element)).inspect end mt.amrita_prefix = "macro:" mt.render_with(macro_data(element)) end private # from activesupport def underscore(camel_cased_word) camel_cased_word.to_s.gsub(/::/, '/'). gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). gsub(/([a-z\d])([A-Z])/,'\1_\2'). tr("-", "_"). downcase end end end module Filters class MacroFilter < Base include Amrita2 include Util include OptionSupport attr_reader :macros def initialize(*macros) @macros = macros.collect do |m| case m when Class m.new else m end end @element_names = {} @macros.each do |m| @element_names[m.get_element_name.to_s] = true end end def check_element(element) return true if @element_names[element.name] element.each_child do |c| next unless c.kind_of?(Hpricot::Elem) return true if @element_names[c.name] or check_element(c) end false end def filter_element(de, element) return element unless check_element(element) @macros.each do |m| if m.match_element(element) ret = m.process(de, element) ret = Core::PreProcessor.new.process(ret.dup) ret.gsub!('<%%', '<%') ret.gsub!('%%>', '%>') root = Hpricot.make("<_ />").first Hpricot.make(ret, :xml=>true).each do |e| root.insert_after(e, nil) end element = replace_target_src(root) else element.each_child do |c| next unless c.kind_of?(Hpricot::Elem) cc = filter_element(de, c) element.replace_child(c, cc) if c != cc end end end element end def replace_target_src(e) %w(src filter v skipif for).each do |k| e.set_attribute("am:#{k}", e.attributes["target_#{k}"]) if e.attributes["target_#{k}"] e.delete_attribute("target_#{k}") end e.each_child do |c| next unless c.kind_of?(Hpricot::Elem) replace_target_src(c) end e end def element_render_code(de, cg, element, &block) if (element.name == 'macroroot') yield else super end end end end end amrita2-2.0.2+dfsg.1/lib/amrita2/rails_bridge.rb000066400000000000000000000145721130125402400212110ustar00rootroot00000000000000require 'amrita2/template' require 'action_view' module Amrita2 module Core class Hook include ActionView::Helpers::FormHelper include ActionView::Helpers::FormHelper end end end module Amrita2View # :nodoc: all module FormHelper class FormFieldHelper include Amrita2::DictionaryData attr_reader :form, :data def initialize(record, form, &block) @record = record @form = form @data = {} block.call(self) end def add_field(name, value) @data[name] = value end def add_field_element(name, element) add_field(name, Amrita2::SanitizedString[element]) end def method_missing(meth, name, *args, &block) value = @form.send(meth, name, *args, &block) add_field_element(name, value) end def as_hash @data end def as_label_field_hash @data.inject(Hash.new) do |h, data| k, v = *data h.merge ({ k => { :label => { :for=>"#{@record}_#{k}", :text=>k.to_s }, :field => v } }) end end end def amrita_define_form(*args, &block) record = args.first method = :form_for format = :as_hash case h = args.last when Hash method = h.delete(:form_method) || method format = h.delete(:amrita_format) || format end amrita_form_hook(method, *args) do |f| FormFieldHelper.new(record, f) do |ff| block.call(ff) end.send(format) end end def amrita_form_hook(meth, *args, &block) view = self hook = Amrita2::Core::Hook.new do _erbout = stream view.instance_eval do self.send(meth, *args) do |f| data = block.call(f) hook.render_me_with(data) end end end end end FormFieldHelper = FormHelper::FormFieldHelper end module ActionView # :nodoc: all class Base #:nodoc: include Amrita2::Runtime include Amrita2View::FormHelper end end module ActiveRecord # :nodoc: all class Base include Amrita2::DictionaryData end class ConnectionAdapters::Column include Amrita2::DictionaryData end end module Amrita2View # :nodoc: all class Base include Amrita2 include Amrita2::Filters include Amrita2::Runtime include Amrita2::Util CompileTimeBinding = binding @@compiled_amrita2_templates = {} @@text_domain = nil cattr_accessor :text_domain def initialize( action_view ) @action_view = action_view end def render(template, local_assigns={}) Thread::current[:amrita_rails_view] = @action_view if template.kind_of?(String) render_amrita(template, local_assigns) else @action_view.render(template, local_assigns) end end def setup_template(template) setup_template_default(template) end def setup_template_default(template) if Amrita2::const_defined?(:GetTextBridge) t = Amrita2::Template.new(template) do |e, src, filters| filters << Amrita2::Filters::GetTextFilter.new end t.text_domain = text_domain bindtextdomain(t.text_domain) #t.set_trace(STDOUT) t.compiletime_binding = CompileTimeBinding t else t = Amrita2::Template.new(template) t.compiletime_binding = CompileTimeBinding t end end def render_amrita(template, local_assigns) @@compiled_amrita2_templates[template] ||= setup_template(template) tmpl = @@compiled_amrita2_templates[template] b = setup_binding_of_view(local_assigns) tmpl.render_with(b) end def setup_binding_of_view(local_assigns) @action_view.instance_eval do evaluate_assigns b = binding local_assigns.each do |k, v| amrita_set_context_value(v) eval "#{k}=amrita_get_context_value",b end b end end end module Helper include ActionView::Helpers::UrlHelper def view @view ||= Thread::current[:amrita_rails_view] end def eval_in_view(&block) view.instance_eval &block end def eval_in_view_without_escape(&block) Amrita2::SanitizedString[eval_in_view(&block)] end end end =begin class WithObject < Amrita2::Macro::Base TemplateText = <<-'END' <<%< <% Thread::current[:amrita2_form_object] = $_[:name] || $_[:object] %> <<_ :| Attr[:target_src=>:object]< <<:contents>> END Option = { :tag => "a:with_object", :use_contents => :contents, } end class Input < Amrita2::Macro::Base TemplateText = <<-'END' <<%< <% object = $_.delete(:object) || Thread::current[:amrita2_form_object] input_id = $_.delete(:id) other = $_.collect do |k, v| "#{k}='#{v}'" end %> target_filter="Attr[:value=><%= input_id.intern.inspect %>]"/> END Option = { :tag => "a:input" } end class TextField < Amrita2::Macro::Base TemplateText = <<-'END' <<%< <% object = $_.delete(:object) || Thread::current[:amrita2_form_object] input_id = $_.delete(:id) $_[:size] ||= 30 other = $_.collect do |k, v| "#{k}='#{v}'" end %> target_filter="Attr[:value=><%= input_id.intern.inspect %>]"/> END Option = { :tag => "a:text_field", } end class TextArea < Amrita2::Macro::Base TemplateText = <<-'END' <<%< <% object = $_.delete(:object) || Thread::current[:amrita2_form_object] input_id = $_.delete(:id) $_[:cols] ||= 40 $_[:rows] ||= 20 other = $_.collect do |k, v| "#{k}='#{v}'" end %>