Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F102857573
compiler.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Feb 24, 22:19
Size
19 KB
Mime Type
text/html
Expires
Wed, Feb 26, 22:19 (1 d, 20 h)
Engine
blob
Format
Raw Data
Handle
24443864
Attached To
R8244 Eawag_Swing_Weight_Elicitation
compiler.js
View Options
'use strict'
;
var
nodes
=
require
(
'./nodes'
);
var
filters
=
require
(
'./filters'
);
var
doctypes
=
require
(
'./doctypes'
);
var
runtime
=
require
(
'./runtime'
);
var
utils
=
require
(
'./utils'
);
var
selfClosing
=
require
(
'void-elements'
);
var
parseJSExpression
=
require
(
'character-parser'
).
parseMax
;
var
constantinople
=
require
(
'constantinople'
);
function
isConstant
(
src
)
{
return
constantinople
(
src
,
{
jade
:
runtime
,
'jade_interp'
:
undefined
});
}
function
toConstant
(
src
)
{
return
constantinople
.
toConstant
(
src
,
{
jade
:
runtime
,
'jade_interp'
:
undefined
});
}
function
errorAtNode
(
node
,
error
)
{
error
.
line
=
node
.
line
;
error
.
filename
=
node
.
filename
;
return
error
;
}
/**
* Initialize `Compiler` with the given `node`.
*
* @param {Node} node
* @param {Object} options
* @api public
*/
var
Compiler
=
module
.
exports
=
function
Compiler
(
node
,
options
)
{
this
.
options
=
options
=
options
||
{};
this
.
node
=
node
;
this
.
hasCompiledDoctype
=
false
;
this
.
hasCompiledTag
=
false
;
this
.
pp
=
options
.
pretty
||
false
;
if
(
this
.
pp
&&
typeof
this
.
pp
!==
'string'
)
{
this
.
pp
=
' '
;
}
this
.
debug
=
false
!==
options
.
compileDebug
;
this
.
indents
=
0
;
this
.
parentIndents
=
0
;
this
.
terse
=
false
;
this
.
mixins
=
{};
this
.
dynamicMixins
=
false
;
if
(
options
.
doctype
)
this
.
setDoctype
(
options
.
doctype
);
};
/**
* Compiler prototype.
*/
Compiler
.
prototype
=
{
/**
* Compile parse tree to JavaScript.
*
* @api public
*/
compile
:
function
(){
this
.
buf
=
[];
if
(
this
.
pp
)
this
.
buf
.
push
(
"var jade_indent = [];"
);
this
.
lastBufferedIdx
=
-
1
;
this
.
visit
(
this
.
node
);
if
(
!
this
.
dynamicMixins
)
{
// if there are no dynamic mixins we can remove any un-used mixins
var
mixinNames
=
Object
.
keys
(
this
.
mixins
);
for
(
var
i
=
0
;
i
<
mixinNames
.
length
;
i
++
)
{
var
mixin
=
this
.
mixins
[
mixinNames
[
i
]];
if
(
!
mixin
.
used
)
{
for
(
var
x
=
0
;
x
<
mixin
.
instances
.
length
;
x
++
)
{
for
(
var
y
=
mixin
.
instances
[
x
].
start
;
y
<
mixin
.
instances
[
x
].
end
;
y
++
)
{
this
.
buf
[
y
]
=
''
;
}
}
}
}
}
return
this
.
buf
.
join
(
'\n'
);
},
/**
* Sets the default doctype `name`. Sets terse mode to `true` when
* html 5 is used, causing self-closing tags to end with ">" vs "/>",
* and boolean attributes are not mirrored.
*
* @param {string} name
* @api public
*/
setDoctype
:
function
(
name
){
this
.
doctype
=
doctypes
[
name
.
toLowerCase
()]
||
'<!DOCTYPE '
+
name
+
'>'
;
this
.
terse
=
this
.
doctype
.
toLowerCase
()
==
'<!doctype html>'
;
this
.
xml
=
0
==
this
.
doctype
.
indexOf
(
'<?xml'
);
},
/**
* Buffer the given `str` exactly as is or with interpolation
*
* @param {String} str
* @param {Boolean} interpolate
* @api public
*/
buffer
:
function
(
str
,
interpolate
)
{
var
self
=
this
;
if
(
interpolate
)
{
var
match
=
/(\\)?([#!]){((?:.|\n)*)$/
.
exec
(
str
);
if
(
match
)
{
this
.
buffer
(
str
.
substr
(
0
,
match
.
index
),
false
);
if
(
match
[
1
])
{
// escape
this
.
buffer
(
match
[
2
]
+
'{'
,
false
);
this
.
buffer
(
match
[
3
],
true
);
return
;
}
else
{
var
rest
=
match
[
3
];
var
range
=
parseJSExpression
(
rest
);
var
code
=
(
'!'
==
match
[
2
]
?
''
:
'jade.escape'
)
+
"((jade_interp = "
+
range
.
src
+
") == null ? '' : jade_interp)"
;
this
.
bufferExpression
(
code
);
this
.
buffer
(
rest
.
substr
(
range
.
end
+
1
),
true
);
return
;
}
}
}
str
=
utils
.
stringify
(
str
);
str
=
str
.
substr
(
1
,
str
.
length
-
2
);
if
(
this
.
lastBufferedIdx
==
this
.
buf
.
length
)
{
if
(
this
.
lastBufferedType
===
'code'
)
this
.
lastBuffered
+=
' + "'
;
this
.
lastBufferedType
=
'text'
;
this
.
lastBuffered
+=
str
;
this
.
buf
[
this
.
lastBufferedIdx
-
1
]
=
'buf.push('
+
this
.
bufferStartChar
+
this
.
lastBuffered
+
'");'
}
else
{
this
.
buf
.
push
(
'buf.push("'
+
str
+
'");'
);
this
.
lastBufferedType
=
'text'
;
this
.
bufferStartChar
=
'"'
;
this
.
lastBuffered
=
str
;
this
.
lastBufferedIdx
=
this
.
buf
.
length
;
}
},
/**
* Buffer the given `src` so it is evaluated at run time
*
* @param {String} src
* @api public
*/
bufferExpression
:
function
(
src
)
{
if
(
isConstant
(
src
))
{
return
this
.
buffer
(
toConstant
(
src
)
+
''
,
false
)
}
if
(
this
.
lastBufferedIdx
==
this
.
buf
.
length
)
{
if
(
this
.
lastBufferedType
===
'text'
)
this
.
lastBuffered
+=
'"'
;
this
.
lastBufferedType
=
'code'
;
this
.
lastBuffered
+=
' + ('
+
src
+
')'
;
this
.
buf
[
this
.
lastBufferedIdx
-
1
]
=
'buf.push('
+
this
.
bufferStartChar
+
this
.
lastBuffered
+
');'
}
else
{
this
.
buf
.
push
(
'buf.push('
+
src
+
');'
);
this
.
lastBufferedType
=
'code'
;
this
.
bufferStartChar
=
''
;
this
.
lastBuffered
=
'('
+
src
+
')'
;
this
.
lastBufferedIdx
=
this
.
buf
.
length
;
}
},
/**
* Buffer an indent based on the current `indent`
* property and an additional `offset`.
*
* @param {Number} offset
* @param {Boolean} newline
* @api public
*/
prettyIndent
:
function
(
offset
,
newline
){
offset
=
offset
||
0
;
newline
=
newline
?
'\n'
:
''
;
this
.
buffer
(
newline
+
Array
(
this
.
indents
+
offset
).
join
(
this
.
pp
));
if
(
this
.
parentIndents
)
this
.
buf
.
push
(
"buf.push.apply(buf, jade_indent);"
);
},
/**
* Visit `node`.
*
* @param {Node} node
* @api public
*/
visit
:
function
(
node
){
var
debug
=
this
.
debug
;
if
(
debug
)
{
this
.
buf
.
push
(
'jade_debug.unshift({ lineno: '
+
node
.
line
+
', filename: '
+
(
node
.
filename
?
utils
.
stringify
(
node
.
filename
)
:
'jade_debug[0].filename'
)
+
' });'
);
}
// Massive hack to fix our context
// stack for - else[ if] etc
if
(
false
===
node
.
debug
&&
this
.
debug
)
{
this
.
buf
.
pop
();
this
.
buf
.
pop
();
}
this
.
visitNode
(
node
);
if
(
debug
)
this
.
buf
.
push
(
'jade_debug.shift();'
);
},
/**
* Visit `node`.
*
* @param {Node} node
* @api public
*/
visitNode
:
function
(
node
){
return
this
[
'visit'
+
node
.
type
](
node
);
},
/**
* Visit case `node`.
*
* @param {Literal} node
* @api public
*/
visitCase
:
function
(
node
){
var
_
=
this
.
withinCase
;
this
.
withinCase
=
true
;
this
.
buf
.
push
(
'switch ('
+
node
.
expr
+
'){'
);
this
.
visit
(
node
.
block
);
this
.
buf
.
push
(
'}'
);
this
.
withinCase
=
_
;
},
/**
* Visit when `node`.
*
* @param {Literal} node
* @api public
*/
visitWhen
:
function
(
node
){
if
(
'default'
==
node
.
expr
)
{
this
.
buf
.
push
(
'default:'
);
}
else
{
this
.
buf
.
push
(
'case '
+
node
.
expr
+
':'
);
}
if
(
node
.
block
)
{
this
.
visit
(
node
.
block
);
this
.
buf
.
push
(
' break;'
);
}
},
/**
* Visit literal `node`.
*
* @param {Literal} node
* @api public
*/
visitLiteral
:
function
(
node
){
this
.
buffer
(
node
.
str
);
},
/**
* Visit all nodes in `block`.
*
* @param {Block} block
* @api public
*/
visitBlock
:
function
(
block
){
var
len
=
block
.
nodes
.
length
,
escape
=
this
.
escape
,
pp
=
this
.
pp
// Pretty print multi-line text
if
(
pp
&&
len
>
1
&&
!
escape
&&
block
.
nodes
[
0
].
isText
&&
block
.
nodes
[
1
].
isText
)
this
.
prettyIndent
(
1
,
true
);
for
(
var
i
=
0
;
i
<
len
;
++
i
)
{
// Pretty print text
if
(
pp
&&
i
>
0
&&
!
escape
&&
block
.
nodes
[
i
].
isText
&&
block
.
nodes
[
i
-
1
].
isText
)
this
.
prettyIndent
(
1
,
false
);
this
.
visit
(
block
.
nodes
[
i
]);
// Multiple text nodes are separated by newlines
if
(
block
.
nodes
[
i
+
1
]
&&
block
.
nodes
[
i
].
isText
&&
block
.
nodes
[
i
+
1
].
isText
)
this
.
buffer
(
'\n'
);
}
},
/**
* Visit a mixin's `block` keyword.
*
* @param {MixinBlock} block
* @api public
*/
visitMixinBlock
:
function
(
block
){
if
(
this
.
pp
)
this
.
buf
.
push
(
"jade_indent.push('"
+
Array
(
this
.
indents
+
1
).
join
(
this
.
pp
)
+
"');"
);
this
.
buf
.
push
(
'block && block();'
);
if
(
this
.
pp
)
this
.
buf
.
push
(
"jade_indent.pop();"
);
},
/**
* Visit `doctype`. Sets terse mode to `true` when html 5
* is used, causing self-closing tags to end with ">" vs "/>",
* and boolean attributes are not mirrored.
*
* @param {Doctype} doctype
* @api public
*/
visitDoctype
:
function
(
doctype
){
if
(
doctype
&&
(
doctype
.
val
||
!
this
.
doctype
))
{
this
.
setDoctype
(
doctype
.
val
||
'default'
);
}
if
(
this
.
doctype
)
this
.
buffer
(
this
.
doctype
);
this
.
hasCompiledDoctype
=
true
;
},
/**
* Visit `mixin`, generating a function that
* may be called within the template.
*
* @param {Mixin} mixin
* @api public
*/
visitMixin
:
function
(
mixin
){
var
name
=
'jade_mixins['
;
var
args
=
mixin
.
args
||
''
;
var
block
=
mixin
.
block
;
var
attrs
=
mixin
.
attrs
;
var
attrsBlocks
=
mixin
.
attributeBlocks
.
slice
();
var
pp
=
this
.
pp
;
var
dynamic
=
mixin
.
name
[
0
]
===
'#'
;
var
key
=
mixin
.
name
;
if
(
dynamic
)
this
.
dynamicMixins
=
true
;
name
+=
(
dynamic
?
mixin
.
name
.
substr
(
2
,
mixin
.
name
.
length
-
3
)
:
'"'
+
mixin
.
name
+
'"'
)
+
']'
;
this
.
mixins
[
key
]
=
this
.
mixins
[
key
]
||
{
used
:
false
,
instances
:
[]};
if
(
mixin
.
call
)
{
this
.
mixins
[
key
].
used
=
true
;
if
(
pp
)
this
.
buf
.
push
(
"jade_indent.push('"
+
Array
(
this
.
indents
+
1
).
join
(
pp
)
+
"');"
)
if
(
block
||
attrs
.
length
||
attrsBlocks
.
length
)
{
this
.
buf
.
push
(
name
+
'.call({'
);
if
(
block
)
{
this
.
buf
.
push
(
'block: function(){'
);
// Render block with no indents, dynamically added when rendered
this
.
parentIndents
++
;
var
_indents
=
this
.
indents
;
this
.
indents
=
0
;
this
.
visit
(
mixin
.
block
);
this
.
indents
=
_indents
;
this
.
parentIndents
--
;
if
(
attrs
.
length
||
attrsBlocks
.
length
)
{
this
.
buf
.
push
(
'},'
);
}
else
{
this
.
buf
.
push
(
'}'
);
}
}
if
(
attrsBlocks
.
length
)
{
if
(
attrs
.
length
)
{
var
val
=
this
.
attrs
(
attrs
);
attrsBlocks
.
unshift
(
val
);
}
this
.
buf
.
push
(
'attributes: jade.merge(['
+
attrsBlocks
.
join
(
','
)
+
'])'
);
}
else
if
(
attrs
.
length
)
{
var
val
=
this
.
attrs
(
attrs
);
this
.
buf
.
push
(
'attributes: '
+
val
);
}
if
(
args
)
{
this
.
buf
.
push
(
'}, '
+
args
+
');'
);
}
else
{
this
.
buf
.
push
(
'});'
);
}
}
else
{
this
.
buf
.
push
(
name
+
'('
+
args
+
');'
);
}
if
(
pp
)
this
.
buf
.
push
(
"jade_indent.pop();"
)
}
else
{
var
mixin_start
=
this
.
buf
.
length
;
args
=
args
?
args
.
split
(
','
)
:
[];
var
rest
;
if
(
args
.
length
&&
/^\.\.\./
.
test
(
args
[
args
.
length
-
1
].
trim
()))
{
rest
=
args
.
pop
().
trim
().
replace
(
/^\.\.\./
,
''
);
}
this
.
buf
.
push
(
name
+
' = function('
+
args
.
join
(
','
)
+
'){'
);
this
.
buf
.
push
(
'var block = (this && this.block), attributes = (this && this.attributes) || {};'
);
if
(
rest
)
{
this
.
buf
.
push
(
'var '
+
rest
+
' = [];'
);
this
.
buf
.
push
(
'for (jade_interp = '
+
args
.
length
+
'; jade_interp < arguments.length; jade_interp++) {'
);
this
.
buf
.
push
(
' '
+
rest
+
'.push(arguments[jade_interp]);'
);
this
.
buf
.
push
(
'}'
);
}
this
.
parentIndents
++
;
this
.
visit
(
block
);
this
.
parentIndents
--
;
this
.
buf
.
push
(
'};'
);
var
mixin_end
=
this
.
buf
.
length
;
this
.
mixins
[
key
].
instances
.
push
({
start
:
mixin_start
,
end
:
mixin_end
});
}
},
/**
* Visit `tag` buffering tag markup, generating
* attributes, visiting the `tag`'s code and block.
*
* @param {Tag} tag
* @api public
*/
visitTag
:
function
(
tag
){
this
.
indents
++
;
var
name
=
tag
.
name
,
pp
=
this
.
pp
,
self
=
this
;
function
bufferName
()
{
if
(
tag
.
buffer
)
self
.
bufferExpression
(
name
);
else
self
.
buffer
(
name
);
}
if
(
'pre'
==
tag
.
name
)
this
.
escape
=
true
;
if
(
!
this
.
hasCompiledTag
)
{
if
(
!
this
.
hasCompiledDoctype
&&
'html'
==
name
)
{
this
.
visitDoctype
();
}
this
.
hasCompiledTag
=
true
;
}
// pretty print
if
(
pp
&&
!
tag
.
isInline
())
this
.
prettyIndent
(
0
,
true
);
if
(
tag
.
selfClosing
||
(
!
this
.
xml
&&
selfClosing
[
tag
.
name
]))
{
this
.
buffer
(
'<'
);
bufferName
();
this
.
visitAttributes
(
tag
.
attrs
,
tag
.
attributeBlocks
.
slice
());
this
.
terse
?
this
.
buffer
(
'>'
)
:
this
.
buffer
(
'/>'
);
// if it is non-empty throw an error
if
(
tag
.
block
&&
!
(
tag
.
block
.
type
===
'Block'
&&
tag
.
block
.
nodes
.
length
===
0
)
&&
tag
.
block
.
nodes
.
some
(
function
(
tag
)
{
return
tag
.
type
!==
'Text'
||
!
/^\s*$/
.
test
(
tag
.
val
)
}))
{
throw
errorAtNode
(
tag
,
new
Error
(
name
+
' is self closing and should not have content.'
));
}
}
else
{
// Optimize attributes buffering
this
.
buffer
(
'<'
);
bufferName
();
this
.
visitAttributes
(
tag
.
attrs
,
tag
.
attributeBlocks
.
slice
());
this
.
buffer
(
'>'
);
if
(
tag
.
code
)
this
.
visitCode
(
tag
.
code
);
this
.
visit
(
tag
.
block
);
// pretty print
if
(
pp
&&
!
tag
.
isInline
()
&&
'pre'
!=
tag
.
name
&&
!
tag
.
canInline
())
this
.
prettyIndent
(
0
,
true
);
this
.
buffer
(
'</'
);
bufferName
();
this
.
buffer
(
'>'
);
}
if
(
'pre'
==
tag
.
name
)
this
.
escape
=
false
;
this
.
indents
--
;
},
/**
* Visit `filter`, throwing when the filter does not exist.
*
* @param {Filter} filter
* @api public
*/
visitFilter
:
function
(
filter
){
var
text
=
filter
.
block
.
nodes
.
map
(
function
(
node
){
return
node
.
val
;
}
).
join
(
'\n'
);
filter
.
attrs
.
filename
=
this
.
options
.
filename
;
try
{
this
.
buffer
(
filters
(
filter
.
name
,
text
,
filter
.
attrs
),
true
);
}
catch
(
err
)
{
throw
errorAtNode
(
filter
,
err
);
}
},
/**
* Visit `text` node.
*
* @param {Text} text
* @api public
*/
visitText
:
function
(
text
){
this
.
buffer
(
text
.
val
,
true
);
},
/**
* Visit a `comment`, only buffering when the buffer flag is set.
*
* @param {Comment} comment
* @api public
*/
visitComment
:
function
(
comment
){
if
(
!
comment
.
buffer
)
return
;
if
(
this
.
pp
)
this
.
prettyIndent
(
1
,
true
);
this
.
buffer
(
'<!--'
+
comment
.
val
+
'-->'
);
},
/**
* Visit a `BlockComment`.
*
* @param {Comment} comment
* @api public
*/
visitBlockComment
:
function
(
comment
){
if
(
!
comment
.
buffer
)
return
;
if
(
this
.
pp
)
this
.
prettyIndent
(
1
,
true
);
this
.
buffer
(
'<!--'
+
comment
.
val
);
this
.
visit
(
comment
.
block
);
if
(
this
.
pp
)
this
.
prettyIndent
(
1
,
true
);
this
.
buffer
(
'-->'
);
},
/**
* Visit `code`, respecting buffer / escape flags.
* If the code is followed by a block, wrap it in
* a self-calling function.
*
* @param {Code} code
* @api public
*/
visitCode
:
function
(
code
){
// Wrap code blocks with {}.
// we only wrap unbuffered code blocks ATM
// since they are usually flow control
// Buffer code
if
(
code
.
buffer
)
{
var
val
=
code
.
val
.
trim
();
val
=
'null == (jade_interp = '
+
val
+
') ? "" : jade_interp'
;
if
(
code
.
escape
)
val
=
'jade.escape('
+
val
+
')'
;
this
.
bufferExpression
(
val
);
}
else
{
this
.
buf
.
push
(
code
.
val
);
}
// Block support
if
(
code
.
block
)
{
if
(
!
code
.
buffer
)
this
.
buf
.
push
(
'{'
);
this
.
visit
(
code
.
block
);
if
(
!
code
.
buffer
)
this
.
buf
.
push
(
'}'
);
}
},
/**
* Visit `each` block.
*
* @param {Each} each
* @api public
*/
visitEach
:
function
(
each
){
this
.
buf
.
push
(
''
+
'// iterate '
+
each
.
obj
+
'\n'
+
';(function(){\n'
+
' var $$obj = '
+
each
.
obj
+
';\n'
+
' if (\'number\' == typeof $$obj.length) {\n'
);
if
(
each
.
alternative
)
{
this
.
buf
.
push
(
' if ($$obj.length) {'
);
}
this
.
buf
.
push
(
''
+
' for (var '
+
each
.
key
+
' = 0, $$l = $$obj.length; '
+
each
.
key
+
' < $$l; '
+
each
.
key
+
'++) {\n'
+
' var '
+
each
.
val
+
' = $$obj['
+
each
.
key
+
'];\n'
);
this
.
visit
(
each
.
block
);
this
.
buf
.
push
(
' }\n'
);
if
(
each
.
alternative
)
{
this
.
buf
.
push
(
' } else {'
);
this
.
visit
(
each
.
alternative
);
this
.
buf
.
push
(
' }'
);
}
this
.
buf
.
push
(
''
+
' } else {\n'
+
' var $$l = 0;\n'
+
' for (var '
+
each
.
key
+
' in $$obj) {\n'
+
' $$l++;'
+
' var '
+
each
.
val
+
' = $$obj['
+
each
.
key
+
'];\n'
);
this
.
visit
(
each
.
block
);
this
.
buf
.
push
(
' }\n'
);
if
(
each
.
alternative
)
{
this
.
buf
.
push
(
' if ($$l === 0) {'
);
this
.
visit
(
each
.
alternative
);
this
.
buf
.
push
(
' }'
);
}
this
.
buf
.
push
(
' }\n}).call(this);\n'
);
},
/**
* Visit `attrs`.
*
* @param {Array} attrs
* @api public
*/
visitAttributes
:
function
(
attrs
,
attributeBlocks
){
if
(
attributeBlocks
.
length
)
{
if
(
attrs
.
length
)
{
var
val
=
this
.
attrs
(
attrs
);
attributeBlocks
.
unshift
(
val
);
}
this
.
bufferExpression
(
'jade.attrs(jade.merge(['
+
attributeBlocks
.
join
(
','
)
+
']), '
+
utils
.
stringify
(
this
.
terse
)
+
')'
);
}
else
if
(
attrs
.
length
)
{
this
.
attrs
(
attrs
,
true
);
}
},
/**
* Compile attributes.
*/
attrs
:
function
(
attrs
,
buffer
){
var
buf
=
[];
var
classes
=
[];
var
classEscaping
=
[];
attrs
.
forEach
(
function
(
attr
){
var
key
=
attr
.
name
;
var
escaped
=
attr
.
escaped
;
if
(
key
===
'class'
)
{
classes
.
push
(
attr
.
val
);
classEscaping
.
push
(
attr
.
escaped
);
}
else
if
(
isConstant
(
attr
.
val
))
{
if
(
buffer
)
{
this
.
buffer
(
runtime
.
attr
(
key
,
toConstant
(
attr
.
val
),
escaped
,
this
.
terse
));
}
else
{
var
val
=
toConstant
(
attr
.
val
);
if
(
key
===
'style'
)
val
=
runtime
.
style
(
val
);
if
(
escaped
&&
!
(
key
.
indexOf
(
'data'
)
===
0
&&
typeof
val
!==
'string'
))
{
val
=
runtime
.
escape
(
val
);
}
buf
.
push
(
utils
.
stringify
(
key
)
+
': '
+
utils
.
stringify
(
val
));
}
}
else
{
if
(
buffer
)
{
this
.
bufferExpression
(
'jade.attr("'
+
key
+
'", '
+
attr
.
val
+
', '
+
utils
.
stringify
(
escaped
)
+
', '
+
utils
.
stringify
(
this
.
terse
)
+
')'
);
}
else
{
var
val
=
attr
.
val
;
if
(
key
===
'style'
)
{
val
=
'jade.style('
+
val
+
')'
;
}
if
(
escaped
&&
!
(
key
.
indexOf
(
'data'
)
===
0
))
{
val
=
'jade.escape('
+
val
+
')'
;
}
else
if
(
escaped
)
{
val
=
'(typeof (jade_interp = '
+
val
+
') == "string" ? jade.escape(jade_interp) : jade_interp)'
;
}
buf
.
push
(
utils
.
stringify
(
key
)
+
': '
+
val
);
}
}
}.
bind
(
this
));
if
(
buffer
)
{
if
(
classes
.
every
(
isConstant
))
{
this
.
buffer
(
runtime
.
cls
(
classes
.
map
(
toConstant
),
classEscaping
));
}
else
{
this
.
bufferExpression
(
'jade.cls(['
+
classes
.
join
(
','
)
+
'], '
+
utils
.
stringify
(
classEscaping
)
+
')'
);
}
}
else
if
(
classes
.
length
)
{
if
(
classes
.
every
(
isConstant
))
{
classes
=
utils
.
stringify
(
runtime
.
joinClasses
(
classes
.
map
(
toConstant
).
map
(
runtime
.
joinClasses
).
map
(
function
(
cls
,
i
)
{
return
classEscaping
[
i
]
?
runtime
.
escape
(
cls
)
:
cls
;
})));
}
else
{
classes
=
'(jade_interp = '
+
utils
.
stringify
(
classEscaping
)
+
','
+
' jade.joinClasses(['
+
classes
.
join
(
','
)
+
'].map(jade.joinClasses).map(function (cls, i) {'
+
' return jade_interp[i] ? jade.escape(cls) : cls'
+
' }))'
+
')'
;
}
if
(
classes
.
length
)
buf
.
push
(
'"class": '
+
classes
);
}
return
'{'
+
buf
.
join
(
','
)
+
'}'
;
}
};
Event Timeline
Log In to Comment