Skip to content

Commit

Permalink
Merge pull request #739 from govorov/angular2
Browse files Browse the repository at this point in the history
Possible solution for Angular2 syntax support
  • Loading branch information
minad committed Nov 28, 2016
2 parents 365abe4 + c2b9225 commit 53723a3
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 3 deletions.
45 changes: 44 additions & 1 deletion README.md
Expand Up @@ -559,6 +559,8 @@ This renders as:
div class="first second third" div class="first second third"
~~~ ~~~
Splat attributes prefix may be configured via `splat_prefix` option. Default value is `'*'`
#### Dynamic tags `*` #### Dynamic tags `*`
You can create completely dynamic tags using the splat attributes. Just create a method which returns a hash You can create completely dynamic tags using the splat attributes. Just create a method which returns a hash
Expand Down Expand Up @@ -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 | | 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) | | 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 | :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 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. have to take a look at the Slim and Temple code for that.
Expand Down Expand Up @@ -1047,6 +1049,47 @@ performance. The rendering time in total will increase. If you want to disable i
Slim::RailsTemplate.set_options streaming: false 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:
```
<h1 #var="" (bind1)="test" [bind2]="ok" [(bind3)]="works?" *ngIf="expr" *ngFor="expression">
{{it works}}
</h1>
```
## Tools ## Tools
### Slim Command 'slimrb' ### Slim Command 'slimrb'
Expand Down
9 changes: 7 additions & 2 deletions lib/slim/parser.rb
Expand Up @@ -18,7 +18,8 @@ class Parser < Temple::Parser
shortcut: { shortcut: {
'#' => { attr: 'id' }, '#' => { attr: 'id' },
'.' => { attr: 'class' } '.' => { attr: 'class' }
} },
splat_prefix: '*'


class SyntaxError < StandardError class SyntaxError < StandardError
attr_reader :error, :file, :line, :lineno, :column attr_reader :error, :file, :line, :lineno, :column
Expand Down Expand Up @@ -413,9 +414,13 @@ def parse_attributes(attributes)
end_re = /\A\s*#{Regexp.escape delimiter}/ end_re = /\A\s*#{Regexp.escape delimiter}/
end 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 while true
case @line case @line
when /\A\s*\*(?=[^\s]+)/ when @splat_attrs_regexp
# Splat attribute # Splat attribute
@line = $' @line = $'
attributes << [:slim, :splat, parse_ruby_code(delimiter)] attributes << [:slim, :splat, parse_ruby_code(delimiter)]
Expand Down
155 changes: 155 additions & 0 deletions 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 '<div a="The letter a" b="The letter b"></div><p a="The letter a" b="The letter b"></p>', source, options(prefix)
end
end

def test_shortcut_splat
prefixes.each do |prefix|
source = %Q{
#{prefix}hash This is my title
}

assert_html '<div a="The letter a" b="The letter b">This is my title</div>', source, options(prefix)
end
end

def test_splat
prefixes.each do |prefix|
source = %Q{
h1 #{prefix}hash class=[] This is my title
}

assert_html '<h1 a="The letter a" b="The letter b">This is my title</h1>', source, options(prefix)
end
end

def test_closed_splat
prefixes.each do |prefix|
source = %Q{
#{prefix}hash /
}

assert_html '<div a="The letter a" b="The letter b" />', 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 '<h1 id="title">This is my title</h1>', 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 '<div id="test">This is my title</div>', source, options(prefix)
end
end

def test_closed_splat_tag
prefixes.each do |prefix|
source = %Q{
#{prefix}hash /
}

assert_html '<div a="The letter a" b="The letter b" />', 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 '<div a="The letter a" b="The letter b" id="myid">This is my title</div>', 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 '<div a="The letter a" b="The letter b" class="myclass">This is my title</div>', 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 '<div a="The letter a" b="The letter b" class="myclass" id="myid">This is my title</div>', 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 '<div a="The letter a" b="The letter b" class="myclass secondclass x y z" id="myid">This is my title</div>', 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 '<div disabled="" nonempty="">This is my title</div>', 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 '<div a="1" b="2" c="3" d="4" e="5" f="6">This is my title</div>', 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 '<h1 a="The letter a" b="The letter b" data-id="123">This is my title</h1>', source, options(prefix)
end
end

end

0 comments on commit 53723a3

Please sign in to comment.