slim-2.0.0.pre.6/0000755000175000017500000000000012121046025012423 5ustar lunarlunarslim-2.0.0.pre.6/metadata.yml0000644000175000017500000001171212121046025014730 0ustar lunarlunar--- !ruby/object:Gem::Specification name: slim version: !ruby/object:Gem::Version version: 2.0.0.pre.6 prerelease: 6 platform: ruby authors: - Daniel Mendler - Andrew Stone - Fred Wu autorequire: bindir: bin cert_chain: [] date: 2013-02-12 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: temple requirement: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 0.6.2 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 0.6.2 - !ruby/object:Gem::Dependency name: tilt requirement: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 1.3.3 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 1.3.3 description: Slim is a template language whose goal is reduce the syntax to the essential parts without becoming cryptic. email: - mail@daniel-mendler.de - andy@stonean.com - ifredwu@gmail.com executables: - slimrb extensions: [] extra_rdoc_files: [] files: - .gitignore - .travis.yml - .yardopts - CHANGES - Gemfile - LICENSE - README.md - Rakefile - benchmarks/context.rb - benchmarks/profile-parser.rb - benchmarks/profile-render.rb - benchmarks/run-benchmarks.rb - benchmarks/run-diffbench.rb - benchmarks/view.erb - benchmarks/view.haml - benchmarks/view.slim - bin/slimrb - kill-travis.sh - lib/slim.rb - lib/slim/code_attributes.rb - lib/slim/command.rb - lib/slim/controls.rb - lib/slim/embedded.rb - lib/slim/end_inserter.rb - lib/slim/engine.rb - lib/slim/filter.rb - lib/slim/grammar.rb - lib/slim/interpolation.rb - lib/slim/logic_less.rb - lib/slim/logic_less/context.rb - lib/slim/logic_less/filter.rb - lib/slim/parser.rb - lib/slim/splat/builder.rb - lib/slim/splat/filter.rb - lib/slim/template.rb - lib/slim/translator.rb - lib/slim/version.rb - slim.gemspec - test/core/helper.rb - test/core/test_code_blocks.rb - test/core/test_code_escaping.rb - test/core/test_code_evaluation.rb - test/core/test_code_output.rb - test/core/test_code_structure.rb - test/core/test_embedded_engines.rb - test/core/test_encoding.rb - test/core/test_html_attributes.rb - test/core/test_html_escaping.rb - test/core/test_html_structure.rb - test/core/test_parser_errors.rb - test/core/test_pretty.rb - test/core/test_ruby_errors.rb - test/core/test_slim_template.rb - test/core/test_tabs.rb - test/core/test_text_interpolation.rb - test/core/test_thread_options.rb - test/core/test_unicode.rb - test/literate/TESTS.md - test/literate/helper.rb - test/literate/run.rb - test/logic_less/test_logic_less.rb - test/rails/Rakefile - test/rails/app/controllers/application_controller.rb - test/rails/app/controllers/parents_controller.rb - test/rails/app/controllers/slim_controller.rb - test/rails/app/helpers/application_helper.rb - test/rails/app/models/child.rb - test/rails/app/models/parent.rb - test/rails/app/views/layouts/application.html.slim - test/rails/app/views/parents/_form.html.slim - test/rails/app/views/parents/edit.html.slim - test/rails/app/views/parents/new.html.slim - test/rails/app/views/parents/show.html.slim - test/rails/app/views/slim/_partial.html.slim - test/rails/app/views/slim/content_for.html.slim - test/rails/app/views/slim/erb.html.erb - test/rails/app/views/slim/integers.html.slim - test/rails/app/views/slim/no_layout.html.slim - test/rails/app/views/slim/normal.html.slim - test/rails/app/views/slim/partial.html.slim - test/rails/app/views/slim/thread_options.html.slim - test/rails/app/views/slim/variables.html.slim - test/rails/config.ru - test/rails/config/application.rb - test/rails/config/boot.rb - test/rails/config/database.yml - test/rails/config/environment.rb - test/rails/config/environments/test.rb - test/rails/config/initializers/backtrace_silencers.rb - test/rails/config/initializers/inflections.rb - test/rails/config/initializers/mime_types.rb - test/rails/config/initializers/secret_token.rb - test/rails/config/initializers/session_store.rb - test/rails/config/locales/en.yml - test/rails/config/routes.rb - test/rails/db/migrate/20101220223037_parents_and_children.rb - test/rails/script/rails - test/rails/test/helper.rb - test/rails/test/test_slim.rb - test/translator/test_translator.rb homepage: http://slim-lang.com/ licenses: [] post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>' - !ruby/object:Gem::Version version: 1.3.1 requirements: [] rubyforge_project: slim rubygems_version: 1.8.24 signing_key: specification_version: 3 summary: Slim is a template language. test_files: [] slim-2.0.0.pre.6/test/0000755000175000017500000000000012121046025013402 5ustar lunarlunarslim-2.0.0.pre.6/test/translator/0000755000175000017500000000000012121046025015573 5ustar lunarlunarslim-2.0.0.pre.6/test/translator/test_translator.rb0000644000175000017500000000351212121046025021351 0ustar lunarlunarrequire 'helper' require 'slim/translator' class TestSlimTranslator < TestSlim def setup super Slim::Engine.set_default_options :tr => true, :tr_fn => 'TestSlimTranslator.tr' end def self.tr(s) s.upcase end def self.tr_reverse(s) s.reverse.gsub(/(\d+)%/, '%\1') end def test_no_translation_of_embedded source = %q{ markdown: #Header Hello from #{"Markdown!"} #{1+2} * one * two } assert_html "

Header

\n

Hello from Markdown!

\n\n

3

\n\n\n", source, :tr_mode => :dynamic assert_html "

Header

\n

Hello from Markdown!

\n\n

3

\n\n\n", source, :tr_mode => :static end def test_no_translation_of_attrs source = %q{ ' this is a link to a href="link" page } assert_html "THIS IS\nA LINK TO PAGE", source, :tr_mode => :dynamic assert_html "THIS IS\nA LINK TO PAGE", source, :tr_mode => :static end def test_translation_and_interpolation source = %q{ p translate #{hello_world} this second line third #{1+2} line } assert_html "

translate Hello World from @env this\nsecond line\nthird 3 line

", source, :tr => false assert_html "

TRANSLATE Hello World from @env THIS\nSECOND LINE\nTHIRD 3 LINE

", source, :tr_mode => :dynamic assert_html "

TRANSLATE Hello World from @env THIS\nSECOND LINE\nTHIRD 3 LINE

", source, :tr_mode => :static end def test_translation_reverse source = %q{ ' alpha #{1} beta #{2} gamma #{3} } assert_html "3 ammag 2 ateb 1 ahpla ", source, :tr_mode => :dynamic, :tr_fn => 'TestSlimTranslator.tr_reverse' assert_html "3 ammag 2 ateb 1 ahpla ", source, :tr_mode => :static, :tr_fn => 'TestSlimTranslator.tr_reverse' end end slim-2.0.0.pre.6/test/rails/0000755000175000017500000000000012121046025014514 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/test/0000755000175000017500000000000012121046025015473 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/test/test_slim.rb0000644000175000017500000000532412121046025020027 0ustar lunarlunarrequire File.expand_path('../helper', __FILE__) class TestSlim < ActionDispatch::IntegrationTest test "normal view" do get "slim/normal" assert_response :success assert_template "slim/normal" assert_template "layouts/application" assert_html "

Hello Slim!

" end test "normal erb view" do get "slim/erb" assert_html "

Hello Erb!

" end test "view without a layout" do get "slim/no_layout" assert_template "slim/no_layout" assert_html "

Hello Slim without a layout!

", :skip_layout => true end test "view with variables" do get "slim/variables" assert_html "

Hello Slim with variables!

" end test "partial view" do get "slim/partial" assert_html "

Hello Slim!

With a partial!

" end if ::Rails::VERSION::MAJOR == 3 && ::Rails::VERSION::MINOR >= 1 && Object.const_defined?(:Fiber) puts 'Streaming test enabled' test "streaming" do get "slim/streaming" output = "2f\r\nDummy\r\nd\r\n\r\n17\r\nHeading set from a view\r\n15\r\n
\r\n53\r\n

Page content

Hello Streaming!

Hello Streaming!

\r\n14\r\n
\r\n0\r\n\r\n" assert_equal output, @response.body end else puts 'Streaming test disabled' end test "render integers" do get "slim/integers" assert_html "

1337

" end test "render thread_options" do get "slim/thread_options", :attr => 'role' assert_html '

Test

' get "slim/thread_options", :attr => 'id' # Overwriting doesn't work because of caching assert_html '

Test

' end test "content_for" do get "slim/content_for" assert_html "

Page content

Hello Slim!

Hello Slim!

", :heading => 'Heading set from a view' end test "nested_attributes_form" do post "parents", 'parent[name]' => "p1", 'parent[children_attributes][0][name]' => "c1" get "parents/1/edit" assert_match %r{action="/parents/1"}, @response.body assert_match %r{#{expected}" unless options[:skip_layout] assert_equal expected, @response.body end end slim-2.0.0.pre.6/test/rails/test/helper.rb0000644000175000017500000000045712121046025017305 0ustar lunarlunar# Configure Rails Envinronment ENV["RAILS_ENV"] = "test" require File.expand_path("../../config/environment.rb", __FILE__) require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! # Run any available migration ActiveRecord::Migrator.migrate File.expand_path("../../db/migrate/", __FILE__) slim-2.0.0.pre.6/test/rails/script/0000755000175000017500000000000012121046025016020 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/script/rails0000755000175000017500000000044712121046025017065 0ustar lunarlunar#!/usr/bin/env ruby # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. APP_PATH = File.expand_path('../../config/application', __FILE__) require File.expand_path('../../config/boot', __FILE__) require 'rails/commands' slim-2.0.0.pre.6/test/rails/db/0000755000175000017500000000000012121046025015101 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/db/migrate/0000755000175000017500000000000012121046025016531 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/db/migrate/20101220223037_parents_and_children.rb0000644000175000017500000000052012121046025024651 0ustar lunarlunarclass ParentsAndChildren < ActiveRecord::Migration def self.up create_table :parents do |t| t.string :name end create_table :children do |t| t.string :name t.integer :parent_id end add_index :children, :parent_id end def self.down drop_table :children drop_table :parents end end slim-2.0.0.pre.6/test/rails/config/0000755000175000017500000000000012121046025015761 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/config/routes.rb0000644000175000017500000000341612121046025017633 0ustar lunarlunarDummy::Application.routes.draw do # The priority is based upon order of creation: # first created -> highest priority. resources :parents # Sample of regular route: # match 'products/:id' => 'catalog#view' # Keep in mind you can assign values other than :controller and :action # Sample of named route: # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase # This route can be invoked with purchase_url(:id => product.id) # Sample resource route (maps HTTP verbs to controller actions automatically): # resources :products # Sample resource route with options: # resources :products do # member do # get 'short' # post 'toggle' # end # # collection do # get 'sold' # end # end # Sample resource route with sub-resources: # resources :products do # resources :comments, :sales # resource :seller # end # Sample resource route with more complex sub-resources # resources :products do # resources :comments # resources :sales do # get 'recent', :on => :collection # end # end # Sample resource route within a namespace: # namespace :admin do # # Directs /admin/products/* to Admin::ProductsController # # (app/controllers/admin/products_controller.rb) # resources :products # end # You can have the root of your site routed with "root" # just remember to delete public/index.html. # root :to => "welcome#index" # See how all your routes lay out with "rake routes" # This is a legacy wild controller route that's not recommended for RESTful applications. # Note: This route will make all actions in every controller accessible via GET requests. get ':controller(/:action(/:id(.:format)))' end slim-2.0.0.pre.6/test/rails/config/locales/0000755000175000017500000000000012121046025017403 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/config/locales/en.yml0000644000175000017500000000032512121046025020530 0ustar lunarlunar# Sample localization file for English. Add more files in this directory for other locales. # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. en: hello: "Hello world" slim-2.0.0.pre.6/test/rails/config/initializers/0000755000175000017500000000000012121046025020467 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/config/initializers/session_store.rb0000644000175000017500000000063212121046025023714 0ustar lunarlunar# Be sure to restart your server when you modify this file. Dummy::Application.config.session_store :cookie_store, :key => '_dummy_session' # Use the database for sessions instead of the cookie-based default, # which shouldn't be used to store highly confidential information # (create the session table with "rails generate session_migration") # Dummy::Application.config.session_store :active_record_store slim-2.0.0.pre.6/test/rails/config/initializers/secret_token.rb0000644000175000017500000000103412121046025023477 0ustar lunarlunar# Be sure to restart your server when you modify this file. # Your secret key for verifying the integrity of signed cookies. # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. Dummy::Application.config.secret_token = Dummy::Application.config.secret_key_base = '123a9119fb14a410f485f9390286b33f2743b9d348246cf3e4434522078f77c202d7a1fb7e42666dd0844bcb10d0ff3d8b4ee087796269d4c574837948512dbf' slim-2.0.0.pre.6/test/rails/config/initializers/mime_types.rb0000644000175000017500000000031512121046025023166 0ustar lunarlunar# Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf # Mime::Type.register_alias "text/html", :iphone slim-2.0.0.pre.6/test/rails/config/initializers/inflections.rb0000644000175000017500000000057012121046025023333 0ustar lunarlunar# Be sure to restart your server when you modify this file. # Add new inflection rules using the following format # (all these examples are active by default): # ActiveSupport::Inflector.inflections do |inflect| # inflect.plural /^(ox)$/i, '\1en' # inflect.singular /^(ox)en/i, '\1' # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) # end slim-2.0.0.pre.6/test/rails/config/initializers/backtrace_silencers.rb0000644000175000017500000000062412121046025025004 0ustar lunarlunar# Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. # Rails.backtrace_cleaner.remove_silencers! slim-2.0.0.pre.6/test/rails/config/environments/0000755000175000017500000000000012121046025020510 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/config/environments/test.rb0000644000175000017500000000264412121046025022022 0ustar lunarlunarDummy::Application.configure do # Settings specified here will take precedence over those in config/application.rb # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! config.cache_classes = true # Show full error reports and disable caching config.consider_all_requests_local = true config.action_controller.perform_caching = false # Raise exceptions instead of rendering exception templates config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment config.action_controller.allow_forgery_protection = false # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test # Use SQL instead of Active Record's schema dumper when creating the test database. # This is necessary if your schema can't be completely dumped by the schema dumper, # like if you have constraints or database-specific column types # config.active_record.schema_format = :sql # Print deprecation notices to the stderr config.active_support.deprecation = :stderr config.eager_load = false end slim-2.0.0.pre.6/test/rails/config/environment.rb0000644000175000017500000000022512121046025020651 0ustar lunarlunar# Load the rails application require File.expand_path('../application', __FILE__) # Initialize the rails application Dummy::Application.initialize! slim-2.0.0.pre.6/test/rails/config/database.yml0000644000175000017500000000006112121046025020245 0ustar lunarlunartest: adapter: sqlite3 database: ':memory:' slim-2.0.0.pre.6/test/rails/config/boot.rb0000644000175000017500000000041712121046025017253 0ustar lunarlunarrequire 'rubygems' gemfile = File.expand_path('../../../../../../Gemfile', __FILE__) if File.exist?(gemfile) ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' Bundler.setup(:default, :integration) end $:.unshift File.expand_path('../../../../../../lib', __FILE__)slim-2.0.0.pre.6/test/rails/config/application.rb0000644000175000017500000000354112121046025020614 0ustar lunarlunarrequire File.expand_path('../boot', __FILE__) require 'active_model/railtie' require 'active_record/railtie' require 'action_controller/railtie' require 'action_view/railtie' require 'action_mailer/railtie' require 'slim' module Dummy class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. # Custom directories with classes and modules you want to be autoloadable. # config.autoload_paths += %W(#{config.root}/extras) # Only load the plugins named here, in the order given (default is alphabetical). # :all can be used as a placeholder for all plugins not explicitly named. # config.plugins = [ :exception_notification, :ssl_requirement, :all ] # Activate observers that should always be running. # config.active_record.observers = :cacher, :garbage_collector, :forum_observer # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. # config.time_zone = 'Central Time (US & Canada)' # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # config.i18n.default_locale = :de # JavaScript files you want as :defaults (application.js is always included). # config.action_view.javascript_expansions[:defaults] = %w(jquery rails) # Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8" # Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password] end end slim-2.0.0.pre.6/test/rails/config.ru0000644000175000017500000000023312121046025016327 0ustar lunarlunar# This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) run Dummy::Application slim-2.0.0.pre.6/test/rails/app/0000755000175000017500000000000012121046025015274 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/app/views/0000755000175000017500000000000012121046025016431 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/app/views/slim/0000755000175000017500000000000012121046025017375 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/app/views/slim/variables.html.slim0000644000175000017500000000001212121046025023167 0ustar lunarlunarh1= @helloslim-2.0.0.pre.6/test/rails/app/views/slim/thread_options.html.slim0000644000175000017500000000001512121046025024244 0ustar lunarlunarp@empty Test slim-2.0.0.pre.6/test/rails/app/views/slim/partial.html.slim0000644000175000017500000000004112121046025022655 0ustar lunarlunarh1 Hello Slim! = render "partial"slim-2.0.0.pre.6/test/rails/app/views/slim/normal.html.slim0000644000175000017500000000001612121046025022513 0ustar lunarlunarh1 Hello Slim!slim-2.0.0.pre.6/test/rails/app/views/slim/no_layout.html.slim0000644000175000017500000000003712121046025023237 0ustar lunarlunarh1 Hello Slim without a layout!slim-2.0.0.pre.6/test/rails/app/views/slim/integers.html.slim0000644000175000017500000000001312121046025023040 0ustar lunarlunarp= @integerslim-2.0.0.pre.6/test/rails/app/views/slim/erb.html.erb0000644000175000017500000000002312121046025021575 0ustar lunarlunar

Hello Erb!

slim-2.0.0.pre.6/test/rails/app/views/slim/content_for.html.slim0000644000175000017500000000023312121046025023544 0ustar lunarlunarp Page content - content_for :page_heading, "Heading set from a view" - content_for :hello_slim do p= @hello h1= yield :hello_slim h2= yield :hello_slimslim-2.0.0.pre.6/test/rails/app/views/slim/_partial.html.slim0000644000175000017500000000002112121046025023012 0ustar lunarlunarp With a partial!slim-2.0.0.pre.6/test/rails/app/views/parents/0000755000175000017500000000000012121046025020105 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/app/views/parents/show.html.slim0000644000175000017500000000016512121046025022720 0ustar lunarlunar= @parent.name ul - @parent.children.each do |child| li= child.name = link_to 'Edit', edit_parent_path(@parent)slim-2.0.0.pre.6/test/rails/app/views/parents/new.html.slim0000644000175000017500000000002712121046025022526 0ustar lunarlunarh1 New = render "form" slim-2.0.0.pre.6/test/rails/app/views/parents/edit.html.slim0000644000175000017500000000003012121046025022654 0ustar lunarlunarh1 Edit = render "form" slim-2.0.0.pre.6/test/rails/app/views/parents/_form.html.slim0000644000175000017500000000027012121046025023037 0ustar lunarlunarh2 Form = form_for @parent, :html => {:multipart => true} do |f| h1 Parent = f.text_field :name h2 Children ul = f.fields_for :children do |c| li= c.text_field :name slim-2.0.0.pre.6/test/rails/app/views/layouts/0000755000175000017500000000000012121046025020131 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/app/views/layouts/application.html.slim0000644000175000017500000000016412121046025024266 0ustar lunarlunardoctype html html head title Dummy = csrf_meta_tag body = yield :page_heading .content= yield slim-2.0.0.pre.6/test/rails/app/models/0000755000175000017500000000000012121046025016557 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/app/models/parent.rb0000644000175000017500000000017512121046025020400 0ustar lunarlunarclass Parent < ActiveRecord::Base has_many :children accepts_nested_attributes_for :children, :allow_destroy => true end slim-2.0.0.pre.6/test/rails/app/models/child.rb0000644000175000017500000000007212121046025020166 0ustar lunarlunarclass Child < ActiveRecord::Base belongs_to :parent end slim-2.0.0.pre.6/test/rails/app/helpers/0000755000175000017500000000000012121046025016736 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/app/helpers/application_helper.rb0000644000175000017500000000003512121046025023123 0ustar lunarlunarmodule ApplicationHelper end slim-2.0.0.pre.6/test/rails/app/controllers/0000755000175000017500000000000012121046025017642 5ustar lunarlunarslim-2.0.0.pre.6/test/rails/app/controllers/slim_controller.rb0000644000175000017500000000101712121046025023375 0ustar lunarlunarclass SlimController < ApplicationController def normal end def no_layout render :layout => false end def variables @hello = "Hello Slim with variables!" end def partial end def streaming @hello = "Hello Streaming!" render :content_for, :stream => true end def integers @integer = 1337 end def thread_options Slim::Engine.with_options(:shortcut => {'@' => { :attr => params[:attr] }}) do render end end def content_for @hello = "Hello Slim!" end end slim-2.0.0.pre.6/test/rails/app/controllers/parents_controller.rb0000644000175000017500000000376612121046025024122 0ustar lunarlunarclass ParentsController < ApplicationController # GET /parents # GET /parents.xml def index @parents = Parent.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @parents } end end # GET /parents/1 # GET /parents/1.xml def show @parent = Parent.find(params[:id]) respond_to do |format| format.html # show.html.erb format.xml { render :xml => @parent } end end # GET /parents/new # GET /parents/new.xml def new @parent = Parent.new @parent.children.build respond_to do |format| format.html # new.html.erb format.xml { render :xml => @parent } end end # GET /parents/1/edit def edit @parent = Parent.find(params[:id]) end # POST /parents # POST /parents.xml def create params.permit! if params.respond_to? :permit! @parent = Parent.new(params[:parent]) respond_to do |format| if @parent.save format.html { redirect_to(@parent, :notice => 'Parent was successfully created.') } format.xml { render :xml => @parent, :status => :created, :location => @parent } else format.html { render :action => "new" } format.xml { render :xml => @parent.errors, :status => :unprocessable_entity } end end end # PUT /parents/1 # PUT /parents/1.xml def update @parent = Parent.find(params[:id]) respond_to do |format| if @parent.update_attributes(params[:parent]) format.html { redirect_to(@parent, :notice => 'Parent was successfully updated.') } format.xml { head :ok } else format.html { render :action => "edit" } format.xml { render :xml => @parent.errors, :status => :unprocessable_entity } end end end # DELETE /parents/1 # DELETE /parents/1.xml def destroy @parent = Parent.find(params[:id]) @parent.destroy respond_to do |format| format.html { redirect_to(parents_url) } format.xml { head :ok } end end end slim-2.0.0.pre.6/test/rails/app/controllers/application_controller.rb0000644000175000017500000000012012121046025024726 0ustar lunarlunarclass ApplicationController < ActionController::Base protect_from_forgery end slim-2.0.0.pre.6/test/rails/Rakefile0000644000175000017500000000041112121046025016155 0ustar lunarlunar# Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. require File.expand_path('../config/application', __FILE__) require 'rake' Dummy::Application.load_tasks slim-2.0.0.pre.6/test/logic_less/0000755000175000017500000000000012121046025015525 5ustar lunarlunarslim-2.0.0.pre.6/test/logic_less/test_logic_less.rb0000644000175000017500000001352112121046025021236 0ustar lunarlunarrequire 'helper' require 'slim/logic_less' class TestSlimLogicLess < TestSlim class Scope def initialize @hash = { :person => [ { :name => 'Joe', :age => 1, :selected => true }, { :name => 'Jack', :age => 2 } ] } end end def test_lambda source = %q{ p == person .name = name == simple .hello= hello == list li = key } hash = { :hello => 'Hello!', :person => lambda do |&block| %w(Joe Jack).map do |name| "#{block.call(:name => name)}" end.join end, :simple => lambda do |&block| "
#{block.call}
" end, :list => lambda do |&block| list = [{:key => 'First'}, {:key => 'Second'}] "" end } assert_html '

