From c2b3b6494834db25dff6b59888c2852f9226706c Mon Sep 17 00:00:00 2001 From: Pirate Praveen Date: Fri, 27 Aug 2021 13:57:59 +0100 Subject: [PATCH] Import ruby-hamlit_2.15.1.orig.tar.gz [dgit import orig ruby-hamlit_2.15.1.orig.tar.gz] --- .github/FUNDING.yml | 1 + .github/workflows/bench.yml | 46 + .github/workflows/test.yml | 40 + .gitignore | 18 + CHANGELOG.md | 826 +++++++ Gemfile | 24 + LICENSE.txt | 47 + README.md | 150 ++ REFERENCE.md | 281 +++ Rakefile | 117 + benchmark/boolean_attribute.haml | 6 + benchmark/class_attribute.haml | 5 + benchmark/common_attribute.haml | 3 + benchmark/data_attribute.haml | 4 + .../dynamic_attributes/boolean_attribute.haml | 4 + .../dynamic_attributes/class_attribute.haml | 4 + .../dynamic_attributes/common_attribute.haml | 2 + .../dynamic_attributes/data_attribute.haml | 2 + .../dynamic_attributes/id_attribute.haml | 2 + benchmark/dynamic_boolean_attribute.haml | 4 + benchmark/dynamic_merger/benchmark.rb | 25 + benchmark/dynamic_merger/hello.haml | 50 + benchmark/dynamic_merger/hello.string | 50 + benchmark/etc/attribute_builder.haml | 5 + benchmark/etc/real_sample.haml | 888 +++++++ benchmark/etc/real_sample.rb | 11 + benchmark/etc/static_analyzer.haml | 1 + benchmark/etc/string_interpolation.haml | 2 + benchmark/etc/tags.haml | 3 + benchmark/etc/tags_loop.haml | 2 + benchmark/ext/build_data.rb | 17 + benchmark/ext/build_id.rb | 13 + benchmark/graph/graph.key | Bin 0 -> 402094 bytes benchmark/graph/graph.png | Bin 0 -> 204194 bytes benchmark/id_attribute.haml | 3 + benchmark/plain.haml | 4 + benchmark/script.haml | 4 + benchmark/slim/LICENSE | 21 + benchmark/slim/context.rb | 11 + benchmark/slim/run-benchmarks.rb | 94 + benchmark/slim/view.erb | 23 + benchmark/slim/view.haml | 18 + benchmark/slim/view.slim | 17 + benchmark/utils/benchmark_ips_extension.rb | 43 + bin/bench | 77 + bin/console | 11 + bin/ruby | 3 + bin/setup | 7 + bin/stackprof | 27 + bin/test | 24 + bin/update-haml | 125 + exe/hamlit | 6 + ext/hamlit/extconf.rb | 10 + ext/hamlit/hamlit.c | 537 +++++ ext/hamlit/hescape.c | 108 + ext/hamlit/hescape.h | 20 + hamlit.gemspec | 47 + lib/hamlit.rb | 13 + lib/hamlit/ambles.rb | 20 + lib/hamlit/attribute_builder.rb | 175 ++ lib/hamlit/attribute_compiler.rb | 128 + lib/hamlit/attribute_parser.rb | 110 + lib/hamlit/cli.rb | 154 ++ lib/hamlit/compiler.rb | 97 + lib/hamlit/compiler/children_compiler.rb | 126 + lib/hamlit/compiler/comment_compiler.rb | 39 + lib/hamlit/compiler/doctype_compiler.rb | 46 + lib/hamlit/compiler/script_compiler.rb | 106 + lib/hamlit/compiler/silent_script_compiler.rb | 24 + lib/hamlit/compiler/tag_compiler.rb | 76 + lib/hamlit/dynamic_merger.rb | 67 + lib/hamlit/engine.rb | 40 + lib/hamlit/error.rb | 15 + lib/hamlit/escapable.rb | 13 + lib/hamlit/filters.rb | 75 + lib/hamlit/filters/base.rb | 12 + lib/hamlit/filters/cdata.rb | 20 + lib/hamlit/filters/coffee.rb | 17 + lib/hamlit/filters/css.rb | 33 + lib/hamlit/filters/erb.rb | 10 + lib/hamlit/filters/escaped.rb | 22 + lib/hamlit/filters/javascript.rb | 33 + lib/hamlit/filters/less.rb | 20 + lib/hamlit/filters/markdown.rb | 11 + lib/hamlit/filters/plain.rb | 29 + lib/hamlit/filters/preserve.rb | 22 + lib/hamlit/filters/ruby.rb | 10 + lib/hamlit/filters/sass.rb | 15 + lib/hamlit/filters/scss.rb | 15 + lib/hamlit/filters/text_base.rb | 25 + lib/hamlit/filters/tilt_base.rb | 49 + lib/hamlit/force_escapable.rb | 29 + lib/hamlit/helpers.rb | 15 + lib/hamlit/html.rb | 22 + lib/hamlit/identity.rb | 13 + lib/hamlit/object_ref.rb | 30 + lib/hamlit/parser.rb | 53 + lib/hamlit/parser/haml_attribute_builder.rb | 164 ++ lib/hamlit/parser/haml_buffer.rb | 238 ++ lib/hamlit/parser/haml_compiler.rb | 1 + lib/hamlit/parser/haml_error.rb | 65 + lib/hamlit/parser/haml_escapable.rb | 1 + lib/hamlit/parser/haml_generator.rb | 1 + lib/hamlit/parser/haml_helpers.rb | 709 ++++++ lib/hamlit/parser/haml_helpers/xss_mods.rb | 114 + lib/hamlit/parser/haml_options.rb | 273 +++ lib/hamlit/parser/haml_parser.rb | 860 +++++++ lib/hamlit/parser/haml_temple_engine.rb | 123 + lib/hamlit/parser/haml_util.rb | 258 ++ lib/hamlit/rails_helpers.rb | 51 + lib/hamlit/rails_template.rb | 64 + lib/hamlit/railtie.rb | 15 + lib/hamlit/ruby_expression.rb | 32 + lib/hamlit/string_splitter.rb | 20 + lib/hamlit/template.rb | 28 + lib/hamlit/temple_line_counter.rb | 31 + lib/hamlit/utils.rb | 20 + lib/hamlit/version.rb | 4 + test/haml/engine_test.rb | 2108 +++++++++++++++++ test/haml/erb/_av_partial_1.erb | 12 + test/haml/erb/_av_partial_2.erb | 8 + test/haml/erb/action_view.erb | 62 + test/haml/erb/standard.erb | 55 + test/haml/filters_test.rb | 262 ++ test/haml/gemfiles/.bundle/config | 1 + test/haml/gemfiles/Gemfile.rails-4.0.x | 10 + test/haml/gemfiles/Gemfile.rails-4.1.x | 4 + test/haml/gemfiles/Gemfile.rails-4.2.x | 4 + test/haml/haml-spec/LICENSE | 14 + test/haml/haml-spec/README.md | 106 + test/haml/haml-spec/Rakefile | 85 + test/haml/haml-spec/tests.yml | 538 +++++ test/haml/haml-spec/ugly_test.rb | 1110 +++++++++ test/haml/helper_test.rb | 698 ++++++ test/haml/markaby/standard.mab | 52 + test/haml/mocks/article.rb | 6 + test/haml/results/content_for_layout.xhtml | 12 + test/haml/results/eval_suppressed.xhtml | 9 + test/haml/results/helpers.xhtml | 72 + test/haml/results/helpful.xhtml | 13 + test/haml/results/just_stuff.xhtml | 68 + test/haml/results/list.xhtml | 12 + test/haml/results/nuke_inner_whitespace.xhtml | 40 + test/haml/results/nuke_outer_whitespace.xhtml | 140 ++ test/haml/results/original_engine.xhtml | 20 + test/haml/results/partial_layout.xhtml | 6 + test/haml/results/partial_layout_erb.xhtml | 6 + test/haml/results/partials.xhtml | 22 + test/haml/results/render_layout.xhtml | 3 + test/haml/results/silent_script.xhtml | 74 + test/haml/results/standard.xhtml | 159 ++ test/haml/results/tag_parsing.xhtml | 23 + test/haml/results/very_basic.xhtml | 5 + test/haml/results/whitespace_handling.xhtml | 94 + test/haml/template_test.rb | 371 +++ test/haml/templates/_av_partial_1.haml | 9 + test/haml/templates/_av_partial_1_ugly.haml | 9 + test/haml/templates/_av_partial_2.haml | 5 + test/haml/templates/_av_partial_2_ugly.haml | 5 + test/haml/templates/_layout.erb | 3 + test/haml/templates/_layout_for_partial.haml | 3 + test/haml/templates/_partial.haml | 8 + test/haml/templates/_text_area.haml | 3 + .../templates/_text_area_helper.html.haml | 4 + test/haml/templates/action_view.haml | 47 + test/haml/templates/action_view_ugly.haml | 47 + test/haml/templates/breakage.haml | 8 + test/haml/templates/content_for_layout.haml | 8 + test/haml/templates/eval_suppressed.haml | 11 + test/haml/templates/helpers.haml | 55 + test/haml/templates/helpful.haml | 11 + test/haml/templates/just_stuff.haml | 86 + test/haml/templates/list.haml | 12 + .../haml/templates/nuke_inner_whitespace.haml | 32 + .../haml/templates/nuke_outer_whitespace.haml | 144 ++ test/haml/templates/original_engine.haml | 17 + test/haml/templates/partial_layout.haml | 3 + test/haml/templates/partial_layout_erb.erb | 4 + test/haml/templates/partialize.haml | 1 + test/haml/templates/partials.haml | 12 + test/haml/templates/render_layout.haml | 2 + test/haml/templates/silent_script.haml | 45 + test/haml/templates/standard.haml | 43 + test/haml/templates/standard_ugly.haml | 43 + test/haml/templates/tag_parsing.haml | 21 + test/haml/templates/very_basic.haml | 4 + test/haml/templates/whitespace_handling.haml | 87 + test/haml/templates/with_bom.haml | 1 + test/hamlit/attribute_parser_test.rb | 101 + test/hamlit/cli_test.rb | 21 + test/hamlit/dynamic_merger_test.rb | 57 + test/hamlit/engine/attributes_test.rb | 361 +++ test/hamlit/engine/comment_test.rb | 75 + test/hamlit/engine/doctype_test.rb | 21 + test/hamlit/engine/indent_test.rb | 44 + test/hamlit/engine/multiline_test.rb | 46 + test/hamlit/engine/new_attribute_test.rb | 101 + test/hamlit/engine/old_attribute_test.rb | 476 ++++ test/hamlit/engine/script_test.rb | 146 ++ test/hamlit/engine/silent_script_test.rb | 222 ++ test/hamlit/engine/tag_test.rb | 200 ++ test/hamlit/engine/text_test.rb | 212 ++ test/hamlit/engine/whitespace_test.rb | 115 + test/hamlit/error_test.rb | 54 + test/hamlit/filters/cdata_test.rb | 27 + test/hamlit/filters/coffee_test.rb | 62 + test/hamlit/filters/css_test.rb | 35 + test/hamlit/filters/erb_test.rb | 19 + test/hamlit/filters/javascript_test.rb | 84 + test/hamlit/filters/markdown_test.rb | 42 + test/hamlit/filters/plain_test.rb | 26 + test/hamlit/filters/ruby_test.rb | 24 + test/hamlit/filters/sass_test.rb | 35 + test/hamlit/filters/scss_test.rb | 39 + test/hamlit/helpers_test.rb | 8 + test/hamlit/line_number_test.rb | 332 +++ test/hamlit/optimization_test.rb | 47 + test/hamlit/rails_template_test.rb | 166 ++ test/hamlit/ruby_expression_test.rb | 44 + test/hamlit/string_splitter_test.rb | 51 + test/hamlit/template_test.rb | 45 + test/test_helper.rb | 119 + 222 files changed, 19328 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/bench.yml create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 Gemfile create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 REFERENCE.md create mode 100644 Rakefile create mode 100644 benchmark/boolean_attribute.haml create mode 100644 benchmark/class_attribute.haml create mode 100644 benchmark/common_attribute.haml create mode 100644 benchmark/data_attribute.haml create mode 100644 benchmark/dynamic_attributes/boolean_attribute.haml create mode 100644 benchmark/dynamic_attributes/class_attribute.haml create mode 100644 benchmark/dynamic_attributes/common_attribute.haml create mode 100644 benchmark/dynamic_attributes/data_attribute.haml create mode 100644 benchmark/dynamic_attributes/id_attribute.haml create mode 100644 benchmark/dynamic_boolean_attribute.haml create mode 100644 benchmark/dynamic_merger/benchmark.rb create mode 100644 benchmark/dynamic_merger/hello.haml create mode 100644 benchmark/dynamic_merger/hello.string create mode 100644 benchmark/etc/attribute_builder.haml create mode 100644 benchmark/etc/real_sample.haml create mode 100644 benchmark/etc/real_sample.rb create mode 100644 benchmark/etc/static_analyzer.haml create mode 100644 benchmark/etc/string_interpolation.haml create mode 100644 benchmark/etc/tags.haml create mode 100644 benchmark/etc/tags_loop.haml create mode 100755 benchmark/ext/build_data.rb create mode 100755 benchmark/ext/build_id.rb create mode 100644 benchmark/graph/graph.key create mode 100644 benchmark/graph/graph.png create mode 100644 benchmark/id_attribute.haml create mode 100644 benchmark/plain.haml create mode 100644 benchmark/script.haml create mode 100644 benchmark/slim/LICENSE create mode 100644 benchmark/slim/context.rb create mode 100644 benchmark/slim/run-benchmarks.rb create mode 100644 benchmark/slim/view.erb create mode 100644 benchmark/slim/view.haml create mode 100644 benchmark/slim/view.slim create mode 100644 benchmark/utils/benchmark_ips_extension.rb create mode 100755 bin/bench create mode 100755 bin/console create mode 100755 bin/ruby create mode 100755 bin/setup create mode 100755 bin/stackprof create mode 100755 bin/test create mode 100755 bin/update-haml create mode 100755 exe/hamlit create mode 100644 ext/hamlit/extconf.rb create mode 100644 ext/hamlit/hamlit.c create mode 100644 ext/hamlit/hescape.c create mode 100644 ext/hamlit/hescape.h create mode 100644 hamlit.gemspec create mode 100644 lib/hamlit.rb create mode 100644 lib/hamlit/ambles.rb create mode 100644 lib/hamlit/attribute_builder.rb create mode 100644 lib/hamlit/attribute_compiler.rb create mode 100644 lib/hamlit/attribute_parser.rb create mode 100644 lib/hamlit/cli.rb create mode 100644 lib/hamlit/compiler.rb create mode 100644 lib/hamlit/compiler/children_compiler.rb create mode 100644 lib/hamlit/compiler/comment_compiler.rb create mode 100644 lib/hamlit/compiler/doctype_compiler.rb create mode 100644 lib/hamlit/compiler/script_compiler.rb create mode 100644 lib/hamlit/compiler/silent_script_compiler.rb create mode 100644 lib/hamlit/compiler/tag_compiler.rb create mode 100644 lib/hamlit/dynamic_merger.rb create mode 100644 lib/hamlit/engine.rb create mode 100644 lib/hamlit/error.rb create mode 100644 lib/hamlit/escapable.rb create mode 100644 lib/hamlit/filters.rb create mode 100644 lib/hamlit/filters/base.rb create mode 100644 lib/hamlit/filters/cdata.rb create mode 100644 lib/hamlit/filters/coffee.rb create mode 100644 lib/hamlit/filters/css.rb create mode 100644 lib/hamlit/filters/erb.rb create mode 100644 lib/hamlit/filters/escaped.rb create mode 100644 lib/hamlit/filters/javascript.rb create mode 100644 lib/hamlit/filters/less.rb create mode 100644 lib/hamlit/filters/markdown.rb create mode 100644 lib/hamlit/filters/plain.rb create mode 100644 lib/hamlit/filters/preserve.rb create mode 100644 lib/hamlit/filters/ruby.rb create mode 100644 lib/hamlit/filters/sass.rb create mode 100644 lib/hamlit/filters/scss.rb create mode 100644 lib/hamlit/filters/text_base.rb create mode 100644 lib/hamlit/filters/tilt_base.rb create mode 100644 lib/hamlit/force_escapable.rb create mode 100644 lib/hamlit/helpers.rb create mode 100644 lib/hamlit/html.rb create mode 100644 lib/hamlit/identity.rb create mode 100644 lib/hamlit/object_ref.rb create mode 100644 lib/hamlit/parser.rb create mode 100644 lib/hamlit/parser/haml_attribute_builder.rb create mode 100644 lib/hamlit/parser/haml_buffer.rb create mode 100644 lib/hamlit/parser/haml_compiler.rb create mode 100644 lib/hamlit/parser/haml_error.rb create mode 100644 lib/hamlit/parser/haml_escapable.rb create mode 100644 lib/hamlit/parser/haml_generator.rb create mode 100644 lib/hamlit/parser/haml_helpers.rb create mode 100644 lib/hamlit/parser/haml_helpers/xss_mods.rb create mode 100644 lib/hamlit/parser/haml_options.rb create mode 100644 lib/hamlit/parser/haml_parser.rb create mode 100644 lib/hamlit/parser/haml_temple_engine.rb create mode 100644 lib/hamlit/parser/haml_util.rb create mode 100644 lib/hamlit/rails_helpers.rb create mode 100644 lib/hamlit/rails_template.rb create mode 100644 lib/hamlit/railtie.rb create mode 100644 lib/hamlit/ruby_expression.rb create mode 100644 lib/hamlit/string_splitter.rb create mode 100644 lib/hamlit/template.rb create mode 100644 lib/hamlit/temple_line_counter.rb create mode 100644 lib/hamlit/utils.rb create mode 100644 lib/hamlit/version.rb create mode 100644 test/haml/engine_test.rb create mode 100644 test/haml/erb/_av_partial_1.erb create mode 100644 test/haml/erb/_av_partial_2.erb create mode 100644 test/haml/erb/action_view.erb create mode 100644 test/haml/erb/standard.erb create mode 100644 test/haml/filters_test.rb create mode 100644 test/haml/gemfiles/.bundle/config create mode 100644 test/haml/gemfiles/Gemfile.rails-4.0.x create mode 100644 test/haml/gemfiles/Gemfile.rails-4.1.x create mode 100644 test/haml/gemfiles/Gemfile.rails-4.2.x create mode 100644 test/haml/haml-spec/LICENSE create mode 100644 test/haml/haml-spec/README.md create mode 100644 test/haml/haml-spec/Rakefile create mode 100644 test/haml/haml-spec/tests.yml create mode 100644 test/haml/haml-spec/ugly_test.rb create mode 100644 test/haml/helper_test.rb create mode 100644 test/haml/markaby/standard.mab create mode 100644 test/haml/mocks/article.rb create mode 100644 test/haml/results/content_for_layout.xhtml create mode 100644 test/haml/results/eval_suppressed.xhtml create mode 100644 test/haml/results/helpers.xhtml create mode 100644 test/haml/results/helpful.xhtml create mode 100644 test/haml/results/just_stuff.xhtml create mode 100644 test/haml/results/list.xhtml create mode 100644 test/haml/results/nuke_inner_whitespace.xhtml create mode 100644 test/haml/results/nuke_outer_whitespace.xhtml create mode 100644 test/haml/results/original_engine.xhtml create mode 100644 test/haml/results/partial_layout.xhtml create mode 100644 test/haml/results/partial_layout_erb.xhtml create mode 100644 test/haml/results/partials.xhtml create mode 100644 test/haml/results/render_layout.xhtml create mode 100644 test/haml/results/silent_script.xhtml create mode 100644 test/haml/results/standard.xhtml create mode 100644 test/haml/results/tag_parsing.xhtml create mode 100644 test/haml/results/very_basic.xhtml create mode 100644 test/haml/results/whitespace_handling.xhtml create mode 100644 test/haml/template_test.rb create mode 100644 test/haml/templates/_av_partial_1.haml create mode 100644 test/haml/templates/_av_partial_1_ugly.haml create mode 100644 test/haml/templates/_av_partial_2.haml create mode 100644 test/haml/templates/_av_partial_2_ugly.haml create mode 100644 test/haml/templates/_layout.erb create mode 100644 test/haml/templates/_layout_for_partial.haml create mode 100644 test/haml/templates/_partial.haml create mode 100644 test/haml/templates/_text_area.haml create mode 100644 test/haml/templates/_text_area_helper.html.haml create mode 100644 test/haml/templates/action_view.haml create mode 100644 test/haml/templates/action_view_ugly.haml create mode 100644 test/haml/templates/breakage.haml create mode 100644 test/haml/templates/content_for_layout.haml create mode 100644 test/haml/templates/eval_suppressed.haml create mode 100644 test/haml/templates/helpers.haml create mode 100644 test/haml/templates/helpful.haml create mode 100644 test/haml/templates/just_stuff.haml create mode 100644 test/haml/templates/list.haml create mode 100644 test/haml/templates/nuke_inner_whitespace.haml create mode 100644 test/haml/templates/nuke_outer_whitespace.haml create mode 100644 test/haml/templates/original_engine.haml create mode 100644 test/haml/templates/partial_layout.haml create mode 100644 test/haml/templates/partial_layout_erb.erb create mode 100644 test/haml/templates/partialize.haml create mode 100644 test/haml/templates/partials.haml create mode 100644 test/haml/templates/render_layout.haml create mode 100644 test/haml/templates/silent_script.haml create mode 100644 test/haml/templates/standard.haml create mode 100644 test/haml/templates/standard_ugly.haml create mode 100644 test/haml/templates/tag_parsing.haml create mode 100644 test/haml/templates/very_basic.haml create mode 100644 test/haml/templates/whitespace_handling.haml create mode 100644 test/haml/templates/with_bom.haml create mode 100644 test/hamlit/attribute_parser_test.rb create mode 100644 test/hamlit/cli_test.rb create mode 100644 test/hamlit/dynamic_merger_test.rb create mode 100644 test/hamlit/engine/attributes_test.rb create mode 100644 test/hamlit/engine/comment_test.rb create mode 100644 test/hamlit/engine/doctype_test.rb create mode 100644 test/hamlit/engine/indent_test.rb create mode 100644 test/hamlit/engine/multiline_test.rb create mode 100644 test/hamlit/engine/new_attribute_test.rb create mode 100644 test/hamlit/engine/old_attribute_test.rb create mode 100644 test/hamlit/engine/script_test.rb create mode 100644 test/hamlit/engine/silent_script_test.rb create mode 100644 test/hamlit/engine/tag_test.rb create mode 100644 test/hamlit/engine/text_test.rb create mode 100644 test/hamlit/engine/whitespace_test.rb create mode 100644 test/hamlit/error_test.rb create mode 100644 test/hamlit/filters/cdata_test.rb create mode 100644 test/hamlit/filters/coffee_test.rb create mode 100644 test/hamlit/filters/css_test.rb create mode 100644 test/hamlit/filters/erb_test.rb create mode 100644 test/hamlit/filters/javascript_test.rb create mode 100644 test/hamlit/filters/markdown_test.rb create mode 100644 test/hamlit/filters/plain_test.rb create mode 100644 test/hamlit/filters/ruby_test.rb create mode 100644 test/hamlit/filters/sass_test.rb create mode 100644 test/hamlit/filters/scss_test.rb create mode 100644 test/hamlit/helpers_test.rb create mode 100644 test/hamlit/line_number_test.rb create mode 100644 test/hamlit/optimization_test.rb create mode 100644 test/hamlit/rails_template_test.rb create mode 100644 test/hamlit/ruby_expression_test.rb create mode 100644 test/hamlit/string_splitter_test.rb create mode 100644 test/hamlit/template_test.rb create mode 100644 test/test_helper.rb diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..36c8bcb --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: k0kubun diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml new file mode 100644 index 0000000..29ca59f --- /dev/null +++ b/.github/workflows/bench.yml @@ -0,0 +1,46 @@ +name: bench +on: + push: + branches: + - master + pull_request: + types: + - opened + - synchronize + - reopened + schedule: + - cron: "00 15 * * *" # 7:00 PST (-8), 8:00 PDT (-7) +jobs: + bench: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - slim: 1 + - template: 'benchmark/boolean_attribute.haml,benchmark/class_attribute.haml,benchmark/id_attribute.haml,benchmark/data_attribute.haml,benchmark/common_attribute.haml' + - template: 'benchmark/dynamic_attributes/boolean_attribute.haml,benchmark/dynamic_attributes/class_attribute.haml,benchmark/dynamic_attributes/id_attribute.haml,benchmark/dynamic_attributes/data_attribute.haml,benchmark/dynamic_attributes/common_attribute.haml' + - template: 'benchmark/etc/attribute_builder.haml' + - template: 'benchmark/etc/static_analyzer.haml' + - template: 'benchmark/etc/string_interpolation.haml' + - template: 'test/haml/templates/standard.haml' + compile: 1 + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.0 + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: ${{ runner.os }}-gems- + - run: sudo apt-get update && sudo apt-get install -y nodejs libxslt-dev # nodejs for execjs, libxslt for TruffleRuby nokogiri + - name: bundle install + run: bundle config path vendor/bundle && bundle install -j$(nproc) --retry 3 + - run: bundle exec rake bench + env: + SLIM_BENCH: ${{ matrix.slim }} + TEMPLATE: ${{ matrix.template }} + COMPILE: ${{ matrix.compile }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..074eded --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,40 @@ +name: test +on: + push: + branches: + - master + pull_request: + types: + - opened + - synchronize + - reopened + schedule: + - cron: "00 15 * * *" # 7:00 PST (-8), 8:00 PDT (-7) +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + ruby: + - '2.5' + - '2.6' + - '2.7' + - '3.0' + - jruby + - truffleruby-head + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: ${{ runner.os }}-gems- + - run: sudo apt-get update && sudo apt-get install -y nodejs libxslt-dev # nodejs for execjs, libxslt for TruffleRuby nokogiri + - name: bundle install + run: bundle config path vendor/bundle && bundle install -j$(nproc) --retry 3 + - run: bundle exec rake test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f20e4cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +/.bundle/ +/.yardoc +/Gemfile.lock +/_yardoc/ +/coverage/ +/doc/ +/pkg/ +/spec/reports/ +/tmp/ +/haml/ +.sass-cache +.ruby-version +*.bundle +*.so +*.su +*.a +*.o +*.swp diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ee39fad --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,826 @@ +# Change Log + +All notable changes to this project will be documented in this file. This +project adheres to [Semantic Versioning](http://semver.org/). This change log is based upon +[keep-a-changelog](https://github.com/olivierlacan/keep-a-changelog). + +## [2.15.1](https://github.com/k0kubun/hamlit/compare/v2.15.0...v2.15.1) - 2021-07-23 + +### Fixed + +- Remove `benchmark` from the gem package to reduce its size [#186](https://github.com/k0kubun/hamlit/issues/186) + *Thanks to @pocke* + +## [2.15.0](https://github.com/k0kubun/hamlit/compare/v2.14.6...v2.15.0) - 2021-04-12 + +### Added + +- Always use Hamlit when both haml.gem and hamlit.gem are installed in Rails + *Thanks to @igor-drozdov* + +## [2.14.6](https://github.com/k0kubun/hamlit/compare/v2.14.5...v2.14.6) - 2021-03-23 + +### Fixed + +- Optimize v2.14.5's implementation a little + +## [2.14.5](https://github.com/k0kubun/hamlit/compare/v2.14.4...v2.14.5) - 2021-03-23 + +### Added + +- Support `config.action_view.annotate_rendered_view_with_filenames = true` of Rails 6.1 + *Thanks to @kirin121* + +## [2.14.4](https://github.com/k0kubun/hamlit/compare/v2.14.3...v2.14.4) - 2021-02-01 + +### Fixed + +- Prevent another SEGV in a C extension after `GC.compact` [#177](https://github.com/k0kubun/hamlit/issues/177) + *Thanks to @stanhu* + +## [2.14.3](https://github.com/k0kubun/hamlit/compare/v2.14.2...v2.14.3) - 2021-01-24 + +### Fixed + +- Ensure the Rails initializer is called before `:load_config_initializers` [#176](https://github.com/k0kubun/hamlit/issues/176) + *Thanks to @sunny* + +## [2.14.2](https://github.com/k0kubun/hamlit/compare/v2.14.1...v2.14.2) - 2021-01-21 + +### Fixed + +- Prevent SEGV in a C extension after `GC.compact` [#171](https://github.com/k0kubun/hamlit/issues/171) + *Thanks to @stanhu* + +## [2.14.1](https://github.com/k0kubun/hamlit/compare/v2.14.0...v2.14.1) - 2021-01-07 + +### Added + +- Add `-c` option to `hamlit compile` that works like `haml -c` [#166](https://github.com/k0kubun/hamlit/issues/166) + *Thanks to @knightq* + +## [2.14.0](https://github.com/k0kubun/hamlit/compare/v2.13.2...v2.14.0) - 2021-01-07 + +### Changed + +- CLI changes + - Remove `-c` shorthand of `--color`. + - Make `--color` default. Please use `--no-color` to disable it. + - `--color` uses IRB instead of Pry for syntax highlight. + - Syntax highlight of `hamlit compile` is enabled only with IRB of Ruby 2.7+. + - Syntax highlight of `hamlit parse` / `hamlit temple` is enabled only with IRB of Ruby 3.1+. + +## [2.13.2](https://github.com/k0kubun/hamlit/compare/v2.13.1...v2.13.2) - 2020-12-27 + +### Added + +- Speed up `hamlit` commands [#166](https://github.com/k0kubun/hamlit/issues/166) + *Thanks to @knightq* + +## [2.13.1](https://github.com/k0kubun/hamlit/compare/v2.13.0...v2.13.1) - 2020-12-27 + +### Added + +- Support [multiline attributes](https://github.com/haml/haml/pull/1043) of Haml 5.2.1. + +## [2.13.0](https://github.com/k0kubun/hamlit/compare/v2.12.0...v2.13.0) - 2020-10-02 + +### Added + +- Support `--enable-frozen-string-literal` [#162](https://github.com/k0kubun/hamlit/issues/162). + *Thanks to @aliismayilov* + +### Changed + +- Upgrade the Haml parser from Haml 4.0 to 5.2 [#163](https://github.com/k0kubun/hamlit/issues/163). + - Allow `@` as tag's class name. + - Fix NameError on an `InvalidAttributeNameError` reference introduced at Hamlit v2.12.0. + - You can no longer specify `ugly` option, which has had no effect. + +## [2.12.0](https://github.com/k0kubun/hamlit/compare/v2.11.1...v2.12.0) - 2020-09-30 + +### Changed + +- Class names are no longer ordered alphabetically. + *Thanks to @aliismayilov* + - This is compatible with [Haml 5.2](https://github.com/haml/haml/blob/v5.2.0/CHANGELOG.md#52) + +## [2.11.1](https://github.com/k0kubun/hamlit/compare/v2.11.0...v2.11.1) - 2020-08-25 + +### Fixed + +- Fix a line number on an error after filters like preserve, plain, and ruby. + *Thanks to @rgisiger* + +## [2.11.0](https://github.com/k0kubun/hamlit/compare/v2.10.1...v2.11.0) - 2019-12-12 + +### Added + +- Support Haml's _revealed_ conditional comment feature on `/![if !IE]` [#153](https://github.com/k0kubun/hamlit/issues/153). + *Thanks to @esb* + +## [2.10.1](https://github.com/k0kubun/hamlit/compare/v2.10.0...v2.10.1) - 2019-11-28 + +### Added + +- Register `Hamlit::Template` to Tilt as :hamlit as well, in addition to :haml + +## [2.10.0](https://github.com/k0kubun/hamlit/compare/v2.9.5...v2.10.0) - 2019-09-15 + +### Added + +- Optimize template rendering by string interpolation [#146](https://github.com/k0kubun/hamlit/issues/146) + - Exploiting pre-allocation of string interpolation introduced in Ruby 2.5 [ruby/ruby#1626](https://github.com/ruby/ruby/pull/1626) + +### Changed + +- Require temple.gem >= 0.8.2 + +## [2.9.5](https://github.com/k0kubun/hamlit/compare/v2.9.4...v2.9.5) - 2019-09-08 + +### Added + +- Supported `:plain` filter in truffleruby + +## [2.9.4](https://github.com/k0kubun/hamlit/compare/v2.9.3...v2.9.4) - 2019-09-08 + +### Added + +- Experimental support of truffleruby [#145](https://github.com/k0kubun/hamlit/issues/145). + +## [2.9.3](https://github.com/k0kubun/hamlit/compare/v2.9.2...v2.9.3) - 2019-04-09 + +### Fixed + +- Fix deprecation warning on Rails 6 [#138](https://github.com/k0kubun/hamlit/issues/138). + *Thanks to @r7kamura* + +## [2.9.2](https://github.com/k0kubun/hamlit/compare/v2.9.1...v2.9.2) - 2018-11-30 + +### Fixed + +- Fix possible `autoload` failure of dependency [#131](https://github.com/k0kubun/hamlit/issues/131). + *Thanks to @wimrijnders* + +## [2.9.1](https://github.com/k0kubun/hamlit/compare/v2.9.0...v2.9.1) - 2018-11-01 + +### Added + +- Start supporting JRuby [#100](https://github.com/k0kubun/hamlit/issues/100). + +## [2.9.0](https://github.com/k0kubun/hamlit/compare/v2.8.10...v2.9.0) - 2018-10-16 + +### Added + +- Consider aria attribute as another attribute that supports hyphenation and boolean like data attribute + [#57](https://github.com/k0kubun/hamlit/pull/57). *Thanks to @francesco-loreti* + +## [2.8.10](https://github.com/k0kubun/hamlit/compare/v2.8.9...v2.8.10) - 2018-09-05 + +### Fixed + +- Fix uninitialized constant error introduced in v2.8.9 + [#125](https://github.com/k0kubun/hamlit/pull/125). *Thanks to @vovchynniko* + +## [2.8.9](https://github.com/k0kubun/hamlit/compare/v2.8.8...v2.8.9) - 2018-09-05 [YANKED] + +### Fixed + +- Don't raise an error on UTF-8 BOM [#117](https://github.com/k0kubun/hamlit/pull/117) + [#124](https://github.com/k0kubun/hamlit/pull/124). *Thanks to @southwolf* + +## [2.8.8](https://github.com/k0kubun/hamlit/compare/v2.8.7...v2.8.8) - 2018-04-06 + +### Fixed + +- Don't require Tilt dependencies if unregistered + [#121](https://github.com/k0kubun/hamlit/pull/121). *Thanks to @michaelglass* + +## [2.8.7](https://github.com/k0kubun/hamlit/compare/v2.8.6...v2.8.7) - 2018-02-17 + +### Fixed + +- Fix parser error on string interpolation in attributes + +## [2.8.6](https://github.com/k0kubun/hamlit/compare/v2.8.5...v2.8.6) - 2017-12-22 + +### Fixed + +- Fix some unused-variable / method-redefinition warnings + +## [2.8.5](https://github.com/k0kubun/hamlit/compare/v2.8.4...v2.8.5) - 2017-11-06 + +### Fixed + +- Fix lexer to work with Ripper of Ruby 2.5 + +## [2.8.4](https://github.com/k0kubun/hamlit/compare/v2.8.3...v2.8.4) - 2017-06-23 + +### Added + +- Allow filename `-` to read input from STDIN for `hamlit [parse|temple|compile|render]` + [#113](https://github.com/k0kubun/hamlit/issues/113). *Thanks to @gfx* + +## [2.8.3](https://github.com/k0kubun/hamlit/compare/v2.8.2...v2.8.3) - 2017-06-19 + +### Added + +- Add `--color` option to `hamlit parse` and `hamlit temple` commands too. + +## [2.8.2](https://github.com/k0kubun/hamlit/compare/v2.8.1...v2.8.2) - 2017-06-19 + +### Added + +- Add `--color` option to opt-in coloring in `hamlit compile` command + [#111](https://github.com/k0kubun/hamlit/issues/111). + +## [2.8.1](https://github.com/k0kubun/hamlit/compare/v2.8.0...v2.8.1) - 2017-04-03 + +### Fixed + +- Fix SEGV caused by nil in old attributes + [#101](https://github.com/k0kubun/hamlit/issues/101). *Thanks to @FND* + +## [2.8.0](https://github.com/k0kubun/hamlit/compare/v2.7.5...v2.8.0) - 2017-02-12 + +### Changed + +- Support Temple >= 0.8.0 and change to use StaticAnalyzer in Temple +- Optimize attribute building code a little + +## [2.7.5](https://github.com/k0kubun/hamlit/compare/v2.7.4...v2.7.5) - 2016-10-15 + +### Fixed + +- Resurrect `Hamlit::RailsTemplate.set_options` dropped in v2.7.4 unexpectedly. + +## [2.7.4](https://github.com/k0kubun/hamlit/compare/v2.7.3...v2.7.4) - 2016-10-15 [YANKED] + +### Fixed + +- Compile template as xhtml when ActionView regards template as text/xml + [#92](https://github.com/k0kubun/hamlit/issues/92). *Thank to @shmargum* + +## [2.7.3](https://github.com/k0kubun/hamlit/compare/v2.7.2...v2.7.3) - 2016-10-12 + +### Fixed + +- Regard download as an boolean attribute + [#91](https://github.com/k0kubun/hamlit/pull/91). *Thank to @pushcx* + +## [2.7.2](https://github.com/k0kubun/hamlit/compare/v2.7.1...v2.7.2) - 2016-09-19 + +### Fixed + +- Fix engine option warning + [#90](https://github.com/k0kubun/hamlit/issues/90). *Thank to @kikonen* + +## [2.7.1](https://github.com/k0kubun/hamlit/compare/v2.7.0...v2.7.1) - 2016-09-19 + +### Fixed + +- Fix Rails handler to use `ActionView::OutputBuffer` instead of `ActionView::SafeBuffer` to justify encoding + [#89](https://github.com/k0kubun/hamlit/pull/89). *Thanks to @akelmanson* + +## [2.7.0](https://github.com/k0kubun/hamlit/compare/v2.6.2...v2.7.0) - 2016-08-31 + +### Changed + +- Don't escape interpolated content in plain filter + [#87](https://github.com/k0kubun/hamlit/pull/87). *Thanks to @shmargum* + +## [2.6.2](https://github.com/k0kubun/hamlit/compare/v2.6.1...v2.6.2) - 2016-08-27 + +### Added + +- Add cdata filter + [#84](https://github.com/k0kubun/hamlit/issues/84). *Thanks to @shmargum* +- Minimize string allocation on template comipilation using `# frozen_string_literal: true` + +## [2.6.1](https://github.com/k0kubun/hamlit/compare/v2.6.0...v2.6.1) - 2016-08-18 + +### Fixed + +- For Rails, escape attributes even if it's html\_safe + - This is the same fix as Rails for [CVE-2016-6316](https://groups.google.com/forum/#!topic/ruby-security-ann/8B2iV2tPRSE) + +## [2.6.0](https://github.com/k0kubun/hamlit/compare/v2.5.0...v2.6.0) - 2016-08-14 + +### Changed + +- Stop using [houdini](https://github.com/vmg/houdini) and rewrite HTML escape function to resolve building or packaging problems [#82](https://github.com/k0kubun/hamlit/pull/82). + - No behavior is changed + +## [2.5.0](https://github.com/k0kubun/hamlit/compare/v2.4.2...v2.5.0) - 2016-06-04 + +### Changed + +- Don't escape the result of `preserve` helper in Rails + +## [2.4.2](https://github.com/k0kubun/hamlit/compare/v2.4.1...v2.4.2) - 2016-06-04 + +### Fixed + +- Regard cygwin and bccwin as Windows environment too + +## [2.4.1](https://github.com/k0kubun/hamlit/compare/v2.4.0...v2.4.1) - 2016-06-03 + +### Fixed + +- Fix C extension builder to work with Ruby 2.3 on Windows + [#69](https://github.com/k0kubun/hamlit/issues/69). *Thanks to @francesco-loreti* + +## [2.4.0](https://github.com/k0kubun/hamlit/compare/v2.3.1...v2.4.0) - 2016-05-13 + +### Added + +- Add `Hamlit::Helpers.preserve` method for Tilt templates + +## [2.3.1](https://github.com/k0kubun/hamlit/compare/v2.3.0...v2.3.1) - 2016-05-09 + +### Fixed + +- Specify Ruby version dependency on gemspec + [#67](https://github.com/k0kubun/hamlit/issues/67). *Thanks to @grosser* + +## [2.3.0](https://github.com/k0kubun/hamlit/compare/v2.2.3...v2.3.0) - 2016-04-24 + +### Added + +- Add `Hamlit::Filters.remove_filter` method + [#66](https://github.com/k0kubun/hamlit/issues/66). *Thanks to @connorshea* + +### Changed + +- `:coffeescript` filter's internal class name is changed from `Coffee` to `CoffeeScript` + +## [2.2.4](https://github.com/k0kubun/hamlit/compare/v2.2.3...v2.2.4) - 2017-12-05 + +### Fixed + +- Fix to work with Ruby 2.5. This version is usable with both 2.0 and 2.5. + +## [2.2.3](https://github.com/k0kubun/hamlit/compare/v2.2.2...v2.2.3) - 2016-03-10 + +### Added + +- Add `hamlit version` subcommand + [#60](https://github.com/k0kubun/hamlit/pull/60). *Thanks to @timoschilling* + +### Fixed + +- Fix load path for CLI + [#61](https://github.com/k0kubun/hamlit/pull/61). *Thanks to @timoschilling* + +## [2.2.2](https://github.com/k0kubun/hamlit/compare/v2.2.1...v2.2.2) - 2016-02-21 + +### Added + +- Optimize performance of plain filter + +### Fixed + +- Escape only interpolated text for plain filter + [#58](https://github.com/k0kubun/hamlit/issues/58). *Thanks to @shaneog* + +## [2.2.1](https://github.com/k0kubun/hamlit/compare/v2.2.0...v2.2.1) - 2016-02-06 + +### Added + +- Support Windows + [#54](https://github.com/k0kubun/hamlit/issues/54). *Thanks to @francesco-loreti* + +## [2.2.0](https://github.com/k0kubun/hamlit/compare/v2.1.2...v2.2.0) - 2015-12-24 + +### Added + +- Optimize inline script inside a tag +- Optimize string interpolation recursively + +## [2.1.2](https://github.com/k0kubun/hamlit/compare/v2.1.1...v2.1.2) - 2015-12-16 + +### Fixed + +- Fix rendering failure for static integer + [#50](https://github.com/k0kubun/hamlit/pull/50). *Thanks to @yatmsu* + +## [2.1.1](https://github.com/k0kubun/hamlit/compare/v2.1.0...v2.1.1) - 2015-12-15 + +### Fixed + +- Use faster HTML-escape method for compiling +- Show proper line number for unbalanced brackets error + +## [2.1.0](https://github.com/k0kubun/hamlit/compare/v2.0.2...v2.1.0) - 2015-12-14 + +### Added + +- `-I` and `-r` options are added to `hamlit render` command + [#37](https://github.com/k0kubun/hamlit/issues/37). *Thanks to @jhurliman* + +### Changed + +- Dropped obsolete `escape_utils` gem dependency + [#48](https://github.com/k0kubun/hamlit/pull/48). *Thanks to @eagletmt* + +### Fixed + +- Accept NUL character in attribute keys + [#49](https://github.com/k0kubun/hamlit/pull/49). *Thanks to @eagletmt* + +## [2.0.2](https://github.com/k0kubun/hamlit/compare/v2.0.1...v2.0.2) - 2015-12-12 + +### Fixed +- Fix a crash in compiling with CLI + [#46](https://github.com/k0kubun/hamlit/pull/46). *Thanks to @walf443* +- Use default engine options properly in CLI commands + +## [2.0.1](https://github.com/k0kubun/hamlit/compare/v2.0.0...v2.0.1) - 2015-11-30 + +### Fixed +- Fix build failure of native extension + +## [2.0.0](https://github.com/k0kubun/hamlit/compare/v1.7.2...v2.0.0) - 2015-11-30 [YANKED] +### Added +- Support object reference + +### Changed +- Full scratch of internal implementation + - Rendering is strongly optimized + - Static analyzer is introduced + - Built with C extension for runtime rendering + - Optimized compilation for 5 types of attributes + - Compilation became faster too + - Many rendering incompatibilities are resolved +- [**breaking**] Replaced parser with original Haml's one + - Incompatible parsing error will never happen, but we can no longer parse + attributes with Ripper +- [**breaking**] Unified behavior for both static and dynamic attributes, see + [5 types of attributes](REFERENCE.md#5-types-of-attributes) + - Though inconsistent behavior is removed, we can no longer rely on + completely-Haml-compatible behavior of static attributes and pass haml-spec +- [**breaking**] Added :escape\_attrs option + - You should specify HTML-escaping availability for script and attrs + separately. + +## [1.7.2](https://github.com/k0kubun/hamlit/compare/v1.7.1...v1.7.2) - 2015-07-22 + +### Fixed +- Bugfix about parsing a content of tag + - This was introduced in v1.6.6. + +## [1.7.1](https://github.com/k0kubun/hamlit/compare/v1.7.0...v1.7.1) - 2015-07-21 + +### Fixed +- Don't escape a block content of some helpers + [#35](https://github.com/k0kubun/hamlit/issues/35). *Thanks to @felixbuenemann* + +## [1.7.0](https://github.com/k0kubun/hamlit/compare/v1.6.7...v1.7.0) - 2015-07-09 + +### Added +- Support Ruby 2.2.0 hash syntax + - like `{ "hyphened-key": "value" }` + +## [1.6.7](https://github.com/k0kubun/hamlit/compare/v1.6.6...v1.6.7) - 2015-06-27 + +### Fixed +- Remove unused variables and avoid shadowing + - To suppress warnings in application using `rspec --warnings` + +## [1.6.6](https://github.com/k0kubun/hamlit/compare/v1.6.5...v1.6.6) - 2015-06-24 + +### Added +- Allow hyphenated HTML-style attributes + [pull #29](https://github.com/k0kubun/hamlit/pull/29). *thanks to @babelfish* + +## [1.6.5](https://github.com/k0kubun/hamlit/compare/v1.6.4...v1.6.5) - 2015-06-13 + +### Fixed +- Don't duplicate element class and attribute class +- Raise an error for an empty tag name + +## [1.6.4](https://github.com/k0kubun/hamlit/compare/v1.6.3...v1.6.4) - 2015-06-13 + +### Changed +- Show human-friendly error messages + +### Fixed +- Fix line number of runtime syntax error +- Increase the number of checked cases for illegal nesting. + *Thanks to @eagletmt* + +## [1.6.3](https://github.com/k0kubun/hamlit/compare/v1.6.2...v1.6.3) - 2015-06-13 + +### Fixed +- Fix ! and & parsing inside a tag + [#27](https://github.com/k0kubun/hamlit/issues/27#issuecomment-111593458). + *Thanks to @leesmith* + +## [1.6.2](https://github.com/k0kubun/hamlit/compare/v1.6.1...v1.6.2) - 2015-06-11 + +### Fixed +- Reject a content for self-closing tags +- Reject nesing within self-closing tags + +## [1.6.1](https://github.com/k0kubun/hamlit/compare/v1.6.0...v1.6.1) - 2015-06-11 + +### Fixed +- Parse N-space indentation + [#26](https://github.com/k0kubun/hamlit/issues/26). *Thanks to @eagletmt* + +## [1.6.0](https://github.com/k0kubun/hamlit/compare/v1.5.9...v1.6.0) - 2015-06-11 + +### Fixed +- Fix line number of compiled code for new attributes +- Render HTML entities normally for plain text + [#27](https://github.com/k0kubun/hamlit/issues/27). *Thanks to @jeffblake* + +## [1.5.9](https://github.com/k0kubun/hamlit/compare/v1.5.8...v1.5.9) - 2015-06-08 + +### Fixed +- Reject silent script after a tag + +## [1.5.8](https://github.com/k0kubun/hamlit/compare/v1.5.7...v1.5.8) - 2015-06-08 + +### Fixed +- Fix parsing inline script for != and &= + +## [1.5.7](https://github.com/k0kubun/hamlit/compare/v1.5.6...v1.5.7) - 2015-06-08 + +### Fixed +- Fix the behavior for multi-line script + +## [1.5.6](https://github.com/k0kubun/hamlit/compare/v1.5.5...v1.5.6) - 2015-06-07 + +### Added +- Raise error for unbalanced brackets + +### Changed +- Don't render newline after block script + +## [1.5.5](https://github.com/k0kubun/hamlit/compare/v1.5.4...v1.5.5) - 2015-06-07 + +### Added +- Support &, &== operator + +### Changed +- Depend on v0.7.6 of temple for refactoring + +### Fixed +- Fix a trivial diff of rendering multiline operator + +## [1.5.4](https://github.com/k0kubun/hamlit/compare/v1.5.3...v1.5.4) - 2015-06-07 + +### Changed +- Recursively remove whitespace inside a tag + +### Fixed +- Fix ! operator immediately before whitespace + +## [1.5.3](https://github.com/k0kubun/hamlit/compare/v1.5.2...v1.5.3) - 2015-06-06 + +### Added +- Support !, !=, !==, &= and ~ as inline operators + +## [1.5.2](https://github.com/k0kubun/hamlit/compare/v1.5.1...v1.5.2) - 2015-06-06 + +### Changed +- Disable html escaping in CSS and JavaScript filter + +## [1.5.1](https://github.com/k0kubun/hamlit/compare/v1.5.0...v1.5.1) - 2015-06-05 + +### Changed +- Remove outer whitespace in the block + +## [1.5.0](https://github.com/k0kubun/hamlit/compare/v1.4.7...v1.5.0) - 2015-06-03 + +### Changed +- Remake implementation of outer whitespace removal + +## [1.4.7](https://github.com/k0kubun/hamlit/compare/v1.4.6...v1.4.7) - 2015-06-03 + +### Changed +- Sort static old attributes by name + +### Fixed +- Bugfix for old array attributes with class element + +## [1.4.6](https://github.com/k0kubun/hamlit/compare/v1.4.5...v1.4.6) - 2015-06-03 + +### Added +- Support `!==`, `==` operator + +### Fixed +- Avoid regarding spaced block as multiline + +## [1.4.5](https://github.com/k0kubun/hamlit/compare/v1.4.4...v1.4.5) - 2015-06-02 + +### Fixed +- Support Ruby 2.0 and 2.1 for v1.4.4 + +## [1.4.4](https://github.com/k0kubun/hamlit/compare/v1.4.3...v1.4.4) - 2015-06-02 [YANKED] + +### Fixed +- Fix old attribute parser to be more flexible + - Accept multiple hashes as old attributes + - Accept old attributes with hash and literal + +## [1.4.3](https://github.com/k0kubun/hamlit/compare/v1.4.2...v1.4.3) - 2015-06-02 + +### Changed +- Allow `when` to have multiple candidates +- Allow `rescue` to specify an error variable + +## [1.4.2](https://github.com/k0kubun/hamlit/compare/v1.4.1...v1.4.2) - 2015-05-31 + +### Added +- Support `!` operator + - It disables html escaping for interpolated text + +## [1.4.1](https://github.com/k0kubun/hamlit/compare/v1.4.0...v1.4.1) - 2015-05-31 + +### Fixed +- Fix code mistake in 1.4.0 + +## [1.4.0](https://github.com/k0kubun/hamlit/compare/v1.3.2...v1.4.0) - 2015-05-31 [YANKED] + +### Added +- Escape interpolated string in plain text + +## [1.3.2](https://github.com/k0kubun/hamlit/compare/v1.3.1...v1.3.2) - 2015-05-30 + +- Render `begin`, `rescue` and `ensure` + +## [1.3.1](https://github.com/k0kubun/hamlit/compare/v1.3.0...v1.3.1) - 2015-05-30 + +### Fixed +- Bugfix about a backslash-only comment +- Don't strip a plain text + +## [1.3.0](https://github.com/k0kubun/hamlit/compare/v1.2.1...v1.3.0) - 2015-05-16 + +### Added +- Resurrect escape\_html option + [#25](https://github.com/k0kubun/hamlit/issues/25). + *Thanks to @resistorsoftware* + - Still enabled by default + - This has been dropped since v0.6.0 + +## [1.2.1](https://github.com/k0kubun/hamlit/compare/v1.2.0...v1.2.1) - 2015-05-15 + +### Fixed +- Fix the list of boolean attributes + [#24](https://github.com/k0kubun/hamlit/issues/24). *Thanks to @jeffblake* + +## [1.2.0](https://github.com/k0kubun/hamlit/compare/v1.1.1...v1.2.0) - 2015-05-06 + +Added +- Support `succeed`, `precede` and `surround` + [#22](https://github.com/k0kubun/hamlit/issues/22). *Thanks to @sneakernets* + +## [1.1.1](https://github.com/k0kubun/hamlit/compare/v1.1.0...v1.1.1) - 2015-05-06 + +### Fixed +- Bugfix of rendering array attributes + +## [1.1.0](https://github.com/k0kubun/hamlit/compare/v1.0.0...v1.1.0) - 2015-05-06 + +### Fixed +- Join id and class attributes + [#23](https://github.com/k0kubun/hamlit/issues/23). + *Thanks to @felixbuenemann* + +## [1.0.0](https://github.com/k0kubun/hamlit/compare/v0.6.2...v1.0.0) - 2015-04-12 + +### Added +- Use escape\_utils gem for faster escape\_html + +## [0.6.2](https://github.com/k0kubun/hamlit/compare/v0.6.1...v0.6.2) - 2015-04-12 + +### Fixed +- Don't render falsy attributes + [#2](https://github.com/k0kubun/hamlit/issues/2). *Thanks to @eagletmt* + +## [0.6.1](https://github.com/k0kubun/hamlit/compare/v0.6.0...v0.6.1) - 2015-04-12 + +### Fixed +- Bugfix of line numbers for better error backtrace + [pull #19](https://github.com/k0kubun/hamlit/pull/19) + +## [0.6.0](https://github.com/k0kubun/hamlit/compare/v0.5.3...v0.6.0) - 2015-04-12 + +### Added +- Automatically escape html in all situations + [pull #18](https://github.com/k0kubun/hamlit/pull/18) + +## [0.5.3](https://github.com/k0kubun/hamlit/compare/v0.5.2...v0.5.3) - 2015-04-12 + +### Fixed +- Bugfix for syntax error in data attribute hash + [#17](https://github.com/k0kubun/hamlit/issues/17). *Thanks to @eagletmt* + +## [0.5.2](https://github.com/k0kubun/hamlit/compare/v0.5.1...v0.5.2) - 2015-04-12 + +### Fixed +- Bugfix for silent script without block + [#16](https://github.com/k0kubun/hamlit/issues/16). *Thanks to @eagletmt* + +## [0.5.1](https://github.com/k0kubun/hamlit/compare/v0.5.0...v0.5.1) - 2015-04-12 + +### Fixed +- Bugfix about duplicated id and class + [#4](https://github.com/k0kubun/hamlit/issues/4). *Thanks to @os0x* + +## [0.5.0](https://github.com/k0kubun/hamlit/compare/v0.4.3...v0.5.0) - 2015-04-12 + +### Fixed +- Escape special characters in attribute values + [#10](https://github.com/k0kubun/hamlit/issues/10). *Thanks to @mono0x, + @eagletmt* + +## [0.4.3](https://github.com/k0kubun/hamlit/compare/v0.4.2...v0.4.3) - 2015-04-12 + +### Fixed +- Allow empty else statement [#14](https://github.com/k0kubun/hamlit/issues/14). + *Thanks to @jeffblake* +- Accept comment-only script [#13](https://github.com/k0kubun/hamlit/issues/13). + *Thanks to @jeffblake* + +## [0.4.2](https://github.com/k0kubun/hamlit/compare/v0.4.1...v0.4.2) - 2015-04-05 + +### Fixed +- Bugfix about parsing nested attributes + [#12](https://github.com/k0kubun/hamlit/issues/12). *Thanks to @creasty* + +## [0.4.1](https://github.com/k0kubun/hamlit/compare/v0.4.0...v0.4.1) - 2015-04-05 + +### Removed +- Automatic escape html is sintara, consult `README.md`. + +### Fixed +- Escape haml operators by backslash + [#11](https://github.com/k0kubun/hamlit/issues/11). *Thanks to @mono0x* + +## [0.4.0](https://github.com/k0kubun/hamlit/compare/v0.3.4...v0.4.0) - 2015-04-05 [YANKED] + +### Added +- Automatically escape html in sinatra + +## [0.3.4](https://github.com/k0kubun/hamlit/compare/v0.3.3...v0.3.4) - 2015-04-02 + +### Fixed +- Allow tab indentation [#9](https://github.com/k0kubun/hamlit/issues/9). + *Thanks to @tdtds* + +## [0.3.3](https://github.com/k0kubun/hamlit/compare/v0.3.2...v0.3.3) - 2015-04-01 + +### Fixed +- Accept multi byte parsing [#8](https://github.com/k0kubun/hamlit/issues/8). + *Thanks to @machu* + +## [0.3.2](https://github.com/k0kubun/hamlit/compare/v0.3.1...v0.3.2) - 2015-03-31 + +### Fixed +- Bugfix for compiling old attributes [#7](https://github.com/k0kubun/hamlit/issues/7). + *Thanks to @creasty* + +## [0.3.1](https://github.com/k0kubun/hamlit/compare/v0.3.0...v0.3.1) - 2015-03-31 + +### Fixed +- Hyphenate data attributes [#5](https://github.com/k0kubun/hamlit/issues/5). + *Thanks to @os0x* + +## [0.3.0](https://github.com/k0kubun/hamlit/compare/v0.2.0...v0.3.0) - 2015-03-31 + +### Added +- Specify a version in dependency of temple + +## [0.2.0](https://github.com/k0kubun/hamlit/compare/v0.1.3...v0.2.0) - 2015-03-30 + +### Added +- Allow comments in script [#3](https://github.com/k0kubun/hamlit/issues/3). + *Thanks to @eagletmt* + +## [0.1.3](https://github.com/k0kubun/hamlit/compare/v0.1.2...v0.1.3) - 2015-03-30 + +### Fixed +- Bugfix for [#1](https://github.com/k0kubun/hamlit/issues/1) attribute nesting + on runtime. *Thanks to @eagletmt* + +## [0.1.2](https://github.com/k0kubun/hamlit/compare/v0.1.1...v0.1.2) - 2015-03-30 + +### Fixed +- Ignore false or nil values in attributes + - Partial fix for [#2](https://github.com/k0kubun/hamlit/issues/2). + *Thanks to @eagletmt* + +## [0.1.1](https://github.com/k0kubun/hamlit/compare/v0.1.0...v0.1.1) - 2015-03-30 + +### Removed +- Drop obsolete `--ugly` option for CLI + - Currently pretty mode is not implemented #2 + +## [0.1.0](https://github.com/k0kubun/hamlit/compare/9cf8216...v0.1.0) - 2015-03-30 + +- Initial release + - Passing haml-spec with ugly mode diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..9515326 --- /dev/null +++ b/Gemfile @@ -0,0 +1,24 @@ +source '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 hamlit.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 'faml' + gem 'stackprof' + end +end diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..bb938b0 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,47 @@ +Copyright (c) 2006-2019 Hampton Catlin and Natalie Weizenbaum + +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. + +=== + +The above license is applied to lib/hamlit/parser/*.rb and test/haml/*. +Everything else is licensed under: + +The MIT License (MIT) + +Copyright (c) 2015 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3211b67 --- /dev/null +++ b/README.md @@ -0,0 +1,150 @@ +# Hamlit + +[![Gem Version](https://badge.fury.io/rb/hamlit.svg)](http://badge.fury.io/rb/hamlit) +[![test](https://github.com/k0kubun/hamlit/workflows/test/badge.svg)](https://github.com/k0kubun/hamlit/actions?query=workflow%3Atest) + +Hamlit is a high performance [Haml](https://github.com/haml/haml) implementation. + +## Introduction + +### What is Hamlit? +Hamlit is another implementation of [Haml](https://github.com/haml/haml). +With some [limitations](REFERENCE.md#limitations) by design for performance, +Hamlit is **1.94x times faster** than original haml gem in [this benchmark](benchmark/slim/run-benchmarks.rb), +which is an HTML-escaped version of [slim-template/slim's one](https://github.com/slim-template/slim/blob/4.1.0/benchmarks/run-benchmarks.rb) for fairness. ([Result on Travis](https://travis-ci.org/github/k0kubun/hamlit/jobs/732178446)) + +Hamlit Benchmark + +``` + hamlit v2.13.0: 247404.4 i/s + erubi v1.9.0: 244356.4 i/s - 1.01x slower + slim v4.1.0: 238254.3 i/s - 1.04x slower + faml v0.8.1: 197293.2 i/s - 1.25x slower + haml v5.2.0: 127834.4 i/s - 1.94x slower +``` + +### Why is Hamlit faster? + +#### Less string concatenation by design +As written in [limitations](REFERENCE.md#limitations), Hamlit drops some not-so-important features which require +works on runtime. With the optimized language design, we can reduce the string concatenation +to build attributes. + +#### Static analyzer +Hamlit analyzes Ruby expressions with Ripper and render it on compilation if the expression +is static. And Hamlit can also compile string literal with string interpolation to reduce +string allocation and concatenation on runtime. + +#### C extension to build attributes +While Hamlit has static analyzer and static attributes are rendered on compilation, +dynamic attributes must be rendered on runtime. So Hamlit optimizes rendering on runtime +with C extension. + +## Usage + +Hamlit currently supports Ruby 2.1 and higher. See [REFERENCE.md](REFERENCE.md) for detail features of Hamlit. + +### Rails + +Add this line to your application's Gemfile or just replace `gem "haml"` with `gem "hamlit"`. +It enables rendering by Hamlit for \*.haml automatically. + +```rb +gem 'hamlit' +``` + +If you want to use view generator, consider using [hamlit-rails](https://github.com/mfung/hamlit-rails). + +### Sinatra + +Replace `gem "haml"` with `gem "hamlit"` in Gemfile, and require "hamlit". + +While Haml disables `escape_html` option by default, Hamlit enables it for security. +If you want to disable it, please write: + +```rb +set :haml, { escape_html: false } +``` + + +## Command line interface + +You can see compiled code or rendering result with "hamlit" command. + +```bash +$ gem install hamlit +$ hamlit --help +Commands: + hamlit compile HAML # Show compile result + hamlit help [COMMAND] # Describe available commands or one specific command + hamlit parse HAML # Show parse result + hamlit render HAML # Render haml template + hamlit temple HAML # Show temple intermediate expression + +$ cat in.haml +- user_id = 123 +%a{ href: "/users/#{user_id}" } + +# Show compiled code +$ hamlit compile in.haml +_buf = []; user_id = 123; +; _buf << ("\n".freeze); _buf = _buf.join + +# Render html +$ hamlit render in.haml + +``` + +## Contributing + +### Test latest version + +```rb +# Gemfile +gem 'hamlit', github: 'k0kubun/hamlit', submodules: true +``` + +### Development + +Contributions are welcomed. It'd be good to see +[Temple's EXPRESSIONS.md](https://github.com/judofyr/temple/blob/v0.7.6/EXPRESSIONS.md) +to learn Temple which is a template engine framework used in Hamlit. + +```bash +$ git clone --recursive https://github.com/k0kubun/hamlit +$ cd hamlit +$ bundle install + +# Run all tests +$ bundle exec rake test + +# Run one test +$ bundle exec ruby -Ilib:test -rtest_helper test/hamlit/line_number_test.rb -l 12 + +# Show compiling/rendering result of some template +$ bundle exec exe/hamlit compile in.haml +$ bundle exec exe/hamlit render in.haml + +# Use rails app to debug Hamlit +$ cd sample/rails +$ bundle install +$ bundle exec rails s +``` + +### Reporting an issue + +Please report an issue with following information: + +- Full error backtrace +- Haml template +- Ruby version +- Hamlit version +- Rails/Sinatra version + +### Coding styles + +Please follow the existing coding styles and do not send patches including cosmetic changes. + +## License + +Copyright (c) 2015 Takashi Kokubun diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 0000000..73d9baa --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,281 @@ +# Hamlit + +Basically Hamlit is the same as Haml. +See [Haml's tutorial](http://haml.info/tutorial.html) if you are not familiar with Haml's syntax. + +[REFERENCE - Haml Documentation](http://haml.info/docs/yardoc/file.REFERENCE.html) + +## Supported features + +See [Haml's reference](http://haml.info/docs/yardoc/file.REFERENCE.html) +for full features in original implementation. + +- [ ] Using Haml + - [x] Rails XSS Protection + - [x] Ruby Module + - [x] Options + - [ ] Encodings +- [x] Plain Text + - [x] Escaping: \ +- [ ] HTML Elements + - [x] Element Name: % + - [ ] Attributes: ` + - [x] :class and :id Attributes + - [x] HTML-style Attributes: () + - [x] Ruby 1.9-style Hashes + - [ ] Attribute Methods + - [x] Boolean Attributes + - [x] HTML5 Custom Data Attributes + - [x] Class and ID: . and # + - Implicit Div Elements + - [x] Empty (void) Tags: / + - [x] Whitespace Removal: > and < + - [x] Object Reference: [] +- [x] Doctype: !!! +- [x] Comments + - [x] HTML Comments: / + - [x] Conditional Comments: /[] + - [x] Haml Comments: -# +- [x] Ruby Evaluation + - [x] Inserting Ruby: = + - [x] Running Ruby: - + - [x] Ruby Blocks + - [x] Whitespace Preservation: ~ + - [x] Ruby Interpolation: #{} + - [x] Escaping HTML: &= + - [x] Unescaping HTML: != +- [ ] Filters + - [x] :cdata + - [x] :coffee + - [x] :css + - [x] :erb + - [x] :escaped + - [x] :javascript + - [x] :less + - [x] :markdown + - [ ] :maruku + - [x] :plain + - [x] :preserve + - [x] :ruby + - `haml_io` API is not supported. Use [hamlit-haml\_io.gem](https://github.com/hamlit/hamlit-haml_io) if you need. + - [x] :sass + - [x] :scss + - [ ] :textile + - [ ] Custom Filters +- [x] Helper Methods + - [x] preserve + - [x] surround + - [x] precede + - [x] succeed +- [x] Multiline: | +- [x] Whitespace Preservation +- [ ] Helpers + + +## Limitations + +### No Haml buffer +Hamlit uses `Array` as buffer for performance. So you can't touch Haml::Buffer from template when using Hamlit. + +### Haml helpers are still in development +At the same time, because some methods in `Haml::Helpers` require `Haml::Buffer`, they are not supported now. +But some helpers are supported on Rails. Some of not-implemented methods are planned to be supported. + +### Limited attributes hyphenation +In Haml, `%a{ foo: { bar: 'baz' } }` is rendered as ``, whatever foo is. +In Hamlit, this feature is supported only for aria and data attribute. Hamlit renders `%a{ data: { foo: 'bar' } }` +as `` because it's data attribute. This design allows us to reduce work on runtime +and the idea is originally in [Faml](https://github.com/eagletmt/faml). + +### Limited boolean attributes +In Haml, `%a{ foo: false }` is rendered as ``, whatever `foo` is. +In Hamlit, this feature is supported for only boolean attributes, which are defined by +http://www.w3.org/TR/xhtml1/guidelines.html or https://html.spec.whatwg.org/. +The list is the same as `ActionView::Helpers::TagHelper::BOOLEAN_ATTRIBUTES`. +In addition, aria-\* and data-\* is also regarded as boolean. + +Since `foo` is not boolean attribute, `%a{ foo: false }` is rendered as `` +This is the same behavior as Rails helpers. Also for `%a{ foo: nil }`, +Hamlit does not remove non-boolean attributes and render `` +(`foo` is not removed). This design allows us to reduce string concatenation and +is the only difference between Faml and Hamlit. + +You may be also interested in +[hamlit/hamlit-boolean\_attributes](https://github.com/hamlit/hamlit-boolean_attributes). + +## 5 Types of Attributes + +Haml has 3 types of attributes: id, class and others. +In addition, Hamlit treats aria/data and boolean attributes specially. +So there are 5 types of attributes in Hamlit. + +### id attribute +Almost the same behavior as Haml, except no hyphenation and boolean support. +Arrays are flattened, falsey values are removed (but attribute itself is not removed) +and merging multiple ids results in concatenation by "\_". + +```rb +# Input +#foo{ id: 'bar' } +%div{ id: %w[foo bar] } +%div{ id: ['foo', false, ['bar', nil]] } +%div{ id: false } + +# Output +
+
+
+
+``` + +### class attribute +Almost the same behavior as Haml, except no hyphenation and boolean support. +Arrays are flattened, falsey values are removed (but attribute itself is not removed) +and merging multiple classes results in unique alphabetical sort. + +```rb +# Input +.d.a(class='b c'){ class: 'c a' } +%div{ class: 'd c b a' } +%div{ class: ['d', nil, 'c', [false, 'b', 'a']] } +%div{ class: false } + +# Output +
+
+
+
+``` + +### aria / data attribute +Completely compatible with Haml, hyphenation and boolean are supported. + +```rb +# Input +%div{ data: { disabled: true } } +%div{ data: { foo: 'bar' } } + +# Output +
+
+``` + +aria attribute works in the same way as data attribute. + +### boolean attributes +No hyphenation but complete boolean support. + +```rb +# Input +%div{ disabled: 'foo' } +%div{ disabled: true } +%div{ disabled: false } + +# Output +
+
+
+``` + +List of boolean attributes is: + +``` +disabled readonly multiple checked autobuffer autoplay controls loop selected hidden scoped async +defer reversed ismap seamless muted required autofocus novalidate formnovalidate open pubdate +itemscope allowfullscreen default inert sortable truespeed typemustmatch +``` + +If you want to customize the list of boolean attributes, you can use +[hamlit/hamlit-boolean\_attributes](https://github.com/hamlit/hamlit-boolean_attributes). + +"aria-\*" and "data-\*" are also regarded as boolean. + +### other attributes +No hyphenation and boolean support. `false` is rendered as "false" (like Rails helpers). + +```rb +# Input +%input{ value: true } +%input{ value: false } + +# Output + + +``` + +## Engine options + +| Option | Default | Feature | +|:-------|:--------|:--------| +| escape\_html | true | HTML-escape for Ruby script and interpolation. This is false in Haml. | +| escape\_attrs | true | HTML-escape for Html attributes. | +| format | :html | You can set :xhtml to change boolean attribute's format. | +| attr\_quote | `'` | You can change attribute's wrapper to `"` or something. | + +### Set options for Rails + +```rb +# config/initializers/hamlit.rb or somewhere +Hamlit::RailsTemplate.set_options attr_quote: '"' +``` + +### Set options for Sinatra + +```rb +set :haml, { attr_quote: '"' } +``` + +## Ruby module + +`Hamlit::Template` is a module registered to `Tilt`. You can use it like: + +```rb +Hamlit::Template.new { "%strong Yay for HAML!" }.render +``` + +## Creating a custom filter + +Currently it doesn't have filter registering interface compatible with Haml. +But you can easily define and register a filter using Tilt like this. + +```rb +module Hamlit + class Filters + class Es6 < TiltBase + def compile(node) + # branch with `@format` here if you want + compile_html(node) + end + + private + + def compile_html(node) + temple = [:multi] + temple << [:static, ""] + temple + end + end + + register :es6, Es6 + end +end +``` + +After requiring the script, you can do: + +```haml +:es6 + const a = 1; +``` + +and it's rendered as: + +```html + +``` diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..a8554ff --- /dev/null +++ b/Rakefile @@ -0,0 +1,117 @@ +require 'bundler/setup' +require 'bundler/gem_tasks' + +# +# Prepend DevKit into compilation phase +# +if Gem.win_platform? + desc 'Activates DevKit' + task :devkit do + begin + require 'devkit' + rescue LoadError + abort 'Failed to load DevKit required for compilation' + end + end + task compile: :devkit +end + +require 'rake/testtask' +if /java/ === RUBY_PLATFORM + # require 'rake/javaextensiontask' + # Rake::JavaExtensionTask.new(:hamlit) do |ext| + # ext.ext_dir = 'ext/java' + # ext.lib_dir = 'lib/hamlit' + # end + + task :compile do + # dummy for now + end +else + require 'rake/extensiontask' + Rake::ExtensionTask.new(:hamlit) do |ext| + ext.lib_dir = 'lib/hamlit' + end +end + +Dir['benchmark/*.rake'].each { |b| import(b) } + +namespace :haml do + Rake::TestTask.new do |t| + t.libs << 'lib' << 'test' + files = Dir['test/haml/*_test.rb'] + files << 'test/haml/haml-spec/*_test.rb' + t.ruby_opts = %w[-rtest_helper] + t.test_files = files + t.verbose = true + end +end + +namespace :hamlit do + Rake::TestTask.new do |t| + t.libs << 'lib' << 'test' + t.ruby_opts = %w[-rtest_helper] + t.test_files = Dir['test/hamlit/**/*_test.rb'] + t.verbose = true + end +end + +namespace :test do + Rake::TestTask.new(:all) do |t| + t.libs << 'lib' << 'test' + files = Dir['test/hamlit/**/*_test.rb'] + files += Dir['test/haml/*_test.rb'] + files << 'test/haml/haml-spec/*_test.rb' + t.ruby_opts = %w[-rtest_helper] + t.test_files = files + t.verbose = true + end + + Rake::TestTask.new(:spec) do |t| + t.libs << 'lib' << 'test' + t.ruby_opts = %w[-rtest_helper] + t.test_files = %w[test/haml/haml-spec/ugly_test.rb test/haml/haml-spec/pretty_test.rb] + t.verbose = true + end + + Rake::TestTask.new(:engine) do |t| + t.libs << 'lib' << 'test' + t.ruby_opts = %w[-rtest_helper] + t.test_files = %w[test/haml/engine_test.rb] + t.verbose = true + end + + Rake::TestTask.new(:filters) do |t| + t.libs << 'lib' << 'test' + t.ruby_opts = %w[-rtest_helper] + t.test_files = %w[test/haml/filters_test.rb] + t.verbose = true + end + + Rake::TestTask.new(:helper) do |t| + t.libs << 'lib' << 'test' + t.ruby_opts = %w[-rtest_helper] + t.test_files = %w[test/haml/helper_test.rb] + t.verbose = true + end + + Rake::TestTask.new(:template) do |t| + t.libs << 'lib' << 'test' + t.ruby_opts = %w[-rtest_helper] + t.test_files = %w[test/haml/template_test.rb] + t.verbose = true + end +end + +desc 'bench task for CI' +task bench: :compile do + if ENV['SLIM_BENCH'] == '1' + cmd = %w[bundle exec ruby benchmark/slim/run-benchmarks.rb] + else + cmd = ['bin/bench', 'bench', ('-c' if ENV['COMPILE'] == '1'), *ENV['TEMPLATE'].split(',')].compact + end + exit system(*cmd) +end + +task default: %w[compile hamlit:test] +task test: %w[compile test:all] diff --git a/benchmark/boolean_attribute.haml b/benchmark/boolean_attribute.haml new file mode 100644 index 0000000..82587a6 --- /dev/null +++ b/benchmark/boolean_attribute.haml @@ -0,0 +1,6 @@ +%input{ disabled: false } +%input{ disabled: true } +- disabled = false +%input{ disabled: disabled } +- disabled = true +%input{ disabled: disabled } diff --git a/benchmark/class_attribute.haml b/benchmark/class_attribute.haml new file mode 100644 index 0000000..2faaf7e --- /dev/null +++ b/benchmark/class_attribute.haml @@ -0,0 +1,5 @@ +.book{ class: 'content active' } +.book(class='content active') + +- klass = %w[content active] +.book{ class: klass } diff --git a/benchmark/common_attribute.haml b/benchmark/common_attribute.haml new file mode 100644 index 0000000..7516da9 --- /dev/null +++ b/benchmark/common_attribute.haml @@ -0,0 +1,3 @@ +%a{ href: '&"\'<>' } +- href = '&"\'<>' +%a{ href: href } diff --git a/benchmark/data_attribute.haml b/benchmark/data_attribute.haml new file mode 100644 index 0000000..b2ba20c --- /dev/null +++ b/benchmark/data_attribute.haml @@ -0,0 +1,4 @@ +%div{ data: { disabled: false } } +%div{ data: { disabled: true } } +- hash = { 'user' => { id: 1234, name: 'k0kubun' }, book_id: 5432 } +%div{ data: hash } data diff --git a/benchmark/dynamic_attributes/boolean_attribute.haml b/benchmark/dynamic_attributes/boolean_attribute.haml new file mode 100644 index 0000000..f619d53 --- /dev/null +++ b/benchmark/dynamic_attributes/boolean_attribute.haml @@ -0,0 +1,4 @@ +- hash = { disabled: false } +%input{ hash } +- hash = { disabled: true } +%input{ hash } diff --git a/benchmark/dynamic_attributes/class_attribute.haml b/benchmark/dynamic_attributes/class_attribute.haml new file mode 100644 index 0000000..3c750de --- /dev/null +++ b/benchmark/dynamic_attributes/class_attribute.haml @@ -0,0 +1,4 @@ +- hash = { class: %w[content active] } +.book{ hash } +- arr = %w[foo bar] +.book(class=arr){ hash } diff --git a/benchmark/dynamic_attributes/common_attribute.haml b/benchmark/dynamic_attributes/common_attribute.haml new file mode 100644 index 0000000..9c3e19f --- /dev/null +++ b/benchmark/dynamic_attributes/common_attribute.haml @@ -0,0 +1,2 @@ +- hash = { href: '&"\'<>' } +%a{ hash } diff --git a/benchmark/dynamic_attributes/data_attribute.haml b/benchmark/dynamic_attributes/data_attribute.haml new file mode 100644 index 0000000..a53d89b --- /dev/null +++ b/benchmark/dynamic_attributes/data_attribute.haml @@ -0,0 +1,2 @@ +- hash = { data: { 'user' => { id: 1234, name: 'k0kubun' }, book_id: 5432 } } +%div{ hash } data diff --git a/benchmark/dynamic_attributes/id_attribute.haml b/benchmark/dynamic_attributes/id_attribute.haml new file mode 100644 index 0000000..2969893 --- /dev/null +++ b/benchmark/dynamic_attributes/id_attribute.haml @@ -0,0 +1,2 @@ +- hash = { id: %w[content active] } +#book{ hash } diff --git a/benchmark/dynamic_boolean_attribute.haml b/benchmark/dynamic_boolean_attribute.haml new file mode 100644 index 0000000..e8b9c90 --- /dev/null +++ b/benchmark/dynamic_boolean_attribute.haml @@ -0,0 +1,4 @@ +- disabled = false +%input{ disabled: disabled } +- disabled = true +%input{ disabled: disabled } diff --git a/benchmark/dynamic_merger/benchmark.rb b/benchmark/dynamic_merger/benchmark.rb new file mode 100644 index 0000000..220281f --- /dev/null +++ b/benchmark/dynamic_merger/benchmark.rb @@ -0,0 +1,25 @@ +# Original: https://github.com/amatsuda/string_template/blob/master/benchmark.rb +require 'benchmark_driver' + +Benchmark.driver(repeat_count: 8) do |x| + x.prelude %{ + require 'rails' + require 'action_view' + require 'string_template' + StringTemplate::Railtie.run_initializers + require 'hamlit' + Hamlit::Railtie.run_initializers + Hamlit::RailsTemplate.set_options(escape_html: false, generator: Temple::Generators::ArrayBuffer) + require 'action_view/base' + + (view = Class.new(ActionView::Base).new(ActionView::LookupContext.new(''))).instance_variable_set(:@world, 'world!') + + # compile template + hello = 'benchmark/dynamic_merger/hello' + view.render(template: hello, handlers: 'string') + view.render(template: hello, handlers: 'haml') + } + x.report 'string', %{ view.render(template: hello, handlers: 'string') } + x.report 'hamlit', %{ view.render(template: hello, handlers: 'haml') } + x.loop_count 100_000 +end diff --git a/benchmark/dynamic_merger/hello.haml b/benchmark/dynamic_merger/hello.haml new file mode 100644 index 0000000..57755b0 --- /dev/null +++ b/benchmark/dynamic_merger/hello.haml @@ -0,0 +1,50 @@ +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } diff --git a/benchmark/dynamic_merger/hello.string b/benchmark/dynamic_merger/hello.string new file mode 100644 index 0000000..57755b0 --- /dev/null +++ b/benchmark/dynamic_merger/hello.string @@ -0,0 +1,50 @@ +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } +hello, #{ @world } diff --git a/benchmark/etc/attribute_builder.haml b/benchmark/etc/attribute_builder.haml new file mode 100644 index 0000000..7c607e1 --- /dev/null +++ b/benchmark/etc/attribute_builder.haml @@ -0,0 +1,5 @@ +- h = { 'user' => { id: 1234, name: 'eagletmt' }, book_id: 5432 } +- c = %w[content active] + +%span.book{data: h, class: c} + Book diff --git a/benchmark/etc/real_sample.haml b/benchmark/etc/real_sample.haml new file mode 100644 index 0000000..1119690 --- /dev/null +++ b/benchmark/etc/real_sample.haml @@ -0,0 +1,888 @@ +#id-1 + = render partial: 'test' + + %ul#id-2.class-1.class-2 + + %section#id-3 + .class-3 string-1 + .class-4 + .class-5 string-2 + %pre.class-6(readonly="readonly" style='width:1px') + :preserve + .class-7 string-3 + + .class-8 string-4 + %pre.class-9(readonly="readonly" style='width:2px') + :preserve + .class-10 string-5 + %p + Hello world + + .class-12 string-6 + %pre.class-13(readonly="readonly" style='width:3px') + :preserve + .class-14 string-7 + %p + Hello world + + %section#id-4 + .class-17 string-8 + .class-18 + .class-19 string-9 + %pre.class-20(readonly="readonly" style='width:4px') + :preserve + .class-21 string-10 + + .class-22 string-11 + %pre.class-23(readonly="readonly" style='width:5px') + :preserve + .class-24 string-12 + + .class-25.class-26 Hello world + %pre.class-27(readonly="readonly" style='width:6px') + :preserve + .class-28.class-29 Hello world + + %section#id-5 + .class-30 string-13 + .class-31 string-14 + .class-32 + %pre.class-33(readonly="readonly" style='width:7px') + :preserve + .class-34 string-15 + + %section#id-6 + .class-35 string-16 + %ul.class-36.class-37 + %li + = link_to 'link', '#' + %li + = link_to 'link', '#', class: 'klass' + %li + = link_to 'link', '#', class: 'klass' + %li + = link_to 'link', '#', class: 'klass' + %li + = link_to 'link', '#', class: 'klass' + .class-38 + %p text-17 + %p text-18 + %pre.class-41(readonly="readonly" style='width:8px') + :preserve + %ul.class-42.class-43 + %li + = link_to 'link', '#' + %li + = link_to 'link', '#', class: 'klass' + %li + = link_to 'link', '#', class: 'klass' + %li + = link_to 'link', '#', class: 'klass' + %li + = link_to 'link', '#', class: 'klass' + + %section#id-7 + .class-44 string-19 + %ul.class-45.class-46 + %li#id-8 + = link_to 'link', '#', class: 'klass1 klass2' + .class-47.class-48.class-49 + Hello world + .class-50 + %pre.class-51(readonly="readonly" style='width:9px') + :preserve + %ul.class-52.class-53 + %li#id-10 + = link_to 'link', + '#id-11', + class: 'klass1 klass2' + .class-54.class-55.class-56 + Hello world + + %section#id-12 + .class-57 string-20 + %ul.class-58.class-59 + %li + = link_to 'link', '#' + .class-60 string-21 + .class-61 string-22 + %li + = link_to 'link', '#' + .class-62 string-23 + .class-63 string-24 + .class-64 + %pre.class-65(readonly="readonly" style='width:10px') + :preserve + %ul.class-66.class-67 + %li + = link_to 'link', '#' + .class-68 string-25 + .class-69 string-26 + %li + = link_to 'link', '#' + .class-70 string-27 + .class-71 string-28 + + %section#id-13 + .class-72 string-29 + %ul.class-73.class-74 + %li + = link_to 'link', '#' + .class-75 string-30 + .class-76 string-31 + %li + = link_to 'link', '#' + = image_tag 'https://google.com/favicon.ico', class: 'klass1' + .class-78 string-32 + %li + = link_to 'link', '#' + = image_tag 'https://google.com/favicon.ico', class: 'klass1' + .class-80 + .class-81 string-33 + .class-82 string-34 + %li + = link_to 'link', '#' + = image_tag 'https://google.com/favicon.ico', class: 'klass1' + .class-84 + .class-85 string-35 + .class-86 string-36 + %li + = link_to 'link', '#' + = image_tag 'https://google.com/favicon.ico', class: 'klass1' + .class-88 string-37 + .class-89 string-38 + .class-90 + %pre.class-91(readonly="readonly" style='width:11px') + :preserve + %ul.class-92.class-93 + %li + = link_to 'link', '#' + .class-94 string-39 + .class-95 string-40 + %li + = link_to 'link', '#' + = image_tag class: 'klass1' + .class-96 string-41 + %li + = link_to 'link', '#' + = image_tag class: 'klass1' + .class-97 + .class-98 string-42 + .class-99 string-43 + %li + = link_to 'link', '#' + = image_tag class: 'klass1' + .class-100 + .class-101 string-44 + .class-102 string-45 + %li + = link_to 'link', '#' + = image_tag class: 'klass1' + .class-103 string-46 + .class-104 string-47 + + %section#id-14 + .class-105 string-48 + %ul.class-106.class-107.class-108 + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + + .class-109 + %pre.class-110(readonly="readonly" style='width:12px') + :preserve + %ul.class-111.class-112.class-113 + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + + %section#id-15 + .class-114 string-49 + %ul.class-115.class-116.class-117 + %li + = link_to 'link', '#', class: 'klass' + = image_tag 'https://github.com/favicon.ico', class: 'klass' + .class-119 string-50 + %li + = link_to 'link', '#', class: 'klass' + = image_tag 'https://github.com/favicon.ico', class: 'klass' + .class-121 string-51 + %li + = link_to 'link', '#', class: 'klass' + = image_tag 'https://github.com/favicon.ico', class: 'klass' + .class-123 string-52 + %li + = link_to 'link', '#', class: 'klass' + = image_tag 'https://github.com/favicon.ico', class: 'klass' + .class-125 string-53 + + .class-126 + %pre.class-127(readonly="readonly" style='width:13px') + :preserve + %ul.class-128.class-129.class-130 + %li + = link_to 'link', '#' + = image_tag clsss: 'klass' + .class-131 string-54 + %li + = link_to 'link', '#' + = image_tag clsss: 'klass' + .class-132 string-55 + + %section#id-16 + .class-133 string-56 + %ul.class-134.class-135 + %li= link_to 'link', '#' + %li= link_to 'link', '#' + %li= link_to 'link', '#' + .class-136 + %pre.class-137(readonly="readonly" style='width:14px') + :preserve + %ul.class-138.class-139 + %li= link_to 'link', '#' + %li= link_to 'link', '#' + %li= link_to 'link', '#' + + %section#id-17 + .class-140 string-57 + .class-141 + %ul.class-142 + %li + = image_tag 'https://github.com/favicon.ico' + %li + = image_tag 'https://github.com/favicon.ico' + %li + = image_tag 'https://github.com/favicon.ico' + + + %pre.class-146(readonly="readonly" style='width:15px') + :preserve + %ul.class-147 + %li + = image_tag '' + %li + = image_tag '' + %li + = image_tag '' + + %section#id-18 + .class-148 string-58 + .class-149 + .class-150 + .class-151.class-152 + = image_tag 'https://github.com/favicon.ico' + .class-154.class-155 + .class-156-title string-59 + Hello world + + %pre.class-157(readonly="readonly" style='width:16px') + :preserve + .class-158 + .class-159.class-160 + Hello world + .class-161.class-162 + Hello world + + %p text-60 + + %section#id-19 + .class-164 string-61 + .class-165 + .class-166 + .class-167 + = image_tag 'https://github.com/favicon.ico' + .class-169 + = image_tag 'https://github.com/favicon.ico' + .class-171 + = image_tag 'https://github.com/favicon.ico' + + .class-173 + .class-174-title string-62 + str + + %pre.class-175(readonly="readonly" style='width:17px') + :preserve + .class-176 + .class-177 + = image_tag '' + .class-178 + = image_tag '' + .class-179 + = image_tag '' + .class-180 + content + %p text-63 + %p text-64 + + + %section#id-20 + .class-182 string-65 + .class-183 + %ul.class-184.class-185 + %li.class-186.class-187 + %span.class-188 str + %li.class-189 + = link_to 'link', '#', class: 'klass' + .class-190 + %pre.class-191(readonly="readonly" style='width:18px') + :preserve + .class-192 + %ul.class-193.class-194 + %li.class-195.class-196 + %span.class-197 str + %li.class-198 + = link_to 'link', '#', class: 'klass' + + %section#id-21 + .class-199 string-66 + .class-200 + %ul.class-201 + %li.class-202.class-203 + %span.class-204 str + %li.class-205 + = link_to 'link', '#', class: 'klass' + %li.class-206 + = link_to 'link', '#', class: 'klass' + .class-207 + %pre.class-208(readonly="readonly" style='width:19px') + :preserve + .class-209 + %ul.class-210 + %li.class-211.class-212 + %span.class-213 str + %li.class-214 + = link_to 'link', '#', class: 'klass' + %li.class-215 + = link_to 'link', '#', class: 'klass' + + %section#id-22 + .class-216 string-67 + %ul.class-217 + %li.class-218 + = link_to 'link', '#' + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + .class-219 + %pre.class-220(readonly="readonly" style='width:20px') + :preserve + %ul.class-221 + %li.class-222 + = link_to 'link', '#' + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + + %p text-68 + + %section#id-23 + .class-223 string-69 + %ul.class-224 + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + .class-225 + %pre.class-226(readonly="readonly" style='width:21px') + :preserve + %ul.class-227 + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + %li + = link_to 'link', '#' + + %section#id-24 + .class-228 string-70 + .class-229 + %a(href="#" class="button") Hello world + %p text-71 + %pre.class-230(readonly="readonly" style='width:22px') + :preserve + = link_to 'link', '#', class: 'klass' + + %a(href="#" class="button min") Hello world + %pre.class-231(readonly="readonly" style='width:23px') + :preserve + = link_to 'link', '#', class: 'klass' + + %section#id-25 + .class-232 string-72 + .class-233 + %a(href="#" class="klass") Hello world + %p text-73 + %pre.class-234(readonly="readonly" style='width:24px') + :preserve + = link_to 'link', '#', + class: 'klass' + + %a(href="#" class="klass") Hello world + %pre.class-235(readonly="readonly" style='width:25px') + :preserve + = link_to 'link', '#', + class: 'klass' + + %a(href="#" class="klass") Hello world + %pre.class-236(readonly="readonly" style='width:26px') + :preserve + = link_to 'link', '#', + class: 'klass' + + %section#id-26 + .class-237 string-74 + .class-238 + %a(href="#" class="klass") Hello world + %p text-75 + %pre.class-239(readonly="readonly" style='width:27px') + :preserve + = link_to 'link', '#', + class: 'klass' + %a(href="#" class="klass") Hello world + %pre.class-240(readonly="readonly" style='width:28px') + :preserve + = link_to 'link', '#', + class: 'klass' + %a(href="#" class="klass") Hello world + %pre.class-241(readonly="readonly" style='width:29px') + :preserve + = link_to 'link', '#', + class: 'klass' + + %section#id-27 + .class-242 string-76 + .class-243 + %a(href="#" class="klass") Hello world + %p text-77 + %pre.class-244(readonly="readonly" style='width:30px') + :preserve + = link_to 'link', '#', + class: 'klass' + %a(href="#" class="klass") Hello world + %pre.class-245(readonly="readonly" style='width:31px') + :preserve + = link_to 'link', '#', + class: 'klass' + %a(href="#" class="klass") Hello world + %pre.class-246(readonly="readonly" style='width:32px') + :preserve + = link_to 'link', '#', + class: 'klass' + + %section#id-28 + .class-247 string-78 + %a(href="#" class="klass") + str + %span.class-248 + str + %b text-79 + str + .class-249 + %pre.class-250(readonly="readonly" style='width:33px') + :preserve + = link_to 'link', '#' + %span.class-251 + str + %b text-80 + str + + %section#id-29 + .class-252 string-81 + %label.class-253{for: 'f1_c1'} + %input{type: 'checkbox', id: 'f1_c1', checked: 'checked'} + str + %label.class-254{for: 'f1_c2'} + %input{type: 'checkbox', id: 'f1_c2'} + str + .class-255 + %pre.class-256(readonly="readonly" style='width:34px') + :preserve + %label.class-257{for: 'f1_c1'} + %input{type: 'checkbox', id: 'f1_c1', checked: 'checked'} + str + %label.class-258{for: 'f1_c2'} + %input{type: 'checkbox', id: 'f1_c2'} + str + + %label.class-259{for: 'f1_r1'} + %input{type: 'radio', name: 'form1', id: 'f1_r1', checked: 'checked'} + str + %label.class-260{for: 'f1_r2'} + %input{type: 'radio', name: 'form1', id: 'f1_r2'} + str + .class-261 + %pre.class-262(readonly="readonly" style='width:35px') + :preserve + %label.class-263{for: 'f1_r1'} + %input{type: 'radio', name: 'form1', id: 'f1_r1', checked: 'checked'} + str + %label.class-264{for: 'f1_r2'} + %input{type: 'radio', name: 'form1', id: 'f1_r2'} + str + + %section#id-30 + .class-265 string-82 + %ul.class-266.class-267 + %li + %label.class-268{for: 'f2_c1'} + %input{type: 'checkbox', id: 'f2_c1', checked: 'checked'} + str + %li + %label.class-269{for: 'f2_c2'} + %input{type: 'checkbox', id: 'f2_c2'} + str + .class-270 + %pre.class-271(readonly="readonly" style='width:36px') + :preserve + %ul.class-272.class-273 + %li + %label.class-274{for: 'f2_c1'} + %input{type: 'checkbox', id: 'f2_c1', checked: 'checked'} + str + %li + %label.class-275{for: 'f2_c2'} + %input{type: 'checkbox', id: 'f2_c2'} + str + + %ul.class-276.class-277 + %li + %label.class-278{for: 'f2_r1'} + %input{type: 'radio', name: 'form2', id: 'f2_r1', checked: 'checked'} + str + %li + %label.class-279{for: 'f2_r2'} + %input{type: 'radio', name: 'form2', id: 'f2_r2'} + str + .class-280 + %pre.class-281(readonly="readonly" style='width:37px') + :preserve + %ul.class-282.class-283 + %li + %label.class-284{for: 'f2_r1'} + %input{type: 'radio', name: 'form2', id: 'f2_r1', checked: 'checked'} + str + %li + %label.class-285{for: 'f2_r2'} + %input{type: 'radio', name: 'form2', id: 'f2_r2'} + str + + %section#id-31 + .class-286 string-83 + .class-287 + %ul.class-288 + %li text-84 + %li text-85 + %pre.class-289(readonly="readonly" style='width:38px') + :preserve + %ul.class-290 + %li text-86 + %li text-87 + + %ul.class-291.class-292 + %li text-88 + %li text-89 + %pre.class-293(readonly="readonly" style='width:39px') + :preserve + %ul.class-294.class-295 + %li text-90 + %li text-91 + + %ul.class-296.class-297 + %li text-92 + %li text-93 + %pre.class-298(readonly="readonly" style='width:40px') + :preserve + %ul.class-299.class-300 + %li text-94 + %li text-95 + + %ul.class-301.class-302 + %li text-96 + %li text-97 + %pre.class-303(readonly="readonly" style='width:41px') + :preserve + %ul.class-304.class-305 + %li text-98 + %li text-99 + + %section#id-32 + .class-306 string-100 + .class-307 + = image_tag '#' + = image_tag '#' + %pre.class-312(readonly="readonly" style='width:42px') + :preserve + = image_tag '#' + = image_tag '#' + + %section#id-33 + .class-315 string-101 + .class-316 + = image_tag '#' + %span.class-317 str + %pre.class-318(readonly="readonly" style='width:43px') + :preserve + = image_tag '#' + %span.class-319 str + + %section#id-34 + .class-320 string-102 + .class-321 + %a(href="#" class="klass") + %pre.class-322(readonly="readonly" style='width:44px') + :preserve + = link_to '', '#', class: 'klass' + + %section#id-35 + .class-323 string-103 + .class-324 + %a(href="#" class="klass") + %pre.class-325(readonly="readonly" style='width:45px') + :preserve + = link_to '', '#', class: 'klass' + + %section#id-36 + .class-326 string-104 + .class-327 + .class-328 + %a(rel="prev" href="#") + %a(rel="next" href="#") + %pre.class-329(readonly="readonly" style='width:46px') + :preserve + .class-330 + = link_to '', '#', rel: 'klass' + = link_to '', '#', rel: 'klass' + + %section#id-37 + .class-331 string-105 + .class-332 + .class-333 + .class-334 + %strong text-106 + %span text-107 + .class-335{ style: "width: 50%;" } + + %pre.class-336{ readonly: "readonly", style: "height: 120px" } + :preserve + .class-337 + .class-338 + %strong text-108 + %span text-109 + .class-339{ style: "width: 50%;" } + + .class-340.class-341 + .class-342 + %strong text-110 + %span text-111 + .class-343{ style: "width: 50%;" } + + %pre.class-344{ readonly: "readonly", style: "height: 120px" } + :preserve + .class-345.class-346 + .class-347 + %strong text-112 + %span text-113 + .class-348{ style: "width: 50%;" } + + %section#id-38 + .class-349 string-114 + .class-350 + = render '#' + = render '#' + %pre.class-351(readonly="readonly" style='width:47px') + :preserve + = render '#' + = render '#' + + %p text-115 + %p text-116 + + %section#id-39 + .class-353 string-117 + .class-354 + = link_to 'link', '#', class: 'klass1 klass2', :'data-foo_bar' => 'foo!!' + .class-355 + .class-356 string-118 + %pre.class-357(readonly="readonly" style='width:48px') + :preserve + = link_to 'link', '#', + class: 'klass1 klass2', + :'data-foo_bar' => 'foo!!' + .class-358 string-119 + %pre.class-359(readonly="readonly" style='width:49px') + :preserve + foo.bar('Hoge') + + %section#id-40 + .class-361 string-120 + .class-362 + = link_to 'link', '#', class: 'klass1 klass2 klass3' + .class-363 + .class-364 string-121 + %pre.class-365(readonly="readonly" style='width:50px') + :preserve + = link_to 'link', '#', + class: 'klass1 klass2 klass3' + + .class-366 string-122 + %pre.class-367(readonly="readonly" style='width:51px') + :preserve + #id-43.class-368.class-369 + .class-370 + .class-371 string-123 + %a.class-372{href: "#"} + str + + %p text-124 + %p text-125 + + .class-373 string-126 + %pre.class-374(readonly="readonly" style='width:52px') + :preserve + // hello + $(window).bind('click', function(event) { + }); + + // hello + $('#id-44').bind('click', function(event) { + }); + + // world + $('#id-45').bind('click', function(event) { + }); + + %p text-127 + + %section#id-46 + .class-378 string-128 + .class-379 + %ul.class-380 + %li.class-381 + str1 + %li.class-382 + str2 + %li.class-383 + str3 + :javascript + $('.class-384').foo({bar: '.class-386'}); + :css + .class-387 { + min-height: 13px; + } + .class-388 { + height: 1px; + background: #000; + padding: 1px; + text-align: center; + } + .class-390 { + background: #000; + } + .class-392 { + background: #000; + } + + .class-394 + %pre.class-395(readonly="readonly" style='width:53px') + :preserve + .class-396 + %ul.class-397 + %li.class-398 str1 + %li.class-399 str2 + %li.class-400 str3 + :javascript + $('.class-401').bar({foo: '.class-403'}); + + %ul.class-404.class-405 + %li= link_to 'link', '#' + %li= link_to 'link', '#' + %li= link_to 'link', '#' + + .class-406 + %ul.class-407 + %li#id-52A.class-408 str1 + %li#id-53B.class-409 str2 + %li#id-54C.class-410 str3 + + :javascript + $('.class-411').click({foo: '.class-413 > li > a'}); + + :css + .class-414 { + height: 1px; + background: #000; + padding: 1px; + text-align: center; + } + .class-416 { + background: #000; + } + .class-418 { + background: #000; + } + + .class-420 + %pre.class-421(readonly="readonly" style='width:54px') + :preserve + %ul.class-422.class-423 + %li= link_to 'link', '#' + %li= link_to 'link', '#' + %li= link_to 'link', '#' + + .class-424 + %ul.class-425 + %li#id-60A.class-426 str1 + %li#id-61B.class-427 str2 + %li#id-62C.class-428 str3 + + :javascript + $('.class-429').bind({links: '.klass'}); + + %section#id-63 + .class-432 string-136 + .class-433 + .class-434 string-137 + %pre.class-435(readonly="readonly" style='width:55px') + :preserve + #id-64 + -# hello + + .class-436 + -# world + + %span.class-437 + + #id-65 + -# hey + .class-438 string-138 + %pre.class-439(readonly="readonly" style='width:56px') + :preserve + // hello + $(document).bind('click', function(event) { + }); + + // world + $(document).bind('click', function(event) { + }); + +#id-66XXX.class-442.class-443 + .class-444 + .class-445 string-139 + + %a.class-446{href: "#"} + str + +:javascript + (function ($) { + $(".foo").removeClass("bar"); + })(jQuery); diff --git a/benchmark/etc/real_sample.rb b/benchmark/etc/real_sample.rb new file mode 100644 index 0000000..5cefec7 --- /dev/null +++ b/benchmark/etc/real_sample.rb @@ -0,0 +1,11 @@ +def render(*) + '
' +end + +def link_to(a, b, *c) + "'.freeze +end + +def image_tag(*) + '' +end diff --git a/benchmark/etc/static_analyzer.haml b/benchmark/etc/static_analyzer.haml new file mode 100644 index 0000000..210a551 --- /dev/null +++ b/benchmark/etc/static_analyzer.haml @@ -0,0 +1 @@ +#foo.bar{ data: { 'user' => { id: 1234, name: 'k0kubun' }, book_id: 5432 } } diff --git a/benchmark/etc/string_interpolation.haml b/benchmark/etc/string_interpolation.haml new file mode 100644 index 0000000..6ccfe11 --- /dev/null +++ b/benchmark/etc/string_interpolation.haml @@ -0,0 +1,2 @@ +- id = 12347 +%a{ href: "https://example.com/users/#{id}" }= "id: #{id}" diff --git a/benchmark/etc/tags.haml b/benchmark/etc/tags.haml new file mode 100644 index 0000000..49c139d --- /dev/null +++ b/benchmark/etc/tags.haml @@ -0,0 +1,3 @@ +%span hello +%div + world diff --git a/benchmark/etc/tags_loop.haml b/benchmark/etc/tags_loop.haml new file mode 100644 index 0000000..e5cf716 --- /dev/null +++ b/benchmark/etc/tags_loop.haml @@ -0,0 +1,2 @@ +- 100.times do + %span hello diff --git a/benchmark/ext/build_data.rb b/benchmark/ext/build_data.rb new file mode 100755 index 0000000..5d47242 --- /dev/null +++ b/benchmark/ext/build_data.rb @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby + +require 'bundler/setup' +require 'hamlit' +require 'faml' +require 'benchmark/ips' +require_relative '../utils/benchmark_ips_extension' + +h = { 'user' => { id: 1234, name: 'k0kubun' }, book_id: 5432 } + +Benchmark.ips do |x| + quote = "'" + faml_options = { data: h } + x.report("Faml::AB.build") { Faml::AttributeBuilder.build(quote, true, nil, faml_options) } + x.report("Hamlit.build_data") { Hamlit::AttributeBuilder.build_data(true, quote, h) } + x.compare! +end diff --git a/benchmark/ext/build_id.rb b/benchmark/ext/build_id.rb new file mode 100755 index 0000000..0551c74 --- /dev/null +++ b/benchmark/ext/build_id.rb @@ -0,0 +1,13 @@ +#!/usr/bin/env ruby + +require 'bundler/setup' +require 'hamlit' +require 'faml' +require 'benchmark/ips' +require_relative '../utils/benchmark_ips_extension' + +Benchmark.ips do |x| + x.report("Faml::AB.build") { Faml::AttributeBuilder.build("'", true, nil, {:id=>"book"}, id: %w[content active]) } + x.report("Hamlit::AB.build_id") { Hamlit::AttributeBuilder.build_id(true, "book", %w[content active]) } + x.compare! +end diff --git a/benchmark/graph/graph.key b/benchmark/graph/graph.key new file mode 100644 index 0000000000000000000000000000000000000000..8e73b78940762846ae3a7e8d5884602d8a980b4a GIT binary patch literal 402094 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 @; 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 g=fd9#DVoW=nfek5*gz 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%0A-MioB?m3CsdWyv;V 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 QAOZdfO(AI3B;?os0Ow5)&j0`b literal 0 HcmV?d00001 diff --git a/benchmark/graph/graph.png b/benchmark/graph/graph.png new file mode 100644 index 0000000000000000000000000000000000000000..d6ca85bb05dd539d654c4aba9fadeaa92fb43e79 GIT binary patch literal 204194 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 z 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 z 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 literal 0 HcmV?d00001 diff --git a/benchmark/id_attribute.haml b/benchmark/id_attribute.haml new file mode 100644 index 0000000..af6acf6 --- /dev/null +++ b/benchmark/id_attribute.haml @@ -0,0 +1,3 @@ +#book{ id: 'content active' } +- id = %w[content active] +#book{ id: id } diff --git a/benchmark/plain.haml b/benchmark/plain.haml new file mode 100644 index 0000000..4c7cdc3 --- /dev/null +++ b/benchmark/plain.haml @@ -0,0 +1,4 @@ +- hello = 'world' +%span aaa#{hello}bbb +%span + aaa#{hello}bbb diff --git a/benchmark/script.haml b/benchmark/script.haml new file mode 100644 index 0000000..f318d7b --- /dev/null +++ b/benchmark/script.haml @@ -0,0 +1,4 @@ +- dynamic = 'dynamic' += "#{ dynamic } script" += "#{ 'static'} script" += ['&', '"', "'", '<', '>'] diff --git a/benchmark/slim/LICENSE b/benchmark/slim/LICENSE new file mode 100644 index 0000000..6af6518 --- /dev/null +++ b/benchmark/slim/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2010 - 2015 Slim Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/benchmark/slim/context.rb b/benchmark/slim/context.rb new file mode 100644 index 0000000..4d71e34 --- /dev/null +++ b/benchmark/slim/context.rb @@ -0,0 +1,11 @@ +class Context + def header + 'Colors' + end + + def item + [ { name: 'red', current: true, url: '#red' }, + { name: 'green', current: false, url: '#green' }, + { name: 'blue', current: false, url: '#blue' } ] + end +end diff --git a/benchmark/slim/run-benchmarks.rb b/benchmark/slim/run-benchmarks.rb new file mode 100644 index 0000000..3f59cc1 --- /dev/null +++ b/benchmark/slim/run-benchmarks.rb @@ -0,0 +1,94 @@ +#!/usr/bin/env ruby + +=begin +The MIT License + +Copyright (c) 2010 - 2015 Slim Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=end + +# +# Original: https://github.com/slim-template/slim/blob/v3.0.6/benchmarks/run-benchmarks.rb +# +# SlimBenchmarks with following modifications: +# 1. Skipping slow engines, tilt and parsing benches. +# 2. All Ruby script and attributes are escaped for fairness. +# 3. Faml and Hamlit are added. +# + +$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__)) + +require 'slim' +require 'context' + +require 'benchmark/ips' +require 'tilt' +require 'erubi' +require 'erb' +require 'haml' +require 'faml' +require 'hamlit' + +class SlimBenchmarks + def initialize(only_haml) + @only_haml = only_haml + @benches = [] + + @erb_code = File.read(File.dirname(__FILE__) + '/view.erb') + @haml_code = File.read(File.dirname(__FILE__) + '/view.haml') + @slim_code = File.read(File.dirname(__FILE__) + '/view.slim') + + init_compiled_benches + end + + def init_compiled_benches + context = Context.new + + haml_ugly = Haml::Engine.new(@haml_code, format: :html5, escape_html: true) + haml_ugly.def_method(context, :run_haml_ugly) + context.instance_eval %{ + def run_erubi; #{Erubi::Engine.new(@erb_code).src}; end + def run_slim_ugly; #{Slim::Engine.new.call @slim_code}; end + def run_faml; #{Faml::Engine.new.call @haml_code}; end + def run_hamlit; #{Hamlit::Engine.new.call @haml_code}; end + } + + bench("erubi v#{Erubi::VERSION}") { context.run_erubi } unless @only_haml + bench("slim v#{Slim::VERSION}") { context.run_slim_ugly } unless @only_haml + bench("haml v#{Haml::VERSION}") { context.run_haml_ugly } + bench("faml v#{Faml::VERSION}") { context.run_faml } + bench("hamlit v#{Hamlit::VERSION}") { context.run_hamlit } + end + + def run + Benchmark.ips do |x| + @benches.each do |name, block| + x.report(name.to_s, &block) + end + x.compare! + end + end + + def bench(name, &block) + @benches.push([name, block]) + end +end + +SlimBenchmarks.new(ENV['ONLY_HAML'] == '1').run diff --git a/benchmark/slim/view.erb b/benchmark/slim/view.erb new file mode 100644 index 0000000..3ffc829 --- /dev/null +++ b/benchmark/slim/view.erb @@ -0,0 +1,23 @@ + + + + + Simple Benchmark + + +

