pax_global_header00006660000000000000000000000064145352631070014520gustar00rootroot0000000000000052 comment=8e68e37b0f1e82ffca725d0b5e8278421f6d4cb5 haml-6.3.0/000077500000000000000000000000001453526310700124475ustar00rootroot00000000000000haml-6.3.0/.github/000077500000000000000000000000001453526310700140075ustar00rootroot00000000000000haml-6.3.0/.github/FUNDING.yml000066400000000000000000000000351453526310700156220ustar00rootroot00000000000000github: - haml - k0kubun haml-6.3.0/.github/workflows/000077500000000000000000000000001453526310700160445ustar00rootroot00000000000000haml-6.3.0/.github/workflows/test.yml000066400000000000000000000014231453526310700175460ustar00rootroot00000000000000name: test on: push: branches: - main pull_request: types: - opened - synchronize - reopened schedule: - cron: "00 15 * * *" jobs: test: runs-on: ubuntu-latest strategy: fail-fast: false matrix: ruby: - '2.5' - '2.6' - '2.7' - '3.0' - '3.1' - '3.2' - jruby - truffleruby-head steps: - uses: actions/checkout@v3 - run: sudo apt-get update && sudo apt-get install -y nodejs libxslt-dev # nodejs for execjs, libxslt for TruffleRuby nokogiri - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: bundle exec rake test haml-6.3.0/.gitignore000066400000000000000000000002401453526310700144330ustar00rootroot00000000000000/.bundle/ /.yardoc /Gemfile.lock /_yardoc/ /.idea /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ /haml/ .sass-cache .ruby-version *.bundle *.so *.su *.a *.o *.swp haml-6.3.0/.yardopts000066400000000000000000000007271453526310700143230ustar00rootroot00000000000000--charset utf-8 --readme README.md --markup markdown --markup-provider kramdown --template-path yard --default-return "" --title "Haml Documentation" --query 'object.type != :classvariable' --query 'object.type != :constant || @api && @api.text == "public"' --exclude lib/haml/railtie.rb --hide-void-return --protected --no-private --no-highlight - FAQ.md CHANGELOG.md REFERENCE.md MIT-LICENSE haml-6.3.0/CHANGELOG.md000066400000000000000000001641141453526310700142670ustar00rootroot00000000000000# Haml Changelog ## 6.3.0 * Remove `Haml::RailsTemplate#default_format` that was added in v6.1.3 for Turbo [#1152](https://github.com/haml/haml/issues/1152), [#1154](https://github.com/haml/haml/issues/1154) ([discussion](https://github.com/haml/haml/pull/1144#issuecomment-1755088572)) * See [the reference](https://github.com/haml/haml/blob/v6.3.0/REFERENCE.md#turbo) for suggested alternatives. ## 6.2.5 * Deprecate `Haml::RailsTemplate#default_format` that was added in v6.1.3 for Turbo ([discussion](https://github.com/haml/haml/pull/1144#issuecomment-1755088572)) * See [the reference](https://github.com/haml/haml/blob/v6.2.5/REFERENCE.md#turbo) for suggested alternatives. ## 6.2.4 * Support case-in statement [#1155](https://github.com/haml/haml/issues/1155) ## 6.2.3 * Resurrect RDFa doctype support [#1147](https://github.com/haml/haml/issues/1147) ## 6.2.2 * Allow adding custom attributes to `Haml::BOOLEAN_ATTRIBUTES` [#1148](https://github.com/haml/haml/issues/1148) * Consider `aria-xxx: false` as a boolean attribute ## 6.2.1 * Fix v6.2.0's bug in rendering dynamic `aria` attributes [#1149](https://github.com/haml/haml/issues/1149) ## 6.2.0 * Drop the C extension [#1146](https://github.com/haml/haml/issues/1146) ## 6.1.4 * Let `Haml::Util.escape_html` use `ERB::Escape` if available [#1145](https://github.com/haml/haml/issues/1145) ## 6.1.3 * Add `Haml::RailsTemplate#default_format` for Turbo compatibility [#1144](https://github.com/haml/haml/issues/1144) ## 6.1.2 * Use the rails template path as `filename` [#1140](https://github.com/haml/haml/issues/1140) ## 6.1.1 * Fix an empty output of Ruby 3.1's Hash shorthand syntax [#1083](https://github.com/haml/haml/issues/1083) ## 6.1.0 * Optimize away a `to_s` call on `=` scripts * Fix escaping for objects that return an `html_safe` string on `to_s` [#1117](https://github.com/haml/haml/issues/1117) ## 6.0.12 * Fix a whitespace removal with `>` and an `if`-`else` statement [#1114](https://github.com/haml/haml/issues/1114) ## 6.0.11 * Fix a whitespace removal with `>` and an `if` statement [#1114](https://github.com/haml/haml/issues/1114) ## 6.0.10 * Evaluate :erb filter in the template context like Haml 5 ## 6.0.9 * Support sass-embedded [#1112](https://github.com/haml/haml/issues/1112) ## 6.0.8 * Support interpolation in HTML comments, which has not been working since 6.0.0 [#1107](https://github.com/haml/haml/issues/1107) ## 6.0.7 * `Haml::Engine` and `Haml::Template` use StringBuffer instead of ArrayBuffer * It seems more performant in many cases with recent Ruby versions. * `Haml::RailsTemplate` is not affected. ## 6.0.6 * Prevent CRuby from accidentally using the Ruby implementation fallback * Reversing what v6.0.3 and v6.0.4 did, but still supporting Wasm. ## 6.0.5 * Resurrect `#haml_object_ref` support in an object reference [#1097](https://github.com/haml/haml/issues/1097) * This was removed in 6.0.0, and added back in this version. * Stop warning `remove_whitespace: true` option. ## 6.0.4 Released on October 2, 2022 ([diff](https://github.com/haml/haml/compare/v6.0.3...v6.0.4)). * Fix a parse failure of `%` in attributes [#1096](https://github.com/haml/haml/issues/1096) * Add another fallback from C to Ruby for Wasm. ## 6.0.3 Released on September 28, 2022 ([diff](https://github.com/haml/haml/compare/v6.0.2...v6.0.3)). * For Wasm, fallback to Ruby when C extension is not available. ## 6.0.2 Released on September 28, 2022 ([diff](https://github.com/haml/haml/compare/v6.0.1...v6.0.2)). * Unescape HTML-safe arguments for `surround`, `succeed`, and `precede` on Rails [#1088](https://github.com/haml/haml/issues/1088) ## 6.0.1 Released on September 23, 2022 ([diff](https://github.com/haml/haml/compare/v6.0.0...v6.0.1)). * Unescape HTML-safe interpolation on Rails [#1084](https://github.com/haml/haml/issues/1084) * Resurrect Haml 5's `AttributeParser.available?` for syntax\_tree-haml [#1085](https://github.com/haml/haml/issues/1085) ## 6.0.0 Released on September 21, 2022 ([diff](https://github.com/haml/haml/compare/v5.2.2...v6.0.0)). * Replace the implementation with Hamlit * Haml 6 is about 1.7x faster than Haml 5 in [this benchmark](benchmark/slim/run-benchmarks.rb). * The parser is kept as is, but everything else is replaced. * The `haml` CLI interface was also replaced. * The interface of `Haml::Engine` is changed. `Haml::Template` is most likely what you need now. * before: `Haml::Engine.new("%p Haml code!").render` * after: `Haml::Template.new { "%p Haml code!" }.render` * Most Haml helpers are removed. * Rails: * Kept: `find_and_reserve`, `preserve`, `surround`, `precede`, `succeed`, `capture_haml` * Removed: `block_is_haml?`, `flatten`, `haml_concat`, `haml_indent`, `haml_tag`, `haml_tag_if`, `html_attrs`, `html_escape`, `init_haml_helpers`, `is_haml?`, `list_of`, `non_haml`, `tab_down`, `tab_up`, `with_tabs` * Tilt: * Kept: `preserve` * Removed: `block_is_haml?`, `capture_haml`, `escape_once`, `find_and_preserve`, `flatten`, `haml_concat`, `haml_indent`, `haml_tag`, `haml_tag_if`, `html_attrs`, `html_escape`, `init_haml_helpers`, `is_haml?`, `list_of`, `non_haml`, `precede`, `succeed`, `surround`, `tab_down`, `tab_up`, `with_tabs` * `:ruby` filter * Removed: `haml_io` * Alternatives to the removed helpers: * Some simple ones could work by copying [the original definition](https://github.com/haml/haml/blob/v5.2.2/lib/haml/helpers.rb). * For helpers generating general HTML tags, also consider using what your framework provides, e.g. Rails `content_tag`. Same applies to `capture_haml`, e.g. Rails `capture`. * Ones that rely on `Haml::Buffer` have no direct alternative by design. They existed at the cost of performance. You need to define a helper, instantiate a String buffer in it, append stuff to it, and call it inside `=`. * Only the following attributes and `aria`/`data` attributes are considered boolean attributes: * `allowfullscreen`, `async`, `autobuffer`, `autofocus`, `autoplay`, `checked`, `controls`, `default`, `defer`, `disabled`, `download`, `formnovalidate`, `hidden`, `inert`, `ismap`, `itemscope`, `loop`, `multiple`, `muted`, `novalidate`, `open`, `pubdate`, `readonly`, `required`, `reversed`, `scoped`, `seamless`, `selected`, `sortable`, `truespeed`, `typemustmatch` * Only `data` and `aria` attributes support using a nested Hash to render hyphenated attributes, e.g. `data: { foo: 'bar' }` becomes `data-foo="bar"`, but this no longer works for non-`data`/`aria` attributes. * Some legacy Rails integration is removed. * The default value of `escape_html` option became true. * `-` script lines no longer support capturing. Only `=` lines are supported to yield a nested block. * Overriding `data` attributes with another falsy `data-*` attribute that has the same name is no longer supported. [#1105](https://github.com/haml/haml/issues/1105) * :erb filter is not executed in the template context (fixed in 6.0.10) ## 5.2.2 Released on July 27, 2021 ([diff](https://github.com/haml/haml/compare/v5.2.1...v5.2.2)). * Support `config.action_view.annotate_rendered_view_with_filenames = true` of Rails 6.1 ## 5.2.1 Released on November 30, 2020 ([diff](https://github.com/haml/haml/compare/v5.2.0...v5.2.1)). * Add in improved "multiline" support for attributes [#1043](https://github.com/haml/haml/issues/1043) ## 5.2 Released on September 28, 2020 ([diff](https://github.com/haml/haml/compare/v5.1.2...v5.2.0)). * Fix crash in the attribute optimizer when `#inspect` is overridden in TrueClass / FalseClass [#972](https://github.com/haml/haml/issues/972) * Do not HTML-escape templates that are declared to be plaintext [#1014](https://github.com/haml/haml/issues/1014) (Thanks [@cesarizu](https://github.com/cesarizu)) * Class names are no longer ordered alphabetically, and now follow a new specification as laid out in REFERENCE [#306](https://github.com/haml/haml/issues/306) ## 5.1.2 Released on August 6, 2019 ([diff](https://github.com/haml/haml/compare/v5.1.1...v5.1.2)). * Fix crash in some environments such as New Relic by unfreezing string literals for ParseNode#inspect. [#1016](https://github.com/haml/haml/pull/1016) (thanks [Jalyna](https://github.com/jalyna)) ## 5.1.1 Released on May 25, 2019 ([diff](https://github.com/haml/haml/compare/v5.1.0...v5.1.1)). * Fix NameError bug that happens on ruby 2.6.1-2.6.3 + haml 5.1.0 + rails < 5.1 + erubi. (Akira Matsuda) ## 5.1.0 Released on May 16, 2019 ([diff](https://github.com/haml/haml/compare/v5.0.4...v5.1.0)). * Rails 6 support [#1008](https://github.com/haml/haml/pull/1008) (thanks [Seb Jacobs](https://github.com/sebjacobs)) * Add `escape_filter_interpolations` option for backwards compatibility with haml 4 defaults [#984](https://github.com/haml/haml/pull/984) (thanks [Will Jordan](https://github.com/wjordan)) * Fix error on empty :javascript and :css filter blocks [#986](https://github.com/haml/haml/pull/986) (thanks [Will Jordan](https://github.com/wjordan)) * Respect changes in Haml::Options.defaults in `Haml::TempleEngine` options (Takashi Kokubun) * Un-freeze TempleEngine precompiled string literals [#983](https://github.com/haml/haml/pull/983) (thanks [Will Jordan](https://github.com/wjordan)) * Various performance/memory improvements [#965](https://github.com/haml/haml/pull/965), [#966](https://github.com/haml/haml/pull/966), [#963](https://github.com/haml/haml/pull/963) (thanks [Dillon Welch](https://github.com/oniofchaos)) * Enable `frozen_string_literal` magic comment for all .rb files [#967](https://github.com/haml/haml/pull/967) (thanks [Dillon Welch](https://github.com/oniofchaos)) ## 5.0.4 Released on October 13, 2017 ([diff](https://github.com/haml/haml/compare/v5.0.3...v5.0.4)). * Fix `haml -c --stdin` regression in 5.0.2. [#958](https://github.com/haml/haml/pull/958) (thanks [Timo Göllner](https://github.com/TeaMoe)) * Ruby 2.5 support (it wasn't working due to Ripper API change). (Akira Matsuda) ## 5.0.3 Released on September 7, 2017 ([diff](https://github.com/haml/haml/compare/v5.0.2...v5.0.3)). * Use `String#dump` instead of `String#inspect` to generate string literal. (Takashi Kokubun) * Fix Erubi superclass mismatch error. [#952](https://github.com/haml/haml/pull/952) (thanks [Robin Daugherty](https://github.com/RobinDaugherty)) ## 5.0.2 Released on August 1, 2017 ([diff](https://github.com/haml/haml/compare/v5.0.1...v5.0.2)). * Let `haml -c` fail if generated Ruby code is syntax error. [#880](https://github.com/haml/haml/issues/880) (Takashi Kokubun) * Fix `NoMethodError` bug caused with Sprockets 3 and :sass filter. [#930](https://github.com/haml/haml/pull/930) (thanks [Gonzalez Maximiliano](https://github.com/emaxi)) * Fix `list_of` helper with multi-line content. [#933](https://github.com/haml/haml/pull/933) (thanks [Benoit Larroque](https://github.com/zetaben)) * Optimize rendering performance by changing timing to fix textareas. [#941](https://github.com/haml/haml/pull/941) (Takashi Kokubun) * Fix `TypeError` with empty :ruby filter. [#942](https://github.com/haml/haml/pull/942) (Takashi Kokubun) * Fix inconsistent attribute sort order. (Takashi Kokubun) ## 5.0.1 Released on May 3, 2017 ([diff](https://github.com/haml/haml/compare/v5.0.0...v5.0.1)). * Fix parsing attributes including string interpolation. [#917](https://github.com/haml/haml/pull/917) [#921](https://github.com/haml/haml/issues/921) * Stop distributing test files in gem package and allow installing on Windows. * Use ActionView's Erubi/Erubis handler for erb filter only on ActionView. [#914](https://github.com/haml/haml/pull/914) ## 5.0.0 Released on April 26, 2017 ([diff](https://github.com/haml/haml/compare/4.0.7...v5.0.0)). Breaking Changes * Haml now requires Ruby 2.0.0 or above. * Rails 3 is no longer supported, matching the official [Maintenance Policy for Ruby on Rails](http://weblog.rubyonrails.org/2013/2/24/maintenance-policy-for-ruby-on-rails/). Use Haml 4 if you want to use Rails 3. (Tee Parham) * Remove `:ugly` option ([#894](https://github.com/haml/haml/pull/894)) * The `haml` command's debug option (`-d`) no longer executes the Haml code, but rather checks the generated Ruby syntax for errors. * Drop parser/compiler accessor from `Haml::Engine`. Modify `Haml::Engine#initialize` options or `Haml::Template.options` instead. (Takashi Kokubun) * Drop dynamic quotes support and always escape `'` for `escape_html`/`escape_attrs` instead. Also, escaped results are slightly changed and always unified to the same characters. (Takashi Kokubun) * Don't preserve newlines in attributes. (Takashi Kokubun) * HTML escape interpolated code in filters. [#770](https://github.com/haml/haml/pull/770) (Matt Wildig) :javascript #{JSON.generate(foo: "bar")} Haml 4 output: {"foo":"bar"} Haml 5 output: {"foo":"bar"} Added * Add a tracing option. When enabled, Haml will output a data-trace attribute on each tag showing the path to the source Haml file from which it was generated. Thanks [Alex Babkin](https://github.com/ababkin). * Add `haml_tag_if` to render a block, conditionally wrapped in another element (Matt Wildig) * Support Rails 5.1 Erubi template handler. * Support Sprockets 3. Thanks [Sam Davies](https://github.com/samphilipd) and [Jeremy Venezia](https://github.com/jvenezia). * General performance and memory usage improvements. (Akira Matsuda) * Analyze attribute values by Ripper and render static attributes beforehand. (Takashi Kokubun) * Optimize attribute rendering about 3x faster. (Takashi Kokubun) * Add temple gem as dependency and create `Haml::TempleEngine` class. Some methods in `Haml::Compiler` are migrated to `Haml::TempleEngine`. (Takashi Kokubun) Fixed * Fix for attribute merging. When an attribute method (or literal nested hash) was used in an old style attribute hash and there is also a (non-static) new style hash there is an error. The fix can result in different behavior in some circumstances. See the [commit message](https://github.com/haml/haml/tree/e475b015d3171fb4c4f140db304f7970c787d6e3) for detailed info. (Matt Wildig) * Make escape_once respect hexadecimal references. (Matt Wildig) * Don't treat the 'data' attribute specially when merging attribute hashes. (Matt Wildig and Norman Clarke) * Fix #@foo and #$foo style interpolation that was not working in html_safe mode. (Akira Matsuda) * Allow `@` as tag's class name. Thanks [Joe Bartlett](https://github.com/redoPop). * Raise `Haml::InvalidAttributeNameError` when attribute name includes invalid characters. (Takashi Kokubun) * Don't ignore unexpected exceptions on initializing `ActionView::OutputBuffer`. (Takashi Kokubun) ## 4.0.7 Released on August 10, 2015 ([diff](https://github.com/haml/haml/compare/4.0.6...4.0.7)). * Significantly improve performance of regexp used to fix whitespace handling in textareas (thanks [Stan Hu](https://github.com/stanhu)). ## 4.0.6 Released on Dec 1, 2014 ([diff](https://github.com/haml/haml/compare/4.0.5...4.0.6)). * Fix warning on Ruby 1.8.7 "regexp has invalid interval" (thanks [Elia Schito](https://github.com/elia)). ## 4.0.5 Released on Jan 7, 2014 ([diff](https://github.com/haml/haml/compare/4.0.4...4.0.5)). * Fix haml_concat appending unescaped HTML after a call to haml_tag. * Fix for bug whereby when HAML :ugly option is "true", ActionView::Helpers::CaptureHelper::capture returns the whole view buffer when passed a block that returns nothing (thanks [Mircea Moise](https://github.com/mmircea16)). ## 4.0.4 Released on November 5, 2013 ([diff](https://github.com/haml/haml/compare/4.0.3...4.0.4)). * Check for Rails::Railtie rather than Rails (thanks [Konstantin Shabanov](https://github.com/etehtsea)). * Parser fix to allow literal '#' with suppress_eval (Matt Wildig). * Helpers#escape_once works on frozen strings (as does ERB::Util.html_escape_once for which it acts as a replacement in Rails (thanks [Patrik Metzmacher](https://github.com/patrik)). * Minor test fix (thanks [Mircea Moise](https://github.com/mmircea16)). ## 4.0.3 Released May 21, 2013 ([diff](https://github.com/haml/haml/compare/4.0.2...4.0.3)). * Compatibility with newer versions of Rails's Erubis handler. * Fix Erubis handler for compatibility with Tilt 1.4.x, too. * Small performance optimization for html_escape. (thanks [Lachlan Sylvester](https://github.com/lsylvester)) * Documentation fixes. * Documented some helper methods that were left out of the reference. (thanks [Shane Riley](https://github.com/shaneriley)) ## 4.0.2 Released April 5, 2013 ([diff](https://github.com/haml/haml/compare/4.0.1...4.0.2)). * Explicitly require Erubis to work around bug in older versions of Tilt. * Fix :erb filter printing duplicate content in Rails views. (thanks [Jori Hardman](https://github.com/jorihardman)) * Replace range with slice to reduce objects created by `capture_haml`. (thanks [Tieg Zaharia](https://github.com/tiegz)) * Correct/improve some documentation. ## 4.0.1 Released March 21, 2013 ([diff](https://github.com/haml/haml/compare/4.0.0...4.0.1)). * Remove Rails 3.2.3+ textarea hack in favor of a more general solution. * Fix some performance regressions. * Fix support for Rails 4 `text_area` helper method. * Fix data attribute flattening with singleton objects. (thanks [Alisdair McDiarmid](https://github.com/alisdair)) * Fix support for sass-rails 4.0 beta. (thanks [Ryunosuke SATO](https://github.com/tricknotes)) * Load "haml/template" in Railtie in order to prevent user options set in a Rails initializer from being overwritten * Don't depend on Rails in haml/template to allow using Haml with ActionView but without Rails itself. (thanks [Hunter Haydel](https://github.com/wedgex)) ## 4.0.0 * The Haml executable now accepts an `--autoclose` option. You can now specify a list of tags that should be autoclosed * The `:ruby` filter no longer redirects $stdout to the Haml document, as this is not thread safe. Instead it provides a `haml_io` local variable, which is an IO object that writes to the document. * HTML5 is now the default output format rather than XHTML. This was already the default on Rails 3+, so many users will notice no difference. * The :sass filter now wraps its output in a style tag, as do the new :less and :scss filters. The :coffee filter wraps its output in a script tag. * Haml now supports only Rails 3 and above, and Ruby 1.8.7 and above. If you still need support for Rails 2 and Ruby 1.8.6, please use Haml 3.1.x which will continue to be maintained for bug fixes. * The :javascript and :css filters no longer add CDATA tags when the format is html4 or html5. This can be overridden by setting the `cdata` option to `true`. CDATA tags are always added when the format is xhtml. * HTML2Haml has been extracted to a separate gem, creatively named "html2haml". * The `:erb` filter now uses Rails's safe output buffer to provide XSS safety. * Haml's internals have been refactored to move the parser, compiler and options handling into independent classes, rather than including them all in the Engine module. You can also specify your own custom Haml parser or compiler class in Haml::Options in order to extend or modify Haml reasonably easily. * Add an {file:REFERENCE.md#hyphenate_data_attrs-option `:hyphenate_data_attrs` option} that converts underscores to hyphens in your HTML5 data keys. This is a language change from 3.1 and is enabled by default. (thanks to [Andrew Smith](https://github.com/fullsailor)) * All Hash attribute values are now treated as HTML5 data, regardless of key. Previously only the "data" key was treated this way. Allowing arbitrary keys means you can now easily use this feature for Aria attributes, among other uses. (thanks to [Elvin Efendi](https://github.com/ElvinEfendi)) * Added `remove_whitespace` option to always remove all whitespace around Haml tags. (thanks to [Tim van der Horst](https://github.com/vdh)) * Haml now flattens deeply nested data attribute hashes. For example: `.foo{:data => {:a => "b", :c => {:d => "e", :f => "g"}}}` would render to: `
` (thanks to [Péter Pál Koszta](https://github.com/koszta)) * Filters that rely on third-party template engines are now implemented using [Tilt](http://github.com/rtomayko/tilt). Several new filters have been added, namely SCSS (:scss), LessCSS, (:less), and Coffeescript (:coffee/:coffeescript). Though the list of "official" filters is kept intentionally small, Haml comes with a helper method that makes adding support for other Tilt-based template engines trivial. As of 4.0, Haml will also ship with a "haml-contrib" gem that includes useful but less-frequently used filters and helpers. This includes several additional filters such as Nokogiri, Yajl, Markaby, and others. * Generate object references based on `#to_key` if it exists in preference to `#id`. * Performance improvements. (thanks to [Chris Heald](https://github.com/cheald)) * Helper `list_of` takes an extra argument that is rendered into list item attributes. (thanks [Iain Barnett](http://iainbarnett.me.uk/)) * Fix parser to allow lines ending with `some_method?` to be a Ruby multinline. (thanks to [Brad Ediger](https://github.com/bradediger)) * Always use :xhtml format when the mime_type of the rendered template is 'text/xml'. (thanks to [Stephen Bannasch](https://github.com/stepheneb)) * html2haml now includes an `--html-attributes` option. (thanks [Stefan Natchev](https://github.com/snatchev)) * Fix for inner whitespace removal in loops. (thanks [Richard Michael](https://github.com/richardkmichael)) * Use numeric character references rather than HTML entities when escaping double quotes and apostrophes in attributes. This works around some bugs in Internet Explorer earlier than version 9. (thanks [Doug Mayer](https://github.com/doxavore)) * Fix multiline silent comments: Haml previously did not allow free indentation inside multline silent comments. * Fix ordering bug with partial layouts on Rails. (thanks [Sam Pohlenz](https://github.com/spohlenz)) * Add command-line option to suppress script evaluation. * It's now possible to use Rails's asset helpers inside the Sass and SCSS filters. Note that to do so, you must make sure sass-rails is loaded in production, usually by moving it out of the assets gem group. * The Haml project now uses [semantic versioning](http://semver.org/). ## 3.2.0 The Haml 3.2 series was released only as far as 3.2.0.rc.4, but then was renamed to Haml 4.0 when the project adopted semantic versioning. ## 3.1.8 * Fix for line numbers reported from exceptions in nested blocks (thanks to Grant Hutchins & Sabrina Staedt). ## 3.1.7 * Fix for compatibility with Sass 3.2.x. (thanks [Michael Westbom](https://github.com/totallymike)). ## 3.1.6 * In indented mode, don't reindent buffers that contain preserved tags, and provide a better workaround for Rails 3.2.3's textarea helpers. ## 3.1.5 * Respect Rails' `html_safe` flag when escaping attribute values (thanks to [Gerad Suyderhoud](https://github.com/gerad)). * Fix for Rails 3.2.3 textarea helpers (thanks to [James Coleman](https://github.com/jcoleman) and others). ## 3.1.4 * Fix the use of `FormBuilder#block` with a label in Haml. * Fix indentation after a self-closing tag with dynamic attributes. ## 3.1.3 * Stop partial layouts from being displayed twice. ## 3.1.2 * If the ActionView `#capture` helper is used in a Haml template but without any Haml being run in the block, return the value of the block rather than the captured buffer. * Don't throw errors when text is nested within comments. * Fix html2haml. * Fix an issue where destructive modification was sometimes performed on Rails SafeBuffers. * Use character code entities for attribute value replacements instead of named/keyword entities. ## 3.1.1 * Update the vendored Sass to version 3.1.0. ## 3.1.0 * Don't add a `type` attribute to ` is now transformed into: :javascript function foo() { return 12; } * `
` and `
    

