slim-3.0.6/0000755000004100000410000000000012555545227012530 5ustar www-datawww-dataslim-3.0.6/Rakefile0000644000004100000410000000454612555545227014206 0ustar www-datawww-databegin require 'bundler/setup' Bundler::GemHelper.install_tasks rescue Exception end require 'rake/testtask' desc 'Run Slim benchmarks! (default parameters slow=false)' task :bench, :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 smart include) 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('smart') do |t| t.libs << 'lib' << 'test/core' t.test_files = FileList['test/smart/test_*.rb'] t.verbose = true end Rake::TestTask.new('include') do |t| t.libs << 'lib' << 'test/core' t.test_files = FileList['test/include/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| file = "#{spec.gem_dir}/test/slim_test.rb" if Sinatra::VERSION =~ /\A1\.3/ # FIXME: Rename deprecated attribute code = File.read(file) code.gsub!('attr_wrapper', 'attr_quote') File.open(file, 'w') {|out| out.write(code) } end # Run Slim integration test in Sinatra t.test_files = FileList[file] t.verbose = true end rescue LoadError task :sinatra do abort 'Sinatra is not available' end 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-3.0.6/bin/0000755000004100000410000000000012555545227013300 5ustar www-datawww-dataslim-3.0.6/bin/slimrb0000755000004100000410000000016712555545227014522 0ustar www-datawww-data#!/usr/bin/env ruby $:.unshift File.dirname(__FILE__) + '/../lib' require 'slim/command' Slim::Command.new(ARGV).run slim-3.0.6/Gemfile0000644000004100000410000000254412555545227014030 0ustar www-datawww-datasource 'https://rubygems.org/' gemspec if ENV['TRAVIS'] || ENV['TEMPLE'] == 'master' gem 'temple', github: 'judofyr/temple' end if ENV['TILT'] if ENV['TILT'] == 'master' gem 'tilt', github: 'rtomayko/tilt' else gem 'tilt', "= #{ENV['TILT']}" end end if ENV['RAILS'] # we need some smarter test logic for the different Rails versions gem 'nokogiri' if ENV['RAILS'] == 'master' gem 'rails', github: 'rails/rails' else gem 'rails', "= #{ENV['RAILS']}" end end #Choose minitest 4.7.x for sinatra < 1.4.6 or rails 3 and 4.0 otherwise go for newer version if (ENV['SINATRA'] && ENV['SINATRA'] < '1.4.6') || (ENV['RAILS'] && ENV['RAILS'].match(/^(3|4\.0)/)) gem 'minitest', '~> 4.7.4' else gem 'minitest', '~> 5.1' end #Ruby >= 2.2.0 has removed test/unit from Stdlib if RUBY_VERSION >= '2.2.0' gem 'test-unit', platforms: :mri end if RUBY_ENGINE == 'rbx' && !ENV['TRAVIS'] gem 'psych' 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 'kramdown' gem 'creole' gem 'builder' gem 'asciidoctor' gem 'org-ruby' if ENV['TASK'] == 'bench' gem 'benchmark-ips' gem 'erubis' gem 'haml' end if ENV['CODECLIMATE_REPO_TOKEN'] gem 'codeclimate-test-reporter' end slim-3.0.6/doc/0000755000004100000410000000000012555545227013275 5ustar www-datawww-dataslim-3.0.6/doc/include.md0000644000004100000410000000104512555545227015242 0ustar www-datawww-data# Include The include plugin allows Slim templates to include other files. The .slim extension is appended automatically to the filename. If the included file is not a Slim file, it is interpreted as a text file with `#{interpolation}`. Example: include partial.slim include partial include partial.txt Enable the include plugin with require 'slim/include' # Options | Type | Name | Default | Purpose | | ---- | ---- | ------- | ------- | | Boolean | :include_dirs | [Dir.pwd, '.'] | Directories where to look for the files | slim-3.0.6/doc/logic_less.md0000644000004100000410000000741112555545227015745 0ustar www-datawww-data# 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. ## Strings The `self` keyword will return the `.to_s` value for the element under consideration. Given { article: [ 'Article 1', 'Article 2' ] } And - article tr: td = self This will yield Article 1 Article 2 ## 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_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_options logic_less: false and activate logic less mode per render call in your application get '/page' slim :page, logic_less: true end ## Options | Type | Name | Default | Purpose | | ---- | ---- | ------- | ------- | | Boolean | :logic_less | true | Enable 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) | slim-3.0.6/doc/smart.md0000644000004100000410000000660612555545227014755 0ustar www-datawww-data# Smart text The easiest way to combine text and markup is to use the smart text mode. Enable the smart text plugin with require 'slim/smart' This automatically enables the `:implicit_text` option as well, so you can easily type text like this: p This is text. This is text, too. Slim will automatically treat any line which doesn't start with a lowercase tag name or any of the special characters as an implicit text line. If the text spans several lines, simply indent them. p This is text, and it spans several lines. You can also mark the text explicitly with `>`, for example when it starts with lowercase letter or unusual character, or when the text spans several lines, or merely for aesthetic consistency, or if you want to use uppercase tag names and therefore need to keep the `:implicit_text` option disabled. p > 'This is text, too.' p > This is text which spans several lines. As long as you leave the `:smart_text_escaping` enabled, any non-verbatim text is automatically escaped for you. However, for your convenience, any HTML entities detected are still used verbatim. This way you are most likely to get what you really wanted, without having to worry about HTML escaping all the time. h1 Questions & Answers footer Copyright © #{Time.now.year} Another cool thing about smart text is that it mixes fairly well with markup. Smart text lines normally preserve newlines, so it is easy to mix them with other tags, like emphasis or links: p Your credit card strong will not > be charged now. p Check a href=r(:faq) our FAQ > for more info. (Note the use of the explicit text indicator `>` to distinguish lowercase text from tags). However, sometimes you do not want the whitespace around the inline tag. Fortunately smart text takes care of the most common cases for you as well. The leading newline is suppressed if the smart text block begins with a character from the `:smart_text_begin_chars` set (`,.;:!?)]}` by default). Similarly, trailing newline is suppressed if the smart text block ends with a character from the `:smart_text_end_chars` set (`([{` by default). This makes it quite easy to mix normal text with links or spans like this: p Please proceed to a href="/" our homepage . p Status: failed ( a href="#1" details ). Note that smart text is smart enough to know about tag shortcuts, too, so it will correctly deal even with cases like this: .class #id #{'More'} i text ... Of course, all this is meant only to make working with short text snippets more convenient. For bulk text content, you are more than welcome to use one of the builtin embedded engines, such as Markdown or Textile. ## Options | Type | Name | Default | Purpose | | ---- | ---- | ------- | ------- | | Boolean | :implicit_text | true | Enable implicit text recognition | | Boolean | :smart_text | true | Enable smart text mode newline processing | | String | :smart_text_begin_chars | ',.;:!?)]}' | Characters suppressing leading newline in smart text | | String | :smart_text_end_chars | '([{' | Characters suppressing trailing newline in smart text | | Boolean | :smart_text_escaping | true | When set, HTML characters which need escaping are automatically escaped in smart text | slim-3.0.6/doc/jp/0000755000004100000410000000000012555545227013706 5ustar www-datawww-dataslim-3.0.6/doc/jp/include.md0000644000004100000410000000133612555545227015656 0ustar www-datawww-data# インクルード インクルードプラグインを使うことで, Slim テンプレートに他の Slim ファイルを読み込むことができます。.slim 拡張子はファイル名に自動的に付加されます。 読み込まれたファイルが Slim でない場合は `#{文字列展開}` を含んだテキストファイルとして扱われます。 例: include partial.slim include partial include partial.txt インクルードプラグインを有効化 require 'slim/include' # オプション | タイプ | 名前 | デフォルト値 | 目的 | | ------ | ---- | ------------ | ---- | | Boolean | :include_dirs | [Dir.pwd, '.'] | ファイルを検索するディレクトリ | slim-3.0.6/doc/jp/logic_less.md0000644000004100000410000001154112555545227016355 0ustar www-datawww-data# ロジックレスモード ロジックレスモードは [Mustache](https://github.com/defunkt/mustache) にインスパイアされています。ロジックレスモードは 例えば動的コンテンツを含む再帰的ハッシュツリーのような辞書オブジェクトを使います。 ## 条件付き オブジェクトが false または empty? ではない場合, コンテンツが表示されます。 - article h1 = title ## 反転条件付き オブジェクトが false または empty? の場合, コンテンツが表示されます。 -! article p Sorry, article not found ## 繰り返し オブジェクトが配列の場合, この部分は繰り返されます。 - articles tr: td = title ## ラムダ式 Mustache のように, Slim はラムダ式をサポートします。 = person = name ラムダ式は次のように定義できます: def lambda_method "
#{yield(name: 'Andrew')}
" end 任意に 1 つ以上のハッシュを `yield` に渡すことができます。複数のハッシュを渡した場合, 先述したようにブロックが繰り返されます。 ## 辞書アクセス サンプルコード: - article h1 = title 辞書オブジェクトは `:dictionary_access` オプションによって設定された順序でアクセスされます。デフォルトの順序: 1. `シンボル` - `article.respond_to?(:has_key?)` 且つ `article.has_key?(:title)` の場合, Slim は `article[:title]` を実行します。 2. `文字列` - `article.respond_to?(:has_key?)` 且つ `article.has_key?('title')` の場合, Slim は `article['title']` を実行します。 3. `メソッド` - `article.respond_to?(:title)` の場合, Slim は `article.send(:title)` を実行します。 4. `インスタンス変数` - `article.instance_variable_defined?(@title)` の場合, Slim は `article.instance_variable_get @title` を実行します。 すべて失敗した場合, Slim は親オブジェクトに対して同じ順序で title の参照を解決しようとします。この例では, 親オブジェクトはレンダリングしているテンプレートに対する辞書オブジェクトになります。 ご想像のとおり, article への参照は辞書オブジェクトに対して同じ手順で行われます。インスタンス変数はビューのコードでは利用を許されていませんが, Slim はそれを見つけて使います。基本的には, テンプレートの中で @ プレフィックスを落として使っています。パラメータ付きメソッドの呼び出しは許可されません。 ## 文字列 `self` キーワードは検討中の要素を `.to_s` した値を返します。 辞書オブジェクトを与え, { article: [ 'Article 1', 'Article 2' ] } ビューで次のように - article tr: td = self これは次のようになります。 Article 1 Article 2 ## Rails でロジックレスモード インストール: $ gem install slim require で指定: gem 'slim', require: 'slim/logic_less' 特定のアクションでのみロジックレスモードを有効化したい場合, まず設定でロジックレスモードを global に無効化します。 Slim::Engine.set_options logic_less: false さらに, アクションの中でレンダリングする度にロジックレスモードを有効化します。 class Controller def action Slim::Engine.with_options(logic_less: true) do render end end end ## Sinatra でロジックレスモード Sinatra には Slim のビルトインサポートがあります。しなければならないのはロジックレス Slim プラグインを require することです。config.ru で require できます: require 'slim/logic_less' これで準備は整いました! 特定のアクションでのみロジックレスモードを有効化したい場合, まず設定でロジックレスモードを global に無効化します。 Slim::Engine.set_options logic_less: false さらに, アクションの中でレンダリングする度にロジックレスモードを有効化します。 get '/page' slim :page, logic_less: true end ## オプション | 種類 | 名前 | デフォルト | 用途 | | ---- | ---- | ------- | ------- | | 真偽値 | :logic_less | true | ロジックレスモードを有効化 ('slim/logic_less' の required が必要) | | 文字列 | :dictionary | "self" | 変数が検索される辞書への参照 | | シンボル/配列<シンボル> | :dictionary_access | [:symbol, :string, :method, :instance_variable] | 辞書のアクセス順序 (:symbol, :string, :method, :instance_variable) | slim-3.0.6/doc/jp/smart.md0000644000004100000410000001041612555545227015360 0ustar www-datawww-data# スマートテキスト テキストとマークアップを組み合わせる最も簡単な方法は スマートテキストモード を使うことです。 スマートテキストプラグインを有効化します。 require 'slim/smart' 自動的に `:implicit_text` オプションが有効になることで, 次のように簡単にテキストを入力できるようになります: p This is text. 小文字のタグ名や暗黙的なテキスト行などの特殊文字で始まっていない行を Slim に自動的に処理させることができます。 テキストが複数行にわたる場合, 単にそれらをインデントします。 p This is text, and it spans several lines. `>` を使って明示的にテキストをマークすることもできます。 例えば, 小文字や特殊文字で始まっている場合, テキストが複数行にわたる場合, 単に見た目の一貫性のために, タグ名に大文字を使いたい場合, `:implicit_text` オプションを無効にしたままにする必要がある場合です。 p > 'This is text, too.' p > This is text which spans several lines. `:smart_text_escaping` が有効化されている限り, エスケープされるべきテキストは自動的にエスケープされます。 しかし, 不便にならないように検出された HTML エンティティはそのまま使われます。 この方法はいつでも HTML のエスケープを気にすることのない, 最も理想的な方法です。 h1 Questions & Answers footer Copyright © #{Time.now.year} スマートテキストの素晴らしいところの 1 つはマークアップとよくミックスしているところです。 スマートテキストの行は通常改行を維持するので, 強調やリンクのような他のタグを簡単に混ぜ合わせて使うことができます: p Your credit card strong will not > be charged now. p Check a href=r(:faq) our FAQ > for more info. (タグから小文字のテキストを区別する場合明示的なテキストを示すインジケーター `>` の使用には注意してください)。 インラインタグのまわりにスペースを入れたくない場合があります。 幸いなことにスマートテキストはこの一般的なケースを処理できます。 スマートテキストのブロックが `:smart_text_begin_chars` で指定 (デフォルトは `,.;:!?)]}`) された文字で始まる場合には先頭の改行が行われません。 同様に, スマートテキストのブロックが `:smart_text_begin_chars` で指定 (デフォルトは `,.;:!?)]}`) された文字で終わる場合には改行されません。 これによって通常のテキストとリンクや span タグを混在させることがとても容易になります: p Please proceed to a href="/" our homepage . p Status: failed ( a href="#1" details ). スマートテキストはタグのショートカットをも把握しているので, 次のような場合にも正しく対応します: .class #id #{'More'} i text ... 当然のことながら, これは短いテキストのスニペットでより便利に作業できることを意味しています。 ほとんどがテキストのコンテンツの場合, Markdown や Textile のような ビルトインの埋め込みエンジンを使う方が良いでしょう。 ## オプション | 種類 | 名前 | デフォルト | 用途 | | ---- | ---- | ---------- | ---- | | 真偽値 | :implicit_text | true | 暗黙的テキストの判別を有効化 | | 真偽値 | :smart_text | true | スマートテキストによる処理を有効化 | | 文字列 | :smart_text_begin_chars | ',.;:!?)]}' | スマートテキストで先頭の改行を抑制する文字 | | 文字列 | :smart_text_end_chars | '([{' | スマートテキストで末尾の改行を抑制する文字 | | 真偽値 | :smart_text_escaping | true | 設定すると, スマートテキスト中のエスケープが必要な HTML 文字は自動的にエスケープされる | slim-3.0.6/doc/jp/translator.md0000644000004100000410000000207712555545227016427 0ustar www-datawww-data# 翻訳/I18n 翻訳プラグインは Gettext, Fast-Gettext または Rails I18n を使ったテンプレートの自動翻訳機能を提供します。 テンプレート内の静的テキストを翻訳版に変換します。 例: h1 Welcome to #{url}! Gettext は文字列を英語からドイツ語に変換し, 文字列が展開される部分は %1, %2, ... の順に変換されます。 "Welcome to %1!" -> "Willkommen auf %1!" 次のようにレンダリングされます。

Willkommen auf slim-lang.com!

翻訳プラグインを有効化します。 require 'slim/translator' # オプション | 種類 | 名前 | デフォルト | 用途 | | ---- | ---- | ---------- | ---- | | 真偽値 | :tr | true | 翻訳の有効化 ('slim/translator' の required が必要) | | シンボル | :tr_mode | :dynamic | 翻訳を :static = コンパイル時に実施, :dynamic = ランタイムで実施 | | 文字列 | :tr_fn | インストールされた翻訳ライブラリに依存 | 翻訳用ヘルパ, gettext の場合 '_' | slim-3.0.6/doc/translator.md0000644000004100000410000000160412555545227016011 0ustar www-datawww-data# 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 | Type | Name | Default | Purpose | | ---- | ---- | ------- | ------- | | Boolean | :tr | true | Enable translator (Enabled if 'slim/translator' is required) | | Symbol | :tr_mode | :dynamic | When to translate: :static = at compile time, :dynamic = at runtime | | String | :tr_fn | Depending on installed translation library | Translation function, could be '_' for gettext | slim-3.0.6/.travis.yml0000644000004100000410000000272712555545227014651 0ustar www-datawww-datalanguage: ruby rvm: - ruby-head - 2.2.2 - 2.1.6 - 2.0.0 - rbx-2 - 1.9.3 - jruby-head - jruby-19mode sudo: false script: "bundle exec rake $TASK" env: global: # travis encrypt CODECLIMATE_REPO_TOKEN=??? - secure: "a7sD9iwPJJn3Fj+mn62GAmy/PEguh3elrilsp1KS+WfDiCiIKD8Q5KG2Jv67DGcQAGI3dPWeh7+ZhZ/W7nEipwWUBmSvGYVeoF63y8j6mNRLeekqspj94l47hXyFePj9bCadY1b1/xY4lE1pMEU8eA8AOUHUqCSuH+Kk/MuvyLM=" matrix: - "TASK=test:core_and_plugins TILT=master" - "TASK=test:core_and_plugins TILT=1.3.7" - "TASK=test:core_and_plugins TILT=1.4.1" - "TASK=test:core_and_plugins TILT=2.0.1" - "TASK=test:rails RAILS=master" - "TASK=test:rails RAILS=3.1.12 TILT=1.3.4" - "TASK=test:rails RAILS=3.2.21 TILT=1.3.4" - "TASK=test:rails RAILS=4.0.13" - "TASK=test:rails RAILS=4.1.10" - "TASK=test:rails RAILS=4.2.1" - "TASK=test:sinatra SINATRA=master" - "TASK=test:sinatra SINATRA=1.3.6" - "TASK=test:sinatra SINATRA=1.4.6" - "TASK=bench" - "TASK=bench slow=1" matrix: exclude: - rvm: rbx-2 env: "TASK=test:rails RAILS=master" - rvm: 1.9.3 env: "TASK=test:rails RAILS=master" - rvm: 2.0.0 env: "TASK=test:rails RAILS=master" allow_failures: - env: "TASK=test:core_and_plugins TILT=master" - env: "TASK=test:rails RAILS=master" - env: "TASK=test:sinatra SINATRA=master" - rvm: ruby-head - rvm: jruby-19mode - rvm: jruby-head notifications: irc: "chat.freenode.net#slim-lang"slim-3.0.6/lib/0000755000004100000410000000000012555545227013276 5ustar www-datawww-dataslim-3.0.6/lib/slim/0000755000004100000410000000000012555545227014242 5ustar www-datawww-dataslim-3.0.6/lib/slim/erb_converter.rb0000644000004100000410000000047612555545227017435 0ustar www-datawww-datarequire 'slim' module Slim # Slim to ERB converter # # @example Conversion # Slim::ERBConverter.new(options).call(slim_code) # outputs erb_code # # @api public class ERBConverter < Engine replace :StaticMerger, Temple::Filters::CodeMerger replace :Generator, Temple::Generators::ERB end end slim-3.0.6/lib/slim/embedded.rb0000644000004100000410000001752712555545227016334 0ustar www-datawww-datamodule 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, @tag = [], '', "%#{object_id.abs.to_s(36)}%" super(exp) @collected end def on_static(text) @collected << text nil end def on_slim_output(escape, text, content) @collected << @tag @protect << [:slim, :output, escape, text, content] nil end def unprotect(text) block = [:multi] while text =~ /#{@tag}/ block << [:static, $`] block << @protect.shift text = $' end block << [:static, text] end end # Temple filter which processes embedded engines # @api private class Embedded < Filter @engines = {} class << self attr_reader :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 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 create(name, options) constructor = engines[name] || raise(Temple::FilterError, "Embedded engine #{name} not found") constructor.call(options) end 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(&:to_sym) 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 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_options tag: :script, attributes: {} def on_slim_embedded(engine, body) super(engine, [:html, :js, body]) end end # Embeds ruby code class RubyEngine < Engine def on_slim_embedded(engine, body) [:multi, [:newline], [:code, collect_text(body)]] end end # These engines are executed at compile time, embedded ruby is interpolated register :asciidoc, InterpolateTiltEngine register :markdown, InterpolateTiltEngine register :textile, InterpolateTiltEngine register :rdoc, InterpolateTiltEngine register :creole, InterpolateTiltEngine register :wiki, InterpolateTiltEngine register :mediawiki, InterpolateTiltEngine register :org, InterpolateTiltEngine # These engines are executed at compile time register :coffee, JavaScriptEngine, engine: TiltEngine register :opal, JavaScriptEngine, engine: TiltEngine register :less, TagEngine, tag: :style, attributes: { type: 'text/css' }, engine: TiltEngine register :styl, TagEngine, tag: :style, attributes: { type: 'text/css' }, engine: TiltEngine 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-3.0.6/lib/slim/grammar.rb0000644000004100000410000000105712555545227016220 0ustar www-datawww-datamodule Slim # Slim expression grammar # @api private module Grammar extend Temple::Grammar TextTypes << :verbatim | :explicit | :implicit | :inline Expression << [:slim, :control, String, Expression] | [:slim, :output, Bool, String, Expression] | [:slim, :interpolate, String] | [:slim, :embedded, String, Expression] | [:slim, :text, TextTypes, Expression] | [:slim, :attrvalue, Bool, String] HTMLAttr << [:slim, :splat, String] end end slim-3.0.6/lib/slim/interpolation.rb0000644000004100000410000000211312555545227017453 0ustar www-datawww-datamodule 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#\{((?>[^{}]|(\{(?>[^{}]|\g<1>)*\}))*)\}/ # Interpolation string, code = $', $1 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 end end slim-3.0.6/lib/slim/end_inserter.rb0000644000004100000410000000362212555545227017253 0ustar www-datawww-datamodule 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 IF_RE = /\A(if|unless|else|elsif|when|rescue|ensure)\b|\bdo\s*(\|[^\|]*\|)?\s*$/ ELSE_RE = /\A(else|elsif|when|rescue|ensure)\b/ END_RE = /\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_RE # 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_RE # Indent if the control code starts a block. prev_indent = exp[2] =~ IF_RE 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-3.0.6/lib/slim/logic_less.rb0000644000004100000410000000021312555545227016706 0ustar www-datawww-datarequire 'slim' require 'slim/logic_less/filter' require 'slim/logic_less/context' Slim::Engine.after Slim::Interpolation, Slim::LogicLess slim-3.0.6/lib/slim/parser.rb0000644000004100000410000004072412555545227016072 0ustar www-datawww-data# 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, code_attr_delims: { '(' => ')', '[' => ']', '{' => '}', }, attr_list_delims: { '(' => ')', '[' => ']', '{' => '}', }, 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 @attr_list_delims = options[:attr_list_delims] @code_attr_delims = options[:code_attr_delims] 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]].flatten raise ArgumentError, 'You can only use special characters for attribute shortcuts' if k =~ /(\p{Word}|-)/ end end keys = Regexp.union @attr_shortcut.keys.sort_by {|k| -k.size } @attr_shortcut_re = /\A(#{keys}+)((?:\p{Word}|-)*)/ keys = Regexp.union @tag_shortcut.keys.sort_by {|k| -k.size } @tag_re = /\A(?:#{keys}|\*(?=[^\s]+)|(\p{Word}(?:\p{Word}|:|-)*\p{Word}|\p{Word}+))/ keys = Regexp.escape @code_attr_delims.keys.join @code_attr_delims_re = /\A[#{keys}]/ keys = Regexp.escape @attr_list_delims.keys.join @attr_list_delims_re = /\A\s*([#{keys}])/ @embedded_re = /\A(#{Regexp.union(Embedded.engines.keys.map(&:to_s))}):(\s*)/ keys = Regexp.escape ('"\'> @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.size > 1 @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, :verbatim, 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 verbatim text block. trailing_ws = $1 == "'" @stacks.last << [:slim, :text, :verbatim, parse_text_block($', @indents.last + $2.size + 1)] @stacks.last << [:static, ' '] if trailing_ws when /\A]*)/ # Found an output block. # We expect the line to be broken or the next line to be indented. @line = $' trailing_ws = $2.include?('>') if $2.include?('\'') deprecated_syntax '=\' for trailing whitespace is deprecated in favor of =>' trailing_ws = true end block = [:multi] @stacks.last << [:static, ' '] if $2.include?('<') @stacks.last << [:slim, :output, $1.empty?, parse_broken_line, block] @stacks.last << [:static, ' '] if trailing_ws @stacks << block when @embedded_re # Embedded template detected. It is treated as block. @stacks.last << [:slim, :embedded, $1, parse_text_block($', @orig_line.size - $'.size + $2.size)] when /\Adoctype\b/ # Found doctype declaration @stacks.last << [:html, :doctype, $'.strip] when @tag_re # Found a HTML tag. @line = $' if $1 parse_tag($&) else unknown_line_indicator end @stacks.last << [:newline] end # Unknown line indicator found. Overwrite this method if # you want to add line indicators to the Slim parser. # The default implementation throws a syntax error. def unknown_line_indicator syntax_error! 'Unknown line indicator' end def parse_comment_block while !@lines.empty? && (@lines.first =~ /\A\s*\Z/ || get_indent(@lines.first) > @indents.last) next_line @stacks.last << [:newline] end end def parse_text_block(first_line = nil, text_indent = nil) 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 text_indent += offset offset = 0 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 # Find any shortcut attributes attributes = [:html, :attrs] 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 syntax_error!('Illegal shortcut') unless shortcut = @attr_shortcut[$1] shortcut.each {|a| attributes << [:html, :attr, a, [:static, $2]] } @line = $' end @line =~ /\A[<>']*/ @line = $' trailing_ws = $&.include?('>') if $&.include?('\'') deprecated_syntax 'tag\' for trailing whitespace is deprecated in favor of tag>' trailing_ws = true end leading_ws = $&.include?('<') parse_attributes(attributes) tag = [:html, :tag, tag, attributes] @stacks.last << [:static, ' '] if leading_ws @stacks.last << tag @stacks.last << [:static, ' '] if trailing_ws case @line when /\A\s*:\s*/ # Block expansion @line = $' if @line =~ @embedded_re tag << [:slim, :embedded, $1, parse_text_block($', @orig_line.size - @line.size + $2.size)] else (@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) end when /\A\s*=(=?)(['<>]*)/ # Handle output code @line = $' trailing_ws2 = $2.include?('>') if $2.include?('\'') deprecated_syntax '=\' for trailing whitespace is deprecated in favor of =>' trailing_ws2 = true end block = [:multi] @stacks.last.insert(-2, [:static, ' ']) if !leading_ws && $2.include?('<') tag << [:slim, :output, $1 != '=', parse_broken_line, block] @stacks.last << [:static, ' '] if !trailing_ws && trailing_ws2 @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 ?/ # Text content tag << [:slim, :text, :inline, parse_text_block($', @orig_line.size - $'.size)] end end def parse_attributes(attributes) # Check to see if there is a delimiter right after the tag name delimiter = nil if @line =~ @attr_list_delims_re delimiter = @attr_list_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, [:multi]] 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 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 =~ @code_attr_delims_re count = 1 delimiter, close_delimiter = $&, @code_attr_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 count == 0 && @line[0] == quote[0] if @line =~ /\A(\\)?\Z/ value << ($1 ? ' ' : "\n") expect_next_line else if @line[0] == ?{ count += 1 elsif @line[0] == ?} count -= 1 end value << @line.slice!(0) end end @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) rescue SyntaxError => ex # HACK: Manipulate stacktrace for Rails and other frameworks # to find the right file. ex.backtrace.unshift "#{options[:file]}:#{@lineno}" raise end def deprecated_syntax(message) line = @orig_line.lstrip column = (@orig_line && @line ? @orig_line.size - @line.size : 0) + line.size - @orig_line.size warn %{Deprecated syntax: #{message} #{options[:file]}, Line #{@lineno}, Column #{@column} #{line} #{' ' * column}^ } end def expect_next_line next_line || syntax_error!('Unexpected end of file') @line.strip! end end end slim-3.0.6/lib/slim/engine.rb0000644000004100000410000000300012555545227016025 0ustar www-datawww-data# The Slim module contains all Slim related classes (e.g. Engine, Parser). # Plugins might also reside within the Slim module (e.g. Include, Smart). # @api public module 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, format: :xhtml, attr_quote: '"', merge_attrs: {'class' => ' '}, generator: Temple::Generators::ArrayBuffer, default_tag: 'div' filter :Encoding filter :RemoveBOM use Slim::Parser use Slim::Embedded use Slim::Interpolation use Slim::Splat::Filter use Slim::DoInserter use Slim::EndInserter use Slim::Controls html :AttributeSorter html :AttributeMerger use Slim::CodeAttributes use(:AttributeRemover) { Temple::HTML::AttributeRemover.new(remove_empty_attrs: options[:merge_attrs].keys) } html :Pretty filter :Escapable filter :ControlFlow filter :MultiFlattener filter :StaticMerger use :Generator do options[:generator].new(options.to_hash.reject {|k,v| !options[:generator].options.valid_key?(k) }) end end end slim-3.0.6/lib/slim/command.rb0000644000004100000410000000666712555545227016224 0ustar www-datawww-datarequire 'slim' require 'optparse' module Slim Engine.set_options pretty: 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 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('-e', '--erb', 'Convert to ERB') do @options[:erb] = true end opts.on('--rails', 'Generate rails compatible code (Implies --compile)') do Engine.set_options disable_capture: true, generator: Temple::Generators::RailsOutputBuffer @options[:compile] = true end opts.on('-r', '--require library', "Load library or plugin with -r slim/plugin") do |lib| require lib.strip end opts.on('-p', '--pretty', 'Produce pretty html') do Engine.set_options pretty: true end opts.on('-o', '--option name=code', String, 'Set slim option') do |str| parts = str.split('=', 2) Engine.options[parts.first.gsub(/\A:/, '').to_sym] = eval(parts.last) end opts.on('-l', '--locals Hash|YAML|JSON', String, 'Set local variables') do |locals| @options[:locals] = if locals =~ /\A\s*\{\s*\p{Word}+:/ eval(locals) else require 'yaml' if RUBY_ENGINE == 'rbx' begin require 'psych' rescue LoadError $stderr.puts 'Please install psych gem as Rubunius ships with an old YAML engine.' end end YAML.load(locals) end end opts.on_tail('-h', '--help', 'Show this message') do puts opts exit end opts.on_tail('-v', '--version', 'Print version') do puts "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 locals = @options.delete(:locals) || {} result = if @options[:erb] require 'slim/erb_converter' ERBConverter.new(file: @options[:file]).call(@options[:input].read) elsif @options[:compile] Engine.new(file: @options[:file]).call(@options[:input].read) else Template.new(@options[:file]) { @options[:input].read }.render(nil, locals) end 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 else unless @options[:output] file = args.shift @options[:output] = file ? File.open(file, 'w') : $stdout end @options[:output].puts(result) exit 0 end end end slim-3.0.6/lib/slim/code_attributes.rb0000644000004100000410000000410212555545227017744 0ustar www-datawww-datamodule 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, name, value]` # # @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, [:multi]] when 'false', 'nil' [:multi] else tmp = unique_name [:multi, [:code, "#{tmp} = #{code}"], [:if, tmp, [:if, "#{tmp} == true", [:html, :attr, name, [:multi]], [:html, :attr, name, [:escape, escape, [:dynamic, tmp]]]]]] end else # Attribute with merging @attr = name 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} = #{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-3.0.6/lib/slim/filter.rb0000644000004100000410000000140712555545227016056 0ustar www-datawww-datamodule 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(type, content) [:slim, :text, type, 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(escape, code, content) [:slim, :output, escape, code, compile(content)] end end end slim-3.0.6/lib/slim/smart.rb0000644000004100000410000000042512555545227015716 0ustar www-datawww-datarequire 'slim' require 'slim/smart/filter' require 'slim/smart/escaper' require 'slim/smart/parser' Slim::Engine.replace Slim::Parser, Slim::Smart::Parser Slim::Engine.after Slim::Smart::Parser, Slim::Smart::Filter Slim::Engine.after Slim::Interpolation, Slim::Smart::Escaper slim-3.0.6/lib/slim/include.rb0000644000004100000410000000340112555545227016210 0ustar www-datawww-datarequire 'slim' module Slim # Handles inlined includes # # Slim files are compiled, non-Slim files are included as text with `#{interpolation}` # # @api private class Include < Slim::Filter define_options :file, include_dirs: [Dir.pwd, '.'] def on_html_tag(tag, attributes, content = nil) return super if tag != 'include' name = content.to_a.flatten.select {|s| String === s }.join raise ArgumentError, 'Invalid include statement' unless attributes == [:html, :attrs] && !name.empty? unless file = find_file(name) name = "#{name}.slim" if name !~ /\.slim\Z/i file = find_file(name) end raise Temple::FilterError, "'#{name}' not found in #{options[:include_dirs].join(':')}" unless file content = File.read(file) if file =~ /\.slim\Z/i Thread.current[:slim_include_engine].call(content) else [:slim, :interpolate, content] end end protected def find_file(name) current_dir = File.dirname(File.expand_path(options[:file])) options[:include_dirs].map {|dir| File.expand_path(File.join(dir, name), current_dir) }.find {|file| File.file?(file) } end end class Engine after Slim::Parser, Slim::Include after Slim::Include, :stop do |exp| throw :stop, exp if Thread.current[:slim_include_level] > 1 exp end # @api private alias call_without_include call # @api private def call(input) Thread.current[:slim_include_engine] = self Thread.current[:slim_include_level] ||= 0 Thread.current[:slim_include_level] += 1 catch(:stop) { call_without_include(input) } ensure Thread.current[:slim_include_engine] = nil if (Thread.current[:slim_include_level] -= 1) == 0 end end end slim-3.0.6/lib/slim/version.rb0000644000004100000410000000011412555545227016250 0ustar www-datawww-datamodule Slim # Slim version string # @api public VERSION = '3.0.6' end slim-3.0.6/lib/slim/controls.rb0000644000004100000410000000400412555545227016430 0ustar www-datawww-datamodule Slim # @api private class Controls < Filter define_options :disable_capture IF_RE = /\A(if|unless)\b|\bdo\s*(\|[^\|]*\|)?\s*$/ # 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 code =~ IF_RE 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]]] else [:multi, [:escape, escape, [:dynamic, code]], content] end end # Handle text expression `[:slim, :text, type, content]` # # @param [Symbol] type Text type # @param [Array] content Temple expression # @return [Array] Compiled temple expression def on_slim_text(type, content) compile(content) end end end slim-3.0.6/lib/slim/splat/0000755000004100000410000000000012555545227015365 5ustar www-datawww-dataslim-3.0.6/lib/slim/splat/filter.rb0000644000004100000410000000567412555545227017213 0ustar www-datawww-datamodule Slim module Splat # @api private class Filter < ::Slim::Filter define_options :merge_attrs, :attr_quote, :sort_attrs, :default_tag, :format, :disable_capture, hyphen_attrs: %w(data aria), use_html_safe: ''.respond_to?(:html_safe?) def call(exp) @splat_options = nil exp = compile(exp) if @splat_options opts = options.to_hash.reject {|k,v| !Filter.options.valid_key?(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) return super if name != '*' builder, block = make_builder(attrs[2..-1]) if content [:multi, block, [:slim, :output, false, "#{builder}.build_tag #{empty_exp?(content) ? '{}' : 'do'}", compile(content)]] else [: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-3.0.6/lib/slim/splat/builder.rb0000644000004100000410000000603612555545227017345 0ustar www-datawww-datamodule 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_html(escape, value)) unless value.empty? elsif @options[:hyphen_attrs].include?(name) && Hash === value hyphen_attr(name, escape, value) elsif value != false && value != nil attr(name, escape_html(value != true && escape, 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.to_s else raise("Multiple #{name} attributes specified") end else @attrs[name] = value end end def build_tag(&block) tag = @attrs.delete('tag').to_s tag = @options[:default_tag] if tag.empty? if block # This is a bit of a hack to get a universal capturing. # # TODO: Add this as a helper somewhere to solve these capturing issues # once and for all. # # If we have Slim capturing disabled and the scope defines the method `capture` (i.e. Rails) # we use this method to capture the content. # # otherwise we just use normal Slim capturing (yield). # # See https://github.com/slim-template/slim/issues/591 # https://github.com/slim-template/slim#helpers-capturing-and-includes # content = if @options[:disable_capture] && (scope = block.binding.eval('self')).respond_to?(:capture) scope.capture(&block) else yield end "<#{tag}#{build_attrs}>#{content}" else "<#{tag}#{build_attrs} />" end end def build_attrs attrs = @options[:sort_attrs] ? @attrs.sort_by(&:first) : @attrs attrs.map do |k, v| if v == true if @options[:format] == :xhtml " #{k}=#{@options[:attr_quote]}#{@options[:attr_quote]}" else " #{k}" end else " #{k}=#{@options[:attr_quote]}#{v}#{@options[:attr_quote]}" end 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_html(value != true && escape, value)) end end def escape_html(escape, value) return value unless escape @options[:use_html_safe] ? Temple::Utils.escape_html_safe(value) : Temple::Utils.escape_html(value) end end end end slim-3.0.6/lib/slim/smart/0000755000004100000410000000000012555545227015370 5ustar www-datawww-dataslim-3.0.6/lib/slim/smart/parser.rb0000644000004100000410000000243112555545227017211 0ustar www-datawww-data# coding: utf-8 module Slim module Smart # @api private class Parser < ::Slim::Parser define_options implicit_text: true def initialize(opts = {}) super word_re = options[:implicit_text] ? '[_a-z0-9]' : '\p{Word}' attr_keys = Regexp.union(@attr_shortcut.keys.sort_by {|k| -k.size } ) @attr_shortcut_re = /\A(#{attr_keys}+)((?:\p{Word}|-)*)/ tag_keys = Regexp.union((@tag_shortcut.keys - @attr_shortcut.keys).sort_by {|k| -k.size } ) @tag_re = /\A(?:#{attr_keys}(?=-*\p{Word})|#{tag_keys}|\*(?=[^\s]+)|(#{word_re}(?:#{word_re}|:|-)*#{word_re}|#{word_re}+))/ end def unknown_line_indicator if @line =~ /\A>( ?)/ # Found explicit text block. @stacks.last << [:slim, :text, :explicit, parse_text_block($', @indents.last + $1.size + 1)] else unless options[:implicit_text] syntax_error! 'Illegal shortcut' if @line =~ @attr_shortcut_re super end # Found implicit smart text block. if line = @lines.first indent = ( line =~ /\A\s*\Z/ ? @indents.last + 1 : get_indent(line) ) end @stacks.last << [:slim, :text, :implicit, parse_text_block(@line, indent)] end end end end end slim-3.0.6/lib/slim/smart/filter.rb0000644000004100000410000000644512555545227017213 0ustar www-datawww-datamodule Slim module Smart # Perform newline processing in the # expressions `[:slim, :text, type, Expression]`. # # @api private class Filter < ::Slim::Filter define_options smart_text: true, smart_text_end_chars: '([{', smart_text_begin_chars: ',.;:!?)]}' def initialize(opts = {}) super @active = @prepend = @append = false @prepend_re = /\A#{chars_re(options[:smart_text_begin_chars])}/ @append_re = /#{chars_re(options[:smart_text_end_chars])}\Z/ end def call(exp) if options[:smart_text] super else exp end end def on_multi(*exps) # The [:multi] blocks serve two purposes. # On outer level, they collect the building blocks like # tags, verbatim text, and implicit/explicit text. # Within a text block, they collect the individual # lines in [:slim, :interpolate, string] blocks. # # Our goal here is to decide when we want to prepend and # append newlines to those individual interpolated lines. # We basically want the text to come out as it was originally entered, # while removing newlines next to the enclosing tags. # # On outer level, we choose to prepend every time, except # right after the opening tag or after other text block. # We also use the append flag to recognize the last expression # before the closing tag, as we don't want to append newline there. # # Within text block, we prepend only before the first line unless # the outer level tells us not to, and we append only after the last line, # unless the outer level tells us it is the last line before the closing tag. # Of course, this is later subject to the special begin/end characters # which may further suppress the newline at the corresponding line boundary. # Also note that the lines themselves are already correctly separated by newlines, # so we don't have to worry about that at all. block = [:multi] prev = nil last_exp = exps.reject{ |exp| exp.first == :newline }.last unless @active && @append exps.each do |exp| @append = exp.equal?(last_exp) if @active @prepend = false if prev else @prepend = prev && ( prev.first != :slim || prev[1] != :text ) end block << compile(exp) prev = exp unless exp.first == :newline end block end def on_slim_text(type, content) @active = type != :verbatim [:slim, :text, type, compile(content)] ensure @active = false end def on_slim_text_inline(content) # Inline text is not wrapped in multi block, so set it up as if it was. @prepend = false @append = true on_slim_text(:inline, content) end def on_slim_interpolate(string) if @active string = "\n" + string if @prepend && string !~ @prepend_re string += "\n" if @append && string !~ @append_re end [:slim, :interpolate, string] end private def chars_re(string) Regexp.union(string.split(//)) end end end end slim-3.0.6/lib/slim/smart/escaper.rb0000644000004100000410000000174212555545227017343 0ustar www-datawww-datamodule Slim module Smart # Perform smart entity escaping in the # expressions `[:slim, :text, type, Expression]`. # # @api private class Escaper < ::Slim::Filter define_options smart_text_escaping: true def call(exp) if options[:smart_text_escaping] super else exp end end def on_slim_text(type, content) [:escape, type != :verbatim, [:slim, :text, type, compile(content)]] end def on_static(string) # Prevent obvious &foo; and Ӓ and ÿ entities from escaping. block = [:multi] until string.empty? case string when /\A&(\w+|#x[0-9a-f]+|#\d+);/i # Entity. block << [:escape, false, [:static, $&]] string = $' when /\A&?[^&]*/ # Other text. block << [:static, $&] string = $' end end block end end end end slim-3.0.6/lib/slim/do_inserter.rb0000644000004100000410000000214612555545227017107 0ustar www-datawww-datamodule Slim # In Slim you don't need the do keyword sometimes. This # filter adds the missing keyword. # # - 10.times # | Hello # # @api private class DoInserter < Filter BLOCK_REGEX = /(\A(if|unless|else|elsif|when|begin|rescue|ensure|case)\b)|\bdo\s*(\|[^\|]*\|\s*)?\Z/ # 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) code = code + ' do' unless code =~ BLOCK_REGEX || empty_exp?(content) [:slim, :control, 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) code = code + ' do' unless code =~ BLOCK_REGEX || empty_exp?(content) [:slim, :output, escape, code, compile(content)] end end end slim-3.0.6/lib/slim/translator.rb0000644000004100000410000000560512555545227016766 0ustar www-datawww-datarequire 'slim' module Slim # @api private class Translator < Filter define_options :tr, tr_mode: :dynamic, tr_fn: '_' if defined?(::I18n) set_options tr_fn: '::Slim::Translator.i18n_text', tr: true elsif defined?(::GetText) set_options tr_fn: '::GetText._', tr: true elsif defined?(::FastGettext) set_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(type, exp) [:slim, :text, type, @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 Slim::Engine.before Slim::EndInserter, Slim::Translator slim-3.0.6/lib/slim/logic_less/0000755000004100000410000000000012555545227016365 5ustar www-datawww-dataslim-3.0.6/lib/slim/logic_less/context.rb0000644000004100000410000000576412555545227020412 0ustar www-datawww-datamodule 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 def to_s scope.to_s 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 def to_s @dict.to_s 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-3.0.6/lib/slim/logic_less/filter.rb0000644000004100000410000000427112555545227020203 0ustar www-datawww-datamodule 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) case name when 'yield' 'yield' when 'self' "#{@context}.to_s" else "#{@context}[#{name.to_sym.inspect}]" end end end end slim-3.0.6/lib/slim/template.rb0000644000004100000410000000167012555545227016406 0ustar www-datawww-datamodule Slim # Tilt template implementation for Slim # @api public Template = Temple::Templates::Tilt(Slim::Engine, register_as: :slim) if defined?(::ActionView) # 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: true) end end slim-3.0.6/lib/slim.rb0000644000004100000410000000053612555545227014573 0ustar www-datawww-datarequire 'temple' require 'slim/parser' require 'slim/filter' require 'slim/do_inserter' 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-3.0.6/metadata.yml0000644000004100000410000001277112555545227015043 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: slim version: !ruby/object:Gem::Version version: 3.0.6 platform: ruby authors: - Daniel Mendler - Andrew Stone - Fred Wu autorequire: bindir: bin cert_chain: [] date: 2015-06-05 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: temple requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.7.3 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.7.3 - !ruby/object:Gem::Dependency name: tilt requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.3.3 - - "<" - !ruby/object:Gem::Version version: '2.1' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.3.3 - - "<" - !ruby/object:Gem::Version version: '2.1' 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.jp.md - 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 - doc/include.md - doc/jp/include.md - doc/jp/logic_less.md - doc/jp/smart.md - doc/jp/translator.md - doc/logic_less.md - doc/smart.md - doc/translator.md - lib/slim.rb - lib/slim/code_attributes.rb - lib/slim/command.rb - lib/slim/controls.rb - lib/slim/do_inserter.rb - lib/slim/embedded.rb - lib/slim/end_inserter.rb - lib/slim/engine.rb - lib/slim/erb_converter.rb - lib/slim/filter.rb - lib/slim/grammar.rb - lib/slim/include.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/smart.rb - lib/slim/smart/escaper.rb - lib/slim/smart/filter.rb - lib/slim/smart/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_commands.rb - test/core/test_embedded_engines.rb - test/core/test_encoding.rb - test/core/test_erb_converter.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/include/files/recursive.slim - test/include/files/slimfile.slim - test/include/files/subdir/test.slim - test/include/files/textfile - test/include/test_include.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/entries_controller.rb - test/rails/app/controllers/slim_controller.rb - test/rails/app/helpers/application_helper.rb - test/rails/app/models/entry.rb - test/rails/app/views/entries/edit.html.slim - test/rails/app/views/layouts/application.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/form_for.html.slim - test/rails/app/views/slim/helper.html.slim - 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/splat.html.slim - test/rails/app/views/slim/thread_options.html.slim - test/rails/app/views/slim/variables.html.slim - test/rails/app/views/slim/xml.slim - test/rails/config.ru - test/rails/config/application.rb - test/rails/config/boot.rb - 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/script/rails - test/rails/test/helper.rb - test/rails/test/test_slim.rb - test/smart/test_smart_text.rb - test/translator/test_translator.rb homepage: http://slim-lang.com/ licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.9.2 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.2.2 signing_key: specification_version: 4 summary: Slim is a template language. test_files: [] has_rdoc: slim-3.0.6/test/0000755000004100000410000000000012555545227013507 5ustar www-datawww-dataslim-3.0.6/test/include/0000755000004100000410000000000012555545227015132 5ustar www-datawww-dataslim-3.0.6/test/include/files/0000755000004100000410000000000012555545227016234 5ustar www-datawww-dataslim-3.0.6/test/include/files/recursive.slim0000644000004100000410000000000512555545227021124 0ustar www-datawww-data| recslim-3.0.6/test/include/files/slimfile.slim0000644000004100000410000000004112555545227020721 0ustar www-datawww-data| slim1 include recursive | slim2slim-3.0.6/test/include/files/subdir/0000755000004100000410000000000012555545227017524 5ustar www-datawww-dataslim-3.0.6/test/include/files/subdir/test.slim0000644000004100000410000000001012555545227021360 0ustar www-datawww-data| subdirslim-3.0.6/test/include/files/textfile0000644000004100000410000000001212555545227017774 0ustar www-datawww-data1+2=#{1+2}slim-3.0.6/test/include/test_include.rb0000644000004100000410000000114012555545227020135 0ustar www-datawww-datarequire 'helper' require 'slim/include' class TestSlimInclude < TestSlim def test_include source = %q{ br/ a: include slimfile b: include textfile c: include slimfile.slim d: include subdir/test } assert_html '
slim1recslim21+2=3slim1recslim2subdir', source, include_dirs: [File.expand_path('files', File.dirname(__FILE__))] end def test_include_with_newline source = %q{ a: include slimfile .content } assert_html 'slim1recslim2
', source, include_dirs: [File.expand_path('files', File.dirname(__FILE__))] end end slim-3.0.6/test/core/0000755000004100000410000000000012555545227014437 5ustar www-datawww-dataslim-3.0.6/test/core/test_text_interpolation.rb0000644000004100000410000000320112555545227021752 0ustar www-datawww-datarequire '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-3.0.6/test/core/test_tabs.rb0000644000004100000410000000302112555545227016750 0ustar www-datawww-datarequire 'helper' class TestSlimTabs < TestSlim def teardown Slim::Engine.set_options tabsize: 4 end def test_single_tab1_expansion Slim::Engine.set_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_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_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_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-3.0.6/test/core/test_embedded_engines.rb0000644000004100000410000001472412555545227021274 0ustar www-datawww-datarequire 'helper' require 'erb' #asciidoctor fail to load it randomly 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_wip_render_with_asciidoc source = %q{ asciidoc: == Header Hello from #{"AsciiDoc!"} #{1+2} * one * two } output = render(source) assert_match 'sect1', output assert_match 'Hello from AsciiDoc!', output end def test_render_with_markdown source = %q{ markdown: #Header Hello from #{"Markdown!"} #{1+2} * one * two } if ::Tilt['md'].name =~ /Redcarpet/ # redcarpet assert_html "

Header

\n\n

Hello from Markdown!

\n\n

3

\n\n\n", source elsif ::Tilt['md'].name =~ /RDiscount/ # rdiscount assert_html "

Header

\n\n

Hello from Markdown!

\n\n

3

\n\n\n\n", source else # kramdown, :auto_ids by default assert_html "

Header

\n

Hello from Markdown!

\n\n

3

\n\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", source end assert_html "

Header

\n

Hello from Markdown!

\n\n

3

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

head1

head2

", source end def test_render_with_creole_one_line source = %q{ creole: Hello **world**, we can write one-line embedded markup now! = Headline Text .nested: creole: **Strong** } assert_html '

Hello world, we can write one-line embedded markup now!

Headline

Text

Strong

', source end def test_render_with_org # HACK: org-ruby registers itself in Tilt require 'org-ruby' source = %q{ org: * point1 * point2 } assert_html "

point1

\n

point2

\n", 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_opal begin # HACK: org-ruby registers itself in Tilt require 'opal' rescue LoadError return end source = %q{ opal: puts 'hello from opal' } assert_match '$puts("hello from opal")', render(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-3.0.6/test/core/helper.rb0000644000004100000410000000774712555545227016262 0ustar www-datawww-data# encoding: utf-8 begin require 'codeclimate-test-reporter' CodeClimate::TestReporter.start rescue LoadError end require 'minitest/autorun' require 'slim' require 'slim/grammar' Slim::Engine.after Slim::Parser, Temple::Filters::Validator, grammar: Slim::Grammar Slim::Engine.before :Pretty, Temple::Filters::Validator class TestSlim < Minitest::Test 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 class HtmlSafeString < String def html_safe? true end def to_s self end end def with_html_safe String.send(:define_method, :html_safe?) { false } String.send(:define_method, :html_safe) { HtmlSafeString.new(self) } yield ensure String.send(:undef_method, :html_safe?) if String.method_defined?(:html_safe?) String.send(:undef_method, :html_safe) if String.method_defined?(:html_safe) 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 message =~ /([^\s]+), Line (\d+)/ assert_backtrace ex, "#{$1}:#{$2}" 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] =~ /([^\s]+:\d+)/ assert_equal from, $1 end else ex.backtrace[0] =~ /([^\s]+:\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 =~ /([^\s]+:\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 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-3.0.6/test/core/test_html_structure.rb0000644000004100000410000003226312555545227021115 0ustar www-datawww-datarequire '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_relaxed_indentation_of_first_line source = %q{ p .content } assert_html "

", 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_relaxed_text_indentation source = %q{ p | text block text line3 } assert_html "

text block\ntext\n line3

", 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_default_attr_delims_option source = %q{ p= output_number } Slim::Parser.options[:attr_list_delims].each do |k,v| str = source.sub('<',k).sub('>',v) assert_html '

1337

', str end end def test_custom_attr_delims_option source = %q{ p { foo="bar" } } assert_html '

', source assert_html '

', source, attr_list_delims: {'{' => '}'} assert_html '

{ foo="bar" }

', source, attr_list_delims: {'(' => ')', '[' => ']'} end def test_closed_tag source = %q{ closed/ } assert_html '', source, format: :xhtml end def test_custom_attr_list_delims_option source = %q{ p { foo="bar" x=(1+1) } p < x=(1+1) > Hello } assert_html '

< x=(1+1) > Hello

', source assert_html '

< x=(1+1) > Hello

', source, attr_list_delims: {'{' => '}'} assert_html '

{ foo="bar" x=(1+1) }

Hello

', source, attr_list_delims: {'<' => '>'}, code_attr_delims: { '(' => ')' } 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.options[:attr_list_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.options[:attr_list_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.options[:attr_list_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.options[:attr_list_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.options[:attr_list_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.options[:attr_list_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-3.0.6/test/core/test_code_blocks.rb0000644000004100000410000000723712555545227020303 0ustar www-datawww-datarequire '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_block_without_do source = %q{ p = hello_world "Hello Ruby!" | Hello from within a block! } assert_html '

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

    ', source end def test_render_variable_ending_with_do source = %q{ - appelido=10 p= appelido - appelido } assert_html '

    10

    ', 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_without_do source = %q{ p = hello_world "Hello Ruby!" = 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_render_with_output_code_within_block_2_without_do source = %q{ p = hello_world "Hello Ruby!" = hello_world "Hello from within a block!" = 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_render_with_control_code_loop_without_do source = %q{ p - 3.times | 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 def test_captured_code_block_with_conditional_without_do source = %q{ = hello_world "Hello Ruby!" - if true | Hello from within a block! } assert_html 'Hello Ruby! Hello from within a block! Hello Ruby!', source end def test_if_without_content source = %q{ - if true } assert_html '', source end def test_unless_without_content source = %q{ - unless true } assert_html '', source end def test_if_with_comment source = %q{ - if true / comment } assert_html '', source end def test_control_do_with_comment source = %q{ - hello_world "Hello" / comment } assert_html '', source end def test_output_do_with_comment source = %q{ = hello_world "Hello" / comment } assert_html 'Hello', source end def test_output_if_without_content source = %q{ = if true } assert_html '', source end def test_output_if_with_comment source = %q{ = if true / comment } assert_html '', source end end slim-3.0.6/test/core/test_commands.rb0000644000004100000410000001443612555545227017634 0ustar www-datawww-data# coding: utf-8 require 'helper' require 'open3' require 'tempfile' class TestSlimCommands < Minitest::Test # nothing complex STATIC_TEMPLATE = "p Hello World!\n" # requires a `name` variable to exist at render time DYNAMIC_TEMPLATE = "p Hello \#{name}!\n" # a more complex example LONG_TEMPLATE = "h1 Hello\np\n | World!\n small Tiny text" # exception raising example EXCEPTION_TEMPLATE = '- raise NotImplementedError' # Temple has this feature... STRING_FREEZER = RUBY_VERSION >= '2.1' ? '.freeze' : '' def test_option_help out, err = exec_slimrb '--help' assert err.empty? assert_match /Show this message/, out end def test_option_version out, err = exec_slimrb '--version' assert err.empty? assert_match /\ASlim #{Regexp.escape Slim::VERSION}$/, out end def test_render prepare_common_test STATIC_TEMPLATE do |out, err| assert err.empty? assert_equal "

    Hello World!

    \n", out end end # superficial test, we don't want to test Tilt/Temple def test_compile prepare_common_test STATIC_TEMPLATE, '--compile' do |out, err| assert err.empty? assert_match %r{\"

    Hello World!<\/p>\"#{STRING_FREEZER}}, out end end def test_erb prepare_common_test DYNAMIC_TEMPLATE, '--erb' do |out, err| assert err.empty? assert_equal "

    Hello <%= ::Temple::Utils.escape_html((name)) %>!

    \n", out end end def test_rails prepare_common_test DYNAMIC_TEMPLATE, '--rails' do |out, err| assert err.empty? assert out.include? %Q{@output_buffer = ActiveSupport::SafeBuffer.new;} assert out.include? %Q{@output_buffer.safe_concat(("

    Hello "#{STRING_FREEZER}));} assert out.include? %Q{@output_buffer.safe_concat(((::Temple::Utils.escape_html((name))).to_s));} assert out.include? %Q{@output_buffer.safe_concat(("!

    "#{STRING_FREEZER}));} end end def test_pretty prepare_common_test LONG_TEMPLATE, '--pretty' do |out, err| assert err.empty? assert_equal "

    \n Hello\n

    \n

    \n World!Tiny text\n

    \n", out end end # We cannot run these two on Travis, because we can't install libyaml. # See https://github.com/slim-template/slim/issues/576 if ENV['TRAVIS'] && RUBY_ENGINE != 'rbx' def test_locals_json data = '{"name":"from slim"}' prepare_common_test DYNAMIC_TEMPLATE, '--locals', data do |out, err| assert err.empty? assert_equal "

    Hello from slim!

    \n", out end end def test_locals_yaml data = "name: from slim" prepare_common_test DYNAMIC_TEMPLATE, '--locals', data do |out, err| assert err.empty? assert_equal "

    Hello from slim!

    \n", out end end end def test_locals_hash data = '{name:"from slim"}' prepare_common_test DYNAMIC_TEMPLATE, '--locals', data do |out, err| assert err.empty? assert_equal "

    Hello from slim!

    \n", out end end def test_require with_tempfile 'puts "Not in slim"', 'rb' do |lib| prepare_common_test STATIC_TEMPLATE, '--require', lib, stdin_file: false, file_file: false do |out, err| assert err.empty? assert_equal "Not in slim\n

    Hello World!

    \n", out end end end def test_error prepare_common_test EXCEPTION_TEMPLATE, stdin_file: false do |out, err| assert out.empty? assert_match /NotImplementedError: NotImplementedError/, err assert_match /Use --trace for backtrace/, err end end def test_trace_error prepare_common_test EXCEPTION_TEMPLATE, '--trace', stdin_file: false do |out, err| assert out.empty? assert_match /bin\/slimrb/, err end end private # Whether you call slimrb with a file argument or pass the slim content # via $stdin; whether you want the output written to $stdout or into # another file given as argument, the output is the same. # # This method prepares a test with this exact behaviour: # # It yields the tupel (out, err) once after the `content` was passed # in via $stdin and once it was passed as a (temporary) file argument. # # In effect, this method executes a test (given as block) 4 times: # # 1. read from $stdin, write to $stdout # 2. read from file, write to $stdout # 3. read from $stdin, write to file # 4. read from file, write to file def prepare_common_test(content, *args) options = Hash === args.last ? args.pop : {} # case 1. $stdin → $stdout unless options[:stdin_stdout] == false out, err = exec_slimrb *args, '--stdin' do |i| i.write content end yield out, err end # case 2. file → $stdout unless options[:file_stdout] == false with_tempfile content do |in_file| out, err = exec_slimrb *args, in_file yield out, err end end # case 3. $stdin → file unless options[:stdin_file] == false with_tempfile content do |out_file| _, err = exec_slimrb *args, '--stdin', out_file do |i| i.write content end yield File.read(out_file), err end end # case 3. file → file unless options[:file_file] == false with_tempfile '' do |out_file| with_tempfile content do |in_file| _, err = exec_slimrb *args, in_file, out_file do |i| i.write content end yield File.read(out_file), err end end end end # Calls bin/slimrb as a subprocess. # # Yields $stdin to the caller and returns a tupel (out,err) with the # contents of $stdout and $stderr. # # (I'd like to use Minitest::Assertions#capture_subprecess_io here, # but then there's no way to insert data via $stdin.) def exec_slimrb(*args) out, err = nil, nil Open3.popen3 'ruby', 'bin/slimrb', *args do |i,o,e,t| yield i if block_given? i.close out, err = o.read, e.read end return out, err end # Creates a temporary file with the given content and yield the path # to this file. The file itself is only available inside the block and # will be deleted afterwards. def with_tempfile(content=nil, extname='slim') f = Tempfile.new ['slim', ".#{extname}"] if content f.write content f.flush # ensure content is actually saved to disk f.rewind end yield f.path ensure f.close f.unlink end end slim-3.0.6/test/core/test_ruby_errors.rb0000644000004100000410000000721412555545227020404 0ustar www-datawww-datarequire '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__):3", source end def test_invalid_nested_output source = %q{ p = "Hello Ruby!" = "Hello from within a block! " } assert_ruby_syntax_error "(__TEMPLATE__):3", 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-3.0.6/test/core/test_erb_converter.rb0000644000004100000410000000307412555545227020666 0ustar www-datawww-datarequire 'helper' require 'slim/erb_converter' class TestSlimERBConverter < TestSlim def test_converter 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!

    <%= ::Temple::Utils.escape_html(("dynamic text with\nnewline")) %>

    } assert_equal result, Slim::ERBConverter.new.call(source) end end slim-3.0.6/test/core/test_pretty.rb0000644000004100000410000000566412555545227017365 0ustar www-datawww-datarequire 'helper' class TestSlimPretty < TestSlim def setup super Slim::Engine.set_options pretty: true end def teardown Slim::Engine.set_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 def test_correct_line_number source = %q{ html head body p Slim = '' = '' = '' = unknown_ruby_method } assert_ruby_error NameError,"(__TEMPLATE__):9", source end def test_unindenting source = %q{ span before span = " middle " span after } result = %q{before middle after} assert_html result, source source = %q{ html body == "
    \n link\n
    " } result = %q{ } assert_html result, source end def test_helper_unindent source = %q{ = define_macro :content div a link html body == call_macro :content } result = %q{ } assert_html result, source end end slim-3.0.6/test/core/test_thread_options.rb0000644000004100000410000000100312555545227021037 0ustar www-datawww-datarequire '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-3.0.6/test/core/test_html_escaping.rb0000644000004100000410000000245612555545227020647 0ustar www-datawww-datarequire '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-3.0.6/test/core/test_encoding.rb0000644000004100000410000000124712555545227017615 0ustar www-datawww-datarequire '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" source.force_encoding(Encoding::BINARY) result = "\xFF\xFF" result.force_encoding(Encoding::BINARY) out = render(source, default_encoding: 'binary') out.force_encoding(Encoding::BINARY) assert_equal result, out end def test_bom source = "\xEF\xBB\xBFh1 Hello World!" result = '

    Hello World!

    ' assert_html result, source end end slim-3.0.6/test/core/test_code_output.rb0000644000004100000410000000567512555545227020372 0ustar www-datawww-datarequire '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-3.0.6/test/core/test_parser_errors.rb0000644000004100000410000000676212555545227020726 0ustar www-datawww-datarequire '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_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_malformed_indentation2 source = %q{ div Valid div Invalid } assert_syntax_error "Malformed indentation\n (__TEMPLATE__), Line 3, 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_missing_quote_unexpected_end source = %q{ p img(src="img.jpg } assert_syntax_error "Unexpected end of file\n (__TEMPLATE__), Line 3, Column 0\n \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_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 def test_illegal_shortcuts source = %{ .#test } assert_syntax_error "Illegal shortcut\n (__TEMPLATE__), Line 2, Column 0\n .#test\n ^\n", source source = %{ div.#test } assert_syntax_error "Illegal shortcut\n (__TEMPLATE__), Line 2, Column 3\n div.#test\n ^\n", source end end slim-3.0.6/test/core/test_code_evaluation.rb0000644000004100000410000001105012555545227021161 0ustar www-datawww-datarequire '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_code_attribute_does_not_modify_argument template = 'span class=attribute' model = OpenStruct.new(attribute: [:a, :b, [:c, :d]]) output = Slim::Template.new { template }.render(model) assert_equal('', output) assert_equal([:a, :b, [:c, :d]], model.attribute) end def test_number_type_interpolation source = %q{ p = output_number } assert_html '

    1337

    ', source end end slim-3.0.6/test/core/test_html_attributes.rb0000644000004100000410000001445112555545227021242 0ustar www-datawww-datarequire '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_splat_without_content source = %q{ *hash p*hash } 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 def test_weird_attribute source = %q{ p img(src='img.png' whatsthis?!) img src='img.png' whatsthis?!="wtf" } assert_html '

    ', source end end slim-3.0.6/test/core/test_code_escaping.rb0000644000004100000410000000701712555545227020613 0ustar www-datawww-datarequire '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_without_html_safe2 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 = "Hello World\\n, meet \\"Slim\\"." } with_html_safe do assert_html "

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

    ", source, use_html_safe: true end end def test_render_with_html_safe_true source = %q{ p = "Hello World\\n, meet \\"Slim\\".".html_safe } with_html_safe do assert_html "

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

    ", source, use_html_safe: true end end def test_render_splat_with_html_safe_true source = %q{ p *{ title: '&'.html_safe } } with_html_safe do assert_html "

    ", source, use_html_safe: true end end def test_render_splat_with_html_safe_false source = %q{ p *{ title: '&' } } with_html_safe do assert_html "

    ", source, use_html_safe: true end end def test_render_attribute_with_html_safe_true source = %q{ p title=('&'.html_safe) } with_html_safe do assert_html "

    ", source, use_html_safe: true end 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 def test_escaping_evil_method_with_pretty source = %q{ p = evil_method } assert_html "

    \n <script>do_something_evil();</script>\n

    ", source, pretty: true end def test_render_without_html_safe_with_pretty source = %q{ p = "Hello World\\n, meet \\"Slim\\"." } assert_html "

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

    ", source, pretty: true end def test_render_with_html_safe_false_with_pretty source = %q{ p = "Hello World\\n, meet \\"Slim\\"." } with_html_safe do assert_html "

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

    ", source, use_html_safe: true, pretty: true end end def test_render_with_html_safe_true_with_pretty source = %q{ p = "Hello World\\n, meet \\"Slim\\".".html_safe } with_html_safe do assert_html "

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

    ", source, use_html_safe: true, pretty: true end end def test_render_with_disable_escape_false_with_pretty source = %q{ = "

    Hello

    " == "

    World

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

    World

    ", source, pretty: true end def test_render_with_disable_escape_true_with_pretty source = %q{ = "

    Hello

    " == "

    World

    " } assert_html "

    Hello

    World

    ", source, disable_escape: true, pretty: true end end slim-3.0.6/test/core/test_slim_template.rb0000644000004100000410000000411412555545227020662 0ustar www-datawww-datarequire '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-3.0.6/test/core/test_code_structure.rb0000644000004100000410000000531412555545227021060 0ustar www-datawww-datarequire '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 | 41 - when 42 | 42 | is the answer p - case 41 - when 41 | 41 - when 42 | 42 | is the answer p - case 42 when 41 | 41 - when 42 | 42 | is the answer p - case 41 when 41 | 41 - when 42 | 42 | is the answer } assert_html '

    42 is the answer

    41 is the answer

    42 is the answer

    41 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 def test_render_with_begin_rescue source = %q{ - begin p Begin - rescue p Rescue p After } assert_html '

    Begin

    After

    ', source end def test_render_with_begin_rescue_exception source = %q{ - begin p Begin - raise 'Boom' p After Boom - rescue => ex p = ex.message p After } assert_html '

    Begin

    Boom

    After

    ', source end def test_render_with_begin_rescue_ensure source = %q{ - begin p Begin - raise 'Boom' p After Boom - rescue => ex p = ex.message - ensure p Ensure p After } assert_html '

    Begin

    Boom

    Ensure

    After

    ', source end end slim-3.0.6/test/core/test_unicode.rb0000644000004100000410000000063312555545227017453 0ustar www-datawww-data# -*- coding: utf-8 -*- 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 slim-3.0.6/test/literate/0000755000004100000410000000000012555545227015320 5ustar www-datawww-dataslim-3.0.6/test/literate/helper.rb0000644000004100000410000000070412555545227017125 0ustar www-datawww-datarequire '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_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-3.0.6/test/literate/run.rb0000644000004100000410000000462412555545227016457 0ustar www-datawww-datarequire '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-3.0.6/test/literate/TESTS.md0000644000004100000410000004644512555545227016561 0ustar www-datawww-data# 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! ~~~ You can also write loops like this ~~~ slim - items = [{name: 'table', price: 10}, {name: 'chair', price: 5}] table#items - for item in items do tr td.name = item[:name] td.price = item[:price] ~~~ which renders as ~~~ html
    table 10
    chair 5
    ~~~ The `do` keyword can be omitted. ~~~ slim - items = [{name: 'table', price: 10}, {name: 'chair', price: 5}] table#items - for item in items tr td.name = item[:name] td.price = item[:price] ~~~ which renders as ~~~ html
    table 10
    chair 5
    ~~~ ### 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 ~~~ The equal sign with modifier `=>` produces dynamic output with a trailing white space. ~~~ slim => 7*7 ~~~ renders as ~~~ html 49 ~~~ ~~~ slim =< 7*7 ~~~ renders as ~~~ html 49 ~~~ The legacy syntax `='` is also supported. ~~~ slim =' 7*7 ~~~ renders as ~~~ html 49 ~~~ The equal sign with modifier `=<` produces dynamic output with a leading white space. ~~~ slim =< 7*7 ~~~ renders as ~~~ html 49 ~~~ The equal sign with modifiers `=<>` produces dynamic output with a leading and 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 ~~~ The double equal sign with modifier `==>` produces dynamic output without HTML escaping and trailing white space. ~~~ slim ==> '' ~~~ renders as ~~~ html ~~~ The legacy syntax `=='` is also supported. ~~~ 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 ~~~ ### Trailing and leading whitespace You can force a trailing whitespace behind a tag by adding `>`. The legacy syntax with `'` is also supported. ~~~ slim a#closed> class="test" / a#closed> class="test"/ a> href='url1' Link1 a< href='url1' Link1 a' href='url2' Link2 ~~~ renders as ~~~ html Link1 Link1Link2 ~~~ If you combine > and =' only one trailing whitespace is added. ~~~ slim a> =' 'Text1' a =' 'Text2' a> = 'Text3' a>= 'Text4' a=> 'Text5' a<= 'Text6' a=< 'Text7' ~~~ renders as ~~~ html Text1 Text2 Text3 Text4 Text5 Text6 Text7 ~~~ You can force a leading whitespace before a tag by adding `<`. ~~~ slim a#closed< class="test" / a#closed< class="test"/ a< href='url1' Link1 a< href='url2' Link2 ~~~ ~~~ html Link1 Link2 ~~~ You can also combine both. ~~~ slim a#closed<> class="test" / a#closed>< class="test"/ a<> href='url1' Link1 a<> href='url2' Link2 ~~~ ~~~ html Link1 Link2 ~~~ ### 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} a href="{"test"}" Test of quoted text in braces ~~~ renders as ~~~ html Goto the slim-lang.comTest of quoted text in braces ~~~ 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 use newlines in quoted attributes ~~~ 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 ~~~ You can break quoted attributes with an 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 ~~~ If html5 is activated the attributes are written as standalone. ~~~ options :format => :html ~~~ ~~~ 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 ~~~ #### 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# ~~~ You can also set multiple attributes per shortcut. ~~~ options :shortcut => {'.' => {attr: %w(id class)} } ~~~ ~~~ slim .test ~~~ renders to ~~~ html
    ~~~ Shortcuts can also have multiple characters. ~~~ options :shortcut => {'.' => {attr: 'class'}, '#' => {attr: 'id'}, '.#' => {attr: %w(class id)} } ~~~ ~~~ slim .#test .test #test ~~~ renders to ~~~ html
    ~~~ #### ID shortcut and class shortcut `.` ID and class shortcuts can contain dashes. ~~~ slim .-test text #test- text .--a#b- text .a--test-123#--b text ~~~ renders as ~~~ html
    text
    text
    text
    text
    ~~~ ## 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>!

    ~~~ ## Pretty printing of XML We can enable XML mode with ~~~ options :format => :xml ~~~ ~~~ slim doctype xml document closed-element/ element(boolean-attribute) child attribute="value" | content ~~~ ~~~ html content ~~~ ## Embedded engines ## Configuring Slim ## Plugins slim-3.0.6/test/smart/0000755000004100000410000000000012555545227014635 5ustar www-datawww-dataslim-3.0.6/test/smart/test_smart_text.rb0000644000004100000410000000771712555545227020427 0ustar www-datawww-data# -*- coding: utf-8 -*- require 'helper' require 'slim/smart' class TestSlimSmartText < TestSlim def test_explicit_smart_text_recognition source = %q{ > a > b > c > d > e f > g h i } result = %q{a b c d e g h } assert_html result, source end def test_implicit_smart_text_recognition source = %q{ p A p B p C p D p E F p G H I } result = %q{

    A

    B

    C

    D

    E

    F

    G H

    I} assert_html result, source end def test_multi_line_smart_text source = %q{ p First line. Second line. Third line with a continuation and one more. Fourth line. } result = %q{

    First line. Second line. Third line with a continuation and one more. Fourth line.

    } assert_html result, source end def test_smart_text_escaping source = %q{ | Not escaped <&>. p Escaped <&>. p Escaped <&>. > Escaped <&>. Protected & < > © Á. Protected  ÿ. Escaped &#xx; f; &;. } result = %q{Not escaped <&>.

    Escaped <&>.

    Escaped <&>. Escaped <&>. Protected & < > © Á. Protected  ÿ. Escaped &#xx; &#1f; &;.

    } assert_html result, source end def test_smart_text_disabled_escaping Slim::Engine.with_options( smart_text_escaping: false ) do source = %q{ p Not escaped <&>. | Not escaped <&>. p Not escaped <&>. > Not escaped <&>. Not escaped & < > © Á. Not escaped  ÿ. Not escaped &#xx; f; &;. } result = %q{

    Not escaped <&>.

    Not escaped <&>.

    Not escaped <&>. Not escaped <&>. Not escaped & < > © Á. Not escaped  ÿ. Not escaped &#xx; f; &;.

    } assert_html result, source end end def test_smart_text_in_tag_escaping source = %q{ p Escaped <&>. Protected & < > © Á. Protected  ÿ. Escaped &#xx; f; &;. } result = %q{

    Escaped <&>. Protected & < > © Á. Protected  ÿ. Escaped &#xx; &#1f; &;.

    } assert_html result, source end def test_smart_text_mixed_with_tags source = %q{ p Text br >is strong really > recognized. More b text . And i more ... span Really ?!? .bold Really !!! #id #{'Good'} ! } result = %q{

    Text
    is really recognized. More text. And more... Really?!?

    Really
    !!!
    Good
    !

    } assert_html result, source end def test_smart_text_mixed_with_links source = %q{ p Text with a href="#1" link . Text with a href="#2" another link > to somewhere else. a href="#3" This link > goes elsewhere. See ( a href="#4" link )? } result = %q{

    Text with link. Text with another link to somewhere else. This link goes elsewhere. See (link)?

    } assert_html result, source end def test_smart_text_mixed_with_code source = %q{ p Try a list ul - 2.times do |i| li Item: #{i} > which stops b here . Right? } result = %q{

    Try a list

    • Item: 0
    • Item: 1
    which stops here. Right?

    } assert_html result, source end # Without unicode support, we can't distinguish uppercase and lowercase # unicode characters reliably. So we only test the basic text, not tag names. def test_basic_unicode_smart_text source = %q{ p 是 čip Čip Žůžo šíp } result = %q{

    是 čip Čip Žůžo šíp

    } assert_html result, source end def test_unicode_smart_text source = %q{ p 是 čip Čip Žůžo šíp .řek . } result = %q{

    是 čip Čip Žůžo šíp

    .

    } assert_html result, source end end slim-3.0.6/test/translator/0000755000004100000410000000000012555545227015700 5ustar www-datawww-dataslim-3.0.6/test/translator/test_translator.rb0000644000004100000410000000503412555545227021457 0ustar www-datawww-datarequire 'helper' require 'slim/translator' class TestSlimTranslator < TestSlim def setup super Slim::Engine.set_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 } case Tilt['md'].name.downcase when /redcarpet/ assert_html "

    Header

    \n\n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n", source, tr_mode: :dynamic assert_html "

    Header

    \n\n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n", source, tr_mode: :static when /rdiscount/ assert_html "

    Header

    \n\n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n\n", source, tr_mode: :dynamic assert_html "

    Header

    \n\n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n\n", source, tr_mode: :static when /kramdown/ assert_html "

    Header

    \n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n", source, tr_mode: :dynamic assert_html "

    Header

    \n

    Hello from Markdown!

    \n\n

    3

    \n\n
      \n
    • one
    • \n
    • two
    • \n
    \n", source, tr_mode: :static else raise "Missing test for #{Tilt['md']}" end 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-3.0.6/test/rails/0000755000004100000410000000000012555545227014621 5ustar www-datawww-dataslim-3.0.6/test/rails/Rakefile0000644000004100000410000000041112555545227016262 0ustar www-datawww-data# 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-3.0.6/test/rails/script/0000755000004100000410000000000012555545227016125 5ustar www-datawww-dataslim-3.0.6/test/rails/script/rails0000755000004100000410000000044712555545227017172 0ustar www-datawww-data#!/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-3.0.6/test/rails/test/0000755000004100000410000000000012555545227015600 5ustar www-datawww-dataslim-3.0.6/test/rails/test/test_slim.rb0000644000004100000410000000531612555545227020135 0ustar www-datawww-datarequire 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 "xml view" do get "/slim/xml" assert_response :success assert_template "slim/xml" assert_template "layouts/application" assert_html "

    Hello Slim!

    " end test "helper" do get "/slim/helper" assert_response :success assert_template "slim/helper" assert_template "layouts/application" assert_html "

    Hello User

    " 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 RUBY_ENGINE == 'jruby' && RUBY_ENGINE < '2.2.0' puts 'Streaming test disabled for JRuby < 9000.', 'See https://github.com/jruby/jruby/issues/1243', 'and https://github.com/jruby/jruby/issues/1789' else 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 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 "form_for" do get "/entries/edit/1" assert_match %r{action="/entries"}, @response.body assert_match %r{}, @response.body assert_xpath '//input[@id="entry_name" and @name="entry[name]" and @type="text"]' end test "splat" do get "/slim/splat" assert_html "
    Hello
    " end end slim-3.0.6/test/rails/test/helper.rb0000644000004100000410000000164112555545227017406 0ustar www-datawww-data# Configure Rails Envinronment ENV["RAILS_ENV"] = "test" require File.expand_path("../../config/environment.rb", __FILE__) require "rails/test_help" require "nokogiri" Rails.backtrace_cleaner.remove_silencers! class ActionDispatch::IntegrationTest protected def assert_xpath(xpath, message="Unable to find '#{xpath}' in response body.") assert_response :success, "Response type is not :success (code 200..299)." body = @response.body assert !body.empty?, "No response body found." doc = Nokogiri::HTML(body) rescue nil assert_not_nil doc, "Cannot parse response body." assert doc.xpath(xpath).size >= 1, message end def assert_html(expected, options = {}) expected = "Dummy#{options[:heading]}
    #{expected}
    " unless options[:skip_layout] assert_equal expected, @response.body end end slim-3.0.6/test/rails/config/0000755000004100000410000000000012555545227016066 5ustar www-datawww-dataslim-3.0.6/test/rails/config/application.rb0000644000004100000410000000354312555545227020723 0ustar www-datawww-datarequire File.expand_path('../boot', __FILE__) require 'active_model/railtie' require 'action_controller/railtie' require 'action_view/railtie' #require 'active_record/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-3.0.6/test/rails/config/initializers/0000755000004100000410000000000012555545227020574 5ustar www-datawww-dataslim-3.0.6/test/rails/config/initializers/secret_token.rb0000644000004100000410000000103412555545227023604 0ustar www-datawww-data# 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-3.0.6/test/rails/config/initializers/session_store.rb0000644000004100000410000000062712555545227024025 0ustar www-datawww-data# 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-3.0.6/test/rails/config/initializers/mime_types.rb0000644000004100000410000000031512555545227023273 0ustar www-datawww-data# 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-3.0.6/test/rails/config/initializers/backtrace_silencers.rb0000644000004100000410000000062412555545227025111 0ustar www-datawww-data# 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-3.0.6/test/rails/config/initializers/inflections.rb0000644000004100000410000000057012555545227023440 0ustar www-datawww-data# 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-3.0.6/test/rails/config/boot.rb0000644000004100000410000000041712555545227017360 0ustar www-datawww-datarequire '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-3.0.6/test/rails/config/environments/0000755000004100000410000000000012555545227020615 5ustar www-datawww-dataslim-3.0.6/test/rails/config/environments/test.rb0000644000004100000410000000264512555545227022130 0ustar www-datawww-dataDummy::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-3.0.6/test/rails/config/routes.rb0000644000004100000410000000340212555545227017733 0ustar www-datawww-dataDummy::Application.routes.draw do # The priority is based upon order of creation: # first created -> highest priority. resources :entries # 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-3.0.6/test/rails/config/environment.rb0000644000004100000410000000022512555545227020756 0ustar www-datawww-data# Load the rails application require File.expand_path('../application', __FILE__) # Initialize the rails application Dummy::Application.initialize! slim-3.0.6/test/rails/config/locales/0000755000004100000410000000000012555545227017510 5ustar www-datawww-dataslim-3.0.6/test/rails/config/locales/en.yml0000644000004100000410000000032512555545227020635 0ustar www-datawww-data# 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-3.0.6/test/rails/app/0000755000004100000410000000000012555545227015401 5ustar www-datawww-dataslim-3.0.6/test/rails/app/views/0000755000004100000410000000000012555545227016536 5ustar www-datawww-dataslim-3.0.6/test/rails/app/views/entries/0000755000004100000410000000000012555545227020207 5ustar www-datawww-dataslim-3.0.6/test/rails/app/views/entries/edit.html.slim0000644000004100000410000000010012555545227022754 0ustar www-datawww-data= form_for @entry do |f| label: b Name = f.text_field :name slim-3.0.6/test/rails/app/views/slim/0000755000004100000410000000000012555545227017502 5ustar www-datawww-dataslim-3.0.6/test/rails/app/views/slim/variables.html.slim0000644000004100000410000000001212555545227023274 0ustar www-datawww-datah1= @helloslim-3.0.6/test/rails/app/views/slim/form_for.html.slim0000644000004100000410000000006012555545227023140 0ustar www-datawww-data= form_for @entry do |f| = f.text_field :name slim-3.0.6/test/rails/app/views/slim/_partial.html.slim0000644000004100000410000000002112555545227023117 0ustar www-datawww-datap With a partial!slim-3.0.6/test/rails/app/views/slim/xml.slim0000644000004100000410000000001612555545227021165 0ustar www-datawww-datah1 Hello Slim!slim-3.0.6/test/rails/app/views/slim/erb.html.erb0000644000004100000410000000002312555545227021702 0ustar www-datawww-data

    Hello Erb!

    slim-3.0.6/test/rails/app/views/slim/content_for.html.slim0000644000004100000410000000023312555545227023651 0ustar www-datawww-datap 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-3.0.6/test/rails/app/views/slim/integers.html.slim0000644000004100000410000000001312555545227023145 0ustar www-datawww-datap= @integerslim-3.0.6/test/rails/app/views/slim/partial.html.slim0000644000004100000410000000004112555545227022762 0ustar www-datawww-datah1 Hello Slim! = render "partial"slim-3.0.6/test/rails/app/views/slim/normal.html.slim0000644000004100000410000000001612555545227022620 0ustar www-datawww-datah1 Hello Slim!slim-3.0.6/test/rails/app/views/slim/helper.html.slim0000644000004100000410000000005312555545227022610 0ustar www-datawww-datap = headline do ' Hello = 'User' slim-3.0.6/test/rails/app/views/slim/splat.html.slim0000644000004100000410000000003712555545227022456 0ustar www-datawww-data#splat *{tag: 'splat'} Hello slim-3.0.6/test/rails/app/views/slim/no_layout.html.slim0000644000004100000410000000003712555545227023344 0ustar www-datawww-datah1 Hello Slim without a layout!slim-3.0.6/test/rails/app/views/slim/thread_options.html.slim0000644000004100000410000000001512555545227024351 0ustar www-datawww-datap@empty Test slim-3.0.6/test/rails/app/views/layouts/0000755000004100000410000000000012555545227020236 5ustar www-datawww-dataslim-3.0.6/test/rails/app/views/layouts/application.html.slim0000644000004100000410000000016412555545227024373 0ustar www-datawww-datadoctype html html head title Dummy = csrf_meta_tag body = yield :page_heading .content= yield slim-3.0.6/test/rails/app/controllers/0000755000004100000410000000000012555545227017747 5ustar www-datawww-dataslim-3.0.6/test/rails/app/controllers/entries_controller.rb0000644000004100000410000000013412555545227024206 0ustar www-datawww-dataclass EntriesController < ApplicationController def edit @entry = Entry.new end end slim-3.0.6/test/rails/app/controllers/slim_controller.rb0000644000004100000410000000105012555545227023477 0ustar www-datawww-dataclass SlimController < ApplicationController def normal end def xml 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 def helper end end slim-3.0.6/test/rails/app/controllers/application_controller.rb0000644000004100000410000000007112555545227025040 0ustar www-datawww-dataclass ApplicationController < ActionController::Base end slim-3.0.6/test/rails/app/models/0000755000004100000410000000000012555545227016664 5ustar www-datawww-dataslim-3.0.6/test/rails/app/models/entry.rb0000644000004100000410000000037412555545227020356 0ustar www-datawww-dataclass Entry include ActiveModel::Conversion extend ActiveModel::Naming attr_accessor :name def initialize(attributes = {}) attributes.each do |name, value| send("#{name}=", value) end end def persisted? false end end slim-3.0.6/test/rails/app/helpers/0000755000004100000410000000000012555545227017043 5ustar www-datawww-dataslim-3.0.6/test/rails/app/helpers/application_helper.rb0000644000004100000410000000014612555545227023233 0ustar www-datawww-datamodule ApplicationHelper def headline(&block) "

    #{capture(&block)}

    ".html_safe end end slim-3.0.6/test/rails/config.ru0000644000004100000410000000023312555545227016434 0ustar www-datawww-data# This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) run Dummy::Application slim-3.0.6/test/logic_less/0000755000004100000410000000000012555545227015632 5ustar www-datawww-dataslim-3.0.6/test/logic_less/test_logic_less.rb0000644000004100000410000001372312555545227021347 0ustar www-datawww-datarequire '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'}] "
      #{block.call(*list)}
    " end } assert_html '

    Joe
    Jack
    Hello!
    • First
    • Second

    ', 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_to_s_access source = %q{ p - people .name = self } hash = { people: [ 'Joe', 'Jack' ] } assert_html '

    Joe
    Jack

    ', source, scope: hash, dictionary_access: :symbol 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 '
    • Andy
    • Atlanta
    • Fred
    • Melbourne
    • Daniel
    • Karlsruhe
    ', 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-3.0.6/slim.gemspec0000644000004100000410000000173512555545227015047 0ustar www-datawww-data# -*- 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.license = 'MIT' 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.required_ruby_version = '>=1.9.2' s.add_runtime_dependency('temple', ['~> 0.7.3']) s.add_runtime_dependency('tilt', ['>= 1.3.3', '< 2.1']) end slim-3.0.6/.gitignore0000644000004100000410000000020012555545227014510 0ustar www-datawww-data*.swp *.gem Gemfile.lock .bundle .redcar .rvmrc .yardoc coverage pkg test/rails/log test/rails/tmp /.ruby-gemset /.ruby-version slim-3.0.6/.yardopts0000644000004100000410000000022412555545227014374 0ustar www-datawww-data--markup-provider redcarpet --markup markdown - README.md CHANGES LICENSE test/literate/TESTS.md doc/logic_less.md doc/translator.md doc/smart.md slim-3.0.6/LICENSE0000644000004100000410000000206512555545227013540 0ustar www-datawww-dataThe MIT License Copyright (c) 2010 - 2015 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-3.0.6/benchmarks/0000755000004100000410000000000012555545227014645 5ustar www-datawww-dataslim-3.0.6/benchmarks/run-benchmarks.rb0000755000004100000410000001106312555545227020115 0ustar www-datawww-data#!/usr/bin/env ruby $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__)) require 'slim' require 'context' require 'benchmark/ips' require 'tilt' require 'erubis' require 'erb' require 'haml' class SlimBenchmarks def initialize(slow) @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_parsing_benches if slow end def init_compiled_benches 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.new(@erb_code).src}; end def run_erubis; #{Erubis::Eruby.new(@erb_code).src}; end def run_temple_erb; #{Temple::ERB::Engine.new.call @erb_code}; end def run_fast_erubis; #{Erubis::FastEruby.new(@erb_code).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_parsing_benches context = Context.new context_binding = context.instance_eval { binding } bench('(3) erb') { ERB.new(@erb_code).result(context_binding) } bench('(3) erubis') { Erubis::Eruby.new(@erb_code).result(context_binding) } bench('(3) fast erubis') { Erubis::FastEruby.new(@erb_code).result(context_binding) } bench('(3) temple erb') { Temple::ERB::Template.new { @erb_code }.render(context) } bench('(3) slim pretty') { Slim::Template.new(pretty: true) { @slim_code }.render(context) } bench('(3) slim ugly') { Slim::Template.new { @slim_code }.render(context) } bench('(3) haml pretty') { Haml::Engine.new(@haml_code, format: :html5).render(context) } bench('(3) haml ugly') { Haml::Engine.new(@haml_code, format: :html5, ugly: true).render(context) } end def run Benchmark.ips do |x| @benches.each do |name, block| x.report(name.to_s, &block) 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) 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']).run slim-3.0.6/benchmarks/view.haml0000644000004100000410000000050712555545227016464 0ustar www-datawww-data!!! 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-3.0.6/benchmarks/run-diffbench.rb0000755000004100000410000000072612555545227017714 0ustar www-datawww-data#!/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-3.0.6/benchmarks/context.rb0000644000004100000410000000035512555545227016661 0ustar www-datawww-dataclass 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-3.0.6/benchmarks/profile-render.rb0000644000004100000410000000045012555545227020106 0ustar www-datawww-data#!/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-3.0.6/benchmarks/view.slim0000644000004100000410000000050112555545227016501 0ustar www-datawww-datadoctype 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-3.0.6/benchmarks/profile-parser.rb0000644000004100000410000000036312555545227020126 0ustar www-datawww-data#!/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-3.0.6/benchmarks/view.erb0000644000004100000410000000072512555545227016315 0ustar www-datawww-data 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-3.0.6/README.jp.md0000644000004100000410000013173112555545227014425 0ustar www-datawww-data# Slim [![Gem Version](https://img.shields.io/gem/v/slim.svg)](http://rubygems.org/gems/slim) [![Build Status](https://img.shields.io/travis/slim-template/slim.svg?branch=master)](http://travis-ci.org/slim-template/slim) [![Dependency Status](https://img.shields.io/gemnasium/slim-template/slim.svg?travis)](https://gemnasium.com/slim-template/slim) [![Code Climate](https://img.shields.io/codeclimate/github/slim-template/slim.svg)](https://codeclimate.com/github/slim-template/slim) [![Gittip donate button](https://img.shields.io/gratipay/bevry.svg)](https://www.gittip.com/min4d/ "Donate weekly to this project using Gittip") [![Flattr donate button](https://raw.github.com/balupton/flattr-buttons/master/badge-89x18.gif)](https://flattr.com/submit/auto?user_id=min4d&url=http%3A%2F%2Fslim-lang.org%2F "Donate monthly to this project using Flattr") Slim は 不可解にならないように view の構文を本質的な部品まで減らすことを目指したテンプレート言語です。標準的な HTML テンプレートからどれだけのものが削除できるか確かめるところから始まりました。(<, >, 閉じタグなど) 多くの人が Slim に興味を持ったことで, 機能性は発展し, 柔軟な構文をもたらしました。 機能の短いリスト * すっきりした構文 * 閉じタグの無い短い構文 (代わりにインデントを用いる) * 閉じタグを用いた HTML 形式の構文 * 設定可能なショートカットタグ (デフォルトでは `#` は `
    ` に, `.` は `
    ` に) * 安全性 * デフォルトで自動 HTML エスケープ * Rails の `html_safe?` に対応 * 柔軟な設定 * プラグインを用いた拡張性: * Mustache と同様のロジックレスモード * インクルード * 多言語化/I18n * 高性能 * ERB/Erubis に匹敵するスピード * Rails のストリーミングに対応 * 全てのメジャーフレームワークが対応 (Rails, Sinatra, ...) * タグや属性の Unicode に完全対応 * Markdown や Textile のような埋め込みエンジン ## リンク * ホームページ: * ソース: * バグ: * リスト: * API ドキュメント: * 最新の Gem: * GitHub master: ## イントロダクション ### Slim とは? Slim は __Rails3 および 4__ に対応した高速, 軽量なテンプレートエンジンです。すべての主要な Ruby の実装でしっかりテストされています。 私たちは継続的インテグレーションを採用しています。(travis-ci) Slim の核となる構文は1つの考えによって導かれます: "この動作を行うために最低限必要なものは何か"。 多くの人々の Slim への貢献によって, 彼らが使う [Haml](https://github.com/haml/haml) や [Jade](https://github.com/visionmedia/jade) の影響を受け構文の追加が行われています。 Slim の開発チームは美は見る人の目の中にあることを分っているのでこういった追加にオープンです。 Slim は 構文解析/コンパイルに [Temple](https://github.com/judofyr/temple) を使い [Tilt](https://github.com/rtomayko/tilt) に組み込まれます。これにより [Sinatra](https://github.com/sinatra/sinatra) やプレーンな [Rack](https://github.com/rack/rack) とも一緒に使えます。 Temple のアーキテクチャはとても柔軟でモンキーパッチなしで構文解析とコンパイルのプロセスの拡張を可能にします。これはロジックレスのプラグインや I18n が提供する翻訳プラグインに 使用されます。ロジックレスモードでは HTML をビルドするために Slim の構文を使いたいが, テンプレートの中で Ruby を書きたくない場合にも Slim を使うことができます。 ### なぜ Slim を使うのか? * Slim によって メンテナンスが容易な限りなく最小限のテンプレートを作成でき, 正しい文法の HTML や XML が書けることを保証します。 * Slim の構文は美的であり, テンプレートを書くのを楽しくしてくれると思います。Slim は主要なフレームワークで互換性があるので簡単に始めることができます。 * Slim のアーキテクチャは非常に柔軟なので構文の拡張やプラグインを書くことができます。 ___そう, Slim は速い!___ Slim は開発当初からパフォーマンスに注意して開発されました。 ベンチマークはコミット毎に で取られています。 この数字が信じられませんか? それは仕方ないことです。是非 rake タスクを使って自分でベンチマークを取ってみてください! 私たちの考えでは, あなたは Slim の機能と構文を使うべきです。Slim はあなたのアプリケーションのパフォーマンスに悪影響を与えないことを保証します。 ### どう始めるの? Slim を gem としてインストール: ~~~ gem install slim ~~~ あなたの Gemfile に `gem 'slim'` と書いてインクルードするか, ファイルに `require 'slim'` と書く必要があります。これだけです! 後は拡張子に .slim を使うだけで準備はできています。 ### 構文例 Slim テンプレートがどのようなものか簡単な例を示します: ~~~ slim doctype html html head title Slim のファイル例 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 は javascript の埋め込みに対応します!') body h1 マークアップ例 #content p このマークアップ例は Slim の典型的なファイルがどのようなものか示します。 == yield - if items.any? table#items - for item in items tr td.name = item.name td.price = item.price - else p アイテムが見つかりませんでした。いくつか目録を追加してください。 ありがとう! div id="footer" == render 'footer' | Copyright © #{@year} #{@author} ~~~ インデントについて, インデントの深さはあなたの好みで選択できます。もし最初のインデントをスペース2つ, その次に5スペースを使いたい場合, それはあなたの選択次第です。マークアップを入れ子にするにはスペース1つのインデントが必要なだけです。 ## ラインインジケータ ### テキスト `|` パイプは Slim に行をコピーしろと命じます。基本的にどのような処理でもエスケープします。 パイプよりも深くインデントされた各行がコピーされます。 ~~~ slim body p | これはテキストブロックのテストです。 ~~~ 構文解析結果は以下: ~~~ html

    これはテキストブロックのテストです。

    ~~~ ブロックの左端はパイプ +1 スペースのインデントに設定されています。 追加のスペースはコピーされます。 ~~~ slim body p | この行は左端になります。 この行はスペース 1 つを持つことになります。 この行はスペース 2 つを持つことになります。 以下同様に... ~~~ テキスト行に HTML を埋め込むこともできます。 ~~~ slim - articles.each do |a| | #{a.name}#{a.description} ~~~ ### テキスト行のスペースをたどる `'` シングルクォートは Slim に行をコピーしろと命じます (`|` と同様に) が, 単一行の末尾にスペースが追加されているかチェックします。 ### インライン html `<` (HTML 形式) あなたは html タグを直接 Slim の中に書くことができます。Slim は閉じタグを使った html タグ形式や html と Slim を混ぜてテンプレートの中に書くことができます。 行頭が '<' の場合, 暗黙の `|` があるものとして動作します: ~~~ slim head title Example - if articles.empty? - else table - articles.each do |a| #{a.name}#{a.description} ~~~ ### 制御コード `-` ダッシュは制御コードを意味します。制御コードの例としてループと条件文があります。`end` は `-` の後ろに置くことができません。ブロックはインデントによってのみ定義されます。 複数行にわたる Ruby のコードが必要な場合, 行末にバックスラッシュ `\` を追加します。行末がカンマ `,` で終わる場合 (例 関数呼び出し) には行末にバックスラッシュを追加する必要はありません。 ~~~ slim body - if articles.empty? | 在庫なし ~~~ ### 出力 `=` イコールはバッファに追加する出力を生成する Ruby 呼び出しを Slim に命令します。Ruby のコードが複数行にわたる場合, 例のように行末にバックスラッシュを追加します。 ~~~ slim = javascript_include_tag \ "jquery", "application" ~~~ 行末がカンマ `,` で終わる場合 (例 関数呼び出し) には行末にバックスラッシュを追加する必要はありません。行末スペースを追加するために修飾子の `>` や `<` もサポートします。 * `=>` は末尾のスペースを伴った出力をします。 末尾のスペースが追加されることを除いて, 単一の等合 (`=`) と同じです。 * `=<` は先頭のスペースを伴った出力をします。先頭のスペースが追加されることを除いて, 単一の等号 (`=`) と同じです。 ### HTML エスケープを伴わない出力 `==` 単一のイコール (`=`) と同じですが, `escape_html` メソッドを経由しません。 末尾や先頭のスペースを追加するための修飾子 `>` と `<` はサポートされています。 * `==>` は HTML エスケープを行わず末尾のスペースを伴った出力をします。末尾のスペースが追加されることを除いて, 二重等号 (`==`) と同じです。 * `==<` は HTML エスケープを行わず先頭のスペースを伴った出力をします。先頭のスペースが追加されることを除いて, 二重等号 (`==`) と同じです。 ### コードコメント `/` コードコメントにはスラッシュを使います。スラッシュ以降は最終的なレンダリング結果に表示されません。コードコメントには `/` を, html コメントには `/!` を使います。 ~~~ slim body p / この行は表示されません。 この行も表示されません。 /! html コメントとして表示されます。 ~~~ 構文解析結果は以下: ~~~ html

    ~~~ ### HTML コメント `/!` html コメントにはスラッシュの直後にエクスクラメーションマークを使います (``)。 ### IE コンディショナルコメント `/[...]` ~~~ slim /[if IE] p もっといいブラウザを使ってください。 ~~~ レンダリング結果 ~~~ html ~~~ ## HTML タグ ### ドキュメントタイプタグ ドキュメントタイプタグはとても簡単な方法で複雑なドキュメントタイプを生成するために使われる特別なタグです。 XML 宣言 ~~~ slim doctype xml doctype xml ISO-8859-1 ~~~ XHTML ドキュメントタイプ ~~~ slim doctype html doctype 5 doctype 1.1 doctype strict doctype frameset doctype mobile doctype basic doctype transitional ~~~ HTML 4 ドキュメントタイプ ~~~ slim doctype strict doctype frameset doctype transitional ~~~ ### 閉じタグ (末尾 `/`) 末尾に `/` を付けることで明示的にタグを閉じることができます。 ~~~ slim img src="image.png"/ ~~~ (注) 標準的な html タグ (img, br, ...) は自動的にタグを閉じるので, 通常必要ありません。 ### スペースを追加する (`<`, `>`) a タグの後に > を追加することで末尾にスペースを追加するよう Slim に強制することができます。 ~~~ slim a> href='url1' リンク1 a> href='url2' リンク2 ~~~ < を追加することで先頭のスペースを追加できます。 ~~~ slim a< href='url1' リンク1 a< href='url2' リンク2 ~~~ これらを組み合わせて使うこともできます。 ~~~ slim a<> href='url1' リンク1 ~~~ ### インラインタグ 時々タグをよりコンパクトにインラインにしたくなるかもしれません。 ~~~ slim ul li.first: a href="/a" A リンク li: a href="/b" B リンク ~~~ 読みやすくするために, 属性を囲むことができるのを忘れないでください。 ~~~ slim ul li.first: a[href="/a"] A リンク li: a[href="/b"] B リンク ~~~ ### テキストコンテンツ タグと同じ行で開始するか ~~~ slim body h1 id="headline" 私のサイトへようこそ。 ~~~ 入れ子にするのかどちらかです。エスケープ処理を行うためにはパイプかバッククォートを使わなければなりません。 ~~~ slim body h1 id="headline" | 私のサイトへようこそ。 ~~~ スマートテキストモードを有効化して利用する場合 ~~~ slim body h1 id="headline" 私のサイトへようこそ。 ~~~ ### 動的コンテンツ (`=` と `==`) 同じ行で呼び出すか ~~~ slim body h1 id="headline" = page_headline ~~~ 入れ子にすることができます。 ~~~ slim body h1 id="headline" = page_headline ~~~ ### 属性 タグの後に直接属性を書きます。属性のテキストにはダブルクォート `"` か シングルクォート `'` を使わなければなりません (引用符で囲まれた属性)。 ~~~ slim a href="http://slim-lang.com" title='Slim のホームページ' Slim のホームページへ ~~~ 引用符で囲まれたテキストを属性として使えます。 #### 属性の囲み 区切り文字が構文を読みやすくするのであれば, `{...}`, `(...)`, `[...]` が属性の囲みに使えます。 これらの記号は設定できます (`:attr_list_delims` オプション参照)。 ~~~ slim body h1(id="logo") = page_logo h2[id="tagline" class="small tagline"] = page_tagline ~~~ 属性を囲んだ場合, 属性を複数行にわたって書くことができます: ~~~ slim h2[id="tagline" class="small tagline"] = page_tagline ~~~ 属性の囲みや変数まわりにスペースを使うことができます: ~~~ slim h1 id = "logo" = page_logo h2 [ id = "tagline" ] = page_tagline ~~~ #### 引用符で囲まれた属性 例: ~~~ slim a href="http://slim-lang.com" title='Slim のホームページ' Slim のホームページへ ~~~ 引用符で囲まれたテキストを属性として使えます: ~~~ slim a href="http://#{url}" #{url} へ ~~~ 属性値はデフォルトでエスケープされます。属性のエスケープを無効にしたい場合 == を使います。 ~~~ slim a href=="&" ~~~ 引用符で囲まれた属性をバックスラッシュ `\` で改行できます。 ~~~ slim a data-title="help" data-content="極めて長い長い長いヘルプテキストで\ 1つずつ1つずつその後はまたやり直して繰り返し...." ~~~ #### Ruby コードを用いた属性 `=` の後に直接 Ruby コードを書きます。コードにスペースが含まれる場合, `(...)` の括弧でコードを囲まなければなりません。ハッシュを `{...}` に, 配列を `[...]` に書くこともできます。 ~~~ slim body table - for user in users 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 ~~~ 属性値はデフォルトでエスケープされます。属性のエスケープを無効にしたい場合 == を使います。 ~~~ slim a href==action_path(:start) ~~~ Ruby コードの属性は, コントロールセクションにあるようにバックスラッシュ `\` や `,` を用いて改行できます。 #### 真偽値属性 属性値の `true`, `false` や `nil` は真偽値として 評価されます。属性を括弧で囲む場合, 属性値の指定を省略することができます。 ~~~ slim 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 ~~~ #### 属性の結合 複数の属性が与えられた場合に属性をまとめるように設定することができます (`:merge_attrs` 参照)。デフォルト設定では class 属性は空白区切りで結合されます。 ~~~ slim a.menu class="highlight" href="http://slim-lang.com/" Slim-lang.com ~~~ レンダリング結果 ~~~ html Slim-lang.com ~~~ また, `Array` や配列要素を属性値として区切り文字で結合し使うこともできます。 ~~~ slim a class=["menu","highlight"] a class=:menu,:highlight ~~~ #### アスタリスク属性 `*` アスタリスクによってハッシュを属性/値のペアとして使うことができます。 ~~~ slim .card*{'data-url'=>place_path(place), 'data-id'=>place.id} = place.name ~~~ レンダリング結果 ~~~ html
    Slim の家
    ~~~ 次のようにハッシュを返すメソッドやインスタンス変数を使うこともできます" ~~~ slim .card *method_which_returns_hash = place.name .card *@hash_instance_variable = place.name ~~~ 属性の結合 (Slim オプション `:merge_attrs` 参照) に対応するハッシュ属性には `Array` を与えることもできます。 ~~~ slim .first *{class: [:second, :third]} テキスト ~~~ レンダリング結果 ~~~ slim div class="first second third" ~~~ #### 動的タグ `*` アスタリスク属性を使用することで完全に動的なタグを作ることができます。:tag をキーにもつハッシュを返すメソッドを 作るだけです。 ~~~ slim ruby: def a_unless_current @page_current ? {tag: 'span'} : {tag: 'a', href: 'http://slim-lang.com/'} end - @page_current = true *a_unless_current リンク - @page_current = false *a_unless_current リンク ~~~ レンダリング結果 ~~~ html リンクリンク ~~~ ### ショートカット #### タグショートカット `:shortcut` オプションを設定することで独自のタグショートカットを定義できます。 ~~~ ruby Slim::Engine.set_options shortcut: {'c' => {tag: 'container'}, '#' => {attr: 'id'}, '.' => {attr: 'class'} } ~~~ Slim コードの中でこの様に使用できます。 ~~~ slim c.content テキスト ~~~ レンダリング結果 ~~~ html テキスト ~~~ #### 属性のショートカット カスタムショートカットを定義することができます (`#` が id で `.` が class であるように)。 例として `&` で作った type 属性付きの input 要素のショートカットを作成し追加します。 ~~~ ruby Slim::Engine.set_options shortcut: {'&' => {tag: 'input', attr: 'type'}, '#' => {attr: 'id'}, '.' => {attr: 'class'}} ~~~ Slim コードの中でこの様に使用できます。 ~~~ slim &text name="user" &password name="pw" &submit ~~~ レンダリング結果 ~~~ html ~~~ 別の例として `@` で作った role 属性のショートカットを作成し追加します。 ~~~ ruby Slim::Engine.set_options shortcut: {'@' => 'role', '#' => 'id', '.' => 'class'} ~~~ Slim コードの中でこの様に使用できます。 ~~~ slim .person@admin = person.name ~~~ レンダリング結果 ~~~ html
    Daniel
    ~~~ 1つのショートカットを使って複数の属性を設定することもできます。 ~~~ ruby Slim::Engine.set_options shortcut: {'@' => {attr: %w(data-role role)}} ~~~ Slim の中で次のように使用し ~~~ slim .person@admin = person.name ~~~ このようのレンダリングされます。 ~~~ html
    Daniel
    ~~~ #### ID ショートカット `#` と class ショートカット `.` `id` と `class` の属性を次のショートカットで指定できます。 ~~~ slim body h1#headline = page_headline h2#tagline.small.tagline = page_tagline .content = show_content ~~~ これは次に同じです ~~~ slim body h1 id="headline" = page_headline h2 id="tagline" class="small tagline" = page_tagline div class="content" = show_content ~~~ ## ヘルパ, キャプチャとインクルード いくつかのヘルパを使用してテンプレートを拡張することもできます。次のヘルパが定義されていることを前提として, ~~~ruby module Helpers def headline(&block) if defined?(::Rails) # Rails の場合には capture メソッドを使う "

    #{capture(&block)}

    " else # フレームワークなしで Slim を使う場合(Tilt の場合), # ただ出力する "

    #{yield}

    " end end end ~~~ このインクルードされたコードのスコープは実行される Slim のテンプレートコードです。Slim テンプレートの中では次のように使用することができます。 ~~~ slim p = headline do ' Hello = user.name ~~~ `do` ブロック内のコンテンツが自動的にキャプチャされ `yield` を通してヘルパに渡されます。糖衣構文として `do` キーワードを省略して書くこともできます。 ~~~ slim p = headline ' Hello = user.name ~~~ ### ローカル変数のキャプチャ 次のように `Binding` を使ってローカル変数をキャプチャすることができます: ~~~ruby module Helpers def capture_to_local(var, &block) set_var = block.binding.eval("lambda {|x| #{var} = x }") # Rails では capture! を使います # Slim をフレームワークなしで使う場合 (Tilt のみを使う場合), # キャプチャブロックを取得するには yield が利用できます set_var.call(defined?(::Rails) ? capture(&block) : yield) end end ~~~ このヘルパは次のように使用できます ~~~ slim / captured_content 変数は Binding 前に定義されていなければいけません。 = capture_to_local captured_content=:captured_content p この段落は captured_content 変数にキャプチャされます = captured_content ~~~ 別の興味深いユースケースは、enumerableを使いそれぞれの要素をキャプチャすることです。ヘルパは、このようになります。 ~~~ ruby module Capture def capture(var, enumerable = nil, &block) value = enumerable ? enumerable.map(&block) : yield block.binding.eval("lambda {|x| #{var} = x }").call(value) nil end end ~~~ そして、次のように使用出来ます。 ~~~ slim - links = { 'http://slim-lang.com' => 'The Slim Template Language' } = capture link_list=:link_list, links do |url, text| a href=url = text ~~~ その後は、`link_list`はキャプチャしたコンテンツを含みます。 ### インクルードヘルパ コンパイル時にインクルード機能を使いたい場合には, [パーシャルのインクルード](doc/jp/include.md) を見てください。 実行時にサブテンプレートを実行すること ( Rails の `#render` のように) もできます。インクルードヘルパを自分で用意する必要があります: ~~~ ruby module Helpers def include_slim(name, options = {}, &block) Slim::Template.new("#{name}.slim", options).render(self, &block) end end ~~~ このヘルパは次のように使用できます ~~~ slim nav = include_slim 'menu' section = include_slim 'content' ~~~ しかし, このヘルパはキャッシュを行いません。その為, 目的にあったよりインテリジェントなバージョンを 実装する必要があります。また, ほとんどのフレームワークにはすでに同様のヘルパが含まれるので注意してください。(例: Rails の `render` メソッド) ## テキストの展開 Ruby の標準的な展開方法を使用します。テキストはデフォルトで html エスケープされます。 ~~~ slim body h1 ようこそ #{current_user.name} ショーへ。 | エスケープしない #{{content}} こともできます。 ~~~ 展開したテキストのエスケープ方法 (言い換えればそのままのレンダリング) ~~~ slim body h1 ようこそ \#{current_user.name} ショーへ。 ~~~ ## 埋め込みエンジン (Markdown, ...) ありがとう [Tilt](https://github.com/rtomayko/tilt), Slim は他のテンプレートエンジンの埋め込みに見事に対応します。 例: ~~~ slim coffee: square = (x) -> x * x markdown: #Header #{"Markdown"} からこんにちわ! 2行目! p: markdown: Tag with **inline** markdown! ~~~ 対応エンジン: | フィルタ | 必要な gems | 種類 | 説明 | | -------- | ----------- | ---- | ----------- | | ruby: | なし | ショートカット | Ruby コードを埋め込むショートカット | | javascript: | なし | ショートカット | javascript コードを埋め込むショートカットで script タグで囲む | | css: | なし | ショートカット | css コードを埋め込むショートカットで style タグで囲む | | sass: | sass | コンパイル時 | sass コードを埋め込むショートカットで style タグで囲む | | scss: | sass | コンパイル時 | scss コードを埋め込むショートカットで style タグで囲む | | less: | less | コンパイル時 | less コードを埋め込むショートカットで style タグで囲む | | styl: | styl | コンパイル時 | stylus コードを埋め込むショートカットで style タグで囲む | | coffee: | coffee-script | コンパイル時 | コンパイルした CoffeeScript で script タグで囲む | | asciidoc: | asciidoctor | コンパイル時 + 展開 | AsciiDoc コードのコンパイルとテキスト中の # \{variables} の展開 | | markdown: | redcarpet/rdiscount/kramdown | コンパイル時 + 展開 | Markdownのコンパイルとテキスト中の # \{variables} の展開 | | textile: | redcloth | コンパイル時 + 展開 | textile のコンパイルとテキスト中の # \{variables} の展開 | | creole: | creole | コンパイル時 + 展開 | cleole のコンパイルとテキスト中の # \{variables} の展開 | | wiki:, mediawiki: | wikicloth | コンパイル時 + 展開 | wiki のコンパイルとテキスト中の # \{variables} の展開 | | rdoc: | rdoc | コンパイル時 + 展開 | RDoc のコンパイルとテキスト中の # \{variables} の展開 | | builder: | builder | プレコンパイル | builder コードの埋め込み | | nokogiri: | nokogiri | プレコンパイル | nokogiri コードの埋め込み | | erb: | なし | プレコンパイル | erb コードの埋め込み | 埋め込みエンジンは Slim の `Slim::Embedded` フィルタのオプションで直接設定されます。例: ~~~ ruby Slim::Embedded.options[:markdown] = {auto_ids: false} ~~~ ## Slim の設定 Slim とその基礎となる [Temple](https://github.com/judofyr/temple) は非常に柔軟に設定可能です。 Slim を設定する方法はコンパイル機構に少し依存します。(Rails や [Tilt](https://github.com/rtomayko/tilt))。デフォルトオプションの設定は `Slim::Engine` クラスでいつでも可能です。Rails の 環境設定ファイルで設定可能です。例えば, config/environments/developers.rb で設定したいとします: ### デフォルトオプション ~~~ ruby # デバック用に html をきれいにインデントし属性をソートしない Slim::Engine.set_options pretty: true, sort_attrs: false ~~~ ハッシュで直接オプションにアクセスすることもできます: ~~~ ruby Slim::Engine.options[:pretty] = true ~~~ ### 実行時のオプション設定 実行時のオプション設定の方法は2つあります。Tilt テンプレート (`Slim::Template`) の場合, テンプレートを インスタンス化する時にオプションを設定できます。 ~~~ ruby Slim::Template.new('template.slim', optional_option_hash).render(scope) ~~~ 他の方法は Rails に主に関係がありますがスレッド毎にオプション設定を行う方法です: ~~~ slim Slim::Engine.with_options(option_hash) do # ここで作成される Slim エンジンは option_hash を使用します # Rails での使用例: render :page, layout: true end ~~~ Rails ではコンパイルされたテンプレートエンジンのコードとオプションはテンプレート毎にキャッシュされ, 後でオプションを変更できないことに注意する必要があります。 ~~~ slim # 最初のレンダリング呼び出し Slim::Engine.with_options(pretty: true) do render :page, layout: true end # 2回目のレンダリング呼び出し Slim::Engine.with_options(pretty: false) do render :page, layout: true # :pretty is still true because it is cached end ~~~ ### 可能なオプション 次のオプションが `Slim::Engine` によって用意され `Slim::Engine.set_options` で設定することができます。 沢山ありますが良いことに, Slim はもし誤った設定キーを使用しようとした場合キーをチェックしエラーを報告します。 | 種類 | 名前 | デフォルト | 用途 | | ---- | ---- | ---------- | ---- | | 文字列 | :file | nil | 解析対象のファイル名ですが, Slim::Template によって自動的に設定されます | | 数値 | :tabsize | 4 | 1 タブあたりのスペース数 (構文解析で利用されます) | | 文字列 | :encoding | "utf-8" | テンプレートのエンコーディングを設定 | | 文字列 | :default_tag | "div" | タグ名が省略されている場合デフォルトのタグとして使用される | | ハッシュ | :shortcut | \{'.' => {attr: 'class'}, '#' => {attr: 'id'}} | 属性のショートカット | | ハッシュ | :code_attr_delims | \{'(' => ')', '[' => ']', '{' => '}'} | Ruby コードの属性区切り文字 | | ハッシュ | :attr_list_delims | \{'(' => ')', '[' => ']', '{' => '}'} | 属性リスト区切り文字 | | 配列<シンボル,文字列> | :enable_engines | nil (すべて可) | 有効な埋め込みエンジンリスト (ホワイトリスト) | | 配列<シンボル,文字列> | :disable_engines | nil (無効なし) | 無効な埋め込みエンジンリスト (ブラックリスト) | | 真偽値 | :disable_capture | false (Rails では true) | ブロック内キャプチャ無効 (ブロックはデフォルトのバッファに書き込む) | | 真偽値 | :disable_escape | false | 文字列の自動エスケープ無効 | | 真偽値 | :use_html_safe | false (Rails では true) | ActiveSupport の String# html_safe? を使う (:disable_escape と一緒に機能する) | | シンボル | :format | :xhtml | html の出力フォーマット (対応フォーマット :html, :xhtml, :xml) | | 文字列 | :attr_quote | '"' | html の属性を囲む文字 (' または " が可能) | | ハッシュ | :merge_attrs | \{'class' => ' '} | 複数の html 属性が与えられた場合結合に使われる文字列 (例: class="class1 class2") | | 配列<文字列> | :hyphen_attrs | %w(data) | 属性にハッシュが与えられた場合ハイフンつなぎされます。(例: data={a:1, b:2} は data-a="1" data-b="2" のように) | | 真偽値 | :sort_attrs | true | 名前によって属性をソート | | シンボル | :js_wrapper | nil | :comment, :cdata や :both で JavaScript をラップします。:guess を指定することで :format オプションに基いて設定することもできます | | 真偽値 | :pretty | false | 綺麗な html インデント (遅くなります!) | | 文字列 | :indent | ' ' | インデントに使用される文字列 | | 真偽値 | :streaming | false (Rails では true, 無効化するにはストリーミングを参照) | ストリーミング出力の有効化, 体感的なパフォーマンスの向上 | | Class | :generator | Temple::Generators::ArrayBuffer/ RailsOutputBuffer | Temple コードジェネレータ (デフォルトのジェネレータは配列バッファを生成します) | | 文字列 | :buffer | '_buf' (Rails では '@output_buffer') | バッファに使用される変数 | Temple フィルタによってもっと多くのオプションがサポートされていますが一覧には載せず公式にはサポートしません。 Slim と Temple のコードを確認しなければなりません。 ### オプションの優先順位と継承 Slim や Temple のアーキテクチャについてよく知っている開発者は異なる場所で設定を 上書きすることができます。 Temple はサブクラスがスーパークラスのオプションを上書きできるように 継承メカニズムを採用しています。オプションの優先順位は次のとおりです: 1. `Slim::Template` オプションはエンジン初期化時に適用されます 2. `Slim::Template.options` 3. `Slim::Engine.thread_options`, `Slim::Engine.options` 5. パーサ/フィルタ/ジェネレータ `thread_options`, `options` (例: `Slim::Parser`, `Slim::Compiler`) `Temple::Engine` のようにスーパークラスのオプションを設定することも可能です。しかしこれはすべての Temple テンプレートエンジンに影響します。 ~~~ ruby Slim::Engine < Temple::Engine Slim::Compiler < Temple::Filter ~~~ ## プラグイン Slim はロジックレスモードと I18n, インクルードプラグインを提供しています。プラグインのドキュメントを確認してください。 * [ロジックレスモード](doc/jp/logic_less.md) * [パーシャルのインクルード](doc/jp/include.md) * [多言語化/I18n](doc/jp/translator.md) * [スマートテキストモード](doc/jp/smart.md) ## フレームワークサポート ### Tilt Slim は生成されたコードをコンパイルするために [Tilt](https://github.com/rtomayko/tilt) を使用します。Slim テンプレートを直接使いたい場合, Tilt インターフェイスが使用できます。 ~~~ ruby 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) ~~~ optional_option_hash は前述のオプションを持つことができます。このオブジェクトのスコープは実行されるテンプレートの コードです。 ### Sinatra ~~~ ruby require 'sinatra' require 'slim' get('/') { slim :index } __END__ @@ index doctype html html head title Slim で Sinatra body h1 Slim は楽しい! ~~~ ### Rails Rails のジェネレータは [slim-rails](https://github.com/slim-template/slim-rails) によって提供されます。 slim-rails は Rails で Slim を使用する場合に必須ではありません。Slim をインストールし Gemfile に `gem 'slim-rails'` を追加するだけです。 後は .slim 拡張子を使えば Rails で使用できます。 #### ストリーミング HTTP ストリーミングは Rails がそれをサポートしているバージョンであればデフォルトで有効化されています。しかし, ストリーミングが体感的なパフォーマンスを改善していることを知る必要があります。 レンダリング時間は増加するでしょう。ストリーミングを無効化したい場合の設定です: ~~~ ruby Slim::RailsTemplate.set_options streaming: false ~~~ ## ツール ### Slim コマンド 'slimrb' gem の 'slim' にはコマンドラインから Slim をテストするための小さなツール 'slimrb' が付属します。
    $ 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
        -e, --erb                        Convert to ERB
            --rails                      Generate rails compatible code (Implies --compile)
        -r, --require library            Load library or plugin with -r slim/plugin
        -p, --pretty                     Produce pretty html
        -o, --option name=code           Set slim option
        -l, --locals Hash|YAML|JSON      Set local variables
        -h, --help                       Show this message
        -v, --version                    Print version
    
    'slimrb' で起動し, コードをタイプし Ctrl-d で EOF を送ります。Windows のコマンドプロンプトでは Ctrl-z で EOF を送ります。使い方例:
    $ slimrb
    markdown:
      最初の段落。
    
      2つ目の段落。
    
      * 1つ
      * 2つ
      * 3つ
    
    //Enter Ctrl-d
    <p>最初の段落。 </p>
    
    <p>2つめの段落。 </p>
    
    <ul>
    <li>1つ</li>
    <li>2つ</li>
    <li>3つ</li>
    </ul>
    
    ### 構文ハイライト 様々なテキストエディタのためのプラグインがあります。(最も重要なものも含めて - Vim, Emacs や 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) ### テンプレート変換 (HAML, ERB, ...) * Slim は gem に含まれる `slimrb` や `Slim::ERBConverter` を用いて ERB に変換できます。 * [Haml2Slim converter](https://github.com/slim-template/haml2slim) * [ERB2Slim, HTML2Slim converter](https://github.com/slim-template/html2slim) ## テスト ### ベンチマーク *そうです, Slim は最速の Ruby のテンプレートエンジンです! production モードの Slim は Erubis (最速のテンプレートエンジン) と同じくらい高速です。 ありがたいことに何らかの理由であなたが Slim を選択した場合, 私たちは パフォーマンスが障害にならないだろうことを保証します。* ベンチマークは `rake bench` で実行します。時間が余計にかかりますが遅い解析ベンチマークを 実行したい場合 `slow` オプションを追加できます。 ~~~ rake bench slow=1 iterations=1000 ~~~ 私たちはコミット毎に Travis-CI でベンチマークをとっています。最新のベンチマーク結果はリンク先を確認: ### テストスイートと継続的インテグレーション Slim は minitest ベースの拡張性のあるテストスイートを提供します。テストは 'rake test' または rails のインテグレーションテストの場合 'rake test:rails' で実行できます。 私たちは現在 markdown ファイルで書かれた人間が読めるテストを試しています: [TESTS.md](test/literate/TESTS.md) Travis-CI は継続的インテグレーションテストに利用されています: Slim はすべての主要な Ruby 実装で動作します: * Ruby 1.9.3, 2.0.0, 2.1.0 および 2.2.0 * Ruby EE * JRuby 1.9 mode * Rubinius 2.0 ## 貢献 Slim の改良を支援したい場合, Git で管理されているプロジェクトを clone してください。 ~~~ $ git clone git://github.com/slim-template/slim ~~~ 魔法をかけた後 pull request を送ってください。私たちは pull request が大好きです! Ruby の 2.2.0, 2.1.0, 2.0.0 と 1.9.3 でテストをすることを覚えておいてください。 もしドキュメントの不足を見つけたら, README.md をアップデートして私たちを助けて下さい。Slim に割く時間がないが, 私たちが知るべきものを何か見つけた場合には issue を送ってください。 ## License Slim は [MIT license](http://www.opensource.org/licenses/MIT) に基づいてリリースされています。 ## 作者 * [Daniel Mendler](https://github.com/minad) (Lead developer) * [Andrew Stone](https://github.com/stonean) * [Fred Wu](https://github.com/fredwu) ## 寄付とサポート このプロジェクトをサポートしたい場合, Gittip や Flattr のページを見てください。 [![Gittip donate button](http://img.shields.io/gittip/bevry.png)](https://www.gittip.com/min4d/ "Donate weekly to this project using Gittip") [![Flattr donate button](https://raw.github.com/balupton/flattr-buttons/master/badge-89x18.gif)](https://flattr.com/submit/auto?user_id=min4d&url=http%3A%2F%2Fslim-lang.org%2F "Donate monthly to this project using Flattr") 今のところ, 寄付はホスティング費用 (ドメインなど) に当てられる予定です。 ## 議論 * [Google Group](http://groups.google.com/group/slim-template) ## 関連プロジェクト テンプレートのコンパイルフレームワーク: * [Temple](https://github.com/judofyr/temple) フレームワークサポート: * [Rails generators (slim-rails)](https://github.com/slim-template/slim-rails) * [slimkeyfy - Translation string extraction](https://github.com/phrase/slimkeyfy) 構文ハイライト: * [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) * [Atom](https://github.com/slim-template/language-slim) 静的コード解析: * [Slim-Lint](https://github.com/sds/slim-lint) テンプレート変換 (HAML, ERB, ...): * [Haml2Slim converter](https://github.com/slim-template/haml2slim) * [ERB2Slim, HTML2Slim converter](https://github.com/slim-template/html2slim) 移植言語/同様の言語: * [Sliq (Slim/Liquid integration)](https://github.com/slim-template/sliq) * [Slm (Slim port to Javascript)](https://github.com/slm-lang/slm) * [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) * [Emblem.js (Javascript, similar to Slim)](https://github.com/machty/emblem.js) * [Hamlit (High performance Haml implementation, based on Temple like Slim)](https://github.com/k0kubun/hamlit) * [Faml (Faster Haml implementation, also using Temple like Slim)](https://github.com/eagletmt/faml) * [Haml (Older engine which inspired Slim)](https://github.com/haml/haml) * [Jade (Similar engine for javascript)](https://github.com/visionmedia/jade) * [Sweet (Similar engine which also allows to write classes and functions)](https://github.com/joaomdmoura/sweet) * [Amber (Similar engine for Go)](https://github.com/eknkc/amber) slim-3.0.6/README.md0000644000004100000410000011235612555545227014017 0ustar www-datawww-data# Slim [![Gem Version](https://img.shields.io/gem/v/slim.svg)](http://rubygems.org/gems/slim) [![Build Status](https://img.shields.io/travis/slim-template/slim.svg?branch=master)](http://travis-ci.org/slim-template/slim) [![Dependency Status](https://img.shields.io/gemnasium/slim-template/slim.svg?travis)](https://gemnasium.com/slim-template/slim) [![Code Climate](https://img.shields.io/codeclimate/github/slim-template/slim.svg)](https://codeclimate.com/github/slim-template/slim) [![Gittip donate button](https://img.shields.io/gratipay/bevry.svg)](https://www.gittip.com/min4d/ "Donate weekly to this project using Gittip") [![Flattr donate button](https://raw.github.com/balupton/flattr-buttons/master/badge-89x18.gif)](https://flattr.com/submit/auto?user_id=min4d&url=http%3A%2F%2Fslim-lang.org%2F "Donate monthly to this project using Flattr") 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 * Extensible via the following plugins: * Logic less mode similar to Mustache * Includes * Translator/I18n * 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 * Embedded engines like Markdown and Textile ## Links * Homepage: * Source: * Bugs: * List: * API documentation: * Latest Gem: * GitHub master: ## Introduction ### What is Slim? Slim is a fast, lightweight templating engine with support for __Rails 3 and 4__. It has been heavily tested on all major ruby implementations. We use continuous 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. In logic-less mode you can use Slim if you like the Slim syntax to build your HTML but don't want to write Ruby in your templates. ### Why use Slim? * Slim allows you to write very minimal templates which are easy to maintain and pretty much guarantees that you write well-formed HTML and XML * We also think that the Slim syntax is also aesthetic and makes it much more fun to write templates. Since you can use Slim as a drop-in replacement in all the major framework you can start easily. * The Slim architecture is very flexible and allows you to write syntax extensions and plugins. ___Yes, Slim is speedy!___ Slim was developed right from the start with performance in mind. 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! However in our opinion you should use Slim because of its features and syntax. We just ensure that Slim doesn't have a negative impact on the performance of your application. ### 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: ~~~ slim 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. == yield - if items.any? table#items - for item in items 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 ### Verbatim 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. ~~~ slim body p | This is a test of the text block. ~~~ The parsed result of the above: ~~~ html

    This is a test of the text block.

    ~~~ If the text starts on the same line, the left margin is set at the indent of the pipe + one space. Any additional spaces will be copied over. ~~~ slim 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 ~~~ slim - articles.each do |a| | #{a.name}#{a.description} ~~~ ### Verbatim 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 `<` 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. The leading `<` works like an implicit `|`: ~~~ slim 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. ~~~ slim 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: ~~~ slim = 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. For trailing or leading whitespace the modifiers `>` and `<` are supported. * Output with trailing white space `=>`. Same as the single equal sign (`=`), except that it adds a trailing white space. * Output with leading white space `=<`. Same as the single equal sign (`=`), except that it adds a leading white space. ### Output without HTML escaping `==` Same as the single equal sign (`=`), but does not go through the `escape_html` method. For trailing or leading whitespace the modifiers `>` and `<` are supported. * Output without HTML escaping and trailing white space `==>`. Same as the double equal sign (`==`), except that it adds a trailing white space. * Output without HTML escaping and leading white space `==<`. Same as the double equal sign (`==`), except that it adds a leading 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 ~~~ slim 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

    ~~~ ### HTML comment `/!` Use the forward slash immediately followed by an exclamation mark for html comments (``). ### IE conditional comment `/[...]` ~~~ slim /[if IE] p Get a better browser. ~~~ renders as ~~~ html ~~~ ## 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 ~~~~ slim doctype xml doctype xml ISO-8859-1 ~~~ XHTML DOCTYPES ~~~ slim doctype html doctype 5 doctype 1.1 doctype strict doctype frameset doctype mobile doctype basic doctype transitional ~~~ HTML 4 DOCTYPES ~~~ slim doctype strict doctype frameset doctype transitional ~~~ ### Closed tags (trailing `/`) You can close tags explicitly by appending a trailing `/`. ~~~ slim img src="image.png"/ ~~~ Note, that this is usually not necessary since the standard html tags (img, br, ...) are closed automatically. ### Trailing and leading whitespace (`<`, `>`) You can force Slim to add a trailing whitespace after a tag by adding a `>`. ~~~ slim a> href='url1' Link1 a> href='url2' Link2 ~~~ You can add a leading whitespace by adding `<`. ~~~ slim a< href='url1' Link1 a< href='url2' Link2 ~~~ You can also combine both. ~~~ slim a<> href='url1' Link1 ~~~ ### Inline tags Sometimes you may want to be a little more compact and inline the tags. ~~~ slim ul li.first: a href="/a" A link li: a href="/b" B link ~~~ For readability, don't forget you can wrap the attributes. ~~~ slim 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 ~~~ slim body h1 id="headline" Welcome to my site. ~~~ Or nest it. You must use a pipe or an apostrophe to escape processing ~~~ slim body h1 id="headline" | Welcome to my site. ~~~ Or enable and rely on smart text instead ~~~ slim body h1 id="headline" Welcome to my site. ~~~ ### Dynamic content (`=` and `==`) Can make the call on the same line ~~~ slim body h1 id="headline" = page_headline ~~~ Or nest it. ~~~ slim 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). ~~~ slim 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. You can configure these symbols (See option `:attr_list_delims`). ~~~ slim 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: ~~~ slim h2[id="tagline" class="small tagline"] = page_tagline ~~~ You may use spaces around the wrappers and assignments: ~~~ slim h1 id = "logo" = page_logo h2 [ id = "tagline" ] = page_tagline ~~~ #### Quoted attributes Example: ~~~ slim a href="http://slim-lang.com" title='Slim Homepage' Goto the Slim homepage ~~~ You can use text interpolation in the quoted attributes: ~~~ slim 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. ~~~ slim a href=="&" ~~~ 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...." ~~~ #### 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 `[...]`. ~~~ slim body table - for user in users 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. ~~~ slim 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 attribute wrapper you can omit the attribute assigment. ~~~ slim 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. ~~~ slim a.menu class="highlight" href="http://slim-lang.com/" Slim-lang.com ~~~ This 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 a class=["menu","highlight"] a class=:menu,:highlight ~~~ #### Splat attributes `*` The splat shortcut allows you turn a hash in to attribute/value pairs ~~~ slim .card*{'data-url'=>place_path(place), 'data-id'=>place.id} = place.name ~~~ renders as ~~~ html
    Slim's house
    ~~~ You can also use methods or instance variables which return a hash as shown here: ~~~ slim .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` ~~~ slim .first *{class: [:second, :third]} Text ~~~ renders as ~~~ html 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. ~~~ 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 You can define custom tag shortcuts by setting the option `:shortcut`. ~~~ ruby Slim::Engine.set_options shortcut: {'c' => {tag: 'container'}, '#' => {attr: 'id'}, '.' => {attr: 'class'} } ~~~ We can use it in Slim code like this ~~~ slim c.content Text ~~~ which renders to ~~~ html 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. ~~~ ruby Slim::Engine.set_options shortcut: {'&' => {tag: 'input', attr: 'type'}, '#' => {attr: 'id'}, '.' => {attr: 'class'}} ~~~ We can use it in Slim code like this ~~~ slim &text name="user" &password name="pw" &submit ~~~ which renders to ~~~ html ~~~ In another example we add `@` to create a shortcut for the role attribute. ~~~ ruby Slim::Engine.set_options shortcut: {'@' => {attr: 'role'}, '#' => {attr: 'id'}, '.' => {attr: 'class'}} ~~~ We can use it in Slim code like this ~~~ slim .person@admin = person.name ~~~ which renders to ~~~ html
    Daniel
    ~~~ You can also set multiple attributes at once using one shortcut. ~~~ ruby Slim::Engine.set_options shortcut: {'@' => {attr: %w(data-role role)}} ~~~ We can use it in Slim code like this ~~~ slim .person@admin = person.name ~~~ which renders to ~~~ html
    Daniel
    ~~~ #### ID shortcut `#` and class shortcut `.` You can specify the `id` and `class` attributes in the following shortcut form ~~~ slim body h1#headline = page_headline h2#tagline.small.tagline = page_tagline .content = show_content ~~~ This is the same as ~~~ slim body h1 id="headline" = page_headline h2 id="tagline" class="small tagline" = page_tagline div class="content" = show_content ~~~ ## Helpers, capturing and includes If you use Slim you might want to extend your template with some helpers. Assume that you have the following helper ~~~ruby module Helpers def headline(&block) if defined?(::Rails) # In Rails we have to use capture! "

    #{capture(&block)}

    " else # If we are using Slim without a framework (Plain Tilt), # this works directly. "

    #{yield}

    " end end end ~~~ which is included in the scope that executes the Slim template code. The helper can then be used in the Slim template as follows ~~~ slim p = headline do ' Hello = user.name ~~~ The content in the `do` block is then captured automatically and passed to the helper via `yield`. As a syntactic sugar you can omit the `do` keyword and write only ~~~ slim p = headline ' Hello = user.name ~~~ ### Capturing to local variables Using the `Binding` you can capture to local variables as follows: ~~~ruby module Helpers def capture_to_local(var, &block) set_var = block.binding.eval("lambda {|x| #{var} = x }") # In Rails we have to use capture! # If we are using Slim without a framework (Plain Tilt), # you can just yield to get the captured block. set_var.call(defined?(::Rails) ? capture(&block) : yield) end end ~~~ The helper can then be used in the Slim template as follows ~~~ slim / The captured_content variable must be known by the Binding beforehand. = capture_to_local captured_content=:captured_content p This will be captured in the variable captured_content = captured_content ~~~ Another interesting use case is to use an enumerable and capture for each element. The helper could look like this ~~~ ruby module Capture def capture(var, enumerable = nil, &block) value = enumerable ? enumerable.map(&block) : yield block.binding.eval("lambda {|x| #{var} = x }").call(value) nil end end ~~~ and it would be used as follows ~~~ slim - links = { 'http://slim-lang.com' => 'The Slim Template Language' } = capture link_list=:link_list, links do |url, text| a href=url = text ~~~ Afterwards, `link_list` contains the captured content. ### Include helper If you want includes which are processed at compile time, you can take a look at [Include partials](doc/include.md). However you can also execute subtemplates at runtime (similar to Rails' `#render`). You have to write your own include helper: ~~~ ruby module Helpers def include_slim(name, options = {}, &block) Slim::Template.new("#{name}.slim", options).render(self, &block) end end ~~~ This helper can then be used as follows ~~~ slim nav = include_slim 'menu' section = include_slim 'content' ~~~ However this helper doesn't do any caching. You should therefore implement a more intelligent version of the helper which fits your purposes. You should also be aware that most frameworks already bring their own include helper, e.g. Rails has `render`. ## Text interpolation Use standard Ruby interpolation. The text will be html escaped by default. ~~~ slim body h1 Welcome #{current_user.name} to the show. | Unescaped #{{content}} is also possible. ~~~ To escape the interpolation (i.e. render as is) ~~~ slim 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: ~~~ slim coffee: square = (x) -> x * x markdown: #Header Hello from #{"Markdown!"} Second Line! p: markdown: Tag with **inline** markdown! ~~~ Supported engines: | Filter | Required gems | Type | Description | | ------ | ------------- | ---- | ----------- | | ruby: | none | Shortcut | Shortcut to embed ruby code | | javascript: | none | Shortcut | Shortcut to embed javascript code and wrap in script tag | | css: | none | Shortcut | Shortcut to embed css code and wrap in style tag | | sass: | sass | Compile time | Embed sass code and wrap in style tag | | scss: | sass | Compile time | Embedd scss code and wrap in style tag | | less: | less | Compile time | Embed less css code and wrap in style tag | | styl: | styl | Compile time | Embed stylus css code and wrap in style tag | | coffee: | coffee-script | Compile time | Compile coffee script code and wrap in script tag | | asciidoc: | asciidoctor | Compile time + Interpolation | Compile AsciiDoc code and interpolate #\{variables} in text | | markdown: | redcarpet/rdiscount/kramdown | Compile time + Interpolation | Compile markdown code and interpolate #\{variables} in text | | textile: | redcloth | Compile time + Interpolation | Compile textile code and interpolate #\{variables} in text | | creole: | creole | Compile time + Interpolation | Compile creole code and interpolate #\{variables} in text | | wiki:, mediawiki: | wikicloth | Compile time + Interpolation | Compile wiki code and interpolate #\{variables} in text | | rdoc: | rdoc | Compile time + Interpolation | Compile rdoc code and interpolate #\{variables} in text | | builder: | builder | Precompiled | Embed builder code | | nokogiri: | nokogiri | Precompiled | Embed nokogiri builder code | | erb: | none | Precompiled | Embed erb code | The embedded engines can be configured in Slim by setting the options directly on the `Slim::Embedded` filter. Example: ~~~ ruby Slim::Embedded.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 ~~~ ruby # Indent html for pretty debugging and do not sort attributes Slim::Engine.set_options pretty: true, sort_attrs: false ~~~ You can also access the option hash directly: ~~~ ruby Slim::Engine.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 instantiate the template: ~~~ ruby 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: ~~~ ruby 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. ~~~ ruby # 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_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. | Type | Name | Default | Purpose | | ---- | ---- | ------- | ------- | | String | :file | nil | Name of parsed file, set automatically by Slim::Template | | Integer | :tabsize | 4 | Number 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 | | Hash | :code_attr_delims | \{'(' => ')', '[' => ']', '{' => '}'} | Attribute delimiters for Ruby code attributes | | Hash | :attr_list_delims | \{'(' => ')', '[' => ']', '{' => '}'} | Attribute list delimiter | | Array<Symbol,String> | :enable_engines | nil (All enabled) | List of enabled embedded engines (whitelist) | | Array<Symbol,String> | :disable_engines | nil (None disabled) | List of disabled embedded engines (blacklist) | | Boolean | :disable_capture | false (true in Rails) | Disable capturing in blocks (blocks write to the default buffer | | Boolean | :disable_escape | false | Disable automatic escaping of strings | | Boolean | :use_html_safe | false (true in Rails) | Use String#html_safe? from ActiveSupport (Works together with :disable_escape) | | Symbol | :format | :xhtml | HTML output format (Possible formats :html, :xhtml, :xml) | | 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_attrs | true | Sort attributes by name | | Symbol | :js_wrapper | nil | Wrap javascript by :comment, :cdata or :both. You can also :guess the wrapper based on :format. | | Boolean | :pretty | false | Pretty HTML indenting, only block level tags are indented (This is slower!) | | String | :indent | ' ' | Indentation string | | Boolean | :streaming | false (true in Rails, see below how to disable it!) | Enable output streaming, improves the perceived performance | | Class | :generator | Temple::Generators::ArrayBuffer/ RailsOutputBuffer | Temple 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 instantiation 2. `Slim::Template.options` 3. `Slim::Engine.thread_options`, `Slim::Engine.options` 5. Parser/Filter/Generator `thread_options`, `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. ~~~ ruby Slim::Engine < Temple::Engine Slim::Compiler < Temple::Filter ~~~ ## Plugins Slim currently provides plugins for logic less mode, includes and I18n. See the plugin documentation. * [Logic less mode](doc/logic_less.md) * [Include partials](doc/include.md) * [Translator/I18n](doc/translator.md) * [Smart text mode](doc/smart.md) ## 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. ~~~ ruby 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. The scope is the object in which the template code is executed. ### Sinatra ~~~ ruby 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-rails'`. 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. However you have to be aware that streaming only improves the perceived performance. The rendering time in total will increase. If you want to disable it use: ~~~ ruby Slim::RailsTemplate.set_options streaming: false ~~~ ## 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
        -e, --erb                        Convert to ERB
            --rails                      Generate rails compatible code (Implies --compile)
        -r, --require library            Load library or plugin with -r slim/plugin
        -p, --pretty                     Produce pretty html
        -o, --option name=code           Set slim option
        -l, --locals Hash|YAML|JSON      Set local variables
        -h, --help                       Show this message
        -v, --version                    Print version
    
    Start 'slimrb', type your code and press Ctrl-d to send EOF. In Windows Command Prompt press Ctrl-z, Enter 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, ...) * Slim can be converted to ERB using `slimrb` or `Slim::ERBConverter' which are both included in the Slim gem * [Haml2Slim converter](https://github.com/slim-template/haml2slim) * [ERB2Slim, 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 continuous 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 continuous integration testing: Slim is working well on all major Ruby implementations: * Ruby 1.9.3, 2.0.0, 2.1.0 and 2.2.0 * Ruby EE * JRuby 1.9 mode * 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 keep the compatibility with Ruby versions 1.9.3, 2.0.0, 2.1.0 and 2.2.0. If you find the documentation lacking, 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) ## Donations and sponsoring If you want to support this project please visit the Gittip and Flattr pages. [![Gittip donate button](https://img.shields.io/gratipay/bevry.svg)](https://www.gittip.com/min4d/ "Donate weekly to this project using Gittip") [![Flattr donate button](https://raw.github.com/balupton/flattr-buttons/master/badge-89x18.gif)](https://flattr.com/submit/auto?user_id=min4d&url=http%3A%2F%2Fslim-lang.org%2F "Donate monthly to this project using Flattr") Currently the donations will be used to cover the hosting costs (domain name etc). ## Discuss * [Google Group](http://groups.google.com/group/slim-template) ## Related projects Template compilation framework: * [Temple](https://github.com/judofyr/temple) Framework support: * [Rails generators (slim-rails)](https://github.com/slim-template/slim-rails) * [slimkeyfy - Translation string extraction](https://github.com/phrase/slimkeyfy) 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) * [Atom](https://github.com/slim-template/language-slim) Static code analysis: * [Slim-Lint](https://github.com/sds/slim-lint) Template Converters (HAML, ERB, ...): * [Haml2Slim converter](https://github.com/slim-template/haml2slim) * [ERB2Slim, HTML2Slim converter](https://github.com/slim-template/html2slim) Language ports/Similar languages: * [Sliq (Slim/Liquid integration)](https://github.com/slim-template/sliq) * [Slm (Slim port to Javascript)](https://github.com/slm-lang/slm) * [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) * [Emblem.js (Javascript, similar to Slim)](https://github.com/machty/emblem.js) * [Hamlit (High performance Haml implementation, based on Temple like Slim)](https://github.com/k0kubun/hamlit) * [Faml (Faster Haml implementation, also using Temple like Slim)](https://github.com/eagletmt/faml) * [Haml (Older engine which inspired Slim)](https://github.com/haml/haml) * [Jade (Similar engine for javascript)](https://github.com/visionmedia/jade) * [Sweet (Similar engine which also allows to write classes and functions)](https://github.com/joaomdmoura/sweet) * [Amber (Similar engine for Go)](https://github.com/eknkc/amber) slim-3.0.6/CHANGES0000644000004100000410000003622612555545227013534 0ustar www-datawww-data3.0.6 (2015-06-05) * Fix warnings #625 3.0.4 (2015-06-02) * javascript: doesn't add type='text/javascript' anymore * slimrb: --require added * Fix #624 3.0.3 (2015-03-06) * Fix #392, capturing for splat attributes didn't work correctly under Rails 3.0.2 (2015-02-02) * slimrb: Add option --locals * Fix issues in the test suite (#576), thanks @dmke! 3.0.1 (2014-12-22) * Allow more special characters in html attribute names (See https://html.spec.whatwg.org/multipage/syntax.html#attributes-2), #567 * Fix: Code attributes mutate their argument (#571) 3.0.0 (2014-12-07) * Drop 1.8.7 support * Deprecate default_options in favor of options * Support xml pretty printing with format: :xml * Deprecate `='`, `=='` and `tag'` syntax for trailing whitespace. Use `=<` etc. instead. * slimrb: Remove deprecated plugin options -l and -t 2.1.0 (2014-10-15) * Parser: Require pairwise braces in quoted attributes * Parser: add :attr_list_delims and :code_attr_delims * Parser: deprecate :attr_delims * Parser: relax text indentation requirements: | line next line tag some text more text * Parser: allow first line to be indented * Parser: allow inline embedded languages: .content: markdown: This is **important** * Parser: allow line breaks in quoted attributes * Added Opal as embedded engine * slimrb: Change meaning of -r, deprecate -t and -l * Fix issue with inserted end (#485) * Add experimental 'slim/include' plugin (Might change in the future) * Add experimental 'slim/smart' plugin (Might change in the future) * Drop jruby18 support * Fix rails error reporting #587 (Manipulate stacktrace) * Splat: handle html_safe 2.0.3 (2014-07-04) * slimrb: Don't update HTML output on exceptions * Allow dashes at the beginning of class names (#474) * Render empty attributes as standalone in html mode (#480) * Fix #482: problem with whitespace modifier `tag=<` * Fix #485: missing end for empty `if` control blocks * Fix #510: double dash in class name 2.0.2 (2013-10-27) * Add option :attr_delims 2.0.1 (2013-07-31) * Support multiple attributes per shortcut (See issue #415) * Add support for org-ruby embedded engine * Render true boolean attributes with empty value * Support case-when statements * Fix issue #431 * Also escape ' to ' 2.0.0 (2013-05-27) * 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'] * Quoted attributes are escaped by default 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 '
    ' * Removed deprecated options: - :escape_quoted_attrs - :remove_empty_attrs - :chain - :attr_wrapper (renamed to :attr_quote) - :attr_delimiter (renamed to :merge_attrs) - Slim::LogicLess :wrapped dictionary - Slim::Parser :shortcut string option * Allow spaces around attributes, e.g 'a [ href = url ] text' and 'a href = url text' * Add unicode support for tags and attributes (Issue #212) * Generate missing `do` keywords for code blocks (see #342) * Logic-less: Add keyword `self` for string access * Added Slim::ERBConverter, require 'slim/erb_converter' * Added option '-e' for ERB conversion to slimrb * Add syntax for trailing or leading whitespace after tag, e.g. input>, input< * Add syntax for trailing or leading whitespace after output, e.g. =>, =< 1.3.8 (2013-04-11) * Disable some superflous deprecation warnings 1.3.7 (2013-04-10) * Fixed issue #374, rescue and ensure blocks * Fixed issue #333 (Throw syntax error if you write text after closed tag) * Deprecated :attr_delimiter (renamed to :merge_attrs) * Deprecated :attr_wrapper (renamed to :attr_quote) * Warn if you use curly braces or brackets for ruby attributes since curly braces and brackets will be interpreted as Hash/Array in Slim 2.0.0 Old syntax: div id={person && person.id} div id=[person && person.id] New syntax in 2.0.0: div id=(person && person.id) * Deprecated :escape_quoted_attrs (done by default in 2.0) * Warn if quoted attributes might be double escaped in Slim 2.0.0 Old syntax: a href='http://slim-lang.com/?a=1&b=2' a href=='http://slim-lang.com/?a=1&b=2' New syntax in 2.0.0: a href='http://slim-lang.com/?a=1&b=2' a href=='http://slim-lang.com/?a=1&b=2' * Improved pretty printing (Issue #202) * Renamed Slim::EmbeddedEngine to Slim::Embedded (Old constant still available until 2.0) * 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) * Asciidoc embedded engine added 1.3.6 (2013-01-06) * 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 (2012-12-19) * 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 (2012-11-15) * Fixed #314 * Logic-less test cases added 1.3.3 (2012-10-16) * 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 (2012-09-26) * Fix boolean attributes #299 1.3.1 (2012-09-23) * 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 (2012-09-04) * 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 (2012-06-21) * Fix issue #264 1.2.1 (2012-05-22) * Support stylus as embedded engine * Fix issue #257 1.2.0 (2012-03-30) * 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 (2012-02-29) * 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 (2012-01-06) * 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 (2011-11-03) * 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 (2011-10-08) * 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 (2011-08-26) * 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 (2011-08-07) * 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 (2011-07-24) * 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 (2011-05-15) * 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 (2011-03-30) * 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 (2011-03-10) * add new doctype syntax without ! * slim directive expression has type and args 0.9.0 (2011-01-30) * slim should not be registered as the default template handler. * add support for unescaped text interpolation 0.8.4 (2011-01-26) * 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 (2010-12-23) * 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 (2010-12-22) * fix issue #96 * Added the Temple Debugger filter. * Rails problems fixed 0.8.1 (2010-12-17) * remove backtick slim syntax -- no longer supported * slim executable conflict. issue #91 * vim syntax support improved 0.8.0 (2010-11-29) * rails logic less support 0.7.4 (2010-11-22) * use ' for text block with trailing whitespace * allow to disable/enable embedded engines 0.7.3 (2010-11-16) * fix #82 * basic rails test added 0.7.2 (2010-11-09) * get rid of rails deprecation warning * use_html_safe is activated automatically by temple 0.7.1 (2010-11-03) * logic less mode * add syntax for explicitly closed tags 0.7.0 (2010-10-25) * 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 (2010-10-17) * can wrap parens around attributes if you so desire * added erubis to the benchmarks 0.6.0 (2010-10-17) * 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 (2010-10-08) * Consecutive condition statements now working as expected. 0.5.0 (2010-10-07) * 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 (2010-10-03) * 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 (2010-09-21) * 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 (2010-09-17) * fix bug with adding end to nesting ruby code 0.3.0 (2010-09-17) * Optimize compiled string to reduce number of concatentations to the buffer 0.2.0 (2010-09-17) * can now make code call on same line as tag 0.1.0 (2010-09-15) * Initial release