<%== header %>

+ <% unless item.empty? %> +
+ <% else %> +

The list is empty.

+ <% end %> + + diff --git a/benchmark/slim/view.haml b/benchmark/slim/view.haml new file mode 100644 index 0000000..2e37c85 --- /dev/null +++ b/benchmark/slim/view.haml @@ -0,0 +1,18 @@ +!!! html + +%html + %head + %title Simple Benchmark + %body + %h1= header + - unless item.empty? + %ul + - for i in item + - if i[:current] + %li + %strong= i[:name] + - else + %li + %a{:href => i[:url]}= i[:name] + - else + %p The list is empty. diff --git a/benchmark/slim/view.slim b/benchmark/slim/view.slim new file mode 100644 index 0000000..9853bc7 --- /dev/null +++ b/benchmark/slim/view.slim @@ -0,0 +1,17 @@ +doctype html +html + head + title Simple Benchmark + body + h1 = header + - unless item.empty? + ul + - for i in item + - if i[:current] + li + strong = i[:name] + - else + li + a href=i[:url] = i[:name] + - else + p The list is empty. diff --git a/benchmark/utils/benchmark_ips_extension.rb b/benchmark/utils/benchmark_ips_extension.rb new file mode 100644 index 0000000..a8fbe1e --- /dev/null +++ b/benchmark/utils/benchmark_ips_extension.rb @@ -0,0 +1,43 @@ +# Monkey patch to show milliseconds +module Benchmark + module IPS + class Report + module EntryExtension + def body + return super if Benchmark::IPS.options[:format] != :human + + left = "%s i/s (%1.3fms)" % [Helpers.scale(ips), (1000.0 / ips)] + iters = Helpers.scale(@iterations) + + if @show_total_time + left.ljust(20) + (" - %s in %10.6fs" % [iters, runtime]) + else + left.ljust(20) + (" - %s" % iters) + end + end + end + Entry.prepend(EntryExtension) + end + end + + module CompareExtension + def compare(*reports) + return if reports.size < 2 + + sorted = reports.sort_by(&:ips).reverse + best = sorted.shift + $stdout.puts "\nComparison:" + $stdout.printf "%20s: %10.1f i/s (%1.3fms)\n", best.label, best.ips, (1000.0 / best.ips) + + sorted.each do |report| + name = report.label.to_s + + x = (best.ips.to_f / report.ips.to_f) + $stdout.printf "%20s: %10.1f i/s (%1.3fms) - %.2fx slower\n", name, report.ips, (1000.0 / report.ips), x + end + + $stdout.puts + end + end + extend CompareExtension +end diff --git a/bin/bench b/bin/bench new file mode 100755 index 0000000..93ca8b5 --- /dev/null +++ b/bin/bench @@ -0,0 +1,77 @@ +#!/usr/bin/env ruby + +require 'bundler/setup' +require 'hamlit' +require 'faml' +require 'thor' +require 'benchmark/ips' +require_relative '../benchmark/utils/benchmark_ips_extension' + +class Bench < Thor + class_option :show_template, type: :boolean, aliases: ['-t'] + + desc 'bench HAML', 'Benchmark haml template' + option :compile, type: :boolean, aliases: ['-c'] + option :show_code, type: :boolean, aliases: ['-s'] + def bench(*files) + files.each { |file| render(file) } + files.each { |file| compile(file) if options[:compile] } + files.each { |file| code(file) if options[:show_code] } + end + + desc 'compile HAML', 'Benchmark compilation' + def compile(file) + puts "#{?= * 49}\n Compilation: #{file}\n#{?= * 49}" + haml = File.read(file) + + Benchmark.ips do |x| + x.report("haml v#{Haml::VERSION}") { Haml::Engine.new(haml, escape_html: true, escape_attrs: true).precompiled } + x.report("faml v#{Faml::VERSION}") { Faml::Engine.new.call(haml) } + x.report("hamlit v#{Hamlit::VERSION}") { Hamlit::Engine.new.call(haml) } + x.compare! + end + end + + desc 'render HAML', 'Benchmark rendering' + def render(file) + puts "#{?= * 49}\n Rendering: #{file}\n#{?= * 49}" + haml = File.read(file) + puts haml + "\n" if options[:show_template] + object = Object.new + ruby_file = file.gsub(/\.haml\z/, '.rb') + if File.exist?(ruby_file) + object.instance_eval(File.read(ruby_file)) + end + + Haml::Engine.new(haml, escape_html: true, escape_attrs: true).def_method(object, :haml) + object.instance_eval "def faml; #{Faml::Engine.new.call(haml)}; end" + object.instance_eval "def hamlit; #{Hamlit::Engine.new.call(haml)}; end" + + Benchmark.ips do |x| + x.report("haml v#{Haml::VERSION}") { object.haml } + x.report("faml v#{Faml::VERSION}") { object.faml } + x.report("hamlit v#{Hamlit::VERSION}") { object.hamlit } + x.compare! + end + end + + desc 'code HAML', 'Show compiled code' + def code(file) + haml = File.read(file) + puts "#{?= * 49}\n Haml Source: #{file}\n#{?= * 49}" + puts Haml::Engine.new(haml, escape_html: true, escape_attrs: true).precompiled + puts "\n#{?= * 49}\n Faml Source: #{file}\n#{?= * 49}" + puts Faml::Engine.new.call(haml) + puts "\n#{?= * 49}\n Hamlit Source: #{file}\n#{?= * 49}" + puts Hamlit::Engine.new.call(haml) + end + + private + + def method_missing(*args) + return super if args.length > 1 + render(args.first.to_s) + end +end + +Bench.start diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..9249aa5 --- /dev/null +++ b/bin/console @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby + +require 'bundler/setup' +require 'hamlit' + +# You can add fixtures and/or initialization code here to make experimenting +# with your gem easier. You can also use a different console, if you like. + +# (If you use this, don't forget to add pry to your Gemfile!) +require 'pry' +Pry.start diff --git a/bin/ruby b/bin/ruby new file mode 100755 index 0000000..4e72e3f --- /dev/null +++ b/bin/ruby @@ -0,0 +1,3 @@ +#!/bin/bash + +bundle exec ruby -Ilib:test -rtest_helper $@ diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000..b65ed50 --- /dev/null +++ b/bin/setup @@ -0,0 +1,7 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +bundle install + +# Do any other automated setup that you need to do here diff --git a/bin/stackprof b/bin/stackprof new file mode 100755 index 0000000..76078d4 --- /dev/null +++ b/bin/stackprof @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby + +require 'bundler/setup' +require 'hamlit' +require 'stackprof' + +def open_flamegraph(report) + temp = `mktemp /tmp/stackflame-XXXXXXXX`.strip + data_path = "#{temp}.js" + system("mv #{temp} #{data_path}") + + File.open(data_path, 'w') do |f| + report.print_flamegraph(f) + end + + viewer_path = File.join(`bundle show stackprof`.strip, 'lib/stackprof/flamegraph/viewer.html') + url = "file://#{viewer_path}?data=#{data_path}" + system(%Q[osascript -e 'open location "#{url}"']) +end + +haml = File.read(ARGV.first) +StackProf.start(mode: :wall, interval: 1, raw: false) +Hamlit::Engine.new.call(haml) +StackProf.stop + +report = StackProf::Report.new(StackProf.results) +report.print_text(false) diff --git a/bin/test b/bin/test new file mode 100755 index 0000000..6d353b0 --- /dev/null +++ b/bin/test @@ -0,0 +1,24 @@ +#!/bin/bash + +VERSIONS=( + 2.1.10 + 2.2.5 + 2.3.1 +) + +set -e +trap 'echo "${VERSIONS[2]}" > .ruby-version' 0 + +function test_with() { + version=$1 + rbenv local $version + if ! bundle check > /dev/null; then + bundle install + fi + ruby -v + bundle exec rake test +} + +for version in ${VERSIONS[@]}; do + test_with $version +done diff --git a/bin/update-haml b/bin/update-haml new file mode 100755 index 0000000..2e49933 --- /dev/null +++ b/bin/update-haml @@ -0,0 +1,125 @@ +#!/usr/bin/env ruby +require 'fileutils' +require 'tmpdir' + +HAML_REPO = 'haml/haml' +HAML_VERSION = '5.2.1' + +module GitHubFetcher + def self.fetch(repo, tag:, path:) + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + url = "https://github.com/#{repo}/archive/#{tag}.tar.gz" + system("curl -L --fail --retry 3 --retry-delay 1 #{url} -o - | tar zxf -") + FileUtils.mv("#{File.basename(repo)}-#{tag.sub(/\Av/, '')}", path) + end + end + end +end + +class LicenseBuilder + DELIMITER = "\n===" + + def initialize(haml_license:, hamlit_license:) + @haml_license = haml_license + @hamlit_license = hamlit_license + end + + def build + license = [ + File.read(@haml_license), + File.read(@hamlit_license).split(DELIMITER, 2).last, + ].join(DELIMITER) + File.write(@hamlit_license, license) + end +end + +# Generate lib/hamlit/parser from haml +class HamlitParserBuilder + TARGET_FILES = [ + 'attribute_builder.rb', + 'buffer.rb', + 'error.rb', + 'helpers.rb', + 'options.rb', + 'temple_engine.rb', + # TODO: make the upstream sharable first + # 'parser.rb', + 'util.rb', + 'helpers/xss_mods.rb', + ] + + # Classes which are just referenced by Options and not really used by the parser + DUMMY_CLASSES = { + 'compiler.rb' => 'Compiler', + 'escapable.rb' => 'Escapable', + 'generator.rb' => 'Generator', + } + + def initialize(haml:, hamlit_parser:) + @haml = haml + @hamlit_parser = hamlit_parser + end + + def build + TARGET_FILES.each do |file| + src_path = File.join(@haml, file) + dest_path = File.join(@hamlit_parser, "haml_#{file}") + + FileUtils.mkdir_p(File.dirname(dest_path)) + FileUtils.cp(src_path, dest_path) + + src = File.read(dest_path) + patch_source!(src, file: file) + File.write(dest_path, src) + end + + DUMMY_CLASSES.each do |file, klass| + dest_path = File.join(@hamlit_parser, "haml_#{file}") + src = "class Hamlit::Haml#{klass}; end\n" + File.write(dest_path, src) + end + end + + private + + def patch_source!(src, file:) + # Use Hamlit::HamlFoo instead of Haml::Foo + src.gsub!(/^module Haml\n((?: #[^\n]+\n)*) (module|class) ([^ ]+)/, "module Hamlit\n\\1 \\2 Haml\\3") + src.gsub!(/\bHaml::/, 'Hamlit::Haml') + + # Prefix Haml to references without Haml:: + src.gsub!(/\b(AttributeBuilder|Error|InvalidAttributeNameError|Options|Parser|SyntaxError)\./, 'Haml\0') + src.gsub!(/\brescue SyntaxError /, 'rescue HamlSyntaxError ') + + # Hamlit should not rely on Haml + src.gsub!(/^require 'haml\/([^']+)'/, "require 'hamlit/parser/haml_\\1'") + + case file + when 'error.rb' + src.gsub!(/^ class ([^ ]+) < ([^ ]+);/, ' class Haml\1 < Haml\2;') + when 'helpers.rb' + src.gsub!(/^ def is_haml\?\n false\n end/m) { |str| str.gsub(/^ /, ' # ') } # not needed for the parser + when 'options.rb' + src.gsub!(/\.is_a\?\(Options\)/, '.is_a?(HamlOptions)') + when 'temple_engine.rb' + src.gsub!(/\buse (Generator|Escapable)$/, 'use Haml\1') + end + end +end + +FileUtils.rm_rf(haml = File.expand_path('../haml', __dir__)) +GitHubFetcher.fetch(HAML_REPO, tag: HAML_VERSION, path: haml) + +hamlit = File.expand_path('..', __dir__) +LicenseBuilder.new( + haml_license: File.join(haml, 'MIT-LICENSE'), + hamlit_license: File.join(hamlit, 'LICENSE.txt'), +).build + +hamlit_parser = File.join(hamlit, 'lib/hamlit/parser') +# TODO: FileUtils.rm_rf(hamlit_parser = File.join(hamlit, 'lib/hamlit/parser')) +HamlitParserBuilder.new( + haml: File.join(haml, 'lib/haml'), + hamlit_parser: hamlit_parser, +).build diff --git a/exe/hamlit b/exe/hamlit new file mode 100755 index 0000000..0978976 --- /dev/null +++ b/exe/hamlit @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby + +$:.unshift File.expand_path('../../lib', __FILE__) +require 'hamlit/cli' + +Hamlit::CLI.start(ARGV) diff --git a/ext/hamlit/extconf.rb b/ext/hamlit/extconf.rb new file mode 100644 index 0000000..182716d --- /dev/null +++ b/ext/hamlit/extconf.rb @@ -0,0 +1,10 @@ +require 'mkmf' + +$CFLAGS << ' -Wall -Wextra' + +$srcs = %w[ + hamlit.c + hescape.c +] + +create_makefile('hamlit/hamlit') diff --git a/ext/hamlit/hamlit.c b/ext/hamlit/hamlit.c new file mode 100644 index 0000000..06bbbd5 --- /dev/null +++ b/ext/hamlit/hamlit.c @@ -0,0 +1,537 @@ +#include +#include +#ifndef TRUFFLERUBY +#include "hescape.h" +#include "string.h" + +VALUE mAttributeBuilder, mObjectRef; +static ID id_flatten, id_keys, id_parse, id_prepend, id_tr, id_uniq_bang; +static ID id_xhtml; + +static VALUE str_aria, str_data, str_equal, str_hyphen, str_space, str_underscore; + +static void +delete_falsey_values(VALUE values) +{ + VALUE value; + long i; + + for (i = RARRAY_LEN(values) - 1; 0 <= i; i--) { + value = rb_ary_entry(values, i); + if (!RTEST(value)) { + rb_ary_delete_at(values, i); + } + } +} + +static int +str_eq(VALUE str, const char *cstr, long n) +{ + return RSTRING_LEN(str) == n && memcmp(RSTRING_PTR(str), cstr, n) == 0; +} + +static VALUE +to_s(VALUE value) +{ + return rb_convert_type(value, T_STRING, "String", "to_s"); +} + +static VALUE +hyphenate(VALUE str) +{ + long i; + + if (OBJ_FROZEN(str)) str = rb_str_dup(str); + + for (i = 0; i < RSTRING_LEN(str); i++) { + if (RSTRING_PTR(str)[i] == '_') { + rb_str_update(str, i, 1, str_hyphen); + } + } + return str; +} + +static VALUE +escape_html(VALUE str) +{ + char *buf; + unsigned int size; + Check_Type(str, T_STRING); + + size = hesc_escape_html(&buf, RSTRING_PTR(str), RSTRING_LEN(str)); + if (size > RSTRING_LEN(str)) { + str = rb_enc_str_new(buf, size, rb_utf8_encoding()); + free((void *)buf); + } + + return str; +} + +static VALUE +escape_attribute(VALUE escape_attrs, VALUE str) +{ + if (RTEST(escape_attrs)) { + return escape_html(str); + } else { + return str; + } +} + +static VALUE +rb_escape_html(RB_UNUSED_VAR(VALUE self), VALUE value) +{ + return escape_html(to_s(value)); +} + +static VALUE +hamlit_build_id(VALUE escape_attrs, VALUE values) +{ + VALUE attr_value; + + values = rb_funcall(values, id_flatten, 0); + delete_falsey_values(values); + + attr_value = rb_ary_join(values, str_underscore); + return escape_attribute(escape_attrs, attr_value); +} + +static VALUE +hamlit_build_single_class(VALUE escape_attrs, VALUE value) +{ + switch (TYPE(value)) { + case T_STRING: + break; + case T_ARRAY: + value = rb_funcall(value, id_flatten, 0); + delete_falsey_values(value); + value = rb_ary_join(value, str_space); + break; + default: + if (RTEST(value)) { + value = to_s(value); + } else { + return rb_str_new_cstr(""); + } + break; + } + return escape_attribute(escape_attrs, value); +} + +static VALUE +hamlit_build_multi_class(VALUE escape_attrs, VALUE values) +{ + long i, j; + VALUE value, buf; + + buf = rb_ary_new2(RARRAY_LEN(values)); + + for (i = 0; i < RARRAY_LEN(values); i++) { + value = rb_ary_entry(values, i); + switch (TYPE(value)) { + case T_STRING: + rb_ary_concat(buf, rb_str_split(value, " ")); + break; + case T_ARRAY: + value = rb_funcall(value, id_flatten, 0); + delete_falsey_values(value); + for (j = 0; j < RARRAY_LEN(value); j++) { + rb_ary_push(buf, to_s(rb_ary_entry(value, j))); + } + break; + default: + if (RTEST(value)) { + rb_ary_push(buf, to_s(value)); + } + break; + } + } + + rb_funcall(buf, id_uniq_bang, 0); + + return escape_attribute(escape_attrs, rb_ary_join(buf, str_space)); +} + +static VALUE +hamlit_build_class(VALUE escape_attrs, VALUE array) +{ + if (RARRAY_LEN(array) == 1) { + return hamlit_build_single_class(escape_attrs, rb_ary_entry(array, 0)); + } else { + return hamlit_build_multi_class(escape_attrs, array); + } +} + +struct merge_data_attrs_var { + VALUE merged; + VALUE key_str; +}; + +static int +merge_data_attrs_i(VALUE key, VALUE value, VALUE ptr) +{ + struct merge_data_attrs_var *arg = (struct merge_data_attrs_var *)ptr; + VALUE merged = arg->merged; + VALUE key_str = arg->key_str; + + if (NIL_P(key)) { + rb_hash_aset(merged, key_str, value); + } else { + key = rb_str_concat(rb_str_concat(rb_str_dup(key_str), rb_str_new_cstr("-")), to_s(key)); + rb_hash_aset(merged, key, value); + } + return ST_CONTINUE; +} + +static VALUE +merge_data_attrs(VALUE values, VALUE key_str) +{ + long i; + VALUE value, merged = rb_hash_new(); + + for (i = 0; i < RARRAY_LEN(values); i++) { + struct merge_data_attrs_var arg; + arg.merged = merged; + arg.key_str = key_str; + + value = rb_ary_entry(values, i); + switch (TYPE(value)) { + case T_HASH: + rb_hash_foreach(value, merge_data_attrs_i, (VALUE)&arg); + break; + default: + rb_hash_aset(merged, key_str, value); + break; + } + } + return merged; +} + +struct flatten_data_attrs_i2_arg { + VALUE flattened; + VALUE key; +}; + +static int +flatten_data_attrs_i2(VALUE k, VALUE v, VALUE ptr) +{ + VALUE key; + struct flatten_data_attrs_i2_arg *arg = (struct flatten_data_attrs_i2_arg *)ptr; + + if (!RTEST(v)) return ST_CONTINUE; + + if (k == Qnil) { + rb_hash_aset(arg->flattened, arg->key, v); + } else { + key = rb_str_dup(arg->key); + rb_str_cat(key, "-", 1); + rb_str_concat(key, to_s(k)); + + rb_hash_aset(arg->flattened, key, v); + } + return ST_CONTINUE; +} + +static VALUE flatten_data_attrs(VALUE attrs); + +static int +flatten_data_attrs_i(VALUE key, VALUE value, VALUE flattened) +{ + struct flatten_data_attrs_i2_arg arg; + key = hyphenate(to_s(key)); + + switch (TYPE(value)) { + case T_HASH: + value = flatten_data_attrs(value); + arg.key = key; + arg.flattened = flattened; + rb_hash_foreach(value, flatten_data_attrs_i2, (VALUE)(&arg)); + break; + default: + if (RTEST(value)) rb_hash_aset(flattened, key, value); + break; + } + return ST_CONTINUE; +} + +static VALUE +flatten_data_attrs(VALUE attrs) +{ + VALUE flattened = rb_hash_new(); + rb_hash_foreach(attrs, flatten_data_attrs_i, flattened); + + return flattened; +} + +static VALUE +hamlit_build_data(VALUE escape_attrs, VALUE quote, VALUE values, VALUE key_str) +{ + long i; + VALUE attrs, buf, keys, key, value; + + attrs = merge_data_attrs(values, key_str); + attrs = flatten_data_attrs(attrs); + keys = rb_ary_sort_bang(rb_funcall(attrs, id_keys, 0)); + buf = rb_str_new("", 0); + + for (i = 0; i < RARRAY_LEN(keys); i++) { + key = rb_ary_entry(keys, i); + value = rb_hash_aref(attrs, key); + + switch (value) { + case Qtrue: + rb_str_concat(buf, str_space); + rb_str_concat(buf, key); + break; + case Qnil: + break; // noop + case Qfalse: + break; // noop + default: + rb_str_concat(buf, str_space); + rb_str_concat(buf, key); + rb_str_concat(buf, str_equal); + rb_str_concat(buf, quote); + rb_str_concat(buf, escape_attribute(escape_attrs, to_s(value))); + rb_str_concat(buf, quote); + break; + } + } + + return buf; +} + +static VALUE +parse_object_ref(VALUE object_ref) +{ + return rb_funcall(mObjectRef, id_parse, 1, object_ref); +} + +static int +merge_all_attrs_i(VALUE key, VALUE value, VALUE merged) +{ + VALUE array; + + key = to_s(key); + if (str_eq(key, "id", 2) || str_eq(key, "class", 5) || str_eq(key, "data", 4) || str_eq(key, "aria", 4)) { + array = rb_hash_aref(merged, key); + if (NIL_P(array)) { + array = rb_ary_new2(1); + rb_hash_aset(merged, key, array); + } + rb_ary_push(array, value); + } else { + rb_hash_aset(merged, key, value); + } + return ST_CONTINUE; +} + +static VALUE +merge_all_attrs(VALUE hashes) +{ + long i; + VALUE hash, merged = rb_hash_new(); + + for (i = 0; i < RARRAY_LEN(hashes); i++) { + hash = rb_ary_entry(hashes, i); + if (!RB_TYPE_P(hash, T_HASH)) { + rb_raise(rb_eArgError, "Non-hash object is given to attributes!"); + } + rb_hash_foreach(hash, merge_all_attrs_i, merged); + } + return merged; +} + +int +is_boolean_attribute(VALUE key, VALUE boolean_attributes) +{ + if (str_eq(rb_str_substr(key, 0, 5), "data-", 5)) return 1; + if (str_eq(rb_str_substr(key, 0, 5), "aria-", 5)) return 1; + return RTEST(rb_ary_includes(boolean_attributes, key)); +} + +void +hamlit_build_for_id(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values) +{ + rb_str_cat(buf, " id=", 4); + rb_str_concat(buf, quote); + rb_str_concat(buf, hamlit_build_id(escape_attrs, values)); + rb_str_concat(buf, quote); +} + +void +hamlit_build_for_class(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values) +{ + rb_str_cat(buf, " class=", 7); + rb_str_concat(buf, quote); + rb_str_concat(buf, hamlit_build_class(escape_attrs, values)); + rb_str_concat(buf, quote); +} + +void +hamlit_build_for_data(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values) +{ + rb_str_concat(buf, hamlit_build_data(escape_attrs, quote, values, str_data)); +} + +void +hamlit_build_for_aria(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values) +{ + rb_str_concat(buf, hamlit_build_data(escape_attrs, quote, values, str_aria)); +} + +void +hamlit_build_for_others(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE key, VALUE value) +{ + rb_str_cat(buf, " ", 1); + rb_str_concat(buf, key); + rb_str_cat(buf, "=", 1); + rb_str_concat(buf, quote); + rb_str_concat(buf, escape_attribute(escape_attrs, to_s(value))); + rb_str_concat(buf, quote); +} + +void +hamlit_build_for_boolean(VALUE escape_attrs, VALUE quote, VALUE format, VALUE buf, VALUE key, VALUE value) +{ + switch (value) { + case Qtrue: + rb_str_cat(buf, " ", 1); + rb_str_concat(buf, key); + if ((TYPE(format) == T_SYMBOL || TYPE(format) == T_STRING) && rb_to_id(format) == id_xhtml) { + rb_str_cat(buf, "=", 1); + rb_str_concat(buf, quote); + rb_str_concat(buf, key); + rb_str_concat(buf, quote); + } + break; + case Qfalse: + break; // noop + case Qnil: + break; // noop + default: + hamlit_build_for_others(escape_attrs, quote, buf, key, value); + break; + } +} + +static VALUE +hamlit_build(VALUE escape_attrs, VALUE quote, VALUE format, VALUE boolean_attributes, VALUE object_ref, VALUE hashes) +{ + long i; + VALUE attrs, buf, key, keys, value; + + if (!NIL_P(object_ref)) rb_ary_push(hashes, parse_object_ref(object_ref)); + attrs = merge_all_attrs(hashes); + buf = rb_str_new("", 0); + keys = rb_ary_sort_bang(rb_funcall(attrs, id_keys, 0)); + + for (i = 0; i < RARRAY_LEN(keys); i++) { + key = rb_ary_entry(keys, i); + value = rb_hash_aref(attrs, key); + if (str_eq(key, "id", 2)) { + hamlit_build_for_id(escape_attrs, quote, buf, value); + } else if (str_eq(key, "class", 5)) { + hamlit_build_for_class(escape_attrs, quote, buf, value); + } else if (str_eq(key, "data", 4)) { + hamlit_build_for_data(escape_attrs, quote, buf, value); + } else if (str_eq(key, "aria", 4)) { + hamlit_build_for_aria(escape_attrs, quote, buf, value); + } else if (is_boolean_attribute(key, boolean_attributes)) { + hamlit_build_for_boolean(escape_attrs, quote, format, buf, key, value); + } else { + hamlit_build_for_others(escape_attrs, quote, buf, key, value); + } + } + + return buf; +} + +static VALUE +rb_hamlit_build_id(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self)) +{ + VALUE array; + + rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); + rb_scan_args(argc - 1, argv + 1, "*", &array); + + return hamlit_build_id(argv[0], array); +} + +static VALUE +rb_hamlit_build_class(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self)) +{ + VALUE array; + + rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); + rb_scan_args(argc - 1, argv + 1, "*", &array); + + return hamlit_build_class(argv[0], array); +} + +static VALUE +rb_hamlit_build_aria(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self)) +{ + VALUE array; + + rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS); + rb_scan_args(argc - 2, argv + 2, "*", &array); + + return hamlit_build_data(argv[0], argv[1], array, str_aria); +} + +static VALUE +rb_hamlit_build_data(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self)) +{ + VALUE array; + + rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS); + rb_scan_args(argc - 2, argv + 2, "*", &array); + + return hamlit_build_data(argv[0], argv[1], array, str_data); +} + +static VALUE +rb_hamlit_build(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self)) +{ + VALUE array; + + rb_check_arity(argc, 5, UNLIMITED_ARGUMENTS); + rb_scan_args(argc - 5, argv + 5, "*", &array); + + return hamlit_build(argv[0], argv[1], argv[2], argv[3], argv[4], array); +} + +void +Init_hamlit(void) +{ + VALUE mHamlit, mUtils; + + mHamlit = rb_define_module("Hamlit"); + mObjectRef = rb_define_module_under(mHamlit, "ObjectRef"); + mUtils = rb_define_module_under(mHamlit, "Utils"); + mAttributeBuilder = rb_define_module_under(mHamlit, "AttributeBuilder"); + + rb_define_singleton_method(mUtils, "escape_html", rb_escape_html, 1); + rb_define_singleton_method(mAttributeBuilder, "build", rb_hamlit_build, -1); + rb_define_singleton_method(mAttributeBuilder, "build_id", rb_hamlit_build_id, -1); + rb_define_singleton_method(mAttributeBuilder, "build_class", rb_hamlit_build_class, -1); + rb_define_singleton_method(mAttributeBuilder, "build_aria", rb_hamlit_build_aria, -1); + rb_define_singleton_method(mAttributeBuilder, "build_data", rb_hamlit_build_data, -1); + + id_flatten = rb_intern("flatten"); + id_keys = rb_intern("keys"); + id_parse = rb_intern("parse"); + id_prepend = rb_intern("prepend"); + id_tr = rb_intern("tr"); + id_uniq_bang = rb_intern("uniq!"); + id_xhtml = rb_intern("xhtml"); + + // Consider using rb_interned_str() once we stop supporting Ruby 2.7. + rb_gc_register_mark_object(str_aria = rb_obj_freeze(rb_str_new_cstr("aria"))); + rb_gc_register_mark_object(str_data = rb_obj_freeze(rb_str_new_cstr("data"))); + rb_gc_register_mark_object(str_equal = rb_obj_freeze(rb_str_new_cstr("="))); + rb_gc_register_mark_object(str_hyphen = rb_obj_freeze(rb_str_new_cstr("-"))); + rb_gc_register_mark_object(str_space = rb_obj_freeze(rb_str_new_cstr(" "))); + rb_gc_register_mark_object(str_underscore = rb_obj_freeze(rb_str_new_cstr("_"))); +} +#endif diff --git a/ext/hamlit/hescape.c b/ext/hamlit/hescape.c new file mode 100644 index 0000000..3400cba --- /dev/null +++ b/ext/hamlit/hescape.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include "hescape.h" + +static const char *ESCAPED_STRING[] = { + "", + """, + "&", + "'", + "<", + ">", +}; + +// This is strlen(ESCAPED_STRING[x]) optimized specially. +// Mapping: 1 => 6, 2 => 5, 3 => 5, 4 => 4, 5 => 4 +#define ESC_LEN(x) ((13 - x) / 2) + +/* + * Given ASCII-compatible character, return index of ESCAPED_STRING. + * + * " (34) => 1 (") + * & (38) => 2 (&) + * ' (39) => 3 (') + * < (60) => 4 (<) + * > (62) => 5 (>) + */ +static const char HTML_ESCAPE_TABLE[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static char* +ensure_allocated(char *buf, size_t size, size_t *asize) +{ + size_t new_size; + + if (size < *asize) + return buf; + + if (*asize == 0) { + new_size = size; + } else { + new_size = *asize; + } + + // Increase buffer size by 1.5x if realloced multiple times. + while (new_size < size) + new_size = (new_size << 1) - (new_size >> 1); + + // Round allocation up to multiple of 8. + new_size = (new_size + 7) & ~7; + + *asize = new_size; + return realloc(buf, new_size); +} + +size_t +hesc_escape_html(char **dest, const char *buf, size_t size) +{ + size_t asize = 0, esc_i = 0, esize = 0, i = 0, rbuf_end = 0; + const char *esc; + char *rbuf = NULL; + + while (i < size) { + // Loop here to skip non-escaped characters fast. + while (i < size && (esc_i = HTML_ESCAPE_TABLE[(unsigned char)buf[i]]) == 0) + i++; + + if (i < size && esc_i) { + esc = ESCAPED_STRING[esc_i]; + rbuf = ensure_allocated(rbuf, sizeof(char) * (size + esize + ESC_LEN(esc_i) + 1), &asize); + + // Copy pending characters and escaped string. + memmove(rbuf + rbuf_end, buf + (rbuf_end - esize), i - (rbuf_end - esize)); + memmove(rbuf + i + esize, esc, ESC_LEN(esc_i)); + rbuf_end = i + esize + ESC_LEN(esc_i); + esize += ESC_LEN(esc_i) - 1; + } + i++; + } + + if (rbuf_end == 0) { + // Return given buf and size if there are no escaped characters. + *dest = (char *)buf; + return size; + } else { + // Copy pending characters including NULL character. + memmove(rbuf + rbuf_end, buf + (rbuf_end - esize), (size + 1) - (rbuf_end - esize)); + + *dest = rbuf; + return size + esize; + } +} diff --git a/ext/hamlit/hescape.h b/ext/hamlit/hescape.h new file mode 100644 index 0000000..df18f4b --- /dev/null +++ b/ext/hamlit/hescape.h @@ -0,0 +1,20 @@ +#ifndef HESCAPE_H +#define HESCAPE_H + +#include + +/* + * Replace characters according to the following rules. + * Note that this function can handle only ASCII-compatible string. + * + * " => " + * & => & + * ' => ' + * < => < + * > => > + * + * @return size of dest. If it's larger than len, dest is required to be freed. + */ +extern size_t hesc_escape_html(char **dest, const char *src, size_t size); + +#endif diff --git a/hamlit.gemspec b/hamlit.gemspec new file mode 100644 index 0000000..bce4e31 --- /dev/null +++ b/hamlit.gemspec @@ -0,0 +1,47 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'hamlit/version' + +Gem::Specification.new do |spec| + spec.name = 'hamlit' + spec.version = Hamlit::VERSION + spec.authors = ['Takashi Kokubun'] + spec.email = ['takashikkbn@gmail.com'] + + spec.summary = %q{High Performance Haml Implementation} + spec.description = %q{High Performance Haml Implementation} + spec.homepage = 'https://github.com/k0kubun/hamlit' + spec.license = 'MIT' + + spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|sample|benchmark)/}) } + spec.bindir = 'exe' + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.require_paths = ['lib'] + + if /java/ === RUBY_PLATFORM + spec.platform = 'java' + else + spec.extensions = ['ext/hamlit/extconf.rb'] + spec.required_ruby_version = '>= 2.1.0' + end + + spec.add_dependency 'temple', '>= 0.8.2' + spec.add_dependency 'thor' + spec.add_dependency 'tilt' + + spec.add_development_dependency 'benchmark_driver' + spec.add_development_dependency 'bundler' + spec.add_development_dependency 'coffee-script' + spec.add_development_dependency 'erubi' + spec.add_development_dependency 'haml', '>= 5' + spec.add_development_dependency 'less' + spec.add_development_dependency 'minitest-reporters', '~> 1.1' + spec.add_development_dependency 'rails', '>= 4.0' + spec.add_development_dependency 'rake' + spec.add_development_dependency 'rake-compiler' + spec.add_development_dependency 'sass' + spec.add_development_dependency 'slim' + spec.add_development_dependency 'string_template' + spec.add_development_dependency 'unindent' +end diff --git a/lib/hamlit.rb b/lib/hamlit.rb new file mode 100644 index 0000000..ce7c5ca --- /dev/null +++ b/lib/hamlit.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +require 'hamlit/engine' +require 'hamlit/error' +require 'hamlit/version' +require 'hamlit/template' + +if File.basename($0) != 'hamlit' + begin + require 'rails' + require 'hamlit/railtie' + rescue LoadError + end +end diff --git a/lib/hamlit/ambles.rb b/lib/hamlit/ambles.rb new file mode 100644 index 0000000..3036a82 --- /dev/null +++ b/lib/hamlit/ambles.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true +module Hamlit + class Ambles < Temple::Filter + define_options :preamble, :postamble + + def initialize(*) + super + @preamble = options[:preamble] + @postamble = options[:postamble] + end + + def call(ast) + ret = [:multi] + ret << [:static, @preamble] if @preamble + ret << ast + ret << [:static, @postamble] if @postamble + ret + end + end +end diff --git a/lib/hamlit/attribute_builder.rb b/lib/hamlit/attribute_builder.rb new file mode 100644 index 0000000..0893083 --- /dev/null +++ b/lib/hamlit/attribute_builder.rb @@ -0,0 +1,175 @@ +# frozen_string_literal: true +require 'hamlit/object_ref' + +module Hamlit::AttributeBuilder + BOOLEAN_ATTRIBUTES = %w[disabled readonly multiple checked autobuffer + autoplay controls loop selected hidden scoped async + defer reversed ismap seamless muted required + autofocus novalidate formnovalidate open pubdate + itemscope allowfullscreen default inert sortable + truespeed typemustmatch download].freeze + + # Java extension is not implemented for JRuby yet. + # TruffleRuby does not implement `rb_ary_sort_bang`, etc. + if /java/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby' + class << self + def build(escape_attrs, quote, format, boolean_attributes, object_ref, *hashes) + hashes << Hamlit::ObjectRef.parse(object_ref) if object_ref + buf = [] + hash = merge_all_attrs(hashes) + + keys = hash.keys.sort! + keys.each do |key| + case key + when 'id'.freeze + buf << " id=#{quote}#{build_id(escape_attrs, *hash[key])}#{quote}" + when 'class'.freeze + buf << " class=#{quote}#{build_class(escape_attrs, *hash[key])}#{quote}" + when 'data'.freeze + buf << build_data(escape_attrs, quote, *hash[key]) + when *boolean_attributes, /\Adata-/ + build_boolean!(escape_attrs, quote, format, buf, key, hash[key]) + else + buf << " #{key}=#{quote}#{escape_html(escape_attrs, hash[key].to_s)}#{quote}" + end + end + buf.join + end + + def build_id(escape_attrs, *values) + escape_html(escape_attrs, values.flatten.select { |v| v }.join('_')) + end + + def build_class(escape_attrs, *values) + if values.size == 1 + value = values.first + case + when value.is_a?(String) + # noop + when value.is_a?(Array) + value = value.flatten.select { |v| v }.map(&:to_s).uniq.join(' ') + when value + value = value.to_s + else + return '' + end + return escape_html(escape_attrs, value) + end + + classes = [] + values.each do |value| + case + when value.is_a?(String) + classes += value.split(' ') + when value.is_a?(Array) + classes += value.select { |v| v } + when value + classes << value.to_s + end + end + escape_html(escape_attrs, classes.map(&:to_s).uniq.join(' ')) + end + + def build_data(escape_attrs, quote, *hashes) + build_data_attribute(:data, escape_attrs, quote, *hashes) + end + + def build_aria(escape_attrs, quote, *hashes) + build_data_attribute(:aria, escape_attrs, quote, *hashes) + end + + private + + def build_data_attribute(key, escape_attrs, quote, *hashes) + attrs = [] + if hashes.size > 1 && hashes.all? { |h| h.is_a?(Hash) } + data_value = merge_all_attrs(hashes) + else + data_value = hashes.last + end + hash = flatten_attributes(key => data_value) + + hash.sort_by(&:first).each do |key, value| + case value + when true + attrs << " #{key}" + when nil, false + # noop + else + attrs << " #{key}=#{quote}#{escape_html(escape_attrs, value.to_s)}#{quote}" + end + end + attrs.join + end + + def flatten_attributes(attributes) + flattened = {} + + attributes.each do |key, value| + case value + when attributes + when Hash + flatten_attributes(value).each do |k, v| + if k.nil? + flattened[key] = v + else + flattened["#{key}-#{k.to_s.gsub(/_/, '-')}"] = v + end + end + else + flattened[key] = value if value + end + end + flattened + end + + def merge_all_attrs(hashes) + merged = {} + hashes.each do |hash| + hash.each do |key, value| + key = key.to_s + case key + when 'id'.freeze, 'class'.freeze, 'data'.freeze + merged[key] ||= [] + merged[key] << value + else + merged[key] = value + end + end + end + merged + end + + def build_boolean!(escape_attrs, quote, format, buf, key, value) + case value + when true + case format + when :xhtml + buf << " #{key}=#{quote}#{key}#{quote}" + else + buf << " #{key}" + end + when false, nil + # omitted + else + buf << " #{key}=#{quote}#{escape_html(escape_attrs, value)}#{quote}" + end + end + + def escape_html(escape_attrs, str) + if escape_attrs + Hamlit::Utils.escape_html(str) + else + str + end + end + end + else + # Hamlit::AttributeBuilder.build + # Hamlit::AttributeBuilder.build_id + # Hamlit::AttributeBuilder.build_class + # Hamlit::AttributeBuilder.build_data + # Hamlit::AttributeBuilder.build_aria + require 'hamlit/hamlit' + end +end diff --git a/lib/hamlit/attribute_compiler.rb b/lib/hamlit/attribute_compiler.rb new file mode 100644 index 0000000..ac7cbcb --- /dev/null +++ b/lib/hamlit/attribute_compiler.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true +require 'hamlit/attribute_builder' +require 'hamlit/attribute_parser' +require 'hamlit/ruby_expression' + +module Hamlit + class AttributeCompiler + def initialize(identity, options) + @identity = identity + @quote = options[:attr_quote] + @format = options[:format] + @escape_attrs = options[:escape_attrs] + end + + def compile(node) + hashes = [] + if node.value[:object_ref] != :nil || !Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby + return runtime_compile(node) + end + [node.value[:dynamic_attributes].new, node.value[:dynamic_attributes].old].compact.each do |attribute_str| + hash = AttributeParser.parse(attribute_str) + return runtime_compile(node) unless hash + hashes << hash + end + static_compile(node.value[:attributes], hashes) + end + + private + + def runtime_compile(node) + attrs = [] + attrs.unshift(node.value[:attributes].inspect) if node.value[:attributes] != {} + + args = [ + @escape_attrs.inspect, "#{@quote.inspect}.freeze", @format.inspect, + '::Hamlit::AttributeBuilder::BOOLEAN_ATTRIBUTES', node.value[:object_ref], + ] + attrs + [:html, :attrs, [:dynamic, "::Hamlit::AttributeBuilder.build(#{args.join(', ')}, #{node.value[:dynamic_attributes].to_literal})"]] + end + + def static_compile(static_hash, dynamic_hashes) + temple = [:html, :attrs] + keys = [*static_hash.keys, *dynamic_hashes.map(&:keys).flatten].uniq.sort + keys.each do |key| + values = [[:static, static_hash[key]], *dynamic_hashes.map { |h| [:dynamic, h[key]] }] + values.select! { |_, exp| exp != nil } + + case key + when 'id' + compile_id!(temple, key, values) + when 'class' + compile_class!(temple, key, values) + when 'data', 'aria' + compile_data!(temple, key, values) + when *AttributeBuilder::BOOLEAN_ATTRIBUTES, /\Adata-/, /\Aaria-/ + compile_boolean!(temple, key, values) + else + compile_common!(temple, key, values) + end + end + temple + end + + def compile_id!(temple, key, values) + build_code = attribute_builder(:id, values) + if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) } + temple << [:html, :attr, key, [:static, eval(build_code).to_s]] + else + temple << [:html, :attr, key, [:dynamic, build_code]] + end + end + + def compile_class!(temple, key, values) + build_code = attribute_builder(:class, values) + if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) } + temple << [:html, :attr, key, [:static, eval(build_code).to_s]] + else + temple << [:html, :attr, key, [:dynamic, build_code]] + end + end + + def compile_data!(temple, key, values) + args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", values.map { |v| literal_for(v) }] + build_code = "::Hamlit::AttributeBuilder.build_#{key}(#{args.join(', ')})" + + if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) } + temple << [:static, eval(build_code).to_s] + else + temple << [:dynamic, build_code] + end + end + + def compile_boolean!(temple, key, values) + exp = literal_for(values.last) + + if Temple::StaticAnalyzer.static?(exp) + value = eval(exp) + case value + when true then temple << [:html, :attr, key, @format == :xhtml ? [:static, key] : [:multi]] + when false, nil + else temple << [:html, :attr, key, [:fescape, @escape_attrs, [:static, value.to_s]]] + end + else + var = @identity.generate + temple << [ + :case, "(#{var} = (#{exp}))", + ['true', [:html, :attr, key, @format == :xhtml ? [:static, key] : [:multi]]], + ['false, nil', [:multi]], + [:else, [:multi, [:static, " #{key}=#{@quote}"], [:fescape, @escape_attrs, [:dynamic, var]], [:static, @quote]]], + ] + end + end + + def compile_common!(temple, key, values) + temple << [:html, :attr, key, [:fescape, @escape_attrs, values.last]] + end + + def attribute_builder(type, values) + args = [@escape_attrs.inspect, *values.map { |v| literal_for(v) }] + "::Hamlit::AttributeBuilder.build_#{type}(#{args.join(', ')})" + end + + def literal_for(value) + type, exp = value + type == :static ? "#{exp.inspect}.freeze" : exp + end + end +end diff --git a/lib/hamlit/attribute_parser.rb b/lib/hamlit/attribute_parser.rb new file mode 100644 index 0000000..6636b20 --- /dev/null +++ b/lib/hamlit/attribute_parser.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true +require 'hamlit/ruby_expression' + +module Hamlit + class AttributeParser + class ParseSkip < StandardError + end + + def self.parse(text) + self.new.parse(text) + end + + def parse(text) + exp = wrap_bracket(text) + return if RubyExpression.syntax_error?(exp) + + hash = {} + tokens = Ripper.lex(exp)[1..-2] || [] + each_attr(tokens) do |attr_tokens| + key = parse_key!(attr_tokens) + hash[key] = attr_tokens.map { |t| t[2] }.join.strip + end + hash + rescue ParseSkip + nil + end + + private + + def wrap_bracket(text) + text = text.strip + return text if text[0] == '{' + "{#{text}}" + end + + def parse_key!(tokens) + _, type, str = tokens.shift + case type + when :on_sp + parse_key!(tokens) + when :on_label + str.tr(':', '') + when :on_symbeg + _, _, key = tokens.shift + assert_type!(tokens.shift, :on_tstring_end) if str != ':' + skip_until_hash_rocket!(tokens) + key + when :on_tstring_beg + _, _, key = tokens.shift + next_token = tokens.shift + unless next_token[1] == :on_label_end + assert_type!(next_token, :on_tstring_end) + skip_until_hash_rocket!(tokens) + end + key + else + raise ParseSkip + end + end + + def assert_type!(token, type) + raise ParseSkip if token[1] != type + end + + def skip_until_hash_rocket!(tokens) + until tokens.empty? + _, type, str = tokens.shift + break if type == :on_op && str == '=>' + end + end + + def each_attr(tokens) + attr_tokens = [] + open_tokens = Hash.new { |h, k| h[k] = 0 } + + tokens.each do |token| + _, type, _ = token + case type + when :on_comma + if open_tokens.values.all?(&:zero?) + yield(attr_tokens) + attr_tokens = [] + next + end + when :on_lbracket + open_tokens[:array] += 1 + when :on_rbracket + open_tokens[:array] -= 1 + when :on_lbrace + open_tokens[:block] += 1 + when :on_rbrace + open_tokens[:block] -= 1 + when :on_lparen + open_tokens[:paren] += 1 + when :on_rparen + open_tokens[:paren] -= 1 + when :on_embexpr_beg + open_tokens[:embexpr] += 1 + when :on_embexpr_end + open_tokens[:embexpr] -= 1 + when :on_sp + next if attr_tokens.empty? + end + + attr_tokens << token + end + yield(attr_tokens) unless attr_tokens.empty? + end + end +end diff --git a/lib/hamlit/cli.rb b/lib/hamlit/cli.rb new file mode 100644 index 0000000..106c882 --- /dev/null +++ b/lib/hamlit/cli.rb @@ -0,0 +1,154 @@ +# frozen_string_literal: true +require 'hamlit' +require 'thor' + +module Hamlit + class CLI < Thor + class_option :escape_html, type: :boolean, default: true + class_option :escape_attrs, type: :boolean, default: true + + desc 'render HAML', 'Render haml template' + option :load_path, type: :string, aliases: %w[-I] + option :require, type: :string, aliases: %w[-r] + def render(file) + process_load_options + code = generate_code(file) + puts eval(code, binding, file) + end + + desc 'compile HAML', 'Show compile result' + option :actionview, type: :boolean, default: false, aliases: %w[-a] + option :color, type: :boolean, default: true + option :check, type: :boolean, default: false, aliases: %w[-c] + def compile(file) + code = generate_code(file) + if options[:check] + if error = validate_ruby(code, file) + abort error.message.split("\n").first + end + puts "Syntax OK" + return + end + puts_code(code, color: options[:color]) + end + + desc 'temple HAML', 'Show temple intermediate expression' + option :color, type: :boolean, default: true + def temple(file) + pp_object(generate_temple(file), color: options[:color]) + end + + desc 'parse HAML', 'Show parse result' + option :color, type: :boolean, default: true + def parse(file) + pp_object(generate_ast(file), color: options[:color]) + end + + desc 'version', 'Show the used hamlit version' + def version + puts Hamlit::VERSION + end + + private + + def process_load_options + if options[:load_path] + options[:load_path].split(':').each do |dir| + $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) + end + end + + if options[:require] + require options[:require] + end + end + + def read_file(file) + if file == '-' + STDIN.read + else + File.read(file) + end + end + + def generate_code(file) + template = read_file(file) + if options[:actionview] + require 'action_view' + require 'action_view/base' + require 'hamlit/rails_template' + handler = Hamlit::RailsTemplate.new + template = ActionView::Template.new(template, 'inline template', handler, { locals: [] }) + code = handler.call(template) + <<-end_src + def _inline_template___2144273726781623612_70327218547300(local_assigns, output_buffer) + _old_virtual_path, @virtual_path = @virtual_path, nil;_old_output_buffer = @output_buffer;;#{code} + ensure + @virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer + end + end_src + else + Hamlit::Engine.new(engine_options).call(template) + end + end + + def generate_ast(file) + template = read_file(file) + Hamlit::Parser.new(engine_options).call(template) + end + + def generate_temple(file) + ast = generate_ast(file) + Hamlit::Compiler.new(engine_options).call(ast) + end + + def engine_options + Hamlit::Engine.options.to_h.merge( + escape_attrs: options[:escape_attrs], + escape_html: options[:escape_html], + ) + end + + # Flexible default_task, compatible with haml's CLI + def method_missing(*args) + return super(*args) if args.length > 1 + render(args.first.to_s) + end + + def puts_code(code, color: true) + begin + require 'irb/color' + rescue LoadError + color = false + end + if color + puts IRB::Color.colorize_code(code) + else + puts code + end + end + + # Enable colored pretty printing only for development environment. + def pp_object(arg, color: true) + begin + require 'irb/color_printer' + rescue LoadError + color = false + end + if color + IRB::ColorPrinter.pp(arg) + else + require 'pp' + pp(arg) + end + end + + def validate_ruby(code, file) + begin + eval("BEGIN {return nil}; #{code}", binding, file) + rescue ::SyntaxError # Not to be confused with Hamlit::SyntaxError + $! + end + end + end +end diff --git a/lib/hamlit/compiler.rb b/lib/hamlit/compiler.rb new file mode 100644 index 0000000..4f2584f --- /dev/null +++ b/lib/hamlit/compiler.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true +require 'hamlit/compiler/children_compiler' +require 'hamlit/compiler/comment_compiler' +require 'hamlit/compiler/doctype_compiler' +require 'hamlit/compiler/script_compiler' +require 'hamlit/compiler/silent_script_compiler' +require 'hamlit/compiler/tag_compiler' +require 'hamlit/filters' +require 'hamlit/identity' + +module Hamlit + class Compiler + def initialize(options = {}) + identity = Identity.new + @children_compiler = ChildrenCompiler.new + @comment_compiler = CommentCompiler.new + @doctype_compiler = DoctypeCompiler.new(options) + @filter_compiler = Filters.new(options) + @script_compiler = ScriptCompiler.new(identity) + @silent_script_compiler = SilentScriptCompiler.new + @tag_compiler = TagCompiler.new(identity, options) + end + + def call(ast) + return runtime_error(ast) if ast.is_a?(HamlError) + compile(ast) + rescue Error => e + runtime_error(e) + end + + private + + def compile(node) + case node.type + when :root + compile_children(node) + when :comment + compile_comment(node) + when :doctype + compile_doctype(node) + when :filter + compile_filter(node) + when :plain + compile_plain(node) + when :script + compile_script(node) + when :silent_script + compile_silent_script(node) + when :tag + compile_tag(node) + when :haml_comment + [:multi] + else + raise InternalError.new("Unexpected node type: #{node.type}") + end + end + + def compile_children(node) + @children_compiler.compile(node) { |n| compile(n) } + end + + def compile_comment(node) + @comment_compiler.compile(node) { |n| compile_children(n) } + end + + def compile_doctype(node) + @doctype_compiler.compile(node) + end + + def compile_filter(node) + @filter_compiler.compile(node) + end + + def compile_plain(node) + [:static, node.value[:text]] + end + + def compile_script(node) + @script_compiler.compile(node) { |n| compile_children(n) } + end + + def compile_silent_script(node) + @silent_script_compiler.compile(node) { |n| compile_children(n) } + end + + def compile_tag(node) + @tag_compiler.compile(node) { |n| compile_children(n) } + end + + def runtime_error(error) + [:multi].tap do |temple| + error.line.times { temple << [:newline] } if error.line + temple << [:code, %Q[raise #{error.class}.new(%q[#{error.message}], #{error.line.inspect})]] + end + end + end +end diff --git a/lib/hamlit/compiler/children_compiler.rb b/lib/hamlit/compiler/children_compiler.rb new file mode 100644 index 0000000..d408b0d --- /dev/null +++ b/lib/hamlit/compiler/children_compiler.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true +require 'hamlit/temple_line_counter' + +module Hamlit + class Compiler + class ChildrenCompiler + def initialize + @lineno = 1 + end + + def compile(node, &block) + temple = [:multi] + return temple if node.children.empty? + + temple << :whitespace if prepend_whitespace?(node) + node.children.each do |n| + rstrip_whitespace!(temple) if nuke_prev_whitespace?(n) + insert_newlines!(temple, n) + temple << moving_lineno(n) { block.call(n) } + temple << :whitespace if insert_whitespace?(n) + end + rstrip_whitespace!(temple) if nuke_inner_whitespace?(node) + confirm_whitespace(temple) + end + + private + + def insert_newlines!(temple, node) + (node.line - @lineno).times do + temple << [:newline] + end + + @lineno = node.line + end + + def moving_lineno(node, &block) + # before: As they may have children, we need to increment lineno before compilation. + case node.type + when :script, :silent_script + @lineno += 1 + when :tag + [node.value[:dynamic_attributes].new, node.value[:dynamic_attributes].old].compact.each do |attribute_hash| + @lineno += attribute_hash.count("\n") + end + @lineno += 1 if node.children.empty? && node.value[:parse] + end + + temple = block.call # compile + + # after: filter may not have children, and for some dynamic filters we can't predict the number of lines. + case node.type + when :filter + @lineno += TempleLineCounter.count_lines(temple) + end + + temple + end + + def confirm_whitespace(temple) + temple.map do |exp| + case exp + when :whitespace + [:static, "\n"] + else + exp + end + end + end + + def prepend_whitespace?(node) + return false unless %i[comment tag].include?(node.type) + !nuke_inner_whitespace?(node) + end + + def nuke_inner_whitespace?(node) + case + when node.type == :tag + node.value[:nuke_inner_whitespace] + when node.parent.nil? + false + else + nuke_inner_whitespace?(node.parent) + end + end + + def nuke_prev_whitespace?(node) + case node.type + when :tag + node.value[:nuke_outer_whitespace] + when :silent_script + !node.children.empty? && nuke_prev_whitespace?(node.children.first) + else + false + end + end + + def nuke_outer_whitespace?(node) + return false if node.type != :tag + node.value[:nuke_outer_whitespace] + end + + def rstrip_whitespace!(temple) + if temple[-1] == :whitespace + temple.delete_at(-1) + end + end + + def insert_whitespace?(node) + return false if nuke_outer_whitespace?(node) + + case node.type + when :doctype + node.value[:type] != 'xml' + when :comment, :plain, :tag + true + when :script + node.children.empty? && !nuke_inner_whitespace?(node) + when :filter + !%w[ruby].include?(node.value[:name]) + else + false + end + end + end + end +end diff --git a/lib/hamlit/compiler/comment_compiler.rb b/lib/hamlit/compiler/comment_compiler.rb new file mode 100644 index 0000000..f452e04 --- /dev/null +++ b/lib/hamlit/compiler/comment_compiler.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true +module Hamlit + class Compiler + class CommentCompiler + def compile(node, &block) + if node.value[:conditional] + compile_conditional_comment(node, &block) + else + compile_html_comment(node, &block) + end + end + + private + + def compile_html_comment(node, &block) + if node.children.empty? + [:html, :comment, [:static, " #{node.value[:text]} "]] + else + [:html, :comment, yield(node)] + end + end + + def compile_conditional_comment(node, &block) + condition = node.value[:conditional] + if node.value[:conditional] =~ /\A\[(\[*[^\[\]]+\]*)\]/ + condition = $1 + end + + content = + if node.children.empty? + [:static, " #{node.value[:text]} "] + else + yield(node) + end + [:html, :condcomment, condition, content, node.value[:revealed]] + end + end + end +end diff --git a/lib/hamlit/compiler/doctype_compiler.rb b/lib/hamlit/compiler/doctype_compiler.rb new file mode 100644 index 0000000..5ad4299 --- /dev/null +++ b/lib/hamlit/compiler/doctype_compiler.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true +module Hamlit + class Compiler + class DoctypeCompiler + def initialize(options = {}) + @format = options[:format] + end + + def compile(node) + case node.value[:type] + when 'xml' + xml_doctype + when '' + html_doctype(node) + else + [:html, :doctype, node.value[:type]] + end + end + + private + + def html_doctype(node) + version = node.value[:version] || :transitional + case @format + when :xhtml + [:html, :doctype, version] + when :html4 + [:html, :doctype, :transitional] + when :html5 + [:html, :doctype, :html] + else + [:html, :doctype, @format] + end + end + + def xml_doctype + case @format + when :xhtml + [:static, "\n"] + else + [:multi] + end + end + end + end +end diff --git a/lib/hamlit/compiler/script_compiler.rb b/lib/hamlit/compiler/script_compiler.rb new file mode 100644 index 0000000..18d4002 --- /dev/null +++ b/lib/hamlit/compiler/script_compiler.rb @@ -0,0 +1,106 @@ +# frozen_string_literal: true +require 'temple/static_analyzer' +require 'hamlit/ruby_expression' +require 'hamlit/string_splitter' + +module Hamlit + class Compiler + class ScriptCompiler + def initialize(identity) + @identity = identity + end + + def compile(node, &block) + unless Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby + return dynamic_compile(node, &block) + end + + no_children = node.children.empty? + case + when no_children && node.value[:escape_interpolation] + compile_interpolated_plain(node) + when no_children && RubyExpression.string_literal?(node.value[:text]) + delegate_optimization(node) + when no_children && Temple::StaticAnalyzer.static?(node.value[:text]) + static_compile(node) + else + dynamic_compile(node, &block) + end + end + + private + + # String-interpolated plain text must be compiled with this method + # because we have to escape only interpolated values. + def compile_interpolated_plain(node) + temple = [:multi] + StringSplitter.compile(node.value[:text]).each do |type, value| + case type + when :static + temple << [:static, value] + when :dynamic + temple << [:escape, node.value[:escape_interpolation], [:dynamic, value]] + end + end + temple << [:newline] + end + + # :dynamic is optimized in other filter: StringSplitter + def delegate_optimization(node) + [:multi, + [:escape, node.value[:escape_html], [:dynamic, node.value[:text]]], + [:newline], + ] + end + + def static_compile(node) + str = eval(node.value[:text]).to_s + if node.value[:escape_html] + str = Hamlit::Utils.escape_html(str) + elsif node.value[:preserve] + str = ::Hamlit::HamlHelpers.find_and_preserve(str, %w(textarea pre code)) + end + [:multi, [:static, str], [:newline]] + end + + def dynamic_compile(node, &block) + var = @identity.generate + temple = compile_script_assign(var, node, &block) + temple << compile_script_result(var, node) + end + + def compile_script_assign(var, node, &block) + if node.children.empty? + [:multi, + [:code, "#{var} = (#{node.value[:text]}"], + [:newline], + [:code, ')'], + ] + else + [:multi, + [:block, "#{var} = #{node.value[:text]}", + [:multi, [:newline], yield(node)], + ], + ] + end + end + + def compile_script_result(result, node) + if !node.value[:escape_html] && node.value[:preserve] + result = find_and_preserve(result) + else + result = "(#{result}).to_s" + end + [:escape, node.value[:escape_html], [:dynamic, result]] + end + + def find_and_preserve(code) + %Q[::Hamlit::HamlHelpers.find_and_preserve(#{code}, %w(textarea pre code))] + end + + def escape_html(temple) + [:escape, true, temple] + end + end + end +end diff --git a/lib/hamlit/compiler/silent_script_compiler.rb b/lib/hamlit/compiler/silent_script_compiler.rb new file mode 100644 index 0000000..29bed67 --- /dev/null +++ b/lib/hamlit/compiler/silent_script_compiler.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true +module Hamlit + class Compiler + class SilentScriptCompiler + def compile(node, &block) + if node.children.empty? + [:multi, [:code, node.value[:text]], [:newline]] + else + compile_with_children(node, &block) + end + end + + private + + def compile_with_children(node, &block) + [:multi, + [:block, node.value[:text], + [:multi, [:newline], yield(node)], + ], + ] + end + end + end +end diff --git a/lib/hamlit/compiler/tag_compiler.rb b/lib/hamlit/compiler/tag_compiler.rb new file mode 100644 index 0000000..8e03e2b --- /dev/null +++ b/lib/hamlit/compiler/tag_compiler.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true +require 'hamlit/parser/haml_util' +require 'hamlit/attribute_compiler' +require 'hamlit/string_splitter' + +module Hamlit + class Compiler + class TagCompiler + def initialize(identity, options) + @autoclose = options[:autoclose] + @identity = identity + @attribute_compiler = AttributeCompiler.new(identity, options) + end + + def compile(node, &block) + attrs = @attribute_compiler.compile(node) + contents = compile_contents(node, &block) + [:html, :tag, node.value[:name], attrs, contents] + end + + private + + def compile_contents(node, &block) + case + when !node.children.empty? + yield(node) + when node.value[:value].nil? && self_closing?(node) + nil + when node.value[:parse] + return compile_interpolated_plain(node) if node.value[:escape_interpolation] + if Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby + return delegate_optimization(node) if RubyExpression.string_literal?(node.value[:value]) + return delegate_optimization(node) if Temple::StaticAnalyzer.static?(node.value[:value]) + end + + var = @identity.generate + [:multi, + [:code, "#{var} = (#{node.value[:value]}"], + [:newline], + [:code, ')'], + [:escape, node.value[:escape_html], [:dynamic, var]] + ] + else + [:static, node.value[:value]] + end + end + + # :dynamic is optimized in other filters: StringSplitter or StaticAnalyzer + def delegate_optimization(node) + [:multi, + [:escape, node.value[:escape_html], [:dynamic, node.value[:value]]], + [:newline], + ] + end + + # We should handle interpolation here to escape only interpolated values. + def compile_interpolated_plain(node) + temple = [:multi] + StringSplitter.compile(node.value[:value]).each do |type, value| + case type + when :static + temple << [:static, value] + when :dynamic + temple << [:escape, node.value[:escape_interpolation], [:dynamic, value]] + end + end + temple << [:newline] + end + + def self_closing?(node) + return true if @autoclose && @autoclose.include?(node.value[:name]) + node.value[:self_closing] + end + end + end +end diff --git a/lib/hamlit/dynamic_merger.rb b/lib/hamlit/dynamic_merger.rb new file mode 100644 index 0000000..35cfa11 --- /dev/null +++ b/lib/hamlit/dynamic_merger.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true +module Hamlit + # Compile [:multi, [:static, 'foo'], [:dynamic, 'bar']] to [:dynamic, '"foo#{bar}"'] + class DynamicMerger < Temple::Filter + def on_multi(*exps) + exps = exps.dup + result = [:multi] + buffer = [] + + until exps.empty? + type, arg = exps.first + if type == :dynamic && arg.count("\n") == 0 + buffer << exps.shift + elsif type == :static && exps.size > (count = arg.count("\n")) && + exps[1, count].all? { |e| e == [:newline] } + (1 + count).times { buffer << exps.shift } + elsif type == :newline && exps.size > (count = count_newline(exps)) && + exps[count].first == :static && count == exps[count].last.count("\n") + (count + 1).times { buffer << exps.shift } + else + result.concat(merge_dynamic(buffer)) + buffer = [] + result << compile(exps.shift) + end + end + result.concat(merge_dynamic(buffer)) + + result.size == 2 ? result[1] : result + end + + private + + def merge_dynamic(exps) + # Merge exps only when they have both :static and :dynamic + unless exps.any? { |type,| type == :static } && exps.any? { |type,| type == :dynamic } + return exps + end + + strlit_body = String.new + exps.each do |type, arg| + case type + when :static + strlit_body << arg.dump.sub!(/\A"/, '').sub!(/"\z/, '').gsub('\n', "\n") + when :dynamic + strlit_body << "\#{#{arg}}" + when :newline + # newline is added by `gsub('\n', "\n")` + else + raise "unexpected type #{type.inspect} is given to #merge_dynamic" + end + end + [[:dynamic, "%Q\0#{strlit_body}\0"]] + end + + def count_newline(exps) + count = 0 + exps.each do |exp| + if exp == [:newline] + count += 1 + else + return count + end + end + return count + end + end +end diff --git a/lib/hamlit/engine.rb b/lib/hamlit/engine.rb new file mode 100644 index 0000000..886e33b --- /dev/null +++ b/lib/hamlit/engine.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +require 'temple' +require 'hamlit/parser' +require 'hamlit/compiler' +require 'hamlit/html' +require 'hamlit/escapable' +require 'hamlit/force_escapable' +require 'hamlit/dynamic_merger' +require 'hamlit/ambles' + +module Hamlit + class Engine < Temple::Engine + define_options( + :buffer_class, + generator: Temple::Generators::ArrayBuffer, + format: :html, + attr_quote: "'", + escape_html: true, + escape_attrs: true, + autoclose: %w(area base basefont br col command embed frame + hr img input isindex keygen link menuitem meta + param source track wbr), + filename: "", + ) + + use Parser + use Compiler + use HTML + filter :StringSplitter + filter :StaticAnalyzer + use Escapable + use ForceEscapable + filter :ControlFlow + use Ambles + filter :MultiFlattener + filter :StaticMerger + use DynamicMerger + use :Generator, -> { options[:generator] } + end +end diff --git a/lib/hamlit/error.rb b/lib/hamlit/error.rb new file mode 100644 index 0000000..85989f2 --- /dev/null +++ b/lib/hamlit/error.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +module Hamlit + class Error < StandardError + attr_reader :line + + def initialize(message = nil, line = nil) + super(message) + @line = line + end + end + + class SyntaxError < Error; end + class InternalError < Error; end + class FilterNotFound < Error; end +end diff --git a/lib/hamlit/escapable.rb b/lib/hamlit/escapable.rb new file mode 100644 index 0000000..53f71af --- /dev/null +++ b/lib/hamlit/escapable.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +require 'hamlit/utils' + +module Hamlit + class Escapable < Temple::Filters::Escapable + def initialize(opts = {}) + super + @escape_code = options[:escape_code] || + "::Hamlit::Utils.escape_html#{options[:use_html_safe] ? '_safe' : ''}((%s))" + @escaper = eval("proc {|v| #{@escape_code % 'v'} }") + end + end +end diff --git a/lib/hamlit/filters.rb b/lib/hamlit/filters.rb new file mode 100644 index 0000000..d81f338 --- /dev/null +++ b/lib/hamlit/filters.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true +require 'hamlit/filters/base' +require 'hamlit/filters/text_base' +require 'hamlit/filters/tilt_base' +require 'hamlit/filters/coffee' +require 'hamlit/filters/css' +require 'hamlit/filters/erb' +require 'hamlit/filters/escaped' +require 'hamlit/filters/javascript' +require 'hamlit/filters/less' +require 'hamlit/filters/markdown' +require 'hamlit/filters/plain' +require 'hamlit/filters/preserve' +require 'hamlit/filters/ruby' +require 'hamlit/filters/sass' +require 'hamlit/filters/scss' +require 'hamlit/filters/cdata' + +module Hamlit + class Filters + @registered = {} + + class << self + attr_reader :registered + + def remove_filter(name) + registered.delete(name.to_s.downcase.to_sym) + if constants.map(&:to_s).include?(name.to_s) + remove_const name.to_sym + end + end + + private + + def register(name, compiler) + registered[name] = compiler + end + end + + register :coffee, Coffee + register :coffeescript, CoffeeScript + register :css, Css + register :erb, Erb + register :escaped, Escaped + register :javascript, Javascript + register :less, Less + register :markdown, Markdown + register :plain, Plain + register :preserve, Preserve + register :ruby, Ruby + register :sass, Sass + register :scss, Scss + register :cdata, Cdata + + def initialize(options = {}) + @options = options + @compilers = {} + end + + def compile(node) + node.value[:text] ||= '' + find_compiler(node).compile(node) + end + + private + + def find_compiler(node) + name = node.value[:name].to_sym + compiler = Filters.registered[name] + raise FilterNotFound.new("FilterCompiler for '#{name}' was not found", node.line.to_i - 1) unless compiler + + @compilers[name] ||= compiler.new(@options) + end + end +end diff --git a/lib/hamlit/filters/base.rb b/lib/hamlit/filters/base.rb new file mode 100644 index 0000000..d98d457 --- /dev/null +++ b/lib/hamlit/filters/base.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true +require 'hamlit/parser/haml_util' + +module Hamlit + class Filters + class Base + def initialize(options = {}) + @format = options[:format] + end + end + end +end diff --git a/lib/hamlit/filters/cdata.rb b/lib/hamlit/filters/cdata.rb new file mode 100644 index 0000000..c90f143 --- /dev/null +++ b/lib/hamlit/filters/cdata.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true +module Hamlit + class Filters + class Cdata < TextBase + def compile(node) + compile_cdata(node) + end + + private + + def compile_cdata(node) + temple = [:multi] + temple << [:static, ""] + temple + end + end + end +end diff --git a/lib/hamlit/filters/coffee.rb b/lib/hamlit/filters/coffee.rb new file mode 100644 index 0000000..5aee191 --- /dev/null +++ b/lib/hamlit/filters/coffee.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true +module Hamlit + class Filters + class Coffee < TiltBase + def compile(node) + require 'tilt/coffee' if explicit_require?('coffee') + temple = [:multi] + temple << [:static, ""] + temple + end + end + + CoffeeScript = Coffee + end +end diff --git a/lib/hamlit/filters/css.rb b/lib/hamlit/filters/css.rb new file mode 100644 index 0000000..db7769b --- /dev/null +++ b/lib/hamlit/filters/css.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +module Hamlit + 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 diff --git a/lib/hamlit/filters/erb.rb b/lib/hamlit/filters/erb.rb new file mode 100644 index 0000000..67d9297 --- /dev/null +++ b/lib/hamlit/filters/erb.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +module Hamlit + class Filters + class Erb < TiltBase + def compile(node) + compile_with_tilt(node, 'erb') + end + end + end +end diff --git a/lib/hamlit/filters/escaped.rb b/lib/hamlit/filters/escaped.rb new file mode 100644 index 0000000..9c37f51 --- /dev/null +++ b/lib/hamlit/filters/escaped.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +module Hamlit + 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 ::Hamlit::HamlUtil.contains_interpolation?(text) + [:dynamic, ::Hamlit::HamlUtil.unescape_interpolation(text)] + else + [:static, text] + end + end + end + end +end diff --git a/lib/hamlit/filters/javascript.rb b/lib/hamlit/filters/javascript.rb new file mode 100644 index 0000000..57ec162 --- /dev/null +++ b/lib/hamlit/filters/javascript.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +module Hamlit + 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 diff --git a/lib/hamlit/filters/less.rb b/lib/hamlit/filters/less.rb new file mode 100644 index 0000000..c5530a8 --- /dev/null +++ b/lib/hamlit/filters/less.rb @@ -0,0 +1,20 @@ +# 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 Hamlit + class Filters + class Less < TiltBase + def compile(node) + require 'tilt/less' if explicit_require?('less') + temple = [:multi] + temple << [:static, "'] + temple + end + end + end +end diff --git a/lib/hamlit/filters/markdown.rb b/lib/hamlit/filters/markdown.rb new file mode 100644 index 0000000..48bde2e --- /dev/null +++ b/lib/hamlit/filters/markdown.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true +module Hamlit + class Filters + class Markdown < TiltBase + def compile(node) + require 'tilt/redcarpet' if explicit_require?('markdown') + compile_with_tilt(node, 'markdown') + end + end + end +end diff --git a/lib/hamlit/filters/plain.rb b/lib/hamlit/filters/plain.rb new file mode 100644 index 0000000..9fa3fae --- /dev/null +++ b/lib/hamlit/filters/plain.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true +require 'hamlit/string_splitter' + +module Hamlit + class Filters + class Plain < Base + def compile(node) + text = node.value[:text] + text = text.rstrip unless ::Hamlit::HamlUtil.contains_interpolation?(text) # for compatibility + [:multi, *compile_plain(text)] + end + + private + + def compile_plain(text) + string_literal = ::Hamlit::HamlUtil.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 diff --git a/lib/hamlit/filters/preserve.rb b/lib/hamlit/filters/preserve.rb new file mode 100644 index 0000000..f98a4f2 --- /dev/null +++ b/lib/hamlit/filters/preserve.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +module Hamlit + 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 ::Hamlit::HamlUtil.contains_interpolation?(text) + [:dynamic, ::Hamlit::HamlUtil.unescape_interpolation(text)] + else + [:static, text] + end + end + end + end +end diff --git a/lib/hamlit/filters/ruby.rb b/lib/hamlit/filters/ruby.rb new file mode 100644 index 0000000..e6dccd9 --- /dev/null +++ b/lib/hamlit/filters/ruby.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +module Hamlit + class Filters + class Ruby < Base + def compile(node) + [:code, node.value[:text]] + end + end + end +end diff --git a/lib/hamlit/filters/sass.rb b/lib/hamlit/filters/sass.rb new file mode 100644 index 0000000..0f1d715 --- /dev/null +++ b/lib/hamlit/filters/sass.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +module Hamlit + class Filters + class Sass < TiltBase + def compile(node) + require 'tilt/sass' if explicit_require?('sass') + temple = [:multi] + temple << [:static, ""] + temple + end + end + end +end diff --git a/lib/hamlit/filters/scss.rb b/lib/hamlit/filters/scss.rb new file mode 100644 index 0000000..e74e48c --- /dev/null +++ b/lib/hamlit/filters/scss.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +module Hamlit + class Filters + class Scss < TiltBase + def compile(node) + require 'tilt/sass' if explicit_require?('scss') + temple = [:multi] + temple << [:static, ""] + temple + end + end + end +end diff --git a/lib/hamlit/filters/text_base.rb b/lib/hamlit/filters/text_base.rb new file mode 100644 index 0000000..f29742b --- /dev/null +++ b/lib/hamlit/filters/text_base.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true +module Hamlit + class Filters + class TextBase < Base + def compile_text!(temple, node, prefix) + text = node.value[:text].rstrip.gsub(/^/, prefix) + if ::Hamlit::HamlUtil.contains_interpolation?(node.value[:text]) + # original: Haml::Filters#compile + text = ::Hamlit::HamlUtil.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 diff --git a/lib/hamlit/filters/tilt_base.rb b/lib/hamlit/filters/tilt_base.rb new file mode 100644 index 0000000..cb7e1d4 --- /dev/null +++ b/lib/hamlit/filters/tilt_base.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true +require 'tilt' + +module Hamlit + 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 + text.gsub!(/^/, ' ' * indent_width) + end + + def explicit_require?(needed_registration) + Gem::Version.new(Tilt::VERSION) >= Gem::Version.new('2.0.0') && + !Tilt.registered?(needed_registration) + end + + private + + def compile_with_tilt(node, name, indent_width: 0) + if ::Hamlit::HamlUtil.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 = ::Hamlit::HamlUtil.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, "::Hamlit::Filters::TiltBase.render('#{name}', #{text}, indent_width: #{indent_width})"] + end + end + end +end diff --git a/lib/hamlit/force_escapable.rb b/lib/hamlit/force_escapable.rb new file mode 100644 index 0000000..6b52638 --- /dev/null +++ b/lib/hamlit/force_escapable.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true +require 'hamlit/escapable' + +module Hamlit + # 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 Hamlit::Escapable, this escapes value even if it's html_safe. + class ForceEscapable < Escapable + def initialize(opts = {}) + super + @escape_code = options[:escape_code] || "::Hamlit::Utils.escape_html((%s))" + @escaper = eval("proc {|v| #{@escape_code % 'v'} }") + end + + alias_method :on_fescape, :on_escape + + # ForceEscapable doesn't touch :escape expression. + # This method is not used if it's inserted after Hamlit::Escapable. + def on_escape(flag, exp) + [:escape, flag, compile(exp)] + end + end +end diff --git a/lib/hamlit/helpers.rb b/lib/hamlit/helpers.rb new file mode 100644 index 0000000..48e3367 --- /dev/null +++ b/lib/hamlit/helpers.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +module Hamlit + module Helpers + extend self + + # The same as original Haml::Helpers#preserve without block support. + def preserve(input) + # https://github.com/haml/haml/blob/4.1.0.beta.1/lib/haml/helpers.rb#L130-L133 + s = input.to_s.chomp("\n") + s.gsub!(/\n/, ' ') + s.delete!("\r") + s + end + end +end diff --git a/lib/hamlit/html.rb b/lib/hamlit/html.rb new file mode 100644 index 0000000..ee056be --- /dev/null +++ b/lib/hamlit/html.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +module Hamlit + 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" + options[: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) + + # https://github.com/haml/haml/blob/4.0.7/lib/haml/template.rb + module HamlHelpers + require 'hamlit/parser/haml_helpers/xss_mods' + include Hamlit::HamlHelpers::XssMods + end + + module HamlUtil + undef :rails_xss_safe? if defined? rails_xss_safe? + def rails_xss_safe?; true; end + end +end + +# Haml extends Haml::Helpers in ActionView each time. +# It costs much, so Hamlit includes a compatible module at first. +ActionView::Base.send :include, Hamlit::RailsHelpers diff --git a/lib/hamlit/railtie.rb b/lib/hamlit/railtie.rb new file mode 100644 index 0000000..ff1e5ab --- /dev/null +++ b/lib/hamlit/railtie.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +require 'rails' + +module Hamlit + class Railtie < ::Rails::Railtie + initializer :hamlit, before: :load_config_initializers do |app| + # Load haml/plugin first to override if available + begin + require 'haml/plugin' + rescue LoadError + end + require 'hamlit/rails_template' + end + end +end diff --git a/lib/hamlit/ruby_expression.rb b/lib/hamlit/ruby_expression.rb new file mode 100644 index 0000000..5aecb01 --- /dev/null +++ b/lib/hamlit/ruby_expression.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true +require 'ripper' + +module Hamlit + 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 diff --git a/lib/hamlit/string_splitter.rb b/lib/hamlit/string_splitter.rb new file mode 100644 index 0000000..6366fd5 --- /dev/null +++ b/lib/hamlit/string_splitter.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true +require 'ripper' +require 'hamlit/ruby_expression' + +module Hamlit + module StringSplitter + # `code` param must be valid string literal + def self.compile(code) + unless Ripper.respond_to?(:lex) # truffleruby doesn't have Ripper.lex + return [[:dynamic, code]] + end + + begin + Temple::Filters::StringSplitter.compile(code) + rescue Temple::FilterError => e + raise Hamlit::InternalError.new(e.message) + end + end + end +end diff --git a/lib/hamlit/template.rb b/lib/hamlit/template.rb new file mode 100644 index 0000000..7fb93a1 --- /dev/null +++ b/lib/hamlit/template.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: false +require 'temple' +require 'hamlit/engine' +require 'hamlit/helpers' + +# Load tilt/haml first to override if available +begin + require 'haml' +rescue LoadError +else + require 'tilt/haml' +end + +module Hamlit + Template = Temple::Templates::Tilt.create( + Hamlit::Engine, + register_as: [:haml, :hamlit], + ) + + module TemplateExtension + # Activate Hamlit::Helpers for tilt templates. + # https://github.com/judofyr/temple/blob/v0.7.6/lib/temple/mixins/template.rb#L7-L11 + def compile(*) + "extend Hamlit::Helpers; #{super}" + end + end + Template.send(:extend, TemplateExtension) +end diff --git a/lib/hamlit/temple_line_counter.rb b/lib/hamlit/temple_line_counter.rb new file mode 100644 index 0000000..084d69f --- /dev/null +++ b/lib/hamlit/temple_line_counter.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +module Hamlit + # 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 diff --git a/lib/hamlit/utils.rb b/lib/hamlit/utils.rb new file mode 100644 index 0000000..e23ed0a --- /dev/null +++ b/lib/hamlit/utils.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true +module Hamlit + module Utils + # Java extension is not implemented for JRuby yet. + # TruffleRuby does not implement `rb_ary_sort_bang`, etc. + if /java/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby' + require 'cgi/escape' + + def self.escape_html(html) + CGI.escapeHTML(html.to_s) + end + else + require 'hamlit/hamlit' # Hamlit::Utils.escape_html + end + + def self.escape_html_safe(html) + html.html_safe? ? html : escape_html(html) + end + end +end diff --git a/lib/hamlit/version.rb b/lib/hamlit/version.rb new file mode 100644 index 0000000..8543b94 --- /dev/null +++ b/lib/hamlit/version.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true +module Hamlit + VERSION = '2.15.1' +end diff --git a/test/haml/engine_test.rb b/test/haml/engine_test.rb new file mode 100644 index 0000000..83d80e9 --- /dev/null +++ b/test/haml/engine_test.rb @@ -0,0 +1,2108 @@ +$:.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) + Hamlit::Template.new(hamlit_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] Hamlit 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] Hamlit 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] Hamlit 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] Hamlit 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] Hamlit 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_interpolation_with_global_at_the_beginning_of_a_line; skip # special interpolation + $global_var_for_testing = 2 + + assert_equal("