However, if a helper is generating the tag, Haml can't detect that and so you'll have to call {Haml::Helpers#find_and_preserve} yourself. You can also use `~`, which is the same as `=` except that it automatically runs `find_and_preserve` on its input. For example: %p= find_and_preserve "" is the same as %p~ "" and renders

### How do I make my long lines of Ruby code look nicer in my Haml document? {#q-multiline} Put them in a helper or your model. Haml purposefully makes it annoying to put lots of Ruby code into your templates, because lots of code doesn't belong in the view. If you take that huge `link_to_remote` call and move it to a `update_sidebar_link` helper, it'll make your view both easier to read and more semantic. If you absolutely must put lots of code in your template, Haml offers a somewhat awkward multiline-continuation tool. Put a `|` (pipe character) at the end of each line you want to be merged into one (including the last line!). For example: %p= @this.is(way.too.much). | code("and I should"). | really_move.it.into( | :a => @helper) | Note that sometimes it is valid to include lots of Ruby in a template when that Ruby is a helper call that passes in a lot of template information. Thus when a function has lots of arguments, it's possible to wrap it across multiple lines as long as each line ends in a comma. For example: = link_to_remote "Add to cart", :url => { :action => "add", :id => product.id }, :update => { :success => "cart", :failure => "error" } ### `form_for` is printing the form tag twice! Make sure you're calling it with `-`, not `=`. Just like in ERB, you have to do <% form_for stuff do %> ... <% end %> in Haml, you have to do - form_for stuff do ... ### I have Haml installed. Why is Rails (only looking for `.html.erb` files | rendering Haml files as plain text | rendering Haml files as blank pages)? {#q-blank-page} There are several reasons these things might be happening. First of all, make sure that Haml really is installed; either you've loaded the gem (via `config.gem` in Rails 2.3 or in the Gemfile in Rails 3), or `vendor/plugins/haml` exists and contains files. Then try restarting Mongrel or WEBrick or whatever you might be using. Finally, if none of these work, chances are you've got some localization plugin like Globalize installed. Such plugins often don't play nicely with Haml. Luckily, there's usually an easy fix. For Globalize, just edit `globalize/lib/globalize/rails/action_view.rb` and change @@re_extension = /\.(rjs|rhtml|rxml)$/ to @@re_extension = /\.(rjs|rhtml|rxml|erb|builder|haml)$/ For other plugins, a little searching will probably turn up a way to fix them as well. ## You still haven't answered my question! Sorry! Try looking at the [Haml](https://haml.info/docs/yardoc/file.REFERENCE.html) reference, If you can't find an answer there, feel free to ask in `#haml` on irc.freenode.net or send an email to the [mailing list](http://groups.google.com/group/haml). haml-6.3.0/Gemfile000066400000000000000000000010321453526310700137360ustar00rootroot00000000000000source 'https://rubygems.org' git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") "https://github.com/#{repo_name}.git" end # Specify your gem's dependencies in haml.gemspec gemspec gem 'benchmark-ips', '2.3.0' gem 'maxitest' gem 'pry' if /java/ === RUBY_PLATFORM # JRuby gem 'pandoc-ruby' else gem 'redcarpet' if RUBY_PLATFORM !~ /mswin|mingw/ && RUBY_ENGINE != 'truffleruby' gem 'stackprof' end end if RUBY_VERSION < '2.6' gem 'rake-compiler', '< 1.2.4' end haml-6.3.0/MIT-LICENSE000066400000000000000000000021171453526310700141040ustar00rootroot00000000000000Copyright (c) 2006-2021 Hampton Catlin, Natalie Weizenbaum and Takashi Kokubun 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. haml-6.3.0/README.md000066400000000000000000000136121453526310700137310ustar00rootroot00000000000000# Haml [![Gem Version](https://badge.fury.io/rb/haml.svg)](https://rubygems.org/gems/haml) [![test](https://github.com/haml/haml/actions/workflows/test.yml/badge.svg)](https://github.com/haml/haml/actions/workflows/test.yml) [![Code Climate](https://codeclimate.com/github/haml/haml/badges/gpa.svg)](https://codeclimate.com/github/haml/haml) [![Inline docs](https://inch-ci.org/github/haml/haml.svg)](https://inch-ci.org/github/haml/haml) Haml is a templating engine for HTML. It's designed to make it both easier and more pleasant to write HTML documents, by eliminating redundancy, reflecting the underlying structure that the document represents, and providing an elegant syntax that's both powerful and easy to understand. ## Basic Usage Haml can be used from the command line or as part of a Ruby web framework. The first step is to install the gem: ~~~sh gem install haml ~~~ After you write some Haml, you can run ~~~sh haml render document.haml ~~~ to compile it to HTML. For more information on these commands, check out ~~~sh haml --help ~~~ To use Haml programmatically, check out the [YARD documentation](https://haml.info/docs/yardoc/). ## Using Haml with Rails To use Haml with Rails, simply add Haml to your Gemfile and run `bundle`. ~~~ruby gem 'haml' ~~~ If you'd like to replace Rails's ERB-based generators with Haml, add [haml-rails](https://github.com/haml/haml-rails) to your Gemfile as well. ## Formatting The most basic element of Haml is a shorthand for creating HTML: ~~~haml %tagname{:attr1 => 'value1', :attr2 => 'value2'} Contents ~~~ No end-tag is needed; Haml handles that automatically. If you prefer HTML-style attributes, you can also use: ~~~haml %tagname(attr1='value1' attr2='value2') Contents ~~~ Adding `class` and `id` attributes is even easier. Haml uses the same syntax as the CSS that styles the document: ~~~haml %tagname#id.class ~~~ In fact, when you're using the `
` tag, it becomes _even easier_. Because `
` is such a common element, a tag without a name defaults to a div. So ~~~haml #foo Hello! ~~~ becomes ~~~html
Hello!
~~~ Haml uses indentation to bring the individual elements to represent the HTML structure. A tag's children are indented beneath than the parent tag. Again, a closing tag is automatically added. For example: ~~~haml %ul %li Salt %li Pepper ~~~ becomes: ~~~html
  • Salt
  • Pepper
~~~ You can also put plain text as a child of an element: ~~~haml %p Hello, World! ~~~ It's also possible to embed Ruby code into Haml documents. An equals sign, `=`, will output the result of the code. A hyphen, `-`, will run the code but not output the result. You can even use control statements like `if` and `while`: ~~~haml %p Date/Time: - now = DateTime.now %strong= now - if now > DateTime.parse("December 31, 2006") = "Happy new " + "year!" ~~~ Haml provides far more tools than those presented here. Check out the [reference documentation](https://haml.info/docs/yardoc/file.REFERENCE.html) for full details. ### Indentation Haml's indentation can be made up of one or more tabs or spaces. However, indentation must be consistent within a given document. Hard tabs and spaces can't be mixed, and the same number of tabs or spaces must be used throughout. ## Contributing Contributions are welcomed, but before you get started please read the [guidelines](https://haml.info/development.html#contributing). After forking and then cloning the repo locally, install Bundler and then use it to install the development gem dependencies: ~~~sh gem install bundler bundle install ~~~ Once this is complete, you should be able to run the test suite: ~~~sh rake ~~~ At this point `rake` should run without error or warning and you are ready to start working on your patch! Note that you can also run just one test out of the test suite if you're working on a specific area: ~~~sh ruby -Itest test/helper_test.rb -n test_buffer_access ~~~ Haml currently supports Ruby 2.0.0 and higher, so please make sure your changes run on 2.0+. ## Team ### Current Maintainers * [Akira Matsuda](https://github.com/amatsuda) * [Matt Wildig](https://github.com/mattwildig) * [Tee Parham](https://github.com/teeparham) * [Takashi Kokubun](https://github.com/k0kubun) ### Alumni Haml was created by [Hampton Catlin](http://hamptoncatlin.com), the author of the original implementation. Hampton is no longer involved in day-to-day coding, but still consults on language issues. [Natalie Weizenbaum](http://nex-3.com) was for many years the primary developer and architect of the "modern" Ruby implementation of Haml. [Norman Clarke](https://github.com/norman) was the primary maintainer of Haml from 2012 to 2016. ## License Some of Natalie's work on Haml was supported by Unspace Interactive. Beyond that, the implementation is licensed under the MIT License. Copyright (c) 2006-2019 Hampton Catlin, Natalie Weizenbaum and the Haml 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. haml-6.3.0/REFERENCE.md000066400000000000000000001077111453526310700142760ustar00rootroot00000000000000# Haml (HTML Abstraction Markup Language) Haml is a markup language that's used to cleanly and simply describe the HTML of any web document, without the use of inline code. Haml functions as a replacement for inline page templating systems such as PHP, ERB, and ASP. However, Haml avoids the need for explicitly coding HTML into the template, because it is actually an abstract description of the HTML, with some code to generate dynamic content. ## Features * Whitespace active * Well-formatted markup * DRY * Follows CSS conventions * Integrates Ruby code * Implements Rails templates with the .haml extension ## Using Haml Haml can be used in three ways: * as a command-line tool, * as a plugin for Ruby on Rails, * and as a standalone Ruby module. The first step for all of these is to install the Haml gem: gem install haml To run Haml from the command line, just use haml render input.haml > output.html Use `haml --help` for full documentation. To use Haml with Rails, add the following line to the Gemfile: gem "haml" Once it's installed, all view files with the `".html.haml"` extension will be compiled using Haml. You can access instance variables in Haml templates the same way you do in ERB templates. Helper methods are also available in Haml templates. For example: # file: app/controllers/movies_controller.rb class MoviesController < ApplicationController def index @title = "Teen Wolf" end end -# file: app/views/movies/index.html.haml #content .title %h1= @title = link_to 'Home', home_url may be compiled to:

Teen Wolf

Home
### Ruby Module Haml can also be used completely separately from Rails and ActionView. To do this, install the gem with RubyGems: gem install haml You can then use it by including the `haml` gem in Ruby code, and using {Haml::Template} like so: engine = Haml::Template.new { "%p Haml code!" } engine.render #=> "

Haml code!

\n" ### Options Haml understands various configuration options that affect its performance and output. In Rails, options can be set by using `Haml::RailsTemplate.set_options` in an initializer: ```ruby # config/initializers/haml.rb Haml::RailsTemplate.set_options(escape_html: false) ``` Outside Rails, you can set them by configuring them globally in `Haml::Template.options`: ```ruby Haml::Template.options[:escape_html] = false ``` In sinatra specifically, you can set them in global config with: ```ruby set :haml, { escape_html: false } ``` Finally, you can also set them by passing an options hash to `Haml::Engine.new` or `Haml::Template.new`. For the complete list of available options, please see `Haml::Engine`. ## Plain Text A substantial portion of any HTML document is its content, which is plain old text. Any Haml line that's not interpreted as something else is taken to be plain text, and passed through unmodified. For example: %gee %whiz Wow this is cool! is compiled to: Wow this is cool! Note that HTML tags are passed through unmodified as well. If you have some HTML you don't want to convert to Haml, or you're converting a file line-by-line, you can just include it as-is. For example: %p
Blah!
is compiled to:

Blah!

### Escaping: `\` The backslash character escapes the first character of a line, allowing use of otherwise interpreted characters as plain text. For example: %title = @title \= @title is compiled to: MyPage = @title ## HTML Elements ### Element Name: `%` The percent character is placed at the beginning of a line. It's followed immediately by the name of an element, then optionally by modifiers (see below), a space, and text to be rendered inside the element. It creates an element in the form of ``. For example: %one %two %three Hey there is compiled to: Hey there Any string is a valid element name; Haml will automatically generate opening and closing tags for any element. ### Attributes: `{}` or `()` {#attributes} Braces represent a Ruby hash that is used for specifying the attributes of an element. It is literally evaluated as a Ruby hash, so logic will work in it and local variables may be used. Quote characters within the attribute will be replaced with appropriate escape sequences. The hash is placed after the tag is defined. For example: %html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en"} is compiled to: Attribute hashes can also be stretched out over multiple lines to accommodate many attributes. %script{ "type": text/javascript", "src": javascripts/script_#{2 + 7}", "data": { "controller": "reporter", }, } is compiled to: #### `:class` and `:id` Attributes {#class-and-id-attributes} The `:class` and `:id` attributes can also be specified as a Ruby array whose elements will be joined together. A `:class` array is joined with `" "` and an `:id` array is joined with `"_"`. For example: %div{:id => [@item.type, @item.number], :class => [@item.type, @item.urgency]} is equivalent to: %div{:id => "#{@item.type}_#{@item.number}", :class => "#{@item.type} #{@item.urgency}"} The array will first be flattened and any elements that do not test as true will be removed. The remaining elements will be converted to strings. For example: %div{:class => [@item.type, @item == @sortcol && [:sort, @sortdir]] } Contents could render as any of:
Contents
Contents
Contents
Contents
depending on whether `@item.type` is `"numeric"` or `nil`, whether `@item == @sortcol`, and whether `@sortdir` is `"ascending"` or `"descending"`. If a single value is specified and it evaluates to false it is ignored; otherwise it gets converted to a string. For example: .item{:class => @item.is_empty? && "empty"} could render as either of: class="item" class="item empty" #### HTML-style Attributes: `()` Haml also supports a terser, less Ruby-specific attribute syntax based on HTML's attributes. These are used with parentheses instead of braces, like so: %html(xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en") Ruby variables can be used by omitting the quotes. Local variables or instance variables can be used. For example: %a(title=@title href=href) Stuff This is the same as: %a{:title => @title, :href => href} Stuff Because there are no commas separating attributes, though, more complicated expressions aren't allowed. For those you'll have to use the `{}` syntax. You can, however, use both syntaxes together: %a(title=@title){:href => @link.href} Stuff You can also use `#{}` interpolation to insert complicated expressions in a HTML-style attribute: %span(class="widget_#{@widget.number}") HTML-style attributes can be stretched across multiple lines just like hash-style attributes: %script(type="text/javascript" src="javascripts/script_#{2 + 7}") #### Ruby 1.9-style Hashes Haml also supports Ruby's new hash syntax: %a{title: @title, href: href} Stuff #### Boolean Attributes Some attributes, such as "checked" for `input` tags or "selected" for `option` tags, are "boolean" in the sense that their values don't matter - it only matters whether or not they're present. In HTML (but not XHTML), these attributes can be written as To do this in Haml using hash-style attributes, just assign a Ruby `true` value to the attribute: %input{:selected => true} In XHTML, the only valid value for these attributes is the name of the attribute. Thus this will render in XHTML as To set these attributes to false, simply assign them to a Ruby false value. In both XHTML and HTML, %input{:selected => false} will just render as: HTML-style boolean attributes can be written just like HTML: %input(selected) or using `true` and `false`: %input(selected=true) This feature works only for attributes that are included in [`Haml::AttributeBuilder::BOOLEAN_ATTRIBUTES`](https://github.com/haml/haml/blob/main/lib/haml/attribute_builder.rb#L5), as well as `data-` and `aria-` attributes. %input{'data-hidden' => false} %input{'aria-hidden' => false} %input{'xyz-hidden' => false} will render as: #### Data Attributes HTML5 allows for adding [custom non-visible data attributes](http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes) to elements using attribute names beginning with `data-`. The [Accessible Rich Internet Applications](http://www.w3.org/WAI/intro/aria) specification makes use of attributes beginning with `aria-`. Haml can help generate collections of attributes that share a prefix like these. Any entry in an `data` or `aria` attribute hash that has a Hash as its value is expanded into a series of attributes, one for each key/value pair in the hash, with the attribute name formed by joining the “parent” key name to the key name with a hyphen. This works only for `data` or `aria`. For example: %a{:href=>"/posts", :data => {:author_id => 123, :category => 7}} Posts By Author will render as: Posts By Author Notice that the underscore in `author_id` was replaced with a hyphen. If you wish to suppress this behavior, you can set Haml's {Haml::Options#hyphenate_data_attrs `:hyphenate_data_attrs` option} to `false`, and the output will be rendered as: Posts By Author This expansion of hashes is recursive – any value of the child hash that is itself a hash will create an attribute for each entry, with the attribute name prefixed with all ancestor keys. For example: .book-info{:data => {:book => {:id => 123, :genre => 'programming'}, :category => 7}} will render as:
### Class and ID: `.` and `#` The period and pound sign are borrowed from CSS. They are used as shortcuts to specify the `class` and `id` attributes of an element, respectively. Multiple class names can be specified in a similar way to CSS, by chaining the class names together with periods. They are placed immediately after the tag and before an attributes hash. For example: %div#things %span#rice Chicken Fried %p.beans{ :food => 'true' } The magical fruit %h1.class.otherclass#id La La La is compiled to:
Chicken Fried

The magical fruit

La La La

And, %div#content %div.articles %div.article.title Doogie Howser Comes Out %div.article.date 2006-11-05 %div.article.entry Neil Patrick Harris would like to dispel any rumors that he is straight is compiled to:
Doogie Howser Comes Out
2006-11-05
Neil Patrick Harris would like to dispel any rumors that he is straight
These shortcuts can be combined with long-hand attributes; the two values will be merged together as though they were all placed in an array (see [the documentation on `:class` and `:id` attributes](#class-and-id-attributes)). For example: %div#Article.article.entry{:id => @article.number, :class => @article.visibility} is equivalent to %div{:id => ['Article', @article.number], :class => ['article', 'entry', @article.visibility]} Gabba Hey and could compile to:
Gabba Hey
#### Implicit Div Elements Because divs are used so often, they're the default elements. If you only define a class and/or id using `.` or `#`, a div is automatically used. For example: #collection .item .description What a cool item! is the same as: %div#collection %div.item %div.description What a cool item! and is compiled to:
What a cool item!
#### Class Name Merging and Ordering Class names are ordered in the following way: 1) Tag identifiers in order (aka, ".alert.me" => "alert me") 2) Classes appearing in HTML-style attributes 3) Classes appearing in Hash-style attributes For instance, this is a complicated and unintuitive test case illustrating the ordering .foo.moo{:class => ['bar', 'alpha']}(class='baz') The resulting HTML would be as follows:
*Versions of Haml prior to 5.0 would alphabetically sort class names.* ### Empty (void) Tags: `/` The forward slash character, when placed at the end of a tag definition, causes Haml to treat it as being an empty (or void) element. Depending on the format, the tag will be rendered either without a closing tag (`:html4` or `:html5`), or as a self-closing tag (`:xhtml`). Taking the following as an example: %br/ %meta{'http-equiv' => 'Content-Type', :content => 'text/html'}/ When the format is `:html4` or `:html5` this is compiled to:
and when the format is `:xhtml` it is compiled to:
Some tags are automatically treated as being empty, as long as they have no content in the Haml source. `meta`, `img`, `link`, `br`, `hr`, `input`, `area`, `param`, `col` and `base` tags are treated as empty by default. This list can be customized by setting the {Haml::Options#autoclose `:autoclose`} option. ### Whitespace Removal: `>` and `<` `>` and `<` give you more control over the whitespace near a tag. `>` will remove all whitespace surrounding a tag, while `<` will remove all whitespace immediately within a tag. You can think of them as alligators eating the whitespace: `>` faces out of the tag and eats the whitespace on the outside, and `<` faces into the tag and eats the whitespace on the inside. They're placed at the end of a tag definition, after class, id, and attribute declarations but before `/` or `=`. For example: %blockquote< %div Foo! is compiled to:
Foo!
And: %img %img> %img is compiled to: And: %p<= "Foo\nBar" is compiled to:

Foo Bar

And finally: %img %pre>< foo bar %img is compiled to:
foo
    bar
### Object Reference: `[]` Square brackets follow a tag definition and contain a Ruby object that is used to set the class and id of that tag. The class is set to the object's class (transformed to use underlines rather than camel case) and the id is set to the object's class, followed by the value of its `#to_key` or `#id` method (in that order). This is most useful for elements that represent instances of Active Model models. Additionally, the second argument (if present) will be used as a prefix for both the id and class attributes. For example: # file: app/controllers/users_controller.rb def show @user = CrazyUser.find(15) end -# file: app/views/users/show.haml %div[@user, :greeting] %bar[290]/ Hello! is compiled to:
Hello!
If you require that the class be something other than the underscored object's class, you can implement the `haml_object_ref` method on the object. # file: app/models/crazy_user.rb class CrazyUser < ActiveRecord::Base def haml_object_ref "a_crazy_user" end end -# file: app/views/users/show.haml %div[@user] Hello! is compiled to:
Hello!
The `:class` attribute may be used in conjunction with an object reference. The compiled element will have the union of all classes. - user = User.find(1) %p[user]{:class => 'alpha bravo'}

## Doctype: `!!!` When describing HTML documents with Haml, you can have a document type or XML prolog generated automatically by including the characters `!!!`. For example: !!! XML !!! %html %head %title Myspace %body %h1 I am the international space station %p Sign my guestbook is compiled to: Myspace

I am the international space station

Sign my guestbook

You can also specify the specific doctype after the `!!!` When the {Haml::Options#format `:format`} is set to `:xhtml`. The following doctypes are supported: `!!!` : XHTML 1.0 Transitional
`` `!!! Strict` : XHTML 1.0 Strict
`` `!!! Frameset` : XHTML 1.0 Frameset
`` `!!! 5` : XHTML 5
``
`!!! 1.1` : XHTML 1.1
`` `!!! Basic` : XHTML Basic 1.1
` ` `!!! Mobile` : XHTML Mobile 1.2
`` `!!! RDFa` : XHTML+RDFa 1.0
`` When the {Haml::Options#format `:format`} option is set to `:html4`, the following doctypes are supported: `!!!` : HTML 4.01 Transitional
`` `!!! Strict` : HTML 4.01 Strict
`` `!!! Frameset` : HTML 4.01 Frameset
`` When the {Haml::Options#format `:format`} option is set to `:html5`, `!!!` is always ``. If you're not using the UTF-8 character set for your document, you can specify which encoding should appear in the XML prolog in a similar way. For example: !!! XML iso-8859-1 is compiled to: If the mime_type of the template being rendered is `text/xml` then a format of `:xhtml` will be used even if the global output format is set to `:html4` or `:html5`. ## Comments Haml supports two sorts of comments: those that show up in the HTML output and those that don't. ### HTML Comments: `/` The forward slash character, when placed at the beginning of a line, wraps all text after it in an HTML comment. For example: %peanutbutterjelly / This is the peanutbutterjelly element I like sandwiches! is compiled to: I like sandwiches! The forward slash can also wrap indented sections of code. For example: / %p This doesn't render... %div %h1 Because it's commented out! is compiled to: #### Conditional Comments: `/[]` You can also use [Internet Explorer conditional comments](http://www.quirksmode.org/css/condcom.html) by enclosing the condition in square brackets after the `/`. For example: /[if IE] %a{ :href => 'http://www.mozilla.com/en-US/firefox/' } %h1 Get Firefox is compiled to: To generate “downlevel-revealed” conditional comments, where the content is hidden from IE but not other browsers, add a `!` before the brackets: `/![]`. Haml will produce valid HTML when generating this kind of conditional comment. For example: /![if !IE] You are not using Internet Explorer, or are using version 10+. is compiled to: You are not using Internet Explorer, or are using version 10+. ### Haml Comments: `-#` The hyphen followed immediately by the pound sign signifies a silent comment. Any text following this isn't rendered in the resulting document at all. For example: %p foo -# This is a comment %p bar is compiled to:

foo

bar

You can also nest text beneath a silent comment. None of this text will be rendered. For example: %p foo -# This won't be displayed Nor will this Nor will this. %p bar is compiled to:

foo

bar

## Ruby Evaluation ### Inserting Ruby: `=` {#inserting_ruby} The equals character is followed by Ruby code. This code is evaluated and the output is inserted into the document. For example: %p = ['hi', 'there', 'reader!'].join " " = "yo" is compiled to:

hi there reader! yo

If the {Haml::Options#escape_html `:escape_html`} option is set, `=` will sanitize any HTML-sensitive characters generated by the script. For example: = '' would be compiled to <script>alert("I'm evil!");</script> `=` can also be used at the end of a tag to insert Ruby code within that tag. For example: %p= "hello" would be compiled to:

hello

A line of Ruby code can be stretched over multiple lines as long as each line but the last ends with a comma. For example: = link_to_remote "Add to cart", :url => { :action => "add", :id => product.id }, :update => { :success => "cart", :failure => "error" } Note that it's illegal to nest code within a tag that ends with `=`. ### Running Ruby: `-` The hyphen character is also followed by Ruby code. This code is evaluated but *not* inserted into the document. **It is not recommended that you use this widely; almost all processing code and logic should be restricted to Controllers, Helpers, or partials.** For example: - foo = "hello" - foo << " there" - foo << " you!" %p= foo is compiled to:

hello there you!

A line of Ruby code can be stretched over multiple lines as long as each line but the last ends with a comma. For example: - links = {:home => "/", :docs => "/docs", :about => "/about"} #### Ruby Blocks Ruby blocks, like XHTML tags, don't need to be explicitly closed in Haml. Rather, they're automatically closed, based on indentation. A block begins whenever the indentation is increased after a Ruby evaluation command. It ends when the indentation decreases (as long as it's not an `else` clause or something similar). For example: - (42...47).each do |i| %p= i %p See, I can count! is compiled to:

42

43

44

45

46

See, I can count!

Another example: %p - case 2 - when 1 = "1!" - when 2 = "2?" - when 3 = "3." is compiled to:

2?

### Whitespace Preservation: `~` {#tilde} `~` works just like `=`, except that it runs {Haml::Helpers.preserve} on its input. For example, ~ "Foo\n
Bar\nBaz
" is the same as: = find_and_preserve("Foo\n
Bar\nBaz
") and is compiled to: Foo
Bar
Baz
See also [Whitespace Preservation](#whitespace_preservation). ### Ruby Interpolation: `#{}` Ruby code can also be interpolated within plain text using `#{}`, similarly to Ruby string interpolation. For example, %p This is #{h quality} cake! is the same as %p= "This is #{h quality} cake!" and might compile to:

This is scrumptious cake!

Backslashes can be used to escape `#{}` strings, but they don't act as escapes anywhere else in the string. For example: %p Look at \\#{h word} lack of backslash: \#{foo} And yon presence thereof: \{foo} might compile to:

Look at \yon lack of backslash: #{foo} And yon presence thereof: \{foo}

Interpolation can also be used within [filters](#filters). For example: :javascript $(document).ready(function() { alert(#{@message.to_json}); }); might compile to: #### Gotchas Haml uses an overly simplistic regular expression to identify string interpolation rather than a full-blown Ruby parser. This is fast and works for most code but you may have errors with code like the following: %span #{'{'} This code will generate a syntax error, complaining about unbalanced braces. In cases like this, the recommended workaround is output the code as a Ruby string to force Haml to parse the code with Ruby. %span= "#{'{'}" ### Escaping HTML: `&=` {#escaping_html} An ampersand followed by one or two equals characters evaluates Ruby code just like the equals without the ampersand, but sanitizes any HTML-sensitive characters in the result of the code. For example: &= "I like cheese & crackers" compiles to I like cheese & crackers If the {Haml::Options#escape_html `:escape_html`} option is set, `&=` behaves identically to `=`. `&` can also be used on its own so that `#{}` interpolation is escaped. For example, & I like #{"cheese & crackers"} compiles to: I like cheese & crackers ### Unescaping HTML: `!=` {#unescaping_html} An exclamation mark followed by one or two equals characters evaluates Ruby code just like the equals would, but never sanitizes the HTML. By default, the single equals doesn't sanitize HTML either. However, if the {Haml::Options#escape_html `:escape_html`} option is set, `=` will sanitize the HTML, but `!=` still won't. For example, if `:escape_html` is set: = "I feel !" != "I feel !" compiles to I feel <strong>! I feel ! `!` can also be used on its own so that `#{}` interpolation is unescaped. For example, ! I feel #{""}! compiles to I feel ! ## Filters {#filters} The colon character designates a filter. This allows you to pass an indented block of text as input to another filtering program and add the result to the output of Haml. The syntax is simply a colon followed by the name of the filter. For example: %p :markdown # Greetings Hello, *World* is compiled to:

Greetings

Hello, World

Filters can have Ruby code interpolated with `#{}`. For example: - flavor = "raspberry" #content :textile I *really* prefer _#{flavor}_ jam. is compiled to

I really prefer raspberry jam.

The functionality of some filters such as Markdown can be provided by many different libraries. Usually you don't have to worry about this - you can just load the gem of your choice and Haml will automatically use it. However in some cases you may want to make Haml explicitly use a specific gem to be used by a filter. In these cases you can do this via Tilt, the library Haml uses to implement many of its filters: Tilt.prefer Tilt::RedCarpetTemplate See the [Tilt documentation](https://github.com/rtomayko/tilt) for more info. Haml comes with the following filters defined: ### `:cdata` {#cdata-filter} Surrounds the filtered text with CDATA tags. ### `:coffee` {#coffee-filter} Compiles the filtered text to JavaScript in `"] temple end end CoffeeScript = Coffee end end haml-6.3.0/lib/haml/filters/css.rb000066400000000000000000000013361453526310700167260ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Css < TextBase def compile(node) case @format when :xhtml compile_xhtml(node) else compile_html(node) end end private def compile_html(node) temple = [:multi] temple << [:static, ""] temple end def compile_xhtml(node) temple = [:multi] temple << [:static, ""] temple end end end end haml-6.3.0/lib/haml/filters/erb.rb000066400000000000000000000002621453526310700167030ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Erb < TiltBase def compile(node) precompiled_with_tilt(node, 'erb') end end end end haml-6.3.0/lib/haml/filters/escaped.rb000066400000000000000000000007231453526310700175410ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Escaped < Base def compile(node) text = node.value[:text].rstrip temple = compile_text(text) [:escape, true, temple] end private def compile_text(text) if ::Haml::Util.contains_interpolation?(text) [:dynamic, ::Haml::Util.unescape_interpolation(text)] else [:static, text] end end end end end haml-6.3.0/lib/haml/filters/javascript.rb000066400000000000000000000013541453526310700203040ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Javascript < TextBase def compile(node) case @format when :xhtml compile_xhtml(node) else compile_html(node) end end private def compile_html(node) temple = [:multi] temple << [:static, ""] temple end def compile_xhtml(node) temple = [:multi] temple << [:static, ""] temple end end end end haml-6.3.0/lib/haml/filters/less.rb000066400000000000000000000010761453526310700171050ustar00rootroot00000000000000# frozen_string_literal: true # LESS support is deprecated since it requires therubyracer.gem, # which is hard to maintain. # # It's not supported in Sprockets 3.0+ too. # https://github.com/sstephenson/sprockets/pull/547 module Haml class Filters class Less < TiltBase def compile(node) require 'tilt/less' if explicit_require?('less') temple = [:multi] temple << [:static, "'] temple end end end end haml-6.3.0/lib/haml/filters/markdown.rb000066400000000000000000000003721453526310700177570ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Markdown < TiltBase def compile(node) require 'tilt/redcarpet' if explicit_require?('markdown') compile_with_tilt(node, 'markdown') end end end end haml-6.3.0/lib/haml/filters/plain.rb000066400000000000000000000012731453526310700172410ustar00rootroot00000000000000# frozen_string_literal: true require 'haml/string_splitter' module Haml class Filters class Plain < Base def compile(node) text = node.value[:text] text = text.rstrip unless ::Haml::Util.contains_interpolation?(text) # for compatibility [:multi, *compile_plain(text)] end private def compile_plain(text) string_literal = ::Haml::Util.unescape_interpolation(text) StringSplitter.compile(string_literal).map do |temple| type, str = temple case type when :dynamic [:escape, false, [:dynamic, str]] else temple end end end end end end haml-6.3.0/lib/haml/filters/preserve.rb000066400000000000000000000007351453526310700177730ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Preserve < Base def compile(node) text = node.value[:text].rstrip + "\n" text = text.gsub("\n", ' ') compile_text(text) end private def compile_text(text) if ::Haml::Util.contains_interpolation?(text) [:dynamic, ::Haml::Util.unescape_interpolation(text)] else [:static, text] end end end end end haml-6.3.0/lib/haml/filters/ruby.rb000066400000000000000000000002471453526310700171170ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Ruby < Base def compile(node) [:code, node.value[:text]] end end end end haml-6.3.0/lib/haml/filters/sass.rb000066400000000000000000000005761453526310700171140ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Sass < TiltBase def compile(node) require 'tilt/sass' if explicit_require?('sass') temple = [:multi] temple << [:static, ""] temple end end end end haml-6.3.0/lib/haml/filters/scss.rb000066400000000000000000000005761453526310700171160ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class Scss < TiltBase def compile(node) require 'tilt/sass' if explicit_require?('scss') temple = [:multi] temple << [:static, ""] temple end end end end haml-6.3.0/lib/haml/filters/text_base.rb000066400000000000000000000013671453526310700201200ustar00rootroot00000000000000# frozen_string_literal: true module Haml class Filters class TextBase < Base def compile_text!(temple, node, prefix) text = node.value[:text].rstrip.gsub(/^/, prefix) if ::Haml::Util.contains_interpolation?(node.value[:text]) # original: Haml::Filters#compile text = ::Haml::Util.unescape_interpolation(text).gsub(/(\\+)n/) do |s| escapes = $1.size next s if escapes % 2 == 0 "#{'\\' * (escapes - 1)}\n" end text.prepend("\n") temple << [:dynamic, text] else node.value[:text].split("\n").size.times do temple << [:newline] end temple << [:static, text] end end end end end haml-6.3.0/lib/haml/filters/tilt_base.rb000066400000000000000000000035041453526310700201030ustar00rootroot00000000000000# frozen_string_literal: true require 'tilt' module Haml class Filters class TiltBase < Base def self.render(name, source, indent_width: 0) text = ::Tilt["t.#{name}"].new { source }.render return text if indent_width == 0 if text.frozen? text.gsub(/^/, ' ' * indent_width) else text.gsub!(/^/, ' ' * indent_width) end end def explicit_require?(needed_registration) Gem::Version.new(Tilt::VERSION) >= Gem::Version.new('2.0.0') && !Tilt.registered?(needed_registration) end private # TODO: support interpolation def precompiled_with_tilt(node, name) src = ::Tilt["t.#{name}"].new { node.value[:text] }.send(:precompiled, {}).first [:dynamic, src] end def compile_with_tilt(node, name, indent_width: 0) if ::Haml::Util.contains_interpolation?(node.value[:text]) dynamic_compile(node, name, indent_width: indent_width) else static_compile(node, name, indent_width: indent_width) end end def static_compile(node, name, indent_width: 0) temple = [:multi, [:static, TiltBase.render(name, node.value[:text], indent_width: indent_width)]] node.value[:text].split("\n").size.times do temple << [:newline] end temple end def dynamic_compile(node, name, indent_width: 0) # original: Haml::Filters#compile text = ::Haml::Util.unescape_interpolation(node.value[:text]).gsub(/(\\+)n/) do |s| escapes = $1.size next s if escapes % 2 == 0 "#{'\\' * (escapes - 1)}\n" end text.prepend("\n").sub!(/\n"\z/, '"') [:dynamic, "::Haml::Filters::TiltBase.render('#{name}', #{text}, indent_width: #{indent_width})"] end end end end haml-6.3.0/lib/haml/force_escape.rb000066400000000000000000000014671453526310700171110ustar00rootroot00000000000000# frozen_string_literal: true require 'haml/escape' module Haml # This module allows Temple::Filter to dispatch :fescape on `#compile`. module FescapeDispathcer def on_fescape(flag, exp) [:fescape, flag, compile(exp)] end end ::Temple::Filter.include FescapeDispathcer # Unlike Haml::Escape, this escapes value even if it's html_safe. class ForceEscape < Escape def initialize(opts = {}) super @escape_code = options[:escape_code] || "::Haml::Util.escape_html((%s))" @escaper = eval("proc {|v| #{@escape_code % 'v'} }") end alias_method :on_fescape, :on_escape # ForceEscape doesn't touch :escape expression. # This method is not used if it's inserted after Haml::Escape. def on_escape(flag, exp) [:escape, flag, compile(exp)] end end end haml-6.3.0/lib/haml/helpers.rb000066400000000000000000000004101453526310700161200ustar00rootroot00000000000000# frozen_string_literal: true module Haml module Helpers def self.preserve(input) s = input.to_s.chomp("\n") s.gsub!(/\n/, ' ') s.delete!("\r") s end def preserve(input) Helpers.preserve(input) end end end haml-6.3.0/lib/haml/html.rb000066400000000000000000000012221453526310700154240ustar00rootroot00000000000000# frozen_string_literal: true module Haml class HTML < Temple::HTML::Fast DEPRECATED_FORMATS = %i[html4 html5].freeze def initialize(opts = {}) if DEPRECATED_FORMATS.include?(opts[:format]) opts = opts.dup opts[:format] = :html end super(opts) end # This dispatcher supports Haml's "revealed" conditional comment. def on_html_condcomment(condition, content, revealed = false) on_html_comment [:multi, [:static, "[#{condition}]>#{'' if revealed}"], content, [:static, "#{'\n", postamble: "\n", ) end Engine.new(options).call(source) end def supports_streaming? RailsTemplate.options[:streaming] end end ActionView::Template.register_template_handler(:haml, RailsTemplate.new) end # Haml extends Haml::Helpers in ActionView each time. # It costs much, so Haml includes a compatible module at first. ActiveSupport.on_load(:action_view) do include Haml::RailsHelpers end haml-6.3.0/lib/haml/railtie.rb000066400000000000000000000003261453526310700161150ustar00rootroot00000000000000# frozen_string_literal: true require 'rails' module Haml class Railtie < ::Rails::Railtie initializer :haml, before: :load_config_initializers do |app| require 'haml/rails_template' end end end haml-6.3.0/lib/haml/ruby_expression.rb000066400000000000000000000011421453526310700177210ustar00rootroot00000000000000# frozen_string_literal: true require 'ripper' module Haml class RubyExpression < Ripper class ParseError < StandardError; end def self.syntax_error?(code) self.new(code).parse false rescue ParseError true end def self.string_literal?(code) return false if syntax_error?(code) type, instructions = Ripper.sexp(code) return false if type != :program return false if instructions.size > 1 type, _ = instructions.first type == :string_literal end private def on_parse_error(*) raise ParseError end end end haml-6.3.0/lib/haml/string_splitter.rb000066400000000000000000000073051453526310700177240ustar00rootroot00000000000000# frozen_string_literal: true begin require 'ripper' rescue LoadError end module Haml # Compile [:dynamic, "foo#{bar}"] to [:multi, [:static, 'foo'], [:dynamic, 'bar']] class StringSplitter < Temple::Filter if defined?(Ripper) && RUBY_VERSION >= "2.0.0" && Ripper.respond_to?(:lex) class << self # `code` param must be valid string literal def compile(code) [].tap do |exps| tokens = Ripper.lex(code.strip) tokens.pop while tokens.last && [:on_comment, :on_sp].include?(tokens.last[1]) if tokens.size < 2 raise(Haml::InternalError, "Expected token size >= 2 but got: #{tokens.size}") end compile_tokens!(exps, tokens) end end private def strip_quotes!(tokens) _, type, beg_str = tokens.shift if type != :on_tstring_beg raise(Haml::InternalError, "Expected :on_tstring_beg but got: #{type}") end _, type, end_str = tokens.pop if type != :on_tstring_end raise(Haml::InternalError, "Expected :on_tstring_end but got: #{type}") end [beg_str, end_str] end def compile_tokens!(exps, tokens) beg_str, end_str = strip_quotes!(tokens) until tokens.empty? _, type, str = tokens.shift case type when :on_tstring_content beg_str, end_str = escape_quotes(beg_str, end_str) exps << [:static, eval("#{beg_str}#{str}#{end_str}").to_s] when :on_embexpr_beg embedded = shift_balanced_embexpr(tokens) exps << [:dynamic, embedded] unless embedded.empty? end end end # Some quotes are split-unsafe. Replace such quotes with null characters. def escape_quotes(beg_str, end_str) case [beg_str[-1], end_str] when ['(', ')'], ['[', ']'], ['{', '}'] [beg_str.sub(/.\z/) { "\0" }, "\0"] else [beg_str, end_str] end end def shift_balanced_embexpr(tokens) String.new.tap do |embedded| embexpr_open = 1 until tokens.empty? _, type, str = tokens.shift case type when :on_embexpr_beg embexpr_open += 1 when :on_embexpr_end embexpr_open -= 1 break if embexpr_open == 0 end embedded << str end end end end def on_dynamic(code) return [:dynamic, code] unless string_literal?(code) return [:dynamic, code] if code.include?("\n") temple = [:multi] StringSplitter.compile(code).each do |type, content| case type when :static temple << [:static, content] when :dynamic temple << on_dynamic(content) end end temple end private def string_literal?(code) return false if SyntaxChecker.syntax_error?(code) type, instructions = Ripper.sexp(code) return false if type != :program return false if instructions.size > 1 type, _ = instructions.first type == :string_literal end class SyntaxChecker < Ripper class ParseError < StandardError; end def self.syntax_error?(code) self.new(code).parse false rescue ParseError true end private def on_parse_error(*) raise ParseError end end else # Do nothing if ripper is unavailable def call(ast) ast end end end end haml-6.3.0/lib/haml/template.rb000066400000000000000000000007541453526310700163040ustar00rootroot00000000000000# frozen_string_literal: false require 'temple' require 'haml/engine' require 'haml/helpers' module Haml Template = Temple::Templates::Tilt.create( Haml::Engine, register_as: [:haml, :haml], ) module TemplateExtension # Activate Haml::Helpers for tilt templates. # https://github.com/judofyr/temple/blob/v0.7.6/lib/temple/mixins/template.rb#L7-L11 def compile(*) "extend Haml::Helpers; #{super}" end end Template.send(:extend, TemplateExtension) end haml-6.3.0/lib/haml/temple_line_counter.rb000066400000000000000000000016441453526310700205240ustar00rootroot00000000000000# frozen_string_literal: true module Haml # A module to count lines of expected code. This would be faster than actual code generation # and counting newlines in it. module TempleLineCounter class UnexpectedExpression < StandardError; end def self.count_lines(exp) type, *args = exp case type when :multi args.map { |a| count_lines(a) }.reduce(:+) || 0 when :dynamic, :code args.first.count("\n") when :static 0 # It has not real newline "\n" but escaped "\\n". when :case arg, *cases = args arg.count("\n") + cases.map do |cond, e| (cond == :else ? 0 : cond.count("\n")) + count_lines(e) end.reduce(:+) when :escape count_lines(args[1]) when :newline 1 else raise UnexpectedExpression.new("[HAML BUG] Unexpected Temple expression '#{type}' is given!") end end end end haml-6.3.0/lib/haml/util.rb000066400000000000000000000216161453526310700154460ustar00rootroot00000000000000# frozen_string_literal: true begin require 'erubis/tiny' rescue LoadError require 'erb' end require 'set' require 'stringio' require 'strscan' module Haml # A module containing various useful functions. module Util extend self begin # Ruby 3.2+ or ERB 4+ require 'erb/escape' define_singleton_method(:escape_html, ERB::Escape.instance_method(:html_escape)) rescue LoadError require 'cgi/escape' def self.escape_html(html) CGI.escapeHTML(html.to_s) end end # TODO: Remove unescape_interpolation's workaround and get rid of `respond_to?`. def self.escape_html_safe(html) html = html.to_s (html.respond_to?(:html_safe?) && html.html_safe?) ? html : escape_html(html) end # Silence all output to STDERR within a block. # # @yield A block in which no output will be printed to STDERR def silence_warnings the_real_stderr, $stderr = $stderr, StringIO.new yield ensure $stderr = the_real_stderr end ## Rails XSS Safety # Whether or not ActionView's XSS protection is available and enabled, # as is the default for Rails 3.0+, and optional for version 2.3.5+. # Overridden in haml/template.rb if this is the case. # # @return [Boolean] def rails_xss_safe? false end # Checks that the encoding of a string is valid # and cleans up potential encoding gotchas like the UTF-8 BOM. # If it's not, yields an error string describing the invalid character # and the line on which it occurs. # # @param str [String] The string of which to check the encoding # @yield [msg] A block in which an encoding error can be raised. # Only yields if there is an encoding error # @yieldparam msg [String] The error message to be raised # @return [String] `str`, potentially with encoding gotchas like BOMs removed def check_encoding(str) if str.valid_encoding? # Get rid of the Unicode BOM if possible # Shortcut for UTF-8 which might be the majority case if str.encoding == Encoding::UTF_8 return str.gsub(/\A\uFEFF/, '') elsif str.encoding.name =~ /^UTF-(16|32)(BE|LE)?$/ return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding)), '') else return str end end encoding = str.encoding newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding(Encoding::ASCII_8BIT)) str.force_encoding(Encoding::ASCII_8BIT).split(newlines).each_with_index do |line, i| begin line.encode(encoding) rescue Encoding::UndefinedConversionError => e yield < bar') } it { assert_parse(nil, '[] => bar') } it { assert_parse(nil, '[1,2,3] => bar') } end describe 'foo: bar' do it { assert_parse({ '_' => '1' }, '_:1,') } it { assert_parse({ 'foo' => 'bar' }, ' foo: bar ') } it { assert_parse({ 'a' => 'b', 'c' => ':d' }, 'a: b, c: :d') } it { assert_parse({ 'a' => '[]', 'c' => '"d"' }, 'a: [], c: "d"') } it { assert_parse({ '_' => '1' }, ' { _:1, } ') } it { assert_parse({ 'foo' => 'bar' }, ' { foo: bar } ') } it { assert_parse({ 'a' => 'b', 'c' => ':d' }, ' { a: b, c: :d } ') } it { assert_parse({ 'a' => '[]', 'c' => '"d"' }, ' { a: [], c: "d" } ') } end describe ':foo => bar' do it { assert_parse({ 'foo' => ':bar' }, ' :foo => :bar ') } it { assert_parse({ '_' => '"foo"' }, ':_=>"foo"') } it { assert_parse({ 'a' => '[]', 'c' => '""', 'b' => '"#{3}"' }, ':a => [], c: "", :b => "#{3}"') } it { assert_parse({ 'foo' => ':bar' }, ' { :foo => :bar } ') } it { assert_parse({ '_' => '"foo"' }, ' { :_=>"foo" } ') } it { assert_parse({ 'a' => '[]', 'c' => '""', 'b' => '"#{3}"' }, ' { :a => [], c: "", :b => "#{3}" } ') } it { assert_parse(nil, ':"f#{o}o" => bar') } it { assert_parse(nil, ':"#{f}oo" => bar') } it { assert_parse(nil, ':"#{foo}" => bar') } end describe '"foo" => bar' do it { assert_parse({ 'foo' => '[1]' }, '"foo"=>[1]') } it { assert_parse({ 'foo' => 'nya' }, " 'foo' => nya ") } it { assert_parse({ 'foo' => 'bar' }, '%q[foo] => bar ') } it { assert_parse({ 'foo' => '[1]' }, ' { "foo"=>[1] } ') } it { assert_parse({ 'foo' => 'nya' }, " { 'foo' => nya } ") } it { assert_parse({ 'foo' => 'bar' }, ' { %q[foo] => bar } ') } it { assert_parse(nil, '"f#{o}o" => bar') } it { assert_parse(nil, '"#{f}oo" => bar') } it { assert_parse(nil, '"#{foo}" => bar') } it { assert_parse({ 'f#{o}o' => 'bar' }, '%q[f#{o}o] => bar ') } it { assert_parse({ 'f#{o}o' => 'bar' }, ' { %q[f#{o}o] => bar, } ') } it { assert_parse(nil, '%Q[f#{o}o] => bar ') } end if RUBY_VERSION >= '2.2.0' describe '"foo": bar' do it { assert_parse({ 'foo' => '()' }, '"foo":()') } it { assert_parse({ 'foo' => 'nya' }, " 'foo': nya ") } it { assert_parse({ 'foo' => '()' }, ' { "foo":() , }') } it { assert_parse({ 'foo' => 'nya' }, " { 'foo': nya , }") } it { assert_parse(nil, '"f#{o}o": bar') } it { assert_parse(nil, '"#{f}oo": bar') } it { assert_parse(nil, '"#{foo}": bar') } end end describe 'nested array' do it { assert_parse({ 'foo' => '[1,2,]' }, 'foo: [1,2,],') } it { assert_parse({ 'foo' => '[1,2,[3,4],5]' }, 'foo: [1,2,[3,4],5],') } it { assert_parse({ 'foo' => '[1,2,[3,4],5]', 'bar' => '[[1,2],]'}, 'foo: [1,2,[3,4],5],bar: [[1,2],],') } it { assert_parse({ 'foo' => '[1,2,]' }, ' { foo: [1,2,], } ') } it { assert_parse({ 'foo' => '[1,2,[3,4],5]' }, ' { foo: [1,2,[3,4],5], } ') } it { assert_parse({ 'foo' => '[1,2,[3,4],5]', 'bar' => '[[1,2],]'}, ' { foo: [1,2,[3,4],5],bar: [[1,2],], } ') } end describe 'nested hash' do it { assert_parse({ 'foo' => '{ }', 'bar' => '{}' }, 'foo: { }, bar: {}') } it { assert_parse({ 'foo' => '{ bar: baz, hoge: fuga, }' }, 'foo: { bar: baz, hoge: fuga, }, ') } it { assert_parse({ 'data' => '{ confirm: true, disable: false }', 'hello' => '{ world: foo, }' }, 'data: { confirm: true, disable: false }, :hello => { world: foo, },') } it { assert_parse({ 'foo' => '{ }', 'bar' => '{}' }, ' { foo: { }, bar: {} } ') } it { assert_parse({ 'foo' => '{ bar: baz, hoge: fuga, }' }, ' { foo: { bar: baz, hoge: fuga, }, } ') } it { assert_parse({ 'data' => '{ confirm: true, disable: false }', 'hello' => '{ world: foo, }' }, ' { data: { confirm: true, disable: false }, :hello => { world: foo, }, } ') } end describe 'nested method' do it { assert_parse({ 'foo' => 'bar(a, b)', 'hoge' => 'piyo(a, b,)' }, 'foo: bar(a, b), hoge: piyo(a, b,),') } it { assert_parse({ 'foo' => 'bar(a, b)', 'hoge' => 'piyo(a, b,)' }, ' { foo: bar(a, b), hoge: piyo(a, b,), } ') } end end if RUBY_ENGINE != 'truffleruby' # truffleruby doesn't have Ripper.lex end haml-6.3.0/test/haml/cli_test.rb000066400000000000000000000006271453526310700165070ustar00rootroot00000000000000require 'haml/cli' describe Haml::CLI do describe '#temple' do def redirect_output out, $stdout = $stdout, StringIO.new yield ensure $stdout = out end it 'does not crash when compiling a tag' do redirect_output do f = Tempfile.open('haml') f.write('%input{ hash }') f.close Haml::CLI.new.temple(f.path) end end end end haml-6.3.0/test/haml/dynamic_merger_test.rb000066400000000000000000000043301453526310700207200ustar00rootroot00000000000000describe Haml::DynamicMerger do describe '#call' do def assert_compile(expected, input) actual = Haml::DynamicMerger.new.compile(input) assert_equal expected, actual end def assert_noop(input) actual = Haml::DynamicMerger.new.compile(input) assert_equal input, actual end def strlit(body) "%Q\0#{body}\0" end specify { assert_compile([:static, 'foo'], [:multi, [:static, 'foo']]) } specify { assert_compile([:dynamic, 'foo'], [:multi, [:dynamic, 'foo']]) } specify { assert_noop([:multi, [:static, 'foo'], [:newline]]) } specify { assert_noop([:multi, [:dynamic, 'foo'], [:newline]]) } specify { assert_noop([:multi, [:static, "foo\n"], [:newline]]) } specify { assert_noop([:multi, [:static, 'foo'], [:dynamic, "foo\n"], [:newline]]) } specify { assert_noop([:multi, [:static, "foo\n"], [:dynamic, 'foo'], [:newline]]) } specify do assert_compile([:dynamic, strlit("\#{foo}foo\n")], [:multi, [:dynamic, 'foo'], [:static, "foo\n"], [:newline]]) end specify do assert_compile([:multi, [:dynamic, strlit("\#{foo}foo\n\n")], [:newline], [:code, 'foo'], ], [:multi, [:dynamic, 'foo'], [:static, "foo\n\n"], [:newline], [:newline], [:newline], [:code, 'foo'], ]) end specify do assert_compile([:multi, [:dynamic, strlit("\#{foo}foo\n")], [:code, 'bar'], [:dynamic, strlit("\#{foo}foo\n")], ], [:multi, [:dynamic, 'foo'], [:static, "foo\n"], [:newline], [:code, 'bar'], [:dynamic, 'foo'], [:static, "foo\n"], [:newline], ]) end specify do assert_compile([:multi, [:newline], [:dynamic, strlit("foo\n\#{foo}")]], [:multi, [:newline], [:newline], [:static, "foo\n"], [:dynamic, 'foo']]) end specify { assert_compile([:static, "\n"], [:multi, [:static, "\n"]]) } specify { assert_compile([:newline], [:multi, [:newline]]) } end end haml-6.3.0/test/haml/engine/000077500000000000000000000000001453526310700156145ustar00rootroot00000000000000haml-6.3.0/test/haml/engine/attributes_test.rb000066400000000000000000000522251453526310700213740ustar00rootroot00000000000000require_relative '../../test_helper' describe Haml::Engine do include RenderHelper describe 'id attributes' do describe 'compatilibity' do # TODO: assert_haml tests nothing since migration to haml repository. Use assert_render instead. it { assert_haml(%q|#a|) } it { assert_haml(%q|#a{ id: nil }|) } it { assert_haml(%q|#a{ id: nil }(id=nil)|) } it { assert_haml(%q|#a{ id: false }|) } it { assert_haml(%q|#a{ id: 'b' }|) } it { assert_haml(%q|#b{ id: 'a' }|) } it { assert_haml(%q|%a{ 'id' => 60 }|) } if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.4.0') it { assert_haml(%q|%p{class: "a #{["1", "2", "3"].join}"} foo|) } end it { assert_haml(%q|#a{ id: 'b' }(id=id)|, locals: { id: 'c' }) } it { assert_haml(%q|#c{ id: a = 'a' }(id=id)|, locals: { id: 'b' }) } it { assert_haml(%q|#d#c{ id: a = 'b' }(id=id)|, locals: { id: 'a' }) } it { assert_haml(%q|#d#c{ id: %w[b e] }(id=id)|, locals: { id: 'a' }) } it { assert_haml(%q|%div{ hash }|, locals: { hash: { id: 'a' } }) } it { assert_haml(%q|#b{ hash }|, locals: { hash: { id: 'a' } }) } it { assert_haml(%q|#b{ hash }(id='c')|, locals: { hash: { id: 'a' }, id: 'c' }) } it { assert_haml(%q|#b{ hash }(id=id)|, locals: { hash: { id: 'a' }, id: 'c' }) } it { assert_haml(<<-HAML.unindent) } .haml#info{ "data": { "content": "/:|}", "haml-info": { "url": "https://haml.info", } } } Haml HAML end describe 'incompatibility' do # TODO: assert_haml tests nothing since migration to haml repository. Use assert_render instead. it { assert_render(%Q|
\n|, %q|#a{ id: [] }|) } it { assert_render(%Q|
\n|, %q|%div{ id: [nil, false] }|) } it { assert_render(%Q|
\n|, %q|#d#c{ id: [] }(id=id)|, locals: { id: 'a' }) } it { assert_render(%Q|
\n|, %q|%div{ id: nil }|) } it { assert_render(%Q|\n|, %q|%input{ id: false }|) } it { assert_render(%Q|\n|, %q|%input{ id: val }|, locals: { val: false }) } it { assert_render(%Q|\n|, %q|%input{ hash }|, locals: { hash: { id: false } }) } end end describe 'class attributes' do describe 'compatibility' do # TODO: assert_haml tests nothing since migration to haml repository. Use assert_render instead. it { assert_haml(%q|.bar.foo|) } it { assert_haml(%q|.foo.bar|) } it { assert_haml(%q|%div(class='bar foo')|) } it { assert_haml(%q|%div(class='foo bar')|) } it { assert_haml(%q|%div{ class: 'bar foo' }|) } it { assert_haml(%q|.b{ class: 'a' }|) } it { assert_haml(%q|.a{ class: 'b a' }|) } it { assert_haml(%q|.b.a{ class: 'b a' }|) } it { assert_haml(%q|.b{ class: 'b a' }|) } it { assert_haml(%q|.a{ class: klass }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.b{ class: klass }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.b.a{ class: klass }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.b{ class: 'c a' }|) } it { assert_haml(%q|.b{ class: 'a c' }|) } it { assert_haml(%q|.a{ class: [] }|) } it { assert_haml(%q|.a{ class: %w[c b] }|) } it { assert_haml(%q|.a.c(class='b')|) } it { assert_haml(%q|%a{ 'class' => 60 }|) } it { assert_haml(%q|%div{ class: 'b a' }(class=klass)|, locals: { klass: 'b a' }) } it { assert_haml(%q|%div(class=klass){ class: 'b a' }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.a.d(class=klass){ class: 'c d' }|, locals: { klass: 'b a' }) } it { assert_haml(%q|.a.d(class=klass)|, locals: { klass: 'b a' }) } it { assert_haml(%q|.a{:class => klass}|, locals: { klass: nil }) } it { assert_haml(%q|.a{:class => nil}(class=klass)|, locals: { klass: nil }) } it { assert_haml(%q|.a{:class => nil}|) } it { assert_haml(%q|.a{:class => false}|) } it { assert_haml(%q|.b{ hash, class: 'a' }|, locals: { hash: { class: nil } }) } it { assert_haml(%q|.b{ hash, :class => 'a' }|, locals: { hash: { class: nil } }) } it { assert_haml(%q|.b{ hash, 'class' => 'a' }|, locals: { hash: { class: nil } }) } it { assert_haml(%q|.a{ hash }|, locals: { hash: { class: 'd' } }) } it { assert_haml(%q|.b{ hash, class: 'a' }(class='c')|, locals: { hash: { class: 'd' } }) } it { assert_haml(%q|.b{ hash, class: 'a' }(class=klass)|, locals: { hash: { class: 'd' }, klass: nil }) } it { assert_haml(%q|%div{ class: 'b a' }|) } it { assert_haml(%q|%div{ class: klass }|, locals: { klass: 'b a' }) } it { assert_haml(%q|%div(class='b a')|) } it { assert_haml(%q|%div(class=klass)|, locals: { klass: 'b a' }) } it { assert_haml(%q|%div{ class: [false, 'a', nil] }|) } it { assert_haml(%q|%div{ class: %q[b a] }|) } it { assert_haml(%q|%div{ class: %q[b a b] }|) } it { assert_haml(%q|%span.c2{class: ["c1", "c3", :c2]}|) } it { assert_haml(%q|%span{class: [1, nil, false, true]}|) } it do assert_haml(<<-HAML.unindent) - v = [1, nil, false, true] %span{class: v} HAML end it do assert_haml(<<-HAML.unindent) - h1 = {class: 'c1', id: ['id1', 'id3']} - h2 = {class: [{}, 'c2'], id: 'id2'} %span#main.content{h1, h2} hello HAML end end describe 'incompatibility' do it { assert_render(%Q|
\n|, %q|%div{ class: nil }|) } it { assert_render(%Q|
\n|, %q|%div{ class: false }|) } it { assert_render(%Q|
\n|, %q|%div{ class: false }|) } it { assert_render(%Q|
\n|, %q|%div{ class: val }|, locals: { val: false }) } it { assert_render(%Q|
\n|, %q|%div{ hash }|, locals: { hash: { class: false } }) } end end describe 'data attributes' do # TODO: assert_haml tests nothing since migration to haml repository. Use assert_render instead. it { assert_haml(%q|#foo.bar{ data: { disabled: val } }|, locals: { val: false }) } it { skip; assert_haml(%q|%div{:data => hash}|, locals: { hash: { :a => { :b => 'c' } }.tap { |h| h[:d] = h } }) } it { skip; assert_haml(%q|%div{ hash }|, locals: { hash: { data: { :a => { :b => 'c' } }.tap { |h| h[:d] = h } } }) } it { assert_haml(%q|%div{:data => {:foo_bar => 'blip', :baz => 'bang'}}|) } it { assert_haml(%q|%div{ data: { raw_src: 'foo' } }|) } it { assert_haml(%q|%a{ data: { value: [count: 1] } }|) } it { assert_haml(%q|%a{ 'data-disabled' => true }|) } it { assert_haml(%q|%a{ :'data-disabled' => true }|) } it { assert_haml(%q|%a{ data: { nil => 3 } }|) } it { assert_haml(%q|%a{ data: 3 }|) } it { assert_haml(%q|%a(data=3)|) } it { assert_haml(%q|%a{ 'data-bar' => 60 }|) } it { assert_haml(%q|%a{ data: { overlay_modal: 'foo' } }|) } it { assert_haml(%q|%a{ data: { overlay_modal: true } }|) } it { assert_haml(%q|%a{ data: { overlay_modal: false } }|) } it { assert_haml(%q|%a{ data: true }|) } it { assert_haml(%q|%a{ data: { nil => true } }|) } it { assert_haml(%q|%a{ data: { false => true } }|) } it { skip; assert_haml(%q|%a{ { data: { 'foo-bar' => 1 } }, data: { foo: { bar: 2 } } }|) } it { assert_haml(%q|%a{ { data: { foo: { bar: 2 } } }, data: { 'foo-bar' => 2 } }|) } it { assert_haml(%q|%a{ { data: { :'foo-bar' => 1 } }, data: { 'foo-bar' => 2 } }|) } it do assert_haml(<<-HAML.unindent) - old = { disabled: true, checked: false, href: false, 'hello-world' => '<>/' } - new = { disabled: false, checked: true, href: '<>/', hello: {}, 'hello_hoge' => true, foo: { 'bar&baz' => 'hoge' } } - hash = { data: { href: true, hash: true } } %a(data=new){ hash, data: old } HAML end it do assert_haml(<<-HAML.unindent) - h1 = { data: 'should be overwritten' } - h2 = { data: nil } %div{ h1, h2 } HAML end end describe 'boolean attributes' do # TODO: assert_haml tests nothing since migration to haml repository. Use assert_render instead. it { assert_haml(%q|%input{ disabled: nil }|) } it { assert_haml(%q|%input{ disabled: false }|) } it { assert_haml(%q|%input{ disabled: true }|) } it { assert_haml(%q|%input{ disabled: 'false' }|) } it { assert_haml(%q|%input{ disabled: val = nil }|) } it { assert_haml(%q|%input{ disabled: val = false }|) } it { assert_haml(%q|%input{ disabled: val = true }|) } it { assert_haml(%q|%input{ disabled: val = 'false' }|) } it { assert_haml(%q|%input{ disabled: nil }(disabled=true)|) } it { assert_haml(%q|%input{ disabled: false }(disabled=true)|) } it { assert_haml(%q|%input{ disabled: true }(disabled=false)|) } it { assert_haml(%q|%a{ hash }|, locals: { hash: { disabled: false } }) } it { assert_haml(%q|%a{ hash }|, locals: { hash: { disabled: nil } }) } it { assert_haml(%q|input(disabled=true){ disabled: nil }|) } it { assert_haml(%q|input(disabled=true){ disabled: false }|) } it { assert_haml(%q|input(disabled=false){ disabled: true }|) } it { assert_haml(%q|%input(disabled=val){ disabled: false }|, locals: { val: true }) } it { assert_haml(%q|%input(disabled=val){ disabled: false }|, locals: { val: false }) } it { assert_haml(%q|%input(disabled=nil)|) } it { assert_haml(%q|%input(disabled=false)|) } it { assert_haml(%q|%input(disabled=true)|) } it { assert_haml(%q|%input(disabled='false')|) } it { assert_haml(%q|%input(disabled=val)|, locals: { val: 'false' }) } it { assert_haml(%q|%input(disabled='false'){ disabled: true }|) } it { assert_haml(%q|%input(disabled='false'){ disabled: false }|) } it { assert_haml(%q|%input(disabled='false'){ disabled: nil }|) } it { assert_haml(%q|%input(disabled=''){ disabled: nil }|) } it { assert_haml(%q|%input(checked=true)|) } it { assert_haml(%q|%input(checked=true)|, format: :xhtml) } it { assert_haml(%q|%input{ 'data-overlay_modal' => nil }|) } it { assert_haml(%q|%input{ 'data-overlay_modal' => false }|) } it { assert_haml(%q|%input{ 'data-overlay_modal' => true }|) } it { assert_haml(%q|%input{ 'data-overlay_modal' => 'false' }|) } it { assert_haml(%q|%input{ :'data-overlay_modal' => val = nil }|) } it { assert_haml(%q|%input{ :'data-overlay_modal' => val = false }|) } it { assert_haml(%q|%input{ :'data-overlay_modal' => val = true }|) } it { assert_haml(%q|%input{ :'data-overlay_modal' => val = 'false' }|) } it { assert_haml(%q|%a{ hash }|, locals: { hash: { 'data-overlay_modal' => false } }) } it { assert_haml(%q|%a{ hash }|, locals: { hash: { 'data-overlay_modal' => true } }) } it { assert_haml(%q|%a{ 'disabled' => 60 }|) } end describe 'common attributes' do describe 'compatibility' do # TODO: assert_haml tests nothing since migration to haml repository. Use assert_render instead. it { assert_haml(%Q|%a{ href: '/search?foo=bar&hoge=' }|) } it { assert_haml(%Q|- h = {foo: 1, 'foo' => 2}\n%span{ h }|) } it { assert_haml(%q|%span(foo='new'){ foo: 'old' }|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span(foo=new){ foo: 'old' }|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span(foo=new){ foo: old }|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span{ foo: 'old' }(foo='new')|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span{ foo: 'old' }(foo=new)|, locals: { new: 'new', old: 'old' }) } it { assert_haml(%q|%span{ foo: old }(foo=new)|, locals: { new: 'new', old: 'old' }) } it do assert_haml(<<-HAML.unindent) - h1 = { foo: 1 } - h2 = { foo: 2 } %div{ h1, h2 } HAML end it do assert_haml(<<-'HAML'.unindent) - h = { "class\0with null" => 'is not class' } %div{ h } HAML end it { assert_haml(%q|%a{ 'href' => 60 }|) } end describe 'incompatibility' do it { assert_render(%Q|\n|, %q|%a{ href: "'\"" }|) } it { assert_render(%Q|\n|, %q|%input{ value: nil }|) } it { assert_render(%Q|\n|, %q|%input{ value: false }|) } it { assert_render(%Q|\n|, %q|%input{ value: val }|, locals: { val: false }) } it { assert_render(%Q|\n|, %q|%input{ hash }|, locals: { hash: { value: false } }) } it do assert_render(%Q|
\n|, <<-HAML.unindent) - h1 = { foo: 'should be overwritten' } - h2 = { foo: nil } %div{ h1, h2 } HAML end end end describe 'object reference' do ::TestObject = Struct.new(:id) unless defined?(::TestObject) it { assert_render(%Q|\n|, %q|%a[foo]|, locals: { foo: TestObject.new(10) }) } it { assert_render(%Q|\n|, %q|%a[foo, nil]|, locals: { foo: TestObject.new(10) }) } it { assert_render(%Q|\n|, %q|%a[foo]|, locals: { foo: TestObject.new(nil) }) } it { assert_render(%Q|\n|, %q|%a[foo, 'pre']|, locals: { foo: TestObject.new(10) }) } it { assert_render(%Q|
\n|, %q|.static#static[TestObject.new(10)]|) } it { assert_render(%Q|
\n|, %q|.static#static[nil]|) } it do assert_render( %Q|\n|, %q|%a.static#static[foo, 'pre']{ id: dynamic, class: dynamic }|, locals: { foo: TestObject.new(10), dynamic: 'dynamic' }, ) end end describe 'engine options' do describe 'attr_quote' do it { assert_render(%Q|\n|, %q|%a{ href: '/' }|) } it { assert_render(%Q|\n|, %q|%a{ href: '/' }|, attr_quote: ?') } it { assert_render(%Q|\n|, %q|%a{ href: '/' }|, attr_quote: ?*) } it { assert_render(%Q|\n|, %q|%a{ id: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ id: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, attr_quote: ?", locals: { hash: { id: '/' } }) } it { assert_render(%Q|\n|, %q|%a{ class: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ class: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, attr_quote: ?", locals: { hash: { class: '/' } }) } it { assert_render(%Q|\n|, %q|%a{ data: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ data: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %q|%a{ data: { url: '/' } }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ data: val }|, attr_quote: ?", locals: { val: { url: '/' } }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, attr_quote: ?", locals: { hash: { data: { url: '/' } } }) } it { assert_render(%Q|\n|, %q|%a{ disabled: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %Q|%a{ disabled: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, attr_quote: ?", locals: { hash: { disabled: '/' } }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, attr_quote: ?", format: :xhtml, locals: { hash: { disabled: true } }) } it { assert_render(%Q|\n|, %q|%a{ href: '/' }|, attr_quote: ?") } it { assert_render(%Q|\n|, %q|%a{ href: val }|, attr_quote: ?", locals: { val: '/' }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, attr_quote: ?", locals: { hash: { href: '/' } }) } end describe 'escape_attrs' do it { assert_render(%Q|\n|, %q|%a{ id: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ id: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { id: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ id: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ id: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { id: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ class: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ class: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { class: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ class: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ class: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { class: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ data: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ data: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { data: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ data: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ data: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { data: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ disabled: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ disabled: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { disabled: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ disabled: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ disabled: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { disabled: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ href: '&<>"/' }|, escape_attrs: false) } it { assert_render(%Q|\n|, %Q|%a{ href: val }|, escape_attrs: false, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: false, locals: { hash: { href: '&<>"/' } }) } it { assert_render(%Q|\n|, %q|%a{ href: '&<>"/' }|, escape_attrs: true) } it { assert_render(%Q|\n|, %Q|%a{ href: val }|, escape_attrs: true, locals: { val: '&<>"/' }) } it { assert_render(%Q|\n|, %Q|%a{ hash }|, escape_attrs: true, locals: { hash: { href: '&<>"/' } }) } end describe 'format' do it { assert_render(%Q|\n|, %q|%a{ disabled: true }|, format: :html) } it { assert_render(%Q|\n|, %q|%a{ disabled: val }|, format: :html, locals: { val: true }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, format: :html, locals: { hash: { disabled: true } }) } it { assert_render(%Q|\n|, %q|%a{ disabled: true }|, format: :xhtml) } it { assert_render(%Q|\n|, %q|%a{ disabled: val }|, format: :xhtml, locals: { val: true }) } it { assert_render(%Q|\n|, %q|%a{ hash }|, format: :xhtml, locals: { hash: { disabled: true } }) } end end end haml-6.3.0/test/haml/engine/comment_test.rb000066400000000000000000000031571453526310700206500ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'comment' do it 'renders html comment' do assert_render(%Q|\n|, '/ comments') end it 'renders intepolation' do assert_render(%Q|\n|, '/ #{"comments"}') end it 'strips html comment ignoring around spcaes' do assert_render(%Q|\n|, '/ comments ') end it 'accepts backslash-only line in a comment' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML / \ HAML end it 'renders a deeply indented comment starting with backslash' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML / \ a / a HAML end it 'ignores multiline comment' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) ok HTML -# if true - raise 'ng' = invalid script too deep indent ok HAML end it 'renders conditional comment' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML /[[if IE]] %span hello world HAML end it 'renders conditional comment' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML /[if lt IE 9] hello HAML end end end haml-6.3.0/test/haml/engine/doctype_test.rb000066400000000000000000000012771453526310700206560ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'doctype' do it 'renders html5 doctype' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML !!! HAML end it 'renders xml doctype' do assert_render(<<-HTML.unindent, <<-HAML.unindent, format: :xhtml) HTML !!! XML HAML end it 'renders rdfa doctype' do assert_render(<<-HTML.unindent, <<-HAML.unindent, format: :xhtml) HTML !!! RDFa HAML end end end haml-6.3.0/test/haml/engine/indent_test.rb000066400000000000000000000013561453526310700204660ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'tab indent' do it 'accepts tab indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

HTML %p \t%a HAML end it 'accepts N-space indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

foo

HTML %p %span foo HAML end it 'accepts N-tab indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

foo

HTML %p \t%span \t\tfoo HAML end end end haml-6.3.0/test/haml/engine/multiline_test.rb000066400000000000000000000014351453526310700212050ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'multiline' do it 'joins multi-lines ending with pipe' do assert_render(<<-HTML.unindent, <<-HAML.unindent) a b HTML a | b | HAML end it 'renders multi lines' do assert_render(<<-HTML.unindent, <<-HAML.unindent) abc 'd' HTML = 'a' + | 'b' + | 'c' | 'd' HAML end it 'accepts invalid indent' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
12
3
HTML %span %div = '1' + | '2' | %div 3 HAML end end end haml-6.3.0/test/haml/engine/new_attribute_test.rb000066400000000000000000000052351453526310700220610ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'new attributes' do it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

bar

HTML %p(class='foo') bar HAML end it 'renders multiple attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

bar

HTML %p(a=1 b=2) bar HAML end it 'renders hyphenated attributes properly' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

bar

HTML %p(data-foo='bar') bar HAML end it 'renders multiply hyphenated attributes properly' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

bar

HTML %p(data-x-foo='bar') bar HAML end describe 'html escape' do it 'escapes attribute values on static attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %a(title="'") %a(title = "'\"") %a(href='/search?foo=bar&hoge=') HAML end it 'escapes attribute values on dynamic attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML - title = "'\"" - href = '/search?foo=bar&hoge=' %a(title=title) %a(href=href) HAML end end describe 'element class with attribute class' do it 'does not generate double classes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML .item(class='first') HAML end it 'does not generate double classes for a variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = 'val' .element(class=val) HAML end end describe 'element id with attribute id' do it 'concatenates ids with underscore' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML #item(id='first') HAML end it 'concatenates ids with underscore for a variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = 'first' #item(id=val) HAML end end end end haml-6.3.0/test/haml/engine/old_attribute_test.rb000066400000000000000000000370701453526310700220500ustar00rootroot00000000000000require_relative '../../test_helper' describe Haml::Engine do include RenderHelper describe 'old attributes' do it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{class: 'foo'} bar HAML end it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ data: 2 } bar HAML end it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ :class => 'foo' } bar HAML end it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ :class => 'foo', id: 'bar' } bar HAML end it 'renders attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ :'data-disabled' => true } bar HAML end it 'renders value-less attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - data = { yabba: 'dabba', doo: 'yep' } .foo{ data: } HAML end if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.1') it 'accepts method call including comma' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %body{ class: "#{"ab".gsub(/a/, 'b')}", data: { confirm: 'really?', disabled: true }, id: 'c'.gsub(/c/, 'a') } HAML end it 'accepts tag content' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ class: 'foo' } bar HAML end it 'renders multi-byte chars as static attribute value' do assert_render(<<-HTML.unindent, <<-HAML.unindent) こんにちは HTML %img{ alt: 'こんにちは' } HAML end it 'sorts static attributes by name' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span{ :foo => "bar", :hoge => "piyo"} %span{ :hoge => "piyo", :foo => "bar"} HAML end it 'renders %() string attributes' do assert_render(<<-'HTML'.unindent, <<-'HAML'.unindent)

HTML - some_local_variable = 'a' %p{ title: %(foo(#{some_local_variable})) } HAML end describe 'runtime attributes' do it 'renders runtime hash attribute' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { foo: 'bar' } %span{ hash } HAML end it 'renders multiples hashes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - h1 = { a: 'b' } - h2 = { c: 'd' } - h3 = { e: 'f' } %span{ h1, h2, h3 } HAML end it 'renders multiples hashes and literal hash' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - h1 = { a: 'b' } - h2 = { c: 'd' } - h3 = { e: 'f' } %span{ h1, h2, h3, g: 'h', i: 'j' } HAML end it 'does not crash when nil is given' do if /java/ === RUBY_PLATFORM skip 'maybe due to Ripper of JRuby' end assert_raises ArgumentError do render_haml("%div{ nil }") end end end describe 'joinable attributes' do it 'joins class with a space' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

HTML - val = ['a', 'b', 'c'] %p{ class: val } %p{ class: %w[a b c] } %p{ class: ['a', 'b', 'c'] } HAML end it 'joins attribute class and element class' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML .foo{ class: ['bar'] } .foo{ class: ['bar', 'foo'] } .foo{ class: ['bar', nil] } .foo{ class: ['bar', 'baz'] } HAML end it 'joins id with an underscore' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

HTML - val = ['a', 'b', 'c'] %p{ id: val } %p{ id: %w[a b c] } %p{ id: ['a', 'b', 'c'] } HAML end it 'does not join others' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %a{ data: { value: [count: 1] } } HAML end end describe 'deletable attributes' do def with_custom_attributes(*attributes, &block) begin old_attributes = Haml::BOOLEAN_ATTRIBUTES.dup Haml::BOOLEAN_ATTRIBUTES.push(*attributes) block.call ensure Haml::BOOLEAN_ATTRIBUTES.replace(old_attributes) end end it 'deletes attributes whose value is nil or false' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { checked: false } %input{ hash } %input{ checked: false } %input{ checked: nil } - checked = nil %input{ checked: checked } - checked = false %input{ checked: checked } HAML end it 'deletes some limited attributes with dynamic value' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = false #foo.bar{ autofocus: val } #foo.bar{ checked: val } #foo.bar{ data: { disabled: val } } #foo.bar{ disabled: val } #foo.bar{ formnovalidate: val } #foo.bar{ multiple: val } #foo.bar{ readonly: val } #foo.bar{ required: val } HAML end it 'does not delete non-boolean attributes, for optimization' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %a{ href: false } - val = false %a{ href: val } - hash = { href: false } %a{ hash } %a{ disabled: false } - val = false %a{ disabled: val } - hash = { disabled: false } %a{ hash } %a{ href: nil } - val = nil %a{ href: val } - hash = { href: nil } %a{ hash } %a{ disabled: nil } - val = nil %a{ disabled: val } - hash = { disabled: nil } %a{ hash } HAML end it 'deletes custom attributes in BOOLEAN_ATTRIBUTES' do with_custom_attributes('custom') do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML %div(custom=false) - custom = false %div(custom=custom) %div{ custom: false } %div{ custom: custom } - hash = { custom: custom } %div{ hash } HAML end end it 'deletes data- attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML %div{ "data-foo" => false } - foo = false %div{ "data-foo" => foo } - hash = { "data-foo" => foo } %div{ hash } HAML end it 'deletes aria- attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML %div{ "aria-foo" => false } - foo = false %div{ "aria-foo" => foo } - hash = { "aria-foo" => foo } %div{ hash } HAML end end describe 'html escape' do it 'escapes attribute values on static attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %a{title: "'"} %a{title: "'\""} %a{href: '/search?foo=bar&hoge='} HAML end it 'escapes attribute values on dynamic attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML - title = "'\"" - href = '/search?foo=bar&hoge=' %a{title: title} %a{href: href} HAML end it 'escapes attribute values on hash attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML - title = { title: "'\"" } - href = { href: '/search?foo=bar&hoge=' } %a{ title } %a{ href } HAML end end describe 'nested data attributes' do it 'renders data attribute by hash' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { bar: 'baz' } %span.foo{ data: hash } HAML end it 'renders true attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ data: { disabled: true } } bar HAML end it 'renders nested hash whose value is variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML - hash = { disabled: true } %span{ data: hash } bar HAML end it 'changes an underscore in a nested key to a hyphen' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML %div{ data: { raw_src: 'foo' } } HAML end it 'changes an underscore in a nested dynamic attribute' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { raw_src: 'foo' } %div{ data: hash } HAML end end describe 'nested aria attributes' do it 'renders aria attribute by hash' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { bar: 'baz' } %span.foo{ aria: hash } HAML end it 'renders true attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML %span{ aria: { disabled: true } } bar HAML end it 'renders nested hash whose value is variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar HTML - hash = { disabled: true } %span{ aria: hash } bar HAML end it 'changes an underscore in a nested key to a hyphen' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML %div{ aria: { raw_src: 'foo' } } HAML end it 'changes an underscore in a nested dynamic attribute' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { raw_src: 'foo' } %div{ aria: hash } HAML end it 'renders hash-only dynamic attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { aria: { label: 'foo' } } %div{ hash } HAML end end describe 'element class with attribute class' do it 'does not generate double classes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML .item{ class: 'first' } HAML end it 'does not generate double classes for a variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = 'val' .element{ class: val } HAML end it 'does not generate double classes for hash attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { class: 'val' } .element{ hash } HAML end end describe 'element id with attribute id' do it 'does not generate double ids' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML #item{ id: 'first' } HAML end it 'does not generate double ids for a variable' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - val = 'first' #item{ id: val } HAML end it 'does not generate double ids for hash attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { id: 'first' } #item{ hash } HAML end it 'does not generate double ids and classes for hash attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML - hash = { id: 'first', class: 'foo' } #item.bar{ hash } HAML end end if RUBY_VERSION >= "2.2.0" describe 'Ruby 2.2 syntax' do it 'renders static attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %meta{ content: 'IE=edge', 'http-equiv': 'X-UA-Compatible' } HAML end it 'renders dynamic attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - hash = { content: 'IE=edge' } %meta{ hash, 'http-equiv': 'X-UA-Compatible' } HAML end end end end end haml-6.3.0/test/haml/engine/script_test.rb000066400000000000000000000061241453526310700205070ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'script' do it 'renders one-line script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 3 12 HTML = 1 + 2 %span= 3 * 4 HAML end it 'renders dynamic interpolated string' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) hello nya world HTML - nya = 'nya' = "hello #{nya} world" HAML end it 'renders array with escape_html: false' do assert_render(<<-HTML.unindent, <<-HAML.unindent, escape_html: false) ["<", ">"] HTML = ['<', '>'] HAML end it 'renders one-line script with comment' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ## ["#", "#"] HTML = # comment_only = '#' + "#" # = 3 # = ['#', "#"] # comment HAML end it 'renders multi-lines script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 3 4 / 2 -1 HTML %span = 1 + 2 4 / 2 %a= 3 - 4 HAML end it 'renders block script' do assert_render(<<-HTML.unindent, <<-HAML.unindent, disable_capture: true) 0 1 2 34 HTML = 3.times do |i| = i 4 HAML end it 'renders tag internal block script' do assert_render(<<-HTML.unindent, <<-HAML.unindent, disable_capture: true) 0 1 HTML %span = 1.times do |i| = i HAML end it 'renders block and a variable with spaces' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 0 HTML - 1.times do | i | = i HAML end it 'accepts a continuing script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 3 HTML - obj = Object.new; def obj.foo(a, b); a + b; end = obj.foo(1, 2) HAML end it 'renders !=' do assert_render(<<-HTML.unindent.strip, <<-HAML.unindent, escape_html: false) <"&> <"&> HTML != '<"&>' != '<"&>'.tap do |str| -# no operation HAML end it 'renders &=' do assert_render(<<-HTML.unindent.strip, <<-HAML.unindent, escape_html: false) <"&> <"&> HTML &= '<"&>' &= '<"&>'.tap do |str| -# no operation HAML end it 'regards ~ operator as =' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) <code>hello world</code> HTML ~ "hello\nworld" HAML end it 'renders comment-only nested script' do assert_render('1', <<-HAML.unindent) = 1.times do # comment - # comment only HAML end it 'renders inline script with comment' do assert_render(%Q|3\n|, %q|%span= 1 + 2 # comments|) end end end haml-6.3.0/test/haml/engine/silent_script_test.rb000066400000000000000000000105701453526310700220650ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'silent script' do it 'renders nothing' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML - _ = nil - _ = 3 - _ = 'foo' HAML end it 'renders silent script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 5 HTML - foo = 3 - bar = 2 = foo + bar HAML end it 'renders nested block' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 0 1 2 3 4 HTML - 2.times do |i| = i 2 - 3.upto(4).each do |i| = i HAML end it 'renders if' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML - if true ok HAML end it 'renders if-else' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok ok HTML - if true ok - else ng - if false ng - else ok HAML end it 'renders nested if-else' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML %span - if false ng - else ok HAML end it 'renders empty elsif statement' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span - if false - elsif false HAML end it 'renders empty else statement' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span - if false ng - else HAML end it 'renders empty when statement' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span - case - when false HAML end it 'accept if inside if-else' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML - if false - if true ng - else ok HAML end it 'renders if-elsif' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok ok HTML - if false - elsif true ok - if false - elsif false - else ok HAML end it 'renders case-when' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) ok HTML - case 'foo' - when /\Ao/ ng - when /\Af/ ok - else ng HAML end it 'renders case-when with multiple candidates' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML - case 'a' - when 'a', 'b' ok HAML end it 'renders case-in' do skip 'pattern-matching not supported' if RUBY_VERSION < '2.7' || RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) ok HTML - case [:foo, 'ok'] - in [:foo, msg] = msg - else ng HAML end it 'renders begin-rescue' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello world HTML - begin - raise 'error' - rescue hello - ensure world HAML end it 'renders rescue with error' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML - begin - raise 'error' - rescue RuntimeError => _e hello HAML end it 'joins a next line if a current line ends with ","' do assert_render(<<-HTML.unindent, "- foo = [', \n ']\n= foo") [", "] HTML end it 'accepts illegal indent in continuing code' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
3
HTML %span %div - obj = Object.new; def obj.foo(a, b); a + b; end - num = obj.foo(1, 2) = num HAML end it 'renders comment-only nested silent script' do assert_render('', <<-HAML.unindent) - if true - # comment only HAML end end end haml-6.3.0/test/haml/engine/tag_test.rb000066400000000000000000000075741453526310700177700ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'tag' do it 'renders one-line tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span hello HAML end it 'accepts multi-line =' do assert_render(<<-HTML.unindent, <<-HAML.unindent) o HTML %span= 'hello'.gsub('hell', '') HAML end it 'renders multi-line tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span hello HAML end it 'renders a nested tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello world HTML %span %b hello %i %small world HAML end it 'renders multi-line texts' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello world HTML %span %b hello world HAML end it 'ignores empty lines' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span %b hello HAML end it 'renders classes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span.foo-1.bar_A hello HAML end it 'renders ids only last one' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span#Bar_0#bar- hello HAML end it 'renders ids and classes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) hello HTML %span#a.b#c.d hello HAML end it 'renders implicit div tag starting with id' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
HTML #hello.world HAML end it 'renders implicit div tag starting with class' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
foo
HTML .world#hello foo HAML end it 'renders large-case tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent) foo HTML %SPAN foo HAML end it 'renders h1 tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

foo

HTML %h1 foo HAML end it 'renders tag including hyphen or underscore' do assert_render(<<-HTML.unindent, <<-HAML.unindent) <-_>foo HTML %-_ foo HAML end it 'does not render silent script just after a tag' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) raise 'a' HTML %span- raise 'a' HAML end it 'renders a text just after attributes' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) a HTML %span{a: 2}a HAML end it 'strips a text' do assert_render(<<-HTML.unindent, <<-HAML.unindent) foo HTML %span foo HAML end it 'ignores spaces after tag' do assert_render(<<-HTML.unindent, "%span \n a") a HTML end it 'parses self-closing tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent, format: :xhtml)
HTML %div/ %div HAML end end end haml-6.3.0/test/haml/engine/text_test.rb000066400000000000000000000123561453526310700201730ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'text' do it 'renders string interpolation' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) a3aa" ["1", 2] b " ! a{:a=>3} HTML #{ "a#{3}a" }a" #{["1", 2]} b " ! a#{{ a: 3 }} HAML end it 'escapes all operators by backslash' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) a = 'a' - HTML = 'a' - \= 'a' \- HAML end it 'renders == operator' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) = = <a> HTML === == = == == #{''} HAML end it 'renders !== operator' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) <a> = = HTML == #{''} !== #{''} !=== !== = HAML end it 'leaves empty spaces after backslash' do assert_render(" a\n", '\ a') end it 'renders spaced - properly' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent)
foo
- bar
- baz
HTML %div foo .test - bar .test - baz HAML end describe 'inline operator' do it 'renders ! operator' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %span!#{''} %span! #{''} ! #{''} HAML end it 'renders & operator' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) <nyaa> <nyaa> <nyaa> HTML %span& #{''} %span&#{''} & #{''} HAML end it 'renders !, & operator right before a non-space character' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent)     !hello !hello HTML   \  !hello \!hello HAML end it 'renders &, ! operator inside a tag' do assert_render(<<-HTML.unindent, <<-HAML.unindent)   nbsp; nbsp; !hello hello hello HTML %span   %span  %span& nbsp; %span !hello %span!hello %span! hello HAML end it 'does not accept backslash operator' do assert_render(<<-'HTML'.unindent, <<-'HAML'.unindent) \ foo HTML %span\ foo HAML end it 'renders != operator' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML %span!= '' HAML end it 'renders !== operator' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML %span!==#{''} %span!== #{''} !==#{''} !== #{''} HAML end it 'renders &= operator' do assert_render(<<-HTML.unindent, <<-HAML.unindent) <nyaa> HTML %span&= '' HAML end it 'renders &== operator' do skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_render(<<-HTML.unindent, <<-'HAML'.unindent) = = <p> HTML &=== &== = &== #{'

'} HAML end it 'renders ~ operator' do assert_render(<<-HTML.unindent, <<-HAML.unindent, escape_html: false) 1 HTML %span~ 1 HAML end end describe 'string interpolation' do it { assert_render("\n", '#{}') } it { assert_render("1\n", '1#{}') } it { assert_render("12\n", '1#{2}') } it { assert_render("}1\n", '}#{1}') } it { assert_render("12\n", '#{1}2') } it { assert_render("12345\n", '1#{ "2#{3}4" }5') } it { assert_render("123456789\n", '#{1}2#{3}4#{5}6#{7}8#{9}') } it { assert_render(%Q{'"!@$%^&*|=1112\n}, %q{'"!@$%^&*|=#{1}1#{1}2}) } it { assert_render("あ1\n", 'あ#{1}') } it { assert_render("あいう\n", 'あ#{"い"}う') } it { assert_render("a<b>c\n", 'a#{""}c') } if RUBY_ENGINE != 'truffleruby' # escape is not working in truffleruby end end end haml-6.3.0/test/haml/engine/whitespace_test.rb000066400000000000000000000060171453526310700213400ustar00rootroot00000000000000describe Haml::Engine do include RenderHelper describe 'whitespace removal' do it 'removes outer whitespace by >' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ab c d e f HTML %span> a %span b %span c %span> d %span e %span f HAML end it 'removes top-level outer whitespaces with >' do assert_render(<<-HTML.unindent, <<-HAML.unindent) a
b HTML - if true a %br> b HAML end it 'removes top-level outer whitespaces with >' do assert_render(<<-HTML.unindent, <<-HAML.unindent) a
c HTML - if true a - else b %br> c HAML end it 'removes outer whitespace by > from inside of block' do assert_render(<<-HTML.unindent, <<-HAML.unindent) a b c HTML %span a - if true %span> b %span c HAML end it 'removes whitespaces inside block script' do assert_render(<<-HTML.unindent, <<-HAML.unindent, disable_capture: true) foofoo2bar HTML %span< = 2.times do = 'foo' %span> bar HAML end it 'removes whitespace inside script inside silent script' do assert_render(<<-HTML.unindent, <<-HAML.unindent)

foofoofoo
HTML .bar< - 3.times do = 'foo' HAML end it 'removes whitespace inside script recursively' do assert_render(<<-HTML.unindent, <<-HAML.unindent, disable_capture: true)
bar1bar1bar1bar12
HTML .foo< - 1.times do = 2.times do - 2.times do = 1.times do = 'bar' HAML end it 'does not remove whitespace after string interpolation' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent)
helloworld
HTML %div< #{'hello'} world HAML end it 'removes whitespace inside script inside silent script' do assert_render(<<-HTML.unindent, <<-HAML.unindent)
12
HTML .bar< - 1.times do = '1' = '2' HAML end it 'does not nuke internal recursively' do assert_render(%Q|
\nhello\n
|, <<-HAML.unindent) %div>< %span> hello HAML end it 'does not nuke inside script' do assert_render(%Q|
\nhello\n1
|, <<-HAML.unindent, disable_capture: true) %div>< = 1.times do %span> hello HAML end end end haml-6.3.0/test/haml/engine_test.rb000066400000000000000000002023661453526310700172110ustar00rootroot00000000000000$:.unshift __dir__ require_relative '../test_helper' class EngineTest < Haml::TestCase # A map of erroneous Haml documents to the error messages they should produce. # The error messages may be arrays; # if so, the second element should be the line number that should be reported for the error. # If this isn't provided, the tests will assume the line number should be the last line of the document. EXCEPTION_MAP = { "!!!\n a" => error(:illegal_nesting_header), "a\n b" => error(:illegal_nesting_plain), "/ a\n b" => error(:illegal_nesting_content), "% a" => error(:invalid_tag, '% a'), "%p a\n b" => error(:illegal_nesting_line, 'p'), "%p=" => error(:no_ruby_code, '='), "%p~" => error(:no_ruby_code, '~'), "~" => error(:no_ruby_code, '~'), "=" => error(:no_ruby_code, '='), "%p/\n a" => error(:illegal_nesting_self_closing), #":a\n b" => [error(:filter_not_defined, 'a'), 1], ":a= b" => error(:invalid_filter_name, 'a= b'), "." => error(:illegal_element), ".#" => error(:illegal_element), ".{} a" => error(:illegal_element), ".() a" => error(:illegal_element), ".= a" => error(:illegal_element), "%p..a" => error(:illegal_element), "%a/ b" => error(:self_closing_content), " %p foo" => error(:indenting_at_start), " %p foo" => error(:indenting_at_start), "- end" => error(:no_end), "%p{:a => 'b',\n:c => 'd'}/ e" => [error(:self_closing_content), 2], "%p{:a => 'b',\n:c => 'd'}=" => [error(:no_ruby_code, '='), 2], "%p.{:a => 'b',\n:c => 'd'} e" => [error(:illegal_element), 1], "%p{:a => 'b',\n:c => 'd',\n:e => 'f'}\n%p/ a" => [error(:self_closing_content), 4], "%p{:a => 'b',\n:c => 'd',\n:e => 'f'}\n- raise 'foo'" => ["foo", 4], "%p{:a => 'b',\n:c => raise('foo'),\n:e => 'f'}" => ["foo", 2], "%p{:a => 'b',\n:c => 'd',\n:e => raise('foo')}" => ["foo", 3], " \n\t\n %p foo" => [error(:indenting_at_start), 3], "\n\n %p foo" => [error(:indenting_at_start), 3], "%p\n foo\n foo" => [error(:inconsistent_indentation, "1 space", "2 spaces"), 3], "%p\n foo\n%p\n foo" => [error(:inconsistent_indentation, "1 space", "2 spaces"), 4], "%p\n\t\tfoo\n\tfoo" => [error(:inconsistent_indentation, "1 tab", "2 tabs"), 3], "%p\n foo\n foo" => [error(:inconsistent_indentation, "3 spaces", "2 spaces"), 3], "%p\n foo\n %p\n bar" => [error(:inconsistent_indentation, "3 spaces", "2 spaces"), 4], "%p\n :plain\n bar\n \t baz" => [error(:inconsistent_indentation, '" \t "', "2 spaces"), 4], "%p\n foo\n%p\n bar" => [error(:deeper_indenting, 2), 4], "%p\n foo\n %p\n bar" => [error(:deeper_indenting, 3), 4], "%p\n \tfoo" => [error(:cant_use_tabs_and_spaces), 2], "%p(" => error(:invalid_attribute_list, '"("'), "%p(foo=)" => error(:invalid_attribute_list, '"(foo=)"'), "%p(foo 'bar')" => error(:invalid_attribute_list, '"(foo \'bar\')"'), "%p(foo=\nbar)" => [error(:invalid_attribute_list, '"(foo="'), 1], "%p(foo 'bar'\nbaz='bang')" => [error(:invalid_attribute_list, '"(foo \'bar\'"'), 1], "%p(foo='bar'\nbaz 'bang'\nbip='bop')" => [error(:invalid_attribute_list, '"(foo=\'bar\' baz \'bang\'"'), 2], "%p{'foo' => 'bar' 'bar' => 'baz'}" => :compile, "%p{:foo => }" => :compile, "%p{=> 'bar'}" => :compile, "%p{'foo => 'bar'}" => error(:unbalanced_brackets), "%p{:foo => 'bar}" => error(:unbalanced_brackets), "%p{:foo => 'bar\"}" => error(:unbalanced_brackets), # Regression tests "foo\n\n\n bar" => [error(:illegal_nesting_plain), 4], "%p/\n\n bar" => [error(:illegal_nesting_self_closing), 3], "%p foo\n\n bar" => [error(:illegal_nesting_line, 'p'), 3], "/ foo\n\n bar" => [error(:illegal_nesting_content), 3], "!!!\n\n bar" => [error(:illegal_nesting_header), 3], "- raise 'foo'\n\n\n\nbar" => ["foo", 1], "= 'foo'\n-raise 'foo'" => ["foo", 2], "\n\n\n- raise 'foo'" => ["foo", 4], "%p foo |\n bar |\n baz |\nbop\n- raise 'foo'" => ["foo", 5], #"foo\n:ruby\n 1\n 2\n 3\n- raise 'foo'" => ["foo", 6], #"foo\n:erb\n 1\n 2\n 3\n- raise 'foo'" => ["foo", 6], "foo\n:plain\n 1\n 2\n 3\n- raise 'foo'" => ["foo", 6], "foo\n:plain\n 1\n 2\n 3\n4\n- raise 'foo'" => ["foo", 7], "foo\n:plain\n 1\n 2\n 3\#{''}\n- raise 'foo'" => ["foo", 6], "foo\n:plain\n 1\n 2\n 3\#{''}\n4\n- raise 'foo'" => ["foo", 7], "foo\n:plain\n 1\n 2\n \#{raise 'foo'}" => ["foo", 5], "= raise 'foo'\nfoo\nbar\nbaz\nbang" => ["foo", 1], "- case 1\n\n- when 1\n - raise 'foo'" => ["foo", 4], } User = Struct.new('User', :id) class CustomHamlClass < Struct.new(:id) def haml_object_ref "my_thing" end end CpkRecord = Struct.new('CpkRecord', :id) do def to_key [*self.id] unless id.nil? end end def use_test_tracing(options) unless options[:filename] # use caller method name as fake filename. useful for debugging i = -1 caller[i+=1] =~ /`(.+?)'/ until $1 and $1.index('test_') == 0 options[:filename] = "(#{$1})" end options end def render(text, options = {}, &block) options = use_test_tracing(options) super end def engine(text, options = {}) options = use_test_tracing(options) Haml::Template.new(haml_base.merge(options)) { text } end def setup @old_default_internal = Encoding.default_internal silence_warnings{Encoding.default_internal = nil} end def teardown silence_warnings{Encoding.default_internal = @old_default_internal} end def test_empty_render assert_equal "", render("") end def test_flexible_tabulation assert_haml_ugly("%p\n foo\n%q\n bar\n %a\n baz") assert_haml_ugly("%p\n\tfoo\n%q\n\tbar\n\t%a\n\t\tbaz") assert_haml_ugly("%p\n :plain\n \t \t bar\n baz") end def test_empty_render_should_remain_empty assert_equal('', render('')) end def test_attributes_should_render_correctly assert_equal("
", render(".atlantis{:style => 'ugly'}").chomp) end def test_css_id_as_attribute_should_be_appended_with_underscore assert_equal("
", render("#my_id{:id => '1'}").chomp) assert_equal("
", render("#my_id{:id => 1}").chomp) end def test_ruby_code_should_work_inside_attributes assert_equal("

foo

", render("%p{:class => 1+2} foo").chomp) end def test_class_attr_with_array assert_equal("

foo

\n", render("%p{:class => %w[a b]} foo")) # basic assert_equal("

foo

\n", render("%p.css{:class => %w[a b]} foo")) # merge with css assert_equal("

foo

\n", render("%p.css{:class => %w[css b]} foo")) # merge uniquely assert_equal("

foo

\n", render("%p{:class => [%w[a b], %w[c d]]} foo")) # flatten assert_equal("

foo

\n", render("%p{:class => [:a, :b] } foo")) # stringify # [INCOMPATIBILITY] Haml limits boolean attributes # assert_equal("

foo

\n", render("%p{:class => [nil, false] } foo")) # strip falsey assert_equal("

foo

\n", render("%p{:class => [nil, false] } foo")) # strip falsey assert_equal("

foo

\n", render("%p{:class => :a} foo")) # single stringify # [INCOMPATIBILITY] Haml limits boolean attributes # assert_equal("

foo

\n", render("%p{:class => false} foo")) # single falsey assert_equal("

foo

\n", render("%p{:class => false} foo")) # single falsey assert_equal("

foo

\n", render("%p(class='html'){:class => %w[a b]} foo")) # html attrs end def test_id_attr_with_array assert_equal("

foo

\n", render("%p{:id => %w[a b]} foo")) # basic assert_equal("

foo

\n", render("%p#css{:id => %w[a b]} foo")) # merge with css assert_equal("

foo

\n", render("%p{:id => [%w[a b], %w[c d]]} foo")) # flatten assert_equal("

foo

\n", render("%p{:id => [:a, :b] } foo")) # stringify # [INCOMPATIBILITY] Haml limits boolean attributes # assert_equal("

foo

\n", render("%p{:id => [nil, false] } foo")) # strip falsey assert_equal("

foo

\n", render("%p{:id => [nil, false] } foo")) # strip falsey assert_equal("

foo

\n", render("%p{:id => :a} foo")) # single stringify # [INCOMPATIBILITY] Haml limits boolean attributes # assert_equal("

foo

\n", render("%p{:id => false} foo")) # single falsey assert_equal("

foo

\n", render("%p{:id => false} foo")) # single falsey assert_equal("

foo

\n", render("%p(id='html'){:id => %w[a b]} foo")) # html attrs end def test_colon_in_class_attr assert_equal("

\n", render("%p.foo:bar/")) end def test_colon_in_id_attr assert_equal("

\n", render("%p#foo:bar/")) end def test_dynamic_attributes_with_no_content assert_haml_ugly(< "http://" + "haml.info"} HAML end def test_attributes_with_to_s assert_equal(<

HTML %p#foo{:id => 1+1} %p.foo{:class => 1+1} %p{:blaz => 1+1} %p{(1+1) => 1+1} HAML end def test_nil_should_render_empty_tag # [INCOMPATIBILITY] Haml limits boolean attributes # assert_equal("
", # render(".no_attributes{:nil => nil}").chomp) assert_equal("
", render(".no_attributes{:nil => nil}").chomp) end def test_strings_should_get_stripped_inside_tags assert_equal("
This should have no spaces in front of it
", render(".stripped This should have no spaces in front of it").chomp) end def test_one_liner_should_be_one_line assert_equal("

Hello

", render('%p Hello').chomp) end def test_one_liner_with_newline_shouldnt_be_one_line assert_haml_ugly('%p= "foo\nbar"') end def test_multi_render; skip engine = engine("%strong Hi there!") assert_equal("Hi there!\n", engine.render) assert_equal("Hi there!\n", engine.render) assert_equal("Hi there!\n", engine.render) end def test_interpolation assert_haml_ugly('%p Hello #{who}', locals: {who: 'World'}, escape_html: false) assert_haml_ugly("%p\n Hello \#{who}", locals: {who: 'World'}, escape_html: false) assert_haml_ugly('%p Hello #{who}', locals: {who: 'World'}, escape_html: true) assert_haml_ugly("%p\n Hello \#{who}", locals: {who: 'World'}, escape_html: true) end def test_interpolation_with_instance_var; skip # special interpolation scope = Object.new scope.instance_variable_set(:@who, 'World') assert_equal("

Hello World

\n", render('%p Hello #@who', scope: scope, escape_html: false)) assert_equal("

\n Hello World\n

\n", render("%p\n Hello \#@who", scope: scope, escape_html: false)) assert_equal("

Hello World

\n", render('%p Hello #@who', scope: scope, escape_html: true)) assert_equal("

\n Hello World\n

\n", render("%p\n Hello \#@who", scope: scope, escape_html: true)) end def test_interpolation_with_global; skip # special interpolation $global_var_for_testing = 'World' assert_equal("

Hello World

\n", render('%p Hello #$global_var_for_testing', escape_html: false)) assert_equal("

\n Hello World\n

\n", render("%p\n Hello \#$global_var_for_testing", escape_html: false)) assert_equal("

Hello World

\n", render('%p Hello #$global_var_for_testing', escape_html: true)) assert_equal("

\n Hello World\n

\n", render("%p\n Hello \#$global_var_for_testing", escape_html: true)) ensure $global_var_for_testing = nil end def test_interpolation_in_the_middle_of_a_string assert_equal("\"title 'Title'. \"\n", render("\"title '\#{\"Title\"}'. \"")) end def test_interpolation_with_instance_var_in_the_middle_of_a_string; skip # special interpolation scope = Object.new scope.instance_variable_set(:@title, 'Title') assert_equal("\"title 'Title'. \"\n", render("\"title '\#@title'. \"", :scope => scope)) end def test_interpolation_with_global_in_the_middle_of_a_string; skip # special interpolation $global_var_for_testing = 'Title' assert_equal("\"title 'Title'. \"\n", render("\"title '\#$global_var_for_testing'. \"")) ensure $global_var_for_testing = nil end def test_interpolation_at_the_beginning_of_a_line assert_haml_ugly('%p #{1 + 1}') assert_haml_ugly("%p\n \#{1 + 1}") end def test_interpolation_with_instance_var_at_the_beginning_of_a_line; skip # special interpolation scope = Object.new scope.instance_variable_set(:@foo, 2) assert_equal("

2

\n", render('%p #@foo', :scope => scope)) assert_equal("

\n 2\n

\n", render("%p\n \#@foo", :scope => scope)) end def test_escaped_interpolation assert_equal("

Foo & Bar & Baz

\n", render('%p& Foo #{"&"} Bar & Baz')) end def test_nil_tag_value_should_render_as_empty assert_equal("

\n", render("%p= nil")) end def test_tag_with_failed_if_should_render_as_empty assert_equal("

\n", render("%p= 'Hello' if false")) end def test_static_attributes_with_empty_attr assert_equal("\n", render("%img{:src => '/foo.png', :alt => ''}")) end def test_dynamic_attributes_with_empty_attr # [INCOMPATIBILITY] Haml limits boolean attributes # assert_equal("\n", render("%img{:width => nil, :src => '/foo.png', :alt => String.new}")) assert_equal("\n", render("%img{:width => nil, :src => '/foo.png', :alt => String.new}")) end def test_attribute_hash_with_newlines assert_haml_ugly("%p{:a => 'b',\n :c => 'd'} foop") assert_haml_ugly("%p{:a => 'b',\n :c => 'd'}\n foop") assert_haml_ugly("%p{:a => 'b',\n :c => 'd'}/") assert_haml_ugly("%p{:a => 'b',\n :c => 'd',\n :e => 'f'}") end def test_attr_hashes_not_modified hash = {:color => 'red'} assert_haml_ugly(< {:hash => hash})
HTML %div{hash} .special{hash} %div{hash} HAML assert_equal(hash, {:color => 'red'}) end def test_ugly_semi_prerendered_tags assert_equal(< true))

foo

foo

foo bar

foo bar

foo

HTML %p{:a => 1 + 1} %p{:a => 1 + 1} foo %p{:a => 1 + 1}/ %p{:a => 1 + 1}= "foo" %p{:a => 1 + 1}= "foo\\nbar" %p{:a => 1 + 1}~ "foo\\nbar" %p{:a => 1 + 1} foo HAML end def test_end_of_file_multiline assert_equal("

0

\n

1

\n

2

\n", render("- for i in (0...3)\n %p= |\n i |")) end def test_cr_newline assert_equal("

foo

\n

bar

\n

baz

\n

boom

\n", render("%p foo\r%p bar\r\n%p baz\n\r%p boom")) end def test_textareas; skip # script bug assert_equal("\n", render('%textarea= "Foo\n bar\n baz"')) assert_equal("
Foo
  bar
   baz
\n", render('%pre= "Foo\n bar\n baz"')) assert_equal("\n", render("%textarea #{'a' * 100}")) assert_equal("

\n \n

\n", render(<Foo bar baz
HTML %pre %code :preserve Foo bar baz HAML end def test_boolean_attributes # [INCOMPATIBILITY] Haml limits boolean attributes # assert_equal("

\n", # render("%p{:foo => 'bar', :bar => true, :baz => 'true'}", :format => :html4)) # assert_equal("

\n", # render("%p{:foo => 'bar', :bar => true, :baz => 'true'}", :format => :xhtml)) # # assert_equal("

\n", # render("%p{:foo => 'bar', :bar => false, :baz => 'false'}", :format => :html4)) # assert_equal("

\n", # render("%p{:foo => 'bar', :bar => false, :baz => 'false'}", :format => :xhtml)) assert_equal("

\n", render("%p{:foo => 'bar', :bar => true, :baz => 'true'}", :format => :html4)) assert_equal("

\n", render("%p{:foo => 'bar', :bar => true, :baz => 'true'}", :format => :xhtml)) assert_equal("

\n", render("%p{:foo => 'bar', :bar => false, :baz => 'false'}", :format => :html4)) assert_equal("

\n", render("%p{:foo => 'bar', :bar => false, :baz => 'false'}", :format => :xhtml)) end def test_nuke_inner_whitespace_in_loops assert_equal(<foobarbaz HTML %ul< - for str in %w[foo bar baz] = str HAML end def test_both_whitespace_nukes_work_together; skip # dynamic indentation assert_equal(<Foo Bar

RESULT %p %q><= "Foo\\nBar" SOURCE end def test_nil_option assert_equal("

\n", render('%p{:foo => "bar"}', :attr_wrapper => nil)) end def test_comment_with_crazy_nesting assert_equal(< 'te'+'st'} = "foo\\nbar" HAML end def test_whitespace_nuke_with_both_newlines; skip # script bug # runtime nuke assert_equal("

foo

\n", render('%p<= "\nfoo\n"')) assert_equal(<

foo

HTML %p %p<= "\\nfoo\\n" HAML end def test_whitespace_nuke_with_tags_and_else assert_haml_ugly(< foo

HTML %p foo = " " %a> HAML end def test_both_case_indentation_work_with_deeply_nested_code assert_haml_ugly(< true)) = capture_haml do foo HAML end def test_plain_equals_with_ugly assert_equal("foo\nbar\n", render(< true)) = "foo" bar HAML end def test_inline_if assert_equal(<One

Three

HTML - for name in ["One", "Two", "Three"] %p= name unless name == "Two" HAML end def test_end_with_method_call; skip # block script # silent script assert_equal(< 2|3|4 b-a-r

HTML %p = [1, 2, 3].map do |i| - i + 1 - end.join("|") = "bar".gsub(/./) do |s| - s + "-" - end.gsub(/-$/) do |s| - '' HAML end def test_silent_end_with_stuff; skip # silent script assert_equal(<hi!

HTML - if true %p hi! - end if "foo".gsub(/f/) do - "z" - end + "bar" HAML end def test_multiline_with_colon_after_filter assert_equal(< "Bar", | :b => "Baz" }[:a] | HAML assert_equal(< "Bar", | :b => "Baz" }[:a] | HAML end def test_multiline_in_filter assert_equal(< false) #foo{:class => ''} bar HAML end def test_escape_attrs_always; skip # attribute escape assert_equal(< :always))
bar
HTML #foo{:class => '"<>&"'} bar HAML end def test_escape_html html = < true)) &= "&" != "&" = "&" HAML assert_equal(html, render(< true)) &~ "&" !~ "&" ~ "&" HAML assert_equal(html, render(< true)) & \#{"&"} ! \#{"&"} \#{"&"} HAML assert_equal(html, render(< true)) &== \#{"&"} !== \#{"&"} == \#{"&"} HAML tag_html = <&

&

&

HTML assert_equal(tag_html, render(< true)) %p&= "&" %p!= "&" %p= "&" HAML assert_equal(tag_html, render(< true)) %p&~ "&" %p!~ "&" %p~ "&" HAML assert_equal(tag_html, render(< true)) %p& \#{"&"} %p! \#{"&"} %p \#{"&"} HAML assert_equal(tag_html, render(< true)) %p&== \#{"&"} %p!== \#{"&"} %p== \#{"&"} HAML end def test_new_attrs_with_hash assert_equal("\n", render('%a(href="#")')) end def test_silent_script_with_hyphen_case assert_equal("", render("- a = 'foo-case-bar-case'")) end def test_silent_script_with_hyphen_end assert_equal("", render("- a = 'foo-end-bar-end'")) end def test_silent_script_with_hyphen_end_and_block; skip # silent script silence_warnings do assert_equal(<foo-end

bar-end

HTML - ("foo-end-bar-end".gsub(/\\w+-end/) do |s| %p= s - end; nil) HAML end end def test_if_without_content_and_else assert_equal(<Foo\n", render('%a(href="#" rel="top") Foo')) assert_equal("Foo\n", render('%a(href="#") #{"Foo"}')) assert_equal("\n", render('%a(href="#\\"")')) end def test_case_assigned_to_var assert_equal(< true)) foo, HTML foo\#{"," if true} HAML end # HTML escaping tests def test_ampersand_equals_should_escape assert_haml_ugly("%p\n &= 'foo & bar'", :escape_html => false) end def test_ampersand_equals_inline_should_escape; skip # script bug assert_equal("

foo & bar

\n", render("%p&= 'foo & bar'", :escape_html => false)) end def test_ampersand_equals_should_escape_before_preserve; skip # script bug assert_equal("\n", render('%textarea&= "foo\nbar"', :escape_html => false)) end def test_bang_equals_should_not_escape assert_haml_ugly("%p\n != 'foo & bar'", :escape_html => true) end def test_bang_equals_inline_should_not_escape assert_equal("

foo & bar

\n", render("%p!= 'foo & bar'", :escape_html => true)) end def test_static_attributes_should_be_escaped; skip # attribute escape assert_equal("\n", render("%img.atlantis{:style => 'ugly&stupid'}")) assert_equal("
foo
\n", render(".atlantis{:style => 'ugly&stupid'} foo")) assert_equal("

foo

\n", render("%p.atlantis{:style => 'ugly&stupid'}= 'foo'")) assert_equal("

\n", render("%p.atlantis{:style => \"ugly\\nstupid\"}")) end def test_dynamic_attributes_should_be_escaped; skip # script bug assert_equal("\n", render("%img{:width => nil, :src => '&foo.png', :alt => String.new}")) assert_equal("

foo

\n", render("%p{:width => nil, :src => '&foo.png', :alt => String.new} foo")) assert_equal("
foo
\n", render("%div{:width => nil, :src => '&foo.png', :alt => String.new}= 'foo'")) assert_equal("\n", render("%img{:width => nil, :src => \"foo\\n.png\", :alt => String.new}")) end def test_string_double_equals_should_be_escaped assert_equal("

4&<

\n", render("%p== \#{2+2}&\#{'<'}", :escape_html => true)) assert_equal("

4&<

\n", render("%p== \#{2+2}&\#{'<'}", :escape_html => false)) end def test_escaped_inline_string_double_equals assert_equal("

4&<

\n", render("%p&== \#{2+2}&\#{'<'}", :escape_html => true)) assert_equal("

4&<

\n", render("%p&== \#{2+2}&\#{'<'}", :escape_html => false)) end def test_unescaped_inline_string_double_equals assert_equal("

4&<

\n", render("%p!== \#{2+2}&\#{'<'}", :escape_html => true)) assert_equal("

4&<

\n", render("%p!== \#{2+2}&\#{'<'}", :escape_html => false)) end def test_escaped_string_double_equals assert_haml_ugly("%p\n &== \#{2+2}&\#{'<'}", :escape_html => true) assert_haml_ugly("%p\n &== \#{2+2}&\#{'<'}", :escape_html => false) end def test_unescaped_string_double_equals assert_haml_ugly("%p\n !== \#{2+2}&\#{'<'}", :escape_html => true) assert_haml_ugly("%p\n !== \#{2+2}&\#{'<'}", :escape_html => false) end def test_string_interpolation_should_be_esaped assert_equal("

4&<

\n", render("%p \#{2+2}&\#{'<'}", :escape_html => true)) assert_equal("

4&<

\n", render("%p \#{2+2}&\#{'<'}", :escape_html => false)) end def test_escaped_inline_string_interpolation assert_equal("

4&<

\n", render("%p& \#{2+2}&\#{'<'}", :escape_html => true)) assert_equal("

4&<

\n", render("%p& \#{2+2}&\#{'<'}", :escape_html => false)) end def test_unescaped_inline_string_interpolation assert_equal("

4&<

\n", render("%p! \#{2+2}&\#{'<'}", :escape_html => true)) assert_equal("

4&<

\n", render("%p! \#{2+2}&\#{'<'}", :escape_html => false)) end def test_escaped_string_interpolation assert_haml_ugly("%p\n & \#{2+2}&\#{'<'}", :escape_html => true) assert_haml_ugly("%p\n & \#{2+2}&\#{'<'}", :escape_html => false) end def test_escaped_string_interpolation_with_no_space assert_equal("<br>\n", render('&#{"
"}')) assert_equal("<br>\n", render('%span&#{"
"}')) end def test_unescaped_string_interpolation assert_haml_ugly("%p\n ! \#{2+2}&\#{'<'}", :escape_html => true) assert_haml_ugly("%p\n ! \#{2+2}&\#{'<'}", :escape_html => false) end def test_unescaped_string_interpolation_with_no_space assert_equal("
\n", render('!#{"
"}')) assert_equal("
\n", render('%span!#{"
"}')) end def test_scripts_should_respect_escape_html_option assert_haml_ugly("%p\n = 'foo & bar'", :escape_html => true) assert_haml_ugly("%p\n = 'foo & bar'", :escape_html => false) end def test_inline_scripts_should_respect_escape_html_option; skip # escape html assert_equal("

foo & bar

\n", render("%p= 'foo & bar'", :escape_html => true)) assert_equal("

foo & bar

\n", render("%p= 'foo & bar'", :escape_html => false)) end def test_script_ending_in_comment_should_render_when_html_is_escaped assert_equal("foo&bar\n", render("= 'foo&bar' #comment", :escape_html => true)) end def test_script_with_if_shouldnt_output assert_equal(<foo

HTML %p= "foo" %p= "bar" if false HAML end # Options tests def test_filename_and_line; skip # options begin render("\n\n = abc", :filename => 'test', :line => 2) rescue Exception => e assert_kind_of Haml::SyntaxError, e assert_match(/test:4/, e.backtrace.first) end begin render("\n\n= 123\n\n= nil[]", :filename => 'test', :line => 2) rescue Exception => e assert_kind_of NoMethodError, e backtrace = e.backtrace backtrace.shift if rubinius? assert_match(/test:6/, backtrace.first) end end def test_stop_eval; skip # options assert_equal("", render("= 'Hello'", :suppress_eval => true)) assert_equal("", render("- haml_concat 'foo'", :suppress_eval => true)) assert_equal("
\n", render("#foo{:yes => 'no'}/", :suppress_eval => true)) assert_equal("
\n", render("#foo{:yes => 'no', :call => a_function() }/", :suppress_eval => true)) assert_equal("
\n", render("%div[1]/", :suppress_eval => true)) assert_equal("", render(":ruby\n Kernel.puts 'hello'", :suppress_eval => true)) end def test_doctypes assert_equal('', render('!!!', :format => :html5).strip) assert_equal('', render('!!! 5').strip) assert_equal('', render('!!! strict', :format => :xhtml).strip) assert_equal('', render('!!! frameset', :format => :xhtml).strip) assert_equal('', render('!!! mobile', :format => :xhtml).strip) assert_equal('', render('!!! basic', :format => :xhtml).strip) assert_equal('', render('!!! transitional', :format => :xhtml).strip) assert_equal('', render('!!!', :format => :xhtml).strip) assert_equal('', render('!!! strict', :format => :html4).strip) assert_equal('', render('!!! frameset', :format => :html4).strip) assert_equal('', render('!!! transitional', :format => :html4).strip) assert_equal('', render('!!!', :format => :html4).strip) end def test_attr_wrapper; skip # options assert_equal("

\n", render("%p{ :strange => 'attrs'}", :attr_wrapper => '*')) assert_equal("

\n", render("%p{ :escaped => 'quo\"te'}", :attr_wrapper => '"')) assert_equal("

\n", render("%p{ :escaped => 'quo\\'te'}", :attr_wrapper => '"')) assert_equal("

\n", render("%p{ :escaped => 'q\\'uo\"te'}", :attr_wrapper => '"')) assert_equal("\n", render("!!! XML", :attr_wrapper => '"', :format => :xhtml)) end def test_autoclose_option assert_equal("\n", render("%flaz{:foo => 'bar'}", :autoclose => ["flaz"])) assert_equal(< [/^flaz/])) HTML %flaz %flaznicate %flan HAML end def test_attrs_parsed_correctly; skip # attribute escape assert_equal("

biddly='bar => baz'>

\n", render("%p{'boom=>biddly' => 'bar => baz'}")) assert_equal("

\n", render("%p{'foo,bar' => 'baz, qux'}")) assert_equal("

\n", render("%p{ :escaped => \"quo\\nte\"}")) assert_equal("

\n", render("%p{ :escaped => \"quo\#{2 + 2}te\"}")) end def test_correct_parsing_with_brackets; skip # script bug assert_equal("

{tada} foo

\n", render("%p{:class => 'foo'} {tada} foo")) assert_equal("

deep {nested { things }}

\n", render("%p{:class => 'foo'} deep {nested { things }}")) assert_equal("

{a { d

\n", render("%p{{:class => 'foo'}, :class => 'bar'} {a { d")) assert_equal("

a}

\n", render("%p{:foo => 'bar'} a}")) foo = [] foo[0] = Struct.new('Foo', :id).new assert_equal("

New User]

\n", render("%p[foo[0]] New User]", :locals => {:foo => foo})) assert_equal("

New User]

\n", render("%p[foo[0], :prefix] New User]", :locals => {:foo => foo})) foo[0].id = 1 assert_equal("

New User]

\n", render("%p[foo[0]] New User]", :locals => {:foo => foo})) assert_equal("

New User]

\n", render("%p[foo[0], :prefix] New User]", :locals => {:foo => foo})) end def test_empty_attrs assert_haml_ugly("%p{ :attr => '' } empty") assert_haml_ugly("%p{ :attr => x } empty", :locals => {:x => ''}) end def test_nil_attrs skip '[INCOMPATIBILITY] Haml limits boolean attributes' assert_equal("