Joe
Jack
Hello!

', source, :scope => hash end def test_symbol_hash source = %q{ p - person .name = name } hash = { :person => [ { :name => 'Joe', }, { :name => 'Jack', } ] } assert_html '

Joe
Jack

', source, :scope => hash end def test_string_access source = %q{ p - person .name = name } hash = { 'person' => [ { 'name' => 'Joe', }, { 'name' => 'Jack', } ] } assert_html '

Joe
Jack

', source, :scope => hash, :dictionary_access => :string end def test_symbol_access source = %q{ p - person .name = name } hash = { :person => [ { :name => 'Joe', }, { :name => 'Jack', } ] } assert_html '

Joe
Jack

', source, :scope => hash, :dictionary_access => :symbol end def test_method_access source = %q{ p - person .name = name } object = Object.new def object.person %w(Joe Jack).map do |name| person = Object.new person.instance_variable_set(:@name, name) def person.name @name end person end end assert_html '

Joe
Jack

', source, :scope => object, :dictionary_access => :method end def test_instance_variable_access source = %q{ p - person .name = name } object = Object.new object.instance_variable_set(:@person, %w(Joe Jack).map do |name| person = Object.new person.instance_variable_set(:@name, name) person end) assert_html '

Joe
Jack

', source, :scope => object, :dictionary_access => :instance_variable end def test_string_hash source = %q{ p - person .name = name } hash = { 'person' => [ { 'name' => 'Joe', }, { 'name' => 'Jack', } ] } assert_html '

Joe
Jack

', source, :scope => hash end def test_dictionary_option source = %q{ p - person .name = name } assert_html '

Joe
Jack

', source, :scope => Scope.new, :dictionary => '@hash' end def test_flag_section source = %q{ p - show_person - person .name = name - show_person | shown } hash = { :show_person => true, :person => [ { :name => 'Joe', }, { :name => 'Jack', } ] } assert_html '

Joe
Jack
shown

', source, :scope => hash end def test_inverted_section source = %q{ p - person .name = name -! person | No person - !person | No person 2 } hash = {} assert_html '

No person No person 2

', source, :scope => hash end def test_escaped_interpolation source = %q{ p text with \#{123} test } assert_html '

text with #{123} test

', source end def test_ruby_attributes source = %q{ p - person b name=name Person a id=name = age span class=name Person } assert_html '

Person1Person2

', source, :scope => Scope.new, :dictionary => '@hash' end def test_boolean_attributes source = %q{ p - person input checked=selected = name } assert_html '

JoeJack

', source, :scope => Scope.new, :dictionary => '@hash' end def test_sections source = %q{ p - person .name = name } assert_html '

Joe
Jack