2

\n", render('%p #$global_var_for_testing')) + assert_equal("

\n 2\n

\n", render("%p\n \#$global_var_for_testing")) + ensure + $global_var_for_testing = nil + 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] Hamlit 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] Hamlit 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] Hamlit 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 Hamlit::SyntaxError => e + assert_equal(Hamlit::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; skip # object reference + user = User.new 42 + assert_equal("

New User

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

My Thing

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

CPK Record

\n", + render("%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 Hamlit::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 Hamlit::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 Hamlit::Error").render_proc(scope) + proc.call + assert(false, "Expected exception") + rescue Exception; skip + assert_nil(scope.send(:haml_buffer)) + end + + def test_render_proc_should_raise_haml_syntax_error_not_ruby_syntax_error + assert_raises(Haml::SyntaxError) do + Haml::Engine.new("%p{:foo => !}").render_proc(Object.new, :foo).call + end + end + + def test_render_should_raise_haml_syntax_error_not_ruby_syntax_error + assert_raises(Haml::SyntaxError) do + Haml::Engine.new("%p{:foo => !}").render + end + 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; skip # options + 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(Hamlit::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_interpolates_global_vars_in_attribute_values + # make sure the value isn't just interpolated in during template compilation + engine = Haml::Engine.new('%a{:b => "a #$global_var_for_testing b"}') + $global_var_for_testing = 'bar' + assert_equal("\n", engine.to_html) + ensure + $global_var_for_testing = nil + 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] Hamlit 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] Hamlit 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_convert_template_render_proc + assert_converts_template_properly {|e| e.render_proc.call} + end + + def test_convert_template_render + assert_converts_template_properly {|e| e.render} + end + + def test_convert_template_def_method + assert_converts_template_properly do |e| + o = Object.new + e.def_method(o, :render) + o.render + end + end + + def test_encoding_error # encoding + render("foo\nbar\nb\xFEaz".dup.force_encoding("utf-8")) + assert(false, "Expected exception") + rescue Hamlit::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 Hamlit::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_converts_template_properly + engine = Haml::Engine.new(< "macRoman") +%p bâr +%p föö +HAML + assert_encoded_equal(<bâr

