riot-compiler
Advanced tools
Comparing version 2.3.19 to 2.3.20
# Compiler Changes | ||
### v2.3.20 | ||
- Fix [riot#1495](https://github.com/riot/riot/issues/1495) : Warning of input tag value - Avoids warnings for date/datetime/time/month/email/color types with expression in its value. | ||
- Fix [riot#1488](https://github.com/riot/riot/issues/1488) : Cannot read property 'replace' of undefined when compiling in Node a tag with an import in its less stylesheet -- Thanks to @jrx-jsj | ||
- Fix [riot#1448](https://github.com/riot/riot/issues/1448) : Riot compiler parses and removes content from string declaration. This is partial fix, you need to write `<\/script>` for closing script tags within quoted strings. | ||
- Revised regex that matches `<pre>` tags. | ||
- `@import` directives of `stylus`, `sass`, `scss`, and `less` can be relative to the file being processed. | ||
- Fixed lint issues with new .eslintrc.yml, almost compatible with [JavaScript Standard Style](http://standardjs.com/) | ||
### v2.3.19 | ||
@@ -4,0 +12,0 @@ - Fixing issues with double quotes. |
@@ -1,3 +0,3 @@ | ||
/* riot-compiler v2.3.19, @license MIT, (c) 2015 Muut Inc. + contributors */ | ||
'use strict' // eslint-disable-line | ||
/* riot-compiler v2.3.20, @license MIT, (c) 2015 Muut Inc. + contributors */ | ||
'use strict' | ||
@@ -15,2 +15,4 @@ /** | ||
var path = require('path') | ||
var _modnames = { | ||
@@ -27,10 +29,10 @@ es6: 'babel', | ||
function _modname(name) { | ||
function _modname (name) { | ||
return _modnames[name] || name | ||
} | ||
function _try(name, req) { //eslint-disable-line complexity | ||
function _try (name, req) { //eslint-disable-line complexity | ||
var parser | ||
function fn(r) { | ||
function fn (r) { | ||
try { | ||
@@ -54,6 +56,18 @@ _mods[name] = require(r) | ||
function _req(name, req) { | ||
function _req (name, req) { | ||
return name in _mods ? _mods[name] : _try(name, req) | ||
} | ||
function extend (obj, props) { | ||
if (props) { | ||
for (var prop in props) { | ||
/* istanbul ignore next */ | ||
if (props.hasOwnProperty(prop)) { | ||
obj[prop] = props[prop] | ||
} | ||
} | ||
} | ||
return obj | ||
} | ||
var _html = { | ||
@@ -70,3 +84,3 @@ jade: function (html, opts, url) { | ||
var _css = { | ||
sass: function(tag, css, opts, url) { | ||
sass: function (tag, css, opts, url) { | ||
var sass = _req('sass') | ||
@@ -76,2 +90,3 @@ | ||
data: css, | ||
includePaths: [path.dirname(url)], | ||
indentedSyntax: true, | ||
@@ -82,3 +97,3 @@ omitSourceMapUrl: true, | ||
}, | ||
scss: function(tag, css, opts, url) { | ||
scss: function (tag, css, opts, url) { | ||
var scss = _req('scss') | ||
@@ -88,2 +103,3 @@ | ||
data: css, | ||
includePaths: [path.dirname(url)], | ||
indentedSyntax: false, | ||
@@ -94,3 +110,3 @@ omitSourceMapUrl: true, | ||
}, | ||
less: function(tag, css, opts, url) { | ||
less: function (tag, css, opts, url) { | ||
var less = _req('less'), | ||
@@ -101,2 +117,4 @@ ret | ||
sync: true, | ||
syncImport: true, | ||
filename: url, | ||
compress: true | ||
@@ -112,6 +130,9 @@ }, opts), function (err, result) { | ||
var | ||
stylus = _req('stylus'), nib = _req('nib') | ||
xopts = extend({filename: url}, opts), | ||
stylus = _req('stylus'), | ||
nib = _req('nib') | ||
/* istanbul ignore next: can't run both */ | ||
return nib ? | ||
stylus(css).use(nib()).import('nib').render() : stylus.render(css) | ||
stylus(css, xopts).use(nib()).import('nib').render() : stylus.render(css, xopts) | ||
} | ||
@@ -121,9 +142,9 @@ } | ||
var _js = { | ||
livescript: function (js, opts, url) { | ||
livescript: function (js, opts) { | ||
return _req('livescript').compile(js, extend({bare: true, header: false}, opts)) | ||
}, | ||
typescript: function (js, opts, url) { | ||
typescript: function (js, opts) { | ||
return _req('typescript')(js, opts).replace(/\r\n?/g, '\n') | ||
}, | ||
es6: function (js, opts, url) { | ||
es6: function (js, opts) { | ||
return _req('es6').transform(js, extend({ | ||
@@ -134,10 +155,5 @@ blacklist: ['useStrict', 'strict', 'react'], sourceMaps: false, comments: false | ||
babel: function (js, opts, url) { | ||
// istanbul ignore next: url empty if comming from expression | ||
return _req('babel').transform(js, | ||
extend({ | ||
filename: url || '' | ||
}, opts) | ||
).code | ||
return _req('babel').transform(js, extend({filename: url}, opts)).code | ||
}, | ||
coffee: function (js, opts, url) { | ||
coffee: function (js, opts) { | ||
return _req('coffee').compile(js, extend({bare: true}, opts)) | ||
@@ -198,3 +214,3 @@ }, | ||
function _rewrite(re, bp) { | ||
function _rewrite (re, bp) { | ||
return RegExp( | ||
@@ -211,3 +227,3 @@ re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : '' | ||
_brackets.split = function split(str, tmpl, _bp) { | ||
_brackets.split = function split (str, tmpl, _bp) { | ||
@@ -253,10 +269,10 @@ var | ||
function unescapeStr(str) { | ||
function unescapeStr (s) { | ||
if (isexpr) | ||
parts.push(str && str.replace(_bp[5], '$1')) | ||
parts.push(s && s.replace(_bp[5], '$1')) | ||
else | ||
parts.push(str) | ||
parts.push(s) | ||
} | ||
function skipBraces(ch, pos) { | ||
function skipBraces (ch, pos) { | ||
var | ||
@@ -278,3 +294,3 @@ match, | ||
_brackets.array = function array(pair) { | ||
_brackets.array = function array (pair) { | ||
@@ -308,3 +324,3 @@ if (!pair || pair === DEFAULT) return _pairs | ||
function _regEx(str, opt) { return new RegExp(str, opt) } | ||
function _regEx (str, opt) { return new RegExp(str, opt) } | ||
@@ -324,8 +340,9 @@ var | ||
HTML_ATTR = /\s*([-\w:\xA0-\xFF]+)\s*(?:=\s*('[^']+'|"[^"]+"|\S+))?/g, | ||
SPEC_TYPES = /^"(?:number|date(?:time)?|time|month|email|color)\b/i, | ||
TRIM_TRAIL = /[ \t]+$/gm, | ||
S_STRINGS = brackets.R_STRINGS.source | ||
TRIM_TRAIL = /[ \t]+$/gm | ||
var path = require('path') | ||
function q(s) { | ||
function q (s) { | ||
return "'" + (s ? s | ||
@@ -336,3 +353,3 @@ .replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '\\r') : | ||
function mktag(name, html, css, attrs, js, pcex) { | ||
function mktag (name, html, css, attrs, js, pcex) { | ||
var | ||
@@ -348,18 +365,7 @@ c = ', ', | ||
function extend(obj, props) { | ||
for (var prop in props) { | ||
/* istanbul ignore next */ | ||
if (props.hasOwnProperty(prop)) { | ||
obj[prop] = props[prop] | ||
} | ||
} | ||
return obj | ||
} | ||
function parseAttrs(str, pcex) { | ||
function parseAttrs (str, pcex) { | ||
var | ||
list = [], | ||
match, | ||
k, v, | ||
_bp = pcex._bp, | ||
k, v, t, e, | ||
DQ = '"' | ||
@@ -384,22 +390,26 @@ | ||
if (k === 'type' && v.toLowerCase() === '"number"') { | ||
v = DQ + _bp[0] + "'number'" + _bp[1] + DQ | ||
if (k === 'type' && SPEC_TYPES.test(v)) { | ||
t = v | ||
} | ||
else if (/\u0001\d/.test(v)) { | ||
else { | ||
if (/\u0001\d/.test(v)) { | ||
if (BOOL_ATTRS.test(k)) { | ||
k = '__' + k | ||
if (k === 'value') e = 1 | ||
else if (BOOL_ATTRS.test(k)) k = '__' + k | ||
else if (~RIOT_ATTRS.indexOf(k)) k = 'riot-' + k | ||
} | ||
else if (~RIOT_ATTRS.indexOf(k)) { | ||
k = 'riot-' + k | ||
} | ||
list.push(k + '=' + v) | ||
} | ||
list.push(k + '=' + v) | ||
} | ||
} | ||
if (t) { | ||
if (e) t = DQ + pcex._bp[0] + "'" + t.slice(1, -1) + "'" + pcex._bp[1] + DQ | ||
list.push('type=' + t) | ||
} | ||
return list.join(' ') | ||
} | ||
function splitHtml(html, opts, pcex) { | ||
function splitHtml (html, opts, pcex) { | ||
var _bp = pcex._bp | ||
@@ -409,3 +419,3 @@ | ||
var | ||
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0, | ||
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0, //eslint-disable-line | ||
list = brackets.split(html, 0, _bp), | ||
@@ -431,3 +441,3 @@ expr | ||
function restoreExpr(html, pcex) { | ||
function restoreExpr (html, pcex) { | ||
if (pcex.length) { | ||
@@ -451,9 +461,8 @@ html = html | ||
var | ||
HTML_COMMENT = /<!--(?!>)[\S\s]*?-->/g, | ||
HTML_COMMENT = _regEx(/<!--(?!>)[\S\s]*?-->/.source + '|' + S_STRINGS, 'g'), | ||
HTML_TAGS = /<([-\w]+)\s*([^"'\/>]*(?:(?:"[^"]*"|'[^']*'|\/[^>])[^'"\/>]*)*)(\/?)>/g, | ||
PRE_TAG = _regEx( | ||
/<pre(?:\s+[^'">]+(?:(?:@Q)[^'">]*)*|\s*)?>([\S\s]*?)<\/pre\s*>/ | ||
.source.replace('@Q', brackets.R_STRINGS.source), 'gi') | ||
/<pre(?:\s+[^'">]+(?:(?:@Q)|[^>]*)*|\s*)?>([\S\s]*?)<\/pre\s*>/.source.replace('@Q', S_STRINGS), 'gi') | ||
function _compileHTML(html, opts, pcex) { | ||
function _compileHTML (html, opts, pcex) { | ||
@@ -475,7 +484,8 @@ html = splitHtml(html, opts, pcex) | ||
var p = [] | ||
html = html.replace(PRE_TAG, function (q) | ||
{ return p.push(q) && '\u0002' }).trim().replace(/\s+/g, ' ') | ||
html = html.replace(PRE_TAG, function (_q) { | ||
return p.push(_q) && '\u0002' | ||
}).trim().replace(/\s+/g, ' ') | ||
// istanbul ignore else | ||
if (p.length) | ||
html = html.replace(/\u0002/g, function (_) { return p.shift() }) | ||
html = html.replace(/\u0002/g, function () { return p.shift() }) | ||
} | ||
@@ -492,3 +502,3 @@ else | ||
// istanbul ignore next | ||
function compileHTML(html, opts, pcex) { | ||
function compileHTML (html, opts, pcex) { | ||
if (Array.isArray(opts)) { | ||
@@ -503,4 +513,4 @@ pcex = opts | ||
if (!pcex.__intflag) | ||
html = html.replace(/\r\n?/g, '\n').replace(HTML_COMMENT, '').replace(TRIM_TRAIL, '') | ||
html = html.replace(/\r\n?/g, '\n').replace(HTML_COMMENT, | ||
function (s) { return s[0] === '<' ? '' : s }).replace(TRIM_TRAIL, '') | ||
@@ -516,3 +526,3 @@ if (!pcex._bp) pcex._bp = brackets.array(opts.brackets) | ||
function riotjs(js) { | ||
function riotjs (js) { | ||
var | ||
@@ -524,3 +534,3 @@ match, | ||
js = js.replace(JS_RMCOMMS, function (m, q) { return q ? m : ' ' }) | ||
js = js.replace(JS_RMCOMMS, function (m, _q) { return _q ? m : ' ' }) | ||
@@ -544,11 +554,11 @@ while (match = js.match(JS_ES6SIGN)) { | ||
function skipBlock(str) { | ||
function skipBlock (str) { | ||
var | ||
re = _regEx('([{}])|' + brackets.S_QBLOCKS, 'g'), | ||
level = 1, | ||
match | ||
mm | ||
while (level && (match = re.exec(str))) { | ||
if (match[1]) | ||
match[1] === '{' ? ++level : --level | ||
while (level && (mm = re.exec(str))) { | ||
if (mm[1]) | ||
mm[1] === '{' ? ++level : --level | ||
} | ||
@@ -559,3 +569,3 @@ return level ? str.length : re.lastIndex | ||
function _compileJS(js, opts, type, parserOpts, url) { | ||
function _compileJS (js, opts, type, parserOpts, url) { | ||
if (!js) return '' | ||
@@ -572,3 +582,3 @@ if (!type) type = opts.type | ||
// istanbul ignore next | ||
function compileJS(js, opts, type, extra) { | ||
function compileJS (js, opts, type, extra) { | ||
if (typeof opts === 'string') { | ||
@@ -588,5 +598,5 @@ extra = type | ||
var CSS_SELECTOR = _regEx('(}|{|^)[ ;]*([^@ ;{}][^{}]*)(?={)|' + brackets.R_STRINGS.source, 'g') | ||
var CSS_SELECTOR = _regEx('(}|{|^)[ ;]*([^@ ;{}][^{}]*)(?={)|' + S_STRINGS, 'g') | ||
function scopedCSS(tag, style) { | ||
function scopedCSS (tag, style) { | ||
var scope = ':scope' | ||
@@ -614,3 +624,3 @@ | ||
function _compileCSS(style, tag, type, opts) { | ||
function _compileCSS (style, tag, type, opts) { | ||
var scoped = (opts || (opts = {})).scoped | ||
@@ -623,3 +633,3 @@ | ||
else if (parsers.css[type]) { | ||
style = parsers.css[type](tag, style, opts.parserOpts, opts.url) | ||
style = parsers.css[type](tag, style, opts.parserOpts || {}, opts.url) | ||
} | ||
@@ -643,3 +653,3 @@ else if (type !== 'css') { | ||
// istanbul ignore next | ||
function compileCSS(style, parser, opts) { | ||
function compileCSS (style, parser, opts) { | ||
if (typeof parser === 'object') { | ||
@@ -649,3 +659,2 @@ opts = parser | ||
} | ||
else if (!opts) opts = {} | ||
return _compileCSS(style, opts.tagName, parser, opts) | ||
@@ -658,3 +667,3 @@ } | ||
function getType(str) { | ||
function getType (str) { | ||
@@ -668,3 +677,3 @@ if (str) { | ||
function getAttr(str, name) { | ||
function getAttr (str, name) { | ||
@@ -682,3 +691,3 @@ if (str) { | ||
function getParserOptions(attrs) { | ||
function getParserOptions (attrs) { | ||
var opts = getAttr(attrs, 'options') | ||
@@ -690,3 +699,3 @@ | ||
function getCode(code, opts, attrs, url) { | ||
function getCode (code, opts, attrs, url) { | ||
var type = getType(attrs), | ||
@@ -708,5 +717,14 @@ parserOpts = getParserOptions(attrs) | ||
function cssCode (code, opts, attrs, url, tag) { | ||
var extraOpts = { | ||
parserOpts: getParserOptions(attrs), | ||
scoped: attrs && /\sscoped(\s|=|$)/i.test(attrs), | ||
url: url | ||
} | ||
return _compileCSS(code, tag, getType(attrs) || opts.style, extraOpts) | ||
} | ||
var END_TAGS = /\/>\n|^<(?:\/[\w\-]+\s*|[\w\-]+(?:\s+(?:[-\w:\xA0-\xFF][\S\s]*?)?)?)>\n/ | ||
function splitBlocks(str) { | ||
function splitBlocks (str) { | ||
var k, m | ||
@@ -723,3 +741,3 @@ | ||
} | ||
k = str.lastIndexOf('<', k -1) | ||
k = str.lastIndexOf('<', k - 1) | ||
} | ||
@@ -729,3 +747,3 @@ return ['', str] | ||
function compileTemplate(html, url, lang, opts) { | ||
function compileTemplate (html, url, lang, opts) { | ||
var parser = parsers.html[lang] | ||
@@ -742,7 +760,8 @@ | ||
/^([ \t]*)<([-\w]+)(?:\s+([^'"\/>]+(?:(?:@Q|\/[^>])[^'"\/>]*)*)|\s*)?(?:\/>|>[ \t]*\n?([\S\s]*)^\1<\/\2\s*>|>(.*)<\/\2\s*>)/ | ||
.source.replace('@Q', brackets.R_STRINGS.source), 'gim'), | ||
STYLE = /<style(\s+[^>]*)?>\n?([^<]*(?:<(?!\/style\s*>)[^<]*)*)<\/style\s*>/gi, | ||
SCRIPT = _regEx(STYLE.source.replace(/tyle/g, 'cript'), 'gi') | ||
.source.replace('@Q', S_STRINGS), 'gim'), | ||
SRC_TAGS = /<style(\s+[^>]*)?>\n?([^<]*(?:<(?!\/style\s*>)[^<]*)*)<\/style\s*>/.source + '|' + S_STRINGS, | ||
STYLES = _regEx(SRC_TAGS, 'gi'), | ||
SCRIPT = _regEx(SRC_TAGS.replace(/style/g, 'script'), 'gi') | ||
function compile(src, opts, url) { | ||
function compile (src, opts, url) { | ||
var | ||
@@ -754,6 +773,6 @@ parts = [], | ||
url = url || process.cwd() + '/.' | ||
if (!url) url = process.cwd() + '/.' | ||
exclude = opts.exclude || false | ||
function included(s) { return !(exclude && ~exclude.indexOf(s)) } | ||
function included (s) { return !(exclude && ~exclude.indexOf(s)) } | ||
@@ -776,3 +795,2 @@ var _bp = brackets.array(opts.brackets) | ||
pcex._bp = _bp | ||
pcex.__intflag = 1 | ||
@@ -786,3 +804,4 @@ tagName = tagName.toLowerCase() | ||
if (body && (body = body.replace(HTML_COMMENT, '')) && /\S/.test(body)) { | ||
if (body && (body = body.replace(HTML_COMMENT, | ||
function (s) { return s[0] === '<' ? '' : s })) && /\S/.test(body)) { | ||
@@ -796,17 +815,15 @@ if (body2) { | ||
body = body.replace(STYLE, included('css') ? function (_, _attrs, _style) { | ||
var extraOpts = { | ||
scoped: _attrs && /\sscoped(\s|=|$)/i.test(_attrs), | ||
url: url, | ||
parserOpts: getParserOptions(_attrs) | ||
} | ||
styles += (styles ? ' ' : '') + | ||
_compileCSS(_style, tagName, getType(_attrs) || opts.style, extraOpts) | ||
body = body.replace(STYLES, function (_m, _attrs, _style) { | ||
if (_m[0] !== '<') return _m | ||
if (included('css')) | ||
styles += (styles ? ' ' : '') + cssCode(_style, opts, _attrs, url, tagName) | ||
return '' | ||
} : '') | ||
}) | ||
body = body.replace(SCRIPT, included('js') ? function (_, _attrs, _script) { | ||
jscode += (jscode ? '\n' : '') + getCode(_script, opts, _attrs, url) | ||
body = body.replace(SCRIPT, function (_m, _attrs, _script) { | ||
if (_m[0] !== '<') return _m | ||
if (included('js')) | ||
jscode += (jscode ? '\n' : '') + getCode(_script, opts, _attrs, url) | ||
return '' | ||
} : '') | ||
}) | ||
@@ -862,3 +879,3 @@ var blocks = splitBlocks(body.replace(TRIM_TRAIL, '')) | ||
parsers: parsers, | ||
version: 'v2.3.19' | ||
version: 'v2.3.20' | ||
} |
/** | ||
* Compiler for riot custom tags | ||
* @version v2.3.19 | ||
* @version v2.3.20 | ||
*/ | ||
@@ -19,19 +19,21 @@ | ||
function _try(name, req) { //eslint-disable-line complexity | ||
function _try (name, req) { //eslint-disable-line complexity | ||
var parser | ||
/*global window */ | ||
switch (name) { | ||
case 'coffee': | ||
req = 'CoffeeScript' | ||
break | ||
case 'es6': | ||
case 'babel': | ||
req = 'babel' | ||
break | ||
case 'none': | ||
case 'javascript': | ||
return _mods.none | ||
default: | ||
if (!req) req = name | ||
break | ||
case 'coffee': | ||
req = 'CoffeeScript' | ||
break | ||
case 'es6': | ||
case 'babel': | ||
req = 'babel' | ||
break | ||
case 'none': | ||
case 'javascript': | ||
return _mods.none | ||
default: | ||
if (!req) req = name | ||
break | ||
} | ||
@@ -47,6 +49,18 @@ parser = window[req] | ||
function _req(name, req) { | ||
function _req (name, req) { | ||
return name in _mods ? _mods[name] : _try(name, req) | ||
} | ||
function extend (obj, props) { | ||
if (props) { | ||
for (var prop in props) { | ||
/* istanbul ignore next */ | ||
if (props.hasOwnProperty(prop)) { | ||
obj[prop] = props[prop] | ||
} | ||
} | ||
} | ||
return obj | ||
} | ||
var _html = { | ||
@@ -63,3 +77,3 @@ jade: function (html, opts, url) { | ||
var _css = { | ||
less: function(tag, css, opts, url) { | ||
less: function (tag, css, opts, url) { | ||
var less = _req('less'), | ||
@@ -70,2 +84,4 @@ ret | ||
sync: true, | ||
syncImport: true, | ||
filename: url, | ||
compress: true | ||
@@ -81,6 +97,9 @@ }, opts), function (err, result) { | ||
var | ||
stylus = _req('stylus'), nib = _req('nib') | ||
xopts = extend({filename: url}, opts), | ||
stylus = _req('stylus'), | ||
nib = _req('nib') | ||
/* istanbul ignore next: can't run both */ | ||
return nib ? | ||
stylus(css).use(nib()).import('nib').render() : stylus.render(css) | ||
stylus(css, xopts).use(nib()).import('nib').render() : stylus.render(css, xopts) | ||
} | ||
@@ -90,9 +109,9 @@ } | ||
var _js = { | ||
livescript: function (js, opts, url) { | ||
livescript: function (js, opts) { | ||
return _req('livescript').compile(js, extend({bare: true, header: false}, opts)) | ||
}, | ||
typescript: function (js, opts, url) { | ||
typescript: function (js, opts) { | ||
return _req('typescript')(js, opts).replace(/\r\n?/g, '\n') | ||
}, | ||
es6: function (js, opts, url) { | ||
es6: function (js, opts) { | ||
return _req('es6').transform(js, extend({ | ||
@@ -103,10 +122,5 @@ blacklist: ['useStrict', 'strict', 'react'], sourceMaps: false, comments: false | ||
babel: function (js, opts, url) { | ||
// istanbul ignore next: url empty if comming from expression | ||
return _req('babel').transform(js, | ||
extend({ | ||
filename: url || '' | ||
}, opts) | ||
).code | ||
return _req('babel').transform(js, extend({filename: url}, opts)).code | ||
}, | ||
coffee: function (js, opts, url) { | ||
coffee: function (js, opts) { | ||
return _req('coffee').compile(js, extend({bare: true}, opts)) | ||
@@ -132,3 +146,3 @@ }, | ||
function _regEx(str, opt) { return new RegExp(str, opt) } | ||
function _regEx (str, opt) { return new RegExp(str, opt) } | ||
@@ -148,6 +162,7 @@ var | ||
HTML_ATTR = /\s*([-\w:\xA0-\xFF]+)\s*(?:=\s*('[^']+'|"[^"]+"|\S+))?/g, | ||
SPEC_TYPES = /^"(?:number|date(?:time)?|time|month|email|color)\b/i, | ||
TRIM_TRAIL = /[ \t]+$/gm, | ||
S_STRINGS = brackets.R_STRINGS.source | ||
TRIM_TRAIL = /[ \t]+$/gm | ||
function q(s) { | ||
function q (s) { | ||
return "'" + (s ? s | ||
@@ -158,3 +173,3 @@ .replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '\\r') : | ||
function mktag(name, html, css, attrs, js, pcex) { | ||
function mktag (name, html, css, attrs, js, pcex) { | ||
var | ||
@@ -170,18 +185,7 @@ c = ', ', | ||
function extend(obj, props) { | ||
for (var prop in props) { | ||
/* istanbul ignore next */ | ||
if (props.hasOwnProperty(prop)) { | ||
obj[prop] = props[prop] | ||
} | ||
} | ||
return obj | ||
} | ||
function parseAttrs(str, pcex) { | ||
function parseAttrs (str, pcex) { | ||
var | ||
list = [], | ||
match, | ||
k, v, | ||
_bp = pcex._bp, | ||
k, v, t, e, | ||
DQ = '"' | ||
@@ -206,22 +210,26 @@ | ||
if (k === 'type' && v.toLowerCase() === '"number"') { | ||
v = DQ + _bp[0] + "'number'" + _bp[1] + DQ | ||
if (k === 'type' && SPEC_TYPES.test(v)) { | ||
t = v | ||
} | ||
else if (/\u0001\d/.test(v)) { | ||
else { | ||
if (/\u0001\d/.test(v)) { | ||
if (BOOL_ATTRS.test(k)) { | ||
k = '__' + k | ||
if (k === 'value') e = 1 | ||
else if (BOOL_ATTRS.test(k)) k = '__' + k | ||
else if (~RIOT_ATTRS.indexOf(k)) k = 'riot-' + k | ||
} | ||
else if (~RIOT_ATTRS.indexOf(k)) { | ||
k = 'riot-' + k | ||
} | ||
list.push(k + '=' + v) | ||
} | ||
list.push(k + '=' + v) | ||
} | ||
} | ||
if (t) { | ||
if (e) t = DQ + pcex._bp[0] + "'" + t.slice(1, -1) + "'" + pcex._bp[1] + DQ | ||
list.push('type=' + t) | ||
} | ||
return list.join(' ') | ||
} | ||
function splitHtml(html, opts, pcex) { | ||
function splitHtml (html, opts, pcex) { | ||
var _bp = pcex._bp | ||
@@ -231,3 +239,3 @@ | ||
var | ||
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0, | ||
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0, //eslint-disable-line | ||
list = brackets.split(html, 0, _bp), | ||
@@ -253,3 +261,3 @@ expr | ||
function restoreExpr(html, pcex) { | ||
function restoreExpr (html, pcex) { | ||
if (pcex.length) { | ||
@@ -273,9 +281,8 @@ html = html | ||
var | ||
HTML_COMMENT = /<!--(?!>)[\S\s]*?-->/g, | ||
HTML_COMMENT = _regEx(/<!--(?!>)[\S\s]*?-->/.source + '|' + S_STRINGS, 'g'), | ||
HTML_TAGS = /<([-\w]+)\s*([^"'\/>]*(?:(?:"[^"]*"|'[^']*'|\/[^>])[^'"\/>]*)*)(\/?)>/g, | ||
PRE_TAG = _regEx( | ||
/<pre(?:\s+[^'">]+(?:(?:@Q)[^'">]*)*|\s*)?>([\S\s]*?)<\/pre\s*>/ | ||
.source.replace('@Q', brackets.R_STRINGS.source), 'gi') | ||
/<pre(?:\s+[^'">]+(?:(?:@Q)|[^>]*)*|\s*)?>([\S\s]*?)<\/pre\s*>/.source.replace('@Q', S_STRINGS), 'gi') | ||
function _compileHTML(html, opts, pcex) { | ||
function _compileHTML (html, opts, pcex) { | ||
@@ -297,7 +304,8 @@ html = splitHtml(html, opts, pcex) | ||
var p = [] | ||
html = html.replace(PRE_TAG, function (q) | ||
{ return p.push(q) && '\u0002' }).trim().replace(/\s+/g, ' ') | ||
html = html.replace(PRE_TAG, function (_q) { | ||
return p.push(_q) && '\u0002' | ||
}).trim().replace(/\s+/g, ' ') | ||
// istanbul ignore else | ||
if (p.length) | ||
html = html.replace(/\u0002/g, function (_) { return p.shift() }) | ||
html = html.replace(/\u0002/g, function () { return p.shift() }) | ||
} | ||
@@ -314,3 +322,3 @@ else | ||
// istanbul ignore next | ||
function compileHTML(html, opts, pcex) { | ||
function compileHTML (html, opts, pcex) { | ||
if (Array.isArray(opts)) { | ||
@@ -325,4 +333,4 @@ pcex = opts | ||
if (!pcex.__intflag) | ||
html = html.replace(/\r\n?/g, '\n').replace(HTML_COMMENT, '').replace(TRIM_TRAIL, '') | ||
html = html.replace(/\r\n?/g, '\n').replace(HTML_COMMENT, | ||
function (s) { return s[0] === '<' ? '' : s }).replace(TRIM_TRAIL, '') | ||
@@ -338,3 +346,3 @@ if (!pcex._bp) pcex._bp = brackets.array(opts.brackets) | ||
function riotjs(js) { | ||
function riotjs (js) { | ||
var | ||
@@ -346,3 +354,3 @@ match, | ||
js = js.replace(JS_RMCOMMS, function (m, q) { return q ? m : ' ' }) | ||
js = js.replace(JS_RMCOMMS, function (m, _q) { return _q ? m : ' ' }) | ||
@@ -366,11 +374,11 @@ while (match = js.match(JS_ES6SIGN)) { | ||
function skipBlock(str) { | ||
function skipBlock (str) { | ||
var | ||
re = _regEx('([{}])|' + brackets.S_QBLOCKS, 'g'), | ||
level = 1, | ||
match | ||
mm | ||
while (level && (match = re.exec(str))) { | ||
if (match[1]) | ||
match[1] === '{' ? ++level : --level | ||
while (level && (mm = re.exec(str))) { | ||
if (mm[1]) | ||
mm[1] === '{' ? ++level : --level | ||
} | ||
@@ -381,3 +389,3 @@ return level ? str.length : re.lastIndex | ||
function _compileJS(js, opts, type, parserOpts, url) { | ||
function _compileJS (js, opts, type, parserOpts, url) { | ||
if (!js) return '' | ||
@@ -394,3 +402,3 @@ if (!type) type = opts.type | ||
// istanbul ignore next | ||
function compileJS(js, opts, type, extra) { | ||
function compileJS (js, opts, type, extra) { | ||
if (typeof opts === 'string') { | ||
@@ -410,5 +418,5 @@ extra = type | ||
var CSS_SELECTOR = _regEx('(}|{|^)[ ;]*([^@ ;{}][^{}]*)(?={)|' + brackets.R_STRINGS.source, 'g') | ||
var CSS_SELECTOR = _regEx('(}|{|^)[ ;]*([^@ ;{}][^{}]*)(?={)|' + S_STRINGS, 'g') | ||
function scopedCSS(tag, style) { | ||
function scopedCSS (tag, style) { | ||
var scope = ':scope' | ||
@@ -436,3 +444,3 @@ | ||
function _compileCSS(style, tag, type, opts) { | ||
function _compileCSS (style, tag, type, opts) { | ||
var scoped = (opts || (opts = {})).scoped | ||
@@ -445,3 +453,3 @@ | ||
else if (parsers.css[type]) { | ||
style = parsers.css[type](tag, style, opts.parserOpts, opts.url) | ||
style = parsers.css[type](tag, style, opts.parserOpts || {}, opts.url) | ||
} | ||
@@ -465,3 +473,3 @@ else if (type !== 'css') { | ||
// istanbul ignore next | ||
function compileCSS(style, parser, opts) { | ||
function compileCSS (style, parser, opts) { | ||
if (typeof parser === 'object') { | ||
@@ -471,3 +479,2 @@ opts = parser | ||
} | ||
else if (!opts) opts = {} | ||
return _compileCSS(style, opts.tagName, parser, opts) | ||
@@ -480,3 +487,3 @@ } | ||
function getType(str) { | ||
function getType (str) { | ||
@@ -490,3 +497,3 @@ if (str) { | ||
function getAttr(str, name) { | ||
function getAttr (str, name) { | ||
@@ -504,3 +511,3 @@ if (str) { | ||
function getParserOptions(attrs) { | ||
function getParserOptions (attrs) { | ||
var opts = getAttr(attrs, 'options') | ||
@@ -512,3 +519,3 @@ | ||
function getCode(code, opts, attrs, url) { | ||
function getCode (code, opts, attrs, url) { | ||
var type = getType(attrs), | ||
@@ -520,5 +527,14 @@ parserOpts = getParserOptions(attrs) | ||
function cssCode (code, opts, attrs, url, tag) { | ||
var extraOpts = { | ||
parserOpts: getParserOptions(attrs), | ||
scoped: attrs && /\sscoped(\s|=|$)/i.test(attrs), | ||
url: url | ||
} | ||
return _compileCSS(code, tag, getType(attrs) || opts.style, extraOpts) | ||
} | ||
var END_TAGS = /\/>\n|^<(?:\/[\w\-]+\s*|[\w\-]+(?:\s+(?:[-\w:\xA0-\xFF][\S\s]*?)?)?)>\n/ | ||
function splitBlocks(str) { | ||
function splitBlocks (str) { | ||
var k, m | ||
@@ -535,3 +551,3 @@ | ||
} | ||
k = str.lastIndexOf('<', k -1) | ||
k = str.lastIndexOf('<', k - 1) | ||
} | ||
@@ -541,3 +557,3 @@ return ['', str] | ||
function compileTemplate(html, url, lang, opts) { | ||
function compileTemplate (html, url, lang, opts) { | ||
var parser = parsers.html[lang] | ||
@@ -554,7 +570,8 @@ | ||
/^([ \t]*)<([-\w]+)(?:\s+([^'"\/>]+(?:(?:@Q|\/[^>])[^'"\/>]*)*)|\s*)?(?:\/>|>[ \t]*\n?([\S\s]*)^\1<\/\2\s*>|>(.*)<\/\2\s*>)/ | ||
.source.replace('@Q', brackets.R_STRINGS.source), 'gim'), | ||
STYLE = /<style(\s+[^>]*)?>\n?([^<]*(?:<(?!\/style\s*>)[^<]*)*)<\/style\s*>/gi, | ||
SCRIPT = _regEx(STYLE.source.replace(/tyle/g, 'cript'), 'gi') | ||
.source.replace('@Q', S_STRINGS), 'gim'), | ||
SRC_TAGS = /<style(\s+[^>]*)?>\n?([^<]*(?:<(?!\/style\s*>)[^<]*)*)<\/style\s*>/.source + '|' + S_STRINGS, | ||
STYLES = _regEx(SRC_TAGS, 'gi'), | ||
SCRIPT = _regEx(SRC_TAGS.replace(/style/g, 'script'), 'gi') | ||
function compile(src, opts, url) { | ||
function compile (src, opts, url) { | ||
var | ||
@@ -566,4 +583,6 @@ parts = [], | ||
if (!url) url = '' | ||
exclude = opts.exclude || false | ||
function included(s) { return !(exclude && ~exclude.indexOf(s)) } | ||
function included (s) { return !(exclude && ~exclude.indexOf(s)) } | ||
@@ -586,3 +605,2 @@ var _bp = brackets.array(opts.brackets) | ||
pcex._bp = _bp | ||
pcex.__intflag = 1 | ||
@@ -596,3 +614,4 @@ tagName = tagName.toLowerCase() | ||
if (body && (body = body.replace(HTML_COMMENT, '')) && /\S/.test(body)) { | ||
if (body && (body = body.replace(HTML_COMMENT, | ||
function (s) { return s[0] === '<' ? '' : s })) && /\S/.test(body)) { | ||
@@ -606,17 +625,15 @@ if (body2) { | ||
body = body.replace(STYLE, included('css') ? function (_, _attrs, _style) { | ||
var extraOpts = { | ||
scoped: _attrs && /\sscoped(\s|=|$)/i.test(_attrs), | ||
url: url, | ||
parserOpts: getParserOptions(_attrs) | ||
} | ||
styles += (styles ? ' ' : '') + | ||
_compileCSS(_style, tagName, getType(_attrs) || opts.style, extraOpts) | ||
body = body.replace(STYLES, function (_m, _attrs, _style) { | ||
if (_m[0] !== '<') return _m | ||
if (included('css')) | ||
styles += (styles ? ' ' : '') + cssCode(_style, opts, _attrs, url, tagName) | ||
return '' | ||
} : '') | ||
}) | ||
body = body.replace(SCRIPT, included('js') ? function (_, _attrs, _script) { | ||
jscode += (jscode ? '\n' : '') + getCode(_script, opts, _attrs, url) | ||
body = body.replace(SCRIPT, function (_m, _attrs, _script) { | ||
if (_m[0] !== '<') return _m | ||
if (included('js')) | ||
jscode += (jscode ? '\n' : '') + getCode(_script, opts, _attrs, url) | ||
return '' | ||
} : '') | ||
}) | ||
@@ -660,3 +677,3 @@ var blocks = splitBlocks(body.replace(TRIM_TRAIL, '')) | ||
var version = 'v2.3.19' | ||
var version = 'v2.3.20' | ||
@@ -663,0 +680,0 @@ export default { |
@@ -13,19 +13,21 @@ | ||
function _try(name, req) { //eslint-disable-line complexity | ||
function _try (name, req) { //eslint-disable-line complexity | ||
var parser | ||
/*global window */ | ||
switch (name) { | ||
case 'coffee': | ||
req = 'CoffeeScript' | ||
break | ||
case 'es6': | ||
case 'babel': | ||
req = 'babel' | ||
break | ||
case 'none': | ||
case 'javascript': | ||
return _mods.none | ||
default: | ||
if (!req) req = name | ||
break | ||
case 'coffee': | ||
req = 'CoffeeScript' | ||
break | ||
case 'es6': | ||
case 'babel': | ||
req = 'babel' | ||
break | ||
case 'none': | ||
case 'javascript': | ||
return _mods.none | ||
default: | ||
if (!req) req = name | ||
break | ||
} | ||
@@ -41,6 +43,18 @@ parser = window[req] | ||
function _req(name, req) { | ||
function _req (name, req) { | ||
return name in _mods ? _mods[name] : _try(name, req) | ||
} | ||
function extend (obj, props) { | ||
if (props) { | ||
for (var prop in props) { | ||
/* istanbul ignore next */ | ||
if (props.hasOwnProperty(prop)) { | ||
obj[prop] = props[prop] | ||
} | ||
} | ||
} | ||
return obj | ||
} | ||
var _html = { | ||
@@ -57,3 +71,3 @@ jade: function (html, opts, url) { | ||
var _css = { | ||
less: function(tag, css, opts, url) { | ||
less: function (tag, css, opts, url) { | ||
var less = _req('less'), | ||
@@ -64,2 +78,4 @@ ret | ||
sync: true, | ||
syncImport: true, | ||
filename: url, | ||
compress: true | ||
@@ -75,6 +91,9 @@ }, opts), function (err, result) { | ||
var | ||
stylus = _req('stylus'), nib = _req('nib') | ||
xopts = extend({filename: url}, opts), | ||
stylus = _req('stylus'), | ||
nib = _req('nib') | ||
/* istanbul ignore next: can't run both */ | ||
return nib ? | ||
stylus(css).use(nib()).import('nib').render() : stylus.render(css) | ||
stylus(css, xopts).use(nib()).import('nib').render() : stylus.render(css, xopts) | ||
} | ||
@@ -84,9 +103,9 @@ } | ||
var _js = { | ||
livescript: function (js, opts, url) { | ||
livescript: function (js, opts) { | ||
return _req('livescript').compile(js, extend({bare: true, header: false}, opts)) | ||
}, | ||
typescript: function (js, opts, url) { | ||
typescript: function (js, opts) { | ||
return _req('typescript')(js, opts).replace(/\r\n?/g, '\n') | ||
}, | ||
es6: function (js, opts, url) { | ||
es6: function (js, opts) { | ||
return _req('es6').transform(js, extend({ | ||
@@ -97,10 +116,5 @@ blacklist: ['useStrict', 'strict', 'react'], sourceMaps: false, comments: false | ||
babel: function (js, opts, url) { | ||
// istanbul ignore next: url empty if comming from expression | ||
return _req('babel').transform(js, | ||
extend({ | ||
filename: url || '' | ||
}, opts) | ||
).code | ||
return _req('babel').transform(js, extend({filename: url}, opts)).code | ||
}, | ||
coffee: function (js, opts, url) { | ||
coffee: function (js, opts) { | ||
return _req('coffee').compile(js, extend({bare: true}, opts)) | ||
@@ -126,7 +140,7 @@ }, | ||
* Compiler for riot custom tags | ||
* @version v2.3.19 | ||
* @version v2.3.20 | ||
*/ | ||
var compile = (function () { | ||
function _regEx(str, opt) { return new RegExp(str, opt) } | ||
function _regEx (str, opt) { return new RegExp(str, opt) } | ||
@@ -146,6 +160,7 @@ var | ||
HTML_ATTR = /\s*([-\w:\xA0-\xFF]+)\s*(?:=\s*('[^']+'|"[^"]+"|\S+))?/g, | ||
SPEC_TYPES = /^"(?:number|date(?:time)?|time|month|email|color)\b/i, | ||
TRIM_TRAIL = /[ \t]+$/gm, | ||
S_STRINGS = brackets.R_STRINGS.source | ||
TRIM_TRAIL = /[ \t]+$/gm | ||
function q(s) { | ||
function q (s) { | ||
return "'" + (s ? s | ||
@@ -156,3 +171,3 @@ .replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '\\r') : | ||
function mktag(name, html, css, attrs, js, pcex) { | ||
function mktag (name, html, css, attrs, js, pcex) { | ||
var | ||
@@ -168,18 +183,7 @@ c = ', ', | ||
function extend(obj, props) { | ||
for (var prop in props) { | ||
/* istanbul ignore next */ | ||
if (props.hasOwnProperty(prop)) { | ||
obj[prop] = props[prop] | ||
} | ||
} | ||
return obj | ||
} | ||
function parseAttrs(str, pcex) { | ||
function parseAttrs (str, pcex) { | ||
var | ||
list = [], | ||
match, | ||
k, v, | ||
_bp = pcex._bp, | ||
k, v, t, e, | ||
DQ = '"' | ||
@@ -204,22 +208,26 @@ | ||
if (k === 'type' && v.toLowerCase() === '"number"') { | ||
v = DQ + _bp[0] + "'number'" + _bp[1] + DQ | ||
if (k === 'type' && SPEC_TYPES.test(v)) { | ||
t = v | ||
} | ||
else if (/\u0001\d/.test(v)) { | ||
else { | ||
if (/\u0001\d/.test(v)) { | ||
if (BOOL_ATTRS.test(k)) { | ||
k = '__' + k | ||
if (k === 'value') e = 1 | ||
else if (BOOL_ATTRS.test(k)) k = '__' + k | ||
else if (~RIOT_ATTRS.indexOf(k)) k = 'riot-' + k | ||
} | ||
else if (~RIOT_ATTRS.indexOf(k)) { | ||
k = 'riot-' + k | ||
} | ||
list.push(k + '=' + v) | ||
} | ||
list.push(k + '=' + v) | ||
} | ||
} | ||
if (t) { | ||
if (e) t = DQ + pcex._bp[0] + "'" + t.slice(1, -1) + "'" + pcex._bp[1] + DQ | ||
list.push('type=' + t) | ||
} | ||
return list.join(' ') | ||
} | ||
function splitHtml(html, opts, pcex) { | ||
function splitHtml (html, opts, pcex) { | ||
var _bp = pcex._bp | ||
@@ -229,3 +237,3 @@ | ||
var | ||
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0, | ||
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0, //eslint-disable-line | ||
list = brackets.split(html, 0, _bp), | ||
@@ -251,3 +259,3 @@ expr | ||
function restoreExpr(html, pcex) { | ||
function restoreExpr (html, pcex) { | ||
if (pcex.length) { | ||
@@ -271,9 +279,8 @@ html = html | ||
var | ||
HTML_COMMENT = /<!--(?!>)[\S\s]*?-->/g, | ||
HTML_COMMENT = _regEx(/<!--(?!>)[\S\s]*?-->/.source + '|' + S_STRINGS, 'g'), | ||
HTML_TAGS = /<([-\w]+)\s*([^"'\/>]*(?:(?:"[^"]*"|'[^']*'|\/[^>])[^'"\/>]*)*)(\/?)>/g, | ||
PRE_TAG = _regEx( | ||
/<pre(?:\s+[^'">]+(?:(?:@Q)[^'">]*)*|\s*)?>([\S\s]*?)<\/pre\s*>/ | ||
.source.replace('@Q', brackets.R_STRINGS.source), 'gi') | ||
/<pre(?:\s+[^'">]+(?:(?:@Q)|[^>]*)*|\s*)?>([\S\s]*?)<\/pre\s*>/.source.replace('@Q', S_STRINGS), 'gi') | ||
function _compileHTML(html, opts, pcex) { | ||
function _compileHTML (html, opts, pcex) { | ||
@@ -295,7 +302,8 @@ html = splitHtml(html, opts, pcex) | ||
var p = [] | ||
html = html.replace(PRE_TAG, function (q) | ||
{ return p.push(q) && '\u0002' }).trim().replace(/\s+/g, ' ') | ||
html = html.replace(PRE_TAG, function (_q) { | ||
return p.push(_q) && '\u0002' | ||
}).trim().replace(/\s+/g, ' ') | ||
// istanbul ignore else | ||
if (p.length) | ||
html = html.replace(/\u0002/g, function (_) { return p.shift() }) | ||
html = html.replace(/\u0002/g, function () { return p.shift() }) | ||
} | ||
@@ -312,3 +320,3 @@ else | ||
// istanbul ignore next | ||
function compileHTML(html, opts, pcex) { | ||
function compileHTML (html, opts, pcex) { | ||
if (Array.isArray(opts)) { | ||
@@ -323,4 +331,4 @@ pcex = opts | ||
if (!pcex.__intflag) | ||
html = html.replace(/\r\n?/g, '\n').replace(HTML_COMMENT, '').replace(TRIM_TRAIL, '') | ||
html = html.replace(/\r\n?/g, '\n').replace(HTML_COMMENT, | ||
function (s) { return s[0] === '<' ? '' : s }).replace(TRIM_TRAIL, '') | ||
@@ -336,3 +344,3 @@ if (!pcex._bp) pcex._bp = brackets.array(opts.brackets) | ||
function riotjs(js) { | ||
function riotjs (js) { | ||
var | ||
@@ -344,3 +352,3 @@ match, | ||
js = js.replace(JS_RMCOMMS, function (m, q) { return q ? m : ' ' }) | ||
js = js.replace(JS_RMCOMMS, function (m, _q) { return _q ? m : ' ' }) | ||
@@ -364,11 +372,11 @@ while (match = js.match(JS_ES6SIGN)) { | ||
function skipBlock(str) { | ||
function skipBlock (str) { | ||
var | ||
re = _regEx('([{}])|' + brackets.S_QBLOCKS, 'g'), | ||
level = 1, | ||
match | ||
mm | ||
while (level && (match = re.exec(str))) { | ||
if (match[1]) | ||
match[1] === '{' ? ++level : --level | ||
while (level && (mm = re.exec(str))) { | ||
if (mm[1]) | ||
mm[1] === '{' ? ++level : --level | ||
} | ||
@@ -379,3 +387,3 @@ return level ? str.length : re.lastIndex | ||
function _compileJS(js, opts, type, parserOpts, url) { | ||
function _compileJS (js, opts, type, parserOpts, url) { | ||
if (!js) return '' | ||
@@ -392,3 +400,3 @@ if (!type) type = opts.type | ||
// istanbul ignore next | ||
function compileJS(js, opts, type, extra) { | ||
function compileJS (js, opts, type, extra) { | ||
if (typeof opts === 'string') { | ||
@@ -408,5 +416,5 @@ extra = type | ||
var CSS_SELECTOR = _regEx('(}|{|^)[ ;]*([^@ ;{}][^{}]*)(?={)|' + brackets.R_STRINGS.source, 'g') | ||
var CSS_SELECTOR = _regEx('(}|{|^)[ ;]*([^@ ;{}][^{}]*)(?={)|' + S_STRINGS, 'g') | ||
function scopedCSS(tag, style) { | ||
function scopedCSS (tag, style) { | ||
var scope = ':scope' | ||
@@ -434,3 +442,3 @@ | ||
function _compileCSS(style, tag, type, opts) { | ||
function _compileCSS (style, tag, type, opts) { | ||
var scoped = (opts || (opts = {})).scoped | ||
@@ -443,3 +451,3 @@ | ||
else if (parsers.css[type]) { | ||
style = parsers.css[type](tag, style, opts.parserOpts, opts.url) | ||
style = parsers.css[type](tag, style, opts.parserOpts || {}, opts.url) | ||
} | ||
@@ -463,3 +471,3 @@ else if (type !== 'css') { | ||
// istanbul ignore next | ||
function compileCSS(style, parser, opts) { | ||
function compileCSS (style, parser, opts) { | ||
if (typeof parser === 'object') { | ||
@@ -469,3 +477,2 @@ opts = parser | ||
} | ||
else if (!opts) opts = {} | ||
return _compileCSS(style, opts.tagName, parser, opts) | ||
@@ -478,3 +485,3 @@ } | ||
function getType(str) { | ||
function getType (str) { | ||
@@ -488,3 +495,3 @@ if (str) { | ||
function getAttr(str, name) { | ||
function getAttr (str, name) { | ||
@@ -502,3 +509,3 @@ if (str) { | ||
function getParserOptions(attrs) { | ||
function getParserOptions (attrs) { | ||
var opts = getAttr(attrs, 'options') | ||
@@ -510,3 +517,3 @@ | ||
function getCode(code, opts, attrs, url) { | ||
function getCode (code, opts, attrs, url) { | ||
var type = getType(attrs), | ||
@@ -518,5 +525,14 @@ parserOpts = getParserOptions(attrs) | ||
function cssCode (code, opts, attrs, url, tag) { | ||
var extraOpts = { | ||
parserOpts: getParserOptions(attrs), | ||
scoped: attrs && /\sscoped(\s|=|$)/i.test(attrs), | ||
url: url | ||
} | ||
return _compileCSS(code, tag, getType(attrs) || opts.style, extraOpts) | ||
} | ||
var END_TAGS = /\/>\n|^<(?:\/[\w\-]+\s*|[\w\-]+(?:\s+(?:[-\w:\xA0-\xFF][\S\s]*?)?)?)>\n/ | ||
function splitBlocks(str) { | ||
function splitBlocks (str) { | ||
var k, m | ||
@@ -533,3 +549,3 @@ | ||
} | ||
k = str.lastIndexOf('<', k -1) | ||
k = str.lastIndexOf('<', k - 1) | ||
} | ||
@@ -539,3 +555,3 @@ return ['', str] | ||
function compileTemplate(html, url, lang, opts) { | ||
function compileTemplate (html, url, lang, opts) { | ||
var parser = parsers.html[lang] | ||
@@ -552,7 +568,8 @@ | ||
/^([ \t]*)<([-\w]+)(?:\s+([^'"\/>]+(?:(?:@Q|\/[^>])[^'"\/>]*)*)|\s*)?(?:\/>|>[ \t]*\n?([\S\s]*)^\1<\/\2\s*>|>(.*)<\/\2\s*>)/ | ||
.source.replace('@Q', brackets.R_STRINGS.source), 'gim'), | ||
STYLE = /<style(\s+[^>]*)?>\n?([^<]*(?:<(?!\/style\s*>)[^<]*)*)<\/style\s*>/gi, | ||
SCRIPT = _regEx(STYLE.source.replace(/tyle/g, 'cript'), 'gi') | ||
.source.replace('@Q', S_STRINGS), 'gim'), | ||
SRC_TAGS = /<style(\s+[^>]*)?>\n?([^<]*(?:<(?!\/style\s*>)[^<]*)*)<\/style\s*>/.source + '|' + S_STRINGS, | ||
STYLES = _regEx(SRC_TAGS, 'gi'), | ||
SCRIPT = _regEx(SRC_TAGS.replace(/style/g, 'script'), 'gi') | ||
function compile(src, opts, url) { | ||
function compile (src, opts, url) { | ||
var | ||
@@ -564,4 +581,6 @@ parts = [], | ||
if (!url) url = '' | ||
exclude = opts.exclude || false | ||
function included(s) { return !(exclude && ~exclude.indexOf(s)) } | ||
function included (s) { return !(exclude && ~exclude.indexOf(s)) } | ||
@@ -584,3 +603,2 @@ var _bp = brackets.array(opts.brackets) | ||
pcex._bp = _bp | ||
pcex.__intflag = 1 | ||
@@ -594,3 +612,4 @@ tagName = tagName.toLowerCase() | ||
if (body && (body = body.replace(HTML_COMMENT, '')) && /\S/.test(body)) { | ||
if (body && (body = body.replace(HTML_COMMENT, | ||
function (s) { return s[0] === '<' ? '' : s })) && /\S/.test(body)) { | ||
@@ -604,17 +623,15 @@ if (body2) { | ||
body = body.replace(STYLE, included('css') ? function (_, _attrs, _style) { | ||
var extraOpts = { | ||
scoped: _attrs && /\sscoped(\s|=|$)/i.test(_attrs), | ||
url: url, | ||
parserOpts: getParserOptions(_attrs) | ||
} | ||
styles += (styles ? ' ' : '') + | ||
_compileCSS(_style, tagName, getType(_attrs) || opts.style, extraOpts) | ||
body = body.replace(STYLES, function (_m, _attrs, _style) { | ||
if (_m[0] !== '<') return _m | ||
if (included('css')) | ||
styles += (styles ? ' ' : '') + cssCode(_style, opts, _attrs, url, tagName) | ||
return '' | ||
} : '') | ||
}) | ||
body = body.replace(SCRIPT, included('js') ? function (_, _attrs, _script) { | ||
jscode += (jscode ? '\n' : '') + getCode(_script, opts, _attrs, url) | ||
body = body.replace(SCRIPT, function (_m, _attrs, _script) { | ||
if (_m[0] !== '<') return _m | ||
if (included('js')) | ||
jscode += (jscode ? '\n' : '') + getCode(_script, opts, _attrs, url) | ||
return '' | ||
} : '') | ||
}) | ||
@@ -663,3 +680,3 @@ var blocks = splitBlocks(body.replace(TRIM_TRAIL, '')) | ||
js: compileJS, | ||
version: 'v2.3.19' | ||
version: 'v2.3.20' | ||
} | ||
@@ -666,0 +683,0 @@ return compile |
Boolean attributes in riot 2.3 | ||
============================== | ||
From HTML5 - A vocabulary and associated APIs for HTML and XHTML - W3C Recommendation 28 October 2014: | ||
From _HTML5 - A vocabulary and associated APIs for HTML and XHTML_ - W3C Recommendation, 28 October 2014: | ||
@@ -15,3 +15,3 @@ > 2.4.2 Boolean attributes | ||
When the expression is trueish, riot sets the boolean attribute values to attribute's name: | ||
When the expression is trueish, riot sets the boolean attribute value to the attribute's name: | ||
```html | ||
@@ -38,3 +38,3 @@ <my-tag disabled={ 'yes' }></my-tag> | ||
* disabled - used in almost all form elements | ||
* ismap - `<img>` - for `<img>` elements descendant of an `<a>` element | ||
* ismap - for `<img>` elements descendant of an `<a>` element with href | ||
* noresize - `<frame>` - deprecated in html5 | ||
@@ -49,3 +49,3 @@ * noshade - `<hr>` - deprecated in html5 | ||
**Recognized html5 attributes** | ||
...and these html5 attributes: | ||
* autofocus | ||
@@ -67,4 +67,4 @@ * autoplay - `<audio>`/`<video>` | ||
**WARNING:** Please don't use expressions in the `loop` attribute within `<img>` tags. | ||
In images, `loop` is not a boolean attribute. This will fix soon. | ||
**Warning:** Please don't use expressions in the `loop` attribute for `<img>` tags. | ||
In images, `loop` is not a boolean attribute. ~~This will fix soon.~~ | ||
@@ -76,14 +76,14 @@ Tested with [the w3c Validator](https://validator.w3.org/nu) | ||
This unused or non-boolean attributes, recognized in previous versions, are removed in v2.3.0: | ||
The following unused or non-boolean attributes, recognized in previous versions, are removed in v2.3.0: | ||
* async - `<script>` - riot does not handle this | ||
* async - `<script>` - riot does not support async scripts in custom tags | ||
* declare - `<object>` - unuseful in main browsers | ||
* defaultChecked - it is a property, not attribute | ||
* defer - `<script>` - riot does not handle this, only IE8+ honors this attribute | ||
* defaultChecked - it is a property, not an attribute | ||
* defer - `<script>` - riot does not handle this, only IE8/9 honors this attribute | ||
* draggable - not boolean, this is an enumerated attribute: true, false, auto | ||
* inert - this proposed html5 attribute was [dropped](https://html5.org/r/8536) from the spec | ||
* enabled - not in the HTML spec | ||
* indeterminate - boolean attr, but can't be set with markup | ||
* nohref - `<area>` - deprecated, same effect as NOT including a `href` attribute | ||
* pauseonexit - `<track>` - not for markup, or its too complex | ||
* indeterminate - this attribute can't be set with markup | ||
* nohref - `<area>` - deprecated, same effect as _not_ including a `href` attribute | ||
* pauseonexit - `<track>` - not for markup, it is too complex | ||
* spellcheck - not boolean, this is an enumerated attribute: true, false | ||
@@ -96,4 +96,4 @@ * translate - not boolean, this is an enumerated attribute: yes, no | ||
The following attributes give error when parsed on browser with `{ exrp_value }`. | ||
`d` describes the SVG `<path>`, Chrome gives error if the value has invalid format. | ||
The following attributes give error when parsed on browsers with `{ exrp_value }`. | ||
`d` describes the SVG `<path>`, Chrome gives error if the value has an invalid format. | ||
@@ -100,0 +100,0 @@ See: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d |
# Compiler Guide (complement, WIP) | ||
Please note the compiler generates code for call to the internal function `riot.tag2`, which is a simplified version of `riot.tag`. Since the type and order of the parameters of `riot.tag2` can change in any moment, we are using the `riot.tag` here for illustration purposes. | ||
## Indentation | ||
@@ -10,2 +12,4 @@ | ||
Inside `<pre>` tags, linefeeds are preserved. | ||
Example: | ||
@@ -26,4 +30,4 @@ ```html | ||
// This JS comment is at column 0, out of the tag | ||
riot.tag2('treeitem', '<pre>one\n two\n</pre> <treeitem> </treeitem>', '', '', function(opts) { | ||
click(e) {} | ||
riot.tag('treeitem', '<pre>one\n two\n</pre> <treeitem> </treeitem>', function(opts) { | ||
this.click = function(e) {}.bind(this) | ||
}); // the closing tag is indented by 2 spaces, this comment must be JS | ||
@@ -63,4 +67,3 @@ ``` | ||
This may seem counterintuitive, but maintains backward compatibility with the behavior of previous versions. | ||
See [The untagged JS block](the-untagged-js-block) for details. | ||
This may seem counterintuitive, but complies with the riot specification for [untagged JavaScript blocks](the-untagged-javascript-block). | ||
@@ -87,3 +90,3 @@ | ||
* spacing between name and value is removed | ||
* the value is enclosed in double quotes. | ||
* the value is enclosed in double quotes | ||
@@ -113,6 +116,6 @@ Content of `style` blocks and expressions are trimmed and newlines converted to compacted spaces. | ||
```js | ||
riot.tag2('my-tag', '<p></p>', 'p { display: none; }', 'style=" top:0; left:0" expr="{{ foo:"bar" }}"', function(opts) { | ||
riot.tag('my-tag', '<p></p>', 'p { display: none; }', 'style=" top:0; left:0" expr="{{ foo:"bar" }}"', function(opts) { | ||
this.click = function(e) | ||
{}.bind(this) | ||
}, '{ }'); | ||
}); | ||
``` | ||
@@ -138,6 +141,4 @@ | ||
```js | ||
// This JS comment is at column 0, out of the tag | ||
riot.tag2('my-tag', '', '', 'non-expr="\\{ empty:\\{} }" expr="{empty:{}}"', function(opts) { | ||
click(e) {} | ||
}); // the closing tag is indented by 2 spaces, this comment must be JS | ||
riot.tag('my-tag', '', '', 'non-expr="\\{ empty:\\{} }" expr="{empty:{}}"', function(opts) { | ||
}); | ||
``` | ||
@@ -192,3 +193,3 @@ at runtime, the backslashes in `non-expr` will be removed. If you need output a literal backslash in front of brackets, you must use `\\{` to generate `\\\\{`. | ||
Be aware that the `html` and `js` properties can contain raw line endings --i.e. unescaped `\r` and/or `\n`. | ||
Be aware that the `html` and `js` properties can contain raw line endings --i.e. unescaped `\r` and `\n`. | ||
@@ -198,3 +199,3 @@ | ||
In addition to the `type` attribute, `script` and `style` tags can include additional configuration at tag level through the `options` attribute. | ||
In addition to the `type` attribute, the `script` and `style` tags can include additional configuration at tag level through the `options` attribute. | ||
@@ -217,3 +218,3 @@ This attribute is a [JSON](http://json.org/) object that specifies options for the JS or CSS parser. | ||
**NOTE:** The `options` attribute must comply with the [JSON specs](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf), i.e. with double-quoted property names and strings, in a format suitable for `JSON.parse` | ||
**Note:** The `options` attribute must comply with the [JSON specs](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf), i.e. with double-quoted property names and strings, in a format suitable for `JSON.parse` | ||
@@ -228,14 +229,11 @@ | ||
The first action taken by the compiler is send the received source to any html parser. | ||
After that, it normalizes line endings to `\n` and removes _html_ comments. | ||
Once prepared the source, searches the tags, separate its parts (closing/opening tag, root | ||
attributes, and content). In the content, one by one, removes the `style` blocks and sends its | ||
content to the CSS parser. Next, it does the same for the `script` tags. | ||
This is done in the entire content. | ||
After that, the compiler normalizes line endings to `\n` and removes _html_ comments. | ||
Once prepared the source, searches the tags, separate its parts (closing/opening tag, root attributes, and content). In the content, one by one, removes the `style` blocks and sends its content to the CSS parser. Next, it does the same for the `script` tags. | ||
This is done in the entire tag content. | ||
In the remaining content, looks for the last html tag which ends a line. | ||
In the remaining content, looks for the last html tag which _ends a line_. | ||
If found, this closing tag signals the end of the html markup and the beginning of the JavaScript code. | ||
If not found, all remaining is considered JavaScript. | ||
So, you can put html comments, `style`, and `script` blocks, anywhere inside the tag. | ||
The only restriction is that the untagged JavaScript code must finish the content and you can't use JavaScript comments out of this block. | ||
So, although not a good idea, you can put html comments, `style`, and `script` blocks, anywhere inside the tag; the only restriction is that the untagged JavaScript block must follow the remaining html content and you can't use JavaScript comments out of this block. | ||
@@ -246,2 +244,3 @@ ### Multiple JavaScript Blocks | ||
Once parsed, all blocks will be merged by the compiler. | ||
The resulting block is enclosed in a function, executed at mount time in the tag context, this is why sometimes is referred to as the tag "constructor". | ||
@@ -251,8 +250,9 @@ ### Loading JavaScript from the File System (v2.3.13) | ||
The `src` attribute of the `script` tags inside a riot tag, allows load source files from the file system. | ||
The filename in `src` can be absolute or relative. | ||
It can be combined with the `charset` attribute. `charset` defaults to `utf8` and the JavaScript type defaults to the `type` option specified in the options passed to the compiler. | ||
**Note** | ||
If you pass a third parameter to the `compile` function with the full name of the file being compiled, relative paths will be resolved from this name, if not, these will be relative to the current working directory (as returned by `proccess.cwd()`). | ||
The filename in `src` can be absolute or relative. If you pass a third parameter to the `compile` function with the full name of the file being compiled, relative paths will be resolved from this name, if not, these will be relative to the current working directory (as returned by `proccess.cwd()`). | ||
JavaScript type defaults to the `type` specified in the options passed to the compiler. If you don't want the code to be parsed, use `type="none"`. | ||
The encoding is specified by the `charset` attribute. It defaults to `utf8`. | ||
Example: | ||
@@ -266,12 +266,14 @@ ```js | ||
So, if we have a mytag.tag and a js/data.js file... | ||
So, if you have a js/data.js loaded by a mytag.tag file... | ||
```js | ||
// ./js/data.js file | ||
this.title = "my title" | ||
// js/data.js file | ||
const APP_NAME = 'My App' | ||
``` | ||
```html | ||
// ./mytag.tag file | ||
// mytag.tag file | ||
<my-tag> | ||
<p>{ title }</p> | ||
<h1>{ title }</h1> | ||
<script src="js/data.js" type="es6"></script> | ||
this.title = APP_NAME | ||
</my-tag> | ||
@@ -283,6 +285,7 @@ ``` | ||
<my-tag> | ||
<p>{ title }</p> | ||
<h1>{ title }</h1> | ||
<script type="es6"> | ||
this.title = "my title" | ||
const APP_NAME = 'My App' | ||
</script> | ||
this.title = APP_NAME | ||
</my-tag> | ||
@@ -303,3 +306,3 @@ ``` | ||
#### html(source, compilerOptions, compiledExpressions) | ||
#### html(source, compilerOptions, expressions) | ||
@@ -310,6 +313,8 @@ | parameter | type | description | ||
| compilerOptions | object | optional. Used properties: `brackets`, `withespace`, `compact`, `type`, `expr` | ||
| compiledExpressions | Array | optional. See below. | ||
| expressions | Array | optional. See below. | ||
`compiledExpressions` is interesting, on return it holds, in order of appearance, trimmed and without brackets, the expressions found in the html. If you set `type` and `expr` in the `compilerOptions` parameter, the expressions will be compiled. | ||
The `expressions` parameter is interesting, on return it holds, in order of appearance, trimmed and without brackets, the expressions found in the html. If you set `type` and `expr` in the `compilerOptions` parameter, the expressions will be compiled. | ||
**Note:** `expressions` is exposed for debugging purposes, but not dependent on it, its format may be altered in future versions. | ||
#### css(source, parserName, extraOptions) | ||
@@ -320,3 +325,3 @@ | ||
| source | string | styles | ||
| parserName | string/function | optional, can be omited. If string, must be one of `parsers.js` | ||
| parserName | string | optional, can be omited. Must be one of `parsers.js` | ||
| extraOptions | Object | optional, can be omited. Used properties: `tagName`, `parserOpts`, `url`, and `scoped` | ||
@@ -357,7 +362,6 @@ | ||
``` | ||
Since the default JS parser does not make use of the extra options, this is the same: | ||
Since the default JS parser does not make use of the extra options, this is equivalent: | ||
```js | ||
var js = compiler.js(source) | ||
``` | ||
`compilerOptions` will be removed in a future version. | ||
The `compilerOptions` parameter will be removed in a future version. |
/* riot-compiler WIP, @license MIT, (c) 2015 Muut Inc. + contributors */ | ||
'use strict' // eslint-disable-line | ||
'use strict' | ||
@@ -4,0 +4,0 @@ //#include_once parsers |
@@ -8,2 +8,5 @@ /** | ||
*/ | ||
//#if 0 // only in the unprocessed source | ||
/*eslint no-unused-vars: [2, {args: "after-used", varsIgnorePattern: "^brackets$"}] */ | ||
//#endif | ||
@@ -31,4 +34,4 @@ //#set $_RIX_TEST = 4 | ||
// `MLCOMMS` - Multiline comments in almost all their forms<br> | ||
// `STRINGS` - Quoted strings. Don't care about inner eols<br> | ||
// `MLCOMMS` - Multiline comments in almost all their forms | ||
// `STRINGS` - Quoted strings. Don't care about inner eols | ||
@@ -82,3 +85,3 @@ MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g, | ||
*/ | ||
function _rewrite(re, bp) { | ||
function _rewrite (re, bp) { | ||
return RegExp( | ||
@@ -109,3 +112,3 @@ re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : '' | ||
*/ | ||
_brackets.split = function split(str, tmpl, _bp) { | ||
_brackets.split = function split (str, tmpl, _bp) { | ||
@@ -174,7 +177,7 @@ // Template text is easy: closing brackets are ignored, all we have to do is find | ||
// tmpl, from the HTML part too. | ||
function unescapeStr(str) { | ||
function unescapeStr (s) { | ||
if (isexpr) | ||
parts.push(str && str.replace(_bp[$_RIX_ESC], '$1')) | ||
parts.push(s && s.replace(_bp[$_RIX_ESC], '$1')) | ||
else | ||
parts.push(str) | ||
parts.push(s) | ||
} | ||
@@ -184,3 +187,3 @@ | ||
// Skips strings, regexes, and other inner blocks. | ||
function skipBraces(ch, pos) { | ||
function skipBraces (ch, pos) { | ||
var | ||
@@ -208,3 +211,3 @@ match, | ||
*/ | ||
_brackets.array = function array(pair) { | ||
_brackets.array = function array (pair) { | ||
@@ -211,0 +214,0 @@ if (!pair || pair === DEFAULT) return _pairs |
193
lib/core.js
@@ -0,3 +1,7 @@ | ||
//#if 0 // only in the unprocessed source | ||
/*eslint no-unused-vars: [2, {args: "after-used", varsIgnorePattern: "^compile*"}] */ | ||
/*global brackets, parsers */ | ||
//#endif | ||
function _regEx(str, opt) { return new RegExp(str, opt) } | ||
function _regEx (str, opt) { return new RegExp(str, opt) } | ||
@@ -27,5 +31,6 @@ // Looks like, in [jsperf tests](http://jsperf.com/riot-regexp-test-vs-array-indexof) | ||
HTML_ATTR = /\s*([-\w:\xA0-\xFF]+)\s*(?:=\s*('[^']+'|"[^"]+"|\S+))?/g, | ||
SPEC_TYPES = /^"(?:number|date(?:time)?|time|month|email|color)\b/i, | ||
TRIM_TRAIL = /[ \t]+$/gm, | ||
S_STRINGS = brackets.R_STRINGS.source | ||
TRIM_TRAIL = /[ \t]+$/gm | ||
//#if NODE | ||
@@ -36,5 +41,2 @@ var path = require('path') | ||
//#set $_RIX_TEST = 4 | ||
//#set $_RIX_ESC = 5 | ||
//#set $_RIX_OPEN = 6 | ||
//#set $_RIX_CLOSE = 7 | ||
//#set $_RIX_PAIR = 8 | ||
@@ -44,5 +46,2 @@ //#ifndef $_RIX_TEST | ||
$_RIX_TEST = 4, // DONT'T FORGET SYNC THE #set BLOCK!!! | ||
$_RIX_ESC = 5, | ||
$_RIX_OPEN = 6, | ||
$_RIX_CLOSE = 7, | ||
$_RIX_PAIR = 8 | ||
@@ -52,3 +51,3 @@ //#endif | ||
// Escape backslashes and inner single quotes, and enclose s in single quotes | ||
function q(s) { | ||
function q (s) { | ||
return "'" + (s ? s | ||
@@ -60,3 +59,3 @@ .replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '\\r') : | ||
// Generates the `riot.tag2` call with the processed parts. | ||
function mktag(name, html, css, attrs, js, pcex) { | ||
function mktag (name, html, css, attrs, js, pcex) { | ||
var | ||
@@ -74,20 +73,2 @@ c = ', ', | ||
/** | ||
* Merge two javascript object extending the properties of the first one with | ||
* the second | ||
* | ||
* @param {object} obj - source object | ||
* @param {object} props - extra properties | ||
* @returns {object} source object containing the new properties | ||
*/ | ||
function extend(obj, props) { | ||
for (var prop in props) { | ||
/* istanbul ignore next */ | ||
if (props.hasOwnProperty(prop)) { | ||
obj[prop] = props[prop] | ||
} | ||
} | ||
return obj | ||
} | ||
/** | ||
* Parses and format attributes. | ||
@@ -99,8 +80,7 @@ * | ||
*/ | ||
function parseAttrs(str, pcex) { | ||
function parseAttrs (str, pcex) { | ||
var | ||
list = [], | ||
match, | ||
k, v, | ||
_bp = pcex._bp, | ||
k, v, t, e, | ||
DQ = '"' | ||
@@ -122,3 +102,2 @@ | ||
else { | ||
// attribute values must be enclosed in double quotes | ||
@@ -128,19 +107,22 @@ if (v[0] !== DQ) | ||
if (k === 'type' && v.toLowerCase() === '"number"') { | ||
v = DQ + _bp[0] + "'number'" + _bp[1] + DQ // fix #827 by @rsbondi | ||
if (k === 'type' && SPEC_TYPES.test(v)) { | ||
t = v | ||
} | ||
else if (/\u0001\d/.test(v)) { | ||
// renames special attributes with expressiones in their value. | ||
if (BOOL_ATTRS.test(k)) { | ||
k = '__' + k | ||
else { | ||
if (/\u0001\d/.test(v)) { | ||
// renames special attributes with expressiones in their value. | ||
if (k === 'value') e = 1 | ||
else if (BOOL_ATTRS.test(k)) k = '__' + k | ||
else if (~RIOT_ATTRS.indexOf(k)) k = 'riot-' + k | ||
} | ||
else if (~RIOT_ATTRS.indexOf(k)) { | ||
k = 'riot-' + k | ||
} | ||
// join the key-value pair, with no spaces between the parts | ||
list.push(k + '=' + v) | ||
} | ||
// join the key-value pair, with no spaces between the parts | ||
list.push(k + '=' + v) | ||
} | ||
} | ||
// update() will evaluate `type` after the value, avoiding warnings | ||
if (t) { | ||
if (e) t = DQ + pcex._bp[0] + "'" + t.slice(1, -1) + "'" + pcex._bp[1] + DQ | ||
list.push('type=' + t) | ||
} | ||
return list.join(' ') // returns the attribute list | ||
@@ -151,3 +133,3 @@ } | ||
// through the parser, except those beginning with `{^`. | ||
function splitHtml(html, opts, pcex) { | ||
function splitHtml (html, opts, pcex) { | ||
var _bp = pcex._bp | ||
@@ -158,3 +140,3 @@ | ||
var | ||
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0, | ||
jsfn = opts.expr && (opts.parser || opts.type) ? _compileJS : 0, //eslint-disable-line | ||
list = brackets.split(html, 0, _bp), | ||
@@ -181,3 +163,3 @@ expr | ||
// Restores expressions hidden by splitHtml and escape literal internal brackets | ||
function restoreExpr(html, pcex) { | ||
function restoreExpr (html, pcex) { | ||
if (pcex.length) { | ||
@@ -206,9 +188,8 @@ html = html | ||
var | ||
HTML_COMMENT = /<!--(?!>)[\S\s]*?-->/g, | ||
HTML_COMMENT = _regEx(/<!--(?!>)[\S\s]*?-->/.source + '|' + S_STRINGS, 'g'), | ||
HTML_TAGS = /<([-\w]+)\s*([^"'\/>]*(?:(?:"[^"]*"|'[^']*'|\/[^>])[^'"\/>]*)*)(\/?)>/g, | ||
PRE_TAG = _regEx( | ||
/<pre(?:\s+[^'">]+(?:(?:@Q)[^'">]*)*|\s*)?>([\S\s]*?)<\/pre\s*>/ | ||
.source.replace('@Q', brackets.R_STRINGS.source), 'gi') | ||
/<pre(?:\s+[^'">]+(?:(?:@Q)|[^>]*)*|\s*)?>([\S\s]*?)<\/pre\s*>/.source.replace('@Q', S_STRINGS), 'gi') | ||
function _compileHTML(html, opts, pcex) { | ||
function _compileHTML (html, opts, pcex) { | ||
@@ -232,7 +213,8 @@ // separate the expressions, then parse the tags and their attributes | ||
var p = [] | ||
html = html.replace(PRE_TAG, function (q) | ||
{ return p.push(q) && '\u0002' }).trim().replace(/\s+/g, ' ') | ||
html = html.replace(PRE_TAG, function (_q) { | ||
return p.push(_q) && '\u0002' | ||
}).trim().replace(/\s+/g, ' ') | ||
// istanbul ignore else | ||
if (p.length) | ||
html = html.replace(/\u0002/g, function (_) { return p.shift() }) | ||
html = html.replace(/\u0002/g, function () { return p.shift() }) | ||
} | ||
@@ -259,3 +241,3 @@ else | ||
// istanbul ignore next | ||
function compileHTML(html, opts, pcex) { | ||
function compileHTML (html, opts, pcex) { | ||
if (Array.isArray(opts)) { | ||
@@ -270,4 +252,4 @@ pcex = opts | ||
if (!pcex.__intflag) | ||
html = html.replace(/\r\n?/g, '\n').replace(HTML_COMMENT, '').replace(TRIM_TRAIL, '') | ||
html = html.replace(/\r\n?/g, '\n').replace(HTML_COMMENT, | ||
function (s) { return s[0] === '<' ? '' : s }).replace(TRIM_TRAIL, '') | ||
@@ -291,3 +273,3 @@ // `_bp` is undefined when `compileHTML` is not called by compile | ||
// Default parser for JavaScript code | ||
function riotjs(js) { | ||
function riotjs (js) { | ||
var | ||
@@ -300,3 +282,3 @@ match, | ||
// remove comments | ||
js = js.replace(JS_RMCOMMS, function (m, q) { return q ? m : ' ' }) | ||
js = js.replace(JS_RMCOMMS, function (m, _q) { return _q ? m : ' ' }) | ||
@@ -326,11 +308,11 @@ // $1: indentation, | ||
// Inner helper - find the position following the closing bracket for the current block | ||
function skipBlock(str) { | ||
function skipBlock (str) { | ||
var | ||
re = _regEx('([{}])|' + brackets.S_QBLOCKS, 'g'), | ||
level = 1, | ||
match | ||
mm | ||
while (level && (match = re.exec(str))) { | ||
if (match[1]) | ||
match[1] === '{' ? ++level : --level | ||
while (level && (mm = re.exec(str))) { | ||
if (mm[1]) | ||
mm[1] === '{' ? ++level : --level | ||
} | ||
@@ -341,3 +323,3 @@ return level ? str.length : re.lastIndex | ||
function _compileJS(js, opts, type, parserOpts, url) { | ||
function _compileJS (js, opts, type, parserOpts, url) { | ||
if (!js) return '' | ||
@@ -363,3 +345,3 @@ if (!type) type = opts.type | ||
// istanbul ignore next | ||
function compileJS(js, opts, type, extra) { | ||
function compileJS (js, opts, type, extra) { | ||
if (typeof opts === 'string') { | ||
@@ -385,7 +367,7 @@ extra = type | ||
// Prepare regex to match CSS selectors, excluding those beginning with '@'. | ||
var CSS_SELECTOR = _regEx('(}|{|^)[ ;]*([^@ ;{}][^{}]*)(?={)|' + brackets.R_STRINGS.source, 'g') | ||
var CSS_SELECTOR = _regEx('(}|{|^)[ ;]*([^@ ;{}][^{}]*)(?={)|' + S_STRINGS, 'g') | ||
// Parses styles enclosed in a "scoped" tag (`scoped` is deprecated in HTML5). | ||
// The "style" string is received without comments or surrounding spaces. | ||
function scopedCSS(tag, style) { | ||
function scopedCSS (tag, style) { | ||
var scope = ':scope' | ||
@@ -416,3 +398,3 @@ | ||
function _compileCSS(style, tag, type, opts) { | ||
function _compileCSS (style, tag, type, opts) { | ||
var scoped = (opts || (opts = {})).scoped | ||
@@ -425,3 +407,3 @@ | ||
else if (parsers.css[type]) { | ||
style = parsers.css[type](tag, style, opts.parserOpts, opts.url) | ||
style = parsers.css[type](tag, style, opts.parserOpts || {}, opts.url) | ||
} | ||
@@ -456,3 +438,3 @@ else if (type !== 'css') { | ||
// istanbul ignore next | ||
function compileCSS(style, parser, opts) { | ||
function compileCSS (style, parser, opts) { | ||
if (typeof parser === 'object') { | ||
@@ -462,3 +444,2 @@ opts = parser | ||
} | ||
else if (!opts) opts = {} | ||
return _compileCSS(style, opts.tagName, parser, opts) | ||
@@ -476,3 +457,3 @@ } | ||
// Returns the value of the 'type' attribute, with the prefix "text/" removed. | ||
function getType(str) { | ||
function getType (str) { | ||
@@ -487,3 +468,3 @@ if (str) { | ||
// Returns the value of any attribute, or the empty string for missing attribute. | ||
function getAttr(str, name) { | ||
function getAttr (str, name) { | ||
@@ -502,3 +483,3 @@ if (str) { | ||
// get the parser options from the options attribute | ||
function getParserOptions(attrs) { | ||
function getParserOptions (attrs) { | ||
var opts = getAttr(attrs, 'options') | ||
@@ -512,3 +493,3 @@ // convert the string into a valid js object | ||
// The CLI version can read code from the file system (experimental) | ||
function getCode(code, opts, attrs, url) { | ||
function getCode (code, opts, attrs, url) { | ||
var type = getType(attrs), | ||
@@ -532,2 +513,11 @@ parserOpts = getParserOptions(attrs) | ||
function cssCode (code, opts, attrs, url, tag) { | ||
var extraOpts = { | ||
parserOpts: getParserOptions(attrs), | ||
scoped: attrs && /\sscoped(\s|=|$)/i.test(attrs), | ||
url: url | ||
} | ||
return _compileCSS(code, tag, getType(attrs) || opts.style, extraOpts) | ||
} | ||
// Matches HTML tag ending a line. This regex still can be fooled by code as: | ||
@@ -540,3 +530,3 @@ // ```js | ||
function splitBlocks(str) { | ||
function splitBlocks (str) { | ||
var k, m | ||
@@ -553,3 +543,3 @@ | ||
} | ||
k = str.lastIndexOf('<', k -1) | ||
k = str.lastIndexOf('<', k - 1) | ||
} | ||
@@ -568,3 +558,3 @@ return ['', str] | ||
*/ | ||
function compileTemplate(html, url, lang, opts) { | ||
function compileTemplate (html, url, lang, opts) { | ||
var parser = parsers.html[lang] | ||
@@ -580,3 +570,3 @@ | ||
CUST_TAG regex don't allow unquoted expressions containing the `>` operator. | ||
STYLE and SCRIPT disallows the operator `>` at all. | ||
STYLES and SCRIPT disallows the operator `>` at all. | ||
@@ -592,5 +582,6 @@ The beta.4 CUST_TAG regex is fast, with RegexBuddy I get 76 steps and 14 backtracks on | ||
/^([ \t]*)<([-\w]+)(?:\s+([^'"\/>]+(?:(?:@Q|\/[^>])[^'"\/>]*)*)|\s*)?(?:\/>|>[ \t]*\n?([\S\s]*)^\1<\/\2\s*>|>(.*)<\/\2\s*>)/ | ||
.source.replace('@Q', brackets.R_STRINGS.source), 'gim'), | ||
STYLE = /<style(\s+[^>]*)?>\n?([^<]*(?:<(?!\/style\s*>)[^<]*)*)<\/style\s*>/gi, | ||
SCRIPT = _regEx(STYLE.source.replace(/tyle/g, 'cript'), 'gi') | ||
.source.replace('@Q', S_STRINGS), 'gim'), | ||
SRC_TAGS = /<style(\s+[^>]*)?>\n?([^<]*(?:<(?!\/style\s*>)[^<]*)*)<\/style\s*>/.source + '|' + S_STRINGS, | ||
STYLES = _regEx(SRC_TAGS, 'gi'), | ||
SCRIPT = _regEx(SRC_TAGS.replace(/style/g, 'script'), 'gi') | ||
@@ -610,3 +601,3 @@ /** | ||
*/ | ||
function compile(src, opts, url) { | ||
function compile (src, opts, url) { | ||
var | ||
@@ -622,7 +613,9 @@ parts = [], | ||
// their transpiler setup | ||
url = url || process.cwd() + '/.' // getCode expect a file | ||
if (!url) url = process.cwd() + '/.' // getCode expect a file | ||
//#else | ||
if (!url) url = '' | ||
//#endif | ||
exclude = opts.exclude || false | ||
function included(s) { return !(exclude && ~exclude.indexOf(s)) } | ||
function included (s) { return !(exclude && ~exclude.indexOf(s)) } | ||
@@ -650,3 +643,2 @@ // get a static brackets array for use on the entire source | ||
pcex._bp = _bp // local copy, in preparation for async compilation | ||
pcex.__intflag = 1 | ||
@@ -662,3 +654,4 @@ tagName = tagName.toLowerCase() | ||
// remove comments and trim trailing whitespace | ||
if (body && (body = body.replace(HTML_COMMENT, '')) && /\S/.test(body)) { | ||
if (body && (body = body.replace(HTML_COMMENT, | ||
function (s) { return s[0] === '<' ? '' : s })) && /\S/.test(body)) { | ||
@@ -674,19 +667,17 @@ if (body2) { | ||
body = body.replace(STYLE, included('css') ? function (_, _attrs, _style) { | ||
var extraOpts = { | ||
scoped: _attrs && /\sscoped(\s|=|$)/i.test(_attrs), | ||
url: url, | ||
parserOpts: getParserOptions(_attrs) | ||
} | ||
styles += (styles ? ' ' : '') + | ||
_compileCSS(_style, tagName, getType(_attrs) || opts.style, extraOpts) | ||
body = body.replace(STYLES, function (_m, _attrs, _style) { | ||
if (_m[0] !== '<') return _m | ||
if (included('css')) | ||
styles += (styles ? ' ' : '') + cssCode(_style, opts, _attrs, url, tagName) | ||
return '' | ||
} : '') | ||
}) | ||
// now the script blocks | ||
body = body.replace(SCRIPT, included('js') ? function (_, _attrs, _script) { | ||
jscode += (jscode ? '\n' : '') + getCode(_script, opts, _attrs, url) | ||
body = body.replace(SCRIPT, function (_m, _attrs, _script) { | ||
if (_m[0] !== '<') return _m | ||
if (included('js')) | ||
jscode += (jscode ? '\n' : '') + getCode(_script, opts, _attrs, url) | ||
return '' | ||
} : '') | ||
}) | ||
@@ -693,0 +684,0 @@ // separate the untagged javascript block from the html markup |
@@ -0,1 +1,4 @@ | ||
//#if 0 | ||
/*eslint no-unused-vars: [2, {args: "after-used", varsIgnorePattern: "^parsers*"}] */ | ||
//#endif | ||
/** | ||
@@ -13,2 +16,4 @@ * @module parsers | ||
//#if NODE | ||
var path = require('path') | ||
var _modnames = { // for name-module convertion | ||
@@ -31,3 +36,3 @@ es6: 'babel', | ||
*/ | ||
function _modname(name) { | ||
function _modname (name) { | ||
return _modnames[name] || name | ||
@@ -45,7 +50,7 @@ } | ||
*/ | ||
function _try(name, req) { //eslint-disable-line complexity | ||
function _try (name, req) { //eslint-disable-line complexity | ||
var parser | ||
//#if NODE | ||
function fn(r) { | ||
function fn (r) { | ||
try { | ||
@@ -66,17 +71,18 @@ _mods[name] = require(r) | ||
//#else | ||
/*global window */ | ||
switch (name) { | ||
case 'coffee': | ||
req = 'CoffeeScript' | ||
break | ||
case 'es6': | ||
case 'babel': | ||
req = 'babel' | ||
break | ||
case 'none': | ||
case 'javascript': | ||
return _mods.none | ||
default: | ||
if (!req) req = name | ||
break | ||
case 'coffee': | ||
req = 'CoffeeScript' | ||
break | ||
case 'es6': | ||
case 'babel': | ||
req = 'babel' | ||
break | ||
case 'none': | ||
case 'javascript': | ||
return _mods.none | ||
default: | ||
if (!req) req = name | ||
break | ||
} | ||
@@ -93,8 +99,34 @@ parser = window[req] | ||
// Returns a parser instance, null if the parser is not found. | ||
// Public through the parsers._get function. | ||
function _req(name, req) { | ||
/** | ||
* Returns a parser instance by its name, require the module if necessary. | ||
* Public through the `parsers._req` function. | ||
* | ||
* @param {string} name - The parser's name, as registered in the parsers object | ||
* @param {string} [req] - To be used by require(). Defaults to parser's name | ||
* @returns {Function} - The parser instance, null if the parser is not found | ||
*/ | ||
function _req (name, req) { | ||
return name in _mods ? _mods[name] : _try(name, req) | ||
} | ||
/** | ||
* Merge two javascript object extending the properties of the first one with | ||
* the second. | ||
* | ||
* @param {object} obj - source object | ||
* @param {object} props - extra properties | ||
* @returns {object} source object containing the new properties | ||
*/ | ||
function extend (obj, props) { | ||
if (props) { | ||
for (var prop in props) { | ||
/* istanbul ignore next */ | ||
if (props.hasOwnProperty(prop)) { | ||
obj[prop] = props[prop] | ||
} | ||
} | ||
} | ||
return obj | ||
} | ||
//// The parsers object -- | ||
@@ -114,3 +146,3 @@ | ||
//#if NODE | ||
sass: function(tag, css, opts, url) { // there's no standard sass for browsers | ||
sass: function (tag, css, opts, url) { // there's no standard sass for browsers | ||
var sass = _req('sass') | ||
@@ -120,2 +152,3 @@ | ||
data: css, | ||
includePaths: [path.dirname(url)], | ||
indentedSyntax: true, | ||
@@ -126,3 +159,3 @@ omitSourceMapUrl: true, | ||
}, | ||
scss: function(tag, css, opts, url) { // there's no standard sass for browsers | ||
scss: function (tag, css, opts, url) { // there's no standard sass for browsers | ||
var scss = _req('scss') | ||
@@ -132,2 +165,3 @@ | ||
data: css, | ||
includePaths: [path.dirname(url)], | ||
indentedSyntax: false, | ||
@@ -139,3 +173,3 @@ omitSourceMapUrl: true, | ||
//#endif | ||
less: function(tag, css, opts, url) { | ||
less: function (tag, css, opts, url) { | ||
var less = _req('less'), | ||
@@ -146,2 +180,4 @@ ret | ||
sync: true, | ||
syncImport: true, | ||
filename: url, | ||
compress: true | ||
@@ -157,6 +193,9 @@ }, opts), function (err, result) { | ||
var | ||
stylus = _req('stylus'), nib = _req('nib') // optional nib support | ||
xopts = extend({filename: url}, opts), | ||
stylus = _req('stylus'), | ||
nib = _req('nib') // optional nib support | ||
/* istanbul ignore next: can't run both */ | ||
return nib ? | ||
stylus(css).use(nib()).import('nib').render() : stylus.render(css) | ||
stylus(css, xopts).use(nib()).import('nib').render() : stylus.render(css, xopts) | ||
} | ||
@@ -166,9 +205,9 @@ } | ||
var _js = { | ||
livescript: function (js, opts, url) { | ||
livescript: function (js, opts) { | ||
return _req('livescript').compile(js, extend({bare: true, header: false}, opts)) | ||
}, | ||
typescript: function (js, opts, url) { | ||
typescript: function (js, opts) { | ||
return _req('typescript')(js, opts).replace(/\r\n?/g, '\n') | ||
}, | ||
es6: function (js, opts, url) { | ||
es6: function (js, opts) { | ||
return _req('es6').transform(js, extend({ | ||
@@ -179,10 +218,5 @@ blacklist: ['useStrict', 'strict', 'react'], sourceMaps: false, comments: false | ||
babel: function (js, opts, url) { | ||
// istanbul ignore next: url empty if comming from expression | ||
return _req('babel').transform(js, | ||
extend({ | ||
filename: url || '' | ||
}, opts) | ||
).code | ||
return _req('babel').transform(js, extend({filename: url}, opts)).code | ||
}, | ||
coffee: function (js, opts, url) { | ||
coffee: function (js, opts) { | ||
return _req('coffee').compile(js, extend({bare: true}, opts)) | ||
@@ -189,0 +223,0 @@ }, |
{ | ||
"name": "riot-compiler", | ||
"version": "2.3.19", | ||
"version": "2.3.20", | ||
"description": "Compiler for riot .tag files", | ||
@@ -19,3 +19,3 @@ "main": "dist/compiler.js", | ||
"test": "make test", | ||
"prepublish": "make build && node bump" | ||
"prepublish": "make build && ./node_modules/.bin/riot-bump" | ||
}, | ||
@@ -37,4 +37,5 @@ "repository": { | ||
"istanbul": "^0.4.1", | ||
"jspreproc": "^0.2.5", | ||
"mocha": "^2.3.4" | ||
"jspreproc": "^0.2.7", | ||
"mocha": "^2.3.4", | ||
"riot-bump": "^1.0.0" | ||
}, | ||
@@ -41,0 +42,0 @@ "author": "Muut, Inc. and other contributors", |
@@ -29,6 +29,6 @@ [![Build Status][travis-image]][travis-url] | ||
Due to changes in the babel API, from our v2.3.0-beta.7 we are separating the babel support in the following types: | ||
Due to changes in the babel API, from our v2.3.0 we are separating the babel support in the following types: | ||
* es6 - For `babel` and `babel-core` v5.8.x and below | ||
* babel - For `babel-core` v6.x - You must `npm install babel-preset-es2015` too, for this to work. | ||
* babel - For `babel-core` v6.x - You must `npm install babel-preset-es2015-riot` too, for this to work. | ||
@@ -35,0 +35,0 @@ |
/* | ||
Performance test for the compiler | ||
*/ | ||
'use strict' // eslint-disable-line strict, global-strict | ||
/*eslint no-console: 0 */ | ||
'use strict' // eslint-disable-line | ||
@@ -9,5 +10,2 @@ var | ||
compiler22 = require('./v223/compiler223.js').compile, | ||
tmpl23 = require('riot-tmpl').tmpl, | ||
tmpl22 = require('./v223/compiler223.js').tmpl, | ||
assert = require('assert'), | ||
path = require('path'), | ||
@@ -18,4 +16,3 @@ fs = require('fs') | ||
basedir = path.join(__dirname, 'specs', 'fixtures'), | ||
tags = ['box', 'empty', 'input-last', 'mixed-js', 'same', 'scoped', 'timetable', 'treeview', 'oneline'], | ||
data = { num: 1, str: 'string', date: new Date(), bool: true, item: null } | ||
tags = ['box', 'empty', 'input-last', 'mixed-js', 'same', 'scoped', 'timetable', 'treeview', 'oneline'] | ||
@@ -40,3 +37,3 @@ var files = tags.map(function (f) { | ||
console.log('Testing each compiler with %d files, %dx%d iterations (%d total)', | ||
tags.length, TMAX-2, LOOP, tags.length * (TMAX-2) * LOOP) | ||
tags.length, TMAX - 2, LOOP, tags.length * (TMAX - 2) * LOOP) | ||
@@ -71,3 +68,3 @@ console.log('Running the compiler v2.2.4 ...') | ||
function test(compiler, times, ogc) { | ||
function test (compiler, times, ogc) { | ||
var gcm | ||
@@ -81,3 +78,3 @@ global.gc() | ||
tt = new Array(TMAX), | ||
s, i, j | ||
i, j | ||
@@ -87,3 +84,3 @@ for (i = 0; i < tt.length; ++i) { | ||
for (j = 0; j < LOOP; ++j) { | ||
s = compiler(text) | ||
compiler(text) | ||
} | ||
@@ -102,18 +99,18 @@ tt[i] = Date.now() - tt[i] | ||
function numsort(a, b) { | ||
function numsort (a, b) { | ||
return a - b | ||
} | ||
function numsum(a, b) { | ||
function numsum (a, b) { | ||
return a + b | ||
} | ||
function replicate(s, n) { | ||
function replicate (s, n) { | ||
return n < 1 ? '' : (new Array(n + 1)).join(s) | ||
} | ||
function padr(s, n) { | ||
function padr (s, n) { | ||
s = '' + s | ||
return s + replicate(' ', n - s.length) | ||
} | ||
function padl(s, n) { | ||
function padl (s, n) { | ||
s = '' + s | ||
return replicate(' ', n - s.length) + s | ||
} |
var isNode = typeof window === 'undefined' | ||
describe('Compiler Tests', function() { | ||
describe('Compiler Tests', function () { | ||
expect = require('expect.js') | ||
@@ -5,0 +5,0 @@ compiler = require('../dist/compiler.js') |
//src: test/specs/fixtures/pre.tag | ||
riot.tag2('pre-tag', '<pre>xyz\n cc\n ss</pre> <pre-fake>xyz cc ss</pre-fake> <pre x="{1>2}">xyz\n cc\n ss</pre>', '', '', function(opts) { | ||
riot.tag2('pre-tag', '<pre>xyz\n cc\n ss</pre> <pre-fake>xyz cc ss</pre-fake> <pre x="{1>2}" y="{3}">xyz\n cc\n ss</pre>', '', '', function(opts) { | ||
}, '{ }'); |
@@ -10,1 +10,2 @@ | ||
}.bind(this) | ||
var str = '/* str */' |
@@ -14,4 +14,5 @@ //THIS IS A LINE COMMENT | ||
} | ||
var str = '/* str */' | ||
/*COMMENT | ||
click (e) {} | ||
*/ |
@@ -0,13 +1,15 @@ | ||
/*eslint-env mocha */ | ||
/*global compiler, expect */ | ||
describe('Compile HTML', function() { | ||
describe('Compile HTML', function () { | ||
function render(str, opts) { | ||
function render (str, opts) { | ||
return compiler.html(str, opts || {}) | ||
} | ||
function testStr(str1, str2, opts) { | ||
function testStr (str1, str2, opts) { | ||
expect(render(str1, opts)).to.be(str2) | ||
} | ||
it('compiles void tag into separated: <x/> -> <x></x>', function() { | ||
it('compiles void tag into separated: <x/> -> <x></x>', function () { | ||
testStr('<p/>', '<p></p>') | ||
@@ -18,3 +20,3 @@ testStr('<a><b/></a>', '<a><b></b></a>') | ||
it('adds the prefix `riot-` to some attributes', function() { | ||
it('adds the prefix `riot-` to some attributes', function () { | ||
testStr('<img src={ a }>', '<img riot-src="{a}">') | ||
@@ -24,3 +26,3 @@ testStr('<p style="left:0; top={ n }">', '<p riot-style="left:0; top={n}">') | ||
it('adds the prefix `__` to boolean attributes with expressions', function() { | ||
it('adds the prefix `__` to boolean attributes with expressions', function () { | ||
testStr('<a disabled={ a } nowrap="{ b }">', '<a __disabled="{a}" __nowrap="{b}">') | ||
@@ -31,3 +33,3 @@ testStr('<a disabled readonly={}>', '<a disabled __readonly="{}">') | ||
it('adds double quotes to the attribute value', function() { | ||
it('adds double quotes to the attribute value', function () { | ||
testStr('<a a={ a }>', '<a a="{a}">') | ||
@@ -40,3 +42,3 @@ testStr("<a a='{ a }'>", '<a a="{a}">') | ||
it('keeps interpolations', function() { | ||
it('keeps interpolations', function () { | ||
testStr('<a href="a?b={ c }">', '<a href="a?b={c}">') | ||
@@ -46,3 +48,3 @@ testStr('<a id="{ a }b">', '<a id="{a}b">') | ||
it('skips HTML comments', function() { | ||
it('skips HTML comments', function () { | ||
testStr('{ a }<!-- c -->', '{a}') | ||
@@ -53,7 +55,7 @@ testStr('<!-- c -->{ a }', '{a}') | ||
it('option `whitespace` normalizes and preserves line endings', function() { | ||
it('option `whitespace` normalizes and preserves line endings', function () { | ||
testStr('<p>a\r</p>\r\r\n<p>\n</p>', '<p>a\n</p>\n\n<p>\n</p>', { whitespace: 1 }) | ||
}) | ||
it('option `compact` removes line endings between tags', function() { | ||
it('option `compact` removes line endings between tags', function () { | ||
testStr('<p>a\r</p>\r\r\n<p>\n</p>', '<p>a </p><p></p>', { compact: 1 }) | ||
@@ -64,6 +66,18 @@ }) | ||
it('fix #827 to input type=number', function () { | ||
testStr('<input type=number>', '<input type="{\'number\'}">') | ||
it('fix #827 input type=number and expression in the value', function () { | ||
testStr('<input type=number>', '<input type="number">') // no value | ||
testStr('<input type=number value=1>', '<input value="1" type="number">') // no expression | ||
testStr('<input type=number value={ 1 }>', '<input value="{1}" type="{\'number\'}">') | ||
}) | ||
it('fix #1495 Warning of input tag value - for date/time/month/email/color values', function () { | ||
testStr('<input type=date value={d}>', '<input value="{d}" type="{\'date\'}">') | ||
testStr('<input type=time value={t}>', '<input value="{t}" type="{\'time\'}">') | ||
testStr('<input type=date-local value={dl}>', '<input value="{dl}" type="{\'date-local\'}">') | ||
testStr('<input type=datetime value={dt}>', '<input value="{dt}" type="{\'datetime\'}">') | ||
testStr('<input type=month value={m}>', '<input value="{m}" type="{\'month\'}">') | ||
testStr('<input type=email value={e}>', '<input value="{e}" type="{\'email\'}">') | ||
testStr('<input type=color value={c}>', '<input value="{c}" type="{\'color\'}">') | ||
}) | ||
it('normalizes attributes, all values in double quotes', function () { | ||
@@ -98,3 +112,3 @@ testStr('<a a={a} b=number c =\'x\'>', '<a a="{a}" b="number" c="x">') | ||
// compile.html must preserve escaped brackets | ||
it('preserves escaped riot brackets', function() { | ||
it('preserves escaped riot brackets', function () { | ||
testStr('\\{ a }', '\\{ a }') | ||
@@ -131,5 +145,5 @@ testStr(' \\{ a \\}', '\\{ a \\}') // trim is ok | ||
'<p>{= \'<\' + myElem + \' style=\u2057color: \' + myColor + \';\u2057>\\n Click me</\' + myElem + \'>\'}</p>') | ||
testStr( | ||
'<ul><li>{= ["foo", "bar"].join(\'<br/>\') }</li></ul>', | ||
'<ul><li>{= [\u2057foo\u2057, \u2057bar\u2057].join(\'<br/>\')}</li></ul>') | ||
testStr( | ||
'<ul><li>{= ["foo", "bar"].join(\'<br/>\') }</li></ul>', | ||
'<ul><li>{= [\u2057foo\u2057, \u2057bar\u2057].join(\'<br/>\')}</li></ul>') | ||
}) | ||
@@ -136,0 +150,0 @@ |
// | ||
// Parsers Suite | ||
// | ||
/*eslint-env node, mocha */ | ||
/*eslint-env mocha */ | ||
/*global compiler, expect */ | ||
/*eslint no-console: 0 */ | ||
var | ||
path = require('path'), | ||
fs = require('fs') | ||
var | ||
@@ -12,3 +16,3 @@ fixtures = __dirname, | ||
function have(mod, req) { | ||
function have (mod, req) { | ||
if (compiler.parsers._req(mod, req)) | ||
@@ -20,7 +24,7 @@ return true | ||
function cat(dir, filename) { | ||
function cat (dir, filename) { | ||
return fs.readFileSync(path.join(dir, filename), 'utf8') | ||
} | ||
function normalize(str) { | ||
function normalize (str) { | ||
var | ||
@@ -34,8 +38,9 @@ n = str.search(/[^\n]/) | ||
function testParser(name, opts, save) { | ||
function testParser (name, opts, save) { | ||
opts = opts || {} | ||
var | ||
file = name + (opts.type ? '.' + opts.type : ''), | ||
str1 = cat(fixtures, file + '.tag'), | ||
str2 = cat(expected, file + '.js') | ||
js = compiler.compile(str1, opts || {}, path.join(fixtures, file + '.tag')) | ||
str2 = cat(expected, file + '.js'), | ||
js = compiler.compile(str1, opts, path.join(fixtures, file + '.tag')) | ||
@@ -53,3 +58,3 @@ if (save) | ||
function testStr(str, resStr, opts) { | ||
function testStr (str, resStr, opts) { | ||
expect(compiler.html(str, opts || {})).to.be(resStr) | ||
@@ -104,3 +109,3 @@ } | ||
function _custom(js) { | ||
function _custom () { | ||
return 'var foo' | ||
@@ -114,3 +119,3 @@ } | ||
if (have('none')) { // testing none, for coverage too | ||
testParser('complex', {}) | ||
testParser('complex') | ||
} | ||
@@ -132,3 +137,3 @@ else expect().fail('parsers.js must have a "none" property') | ||
if (have('javascript')) { // for js, for coverage too | ||
testParser('mixed-js', {}) | ||
testParser('mixed-js') | ||
} | ||
@@ -196,3 +201,3 @@ else expect().fail('parsers.js must have a "javascript" property') | ||
// custom parser | ||
compiler.parsers.css.postcss = function(tag, css, opts) { | ||
compiler.parsers.css.postcss = function (tag, css) { | ||
return require('postcss')([require('autoprefixer')]).process(css).css | ||
@@ -203,3 +208,3 @@ } | ||
it('default style', function () { | ||
testParser('style', {}) | ||
testParser('style') | ||
}) | ||
@@ -209,3 +214,3 @@ | ||
it('scoped styles', function () { | ||
testParser('style.scoped', {}) | ||
testParser('style.scoped') | ||
}) | ||
@@ -216,3 +221,4 @@ | ||
if (have('stylus')) { | ||
testParser('stylus', {}) | ||
testParser('stylus') | ||
testParser('stylus-import') | ||
} | ||
@@ -224,3 +230,3 @@ }) | ||
if (have('sass')) { | ||
testParser('sass', {}) | ||
testParser('sass') | ||
} | ||
@@ -232,3 +238,4 @@ }) | ||
if (have('scss')) { | ||
testParser('scss', {}) | ||
testParser('scss') | ||
testParser('scss-import') | ||
} | ||
@@ -240,3 +247,3 @@ }) | ||
if (have('sass')) { | ||
testParser('sass.options', {}) | ||
testParser('sass.options') | ||
} | ||
@@ -248,3 +255,3 @@ }) | ||
if (have('postcss', 'postcss')) { | ||
testParser('postcss', {}) | ||
testParser('postcss') | ||
} | ||
@@ -256,3 +263,4 @@ }) | ||
if (have('less')) { | ||
testParser('less', {}) | ||
testParser('less') | ||
testParser('less-import') | ||
} | ||
@@ -262,3 +270,3 @@ }) | ||
it('mixing CSS blocks with different type', function () { | ||
testParser('mixed-css', {}) | ||
testParser('mixed-css') | ||
}) | ||
@@ -314,3 +322,3 @@ | ||
// custom parser | ||
compiler.parsers.js.rawhtml = function(js) { | ||
compiler.parsers.js.rawhtml = function (js) { | ||
return js.replace(/"/g, '"') | ||
@@ -317,0 +325,0 @@ } |
@@ -0,1 +1,4 @@ | ||
/*eslint-env mocha */ | ||
/*global compiler, expect */ | ||
var fs = require('fs'), | ||
@@ -6,11 +9,11 @@ path = require('path') | ||
function render(str) { | ||
function render (str) { | ||
return compiler.js(str, {}) | ||
} | ||
function cat(dir, filename) { | ||
function cat (dir, filename) { | ||
return fs.readFileSync(path.join(__dirname, dir, filename), 'utf8') | ||
} | ||
function testFile(file, opts) { | ||
function testFile (file/*, opts*/) { | ||
expect(render(cat('fixtures', file))).to.be(cat('expect', file)) | ||
@@ -17,0 +20,0 @@ } |
@@ -1,68 +0,71 @@ | ||
describe('Scoped CSS', function() { | ||
/*eslint-env mocha */ | ||
/*global compiler, expect */ | ||
function render(str, parser) { | ||
describe('Scoped CSS', function () { | ||
function render (str, parser) { | ||
return compiler.style(str, 'my-tag', parser || 'scoped-css') | ||
} | ||
it('add my-tag to the simple selector', function() { | ||
it('add my-tag to the simple selector', function () { | ||
expect(render('h1 { font-size: 150% }')) | ||
.to.equal('my-tag h1,[riot-tag="my-tag"] h1 { font-size: 150% }') | ||
}) | ||
it('add my-tag to the multi selector in a line', function() { | ||
it('add my-tag to the multi selector in a line', function () { | ||
expect(render('h1 { font-size: 150% } #id { color: #f00 }')) | ||
.to.equal('my-tag h1,[riot-tag="my-tag"] h1 { font-size: 150% } my-tag #id,[riot-tag="my-tag"] #id { color: #f00 }') | ||
}) | ||
it('add my-tag to the complex selector', function() { | ||
it('add my-tag to the complex selector', function () { | ||
expect(render('header a.button:hover { text-decoration: none }')) | ||
.to.equal('my-tag header a.button:hover,[riot-tag="my-tag"] header a.button:hover { text-decoration: none }') | ||
}) | ||
it('add my-tag to the comma-separated selector', function() { | ||
it('add my-tag to the comma-separated selector', function () { | ||
expect(render('h2, h3 { border-bottom: 1px solid #000 }')) | ||
.to.equal('my-tag h2,[riot-tag="my-tag"] h2,my-tag h3,[riot-tag="my-tag"] h3 { border-bottom: 1px solid #000 }') | ||
}) | ||
it('add my-tag to the attribute selector', function() { | ||
it('add my-tag to the attribute selector', function () { | ||
expect(render('i[class=twitter] { background: #55ACEE }')) | ||
.to.equal('my-tag i[class=twitter],[riot-tag="my-tag"] i[class=twitter] { background: #55ACEE }') | ||
}) | ||
it('add my-tag to the selector with a pseudo-class', function() { | ||
it('add my-tag to the selector with a pseudo-class', function () { | ||
expect(render('a:after { content: "*" }')) | ||
.to.equal('my-tag a:after,[riot-tag="my-tag"] a:after { content: "*" }') | ||
}) | ||
it('add my-tag to the selector with multi-line definitions', function() { | ||
it('add my-tag to the selector with multi-line definitions', function () { | ||
expect(render('header {\n text-align: center;\n background: rgba(0,0,0,.2);\n}')) | ||
.to.equal('my-tag header,[riot-tag="my-tag"] header { text-align: center; background: rgba(0,0,0,.2); }') | ||
}) | ||
it('add my-tag to the root selector', function() { | ||
it('add my-tag to the root selector', function () { | ||
expect(render(':scope { display: block }')) | ||
.to.equal('my-tag,[riot-tag="my-tag"] { display: block }') | ||
}) | ||
it('add my-tag to the nested root selector', function() { | ||
it('add my-tag to the nested root selector', function () { | ||
expect(render(':scope > ul { padding: 0 }')) | ||
.to.equal('my-tag > ul,[riot-tag="my-tag"] > ul { padding: 0 }') | ||
}) | ||
it('add my-tag to the root selector with attribute', function() { | ||
it('add my-tag to the root selector with attribute', function () { | ||
expect(render(':scope[disabled] { color: gray }')) | ||
.to.equal('my-tag[disabled],[riot-tag="my-tag"][disabled] { color: gray }') | ||
}) | ||
it('add my-tag to the root selector with class', function() { | ||
it('add my-tag to the root selector with class', function () { | ||
expect(render(':scope.great { color: gray }')) | ||
.to.equal('my-tag.great,[riot-tag="my-tag"].great { color: gray }') | ||
}) | ||
it('not add my-tag to @font-face', function() { | ||
it('not add my-tag to @font-face', function () { | ||
expect(render('@font-face { font-family: "FontAwesome" }')) | ||
.to.equal('@font-face { font-family: "FontAwesome" }') | ||
}) | ||
it('not add my-tag to @media, and add it to the selector inside', function() { | ||
it('not add my-tag to @media, and add it to the selector inside', function () { | ||
expect(render('@media (min-width: 500px) {\n header {\n text-align: left;\n }\n}')) | ||
.to.equal('@media (min-width: 500px) { my-tag header,[riot-tag="my-tag"] header { text-align: left; } }') | ||
}) | ||
it('not add my-tag to "from" and "to" in @keyframes', function() { | ||
it('not add my-tag to "from" and "to" in @keyframes', function () { | ||
expect(render('@keyframes fade { from { opacity: 1; } to { opacity: 0; } }')) | ||
.to.equal('@keyframes fade { from { opacity: 1; } to { opacity: 0; } }') | ||
}) | ||
it('not add my-tag to parcentage values in @keyframes', function() { | ||
it('not add my-tag to parcentage values in @keyframes', function () { | ||
expect(render('@keyframes fade { 10% { opacity: 1; } 85% { opacity: 0; } }')) | ||
.to.equal('@keyframes fade { 10% { opacity: 1; } 85% { opacity: 0; } }') | ||
}) | ||
it('compile empty style', function() { | ||
it('compile empty style', function () { | ||
expect(render('h1 {} h2 { font-size: 130% }')) | ||
@@ -72,4 +75,4 @@ .to.equal('my-tag h1,[riot-tag="my-tag"] h1 {} my-tag h2,[riot-tag="my-tag"] h2 { font-size: 130% }') | ||
it('use a custom css parser to render the css', function() { | ||
compiler.parsers.css.myParser = function(tag, css) { | ||
it('use a custom css parser to render the css', function () { | ||
compiler.parsers.css.myParser = function (tag, css) { | ||
return css.replace(/@tag/, tag) | ||
@@ -76,0 +79,0 @@ } |
@@ -0,5 +1,8 @@ | ||
/*eslint-env mocha */ | ||
/*global compiler, expect */ | ||
var fs = require('fs'), | ||
path = require('path') | ||
describe('Compile tags', function() { | ||
describe('Compile tags', function () { | ||
// in Windows __dirname is the real path, path.relative uses symlink | ||
@@ -13,19 +16,19 @@ var | ||
// css | ||
compiler.parsers.css.myparser = function(tag, css) { | ||
compiler.parsers.css.myparser = function (tag, css) { | ||
return css.replace(/@tag/, tag) | ||
} | ||
// js | ||
compiler.parsers.js.myparser = function(js) { | ||
compiler.parsers.js.myparser = function (js) { | ||
return js.replace(/@version/, '1.0.0') | ||
} | ||
function render(str, name) { | ||
function render (str, name) { | ||
return compiler.compile(str, { debug: true }, path.join(fixtures, name)) | ||
} | ||
function cat(dir, filename) { | ||
function cat (dir, filename) { | ||
return fs.readFileSync(path.join(dir, filename)).toString() | ||
} | ||
function testFile(name, save) { | ||
function testFile (name, save) { | ||
var src = cat(fixtures, name + '.tag'), | ||
@@ -41,27 +44,27 @@ js = render(src, name + '.tag') | ||
it('Timetable tag', function() { | ||
it('Timetable tag', function () { | ||
testFile('timetable') | ||
}) | ||
it('Mixing JavaScript and custom tags', function() { | ||
it('Mixing JavaScript and custom tags', function () { | ||
testFile('mixed-js') | ||
}) | ||
it('Tag definition and usage on same file', function() { | ||
it('Tag definition and usage on same file', function () { | ||
testFile('same') | ||
}) | ||
it('Scoped CSS', function() { | ||
it('Scoped CSS', function () { | ||
testFile('scoped') | ||
}) | ||
it('Quotes before ending HTML bracket', function() { | ||
it('Quotes before ending HTML bracket', function () { | ||
testFile('input-last') | ||
}) | ||
it('Preserves the object inside the tags', function() { | ||
it('Preserves the object inside the tags', function () { | ||
testFile('box') | ||
}) | ||
it('Flexible method style (v2.3)', function() { | ||
it('Flexible method style (v2.3)', function () { | ||
testFile('free-style') | ||
@@ -78,3 +81,3 @@ }) | ||
it('Included files (v2.3.1)', function() { | ||
it('Included files (v2.3.1)', function () { | ||
testFile('includes') | ||
@@ -100,6 +103,7 @@ }) | ||
var | ||
src = cat(fixtures, 'script-options.tag'), | ||
js = compiler.compile(src, { parser: testOpts }) | ||
src = cat(fixtures, 'script-options.tag') | ||
function testOpts(src, opts) { | ||
compiler.compile(src, { parser: testOpts }) | ||
function testOpts (src, opts) { | ||
expect(opts).to.eql({ val: true }) | ||
@@ -126,3 +130,3 @@ } | ||
it('Whitespace is compacted in other parts', function() { | ||
it('Whitespace is compacted in other parts', function () { | ||
testFile('whitespace') | ||
@@ -151,3 +155,3 @@ }) | ||
resarr = [ | ||
[ 'treeview', | ||
['treeview', | ||
/^<ul id="treeview"> <li> <treeitem data="\{treedata}">/, | ||
@@ -157,3 +161,3 @@ '', '', | ||
], | ||
[ 'treeitem', | ||
['treeitem', | ||
/^<div class="\{bold: isFolder\(\)}" onclick="\{toggle}"/, | ||
@@ -228,2 +232,10 @@ '', '', | ||
it('Script and Style blocks inside strings must be skipped #1448', function () { | ||
testFile('quoted-tags') | ||
}) | ||
it('Html comments are removed anywhere, except inside JS strings', function () { | ||
testFile('html-comments') | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
188796
142
4177
7