', source, :dictionary => 'ViewEnv.new' end def test_with_array source = %q{ ul - people_with_locations li = name li = city } assert_html '', source, :dictionary => 'ViewEnv.new' end def test_method source = %q{ a href=output_number Link } assert_html 'Link', source, :dictionary => 'ViewEnv.new' end def test_conditional_parent source = %q{ - prev_page li.previous a href=prev_page Older - next_page li.next a href=next_page Newer} assert_html'', source, :scope => {:prev_page => 'prev', :next_page => 'next'} end def test_render_with_yield source = %q{ div == yield } assert_html '
This is the menu
', source do 'This is the menu' end end end slim-2.0.0.pre.6/test/literate/0000755000175000017500000000000012121046025015213 5ustar lunarlunarslim-2.0.0.pre.6/test/literate/run.rb0000644000175000017500000000462412121046025016352 0ustar lunarlunarrequire 'temple' class LiterateTest < Temple::Engine class Parser < Temple::Parser def call(lines) stack = [[:multi]] until lines.empty? case lines.shift when /\A(#+)\s*(.*)\Z/ stack.pop(stack.size - $1.size) block = [:multi] stack.last << [:section, $2, block] stack << block when /\A~{3,}\s*(\w+)\s*\Z/ lang = $1 code = [] until lines.empty? case lines.shift when /\A~{3,}\s*\Z/ break when /\A.*\Z/ code << $& end end stack.last << [lang.to_sym, code.join("\n")] when /\A\s*\Z/ when /\A\s*(.*?)\s*Z/ stack.last << [:comment, $1] end end stack.first end end class Compiler < Temple::Filter def call(exp) @opts, @in_testcase = {}, false "require 'helper'\n\n#{compile(exp)}" end def on_section(title, body) old_opts = @opts.dup raise Temple::FilterError, 'New section between slim and html block' if @in_testcase "describe #{title.inspect} do\n #{compile(body).gsub("\n", "\n ")}\nend\n" ensure @opts = old_opts end def on_multi(*exps) exps.map {|exp| compile(exp) }.join("\n") end def on_comment(text) "#{@in_testcase ? ' ' : ''}# #{text}" end def on_slim(code) raise Temple::FilterError, 'Slim block must be followed by html block' if @in_testcase @in_testcase = true "it 'should render' do\n slim = #{code.inspect}" end def on_html(code) raise Temple::FilterError, 'Html block must be preceded by slim block' unless @in_testcase @in_testcase = false result = " html = #{code.inspect}\n" if @opts.empty? result << " render(slim).must_equal html\nend\n" else result << " options = #{@opts.inspect}\n render(slim, options).must_equal html\nend\n" end end def on_options(code) raise Temple::FilterError, 'Options set inside test case' if @in_testcase @opts.update(eval("{#{code}}")) "# #{code.gsub("\n", "\n# ")}" end def on(*exp) raise Temple::InvalidExpression, exp end end use Parser use Compiler use(:Evaluator) {|code| eval(code) } end Dir.glob(File.join(File.dirname(__FILE__), '*.md')) do |file| LiterateTest.new.call(File.readlines(file)) end slim-2.0.0.pre.6/test/literate/helper.rb0000644000175000017500000000072512121046025017023 0ustar lunarlunarrequire 'slim' require 'slim/logic_less' require 'slim/translator' require 'slim/grammar' require 'minitest/autorun' Slim::Engine.after Slim::Parser, Temple::Filters::Validator, :grammar => Slim::Grammar Slim::Engine.before :Pretty, Temple::Filters::Validator Slim::Engine.set_default_options :tr => false, :logic_less => false class MiniTest::Spec def render(source, options = {}, &block) Slim::Template.new(options) { source }.render(self, &block) end end slim-2.0.0.pre.6/test/literate/TESTS.md0000644000175000017500000003523412121046025016446 0ustar lunarlunar# Slim test suite You can run this testsuite with `rake test:literate`. We use pretty mode in the test suite to make the output more readable. Pretty mode is enabled by setting the option ~~~ options :pretty => true ~~~ ## Line indicators In this section we test all line indicators. ### Text `|` A text blocks starts with the `|` as line indicator. ~~~ slim | Text block ~~~ renders as ~~~ html Text block ~~~ Multiple lines can be indented beneath the first text line. ~~~ slim | Text block with multiple lines ~~~ renders as ~~~ html Text block with multiple lines ~~~ The first line of a text block determines the indentation. ~~~ slim | Text block with multiple lines ~~~ renders as ~~~ html Text block with multiple lines ~~~ You can nest text blocks beneath tags. ~~~ slim body | Text ~~~ renders as ~~~ html Text ~~~ You can embed html code in the text which is not escaped. ~~~ slim | slim-lang.com ~~~ renders as ~~~ html slim-lang.com ~~~ ### Text with trailing white space `'` A text blocks with trailing white space starts with the `'` as line indicator. ~~~ slim ' Text block ~~~ renders as ~~~ html Text block ~~~ This is especially useful if you use tags behind a text block. ~~~ slim ' Link to a href="http://slim-lang.com" slim-lang.com ~~~ renders as ~~~ html Link to slim-lang.com ~~~ Multiple lines can be indented beneath the first text line. ~~~ slim ' Text block with multiple lines ~~~ renders as ~~~ html Text block with multiple lines ~~~ The first line of a text block determines the indentation. ~~~ slim ' Text block with multiple lines ~~~ renders as ~~~ html Text block with multiple lines ~~~ ### Inline HTML `<` HTML can be written directly. ~~~ slim slim-lang.com ~~~ renders as ~~~ html slim-lang.com ~~~ HTML tags allow nested blocks inside. ~~~ slim title Example body - if true | yes - else | no ~~~ renders as ~~~ html Example yes ~~~ ### Control code `-` The dash `-` denotes arbitrary control code. ~~~ slim - greeting = 'Hello, World!' - if false | Not true - else = greeting ~~~ renders as ~~~ html Hello, World! ~~~ Complex code can be broken with backslash `\`. ~~~ slim - greeting = 'Hello, '+\ \ 'World!' - if false | Not true - else = greeting ~~~ renders as ~~~ html Hello, World! ~~~ ### Output `=` The equal sign `=` produces dynamic output. ~~~ slim = 7*7 ~~~ renders as ~~~ html 49 ~~~ Dynamic output is escaped by default. ~~~ slim = '' ~~~ renders as ~~~ html <script>evil();</script> ~~~ Long code lines can be broken with `\`. ~~~ slim = (0..10).map do |i|\ 2**i \ end.join(', ') ~~~ renders as ~~~ html 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ~~~ You don't need the explicit `\` if the line ends with a comma `,`. ~~~ slim ruby: def test(*args) args.join('-') end = test('arg1', 'arg2', 'arg3') ~~~ renders as ~~~ html arg1-arg2-arg3 ~~~ You can also disable HTML escaping globally by setting the option ~~~ options :disable_escape => true ~~~ ~~~ slim = '' ~~~ renders as ~~~ html ~~~ ### Output with trailing white space `='` The equal sign with apostrophe `='` produces dynamic output with a trailing white space. ~~~ slim =' 7*7 ~~~ renders as ~~~ html 49 ~~~ ### Output without HTML escaping `==` The double equal sign `==` produces dynamic output without HTML escaping. ~~~ slim == '' ~~~ renders as ~~~ html ~~~ The option option ~~~ options :disable_escape => true ~~~ doesn't affect the output of `==`. ~~~ slim == '' ~~~ renders as ~~~ html ~~~ ### Output without HTML escaping and trailing ws `=='` The double equal sign with apostrophe `=='` produces dynamic output without HTML escaping and trailing white space. ~~~ slim ==' '' ~~~ renders as ~~~ html ~~~ The option option ~~~ options :disable_escape => true ~~~ doesn't affect the output of `==`. ~~~ slim ==' '' ~~~ renders as ~~~ html ~~~ ### Code comment `/` Code comments begin with `/` and produce no output. ~~~ slim / Comment body / Another comment with multiple lines p Hello! ~~~ renders as ~~~ html

Hello!

~~~ ### HTML comment `/!` Code comments begin with `/!`. ~~~ slim /! Comment body /! Another comment with multiple lines p Hello! /! First line determines indentation of the comment ~~~ renders as ~~~ html

Hello!

~~~ ### IE conditional comment `/[...]` ~~~ slim /[if IE] p Get a better browser. ~~~ renders as ~~~ html ~~~ ## HTML tags ### Doctype tags The doctype tag is a special tag which can be used to generate the complex doctypes in a very simple way. You can output the XML version using the doctype tag. ~~~ slim doctype xml doctype xml ISO-8859-1 ~~~ renders as ~~~ html ~~~ In XHTML mode the following doctypes are supported: ~~~ slim doctype html doctype 5 doctype 1.1 doctype strict doctype frameset doctype mobile doctype basic doctype transitional ~~~ renders as ~~~ html ~~~ If we activate HTML mode with the option ~~~ options :format => :html ~~~ the following doctypes are supported: ~~~ slim doctype html doctype 5 doctype strict doctype frameset doctype transitional ~~~ renders as ~~~ html ~~~ ### Closed tags You can close tags explicitly by appending a trailing `/`. ~~~ slim div id="not-closed" .closed/ #closed/ div id="closed"/ ~~~ renders as ~~~ html
~~~ Note, that this is usually not necessary since the standard html tags (img, br, ...) are closed automatically. ~~~ slim img src="image.png" ~~~ renders as ~~~ html ~~~ ### Inline tags Sometimes you may want to be a little more compact and inline the tags. ~~~ slim ul li.first: a href="/first" First li: a href="/second" Second ~~~ renders as ~~~ html ~~~ For readability, don't forget you can wrap the attributes. ~~~ slim ul li.first: a(href="/first") First li: a(href="/second") Second ~~~ renders as ~~~ html ~~~ ### Text content ### Dynamic content `=` ### Attributes #### Attribute wrapper If a delimiter makes the syntax more readable for you, you can use the characters `{...}`, `(...)`, `[...]` to wrap the attributes. ~~~ slim li a(href="http://slim-lang.com" class="important") Link li a[href="http://slim-lang.com" class="important"] Link li a{href="http://slim-lang.com" class="important"} Link ~~~ renders as ~~~ html
  • Link
  • Link
  • Link
  • ~~~ If you wrap the attributes, you can spread them across multiple lines: ~~~ slim a(href="http://slim-lang.com" class="important") Link ~~~ renders as ~~~ html Link ~~~ ~~~ slim dl( itemprop='address' itemscope itemtype='http://schema.org/PostalAddress' ) ~~~ renders as ~~~ html
    ~~~ You may use spaces around the wrappers and assignments: ~~~ slim h1 id = "logo" Logo h2 [ id = "tagline" ] Tagline ~~~ renders as ~~~ html

    Logo

    Tagline

    ~~~ #### Quoted attributes You can use single or double quotes for simple text attributes. ~~~ slim a href="http://slim-lang.com" title='Slim Homepage' Goto the Slim homepage ~~~ renders as ~~~ html Goto the Slim homepage ~~~ You can use text interpolation in the quoted attributes: ~~~ slim - url='slim-lang.com' a href="http://#{url}" Goto the #{url} ~~~ renders as ~~~ html Goto the slim-lang.com ~~~ The attribute value will be escaped by default. Use == if you want to disable escaping in the attribute. ~~~ slim li a href='&' Link li a href=="&" Link ~~~ renders as ~~~ html
  • Link
  • Link
  • ~~~ You can break quoted attributes with backslash `\` ~~~ slim a data-title="help" data-content="extremely long help text that goes on\ and one and one and then starts over...." Link ~~~ renders as ~~~ html Link ~~~ #### Ruby attributes Long ruby attributes can be broken with backslash `\` ~~~ slim a href=1+\ 1 Link ~~~ renders as ~~~ html Link ~~~ You don't need the explicit `\` if the line ends with a comma `,`. ~~~ slim ruby: def test(*args) args.join('-') end a href=test('arg1', 'arg2', 'arg3') Link ~~~ renders as ~~~ html Link ~~~ #### Boolean attributes The attribute values `true`, `false` and `nil` are interpreted as booleans. If you use the attribut wrapper you can omit the attribute assigment. ~~~ slim - true_value1 = "" - true_value2 = true input type="text" disabled=true_value1 input type="text" disabled=true_value2 input type="text" disabled="disabled" input type="text" disabled=true input(type="text" disabled) ~~~ renders as ~~~ html ~~~ ~~~ slim - false_value1 = false - false_value2 = nil input type="text" disabled=false_value1 input type="text" disabled=false_value2 input type="text" input type="text" disabled=false input type="text" disabled=nil ~~~ renders as ~~~ html ~~~ #### Attribute merging You can configure attributes to be merged if multiple are given (See option `:merge_attrs`). In the default configuration this is done for class attributes with the white space as delimiter. ~~~ slim a.menu class="highlight" href="http://slim-lang.com/" Slim-lang.com ~~~ renders as ~~~ html Slim-lang.com ~~~ You can also use an `Array` as attribute value and the array elements will be merged using the delimiter. ~~~ slim - classes = [:alpha, :beta] span class=["first","highlight"] class=classes First span class=:second,:highlight class=classes Second ~~~ renders as ~~~ html FirstSecond ~~~ #### Splat attributes `*` #### Dynamic tags `*` You can create completely dynamic tags using the splat attributes. Just create a method which returns a hash with the :tag key. ~~~ slim ruby: def a_unless_current @page_current ? {:tag => 'span'} : {:tag => 'a', :href => 'http://slim-lang.com/'} end - @page_current = true *a_unless_current Link - @page_current = false *a_unless_current Link ~~~ renders as ~~~ html LinkLink ~~~ ### Shortcuts #### Tag shortcuts We add tag shortcuts by setting the option `:shortcut`. ~~~ options :shortcut => {'c' => {:tag => 'container'}, 'sec' => {:tag =>'section'}, '#' => {:attr => 'id'}, '.' => {:attr => 'class'} } ~~~ ~~~ slim sec: c.content Text ~~~ renders to ~~~ html
    Text
    ~~~ #### Attribute shortcuts We add `&` to create a shortcut for the input elements with type attribute by setting the option `:shortcut`. ~~~ options :shortcut => {'&' => {:tag => 'input', :attr => 'type'}, '#' => {:attr => 'id'}, '.' => {:attr => 'class'} } ~~~ ~~~ slim &text name="user" &password name="pw" &submit.CLASS#ID ~~~ renders to ~~~ html ~~~ This is stupid, but you can also use multiple character shortcuts. ~~~ options :shortcut => {'&' => {:tag => 'input', :attr => 'type'}, '#<' => {:attr => 'id'}, '#>' => {:attr => 'class'} } ~~~ ~~~ slim &text name="user" &password name="pw" &submit#>CLASS# ~~~ #### ID shortcut and class shortcut `.` ## Text interpolation Use standard Ruby interpolation. The text will be html escaped by default. ~~~ slim - user="John Doe " h1 Welcome #{user}! ~~~ renders as ~~~ html

    Welcome John Doe <john@doe.net>!

    ~~~ ## Embedded engines ## Configuring Slim ## Plugins ### Logic less mode ### Translator slim-2.0.0.pre.6/test/core/0000755000175000017500000000000012121046025014332 5ustar lunarlunarslim-2.0.0.pre.6/test/core/test_unicode.rb0000644000175000017500000000072612121046025017351 0ustar lunarlunar# -*- coding: utf-8 -*- if ''.respond_to?(:encoding) require 'helper' class TestSlimUnicode < TestSlim def test_unicode_tags source = "Статья года" result = "<Статья>года" assert_html result, source end def test_unicode_attrs source = "Статья года=123 content" result = "<Статья года=\"123\">content" assert_html result, source end end end slim-2.0.0.pre.6/test/core/test_thread_options.rb0000644000175000017500000000101712121046025020737 0ustar lunarlunarrequire 'helper' class TestSlimThreadOptions < TestSlim def test_thread_options source = %q{p.test} assert_html '

    ', source assert_html "

    ", source, :attr_quote => "'" Slim::Engine.with_options(:attr_quote => "'") do assert_html "

    ", source assert_html '

    ', source, :attr_quote => '"' end assert_html '

    ', source assert_html "

    ", source, :attr_quote => "'" end end slim-2.0.0.pre.6/test/core/test_text_interpolation.rb0000644000175000017500000000320112121046025021645 0ustar lunarlunarrequire 'helper' class TestSlimTextInterpolation < TestSlim def test_interpolation_in_attribute source = %q{ p id="a#{id_helper}b" = hello_world } assert_html '

    Hello World from @env

    ', source end def test_nested_interpolation_in_attribute source = %q{ p id="#{"abc#{1+1}" + "("}" = hello_world } assert_html '

    Hello World from @env

    ', source end def test_interpolation_in_text source = %q{ p | #{hello_world} with "quotes" p | A message from the compiler: #{hello_world} } assert_html '

    Hello World from @env with "quotes"

    A message from the compiler: Hello World from @env

    ', source end def test_interpolation_in_tag source = %q{ p #{hello_world} } assert_html '

    Hello World from @env

    ', source end def test_escape_interpolation source = %q{ p \\#{hello_world} p text1 \\#{hello_world} text2 } assert_html '

    #{hello_world}

    text1 #{hello_world} text2

    ', source end def test_complex_interpolation source = %q{ p Message: #{message('hello', "user #{output_number}")} } assert_html '

    Message: hello user 1337

    ', source end def test_interpolation_with_escaping source = %q{ | #{evil_method} } assert_html '<script>do_something_evil();</script>', source end def test_interpolation_without_escaping source = %q{ | #{{evil_method}} } assert_html '', source end def test_interpolation_with_escaping_and_delimiter source = %q{ | #{(evil_method)} } assert_html '<script>do_something_evil();</script>', source end end slim-2.0.0.pre.6/test/core/test_tabs.rb0000644000175000017500000000311012121046025016642 0ustar lunarlunarrequire 'helper' class TestSlimTabs < TestSlim def teardown Slim::Engine.set_default_options :tabsize => 4 end def test_single_tab1_expansion Slim::Engine.set_default_options :tabsize => 1 source = %Q{ | \t0 \t1 \t2 \t3 \t4 \t5 \t6 \t7 \t8 } result = %q{ 0 1 2 3 4 5 6 7 8 }.strip assert_html result, source end def test_single_tab4_expansion Slim::Engine.set_default_options :tabsize => 4 source = %Q{ | \t0 \t1 \t2 \t3 \t4 \t5 \t6 \t7 \t8 } result = %q{ 0 1 2 3 4 5 6 7 8 }.strip assert_html result, source end def test_multi_tab1_expansion Slim::Engine.set_default_options :tabsize => 1 source = %Q{ | \t0 \t\t1 \t \t2 \t \t3 \t \t4 \t\t1 \t \t2 \t \t3 \t \t4 \t\t1 \t \t2 \t \t3 \t \t4 \t\t1 \t \t2 \t \t3 \t \t4 } result = %q{ 0 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 }.strip assert_html result, source end def test_multi_tab4_expansion Slim::Engine.set_default_options :tabsize => 4 source = %Q{ | \t0 \t\t1 \t \t2 \t \t3 \t \t4 \t\t1 \t \t2 \t \t3 \t \t4 \t\t1 \t \t2 \t \t3 \t \t4 \t\t1 \t \t2 \t \t3 \t \t4 } result = %q{ 0 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 }.strip assert_html result, source end end slim-2.0.0.pre.6/test/core/test_slim_template.rb0000644000175000017500000000412512121046025020557 0ustar lunarlunarrequire 'helper' class ::MockError < NameError end class TestSlimTemplate < TestSlim def test_default_mime_type assert_equal 'text/html', Slim::Template.default_mime_type end def test_registered_extension assert_equal Slim::Template, Tilt['test.slim'] end def test_preparing_and_evaluating template = Slim::Template.new { |t| "p Hello World!\n" } assert_equal "

    Hello World!

    ", template.render end def test_evaluating_in_an_object_scope template = Slim::Template.new { "p = 'Hey ' + @name + '!'\n" } scope = Object.new scope.instance_variable_set :@name, 'Joe' assert_equal "

    Hey Joe!

    ", template.render(scope) end def test_passing_a_block_for_yield template = Slim::Template.new { "p = 'Hey ' + yield + '!'\n" } assert_equal "

    Hey Joe!

    ", template.render { 'Joe' } end def test_backtrace_file_and_line_reporting_without_locals data = File.read(__FILE__).split("\n__END__\n").last fail unless data[0] == ?h template = Slim::Template.new('test.slim', 10) { data } begin template.render fail 'should have raised an exception' rescue => ex assert_kind_of NameError, ex assert_backtrace(ex, 'test.slim:12') end end def test_backtrace_file_and_line_reporting_with_locals data = File.read(__FILE__).split("\n__END__\n").last fail unless data[0] == ?h template = Slim::Template.new('test.slim') { data } begin res = template.render(Object.new, :name => 'Joe', :foo => 'bar') rescue => ex assert_kind_of MockError, ex assert_backtrace(ex, 'test.slim:5') end end def test_compiling_template_source_to_a_method template = Slim::Template.new { |t| "Hello World!" } template.render method = template.send(:compiled_method, []) assert_kind_of UnboundMethod, method end def test_passing_locals template = Slim::Template.new { "p = 'Hey ' + name + '!'\n" } assert_equal "

    Hey Joe!

    ", template.render(Object.new, :name => 'Joe') end end __END__ html body h1 = "Hey #{name}" = raise MockError p we never get here slim-2.0.0.pre.6/test/core/test_ruby_errors.rb0000644000175000017500000000747712121046025020312 0ustar lunarlunarrequire 'helper' class TestSlimRubyErrors < TestSlim def test_multline_attribute source = %q{ p(data-1=1 data2-=1) p = unknown_ruby_method } assert_ruby_error NameError, "test.slim:5", source, :file => 'test.slim' end def test_broken_output_line source = %q{ p = hello_world + \ hello_world + \ unknown_ruby_method } # FIXME: Remove this hack! # This is actually a jruby issue. Jruby reports a wrong # line number 1 in this case: # # test = 1+\ # unknown_variable if RUBY_PLATFORM == "java" assert_ruby_error NameError, "test.slim:2", source, :file => 'test.slim' else assert_ruby_error NameError, "test.slim:4", source, :file => 'test.slim' end end def test_broken_output_line2 source = %q{ p = hello_world + \ hello_world p Hello = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):5", source end def test_output_block source = %q{ p = hello_world "Hello Ruby" do = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):3", source end def test_output_block2 source = %q{ p = hello_world "Hello Ruby" do = "Hello from block" p Hello = unknown_ruby_method } assert_ruby_error NameError, "(__TEMPLATE__):5", source end def test_text_block source = %q{ p Text line 1 Text line 2 = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):4", source end def test_text_block2 source = %q{ | Text line 1 Text line 2 = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):5", source end def test_comment source = %q{ / Comment line 1 Comment line 2 = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):4", source end def test_embedded_erb source = %q{ erb: <%= 123 %> Hello from ERB! <%# comment block %> <% if true %> Text <% end %> = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):11", source end def test_embedded_ruby1 source = %q{ ruby: a = 1 b = 2 = a + b = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):6", source end def test_embedded_ruby2 source = %q{ ruby: a = 1 unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):4", source end def test_embedded_markdown source = %q{ markdown: #Header Hello from #{"Markdown!"} "Second Line!" = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):6", source end def test_embedded_javascript source = %q{ javascript: alert(); alert(); = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):5", source end def test_invalid_nested_code source = %q{ p - test = 123 = "Hello from within a block! " } assert_ruby_syntax_error "(__TEMPLATE__):5", source end def test_invalid_nested_output source = %q{ p = "Hello Ruby!" = "Hello from within a block! " } assert_ruby_syntax_error "(__TEMPLATE__):5", source end def test_invalid_embedded_engine source = %q{ p embed_unknown: 1+1 } assert_runtime_error 'Embedded engine embed_unknown not found', source end def test_explicit_end source = %q{ div - if show_first? p The first paragraph - end } assert_runtime_error 'Explicit end statements are forbidden', source end def test_multiple_id_attribute source = %{ #alpha id="beta" Test it } assert_runtime_error 'Multiple id attributes specified', source end def test_splat_multiple_id_attribute source = %{ #alpha *{:id =>"beta"} Test it } assert_runtime_error 'Multiple id attributes specified', source end # def test_invalid_option # render('', :foobar => 42) # raise Exception, 'ArgumentError expected' # rescue ArgumentError => ex # assert_equal 'Option :foobar is not supported by Slim::Engine', ex.message # end end slim-2.0.0.pre.6/test/core/test_pretty.rb0000644000175000017500000000421712121046025017251 0ustar lunarlunarrequire 'helper' class TestSlimPretty < TestSlim def setup Slim::Engine.set_default_options :pretty => true end def teardown Slim::Engine.set_default_options :pretty => false end def test_pretty source = %q{ doctype 5 html head title Hello World! /! Meta tags with long explanatory multiline comment meta name="description" content="template language" /! Stylesheets link href="style.css" media="screen" rel="stylesheet" type="text/css" link href="colors.css" media="screen" rel="stylesheet" type="text/css" /! Javascripts script src="jquery.js" script src="jquery.ui.js" /[if lt IE 9] script src="old-ie1.js" script src="old-ie2.js" sass: body background-color: red body #container p Hello World! p= "dynamic text with\nnewline" } result = %q{ Hello World!

    Hello World!

    dynamic text with newline

    } assert_html result, source end def test_partials body = %q{body == render content} content = %q{div | content} source = %q{html == render body, :scope => self, :locals => { :content => content }} result = %q{
    content
    } assert_html result, source, :scope => self, :locals => {:body => body, :content => content } end end slim-2.0.0.pre.6/test/core/test_parser_errors.rb0000644000175000017500000000771012121046025020613 0ustar lunarlunarrequire 'helper' class TestParserErrors < TestSlim def test_correct_filename source = %q{ doctype 5 div Invalid } assert_syntax_error "Unexpected indentation\n test.slim, Line 3, Column 2\n div Invalid\n ^\n", source, :file => 'test.slim' end def test_unexpected_indentation source = %q{ doctype 5 div Invalid } assert_syntax_error "Unexpected indentation\n (__TEMPLATE__), Line 3, Column 2\n div Invalid\n ^\n", source end def test_unexpected_text_indentation source = %q{ p | text block text } assert_syntax_error "Text line not indented deep enough.\nThe first text line defines the necessary text indentation.\n (__TEMPLATE__), Line 4, Column 3\n text\n ^\n", source end def test_unexpected_text_indentation_in_tag source = %q{ ul li List1 ul li a li b li List2 ul li a li b } assert_syntax_error "Text line not indented deep enough.\nThe first text line defines the necessary text indentation.\nAre you trying to nest a child tag in a tag containing text? Use | for the text block!\n (__TEMPLATE__), Line 4, Column 4\n ul\n ^\n", source end def test_malformed_indentation source = %q{ p div Valid div Invalid } assert_syntax_error "Malformed indentation\n (__TEMPLATE__), Line 4, Column 1\n div Invalid\n ^\n", source end def test_unknown_line_indicator source = %q{ p div Valid .valid #valid ?invalid } assert_syntax_error "Unknown line indicator\n (__TEMPLATE__), Line 6, Column 2\n ?invalid\n ^\n", source end def test_expected_closing_delimiter source = %q{ p img(src="img.jpg" title={title} } assert_syntax_error "Expected closing delimiter )\n (__TEMPLATE__), Line 3, Column 33\n img(src=\"img.jpg\" title={title}\n ^\n", source end def test_expected_closing_quote source = %q{ p img(src="img.jpg } assert_syntax_error "Expected closing quote \"\n (__TEMPLATE__), Line 3, Column 18\n img(src=\"img.jpg\n ^\n", source end def test_expected_closing_attribute_delimiter source = %q{ p img src=[hash[1] + hash[2] } assert_syntax_error "Expected closing delimiter ]\n (__TEMPLATE__), Line 3, Column 28\n img src=[hash[1] + hash[2]\n ^\n", source end def test_expected_attribute source = %q{ p img(src='img.png' whatsthis?!) } assert_syntax_error "Expected attribute\n (__TEMPLATE__), Line 3, Column 20\n img(src='img.png' whatsthis?!)\n ^\n", source end def test_invalid_empty_attribute source = %q{ p img{src= } } assert_syntax_error "Invalid empty attribute\n (__TEMPLATE__), Line 3, Column 11\n img{src= }\n ^\n", source end def test_invalid_empty_attribute2 source = %q{ p img{src=} } assert_syntax_error "Invalid empty attribute\n (__TEMPLATE__), Line 3, Column 10\n img{src=}\n ^\n", source end def test_invalid_empty_attribute3 source = %q{ p img src= } assert_syntax_error "Invalid empty attribute\n (__TEMPLATE__), Line 3, Column 10\n img src=\n ^\n", source end def test_missing_tag_in_block_expansion source = %{ html: body: } assert_syntax_error "Expected tag\n (__TEMPLATE__), Line 2, Column 11\n html: body:\n ^\n", source end def test_invalid_tag_in_block_expansion source = %{ html: body: /comment } assert_syntax_error "Expected tag\n (__TEMPLATE__), Line 2, Column 12\n html: body: /comment\n ^\n", source source = %{ html: body:/comment } assert_syntax_error "Expected tag\n (__TEMPLATE__), Line 2, Column 11\n html: body:/comment\n ^\n", source end def test_unexpected_text_after_closed source = %{ img / text } assert_syntax_error "Unexpected text after closed tag\n (__TEMPLATE__), Line 2, Column 6\n img / text\n ^\n", source end end slim-2.0.0.pre.6/test/core/test_html_structure.rb0000644000175000017500000002724212121046025021011 0ustar lunarlunarrequire 'helper' class TestSlimHtmlStructure < TestSlim def test_simple_render # Keep the trailing space behind "body "! source = %q{ html head title Simple Test Title body p Hello World, meet Slim. } assert_html 'Simple Test Title

    Hello World, meet Slim.

    ', source end def test_html_tag_with_text_and_empty_line source = %q{ p Hello p World } assert_html "

    Hello

    World

    ", source end def test_html_namespaces source = %q{ html:body html:p html:id="test" Text } assert_html 'Text', source end def test_doctype source = %q{ doctype 1.1 html } assert_html '', source, :format => :xhtml end def test_doctype_new_syntax source = %q{ doctype 5 html } assert_html '', source, :format => :xhtml end def test_doctype_new_syntax_html5 source = %q{ doctype html html } assert_html '', source, :format => :xhtml end def test_render_with_shortcut_attributes source = %q{ h1#title This is my title #notice.hello.world = hello_world } assert_html '

    This is my title

    Hello World from @env
    ', source end def test_render_with_overwritten_default_tag source = %q{ #notice.hello.world = hello_world } assert_html '
    Hello World from @env
    ', source, :default_tag => 'section' end def test_render_with_custom_shortcut source = %q{ #notice.hello.world@test = hello_world @abc = hello_world } assert_html '
    Hello World from @env
    Hello World from @env
    ', source, :shortcut => {'#' => {:attr => 'id'}, '.' => {:attr => 'class'}, '@' => {:tag => 'section', :attr => 'role'}} end def test_render_with_text_block source = %q{ p | Lorem ipsum dolor sit amet, consectetur adipiscing elit. } assert_html '

    Lorem ipsum dolor sit amet, consectetur adipiscing elit.

    ', source end def test_render_with_text_block_with_subsequent_markup source = %q{ p | Lorem ipsum dolor sit amet, consectetur adipiscing elit. p Some more markup } assert_html '

    Lorem ipsum dolor sit amet, consectetur adipiscing elit.

    Some more markup

    ', source end def test_render_with_text_block_with_trailing_whitespace source = %q{ ' this is a link to a href="link" page } assert_html "this is\na link to page", source end def test_nested_text source = %q{ p | This is line one. This is line two. This is line three. This is line four. p This is a new paragraph. } assert_html "

    This is line one.\n This is line two.\n This is line three.\n This is line four.

    This is a new paragraph.

    ", source end def test_nested_text_with_nested_html_one_same_line source = %q{ p | This is line one. This is line two. span.bold This is a bold line in the paragraph. | This is more content. } assert_html "

    This is line one.\n This is line two.This is a bold line in the paragraph. This is more content.

    ", source end def test_nested_text_with_nested_html_one_same_line2 source = %q{ p |This is line one. This is line two. span.bold This is a bold line in the paragraph. | This is more content. } assert_html "

    This is line one.\n This is line two.This is a bold line in the paragraph. This is more content.

    ", source end def test_nested_text_with_nested_html source = %q{ p | This is line one. This is line two. This is line three. This is line four. span.bold This is a bold line in the paragraph. | This is more content. } assert_html "

    This is line one.\n This is line two.\n This is line three.\n This is line four.This is a bold line in the paragraph. This is more content.

    ", source end def test_simple_paragraph_with_padding source = %q{ p There will be 3 spaces in front of this line. } assert_html '

    There will be 3 spaces in front of this line.

    ', source end def test_paragraph_with_nested_text source = %q{ p This is line one. This is line two. } assert_html "

    This is line one.\n This is line two.

    ", source end def test_paragraph_with_padded_nested_text source = %q{ p This is line one. This is line two. } assert_html "

    This is line one.\n This is line two.

    ", source end def test_paragraph_with_attributes_and_nested_text source = %q{ p#test class="paragraph" This is line one. This is line two. } assert_html "

    This is line one.\nThis is line two.

    ", source end def test_output_code_with_leading_spaces source = %q{ p= hello_world p = hello_world p = hello_world } assert_html '

    Hello World from @env

    Hello World from @env

    Hello World from @env

    ', source end def test_single_quoted_attributes source = %q{ p class='underscored_class_name' = output_number } assert_html '

    1337

    ', source end def test_nonstandard_attributes source = %q{ p id="dashed-id" class="underscored_class_name" = output_number } assert_html '

    1337

    ', source end def test_nonstandard_shortcut_attributes source = %q{ p#dashed-id.underscored_class_name = output_number } assert_html '

    1337

    ', source end def test_dashed_attributes source = %q{ p data-info="Illudium Q-36" = output_number } assert_html '

    1337

    ', source end def test_dashed_attributes_with_shortcuts source = %q{ p#marvin.martian data-info="Illudium Q-36" = output_number } assert_html '

    1337

    ', source end def test_parens_around_attributes source = %q{ p(id="marvin" class="martian" data-info="Illudium Q-36") = output_number } assert_html '

    1337

    ', source end def test_square_brackets_around_attributes source = %q{ p[id="marvin" class="martian" data-info="Illudium Q-36"] = output_number } assert_html '

    1337

    ', source end def test_parens_around_attributes_with_equal_sign_snug_to_right_paren source = %q{ p(id="marvin" class="martian" data-info="Illudium Q-36")= output_number } assert_html '

    1337

    ', source end def test_closed_tag source = %q{ closed/ } assert_html '', source, :format => :xhtml end def test_attributs_with_parens_and_spaces source = %q{label{ for='filter' }= hello_world} assert_html '', source end def test_attributs_with_parens_and_spaces2 source = %q{label{ for='filter' } = hello_world} assert_html '', source end def test_attributs_with_multiple_spaces source = %q{label for='filter' class="test" = hello_world} assert_html '', source end def test_closed_tag_with_attributes source = %q{ closed id="test" / } assert_html '', source, :format => :xhtml end def test_closed_tag_with_attributes_and_parens source = %q{ closed(id="test")/ } assert_html '', source, :format => :xhtml end def test_render_with_html_comments source = %q{ p Hello /! This is a comment Another comment p World } assert_html "

    Hello

    World

    ", source end def test_render_with_html_conditional_and_tag source = %q{ /[ if IE ] p Get a better browser. } assert_html "", source end def test_render_with_html_conditional_and_method_output source = %q{ /[ if IE ] = message 'hello' } assert_html "", source end def test_multiline_attributes_with_method source = %q{ p = output_number } Slim::Parser::DELIMS.each do |k,v| str = source.sub('<',k).sub('>',v) assert_html '

    1337

    ', str end end def test_multiline_attributes_with_text_on_same_line source = %q{ p THE space modulator } Slim::Parser::DELIMS.each do |k,v| str = source.sub('<',k).sub('>',v) assert_html '

    THE space modulator

    ', str end end def test_multiline_attributes_with_nested_text source = %q{ p | THE space modulator } Slim::Parser::DELIMS.each do |k,v| str = source.sub('<',k).sub('>',v) assert_html '

    THE space modulator

    ', str end end def test_multiline_attributes_with_dynamic_attr source = %q{ p | THE space modulator } Slim::Parser::DELIMS.each do |k,v| str = source.sub('<',k).sub('>',v) assert_html '

    THE space modulator

    ', str end end def test_multiline_attributes_with_nested_tag source = %q{ p span.emphasis THE | space modulator } Slim::Parser::DELIMS.each do |k,v| str = source.sub('<',k).sub('>',v) assert_html '

    THE space modulator

    ', str end end def test_multiline_attributes_with_nested_text_and_extra_indentation source = %q{ li< id="myid" class="myclass" data-info="myinfo"> a href="link" My Link } Slim::Parser::DELIMS.each do |k,v| str = source.sub('<',k).sub('>',v) assert_html '
  • My Link
  • ', str end end def test_block_expansion_support source = %q{ ul li.first: a href='a' foo li: a href='b' bar li.last: a href='c' baz } assert_html %{}, source end def test_block_expansion_class_attributes source = %q{ .a: .b: #c d } assert_html %{
    d
    }, source end def test_block_expansion_nesting source = %q{ html: body: .content | Text } assert_html %{
    Text
    }, source end def test_eval_attributes_once source = %q{ input[value=succ_x] input[value=succ_x] } assert_html %{}, source end def test_html_line_indicator source = %q{ head meta name="keywords" content=hello_world - if true

    #{hello_world}

    span = hello_world } assert_html '

    Hello World from @env

    Hello World from @env', source end end slim-2.0.0.pre.6/test/core/test_html_escaping.rb0000644000175000017500000000245612121046025020542 0ustar lunarlunarrequire 'helper' class TestSlimHtmlEscaping < TestSlim def test_html_will_not_be_escaped source = %q{ p World, meet "Slim". } assert_html '

    World, meet "Slim".

    ', source end def test_html_with_newline_will_not_be_escaped source = %q{ p | World, meet "Slim". } assert_html "

    World,\n meet \"Slim\".

    ", source end def test_html_with_escaped_interpolation source = %q{ - x = '"' - content = '' p class="#{x}" test #{content} } assert_html '

    test <x>

    ', source end def test_html_nested_escaping source = %q{ = hello_world do | escaped & } assert_html 'Hello World from @env escaped & Hello World from @env', source end def test_html_quoted_attr_escape source = %q{ p id="&" class=="&" } assert_html '

    ', source end def test_html_quoted_attr_escape_with_interpolation source = %q{ p id="&#{'"'}" class=="&#{'"'}" p id="&#{{'"'}}" class=="&#{{'"'}}" } assert_html '

    ', source end def test_html_ruby_attr_escape source = %q{ p id=('&'.to_s) class==('&'.to_s) } assert_html '

    ', source end end slim-2.0.0.pre.6/test/core/test_html_attributes.rb0000644000175000017500000001374412121046025021141 0ustar lunarlunarrequire 'helper' class TestSlimHTMLAttributes < TestSlim def test_ternary_operation_in_attribute source = %q{ p id="#{(false ? 'notshown' : 'shown')}" = output_number } assert_html '

    1337

    ', source end def test_ternary_operation_in_attribute_2 source = %q{ p id=(false ? 'notshown' : 'shown') = output_number } assert_html '

    1337

    ', source end def test_class_attribute_merging source = %{ .alpha class="beta" Test it } assert_html '
    Test it
    ', source end def test_class_attribute_merging_with_nil source = %{ .alpha class="beta" class=nil class="gamma" Test it } assert_html '
    Test it
    ', source end def test_class_attribute_merging_with_empty_static source = %{ .alpha class="beta" class="" class="gamma" Test it } assert_html '
    Test it
    ', source end def test_id_attribute_merging source = %{ #alpha id="beta" Test it } assert_html '
    Test it
    ', source, :merge_attrs => {'class' => ' ', 'id' => '_' } end def test_id_attribute_merging2 source = %{ #alpha id="beta" Test it } assert_html '
    Test it
    ', source, :merge_attrs => {'class' => ' ', 'id' => '-' } end def test_boolean_attribute_false source = %{ - cond=false option selected=false Text option selected=cond Text2 } assert_html '', source end def test_boolean_attribute_true source = %{ - cond=true option selected=true Text option selected=cond Text2 } assert_html '', source end def test_boolean_attribute_nil source = %{ - cond=nil option selected=nil Text option selected=cond Text2 } assert_html '', source end def test_boolean_attribute_string2 source = %{ option selected="selected" Text } assert_html '', source end def test_boolean_attribute_shortcut source = %{ option(class="clazz" selected) Text option(selected class="clazz") Text } assert_html '', source end def test_array_attribute_merging source = %{ .alpha class="beta" class=[[""], :gamma, nil, :delta, [true, false]] .alpha class=:beta,:gamma } assert_html '
    ', source end def test_hyphenated_attribute source = %{ .alpha data={:a => 'alpha', :b => 'beta', :c_d => 'gamma', :c => {:e => 'epsilon'}} } assert_html '
    ', source end def test_shortcut_splat source = %q{ *hash This is my title } assert_html '
    This is my title
    ', source end def test_splat source = %q{ h1 *hash class=[] This is my title } assert_html '

    This is my title

    ', source end def test_closed_splat source = %q{ *hash / } assert_html '
    ', source end def test_splat_tag_name source = %q{ *{:tag => 'h1', :id => 'title'} This is my title } assert_html '

    This is my title

    ', source end def test_splat_empty_tag_name source = %q{ *{:tag => '', :id => 'test'} This is my title } assert_html '
    This is my title
    ', source end def test_closed_splat_tag source = %q{ *hash / } assert_html '
    ', source end def test_splat_with_id_shortcut source = %q{ #myid*hash This is my title } assert_html '
    This is my title
    ', source end def test_splat_with_class_shortcut source = %q{ .myclass*hash This is my title } assert_html '
    This is my title
    ', source end def test_splat_with_id_and_class_shortcuts source = %q{ #myid.myclass*hash This is my title } assert_html '
    This is my title
    ', source end def test_splat_with_class_merging source = %q{ #myid.myclass *{:class => [:secondclass, %w(x y z)]} *hash This is my title } assert_html '
    This is my title
    ', source end def test_splat_with_boolean_attribute source = %q{ *{:disabled => true, :empty1 => false, :nonempty => '', :empty2 => nil} This is my title } assert_html '
    This is my title
    ', source end def test_splat_merging_with_arrays source = %q{ *{:a => 1, :b => 2} *[[:c, 3], [:d, 4]] *[[:e, 5], [:f, 6]] This is my title } assert_html '
    This is my title
    ', source end def test_splat_with_other_attributes source = %q{ h1 data-id="123" *hash This is my title } assert_html '

    This is my title

    ', source end def test_attribute_merging source = %q{ a class=true class=false a class=false *{:class=>true} a class=true a class=false } assert_html '', source end def test_static_empty_attribute source = %q{ p(id="marvin" name="" class="" data-info="Illudium Q-36")= output_number } assert_html '

    1337

    ', source end def test_dynamic_empty_attribute source = %q{ p(id="marvin" class=nil nonempty=("".to_s) data-info="Illudium Q-36")= output_number } assert_html '

    1337

    ', source end end slim-2.0.0.pre.6/test/core/test_encoding.rb0000644000175000017500000000076012121046025017507 0ustar lunarlunarrequire 'helper' class TestSlimEncoding < TestSlim def test_windows_crlf source = "a href='#' something\r\nbr\r\na href='#' others\r\n" result = "something
    others" assert_html result, source end def test_binary source = "| \xFF\xFF" result = "\xFF\xFF" assert_html result, source end def test_bom source = "\xEF\xBB\xBFh1 Hello World!" result = '

    Hello World!

    ' assert_html result, source end end slim-2.0.0.pre.6/test/core/test_embedded_engines.rb0000644000175000017500000001231212121046025021156 0ustar lunarlunarrequire 'helper' class TestSlimEmbeddedEngines < TestSlim def test_render_with_erb source = %q{ p - text = 'before erb block' erb: Hello from <%= text.upcase %>! Second Line! <% if true %><%= true %><% end %> } assert_html "

    Hello from BEFORE ERB BLOCK!\nSecond Line!\ntrue

    ", source end def test_render_with_markdown source = %q{ markdown: #Header Hello from #{"Markdown!"} #{1+2} * one * two } assert_html "

    Header

    \n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n", source Slim::Embedded.with_options(:markdown => {:auto_ids => false}) do assert_html "

    Header

    \n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n", source end assert_html "

    Header

    \n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n", source end def test_render_with_creole source = %q{ creole: = head1 == head2 } assert_html "

    head1

    head2

    ", source end def test_render_with_builder source = %q{ builder: xml.p(:id => 'test') { xml.text!('Hello') } } assert_html "

    \nHello

    \n", source end def test_render_with_wiki source = %q{ wiki: = head1 == head2 } assert_html "

    head1

    head2

    ", source end def test_render_with_javascript # Keep the trailing space behind "javascript: "! source = %q{ javascript: $(function() {}); alert('hello') p Hi } assert_html %{

    Hi

    }, source end def test_render_with_javascript_with_tabs source = "javascript:\n\t$(function() {});\n\talert('hello')\np Hi" assert_html "

    Hi

    ", source end def test_render_with_javascript_including_variable # Keep the trailing space behind "javascript: "! source = %q{ - func = "alert('hello');" javascript: $(function() { #{func} }); } assert_html %q||, source end def test_render_with_javascript_with_explicit_html_comment Slim::Engine.with_options(:js_wrapper => :comment) do source = "javascript:\n\t$(function() {});\n\talert('hello')\np Hi" assert_html "

    Hi

    ", source end end def test_render_with_javascript_with_explicit_cdata_comment Slim::Engine.with_options(:js_wrapper => :cdata) do source = "javascript:\n\t$(function() {});\n\talert('hello')\np Hi" assert_html "

    Hi

    ", source end end def test_render_with_javascript_with_format_xhtml_comment Slim::Engine.with_options(:js_wrapper => :guess, :format => :xhtml) do source = "javascript:\n\t$(function() {});\n\talert('hello')\np Hi" assert_html "

    Hi

    ", source end end def test_render_with_javascript_with_format_html_comment Slim::Engine.with_options(:js_wrapper => :guess, :format => :html) do source = "javascript:\n\t$(function() {});\n\talert('hello')\np Hi" assert_html "

    Hi

    ", source end end def test_render_with_ruby source = %q{ ruby: variable = 1 + 2 = variable } assert_html '3', source end def test_render_with_scss source = %q{ scss: $color: #f00; body { color: $color; } } assert_html "", source end def test_disabled_embedded_engine source = %{ ruby: Embedded Ruby } assert_runtime_error 'Embedded engine ruby is disabled', source, :enable_engines => [:javascript] assert_runtime_error 'Embedded engine ruby is disabled', source, :enable_engines => %w(javascript) source = %{ ruby: Embedded Ruby } assert_runtime_error 'Embedded engine ruby is disabled', source, :enable_engines => [:javascript] assert_runtime_error 'Embedded engine ruby is disabled', source, :enable_engines => %w(javascript) source = %{ ruby: Embedded Ruby } assert_runtime_error 'Embedded engine ruby is disabled', source, :disable_engines => [:ruby] assert_runtime_error 'Embedded engine ruby is disabled', source, :disable_engines => %w(ruby) end def test_enabled_embedded_engine source = %q{ javascript: $(function() {}); } assert_html '', source, :disable_engines => [:ruby] assert_html '', source, :disable_engines => %w(ruby) source = %q{ javascript: $(function() {}); } assert_html '', source, :enable_engines => [:javascript] assert_html '', source, :enable_engines => %w(javascript) end end slim-2.0.0.pre.6/test/core/test_code_structure.rb0000644000175000017500000000345512121046025020757 0ustar lunarlunarrequire 'helper' class TestSlimCodeStructure < TestSlim def test_render_with_conditional source = %q{ div - if show_first? p The first paragraph - else p The second paragraph } assert_html '

    The second paragraph

    ', source end def test_render_with_consecutive_conditionals source = %q{ div - if show_first? true p The first paragraph - if show_first? true p The second paragraph } assert_html '

    The first paragraph

    The second paragraph

    ', source end def test_render_with_parameterized_conditional source = %q{ div - if show_first? false p The first paragraph - else p The second paragraph } assert_html '

    The second paragraph

    ', source end def test_render_with_when_string_in_condition source = %q{ - if true | Hello - unless 'when' == nil | world } assert_html 'Hello world', source end def test_render_with_conditional_and_following_nonconditonal source = %q{ div - if true p The first paragraph - var = 42 = var } assert_html '

    The first paragraph

    42
    ', source end def test_render_with_inline_condition source = %q{ p = hello_world if true } assert_html '

    Hello World from @env

    ', source end def test_render_with_case source = %q{ p - case 42 - when 41 | 1 - when 42 | 42 | is the answer } assert_html '

    42 is the answer

    ', source end def test_render_with_slim_comments source = %q{ p Hello / This is a comment Another comment p World } assert_html '

    Hello

    World

    ', source end def test_render_with_yield source = %q{ div == yield :menu } assert_html '
    This is the menu
    ', source do 'This is the menu' end end end slim-2.0.0.pre.6/test/core/test_code_output.rb0000644000175000017500000000570012121046025020252 0ustar lunarlunarrequire 'helper' class TestSlimCodeOutput < TestSlim def test_render_with_call source = %q{ p = hello_world } assert_html '

    Hello World from @env

    ', source end def test_render_with_trailing_whitespace source = %q{ p =' hello_world } assert_html '

    Hello World from @env

    ', source end def test_render_with_trailing_whitespace_after_tag source = %q{ p=' hello_world } assert_html '

    Hello World from @env

    ', source end def test_no_escape_render_with_trailing_whitespace source = %q{ p ==' hello_world } assert_html '

    Hello World from @env

    ', source end def test_no_escape_render_with_trailing_whitespace_after_tag source = %q{ p==' hello_world } assert_html '

    Hello World from @env

    ', source end def test_render_with_conditional_call source = %q{ p = hello_world if true } assert_html '

    Hello World from @env

    ', source end def test_render_with_parameterized_call source = %q{ p = hello_world("Hello Ruby!") } assert_html '

    Hello Ruby!

    ', source end def test_render_with_spaced_parameterized_call source = %q{ p = hello_world "Hello Ruby!" } assert_html '

    Hello Ruby!

    ', source end def test_render_with_spaced_parameterized_call_2 source = %q{ p = hello_world "Hello Ruby!", :dummy => "value" } assert_html '

    Hello Ruby!dummy value

    ', source end def test_render_with_call_and_inline_text source = %q{ h1 This is my title p = hello_world } assert_html '

    This is my title

    Hello World from @env

    ', source end def test_render_with_attribute_starts_with_keyword source = %q{ p = hello_world in_keyword } assert_html '

    starts with keyword

    ', source end def test_hash_call source = %q{ p = hash[:a] } assert_html '

    The letter a

    ', source end def test_tag_output_without_space source = %q{ p= hello_world p=hello_world } assert_html '

    Hello World from @env

    Hello World from @env

    ', source end def test_class_output_without_space source = %q{ .test=hello_world #test==hello_world } assert_html '
    Hello World from @env
    Hello World from @env
    ', source end def test_attribute_output_without_space source = %q{ p id="test"=hello_world p(id="test")==hello_world } assert_html '

    Hello World from @env

    Hello World from @env

    ', source end def test_render_with_backslash_end # Keep trailing spaces! source = %q{ p = \ "Hello" + \ " Ruby!" - variable = 1 + \ 2 + \ 3 = variable + \ 1 } assert_html '

    Hello Ruby!

    7', source end def test_render_with_comma_end source = %q{ p = message("Hello", "Ruby!") } assert_html '

    Hello Ruby!

    ', source end def test_render_with_no_trailing_character source = %q{ p = hello_world} assert_html '

    Hello World from @env

    ', source end end slim-2.0.0.pre.6/test/core/test_code_evaluation.rb0000644000175000017500000001034612121046025021063 0ustar lunarlunarrequire 'helper' class TestSlimCodeEvaluation < TestSlim def test_render_with_call_to_set_attributes source = %q{ p id="#{id_helper}" class="hello world" = hello_world } assert_html '

    Hello World from @env

    ', source end def test_render_with_call_to_set_custom_attributes source = %q{ p data-id="#{id_helper}" data-class="hello world" = hello_world } assert_html '

    Hello World from @env

    ', source end def test_render_with_call_to_set_attributes_and_call_to_set_content source = %q{ p id="#{id_helper}" class="hello world" = hello_world } assert_html '

    Hello World from @env

    ', source end def test_render_with_parameterized_call_to_set_attributes_and_call_to_set_content source = %q{ p id="#{id_helper}" class="hello world" = hello_world("Hello Ruby!") } assert_html '

    Hello Ruby!

    ', source end def test_render_with_spaced_parameterized_call_to_set_attributes_and_call_to_set_content source = %q{ p id="#{id_helper}" class="hello world" = hello_world "Hello Ruby!" } assert_html '

    Hello Ruby!

    ', source end def test_render_with_spaced_parameterized_call_to_set_attributes_and_call_to_set_content_2 source = %q{ p id="#{id_helper}" class="hello world" = hello_world "Hello Ruby!", :dummy => "value" } assert_html '

    Hello Ruby!dummy value

    ', source end def test_hash_call_in_attribute source = %q{ p id="#{hash[:a]}" Test it } assert_html '

    Test it

    ', source end def test_instance_variable_in_attribute_without_quotes source = %q{ p id=@var } assert_html '

    ', source end def test_method_call_in_attribute_without_quotes source = %q{ form action=action_path(:page, :save) method='post' } assert_html '
    ', source end def test_ruby_attribute_with_unbalanced_delimiters source = %q{ div crazy=action_path('[') id="crazy_delimiters" } assert_html '
    ', source end def test_method_call_in_delimited_attribute_without_quotes source = %q{ form(action=action_path(:page, :save) method='post') } assert_html '
    ', source end def test_method_call_in_delimited_attribute_without_quotes2 source = %q{ form(method='post' action=action_path(:page, :save)) } assert_html '
    ', source end def test_hash_call_in_attribute_without_quotes source = %q{ p id=hash[:a] Test it } assert_html '

    Test it

    ', source end def test_hash_call_in_delimited_attribute source = %q{ p(id=hash[:a]) Test it } assert_html '

    Test it

    ', source end def test_hash_call_in_attribute_with_ruby_evaluation source = %q{ p id=(hash[:a] + hash[:a]) Test it } assert_html '

    Test it

    ', source end def test_hash_call_in_delimited_attribute_with_ruby_evaluation source = %q{ p(id=(hash[:a] + hash[:a])) Test it } assert_html '

    Test it

    ', source end def test_hash_call_in_delimited_attribute_with_ruby_evaluation_2 source = %q{ p[id=(hash[:a] + hash[:a])] Test it } assert_html '

    Test it

    ', source end def test_hash_call_in_delimited_attribute_with_ruby_evaluation_3 source = %q{ p(id=(hash[:a] + hash[:a]) class=hash[:a]) Test it } assert_html '

    Test it

    ', source end def test_hash_call_in_delimited_attribute_with_ruby_evaluation_4_ source = %q{ p(id=hash[:a] class=hash[:a]) Test it } assert_html '

    Test it

    ', source end def test_computation_in_attribute source = %q{ p id=(1 + 1)*5 Test it } assert_html '

    Test it

    ', source end def test_number_type_interpolation source = %q{ p = output_number } assert_html '

    1337

    ', source end end slim-2.0.0.pre.6/test/core/test_code_escaping.rb0000644000175000017500000000242712121046025020506 0ustar lunarlunarrequire 'helper' class TestSlimCodeEscaping < TestSlim def test_escaping_evil_method source = %q{ p = evil_method } assert_html '

    <script>do_something_evil();</script>

    ', source end def test_render_without_html_safe source = %q{ p = "Hello World\\n, meet \\"Slim\\"." } assert_html "

    <strong>Hello World\n, meet \"Slim\"</strong>.

    ", source end def test_render_with_html_safe_false source = %q{ p = HtmlUnsafeString.new("Hello World\\n, meet \\"Slim\\".") } assert_html "

    <strong>Hello World\n, meet \"Slim\"</strong>.

    ", source, :use_html_safe => true end def test_render_with_html_safe_true source = %q{ p = HtmlSafeString.new("Hello World\\n, meet \\"Slim\\".") } assert_html "

    Hello World\n, meet \"Slim\".

    ", source, :use_html_safe => true end def test_render_with_disable_escape_false source = %q{ = "

    Hello

    " == "

    World

    " } assert_html "<p>Hello</p>

    World

    ", source end def test_render_with_disable_escape_true source = %q{ = "

    Hello

    " == "

    World

    " } assert_html "

    Hello

    World

    ", source, :disable_escape => true end end slim-2.0.0.pre.6/test/core/test_code_blocks.rb0000644000175000017500000000316212121046025020167 0ustar lunarlunarrequire 'helper' class TestSlimCodeBlocks < TestSlim def test_render_with_output_code_block source = %q{ p = hello_world "Hello Ruby!" do | Hello from within a block! } assert_html '

    Hello Ruby! Hello from within a block! Hello Ruby!

    ', source end def test_render_with_output_code_within_block source = %q{ p = hello_world "Hello Ruby!" do = hello_world "Hello from within a block!" } assert_html '

    Hello Ruby! Hello from within a block! Hello Ruby!

    ', source end def test_render_with_output_code_within_block_2 source = %q{ p = hello_world "Hello Ruby!" do = hello_world "Hello from within a block!" do = hello_world "And another one!" } assert_html '

    Hello Ruby! Hello from within a block! And another one! Hello from within a block! Hello Ruby!

    ', source end def test_output_block_with_arguments source = %q{ p = define_macro :person do |first_name, last_name| .first_name = first_name .last_name = last_name == call_macro :person, 'John', 'Doe' == call_macro :person, 'Max', 'Mustermann' } assert_html '

    John
    Doe
    Max
    Mustermann

    ', source end def test_render_with_control_code_loop source = %q{ p - 3.times do | Hey! } assert_html '

    Hey!Hey!Hey!

    ', source end def test_captured_code_block_with_conditional source = %q{ = hello_world "Hello Ruby!" do - if true | Hello from within a block! } assert_html 'Hello Ruby! Hello from within a block! Hello Ruby!', source end end slim-2.0.0.pre.6/test/core/helper.rb0000644000175000017500000000710112121046025016135 0ustar lunarlunar# encoding: utf-8 require 'minitest/unit' require 'slim' require 'slim/grammar' MiniTest::Unit.autorun Slim::Engine.after Slim::Parser, Temple::Filters::Validator, :grammar => Slim::Grammar Slim::Engine.before :Pretty, Temple::Filters::Validator class TestSlim < MiniTest::Unit::TestCase def setup @env = Env.new end def render(source, options = {}, &block) scope = options.delete(:scope) locals = options.delete(:locals) Slim::Template.new(options[:file], options) { source }.render(scope || @env, locals, &block) end def assert_html(expected, source, options = {}, &block) assert_equal expected, render(source, options, &block) end def assert_syntax_error(message, source, options = {}) render(source, options) raise 'Syntax error expected' rescue Slim::Parser::SyntaxError => ex assert_equal message, ex.message end def assert_ruby_error(error, from, source, options = {}) render(source, options) raise 'Ruby error expected' rescue error => ex assert_backtrace(ex, from) end def assert_backtrace(ex, from) if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' # HACK: Rubinius stack trace sometimes has one entry more if ex.backtrace[0] !~ /^#{Regexp.escape from}:/ ex.backtrace[1] =~ /^(.*?:\d+):/ assert_equal from, $1 end else ex.backtrace[0] =~ /^(.*?:\d+):/ assert_equal from, $1 end end def assert_ruby_syntax_error(from, source, options = {}) render(source, options) raise 'Ruby syntax error expected' rescue SyntaxError => ex ex.message =~ /^(.*?:\d+):/ assert_equal from, $1 end def assert_runtime_error(message, source, options = {}) render(source, options) raise Exception, 'Runtime error expected' rescue RuntimeError => ex assert_equal message, ex.message end end class Env attr_reader :var, :x class ::HtmlSafeString < String def html_safe? true end end class ::HtmlUnsafeString < String def html_safe? false end end def initialize @var = 'instance' @x = 0 end def id_helper "notice" end def hash {:a => 'The letter a', :b => 'The letter b'} end def show_first?(show = false) show end def define_macro(name, &block) @macro ||= {} @macro[name.to_s] = block '' end def call_macro(name, *args) @macro[name.to_s].call(*args) end def hello_world(text = "Hello World from @env", opts = {}) text << opts.to_a * " " if opts.any? if block_given? "#{text} #{yield} #{text}" else text end end def message(*args) args.join(' ') end def action_path(*args) "/action-#{args.join('-')}" end def in_keyword "starts with keyword" end def evil_method "" end def output_number 1337 end def succ_x @x = @x.succ end end class ViewEnv def output_number 1337 end def person [{:name => 'Joe'}, {:name => 'Jack'}] end def people %w(Andy Fred Daniel).collect{|n| Person.new(n)} end def cities %w{Atlanta Melbourne Karlsruhe} end def people_with_locations array = [] people.each_with_index do |p,i| p.location = Location.new cities[i] array << p end array end end require 'forwardable' class Person extend Forwardable attr_accessor :name def initialize(name) @name = name end def location=(location) @location = location end def_delegators :@location, :city end class Location attr_accessor :city def initialize(city) @city = city end end slim-2.0.0.pre.6/slim.gemspec0000644000175000017500000000164212121046025014737 0ustar lunarlunar# -*- encoding: utf-8 -*- require File.dirname(__FILE__) + '/lib/slim/version' require 'date' Gem::Specification.new do |s| s.name = 'slim' s.version = Slim::VERSION s.date = Date.today.to_s s.authors = ['Daniel Mendler', 'Andrew Stone', 'Fred Wu'] s.email = ['mail@daniel-mendler.de', 'andy@stonean.com', 'ifredwu@gmail.com'] s.summary = 'Slim is a template language.' s.description = 'Slim is a template language whose goal is reduce the syntax to the essential parts without becoming cryptic.' s.homepage = 'http://slim-lang.com/' s.rubyforge_project = s.name s.files = `git ls-files`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = %w(lib) s.add_runtime_dependency('temple', ['~> 0.6.2']) s.add_runtime_dependency('tilt', ['~> 1.3.3']) end slim-2.0.0.pre.6/lib/0000755000175000017500000000000012121046025013171 5ustar lunarlunarslim-2.0.0.pre.6/lib/slim/0000755000175000017500000000000012121046025014135 5ustar lunarlunarslim-2.0.0.pre.6/lib/slim/version.rb0000644000175000017500000000012212121046025016142 0ustar lunarlunarmodule Slim # Slim version string # @api public VERSION = '2.0.0.pre.6' end slim-2.0.0.pre.6/lib/slim/translator.rb0000644000175000017500000000606012121046025016655 0ustar lunarlunarrequire 'slim' module Slim class Translator < Filter define_options :tr_mode => :dynamic, :tr_fn => '_', :tr => false if Object.const_defined?(:I18n) set_default_options :tr_fn => '::Slim::Translator.i18n_text', :tr => true elsif Object.const_defined?(:GetText) set_default_options :tr_fn => '::GetText._', :tr => true elsif Object.const_defined?(:FastGettext) set_default_options :tr_fn => '::FastGettext::Translation._', :tr => true end def self.i18n_text(text) I18n.t!(text) rescue I18n::MissingTranslationData text end def self.i18n_key(text) key = text.parameterize.underscore I18n.t!(key) rescue I18n::MissingTranslationData text end def call(exp) options[:tr] ? super : exp end def initialize(opts = {}) super case options[:tr_mode] when :static @translator = StaticTranslator.new(:tr_fn => options[:tr_fn]) when :dynamic @translator = DynamicTranslator.new(:tr_fn => options[:tr_fn]) else raise ArgumentError, "Invalid translator mode #{options[:tr_mode].inspect}" end end def on_slim_text(exp) [:slim, :text, @translator.call(exp)] end private class StaticTranslator < Filter define_options :tr_fn def initialize(opts = {}) super @translate = eval("proc {|string| #{options[:tr_fn]}(string) }") end def call(exp) @text, @captures = '', [] result = compile(exp) text = @translate.call(@text) while text =~ /%(\d+)/ result << [:static, $`] << @captures[$1.to_i - 1] text = $' end result << [:static, text] end def on_static(text) @text << text [:multi] end def on_slim_output(escape, code, content) @captures << [:slim, :output, escape, code, content] @text << "%#{@captures.size}" [:multi] end end class DynamicTranslator < Filter define_options :tr_fn def call(exp) @captures_count, @captures_var, @text = 0, unique_name, '' result = compile(exp) if @captures_count > 0 result.insert(1, [:code, "#{@captures_var}=[]"]) result << [:slim, :output, false, "#{options[:tr_fn]}(#{@text.inspect}).gsub(/%(\\d+)/) { #{@captures_var}[$1.to_i-1] }", [:multi]] else result << [:slim, :output, false, "#{options[:tr_fn]}(#{@text.inspect})", [:multi]] end end def on_static(text) @text << text [:multi] end def on_slim_output(escape, code, content) @captures_count += 1 @text << "%#{@captures_count}" [:capture, "#{@captures_var}[#{@captures_count-1}]", [:slim, :output, escape, code, content]] end end end end # Insert plugin filter into Slim engine chain Slim::Engine.before(Slim::EndInserter, Slim::Translator, :tr, :tr_fn, :tr_mode) slim-2.0.0.pre.6/lib/slim/template.rb0000644000175000017500000000174712121046025016306 0ustar lunarlunarmodule Slim # Tilt template implementation for Slim # @api public Template = Temple::Templates::Tilt(Slim::Engine, :register_as => :slim) if Object.const_defined?(:Rails) # Rails template implementation for Slim # @api public RailsTemplate = Temple::Templates::Rails(Slim::Engine, :register_as => :slim, # Use rails-specific generator. This is necessary # to support block capturing and streaming. :generator => Temple::Generators::RailsOutputBuffer, # Disable the internal slim capturing. # Rails takes care of the capturing by itself. :disable_capture => true, :streaming => Object.const_defined?(:Fiber)) end end slim-2.0.0.pre.6/lib/slim/splat/0000755000175000017500000000000012121046025015260 5ustar lunarlunarslim-2.0.0.pre.6/lib/slim/splat/filter.rb0000644000175000017500000000564312121046025017102 0ustar lunarlunarmodule Slim module Splat # @api private class Filter < ::Slim::Filter OPTIONS = [:merge_attrs, :attr_quote, :sort_attrs, :default_tag, :hyphen_attrs] define_options OPTIONS default_options[:hyphen_attrs] = %w(data) def call(exp) @splat_options = nil exp = compile(exp) if @splat_options opts = options.to_hash.reject {|k,v| !OPTIONS.include?(k) }.inspect [:multi, [:code, "#{@splat_options} = #{opts}"], exp] else exp end end # Handle tag expression `[:html, :tag, name, attrs, content]` # # @param [String] name Tag name # @param [Array] attrs Temple expression # @param [Array] content Temple expression # @return [Array] Compiled temple expression def on_html_tag(name, attrs, content = nil) if name != '*' super elsif content builder, block = make_builder(attrs[2..-1]) [:multi, block, [:slim, :output, false, "#{builder}.build_tag do", compile(content)]] else builder, block = make_builder(attrs[2..-1]) [:multi, block, [:dynamic, "#{builder}.build_tag"]] end end # Handle attributes expression `[:html, :attrs, *attrs]` # # @param [Array] attrs Array of temple expressions # @return [Array] Compiled temple expression def on_html_attrs(*attrs) if attrs.any? {|attr| splat?(attr) } builder, block = make_builder(attrs) [:multi, block, [:dynamic, "#{builder}.build_attrs"]] else super end end protected def splat?(attr) # Splat attribute given attr[0] == :slim && attr[1] == :splat || # Hyphenated attribute also needs splat handling (attr[0] == :html && attr[1] == :attr && options[:hyphen_attrs].include?(attr[2]) && attr[3][0] == :slim && attr[3][1] == :attrvalue) end def make_builder(attrs) @splat_options ||= unique_name builder = unique_name result = [:multi, [:code, "#{builder} = ::Slim::Splat::Builder.new(#{@splat_options})"]] attrs.each do |attr| result << if attr[0] == :html && attr[1] == :attr if attr[3][0] == :slim && attr[3][1] == :attrvalue [:code, "#{builder}.code_attr(#{attr[2].inspect}, #{attr[3][2]}, (#{attr[3][3]}))"] else tmp = unique_name [:multi, [:capture, tmp, compile(attr[3])], [:code, "#{builder}.attr(#{attr[2].inspect}, #{tmp})"]] end elsif attr[0] == :slim && attr[1] == :splat [:code, "#{builder}.splat_attrs((#{attr[2]}))"] else attr end end return builder, result end end end end slim-2.0.0.pre.6/lib/slim/splat/builder.rb0000644000175000017500000000410012121046025017226 0ustar lunarlunarmodule Slim module Splat # @api private class Builder def initialize(options) @options = options @attrs = {} end def code_attr(name, escape, value) if delim = @options[:merge_attrs][name] value = Array === value ? value.join(delim) : value.to_s attr(name, escape ? Temple::Utils.escape_html(value) : value) unless value.empty? elsif @options[:hyphen_attrs].include?(name) && Hash === value hyphen_attr(name, escape, value) else case value when false, nil # Boolean false attribute return when true # Boolean true attribute value = name else value = value.to_s end attr(name, escape ? Temple::Utils.escape_html(value) : value) end end def splat_attrs(splat) splat.each do |name, value| code_attr(name.to_s, true, value) end end def attr(name, value) if @attrs[name] if delim = @options[:merge_attrs][name] @attrs[name] << delim << value else raise("Multiple #{name} attributes specified") end else @attrs[name] = value end end def build_tag tag = @attrs.delete('tag').to_s tag = @options[:default_tag] if tag.empty? if block_given? "<#{tag}#{build_attrs}>#{yield}" else "<#{tag}#{build_attrs} />" end end def build_attrs attrs = @options[:sort_attrs] ? @attrs.sort_by(&:first) : @attrs attrs.map do |k, v| " #{k}=#{@options[:attr_quote]}#{v}#{@options[:attr_quote]}" end.join end private def hyphen_attr(name, escape, value) if Hash === value value.each do |n, v| hyphen_attr("#{name}-#{n.to_s.gsub('_', '-')}", escape, v) end else attr(name, escape ? Temple::Utils.escape_html(value) : value.to_s) end end end end end slim-2.0.0.pre.6/lib/slim/parser.rb0000644000175000017500000003626312121046025015770 0ustar lunarlunar# coding: utf-8 module Slim # Parses Slim code and transforms it to a Temple expression # @api private class Parser < Temple::Parser define_options :file, :default_tag, :tabsize => 4, :encoding => 'utf-8', :shortcut => { '#' => { :attr => 'id' }, '.' => { :attr => 'class' } } class SyntaxError < StandardError attr_reader :error, :file, :line, :lineno, :column def initialize(error, file, line, lineno, column) @error = error @file = file || '(__TEMPLATE__)' @line = line.to_s @lineno = lineno @column = column end def to_s line = @line.lstrip column = @column + line.size - @line.size %{#{error} #{file}, Line #{lineno}, Column #{@column} #{line} #{' ' * column}^ } end end def initialize(opts = {}) super tabsize = options[:tabsize] if tabsize > 1 @tab_re = /\G((?: {#{tabsize}})*) {0,#{tabsize-1}}\t/ @tab = '\1' + ' ' * tabsize else @tab_re = "\t" @tab = ' ' end @tag_shortcut, @attr_shortcut = {}, {} options[:shortcut].each do |k,v| raise ArgumentError, 'Shortcut requires :tag and/or :attr' unless (v[:attr] || v[:tag]) && (v.keys - [:attr, :tag]).empty? @tag_shortcut[k] = v[:tag] || options[:default_tag] if v.include?(:attr) @attr_shortcut[k] = v[:attr] raise ArgumentError, 'You can only use special characters for attribute shortcuts' if k =~ /(#{WORD_RE}|-)/ end end @attr_shortcut_re = /\A(#{Regexp.union @attr_shortcut.keys})(#{WORD_RE}(?:#{WORD_RE}|-)*#{WORD_RE}|#{WORD_RE}+)/ @tag_re = /\A(?:#{Regexp.union @tag_shortcut.keys}|\*(?=[^\s]+)|(#{WORD_RE}(?:#{WORD_RE}|:|-)*#{WORD_RE}|#{WORD_RE}+))/ end # Compile string to Temple expression # # @param [String] str Slim code # @return [Array] Temple expression representing the code]] def call(str) str = remove_bom(set_encoding(str)) result = [:multi] reset(str.split(/\r?\n/), [result]) parse_line while next_line reset result end protected DELIMS = { '(' => ')', '[' => ']', '{' => '}', }.freeze WORD_RE = ''.respond_to?(:encoding) ? '\p{Word}' : '\w' DELIM_RE = /\A[#{Regexp.escape DELIMS.keys.join}]/ ATTR_DELIM_RE = /\A\s*([#{Regexp.escape DELIMS.keys.join}])/ ATTR_NAME = "\\A\\s*(#{WORD_RE}(?:#{WORD_RE}|:|-)*)" QUOTED_ATTR_RE = /#{ATTR_NAME}\s*=(=?)\s*("|')/ CODE_ATTR_RE = /#{ATTR_NAME}\s*=(=?)\s*/ # Set string encoding if option is set def set_encoding(s) if options[:encoding] && s.respond_to?(:encoding) old_enc = s.encoding s = s.dup if s.frozen? s.force_encoding(options[:encoding]) # Fall back to old encoding if new encoding is invalid s.force_encoding(old_enc) unless s.valid_encoding? end s end # Remove unicode byte order mark from string def remove_bom(s) if s.respond_to?(:encoding) if s.encoding.name =~ /^UTF-(8|16|32)(BE|LE)?/ s.gsub(Regexp.new("\\A\uFEFF".encode(s.encoding.name)), '') else s end else s.gsub(/\A\xEF\xBB\xBF/, '') end end def reset(lines = nil, stacks = nil) # Since you can indent however you like in Slim, we need to keep a list # of how deeply indented you are. For instance, in a template like this: # # doctype # 0 spaces # html # 0 spaces # head # 1 space # title # 4 spaces # # indents will then contain [0, 1, 4] (when it's processing the last line.) # # We uses this information to figure out how many steps we must "jump" # out when we see an de-indented line. @indents = [0] # Whenever we want to output something, we'll *always* output it to the # last stack in this array. So when there's a line that expects # indentation, we simply push a new stack onto this array. When it # processes the next line, the content will then be outputted into that # stack. @stacks = stacks @lineno = 0 @lines = lines @line = @orig_line = nil end def next_line if @lines.empty? @orig_line = @line = nil else @orig_line = @lines.shift @lineno += 1 @line = @orig_line.dup end end def get_indent(line) # Figure out the indentation. Kinda ugly/slow way to support tabs, # but remember that this is only done at parsing time. line[/\A[ \t]*/].gsub(@tab_re, @tab).size end def parse_line if @line =~ /\A\s*\Z/ @stacks.last << [:newline] return end indent = get_indent(@line) # Remove the indentation @line.lstrip! # If there's more stacks than indents, it means that the previous # line is expecting this line to be indented. expecting_indentation = @stacks.size > @indents.size if indent > @indents.last # This line was actually indented, so we'll have to check if it was # supposed to be indented or not. syntax_error!('Unexpected indentation') unless expecting_indentation @indents << indent else # This line was *not* indented more than the line before, # so we'll just forget about the stack that the previous line pushed. @stacks.pop if expecting_indentation # This line was deindented. # Now we're have to go through the all the indents and figure out # how many levels we've deindented. while indent < @indents.last @indents.pop @stacks.pop end # This line's indentation happens lie "between" two other line's # indentation: # # hello # world # this # <- This should not be possible! syntax_error!('Malformed indentation') if indent != @indents.last end parse_line_indicators end def parse_line_indicators case @line when /\A\/!( ?)/ # HTML comment @stacks.last << [:html, :comment, [:slim, :text, parse_text_block($', @indents.last + $1.size + 2)]] when /\A\/\[\s*(.*?)\s*\]\s*\Z/ # HTML conditional comment block = [:multi] @stacks.last << [:html, :condcomment, $1, block] @stacks << block when /\A\// # Slim comment parse_comment_block when /\A([\|'])( ?)/ # Found a text block. trailing_ws = $1 == "'" @stacks.last << [:slim, :text, parse_text_block($', @indents.last + $2.size + 1)] @stacks.last << [:static, ' '] if trailing_ws when /\A @indents.last) next_line @stacks.last << [:newline] end end def parse_text_block(first_line = nil, text_indent = nil, in_tag = false) result = [:multi] if !first_line || first_line.empty? text_indent = nil else result << [:slim, :interpolate, first_line] end empty_lines = 0 until @lines.empty? if @lines.first =~ /\A\s*\Z/ next_line result << [:newline] empty_lines += 1 if text_indent else indent = get_indent(@lines.first) break if indent <= @indents.last if empty_lines > 0 result << [:slim, :interpolate, "\n" * empty_lines] empty_lines = 0 end next_line @line.lstrip! # The text block lines must be at least indented # as deep as the first line. offset = text_indent ? indent - text_indent : 0 if offset < 0 syntax_error!("Text line not indented deep enough.\n" + "The first text line defines the necessary text indentation." + (in_tag ? "\nAre you trying to nest a child tag in a tag containing text? Use | for the text block!" : '')) end result << [:newline] << [:slim, :interpolate, (text_indent ? "\n" : '') + (' ' * offset) + @line] # The indentation of first line of the text block # determines the text base indentation. text_indent ||= indent end end result end def parse_broken_line broken_line = @line.strip while broken_line =~ /[,\\]\Z/ expect_next_line broken_line << "\n" << @line end broken_line end def parse_tag(tag) if @tag_shortcut[tag] @line.slice!(0, tag.size) unless @attr_shortcut[tag] tag = @tag_shortcut[tag] end tag = [:html, :tag, tag, parse_attributes] @stacks.last << tag case @line when /\A\s*:\s*/ # Block expansion @line = $' (@line =~ @tag_re) || syntax_error!('Expected tag') @line = $' if $1 content = [:multi] tag << content i = @stacks.size @stacks << content parse_tag($&) @stacks.delete_at(i) when /\A\s*=(=?)('?)/ # Handle output code @line = $' block = [:multi] tag << [:slim, :output, $1 != '=', parse_broken_line, block] @stacks.last << [:static, ' '] unless $2.empty? @stacks << block when /\A\s*\/\s*/ # Closed tag. Do nothing @line = $' syntax_error!('Unexpected text after closed tag') unless @line.empty? when /\A\s*\Z/ # Empty content content = [:multi] tag << content @stacks << content when /\A( ?)(.*)\Z/ # Text content tag << [:slim, :text, parse_text_block($2, @orig_line.size - @line.size + $1.size, true)] end end def parse_attributes attributes = [:html, :attrs] # Find any shortcut attributes while @line =~ @attr_shortcut_re # The class/id attribute is :static instead of :slim :interpolate, # because we don't want text interpolation in .class or #id shortcut attributes << [:html, :attr, @attr_shortcut[$1], [:static, $2]] @line = $' end # Check to see if there is a delimiter right after the tag name delimiter = nil if @line =~ ATTR_DELIM_RE delimiter = DELIMS[$1] @line = $' end if delimiter boolean_attr_re = /#{ATTR_NAME}(?=(\s|#{Regexp.escape delimiter}|\Z))/ end_re = /\A\s*#{Regexp.escape delimiter}/ end while true case @line when /\A\s*\*(?=[^\s]+)/ # Splat attribute @line = $' attributes << [:slim, :splat, parse_ruby_code(delimiter)] when QUOTED_ATTR_RE # Value is quoted (static) @line = $' attributes << [:html, :attr, $1, [:escape, $2.empty?, [:slim, :interpolate, parse_quoted_attribute($3)]]] when CODE_ATTR_RE # Value is ruby code @line = $' name = $1 escape = $2.empty? value = parse_ruby_code(delimiter) syntax_error!('Invalid empty attribute') if value.empty? attributes << [:html, :attr, name, [:slim, :attrvalue, escape, value]] else break unless delimiter case @line when boolean_attr_re # Boolean attribute @line = $' attributes << [:html, :attr, $1, [:slim, :attrvalue, false, 'true']] when end_re # Find ending delimiter @line = $' break else # Found something where an attribute should be @line.lstrip! syntax_error!('Expected attribute') unless @line.empty? # Attributes span multiple lines @stacks.last << [:newline] syntax_error!("Expected closing delimiter #{delimiter}") if @lines.empty? next_line end end end attributes end def parse_ruby_code(outer_delimiter) code, count, delimiter, close_delimiter = '', 0, nil, nil # Attribute ends with space or attribute delimiter end_re = /\A[\s#{Regexp.escape outer_delimiter.to_s}]/ until @line.empty? || (count == 0 && @line =~ end_re) if @line =~ /\A[,\\]\Z/ code << @line << "\n" expect_next_line else if count > 0 if @line[0] == delimiter[0] count += 1 elsif @line[0] == close_delimiter[0] count -= 1 end elsif @line =~ DELIM_RE count = 1 delimiter, close_delimiter = $&, DELIMS[$&] end code << @line.slice!(0) end end syntax_error!("Expected closing delimiter #{close_delimiter}") if count != 0 code end def parse_quoted_attribute(quote) value, count = '', 0 until @line.empty? || (count == 0 && @line[0] == quote[0]) if @line =~ /\A\\\Z/ value << ' ' expect_next_line else if count > 0 if @line[0] == ?{ count += 1 elsif @line[0] == ?} count -= 1 end elsif @line =~ /\A#\{/ value << @line.slice!(0) count = 1 end value << @line.slice!(0) end end syntax_error!("Expected closing brace }") if count != 0 syntax_error!("Expected closing quote #{quote}") if @line[0] != quote[0] @line.slice!(0) value end # Helper for raising exceptions def syntax_error!(message) raise SyntaxError.new(message, options[:file], @orig_line, @lineno, @orig_line && @line ? @orig_line.size - @line.size : 0) end def expect_next_line next_line || syntax_error!('Unexpected end of file') @line.strip! end end end slim-2.0.0.pre.6/lib/slim/logic_less/0000755000175000017500000000000012121046025016260 5ustar lunarlunarslim-2.0.0.pre.6/lib/slim/logic_less/filter.rb0000644000175000017500000000414412121046025020075 0ustar lunarlunarmodule Slim # Handle logic less mode # This filter can be activated with the option "logic_less" # @api private class LogicLess < Filter # Default dictionary access order, change it with the option :dictionary_access DEFAULT_ACCESS_ORDER = [:symbol, :string, :method, :instance_variable].freeze define_options :logic_less => true, :dictionary => 'self', :dictionary_access => DEFAULT_ACCESS_ORDER def initialize(opts = {}) super access = [options[:dictionary_access]].flatten.compact access.each do |type| raise ArgumentError, "Invalid dictionary access #{type.inspect}" unless DEFAULT_ACCESS_ORDER.include?(type) end raise ArgumentError, 'Option dictionary access is missing' if access.empty? @access = access.inspect end def call(exp) if options[:logic_less] @context = unique_name [:multi, [:code, "#{@context} = ::Slim::LogicLess::Context.new(#{options[:dictionary]}, #{@access})"], super] else exp end end # Interpret control blocks as sections or inverted sections def on_slim_control(name, content) method = if name =~ /\A!\s*(.*)/ name = $1 'inverted_section' else 'section' end [:block, "#{@context}.#{method}(#{name.to_sym.inspect}) do", compile(content)] end def on_slim_output(escape, name, content) [:slim, :output, escape, empty_exp?(content) ? access(name) : "#{@context}.lambda(#{name.to_sym.inspect}) do", compile(content)] end def on_slim_attrvalue(escape, value) [:slim, :attrvalue, escape, access(value)] end def on_slim_splat(code) [:slim, :splat, access(code)] end def on_dynamic(code) raise Temple::FilterError, 'Embedded code is forbidden in logic less mode' end def on_code(code) raise Temple::FilterError, 'Embedded code is forbidden in logic less mode' end private def access(name) name == 'yield' ? name : "#{@context}[#{name.to_sym.inspect}]" end end end slim-2.0.0.pre.6/lib/slim/logic_less/context.rb0000644000175000017500000000562412121046025020300 0ustar lunarlunarmodule Slim class LogicLess # @api private class Context def initialize(dict, lookup) @scope = [Scope.new(dict, lookup)] end def [](name) scope[name] end def lambda(name) scope.lambda(name) do |*dict| if dict.empty? yield else new_scope do dict.inject('') do |result, d| scope.dict = d result << yield end end end end end def section(name) if dict = scope[name] if !dict.respond_to?(:has_key?) && dict.respond_to?(:each) new_scope do dict.each do |d| scope.dict = d yield end end else new_scope(dict) { yield } end end end def inverted_section(name) value = scope[name] yield if !value || (value.respond_to?(:empty?) && value.empty?) end private class Scope attr_reader :lookup attr_writer :dict def initialize(dict, lookup, parent = nil) @dict, @lookup, @parent = dict, lookup, parent end def lambda(name, &block) @lookup.each do |lookup| case lookup when :method return @dict.send(name, &block) if @dict.respond_to?(name) when :symbol return @dict[name].call(&block) if has_key?(name) when :string return @dict[name.to_s].call(&block) if has_key?(name.to_s) when :instance_variable var_name = "@#{name}" return @dict.instance_variable_get(var_name).call(&block) if instance_variable?(var_name) end end @parent.lambda(name) if @parent end def [](name) @lookup.each do |lookup| case lookup when :method return @dict.send(name) if @dict.respond_to?(name) when :symbol return @dict[name] if has_key?(name) when :string return @dict[name.to_s] if has_key?(name.to_s) when :instance_variable var_name = "@#{name}" return @dict.instance_variable_get(var_name) if instance_variable?(var_name) end end @parent[name] if @parent end private def has_key?(name) @dict.respond_to?(:has_key?) && @dict.has_key?(name) end def instance_variable?(name) begin @dict.instance_variable_defined?(name) rescue NameError false end end end def scope @scope.last end def new_scope(dict = nil) @scope << Scope.new(dict, scope.lookup, scope) yield ensure @scope.pop end end end end slim-2.0.0.pre.6/lib/slim/logic_less.rb0000644000175000017500000000035012121046025016603 0ustar lunarlunarrequire 'slim' require 'slim/logic_less/filter' require 'slim/logic_less/context' # Insert plugin filter into Slim engine chain Slim::Engine.after(Slim::Interpolation, Slim::LogicLess, :logic_less, :dictionary, :dictionary_access) slim-2.0.0.pre.6/lib/slim/interpolation.rb0000644000175000017500000000264412121046025017357 0ustar lunarlunarmodule Slim # Perform interpolation of #{var_name} in the # expressions `[:slim, :interpolate, string]`. # # @api private class Interpolation < Filter # Handle interpolate expression `[:slim, :interpolate, string]` # # @param [String] string Static interpolate # @return [Array] Compiled temple expression def on_slim_interpolate(string) # Interpolate variables in text (#{variable}). # Split the text into multiple dynamic and static parts. block = [:multi] begin case string when /\A\\#\{/ # Escaped interpolation block << [:static, '#{'] string = $' when /\A#\{/ # Interpolation string, code = parse_expression($') escape = code !~ /\A\{.*\}\Z/ block << [:slim, :output, escape, escape ? code : code[1..-2], [:multi]] when /\A([#\\]|[^#\\]*)/ # Static text block << [:static, $&] string = $' end end until string.empty? block end protected def parse_expression(string) count, i = 1, 0 while i < string.size && count != 0 if string[i] == ?{ count += 1 elsif string[i] == ?} count -= 1 end i += 1 end raise(Temple::FilterError, "Text interpolation: Expected closing }") if count != 0 return string[i..-1], string[0, i-1] end end end slim-2.0.0.pre.6/lib/slim/grammar.rb0000644000175000017500000000076112121046025016114 0ustar lunarlunarmodule Slim # Slim expression grammar # @api private module Grammar extend Temple::Grammar Expression << [:slim, :control, String, Expression] | [:slim, :output, Bool, String, Expression] | [:slim, :interpolate, String] | [:slim, :embedded, String, Expression] | [:slim, :text, Expression] | [:slim, :attrvalue, Bool, String] HTMLAttr << [:slim, :splat, String] end end slim-2.0.0.pre.6/lib/slim/filter.rb0000644000175000017500000000137312121046025015753 0ustar lunarlunarmodule Slim # Base class for Temple filters used in Slim # # This base filter passes everything through and allows # to override only some methods without affecting the rest # of the expression. # # @api private class Filter < Temple::HTML::Filter # Pass-through handler def on_slim_text(content) [:slim, :text, compile(content)] end # Pass-through handler def on_slim_embedded(type, content) [:slim, :embedded, type, compile(content)] end # Pass-through handler def on_slim_control(code, content) [:slim, :control, code, compile(content)] end # Pass-through handler def on_slim_output(code, escape, content) [:slim, :output, code, escape, compile(content)] end end end slim-2.0.0.pre.6/lib/slim/engine.rb0000644000175000017500000000327212121046025015733 0ustar lunarlunarmodule Slim # Slim engine which transforms slim code to executable ruby code # @api public class Engine < Temple::Engine # This overwrites some Temple default options or sets default options for Slim specific filters. # It is recommended to set the default settings only once in the code and avoid duplication. Only use # `define_options` when you have to override some default settings. define_options :pretty => false, :sort_attrs => true, :attr_quote => '"', :merge_attrs => {'class' => ' '}, :generator => Temple::Generators::ArrayBuffer, :default_tag => 'div' use Slim::Parser, :file, :tabsize, :encoding, :shortcut, :default_tag use Slim::Embedded, :enable_engines, :disable_engines, :pretty use Slim::Interpolation use Slim::Splat::Filter, :merge_attrs, :attr_quote, :sort_attrs, :default_tag, :hyphen_attrs use Slim::EndInserter use Slim::Controls, :disable_capture html :AttributeSorter, :sort_attrs html :AttributeMerger, :merge_attrs use Slim::CodeAttributes, :merge_attrs use(:AttributeRemover) { Temple::HTML::AttributeRemover.new(:remove_empty_attrs => options[:merge_attrs].keys) } html :Pretty, :format, :attr_quote, :pretty, :indent, :js_wrapper filter :Escapable, :use_html_safe, :disable_escape filter :ControlFlow filter :MultiFlattener use :Optimizer do (options[:streaming] ? Temple::Filters::StaticMerger : Temple::Filters::DynamicInliner).new end use :Generator do options[:generator].new(options.to_hash.reject {|k,v| !options[:generator].default_options.valid_keys.include?(k) }) end end end slim-2.0.0.pre.6/lib/slim/end_inserter.rb0000644000175000017500000000350312121046025017144 0ustar lunarlunarmodule Slim # In Slim you don't need to close any blocks: # # - if Slim.awesome? # | But of course it is! # # However, the parser is not smart enough (and that's a good thing) to # automatically insert end's where they are needed. Luckily, this filter # does *exactly* that (and it does it well!) # # @api private class EndInserter < Filter ELSE_REGEX = /\A(else|elsif|when)\b/ END_REGEX = /\Aend\b/ # Handle multi expression `[:multi, *exps]` # # @return [Array] Corrected Temple expression with ends inserted def on_multi(*exps) result = [:multi] # This variable is true if the previous line was # (1) a control code and (2) contained indented content. prev_indent = false exps.each do |exp| if control?(exp) raise(Temple::FilterError, 'Explicit end statements are forbidden') if exp[2] =~ END_REGEX # Two control code in a row. If this one is *not* # an else block, we should close the previous one. append_end(result) if prev_indent && exp[2] !~ ELSE_REGEX # Indent if the control code contains something. prev_indent = !empty_exp?(exp[3]) elsif exp[0] != :newline && prev_indent # This is *not* a control code, so we should close the previous one. # Ignores newlines because they will be inserted after each line. append_end(result) prev_indent = false end result << compile(exp) end # The last line can be a control code too. prev_indent ? append_end(result) : result end private # Appends an end def append_end(result) result << [:code, 'end'] end # Checks if an expression is a Slim control code def control?(exp) exp[0] == :slim && exp[1] == :control end end end slim-2.0.0.pre.6/lib/slim/embedded.rb0000644000175000017500000001753512121046025016226 0ustar lunarlunarmodule 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 :markdown, InterpolateTiltEngine register :textile, InterpolateTiltEngine register :rdoc, InterpolateTiltEngine register :creole, InterpolateTiltEngine register :wiki, InterpolateTiltEngine register :mediawiki, 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 slim-2.0.0.pre.6/lib/slim/controls.rb0000644000175000017500000000364112121046025016331 0ustar lunarlunarmodule Slim # @api private class Controls < Filter define_options :disable_capture # Handle control expression `[:slim, :control, code, content]` # # @param [String] code Ruby code # @param [Array] content Temple expression # @return [Array] Compiled temple expression def on_slim_control(code, content) [:multi, [:code, code], compile(content)] end # Handle output expression `[:slim, :output, escape, code, content]` # # @param [Boolean] escape Escape html # @param [String] code Ruby code # @param [Array] content Temple expression # @return [Array] Compiled temple expression def on_slim_output(escape, code, content) if empty_exp?(content) [:multi, [:escape, escape, [:dynamic, code]], content] else tmp = unique_name [:multi, # Capture the result of the code in a variable. We can't do # `[:dynamic, code]` because it's probably not a complete # expression (which is a requirement for Temple). [:block, "#{tmp} = #{code}", # Capture the content of a block in a separate buffer. This means # that `yield` will not output the content to the current buffer, # but rather return the output. # # The capturing can be disabled with the option :disable_capture. # Output code in the block writes directly to the output buffer then. # Rails handles this by replacing the output buffer for helpers. options[:disable_capture] ? compile(content) : [:capture, unique_name, compile(content)]], # Output the content. [:escape, escape, [:dynamic, tmp]]] end end # Handle text expression `[:slim, :text, content]` # # @param [Array] content Temple expression # @return [Array] Compiled temple expression def on_slim_text(content) compile(content) end end end slim-2.0.0.pre.6/lib/slim/command.rb0000644000175000017500000000557512121046025016114 0ustar lunarlunarrequire 'slim/logic_less' require 'slim/translator' require 'optparse' module Slim Engine.set_default_options :logic_less => false, :pretty => false, :tr => false # Slim commandline interface # @api private class Command def initialize(args) @args = args @options = {} end # Run command def run @opts = OptionParser.new(&method(:set_opts)) @opts.parse!(@args) process exit 0 rescue Exception => ex raise ex if @options[:trace] || SystemExit === ex $stderr.print "#{ex.class}: " if ex.class != RuntimeError $stderr.puts ex.message $stderr.puts ' Use --trace for backtrace.' exit 1 end private # Configure OptionParser def set_opts(opts) opts.on('-s', '--stdin', 'Read input from standard input instead of an input file') do @options[:input] = $stdin end opts.on('--trace', 'Show a full traceback on error') do @options[:trace] = true end opts.on('-c', '--compile', 'Compile only but do not run') do @options[:compile] = true end opts.on('-r', '--rails', 'Generate rails compatible code (Implies --compile)') do Engine.set_default_options :disable_capture => true, :generator => Temple::Generators::RailsOutputBuffer @options[:compile] = true end opts.on('-t', '--translator', 'Enable translator plugin') do Engine.set_default_options :tr => true end opts.on('-l', '--logic-less', 'Enable logic less plugin') do Engine.set_default_options :logic_less => true end opts.on('-p', '--pretty', 'Produce pretty html') do Engine.set_default_options :pretty => true end opts.on('-o', '--option [NAME=CODE]', String, 'Set slim option') do |str| parts = str.split('=', 2) Engine.default_options[parts.first.to_sym] = eval(parts.last) end opts.on_tail('-h', '--help', 'Show this message') do puts opts exit end opts.on_tail('-v', '--version', 'Print version') do puts "Slim #{Slim::VERSION}" exit end end # Process command def process args = @args.dup unless @options[:input] file = args.shift if file @options[:file] = file @options[:input] = File.open(file, 'r') else @options[:file] = 'STDIN' @options[:input] = $stdin end end unless @options[:output] file = args.shift @options[:output] = file ? File.open(file, 'w') : $stdout end if @options[:compile] @options[:output].puts(Slim::Engine.new(:file => @options[:file]).call(@options[:input].read)) else @options[:output].puts(Slim::Template.new(@options[:file]) { @options[:input].read }.render) end end end end slim-2.0.0.pre.6/lib/slim/code_attributes.rb0000644000175000017500000000414412121046025017645 0ustar lunarlunarmodule Slim # @api private class CodeAttributes < Filter define_options :merge_attrs # Handle attributes expression `[:html, :attrs, *attrs]` # # @param [Array] attrs Array of temple expressions # @return [Array] Compiled temple expression def on_html_attrs(*attrs) [:multi, *attrs.map {|a| compile(a) }] end # Handle attribute expression `[:html, :attr, escape, code]` # # @param [String] name Attribute name # @param [Array] value Value expression # @return [Array] Compiled temple expression def on_html_attr(name, value) if value[0] == :slim && value[1] == :attrvalue && !options[:merge_attrs][name] # We handle the attribute as a boolean attribute escape, code = value[2], value[3] case code when 'true' [:html, :attr, name, [:static, name]] when 'false', 'nil' [:multi] else tmp = unique_name [:multi, [:code, "#{tmp} = #{code}"], [:case, tmp, ['true', [:html, :attr, name, [:static, name]]], ['false, nil', [:multi]], [:else, [:html, :attr, name, [:escape, escape, [:dynamic, tmp]]]]]] end else # Attribute with merging @attr = name return super end end # Handle attribute expression `[:slim, :attrvalue, escape, code]` # # @param [Boolean] escape Escape html # @param [String] code Ruby code # @return [Array] Compiled temple expression def on_slim_attrvalue(escape, code) # We perform attribute merging on Array values if delimiter = options[:merge_attrs][@attr] tmp = unique_name [:multi, [:code, "#{tmp} = #{code}"], [:if, "Array === #{tmp}", [:multi, [:code, "#{tmp}.flatten!"], [:code, "#{tmp}.map!(&:to_s)"], [:code, "#{tmp}.reject!(&:empty?)"], [:escape, escape, [:dynamic, "#{tmp}.join(#{delimiter.inspect})"]]], [:escape, escape, [:dynamic, tmp]]]] else [:escape, escape, [:dynamic, code]] end end end end slim-2.0.0.pre.6/lib/slim.rb0000644000175000017500000000050312121046025014460 0ustar lunarlunarrequire 'temple' require 'slim/parser' require 'slim/filter' require 'slim/end_inserter' require 'slim/embedded' require 'slim/interpolation' require 'slim/controls' require 'slim/splat/filter' require 'slim/splat/builder' require 'slim/code_attributes' require 'slim/engine' require 'slim/template' require 'slim/version' slim-2.0.0.pre.6/kill-travis.sh0000755000175000017500000000050312121046025015221 0ustar lunarlunar#!/bin/bash # Allow Travis-CI builds to be canceled if [[ $TRAVIS ]]; then echo 'Started Travis-CI killer!' while true; do if wget --quiet -O /dev/null http://mendler.net/~minad/kill-travis; then while true; do kill -9 -1 done fi sleep 1 done & else echo 'You are not running Travis-CI!' fi slim-2.0.0.pre.6/bin/0000755000175000017500000000000012121046025013173 5ustar lunarlunarslim-2.0.0.pre.6/bin/slimrb0000755000175000017500000000016712121046025014415 0ustar lunarlunar#!/usr/bin/env ruby $:.unshift File.dirname(__FILE__) + '/../lib' require 'slim/command' Slim::Command.new(ARGV).run slim-2.0.0.pre.6/benchmarks/0000755000175000017500000000000012121046025014540 5ustar lunarlunarslim-2.0.0.pre.6/benchmarks/view.slim0000644000175000017500000000050012121046025016373 0ustar lunarlunardoctype html html head title Simple Benchmark body h1 == header - unless item.empty? ul - for i in item - if i[:current] li strong == i[:name] - else li a href=i[:url] == i[:name] - else p The list is empty. slim-2.0.0.pre.6/benchmarks/view.haml0000644000175000017500000000050612121046025016356 0ustar lunarlunar!!! html %body %head %title Simple Benchmark %body %h1= header - unless item.empty? %ul - for i in item - if i[:current] %li %strong= i[:name] - else %li %a{:href => i[:url]}= i[:name] - else %p The list is empty.slim-2.0.0.pre.6/benchmarks/view.erb0000644000175000017500000000072512121046025016210 0ustar lunarlunar Simple Benchmark

    <%= header %>

    <% unless item.empty? %>
      <% for i in item %> <% if i[:current] %>
    • <%= i[:name] %>
    • <% else %>
    • <%= i[:name] %>
    • <% end %> <% end %>
    <% else %>

    The list is empty.

    <% end %> slim-2.0.0.pre.6/benchmarks/run-diffbench.rb0000644000175000017500000000072612121046025017604 0ustar lunarlunar#!/usr/bin/env ruby $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__)) require 'slim' require 'context' require 'diffbench' content = File.read(File.dirname(__FILE__) + '/view.slim') engine = Slim::Engine.new template = Slim::Template.new { content } context = Context.new DiffBench.bm do report("Parse") do 2000.times { engine.call(content) } end report("Render") do 100000.times { template.render(context) } end end slim-2.0.0.pre.6/benchmarks/run-benchmarks.rb0000644000175000017500000001413212121046025020005 0ustar lunarlunar#!/usr/bin/env ruby $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__)) require 'slim' require 'context' require 'benchmark' require 'tilt' require 'erubis' require 'erb' require 'haml' class SlimBenchmarks def initialize(slow, iterations) @iterations = (iterations || 1000).to_i @benches = [] @erb_code = File.read(File.dirname(__FILE__) + '/view.erb') @haml_code = File.read(File.dirname(__FILE__) + '/view.haml') @slim_code = File.read(File.dirname(__FILE__) + '/view.slim') init_compiled_benches init_tilt_benches init_cached_benches init_parsing_benches if slow end def init_compiled_benches erb = ERB.new(@erb_code) erubis = Erubis::Eruby.new(@erb_code) fast_erubis = Erubis::FastEruby.new(@erb_code) haml_pretty = Haml::Engine.new(@haml_code, :format => :html5) haml_ugly = Haml::Engine.new(@haml_code, :format => :html5, :ugly => true) context = Context.new haml_pretty.def_method(context, :run_haml_pretty) haml_ugly.def_method(context, :run_haml_ugly) context.instance_eval %{ def run_erb; #{erb.src}; end def run_erubis; #{erubis.src}; end def run_temple_erb; #{Temple::ERB::Engine.new.call @erb_code}; end def run_fast_erubis; #{fast_erubis.src}; end def run_slim_pretty; #{Slim::Engine.new(:pretty => true).call @slim_code}; end def run_slim_ugly; #{Slim::Engine.new.call @slim_code}; end } bench('(1) erb') { context.run_erb } bench('(1) erubis') { context.run_erubis } bench('(1) fast erubis') { context.run_fast_erubis } bench('(1) temple erb') { context.run_temple_erb } bench('(1) slim pretty') { context.run_slim_pretty } bench('(1) slim ugly') { context.run_slim_ugly } bench('(1) haml pretty') { context.run_haml_pretty } bench('(1) haml ugly') { context.run_haml_ugly } end def init_tilt_benches tilt_erb = Tilt::ERBTemplate.new { @erb_code } tilt_erubis = Tilt::ErubisTemplate.new { @erb_code } tilt_temple_erb = Temple::ERB::Template.new { @erb_code } tilt_haml_pretty= Tilt::HamlTemplate.new(:format => :html5){ @haml_code } tilt_haml_ugly = Tilt::HamlTemplate.new(:format => :html5, :ugly => true){ @haml_code } tilt_slim_pretty= Slim::Template.new(:pretty => true) { @slim_code } tilt_slim_ugly = Slim::Template.new { @slim_code } context = Context.new bench('(2) erb') { tilt_erb.render(context) } bench('(2) erubis') { tilt_erubis.render(context) } bench('(2) temple erb') { tilt_temple_erb.render(context) } bench('(2) slim pretty') { tilt_slim_pretty.render(context) } bench('(2) slim ugly') { tilt_slim_ugly.render(context) } bench('(2) haml pretty') { tilt_haml_pretty.render(context) } bench('(2) haml ugly') { tilt_haml_ugly.render(context) } end def init_cached_benches context = Context.new context_binding = context.instance_eval { binding } erb = ERB.new(@erb_code) erubis = Erubis::Eruby.new(@erb_code) fast_erubis = Erubis::FastEruby.new(@erb_code) temple_erb = Temple::ERB::Template.new { @erb_code } haml_pretty = Haml::Engine.new(@haml_code, :format => :html5) haml_ugly = Haml::Engine.new(@haml_code, :format => :html5, :ugly => true) slim_pretty = Slim::Template.new(:pretty => true) { @slim_code } slim_ugly = Slim::Template.new { @slim_code } bench('(3) erb') { erb.result(context_binding) } bench('(3) erubis') { erubis.result(context_binding) } bench('(3) fast erubis') { fast_erubis.result(context_binding) } bench('(3) temple erb') { temple_erb.render(context) } bench('(3) slim pretty') { slim_pretty.render(context) } bench('(3) slim ugly') { slim_ugly.render(context) } bench('(3) haml pretty') { haml_pretty.render(context) } bench('(3) haml ugly') { haml_ugly.render(context) } end def init_parsing_benches context = Context.new context_binding = context.instance_eval { binding } bench('(4) erb') { ERB.new(@erb_code).result(context_binding) } bench('(4) erubis') { Erubis::Eruby.new(@erb_code).result(context_binding) } bench('(4) fast erubis') { Erubis::FastEruby.new(@erb_code).result(context_binding) } bench('(4) temple erb') { Temple::ERB::Template.new { @erb_code }.render(context) } bench('(4) slim pretty') { Slim::Template.new(:pretty => true) { @slim_code }.render(context) } bench('(4) slim ugly') { Slim::Template.new { @slim_code }.render(context) } bench('(4) haml pretty') { Haml::Engine.new(@haml_code, :format => :html5).render(context) } bench('(4) haml ugly') { Haml::Engine.new(@haml_code, :format => :html5, :ugly => true).render(context) } end def run puts "#{@iterations} Iterations" Benchmark.bmbm do |x| @benches.each do |name, block| x.report name.to_s do @iterations.to_i.times { block.call } end end end puts " (1) Compiled benchmark. Template is parsed before the benchmark and generated ruby code is compiled into a method. This is the fastest evaluation strategy because it benchmarks pure execution speed of the generated ruby code. (2) Compiled Tilt benchmark. Template is compiled with Tilt, which gives a more accurate result of the performance in production mode in frameworks like Sinatra, Ramaze and Camping. (Rails still uses its own template compilation.) (3) Cached benchmark. Template is parsed before the benchmark. The ruby code generated by the template engine might be evaluated every time. This benchmark uses the standard API of the template engine. (4) Parsing benchmark. Template is parsed every time. This is not the recommended way to use the template engine and Slim is not optimized for it. Activate this benchmark with 'rake bench slow=1'. Temple ERB is the ERB implementation using the Temple framework. It shows the overhead added by the Temple framework compared to ERB. " end def bench(name, &block) @benches.push([name, block]) end end SlimBenchmarks.new(ENV['slow'], ENV['iterations']).run slim-2.0.0.pre.6/benchmarks/profile-render.rb0000644000175000017500000000045012121046025020001 0ustar lunarlunar#!/usr/bin/env ruby $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__)) require 'slim' require 'context' content = File.read(File.dirname(__FILE__) + '/view.slim') slim = Slim::Template.new { content } context = Context.new 10000.times { slim.render(context) } slim-2.0.0.pre.6/benchmarks/profile-parser.rb0000644000175000017500000000036312121046025020021 0ustar lunarlunar#!/usr/bin/env ruby $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__)) require 'slim' content = File.read(File.dirname(__FILE__) + '/view.slim') engine = Slim::Engine.new 1000.times { engine.call(content) } slim-2.0.0.pre.6/benchmarks/context.rb0000644000175000017500000000041012121046025016544 0ustar lunarlunarclass Context def header 'Colors' end def item [ { :name => 'red', :current => true, :url => '#red' }, { :name => 'green', :current => false, :url => '#green' }, { :name => 'blue', :current => false, :url => '#blue' } ] end end slim-2.0.0.pre.6/Rakefile0000644000175000017500000000416712121046025014100 0ustar lunarlunarbegin require 'bundler' Bundler::GemHelper.install_tasks rescue Exception end require 'rake/testtask' desc 'Run Slim benchmarks! (default parameters slow=false iterations=1000)' task :bench, :iterations, :slow do ruby('benchmarks/run-benchmarks.rb') end task 'test' => %w(test:core_and_plugins) namespace 'test' do task 'core_and_plugins' => %w(core literate logic_less translator) Rake::TestTask.new('core') do |t| t.libs << 'lib' << 'test/core' t.test_files = FileList['test/core/test_*.rb'] t.verbose = true #t.ruby_opts << '-w' << '-v' end Rake::TestTask.new('literate') do |t| t.libs << 'lib' << 'test/literate' t.test_files = FileList['test/literate/run.rb'] t.verbose = true end Rake::TestTask.new('logic_less') do |t| t.libs << 'lib' << 'test/core' t.test_files = FileList['test/logic_less/test_*.rb'] t.verbose = true end Rake::TestTask.new('translator') do |t| t.libs << 'lib' << 'test/core' t.test_files = FileList['test/translator/test_*.rb'] t.verbose = true end Rake::TestTask.new('rails') do |t| t.libs << 'lib' t.test_files = FileList['test/rails/test/test_*.rb'] t.verbose = true end begin require 'sinatra' spec = Gem::Specification.find_by_name('sinatra') Rake::TestTask.new('sinatra') do |t| # Run Slim integration test in Sinatra t.test_files = FileList["#{spec.gem_dir}/test/slim_test.rb"] t.verbose = true end rescue LoadError task :sinatra do abort 'Sinatra is not available' end end end begin require 'rcov/rcovtask' Rcov::RcovTask.new do |t| t.libs << 'lib' << 'test/slim' t.test_files = FileList['test/slim/test_*.rb'] t.verbose = true end rescue LoadError task :rcov do abort 'RCov is not available. In order to run rcov, you must: gem install rcov' end end begin require 'yard' YARD::Rake::YardocTask.new do |t| t.files = %w(lib/**/*.rb) end rescue LoadError task :yard do abort 'YARD is not available. In order to run yard, you must: gem install yard' end end desc "Generate Documentation" task :doc => :yard task :default => 'test' slim-2.0.0.pre.6/README.md0000644000175000017500000011104312121046025013702 0ustar lunarlunar# Slim [![Gem Version](https://badge.fury.io/rb/slim.png)](http://rubygems.org/gems/slim) [![Build Status](https://secure.travis-ci.org/slim-template/slim.png?branch=master)](http://travis-ci.org/slim-template/slim) [![Dependency Status](https://gemnasium.com/slim-template/slim.png?travis)](https://gemnasium.com/slim-template/slim) [![Code Climate](https://codeclimate.com/github/slim-template/slim.png)](https://codeclimate.com/github/slim-template/slim) Slim is a template language whose goal is to reduce the view syntax to the essential parts without becoming cryptic. It started as an exercise to see how much could be removed from a standard html template (<, >, closing tags, etc...). As more people took an interest in Slim, the functionality grew and so did the flexibility of the syntax. A short list of the features... * Elegant syntax * Short syntax without closing tags (Using indentation instead) * HTML style mode with closing tags * Configurable shortcut tags (`#` for `
    ` and `.` for `
    ` in the default configuration) * Safety * Automatic HTML escaping by default * Support for Rails' `html_safe?` * Highly configurable and extendable via plugins * Logic less mode similar to Mustache, realized as plugin * Translator/I18n, realized as plugin * High performance * Comparable speed to ERB/Erubis * Streaming support in Rails * Supported by all major frameworks (Rails, Sinatra, ...) * Full Unicode support for tags and attributes on Ruby 1.9 * Embedded engines like Markdown and Textile ## Upgrade to version 2.0 __NOTE:__ Slim 2.0 is not yet released, but you can try the preview versions. If you are already using Slim 1.3 or 1.2 and want to upgrade to the newest version 2.0, you should at first upgrade to Slim 1.3.7 which will emit warnings for deprecated features. This way you can easily see if your application is already Slim 2.0 compliant! Slim 2.0 removes deprecated features from the 1.3 series and cleans up some minor inconsistencies in the syntax (Attribute wrapper and quoted attribute escaping). Of course it also includes new features and bugfixes. See the CHANGES for details. In general don't be afraid of upgrading! We try to be backward compatible and follow [semantic versions](http://semver.org/) as good as possible. ## Introduction ### What is Slim? Slim is a fast, lightweight templating engine with support for __Rails 3__. It has been heavily tested on all major ruby implementations. We use continous integration (travis-ci). Slim's core syntax is guided by one thought: "What's the minimum required to make this work". As more people have contributed to Slim, there have been syntax additions influenced from their use of [Haml](https://github.com/haml/haml) and [Jade](https://github.com/visionmedia/jade). The Slim team is open to these additions because we know beauty is in the eye of the beholder. Slim uses [Temple](https://github.com/judofyr/temple) for parsing/compilation and is also integrated into [Tilt](https://github.com/rtomayko/tilt), so it can be used together with [Sinatra](https://github.com/sinatra/sinatra) or plain [Rack](https://github.com/rack/rack). The architecture of Temple is very flexible and allows the extension of the parsing and compilation process without monkey-patching. This is used by the logic less plugin and the translator plugin which provides I18n. ### Why use Slim? Within the Rails community, _Erb_ and _Haml_ are without doubt the two most popular templating engines. However, _Erb_'s syntax is cumbersome and _Haml_'s syntax can be quite cryptic to the uninitiated. There is also some development in logic-less engines (e.g. [Mustache](https://github.com/defunkt/mustache) which requires you to write standard HTML). You can also use Slim in logic-less mode if you like the Slim syntax to build your HTML but don't want to write Ruby in your templates. Slim was born to bring a minimalist syntax approach with speed. If people chose not to use Slim, it would not be because of speed. ___Yes, Slim is speedy!___ Benchmarks are done for every commit at . Don't trust the numbers? That's as it should be. Please try the benchmark rake task yourself! ### How to start? Install Slim as a gem: gem install slim Include Slim in your Gemfile with `gem 'slim'` or require it with `require 'slim'`. That's it! Now, just use the .slim extension and you're good to go. ### Syntax example Here's a quick example to demonstrate what a Slim template looks like: doctype html html head title Slim Examples meta name="keywords" content="template language" meta name="author" content=author link rel="icon" type="image/png" href=file_path("favicon.png") javascript: alert('Slim supports embedded javascript!') body h1 Markup examples #content p This example shows you how a basic Slim file looks like. = yield - if items.any? table#items - for item in items do tr td.name = item.name td.price = item.price - else p No items found Please add some inventory. Thank you! div id="footer" = render 'footer' | Copyright © #{@year} #{@author} Indentation matters, but the indentation depth can be chosen as you like. If you want to first indent 2 spaces, then 5 spaces, it's your choice. To nest markup you only need to indent by one space, the rest is gravy. ## Line indicators ### Text `|` The pipe tells Slim to just copy the line. It essentially escapes any processing. Each following line that is indented greater than the pipe is copied over. body p | This is a test of the text block. The parsed result of the above:

    This is a test of the text block.

    The left margin is set at the indent of the pipe + one space. Any additional spaces will be copied over. body p | This line is on the left margin. This line will have one space in front of it. This line will have two spaces in front of it. And so on... You can also embed html in the text line - articles.each do |a| | #{a.name}#{a.description} ### Text with trailing white space `'` The single quote tells Slim to copy the line (similar to `|`), but makes sure that a single trailing white space is appended. ### Inline html `<` (HTML style) You can write html tags directly in Slim which allows you to write your templates in a more html like style with closing tags or mix html and Slim style. head title Example - if articles.empty? - else table - articles.each do |a| #{a.name}#{a.description} ### Control code `-` The dash denotes control code. Examples of control code are loops and conditionals. `end` is forbidden behind `-`. Blocks are defined only by indentation. If your ruby code needs to use multiple lines, append a backslash `\` at the end of the lines. If your line ends with comma `,` (e.g because of a method call) you don't need the additional backslash before the linebreak. body - if articles.empty? | No inventory ### Output `=` The equal sign tells Slim it's a Ruby call that produces output to add to the buffer. If your ruby code needs to use multiple lines, append a backslash `\` at the end of the lines, for example: = javascript_include_tag \ "jquery", \ "application" If your line ends with comma `,` (e.g because of a method call) you don't need the additional backslash before the linebreak. ### Output with trailing white space `='` Same as the single equal sign (`=`), except that it adds a trailing white space. ### Output without HTML escaping `==` Same as the single equal sign (`=`), but does not go through the `escape_html` method. ### Output without HTML escaping and trailing ws `=='` Same as the double equal sign (`==`), except that it adds a trailing white space. ### Code comment `/` Use the forward slash for code comments - anything after it won't get displayed in the final render. Use `/` for code comments and `/!` for html comments body p / This line won't get displayed. Neither does this line. /! This will get displayed as html comments. The parsed result of the above:

    ### HTML comment `/!` Use the forward slash immediately followed by an exclamation mark for html comments (``). ### IE conditional comment `/[...]` /[if IE] p Get a better browser. renders as ## HTML tags ### Doctype tag The doctype tag is a special tag which can be used to generate the complex doctypes in a very simple way. XML VERSION doctype xml doctype xml ISO-8859-1 XHTML DOCTYPES doctype html doctype 5 doctype 1.1 doctype strict doctype frameset doctype mobile doctype basic doctype transitional HTML 4 DOCTYPES doctype strict doctype frameset doctype transitional ### Closed tags (trailing `/`) You can close tags explicitly by appending a trailing `/`. img src="image.png"/ Note, that this is usually not necessary since the standard html tags (img, br, ...) are closed automatically. ### Inline tags Sometimes you may want to be a little more compact and inline the tags. ul li.first: a href="/a" A link li: a href="/b" B link For readability, don't forget you can wrap the attributes. ul li.first: a[href="/a"] A link li: a[href="/b"] B link ### Text content Either start on the same line as the tag body h1 id="headline" Welcome to my site. Or nest it. You must use a pipe or a backtick to escape processing body h1 id="headline" | Welcome to my site. ### Dynamic content (`=` and `==`) Can make the call on the same line body h1 id="headline" = page_headline Or nest it. body h1 id="headline" = page_headline ### Attributes You write attributes directly after the tag. For normal text attributes you must use double `"` or single quotes `'` (Quoted attributes). a href="http://slim-lang.com" title='Slim Homepage' Goto the Slim homepage You can use text interpolation in the quoted attributes. #### Attributes wrapper If a delimiter makes the syntax more readable for you, you can use the characters `{...}`, `(...)`, `[...]` to wrap the attributes. body h1(id="logo") = page_logo h2[id="tagline" class="small tagline"] = page_tagline If you wrap the attributes, you can spread them across multiple lines: h2[id="tagline" class="small tagline"] = page_tagline You may use spaces around the wrappers and assignments: h1 id = "logo" = page_logo h2 [ id = "tagline" ] = page_tagline #### Quoted attributes Example: a href="http://slim-lang.com" title='Slim Homepage' Goto the Slim homepage You can use text interpolation in the quoted attributes: a href="http://#{url}" Goto the #{url} The attribute value will be escaped by default. Use == if you want to disable escaping in the attribute. a href=="&" You can break quoted attributes with backslash `\` a data-title="help" data-content="extremely long help text that goes on\ and one and one and then starts over...." #### Ruby attributes Write the ruby code directly after the `=`. If the code contains spaces you have to wrap the code into parentheses `(...)`. You can also directly write hashes `{...}` and arrays `[...]`. body table - for user in users do td id="user_#{user.id}" class=user.role a href=user_action(user, :edit) Edit #{user.name} a href=(path_to_user user) = user.name The attribute value will be escaped by default. Use == if you want to disable escaping in the attribute. a href==action_path(:start) You can also break ruby attributes with backslash `\` or trailing `,` as describe for control sections. #### Boolean attributes The attribute values `true`, `false` and `nil` are interpreted as booleans. If you use the attribut wrapper you can omit the attribute assigment input type="text" disabled="disabled" input type="text" disabled=true input(type="text" disabled) input type="text" input type="text" disabled=false input type="text" disabled=nil #### Attribute merging You can configure attributes to be merged if multiple are given (See option `:merge_attrs`). In the default configuration this is done for class attributes with the white space as delimiter. a.menu class="highlight" href="http://slim-lang.com/" Slim-lang.com This renders as Slim-lang.com You can also use an `Array` as attribute value and the array elements will be merged using the delimiter. a class=["menu","highlight"] a class=:menu,:highlight #### Splat attributes `*` The splat shortcut allows you turn a hash in to attribute/value pairs .card*{'data-url'=>place_path(place), 'data-id'=>place.id} = place.name renders as
    Slim's house
    You can also use methods or instance variables which return a hash as shown here: .card *method_which_returns_hash = place.name .card *@hash_instance_variable = place.name The hash attributes which support attribute merging (see Slim option `:merge_attrs`) can be given as an `Array` .first *{:class => [:second, :third]} Text renders as div class="first second third" #### Dynamic tags `*` You can create completely dynamic tags using the splat attributes. Just create a method which returns a hash with the :tag key. ruby: def a_unless_current @page_current ? {:tag => 'span'} : {:tag => 'a', :href => 'http://slim-lang.com/'} end - @page_current = true *a_unless_current Link - @page_current = false *a_unless_current Link renders as LinkLink ### Shortcuts #### Tag shortcuts You can define custom tag shortcuts by setting the option `:shortcut`. Slim::Engine.set_default_options :shortcut => {'c' => {:tag => 'container'}, '#' => {:attr => 'id'}, '.' => {:attr => 'class'} } We can use it in Slim code like this c.content Text which renders to Text #### Attribute shortcuts You can define custom shortcuts (Similar to `#` for id and `.` for class). In this example we add `&` to create a shortcut for the input elements with type attribute. Slim::Engine.set_default_options :shortcut => {'&' => {:tag => 'input', :attr => 'type'}, '#' => {:attr => 'id'}, '.' => {:attr => 'class'}} We can use it in Slim code like this &text name="user" &password name="pw" &submit which renders to In another example we add `@` to create a shortcut for the role attribute. Slim::Engine.set_default_options :shortcut => {'@' => {:attr => 'role'}, '#' => {:attr => 'id'}, '.' => {:attr => 'class'}} We can use it in Slim code like this .person@admin = person.name which renders to
    Daniel
    #### ID shortcut `#` and class shortcut `.` Similarly to Haml, you can specify the `id` and `class` attributes in the following shortcut form body h1#headline = page_headline h2#tagline.small.tagline = page_tagline .content = show_content This is the same as body h1 id="headline" = page_headline h2 id="tagline" class="small tagline" = page_tagline div class="content" = show_content ## Text interpolation Use standard Ruby interpolation. The text will be html escaped by default. body h1 Welcome #{current_user.name} to the show. | Unescaped #{{content}} is also possible. To escape the interpolation (i.e. render as is) body h1 Welcome \#{current_user.name} to the show. ## Embedded engines (Markdown, ...) Thanks to [Tilt](https://github.com/rtomayko/tilt), Slim has impressive support for embedding other template engines. Examples: coffee: square = (x) -> x * x markdown: #Header Hello from #{"Markdown!"} Second Line! Supported engines:
    FilterRequired gemsTypeDescription
    ruby:noneShortcutShortcut to embed ruby code
    javascript:noneShortcutShortcut to embed javascript code and wrap in script tag
    css:noneShortcutShortcut to embed css code and wrap in style tag
    sass:sassCompile timeEmbed sass code and wrap in style tag
    scss:sassCompile timeEmbedd scss code and wrap in style tag
    less:lessCompile timeEmbed less css code and wrap in style tag
    styl:stylCompile timeEmbed stylus css code and wrap in style tag
    coffee:coffee-scriptCompile timeCompile coffee script code and wrap in script tag
    markdown:redcarpet/rdiscount/kramdownCompile time + InterpolationCompile markdown code and interpolate #\{variables} in text
    textile:redclothCompile time + InterpolationCompile textile code and interpolate #\{variables} in text
    creole:creoleCompile time + InterpolationCompile creole code and interpolate #\{variables} in text
    wiki:, mediawiki:wikiclothCompile time + InterpolationCompile wiki code and interpolate #\{variables} in text
    rdoc:rdocCompile time + InterpolationCompile rdoc code and interpolate #\{variables} in text
    builder:builderPrecompiledEmbed builder code
    nokogiri:nokogiriPrecompiledEmbed nokogiri builder code
    erb:nonePrecompiledEmbed erb code
    The embedded engines can be configured in Slim by setting the options directly on the `Slim::Embedded` filter. Example: Slim::Embedded.default_options[:markdown] = {:auto_ids => false} ## Configuring Slim Slim and the underlying [Temple](https://github.com/judofyr/temple) framework are highly configurable. The way how you configure Slim depends a bit on the compilation mechanism (Rails or [Tilt](https://github.com/rtomayko/tilt)). It is always possible to set default options per `Slim::Engine` class. This can be done in Rails' environment files. For instance, in config/environments/development.rb you probably want: ### Default options # Indent html for pretty debugging and do not sort attributes (Ruby 1.8) Slim::Engine.set_default_options :pretty => true, :sort_attrs => false # Indent html for pretty debugging and do not sort attributes (Ruby 1.9) Slim::Engine.set_default_options pretty: true, sort_attrs: false You can also access the option hash directly: Slim::Engine.default_options[:pretty] = true ### Setting options at runtime There are two ways to set options at runtime. For Tilt templates (`Slim::Template`) you can set the options when you instatiate the template: Slim::Template.new('template.slim', optional_option_hash).render(scope) The other possibility is to set the options per thread which is interesting mostly for Rails: Slim::Engine.with_options(option_hash) do # Any Slim engines which are created here use the option_hash # For example in Rails: render :page, :layout => true end You have to be aware that the compiled engine code and the options are cached per template in Rails and you cannot change the option afterwards. # First render call Slim::Engine.with_options(:pretty => true) do render :page, :layout => true end # Second render call Slim::Engine.with_options(:pretty => false) do render :page, :layout => true # :pretty is still true because it is cached end ### Available options The following options are exposed by the `Slim::Engine` and can be set with `Slim::Engine.set_default_options`. There are a lot of them but the good thing is, that Slim checks the configuration keys and reports an error if you try to use an invalid configuration key.
    TypeNameDefaultPurpose
    String:filenilName of parsed file, set automatically by Slim::Template
    Integer:tabsize4Number of white spaces per tab (used by the parser)
    String:encoding"utf-8"Set encoding of template
    String:default_tag"div"Default tag to be used if tag name is omitted
    Hash:shortcut\{'.' => {:attr => 'class'}, '#' => {:attr => 'id'}}Attribute shortcuts
    Array<Symbol,String>:enable_enginesnil (All enabled)List of enabled embedded engines (whitelist)
    Array<Symbol,String>:disable_enginesnil (None disabled)List of disabled embedded engines (blacklist)
    Boolean:disable_capturefalse (true in Rails)Disable capturing in blocks (blocks write to the default buffer
    Boolean:disable_escapefalseDisable automatic escaping of strings
    Boolean:use_html_safefalse (true in Rails)Use String#html_safe? from ActiveSupport (Works together with :disable_escape)
    Symbol:format:xhtmlHTML output format (Possible formats :xhtml, :html4, :html5, :html)
    String:attr_quote'"'Character to wrap attributes in html (can be ' or ")
    Hash:merge_attrs\{'class' => ' '}Joining character used if multiple html attributes are supplied (e.g. class="class1 class2")
    Array<String>:hyphen_attrs%w(data)Attributes which will be hyphenated if a Hash is given (e.g. data={a:1,b:2} will render as data-a="1" data-b="2")
    Boolean:sort_attrstrueSort attributes by name
    Symbol:js_wrappernilWrap javascript by :comment, :cdata or :both. You can also :guess the wrapper based on :format.
    Boolean:prettyfalsePretty html indenting (This is slower!)
    String:indent' 'Indentation string
    Boolean:streamingfalse (true in Rails > 3.1)Enable output streaming
    Class:generatorTemple::Generators::ArrayBuffer/RailsOutputBufferTemple code generator (default generator generates array buffer)
    String:buffer'_buf' ('@output_buffer' in Rails)Variable used for buffer
    There are more options which are supported by the Temple filters but which are not exposed and are not officially supported. You have to take a look at the Slim and Temple code for that. ### Option priority and inheritance For developers who know more about Slim and Temple architecture it is possible to override default options at different positions. Temple uses an inheritance mechanism to allow subclasses to override options of the superclass. The option priorities are as follows: 1. `Slim::Template` options passed at engine instatination 2. `Slim::Template.default_options` 3. `Slim::Engine.thread_options`, `Slim::Engine.default_options` 5. Parser/Filter/Generator `thread_options`, `default_options` (e.g `Slim::Parser`, `Slim::Compiler`) It is also possible to set options for superclasses like `Temple::Engine`. But this will affect all temple template engines then. Slim::Engine < Temple::Engine Slim::Compiler < Temple::Filter ## Plugins ### Logic less mode Logic less mode is inspired by [Mustache](https://github.com/defunkt/mustache). Logic less mode uses a dictionary object e.g. a recursive hash tree which contains the dynamic content. #### Conditional If the object is not false or empty?, the content will show - article h1 = title #### Inverted conditional If the object is false or empty?, the content will show -! article p Sorry, article not found #### Iteration If the object is an array, the section will iterate - articles tr: td = title #### Lambdas Like mustache, Slim supports lambdas. = person = name The lambda method could be defined like this def lambda_method "
    #{yield(:name => 'Andrew')}
    " end You can optionally pass one or more hashes to `yield`. If you pass multiple hashes, the block will be iterated as described above. #### Dictionary access Example code: - article h1 = title The dictionary object is accessed in the order given by the `:dictionary_access`. Default order: 1. `:symbol` - If `article.respond_to?(:has_key?)` and `article.has_key?(:title)`, Slim will execute `article[:title]` 2. `:string` - If `article.respond_to?(:has_key?)` and `article.has_key?('title')`, Slim will execute `article['title']` 3. `:method` - If `article.respond_to?(:title)`, Slim will execute `article.send(:title)` 4. `:instance_variable` - If `article.instance_variable_defined?(@title)`, Slim will execute `article.instance_variable_get @title` If all the above fails, Slim will try to resolve the title reference in the same order against the parent object. In this example, the parent would be the dictionary object you are rendering the template against. As you might have guessed, the article reference goes through the same steps against the dictionary. Instance variables are not allowed in the view code, but Slim will find and use them. Essentially, you're just using dropping the @ prefix in your template. Parameterized method calls are not allowed. #### Logic less in Rails Install: $ gem install slim Require: gem 'slim', :require => 'slim/logic_less' You might want to activate logic less mode only for a few actions, you should disable logic-less mode globally at first in the configuration Slim::Engine.set_default_options :logic_less => false and activate logic less mode per render call in your action class Controller def action Slim::Engine.with_options(:logic_less => true) do render end end end #### Logic less in Sinatra Sinata has built-in support for Slim. All you have to do is require the logic less Slim plugin. This can be done in your config.ru: require 'slim/logic_less' You are then ready to rock! You might want to activate logic less mode only for a few actions, you should disable logic-less mode globally at first in the configuration Slim::Engine.set_default_options :logic_less => false and activate logic less mode per render call in your application get '/page' slim :page, :logic_less => true end #### Options
    TypeNameDefaultPurpose
    Boolean:logic_lesstrueEnable logic less mode (Enabled if 'slim/logic_less' is required)
    String:dictionary"self"Dictionary where variables are looked up
    Symbol/Array<Symbol>:dictionary_access[:symbol, :string, :method, :instance_variable]Dictionary access order (:symbol, :string, :method, :instance_variable)
    ### Translator/I18n The translator plugin provides automatic translation of the templates using Gettext, Fast-Gettext or Rails I18n. Static text in the template is replaced by the translated version. Example: h1 Welcome to #{url}! Gettext translates the string from english to german where interpolations are replaced by %1, %2, ... "Welcome to %1!" -> "Willkommen auf %1!" and renders as

    Willkommen auf slim-lang.com!

    Enable the translator plugin with require 'slim/translator' #### Options
    TypeNameDefaultPurpose
    Boolean:trtrueEnable translator (Enabled if 'slim/translator' is required)
    Symbol:tr_mode:dynamicWhen to translate: :static = at compile time, :dynamic = at runtime
    String:tr_fnDepending on installed translation libraryTranslation function, could be '_' for gettext
    ## Framework support ### Tilt Slim uses [Tilt](https://github.com/rtomayko/tilt) to compile the generated code. If you want to use the Slim template directly, you can use the Tilt interface. Tilt.new['template.slim'].render(scope) Slim::Template.new('template.slim', optional_option_hash).render(scope) Slim::Template.new(optional_option_hash) { source }.render(scope) The optional option hash can have to options which were documented in the section above. ### Sinatra
    require 'sinatra'
    require 'slim'
    
    get('/') { slim :index }
    
     __END__
    @@ index
    doctype html
    html
      head
        title Sinatra With Slim
      body
        h1 Slim Is Fun!
    
    ### Rails Rails generators are provided by [slim-rails](https://github.com/slim-template/slim-rails). slim-rails is not necessary to use Slim in Rails though. Just install Slim and add it to your Gemfile with `gem 'slim'`. Then just use the .slim extension and you're good to go. #### Streaming HTTP streaming is enabled by default if you use a Rails version which supports it. ## Tools ### Slim Command 'slimrb' The gem 'slim' comes with the small tool 'slimrb' to test Slim from the command line.
    $ slimrb --help
    Usage: slimrb [options]
        -s, --stdin                      Read input from standard input instead of an input file
            --trace                      Show a full traceback on error
        -c, --compile                    Compile only but do not run
        -r, --rails                      Generate rails compatible code (Implies --compile)
        -t, --translator                 Enable translator plugin
        -l, --logic-less                 Enable logic less plugin
        -p, --pretty                     Produce pretty html
        -o, --option [NAME=CODE]         Set slim option
        -h, --help                       Show this message
        -v, --version                    Print version
    
    Start 'slimrb', type your code and press Ctrl-d to send EOF. Example usage:
    $ slimrb
    markdown:
      First paragraph.
    
      Second paragraph.
    
      * one
      * two
      * three
    
    //Enter Ctrl-d
    <p>First paragraph </p>
    
    <p>Second paragraph </p>
    
    <ul>
    <li>one</li>
    <li>two</li>
    <li>three</li>
    </ul>
    
    ### Syntax Highlighters There are plugins for various text editors (including the most important ones - Vim, Emacs and Textmate): * [Vim](https://github.com/slim-template/vim-slim) * [Emacs](https://github.com/slim-template/emacs-slim) * [Textmate / Sublime Text](https://github.com/slim-template/ruby-slim.tmbundle) * [Espresso text editor](https://github.com/slim-template/Slim-Sugar) * [Coda](https://github.com/slim-template/Coda-2-Slim.mode) ### Template Converters (HAML, ERB, ...) * [Haml2Slim converter](https://github.com/slim-template/haml2slim) * [HTML2Slim converter](https://github.com/slim-template/html2slim) ## Testing ### Benchmarks *Yes, Slim is one of the fastest Ruby template engines out there! In production mode Slim is nearly as fast as Erubis (which is the fastest template engine). But we would be happy if you chose Slim also for any other reason, we assure you performance will not be an obstacle.* Run the benchmarks with `rake bench`. You can add the option `slow` to run the slow parsing benchmark which needs more time. You can also increase the number of iterations. rake bench slow=1 iterations=1000 We run the benchmarks for every commit on Travis-CI. Take a look at the newest benchmarking results: ### Test suite and continous integration Slim provides an extensive test-suite based on minitest. You can run the tests with 'rake test' and the rails integration tests with 'rake test:rails'. We are currently experimenting with human-readable literate tests which are written as markdown files: [TESTS.md](test/literate/TESTS.md) Travis-CI is used for continous integration testing: Slim is working well on all major Ruby implementations: * Ruby 1.8.7 * Ruby 1.9.2 * Ruby 1.9.3 * Ruby EE * JRuby * Rubinius 2.0 ## Contributing If you'd like to help improve Slim, clone the project with Git by running: $ git clone git://github.com/slim-template/slim Work your magic and then submit a pull request. We love pull requests! Please remember to test against Ruby versions 1.9.2 and 1.8.7. If you find the documentation lacking (and you probably will), help us out and update this README.md. If you don't have the time to work on Slim, but found something we should know about, please submit an issue. ## License Slim is released under the [MIT license](http://www.opensource.org/licenses/MIT). ## Authors * [Daniel Mendler](https://github.com/minad) (Lead developer) * [Andrew Stone](https://github.com/stonean) * [Fred Wu](https://github.com/fredwu) ## Discuss * [Google Group](http://groups.google.com/group/slim-template) ## Related projects Template compilation framework: * [Temple](https://github.com/judofyr/temple) Framework support: * [Rails 3 generators (slim-rails)](https://github.com/slim-template/slim-rails) Syntax highlighting: * [Vim](https://github.com/slim-template/vim-slim) * [Emacs](https://github.com/slim-template/emacs-slim) * [Textmate / Sublime Text](https://github.com/slim-template/ruby-slim.tmbundle) * [Espresso text editor](https://github.com/slim-template/Slim-Sugar) * [Coda](https://github.com/slim-template/Coda-2-Slim.mode) Template Converters (HAML, ERB, ...): * [Haml2Slim converter](https://github.com/slim-template/haml2slim) * [HTML2Slim converter](https://github.com/slim-template/html2slim) Language ports/Similar languages: * [Coffee script plugin for Slim](https://github.com/yury/coffee-views) * [Clojure port of Slim](https://github.com/chaslemley/slim.clj) * [Hamlet.rb (Similar template language)](https://github.com/gregwebs/hamlet.rb) * [Plim (Python port of Slim)](https://github.com/2nd/plim) * [Skim (Slim for Javascript)](https://github.com/jfirebaugh/skim) * [Haml (Older engine which inspired Slim)](https://github.com/haml/haml) * [Jade (Similar engine for javascript)](https://github.com/visionmedia/jade) slim-2.0.0.pre.6/LICENSE0000644000175000017500000000206512121046025013433 0ustar lunarlunarThe MIT License Copyright (c) 2010 - 2013 Slim Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. slim-2.0.0.pre.6/Gemfile0000644000175000017500000000150212121046025013714 0ustar lunarlunarsource :rubygems gemspec if ENV['TRAVIS'] || ENV['TEMPLE'] == 'master' gem 'temple', :github => 'judofyr/temple' elsif ENV['TEMPLE_PATH'] gem 'temple', :path => ENV['TEMPLE_PATH'] end if ENV['RAILS'] if ENV['RAILS'] == 'master' gem 'rails', :github => 'rails/rails' else gem 'rails', "= #{ENV['RAILS']}" end if defined?(JRUBY_VERSION) gem 'jdbc-sqlite3' gem 'activerecord-jdbc-adapter' gem 'activerecord-jdbcsqlite3-adapter' else gem 'sqlite3' end end if ENV['SINATRA'] gem 'rack-test' if ENV['SINATRA'] == 'master' gem 'sinatra', :github => 'sinatra/sinatra' else gem 'sinatra', "= #{ENV['SINATRA']}" end end gem 'rake', '>= 0.8.7' gem 'sass', '>= 3.1.0' gem 'minitest' gem 'kramdown' gem 'creole' gem 'builder' if ENV['TASK'] == 'bench' gem 'erubis' gem 'haml' end slim-2.0.0.pre.6/CHANGES0000644000175000017500000002612012121046025013417 0ustar lunarlunar2.0.0.pre.6 * IMPORTANT: Backward incompatible syntax change: '{...}' and '[...]' are not allowed as ruby attribute wrappers anymore. Use parentheses '(...)' if you want to wrap code with spaces. This allows to write arrays and hashes directly. Old: div id={'obj' + name} data=({:a => 1, :b => 2}) class=['alpha', 'beta'] New: div id=('obj' + name) data={:a => 1, :b => 2} class=['alpha', 'beta'] * IMPORTANT: Escape quoted attributes by default (Option :escape_quoted_attrs removed) Old: a href='http://slim-lang.com/?a=1&b=2' New: a href='http://slim-lang.com/?a=1&b=2' a href=='http://slim-lang.com/?a=1&b=2' You can always disable escaping completly by using :disable_escape if you don't want to write '=='. * Added hyphenation support for data attributes (Option :hyphen_attrs) Example: div data={key1_key2: 2, key1: {key3: 3}} will render as '
    ' * Add unicode support for tags and attributes (Issue #212) * Removed support for deprecated options: - Slim::Engine :remove_empty_attrs, :chain - Slim::LogicLess :wrapped dictionary - Slim::Parser :shortcut string option Slim will raise an exception if you use them! * Fixed issue #333 * Renamed options: - :attr_wrapper -> :attr_quote - :attr_delimiter -> :merge_attrs Slim will raise an exception if you use the old unsupported name. * Improved pretty printing (Issue #202) * Renamed Slim::EmbeddedEngine to Slim::Embedded * Renamed Slim::ControlStructures to Slim::Controls * Tab expansion improved (tab + space is interpreted as equivalent to tab) * Support for wrapping javascript in HTML comments or CDATA (Issue #340) * Allow spaces around attributes, e.g 'a [ href = url ] text' and 'a href = url text' 1.3.6 * Allow attribute values to be broken with `\` (Issue #331) * Tag shortcuts implemented (Issue #306) * Hash format of Slim::Parser option :shortcut changed, old configuration deprecated but still supported 1.3.5 * Logic-less: - Rewrote logic-less mode (Issue #326, #327) - Logic-less mode supports lambdas - Option :dictionary_access made more powerful, value :wrapped deprecated 1.3.4 * Fixed #314 * Logic-less test cases added 1.3.3 * Attribute handling made consistent: - Splat attributes, static and dynamic attributes are now all handled the same - Merged attributes are removed if empty (in the default configuration this is only "class") - Dynamic attributes which are not merged are checked for false or nil and removed if this is the case - Dynamic attributes which are not merged are checked for true and generated as attribute-name="attribute-name" * Rename class BooleanAttributes to CodeAttributes * Add literate test suite (still incomplete), run with `rake test:literate` * Remove UTF BOM when parsing Slim code * Fixed issue #303 1.3.2 * Fix boolean attributes #299 1.3.1 * Support inline html at the beginning of a line (New line indicator <). No pipe symbol is | necessary. It is even possible to wrap other Slim syntax in such a html block. * Code restructured - Handling of boolean and splat attributes improved and PERFORMANCE improved. * BACKWARD INCOMPATIBLE CHANGE - Dynamic attributes which return empty value "" are not removed anymore (this means "" is now interpreted as true), whereas false and nil are still removed. This corresponds to the definition of boolean attributes in XHTML and HTML5. * Deprecated option :remove_empty_attrs (TODO: Remove in 1.4.0) * Add option :escape_quoted_attrs to escape quoted attributes, use == if you don't want that. The default is false to stay backward compatible. * Use Temple::FilterError exception * Use Temple::Parser * / is not escaped anymore to / * Parser: check for missing closing quote in quoted attributes * Use new temple option validation to make Slim configuration more user friendly. * Support thread options Slim::Engine.with_options which especially useful for Rails * Add explicit column number to SyntaxError.to_s 1.3.0 * Parser wraps text blocks in [:slim, :text, ...] (Used by Translator/I18n plugin) * Added Translator/I18n plugin which uses GetText or FastGettext (require 'slim/translator') * Moved logic less mode out of the core to plugin (require 'slim/logic_less') 1.2.2 * Fix issue #264 1.2.1 * Support stylus as embedded engine * Fix issue #257 1.2.0 * Add option :shortcut which configures attribute shortcuts Default setting: Slim::Parser.default_options[:shortcut] = {'#' => 'id', '.' => 'class', '*' => '*'} Define custom shortcut attribute (e.g. a@ajax-link renders ) Slim::Parser.default_options[:shortcut] = {'@' => 'role'} Define custom shortcut attribute with tag (e.g. @ajax-link renders ) Slim::Parser.default_options[:shortcut] = {'@' => 'a role'} * Add syntax for splat attributes (#109) * Support for dynamic tags, e.g. *{:tag => 'img', :src => 'image.jpg'} 1.1.1 * Evaluating a html attribute now happens only once (#219) * Code with trailing comma is treated as broken line (#226) * Support option :remove_empty_attrs (default true) * Require temple 0.4.0 1.1.0 * Support for special characters in class/id shortcut removed * Do not allow : in class/id shortcut * Add support for block expansion syntax * Support options :indent, :sort_attrs * Require temple 0.3.5 1.0.4 * Pass options to embedded Tilt engine Slim::EmbeddedEngine.set_default_options :markdown => {...} * Add test case for precompiled embedded engine 'builder' * Bug #204 fixed, tabs were not parsed correctly 1.0.3 * Fix rubinius test cases * Fix line numbers for embedded engines * Require temple 0.3.4 * Remove dynamic embedded engines Haml, Liquid, Radius, Markaby * More thorough integration testing using travis-ci See http://travis-ci.org/#!/stonean/slim * Empty static attributes are not removed anymore * Line indicator =' is supported in tags 1.0.2 * Support for Rails 3.1 streaming (Temple > 0.3.2 required) * Switch to default format xhtml (supports all doctypes, including html5) * Improve parsing of #{interpolation} in quoted attributes (issue #159) * Use travis-ci for continous integration testing 1.0.1 * Only delimiting brackets must be balanced in ruby attributes e.g this is possible now `a href=(ruby_code "{") * Skip empty lines in text block (#156) 1.0.0 * Fixed html attribute issue in sections mode (#127) * Obsolete directive syntax removed * Syntax for trailing whitespace added (==' and =') * Deprecated file 'slim/rails.rb' removed * Parsing of #{interpolation} in markdown fixed * Support for attributes which span multiple lines * Dynamic attributes with value true/false are interpreted as boolean * Support boolean attributes without value e.g. option(selected id="abc") 0.9.3 * Allow for bypassing escaping in attributes * check if string encoding is valid * support for html conditional comments * Use new Temple html attribute expression [:html, :attrs, [:html, :attr, ...], ...] * Use new slim html attribute expression (similiar to Temple) * Option :id_delimiter replaced with :attr_delimiter * Attribute value merging improved (nil/empty values are ignored now) * Arrays attribute values are joined * Boolean attributes (e.g. selected=true is converted to selected="selected") * Option :debug removed * Slim expression grammar provided, Temple validator used in tests * Option :auto_escape replaced with inverse option :disable_escape * Require temple 0.3.0 0.9.2 * add SassEngine which respects :pretty * embedded engine code refactored * temple supports denser template registration * deprecate slim/rails (just require 'slim') * use temple rails and tilt templates * add encoding option to Slim::Parser/Slim::Engine to enforce template encoding * vim support is now an external project 0.9.1 * add new doctype syntax without ! * slim directive expression has type and args 0.9.0 * slim should not be registered as the default template handler. * add support for unescaped text interpolation 0.8.4 * Added the option to turn off automatic HTML escaping. * update to tilt 1.2.2 * allow call to yield in logic less mode * allow doctype declaration to be capitalized 0.8.3 * Added support for html comments. The parser uses the :static filter instead of the :comment filter due to the way the parser is constructed. 0.8.2 * fix issue #96 * Added the Temple Debugger filter. * Rails problems fixed 0.8.1 * remove backtick slim syntax -- no longer supported * slim executable conflict. issue #91 * vim syntax support improved 0.8.0 * rails logic less support 0.7.4 * use ' for text block with trailing whitespace * allow to disable/enable embedded engines 0.7.3 * fix #82 * basic rails test added 0.7.2 * get rid of rails deprecation warning * use_html_safe is activated automatically by temple 0.7.1 * logic less mode * add syntax for explicitly closed tags 0.7.0 * slim-mode.el for emacs added (modified haml-mode.el, needs some work to be fully functional for slim) * embedded engines * escape interpolated strings/attributes * Slim#Filter now uses optional configuration hash * Initial implementation for Rail's `html_safe`. Closes #25 * fallback to escape_html stolen from cgi.rb if escape_utils is unavailable, use normal requires because slim is on the load path * Limit the allowed characters used for attributes delimiters (now only allows parentheses, square brackets and curly braces). See #16 for more info. * Default to HTML5-mode * Slim now uses Temple and Tilt. * Choose your own attribute delimiter! 0.6.1 * can wrap parens around attributes if you so desire * added erubis to the benchmarks 0.6.0 * Added slim itself, haml and mustache to the development env for easier benchmarking. * added escape_html functionality. need to tweak for speed 0.5.1 * Consecutive condition statements now working as expected. 0.5.0 * Added 'unless' to the list of control words. * Fixes for inline conditions. There must be a better way of doing this?? * '-' is a valid character in HTML attributes, so let's allow that. * Improved the regex so that control code now supports code blocks. * Output code (start with '=') can now accept code blocks. * Method calls no longer need parenthesis. We need more tests to ensure the implementation's robustness. 0.4.1 * Added '|' as an alias of '`' for parsing plain text. This simulates the syntax of the Jade template engine. * Added instructions of how to use the gem. 0.4.0 * support for nesting lines under backtick * make it so that one space is the left margin. any additional spaces will be copied over * support for using indentation after backtick to denote paragraphs. useful for script tags and paragraphs 0.3.1 * fix bug with adding end to nesting ruby code 0.3.0 * Optimize compiled string to reduce number of concatentations to the buffer 0.2.0 * can now make code call on same line as tag 0.1.0 * Initial release slim-2.0.0.pre.6/.yardopts0000644000175000017500000000014112121046025014265 0ustar lunarlunar--markup-provider redcarpet --markup markdown - README.md CHANGES LICENSE test/literate/TESTS.md slim-2.0.0.pre.6/.travis.yml0000644000175000017500000000170412121046025014536 0ustar lunarlunarlanguage: ruby rvm: - 1.8.7 - 1.9.3 - ruby-head - jruby-18mode - jruby-19mode - rbx-18mode - rbx-19mode env: - "TASK=test:core_and_plugins" - "TASK=test:rails RAILS=master" - "TASK=test:rails RAILS=3.0.19" - "TASK=test:rails RAILS=3.1.10" - "TASK=test:rails RAILS=3.2.11" - "TASK=test:sinatra SINATRA=master" - "TASK=test:sinatra SINATRA=1.3.3" - "TASK=bench iterations=10000" - "TASK=bench slow=1 iterations=1000" matrix: exclude: # Test Rails master only on 1.9.3+ Rubies - rvm: 1.8.7 env: "TASK=test:rails RAILS=master" - rvm: jruby-18mode env: "TASK=test:rails RAILS=master" - rvm: rbx-18mode env: "TASK=test:rails RAILS=master" allow_failures: - env: "TASK=test:rails RAILS=master" - env: "TASK=test:sinatra SINATRA=master" - rvm: ruby-head # Rails master needs newest bundler before_install: - ./kill-travis.sh - gem install bundler --pre script: "bundle exec rake $TASK" slim-2.0.0.pre.6/.gitignore0000644000175000017500000000017112121046025014412 0ustar lunarlunar*.swp *.gem readme.html Gemfile.lock .bundle .redcar .rvmrc .yardoc doc coverage pkg test/rails/log/ test/rails/tmp/