+

föö

+HTML + 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 if RUBY_ENGINE != 'truffleruby' # truffleruby cannot run Haml diff --git a/test/haml/erb/_av_partial_1.erb b/test/haml/erb/_av_partial_1.erb new file mode 100644 index 0000000..0c836a1 --- /dev/null +++ b/test/haml/erb/_av_partial_1.erb @@ -0,0 +1,12 @@ +

This is a pretty complicated partial

+
+

It has several nested partials,

+
    + <% 5.times do %> +
  • + Partial: + <% @nesting = 5 %> + <%= render :partial => 'erb/av_partial_2' %> + <% end %> +
+
diff --git a/test/haml/erb/_av_partial_2.erb b/test/haml/erb/_av_partial_2.erb new file mode 100644 index 0000000..189d858 --- /dev/null +++ b/test/haml/erb/_av_partial_2.erb @@ -0,0 +1,8 @@ +<% @nesting -= 1 %> +
+

This is a crazy deep-nested partial.

+

Nesting level <%= @nesting %>

+ <% if @nesting > 0 %> + <%= render :partial => 'erb/av_partial_2' %> + <% end %> +
diff --git a/test/haml/erb/action_view.erb b/test/haml/erb/action_view.erb new file mode 100644 index 0000000..389ffe9 --- /dev/null +++ b/test/haml/erb/action_view.erb @@ -0,0 +1,62 @@ + + + + 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 %> + + + diff --git a/test/haml/erb/standard.erb b/test/haml/erb/standard.erb new file mode 100644 index 0000000..0cc8ea7 --- /dev/null +++ b/test/haml/erb/standard.erb @@ -0,0 +1,55 @@ + + + + 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 %> + + + diff --git a/test/haml/filters_test.rb b/test/haml/filters_test.rb new file mode 100644 index 0000000..933c187 --- /dev/null +++ b/test/haml/filters_test.rb @@ -0,0 +1,262 @@ +require 'test_helper' + +class FiltersTest < Haml::TestCase + test "should be registered as filters when including Hamlit::Filters::Base" do; skip + begin + refute Hamlit::Filters.defined.has_key? "bar" + Module.new {def self.name; "Foo::Bar"; end; include Hamlit::Filters::Base} + assert Hamlit::Filters.defined.has_key? "bar" + ensure + Hamlit::Filters.remove_filter "Bar" + end + end + + test "should raise error when attempting to register a defined Tilt filter" do; skip + begin + assert_raises RuntimeError do + 2.times do + Hamlit::Filters.register_tilt_filter "Foo" + end + end + ensure + Hamlit::Filters.remove_filter "Foo" + end + end + + test "should raise error when a Tilt filters dependencies are unavailable for extension" do; skip + begin + assert_raises Hamlit::Error do + # ignore warnings from Tilt + silence_warnings do + Hamlit::Filters.register_tilt_filter "Textile" + Hamlit::Filters.defined["textile"].template_class + end + end + ensure + Hamlit::Filters.remove_filter "Textile" + end + end + + test "should raise error when a Tilt filters dependencies are unavailable for filter without extension" do; skip + begin + assert_raises Hamlit::Error do + Hamlit::Filters.register_tilt_filter "Maruku" + Hamlit::Filters.defined["maruku"].template_class + end + ensure + Hamlit::Filters.remove_filter "Maruku" + end + end + + test "should raise informative error about Maruku being moved to haml-contrib" do; skip + begin + render(":maruku\n # foo") + flunk("Should have raised error with message about the haml-contrib gem.") + rescue Hamlit::Error => e + assert_equal e.message, Hamlit::Error.message(:install_haml_contrib, "maruku") + end + end + + test "should raise informative error about Textile being moved to haml-contrib" do; skip + begin + render(":textile\n h1. foo") + flunk("Should have raised error with message about the haml-contrib gem.") + rescue Hamlit::Error => e + assert_equal e.message, Hamlit::Error.message(:install_haml_contrib, "textile") + end + end + + test "should respect escaped newlines and interpolation" do + assert_haml_ugly(":plain\n \\n\#{""}") + end + + test "should process an filter with no content" do + assert_equal("\n", render(':plain')) + end + + test "should be compatible with ugly mode" do + expectation = "foo\n" + assert_equal(expectation, render(":plain\n foo")) + end + + test "should pass options to Tilt filters that precompile" do; skip + begin + orig_erb_opts = Hamlit::Filters::Erb.options + haml = ":erb\n <%= 'foo' %>" + refute_match('test_var', Haml::Engine.new(haml).compiler.precompiled) + Hamlit::Filters::Erb.options = {:outvar => 'test_var'} + assert_match('test_var', Haml::Engine.new(haml).compiler.precompiled) + ensure + Hamlit::Filters::Erb.options = orig_erb_opts + end + end + + test "should pass options to Tilt filters that don't precompile" do; skip + begin + filter = Class.new(Tilt::Template) do + def self.name + "Foo" + end + + def prepare + @engine = {:data => data, :options => options} + end + + def evaluate(scope, locals, &block) + @output = @engine[:options].to_a.join + end + end + Hamlit::Filters.register_tilt_filter "Foo", :template_class => filter + Hamlit::Filters::Foo.options[:foo] = "bar" + haml = ":foo" + assert_equal "foobar\n", render(haml) + ensure + Hamlit::Filters.remove_filter "Foo" + end + end + + test "interpolated code should be escaped if escape_html is set" do; skip + assert_haml_ugly(":plain\n \#{''}") + 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; skip + haml = ":erb\n <%= foo %>" + html = "bar\n" + scope = Object.new.instance_eval {foo = "bar"; nil if foo; binding} + assert_equal(html, render(haml, :scope => scope)) + 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 diff --git a/test/haml/gemfiles/.bundle/config b/test/haml/gemfiles/.bundle/config new file mode 100644 index 0000000..2fbf0ff --- /dev/null +++ b/test/haml/gemfiles/.bundle/config @@ -0,0 +1 @@ +--- {} diff --git a/test/haml/gemfiles/Gemfile.rails-4.0.x b/test/haml/gemfiles/Gemfile.rails-4.0.x new file mode 100644 index 0000000..9769d16 --- /dev/null +++ b/test/haml/gemfiles/Gemfile.rails-4.0.x @@ -0,0 +1,10 @@ +source "https://rubygems.org" + +if ENV['TRAVIS'] + platform :mri_21 do + gem 'coveralls', require: false + end +end + +gem 'rails', '~> 4.0.0' +gemspec :path => '../..' diff --git a/test/haml/gemfiles/Gemfile.rails-4.1.x b/test/haml/gemfiles/Gemfile.rails-4.1.x new file mode 100644 index 0000000..23af5b1 --- /dev/null +++ b/test/haml/gemfiles/Gemfile.rails-4.1.x @@ -0,0 +1,4 @@ +source "https://rubygems.org" + +gem 'rails', '~> 4.1.0' +gemspec :path => '../..' diff --git a/test/haml/gemfiles/Gemfile.rails-4.2.x b/test/haml/gemfiles/Gemfile.rails-4.2.x new file mode 100644 index 0000000..fa56c67 --- /dev/null +++ b/test/haml/gemfiles/Gemfile.rails-4.2.x @@ -0,0 +1,4 @@ +source "https://rubygems.org" + +gem 'rails', '~> 4.2.0' +gemspec :path => '../..' diff --git a/test/haml/haml-spec/LICENSE b/test/haml/haml-spec/LICENSE new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/test/haml/haml-spec/LICENSE @@ -0,0 +1,14 @@ + 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. + diff --git a/test/haml/haml-spec/README.md b/test/haml/haml-spec/README.md new file mode 100644 index 0000000..3366c7b --- /dev/null +++ b/test/haml/haml-spec/README.md @@ -0,0 +1,106 @@ +# 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) diff --git a/test/haml/haml-spec/Rakefile b/test/haml/haml-spec/Rakefile new file mode 100644 index 0000000..601bc73 --- /dev/null +++ b/test/haml/haml-spec/Rakefile @@ -0,0 +1,85 @@ +$:.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 "hamlit" + 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.hamlit_result(haml, options, locals) + eval Hamlit::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) + hamlit_result = #{mode.capitalize}Test.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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 diff --git a/test/haml/haml-spec/tests.yml b/test/haml/haml-spec/tests.yml new file mode 100644 index 0000000..4589fe9 --- /dev/null +++ b/test/haml/haml-spec/tests.yml @@ -0,0 +1,538 @@ +--- +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

      diff --git a/test/haml/haml-spec/ugly_test.rb b/test/haml/haml-spec/ugly_test.rb new file mode 100644 index 0000000..6eccfe8 --- /dev/null +++ b/test/haml/haml-spec/ugly_test.rb @@ -0,0 +1,1110 @@ +$:.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, escape_attrs: 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.hamlit_result(haml, options, locals) + Hamlit::Template.new(HAMLIT_DEFAULT_OPTIONS.merge(options)) { haml }.render(Object.new, locals) + 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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_an_HTML_5_doctype + haml = %q{!!!} + _html = %q{} + locals = {} + options = {:format=>:html5} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_a_tag_with_underscores + haml = %q{%snake_case} + _html = %q{} + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_a_tag_with_dashes + haml = %q{%dashed-tag} + _html = %q{} + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_a_tag_with_camelCase + haml = %q{%camelCase} + _html = %q{} + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_a_tag_with_PascalCase + haml = %q{%PascalCase} + _html = %q{} + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_a_class_with_underscores + haml = %q{.__} + _html = %q{
      } + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_a_class_with_dashes + haml = %q{.--} + _html = %q{
      } + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_HTML_style_tag_multiple_CSS_classes_sorted_correctly_ + haml = %q{.z(class=var)} + _html = %q{
      } + locals = {:var=>"a"} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_HTML_style_tag_with_an_atomic_attribute + skip '[INCOMPATIBILITY] Hamlit limits boolean attributes' + haml = %q{%a(flag)} + _html = %q{} + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_Ruby_style_tag_multiple_CSS_classes_sorted_correctly_ + haml = %q{.z{:class => var}} + _html = %q{
      } + locals = {:var=>"a"} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_a_nested_silent_comment + haml = %q{-# + hello} + _html = %q{} + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_a_nested_markup_comment + haml = %q{/ + comment + comment2} + _html = %q{} + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_interpolation_when_the_escape_character_is_escaped + haml = %q{%p \\#{var}} + _html = %q{

      \value

      } + locals = {:var=>"value"} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + + def test_boolean_attribute_with_HTML + haml = %q{%input(checked=true)} + _html = %q{} + locals = {} + options = {:format=>:html5} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + end + + class Whitespacepreservation < MiniTest::Test + def test_following_the_operator + haml = %q{~ "Foo\n
      Bar\nBaz
      "} + _html = %q{Foo +
      Bar
      Baz
      } + locals = {} + options = {} + haml_result = UglyTest.haml_result(haml, options, locals) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_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) + hamlit_result = UglyTest.hamlit_result(haml, options, locals) + assert_equal haml_result, hamlit_result + end + end +end if RUBY_ENGINE != 'truffleruby' # truffleruby cannot run Haml diff --git a/test/haml/helper_test.rb b/test/haml/helper_test.rb new file mode 100644 index 0000000..5c9e412 --- /dev/null +++ b/test/haml/helper_test.rb @@ -0,0 +1,698 @@ +require '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 + @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(''), {}, ActionController::Base.new) + @base.view_paths << File.expand_path("../templates", __FILE__) + @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_flatten + assert_equal("FooBar", Haml::Helpers.flatten("FooBar")) + + assert_equal("FooBar", Haml::Helpers.flatten("Foo\rBar")) + + assert_equal("Foo Bar", Haml::Helpers.flatten("Foo\nBar")) + + assert_equal("Hello World! YOU ARE FLAT? OMGZ!", + Haml::Helpers.flatten("Hello\nWorld!\nYOU ARE \rFLAT?\n\rOMGZ!")) + 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_init_haml_helpers + context = Object.new + class << context + include Haml::Helpers + end + context.init_haml_helpers + + result = context.capture_haml do + context.haml_tag :p, :attr => "val" do + context.haml_concat "Blah" + end + end + + assert_equal("