nil

\n", render("%p{ :attr => nil } nil")) assert_equal("

nil

\n", render("%p{ :attr => x } nil", :locals => {:x => nil})) end def test_nil_id_with_syntactic_id assert_equal("

nil

\n", render("%p#foo{:id => nil} nil")) assert_equal("

nil

\n", render("%p#foo{{:id => 'bar'}, :id => nil} nil")) assert_equal("

nil

\n", render("%p#foo{{:id => nil}, :id => 'bar'} nil")) end def test_nil_class_with_syntactic_class assert_equal("

nil

\n", render("%p.foo{:class => nil} nil")) assert_equal("

nil

\n", render("%p.bar.foo{:class => nil} nil")) assert_equal("

nil

\n", render("%p.foo{{:class => 'bar'}, :class => nil} nil")) assert_equal("

nil

\n", render("%p.foo{{:class => nil}, :class => 'bar'} nil")) end def test_locals assert_haml_ugly("%p= text", :locals => { :text => "Paragraph!" }) end def test_dynamic_attrs_shouldnt_register_as_literal_values assert_equal("

\n", render('%p{:a => "b#{1 + 1}c"}')) assert_equal("

\n", render("%p{:a => 'b' + (1 + 1).to_s + 'c'}")) end def test_dynamic_attrs_with_self_closed_tag assert_equal("\nc\n", render("%a{'b' => 1 + 1}/\n= 'c'\n")) end EXCEPTION_MAP.each do |key, value| define_method("test_exception (#{key.inspect})") do begin silence_warnings do render(key, :filename => "(test_exception (#{key.inspect}))") end rescue Exception => err value = [value] unless value.is_a?(Array) expected_message, line_no = value line_no ||= key.split("\n").length if expected_message == :compile assert_match(/(compile error|syntax error|unterminated string|expecting)/, err.message, "Line: #{key}") else assert_equal(expected_message, err.message, "Line: #{key}") end else assert(false, "Exception not raised for\n#{key}") end end end def test_exception_map skip EXCEPTION_MAP end def test_exception_line; skip # error render("a\nb\n!!!\n c\nd") rescue Haml::SyntaxError => e assert_equal("(test_exception_line):4", e.backtrace[0]) else assert(false, '"a\nb\n!!!\n c\nd" doesn\'t produce an exception') end def test_exception; skip # error render("%p\n hi\n %a= undefined\n= 12") rescue Exception => e skip backtrace = e.backtrace backtrace.shift if rubinius? assert_match("(test_exception):3", backtrace[0]) else # Test failed... should have raised an exception assert(false) end def test_compile_error; skip # error render("a\nb\n- fee)\nc") rescue Exception => e skip assert_match(/\(test_compile_error\):3:/i, e.message) assert_match(/(syntax error|expecting \$end)/i, e.message) else assert(false, '"a\nb\n- fee)\nc" doesn\'t produce an exception!') end def test_unbalanced_brackets; skip # error render('foo #{1 + 5} foo #{6 + 7 bar #{8 + 9}') rescue Haml::SyntaxError => e assert_equal(Haml::Error.message(:unbalanced_brackets), e.message) end def test_single_line_comments_are_interpolated; skip # comment assert_equal("\n", render('/ Hello #{1 + 1}')) end def test_single_line_comments_are_not_interpolated_with_suppress_eval; skip # comment assert_equal("\n", render('/ Hello #{1 + 1}', :suppress_eval => true)) end def test_single_line_comments_with_interpolation_dont_break_tabulation; skip # comment assert_equal("\nconcatted\n", render("/ Hello \#{1 + 1}\n- haml_concat 'concatted'")) end def test_balanced_conditional_comments assert_equal("\n", render("/[if !(IE 6)|(IE 7)] Bracket: ]")) end def test_downlevel_revealed_conditional_comments; skip assert_equal(" A comment \n", render("/![if !IE] A comment")) end def test_downlevel_revealed_conditional_comments_block assert_equal("\nA comment\n\n", render("/![if !IE]\n A comment")) end def test_local_assigns_dont_modify_class assert_haml_ugly("= foo", :locals => {:foo => 'bar'}) assert_nil(defined?(foo)) end def test_object_ref_with_nil_id; skip # object reference user = User.new assert_equal("

New User

\n", render("%p[user] New User", :locals => {:user => user})) end def test_object_ref_before_attrs user = User.new 42 assert_equal("

New User

\n", render_template("%p[user]{:style => 'width: 100px;'} New User", locals: { user: user })) end def test_object_ref_with_custom_haml_class custom = CustomHamlClass.new 42 assert_equal("

My Thing

\n", render_template("%p[custom]{:style => 'width: 100px;'} My Thing", locals: { custom: custom })) end def test_object_ref_with_multiple_ids cpk_record = CpkRecord.new([42,6,9]) assert_equal("

CPK Record

\n", render_template("%p[cpk_record]{:style => 'width: 100px;'} CPK Record", locals: { cpk_record: cpk_record })) end def test_non_literal_attributes assert_haml_ugly("%p{a2, a1, :a3 => 'baz'}", :locals => {:a1 => {:a1 => 'foo'}, :a2 => {:a2 => 'bar'}}) end def test_render_should_accept_a_binding_as_scope; skip string = "This is a string!" string.instance_variable_set(:@var, "Instance variable") b = string.instance_eval do var = "Local variable" # Silence unavoidable warning; Ruby doesn't know we're going to use this # later. nil if var binding end assert_haml_ugly("%p= upcase\n%p= @var\n%p= var", :scope => b) end def test_yield_should_work_with_binding; skip # options assert_equal("12\nFOO\n", render("= yield\n= upcase", :scope => "foo".instance_eval{binding}) { 12 }) end def test_yield_should_work_with_def_method; skip # def_method s = "foo" engine("= yield\n= upcase").def_method(s, :render) assert_equal("12\nFOO\n", s.render { 12 }) end def test_def_method_with_module; skip # def_method engine("= yield\n= upcase").def_method(String, :render_haml) assert_equal("12\nFOO\n", "foo".render_haml { 12 }) end def test_def_method_locals; skip # def_method obj = Object.new engine("%p= foo\n.bar{:baz => baz}= boom").def_method(obj, :render, :foo, :baz, :boom) assert_equal("

1

\n
3
\n", obj.render(:foo => 1, :baz => 2, :boom => 3)) end def test_render_proc_locals; skip # render_proc proc = engine("%p= foo\n.bar{:baz => baz}= boom").render_proc(Object.new, :foo, :baz, :boom) assert_equal("

1

\n
3
\n", proc[:foo => 1, :baz => 2, :boom => 3]) end def test_render_proc_with_binding; skip # render_proc assert_equal("FOO\n", engine("= upcase").render_proc("foo".instance_eval{binding}).call) end def test_haml_buffer_gets_reset_even_with_exception; skip # haml_buffer scope = Object.new render("- raise Haml::Error", :scope => scope) assert(false, "Expected exception") rescue Exception skip assert_nil(scope.send(:haml_buffer)) end def test_def_method_haml_buffer_gets_reset_even_with_exception; skip # def_method scope = Object.new engine("- raise Haml::Error").def_method(scope, :render) scope.render assert(false, "Expected exception") rescue Exception; skip assert_nil(scope.send(:haml_buffer)) end def test_render_proc_haml_buffer_gets_reset_even_with_exception; skip # render_proc scope = Object.new proc = engine("- raise Haml::Error").render_proc(scope) proc.call assert(false, "Expected exception") rescue Exception; skip assert_nil(scope.send(:haml_buffer)) end def test_ugly_true assert_equal("
\n
\n

hello world

\n
\n
\n", render("#outer\n #inner\n %p hello world", :ugly => true)) assert_equal("

#{'s' * 75}

\n", render("%p #{'s' * 75}", :ugly => true)) assert_equal("

#{'s' * 75}

\n", render("%p= 's' * 75", :ugly => true)) end def test_remove_whitespace_true assert_equal("

hello world

", render("#outer\n #inner\n %p hello world", :remove_whitespace => true)) assert_equal("

hello world

foo   bar\nbaz

", render(< true)) %p hello world %pre foo bar baz HAML assert_equal("
foo bar
", render('%div foo bar', :remove_whitespace => true)) end def test_auto_preserve_unless_ugly; skip # preserve assert_equal("
foo
bar
\n", render('%pre="foo\nbar"')) assert_equal("
foo\nbar
\n", render("%pre\n foo\n bar")) assert_equal("
foo\nbar
\n", render('%pre="foo\nbar"', :ugly => true)) assert_equal("
foo\nbar
\n", render("%pre\n foo\n bar", :ugly => true)) end def test_xhtml_output_option assert_haml_ugly("%p\n %br", :format => :xhtml) assert_haml_ugly("%a/", :format => :xhtml) end def test_arbitrary_output_option; skip # error assert_raises_message(Haml::Error, "Invalid output format :html1") do engine("%br", :format => :html1) end end def test_static_hashes assert_equal("
\n", render("%a{:b => 'a => b'}", :suppress_eval => true)) assert_equal("\n", render("%a{:b => 'a, b'}", :suppress_eval => true)) assert_equal("\n", render('%a{:b => "a\tb"}', :suppress_eval => true)) assert_equal("\n", render('%a{:b => "a\\#{foo}b"}', :suppress_eval => true)) assert_equal("\n", render("%a{:b => '#f00'}", :suppress_eval => true)) end def test_dynamic_hashes_with_suppress_eval; skip # options assert_equal("\n", render('%a{:b => "a #{1 + 1} b", :c => "d"}', :suppress_eval => true)) end def test_interpolates_instance_vars_in_attribute_values; skip # special interpolation scope = Object.new scope.instance_variable_set :@foo, 'bar' assert_haml_ugly('%a{:b => "a #@foo b"}', :scope => scope) end def test_utf8_attrs assert_equal("\n", render("%a{:href => 'héllo'}")) assert_equal("\n", render("%a(href='héllo')")) end # HTML 4.0 def test_html_has_no_self_closing_tags assert_haml_ugly("%p\n %br", :format => :html4) assert_haml_ugly("%br/", :format => :html4) end def test_html_renders_empty_node_with_closing_tag assert_equal "
\n", render(".foo", :format => :html4) end def test_html_doesnt_add_slash_to_self_closing_tags assert_equal "\n", render("%a/", :format => :html4) assert_equal "\n", render("%a{:foo => 1 + 1}/", :format => :html4) assert_equal "\n", render("%meta", :format => :html4) assert_equal "\n", render("%meta{:foo => 1 + 1}", :format => :html4) end def test_html_ignores_xml_prolog_declaration assert_equal "", render('!!! XML', :format => :html4) end def test_html_has_different_doctype assert_equal %{\n}, render('!!!', :format => :html4) end # because anything before the doctype triggers quirks mode in IE def test_xml_prolog_and_doctype_dont_result_in_a_leading_whitespace_in_html refute_match(/^\s+/, render("!!! xml\n!!!", :format => :html4)) end # HTML5 def test_html5_doctype assert_equal %{\n}, render('!!!', :format => :html5) end # HTML5 custom data attributes def test_html5_data_attributes_without_hyphenation; skip # hyphenate assert_equal("
\n", render("%div{:data => {:author_id => 123, :foo => 'bar', :biz => 'baz'}}", :hyphenate_data_attrs => false)) assert_equal("
\n", render("%div{:data => {:one_plus_one => 1+1}}", :hyphenate_data_attrs => false)) assert_equal("
\n", render(%{%div{:data => {:foo => %{Here's a "quoteful" string.}}}}, :hyphenate_data_attrs => false)) #' end def test_html5_data_attributes_with_hyphens assert_equal("
\n", render("%div{:data => {:foo_bar => 'blip'}}")) assert_equal("
\n", render("%div{:data => {:foo_bar => 'blip', :baz => 'bang'}}")) end def test_html5_arbitrary_hash_valued_attributes_with skip '[INCOMPATIBILITY] Haml supports hyphenation only for data attributes' assert_equal("
\n", render("%div{:aria => {:foo => 'blip'}}")) assert_equal("
\n", render("%div{:foo => {:baz => 'bang'}}")) end def test_arbitrary_attribute_hash_merging skip '[INCOMPATIBILITY] Haml supports hyphenation only for data attributes' assert_equal(%Q{
\n}, render(<<-HAML)) - h1 = {:aria => {:foo => :bar}} - h2 = {:baz => :qux} %a{h1, :aria => h2} HAML end def test_html5_data_attributes_with_nested_hash; skip # cyclic reference assert_equal("
\n", render(<<-HAML)) - hash = {:a => {:b => 'c'}} - hash[:d] = hash %div{:data => hash} HAML end def test_html5_data_attributes_with_nested_hash_and_without_hyphenation; skip # hyphenate assert_equal("
\n", render(<<-HAML, :hyphenate_data_attrs => false)) - hash = {:a => {:b => 'c'}} - hash[:d] = hash %div{:data => hash} HAML end def test_html5_data_attributes_with_multiple_defs; skip # hyphenate # Should always use the more-explicit attribute assert_equal("
\n", render("%div{:data => {:foo => 'first'}, 'data-foo' => 'second'}")) assert_equal("
\n", render("%div{'data-foo' => 'first', :data => {:foo => 'second'}}")) end def test_html5_data_attributes_with_attr_method; skip # runtime attribute obj = Object.new def obj.data_hash {:data => {:foo => "bar", :baz => "bang"}} end def obj.data_val {:data => "dat"} end assert_equal("
\n", render("%div{data_hash, :data => {:foo => 'blip', :brat => 'wurst'}}", scope: obj)) assert_equal("
\n", render("%div{data_hash, 'data-foo' => 'blip'}", scope: obj)) assert_equal("
\n", render("%div{data_hash, :data => 'dat'}", scope: obj)) assert_equal("
\n", render("%div{data_val, :data => {:foo => 'blip', :brat => 'wurst'}}", scope: obj)) end def test_html5_data_attributes_with_identical_attribute_values assert_equal("
\n", render("%div{:data => {:x => 50, :y => 50}}")) end def test_xml_doc_using_html5_format_and_mime_type; skip # mime_type assert_equal(< :html5, :mime_type => 'text/xml' }))
XML !!! XML %root %element/ %hr HAML end def test_xml_doc_using_html4_format_and_mime_type; skip # mime_type assert_equal(< :html4, :mime_type => 'text/xml' }))
XML !!! XML %root %element/ %hr HAML end # New attributes def test_basic_new_attributes assert_equal("bar\n", render("%a() bar")) assert_equal("bar\n", render("%a(href='foo') bar")) assert_equal("baz\n", render(%q{%a(b="c" c='d' d="e") baz})) end def test_new_attribute_ids; skip # object reference assert_equal("
\n", render("#foo(id='bar')")) assert_equal("
\n", render("#foo{:id => 'bar'}(id='baz')")) assert_equal("
\n", render("#foo(id='baz'){:id => 'bar'}")) foo = User.new(42) assert_equal("
\n", render("#foo(id='baz'){:id => 'bar'}[foo]", :locals => {:foo => foo})) assert_equal("
\n", render("#foo(id='baz')[foo]{:id => 'bar'}", :locals => {:foo => foo})) assert_equal("
\n", render("#foo[foo](id='baz'){:id => 'bar'}", :locals => {:foo => foo})) assert_equal("
\n", render("#foo[foo]{:id => 'bar'}(id='baz')", :locals => {:foo => foo})) end def test_new_attribute_classes; skip # object reference assert_equal("
\n", render(".foo(class='bar')")) assert_equal("
\n", render(".foo{:class => 'bar'}(class='baz')")) assert_equal("
\n", render(".foo(class='baz'){:class => 'bar'}")) foo = User.new(42) assert_equal("
\n", render(".foo(class='baz'){:class => 'bar'}[foo]", :locals => {:foo => foo})) assert_equal("
\n", render(".foo[foo](class='baz'){:class => 'bar'}", :locals => {:foo => foo})) assert_equal("
\n", render(".foo[foo]{:class => 'bar'}(class='baz')", :locals => {:foo => foo})) end def test_dynamic_new_attributes assert_haml_ugly("%a(href=foo) bar", :locals => {:foo => 12}) assert_haml_ugly("%a(b=b c='13' d=d) bar", :locals => {:b => 12, :d => 14}) end def test_new_attribute_interpolation assert_haml_ugly('%a(href="1#{1 + 1}") bar') assert_haml_ugly(%q{%a(href='2: #{1 + 1}, 3: #{foo}') bar}, :locals => {:foo => 3}) assert_haml_ugly('%a(href="1\#{1 + 1}") bar') end def test_truthy_new_attributes; skip # xhtml assert_equal("bar\n", render("%a(href) bar", :format => :xhtml)) assert_equal("bar\n", render("%a(href bar='baz') bar", :format => :html5)) assert_equal("bar\n", render("%a(href=true) bar")) assert_equal("bar\n", render("%a(href=false) bar")) end def test_new_attribute_parsing; skip # attribute escape assert_equal("bar\n", render("%a(a2=b2) bar", :locals => {:b2 => 'b2'})) assert_equal(%Q{bar\n}, render(%q{%a(a="#{'foo"bar'}") bar})) #' assert_equal(%Q{bar\n}, render(%q{%a(a="#{"foo'bar"}") bar})) #' assert_equal(%Q{bar\n}, render(%q{%a(a='foo"bar') bar})) assert_equal(%Q{bar\n}, render(%q{%a(a="foo'bar") bar})) assert_equal("bar\n", render("%a(a:b='foo') bar")) assert_equal("bar\n", render("%a(a = 'foo' b = 'bar') bar")) assert_equal("bar\n", render("%a(a = foo b = bar) bar", :locals => {:foo => 'foo', :bar => 'bar'})) assert_equal("(b='bar')\n", render("%a(a='foo')(b='bar')")) assert_equal("baz\n", render("%a(a='foo)bar') baz")) assert_equal("baz\n", render("%a( a = 'foo' ) baz")) end def test_new_attribute_escaping; skip # attribute escape assert_equal(%Q{bar\n}, render(%q{%a(a="foo \" bar") bar})) assert_equal(%Q{bar\n}, render(%q{%a(a="foo \\\\\" bar") bar})) assert_equal(%Q{bar\n}, render(%q{%a(a='foo \' bar') bar})) assert_equal(%Q{bar\n}, render(%q{%a(a='foo \\\\\' bar') bar})) assert_equal(%Q{bar\n}, render(%q{%a(a="foo \\\\ bar") bar})) assert_equal(%Q{bar\n}, render(%q{%a(a="foo \#{1 + 1} bar") bar})) end def test_multiline_new_attribute assert_haml_ugly("%a(a='b'\n c='d') bar") assert_haml_ugly("%a(a='b' b='c'\n c='d' d=e\n e='f' f='j') bar", :locals => {:e => 'e'}) end def test_new_and_old_attributes assert_haml_ugly("%a(a='b'){:c => 'd'} bar") assert_haml_ugly("%a{:c => 'd'}(a='b') bar") assert_haml_ugly("%a(c='d'){:a => 'b'} bar") assert_haml_ugly("%a{:a => 'b'}(c='d') bar") # Old-style always takes precedence over new-style, # because theoretically old-style could have arbitrary end-of-method-call syntax. assert_haml_ugly("%a{:a => 'b'}(a='d') bar") assert_haml_ugly("%a(a='d'){:a => 'b'} bar") assert_haml_ugly("%a{:a => 'b',\n:b => 'c'}(c='d'\nd='e') bar") locals = {:b => 'b', :d => 'd'} assert_haml_ugly("%p{:a => b}(c=d)", :locals => locals) assert_haml_ugly("%p(a=b){:c => d}", :locals => locals) end # Ruby Multiline def test_silent_ruby_multiline assert_equal(<foo

