/usr/lib/ruby/vendor_ruby/slim/embedded.rb is in ruby-slim 2.0.2-3.
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 | module Slim
# @api private
class TextCollector < Filter
def call(exp)
@collected = ''
super(exp)
@collected
end
def on_slim_interpolate(text)
@collected << text
nil
end
end
# @api private
class NewlineCollector < Filter
def call(exp)
@collected = [:multi]
super(exp)
@collected
end
def on_newline
@collected << [:newline]
nil
end
end
# @api private
class OutputProtector < Filter
def call(exp)
@protect = []
@collected = ''
super(exp)
@collected
end
def on_static(text)
@collected << text
nil
end
def on_slim_output(escape, text, content)
@collected << "pro#{@protect.size}tect"
@protect << [:slim, :output, escape, text, content]
nil
end
def unprotect(text)
block = [:multi]
while text =~ /pro(\d+)tect/
block << [:static, $`]
block << @protect[$1.to_i]
text = $'
end
block << [:static, text]
end
end
# Temple filter which processes embedded engines
# @api private
class Embedded < Filter
@engines = {}
# Register embedded engine
#
# @param [String] name Name of the engine
# @param [Class] klass Engine class
# @param option_filter List of options to pass to engine.
# Last argument can be default option hash.
def self.register(name, klass, *option_filter)
name = name.to_sym
local_options = option_filter.last.respond_to?(:to_hash) ? option_filter.pop.to_hash : {}
define_options(name, *option_filter)
klass.define_options(name)
@engines[name.to_sym] = proc do |options|
klass.new({}.update(options).delete_if {|k,v| !option_filter.include?(k) && k != name }.update(local_options))
end
end
def self.create(name, options)
constructor = @engines[name] || raise(Temple::FilterError, "Embedded engine #{name} not found")
constructor.call(options)
end
define_options :enable_engines, :disable_engines
def initialize(opts = {})
super
@engines = {}
@enabled = normalize_engine_list(options[:enable_engines])
@disabled = normalize_engine_list(options[:disable_engines])
end
def on_slim_embedded(name, body)
name = name.to_sym
raise(Temple::FilterError, "Embedded engine #{name} is disabled") unless enabled?(name)
@engines[name] ||= self.class.create(name, options)
@engines[name].on_slim_embedded(name, body)
end
def enabled?(name)
(!@enabled || @enabled.include?(name)) &&
(!@disabled || !@disabled.include?(name))
end
protected
def normalize_engine_list(list)
raise(ArgumentError, "Option :enable_engines/:disable_engines must be String or Symbol list") unless !list || Array === list
list ? list.map {|s| s.to_sym } : list
end
class Engine < Filter
protected
def collect_text(body)
@text_collector ||= TextCollector.new
@text_collector.call(body)
end
def collect_newlines(body)
@newline_collector ||= NewlineCollector.new
@newline_collector.call(body)
end
end
# Basic tilt engine
class TiltEngine < Engine
def on_slim_embedded(engine, body)
tilt_engine = Tilt[engine] || raise(Temple::FilterError, "Tilt engine #{engine} is not available.")
tilt_options = options[engine.to_sym] || {}
[:multi, tilt_render(tilt_engine, tilt_options, collect_text(body)), collect_newlines(body)]
end
end
# Tilt-based static template (evaluated at compile-time)
class StaticTiltEngine < TiltEngine
protected
def tilt_render(tilt_engine, tilt_options, text)
[:static, tilt_engine.new(tilt_options) { text }.render]
end
end
# Sass engine which supports :pretty option
class SassEngine < TiltEngine
define_options :pretty
protected
def tilt_render(tilt_engine, tilt_options, text)
text = tilt_engine.new(tilt_options.merge(
:style => options[:pretty] ? :expanded : :compressed,
:cache => false)) { text }.render
text.chomp!
[:static, text]
end
end
# Tilt-based engine which is precompiled
class PrecompiledTiltEngine < TiltEngine
protected
def tilt_render(tilt_engine, tilt_options, text)
# HACK: Tilt::Engine#precompiled is protected
[:dynamic, tilt_engine.new(tilt_options) { text }.send(:precompiled, {}).first]
end
end
# Static template with interpolated ruby code
class InterpolateTiltEngine < TiltEngine
def collect_text(body)
output_protector.call(interpolation.call(body))
end
def tilt_render(tilt_engine, tilt_options, text)
output_protector.unprotect(tilt_engine.new(tilt_options) { text }.render)
end
private
def interpolation
@interpolation ||= Interpolation.new
end
def output_protector
@output_protector ||= OutputProtector.new
end
end
# ERB engine (uses the Temple ERB implementation)
class ERBEngine < Engine
def on_slim_embedded(engine, body)
[:multi, [:newline], erb_parser.call(collect_text(body))]
end
protected
def erb_parser
@erb_parser ||= Temple::ERB::Parser.new
end
end
# Tag wrapper engine
# Generates a html tag and wraps another engine (specified via :engine option)
class TagEngine < Engine
disable_option_validator!
def on_slim_embedded(engine, body)
if options[:engine]
opts = {}.update(options)
opts.delete(:engine)
opts.delete(:tag)
opts.delete(:attributes)
@engine ||= options[:engine].new(opts)
body = @engine.on_slim_embedded(engine, body)
end
[:html, :tag, options[:tag], [:html, :attrs, *options[:attributes].map {|k, v| [:html, :attr, k, [:static, v]] }], body]
end
end
# Javascript wrapper engine.
# Like TagEngine, but can wrap content in html comment or cdata.
class JavaScriptEngine < TagEngine
disable_option_validator!
set_default_options :tag => :script, :attributes => { :type => 'text/javascript' }
def on_slim_embedded(engine, body)
super(engine, [:html, :js, body])
end
end
# Embeds ruby code
class RubyEngine < Engine
def on_slim_embedded(engine, body)
[:multi, [:newline], [:code, collect_text(body)]]
end
end
# These engines are executed at compile time, embedded ruby is interpolated
register :asciidoc, InterpolateTiltEngine
register :markdown, InterpolateTiltEngine
register :textile, InterpolateTiltEngine
register :rdoc, InterpolateTiltEngine
register :creole, InterpolateTiltEngine
register :wiki, InterpolateTiltEngine
register :mediawiki, InterpolateTiltEngine
register :org, InterpolateTiltEngine
# These engines are executed at compile time
register :coffee, JavaScriptEngine, :engine => StaticTiltEngine
register :less, TagEngine, :tag => :style, :attributes => { :type => 'text/css' }, :engine => StaticTiltEngine
register :styl, TagEngine, :tag => :style, :attributes => { :type => 'text/css' }, :engine => StaticTiltEngine
register :sass, TagEngine, :pretty, :tag => :style, :attributes => { :type => 'text/css' }, :engine => SassEngine
register :scss, TagEngine, :pretty, :tag => :style, :attributes => { :type => 'text/css' }, :engine => SassEngine
# These engines are precompiled, code is embedded
register :erb, ERBEngine
register :nokogiri, PrecompiledTiltEngine
register :builder, PrecompiledTiltEngine
# Embedded javascript/css
register :javascript, JavaScriptEngine
register :css, TagEngine, :tag => :style, :attributes => { :type => 'text/css' }
# Embedded ruby code
register :ruby, RubyEngine
end
end
|