\n Blah\n

\n", result) + 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 + assert_equal ""><&", Haml::Helpers.html_escape('"><&') + end + + def test_html_escape_should_work_on_frozen_strings + begin + assert Haml::Helpers.html_escape('foo'.freeze) + rescue => e + flunk e.message + end + end + + def test_html_escape_encoding + old_stderr, $stderr = $stderr, StringIO.new + string = "\"><&\u00e9" # if you're curious, u00e9 is "LATIN SMALL LETTER E WITH ACUTE" + assert_equal ""><&\u00e9", Haml::Helpers.html_escape(string) + assert $stderr.string == "", "html_escape shouldn't generate warnings with UTF-8 strings: #{$stderr.string}" + ensure + $stderr = old_stderr + 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 + assert_equal ""><&", Haml::Helpers.escape_once('"><&') + end + + def test_escape_once_leaves_entity_references + assert_equal ""><&  ", Haml::Helpers.escape_once('"><&  ') + 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_escape_once_encoding + old_stderr, $stderr = $stderr, StringIO.new + string = "\"><&\u00e9  " + assert_equal ""><&\u00e9  ", Haml::Helpers.escape_once(string) + assert $stderr.string == "", "html_escape shouldn't generate warnings with UTF-8 strings: #{$stderr.string}" + ensure + $stderr = old_stderr + 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 + + def test_escape_once_should_work_on_frozen_strings + begin + Haml::Helpers.escape_once('foo'.freeze) + rescue => e + flunk e.message + end + end + +end diff --git a/test/haml/markaby/standard.mab b/test/haml/markaby/standard.mab new file mode 100644 index 0000000..aff8641 --- /dev/null +++ b/test/haml/markaby/standard.mab @@ -0,0 +1,52 @@ +self << '' +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 diff --git a/test/haml/mocks/article.rb b/test/haml/mocks/article.rb new file mode 100644 index 0000000..805f8ca --- /dev/null +++ b/test/haml/mocks/article.rb @@ -0,0 +1,6 @@ +class Article + attr_accessor :id, :title, :body + def initialize + @id, @title, @body = 1, 'Hello', 'World' + end +end \ No newline at end of file diff --git a/test/haml/results/content_for_layout.xhtml b/test/haml/results/content_for_layout.xhtml new file mode 100644 index 0000000..63bbd22 --- /dev/null +++ b/test/haml/results/content_for_layout.xhtml @@ -0,0 +1,12 @@ + + + + +
+ Lorem ipsum dolor sit amet +
+
+ Lorem ipsum dolor sit amet +
+ + diff --git a/test/haml/results/eval_suppressed.xhtml b/test/haml/results/eval_suppressed.xhtml new file mode 100644 index 0000000..fb7bd33 --- /dev/null +++ b/test/haml/results/eval_suppressed.xhtml @@ -0,0 +1,9 @@ +

