/usr/lib/ruby/vendor_ruby/merb-core/controller/template.rb is in ruby-merb-core 1.1.3+dfsg-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | module Merb::InlineTemplates
end
module Merb::Template
EXTENSIONS = {} unless defined?(EXTENSIONS)
METHOD_LIST = {} unless defined?(METHOD_LIST)
SUPPORTED_LOCALS_LIST = Hash.new([].freeze) unless defined?(SUPPORTED_LOCALS_LIST)
MTIMES = {} unless defined?(MTIMES)
class << self
# Get the template's method name from a full path. This replaces
# non-alphanumeric characters with __ and "." with "_"
#
# Collisions are potentially possible with something like:
# ~foo.bar and __foo.bar or !foo.bar.
#
# ==== Parameters
# path<String>:: A full path to convert to a valid Ruby method name
#
# ==== Returns
# String:: The template name.
#
#
# We might want to replace this with something that varies the
# character replaced based on the non-alphanumeric character
# to avoid edge-case collisions.
#
# :api: private
def template_name(path)
path = File.expand_path(path)
path.gsub(/[^\.a-zA-Z0-9]/, "__").gsub(/\./, "_")
end
chainable do
# For a given path, get an IO object that responds to #path.
#
# This is so that plugins can override this if they provide
# mechanisms for specifying templates that are not just simple
# files. The plugin is responsible for ensuring that the fake
# path provided will work with #template_for, and thus the
# RenderMixin in general.
#
# ==== Parameters
# path<String>:: A full path to find a template for. This is the
# path that the RenderMixin assumes it should find the template
# in.
#
# ==== Returns
# IO#path:: An IO object that responds to path (File or VirtualFile).
#
# :api: plugin
# @overridable
def load_template_io(path)
file = Dir["#{path}.{#{template_extensions.join(',')}}"].first
File.open(file, "r") if file
end
end
# Get the name of the template method for a particular path.
#
# ==== Parameters
# path<String>:: A full path to find a template method for.
# template_stack<Array>:: The template stack. Not used.
# locals<Array[Symbol]>:: The names of local variables
#
# ==== Returns
# <String>:: name of the method that inlines the template.
#
# :api: private
def template_for(path, template_stack = [], locals=[])
path = File.expand_path(path)
if needs_compilation?(path, locals)
template_io = load_template_io(path)
METHOD_LIST[path] = inline_template(template_io, locals) if template_io
end
METHOD_LIST[path]
end
# Decide if a template needs to be re/compiled.
#
# ==== Parameters
# path<String>:: The full path of the template to check support for.
# locals<Array[Symbol]>:: The list of locals that need to be supported
#
# ==== Returns
# Boolean:: Whether or not the template for the provided path needs to be recompiled
#
# :api: private
def needs_compilation?(path, locals)
return true if Merb::Config[:reload_templates] || !METHOD_LIST[path]
current_locals = SUPPORTED_LOCALS_LIST[path]
current_locals != locals &&
!(locals - current_locals).empty?
end
# Get all known template extensions
#
# ==== Returns
# Array:: Extension strings.
#
# :api: plugin
def template_extensions
EXTENSIONS.keys
end
# Takes a template at a particular path and inlines it into a module and
# adds it to the METHOD_LIST table to speed lookup later.
#
# ==== Parameters
# io<#path>::
# An IO that responds to #path (File or VirtualFile)
# locals<Array[Symbol]>::
# A list of local names that should be assigned in the template method
# from the arguments hash. Defaults to [].
# mod<Module>::
# The module to put the compiled method into. Defaults to
# Merb::InlineTemplates
#
# ==== Returns
# Symbol:: The name of the method that the template was compiled into.
#
# ==== Notes
# Even though this method supports inlining into any module, the method
# must be available to instances of AbstractController that will use it.
#
# :api: private
def inline_template(io, locals=[], mod = Merb::InlineTemplates)
full_file_path = File.expand_path(io.path)
engine_neutral_path = full_file_path.gsub(/\.[^\.]*$/, "")
local_list = (SUPPORTED_LOCALS_LIST[engine_neutral_path] |= locals)
ret = METHOD_LIST[engine_neutral_path] =
engine_for(full_file_path).compile_template(io,
template_name(full_file_path), local_list, mod)
io.close
ret
end
# Finds the engine for a particular path.
#
# ==== Parameters
# path<String>:: The path of the file to find an engine for.
#
# ==== Returns
# Class:: The engine.
#
# :api: private
def engine_for(path)
path = File.expand_path(path)
EXTENSIONS[path.match(/\.([^\.]*)$/)[1]]
end
# Registers the extensions that will trigger a particular templating
# engine.
#
# ==== Parameters
# engine<Class>:: The class of the engine that is being registered
# extensions<Array[String]>::
# The list of extensions that will be registered with this templating
# language
#
# ==== Raises
# ArgumentError:: engine does not have a compile_template method.
#
# ==== Returns
# nil
#
# ==== Example
# Merb::Template.register_extensions(Merb::Template::Erubis, ["erb"])
#
# :api: plugin
def register_extensions(engine, extensions)
raise ArgumentError, "The class you are registering does not have a compile_template method" unless
engine.respond_to?(:compile_template)
extensions.each{|ext| EXTENSIONS[ext] = engine }
Merb::AbstractController.class_eval <<-HERE
include #{engine}::Mixin
HERE
end
end
require 'erubis'
class Erubis
# Fixing bug in Erubis
# http://rubyforge.org/tracker/index.php?func=detail&aid=21825&group_id=1320&atid=5201
XmlHelper = ::Erubis::XmlHelper
# ==== Parameters
# io<#path>:: An IO containing the full path of the template.
# name<String>:: The name of the method that will be created.
# locals<Array[Symbol]>:: A list of locals to assign from the args passed into the compiled template.
# mod<Module>:: The module that the compiled method will be placed into.
#
# :api: private
def self.compile_template(io, name, locals, mod)
template = ::Erubis::BlockAwareEruby.new(io.read)
_old_verbose, $VERBOSE = $VERBOSE, nil
assigns = locals.inject([]) do |assigns, local|
assigns << "#{local} = _locals[#{local.inspect}]"
end.join(";")
code = "def #{name}(_locals={}); #{assigns}; #{template.src}; end"
mod.module_eval code, File.expand_path(io.path)
$VERBOSE = _old_verbose
name
end
module Mixin
# ==== Parameters
# *args:: Arguments to pass to the block.
# &block:: The template block to call.
#
# ==== Returns
# String:: The output of the block.
#
# ==== Examples
# Capture being used in a .html.erb page:
#
# <% @foo = capture do %>
# <p>Some Foo content!</p>
# <% end %>
#
# :api: private
def capture_erb(*args, &block)
_old_buf, @_erb_buf = @_erb_buf, ""
block.call(*args)
ret = @_erb_buf
@_erb_buf = _old_buf
ret
end
# :api: private
def concat_erb(string, binding)
@_erb_buf << string
end
end
Merb::Template.register_extensions(self, %w[erb])
end
end
module Erubis
module BlockAwareEnhancer
# :api: private
def add_preamble(src)
src << "_old_buf, @_erb_buf = @_erb_buf, ''; "
src << "@_engine = 'erb'; "
end
# :api: private
def add_postamble(src)
src << "\n" unless src[-1] == ?\n
src << "_ret = @_erb_buf; @_erb_buf = _old_buf; _ret.to_s;\n"
end
# :api: private
def add_text(src, text)
src << " @_erb_buf.concat('" << escape_text(text) << "'); "
end
# :api: private
def add_expr_escaped(src, code)
src << ' @_erb_buf.concat(' << escaped_expr(code) << ');'
end
# :api: private
def add_stmt2(src, code, tailch)
src << code
src << ") ).to_s; " if tailch == "="
src << ';' unless code[-1] == ?\n
end
# :api: private
def add_expr_literal(src, code)
if code =~ /(do|\{)(\s*\|[^|]*\|)?\s*\Z/
src << ' @_erb_buf.concat( (' << code << "; "
else
src << ' @_erb_buf.concat((' << code << ').to_s);'
end
end
end
class BlockAwareEruby < Eruby
include BlockAwareEnhancer
end
# module RubyEvaluator
#
# # DOC
# def def_method(object, method_name, filename=nil)
# m = object.is_a?(Module) ? :module_eval : :instance_eval
# setup = "@_engine = 'erb'"
# object.__send__(m, "def #{method_name}(locals={}); #{setup}; #{@src}; end", filename || @filename || '(erubis)')
# end
#
# end
end
|