HTML - foo = ["bar", "baz", "bang"] = foo.join(", ") %p foo HAML end def test_loud_ruby_multiline assert_equal(<foo

bar

HTML = ["bar", "baz", "bang"].join(", ") %p foo %p bar HAML end def test_ruby_multiline_with_punctuated_methods_is_continuation assert_equal(<foo

bar

HTML = ["bar", " ".strip, "".empty?, "bang"].join(", ") %p foo %p bar HAML end def test_ruby_character_literals_are_not_continuation html = ",\n,\n

foo

\n" assert_equal(html, render(<foo

bar

HTML &= ["bar<", "baz", "bang"].join(", ") %p foo %p bar HAML end def test_unescaped_loud_ruby_multiline assert_equal(< true)) bar<, baz, bang

foo

bar

HTML != ["bar<", "baz", "bang"].join(", ") %p foo %p bar HAML end def test_flattened_loud_ruby_multiline assert_equal(<bar baz bang

foo

bar

HTML ~ "
" + ["bar",
             "baz",
             "bang"].join("\\n") + "
" %p foo %p bar HAML end def test_loud_ruby_multiline_with_block; skip # block script assert_equal(<foo

bar

HTML = ["bar", "baz", "bang"].map do |str| - str.gsub("ba", "fa") %p foo %p bar HAML end def test_silent_ruby_multiline_with_block assert_equal(<foo

bar

HTML - ["bar", "baz", "bang"].map do |str| = str.gsub("ba", "fa") %p foo %p bar HAML end def test_ruby_multiline_in_tag assert_equal(<foo, bar, baz

foo

bar

HTML %p= ["foo", "bar", "baz"].join(", ") %p foo %p bar HAML end def test_escaped_ruby_multiline_in_tag; skip # script bug assert_equal(<foo<, bar, baz

foo

bar

HTML %p&= ["foo<", "bar", "baz"].join(", ") %p foo %p bar HAML end def test_unescaped_ruby_multiline_in_tag assert_equal(< true))

foo<, bar, baz

foo

bar

HTML %p!= ["foo<", "bar", "baz"].join(", ") %p foo %p bar HAML end def test_ruby_multiline_with_normal_multiline assert_equal(<foo

bar

HTML = "foo" + | "bar" + | ["bar", | "baz", "bang"].join(", ") %p foo %p bar HAML end def test_ruby_multiline_after_filter assert_equal(<foo

bar

HTML :plain foo bar = ["bar", "baz", "bang"].join(", ") %p foo %p bar HAML end # Encodings def test_utf_8_bom; # encoding assert_equal <

baz

HTML \xEF\xBB\xBF.foo %p baz HAML end def test_default_encoding assert_equal(Encoding.find("utf-8"), render(< "ascii-8bit"))

bâr

föö

HTML %p bâr %p föö HAML end def test_encoding_error # encoding render("foo\nbar\nb\xFEaz".dup.force_encoding("utf-8")) assert(false, "Expected exception") rescue Haml::Error => e assert_equal(3, e.line) assert_match(/Invalid .* character/, e.message) end def test_ascii_incompatible_encoding_error; skip # encoding template = "foo\nbar\nb_z".encode("utf-16le") template[9] = "\xFE".force_encoding("utf-16le") render(template) assert(false, "Expected exception") rescue Haml::Error => e assert_equal(3, e.line) assert_match(/Invalid .* character/, e.message) end def test_same_coding_comment_as_encoding assert_renders_encoded(<bâr

föö

HTML -# coding: utf-8 %p bâr %p föö HAML end def test_coding_comments; skip # encoding assert_valid_encoding_comment("-# coding: ibm866") assert_valid_encoding_comment("-# CodINg: IbM866") assert_valid_encoding_comment("-#coding:ibm866") assert_valid_encoding_comment("-# CodINg= ibm866") assert_valid_encoding_comment("-# foo BAR FAOJcoding: ibm866") assert_valid_encoding_comment("-# coding: ibm866 ASFJ (&(&#!$") assert_valid_encoding_comment("-# -*- coding: ibm866") assert_valid_encoding_comment("-# coding: ibm866 -*- coding: blah") assert_valid_encoding_comment("-# -*- coding: ibm866 -*-") assert_valid_encoding_comment("-# -*- encoding: ibm866 -*-") assert_valid_encoding_comment('-# -*- coding: "ibm866" -*-') assert_valid_encoding_comment("-#-*-coding:ibm866-*-") assert_valid_encoding_comment("-#-*-coding:ibm866-*-") assert_valid_encoding_comment("-# -*- foo: bar; coding: ibm866; baz: bang -*-") assert_valid_encoding_comment("-# foo bar coding: baz -*- coding: ibm866 -*-") assert_valid_encoding_comment("-# -*- coding: ibm866 -*- foo bar coding: baz") end def test_different_coding_than_system; skip # encoding assert_renders_encoded(<тАЬ

HTML %p тАЬ HAML end def test_block_spacing begin assert render(<<-HAML) - foo = ["bar", "baz", "kni"] - foo.each do | item | = item HAML rescue ::SyntaxError flunk("Should not have raised syntax error") end end def test_tracing; skip # options result = render('%p{:class => "hello"}', :trace => true, :filename => 'foo').strip assert_equal "

", result end private def assert_valid_encoding_comment(comment) assert_renders_encoded(<ЖЛЫ

тАЬ

HTML #{comment} %p ЖЛЫ %p тАЬ HAML end def assert_renders_encoded(html, haml) result = render(haml) assert_encoded_equal html, result end def assert_encoded_equal(expected, actual) assert_equal expected.encoding, actual.encoding assert_equal expected, actual end end haml-6.3.0/test/haml/erb/000077500000000000000000000000001453526310700151175ustar00rootroot00000000000000haml-6.3.0/test/haml/erb/_av_partial_1.erb000066400000000000000000000004431453526310700203130ustar00rootroot00000000000000

This is a pretty complicated partial

It has several nested partials,

    <% 5.times do %>
  • Partial: <% @nesting = 5 %> <%= render :partial => 'erb/av_partial_2' %> <% end %>
haml-6.3.0/test/haml/erb/_av_partial_2.erb000066400000000000000000000003651453526310700203170ustar00rootroot00000000000000<% @nesting -= 1 %>

This is a crazy deep-nested partial.

Nesting level <%= @nesting %>

<% if @nesting > 0 %> <%= render :partial => 'erb/av_partial_2' %> <% end %>
haml-6.3.0/test/haml/erb/action_view.erb000066400000000000000000000042331453526310700201220ustar00rootroot00000000000000 Hampton Catlin Is Totally Awesome

This is very much like the standard template, except that it has some ActionView-specific stuff. It's only used for benchmarking.

<%= render :partial => 'erb/av_partial_1' %>
Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! <%= 1 + 9 + 8 + 2 %> <%# numbers should work and this should be ignored %>
<% 120.times do |number| -%> <%= number %> <% end -%>
<%= " Quotes should be loved! Just like people!" %>
Wow.

<%= "Holy cow " + "multiline " + "tags! " + "A pipe (|) even!" %> <%= [1, 2, 3].collect { |n| "PipesIgnored|" } %> <%= [1, 2, 3].collect { |n| n.to_s }.join("|") %>

<% foo = String.new foo << "this" foo << " shouldn't" foo << " evaluate" %> <%= foo + "but now it should!" %> <%# Woah crap a comment! %>
    <% ('a'..'f').each do |a|%>
  • <%= a %> <% end %>
    <%= @should_eval = "with this text" %>
    <%= [ 104, 101, 108, 108, 111 ].map do |byte| byte.chr end %> haml-6.3.0/test/haml/erb/standard.erb000066400000000000000000000037171453526310700174210ustar00rootroot00000000000000 Hampton Catlin Is Totally Awesome
    Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! <%= 1 + 9 + 8 + 2 %> <%# numbers should work and this should be ignored %>
    <% 120.times do |number| -%> <%= number %> <% end -%>
    <%= " Quotes should be loved! Just like people!" %>
    Wow.

    <%= "Holy cow " + "multiline " + "tags! " + "A pipe (|) even!" %> <%= [1, 2, 3].collect { |n| "PipesIgnored|" }.join %> <%= [1, 2, 3].collect { |n| n.to_s }.join("|") %>

    <% bar = 17 %>
    <% foo = String.new foo << "this" foo << " shouldn't" foo << " evaluate" %> <%= foo + "but now it should!" %> <%# Woah crap a comment! %>
      <% ('a'..'f').each do |a|%>
    • <%= a %>
    • <% end %>
      <%= @should_eval = "with this text" %>
      <%= "foo".each_line do |line| nil end %> haml-6.3.0/test/haml/error_test.rb000066400000000000000000000026641453526310700170740ustar00rootroot00000000000000describe Haml::Engine do describe 'Error' do it 'raises an error when Haml::Parser is used independently' do assert_raises(Haml::Error) do Haml::Parser.new({}).call("%body\n %div\n %p") end end end describe 'SyntaxError' do it 'raises on runtime' do code = Haml::Engine.new.call(" %a") assert_raises(Haml::SyntaxError) do eval code end end it 'returns error with lines before error' do code = Haml::Engine.new.call("\n\n %a") begin eval code rescue Haml::SyntaxError => e assert_equal(2, e.line) end end describe 'Haml v1 syntax' do it 'returns an error with proper line number' do code = Haml::Engine.new.call(<<-HAML.unindent) %span - if true %div{ data: { hello: 'world', } } HAML begin eval code rescue Haml::SyntaxError => e assert_equal(3, e.line) end end end end describe 'FilterNotFound' do it 'raises on runtime' do code = Haml::Engine.new.call(":k0kubun") assert_raises(Haml::FilterNotFound) do eval code end end it 'returns error with lines before error' do code = Haml::Engine.new.call("\n\n:k0kubun") begin eval code rescue Haml::FilterNotFound => e assert_equal(2, e.line) end end end end haml-6.3.0/test/haml/filters/000077500000000000000000000000001453526310700160175ustar00rootroot00000000000000haml-6.3.0/test/haml/filters/cdata_test.rb000066400000000000000000000007671453526310700204710ustar00rootroot00000000000000describe Haml::Filters do include RenderHelper describe '#compile' do it 'renders cdata' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :cdata foo bar HAML end it 'parses string interpolation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) bar ]]> HTML :cdata foo #{'<&>'} bar HAML end end end haml-6.3.0/test/haml/filters/coffee_test.rb000066400000000000000000000025321453526310700206340ustar00rootroot00000000000000describe Haml::Filters do include RenderHelper describe '#compile' do it 'renders coffee filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :coffee foo = -> alert('hello') HAML end it 'renders coffeescript filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :coffeescript foo = -> alert('hello') HAML end it 'renders coffeescript filter' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) HTML :coffee foo = -> alert("#{'<&>'}") HAML end end unless /java/ === RUBY_PLATFORM # execjs is not working with Travis JRuby environment end haml-6.3.0/test/haml/filters/css_test.rb000066400000000000000000000012031453526310700201670ustar00rootroot00000000000000describe Haml::Filters do include RenderHelper describe '#compile' do it 'renders css' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :css .foo { width: 100px; } HAML end it 'parses string interpolation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :css .foo { content: "#{'<&>'}"; } HAML end end end haml-6.3.0/test/haml/filters/erb_test.rb000066400000000000000000000004761453526310700201620ustar00rootroot00000000000000describe Haml::Filters do include RenderHelper describe '#compile' do it 'renders erb filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) ok HTML :erb <% if true %> ok <% else %> ng <% end %> HAML end end end haml-6.3.0/test/haml/filters/javascript_test.rb000066400000000000000000000031341453526310700215520ustar00rootroot00000000000000describe Haml::Filters do include RenderHelper describe '#compile' do it 'just renders script tag for empty filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) before after HTML before :javascript after HAML end it 'compiles javascript filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) before after HTML before :javascript alert('hello'); after HAML end it 'accepts illegal indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :javascript if { alert('hello'); } :javascript if { alert('hello'); } HAML end it 'accepts illegal indentation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :javascript if { alert('a'); } HAML end it 'parses string interpolation' do assert_render(<<-HTML.unindent, <<-HAML.unindent) HTML :javascript var a = "#{'<&>'}"; HAML end end end haml-6.3.0/test/haml/filters/markdown_test.rb000066400000000000000000000017721453526310700212340ustar00rootroot00000000000000describe Haml::Filters do include RenderHelper describe '#compile' do it 'renders markdown filter' do if /java/ === RUBY_PLATFORM && !system('which pandoc > /dev/null') skip 'pandoc is required to test :markdown filter' end assert_render(<<-HTML.unindent, <<-HAML.unindent)

      Haml

      Yet another haml implementation

      HTML :markdown # Haml Yet another haml implementation HAML end it 'renders markdown filter with string interpolation' do if /java/ === RUBY_PLATFORM && !system('which pandoc > /dev/null') skip 'pandoc is required to test :markdown filter' end assert_render(<<-HTML.unindent, <<-'HAML'.unindent)

      <&> Yet another haml implementation

      HTML - project = '' :markdown # #{project} #{'<&>'} Yet another haml implementation HAML end end end haml-6.3.0/test/haml/filters/plain_test.rb000066400000000000000000000010011453526310700204760ustar00rootroot00000000000000describe Haml::Filters do include RenderHelper describe '#compile' do it 'does not escape content without interpolation' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) '}") end end if RUBY_ENGINE != 'truffleruby' # truffleruby does not implement Ripper.lex class ErbFilterTest < Haml::TestCase test "multiline expressions should work" do; skip assert_haml_ugly(%Q{:erb\n <%= "foo" +\n "bar" +\n "baz" %>}) end test "should evaluate in the same context as Haml" do haml = "- foo = 'bar'\n:erb\n <%= foo %>" html = "bar\n\n" assert_equal(html, render(haml)) end test "should use Rails's XSS safety features" do; skip assert_equal("<img>\n", render(":erb\n <%= '' %>")) assert_equal("\n", render(":erb\n <%= ''.html_safe %>")) end end class JavascriptFilterTest < Haml::TestCase test "should interpolate" do; skip scope = Object.new.instance_eval {foo = "bar"; nil if foo; binding} haml = ":javascript\n \#{foo}" html = render(haml, :scope => scope) assert_match(/bar/, html) end test "should never HTML-escape non-interpolated ampersands" do; skip html = "\n" haml = %Q{:javascript\n & < > \#{"&"}} assert_equal(html, render(haml, :escape_html => true)) end test "should not include type in HTML 5 output" do html = "\n" haml = ":javascript\n foo bar" assert_equal(html, render(haml, :format => :html5)) end test "should always include CDATA when format is xhtml" do html = "\n" haml = ":javascript\n foo bar" assert_equal(html, render(haml, :format => :xhtml, :cdata => false)) end test "should omit CDATA when cdata option is false" do html = "\n" haml = ":javascript\n foo bar" assert_equal(html, render(haml, :format => :html5, :cdata => false)) end test "should include CDATA when cdata option is true" do; skip html = "\n" haml = ":javascript\n foo bar" assert_equal(html, render(haml, :format => :html5, :cdata => true)) end test "should default to no CDATA when format is html5" do haml = ":javascript\n foo bar" out = render(haml, :format => :html5) refute_match('//', out) end end class CSSFilterTest < Haml::TestCase test "should wrap output in CDATA and a CSS tag when output is XHTML" do html = "\n" haml = ":css\n foo" assert_equal(html, render(haml, :format => :xhtml)) end test "should not include type in HTML 5 output" do html = "\n" haml = ":css\n foo bar" assert_equal(html, render(haml, :format => :html5)) end test "should always include CDATA when format is xhtml" do html = "\n" haml = ":css\n foo bar" assert_equal(html, render(haml, :format => :xhtml, :cdata => false)) end test "should omit CDATA when cdata option is false" do html = "\n" haml = ":css\n foo bar" assert_equal(html, render(haml, :format => :html5, :cdata => false)) end test "should include CDATA when cdata option is true" do; skip html = "\n" haml = ":css\n foo bar" assert_equal(html, render(haml, :format => :html5, :cdata => true)) end test "should default to no CDATA when format is html5" do haml = ":css\n foo bar" out = render(haml, :format => :html5) refute_match('', out) end end class CDATAFilterTest < Haml::TestCase test "should wrap output in CDATA tag" do html = "\n" haml = ":cdata\n foo" assert_equal(html, render(haml)) end end class EscapedFilterTest < Haml::TestCase test "should escape ampersands" do html = "&\n" haml = ":escaped\n &" assert_equal(html, render(haml)) end end class RubyFilterTest < Haml::TestCase test "can write to haml_io" do; skip haml = ":ruby\n haml_io.puts 'hello'\n" html = "hello\n" assert_equal(html, render(haml)) end test "haml_io appends to output" do; skip haml = "hello\n:ruby\n haml_io.puts 'hello'\n" html = "hello\nhello\n" assert_equal(html, render(haml)) end test "can create local variables" do; skip haml = ":ruby\n a = 7\n=a" html = "7\n" assert_equal(html, render(haml)) end end haml-6.3.0/test/haml/gemfiles/000077500000000000000000000000001453526310700161425ustar00rootroot00000000000000haml-6.3.0/test/haml/gemfiles/.bundle/000077500000000000000000000000001453526310700174715ustar00rootroot00000000000000haml-6.3.0/test/haml/gemfiles/.bundle/config000066400000000000000000000000071453526310700206560ustar00rootroot00000000000000--- {} haml-6.3.0/test/haml/gemfiles/Gemfile.rails-4.0.x000066400000000000000000000002461453526310700213150ustar00rootroot00000000000000source "https://rubygems.org" if ENV['TRAVIS'] platform :mri_21 do gem 'coveralls', require: false end end gem 'rails', '~> 4.0.0' gemspec :path => '../..' haml-6.3.0/test/haml/gemfiles/Gemfile.rails-4.1.x000066400000000000000000000001201453526310700213050ustar00rootroot00000000000000source "https://rubygems.org" gem 'rails', '~> 4.1.0' gemspec :path => '../..' haml-6.3.0/test/haml/gemfiles/Gemfile.rails-4.2.x000066400000000000000000000001201453526310700213060ustar00rootroot00000000000000source "https://rubygems.org" gem 'rails', '~> 4.2.0' gemspec :path => '../..' haml-6.3.0/test/haml/haml-spec/000077500000000000000000000000001453526310700162205ustar00rootroot00000000000000haml-6.3.0/test/haml/haml-spec/LICENSE000066400000000000000000000007441453526310700172320ustar00rootroot00000000000000 DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 Copyright (C) 2004 Sam Hocevar Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. haml-6.3.0/test/haml/haml-spec/README.md000066400000000000000000000102231453526310700174750ustar00rootroot00000000000000# Haml Spec # Haml Spec provides a basic suite of tests for Haml interpreters. It is intented for developers who are creating or maintaining an implementation of the [Haml](http://haml-lang.com) markup language. At the moment, there are test runners for the [original Haml](http://github.com/nex3/haml) in Ruby, [Lua Haml](http://github.com/norman/lua-haml) and the [Text::Haml](http://github.com/vti/text-haml) Perl port. Support for other versions of Haml will be added if their developers/maintainers are interested in using it. ## The Tests ## The tests are kept in JSON format for portability across languages. Each test is a JSON object with expected input, output, local variables and configuration parameters (see below). The test suite only provides tests for features which are portable, therefore no tests for script are provided, nor for external filters such as :markdown or :textile. The one major exception to this are the tests for interpolation, which you may need to modify with a regular expression to run under PHP or Perl, which require a sigil before variable names. These tests are included despite being less than 100% portable because interpolation is an important part of Haml and can be tricky to implement. These tests are flagged as "optional" so that you can avoid running them if your implementation of Haml will not support this feature. ## Running the Tests ## ### Ruby ### The Ruby test runner uses minitest, the same as the Ruby Haml implementation. To run the tests you probably only need to install `haml`, `minitest` and possibly `ruby` if your platform doesn't come with it by default. If you're using Ruby 1.8.x, you'll also need to install `json`: sudo gem install haml sudo gem install minitest # for Ruby 1.8.x; check using "ruby --version" if unsure sudo gem install json Then, running the Ruby test suite is easy: ruby ruby_haml_test.rb At the moment, running the tests with Ruby 1.8.7 fails because of issues with the JSON library. Please use 1.9.2 until this is resolved. ### Lua ### The Lua test depends on [Penlight](http://stevedonovan.github.com/Penlight/), [Telescope](http://github.com/norman/telescope), [jason4lua](http://json.luaforge.net/), and [Lua Haml](http://github.com/norman/lua-haml). Install and run `tsc lua_haml_spec.lua`. ### Getting it ### You can access the [Git repository](http://github.com/norman/haml-spec) at: git://github.com/norman/haml-spec.git Patches are *very* welcome, as are test runners for your Haml implementation. As long as any test you add run against Ruby Haml and are not redundant, I'll be very happy to add them. ### Test JSON format ### "test name" : { "haml" : "haml input", "html" : "expected html output", "result" : "expected test result", "locals" : "local vars", "config" : "config params", "optional" : true|false } * test name: This should be a *very* brief description of what's being tested. It can be used by the test runners to name test methods, or to exclude certain tests from being run. * haml: The Haml code to be evaluated. Always required. * html: The HTML output that should be generated. Required unless "result" is "error". * result: Can be "pass" or "error". If it's absent, then "pass" is assumed. If it's "error", then the goal of the test is to make sure that malformed Haml code generates an error. * locals: An object containing local variables needed for the test. * config: An object containing configuration parameters used to run the test. The configuration parameters should be usable directly by Ruby's Haml with no modification. If your implementation uses config parameters with different names, you may need to process them to make them match your implementation. If your implementation has options that do not exist in Ruby's Haml, then you should add tests for this in your implementation's test rather than here. * optional: whether or not the test is optional ## License ## This project is released under the [WTFPL](http://sam.zoy.org/wtfpl/) in order to be as usable as possible in any project, commercial or free. ## Author ## [Norman Clarke](mailto:norman@njclarke.com) haml-6.3.0/test/haml/haml-spec/Rakefile000066400000000000000000000045501453526310700176710ustar00rootroot00000000000000$:.unshift File.expand_path('../../lib', __FILE__) require 'yaml' require 'unindent' require 'open-uri' def escape_name(name, replacer) name.gsub(/[\s\-\(\)\.\.+'\/<>&=~\!]+/, replacer) end def generate_spec(mode) spec = <<-SPEC.unindent require "minitest/autorun" require "haml" require "haml" # This is a spec converted by haml-spec. # See: https://github.com/haml/haml-spec class #{mode.capitalize}Test < Minitest::Test HAML_DEFAULT_OPTIONS = { ugly: #{mode == :ugly}, escape_html: true }.freeze HAMLIT_DEFAULT_OPTIONS = { escape_html: true }.freeze def self.haml_result(haml, options, locals) Haml::Engine.new(haml, HAML_DEFAULT_OPTIONS.merge(options)).render(Object.new, locals) end def self.haml_result(haml, options, locals) eval Haml::Engine.new(haml, HAMLIT_DEFAULT_OPTIONS.merge(options)).render(Object.new, locals) end SPEC contexts = YAML.load(File.read(File.expand_path('./tests.yml', __dir__))) contexts.each_with_index do |context, index| spec += "\n" if index != 0 spec += " class #{escape_name(context[0], '').capitalize} < Minitest::Test\n" tests = [] context[1].each do |name, test| tests << { name: name, html: test['html'], haml: test['haml'], locals: test['locals'], config: test['config'], } end spec += tests.map { |test| locals = Hash[(test[:locals] || {}).map {|x, y| [x.to_sym, y]}] options = Hash[(test[:config] || {}).map {|x, y| [x.to_sym, y]}] options[:format] = options[:format].to_sym if options[:format] generate_specify(test, locals, options, mode) }.join("\n") spec += " end\n" end spec += "end\n" File.write("#{mode}_test.rb", spec) end def generate_specify(test, locals, options, mode) <<-SPEC def test_#{escape_name(test[:name], '_')} haml = %q{#{test[:haml]}} html = %q{#{test[:html]}} locals = #{locals} options = #{options} haml_result = #{mode.capitalize}Test.haml_result(haml, options, locals) haml_result = #{mode.capitalize}Test.haml_result(haml, options, locals) assert_equal haml_result, haml_result end SPEC end desc 'Convert tests.yml into ugly tests' task :pretty do generate_spec(:pretty) end desc 'Convert tests.yml into ugly tests' task :ugly do generate_spec(:ugly) end haml-6.3.0/test/haml/haml-spec/tests.yml000066400000000000000000000311231453526310700201050ustar00rootroot00000000000000--- headers: an XHTML XML prolog: haml: "!!! XML" html: "" config: format: xhtml an XHTML default (transitional) doctype: haml: "!!!" html: config: format: xhtml an XHTML 1.1 doctype: haml: "!!! 1.1" html: config: format: xhtml an XHTML 1.2 mobile doctype: haml: "!!! mobile" html: config: format: xhtml an XHTML 1.1 basic doctype: haml: "!!! basic" html: config: format: xhtml an XHTML 1.0 frameset doctype: haml: "!!! frameset" html: config: format: xhtml an HTML 5 doctype with XHTML syntax: haml: "!!! 5" html: "" config: format: xhtml an HTML 5 XML prolog (silent): haml: "!!! XML" html: '' config: format: html5 an HTML 5 doctype: haml: "!!!" html: "" config: format: html5 an HTML 4 XML prolog (silent): haml: "!!! XML" html: '' config: format: html4 an HTML 4 default (transitional) doctype: haml: "!!!" html: config: format: html4 an HTML 4 frameset doctype: haml: "!!! frameset" html: config: format: html4 an HTML 4 strict doctype: haml: "!!! strict" html: config: format: html4 basic Haml tags and CSS: a simple Haml tag: haml: "%p" html: "

      " a self-closing tag (XHTML): haml: "%meta" html: "" config: format: xhtml a self-closing tag (HTML4): haml: "%meta" html: "" config: format: html4 a self-closing tag (HTML5): haml: "%meta" html: "" config: format: html5 a self-closing tag ('/' modifier + XHTML): haml: "%zzz/" html: "" config: format: xhtml a self-closing tag ('/' modifier + HTML5): haml: "%zzz/" html: "" config: format: html5 a tag with a CSS class: haml: "%p.class1" html: "

      " a tag with multiple CSS classes: haml: "%p.class1.class2" html: "

      " a tag with a CSS id: haml: "%p#id1" html: "

      " a tag with multiple CSS id's: haml: "%p#id1#id2" html: "

      " a tag with a class followed by an id: haml: "%p.class1#id1" html: "

      " a tag with an id followed by a class: haml: "%p#id1.class1" html: "

      " an implicit div with a CSS id: haml: "#id1" html: "
      " an implicit div with a CSS class: haml: ".class1" html: "
      " multiple simple Haml tags: haml: |- %div %div %p html: |-

      tags with unusual HTML characters: a tag with colons: haml: "%ns:tag" html: "" a tag with underscores: haml: "%snake_case" html: "" a tag with dashes: haml: "%dashed-tag" html: "" a tag with camelCase: haml: "%camelCase" html: "" a tag with PascalCase: haml: "%PascalCase" html: "" tags with unusual CSS identifiers: an all-numeric class: haml: ".123" html: "
      " a class with underscores: haml: ".__" html: "
      " a class with dashes: haml: ".--" html: "
      " tags with inline content: Inline content simple tag: haml: "%p hello" html: "

      hello

      " Inline content tag with CSS: haml: "%p.class1 hello" html: "

      hello

      " Inline content multiple simple tags: haml: |- %div %div %p text html: |-

      text

      tags with nested content: Nested content simple tag: haml: |- %p hello html: |-

      hello

      Nested content tag with CSS: haml: |- %p.class1 hello html: |-

      hello

      Nested content multiple simple tags: haml: |- %div %div %p text html: |-

      text

      tags with HTML-style attributes: HTML-style one attribute: haml: "%p(a='b')" html: "

      " HTML-style multiple attributes: haml: "%p(a='b' c='d')" html: "

      " HTML-style attributes separated with newlines: haml: |- %p(a='b' c='d') html: "

      " HTML-style interpolated attribute: haml: '%p(a="#{var}")' html: "

      " locals: var: value HTML-style 'class' as an attribute: haml: "%p(class='class1')" html: "

      " HTML-style tag with a CSS class and 'class' as an attribute: haml: "%p.class2(class='class1')" html: "

      " HTML-style tag with 'id' as an attribute: haml: "%p(id='1')" html: "

      " HTML-style tag with a CSS id and 'id' as an attribute: haml: "%p#id(id='1')" html: "

      " HTML-style tag with a variable attribute: haml: "%p(class=var)" html: "

      " locals: var: hello HTML-style tag with a CSS class and 'class' as a variable attribute: haml: ".hello(class=var)" html: "
      " locals: var: world HTML-style tag multiple CSS classes (sorted correctly): haml: ".z(class=var)" html: "
      " locals: var: a HTML-style tag with an atomic attribute: haml: "%a(flag)" html: "" tags with Ruby-style attributes: Ruby-style one attribute: haml: "%p{:a => 'b'}" html: "

      " optional: true Ruby-style attributes hash with whitespace: haml: "%p{ :a => 'b' }" html: "

      " optional: true Ruby-style interpolated attribute: haml: '%p{:a =>"#{var}"}' html: "

      " optional: true locals: var: value Ruby-style multiple attributes: haml: "%p{ :a => 'b', 'c' => 'd' }" html: "

      " optional: true Ruby-style attributes separated with newlines: haml: |- %p{ :a => 'b', 'c' => 'd' } html: "

      " optional: true Ruby-style 'class' as an attribute: haml: "%p{:class => 'class1'}" html: "

      " optional: true Ruby-style tag with a CSS class and 'class' as an attribute: haml: "%p.class2{:class => 'class1'}" html: "

      " optional: true Ruby-style tag with 'id' as an attribute: haml: "%p{:id => '1'}" html: "

      " optional: true Ruby-style tag with a CSS id and 'id' as an attribute: haml: "%p#id{:id => '1'}" html: "

      " optional: true Ruby-style tag with a CSS id and a numeric 'id' as an attribute: haml: "%p#id{:id => 1}" html: "

      " optional: true Ruby-style tag with a variable attribute: haml: "%p{:class => var}" html: "

      " optional: true locals: var: hello Ruby-style tag with a CSS class and 'class' as a variable attribute: haml: ".hello{:class => var}" html: "
      " optional: true locals: var: world Ruby-style tag multiple CSS classes (sorted correctly): haml: ".z{:class => var}" html: "
      " optional: true locals: var: a silent comments: an inline silent comment: haml: "-# hello" html: '' a nested silent comment: haml: |- -# hello html: '' a multiply nested silent comment: haml: |- -# %div foo html: '' a multiply nested silent comment with inconsistent indents: haml: |- -# %div foo html: '' markup comments: an inline markup comment: haml: "/ comment" html: "" a nested markup comment: haml: |- / comment comment2 html: |- conditional comments: a conditional comment: haml: |- /[if IE] %p a html: |- internal filters: content in an 'escaped' filter: haml: |- :escaped <&"> html: "<&">" content in a 'preserve' filter: haml: |- :preserve hello %p html: |- hello

      content in a 'plain' filter: haml: |- :plain hello %p html: |- hello

      content in a 'css' filter (XHTML): haml: |- :css hello %p html: |-

      config: format: xhtml content in a 'javascript' filter (XHTML): haml: |- :javascript a(); %p html: |-

      config: format: xhtml content in a 'css' filter (HTML): haml: |- :css hello %p html: |-

      config: format: html5 content in a 'javascript' filter (HTML): haml: |- :javascript a(); %p html: |-

      config: format: html5 Ruby-style interpolation: interpolation inside inline content: haml: "%p #{var}" html: "

      value

      " optional: true locals: var: value no interpolation when escaped: haml: "%p \\#{var}" html: "

      #{var}

      " optional: true locals: var: value interpolation when the escape character is escaped: haml: "%p \\\\#{var}" html: "

      \\value

      " optional: true locals: var: value interpolation inside filtered content: haml: |- :plain #{var} interpolated: #{var} html: 'value interpolated: value' optional: true locals: var: value HTML escaping: code following '&=': haml: '&= ''<"&>''' html: "<"&>" code following '=' when escape_haml is set to true: haml: = '<"&>' html: "<"&>" config: escape_html: 'true' code following '!=' when escape_haml is set to true: haml: '!= ''<"&>''' html: <"&> config: escape_html: 'true' boolean attributes: boolean attribute with XHTML: haml: "%input(checked=true)" html: "" config: format: xhtml boolean attribute with HTML: haml: "%input(checked=true)" html: "" config: format: html5 whitespace preservation: following the '~' operator: haml: ~ "Foo\n
      Bar\nBaz
      " html: |- Foo
      Bar
      Baz
      optional: true inside a textarea tag: haml: |- %textarea hello hello html: |- inside a pre tag: haml: |- %pre hello hello html: |-
      hello
            hello
      whitespace removal: a tag with '>' appended and inline content: haml: |- %li hello %li> world %li again html: "
    • hello
    • world
    • again
    • " a tag with '>' appended and nested content: haml: |- %li hello %li> world %li again html: |-
    • hello
    • world
    • again
    • a tag with '<' appended: haml: |- %p< hello world html: |-

      hello world

      haml-6.3.0/test/haml/haml-spec/ugly_test.rb000066400000000000000000000705521453526310700205750ustar00rootroot00000000000000$:.unshift File.expand_path('../../test', __dir__) require 'test_helper' require 'haml' require 'minitest/autorun' # This is a spec converted by haml-spec. # See: https://github.com/haml/haml-spec class UglyTest < Minitest::Test HAML_DEFAULT_OPTIONS = { escape_html: true }.freeze def self.haml_result(haml, options, locals) Haml::Template.new(HAML_DEFAULT_OPTIONS.merge(options)) { haml }.render(Object.new, locals).rstrip end class Headers < Minitest::Test def test_an_XHTML_XML_prolog haml = %q{!!! XML} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_XHTML_default_transitional_doctype haml = %q{!!!} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_XHTML_1_1_doctype haml = %q{!!! 1.1} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_XHTML_1_2_mobile_doctype haml = %q{!!! mobile} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_XHTML_1_1_basic_doctype haml = %q{!!! basic} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_XHTML_1_0_frameset_doctype haml = %q{!!! frameset} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_html_5_doctype_with_XHTML_syntax haml = %q{!!! 5} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_html_5_XML_prolog_silent_ haml = %q{!!! XML} html = %q{} locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_HTML_5_doctype haml = %q{!!!} html = %q{} locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_HTML_4_XML_prolog_silent_ haml = %q{!!! XML} html = %q{} locals = {} options = {:format=>:html4} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_HTML_4_default_transitional_doctype haml = %q{!!!} html = %q{} locals = {} options = {:format=>:html4} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_HTML_4_frameset_doctype haml = %q{!!! frameset} html = %q{} locals = {} options = {:format=>:html4} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_HTML_4_strict_doctype haml = %q{!!! strict} html = %q{} locals = {} options = {:format=>:html4} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Basichamltagsandcss < Minitest::Test def test_a_simple_Haml_tag haml = %q{%p} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_self_closing_tag_XHTML_ haml = %q{%meta} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_self_closing_tag_HTML4_ haml = %q{%meta} html = %q{} locals = {} options = {:format=>:html4} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_self_closing_tag_HTML5_ haml = %q{%meta} html = %q{} locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_self_closing_tag_modifier_XHTML_ haml = %q{%zzz/} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_self_closing_tag_modifier_html5_ haml = %q{%zzz/} html = %q{} locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_a_CSS_class haml = %q{%p.class1} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_multiple_CSS_classes haml = %q{%p.class1.class2} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_a_CSS_id haml = %q{%p#id1} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_multiple_CSS_id_s haml = %q{%p#id1#id2} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_a_class_followed_by_an_id haml = %q{%p.class1#id1} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_an_id_followed_by_a_class haml = %q{%p#id1.class1} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_implicit_div_with_a_CSS_id haml = %q{#id1} html = %q{
      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_an_implicit_div_with_a_CSS_class haml = %q{.class1} html = %q{
      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_multiple_simple_Haml_tags haml = %q{%div %div %p} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Tagswithunusualhtmlcharacters < Minitest::Test def test_a_tag_with_colons haml = %q{%ns:tag} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_underscores haml = %q{%snake_case} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_dashes haml = %q{%dashed-tag} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_camelCase haml = %q{%camelCase} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_PascalCase haml = %q{%PascalCase} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Tagswithunusualcssidentifiers < Minitest::Test def test_an_all_numeric_class haml = %q{.123} html = %q{
      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_class_with_underscores haml = %q{.__} html = %q{
      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_class_with_dashes haml = %q{.--} html = %q{
      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Tagswithinlinecontent < Minitest::Test def test_Inline_content_simple_tag haml = %q{%p hello} html = %q{

      hello

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Inline_content_tag_with_CSS haml = %q{%p.class1 hello} html = %q{

      hello

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Inline_content_multiple_simple_tags haml = %q{%div %div %p text} html = %q{

      text

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Tagswithnestedcontent < Minitest::Test def test_Nested_content_simple_tag haml = %q{%p hello} html = %q{

      hello

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Nested_content_tag_with_CSS haml = %q{%p.class1 hello} html = %q{

      hello

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Nested_content_multiple_simple_tags haml = %q{%div %div %p text} html = %q{

      text

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Tagswithhtmlstyleattributes < Minitest::Test def test_html_style_one_attribute haml = %q{%p(a='b')} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_multiple_attributes haml = %q{%p(a='b' c='d')} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_attributes_separated_with_newlines haml = %q{%p(a='b' c='d')} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_interpolated_attribute haml = %q{%p(a="#{var}")} html = %q{

      } locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_class_as_an_attribute haml = %q{%p(class='class1')} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_tag_with_a_CSS_class_and_class_as_an_attribute haml = %q{%p.class2(class='class1')} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_tag_with_id_as_an_attribute haml = %q{%p(id='1')} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_tag_with_a_CSS_id_and_id_as_an_attribute haml = %q{%p#id(id='1')} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_tag_with_a_variable_attribute haml = %q{%p(class=var)} html = %q{

      } locals = {:var=>"hello"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_tag_with_a_CSS_class_and_class_as_a_variable_attribute haml = %q{.hello(class=var)} html = %q{
      } locals = {:var=>"world"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_tag_multiple_CSS_classes_sorted_correctly_ skip 'This test is probably not compatible with Haml 5. So the test is outdated.' haml = %q{.z(class=var)} html = %q{
      } locals = {:var=>"a"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_html_style_tag_with_an_atomic_attribute skip '[INCOMPATIBILITY] Haml limits boolean attributes' haml = %q{%a(flag)} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Tagswithrubystyleattributes < Minitest::Test def test_Ruby_style_one_attribute haml = %q{%p{:a => 'b'}} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_attributes_hash_with_whitespace haml = %q{%p{ :a => 'b' }} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_interpolated_attribute haml = %q{%p{:a =>"#{var}"}} html = %q{

      } locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_multiple_attributes haml = %q{%p{ :a => 'b', 'c' => 'd' }} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_attributes_separated_with_newlines haml = %q{%p{ :a => 'b', 'c' => 'd' }} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_class_as_an_attribute haml = %q{%p{:class => 'class1'}} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_tag_with_a_CSS_class_and_class_as_an_attribute haml = %q{%p.class2{:class => 'class1'}} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_tag_with_id_as_an_attribute haml = %q{%p{:id => '1'}} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_tag_with_a_CSS_id_and_id_as_an_attribute haml = %q{%p#id{:id => '1'}} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_tag_with_a_CSS_id_and_a_numeric_id_as_an_attribute haml = %q{%p#id{:id => 1}} html = %q{

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_tag_with_a_variable_attribute haml = %q{%p{:class => var}} html = %q{

      } locals = {:var=>"hello"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_tag_with_a_CSS_class_and_class_as_a_variable_attribute haml = %q{.hello{:class => var}} html = %q{
      } locals = {:var=>"world"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_Ruby_style_tag_multiple_CSS_classes_sorted_correctly_ skip 'This test is probably not compatible with Haml 5. So the test is outdated.' haml = %q{.z{:class => var}} html = %q{
      } locals = {:var=>"a"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Silentcomments < Minitest::Test def test_an_inline_silent_comment haml = %q{-# hello} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_nested_silent_comment haml = %q{-# hello} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_multiply_nested_silent_comment haml = %q{-# %div foo} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_multiply_nested_silent_comment_with_inconsistent_indents haml = %q{-# %div foo} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Markupcomments < Minitest::Test def test_an_inline_markup_comment haml = %q{/ comment} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_nested_markup_comment haml = %q{/ comment comment2} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Conditionalcomments < Minitest::Test def test_a_conditional_comment haml = %q{/[if IE] %p a} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Internalfilters < Minitest::Test def test_content_in_an_escaped_filter haml = %q{:escaped <&">} html = %q{<&">} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_content_in_a_preserve_filter haml = %q{:preserve hello %p} html = %q{hello

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_content_in_a_plain_filter haml = %q{:plain hello %p} html = %q{hello

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_content_in_a_css_filter_XHTML_ haml = %q{:css hello %p} html = %q{

      } locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_content_in_a_javascript_filter_XHTML_ haml = %q{:javascript a(); %p} html = %q{

      } locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_content_in_a_css_filter_html_ haml = %q{:css hello %p} html = %q{

      } locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_content_in_a_javascript_filter_html_ haml = %q{:javascript a(); %p} html = %q{

      } locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Rubystyleinterpolation < Minitest::Test def test_interpolation_inside_inline_content haml = %q{%p #{var}} html = %q{

      value

      } locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_no_interpolation_when_escaped haml = %q{%p \#{var}} html = %q{

      #{var}

      } locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_interpolation_when_the_escape_character_is_escaped skip 'This test is probably not compatible with Haml 5. So the test is outdated.' haml = %q{%p \\#{var}} html = %q{

      \value

      } locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_interpolation_inside_filtered_content haml = %q{:plain #{var} interpolated: #{var}} html = %q{value interpolated: value} locals = {:var=>"value"} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Htmlescaping < Minitest::Test def test_code_following_ haml = %q{&= '<"&>'} html = %q{<"&>} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_code_following_eq_when_escape_haml_is_set_to_true haml = %q{= '<"&>'} html = %q{<"&>} locals = {} options = {:escape_html=>"true"} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_code_following_neq_when_escape_haml_is_set_to_true haml = %q{!= '<"&>'} html = %q{<"&>} locals = {} options = {:escape_html=>"true"} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Booleanattributes < Minitest::Test def test_boolean_attribute_with_XHTML haml = %q{%input(checked=true)} html = %q{} locals = {} options = {:format=>:xhtml} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_boolean_attribute_withhtml haml = %q{%input(checked=true)} html = %q{} locals = {} options = {:format=>:html5} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Whitespacepreservation < Minitest::Test def test_following_the_operator skip 'This test is probably not compatible with Haml 5. So the test is outdated.' haml = %q{~ "Foo\n
      Bar\nBaz
      "} html = %q{Foo
      Bar
      Baz
      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_inside_a_textarea_tag haml = %q{%textarea hello hello} html = %q{} locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_inside_a_pre_tag haml = %q{%pre hello hello} html = %q{
      hello
      hello
      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end class Whitespaceremoval < Minitest::Test def test_a_tag_with_appended_and_inline_content haml = %q{%li hello %li> world %li again} html = %q{
    • hello
    • world
    • again
    • } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_appended_and_nested_content haml = %q{%li hello %li> world %li again} html = %q{
    • hello
    • world
    • again
    • } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end def test_a_tag_with_appended haml = %q{%p< hello world} html = %q{

      hello world

      } locals = {} options = {} haml_result = UglyTest.haml_result(haml, options, locals) assert_equal html, haml_result end end end if RUBY_ENGINE != 'truffleruby' # truffleruby cannot run Haml haml-6.3.0/test/haml/helper_test.rb000066400000000000000000000462641453526310700172260ustar00rootroot00000000000000require 'test_helper' require "active_model/naming" class FormModel extend ActiveModel::Naming end class HelperTest < Haml::TestCase TEXT_AREA_CONTENT_REGEX = /<(textarea)[^>]*>\n(.*?)<\/\1>/im Post = Struct.new('Post', :body, :error_field, :errors) class PostErrors def on(name) return unless name == 'error_field' ["Really bad error"] end alias_method :full_messages, :on def [](name) on(name) || [] end end def setup template_path = File.expand_path("../templates", __FILE__) @base = Class.new(ActionView::Base) do def nested_tag content_tag(:span) {content_tag(:div) {"something"}} end def wacky_form form_tag("/foo") {"bar"} end def compiled_method_container self.class end end.new(ActionView::LookupContext.new(template_path), {}, ActionController::Base.new) @base.instance_variable_set(:@post, Post.new("Foo bar\nbaz", nil, PostErrors.new)) end def render(text, options = {}) return @base.render :inline => text, :type => :haml if options == :action_view super end def test_rendering_with_escapes; skip def @base.render_something_with_haml_concat haml_concat "

      " end def @base.render_something_with_haml_tag_and_concat haml_tag 'p' do haml_concat '' end end output = render(<<-HAML, :action_view) - render_something_with_haml_concat - render_something_with_haml_tag_and_concat - render_something_with_haml_concat HAML assert_equal("<p>\n

      \n <foo>\n

      \n<p>\n", output) end def test_with_raw_haml_concat; skip haml = <&" HAML assert_equal("<>&\n", render(haml, :action_view)) end def test_list_of_should_render_correctly; skip assert_equal("
    • 1
    • \n
    • 2
    • \n", render("= list_of([1, 2]) do |i|\n = i")) assert_equal("
    • [1]
    • \n", render("= list_of([[1]]) do |i|\n = i.inspect")) assert_equal("
    • \n

      Fee

      \n

      A word!

      \n
    • \n
    • \n

      Fi

      \n

      A word!

      \n
    • \n
    • \n

      Fo

      \n

      A word!

      \n
    • \n
    • \n

      Fum

      \n

      A word!

      \n
    • \n", render("= list_of(['Fee', 'Fi', 'Fo', 'Fum']) do |title|\n %h1= title\n %p A word!")) assert_equal("
    • 1
    • \n
    • 2
    • \n", render("= list_of([1, 2], {:c => 3}) do |i|\n = i")) assert_equal("
    • [1]
    • \n", render("= list_of([[1]], {:c => 3}) do |i|\n = i.inspect")) assert_equal("
    • \n

      Fee

      \n

      A word!

      \n
    • \n
    • \n

      Fi

      \n

      A word!

      \n
    • \n
    • \n

      Fo

      \n

      A word!

      \n
    • \n
    • \n

      Fum

      \n

      A word!

      \n
    • \n", render("= list_of(['Fee', 'Fi', 'Fo', 'Fum'], {:c => 3}) do |title|\n %h1= title\n %p A word!")) end def test_buffer_access; skip assert(render("= buffer") =~ /#/) assert_equal(render("= (buffer == _hamlout)"), "true\n") end def test_tabs; skip assert_equal("foo\n bar\nbaz\n", render("foo\n- tab_up\nbar\n- tab_down\nbaz")) assert_equal("

      tabbed

      \n", render("- buffer.tabulation=5\n%p tabbed")) end def test_with_tabs; skip assert_equal(< "<%= flatten('Foo\\nBar') %>") rescue NoMethodError, ActionView::Template::Error proper_behavior = true end assert(proper_behavior) begin action_view_instance.render(:inline => "<%= concat('foo') %>") rescue ArgumentError, NameError proper_behavior = true end assert(proper_behavior) end def test_action_view_included; skip assert(Haml::Helpers.action_view?) end def test_form_tag; skip def @base.protect_against_forgery?; false; end rendered = render(<]+>Foo bar baz\n), render('= content_tag "pre", "Foo bar\n baz"', :action_view)) end def test_text_area_tag; skip output = render('= text_area_tag "body", "Foo\nBar\n Baz\n Boom"', :action_view) match_data = output.match(TEXT_AREA_CONTENT_REGEX) assert_equal "Foo Bar Baz Boom", match_data[2] end def test_text_area; skip output = render('= text_area :post, :body', :action_view) match_data = output.match(TEXT_AREA_CONTENT_REGEX) assert_equal "Foo bar baz", match_data[2] end def test_partials_should_not_cause_textareas_to_be_indented; skip # non-indentation of textareas rendered inside partials @base.instance_variable_set(:@post, Post.new("Foo", nil, PostErrors.new)) output = render(".foo\n .bar\n = render '/text_area_helper'", :action_view) match_data = output.match(TEXT_AREA_CONTENT_REGEX) assert_equal 'Foo', match_data[2] end def test_textareas_should_preserve_leading_whitespace; skip # leading whitespace preservation @base.instance_variable_set(:@post, Post.new(" Foo", nil, PostErrors.new)) output = render(".foo\n = text_area :post, :body", :action_view) match_data = output.match(TEXT_AREA_CONTENT_REGEX) assert_equal ' Foo', match_data[2] end def test_textareas_should_preserve_leading_whitespace_in_partials; skip # leading whitespace in textareas rendered inside partials @base.instance_variable_set(:@post, Post.new(" Foo", nil, PostErrors.new)) output = render(".foo\n .bar\n = render '/text_area_helper'", :action_view) match_data = output.match(TEXT_AREA_CONTENT_REGEX) assert_equal ' Foo', match_data[2] end def test_capture_haml; skip assert_equal(<13

      \\n" HTML - (foo = capture_haml(13) do |a| %p= a - end) = foo.inspect HAML end def test_content_tag_block; skip assert_equal(<

      bar

      bar
HTML = content_tag :div do %p bar %strong bar HAML end def test_content_tag_error_wrapping; skip def @base.protect_against_forgery?; false; end output = render(< :post, :html => {:class => nil, :id => nil}, :url => '' do |f| = f.label 'error_field' HAML fragment = Nokogiri::HTML.fragment(output) refute_nil fragment.css('form div.field_with_errors label[for=post_error_field]').first end def test_form_tag_in_helper_with_string_block; skip def @base.protect_against_forgery?; false; end rendered = render('= wacky_form', :action_view) fragment = Nokogiri::HTML.fragment(rendered) assert_equal 'bar', fragment.text.strip assert_equal '/foo', fragment.css('form').first.attributes['action'].to_s end def test_haml_tag_name_attribute_with_id; skip assert_equal("

\n", render("- haml_tag 'p#some_id'")) end def test_haml_tag_name_attribute_with_colon_id; skip assert_equal("

\n", render("- haml_tag 'p#some:id'")) end def test_haml_tag_without_name_but_with_id; skip assert_equal("
\n", render("- haml_tag '#some_id'")) end def test_haml_tag_without_name_but_with_class; skip assert_equal("
\n", render("- haml_tag '.foo'")) end def test_haml_tag_without_name_but_with_colon_class; skip assert_equal("
\n", render("- haml_tag '.foo:bar'")) end def test_haml_tag_name_with_id_and_class; skip assert_equal("

\n", render("- haml_tag 'p#some_id.foo'")) end def test_haml_tag_name_with_class; skip assert_equal("

\n", render("- haml_tag 'p.foo'")) end def test_haml_tag_name_with_class_and_id; skip assert_equal("

\n", render("- haml_tag 'p.foo#some_id'")) end def test_haml_tag_name_with_id_and_multiple_classes; skip assert_equal("

\n", render("- haml_tag 'p#some_id.foo.bar'")) end def test_haml_tag_name_with_multiple_classes_and_id; skip assert_equal("

\n", render("- haml_tag 'p.foo.bar#some_id'")) end def test_haml_tag_name_and_attribute_classes_merging_with_id; skip assert_equal("

\n", render("- haml_tag 'p#some_id.foo', :class => 'bar'")) end def test_haml_tag_name_and_attribute_classes_merging; skip assert_equal("

\n", render("- haml_tag 'p.foo', :class => 'bar'")) end def test_haml_tag_name_merges_id_and_attribute_id; skip assert_equal("

\n", render("- haml_tag 'p#foo', :id => 'bar'")) end def test_haml_tag_attribute_html_escaping; skip assert_equal("

baz

\n", render("%p{:id => 'foo&bar'} baz", :escape_html => true)) end def test_haml_tag_autoclosed_tags_are_closed_xhtml; skip assert_equal("
\n", render("- haml_tag :br, :class => 'foo'", :format => :xhtml)) end def test_haml_tag_autoclosed_tags_are_closed_html; skip assert_equal("
\n", render("- haml_tag :br, :class => 'foo'", :format => :html5)) end def test_haml_tag_with_class_array; skip assert_equal("

foo

\n", render("- haml_tag :p, 'foo', :class => %w[a b]")) assert_equal("

foo

\n", render("- haml_tag 'p.c.d', 'foo', :class => %w[a b]")) end def test_haml_tag_with_id_array; skip assert_equal("

foo

\n", render("- haml_tag :p, 'foo', :id => %w[a b]")) assert_equal("

foo

\n", render("- haml_tag 'p#c', 'foo', :id => %w[a b]")) end def test_haml_tag_with_data_hash; skip assert_equal("

foo

\n", render("- haml_tag :p, 'foo', :data => {:foo => 'bar', :baz => true}")) end def test_haml_tag_non_autoclosed_tags_arent_closed; skip assert_equal("

\n", render("- haml_tag :p")) end def test_haml_tag_renders_text_on_a_single_line; skip assert_equal("

#{'a' * 100}

\n", render("- haml_tag :p, 'a' * 100")) end def test_haml_tag_raises_error_for_multiple_content; skip assert_raises(Haml::Error) { render("- haml_tag :p, 'foo' do\n bar") } end def test_haml_tag_flags; skip assert_equal("

\n", render("- haml_tag :p, :/", :format => :xhtml)) assert_equal("

\n", render("- haml_tag :p, :/", :format => :html5)) assert_equal("

kumquat

\n", render("- haml_tag :p, :< do\n kumquat")) assert_raises(Haml::Error) { render("- haml_tag :p, 'foo', :/") } assert_raises(Haml::Error) { render("- haml_tag :p, :/ do\n foo") } end def test_haml_tag_error_return; skip assert_raises(Haml::Error) { render("= haml_tag :p") } end def test_haml_tag_with_multiline_string; skip assert_equal(< foo bar baz

HTML - haml_tag :p, "foo\\nbar\\nbaz" HAML end def test_haml_concat_inside_haml_tag_escaped_with_xss; skip assert_equal("

\n <>&\n

\n", render(<&" HAML end def test_haml_concat_with_multiline_string; skip assert_equal(< foo bar baz

HTML %p - haml_concat "foo\\nbar\\nbaz" HAML end def test_haml_tag_with_ugly; skip assert_equal(< true))

Hi!

HTML - haml_tag :p do - haml_tag :strong, "Hi!" HAML end def test_haml_tag_if_positive; skip assert_equal(<

A para

HTML - haml_tag_if true, '.conditional' do %p A para HAML end def test_haml_tag_if_positive_with_attributes; skip assert_equal(<

A para

HTML - haml_tag_if true, '.conditional', {:foo => 'bar'} do %p A para HAML end def test_haml_tag_if_negative; skip assert_equal(<A para

HTML - haml_tag_if false, '.conditional' do %p A para HAML end def test_haml_tag_if_error_return; skip assert_raises(Haml::Error) { render("= haml_tag_if false, '.conditional' do\n %p Hello") } end def test_is_haml; skip assert(!ActionView::Base.new.is_haml?) assert_equal("true\n", render("= is_haml?")) assert_equal("true\n", render("= is_haml?", :action_view)) assert_equal("false", @base.render(:inline => '<%= is_haml? %>')) assert_equal("false\n", render("= render :inline => '<%= is_haml? %>'", :action_view)) end def test_page_class; skip controller = Struct.new(:controller_name, :action_name).new('troller', 'tion') scope = Struct.new(:controller).new(controller) result = render("%div{:class => page_class} MyDiv", :scope => scope) expected = "
MyDiv
\n" assert_equal expected, result end def test_indented_capture assert_equal(" Foo\n ", @base.render(:inline => " <% res = capture do %>\n Foo\n <% end %><%= res %>")) end def test_capture_deals_properly_with_collections; skip obj = Object.new def obj.trc(collection, &block) collection.each do |record| haml_concat capture_haml(record, &block) end end assert_equal("1\n\n2\n\n3\n\n", render("- trc([1, 2, 3]) do |i|\n = i.inspect", scope: obj)) end def test_capture_with_string_block; skip assert_equal("foo\n", render("= capture { 'foo' }", :action_view)) end def test_capture_with_non_string_value_reurns_nil; skip def @base.check_capture_returns_nil(&block) contents = capture(&block) contents << "ERROR" if contents end assert_equal("\n", render("= check_capture_returns_nil { 2 }", :action_view)) end class HomemadeViewContext include ActionView::Context include ActionView::Helpers::FormHelper def initialize _prepare_context end def url_for(*) "/" end def dom_class(*) end def dom_id(*) end def m # I have to inject the model into the view using an instance method, using locals doesn't work. FormModel.new end def protect_against_forgery? end # def capture(*args, &block) # capture_haml(*args, &block) # end end def test_form_for_with_homemade_view_context; skip handler = ActionView::Template.handler_for_extension("haml") template = ActionView::Template.new(< "/") do %b Bold! HAML # see if Bold is within form tags: assert_match(/.*Bold!<\/b>.*<\/form>/m, template.render(HomemadeViewContext.new, {})) end def test_find_and_preserve_with_block; skip assert_equal("
Foo
Bar
\nFoo\nBar\n", render("= find_and_preserve do\n %pre\n Foo\n Bar\n Foo\n Bar")) end def test_find_and_preserve_with_block_and_tags; skip assert_equal("
Foo\nBar
\nFoo\nBar\n", render("= find_and_preserve([]) do\n %pre\n Foo\n Bar\n Foo\n Bar")) end def test_preserve_with_block; skip assert_equal("
Foo
Bar
Foo Bar\n", render("= preserve do\n %pre\n Foo\n Bar\n Foo\n Bar")) end def test_non_haml; skip assert_equal("false\n", render("= non_haml { is_haml? }")) end def test_content_tag_nested; skip assert_equal "
something
", render("= nested_tag", :action_view).strip end def test_error_return; skip assert_raises(Haml::Error, < e assert_equal 2, e.backtrace[1].scan(/:(\d+)/).first.first.to_i end def test_error_return_line_in_helper; skip obj = Object.new def obj.something_that_uses_haml_concat haml_concat('foo').to_s end render("- something_that_uses_haml_concat", scope: obj) assert false, "Expected Haml::Error" rescue Haml::Error => e assert_equal __LINE__ - 6, e.backtrace[0].scan(/:(\d+)/).first.first.to_i end class ActsLikeTag # We want to be able to have people include monkeypatched ActionView helpers # without redefining is_haml?. # This is accomplished via Object#is_haml?, and this is a test for it. include ActionView::Helpers::TagHelper def to_s content_tag :p, 'some tag content' end end def test_random_class_includes_tag_helper assert_equal "

some tag content

", ActsLikeTag.new.to_s end def test_capture_with_nuke_outer; skip assert_equal "
\n*
hi there!
\n", render(< hi there! HAML assert_equal "
\n*
hi there!
\n", render(< hi there! HAML end def test_html_escape_non_string; skip assert_equal('4.58', Haml::Helpers.html_escape(4.58)) assert_equal('4.58', Haml::Helpers.html_escape_without_haml_xss(4.58)) end def test_escape_once_leaves_numeric_references; skip assert_equal ""><&  ", Haml::Helpers.escape_once('"><&  ') #decimal assert_equal ""><&  ", Haml::Helpers.escape_once('"><&  ') #hexadecimal end def test_html_attrs_xhtml; skip assert_equal("\n", render("%html{html_attrs}", :format => :xhtml)) end def test_html_attrs_html4; skip assert_equal("\n", render("%html{html_attrs}", :format => :html4)) end def test_html_attrs_html5; skip assert_equal("\n", render("%html{html_attrs}", :format => :html5)) end def test_html_attrs_xhtml_other_lang; skip assert_equal("\n", render("%html{html_attrs('es-AR')}", :format => :xhtml)) end def test_html_attrs_html4_other_lang; skip assert_equal("\n", render("%html{html_attrs('es-AR')}", :format => :html4)) end def test_html_attrs_html5_other_lang; skip assert_equal("\n", render("%html{html_attrs('es-AR')}", :format => :html5)) end end haml-6.3.0/test/haml/helpers_test.rb000066400000000000000000000003141453526310700173730ustar00rootroot00000000000000describe Haml::Helpers do describe '.preserve' do it 'works without block' do result = Haml::Helpers.preserve("hello\nworld") assert_equal 'hello world', result end end end haml-6.3.0/test/haml/line_number_test.rb000066400000000000000000000161151453526310700202360ustar00rootroot00000000000000require_relative '../test_helper' describe Haml::Engine do include RenderHelper describe 'script' do it 'renders optimized script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 1 2 HTML = '1' = __LINE__ HAML end it 'renders dynamic script' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 1 2 HTML = 'a'.gsub(/a/, '1') = __LINE__ HAML end it 'renders dynamic script with children' do assert_render(<<-HTML.unindent, <<-HAML.unindent, disable_capture: true) 1 3 3 24 HTML = __LINE__ = __LINE__.times do = __LINE__ = __LINE__ HAML end end describe 'silent script' do it 'renders silent script' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 2:3 4 HTML - __LINE__.times do - a = __LINE__ = "#{a}:#{__LINE__}" = __LINE__ HAML end it 'renders silent script with children' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 1:2 HTML - a = __LINE__ = "#{a}:#{__LINE__}" HAML end end describe 'old attributes' do it 'renders multi-line old attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 2 3 HTML %span{ a: __LINE__, b: __LINE__ }= __LINE__ = __LINE__ HAML end it 'renders optimized old attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 3 5 6 HTML %span{ a: 'a', b: 'b' } = __LINE__ %span{ a: 'a', b: 'b' }= __LINE__ = __LINE__ HAML end end describe 'new attributes' do it 'renders multi-line new attributes' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 1 3 HTML %span(a=__LINE__ b=__LINE__)= __LINE__ = __LINE__ HAML end end describe 'filters' do describe 'coffee filter' do it 'renders static filter' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 5 HTML :coffee jQuery ($) -> console.log('#{__LINE__}') console.log('#{__LINE__}') = __LINE__ HAML end it 'renders dynamic filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 5 HTML :coffee jQuery ($) -> console.log('3') console.log('4') = __LINE__ HAML end end unless /java/ === RUBY_PLATFORM # execjs is not working with Travis JRuby environment describe 'css filter' do it 'renders static filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 6 HTML :css body { width: 3px; height: 4px; } = __LINE__ HAML end it 'renders dynamic filter' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 6 HTML :css body { width: #{__LINE__}px; height: #{__LINE__}px; } = __LINE__ HAML end it 'renders dynamic filter with trailing newlines' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 8 HTML :css body { width: #{__LINE__}px; height: #{__LINE__}px; } = __LINE__ HAML end end describe 'javascript filter' do it 'renders static filter' do assert_render(<<-HTML.unindent, <<-HAML.unindent) 5 HTML :javascript console.log("2"); console.log("3"); = __LINE__ HAML end it 'renders dynamic filter' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 5 HTML :javascript console.log("#{__LINE__}"); console.log("#{__LINE__}"); = __LINE__ HAML end end unless /java/ === RUBY_PLATFORM # execjs is not working with Travis JRuby environment describe 'plain filter' do it 'renders line numbers with an empty line correctly' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) hello 4 HTML :plain hello = __LINE__ HAML end it 'renders line numbers with a script line correctly' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) hello 3 4 HTML :plain hello = 3 = __LINE__ HAML end it 'renders line numbers with interpolation' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) hello 3 4 HTML :plain hello#{} = 3 = __LINE__ HAML end end describe 'preserve filter' do it 'renders line numbers correctly' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) hello 4 HTML :preserve hello = __LINE__ HAML end end describe 'ruby filter' do it 'renders line numbers correctly' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) 4 HTML :ruby _ = 1 = __LINE__ HAML end end end describe 'dynamic merger' do it 'renders optimized string' do assert_render(<<-HTML.unindent, <<-'HAML'.unindent) foo1 2 3bar 5baz HTML foo#{__LINE__} #{__LINE__} #{__LINE__}bar - 1.to_s #{__LINE__}baz HAML end end end if RUBY_ENGINE != 'truffleruby' # negetive line numbers are broken in truffleruby haml-6.3.0/test/haml/markaby/000077500000000000000000000000001453526310700157755ustar00rootroot00000000000000haml-6.3.0/test/haml/markaby/standard.mab000066400000000000000000000036701453526310700202640ustar00rootroot00000000000000self << '' html(:xmlns=>'http://www.w3.org/1999/xhtml', 'xml:lang'=>'en-US') do head do title "Hampton Catlin Is Totally Awesome" meta("http-equiv" => "Content-Type", :content => "text/html; charset=utf-8") end body do # You're In my house now! div :class => "header" do self << %|Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah!| self << 1 + 9 + 8 + 2 #numbers should work and this should be ignored end div(:id => "body") { self << "Quotes should be loved! Just like people!"} 120.times do |number| number end self << "Wow.|" p do self << "Holy cow " + "multiline " + "tags! " + "A pipe (|) even!" self << [1, 2, 3].collect { |n| "PipesIgnored|" } self << [1, 2, 3].collect { |n| n.to_s }.join("|") end div(:class => "silent") do foo = String.new foo << "this" foo << " shouldn't" foo << " evaluate" self << foo + " but now it should!" # Woah crap a comment! end # That was a line that shouldn't close everything. ul(:class => "really cool") do ('a'..'f').each do |a| li a end end div((@should_eval = "with this text"), :id => "combo", :class => "of_divs_with_underscore") [ 104, 101, 108, 108, 111 ].map do |byte| byte.chr end div(:class => "footer") do strong("This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid. \nSo, I'm just making it *really* long. God, I hope this works", :class => "shout") end end end haml-6.3.0/test/haml/mocks/000077500000000000000000000000001453526310700154635ustar00rootroot00000000000000haml-6.3.0/test/haml/mocks/article.rb000066400000000000000000000001701453526310700174310ustar00rootroot00000000000000class Article attr_accessor :id, :title, :body def initialize @id, @title, @body = 1, 'Hello', 'World' end endhaml-6.3.0/test/haml/optimization_test.rb000066400000000000000000000027171453526310700204700ustar00rootroot00000000000000require_relative '../test_helper' describe 'optimization' do def compiled_code(haml) Haml::Engine.new.call(haml) end describe 'static analysis' do it 'renders static value for href statically' do haml = %|%a{ href: 1 }| assert_equal true, compiled_code(haml).include?(%|href='1'|) end it 'renders static script statically' do haml = <<-HAML.unindent %span 1 HAML assert_equal true, compiled_code(haml).include?(%q|\n1\n|) end it 'renders inline static script statically' do haml = %|%span= 1| assert_equal true, compiled_code(haml).include?(%|1|) end end describe 'string interpolation' do it 'renders a static part of string literal statically' do haml = %q|%input{ value: "jruby#{9000}#{dynamic}" }| assert_equal true, compiled_code(haml).include?(%|value='jruby9000|) haml = %q|%span= "jruby#{9000}#{dynamic}"| assert_equal true, compiled_code(haml).include?(%|jruby9000|) end it 'optimizes script' do haml = %q|= "jruby#{ "#{9000}" }#{dynamic}"| assert_equal true, compiled_code(haml).include?(%|jruby9000|) end it 'detects a static part recursively' do haml = %q|%input{ value: "#{ "hello#{ hello }" }" }| assert_equal true, compiled_code(haml).include?(%|value='hello|) end end end if RUBY_ENGINE != 'truffleruby' # truffleruby does not implement major Ripper features haml-6.3.0/test/haml/rails_template_test.rb000066400000000000000000000115041453526310700207410ustar00rootroot00000000000000# Explicitly requiring rails_template because rails initializers is not executed here. require 'haml/rails_template' describe Haml::RailsTemplate do def render(haml) ActionView::Template.register_template_handler(:haml, Haml::RailsTemplate.new) base = Class.new(ActionView::Base) do def compiled_method_container self.class end end.new(ActionView::LookupContext.new(''), {}, ActionController::Base.new) base.render(inline: haml, type: :haml) end specify 'html escape' do assert_equal %Q|<script>alert("a");</script>\n|, render(<<-HAML.unindent) = '' HAML assert_equal %Q|\n|, render(<<-HAML.unindent) = ''.html_safe HAML skip 'escape is not working well in truffleruby' if RUBY_ENGINE == 'truffleruby' assert_equal %Q|<script>alert("a");</script>\n|, render(<<-'HAML'.unindent) #{''} HAML assert_equal %Q|\n|, render(<<-'HAML'.unindent) #{''.html_safe} HAML end specify 'attribute escape' do assert_equal %Q|\n|, render(<<-HAML.unindent) %a{ href: '' } HAML assert_equal %Q|\n|, render(<<-HAML.unindent) %a{ href: '
Nested content

Blah

Blah

Blah

Blump

Whee

Woah inner quotes

hello

haml-6.3.0/test/haml/results/list.xhtml000066400000000000000000000001761453526310700201050ustar00rootroot00000000000000!Not a Doctype!
  • a
  • b
  • c
  • d
  • e
  • f
  • g
  • h
  • i
haml-6.3.0/test/haml/results/nuke_inner_whitespace.xhtml000066400000000000000000000004211453526310700234740ustar00rootroot00000000000000

Foo

Foo

Foo Bar

Foo Bar

Foo Bar

Foo Bar

Foo Bar

Foo Bar

foo bar

haml-6.3.0/test/haml/results/nuke_outer_whitespace.xhtml000066400000000000000000000017141453526310700235250ustar00rootroot00000000000000

Foo

Foo

Foo

Foo

Foo

Foo

Foo

Foo

Foo Bar

Foo Bar

Foo Bar

Foo Bar

foo Foo bar

foo Foo bar

fooFoobar

fooFoobar

foo Foo bar

foo Foo bar

fooFoobar

fooFoobar

foo Foo Bar bar

foo Foo Bar bar

fooFoo Barbar

fooFoo Barbar

haml-6.3.0/test/haml/results/original_engine.xhtml000066400000000000000000000007331453526310700222620ustar00rootroot00000000000000 Stop. haml time

This is a title!

Lorem ipsum dolor sit amet, consectetur adipisicing elit

Cigarettes!

Man alive!

  • Slippers
  • Shoes
  • Bathrobe
  • Coffee
This is some text that's in a pre block!
Let's see what happens when it's rendered! What about now, since we're on a new line?
haml-6.3.0/test/haml/results/partial_layout.xhtml000066400000000000000000000002371453526310700221610ustar00rootroot00000000000000

Partial layout used with for block:

This is inside a partial layout

Some content within a layout

haml-6.3.0/test/haml/results/partial_layout_erb.xhtml000066400000000000000000000002301453526310700230020ustar00rootroot00000000000000

Partial layout used with for block:

This is inside a partial layout

Some content within a layout
haml-6.3.0/test/haml/results/partials.xhtml000066400000000000000000000002371453526310700207470ustar00rootroot00000000000000

@foo = value one

@foo = value two

@foo = value two

Toplevel? false

@foo = value three

@foo = value three

haml-6.3.0/test/haml/results/render_layout.xhtml000066400000000000000000000000241453526310700217760ustar00rootroot00000000000000Before During After haml-6.3.0/test/haml/results/silent_script.xhtml000066400000000000000000000013031453526310700220050ustar00rootroot00000000000000

I can count!

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

I know my ABCs!

  • a
  • b
  • c
  • d
  • e
  • f
  • g
  • h
  • i
  • j
  • k
  • l
  • m
  • n
  • o
  • p
  • q
  • r
  • s
  • t
  • u
  • v
  • w
  • x
  • y
  • z

I can catch errors!

Oh no! "foo" happened!

"false" is: false

Even! Odd! Even! Odd! Even!
foobar
0 1 2 3 4

boom

haml-6.3.0/test/haml/results/standard.xhtml000066400000000000000000000030351453526310700207270ustar00rootroot00000000000000 Hampton Catlin Is Totally Awesome
Yes, ladies and gentileman. He is just that egotistical. Fantastic! This should be multi-line output The question is if this would translate! Ahah! 20
Quotes should be loved! Just like people!
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 Wow.|

Holy cow multiline tags! A pipe (|) even! PipesIgnored|PipesIgnored|PipesIgnored| 1|2|3

this shouldn't evaluate but now it should!
  • a
  • b
  • c
  • d
  • e
  • f
with this text
foo haml-6.3.0/test/haml/results/tag_parsing.xhtml000066400000000000000000000010031453526310700214160ustar00rootroot00000000000000
1 2 3 4 5 6 7 8 9 10 11

a
b
c
d
e
f
g
haml-6.3.0/test/haml/results/very_basic.xhtml000066400000000000000000000000731453526310700212540ustar00rootroot00000000000000 haml-6.3.0/test/haml/results/whitespace_handling.xhtml000066400000000000000000000074701453526310700231360ustar00rootroot00000000000000
Foo bar <pre>foo bar</pre> <pre>foo bar</pre>

<pre>foo bar</pre>

foo bar

13 <textarea> a </textarea> <textarea> a </textarea>
Foo bar
foo bar
foo
bar

foo
bar

foo bar

                                                 ___
                                              ,o88888
                                           ,o8888888'
                     ,:o:o:oooo.        ,8O88Pd8888"
                 ,.::.::o:ooooOoOoO. ,oO8O8Pd888'"
               ,.:.::o:ooOoOoOO8O8OOo.8OOPd8O8O"
              , ..:.::o:ooOoOOOO8OOOOo.FdO8O8"
             , ..:.::o:ooOoOO8O888O8O,COCOO"
            , . ..:.::o:ooOoOOOO8OOOOCOCO"
             . ..:.::o:ooOoOoOO8O8OCCCC"o
                . ..:.::o:ooooOoCoCCC"o:o
                . ..:.::o:o:,cooooCo"oo:o:
             `   . . ..:.:cocoooo"'o:o:::'
             .`   . ..::ccccoc"'o:o:o:::'
            :.:.    ,c:cccc"':.:.:.:.:.'
          ..:.:"'`::::c:"'..:.:.:.:.:.'  http://www.chris.com/ASCII/
        ...:.'.:.::::"'    . . . . .'
       .. . ....:."' `   .  . . ''
     . . . ...."'
     .. . ."'     -hrr-
    .


                                              It's a planet!
%strong This shouldn't be bold!
This should!
13
       __     ______        __               ______
.----.|  |--.|__    |.----.|  |--..--------.|  __  |
|  __||     ||__    ||  __||    < |        ||  __  |
|____||__|__||______||____||__|__||__|__|__||______|
foo
bar
haml-6.3.0/test/haml/ruby_expression_test.rb000066400000000000000000000031021453526310700211670ustar00rootroot00000000000000describe Haml::RubyExpression do describe '.syntax_error?' do it { assert_equal(true, Haml::RubyExpression.syntax_error?('{ hash }')) } it { assert_equal(false, Haml::RubyExpression.syntax_error?('{ a: b }')) } end describe '.string_literal?' do def assert_literal(expected, code) actual = Haml::RubyExpression.string_literal?(code) assert_equal expected, actual end describe 'invalid expressions' do it { assert_literal(false, %q|{ hash }|) } it { assert_literal(false, %q|"hello".|) } end describe 'string literal' do it { assert_literal(true, %q|''|) } it { assert_literal(true, %q|""|) } it { assert_literal(true, %Q|'\n'|) } it { assert_literal(true, %q|''; |) } it { assert_literal(true, %q| "" |) } it { assert_literal(true, %q|'hello world'|) } it { assert_literal(true, %q|"hello world"|) } it { assert_literal(true, %q|"h#{ %Q[e#{ "llo wor" }l] }d"|) } it { assert_literal(true, %q|%Q[nya]|) } it { assert_literal(true, %q|%Q[#{123}]|) } end describe 'not string literal' do it { assert_literal(false, %q|123|) } it { assert_literal(false, %q|'hello' + ''|) } it { assert_literal(false, %q|'hello'.to_s|) } it { assert_literal(false, %Q|'' \\ \n ''|) } it { assert_literal(false, %q|['']|) } it { assert_literal(false, %q|return ''|) } end describe 'multiple instructions' do it { assert_literal(false, %Q|''\n''|) } end end end if RUBY_ENGINE != 'truffleruby' # truffleruby doesn't have Ripper.sexp haml-6.3.0/test/haml/string_splitter_test.rb000066400000000000000000000041261453526310700211720ustar00rootroot00000000000000describe Haml::StringSplitter do describe '.compile' do def assert_compile(expected, code) actual = Haml::StringSplitter.compile(code) assert_equal expected, actual end it { assert_compile([], %q|''|) } it { assert_compile([], %q|""|) } it { assert_compile([[:static, 'hello']], %q|"hello"|) } it { assert_compile([[:static, 'hello '], [:static, 'world']], %q|"hello #{}world"|) } it { assert_compile([[:dynamic, 'hello']], %q|"#{hello}"|) } it { assert_compile([[:static, 'nya'], [:dynamic, '123']], %q|"nya#{123}"|) } it { assert_compile([[:dynamic, '()'], [:static, '()']], %q|"#{()}()"|) } it { assert_compile([[:static, ' '], [:dynamic, %q[ " #{ '#{}' } " ]]], %q|" #{ " #{ '#{}' } " }"|) } it { assert_compile([[:static, 'a'], [:dynamic, 'b'], [:static, 'c'], [:dynamic, 'd'], [:static, 'e']], %q|%Q[a#{b}c#{d}e]|) } it { assert_compile([[:static, 'a#{b}c#{d}e']], %q|%q[a#{b}c#{d}e]|) } it { assert_compile([[:static, '#{}'], [:dynamic, '123']], %q|"\#{}#{123}"|) } it { assert_compile([[:dynamic, " '}' "]], %q|"#{ '}' }"|) } it { assert_compile([[:static, 'a']], %q| "a" # hello |) } it { assert_compile([[:static, '"']], %q|"\""|) } it { assert_compile([[:static, '\\"']], %q|"\\\\\\""|) } it { assert_compile([[:static, '\"']], %q|'\"'|) } it { assert_compile([[:static, '\"']], %q|'\\"'|) } it { assert_compile([[:static, '\\"']], %q|'\\\"'|) } describe 'invalid argument' do it 'raises internal error' do assert_raises Haml::InternalError do Haml::StringSplitter.compile('1') end end it 'raises internal error' do assert_raises Haml::InternalError do Haml::StringSplitter.compile('[]') end end it 'raises internal error' do if /java/ === RUBY_PLATFORM skip 'Ripper of JRuby is behaving in a different way' end assert_raises Haml::InternalError do Haml::StringSplitter.compile('"]') end end end end if RUBY_ENGINE != 'truffleruby' # truffleruby doesn't have Ripper.lex end haml-6.3.0/test/haml/template_test.rb000066400000000000000000000262431453526310700175550ustar00rootroot00000000000000require 'test_helper' require 'haml/mocks/article' require 'action_pack/version' require 'haml/rails_template' module Haml::RailsHelpers def test_partial(name, locals = {}) Haml::Template.new { File.read(File.join(TemplateTest::TEMPLATE_PATH, "_#{name}.haml")) }.render(self, locals) end end class Egocentic def method_missing(*args) self end end class DummyController attr_accessor :logger def initialize @logger = Egocentic.new end def self.controller_path '' end def controller_path '' end end class TemplateTest < Haml::TestCase TEMPLATE_PATH = File.join(File.dirname(__FILE__), "templates") TEMPLATES = [ 'very_basic', #'standard', #'helpers', #'whitespace_handling', 'original_engine', 'list', 'helpful', 'silent_script', 'tag_parsing', #'just_stuff', #'partials', #'nuke_outer_whitespace', #'nuke_inner_whitespace', #'render_layout', #'partial_layout', 'partial_layout_erb', ] def setup @base = create_base # filters template uses :sass # Sass::Plugin.options.update(:line_comments => true, :style => :compact) end def create_base vars = { 'article' => Article.new, 'foo' => 'value one' } context = ActionView::LookupContext.new(TEMPLATE_PATH) base = ActionView::Base.new(context, vars, ActionController::Base.new) # This is needed by RJS in (at least) Rails 3 base.instance_variable_set(:@template, base) # This is used by form_for. # It's usually provided by ActionController::Base. def base.protect_against_forgery?; false; end def base.compiled_method_container() self.class; end base end def render(text, options = {}) return @base.render(:inline => text, :type => :haml) if options == :action_view options = options.merge(:format => :xhtml) super(text, options, @base) end def load_result(name) @result = '' File.new(File.dirname(__FILE__) + "/results/#{name}.xhtml").each_line { |l| @result += l } @result end def assert_renders_correctly(name, &render_method) render_method ||= proc { |n| @base.render(template: n) } silence_warnings do load_result(name).split("\n").zip(render_method[name].split("\n")).each_with_index do |pair, line| message = "template: #{name}\nline: #{line}" assert_equal(pair.first, pair.last, message) end end rescue ActionView::Template::Error => e if e.message =~ /Can't run [\w:]+ filter; required (one of|file) ((?:'\w+'(?: or )?)+)(, but none were found| not found)/ puts "\nCouldn't require #{$2}; skipping a test." else raise e end end def test_empty_render_should_remain_empty assert_equal('', render('')) end TEMPLATES.each do |template| define_method "test_template_should_render_correctly [template: #{template}]" do assert_renders_correctly template end end def test_templates skip TEMPLATES end def test_render_method_returning_null_with_ugly; skip @base.instance_eval do def empty nil end def render_something(&block) capture(self, &block) end end content_to_render = "%h1 This is part of the broken view.\n= render_something do |thing|\n = thing.empty do\n = 'test'" result = render(content_to_render, :ugly => true) expected_result = "

This is part of the broken view.

\n" assert_equal(expected_result, result) end def test_simple_rendering_with_ugly skip assert_haml_ugly("%p test\n= capture { 'foo' }") end def test_templates_should_render_correctly_with_render_proc; skip assert_renders_correctly("standard") do |name| engine = Haml::HamlEngine.new(File.read(File.dirname(__FILE__) + "/templates/#{name}.haml"), :format => :xhtml) engine.render_proc(@base).call end end def test_templates_should_render_correctly_with_def_method; skip assert_renders_correctly("standard") do |name| engine = Haml::HamlEngine.new(File.read(File.dirname(__FILE__) + "/templates/#{name}.haml"), :format => :xhtml) engine.def_method(@base, "render_standard") @base.render_standard end end def test_instance_variables_should_work_inside_templates @base.instance_variable_set(:@content_for_layout, 'something') assert_haml_ugly("%p= @content_for_layout", scope: @base) @base.instance_eval("@author = 'Hampton Catlin'") assert_haml_ugly(".author= @author", scope: @base) @base.instance_eval("@author = 'Hampton'") assert_haml_ugly("= @author", scope: @base) @base.instance_eval("@author = 'Catlin'") assert_haml_ugly("= @author", scope: @base) end def test_instance_variables_should_work_inside_attributes skip @base.instance_eval("@author = 'hcatlin'") assert_haml_ugly("%p{:class => @author} foo") end def test_template_renders_should_eval assert_equal("2\n", render("= 1+1")) end def test_haml_options; skip old_options = Haml::Template.options.dup Haml::Template.options[:suppress_eval] = true old_base, @base = @base, create_base assert_renders_correctly("eval_suppressed") ensure skip @base = old_base Haml::Template.options = old_options end def test_with_output_buffer_with_ugly; skip assert_equal(< true))

foo baz

HTML %p foo -# Parenthesis required due to Rails 3.0 deprecation of block helpers -# that return strings. - (with_output_buffer do bar = "foo".gsub(/./) do |s| - "flup" - end) baz HAML end def test_exceptions_should_work_correctly; skip begin render("- raise 'oops!'") rescue Exception => e assert_equal("oops!", e.message) assert_match(/^\(haml\):1/, e.backtrace[0]) else assert false end template = < e assert_match(/^\(haml\):5/, e.backtrace[0]) else assert false end end def test_surround output = render(<'.html_safe do %span HAML assert_equal "
\n", output end def test_precede output = render(<'.html_safe do %span HAML assert_equal "
\n", output end def test_succeed output = render(<'.html_safe do %span HAML assert_equal "
\n", output end def test_form_builder_label_with_block; skip output = render(< :article, :html => {:class => nil, :id => nil}, :url => '' do |f| = f.label :title do Block content HAML fragment = Nokogiri::HTML.fragment output assert_equal "Block content", fragment.css('form label').first.content.strip end ## XSS Protection Tests def test_escape_html_option_set; skip assert Haml::Template.options[:escape_html] end def test_xss_protection; skip assert_equal("Foo & Bar\n", render('= "Foo & Bar"', :action_view)) end def test_xss_protection_with_safe_strings; skip assert_equal("Foo & Bar\n", render('= Haml::Util.html_safe("Foo & Bar")', :action_view)) end def test_xss_protection_with_bang; skip assert_haml_ugly('!= "Foo & Bar"', :action_view) end def test_xss_protection_in_interpolation; skip assert_equal("Foo & Bar\n", render('Foo #{"&"} Bar', :action_view)) end def test_xss_protection_in_attributes; skip assert_equal("
\n", render('%div{ "data-html" => "bar" }', :action_view)) end def test_xss_protection_in_attributes_with_safe_strings; skip assert_equal("
\n", render('%div{ "data-html" => "bar".html_safe }', :action_view)) end def test_xss_protection_with_bang_in_interpolation; skip assert_haml_ugly('! Foo #{"&"} Bar', :action_view) end def test_xss_protection_with_safe_strings_in_interpolation; skip assert_equal("Foo & Bar\n", render('Foo #{Haml::Util.html_safe("&")} Bar', :action_view)) end def test_xss_protection_with_mixed_strings_in_interpolation; skip assert_equal("Foo & Bar & Baz\n", render('Foo #{Haml::Util.html_safe("&")} Bar #{"&"} Baz', :action_view)) end def test_rendered_string_is_html_safe; skip assert(render("Foo").html_safe?) end def test_rendered_string_is_html_safe_with_action_view assert(render("Foo", :action_view).html_safe?) end def test_xss_protection_with_concat; skip assert_equal("Foo & Bar", render('- concat "Foo & Bar"', :action_view)) end def test_xss_protection_with_concat_with_safe_string; skip assert_equal("Foo & Bar", render('- concat(Haml::Util.html_safe("Foo & Bar"))', :action_view)) end def test_xss_protection_with_safe_concat; skip assert_equal("Foo & Bar", render('- safe_concat "Foo & Bar"', :action_view)) end ## Regression def test_xss_protection_with_nested_haml_tag; skip assert_equal(<
  • Content!
HTML - haml_tag :div do - haml_tag :ul do - haml_tag :li, "Content!" HAML end if defined?(ActionView::Helpers::PrototypeHelper) def test_rjs assert_equal(<hello world

\n|, result end it 'has preserve method' do result = compile_template(:haml, %q|= preserve "hello\nworld"|).render(Object.new, {}) assert_equal %Q|hello&#x000A;world\n|, result end describe 'escape_attrs' do it 'escapes attrs by default' do result = compile_template(:haml, %q|%div{ data: '