+

+

Me!

+
+

All

+
+

This

+Should render +
diff --git a/test/haml/results/helpers.xhtml b/test/haml/results/helpers.xhtml new file mode 100644 index 0000000..1d6d8fa --- /dev/null +++ b/test/haml/results/helpers.xhtml @@ -0,0 +1,72 @@ +&&&&&&&&&&& +
+

Title

+

+Woah this is really crazy +I mean wow, +man. +

+
+ +
+

Title

+

+Woah this is really crazy +I mean wow, +man. +

+
+ +
+

Title

+

+Woah this is really crazy +I mean wow, +man. +

+
+ +

foo

+

reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooong

+
+
+
+

Big!

+

Small

+ +
+
+

foo

+

bar

+
+
+(parentheses!) +
+*Not really +click +here. +

baz

+

boom

+foo +
  • google
  • +foo +

    +bar +
    +boom +baz +boom, again +

    + + + + + +
    +strong! +data + +more_data +
    +
    +
    diff --git a/test/haml/results/helpful.xhtml b/test/haml/results/helpful.xhtml new file mode 100644 index 0000000..f18cbdb --- /dev/null +++ b/test/haml/results/helpful.xhtml @@ -0,0 +1,13 @@ +
    +

    Hello

    +
    World
    +
    +
    id
    +
    class
    +
    id class
    +
    boo
    +
    moo
    +
    foo
    + +Boo + diff --git a/test/haml/results/just_stuff.xhtml b/test/haml/results/just_stuff.xhtml new file mode 100644 index 0000000..3ce2adf --- /dev/null +++ b/test/haml/results/just_stuff.xhtml @@ -0,0 +1,68 @@ + + + + + +Boo! +Embedded? false! +Embedded? true! +Embedded? true! +Embedded? twice! true! +Embedded? one af"t"er another! +

    Embedded? false!

    +

    Embedded? true!

    +

    Embedded? true!

    +

    Embedded? twice! true!

    +

    Embedded? one af"t"er another!

    +stuff followed by whitespace +block with whitespace +

    +Escape +- character +%p foo +yee\ha + don't lstrip me +

    + + +

    class attribute should appear!

    +

    this attribute shouldn't appear

    + + + +testtest +
    + + +
    + + +
    +Nested content +
    +

    Blah

    +

    Blah

    +

    Blah

    +

    Blump

    +

    Whee

    +Woah inner quotes +

    +

    + +hello +

    + +
    + diff --git a/test/haml/results/list.xhtml b/test/haml/results/list.xhtml new file mode 100644 index 0000000..c481811 --- /dev/null +++ b/test/haml/results/list.xhtml @@ -0,0 +1,12 @@ +!Not a Doctype! +
      +
    • a
    • +
    • b
    • +
    • c
    • +
    • d
    • +
    • e
    • +
    • f
    • +
    • g
    • +
    • h
    • +
    • i
    • +
    diff --git a/test/haml/results/nuke_inner_whitespace.xhtml b/test/haml/results/nuke_inner_whitespace.xhtml new file mode 100644 index 0000000..4a7bf83 --- /dev/null +++ b/test/haml/results/nuke_inner_whitespace.xhtml @@ -0,0 +1,40 @@ +

    +Foo +

    +

    +Foo +

    +

    +Foo +Bar +

    +

    +Foo +Bar +

    +

    +Foo +Bar +

    +

    +Foo +Bar +

    +

    +

    +Foo +Bar +
    +

    +

    +

    +Foo +Bar +
    +

    +

    +foo + +bar + +

    diff --git a/test/haml/results/nuke_outer_whitespace.xhtml b/test/haml/results/nuke_outer_whitespace.xhtml new file mode 100644 index 0000000..913dc10 --- /dev/null +++ b/test/haml/results/nuke_outer_whitespace.xhtml @@ -0,0 +1,140 @@ +

    +

    +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 +

    +

    +

    +

    +

    +

    +

    +

    +

    +

    +

    +

    +

    +

    diff --git a/test/haml/results/original_engine.xhtml b/test/haml/results/original_engine.xhtml new file mode 100644 index 0000000..e277475 --- /dev/null +++ b/test/haml/results/original_engine.xhtml @@ -0,0 +1,20 @@ + + + +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?
    +
    + + diff --git a/test/haml/results/partial_layout.xhtml b/test/haml/results/partial_layout.xhtml new file mode 100644 index 0000000..6a60101 --- /dev/null +++ b/test/haml/results/partial_layout.xhtml @@ -0,0 +1,6 @@ +

    Partial layout used with for block:

    +
    +

    This is inside a partial layout

    +

    Some content within a layout

    + +
    diff --git a/test/haml/results/partial_layout_erb.xhtml b/test/haml/results/partial_layout_erb.xhtml new file mode 100644 index 0000000..fe433e9 --- /dev/null +++ b/test/haml/results/partial_layout_erb.xhtml @@ -0,0 +1,6 @@ +

    Partial layout used with for block:

    +
    +

    This is inside a partial layout

    +Some content within a layout + +
    diff --git a/test/haml/results/partials.xhtml b/test/haml/results/partials.xhtml new file mode 100644 index 0000000..675c526 --- /dev/null +++ b/test/haml/results/partials.xhtml @@ -0,0 +1,22 @@ +

    +@foo = +value one +

    +

    +@foo = +value two +

    +

    + @foo = + value two +

    +Toplevel? false +

    + @foo = + value three +

    + +

    +@foo = +value three +

    diff --git a/test/haml/results/render_layout.xhtml b/test/haml/results/render_layout.xhtml new file mode 100644 index 0000000..9712bb5 --- /dev/null +++ b/test/haml/results/render_layout.xhtml @@ -0,0 +1,3 @@ +Before +During +After diff --git a/test/haml/results/silent_script.xhtml b/test/haml/results/silent_script.xhtml new file mode 100644 index 0000000..cd7b86f --- /dev/null +++ b/test/haml/results/silent_script.xhtml @@ -0,0 +1,74 @@ +
    +

    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

    +
    diff --git a/test/haml/results/standard.xhtml b/test/haml/results/standard.xhtml new file mode 100644 index 0000000..7d7c6e4 --- /dev/null +++ b/test/haml/results/standard.xhtml @@ -0,0 +1,159 @@ + + + +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 + + diff --git a/test/haml/results/tag_parsing.xhtml b/test/haml/results/tag_parsing.xhtml new file mode 100644 index 0000000..a575d86 --- /dev/null +++ b/test/haml/results/tag_parsing.xhtml @@ -0,0 +1,23 @@ +
    +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +
    +
    +

    +
    a
    +
    b
    +
    c
    +
    d
    +
    e
    +
    f
    +
    g
    +
    diff --git a/test/haml/results/very_basic.xhtml b/test/haml/results/very_basic.xhtml new file mode 100644 index 0000000..25f83eb --- /dev/null +++ b/test/haml/results/very_basic.xhtml @@ -0,0 +1,5 @@ + + + + + diff --git a/test/haml/results/whitespace_handling.xhtml b/test/haml/results/whitespace_handling.xhtml new file mode 100644 index 0000000..8c86da8 --- /dev/null +++ b/test/haml/results/whitespace_handling.xhtml @@ -0,0 +1,94 @@ +
    +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + +
    +
    +
    +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
    diff --git a/test/haml/template_test.rb b/test/haml/template_test.rb new file mode 100644 index 0000000..50b0a97 --- /dev/null +++ b/test/haml/template_test.rb @@ -0,0 +1,371 @@ +require 'test_helper' +require 'haml/mocks/article' + +require 'action_pack/version' +require 'hamlit/rails_template' + +module Haml::Filters::Test + include Haml::Filters::Base + + def render(text) + "TESTING HAHAHAHA!" + end +end + +module Hamlit::RailsHelpers + def test_partial(name, locals = {}) + Hamlit::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) + old_options = Haml::Template.options.dup + Haml::Template.options[:escape_html] = false + 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 + ensure + Haml::Template.options = old_options + 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 = Hamlit::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_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_html_escaping_with_non_strings + assert_haml_ugly("= html_escape(4)") + 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(< 'templates/av_partial_2' \ No newline at end of file diff --git a/test/haml/templates/_av_partial_1_ugly.haml b/test/haml/templates/_av_partial_1_ugly.haml new file mode 100644 index 0000000..02aa9d0 --- /dev/null +++ b/test/haml/templates/_av_partial_1_ugly.haml @@ -0,0 +1,9 @@ +%h2 This is a pretty complicated partial +.partial + %p It has several nested partials, + %ul + - 5.times do + %li + %strong Partial: + - @nesting = 5 + = render :partial => 'templates/av_partial_2_ugly' \ No newline at end of file diff --git a/test/haml/templates/_av_partial_2.haml b/test/haml/templates/_av_partial_2.haml new file mode 100644 index 0000000..e7d2008 --- /dev/null +++ b/test/haml/templates/_av_partial_2.haml @@ -0,0 +1,5 @@ +- @nesting -= 1 +.partial{:level => @nesting} + %h3 This is a crazy deep-nested partial. + %p== Nesting level #{@nesting} + = render :partial => 'templates/av_partial_2' if @nesting > 0 \ No newline at end of file diff --git a/test/haml/templates/_av_partial_2_ugly.haml b/test/haml/templates/_av_partial_2_ugly.haml new file mode 100644 index 0000000..0b854fc --- /dev/null +++ b/test/haml/templates/_av_partial_2_ugly.haml @@ -0,0 +1,5 @@ +- @nesting -= 1 +.partial{:level => @nesting} + %h3 This is a crazy deep-nested partial. + %p== Nesting level #{@nesting} + = render :partial => 'templates/av_partial_2_ugly' if @nesting > 0 \ No newline at end of file diff --git a/test/haml/templates/_layout.erb b/test/haml/templates/_layout.erb new file mode 100644 index 0000000..91c839d --- /dev/null +++ b/test/haml/templates/_layout.erb @@ -0,0 +1,3 @@ +Before +<%= yield -%> +After diff --git a/test/haml/templates/_layout_for_partial.haml b/test/haml/templates/_layout_for_partial.haml new file mode 100644 index 0000000..7cf538b --- /dev/null +++ b/test/haml/templates/_layout_for_partial.haml @@ -0,0 +1,3 @@ +.partial-layout + %h2 This is inside a partial layout + = yield \ No newline at end of file diff --git a/test/haml/templates/_partial.haml b/test/haml/templates/_partial.haml new file mode 100644 index 0000000..756b54b --- /dev/null +++ b/test/haml/templates/_partial.haml @@ -0,0 +1,8 @@ +%p + @foo = + = @foo +- @foo = 'value three' +== Toplevel? #{haml_buffer.toplevel?} +%p + @foo = + = @foo diff --git a/test/haml/templates/_text_area.haml b/test/haml/templates/_text_area.haml new file mode 100644 index 0000000..896b975 --- /dev/null +++ b/test/haml/templates/_text_area.haml @@ -0,0 +1,3 @@ +.text_area_test_area + ~ "" += "" diff --git a/test/haml/templates/_text_area_helper.html.haml b/test/haml/templates/_text_area_helper.html.haml new file mode 100644 index 0000000..f70d044 --- /dev/null +++ b/test/haml/templates/_text_area_helper.html.haml @@ -0,0 +1,4 @@ +- defined?(text_area_helper) and nil # silence a warning +.foo + .bar + = text_area :post, :body diff --git a/test/haml/templates/action_view.haml b/test/haml/templates/action_view.haml new file mode 100644 index 0000000..a90f423 --- /dev/null +++ b/test/haml/templates/action_view.haml @@ -0,0 +1,47 @@ +!!! +%html{html_attrs} + %head + %title Hampton Catlin Is Totally Awesome + %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} + %body + %h1 + This is very much like the standard template, + except that it has some ActionView-specific stuff. + It's only used for benchmarking. + .crazy_partials= render :partial => 'templates/av_partial_1' + / You're In my house now! + .header + 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 + #body= " Quotes should be loved! Just like people!" + - 120.times do |number| + - number + Wow.| + %p + = "Holy cow " + | + "multiline " + | + "tags! " + | + "A pipe (|) even!" | + = [1, 2, 3].collect { |n| "PipesIgnored|" } + = [1, 2, 3].collect { |n| | + n.to_s | + }.join("|") | + %div.silent + - foo = String.new + - foo << "this" + - foo << " shouldn't" + - foo << " evaluate" + = foo + " but now it should!" + -# Woah crap a comment! + + -# That was a line that shouldn't close everything. + %ul.really.cool + - ('a'..'f').each do |a| + %li= a + #combo.of_divs_with_underscore= @should_eval = "with this text" + = [ 104, 101, 108, 108, 111 ].map do |byte| + - byte.chr + .footer + %strong.shout= "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" diff --git a/test/haml/templates/action_view_ugly.haml b/test/haml/templates/action_view_ugly.haml new file mode 100644 index 0000000..9e441a3 --- /dev/null +++ b/test/haml/templates/action_view_ugly.haml @@ -0,0 +1,47 @@ +!!! +%html{html_attrs} + %head + %title Hampton Catlin Is Totally Awesome + %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} + %body + %h1 + This is very much like the standard template, + except that it has some ActionView-specific stuff. + It's only used for benchmarking. + .crazy_partials= render :partial => 'templates/av_partial_1_ugly' + / You're In my house now! + .header + 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 + #body= " Quotes should be loved! Just like people!" + - 120.times do |number| + - number + Wow.| + %p + = "Holy cow " + | + "multiline " + | + "tags! " + | + "A pipe (|) even!" | + = [1, 2, 3].collect { |n| "PipesIgnored|" } + = [1, 2, 3].collect { |n| | + n.to_s | + }.join("|") | + %div.silent + - foo = String.new + - foo << "this" + - foo << " shouldn't" + - foo << " evaluate" + = foo + " but now it should!" + -# Woah crap a comment! + + -# That was a line that shouldn't close everything. + %ul.really.cool + - ('a'..'f').each do |a| + %li= a + #combo.of_divs_with_underscore= @should_eval = "with this text" + = [ 104, 101, 108, 108, 111 ].map do |byte| + - byte.chr + .footer + %strong.shout= "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" diff --git a/test/haml/templates/breakage.haml b/test/haml/templates/breakage.haml new file mode 100644 index 0000000..57c1734 --- /dev/null +++ b/test/haml/templates/breakage.haml @@ -0,0 +1,8 @@ +%p + %h1 Hello! + = "lots of lines" + - raise "Oh no!" + %p + this is after the exception + %strong yes it is! +ho ho ho. diff --git a/test/haml/templates/content_for_layout.haml b/test/haml/templates/content_for_layout.haml new file mode 100644 index 0000000..e9d7e6d --- /dev/null +++ b/test/haml/templates/content_for_layout.haml @@ -0,0 +1,8 @@ +!!! +%html + %head + %body + #yieldy + = yield :layout + #nosym + = yield diff --git a/test/haml/templates/eval_suppressed.haml b/test/haml/templates/eval_suppressed.haml new file mode 100644 index 0000000..1e3c034 --- /dev/null +++ b/test/haml/templates/eval_suppressed.haml @@ -0,0 +1,11 @@ += "not me!" += "nor me!" +- haml_concat "not even me!" +%p= "NO!" +%p~ "UH-UH!" +%h1 Me! +#foo + %p#bar All + %br/ + %p.baz This + Should render diff --git a/test/haml/templates/helpers.haml b/test/haml/templates/helpers.haml new file mode 100644 index 0000000..c4be300 --- /dev/null +++ b/test/haml/templates/helpers.haml @@ -0,0 +1,55 @@ += h("&&&&&&&&&&&") # This is an ActionView Helper... should load +- foo = capture do # This ActionView Helper is designed for ERB, but should work with haml + %div + %p.title Title + %p.text + Woah this is really crazy + I mean wow, + man. +- 3.times do + = foo +%p foo +- tab_up +%p reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooong +- tab_down +.woah + #funky + = capture_haml do + %div + %h1 Big! + %p Small + / Invisible + = capture do + .dilly + %p foo + %h1 bar + = surround '(', ')' do + %strong parentheses! += precede '*' do + %span.small Not really +click += succeed '.' do + %a{:href=>"thing"} here +%p baz +- haml_buffer.tabulation = 10 +%p boom +- concat "foo\n" +- haml_buffer.tabulation = 0 += list_of({:google => 'http://www.google.com'}) do |name, link| + %a{ :href => link }= name +%p + - haml_concat "foo" + %div + - haml_concat "bar" + - haml_concat "boom" + baz + - haml_concat "boom, again" +- haml_tag :table do + - haml_tag :tr do + - haml_tag :td, {:class => 'cell'} do + - haml_tag :strong, "strong!" + - haml_concat "data" + - haml_tag :td do + - haml_concat "more_data" +- haml_tag :hr +- haml_tag :div, '' diff --git a/test/haml/templates/helpful.haml b/test/haml/templates/helpful.haml new file mode 100644 index 0000000..3e44a50 --- /dev/null +++ b/test/haml/templates/helpful.haml @@ -0,0 +1,11 @@ +%div[@article] + %h1= @article.title + %div= @article.body +#id[@article] id +.class[@article] class +#id.class[@article] id class +%div{:class => "article full"}[@article]= "boo" +%div{'class' => "article full"}[@article]= "moo" +%div.articleFull[@article]= "foo" +%span[@not_a_real_variable_and_will_be_nil] + Boo diff --git a/test/haml/templates/just_stuff.haml b/test/haml/templates/just_stuff.haml new file mode 100644 index 0000000..0dd82c7 --- /dev/null +++ b/test/haml/templates/just_stuff.haml @@ -0,0 +1,86 @@ +!!! XML +!!! XML ISO-8859-1 +!!! XML UtF-8 Foo bar +!!! +!!! 1.1 +!!! 1.1 Strict +!!! Strict foo bar +!!! FRAMESET +%strong{:apos => "Foo's bar!"} Boo! +== Embedded? false! +== Embedded? #{true}! +- embedded = true +== Embedded? #{embedded}! +== Embedded? #{"twice! #{true}"}! +== Embedded? #{"one"} af"t"er #{"another"}! +%p== Embedded? false! +%p== Embedded? #{true}! +- embedded = true +%p== Embedded? #{embedded}! +%p== Embedded? #{"twice! #{true}"}! +%p== Embedded? #{"one"} af"t"er #{"another"}! += "stuff followed by whitespace" + +- if true + + %strong block with whitespace +%p + \Escape + \- character + \%p foo + \yee\ha + \ don't lstrip me +/ Short comment +/ + This is a block comment + cool, huh? + %strong there can even be sub-tags! + = "Or script!" +-# Haml comment +-# + Nested Haml comment + - raise 'dead' +%p{ :class => "" } class attribute should appear! +%p{ :gorbachev => nil } this attribute shouldn't appear +/[if lte IE6] conditional comment! +/[if gte IE7] + %p Block conditional comment + %div + %h1 Cool, eh? +/[if gte IE5.2] + Woah a period. += "test" | + "test" | +-# Hard tabs shouldn't throw errors. + +- case :foo +- when :bar + %br Blah +- when :foo + %br +- case :foo + - when :bar + %meta{ :foo => 'blah'} + - when :foo + %meta{ :foo => 'bar'} +%img +%hr +%link +%script Inline content +%br + Nested content +%p.foo{:class => true ? 'bar' : 'baz'}[@article] Blah +%p.foo{:class => false ? 'bar' : ''}[@article] Blah +%p.foo{:class => %w[bar baz]}[@article] Blah +%p.qux{:class => 'quux'}[@article] Blump +%p#foo{:id => %w[bar baz]}[@article] Whee +== #{"Woah inner quotes"} +%p.dynamic_quote{:quotes => "single '", :dyn => 1 + 2} +%p.dynamic_self_closing{:dyn => 1 + 2}/ +%body + :plain + hello + %div + + %img + diff --git a/test/haml/templates/list.haml b/test/haml/templates/list.haml new file mode 100644 index 0000000..40a80e6 --- /dev/null +++ b/test/haml/templates/list.haml @@ -0,0 +1,12 @@ +!Not a Doctype! +%ul + %li a + %li b + %li c + %li d + %li e + %li f + %li g + %li h + %li i + diff --git a/test/haml/templates/nuke_inner_whitespace.haml b/test/haml/templates/nuke_inner_whitespace.haml new file mode 100644 index 0000000..8eebd41 --- /dev/null +++ b/test/haml/templates/nuke_inner_whitespace.haml @@ -0,0 +1,32 @@ +%p + %q< Foo +%p + %q{:a => 1 + 1}< Foo +%p + %q<= "Foo\nBar" +%p + %q{:a => 1 + 1}<= "Foo\nBar" +%p + %q< + Foo + Bar +%p + %q{:a => 1 + 1}< + Foo + Bar +%p + %q< + %div + Foo + Bar +%p + %q{:a => 1 + 1}< + %div + Foo + Bar + +-# Regression test +%p + %q<= "foo" + %q{:a => 1 + 1} + bar diff --git a/test/haml/templates/nuke_outer_whitespace.haml b/test/haml/templates/nuke_outer_whitespace.haml new file mode 100644 index 0000000..1e2a7f5 --- /dev/null +++ b/test/haml/templates/nuke_outer_whitespace.haml @@ -0,0 +1,144 @@ +%p + %p + %q> + Foo +%p + %p + %q{:a => 1 + 1}> + Foo +%p + %p + %q> Foo +%p + %p + %q{:a => 1 + 1}> Foo +%p + %p + %q> + = "Foo" +%p + %p + %q{:a => 1 + 1}> + = "Foo" +%p + %p + %q>= "Foo" +%p + %p + %q{:a => 1 + 1}>= "Foo" +%p + %p + %q> + = "Foo\nBar" +%p + %p + %q{:a => 1 + 1}> + = "Foo\nBar" +%p + %p + %q>= "Foo\nBar" +%p + %p + %q{:a => 1 + 1}>= "Foo\nBar" +%p + %p + - tab_up + foo + %q> + Foo + bar + - tab_down +%p + %p + - tab_up + foo + %q{:a => 1 + 1}> + Foo + bar + - tab_down +%p + %p + - tab_up + foo + %q> Foo + bar + - tab_down +%p + %p + - tab_up + foo + %q{:a => 1 + 1}> Foo + bar + - tab_down +%p + %p + - tab_up + foo + %q> + = "Foo" + bar + - tab_down +%p + %p + - tab_up + foo + %q{:a => 1 + 1}> + = "Foo" + bar + - tab_down +%p + %p + - tab_up + foo + %q>= "Foo" + bar + - tab_down +%p + %p + - tab_up + foo + %q{:a => 1 + 1}>= "Foo" + bar + - tab_down +%p + %p + - tab_up + foo + %q> + = "Foo\nBar" + bar + - tab_down +%p + %p + - tab_up + foo + %q{:a => 1 + 1}> + = "Foo\nBar" + bar + - tab_down +%p + %p + - tab_up + foo + %q>= "Foo\nBar" + bar + - tab_down +%p + %p + - tab_up + foo + %q{:a => 1 + 1}>= "Foo\nBar" + bar + - tab_down +%p + %p + %q> +%p + %p + %q>/ +%p + %p + %q{:a => 1 + 1}> +%p + %p + %q{:a => 1 + 1}>/ diff --git a/test/haml/templates/original_engine.haml b/test/haml/templates/original_engine.haml new file mode 100644 index 0000000..df31a5a --- /dev/null +++ b/test/haml/templates/original_engine.haml @@ -0,0 +1,17 @@ +!!! +%html + %head + %title Stop. haml time + #content + %h1 This is a title! + %p Lorem ipsum dolor sit amet, consectetur adipisicing elit + %p{:class => 'foo'} Cigarettes! + %h2 Man alive! + %ul.things + %li Slippers + %li Shoes + %li Bathrobe + %li Coffee + %pre + 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? diff --git a/test/haml/templates/partial_layout.haml b/test/haml/templates/partial_layout.haml new file mode 100644 index 0000000..a463ea1 --- /dev/null +++ b/test/haml/templates/partial_layout.haml @@ -0,0 +1,3 @@ +%h1 Partial layout used with for block: += render :layout => 'layout_for_partial' do + %p Some content within a layout diff --git a/test/haml/templates/partial_layout_erb.erb b/test/haml/templates/partial_layout_erb.erb new file mode 100644 index 0000000..7f88377 --- /dev/null +++ b/test/haml/templates/partial_layout_erb.erb @@ -0,0 +1,4 @@ +

    Partial layout used with for block:

    +<%= render :layout => 'layout_for_partial' do -%> +Some content within a layout +<% end %> diff --git a/test/haml/templates/partialize.haml b/test/haml/templates/partialize.haml new file mode 100644 index 0000000..327d90d --- /dev/null +++ b/test/haml/templates/partialize.haml @@ -0,0 +1 @@ += render :file => "#{name}.haml" diff --git a/test/haml/templates/partials.haml b/test/haml/templates/partials.haml new file mode 100644 index 0000000..d74f4b4 --- /dev/null +++ b/test/haml/templates/partials.haml @@ -0,0 +1,12 @@ +- @foo = 'value one' +%p + @foo = + = @foo +- @foo = 'value two' +%p + @foo = + = @foo += test_partial "partial" +%p + @foo = + = @foo diff --git a/test/haml/templates/render_layout.haml b/test/haml/templates/render_layout.haml new file mode 100644 index 0000000..549742b --- /dev/null +++ b/test/haml/templates/render_layout.haml @@ -0,0 +1,2 @@ += render :layout => 'layout' do + During diff --git a/test/haml/templates/silent_script.haml b/test/haml/templates/silent_script.haml new file mode 100644 index 0000000..2df83e8 --- /dev/null +++ b/test/haml/templates/silent_script.haml @@ -0,0 +1,45 @@ +%div + %h1 I can count! + - (1..20).each do |i| + = i + %h1 I know my ABCs! + %ul + - ('a'..'z').each do |i| + %li= i + %h1 I can catch errors! + - begin + - raise "foo" + - rescue RuntimeError => e + = "Oh no! \"#{e}\" happened!" + %p + "false" is: + - if false + = "true" + - else + = "false" + - if true + - 5.times do |i| + - if i % 2 == 1 + Odd! + - else + Even! + - unless true + Testing else indent + - case 1 + - when 2 + Also testing else indent + - else + = "This can't happen!" +- 13 | +.foo + %strong foobar +- 5.times | + do | + |a| | + %strong= a +.test + - "foo | + bar | + baz" | + + %p boom diff --git a/test/haml/templates/standard.haml b/test/haml/templates/standard.haml new file mode 100644 index 0000000..c1d4866 --- /dev/null +++ b/test/haml/templates/standard.haml @@ -0,0 +1,43 @@ +!!! +%html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en-US", "lang" => "en-US"} + %head + %title Hampton Catlin Is Totally Awesome + %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} + %body + / You're In my house now! + .header + 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 + #body= " Quotes should be loved! Just like people!" + - 120.times do |number| + = number + Wow.| + %p{:code => 1 + 2} + = "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 + %div.silent{:foo => bar} + - foo = String.new + - foo << "this" + - foo << " shouldn't" + - foo << " evaluate" + = foo + " but now it should!" + -# Woah crap a comment! + + -# That was a line that shouldn't close everything. + %ul.really.cool + - ('a'..'f').each do |a| + %li= a + #combo.of_divs_with_underscore= @should_eval = "with this text" + = "foo".each_line do |line| + - nil + .footer + %strong.shout= "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" diff --git a/test/haml/templates/standard_ugly.haml b/test/haml/templates/standard_ugly.haml new file mode 100644 index 0000000..c1d4866 --- /dev/null +++ b/test/haml/templates/standard_ugly.haml @@ -0,0 +1,43 @@ +!!! +%html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en-US", "lang" => "en-US"} + %head + %title Hampton Catlin Is Totally Awesome + %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"} + %body + / You're In my house now! + .header + 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 + #body= " Quotes should be loved! Just like people!" + - 120.times do |number| + = number + Wow.| + %p{:code => 1 + 2} + = "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 + %div.silent{:foo => bar} + - foo = String.new + - foo << "this" + - foo << " shouldn't" + - foo << " evaluate" + = foo + " but now it should!" + -# Woah crap a comment! + + -# That was a line that shouldn't close everything. + %ul.really.cool + - ('a'..'f').each do |a| + %li= a + #combo.of_divs_with_underscore= @should_eval = "with this text" + = "foo".each_line do |line| + - nil + .footer + %strong.shout= "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" diff --git a/test/haml/templates/tag_parsing.haml b/test/haml/templates/tag_parsing.haml new file mode 100644 index 0000000..f142ebb --- /dev/null +++ b/test/haml/templates/tag_parsing.haml @@ -0,0 +1,21 @@ +%div.tags + %foo 1 + %FOO 2 + %fooBAR 3 + %fooBar 4 + %foo_bar 5 + %foo-bar 6 + %foo:bar 7 + %foo.bar 8 + %fooBAr_baz:boom_bar 9 + %foo13 10 + %foo2u 11 +%div.classes + %p.foo.bar#baz#boom + .fooBar a + .foo-bar b + .foo_bar c + .FOOBAR d + .foo16 e + .123 f + .foo2u g diff --git a/test/haml/templates/very_basic.haml b/test/haml/templates/very_basic.haml new file mode 100644 index 0000000..93396b9 --- /dev/null +++ b/test/haml/templates/very_basic.haml @@ -0,0 +1,4 @@ +!!! +%html + %head + %body diff --git a/test/haml/templates/whitespace_handling.haml b/test/haml/templates/whitespace_handling.haml new file mode 100644 index 0000000..f459e75 --- /dev/null +++ b/test/haml/templates/whitespace_handling.haml @@ -0,0 +1,87 @@ +#whitespace_test + = test_partial "text_area", :value => "Oneline" + = test_partial "text_area", :value => "Two\nlines" + ~ test_partial "text_area", :value => "Oneline" + ~ test_partial "text_area", :value => "Two\nlines" + #flattened~ test_partial "text_area", :value => "Two\nlines" +.hithere + ~ "Foo bar" + ~ "
    foo bar
    " + ~ "
    foo\nbar
    " + %p~ "
    foo\nbar
    " + %p~ "foo\nbar" +.foo + ~ 13 + ~ "".each_line do |l| + - haml_concat l.strip +#whitespace_test + = test_partial "text_area", :value => "Oneline" + = test_partial "text_area", :value => "Two\nlines" + = find_and_preserve test_partial("text_area", :value => "Oneline") + = find_and_preserve test_partial("text_area", :value => "Two\nlines") + #flattened= find_and_preserve test_partial("text_area", :value => "Two\nlines") +.hithere + = find_and_preserve("Foo bar") + = find_and_preserve("
    foo bar
    ") + = find_and_preserve("
    foo\nbar
    ") + %p= find_and_preserve("
    foo\nbar
    ") + %p= find_and_preserve("foo\nbar") + %pre + :preserve + ___ + ,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! + %strong This should! + %textarea + :preserve + ___ ___ ___ ___ + /\__\ /\ \ /\__\ /\__\ + /:/ / /::\ \ /::| | /:/ / + /:/__/ /:/\:\ \ /:|:| | /:/ / + /::\ \ ___ /::\~\:\ \ /:/|:|__|__ /:/ / + /:/\:\ /\__\ /:/\:\ \:\__\ /:/ |::::\__\ /:/__/ + \/__\:\/:/ / \/__\:\/:/ / \/__/~~/:/ / \:\ \ + \::/ / \::/ / /:/ / \:\ \ + /:/ / /:/ / /:/ / \:\ \ + /:/ / /:/ / /:/ / \:\__\ + \/__/ \/__/ \/__/ \/__/ + + Many + thanks + to + http://www.network-science.de/ascii/ + %strong indeed! +.foo + = find_and_preserve(13) +%pre + :preserve + __ ______ __ ______ + .----.| |--.|__ |.----.| |--..--------.| __ | + | __|| ||__ || __|| < | || __ | + |____||__|__||______||____||__|__||__|__|__||______| +%pre + :preserve + foo + bar diff --git a/test/haml/templates/with_bom.haml b/test/haml/templates/with_bom.haml new file mode 100644 index 0000000..c1aa69f --- /dev/null +++ b/test/haml/templates/with_bom.haml @@ -0,0 +1 @@ +BOMG \ No newline at end of file diff --git a/test/hamlit/attribute_parser_test.rb b/test/hamlit/attribute_parser_test.rb new file mode 100644 index 0000000..59997ad --- /dev/null +++ b/test/hamlit/attribute_parser_test.rb @@ -0,0 +1,101 @@ +describe Hamlit::AttributeParser do + describe '.parse' do + def assert_parse(expected, haml) + actual = Hamlit::AttributeParser.parse(haml) + if expected.nil? + assert_nil actual + else + assert_equal expected, actual + end + end + + it { assert_parse({}, '') } + it { assert_parse({}, '{}') } + + describe 'invalid hash' do + it { assert_parse(nil, ' hash ') } + it { assert_parse(nil, 'hash, foo: bar') } + it { assert_parse(nil, ' {hash} ') } + it { assert_parse(nil, ' { hash, foo: bar } ') } + end + + describe 'dynamic key' do + it { assert_parse(nil, 'foo => 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 diff --git a/test/hamlit/cli_test.rb b/test/hamlit/cli_test.rb new file mode 100644 index 0000000..02bf398 --- /dev/null +++ b/test/hamlit/cli_test.rb @@ -0,0 +1,21 @@ +require 'hamlit/cli' + +describe Hamlit::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('hamlit') + f.write('%input{ hash }') + f.close + Hamlit::CLI.new.temple(f.path) + end + end + end +end diff --git a/test/hamlit/dynamic_merger_test.rb b/test/hamlit/dynamic_merger_test.rb new file mode 100644 index 0000000..9af00d8 --- /dev/null +++ b/test/hamlit/dynamic_merger_test.rb @@ -0,0 +1,57 @@ +describe Hamlit::DynamicMerger do + describe '#call' do + def assert_compile(expected, input) + actual = Hamlit::DynamicMerger.new.compile(input) + assert_equal expected, actual + end + + def assert_noop(input) + actual = Hamlit::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 diff --git a/test/hamlit/engine/attributes_test.rb b/test/hamlit/engine/attributes_test.rb new file mode 100644 index 0000000..c5fd5e2 --- /dev/null +++ b/test/hamlit/engine/attributes_test.rb @@ -0,0 +1,361 @@ +require_relative '../../test_helper' + +describe Hamlit::Engine do + include RenderHelper + + describe 'id attributes' do + describe 'compatilibity' do + 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 + 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 + 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 + 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 + 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 + 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 diff --git a/test/hamlit/engine/comment_test.rb b/test/hamlit/engine/comment_test.rb new file mode 100644 index 0000000..a1e0aa7 --- /dev/null +++ b/test/hamlit/engine/comment_test.rb @@ -0,0 +1,75 @@ +describe Hamlit::Engine do + include RenderHelper + + describe 'comment' do + it 'renders html comment' 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 diff --git a/test/hamlit/engine/doctype_test.rb b/test/hamlit/engine/doctype_test.rb new file mode 100644 index 0000000..2b79a6e --- /dev/null +++ b/test/hamlit/engine/doctype_test.rb @@ -0,0 +1,21 @@ +describe Hamlit::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 + end +end diff --git a/test/hamlit/engine/indent_test.rb b/test/hamlit/engine/indent_test.rb new file mode 100644 index 0000000..d91b2e3 --- /dev/null +++ b/test/hamlit/engine/indent_test.rb @@ -0,0 +1,44 @@ +describe Hamlit::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 diff --git a/test/hamlit/engine/multiline_test.rb b/test/hamlit/engine/multiline_test.rb new file mode 100644 index 0000000..40510ee --- /dev/null +++ b/test/hamlit/engine/multiline_test.rb @@ -0,0 +1,46 @@ +describe Hamlit::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 diff --git a/test/hamlit/engine/new_attribute_test.rb b/test/hamlit/engine/new_attribute_test.rb new file mode 100644 index 0000000..f7cbb55 --- /dev/null +++ b/test/hamlit/engine/new_attribute_test.rb @@ -0,0 +1,101 @@ +describe Hamlit::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 diff --git a/test/hamlit/engine/old_attribute_test.rb b/test/hamlit/engine/old_attribute_test.rb new file mode 100644 index 0000000..c727eab --- /dev/null +++ b/test/hamlit/engine/old_attribute_test.rb @@ -0,0 +1,476 @@ +require_relative '../../test_helper' + +describe Hamlit::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 '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 + + 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 + if RUBY_ENGINE == 'truffleruby' + skip 'truffleruby raises NoMethodError' + end + + assert_raises ArgumentError do + render_hamlit("%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 + 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 + 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 + end if RUBY_ENGINE != 'truffleruby' # aria attribute is not working in truffleruby + + 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 diff --git a/test/hamlit/engine/script_test.rb b/test/hamlit/engine/script_test.rb new file mode 100644 index 0000000..eda58a0 --- /dev/null +++ b/test/hamlit/engine/script_test.rb @@ -0,0 +1,146 @@ +describe Hamlit::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) + 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) + + 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 diff --git a/test/hamlit/engine/silent_script_test.rb b/test/hamlit/engine/silent_script_test.rb new file mode 100644 index 0000000..098eaf9 --- /dev/null +++ b/test/hamlit/engine/silent_script_test.rb @@ -0,0 +1,222 @@ +describe Hamlit::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 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 diff --git a/test/hamlit/engine/tag_test.rb b/test/hamlit/engine/tag_test.rb new file mode 100644 index 0000000..821447c --- /dev/null +++ b/test/hamlit/engine/tag_test.rb @@ -0,0 +1,200 @@ +describe Hamlit::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 diff --git a/test/hamlit/engine/text_test.rb b/test/hamlit/engine/text_test.rb new file mode 100644 index 0000000..178b1b1 --- /dev/null +++ b/test/hamlit/engine/text_test.rb @@ -0,0 +1,212 @@ +describe Hamlit::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 diff --git a/test/hamlit/engine/whitespace_test.rb b/test/hamlit/engine/whitespace_test.rb new file mode 100644 index 0000000..20ebd00 --- /dev/null +++ b/test/hamlit/engine/whitespace_test.rb @@ -0,0 +1,115 @@ +describe Hamlit::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 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) + 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) +
    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) + %div>< + = 1.times do + %span> + hello + HAML + end + end +end diff --git a/test/hamlit/error_test.rb b/test/hamlit/error_test.rb new file mode 100644 index 0000000..f1c464c --- /dev/null +++ b/test/hamlit/error_test.rb @@ -0,0 +1,54 @@ +describe Hamlit::Engine do + describe 'HamlSyntaxError' do + it 'raises on runtime' do + code = Hamlit::Engine.new.call(" %a") + assert_raises(Hamlit::HamlSyntaxError) do + eval code + end + end + + it 'returns error with lines before error' do + code = Hamlit::Engine.new.call("\n\n %a") + begin + eval code + rescue Hamlit::HamlSyntaxError => e + assert_equal(2, e.line) + end + end + + describe 'Hamlit v1 syntax' do + it 'returns an error with proper line number' do + code = Hamlit::Engine.new.call(<<-HAML.unindent) + %span + - if true + %div{ data: { + hello: 'world', + } } + HAML + begin + eval code + rescue Hamlit::HamlSyntaxError => e + assert_equal(3, e.line) + end + end + end + end + + describe 'FilterNotFound' do + it 'raises on runtime' do + code = Hamlit::Engine.new.call(":k0kubun") + assert_raises(Hamlit::FilterNotFound) do + eval code + end + end + + it 'returns error with lines before error' do + code = Hamlit::Engine.new.call("\n\n:k0kubun") + begin + eval code + rescue Hamlit::FilterNotFound => e + assert_equal(2, e.line) + end + end + end +end diff --git a/test/hamlit/filters/cdata_test.rb b/test/hamlit/filters/cdata_test.rb new file mode 100644 index 0000000..f9497a0 --- /dev/null +++ b/test/hamlit/filters/cdata_test.rb @@ -0,0 +1,27 @@ +describe Hamlit::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 diff --git a/test/hamlit/filters/coffee_test.rb b/test/hamlit/filters/coffee_test.rb new file mode 100644 index 0000000..d4dbb5c --- /dev/null +++ b/test/hamlit/filters/coffee_test.rb @@ -0,0 +1,62 @@ +describe Hamlit::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 diff --git a/test/hamlit/filters/css_test.rb b/test/hamlit/filters/css_test.rb new file mode 100644 index 0000000..8e3ad29 --- /dev/null +++ b/test/hamlit/filters/css_test.rb @@ -0,0 +1,35 @@ +describe Hamlit::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 diff --git a/test/hamlit/filters/erb_test.rb b/test/hamlit/filters/erb_test.rb new file mode 100644 index 0000000..baf3834 --- /dev/null +++ b/test/hamlit/filters/erb_test.rb @@ -0,0 +1,19 @@ +describe Hamlit::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 diff --git a/test/hamlit/filters/javascript_test.rb b/test/hamlit/filters/javascript_test.rb new file mode 100644 index 0000000..2a0b4b0 --- /dev/null +++ b/test/hamlit/filters/javascript_test.rb @@ -0,0 +1,84 @@ +describe Hamlit::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 diff --git a/test/hamlit/filters/markdown_test.rb b/test/hamlit/filters/markdown_test.rb new file mode 100644 index 0000000..bb84f9f --- /dev/null +++ b/test/hamlit/filters/markdown_test.rb @@ -0,0 +1,42 @@ +describe Hamlit::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) +

    Hamlit

    + +

    Yet another haml implementation

    + + HTML + :markdown + # Hamlit + 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 diff --git a/test/hamlit/filters/plain_test.rb b/test/hamlit/filters/plain_test.rb new file mode 100644 index 0000000..78e4a64 --- /dev/null +++ b/test/hamlit/filters/plain_test.rb @@ -0,0 +1,26 @@ +describe Hamlit::Filters do + include RenderHelper + + describe '#compile' do + it 'does not escape content without interpolation' 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 diff --git a/test/hamlit/optimization_test.rb b/test/hamlit/optimization_test.rb new file mode 100644 index 0000000..303a97e --- /dev/null +++ b/test/hamlit/optimization_test.rb @@ -0,0 +1,47 @@ +require_relative '../test_helper' + +describe 'optimization' do + def compiled_code(haml) + Hamlit::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 diff --git a/test/hamlit/rails_template_test.rb b/test/hamlit/rails_template_test.rb new file mode 100644 index 0000000..59b18e8 --- /dev/null +++ b/test/hamlit/rails_template_test.rb @@ -0,0 +1,166 @@ +# Explicitly requiring rails_template because rails initializers is not executed here. +require 'hamlit/rails_template' + +describe Hamlit::RailsTemplate do + def render(haml) + ActionView::Template.register_template_handler(:haml, Hamlit::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: '