haml-edge 2.1.44 → 2.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/EDGE_GEM_VERSION +1 -1
- data/README.md +5 -1
- data/VERSION +1 -1
- data/extra/haml-mode.el +111 -58
- data/lib/haml/buffer.rb +1 -1
- data/lib/haml/precompiler.rb +110 -14
- data/lib/sass/script/number.rb +2 -2
- data/test/haml/engine_test.rb +105 -0
- metadata +22 -3
data/EDGE_GEM_VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.45
|
data/README.md
CHANGED
@@ -57,11 +57,15 @@ check out the [YARD documentation](http://haml-lang.com/docs/yardoc).
|
|
57
57
|
### Haml
|
58
58
|
|
59
59
|
The most basic element of Haml
|
60
|
-
is a shorthand for creating HTML
|
60
|
+
is a shorthand for creating HTML:
|
61
61
|
|
62
62
|
%tagname{:attr1 => 'value1', :attr2 => 'value2'} Contents
|
63
63
|
|
64
64
|
No end-tag is needed; Haml handles that automatically.
|
65
|
+
If you prefer HTML-style attributes, you can also use:
|
66
|
+
|
67
|
+
%tagname(attr1='value1' attr2='value2') Contents
|
68
|
+
|
65
69
|
Adding `class` and `id` attributes is even easier.
|
66
70
|
Haml uses the same syntax as the CSS that styles the document:
|
67
71
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.45
|
data/extra/haml-mode.el
CHANGED
@@ -61,8 +61,12 @@ if the next line could be nested within this line.
|
|
61
61
|
The function can also return a positive integer to indicate
|
62
62
|
a specific level to which the current line could be indented.")
|
63
63
|
|
64
|
+
(defconst haml-tag-beg-re
|
65
|
+
"^ *\\(?:[%\\.#][a-z0-9_:\\-]*\\)+\\(?:(.*)\\|{.*}\\|\\[.*\\]\\)*"
|
66
|
+
"A regexp matching the beginning of a Haml tag, through (), {}, and [].")
|
67
|
+
|
64
68
|
(defvar haml-block-openers
|
65
|
-
`(
|
69
|
+
`(,(concat haml-tag-beg-re "[><]*[ \t]*$")
|
66
70
|
"^ *[&!]?[-=~].*do[ \t]*\\(|.*|[ \t]*\\)?$"
|
67
71
|
,(concat "^ *[&!]?[-=~][ \t]*\\("
|
68
72
|
(regexp-opt '("if" "unless" "while" "until" "else"
|
@@ -122,53 +126,73 @@ For example, this will highlight all of the following:
|
|
122
126
|
%p= 'baz'
|
123
127
|
%p{:foo => 'bar'}[@bar]= 'baz'"
|
124
128
|
(when (re-search-forward "^ *[%.#]" limit t)
|
125
|
-
(
|
129
|
+
(forward-char -1)
|
130
|
+
|
131
|
+
;; Highlight tag, classes, and ids
|
132
|
+
(while (haml-move "\\([.#%]\\)[a-z0-9_:\\-]*")
|
133
|
+
(put-text-property (match-beginning 0) (match-end 0) 'face
|
134
|
+
(case (char-after (match-beginning 1))
|
135
|
+
(?% font-lock-function-name-face)
|
136
|
+
(?# font-lock-keyword-face)
|
137
|
+
(?. font-lock-type-face))))
|
138
|
+
|
139
|
+
(block loop
|
140
|
+
(while t
|
141
|
+
(let ((eol (save-excursion (end-of-line) (point))))
|
142
|
+
(case (char-after)
|
143
|
+
;; Highlight obj refs
|
144
|
+
(?\[
|
145
|
+
(let ((beg (point)))
|
146
|
+
(haml-limited-forward-sexp eol)
|
147
|
+
(haml-fontify-region-as-ruby beg (point))))
|
148
|
+
;; Highlight new attr hashes
|
149
|
+
(?\(
|
150
|
+
(forward-char 1)
|
151
|
+
(while
|
152
|
+
(and (haml-parse-new-attr-hash
|
153
|
+
(lambda (type beg end)
|
154
|
+
(case type
|
155
|
+
(name (put-text-property beg end 'face font-lock-constant-face))
|
156
|
+
(value (haml-fontify-region-as-ruby beg end)))))
|
157
|
+
(not (eobp)))
|
158
|
+
(forward-line 1)
|
159
|
+
(beginning-of-line)))
|
160
|
+
;; Highlight old attr hashes
|
161
|
+
(?\{
|
162
|
+
(let ((beg (point)))
|
163
|
+
(haml-limited-forward-sexp eol)
|
164
|
+
|
165
|
+
;; Check for multiline
|
166
|
+
(while (and (eolp) (eq (char-before) ?,) (not (eobp)))
|
167
|
+
(forward-line)
|
168
|
+
(let ((eol (save-excursion (end-of-line) (point))))
|
169
|
+
;; If no sexps are closed,
|
170
|
+
;; we're still continuing a multiline hash
|
171
|
+
(if (>= (car (parse-partial-sexp (point) eol)) 0)
|
172
|
+
(end-of-line)
|
173
|
+
;; If sexps have been closed,
|
174
|
+
;; set the point at the end of the total sexp
|
175
|
+
(goto-char beg)
|
176
|
+
(haml-limited-forward-sexp eol))))
|
177
|
+
|
178
|
+
(haml-fontify-region-as-ruby (+ 1 beg) (point))))
|
179
|
+
(t (return-from loop))))))
|
180
|
+
|
181
|
+
;; Move past end chars
|
182
|
+
(when (looking-at "[<>&!]+") (goto-char (match-end 0)))
|
183
|
+
;; Highlight script
|
184
|
+
(if (looking-at "\\([=~]\\) \\(.*\\)$")
|
185
|
+
(haml-fontify-region-as-ruby (match-beginning 2) (match-end 2))
|
186
|
+
;; Give font-lock something to highlight
|
126
187
|
(forward-char -1)
|
188
|
+
(looking-at "\\(\\)"))
|
189
|
+
t))
|
127
190
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
(?# font-lock-keyword-face)
|
134
|
-
(?. font-lock-type-face)))
|
135
|
-
(goto-char (match-end 0)))
|
136
|
-
|
137
|
-
;; Highlight obj refs
|
138
|
-
(when (eq (char-after) ?\[)
|
139
|
-
(let ((beg (point)))
|
140
|
-
(haml-limited-forward-sexp eol)
|
141
|
-
(haml-fontify-region-as-ruby beg (point))))
|
142
|
-
|
143
|
-
;; Highlight attr hashes
|
144
|
-
(when (eq (char-after) ?\{)
|
145
|
-
(let ((beg (point)))
|
146
|
-
(haml-limited-forward-sexp eol)
|
147
|
-
|
148
|
-
;; Check for multiline
|
149
|
-
(while (and (eolp) (eq (char-before) ?,) (not (eobp)))
|
150
|
-
(forward-line)
|
151
|
-
(let ((eol (save-excursion (end-of-line) (point))))
|
152
|
-
;; If no sexps are closed,
|
153
|
-
;; we're still continuing a multiline hash
|
154
|
-
(if (>= (car (parse-partial-sexp (point) eol)) 0)
|
155
|
-
(end-of-line)
|
156
|
-
;; If sexps have been closed,
|
157
|
-
;; set the point at the end of the total sexp
|
158
|
-
(goto-char beg)
|
159
|
-
(haml-limited-forward-sexp eol))))
|
160
|
-
|
161
|
-
(haml-fontify-region-as-ruby (+ 1 beg) (point))))
|
162
|
-
|
163
|
-
;; Move past end chars
|
164
|
-
(when (looking-at "[<>&!]+") (goto-char (match-end 0)))
|
165
|
-
;; Highlight script
|
166
|
-
(if (looking-at "\\([=~]\\) \\(.*\\)$")
|
167
|
-
(haml-fontify-region-as-ruby (match-beginning 2) (match-end 2))
|
168
|
-
;; Give font-lock something to highlight
|
169
|
-
(forward-char -1)
|
170
|
-
(looking-at "\\(\\)"))
|
171
|
-
t)))
|
191
|
+
(defun haml-move (re)
|
192
|
+
"Try matching and moving to the end of a regular expression."
|
193
|
+
(when (looking-at re)
|
194
|
+
(goto-char (match-end 0))
|
195
|
+
t))
|
172
196
|
|
173
197
|
(defun haml-highlight-interpolation (limit)
|
174
198
|
"Highlight Ruby interpolation (#{foo})."
|
@@ -441,10 +465,8 @@ character of the next line."
|
|
441
465
|
"Returns t if the current line can have lines nested beneath it."
|
442
466
|
(let ((attr-props (haml-parse-multiline-attr-hash)))
|
443
467
|
(when attr-props
|
444
|
-
(end-of-line)
|
445
468
|
(return-from haml-indent-p
|
446
|
-
(if (
|
447
|
-
(beginning-of-line)
|
469
|
+
(if (haml-unclosed-attr-hash-p) (cdr (assq 'hash-indent attr-props))
|
448
470
|
(list (+ (cdr (assq 'indent attr-props)) haml-indent-offset) nil)))))
|
449
471
|
(loop for opener in haml-block-openers
|
450
472
|
if (looking-at opener) return t
|
@@ -464,20 +486,51 @@ beginning the hash."
|
|
464
486
|
(save-excursion
|
465
487
|
(while t
|
466
488
|
(beginning-of-line)
|
467
|
-
(if (looking-at
|
489
|
+
(if (looking-at (eval-when-compile (concat haml-tag-beg-re "\\([{(]\\)")))
|
468
490
|
(progn
|
469
491
|
(goto-char (- (match-end 0) 1))
|
470
492
|
(haml-limited-forward-sexp (save-excursion (end-of-line) (point)))
|
471
493
|
(return-from haml-parse-multiline-attr-hash
|
472
|
-
(
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
494
|
+
(when (or (string-equal (match-string 1) "(") (eq (char-before) ?,))
|
495
|
+
`((indent . ,(current-indentation))
|
496
|
+
(hash-indent . ,(- (match-end 0) (match-beginning 0)))
|
497
|
+
(point . ,(match-beginning 0))))))
|
498
|
+
(when (bobp) (return-from haml-parse-multiline-attr-hash))
|
477
499
|
(forward-line -1)
|
478
|
-
(
|
479
|
-
|
480
|
-
|
500
|
+
(unless (haml-unclosed-attr-hash-p)
|
501
|
+
(return-from haml-parse-multiline-attr-hash))))))
|
502
|
+
|
503
|
+
(defun* haml-unclosed-attr-hash-p ()
|
504
|
+
"Return t if this line has an unclosed attribute hash, new or old."
|
505
|
+
(save-excursion
|
506
|
+
(end-of-line)
|
507
|
+
(when (eq (char-before) ?,) (return-from haml-unclosed-attr-hash-p t))
|
508
|
+
(re-search-backward "(\\|^")
|
509
|
+
(haml-move "(")
|
510
|
+
(haml-parse-new-attr-hash)))
|
511
|
+
|
512
|
+
(defun* haml-parse-new-attr-hash (&optional (fn (lambda (type beg end) ())))
|
513
|
+
"Parse a new-style attribute hash on this line, and returns
|
514
|
+
t if it's not finished on the current line.
|
515
|
+
|
516
|
+
FN should take three parameters: TYPE, BEG, and END.
|
517
|
+
TYPE is the type of text parsed ('name or 'value)
|
518
|
+
and BEG and END delimit that text in the buffer."
|
519
|
+
(let ((eol (save-excursion (end-of-line) (point))))
|
520
|
+
(while (not (haml-move ")"))
|
521
|
+
(haml-move " *")
|
522
|
+
(unless (haml-move "[a-z0-9_:\\-]+")
|
523
|
+
(return-from haml-parse-new-attr-hash (haml-move " *$")))
|
524
|
+
(funcall fn 'name (match-beginning 0) (match-end 0))
|
525
|
+
(haml-move " *")
|
526
|
+
(when (haml-move "=")
|
527
|
+
(haml-move " *")
|
528
|
+
(unless (looking-at "[\"'@a-z]") (return-from haml-parse-new-attr-hash))
|
529
|
+
(let ((beg (point)))
|
530
|
+
(haml-limited-forward-sexp eol)
|
531
|
+
(funcall fn 'value beg (point)))
|
532
|
+
(haml-move " *")))
|
533
|
+
nil))
|
481
534
|
|
482
535
|
(defun haml-compute-indentation ()
|
483
536
|
"Calculate the maximum sensible indentation for the current line."
|
data/lib/haml/buffer.rb
CHANGED
@@ -252,7 +252,7 @@ RUBY
|
|
252
252
|
|
253
253
|
if to['class'] && from['class']
|
254
254
|
# Make sure we don't duplicate class names
|
255
|
-
from['class'] = (from['class'].split(' ') | to['class'].split(' ')).join(' ')
|
255
|
+
from['class'] = (from['class'].split(' ') | to['class'].split(' ')).sort.join(' ')
|
256
256
|
elsif to['class'] || from['class']
|
257
257
|
from['class'] ||= to['class']
|
258
258
|
end
|
data/lib/haml/precompiler.rb
CHANGED
@@ -456,8 +456,6 @@ END
|
|
456
456
|
end
|
457
457
|
|
458
458
|
def parse_static_hash(text)
|
459
|
-
return {} unless text
|
460
|
-
|
461
459
|
attributes = {}
|
462
460
|
scanner = StringScanner.new(text)
|
463
461
|
scanner.scan(/\s+/)
|
@@ -512,21 +510,38 @@ END
|
|
512
510
|
def parse_tag(line)
|
513
511
|
raise SyntaxError.new("Invalid tag: \"#{line}\".") unless match = line.scan(/%([-:\w]+)([-\w\.\#]*)(.*)/)[0]
|
514
512
|
tag_name, attributes, rest = match
|
515
|
-
|
513
|
+
new_attributes_hash = old_attributes_hash = last_line = object_ref = nil
|
514
|
+
attributes_hashes = []
|
515
|
+
while rest
|
516
|
+
case rest[0]
|
517
|
+
when ?{
|
518
|
+
break if old_attributes_hash
|
519
|
+
old_attributes_hash, rest, last_line = parse_old_attributes(rest)
|
520
|
+
attributes_hashes << [:old, old_attributes_hash]
|
521
|
+
when ?(
|
522
|
+
break if new_attributes_hash
|
523
|
+
new_attributes_hash, rest, last_line = parse_new_attributes(rest)
|
524
|
+
attributes_hashes << [:new, new_attributes_hash]
|
525
|
+
when ?[
|
526
|
+
break if object_ref
|
527
|
+
object_ref, rest = balance(rest, ?[, ?])
|
528
|
+
else; break
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
516
532
|
if rest
|
517
|
-
object_ref, rest = balance(rest, ?[, ?]) if rest[0] == ?[
|
518
|
-
attributes_hash, rest, last_line = parse_attributes(rest) if rest[0] == ?{ && attributes_hash.nil?
|
519
533
|
nuke_whitespace, action, value = rest.scan(/(<>|><|[><])?([=\/\~&!])?(.*)?/)[0]
|
520
534
|
nuke_whitespace ||= ''
|
521
535
|
nuke_outer_whitespace = nuke_whitespace.include? '>'
|
522
536
|
nuke_inner_whitespace = nuke_whitespace.include? '<'
|
523
537
|
end
|
538
|
+
|
524
539
|
value = value.to_s.strip
|
525
|
-
[tag_name, attributes,
|
540
|
+
[tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace,
|
526
541
|
nuke_inner_whitespace, action, value, last_line || @index]
|
527
542
|
end
|
528
543
|
|
529
|
-
def
|
544
|
+
def parse_old_attributes(line)
|
530
545
|
line = line.dup
|
531
546
|
last_line = @index
|
532
547
|
|
@@ -547,10 +562,77 @@ END
|
|
547
562
|
return attributes_hash, rest, last_line
|
548
563
|
end
|
549
564
|
|
565
|
+
def parse_new_attributes(line)
|
566
|
+
line = line.dup
|
567
|
+
scanner = StringScanner.new(line)
|
568
|
+
last_line = @index
|
569
|
+
attributes = {}
|
570
|
+
|
571
|
+
scanner.scan(/\(\s*/)
|
572
|
+
until (name, value = parse_new_attribute(scanner)).first.nil?
|
573
|
+
if name == false
|
574
|
+
text = (Haml::Shared.balance(line, ?(, ?)) || [line]).first
|
575
|
+
raise Haml::SyntaxError.new("Invalid attribute list: #{text.inspect}.", last_line - 1)
|
576
|
+
end
|
577
|
+
attributes[name] = value
|
578
|
+
scanner.scan(/\s*/)
|
579
|
+
|
580
|
+
if scanner.eos?
|
581
|
+
line << " " << @next_line.text
|
582
|
+
last_line += 1
|
583
|
+
next_line
|
584
|
+
scanner.scan(/\s*/)
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
static_attributes = {}
|
589
|
+
dynamic_attributes = "{"
|
590
|
+
attributes.each do |name, (type, val)|
|
591
|
+
if type == :static
|
592
|
+
static_attributes[name] = val
|
593
|
+
else
|
594
|
+
dynamic_attributes << name.inspect << " => " << val << ","
|
595
|
+
end
|
596
|
+
end
|
597
|
+
dynamic_attributes << "}"
|
598
|
+
dynamic_attributes = nil if dynamic_attributes == "{}"
|
599
|
+
|
600
|
+
return [static_attributes, dynamic_attributes], scanner.rest, last_line
|
601
|
+
end
|
602
|
+
|
603
|
+
def parse_new_attribute(scanner)
|
604
|
+
unless name = scanner.scan(/[-:\w]+/)
|
605
|
+
return if scanner.scan(/\)/)
|
606
|
+
return false
|
607
|
+
end
|
608
|
+
|
609
|
+
scanner.scan(/\s*/)
|
610
|
+
return name, [:static, true] unless scanner.scan(/=/) #/end
|
611
|
+
|
612
|
+
scanner.scan(/\s*/)
|
613
|
+
unless quote = scanner.scan(/["']/)
|
614
|
+
return false unless var = scanner.scan(/(@@?|\$)?\w+/)
|
615
|
+
return name, [:dynamic, var]
|
616
|
+
end
|
617
|
+
|
618
|
+
re = /((?:\\.|\#[^{]|[^#{quote}\\#])*)(#{quote}|#\{)/
|
619
|
+
content = []
|
620
|
+
loop do
|
621
|
+
return false unless scanner.scan(re)
|
622
|
+
content << [:str, scanner[1].gsub(/\\(.)/, '\1')]
|
623
|
+
break if scanner[2] == quote
|
624
|
+
content << [:ruby, balance(scanner, ?{, ?}, 1).first[0...-1]]
|
625
|
+
end
|
626
|
+
|
627
|
+
return name, [:static, content.first[1]] if content.size == 1
|
628
|
+
return name, [:dynamic,
|
629
|
+
'"' + content.map {|(t, v)| t == :str ? v.inspect[1...-1] : "\#{#{v}}"}.join + '"']
|
630
|
+
end
|
631
|
+
|
550
632
|
# Parses a line that will render as an XHTML tag, and adds the code that will
|
551
633
|
# render that tag to <tt>@precompiled</tt>.
|
552
634
|
def render_tag(line)
|
553
|
-
tag_name, attributes,
|
635
|
+
tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace,
|
554
636
|
nuke_inner_whitespace, action, value, last_line = parse_tag(line)
|
555
637
|
|
556
638
|
raise SyntaxError.new("Illegal element: classes and ids must have values.") if attributes =~ /[\.#](\.|#|\z)/
|
@@ -597,10 +679,17 @@ END
|
|
597
679
|
|
598
680
|
object_ref = "nil" if object_ref.nil? || @options[:suppress_eval]
|
599
681
|
|
600
|
-
static_attributes = parse_static_hash(attributes_hash) # Try pre-compiling a static attributes hash
|
601
|
-
attributes_hash = nil if static_attributes || @options[:suppress_eval]
|
602
682
|
attributes = parse_class_and_id(attributes)
|
603
|
-
|
683
|
+
attributes_hashes.map! do |syntax, attributes_hash|
|
684
|
+
if syntax == :old
|
685
|
+
static_attributes = parse_static_hash(attributes_hash)
|
686
|
+
attributes_hash = nil if static_attributes || @options[:suppress_eval]
|
687
|
+
else
|
688
|
+
static_attributes, attributes_hash = attributes_hash
|
689
|
+
end
|
690
|
+
Buffer.merge_attrs(attributes, static_attributes) if static_attributes
|
691
|
+
attributes_hash
|
692
|
+
end.compact!
|
604
693
|
|
605
694
|
raise SyntaxError.new("Illegal nesting: nesting within a self-closing tag is illegal.", @next_line.index) if block_opened? && self_closing
|
606
695
|
raise SyntaxError.new("Illegal nesting: content can't be both given on the same line as %#{tag_name} and nested within it.", @next_line.index) if block_opened? && !value.empty?
|
@@ -614,7 +703,7 @@ END
|
|
614
703
|
(nuke_inner_whitespace && block_opened?)
|
615
704
|
|
616
705
|
# Check if we can render the tag directly to text and not process it in the buffer
|
617
|
-
if object_ref == "nil" &&
|
706
|
+
if object_ref == "nil" && attributes_hashes.empty? && !preserve_script
|
618
707
|
tag_closed = !block_opened? && !self_closing && !parse
|
619
708
|
|
620
709
|
open_tag = prerender_tag(tag_name, self_closing, attributes)
|
@@ -633,11 +722,18 @@ END
|
|
633
722
|
else
|
634
723
|
flush_merged_text
|
635
724
|
content = value.empty? || parse ? 'nil' : value.dump
|
636
|
-
|
725
|
+
if attributes_hashes.empty?
|
726
|
+
attributes_hashes = ''
|
727
|
+
elsif attributes_hashes.size == 1
|
728
|
+
attributes_hashes = ", #{attributes_hashes.first}"
|
729
|
+
else
|
730
|
+
attributes_hashes = ", (#{attributes_hashes.join(").merge(")})"
|
731
|
+
end
|
732
|
+
|
637
733
|
args = [tag_name, self_closing, !block_opened?, preserve_tag, escape_html,
|
638
734
|
attributes, nuke_outer_whitespace, nuke_inner_whitespace
|
639
735
|
].map { |v| v.inspect }.join(', ')
|
640
|
-
push_silent "_hamlout.open_tag(#{args}, #{object_ref}, #{content}#{
|
736
|
+
push_silent "_hamlout.open_tag(#{args}, #{object_ref}, #{content}#{attributes_hashes})"
|
641
737
|
@dont_tab_up_next_text = @dont_indent_next_line = dont_indent_next_line
|
642
738
|
end
|
643
739
|
|
data/lib/sass/script/number.rb
CHANGED
@@ -269,9 +269,9 @@ module Sass::Script
|
|
269
269
|
# An incompatible coercion, e.g. between px and cm, will raise an error.
|
270
270
|
#
|
271
271
|
# @param num_units [Array<String>] The numerator units to coerce this number into.
|
272
|
-
# See {
|
272
|
+
# See {\#numerator\_units}
|
273
273
|
# @param den_units [Array<String>] The denominator units to coerce this number into.
|
274
|
-
# See {
|
274
|
+
# See {\#denominator\_units}
|
275
275
|
# @return [Number] The number with the new units
|
276
276
|
# @raise [Sass::UnitConversionError] if the given units are incompatible with the number's
|
277
277
|
# current units
|
data/test/haml/engine_test.rb
CHANGED
@@ -23,6 +23,7 @@ class EngineTest < Test::Unit::TestCase
|
|
23
23
|
"." => "Illegal element: classes and ids must have values.",
|
24
24
|
".#" => "Illegal element: classes and ids must have values.",
|
25
25
|
".{} a" => "Illegal element: classes and ids must have values.",
|
26
|
+
".() a" => "Illegal element: classes and ids must have values.",
|
26
27
|
".= a" => "Illegal element: classes and ids must have values.",
|
27
28
|
"%p..a" => "Illegal element: classes and ids must have values.",
|
28
29
|
"%a/ b" => "Self-closing tags can't have content.",
|
@@ -47,6 +48,12 @@ class EngineTest < Test::Unit::TestCase
|
|
47
48
|
"%p\n foo\n%p\n bar" => ["The line was indented 2 levels deeper than the previous line.", 4],
|
48
49
|
"%p\n foo\n %p\n bar" => ["The line was indented 3 levels deeper than the previous line.", 4],
|
49
50
|
"%p\n \tfoo" => ["Indentation can't use both tabs and spaces.", 2],
|
51
|
+
"%p(" => "Invalid attribute list: \"(\".",
|
52
|
+
"%p(foo=\nbar)" => ["Invalid attribute list: \"(foo=\".", 1],
|
53
|
+
"%p(foo=)" => "Invalid attribute list: \"(foo=)\".",
|
54
|
+
"%p(foo 'bar')" => "Invalid attribute list: \"(foo 'bar')\".",
|
55
|
+
"%p(foo 'bar'\nbaz='bang')" => ["Invalid attribute list: \"(foo 'bar'\".", 1],
|
56
|
+
"%p(foo='bar'\nbaz 'bang'\nbip='bop')" => ["Invalid attribute list: \"(foo='bar' baz 'bang'\".", 2],
|
50
57
|
|
51
58
|
# Regression tests
|
52
59
|
"- raise 'foo'\n\n\n\nbar" => ["foo", 1],
|
@@ -805,6 +812,104 @@ END
|
|
805
812
|
assert_equal %{<!DOCTYPE html>\n}, render('!!!', :format => :html5)
|
806
813
|
end
|
807
814
|
|
815
|
+
# New attributes
|
816
|
+
|
817
|
+
def test_basic_new_attributes
|
818
|
+
assert_equal("<a>bar</a>\n", render("%a() bar"))
|
819
|
+
assert_equal("<a href='foo'>bar</a>\n", render("%a(href='foo') bar"))
|
820
|
+
assert_equal("<a b='c' c='d' d='e'>baz</a>\n", render(%q{%a(b="c" c='d' d="e") baz}))
|
821
|
+
end
|
822
|
+
|
823
|
+
def test_new_attribute_ids
|
824
|
+
assert_equal("<div id='foo_bar'></div>\n", render("#foo(id='bar')"))
|
825
|
+
assert_equal("<div id='foo_bar_baz'></div>\n", render("#foo{:id => 'bar'}(id='baz')"))
|
826
|
+
assert_equal("<div id='foo_baz_bar'></div>\n", render("#foo(id='baz'){:id => 'bar'}"))
|
827
|
+
foo = User.new(42)
|
828
|
+
assert_equal("<div class='struct_user' id='foo_baz_bar_struct_user_42'></div>\n",
|
829
|
+
render("#foo(id='baz'){:id => 'bar'}[foo]", :locals => {:foo => foo}))
|
830
|
+
assert_equal("<div class='struct_user' id='foo_baz_bar_struct_user_42'></div>\n",
|
831
|
+
render("#foo(id='baz')[foo]{:id => 'bar'}", :locals => {:foo => foo}))
|
832
|
+
assert_equal("<div class='struct_user' id='foo_baz_bar_struct_user_42'></div>\n",
|
833
|
+
render("#foo[foo](id='baz'){:id => 'bar'}", :locals => {:foo => foo}))
|
834
|
+
assert_equal("<div class='struct_user' id='foo_bar_baz_struct_user_42'></div>\n",
|
835
|
+
render("#foo[foo]{:id => 'bar'}(id='baz')", :locals => {:foo => foo}))
|
836
|
+
end
|
837
|
+
|
838
|
+
def test_new_attribute_classes
|
839
|
+
assert_equal("<div class='bar foo'></div>\n", render(".foo(class='bar')"))
|
840
|
+
assert_equal("<div class='bar baz foo'></div>\n", render(".foo{:class => 'bar'}(class='baz')"))
|
841
|
+
assert_equal("<div class='bar baz foo'></div>\n", render(".foo(class='baz'){:class => 'bar'}"))
|
842
|
+
foo = User.new(42)
|
843
|
+
assert_equal("<div class='bar baz foo struct_user' id='struct_user_42'></div>\n",
|
844
|
+
render(".foo(class='baz'){:class => 'bar'}[foo]", :locals => {:foo => foo}))
|
845
|
+
assert_equal("<div class='bar baz foo struct_user' id='struct_user_42'></div>\n",
|
846
|
+
render(".foo[foo](class='baz'){:class => 'bar'}", :locals => {:foo => foo}))
|
847
|
+
assert_equal("<div class='bar baz foo struct_user' id='struct_user_42'></div>\n",
|
848
|
+
render(".foo[foo]{:class => 'bar'}(class='baz')", :locals => {:foo => foo}))
|
849
|
+
end
|
850
|
+
|
851
|
+
def test_dynamic_new_attributes
|
852
|
+
assert_equal("<a href='12'>bar</a>\n", render("%a(href=foo) bar", :locals => {:foo => 12}))
|
853
|
+
assert_equal("<a b='12' c='13' d='14'>bar</a>\n", render("%a(b=b c='13' d=d) bar", :locals => {:b => 12, :d => 14}))
|
854
|
+
end
|
855
|
+
|
856
|
+
def test_new_attribute_interpolation
|
857
|
+
assert_equal("<a href='12'>bar</a>\n", render('%a(href="1#{1 + 1}") bar'))
|
858
|
+
assert_equal("<a href='2: 2, 3: 3'>bar</a>\n", render(%q{%a(href='2: #{1 + 1}, 3: #{foo}') bar}, :locals => {:foo => 3}))
|
859
|
+
assert_equal(%Q{<a href='1\#{1 + 1}'>bar</a>\n}, render('%a(href="1\#{1 + 1}") bar'))
|
860
|
+
end
|
861
|
+
|
862
|
+
def test_truthy_new_attributes
|
863
|
+
assert_equal("<a href='href'>bar</a>\n", render("%a(href) bar"))
|
864
|
+
assert_equal("<a bar='baz' href>bar</a>\n", render("%a(href bar='baz') bar", :format => :html5))
|
865
|
+
assert_equal("<a href='href'>bar</a>\n", render("%a(href=true) bar"))
|
866
|
+
assert_equal("<a>bar</a>\n", render("%a(href=false) bar"))
|
867
|
+
end
|
868
|
+
|
869
|
+
def test_new_attribute_parsing
|
870
|
+
assert_equal("<a a2='b2'>bar</a>\n", render("%a(a2=b2) bar", :locals => {:b2 => 'b2'}))
|
871
|
+
assert_equal(%Q{<a a='foo"bar'>bar</a>\n}, render(%q{%a(a="#{'foo"bar'}") bar})) #'
|
872
|
+
assert_equal(%Q{<a a="foo'bar">bar</a>\n}, render(%q{%a(a="#{"foo'bar"}") bar})) #'
|
873
|
+
assert_equal(%Q{<a a='foo"bar'>bar</a>\n}, render(%q{%a(a='foo"bar') bar}))
|
874
|
+
assert_equal(%Q{<a a="foo'bar">bar</a>\n}, render(%q{%a(a="foo'bar") bar}))
|
875
|
+
assert_equal("<a a:b='foo'>bar</a>\n", render("%a(a:b='foo') bar"))
|
876
|
+
assert_equal("<a a='foo' b='bar'>bar</a>\n", render("%a(a = 'foo' b = 'bar') bar"))
|
877
|
+
assert_equal("<a a='foo' b='bar'>bar</a>\n", render("%a(a = foo b = bar) bar", :locals => {:foo => 'foo', :bar => 'bar'}))
|
878
|
+
assert_equal("<a a='foo'>(b='bar')</a>\n", render("%a(a='foo')(b='bar')"))
|
879
|
+
assert_equal("<a a='foo)bar'>baz</a>\n", render("%a(a='foo)bar') baz"))
|
880
|
+
assert_equal("<a a='foo'>baz</a>\n", render("%a( a = 'foo' ) baz"))
|
881
|
+
end
|
882
|
+
|
883
|
+
def test_new_attribute_escaping
|
884
|
+
assert_equal(%Q{<a a='foo " bar'>bar</a>\n}, render(%q{%a(a="foo \" bar") bar}))
|
885
|
+
assert_equal(%Q{<a a='foo \\" bar'>bar</a>\n}, render(%q{%a(a="foo \\\\\" bar") bar}))
|
886
|
+
|
887
|
+
assert_equal(%Q{<a a="foo ' bar">bar</a>\n}, render(%q{%a(a='foo \' bar') bar}))
|
888
|
+
assert_equal(%Q{<a a="foo \\' bar">bar</a>\n}, render(%q{%a(a='foo \\\\\' bar') bar}))
|
889
|
+
|
890
|
+
assert_equal(%Q{<a a='foo \\ bar'>bar</a>\n}, render(%q{%a(a="foo \\\\ bar") bar}))
|
891
|
+
assert_equal(%Q{<a a='foo \#{1 + 1} bar'>bar</a>\n}, render(%q{%a(a="foo \#{1 + 1} bar") bar}))
|
892
|
+
end
|
893
|
+
|
894
|
+
def test_multiline_new_attribute
|
895
|
+
assert_equal("<a a='b' c='d'>bar</a>\n", render("%a(a='b'\n c='d') bar"))
|
896
|
+
assert_equal("<a a='b' b='c' c='d' d='e' e='f' f='j'>bar</a>\n",
|
897
|
+
render("%a(a='b' b='c'\n c='d' d=e\n e='f' f='j') bar", :locals => {:e => 'e'}))
|
898
|
+
end
|
899
|
+
|
900
|
+
def test_new_and_old_attributes
|
901
|
+
assert_equal("<a a='b' c='d'>bar</a>\n", render("%a(a='b'){:c => 'd'} bar"))
|
902
|
+
assert_equal("<a a='b' c='d'>bar</a>\n", render("%a{:c => 'd'}(a='b') bar"))
|
903
|
+
assert_equal("<a a='b' c='d'>bar</a>\n", render("%a(c='d'){:a => 'b'} bar"))
|
904
|
+
assert_equal("<a a='b' c='d'>bar</a>\n", render("%a{:a => 'b'}(c='d') bar"))
|
905
|
+
|
906
|
+
assert_equal("<a a='d'>bar</a>\n", render("%a{:a => 'b'}(a='d') bar"))
|
907
|
+
assert_equal("<a a='b'>bar</a>\n", render("%a(a='d'){:a => 'b'} bar"))
|
908
|
+
|
909
|
+
assert_equal("<a a='b' b='c' c='d' d='e'>bar</a>\n",
|
910
|
+
render("%a{:a => 'b',\n:b => 'c'}(c='d'\nd='e') bar"))
|
911
|
+
end
|
912
|
+
|
808
913
|
# Encodings
|
809
914
|
|
810
915
|
unless Haml::Util.ruby1_8?
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haml-edge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.45
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Weizenbaum
|
@@ -12,8 +12,27 @@ cert_chain: []
|
|
12
12
|
|
13
13
|
date: 2009-07-04 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
|
-
dependencies:
|
16
|
-
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: yard
|
18
|
+
type: :development
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.2.3
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: maruku
|
28
|
+
type: :development
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.5.9
|
35
|
+
version:
|
17
36
|
description: Haml (HTML Abstraction Markup Language) is a layer on top of XHTML or XML that's designed to express the structure of XHTML or XML documents in a non-repetitive, elegant, easy way, using indentation rather than closing tags and allowing Ruby to be embedded with ease. It was originally envisioned as a plugin for Ruby on Rails, but it can function as a stand-alone templating engine.
|
18
37
|
email: haml@googlegroups.com
|
19
38
|
executables:
|