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