diff --git a/README.md b/README.md index 1dd4691a..07a712c4 100644 --- a/README.md +++ b/README.md @@ -559,6 +559,8 @@ This renders as: div class="first second third" ~~~ +Splat attributes prefix may be configured via `splat_prefix` option. Default value is `'*'` + #### Dynamic tags `*` You can create completely dynamic tags using the splat attributes. Just create a method which returns a hash @@ -967,7 +969,7 @@ There are a lot of them but the good thing is, that Slim checks the configuratio | Boolean | :streaming | false (true in Rails, see below how to disable it!) | Enable output streaming, improves the perceived performance | | Class | :generator | Temple::Generators::StringBuffer/ RailsOutputBuffer | Temple code generator (default generator generates string buffer) | | String | :buffer | '_buf' ('@output_buffer' in Rails) | Variable used for buffer | - +| String | :splat_prefix | '*' | Prefix used for splat attributes | There are more options which are supported by the Temple filters but which are not exposed and are not officially supported. You have to take a look at the Slim and Temple code for that. @@ -1047,6 +1049,47 @@ performance. The rendering time in total will increase. If you want to disable i Slim::RailsTemplate.set_options streaming: false ~~~ +### Angular2 + +Slim now supports Angular2 syntax. But you need to set some configuration options: + +#### `splat_prefix` option + +This option tells parser what syntax to use for splat attributes. +Default value is asterisk: `splat_prefix: '*'` +Asterisk is also used in Angular2 for structural directives such as `*ngIf` and others, so default configuration causes a conflict between slim and angular2 syntax. + +There are two ways to resolve it: + +* Set `splat_prefix` to any custom value, double asterisk, for example: `splat_prefix: '**'`. Now structural directives should work as expected. Remember that now splat attributes should be written with new custom prefix before them. +* Use alternative directive syntax without asterisk. + +#### Attribute delimeters + +Angular and slim both uses brackets in their syntax. So there are also two ways: +* Use alternative syntax for binding (`bind-...` and so on) +* Limit attribute delimeters to curly braces only: +``` +code_attr_delims: { + '{' => '}', +}, +attr_list_delims: { + '{' => '}', +}, +``` + +Now you can use something like this: +``` +h1{ #var (bind1)="test" [bind2]="ok" [(bind3)]="works?" *ngIf="expr" *ngFor="expression" } {{it works}} +``` + +Will be compiled to: +``` +

+ {{it works}} +

+``` + ## Tools ### Slim Command 'slimrb' diff --git a/lib/slim/parser.rb b/lib/slim/parser.rb index 2fdce90a..97c29582 100644 --- a/lib/slim/parser.rb +++ b/lib/slim/parser.rb @@ -18,7 +18,8 @@ class Parser < Temple::Parser shortcut: { '#' => { attr: 'id' }, '.' => { attr: 'class' } - } + }, + splat_prefix: '*' class SyntaxError < StandardError attr_reader :error, :file, :line, :lineno, :column @@ -413,9 +414,13 @@ def parse_attributes(attributes) end_re = /\A\s*#{Regexp.escape delimiter}/ end + splat_prefix = Regexp.escape(options[:splat_prefix]) + splat_regexp_source = '\A\s*' << splat_prefix << '(?=[^\s]+)' + @splat_attrs_regexp = Regexp.new(splat_regexp_source) + while true case @line - when /\A\s*\*(?=[^\s]+)/ + when @splat_attrs_regexp # Splat attribute @line = $' attributes << [:slim, :splat, parse_ruby_code(delimiter)] diff --git a/test/core/test_splat_prefix_option.rb b/test/core/test_splat_prefix_option.rb new file mode 100644 index 00000000..2e5f6508 --- /dev/null +++ b/test/core/test_splat_prefix_option.rb @@ -0,0 +1,155 @@ +require 'helper' + +class TestSplatPrefixOption < TestSlim + + def prefixes + ['*','**','*!','*%','*^','*$'] + end + + def options(prefix) + { splat_prefix: prefix } + end + + def test_splat_without_content + prefixes.each do |prefix| + source = %Q{ + #{prefix}hash + p#{prefix}hash + } + + assert_html '

', source, options(prefix) + end + end + + def test_shortcut_splat + prefixes.each do |prefix| + source = %Q{ +#{prefix}hash This is my title +} + + assert_html '
This is my title
', source, options(prefix) + end + end + + def test_splat + prefixes.each do |prefix| + source = %Q{ +h1 #{prefix}hash class=[] This is my title +} + + assert_html '

This is my title

', source, options(prefix) + end + end + + def test_closed_splat + prefixes.each do |prefix| + source = %Q{ +#{prefix}hash / +} + + assert_html '
', source, options(prefix) + end + end + + def test_splat_tag_name + prefixes.each do |prefix| + source = %Q{ +#{prefix}{tag: 'h1', id: 'title'} This is my title +} + + assert_html '

This is my title

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

This is my title

', source, options(prefix) + end + end + +end