Comparing version 1.0.0-3 to 1.0.0-4
module.exports = { | ||
rules: { | ||
indent: [ | ||
2, 2 | ||
"error", 2 | ||
], | ||
quotes: [ | ||
2, | ||
"error", | ||
"single", | ||
@@ -12,10 +12,12 @@ "avoid-escape" | ||
"linebreak-style": [ | ||
2, | ||
"error", | ||
"unix" | ||
], | ||
semi: [ | ||
2, | ||
"error", | ||
"never" | ||
], | ||
"no-trailing-spaces": [2] | ||
"no-trailing-spaces": "error", | ||
"comma-dangle": "error", | ||
"no-native-reassign": "error" | ||
}, | ||
@@ -22,0 +24,0 @@ parserOptions: { |
define(function () { 'use strict'; | ||
var emptyArray = []; | ||
var emptyObject = {}; | ||
var type = emptyObject.toString; | ||
var ARRAY = type.call(emptyArray); | ||
var OBJECT = type.call(emptyObject); | ||
var STRING = type.call(''); | ||
var FUNCTION = type.call(type); | ||
var own = emptyObject.hasOwnProperty; | ||
var freeze = Object.freeze || function(o) {return o}; | ||
function Default(target, source) { | ||
for (var k in source) if (own.call(source, k)) { | ||
if (k.indexOf('$') && !(k in target)) target[k] = source[k] | ||
} | ||
return target | ||
} | ||
var emptyArray = []; | ||
var emptyObject = {}; | ||
var type = emptyObject.toString; | ||
var ARRAY = type.call(emptyArray); | ||
var OBJECT = type.call(emptyObject); | ||
var STRING = type.call(''); | ||
var FUNCTION = type.call(type); | ||
var own = emptyObject.hasOwnProperty; | ||
var freeze = Object.freeze || function(o) {return o}; | ||
function cartesian(a,b) { | ||
var res = [], i, j | ||
for (j in b) if(own.call(b, j)) | ||
for (i in a) if(own.call(a, i)) | ||
res.push(a[i] + b[j]) | ||
return res | ||
function defaults(target, source) { | ||
for (var k in source) if (own.call(source, k)) { | ||
if (k.indexOf('$') && !(k in target)) target[k] = source[k]; | ||
} | ||
return target | ||
} | ||
// "Tokenizes" the selectors into parts relevant for the next function. | ||
// Strings and comments are matched, but ignored afterwards. | ||
// This is not a full tokenizers. It only recognizes comas, parentheses, | ||
// strings and comments. | ||
// regexp generated by scripts/regexps.js then trimmed by hand | ||
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
function cartesian(a,b) { | ||
var res = [], i, j; | ||
for (j in b) if(own.call(b, j)) | ||
for (i in a) if(own.call(a, i)) | ||
res.push(a[i] + b[j]); | ||
return res | ||
} | ||
// "Tokenizes" the selectors into parts relevant for the next function. | ||
// Strings and comments are matched, but ignored afterwards. | ||
// This is not a full tokenizers. It only recognizes comas, parentheses, | ||
// strings and comments. | ||
// regexp generated by scripts/regexps.js then trimmed by hand | ||
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; | ||
/** | ||
* This will split a coma-separated selector list into individual selectors, | ||
* ignoring comas in strings, comments and in :pseudo-selectors(parameter, lists). | ||
* @param {string} selector | ||
* @return {string[]} | ||
*/ | ||
function splitSelector(selector) { | ||
var indices = [], res = [], inParen = 0, o | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = selectorTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
switch (o[0]) { | ||
case '(': inParen++; break | ||
case ')': inParen--; break | ||
case ',': if (inParen) break; indices.push(o.index) | ||
} | ||
/** | ||
* This will split a coma-separated selector list into individual selectors, | ||
* ignoring comas in strings, comments and in :pseudo-selectors(parameter, lists). | ||
* | ||
* @param {string} selector | ||
* @return {string[]} | ||
*/ | ||
function splitSelector(selector) { | ||
var indices = [], res = [], inParen = 0, o; | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = selectorTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
switch (o[0]) { | ||
case '(': inParen++; break | ||
case ')': inParen--; break | ||
case ',': if (inParen) break; indices.push(o.index); | ||
} | ||
for (o = indices.length; o--;){ | ||
res.unshift(selector.slice(indices[o] + 1)) | ||
selector = selector.slice(0, indices[o]) | ||
} | ||
res.unshift(selector) | ||
return res | ||
} | ||
for (o = indices.length; o--;){ | ||
res.unshift(selector.slice(indices[o] + 1)); | ||
selector = selector.slice(0, indices[o]); | ||
} | ||
res.unshift(selector); | ||
return res | ||
} | ||
// This is like the `selectorTokenizer`, but for the `&` operator | ||
// Like the `selectorTokenizer`, but for the `&` operator | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
function ampersand (selector, parents) { | ||
var indices = [], split = [], res, o | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = ampersandTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
if (o[0] == '&') indices.push(o.index) | ||
} | ||
for (o = indices.length; o--;){ | ||
split.unshift(selector.slice(indices[o] + 1)) | ||
selector = selector.slice(0, indices[o]) | ||
} | ||
split.unshift(selector) | ||
res = [split[0]] | ||
for (o = 1; o < split.length; o++) { | ||
res = cartesian(res, cartesian(parents, [split[o]])) | ||
} | ||
return res.join(',') | ||
function ampersand (selector, parents) { | ||
var indices = [], split = [], res, o; | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = ampersandTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
if (o[0] == '&') indices.push(o.index); | ||
} | ||
function flatIter (f) { | ||
return function iter(arg) { | ||
if (type.call(arg) === ARRAY) for (var i= 0 ; i < arg.length; i ++) iter(arg[i]) | ||
else f(arg) | ||
} | ||
for (o = indices.length; o--;){ | ||
split.unshift(selector.slice(indices[o] + 1)); | ||
selector = selector.slice(0, indices[o]); | ||
} | ||
split.unshift(selector); | ||
if (split.length === 1) split.unshift(''); | ||
res = [split[0]]; | ||
for (o = 1; o < split.length; o++) { | ||
res = cartesian(res, cartesian(parents, [split[o]])); | ||
} | ||
return res.join(',') | ||
} | ||
function decamelize(match) { | ||
return '-' + match.toLowerCase() | ||
function flatIter (f) { | ||
return function iter(arg) { | ||
if (type.call(arg) === ARRAY) for (var i= 0 ; i < arg.length; i ++) iter(arg[i]); | ||
else f(arg); | ||
} | ||
} | ||
/** | ||
* Handles the property:value; pairs. | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {string} prefix - the current property or a prefix in case of nested | ||
* sub-properties. | ||
* @param {array|object|string} o - the declarations. | ||
* @param {boolean} local - are we in @local or in @global scope. | ||
*/ | ||
function decamelize(match) { | ||
return '-' + match.toLowerCase() | ||
} | ||
function declarations(state, emit, prefix, o, local) { | ||
var k, v, kk | ||
if (o==null) return | ||
/** | ||
* Handles the property:value; pairs. | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {string} prefix - the current property or a prefix in case of nested | ||
* sub-properties. | ||
* @param {array|object|string} o - the declarations. | ||
* @param {boolean} local - are we in @local or in @global scope. | ||
*/ | ||
switch ( type.call(o = o.valueOf()) ) { | ||
case ARRAY: | ||
for (k = 0; k < o.length; k++) | ||
function declarations(state, emit, prefix, o, local) { | ||
var k, v, kk; | ||
if (o==null) return | ||
declarations(state, emit, prefix, o[k], local) | ||
switch ( type.call(o = o.valueOf()) ) { | ||
case ARRAY: | ||
for (k = 0; k < o.length; k++) | ||
break | ||
case OBJECT: | ||
// prefix is falsy iif it is the empty string, which means we're at the root | ||
// of the declarations list. | ||
prefix = (prefix && prefix + '-') | ||
for (k in o) if (own.call(o, k)){ | ||
v = o[k] | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
declarations(state, emit, prefix, o[k], local); | ||
declarations(state, emit, prefix + k[kk], v, local) | ||
break | ||
case OBJECT: | ||
// prefix is falsy iif it is the empty string, which means we're at the root | ||
// of the declarations list. | ||
prefix = (prefix && prefix + '-'); | ||
for (k in o) if (own.call(o, k)){ | ||
v = o[k]; | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
} | ||
} else { | ||
declarations(state, emit, prefix + k[kk], v, local); | ||
declarations(state, emit, prefix + k, v, local) | ||
} | ||
} | ||
break | ||
default: | ||
// prefix is falsy when it is "", which means that we're | ||
// at the top level. | ||
// `o` is then treated as a `property:value` pair, or a | ||
// semi-colon-separated list thereof. | ||
// Otherwise, `prefix` is the property name, and | ||
// `o` is the value. | ||
} else { | ||
// restore the dashes | ||
k = prefix.replace(/_/g, '-').replace(/[A-Z]/g, decamelize) | ||
declarations(state, emit, prefix + k, v, local); | ||
if (local && (k == 'animation-name' || k == 'animation' || k == 'list-style')) { | ||
// no need to tokenize here a plain `.split(',')` has all bases covered. | ||
// We may 'localize' a comment, but it's not a big deal. | ||
o = o.split(',').map(function (o) { | ||
} | ||
} | ||
break | ||
default: | ||
// prefix is falsy when it is "", which means that we're | ||
// at the top level. | ||
// `o` is then treated as a `property:value` pair, or a | ||
// semi-colon-separated list thereof. | ||
// Otherwise, `prefix` is the property name, and | ||
// `o` is the value. | ||
return o.replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, state.L) | ||
// restore the dashes | ||
k = prefix.replace(/_/g, '-').replace(/[A-Z]/g, decamelize); | ||
}).join(',') | ||
} | ||
if (local && (k == 'animation-name' || k == 'animation' || k == 'list-style')) { | ||
// no need to tokenize here a plain `.split(',')` has all bases covered. | ||
// We may 'localize' a comment, but it's not a big deal. | ||
o = o.split(',').map(function (o) { | ||
emit.d(k, o) | ||
return o.replace(/^\s*(?:(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*))/, state.localizeReplacer) | ||
}).join(','); | ||
} | ||
} | ||
/** | ||
* Hanldes at-rules | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {array} k - The parsed at-rule, including the parameters, | ||
* if takes both parameters and a block. | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* @param {string|string[]|object|object[]} v - Either parameters for | ||
* block-less rules or | ||
* their block | ||
* for the others. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
emit.decl(k, o); | ||
function atRules(state, emit, k, v, prefix, local, inAtRule) { | ||
} | ||
} | ||
for (var i = 0; i < state.$a.length; i++) { | ||
/** | ||
* Handles a single at-rules | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {array} k - The parsed at-rule, including the parameters, | ||
* if takes both parameters and a block. | ||
* k == [match, fullAtRule, atRuleType, params?] | ||
* So in `@-webkit-keyframes foo`, we have | ||
* - match = "@-webkit-keyframes foo" | ||
* - fullAtRule = "@-webkit-keyframes" | ||
* - atRuleType = "keyframes" | ||
* - params = "foo" | ||
* @param {string|string[]|object|object[]} v - Either parameters for | ||
* block-less rules or | ||
* their block | ||
* for the others. | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
* @param {string} nestingDepth - are we nested in an at-rule or a selector? | ||
*/ | ||
if (state.$a[i](state, emit, k, v, prefix, local, inAtRule)) return | ||
function atRules(state, emit, k, v, prefix, local, nestingDepth) { | ||
} | ||
// First iterate over user-provided at-rules and return if one of them corresponds to the current one | ||
for (var i = 0; i < state.$atHandlers.length; i++) { | ||
// using `/^global$/.test(k[2])` rather that 'global' == k[2] gzips | ||
// slightly better because of the regexps test further down. | ||
// It is slightly less efficient but this isn't a critical path. | ||
if (state.$atHandlers[i](state, emit, k, v, prefix, local, nestingDepth)) return | ||
if (!k[3] && /^global$/.test(k[2])) { | ||
} | ||
rules(state, emit, prefix, v, 0, inAtRule) | ||
// using `/^global$/.test(k[2])` rather that 'global' == k[2] gzips | ||
// slightly better thanks to the regexps tests further down. | ||
// It is slightly less efficient but this isn't a critical path. | ||
if (!k[3] && /^global$/.test(k[2])) { | ||
} else if (!k[3] && /^local$/.test(k[2])) { | ||
rules(state, emit, prefix, v, 0, nestingDepth); | ||
rules(state, emit, prefix, v, 1, inAtRule) | ||
} else if (!k[3] && /^local$/.test(k[2])) { | ||
} else if (k[3] && /^adopt$/.test(k[2])) { | ||
rules(state, emit, prefix, v, 1, nestingDepth); | ||
if (!local || inAtRule) return emit.a('@-error-bad-at-adopt-placement' , JSON.stringify(k[0]), 0) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.a('@-error-bad-at-adopter', k[3], 0) | ||
} else if (k[3] && /^adopt$/.test(k[2])) { | ||
i = [] | ||
flatIter(function(adoptee, asString) { | ||
if (!local || nestingDepth) return emit.err('@adopt global or nested: ' + k[0]) | ||
if(!/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee.toString())) emit.a('@-error-bad-at-adoptee', JSON.stringify(adoptee), 0) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.err('bad adopter ' + JSON.stringify(k[3]) + ' in ' + k[0]) | ||
else i.push(asString.replace(/\./g, '')) | ||
i = []; | ||
flatIter(function(adoptee, asString) { | ||
})(v) | ||
if(adoptee == null || !/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee + '')) emit.err('bad adoptee '+ JSON.stringify(adoptee) + ' in ' + k[0]); | ||
// we may end up with duplicate classes but AFAIK it has no consequences on specificity. | ||
if (i.length) { | ||
state.l(k[3] = k[3].replace(/\./g, '')) | ||
state.n[k[3]] += (' ' + i.join(' ')) | ||
} | ||
else i.push(asString.replace(/\./g, '')); | ||
})(v); | ||
} else if (!k[3] && /^(?:namespace|import|charset)$/.test(k[2])) { | ||
flatIter(function(v) { | ||
// we may end up with duplicate classes but AFAIK it has no consequences on specificity. | ||
if (i.length) { | ||
state.localize(k[3] = k[3].replace(/\./g, '')); | ||
state.names[k[3]] += (' ' + i.join(' ')); | ||
} | ||
emit.a(k[0], v) | ||
})(v) | ||
} else if (!k[3] && /^(?:namespace|import|charset)$/.test(k[2])) { | ||
flatIter(function(v) { | ||
emit.atrule(k[1], k[2], v); | ||
} else if (!k[3] && /^(?:font-face|viewport)$/.test(k[2])) { | ||
flatIter(function(v) { | ||
})(v); | ||
emit.a(k[1], '', 1) | ||
declarations(state, emit, '', v, local) | ||
} else if (!k[3] && /^(?:font-face|viewport)$/.test(k[2])) { | ||
flatIter(function(v) { | ||
emit.A(k[1], '') | ||
emit.atrule(k[1], k[2], k[3], 1); | ||
})(v) | ||
declarations(state, emit, '', v, local); | ||
} else if (k[3] && /^(?:media|supports|page|keyframes)$/.test(k[2])) { | ||
emit._atrule(); | ||
if (local && 'keyframes' == k[2]) { | ||
k[3] = k[3].replace( | ||
// generated by script/regexps.js | ||
/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, | ||
state.L | ||
) | ||
} | ||
})(v); | ||
} else if (k[3] && /^(?:media|supports|page|keyframes)$/.test(k[2])) { | ||
emit.a(k[1], k[3], 1) | ||
if (local && 'keyframes' == k[2]) { | ||
k[3] = k[3].replace( | ||
// generated by script/regexps.js | ||
/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, | ||
state.localizeReplacer | ||
); | ||
} | ||
if ('page' == k[2]) { | ||
declarations(state, emit, '', v, local) | ||
emit.atrule(k[1], k[2], k[3], 1); | ||
} else { | ||
if ('page' == k[2]) { | ||
rules( | ||
state, emit, | ||
'keyframes' == k[2] ? '' : prefix, | ||
v, local, 1 | ||
) | ||
declarations(state, emit, '', v, local); | ||
} | ||
emit.A(k[1], k[3]) | ||
} else { | ||
emit.a('@-error-unsupported-at-rule', JSON.stringify(k[0])) | ||
rules( | ||
state, emit, | ||
'keyframes' == k[2] ? '' : prefix, | ||
v, local, nestingDepth + 1 | ||
); | ||
} | ||
} | ||
/** | ||
* Add rulesets and other CSS tree to the sheet. | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {string} prefix - the current selector or a prefix in case of nested rules | ||
* @param {array|string|object} tree - a source object or sub-object. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
function rules(state, emit, prefix, tree, local, inAtRule) { | ||
var k, v, inDeclaration, kk | ||
emit._atrule(); | ||
switch (type.call(tree)) { | ||
} else { | ||
case OBJECT: | ||
for (k in tree) if (own.call(tree, k)) { | ||
v = tree[k] | ||
emit.err('Unsupported at-rule: ' + k[0]); | ||
if (prefix.length > 0 && /^[-\w$]+$/.test(k)) { | ||
if (!inDeclaration) { | ||
inDeclaration = 1 | ||
} | ||
} | ||
emit.s(prefix) | ||
/** | ||
* Add rulesets and other CSS tree to the sheet. | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {string} prefix - the current selector or a prefix in case of nested rules | ||
* @param {array|string|object} tree - a source object or sub-object. | ||
* @param {string} nestingDepth - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
function rules(state, emit, prefix, tree, local, nestingDepth) { | ||
var k, v, inDeclaration, kk; | ||
} | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
switch (type.call(tree)) { | ||
declarations(state, emit, k[kk], v, local) | ||
case OBJECT: | ||
for (k in tree) if (own.call(tree, k)) { | ||
v = tree[k]; | ||
} | ||
} else { | ||
if (prefix.length > 0 && /^[-\w$]+$/.test(k)) { | ||
if (!inDeclaration) { | ||
inDeclaration = 1; | ||
declarations(state, emit, k, v, local) | ||
emit.rule(prefix); | ||
} | ||
} | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
} else if (/^@/.test(k)) { | ||
// Handle At-rules | ||
inDeclaration = 0 | ||
declarations(state, emit, k[kk], v, local); | ||
atRules(state, emit, | ||
/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(k) || [k,'@','',''], | ||
v, prefix, local, inAtRule | ||
) | ||
} | ||
} else { | ||
// selector or nested sub-selectors | ||
inDeclaration = 0 | ||
rules( | ||
state, emit, | ||
// `prefix` ... Hefty. Ugly. Sadly necessary. | ||
// | ||
(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
declarations(state, emit, k, v, local); | ||
/*0*/ (kk = splitSelector(prefix), splitSelector( | ||
local ? | ||
} | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
) : | ||
} else if (/^@/.test(k)) { | ||
// Handle At-rules | ||
inDeclaration = 0; | ||
k | ||
).map(function (k) { | ||
return /&/.test(k) ? ampersand(k, kk) : kk.map(function(kk) { | ||
return kk + k | ||
}).join(',') | ||
}).join(',')) : | ||
atRules(state, emit, | ||
/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(k) || [k,'@','',''], | ||
v, prefix, local, nestingDepth | ||
); | ||
/*0*/ /&/.test(k) ? | ||
} else { | ||
// selector or nested sub-selectors | ||
inDeclaration = 0; | ||
/*1*/ ampersand( | ||
local ? | ||
rules( | ||
state, emit, | ||
// build the selector `prefix` for the next iteration. | ||
// ugly and full of redundant bits but so far the fastest/shortest.gz | ||
/*0 if*/(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
) : | ||
/*0 then*/ (kk = splitSelector(prefix), splitSelector( | ||
local ? | ||
k, | ||
[prefix] | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.localizeReplacer | ||
) : | ||
/*1*/ prefix + ( | ||
local ? | ||
k | ||
).map(function (k) { | ||
return /&/.test(k) ? ampersand(k, kk) : kk.map(function(kk) { | ||
return kk + k | ||
}).join(',') | ||
}).join(',')) : | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
) : | ||
/*0 else*/ /*1 if*/ /&/.test(k) ? | ||
k | ||
), | ||
v, local, inAtRule | ||
) | ||
/*1 then*/ ampersand( | ||
local ? | ||
} | ||
} | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.localizeReplacer | ||
) : | ||
break | ||
k, | ||
[prefix] | ||
) : | ||
case ARRAY: | ||
for (k = 0; k < tree.length; k++){ | ||
/*1 else*/ prefix + ( | ||
local ? | ||
rules(state, emit, prefix, tree[k], local, inAtRule) | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.localizeReplacer | ||
) : | ||
k | ||
), | ||
v, local, nestingDepth + 1 | ||
); | ||
} | ||
break | ||
} | ||
case STRING: | ||
// CSS hacks or ouptut of `j2c.inline`. | ||
break | ||
emit.s(prefix.length > 0 ? prefix : ':-error-no-selector') | ||
case ARRAY: | ||
for (k = 0; k < tree.length; k++){ | ||
declarations(state, emit, '', tree, local) | ||
rules(state, emit, prefix, tree[k], local, nestingDepth); | ||
} | ||
} | ||
break | ||
// This is the first entry in the filters array, which is | ||
// actually the last step of the compiler. It inserts | ||
// closing braces to close normal (non at-) rules (those | ||
// that start with a selector). Doing it earlier is | ||
// impossible without passing state around in unrelated code | ||
// or ending up with duplicated selectors when the source tree | ||
// contains arrays. | ||
// There's no `S` handler, because the core compiler never | ||
// calls it. | ||
function closeSelectors(next, inline) { | ||
var lastSelector | ||
return inline ? next : { | ||
i: function(){lastSelector = 0; next.i()}, | ||
x: function (raw) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
return next.x(raw) | ||
}, | ||
a: function (rule, param, takesBlock) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.a(rule, param, takesBlock) | ||
}, | ||
A: function (rule) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.A(rule) | ||
}, | ||
s: function (selector) { | ||
if (selector !== lastSelector){ | ||
if (lastSelector) next.S() | ||
next.s(selector) | ||
lastSelector = selector | ||
} | ||
}, | ||
d: next.d | ||
} | ||
} | ||
case STRING: | ||
// CSS hacks or ouptut of `j2c.inline`. | ||
if (!prefix.length) emit.err('No selector'); | ||
emit.rule(prefix || ' '); | ||
function global(x) { | ||
return ':global(' + x + ')' | ||
} | ||
declarations(state, emit, '', tree, local); | ||
function kv (k, v, o) { | ||
o = {} | ||
o[k] = v | ||
return o | ||
} | ||
} | ||
function at (rule, params, block) { | ||
if ( | ||
arguments.length < 3 | ||
) { | ||
// inner curry! | ||
var _at = at.bind.apply(at, [null].concat([].slice.call(arguments,0))) | ||
// So that it can be used as a key in an ES6 object literal. | ||
_at.toString = function(){return '@' + rule + ' ' + params} | ||
return _at | ||
// This is the first entry in the filters array, which is | ||
// actually the last step of the compiler. It inserts | ||
// closing braces to close normal (non at-) rules (those | ||
// that start with a selector). Doing it earlier is | ||
// impossible without passing state around in unrelated code | ||
// or ending up with duplicated selectors when the source tree | ||
// contains arrays. | ||
// There's no `_rule` handler, because the core compiler never | ||
// calls it. | ||
function closeSelectors(next, inline) { | ||
var lastSelector; | ||
return inline ? next : { | ||
init: function(){lastSelector = 0; next.init();}, | ||
done: function (raw) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
return next.done(raw) | ||
}, | ||
atrule: function (rule, kind, param, takesBlock) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
next.atrule(rule, kind, param, takesBlock); | ||
}, | ||
_atrule: function (rule) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
next._atrule(rule); | ||
}, | ||
rule: function (selector) { | ||
if (selector !== lastSelector){ | ||
if (lastSelector) next._rule(); | ||
next.rule(selector); | ||
lastSelector = selector; | ||
} | ||
} | ||
else return kv('@' + rule +' ' + params, block) | ||
} | ||
} | ||
function j2c() { | ||
function global(x) { | ||
return ':global(' + x + ')' | ||
} | ||
// palceholder for the buffer used by the `$sink` handlers | ||
var buf | ||
function kv (k, v, o) { | ||
o = {}; | ||
o[k] = v; | ||
return o | ||
} | ||
// the bottom of the 'codegen' stream. Mirrors the `$filter` plugin API. | ||
var $sink = { | ||
// Init | ||
i: function(){buf=[]}, | ||
// done (eXit) | ||
x: function (raw) {return raw ? buf : buf.join('')}, | ||
// start At-rule | ||
a: function (rule, argument, takesBlock) { | ||
buf.push(rule, argument && ' ',argument, takesBlock ? ' {\n' : ';\n') | ||
}, | ||
// end At-rule | ||
A: function () {buf.push('}\n')}, | ||
// start Selector | ||
s: function (selector) {buf.push(selector, ' {\n')}, | ||
// end Selector | ||
S: function () {buf.push('}\n')}, | ||
// declarations | ||
d: function (prop, value) {buf.push(prop, prop && ':', value, ';\n')} | ||
} | ||
function at (rule, params, block) { | ||
if ( | ||
arguments.length < 3 | ||
) { | ||
// inner curry! | ||
var _at = at.bind.apply(at, [null].concat([].slice.call(arguments,0))); | ||
// So that it can be used as a key in an ES6 object literal. | ||
_at.toString = function(){return '@' + rule + ' ' + params}; | ||
return _at | ||
} | ||
else return kv('@' + rule +' ' + params, block) | ||
} | ||
var $filters = [closeSelectors] | ||
var $atHandlers = [] | ||
function j2c() { | ||
var _instance = { | ||
at: at, | ||
global: global, | ||
kv: kv, | ||
names: {}, | ||
suffix: '__j2c-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36), | ||
use: function() { | ||
_use(emptyArray.slice.call(arguments)) | ||
return _instance | ||
}, | ||
$plugins: [] | ||
} | ||
// the buffer that accumulates the output. Initialized in `$sink.i()` | ||
var buf, err; | ||
var _streams = [] | ||
// the bottom of the 'codegen' stream. Mirrors the `$filter` plugin API. | ||
var $sink = { | ||
init: function(){buf=[], err=[];}, | ||
done: function (raw) { | ||
if (err.length != 0) throw new Error('j2c error(s): ' + JSON.stringify(err,null,2) + 'in context:\n' + buf.join('')) | ||
return raw ? buf : buf.join('') | ||
}, | ||
err: function(msg) { | ||
err.push(msg); | ||
buf.push('/* +++ ERROR +++ ' + msg + ' */\n'); | ||
}, | ||
atrule: function (rule, kind, param, takesBlock) { | ||
buf.push(rule, param && ' ', param, takesBlock ? ' {' : ';', _instance.endline); | ||
}, | ||
// close atrule | ||
_atrule: function () {buf.push('}', _instance.endline);}, | ||
rule: function (selector) {buf.push(selector, ' {', _instance.endline);}, | ||
// close rule | ||
_rule: function () {buf.push('}', _instance.endline);}, | ||
decl: function (prop, value) {buf.push(prop, prop && ':', value, ';', _instance.endline);} | ||
}; | ||
// The `state` (for the core) / `walker` (for the plugins) tables. | ||
// holds the `$filter` and `$at` handlers | ||
var $filters = [closeSelectors]; | ||
var $atHandlers = []; | ||
var _walkers = [ | ||
// for j2c.sheet | ||
{ | ||
// helpers for locaizing class and animation names | ||
L: _localizeReplacer, // second argument to String.prototype.replace | ||
l: _localize, // mangles local names | ||
n: _instance.names, // local => mangled mapping | ||
$a: $atHandlers, // extra at-rules | ||
// The core walker methods, to be provided to plugins | ||
a: atRules, | ||
d: declarations, | ||
r: rules | ||
}, | ||
// likewise, for j2c.inline (idem with `$a`, `a` and `s` removed) | ||
{ | ||
L: _localizeReplacer, | ||
l: _localize, | ||
n: _instance.names, | ||
d: declarations | ||
} | ||
] | ||
// The main API functions | ||
_instance.sheet = function(tree) { | ||
var emit = _getStream(0) | ||
emit.i() | ||
// the public API (see the main docs) | ||
var _instance = { | ||
at: at, | ||
global: global, | ||
kv: kv, | ||
names: {}, | ||
endline: '\n', | ||
suffix: '__j2c-' + | ||
// 128 bits of randomness | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36), | ||
$plugins: [], | ||
sheet: function(tree) { | ||
var emit = _createOrRetrieveStream(0); | ||
emit.init(); | ||
rules( | ||
_walkers[0], | ||
emit, | ||
'', // prefix | ||
'', // prefix | ||
tree, | ||
1, // local, by default | ||
0 // inAtRule | ||
) | ||
1, // local, by default | ||
0 // nesting depth | ||
); | ||
return emit.x() | ||
} | ||
_instance.inline = function (tree) { | ||
var emit = _getStream(1) | ||
emit.i() | ||
return emit.done() | ||
}, | ||
inline: function (tree, options) { | ||
var emit = _createOrRetrieveStream(1); | ||
emit.init(); | ||
declarations( | ||
_walkers[1], | ||
emit, | ||
'', // prefix | ||
'', // prefix | ||
tree, | ||
1 //local | ||
) | ||
return emit.x() | ||
!(options && options.global) // local, by default | ||
); | ||
return emit.done() | ||
} | ||
}; | ||
// inner helpers | ||
// The `state` (for the core functions) / `walker` (for the plugins) tables. | ||
var _walkers = [ | ||
// for j2c.sheet | ||
{ | ||
// helpers for locaizing class and animation names | ||
localizeReplacer: _localizeReplacer, // second argument to String.prototype.replace | ||
localize: _localize, // mangles local names | ||
names: _instance.names, // local => mangled mapping | ||
$atHandlers: $atHandlers, // extra at-rules | ||
// The core walker methods, to be provided to plugins | ||
atrule: atRules, | ||
decl: declarations, | ||
rule: rules | ||
}, | ||
// likewise, for j2c.inline (idem with `$a`, `a` and `s` removed) | ||
{ | ||
localizeReplacer: _localizeReplacer, | ||
localize: _localize, | ||
names: _instance.names, | ||
decl: declarations | ||
} | ||
]; | ||
var _use = flatIter(function(plugin) { | ||
// `~n` is falsy for `n === -1` and truthy otherwise. | ||
// Works well to turn the result of `a.indexOf(x)` | ||
// into a value that reflects the presence of `x` in | ||
// `a`. | ||
if (~_instance.$plugins.indexOf(plugin)) return | ||
_instance.$plugins.push(plugin) | ||
// inner helpers | ||
if (type.call(plugin) === FUNCTION) plugin = plugin(_instance) | ||
var _use = flatIter(function(plugin) { | ||
// `~n` is falsy for `n === -1` and truthy otherwise. | ||
// Works well to turn the result of `a.indexOf(x)` | ||
// into a value that reflects the presence of `x` in | ||
// `a`. | ||
if (~_instance.$plugins.indexOf(plugin)) return | ||
if (!plugin) return | ||
_instance.$plugins.push(plugin); | ||
flatIter(function(filter) { | ||
$filters.push(filter) | ||
})(plugin.$filter || emptyArray) | ||
if (type.call(plugin) === FUNCTION) plugin = plugin(_instance); | ||
flatIter(function(handler) { | ||
$atHandlers.push(handler) | ||
})(plugin.$at || emptyArray) | ||
if (!plugin) return | ||
Default(_instance.names, plugin.$names || emptyObject) | ||
flatIter(function(filter) { | ||
$filters.push(filter); | ||
})(plugin.$filter || emptyArray); | ||
_use(plugin.$plugins || emptyArray) | ||
flatIter(function(handler) { | ||
$atHandlers.push(handler); | ||
})(plugin.$at || emptyArray); | ||
$sink = plugin.$sink || $sink | ||
defaults(_instance.names, plugin.$names || emptyObject); | ||
Default(_instance, plugin) | ||
}) | ||
_use(plugin.$plugins || emptyArray); | ||
function _getStream(inline) { | ||
if (!_streams.length) { | ||
for(var i = 0; i < 2; i++){ | ||
$filters[$filters.length - i] = function(_, inline) {return inline ? {i:$sink.i, d:$sink.d, x:$sink.x} : $sink} | ||
for (var j = $filters.length; j--;) { | ||
_streams[i] = freeze(Default( | ||
$filters[j](_streams[i], !!i, _walkers[i]), | ||
$sink = plugin.$sink || $sink; | ||
defaults(_instance, plugin); | ||
}); | ||
var _streams = []; | ||
/** | ||
* returns the codegen streams, creating them if necessary | ||
* @param | ||
*/ | ||
function _createOrRetrieveStream(inline) { | ||
// build the stream processors if needed | ||
if (!_streams.length) { | ||
// append the $sink as the ultimate filter | ||
$filters.push(function(_, inline) {return inline ? {init:$sink.init, decl:$sink.decl, done:$sink.done, err: $sink.err} : $sink}); | ||
for(var i = 0; i < 2; i++){ // 0 for j2c.sheet, 1 for j2c.inline | ||
for (var j = $filters.length; j--;) { | ||
_streams[i] = freeze( | ||
defaults( | ||
$filters[j](_streams[i], !!i), | ||
_streams[i] | ||
)) | ||
} | ||
) | ||
); | ||
} | ||
} | ||
var res = _streams[inline] | ||
return res | ||
} | ||
return _streams[inline] | ||
} | ||
function _localize(name) { | ||
if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix | ||
return _instance.names[name].match(/^\S+/) | ||
} | ||
/** | ||
* Returns a localized version of a given name. | ||
* Registers the pair in `instnace.name` if needed. | ||
* | ||
* @param {string} name - the name to localize | ||
* @return {string} - the localized version | ||
*/ | ||
function _localize(name) { | ||
if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix; | ||
return _instance.names[name].match(/^\S+/) | ||
} | ||
function _localizeReplacer(match, string, global, dot, name) { | ||
if (string || global) return string || global | ||
return dot + _localize(name) | ||
} | ||
return _instance | ||
/** | ||
* Used as second argument for str.replace(localizeRegex, replacer) | ||
* `ignore`, `global` and `(dot, name)` are mutually exclusive | ||
* | ||
* @param {string} match - the whole match (ignored) | ||
* @param {string|null} ignore - a comment or a string literal | ||
* @param {string|null} global - a global name | ||
* @param {string|null} dot - either '.' for a local class name or the empty string otherwise | ||
* @param {string|null} name - the name to localize | ||
* @return {string} | ||
*/ | ||
function _localizeReplacer(match, ignore, global$$1, dot, name) { | ||
return ignore || global$$1 || dot + _localize(name) | ||
} | ||
var _j2c = j2c() | ||
'sheet|inline|names|at|global|kv|suffix'.split('|').map(function(m){j2c[m] = _j2c[m]}) | ||
_use(emptyArray.slice.call(arguments)); | ||
return _instance | ||
} | ||
return j2c; | ||
return j2c; | ||
}); | ||
}); |
@@ -1,1 +0,1 @@ | ||
define(function(){"use strict";function n(n,t){for(var e in t)S.call(t,e)&&(!e.indexOf("$")||e in n||(n[e]=t[e]));return n}function t(n,t){var e,r,a=[];for(r in t)if(S.call(t,r))for(e in n)S.call(n,e)&&a.push(n[e]+t[r]);return a}function e(n){for(var t,e=[],r=[],a=0;t=x.exec(n);)switch(t[0]){case"(":a++;break;case")":a--;break;case",":if(a)break;e.push(t.index)}for(t=e.length;t--;)r.unshift(n.slice(e[t]+1)),n=n.slice(0,e[t]);return r.unshift(n),r}function r(n,e){for(var r,a,i=[],s=[];a=_.exec(n);)"&"==a[0]&&i.push(a.index);for(a=i.length;a--;)s.unshift(n.slice(i[a]+1)),n=n.slice(0,i[a]);for(s.unshift(n),r=[s[0]],a=1;a<s.length;a++)r=t(r,t(e,[s[a]]));return r.join(",")}function a(n){return function t(e){if(d.call(e)===$)for(var r=0;r<e.length;r++)t(e[r]);else n(e)}}function i(n){return"-"+n.toLowerCase()}function s(n,t,e,r,a){var o,l,u;if(null!=r)switch(d.call(r=r.valueOf())){case $:for(o=0;o<r.length;o++)s(n,t,e,r[o],a);break;case v:e=e&&e+"-";for(o in r)if(S.call(r,o))if(l=r[o],/\$/.test(o))for(u in o=o.split("$"))S.call(o,u)&&s(n,t,e+o[u],l,a);else s(n,t,e+o,l,a);break;default:o=e.replace(/_/g,"-").replace(/[A-Z]/g,i),!a||"animation-name"!=o&&"animation"!=o&&"list-style"!=o||(r=r.split(",").map(function(t){return t.replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,n.L)}).join(",")),t.d(o,r)}}function o(n,t,e,r,i,o,u){for(var f=0;f<n.$a.length;f++)if(n.$a[f](n,t,e,r,i,o,u))return;if(!e[3]&&/^global$/.test(e[2]))l(n,t,i,r,0,u);else if(!e[3]&&/^local$/.test(e[2]))l(n,t,i,r,1,u);else if(e[3]&&/^adopt$/.test(e[2])){if(!o||u)return t.a("@-error-bad-at-adopt-placement",JSON.stringify(e[0]),0);if(!/^\.?[_A-Za-z][-\w]*$/.test(e[3]))return t.a("@-error-bad-at-adopter",e[3],0);f=[],a(function(n,e){/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(e=n.toString())?f.push(e.replace(/\./g,"")):t.a("@-error-bad-at-adoptee",JSON.stringify(n),0)})(r),f.length&&(n.l(e[3]=e[3].replace(/\./g,"")),n.n[e[3]]+=" "+f.join(" "))}else!e[3]&&/^(?:namespace|import|charset)$/.test(e[2])?a(function(n){t.a(e[0],n)})(r):!e[3]&&/^(?:font-face|viewport)$/.test(e[2])?a(function(r){t.a(e[1],"",1),s(n,t,"",r,o),t.A(e[1],"")})(r):e[3]&&/^(?:media|supports|page|keyframes)$/.test(e[2])?(o&&"keyframes"==e[2]&&(e[3]=e[3].replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,n.L)),t.a(e[1],e[3],1),"page"==e[2]?s(n,t,"",r,o):l(n,t,"keyframes"==e[2]?"":i,r,o,1),t.A(e[1],e[3])):t.a("@-error-unsupported-at-rule",JSON.stringify(e[0]))}function l(n,t,a,i,u,f){var c,g,p,h;switch(d.call(i)){case v:for(c in i)if(S.call(i,c))if(g=i[c],a.length>0&&/^[-\w$]+$/.test(c))if(p||(p=1,t.s(a)),/\$/.test(c))for(h in c=c.split("$"))S.call(c,h)&&s(n,t,c[h],g,u);else s(n,t,c,g,u);else/^@/.test(c)?(p=0,o(n,t,/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(c)||[c,"@","",""],g,a,u,f)):(p=0,l(n,t,a.length>0&&(/,/.test(a)||/,/.test(c))?(h=e(a),e(u?c.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,n.L):c).map(function(n){return/&/.test(n)?r(n,h):h.map(function(t){return t+n}).join(",")}).join(",")):/&/.test(c)?r(u?c.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,n.L):c,[a]):a+(u?c.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,n.L):c),g,u,f));break;case $:for(c=0;c<i.length;c++)l(n,t,a,i[c],u,f);break;case b:t.s(a.length>0?a:":-error-no-selector"),s(n,t,"",i,u)}}function u(n,t){var e;return t?n:{i:function(){e=0,n.i()},x:function(t){return e&&(n.S(),e=0),n.x(t)},a:function(t,r,a){e&&(n.S(),e=0),n.a(t,r,a)},A:function(t){e&&(n.S(),e=0),n.A(t)},s:function(t){t!==e&&(e&&n.S(),n.s(t),e=t)},d:n.d}}function f(n){return":global("+n+")"}function c(n,t,e){return e={},e[n]=t,e}function g(n,t,e){if(arguments.length<3){var r=g.bind.apply(g,[null].concat([].slice.call(arguments,0)));return r.toString=function(){return"@"+n+" "+t},r}return c("@"+n+" "+t,e)}function p(){function t(t){if(!S.length)for(var e=0;2>e;e++){$[$.length-e]=function(n,t){return t?{i:p.i,d:p.d,x:p.x}:p};for(var r=$.length;r--;)S[e]=A(n($[r](S[e],!!e,x[e]),S[e]))}var a=S[t];return a}function e(n){return b.names[n]||(b.names[n]=n+b.suffix),b.names[n].match(/^\S+/)}function r(n,t,r,a,i){return t||r?t||r:a+e(i)}var i,p={i:function(){i=[]},x:function(n){return n?i:i.join("")},a:function(n,t,e){i.push(n,t&&" ",t,e?" {\n":";\n")},A:function(){i.push("}\n")},s:function(n){i.push(n," {\n")},S:function(){i.push("}\n")},d:function(n,t){i.push(n,n&&":",t,";\n")}},$=[u],v=[],b={at:g,global:f,kv:c,names:{},suffix:"__j2c-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36),use:function(){return _(h.slice.call(arguments)),b},$plugins:[]},S=[],x=[{L:r,l:e,n:b.names,$a:v,a:o,d:s,r:l},{L:r,l:e,n:b.names,d:s}];b.sheet=function(n){var e=t(0);return e.i(),l(x[0],e,"",n,1,0),e.x()},b.inline=function(n){var e=t(1);return e.i(),s(x[1],e,"",n,1),e.x()};var _=a(function(t){~b.$plugins.indexOf(t)||(b.$plugins.push(t),d.call(t)===w&&(t=t(b)),t&&(a(function(n){$.push(n)})(t.$filter||h),a(function(n){v.push(n)})(t.$at||h),n(b.names,t.$names||m),_(t.$plugins||h),p=t.$sink||p,n(b,t)))});return b}var h=[],m={},d=m.toString,$=d.call(h),v=d.call(m),b=d.call(""),w=d.call(d),S=m.hasOwnProperty,A=Object.freeze||function(n){return n},x=/[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,_=/&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,z=p();return"sheet|inline|names|at|global|kv|suffix".split("|").map(function(n){p[n]=z[n]}),p}); | ||
define(function(){"use strict";function e(e,n){for(var t in n)b.call(n,t)&&(!t.indexOf("$")||t in e||(e[t]=n[t]));return e}function n(e,n){var t,r,l=[];for(r in n)if(b.call(n,r))for(t in e)b.call(e,t)&&l.push(e[t]+n[r]);return l}function t(e){for(var n,t=[],r=[],l=0;n=A.exec(e);)switch(n[0]){case"(":l++;break;case")":l--;break;case",":if(l)break;t.push(n.index)}for(n=t.length;n--;)r.unshift(e.slice(t[n]+1)),e=e.slice(0,t[n]);return r.unshift(e),r}function r(e,t){for(var r,l,a=[],i=[];l=S.exec(e);)"&"==l[0]&&a.push(l.index);for(l=a.length;l--;)i.unshift(e.slice(a[l]+1)),e=e.slice(0,a[l]);for(i.unshift(e),1===i.length&&i.unshift(""),r=[i[0]],l=1;l<i.length;l++)r=n(r,n(t,[i[l]]));return r.join(",")}function l(e){return function n(t){if(m.call(t)===$)for(var r=0;r<t.length;r++)n(t[r]);else e(t)}}function a(e){return"-"+e.toLowerCase()}function i(e,n,t,r,l){var o,u,c;if(null!=r)switch(m.call(r=r.valueOf())){case $:for(o=0;o<r.length;o++)i(e,n,t,r[o],l);break;case _:t=t&&t+"-";for(o in r)if(b.call(r,o))if(u=r[o],/\$/.test(o))for(c in o=o.split("$"))b.call(o,c)&&i(e,n,t+o[c],u,l);else i(e,n,t+o,u,l);break;default:o=t.replace(/_/g,"-").replace(/[A-Z]/g,a),!l||"animation-name"!=o&&"animation"!=o&&"list-style"!=o||(r=r.split(",").map(function(n){return n.replace(/^\s*(?:(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*))/,e.localizeReplacer)}).join(",")),n.decl(o,r)}}function o(e,n,t,r,a,o,c){for(var s=0;s<e.$atHandlers.length;s++)if(e.$atHandlers[s](e,n,t,r,a,o,c))return;if(!t[3]&&/^global$/.test(t[2]))u(e,n,a,r,0,c);else if(!t[3]&&/^local$/.test(t[2]))u(e,n,a,r,1,c);else if(t[3]&&/^adopt$/.test(t[2])){if(!o||c)return n.err("@adopt global or nested: "+t[0]);if(!/^\.?[_A-Za-z][-\w]*$/.test(t[3]))return n.err("bad adopter "+JSON.stringify(t[3])+" in "+t[0]);s=[],l(function(e,r){null!=e&&/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(r=e+"")?s.push(r.replace(/\./g,"")):n.err("bad adoptee "+JSON.stringify(e)+" in "+t[0])})(r),s.length&&(e.localize(t[3]=t[3].replace(/\./g,"")),e.names[t[3]]+=" "+s.join(" "))}else!t[3]&&/^(?:namespace|import|charset)$/.test(t[2])?l(function(e){n.atrule(t[1],t[2],e)})(r):!t[3]&&/^(?:font-face|viewport)$/.test(t[2])?l(function(r){n.atrule(t[1],t[2],t[3],1),i(e,n,"",r,o),n._atrule()})(r):t[3]&&/^(?:media|supports|page|keyframes)$/.test(t[2])?(o&&"keyframes"==t[2]&&(t[3]=t[3].replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,e.localizeReplacer)),n.atrule(t[1],t[2],t[3],1),"page"==t[2]?i(e,n,"",r,o):u(e,n,"keyframes"==t[2]?"":a,r,o,c+1),n._atrule()):n.err("Unsupported at-rule: "+t[0])}function u(e,n,l,a,c,s){var f,p,h,g;switch(m.call(a)){case _:for(f in a)if(b.call(a,f))if(p=a[f],l.length>0&&/^[-\w$]+$/.test(f))if(h||(h=1,n.rule(l)),/\$/.test(f))for(g in f=f.split("$"))b.call(f,g)&&i(e,n,f[g],p,c);else i(e,n,f,p,c);else/^@/.test(f)?(h=0,o(e,n,/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(f)||[f,"@","",""],p,l,c,s)):(h=0,u(e,n,l.length>0&&(/,/.test(l)||/,/.test(f))?(g=t(l),t(c?f.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):f).map(function(e){return/&/.test(e)?r(e,g):g.map(function(n){return n+e}).join(",")}).join(",")):/&/.test(f)?r(c?f.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):f,[l]):l+(c?f.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):f),p,c,s+1));break;case $:for(f=0;f<a.length;f++)u(e,n,l,a[f],c,s);break;case z:l.length||n.err("No selector"),n.rule(l||" "),i(e,n,"",a,c)}}function c(e,n){var t;return n?e:{init:function(){t=0,e.init()},done:function(n){return t&&(e._rule(),t=0),e.done(n)},atrule:function(n,r,l,a){t&&(e._rule(),t=0),e.atrule(n,r,l,a)},_atrule:function(n){t&&(e._rule(),t=0),e._atrule(n)},rule:function(n){n!==t&&(t&&e._rule(),e.rule(n),t=n)}}}function s(e){return":global("+e+")"}function f(e,n,t){return t={},t[e]=n,t}function p(e,n,t){if(arguments.length<3){var r=p.bind.apply(p,[null].concat([].slice.call(arguments,0)));return r.toString=function(){return"@"+e+" "+n},r}return f("@"+e+" "+n,t)}function h(){function n(n){if(!Z.length){_.push(function(e,n){return n?{init:$.init,decl:$.decl,done:$.done,err:$.err}:$});for(var t=0;t<2;t++)for(var r=_.length;r--;)Z[t]=v(e(_[r](Z[t],!!t),Z[t]))}return Z[n]}function t(e){return b.names[e]||(b.names[e]=e+b.suffix),b.names[e].match(/^\S+/)}function r(e,n,r,l,a){return n||r||l+t(a)}var a,h,$={init:function(){a=[],h=[]},done:function(e){if(0!=h.length)throw new Error("j2c error(s): "+JSON.stringify(h,null,2)+"in context:\n"+a.join(""));return e?a:a.join("")},err:function(e){h.push(e),a.push("/* +++ ERROR +++ "+e+" */\n")},atrule:function(e,n,t,r){a.push(e,t&&" ",t,r?" {":";",b.endline)},_atrule:function(){a.push("}",b.endline)},rule:function(e){a.push(e," {",b.endline)},_rule:function(){a.push("}",b.endline)},decl:function(e,n){a.push(e,e&&":",n,";",b.endline)}},_=[c],z=[],b={at:p,global:s,kv:f,names:{},endline:"\n",suffix:"__j2c-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36),$plugins:[],sheet:function(e){var t=n(0);return t.init(),u(A[0],t,"",e,1,0),t.done()},inline:function(e,t){var r=n(1);return r.init(),i(A[1],r,"",e,!(t&&t.global)),r.done()}},A=[{localizeReplacer:r,localize:t,names:b.names,$atHandlers:z,atrule:o,decl:i,rule:u},{localizeReplacer:r,localize:t,names:b.names,decl:i}],S=l(function(n){~b.$plugins.indexOf(n)||(b.$plugins.push(n),m.call(n)===w&&(n=n(b)),n&&(l(function(e){_.push(e)})(n.$filter||g),l(function(e){z.push(e)})(n.$at||g),e(b.names,n.$names||d),S(n.$plugins||g),$=n.$sink||$,e(b,n)))}),Z=[];return S(g.slice.call(arguments)),b}var g=[],d={},m=d.toString,$=m.call(g),_=m.call(d),z=m.call(""),w=m.call(m),b=d.hasOwnProperty,v=Object.freeze||function(e){return e},A=/[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,S=/&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g;return h}); |
@@ -12,5 +12,7 @@ 'use strict'; | ||
var freeze = Object.freeze || function(o) {return o}; | ||
function Default(target, source) { | ||
function defaults(target, source) { | ||
for (var k in source) if (own.call(source, k)) { | ||
if (k.indexOf('$') && !(k in target)) target[k] = source[k] | ||
if (k.indexOf('$') && !(k in target)) target[k] = source[k]; | ||
} | ||
@@ -21,6 +23,6 @@ return target | ||
function cartesian(a,b) { | ||
var res = [], i, j | ||
var res = [], i, j; | ||
for (j in b) if(own.call(b, j)) | ||
for (i in a) if(own.call(a, i)) | ||
res.push(a[i] + b[j]) | ||
res.push(a[i] + b[j]); | ||
return res | ||
@@ -34,3 +36,3 @@ } | ||
// regexp generated by scripts/regexps.js then trimmed by hand | ||
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; | ||
@@ -41,2 +43,3 @@ | ||
* ignoring comas in strings, comments and in :pseudo-selectors(parameter, lists). | ||
* | ||
* @param {string} selector | ||
@@ -47,3 +50,3 @@ * @return {string[]} | ||
function splitSelector(selector) { | ||
var indices = [], res = [], inParen = 0, o | ||
var indices = [], res = [], inParen = 0, o; | ||
/*eslint-disable no-cond-assign*/ | ||
@@ -55,32 +58,32 @@ while (o = selectorTokenizer.exec(selector)) { | ||
case ')': inParen--; break | ||
case ',': if (inParen) break; indices.push(o.index) | ||
case ',': if (inParen) break; indices.push(o.index); | ||
} | ||
} | ||
for (o = indices.length; o--;){ | ||
res.unshift(selector.slice(indices[o] + 1)) | ||
selector = selector.slice(0, indices[o]) | ||
res.unshift(selector.slice(indices[o] + 1)); | ||
selector = selector.slice(0, indices[o]); | ||
} | ||
res.unshift(selector) | ||
res.unshift(selector); | ||
return res | ||
} | ||
// This is like the `selectorTokenizer`, but for the `&` operator | ||
// Like the `selectorTokenizer`, but for the `&` operator | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
function ampersand (selector, parents) { | ||
var indices = [], split = [], res, o | ||
var indices = [], split = [], res, o; | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = ampersandTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
if (o[0] == '&') indices.push(o.index) | ||
if (o[0] == '&') indices.push(o.index); | ||
} | ||
for (o = indices.length; o--;){ | ||
split.unshift(selector.slice(indices[o] + 1)) | ||
selector = selector.slice(0, indices[o]) | ||
split.unshift(selector.slice(indices[o] + 1)); | ||
selector = selector.slice(0, indices[o]); | ||
} | ||
split.unshift(selector) | ||
res = [split[0]] | ||
split.unshift(selector); | ||
if (split.length === 1) split.unshift(''); | ||
res = [split[0]]; | ||
for (o = 1; o < split.length; o++) { | ||
res = cartesian(res, cartesian(parents, [split[o]])) | ||
res = cartesian(res, cartesian(parents, [split[o]])); | ||
} | ||
@@ -92,4 +95,4 @@ return res.join(',') | ||
return function iter(arg) { | ||
if (type.call(arg) === ARRAY) for (var i= 0 ; i < arg.length; i ++) iter(arg[i]) | ||
else f(arg) | ||
if (type.call(arg) === ARRAY) for (var i= 0 ; i < arg.length; i ++) iter(arg[i]); | ||
else f(arg); | ||
} | ||
@@ -115,3 +118,3 @@ } | ||
function declarations(state, emit, prefix, o, local) { | ||
var k, v, kk | ||
var k, v, kk; | ||
if (o==null) return | ||
@@ -123,3 +126,3 @@ | ||
declarations(state, emit, prefix, o[k], local) | ||
declarations(state, emit, prefix, o[k], local); | ||
@@ -130,9 +133,9 @@ break | ||
// of the declarations list. | ||
prefix = (prefix && prefix + '-') | ||
prefix = (prefix && prefix + '-'); | ||
for (k in o) if (own.call(o, k)){ | ||
v = o[k] | ||
v = o[k]; | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
declarations(state, emit, prefix + k[kk], v, local) | ||
declarations(state, emit, prefix + k[kk], v, local); | ||
@@ -142,3 +145,3 @@ } | ||
declarations(state, emit, prefix + k, v, local) | ||
declarations(state, emit, prefix + k, v, local); | ||
@@ -157,3 +160,3 @@ } | ||
// restore the dashes | ||
k = prefix.replace(/_/g, '-').replace(/[A-Z]/g, decamelize) | ||
k = prefix.replace(/_/g, '-').replace(/[A-Z]/g, decamelize); | ||
@@ -165,8 +168,8 @@ if (local && (k == 'animation-name' || k == 'animation' || k == 'list-style')) { | ||
return o.replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, state.L) | ||
return o.replace(/^\s*(?:(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*))/, state.localizeReplacer) | ||
}).join(',') | ||
}).join(','); | ||
} | ||
emit.d(k, o) | ||
emit.decl(k, o); | ||
@@ -177,3 +180,3 @@ } | ||
/** | ||
* Hanldes at-rules | ||
* Handles a single at-rules | ||
* | ||
@@ -185,4 +188,8 @@ * @param {object} state - holds the localizer- and walker-related methods | ||
* if takes both parameters and a block. | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* k == [match, fullAtRule, atRuleType, params?] | ||
* So in `@-webkit-keyframes foo`, we have | ||
* - match = "@-webkit-keyframes foo" | ||
* - fullAtRule = "@-webkit-keyframes" | ||
* - atRuleType = "keyframes" | ||
* - params = "foo" | ||
* @param {string|string[]|object|object[]} v - Either parameters for | ||
@@ -192,11 +199,14 @@ * block-less rules or | ||
* for the others. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
* @param {string} nestingDepth - are we nested in an at-rule or a selector? | ||
*/ | ||
function atRules(state, emit, k, v, prefix, local, inAtRule) { | ||
function atRules(state, emit, k, v, prefix, local, nestingDepth) { | ||
for (var i = 0; i < state.$a.length; i++) { | ||
// First iterate over user-provided at-rules and return if one of them corresponds to the current one | ||
for (var i = 0; i < state.$atHandlers.length; i++) { | ||
if (state.$a[i](state, emit, k, v, prefix, local, inAtRule)) return | ||
if (state.$atHandlers[i](state, emit, k, v, prefix, local, nestingDepth)) return | ||
@@ -206,3 +216,3 @@ } | ||
// using `/^global$/.test(k[2])` rather that 'global' == k[2] gzips | ||
// slightly better because of the regexps test further down. | ||
// slightly better thanks to the regexps tests further down. | ||
// It is slightly less efficient but this isn't a critical path. | ||
@@ -212,3 +222,3 @@ | ||
rules(state, emit, prefix, v, 0, inAtRule) | ||
rules(state, emit, prefix, v, 0, nestingDepth); | ||
@@ -218,3 +228,3 @@ | ||
rules(state, emit, prefix, v, 1, inAtRule) | ||
rules(state, emit, prefix, v, 1, nestingDepth); | ||
@@ -224,19 +234,19 @@ | ||
if (!local || inAtRule) return emit.a('@-error-bad-at-adopt-placement' , JSON.stringify(k[0]), 0) | ||
if (!local || nestingDepth) return emit.err('@adopt global or nested: ' + k[0]) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.a('@-error-bad-at-adopter', k[3], 0) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.err('bad adopter ' + JSON.stringify(k[3]) + ' in ' + k[0]) | ||
i = [] | ||
i = []; | ||
flatIter(function(adoptee, asString) { | ||
if(!/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee.toString())) emit.a('@-error-bad-at-adoptee', JSON.stringify(adoptee), 0) | ||
if(adoptee == null || !/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee + '')) emit.err('bad adoptee '+ JSON.stringify(adoptee) + ' in ' + k[0]); | ||
else i.push(asString.replace(/\./g, '')) | ||
else i.push(asString.replace(/\./g, '')); | ||
})(v) | ||
})(v); | ||
// we may end up with duplicate classes but AFAIK it has no consequences on specificity. | ||
if (i.length) { | ||
state.l(k[3] = k[3].replace(/\./g, '')) | ||
state.n[k[3]] += (' ' + i.join(' ')) | ||
state.localize(k[3] = k[3].replace(/\./g, '')); | ||
state.names[k[3]] += (' ' + i.join(' ')); | ||
} | ||
@@ -248,5 +258,5 @@ | ||
emit.a(k[0], v) | ||
emit.atrule(k[1], k[2], v); | ||
})(v) | ||
})(v); | ||
@@ -257,9 +267,9 @@ | ||
emit.a(k[1], '', 1) | ||
emit.atrule(k[1], k[2], k[3], 1); | ||
declarations(state, emit, '', v, local) | ||
declarations(state, emit, '', v, local); | ||
emit.A(k[1], '') | ||
emit._atrule(); | ||
})(v) | ||
})(v); | ||
@@ -272,12 +282,12 @@ } else if (k[3] && /^(?:media|supports|page|keyframes)$/.test(k[2])) { | ||
/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, | ||
state.L | ||
) | ||
state.localizeReplacer | ||
); | ||
} | ||
emit.a(k[1], k[3], 1) | ||
emit.atrule(k[1], k[2], k[3], 1); | ||
if ('page' == k[2]) { | ||
declarations(state, emit, '', v, local) | ||
declarations(state, emit, '', v, local); | ||
@@ -289,12 +299,12 @@ } else { | ||
'keyframes' == k[2] ? '' : prefix, | ||
v, local, 1 | ||
) | ||
v, local, nestingDepth + 1 | ||
); | ||
} | ||
emit.A(k[1], k[3]) | ||
emit._atrule(); | ||
} else { | ||
emit.a('@-error-unsupported-at-rule', JSON.stringify(k[0])) | ||
emit.err('Unsupported at-rule: ' + k[0]); | ||
@@ -312,7 +322,7 @@ } | ||
* @param {array|string|object} tree - a source object or sub-object. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {string} nestingDepth - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
function rules(state, emit, prefix, tree, local, inAtRule) { | ||
var k, v, inDeclaration, kk | ||
function rules(state, emit, prefix, tree, local, nestingDepth) { | ||
var k, v, inDeclaration, kk; | ||
@@ -323,9 +333,9 @@ switch (type.call(tree)) { | ||
for (k in tree) if (own.call(tree, k)) { | ||
v = tree[k] | ||
v = tree[k]; | ||
if (prefix.length > 0 && /^[-\w$]+$/.test(k)) { | ||
if (!inDeclaration) { | ||
inDeclaration = 1 | ||
inDeclaration = 1; | ||
emit.s(prefix) | ||
emit.rule(prefix); | ||
@@ -336,3 +346,3 @@ } | ||
declarations(state, emit, k[kk], v, local) | ||
declarations(state, emit, k[kk], v, local); | ||
@@ -342,3 +352,3 @@ } | ||
declarations(state, emit, k, v, local) | ||
declarations(state, emit, k, v, local); | ||
@@ -349,20 +359,20 @@ } | ||
// Handle At-rules | ||
inDeclaration = 0 | ||
inDeclaration = 0; | ||
atRules(state, emit, | ||
/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(k) || [k,'@','',''], | ||
v, prefix, local, inAtRule | ||
) | ||
v, prefix, local, nestingDepth | ||
); | ||
} else { | ||
// selector or nested sub-selectors | ||
inDeclaration = 0 | ||
inDeclaration = 0; | ||
rules( | ||
state, emit, | ||
// `prefix` ... Hefty. Ugly. Sadly necessary. | ||
// | ||
(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
// build the selector `prefix` for the next iteration. | ||
// ugly and full of redundant bits but so far the fastest/shortest.gz | ||
/*0 if*/(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
/*0*/ (kk = splitSelector(prefix), splitSelector( | ||
/*0 then*/ (kk = splitSelector(prefix), splitSelector( | ||
local ? | ||
@@ -372,3 +382,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -383,5 +393,5 @@ | ||
/*0*/ /&/.test(k) ? | ||
/*0 else*/ /*1 if*/ /&/.test(k) ? | ||
/*1*/ ampersand( | ||
/*1 then*/ ampersand( | ||
local ? | ||
@@ -391,3 +401,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -399,3 +409,3 @@ | ||
/*1*/ prefix + ( | ||
/*1 else*/ prefix + ( | ||
local ? | ||
@@ -405,3 +415,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -411,4 +421,4 @@ | ||
), | ||
v, local, inAtRule | ||
) | ||
v, local, nestingDepth + 1 | ||
); | ||
@@ -423,3 +433,3 @@ } | ||
rules(state, emit, prefix, tree[k], local, inAtRule) | ||
rules(state, emit, prefix, tree[k], local, nestingDepth); | ||
@@ -431,7 +441,7 @@ } | ||
// CSS hacks or ouptut of `j2c.inline`. | ||
if (!prefix.length) emit.err('No selector'); | ||
emit.rule(prefix || ' '); | ||
emit.s(prefix.length > 0 ? prefix : ':-error-no-selector') | ||
declarations(state, emit, '', tree, local); | ||
declarations(state, emit, '', tree, local) | ||
} | ||
@@ -447,28 +457,27 @@ } | ||
// contains arrays. | ||
// There's no `S` handler, because the core compiler never | ||
// There's no `_rule` handler, because the core compiler never | ||
// calls it. | ||
function closeSelectors(next, inline) { | ||
var lastSelector | ||
var lastSelector; | ||
return inline ? next : { | ||
i: function(){lastSelector = 0; next.i()}, | ||
x: function (raw) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
return next.x(raw) | ||
init: function(){lastSelector = 0; next.init();}, | ||
done: function (raw) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
return next.done(raw) | ||
}, | ||
a: function (rule, param, takesBlock) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.a(rule, param, takesBlock) | ||
atrule: function (rule, kind, param, takesBlock) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
next.atrule(rule, kind, param, takesBlock); | ||
}, | ||
A: function (rule) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.A(rule) | ||
_atrule: function (rule) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
next._atrule(rule); | ||
}, | ||
s: function (selector) { | ||
rule: function (selector) { | ||
if (selector !== lastSelector){ | ||
if (lastSelector) next.S() | ||
next.s(selector) | ||
lastSelector = selector | ||
if (lastSelector) next._rule(); | ||
next.rule(selector); | ||
lastSelector = selector; | ||
} | ||
}, | ||
d: next.d | ||
} | ||
} | ||
@@ -482,4 +491,4 @@ } | ||
function kv (k, v, o) { | ||
o = {} | ||
o[k] = v | ||
o = {}; | ||
o[k] = v; | ||
return o | ||
@@ -493,5 +502,5 @@ } | ||
// inner curry! | ||
var _at = at.bind.apply(at, [null].concat([].slice.call(arguments,0))) | ||
var _at = at.bind.apply(at, [null].concat([].slice.call(arguments,0))); | ||
// So that it can be used as a key in an ES6 object literal. | ||
_at.toString = function(){return '@' + rule + ' ' + params} | ||
_at.toString = function(){return '@' + rule + ' ' + params}; | ||
return _at | ||
@@ -504,28 +513,32 @@ } | ||
// palceholder for the buffer used by the `$sink` handlers | ||
var buf | ||
// the buffer that accumulates the output. Initialized in `$sink.i()` | ||
var buf, err; | ||
// the bottom of the 'codegen' stream. Mirrors the `$filter` plugin API. | ||
var $sink = { | ||
// Init | ||
i: function(){buf=[]}, | ||
// done (eXit) | ||
x: function (raw) {return raw ? buf : buf.join('')}, | ||
// start At-rule | ||
a: function (rule, argument, takesBlock) { | ||
buf.push(rule, argument && ' ',argument, takesBlock ? ' {\n' : ';\n') | ||
init: function(){buf=[], err=[];}, | ||
done: function (raw) { | ||
if (err.length != 0) throw new Error('j2c error(s): ' + JSON.stringify(err,null,2) + 'in context:\n' + buf.join('')) | ||
return raw ? buf : buf.join('') | ||
}, | ||
// end At-rule | ||
A: function () {buf.push('}\n')}, | ||
// start Selector | ||
s: function (selector) {buf.push(selector, ' {\n')}, | ||
// end Selector | ||
S: function () {buf.push('}\n')}, | ||
// declarations | ||
d: function (prop, value) {buf.push(prop, prop && ':', value, ';\n')} | ||
} | ||
err: function(msg) { | ||
err.push(msg); | ||
buf.push('/* +++ ERROR +++ ' + msg + ' */\n'); | ||
}, | ||
atrule: function (rule, kind, param, takesBlock) { | ||
buf.push(rule, param && ' ', param, takesBlock ? ' {' : ';', _instance.endline); | ||
}, | ||
// close atrule | ||
_atrule: function () {buf.push('}', _instance.endline);}, | ||
rule: function (selector) {buf.push(selector, ' {', _instance.endline);}, | ||
// close rule | ||
_rule: function () {buf.push('}', _instance.endline);}, | ||
decl: function (prop, value) {buf.push(prop, prop && ':', value, ';', _instance.endline);} | ||
}; | ||
var $filters = [closeSelectors] | ||
var $atHandlers = [] | ||
// holds the `$filter` and `$at` handlers | ||
var $filters = [closeSelectors]; | ||
var $atHandlers = []; | ||
// the public API (see the main docs) | ||
var _instance = { | ||
@@ -536,3 +549,5 @@ at: at, | ||
names: {}, | ||
endline: '\n', | ||
suffix: '__j2c-' + | ||
// 128 bits of randomness | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
@@ -542,13 +557,32 @@ Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36), | ||
use: function() { | ||
_use(emptyArray.slice.call(arguments)) | ||
return _instance | ||
$plugins: [], | ||
sheet: function(tree) { | ||
var emit = _createOrRetrieveStream(0); | ||
emit.init(); | ||
rules( | ||
_walkers[0], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1, // local, by default | ||
0 // nesting depth | ||
); | ||
return emit.done() | ||
}, | ||
$plugins: [] | ||
} | ||
inline: function (tree, options) { | ||
var emit = _createOrRetrieveStream(1); | ||
emit.init(); | ||
declarations( | ||
_walkers[1], | ||
emit, | ||
'', // prefix | ||
tree, | ||
!(options && options.global) // local, by default | ||
); | ||
return emit.done() | ||
} | ||
}; | ||
var _streams = [] | ||
// The `state` (for the core) / `walker` (for the plugins) tables. | ||
// The `state` (for the core functions) / `walker` (for the plugins) tables. | ||
var _walkers = [ | ||
@@ -558,51 +592,21 @@ // for j2c.sheet | ||
// helpers for locaizing class and animation names | ||
L: _localizeReplacer, // second argument to String.prototype.replace | ||
l: _localize, // mangles local names | ||
n: _instance.names, // local => mangled mapping | ||
$a: $atHandlers, // extra at-rules | ||
localizeReplacer: _localizeReplacer, // second argument to String.prototype.replace | ||
localize: _localize, // mangles local names | ||
names: _instance.names, // local => mangled mapping | ||
$atHandlers: $atHandlers, // extra at-rules | ||
// The core walker methods, to be provided to plugins | ||
a: atRules, | ||
d: declarations, | ||
r: rules | ||
atrule: atRules, | ||
decl: declarations, | ||
rule: rules | ||
}, | ||
// likewise, for j2c.inline (idem with `$a`, `a` and `s` removed) | ||
{ | ||
L: _localizeReplacer, | ||
l: _localize, | ||
n: _instance.names, | ||
d: declarations | ||
localizeReplacer: _localizeReplacer, | ||
localize: _localize, | ||
names: _instance.names, | ||
decl: declarations | ||
} | ||
] | ||
]; | ||
// The main API functions | ||
_instance.sheet = function(tree) { | ||
var emit = _getStream(0) | ||
emit.i() | ||
rules( | ||
_walkers[0], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1, // local, by default | ||
0 // inAtRule | ||
) | ||
return emit.x() | ||
} | ||
_instance.inline = function (tree) { | ||
var emit = _getStream(1) | ||
emit.i() | ||
declarations( | ||
_walkers[1], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1 //local | ||
) | ||
return emit.x() | ||
} | ||
// inner helpers | ||
@@ -617,5 +621,5 @@ | ||
_instance.$plugins.push(plugin) | ||
_instance.$plugins.push(plugin); | ||
if (type.call(plugin) === FUNCTION) plugin = plugin(_instance) | ||
if (type.call(plugin) === FUNCTION) plugin = plugin(_instance); | ||
@@ -625,50 +629,74 @@ if (!plugin) return | ||
flatIter(function(filter) { | ||
$filters.push(filter) | ||
})(plugin.$filter || emptyArray) | ||
$filters.push(filter); | ||
})(plugin.$filter || emptyArray); | ||
flatIter(function(handler) { | ||
$atHandlers.push(handler) | ||
})(plugin.$at || emptyArray) | ||
$atHandlers.push(handler); | ||
})(plugin.$at || emptyArray); | ||
Default(_instance.names, plugin.$names || emptyObject) | ||
defaults(_instance.names, plugin.$names || emptyObject); | ||
_use(plugin.$plugins || emptyArray) | ||
_use(plugin.$plugins || emptyArray); | ||
$sink = plugin.$sink || $sink | ||
$sink = plugin.$sink || $sink; | ||
Default(_instance, plugin) | ||
}) | ||
defaults(_instance, plugin); | ||
}); | ||
function _getStream(inline) { | ||
var _streams = []; | ||
/** | ||
* returns the codegen streams, creating them if necessary | ||
* @param | ||
*/ | ||
function _createOrRetrieveStream(inline) { | ||
// build the stream processors if needed | ||
if (!_streams.length) { | ||
for(var i = 0; i < 2; i++){ | ||
$filters[$filters.length - i] = function(_, inline) {return inline ? {i:$sink.i, d:$sink.d, x:$sink.x} : $sink} | ||
// append the $sink as the ultimate filter | ||
$filters.push(function(_, inline) {return inline ? {init:$sink.init, decl:$sink.decl, done:$sink.done, err: $sink.err} : $sink}); | ||
for(var i = 0; i < 2; i++){ // 0 for j2c.sheet, 1 for j2c.inline | ||
for (var j = $filters.length; j--;) { | ||
_streams[i] = freeze(Default( | ||
$filters[j](_streams[i], !!i, _walkers[i]), | ||
_streams[i] | ||
)) | ||
_streams[i] = freeze( | ||
defaults( | ||
$filters[j](_streams[i], !!i), | ||
_streams[i] | ||
) | ||
); | ||
} | ||
} | ||
} | ||
var res = _streams[inline] | ||
return res | ||
return _streams[inline] | ||
} | ||
/** | ||
* Returns a localized version of a given name. | ||
* Registers the pair in `instnace.name` if needed. | ||
* | ||
* @param {string} name - the name to localize | ||
* @return {string} - the localized version | ||
*/ | ||
function _localize(name) { | ||
if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix | ||
if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix; | ||
return _instance.names[name].match(/^\S+/) | ||
} | ||
function _localizeReplacer(match, string, global, dot, name) { | ||
if (string || global) return string || global | ||
return dot + _localize(name) | ||
/** | ||
* Used as second argument for str.replace(localizeRegex, replacer) | ||
* `ignore`, `global` and `(dot, name)` are mutually exclusive | ||
* | ||
* @param {string} match - the whole match (ignored) | ||
* @param {string|null} ignore - a comment or a string literal | ||
* @param {string|null} global - a global name | ||
* @param {string|null} dot - either '.' for a local class name or the empty string otherwise | ||
* @param {string|null} name - the name to localize | ||
* @return {string} | ||
*/ | ||
function _localizeReplacer(match, ignore, global$$1, dot, name) { | ||
return ignore || global$$1 || dot + _localize(name) | ||
} | ||
_use(emptyArray.slice.call(arguments)); | ||
return _instance | ||
} | ||
var _j2c = j2c() | ||
'sheet|inline|names|at|global|kv|suffix'.split('|').map(function(m){j2c[m] = _j2c[m]}) | ||
module.exports = j2c; | ||
module.exports = j2c; |
@@ -1,1 +0,1 @@ | ||
"use strict";function Default(e,t){for(var n in t)own.call(t,n)&&(!n.indexOf("$")||n in e||(e[n]=t[n]));return e}function cartesian(e,t){var n,a,r=[];for(a in t)if(own.call(t,a))for(n in e)own.call(e,n)&&r.push(e[n]+t[a]);return r}function splitSelector(e){for(var t,n=[],a=[],r=0;t=selectorTokenizer.exec(e);)switch(t[0]){case"(":r++;break;case")":r--;break;case",":if(r)break;n.push(t.index)}for(t=n.length;t--;)a.unshift(e.slice(n[t]+1)),e=e.slice(0,n[t]);return a.unshift(e),a}function ampersand(e,t){for(var n,a,r=[],l=[];a=ampersandTokenizer.exec(e);)"&"==a[0]&&r.push(a.index);for(a=r.length;a--;)l.unshift(e.slice(r[a]+1)),e=e.slice(0,r[a]);for(l.unshift(e),n=[l[0]],a=1;a<l.length;a++)n=cartesian(n,cartesian(t,[l[a]]));return n.join(",")}function flatIter(e){return function t(n){if(type.call(n)===ARRAY)for(var a=0;a<n.length;a++)t(n[a]);else e(n)}}function decamelize(e){return"-"+e.toLowerCase()}function declarations(e,t,n,a,r){var l,i,s;if(null!=a)switch(type.call(a=a.valueOf())){case ARRAY:for(l=0;l<a.length;l++)declarations(e,t,n,a[l],r);break;case OBJECT:n=n&&n+"-";for(l in a)if(own.call(a,l))if(i=a[l],/\$/.test(l))for(s in l=l.split("$"))own.call(l,s)&&declarations(e,t,n+l[s],i,r);else declarations(e,t,n+l,i,r);break;default:l=n.replace(/_/g,"-").replace(/[A-Z]/g,decamelize),!r||"animation-name"!=l&&"animation"!=l&&"list-style"!=l||(a=a.split(",").map(function(t){return t.replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,e.L)}).join(",")),t.d(l,a)}}function atRules(e,t,n,a,r,l,i){for(var s=0;s<e.$a.length;s++)if(e.$a[s](e,t,n,a,r,l,i))return;if(!n[3]&&/^global$/.test(n[2]))rules(e,t,r,a,0,i);else if(!n[3]&&/^local$/.test(n[2]))rules(e,t,r,a,1,i);else if(n[3]&&/^adopt$/.test(n[2])){if(!l||i)return t.a("@-error-bad-at-adopt-placement",JSON.stringify(n[0]),0);if(!/^\.?[_A-Za-z][-\w]*$/.test(n[3]))return t.a("@-error-bad-at-adopter",n[3],0);s=[],flatIter(function(e,n){/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(n=e.toString())?s.push(n.replace(/\./g,"")):t.a("@-error-bad-at-adoptee",JSON.stringify(e),0)})(a),s.length&&(e.l(n[3]=n[3].replace(/\./g,"")),e.n[n[3]]+=" "+s.join(" "))}else!n[3]&&/^(?:namespace|import|charset)$/.test(n[2])?flatIter(function(e){t.a(n[0],e)})(a):!n[3]&&/^(?:font-face|viewport)$/.test(n[2])?flatIter(function(a){t.a(n[1],"",1),declarations(e,t,"",a,l),t.A(n[1],"")})(a):n[3]&&/^(?:media|supports|page|keyframes)$/.test(n[2])?(l&&"keyframes"==n[2]&&(n[3]=n[3].replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,e.L)),t.a(n[1],n[3],1),"page"==n[2]?declarations(e,t,"",a,l):rules(e,t,"keyframes"==n[2]?"":r,a,l,1),t.A(n[1],n[3])):t.a("@-error-unsupported-at-rule",JSON.stringify(n[0]))}function rules(e,t,n,a,r,l){var i,s,o,c;switch(type.call(a)){case OBJECT:for(i in a)if(own.call(a,i))if(s=a[i],n.length>0&&/^[-\w$]+$/.test(i))if(o||(o=1,t.s(n)),/\$/.test(i))for(c in i=i.split("$"))own.call(i,c)&&declarations(e,t,i[c],s,r);else declarations(e,t,i,s,r);else/^@/.test(i)?(o=0,atRules(e,t,/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(i)||[i,"@","",""],s,n,r,l)):(o=0,rules(e,t,n.length>0&&(/,/.test(n)||/,/.test(i))?(c=splitSelector(n),splitSelector(r?i.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.L):i).map(function(e){return/&/.test(e)?ampersand(e,c):c.map(function(t){return t+e}).join(",")}).join(",")):/&/.test(i)?ampersand(r?i.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.L):i,[n]):n+(r?i.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.L):i),s,r,l));break;case ARRAY:for(i=0;i<a.length;i++)rules(e,t,n,a[i],r,l);break;case STRING:t.s(n.length>0?n:":-error-no-selector"),declarations(e,t,"",a,r)}}function closeSelectors(e,t){var n;return t?e:{i:function(){n=0,e.i()},x:function(t){return n&&(e.S(),n=0),e.x(t)},a:function(t,a,r){n&&(e.S(),n=0),e.a(t,a,r)},A:function(t){n&&(e.S(),n=0),e.A(t)},s:function(t){t!==n&&(n&&e.S(),e.s(t),n=t)},d:e.d}}function global(e){return":global("+e+")"}function kv(e,t,n){return n={},n[e]=t,n}function at(e,t,n){if(arguments.length<3){var a=at.bind.apply(at,[null].concat([].slice.call(arguments,0)));return a.toString=function(){return"@"+e+" "+t},a}return kv("@"+e+" "+t,n)}function j2c(){function e(e){if(!o.length)for(var t=0;2>t;t++){l[l.length-t]=function(e,t){return t?{i:r.i,d:r.d,x:r.x}:r};for(var n=l.length;n--;)o[t]=freeze(Default(l[n](o[t],!!t,c[t]),o[t]))}var a=o[e];return a}function t(e){return s.names[e]||(s.names[e]=e+s.suffix),s.names[e].match(/^\S+/)}function n(e,n,a,r,l){return n||a?n||a:r+t(l)}var a,r={i:function(){a=[]},x:function(e){return e?a:a.join("")},a:function(e,t,n){a.push(e,t&&" ",t,n?" {\n":";\n")},A:function(){a.push("}\n")},s:function(e){a.push(e," {\n")},S:function(){a.push("}\n")},d:function(e,t){a.push(e,e&&":",t,";\n")}},l=[closeSelectors],i=[],s={at:at,global:global,kv:kv,names:{},suffix:"__j2c-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36),use:function(){return u(emptyArray.slice.call(arguments)),s},$plugins:[]},o=[],c=[{L:n,l:t,n:s.names,$a:i,a:atRules,d:declarations,r:rules},{L:n,l:t,n:s.names,d:declarations}];s.sheet=function(t){var n=e(0);return n.i(),rules(c[0],n,"",t,1,0),n.x()},s.inline=function(t){var n=e(1);return n.i(),declarations(c[1],n,"",t,1),n.x()};var u=flatIter(function(e){~s.$plugins.indexOf(e)||(s.$plugins.push(e),type.call(e)===FUNCTION&&(e=e(s)),e&&(flatIter(function(e){l.push(e)})(e.$filter||emptyArray),flatIter(function(e){i.push(e)})(e.$at||emptyArray),Default(s.names,e.$names||emptyObject),u(e.$plugins||emptyArray),r=e.$sink||r,Default(s,e)))});return s}var emptyArray=[],emptyObject={},type=emptyObject.toString,ARRAY=type.call(emptyArray),OBJECT=type.call(emptyObject),STRING=type.call(""),FUNCTION=type.call(type),own=emptyObject.hasOwnProperty,freeze=Object.freeze||function(e){return e},selectorTokenizer=/[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,ampersandTokenizer=/&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,_j2c=j2c();"sheet|inline|names|at|global|kv|suffix".split("|").map(function(e){j2c[e]=_j2c[e]}),module.exports=j2c; | ||
"use strict";function defaults(e,t){for(var n in t)own.call(t,n)&&(!n.indexOf("$")||n in e||(e[n]=t[n]));return e}function cartesian(e,t){var n,r,a=[];for(r in t)if(own.call(t,r))for(n in e)own.call(e,n)&&a.push(e[n]+t[r]);return a}function splitSelector(e){for(var t,n=[],r=[],a=0;t=selectorTokenizer.exec(e);)switch(t[0]){case"(":a++;break;case")":a--;break;case",":if(a)break;n.push(t.index)}for(t=n.length;t--;)r.unshift(e.slice(n[t]+1)),e=e.slice(0,n[t]);return r.unshift(e),r}function ampersand(e,t){for(var n,r,a=[],l=[];r=ampersandTokenizer.exec(e);)"&"==r[0]&&a.push(r.index);for(r=a.length;r--;)l.unshift(e.slice(a[r]+1)),e=e.slice(0,a[r]);for(l.unshift(e),1===l.length&&l.unshift(""),n=[l[0]],r=1;r<l.length;r++)n=cartesian(n,cartesian(t,[l[r]]));return n.join(",")}function flatIter(e){return function t(n){if(type.call(n)===ARRAY)for(var r=0;r<n.length;r++)t(n[r]);else e(n)}}function decamelize(e){return"-"+e.toLowerCase()}function declarations(e,t,n,r,a){var l,i,o;if(null!=r)switch(type.call(r=r.valueOf())){case ARRAY:for(l=0;l<r.length;l++)declarations(e,t,n,r[l],a);break;case OBJECT:n=n&&n+"-";for(l in r)if(own.call(r,l))if(i=r[l],/\$/.test(l))for(o in l=l.split("$"))own.call(l,o)&&declarations(e,t,n+l[o],i,a);else declarations(e,t,n+l,i,a);break;default:l=n.replace(/_/g,"-").replace(/[A-Z]/g,decamelize),!a||"animation-name"!=l&&"animation"!=l&&"list-style"!=l||(r=r.split(",").map(function(t){return t.replace(/^\s*(?:(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*))/,e.localizeReplacer)}).join(",")),t.decl(l,r)}}function atRules(e,t,n,r,a,l,i){for(var o=0;o<e.$atHandlers.length;o++)if(e.$atHandlers[o](e,t,n,r,a,l,i))return;if(!n[3]&&/^global$/.test(n[2]))rules(e,t,a,r,0,i);else if(!n[3]&&/^local$/.test(n[2]))rules(e,t,a,r,1,i);else if(n[3]&&/^adopt$/.test(n[2])){if(!l||i)return t.err("@adopt global or nested: "+n[0]);if(!/^\.?[_A-Za-z][-\w]*$/.test(n[3]))return t.err("bad adopter "+JSON.stringify(n[3])+" in "+n[0]);o=[],flatIter(function(e,r){null!=e&&/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(r=e+"")?o.push(r.replace(/\./g,"")):t.err("bad adoptee "+JSON.stringify(e)+" in "+n[0])})(r),o.length&&(e.localize(n[3]=n[3].replace(/\./g,"")),e.names[n[3]]+=" "+o.join(" "))}else!n[3]&&/^(?:namespace|import|charset)$/.test(n[2])?flatIter(function(e){t.atrule(n[1],n[2],e)})(r):!n[3]&&/^(?:font-face|viewport)$/.test(n[2])?flatIter(function(r){t.atrule(n[1],n[2],n[3],1),declarations(e,t,"",r,l),t._atrule()})(r):n[3]&&/^(?:media|supports|page|keyframes)$/.test(n[2])?(l&&"keyframes"==n[2]&&(n[3]=n[3].replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,e.localizeReplacer)),t.atrule(n[1],n[2],n[3],1),"page"==n[2]?declarations(e,t,"",r,l):rules(e,t,"keyframes"==n[2]?"":a,r,l,i+1),t._atrule()):t.err("Unsupported at-rule: "+n[0])}function rules(e,t,n,r,a,l){var i,o,s,c;switch(type.call(r)){case OBJECT:for(i in r)if(own.call(r,i))if(o=r[i],n.length>0&&/^[-\w$]+$/.test(i))if(s||(s=1,t.rule(n)),/\$/.test(i))for(c in i=i.split("$"))own.call(i,c)&&declarations(e,t,i[c],o,a);else declarations(e,t,i,o,a);else/^@/.test(i)?(s=0,atRules(e,t,/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(i)||[i,"@","",""],o,n,a,l)):(s=0,rules(e,t,n.length>0&&(/,/.test(n)||/,/.test(i))?(c=splitSelector(n),splitSelector(a?i.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):i).map(function(e){return/&/.test(e)?ampersand(e,c):c.map(function(t){return t+e}).join(",")}).join(",")):/&/.test(i)?ampersand(a?i.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):i,[n]):n+(a?i.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):i),o,a,l+1));break;case ARRAY:for(i=0;i<r.length;i++)rules(e,t,n,r[i],a,l);break;case STRING:n.length||t.err("No selector"),t.rule(n||" "),declarations(e,t,"",r,a)}}function closeSelectors(e,t){var n;return t?e:{init:function(){n=0,e.init()},done:function(t){return n&&(e._rule(),n=0),e.done(t)},atrule:function(t,r,a,l){n&&(e._rule(),n=0),e.atrule(t,r,a,l)},_atrule:function(t){n&&(e._rule(),n=0),e._atrule(t)},rule:function(t){t!==n&&(n&&e._rule(),e.rule(t),n=t)}}}function global(e){return":global("+e+")"}function kv(e,t,n){return n={},n[e]=t,n}function at(e,t,n){if(arguments.length<3){var r=at.bind.apply(at,[null].concat([].slice.call(arguments,0)));return r.toString=function(){return"@"+e+" "+t},r}return kv("@"+e+" "+t,n)}function j2c(){function e(e){if(!f.length){i.push(function(e,t){return t?{init:l.init,decl:l.decl,done:l.done,err:l.err}:l});for(var t=0;t<2;t++)for(var n=i.length;n--;)f[t]=freeze(defaults(i[n](f[t],!!t),f[t]))}return f[e]}function t(e){return s.names[e]||(s.names[e]=e+s.suffix),s.names[e].match(/^\S+/)}function n(e,n,r,a,l){return n||r||a+t(l)}var r,a,l={init:function(){r=[],a=[]},done:function(e){if(0!=a.length)throw new Error("j2c error(s): "+JSON.stringify(a,null,2)+"in context:\n"+r.join(""));return e?r:r.join("")},err:function(e){a.push(e),r.push("/* +++ ERROR +++ "+e+" */\n")},atrule:function(e,t,n,a){r.push(e,n&&" ",n,a?" {":";",s.endline)},_atrule:function(){r.push("}",s.endline)},rule:function(e){r.push(e," {",s.endline)},_rule:function(){r.push("}",s.endline)},decl:function(e,t){r.push(e,e&&":",t,";",s.endline)}},i=[closeSelectors],o=[],s={at:at,global:global,kv:kv,names:{},endline:"\n",suffix:"__j2c-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36),$plugins:[],sheet:function(t){var n=e(0);return n.init(),rules(c[0],n,"",t,1,0),n.done()},inline:function(t,n){var r=e(1);return r.init(),declarations(c[1],r,"",t,!(n&&n.global)),r.done()}},c=[{localizeReplacer:n,localize:t,names:s.names,$atHandlers:o,atrule:atRules,decl:declarations,rule:rules},{localizeReplacer:n,localize:t,names:s.names,decl:declarations}],u=flatIter(function(e){~s.$plugins.indexOf(e)||(s.$plugins.push(e),type.call(e)===FUNCTION&&(e=e(s)),e&&(flatIter(function(e){i.push(e)})(e.$filter||emptyArray),flatIter(function(e){o.push(e)})(e.$at||emptyArray),defaults(s.names,e.$names||emptyObject),u(e.$plugins||emptyArray),l=e.$sink||l,defaults(s,e)))}),f=[];return u(emptyArray.slice.call(arguments)),s}var emptyArray=[],emptyObject={},type=emptyObject.toString,ARRAY=type.call(emptyArray),OBJECT=type.call(emptyObject),STRING=type.call(""),FUNCTION=type.call(type),own=emptyObject.hasOwnProperty,freeze=Object.freeze||function(e){return e},selectorTokenizer=/[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,ampersandTokenizer=/&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g;module.exports=j2c; |
@@ -10,5 +10,7 @@ var emptyArray = []; | ||
var freeze = Object.freeze || function(o) {return o}; | ||
function Default(target, source) { | ||
function defaults(target, source) { | ||
for (var k in source) if (own.call(source, k)) { | ||
if (k.indexOf('$') && !(k in target)) target[k] = source[k] | ||
if (k.indexOf('$') && !(k in target)) target[k] = source[k]; | ||
} | ||
@@ -19,6 +21,6 @@ return target | ||
function cartesian(a,b) { | ||
var res = [], i, j | ||
var res = [], i, j; | ||
for (j in b) if(own.call(b, j)) | ||
for (i in a) if(own.call(a, i)) | ||
res.push(a[i] + b[j]) | ||
res.push(a[i] + b[j]); | ||
return res | ||
@@ -32,3 +34,3 @@ } | ||
// regexp generated by scripts/regexps.js then trimmed by hand | ||
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; | ||
@@ -39,2 +41,3 @@ | ||
* ignoring comas in strings, comments and in :pseudo-selectors(parameter, lists). | ||
* | ||
* @param {string} selector | ||
@@ -45,3 +48,3 @@ * @return {string[]} | ||
function splitSelector(selector) { | ||
var indices = [], res = [], inParen = 0, o | ||
var indices = [], res = [], inParen = 0, o; | ||
/*eslint-disable no-cond-assign*/ | ||
@@ -53,32 +56,32 @@ while (o = selectorTokenizer.exec(selector)) { | ||
case ')': inParen--; break | ||
case ',': if (inParen) break; indices.push(o.index) | ||
case ',': if (inParen) break; indices.push(o.index); | ||
} | ||
} | ||
for (o = indices.length; o--;){ | ||
res.unshift(selector.slice(indices[o] + 1)) | ||
selector = selector.slice(0, indices[o]) | ||
res.unshift(selector.slice(indices[o] + 1)); | ||
selector = selector.slice(0, indices[o]); | ||
} | ||
res.unshift(selector) | ||
res.unshift(selector); | ||
return res | ||
} | ||
// This is like the `selectorTokenizer`, but for the `&` operator | ||
// Like the `selectorTokenizer`, but for the `&` operator | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
function ampersand (selector, parents) { | ||
var indices = [], split = [], res, o | ||
var indices = [], split = [], res, o; | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = ampersandTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
if (o[0] == '&') indices.push(o.index) | ||
if (o[0] == '&') indices.push(o.index); | ||
} | ||
for (o = indices.length; o--;){ | ||
split.unshift(selector.slice(indices[o] + 1)) | ||
selector = selector.slice(0, indices[o]) | ||
split.unshift(selector.slice(indices[o] + 1)); | ||
selector = selector.slice(0, indices[o]); | ||
} | ||
split.unshift(selector) | ||
res = [split[0]] | ||
split.unshift(selector); | ||
if (split.length === 1) split.unshift(''); | ||
res = [split[0]]; | ||
for (o = 1; o < split.length; o++) { | ||
res = cartesian(res, cartesian(parents, [split[o]])) | ||
res = cartesian(res, cartesian(parents, [split[o]])); | ||
} | ||
@@ -90,4 +93,4 @@ return res.join(',') | ||
return function iter(arg) { | ||
if (type.call(arg) === ARRAY) for (var i= 0 ; i < arg.length; i ++) iter(arg[i]) | ||
else f(arg) | ||
if (type.call(arg) === ARRAY) for (var i= 0 ; i < arg.length; i ++) iter(arg[i]); | ||
else f(arg); | ||
} | ||
@@ -113,3 +116,3 @@ } | ||
function declarations(state, emit, prefix, o, local) { | ||
var k, v, kk | ||
var k, v, kk; | ||
if (o==null) return | ||
@@ -121,3 +124,3 @@ | ||
declarations(state, emit, prefix, o[k], local) | ||
declarations(state, emit, prefix, o[k], local); | ||
@@ -128,9 +131,9 @@ break | ||
// of the declarations list. | ||
prefix = (prefix && prefix + '-') | ||
prefix = (prefix && prefix + '-'); | ||
for (k in o) if (own.call(o, k)){ | ||
v = o[k] | ||
v = o[k]; | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
declarations(state, emit, prefix + k[kk], v, local) | ||
declarations(state, emit, prefix + k[kk], v, local); | ||
@@ -140,3 +143,3 @@ } | ||
declarations(state, emit, prefix + k, v, local) | ||
declarations(state, emit, prefix + k, v, local); | ||
@@ -155,3 +158,3 @@ } | ||
// restore the dashes | ||
k = prefix.replace(/_/g, '-').replace(/[A-Z]/g, decamelize) | ||
k = prefix.replace(/_/g, '-').replace(/[A-Z]/g, decamelize); | ||
@@ -163,8 +166,8 @@ if (local && (k == 'animation-name' || k == 'animation' || k == 'list-style')) { | ||
return o.replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, state.L) | ||
return o.replace(/^\s*(?:(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*))/, state.localizeReplacer) | ||
}).join(',') | ||
}).join(','); | ||
} | ||
emit.d(k, o) | ||
emit.decl(k, o); | ||
@@ -175,3 +178,3 @@ } | ||
/** | ||
* Hanldes at-rules | ||
* Handles a single at-rules | ||
* | ||
@@ -183,4 +186,8 @@ * @param {object} state - holds the localizer- and walker-related methods | ||
* if takes both parameters and a block. | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* k == [match, fullAtRule, atRuleType, params?] | ||
* So in `@-webkit-keyframes foo`, we have | ||
* - match = "@-webkit-keyframes foo" | ||
* - fullAtRule = "@-webkit-keyframes" | ||
* - atRuleType = "keyframes" | ||
* - params = "foo" | ||
* @param {string|string[]|object|object[]} v - Either parameters for | ||
@@ -190,11 +197,14 @@ * block-less rules or | ||
* for the others. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
* @param {string} nestingDepth - are we nested in an at-rule or a selector? | ||
*/ | ||
function atRules(state, emit, k, v, prefix, local, inAtRule) { | ||
function atRules(state, emit, k, v, prefix, local, nestingDepth) { | ||
for (var i = 0; i < state.$a.length; i++) { | ||
// First iterate over user-provided at-rules and return if one of them corresponds to the current one | ||
for (var i = 0; i < state.$atHandlers.length; i++) { | ||
if (state.$a[i](state, emit, k, v, prefix, local, inAtRule)) return | ||
if (state.$atHandlers[i](state, emit, k, v, prefix, local, nestingDepth)) return | ||
@@ -204,3 +214,3 @@ } | ||
// using `/^global$/.test(k[2])` rather that 'global' == k[2] gzips | ||
// slightly better because of the regexps test further down. | ||
// slightly better thanks to the regexps tests further down. | ||
// It is slightly less efficient but this isn't a critical path. | ||
@@ -210,3 +220,3 @@ | ||
rules(state, emit, prefix, v, 0, inAtRule) | ||
rules(state, emit, prefix, v, 0, nestingDepth); | ||
@@ -216,3 +226,3 @@ | ||
rules(state, emit, prefix, v, 1, inAtRule) | ||
rules(state, emit, prefix, v, 1, nestingDepth); | ||
@@ -222,19 +232,19 @@ | ||
if (!local || inAtRule) return emit.a('@-error-bad-at-adopt-placement' , JSON.stringify(k[0]), 0) | ||
if (!local || nestingDepth) return emit.err('@adopt global or nested: ' + k[0]) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.a('@-error-bad-at-adopter', k[3], 0) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.err('bad adopter ' + JSON.stringify(k[3]) + ' in ' + k[0]) | ||
i = [] | ||
i = []; | ||
flatIter(function(adoptee, asString) { | ||
if(!/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee.toString())) emit.a('@-error-bad-at-adoptee', JSON.stringify(adoptee), 0) | ||
if(adoptee == null || !/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee + '')) emit.err('bad adoptee '+ JSON.stringify(adoptee) + ' in ' + k[0]); | ||
else i.push(asString.replace(/\./g, '')) | ||
else i.push(asString.replace(/\./g, '')); | ||
})(v) | ||
})(v); | ||
// we may end up with duplicate classes but AFAIK it has no consequences on specificity. | ||
if (i.length) { | ||
state.l(k[3] = k[3].replace(/\./g, '')) | ||
state.n[k[3]] += (' ' + i.join(' ')) | ||
state.localize(k[3] = k[3].replace(/\./g, '')); | ||
state.names[k[3]] += (' ' + i.join(' ')); | ||
} | ||
@@ -246,5 +256,5 @@ | ||
emit.a(k[0], v) | ||
emit.atrule(k[1], k[2], v); | ||
})(v) | ||
})(v); | ||
@@ -255,9 +265,9 @@ | ||
emit.a(k[1], '', 1) | ||
emit.atrule(k[1], k[2], k[3], 1); | ||
declarations(state, emit, '', v, local) | ||
declarations(state, emit, '', v, local); | ||
emit.A(k[1], '') | ||
emit._atrule(); | ||
})(v) | ||
})(v); | ||
@@ -270,12 +280,12 @@ } else if (k[3] && /^(?:media|supports|page|keyframes)$/.test(k[2])) { | ||
/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, | ||
state.L | ||
) | ||
state.localizeReplacer | ||
); | ||
} | ||
emit.a(k[1], k[3], 1) | ||
emit.atrule(k[1], k[2], k[3], 1); | ||
if ('page' == k[2]) { | ||
declarations(state, emit, '', v, local) | ||
declarations(state, emit, '', v, local); | ||
@@ -287,12 +297,12 @@ } else { | ||
'keyframes' == k[2] ? '' : prefix, | ||
v, local, 1 | ||
) | ||
v, local, nestingDepth + 1 | ||
); | ||
} | ||
emit.A(k[1], k[3]) | ||
emit._atrule(); | ||
} else { | ||
emit.a('@-error-unsupported-at-rule', JSON.stringify(k[0])) | ||
emit.err('Unsupported at-rule: ' + k[0]); | ||
@@ -310,7 +320,7 @@ } | ||
* @param {array|string|object} tree - a source object or sub-object. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {string} nestingDepth - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
function rules(state, emit, prefix, tree, local, inAtRule) { | ||
var k, v, inDeclaration, kk | ||
function rules(state, emit, prefix, tree, local, nestingDepth) { | ||
var k, v, inDeclaration, kk; | ||
@@ -321,9 +331,9 @@ switch (type.call(tree)) { | ||
for (k in tree) if (own.call(tree, k)) { | ||
v = tree[k] | ||
v = tree[k]; | ||
if (prefix.length > 0 && /^[-\w$]+$/.test(k)) { | ||
if (!inDeclaration) { | ||
inDeclaration = 1 | ||
inDeclaration = 1; | ||
emit.s(prefix) | ||
emit.rule(prefix); | ||
@@ -334,3 +344,3 @@ } | ||
declarations(state, emit, k[kk], v, local) | ||
declarations(state, emit, k[kk], v, local); | ||
@@ -340,3 +350,3 @@ } | ||
declarations(state, emit, k, v, local) | ||
declarations(state, emit, k, v, local); | ||
@@ -347,20 +357,20 @@ } | ||
// Handle At-rules | ||
inDeclaration = 0 | ||
inDeclaration = 0; | ||
atRules(state, emit, | ||
/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(k) || [k,'@','',''], | ||
v, prefix, local, inAtRule | ||
) | ||
v, prefix, local, nestingDepth | ||
); | ||
} else { | ||
// selector or nested sub-selectors | ||
inDeclaration = 0 | ||
inDeclaration = 0; | ||
rules( | ||
state, emit, | ||
// `prefix` ... Hefty. Ugly. Sadly necessary. | ||
// | ||
(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
// build the selector `prefix` for the next iteration. | ||
// ugly and full of redundant bits but so far the fastest/shortest.gz | ||
/*0 if*/(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
/*0*/ (kk = splitSelector(prefix), splitSelector( | ||
/*0 then*/ (kk = splitSelector(prefix), splitSelector( | ||
local ? | ||
@@ -370,3 +380,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -381,5 +391,5 @@ | ||
/*0*/ /&/.test(k) ? | ||
/*0 else*/ /*1 if*/ /&/.test(k) ? | ||
/*1*/ ampersand( | ||
/*1 then*/ ampersand( | ||
local ? | ||
@@ -389,3 +399,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -397,3 +407,3 @@ | ||
/*1*/ prefix + ( | ||
/*1 else*/ prefix + ( | ||
local ? | ||
@@ -403,3 +413,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -409,4 +419,4 @@ | ||
), | ||
v, local, inAtRule | ||
) | ||
v, local, nestingDepth + 1 | ||
); | ||
@@ -421,3 +431,3 @@ } | ||
rules(state, emit, prefix, tree[k], local, inAtRule) | ||
rules(state, emit, prefix, tree[k], local, nestingDepth); | ||
@@ -429,7 +439,7 @@ } | ||
// CSS hacks or ouptut of `j2c.inline`. | ||
if (!prefix.length) emit.err('No selector'); | ||
emit.rule(prefix || ' '); | ||
emit.s(prefix.length > 0 ? prefix : ':-error-no-selector') | ||
declarations(state, emit, '', tree, local); | ||
declarations(state, emit, '', tree, local) | ||
} | ||
@@ -445,28 +455,27 @@ } | ||
// contains arrays. | ||
// There's no `S` handler, because the core compiler never | ||
// There's no `_rule` handler, because the core compiler never | ||
// calls it. | ||
function closeSelectors(next, inline) { | ||
var lastSelector | ||
var lastSelector; | ||
return inline ? next : { | ||
i: function(){lastSelector = 0; next.i()}, | ||
x: function (raw) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
return next.x(raw) | ||
init: function(){lastSelector = 0; next.init();}, | ||
done: function (raw) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
return next.done(raw) | ||
}, | ||
a: function (rule, param, takesBlock) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.a(rule, param, takesBlock) | ||
atrule: function (rule, kind, param, takesBlock) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
next.atrule(rule, kind, param, takesBlock); | ||
}, | ||
A: function (rule) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.A(rule) | ||
_atrule: function (rule) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
next._atrule(rule); | ||
}, | ||
s: function (selector) { | ||
rule: function (selector) { | ||
if (selector !== lastSelector){ | ||
if (lastSelector) next.S() | ||
next.s(selector) | ||
lastSelector = selector | ||
if (lastSelector) next._rule(); | ||
next.rule(selector); | ||
lastSelector = selector; | ||
} | ||
}, | ||
d: next.d | ||
} | ||
} | ||
@@ -480,4 +489,4 @@ } | ||
function kv (k, v, o) { | ||
o = {} | ||
o[k] = v | ||
o = {}; | ||
o[k] = v; | ||
return o | ||
@@ -491,5 +500,5 @@ } | ||
// inner curry! | ||
var _at = at.bind.apply(at, [null].concat([].slice.call(arguments,0))) | ||
var _at = at.bind.apply(at, [null].concat([].slice.call(arguments,0))); | ||
// So that it can be used as a key in an ES6 object literal. | ||
_at.toString = function(){return '@' + rule + ' ' + params} | ||
_at.toString = function(){return '@' + rule + ' ' + params}; | ||
return _at | ||
@@ -502,28 +511,32 @@ } | ||
// palceholder for the buffer used by the `$sink` handlers | ||
var buf | ||
// the buffer that accumulates the output. Initialized in `$sink.i()` | ||
var buf, err; | ||
// the bottom of the 'codegen' stream. Mirrors the `$filter` plugin API. | ||
var $sink = { | ||
// Init | ||
i: function(){buf=[]}, | ||
// done (eXit) | ||
x: function (raw) {return raw ? buf : buf.join('')}, | ||
// start At-rule | ||
a: function (rule, argument, takesBlock) { | ||
buf.push(rule, argument && ' ',argument, takesBlock ? ' {\n' : ';\n') | ||
init: function(){buf=[], err=[];}, | ||
done: function (raw) { | ||
if (err.length != 0) throw new Error('j2c error(s): ' + JSON.stringify(err,null,2) + 'in context:\n' + buf.join('')) | ||
return raw ? buf : buf.join('') | ||
}, | ||
// end At-rule | ||
A: function () {buf.push('}\n')}, | ||
// start Selector | ||
s: function (selector) {buf.push(selector, ' {\n')}, | ||
// end Selector | ||
S: function () {buf.push('}\n')}, | ||
// declarations | ||
d: function (prop, value) {buf.push(prop, prop && ':', value, ';\n')} | ||
} | ||
err: function(msg) { | ||
err.push(msg); | ||
buf.push('/* +++ ERROR +++ ' + msg + ' */\n'); | ||
}, | ||
atrule: function (rule, kind, param, takesBlock) { | ||
buf.push(rule, param && ' ', param, takesBlock ? ' {' : ';', _instance.endline); | ||
}, | ||
// close atrule | ||
_atrule: function () {buf.push('}', _instance.endline);}, | ||
rule: function (selector) {buf.push(selector, ' {', _instance.endline);}, | ||
// close rule | ||
_rule: function () {buf.push('}', _instance.endline);}, | ||
decl: function (prop, value) {buf.push(prop, prop && ':', value, ';', _instance.endline);} | ||
}; | ||
var $filters = [closeSelectors] | ||
var $atHandlers = [] | ||
// holds the `$filter` and `$at` handlers | ||
var $filters = [closeSelectors]; | ||
var $atHandlers = []; | ||
// the public API (see the main docs) | ||
var _instance = { | ||
@@ -534,3 +547,5 @@ at: at, | ||
names: {}, | ||
endline: '\n', | ||
suffix: '__j2c-' + | ||
// 128 bits of randomness | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
@@ -540,13 +555,32 @@ Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36), | ||
use: function() { | ||
_use(emptyArray.slice.call(arguments)) | ||
return _instance | ||
$plugins: [], | ||
sheet: function(tree) { | ||
var emit = _createOrRetrieveStream(0); | ||
emit.init(); | ||
rules( | ||
_walkers[0], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1, // local, by default | ||
0 // nesting depth | ||
); | ||
return emit.done() | ||
}, | ||
$plugins: [] | ||
} | ||
inline: function (tree, options) { | ||
var emit = _createOrRetrieveStream(1); | ||
emit.init(); | ||
declarations( | ||
_walkers[1], | ||
emit, | ||
'', // prefix | ||
tree, | ||
!(options && options.global) // local, by default | ||
); | ||
return emit.done() | ||
} | ||
}; | ||
var _streams = [] | ||
// The `state` (for the core) / `walker` (for the plugins) tables. | ||
// The `state` (for the core functions) / `walker` (for the plugins) tables. | ||
var _walkers = [ | ||
@@ -556,51 +590,21 @@ // for j2c.sheet | ||
// helpers for locaizing class and animation names | ||
L: _localizeReplacer, // second argument to String.prototype.replace | ||
l: _localize, // mangles local names | ||
n: _instance.names, // local => mangled mapping | ||
$a: $atHandlers, // extra at-rules | ||
localizeReplacer: _localizeReplacer, // second argument to String.prototype.replace | ||
localize: _localize, // mangles local names | ||
names: _instance.names, // local => mangled mapping | ||
$atHandlers: $atHandlers, // extra at-rules | ||
// The core walker methods, to be provided to plugins | ||
a: atRules, | ||
d: declarations, | ||
r: rules | ||
atrule: atRules, | ||
decl: declarations, | ||
rule: rules | ||
}, | ||
// likewise, for j2c.inline (idem with `$a`, `a` and `s` removed) | ||
{ | ||
L: _localizeReplacer, | ||
l: _localize, | ||
n: _instance.names, | ||
d: declarations | ||
localizeReplacer: _localizeReplacer, | ||
localize: _localize, | ||
names: _instance.names, | ||
decl: declarations | ||
} | ||
] | ||
]; | ||
// The main API functions | ||
_instance.sheet = function(tree) { | ||
var emit = _getStream(0) | ||
emit.i() | ||
rules( | ||
_walkers[0], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1, // local, by default | ||
0 // inAtRule | ||
) | ||
return emit.x() | ||
} | ||
_instance.inline = function (tree) { | ||
var emit = _getStream(1) | ||
emit.i() | ||
declarations( | ||
_walkers[1], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1 //local | ||
) | ||
return emit.x() | ||
} | ||
// inner helpers | ||
@@ -615,5 +619,5 @@ | ||
_instance.$plugins.push(plugin) | ||
_instance.$plugins.push(plugin); | ||
if (type.call(plugin) === FUNCTION) plugin = plugin(_instance) | ||
if (type.call(plugin) === FUNCTION) plugin = plugin(_instance); | ||
@@ -623,50 +627,74 @@ if (!plugin) return | ||
flatIter(function(filter) { | ||
$filters.push(filter) | ||
})(plugin.$filter || emptyArray) | ||
$filters.push(filter); | ||
})(plugin.$filter || emptyArray); | ||
flatIter(function(handler) { | ||
$atHandlers.push(handler) | ||
})(plugin.$at || emptyArray) | ||
$atHandlers.push(handler); | ||
})(plugin.$at || emptyArray); | ||
Default(_instance.names, plugin.$names || emptyObject) | ||
defaults(_instance.names, plugin.$names || emptyObject); | ||
_use(plugin.$plugins || emptyArray) | ||
_use(plugin.$plugins || emptyArray); | ||
$sink = plugin.$sink || $sink | ||
$sink = plugin.$sink || $sink; | ||
Default(_instance, plugin) | ||
}) | ||
defaults(_instance, plugin); | ||
}); | ||
function _getStream(inline) { | ||
var _streams = []; | ||
/** | ||
* returns the codegen streams, creating them if necessary | ||
* @param | ||
*/ | ||
function _createOrRetrieveStream(inline) { | ||
// build the stream processors if needed | ||
if (!_streams.length) { | ||
for(var i = 0; i < 2; i++){ | ||
$filters[$filters.length - i] = function(_, inline) {return inline ? {i:$sink.i, d:$sink.d, x:$sink.x} : $sink} | ||
// append the $sink as the ultimate filter | ||
$filters.push(function(_, inline) {return inline ? {init:$sink.init, decl:$sink.decl, done:$sink.done, err: $sink.err} : $sink}); | ||
for(var i = 0; i < 2; i++){ // 0 for j2c.sheet, 1 for j2c.inline | ||
for (var j = $filters.length; j--;) { | ||
_streams[i] = freeze(Default( | ||
$filters[j](_streams[i], !!i, _walkers[i]), | ||
_streams[i] | ||
)) | ||
_streams[i] = freeze( | ||
defaults( | ||
$filters[j](_streams[i], !!i), | ||
_streams[i] | ||
) | ||
); | ||
} | ||
} | ||
} | ||
var res = _streams[inline] | ||
return res | ||
return _streams[inline] | ||
} | ||
/** | ||
* Returns a localized version of a given name. | ||
* Registers the pair in `instnace.name` if needed. | ||
* | ||
* @param {string} name - the name to localize | ||
* @return {string} - the localized version | ||
*/ | ||
function _localize(name) { | ||
if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix | ||
if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix; | ||
return _instance.names[name].match(/^\S+/) | ||
} | ||
function _localizeReplacer(match, string, global, dot, name) { | ||
if (string || global) return string || global | ||
return dot + _localize(name) | ||
/** | ||
* Used as second argument for str.replace(localizeRegex, replacer) | ||
* `ignore`, `global` and `(dot, name)` are mutually exclusive | ||
* | ||
* @param {string} match - the whole match (ignored) | ||
* @param {string|null} ignore - a comment or a string literal | ||
* @param {string|null} global - a global name | ||
* @param {string|null} dot - either '.' for a local class name or the empty string otherwise | ||
* @param {string|null} name - the name to localize | ||
* @return {string} | ||
*/ | ||
function _localizeReplacer(match, ignore, global$$1, dot, name) { | ||
return ignore || global$$1 || dot + _localize(name) | ||
} | ||
_use(emptyArray.slice.call(arguments)); | ||
return _instance | ||
} | ||
var _j2c = j2c() | ||
'sheet|inline|names|at|global|kv|suffix'.split('|').map(function(m){j2c[m] = _j2c[m]}) | ||
export default j2c; | ||
export default j2c; |
var j2c = (function () { | ||
'use strict'; | ||
'use strict'; | ||
var emptyArray = []; | ||
var emptyObject = {}; | ||
var type = emptyObject.toString; | ||
var ARRAY = type.call(emptyArray); | ||
var OBJECT = type.call(emptyObject); | ||
var STRING = type.call(''); | ||
var FUNCTION = type.call(type); | ||
var own = emptyObject.hasOwnProperty; | ||
var freeze = Object.freeze || function(o) {return o}; | ||
function Default(target, source) { | ||
for (var k in source) if (own.call(source, k)) { | ||
if (k.indexOf('$') && !(k in target)) target[k] = source[k] | ||
} | ||
return target | ||
} | ||
var emptyArray = []; | ||
var emptyObject = {}; | ||
var type = emptyObject.toString; | ||
var ARRAY = type.call(emptyArray); | ||
var OBJECT = type.call(emptyObject); | ||
var STRING = type.call(''); | ||
var FUNCTION = type.call(type); | ||
var own = emptyObject.hasOwnProperty; | ||
var freeze = Object.freeze || function(o) {return o}; | ||
function cartesian(a,b) { | ||
var res = [], i, j | ||
for (j in b) if(own.call(b, j)) | ||
for (i in a) if(own.call(a, i)) | ||
res.push(a[i] + b[j]) | ||
return res | ||
function defaults(target, source) { | ||
for (var k in source) if (own.call(source, k)) { | ||
if (k.indexOf('$') && !(k in target)) target[k] = source[k]; | ||
} | ||
return target | ||
} | ||
// "Tokenizes" the selectors into parts relevant for the next function. | ||
// Strings and comments are matched, but ignored afterwards. | ||
// This is not a full tokenizers. It only recognizes comas, parentheses, | ||
// strings and comments. | ||
// regexp generated by scripts/regexps.js then trimmed by hand | ||
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
function cartesian(a,b) { | ||
var res = [], i, j; | ||
for (j in b) if(own.call(b, j)) | ||
for (i in a) if(own.call(a, i)) | ||
res.push(a[i] + b[j]); | ||
return res | ||
} | ||
// "Tokenizes" the selectors into parts relevant for the next function. | ||
// Strings and comments are matched, but ignored afterwards. | ||
// This is not a full tokenizers. It only recognizes comas, parentheses, | ||
// strings and comments. | ||
// regexp generated by scripts/regexps.js then trimmed by hand | ||
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; | ||
/** | ||
* This will split a coma-separated selector list into individual selectors, | ||
* ignoring comas in strings, comments and in :pseudo-selectors(parameter, lists). | ||
* @param {string} selector | ||
* @return {string[]} | ||
*/ | ||
function splitSelector(selector) { | ||
var indices = [], res = [], inParen = 0, o | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = selectorTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
switch (o[0]) { | ||
case '(': inParen++; break | ||
case ')': inParen--; break | ||
case ',': if (inParen) break; indices.push(o.index) | ||
} | ||
/** | ||
* This will split a coma-separated selector list into individual selectors, | ||
* ignoring comas in strings, comments and in :pseudo-selectors(parameter, lists). | ||
* | ||
* @param {string} selector | ||
* @return {string[]} | ||
*/ | ||
function splitSelector(selector) { | ||
var indices = [], res = [], inParen = 0, o; | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = selectorTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
switch (o[0]) { | ||
case '(': inParen++; break | ||
case ')': inParen--; break | ||
case ',': if (inParen) break; indices.push(o.index); | ||
} | ||
for (o = indices.length; o--;){ | ||
res.unshift(selector.slice(indices[o] + 1)) | ||
selector = selector.slice(0, indices[o]) | ||
} | ||
res.unshift(selector) | ||
return res | ||
} | ||
for (o = indices.length; o--;){ | ||
res.unshift(selector.slice(indices[o] + 1)); | ||
selector = selector.slice(0, indices[o]); | ||
} | ||
res.unshift(selector); | ||
return res | ||
} | ||
// This is like the `selectorTokenizer`, but for the `&` operator | ||
// Like the `selectorTokenizer`, but for the `&` operator | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
function ampersand (selector, parents) { | ||
var indices = [], split = [], res, o | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = ampersandTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
if (o[0] == '&') indices.push(o.index) | ||
} | ||
for (o = indices.length; o--;){ | ||
split.unshift(selector.slice(indices[o] + 1)) | ||
selector = selector.slice(0, indices[o]) | ||
} | ||
split.unshift(selector) | ||
res = [split[0]] | ||
for (o = 1; o < split.length; o++) { | ||
res = cartesian(res, cartesian(parents, [split[o]])) | ||
} | ||
return res.join(',') | ||
function ampersand (selector, parents) { | ||
var indices = [], split = [], res, o; | ||
/*eslint-disable no-cond-assign*/ | ||
while (o = ampersandTokenizer.exec(selector)) { | ||
/*eslint-enable no-cond-assign*/ | ||
if (o[0] == '&') indices.push(o.index); | ||
} | ||
function flatIter (f) { | ||
return function iter(arg) { | ||
if (type.call(arg) === ARRAY) for (var i= 0 ; i < arg.length; i ++) iter(arg[i]) | ||
else f(arg) | ||
} | ||
for (o = indices.length; o--;){ | ||
split.unshift(selector.slice(indices[o] + 1)); | ||
selector = selector.slice(0, indices[o]); | ||
} | ||
split.unshift(selector); | ||
if (split.length === 1) split.unshift(''); | ||
res = [split[0]]; | ||
for (o = 1; o < split.length; o++) { | ||
res = cartesian(res, cartesian(parents, [split[o]])); | ||
} | ||
return res.join(',') | ||
} | ||
function decamelize(match) { | ||
return '-' + match.toLowerCase() | ||
function flatIter (f) { | ||
return function iter(arg) { | ||
if (type.call(arg) === ARRAY) for (var i= 0 ; i < arg.length; i ++) iter(arg[i]); | ||
else f(arg); | ||
} | ||
} | ||
/** | ||
* Handles the property:value; pairs. | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {string} prefix - the current property or a prefix in case of nested | ||
* sub-properties. | ||
* @param {array|object|string} o - the declarations. | ||
* @param {boolean} local - are we in @local or in @global scope. | ||
*/ | ||
function decamelize(match) { | ||
return '-' + match.toLowerCase() | ||
} | ||
function declarations(state, emit, prefix, o, local) { | ||
var k, v, kk | ||
if (o==null) return | ||
/** | ||
* Handles the property:value; pairs. | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {string} prefix - the current property or a prefix in case of nested | ||
* sub-properties. | ||
* @param {array|object|string} o - the declarations. | ||
* @param {boolean} local - are we in @local or in @global scope. | ||
*/ | ||
switch ( type.call(o = o.valueOf()) ) { | ||
case ARRAY: | ||
for (k = 0; k < o.length; k++) | ||
function declarations(state, emit, prefix, o, local) { | ||
var k, v, kk; | ||
if (o==null) return | ||
declarations(state, emit, prefix, o[k], local) | ||
switch ( type.call(o = o.valueOf()) ) { | ||
case ARRAY: | ||
for (k = 0; k < o.length; k++) | ||
break | ||
case OBJECT: | ||
// prefix is falsy iif it is the empty string, which means we're at the root | ||
// of the declarations list. | ||
prefix = (prefix && prefix + '-') | ||
for (k in o) if (own.call(o, k)){ | ||
v = o[k] | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
declarations(state, emit, prefix, o[k], local); | ||
declarations(state, emit, prefix + k[kk], v, local) | ||
break | ||
case OBJECT: | ||
// prefix is falsy iif it is the empty string, which means we're at the root | ||
// of the declarations list. | ||
prefix = (prefix && prefix + '-'); | ||
for (k in o) if (own.call(o, k)){ | ||
v = o[k]; | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
} | ||
} else { | ||
declarations(state, emit, prefix + k[kk], v, local); | ||
declarations(state, emit, prefix + k, v, local) | ||
} | ||
} | ||
break | ||
default: | ||
// prefix is falsy when it is "", which means that we're | ||
// at the top level. | ||
// `o` is then treated as a `property:value` pair, or a | ||
// semi-colon-separated list thereof. | ||
// Otherwise, `prefix` is the property name, and | ||
// `o` is the value. | ||
} else { | ||
// restore the dashes | ||
k = prefix.replace(/_/g, '-').replace(/[A-Z]/g, decamelize) | ||
declarations(state, emit, prefix + k, v, local); | ||
if (local && (k == 'animation-name' || k == 'animation' || k == 'list-style')) { | ||
// no need to tokenize here a plain `.split(',')` has all bases covered. | ||
// We may 'localize' a comment, but it's not a big deal. | ||
o = o.split(',').map(function (o) { | ||
} | ||
} | ||
break | ||
default: | ||
// prefix is falsy when it is "", which means that we're | ||
// at the top level. | ||
// `o` is then treated as a `property:value` pair, or a | ||
// semi-colon-separated list thereof. | ||
// Otherwise, `prefix` is the property name, and | ||
// `o` is the value. | ||
return o.replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, state.L) | ||
// restore the dashes | ||
k = prefix.replace(/_/g, '-').replace(/[A-Z]/g, decamelize); | ||
}).join(',') | ||
} | ||
if (local && (k == 'animation-name' || k == 'animation' || k == 'list-style')) { | ||
// no need to tokenize here a plain `.split(',')` has all bases covered. | ||
// We may 'localize' a comment, but it's not a big deal. | ||
o = o.split(',').map(function (o) { | ||
emit.d(k, o) | ||
return o.replace(/^\s*(?:(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*))/, state.localizeReplacer) | ||
}).join(','); | ||
} | ||
} | ||
/** | ||
* Hanldes at-rules | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {array} k - The parsed at-rule, including the parameters, | ||
* if takes both parameters and a block. | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* @param {string|string[]|object|object[]} v - Either parameters for | ||
* block-less rules or | ||
* their block | ||
* for the others. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
emit.decl(k, o); | ||
function atRules(state, emit, k, v, prefix, local, inAtRule) { | ||
} | ||
} | ||
for (var i = 0; i < state.$a.length; i++) { | ||
/** | ||
* Handles a single at-rules | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {array} k - The parsed at-rule, including the parameters, | ||
* if takes both parameters and a block. | ||
* k == [match, fullAtRule, atRuleType, params?] | ||
* So in `@-webkit-keyframes foo`, we have | ||
* - match = "@-webkit-keyframes foo" | ||
* - fullAtRule = "@-webkit-keyframes" | ||
* - atRuleType = "keyframes" | ||
* - params = "foo" | ||
* @param {string|string[]|object|object[]} v - Either parameters for | ||
* block-less rules or | ||
* their block | ||
* for the others. | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
* @param {string} nestingDepth - are we nested in an at-rule or a selector? | ||
*/ | ||
if (state.$a[i](state, emit, k, v, prefix, local, inAtRule)) return | ||
function atRules(state, emit, k, v, prefix, local, nestingDepth) { | ||
} | ||
// First iterate over user-provided at-rules and return if one of them corresponds to the current one | ||
for (var i = 0; i < state.$atHandlers.length; i++) { | ||
// using `/^global$/.test(k[2])` rather that 'global' == k[2] gzips | ||
// slightly better because of the regexps test further down. | ||
// It is slightly less efficient but this isn't a critical path. | ||
if (state.$atHandlers[i](state, emit, k, v, prefix, local, nestingDepth)) return | ||
if (!k[3] && /^global$/.test(k[2])) { | ||
} | ||
rules(state, emit, prefix, v, 0, inAtRule) | ||
// using `/^global$/.test(k[2])` rather that 'global' == k[2] gzips | ||
// slightly better thanks to the regexps tests further down. | ||
// It is slightly less efficient but this isn't a critical path. | ||
if (!k[3] && /^global$/.test(k[2])) { | ||
} else if (!k[3] && /^local$/.test(k[2])) { | ||
rules(state, emit, prefix, v, 0, nestingDepth); | ||
rules(state, emit, prefix, v, 1, inAtRule) | ||
} else if (!k[3] && /^local$/.test(k[2])) { | ||
} else if (k[3] && /^adopt$/.test(k[2])) { | ||
rules(state, emit, prefix, v, 1, nestingDepth); | ||
if (!local || inAtRule) return emit.a('@-error-bad-at-adopt-placement' , JSON.stringify(k[0]), 0) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.a('@-error-bad-at-adopter', k[3], 0) | ||
} else if (k[3] && /^adopt$/.test(k[2])) { | ||
i = [] | ||
flatIter(function(adoptee, asString) { | ||
if (!local || nestingDepth) return emit.err('@adopt global or nested: ' + k[0]) | ||
if(!/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee.toString())) emit.a('@-error-bad-at-adoptee', JSON.stringify(adoptee), 0) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.err('bad adopter ' + JSON.stringify(k[3]) + ' in ' + k[0]) | ||
else i.push(asString.replace(/\./g, '')) | ||
i = []; | ||
flatIter(function(adoptee, asString) { | ||
})(v) | ||
if(adoptee == null || !/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee + '')) emit.err('bad adoptee '+ JSON.stringify(adoptee) + ' in ' + k[0]); | ||
// we may end up with duplicate classes but AFAIK it has no consequences on specificity. | ||
if (i.length) { | ||
state.l(k[3] = k[3].replace(/\./g, '')) | ||
state.n[k[3]] += (' ' + i.join(' ')) | ||
} | ||
else i.push(asString.replace(/\./g, '')); | ||
})(v); | ||
} else if (!k[3] && /^(?:namespace|import|charset)$/.test(k[2])) { | ||
flatIter(function(v) { | ||
// we may end up with duplicate classes but AFAIK it has no consequences on specificity. | ||
if (i.length) { | ||
state.localize(k[3] = k[3].replace(/\./g, '')); | ||
state.names[k[3]] += (' ' + i.join(' ')); | ||
} | ||
emit.a(k[0], v) | ||
})(v) | ||
} else if (!k[3] && /^(?:namespace|import|charset)$/.test(k[2])) { | ||
flatIter(function(v) { | ||
emit.atrule(k[1], k[2], v); | ||
} else if (!k[3] && /^(?:font-face|viewport)$/.test(k[2])) { | ||
flatIter(function(v) { | ||
})(v); | ||
emit.a(k[1], '', 1) | ||
declarations(state, emit, '', v, local) | ||
} else if (!k[3] && /^(?:font-face|viewport)$/.test(k[2])) { | ||
flatIter(function(v) { | ||
emit.A(k[1], '') | ||
emit.atrule(k[1], k[2], k[3], 1); | ||
})(v) | ||
declarations(state, emit, '', v, local); | ||
} else if (k[3] && /^(?:media|supports|page|keyframes)$/.test(k[2])) { | ||
emit._atrule(); | ||
if (local && 'keyframes' == k[2]) { | ||
k[3] = k[3].replace( | ||
// generated by script/regexps.js | ||
/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, | ||
state.L | ||
) | ||
} | ||
})(v); | ||
} else if (k[3] && /^(?:media|supports|page|keyframes)$/.test(k[2])) { | ||
emit.a(k[1], k[3], 1) | ||
if (local && 'keyframes' == k[2]) { | ||
k[3] = k[3].replace( | ||
// generated by script/regexps.js | ||
/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, | ||
state.localizeReplacer | ||
); | ||
} | ||
if ('page' == k[2]) { | ||
declarations(state, emit, '', v, local) | ||
emit.atrule(k[1], k[2], k[3], 1); | ||
} else { | ||
if ('page' == k[2]) { | ||
rules( | ||
state, emit, | ||
'keyframes' == k[2] ? '' : prefix, | ||
v, local, 1 | ||
) | ||
declarations(state, emit, '', v, local); | ||
} | ||
emit.A(k[1], k[3]) | ||
} else { | ||
emit.a('@-error-unsupported-at-rule', JSON.stringify(k[0])) | ||
rules( | ||
state, emit, | ||
'keyframes' == k[2] ? '' : prefix, | ||
v, local, nestingDepth + 1 | ||
); | ||
} | ||
} | ||
/** | ||
* Add rulesets and other CSS tree to the sheet. | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {string} prefix - the current selector or a prefix in case of nested rules | ||
* @param {array|string|object} tree - a source object or sub-object. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
function rules(state, emit, prefix, tree, local, inAtRule) { | ||
var k, v, inDeclaration, kk | ||
emit._atrule(); | ||
switch (type.call(tree)) { | ||
} else { | ||
case OBJECT: | ||
for (k in tree) if (own.call(tree, k)) { | ||
v = tree[k] | ||
emit.err('Unsupported at-rule: ' + k[0]); | ||
if (prefix.length > 0 && /^[-\w$]+$/.test(k)) { | ||
if (!inDeclaration) { | ||
inDeclaration = 1 | ||
} | ||
} | ||
emit.s(prefix) | ||
/** | ||
* Add rulesets and other CSS tree to the sheet. | ||
* | ||
* @param {object} state - holds the localizer- and walker-related methods | ||
* and state | ||
* @param {object} emit - the contextual emitters to the final buffer | ||
* @param {string} prefix - the current selector or a prefix in case of nested rules | ||
* @param {array|string|object} tree - a source object or sub-object. | ||
* @param {string} nestingDepth - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
function rules(state, emit, prefix, tree, local, nestingDepth) { | ||
var k, v, inDeclaration, kk; | ||
} | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
switch (type.call(tree)) { | ||
declarations(state, emit, k[kk], v, local) | ||
case OBJECT: | ||
for (k in tree) if (own.call(tree, k)) { | ||
v = tree[k]; | ||
} | ||
} else { | ||
if (prefix.length > 0 && /^[-\w$]+$/.test(k)) { | ||
if (!inDeclaration) { | ||
inDeclaration = 1; | ||
declarations(state, emit, k, v, local) | ||
emit.rule(prefix); | ||
} | ||
} | ||
if (/\$/.test(k)) { | ||
for (kk in (k = k.split('$'))) if (own.call(k, kk)) { | ||
} else if (/^@/.test(k)) { | ||
// Handle At-rules | ||
inDeclaration = 0 | ||
declarations(state, emit, k[kk], v, local); | ||
atRules(state, emit, | ||
/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(k) || [k,'@','',''], | ||
v, prefix, local, inAtRule | ||
) | ||
} | ||
} else { | ||
// selector or nested sub-selectors | ||
inDeclaration = 0 | ||
rules( | ||
state, emit, | ||
// `prefix` ... Hefty. Ugly. Sadly necessary. | ||
// | ||
(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
declarations(state, emit, k, v, local); | ||
/*0*/ (kk = splitSelector(prefix), splitSelector( | ||
local ? | ||
} | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
) : | ||
} else if (/^@/.test(k)) { | ||
// Handle At-rules | ||
inDeclaration = 0; | ||
k | ||
).map(function (k) { | ||
return /&/.test(k) ? ampersand(k, kk) : kk.map(function(kk) { | ||
return kk + k | ||
}).join(',') | ||
}).join(',')) : | ||
atRules(state, emit, | ||
/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(k) || [k,'@','',''], | ||
v, prefix, local, nestingDepth | ||
); | ||
/*0*/ /&/.test(k) ? | ||
} else { | ||
// selector or nested sub-selectors | ||
inDeclaration = 0; | ||
/*1*/ ampersand( | ||
local ? | ||
rules( | ||
state, emit, | ||
// build the selector `prefix` for the next iteration. | ||
// ugly and full of redundant bits but so far the fastest/shortest.gz | ||
/*0 if*/(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
) : | ||
/*0 then*/ (kk = splitSelector(prefix), splitSelector( | ||
local ? | ||
k, | ||
[prefix] | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.localizeReplacer | ||
) : | ||
/*1*/ prefix + ( | ||
local ? | ||
k | ||
).map(function (k) { | ||
return /&/.test(k) ? ampersand(k, kk) : kk.map(function(kk) { | ||
return kk + k | ||
}).join(',') | ||
}).join(',')) : | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
) : | ||
/*0 else*/ /*1 if*/ /&/.test(k) ? | ||
k | ||
), | ||
v, local, inAtRule | ||
) | ||
/*1 then*/ ampersand( | ||
local ? | ||
} | ||
} | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.localizeReplacer | ||
) : | ||
break | ||
k, | ||
[prefix] | ||
) : | ||
case ARRAY: | ||
for (k = 0; k < tree.length; k++){ | ||
/*1 else*/ prefix + ( | ||
local ? | ||
rules(state, emit, prefix, tree[k], local, inAtRule) | ||
k.replace( | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.localizeReplacer | ||
) : | ||
k | ||
), | ||
v, local, nestingDepth + 1 | ||
); | ||
} | ||
break | ||
} | ||
case STRING: | ||
// CSS hacks or ouptut of `j2c.inline`. | ||
break | ||
emit.s(prefix.length > 0 ? prefix : ':-error-no-selector') | ||
case ARRAY: | ||
for (k = 0; k < tree.length; k++){ | ||
declarations(state, emit, '', tree, local) | ||
rules(state, emit, prefix, tree[k], local, nestingDepth); | ||
} | ||
} | ||
break | ||
// This is the first entry in the filters array, which is | ||
// actually the last step of the compiler. It inserts | ||
// closing braces to close normal (non at-) rules (those | ||
// that start with a selector). Doing it earlier is | ||
// impossible without passing state around in unrelated code | ||
// or ending up with duplicated selectors when the source tree | ||
// contains arrays. | ||
// There's no `S` handler, because the core compiler never | ||
// calls it. | ||
function closeSelectors(next, inline) { | ||
var lastSelector | ||
return inline ? next : { | ||
i: function(){lastSelector = 0; next.i()}, | ||
x: function (raw) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
return next.x(raw) | ||
}, | ||
a: function (rule, param, takesBlock) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.a(rule, param, takesBlock) | ||
}, | ||
A: function (rule) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.A(rule) | ||
}, | ||
s: function (selector) { | ||
if (selector !== lastSelector){ | ||
if (lastSelector) next.S() | ||
next.s(selector) | ||
lastSelector = selector | ||
} | ||
}, | ||
d: next.d | ||
} | ||
} | ||
case STRING: | ||
// CSS hacks or ouptut of `j2c.inline`. | ||
if (!prefix.length) emit.err('No selector'); | ||
emit.rule(prefix || ' '); | ||
function global(x) { | ||
return ':global(' + x + ')' | ||
} | ||
declarations(state, emit, '', tree, local); | ||
function kv (k, v, o) { | ||
o = {} | ||
o[k] = v | ||
return o | ||
} | ||
} | ||
function at (rule, params, block) { | ||
if ( | ||
arguments.length < 3 | ||
) { | ||
// inner curry! | ||
var _at = at.bind.apply(at, [null].concat([].slice.call(arguments,0))) | ||
// So that it can be used as a key in an ES6 object literal. | ||
_at.toString = function(){return '@' + rule + ' ' + params} | ||
return _at | ||
// This is the first entry in the filters array, which is | ||
// actually the last step of the compiler. It inserts | ||
// closing braces to close normal (non at-) rules (those | ||
// that start with a selector). Doing it earlier is | ||
// impossible without passing state around in unrelated code | ||
// or ending up with duplicated selectors when the source tree | ||
// contains arrays. | ||
// There's no `_rule` handler, because the core compiler never | ||
// calls it. | ||
function closeSelectors(next, inline) { | ||
var lastSelector; | ||
return inline ? next : { | ||
init: function(){lastSelector = 0; next.init();}, | ||
done: function (raw) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
return next.done(raw) | ||
}, | ||
atrule: function (rule, kind, param, takesBlock) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
next.atrule(rule, kind, param, takesBlock); | ||
}, | ||
_atrule: function (rule) { | ||
if (lastSelector) {next._rule(); lastSelector = 0;} | ||
next._atrule(rule); | ||
}, | ||
rule: function (selector) { | ||
if (selector !== lastSelector){ | ||
if (lastSelector) next._rule(); | ||
next.rule(selector); | ||
lastSelector = selector; | ||
} | ||
} | ||
else return kv('@' + rule +' ' + params, block) | ||
} | ||
} | ||
function j2c() { | ||
function global(x) { | ||
return ':global(' + x + ')' | ||
} | ||
// palceholder for the buffer used by the `$sink` handlers | ||
var buf | ||
function kv (k, v, o) { | ||
o = {}; | ||
o[k] = v; | ||
return o | ||
} | ||
// the bottom of the 'codegen' stream. Mirrors the `$filter` plugin API. | ||
var $sink = { | ||
// Init | ||
i: function(){buf=[]}, | ||
// done (eXit) | ||
x: function (raw) {return raw ? buf : buf.join('')}, | ||
// start At-rule | ||
a: function (rule, argument, takesBlock) { | ||
buf.push(rule, argument && ' ',argument, takesBlock ? ' {\n' : ';\n') | ||
}, | ||
// end At-rule | ||
A: function () {buf.push('}\n')}, | ||
// start Selector | ||
s: function (selector) {buf.push(selector, ' {\n')}, | ||
// end Selector | ||
S: function () {buf.push('}\n')}, | ||
// declarations | ||
d: function (prop, value) {buf.push(prop, prop && ':', value, ';\n')} | ||
} | ||
function at (rule, params, block) { | ||
if ( | ||
arguments.length < 3 | ||
) { | ||
// inner curry! | ||
var _at = at.bind.apply(at, [null].concat([].slice.call(arguments,0))); | ||
// So that it can be used as a key in an ES6 object literal. | ||
_at.toString = function(){return '@' + rule + ' ' + params}; | ||
return _at | ||
} | ||
else return kv('@' + rule +' ' + params, block) | ||
} | ||
var $filters = [closeSelectors] | ||
var $atHandlers = [] | ||
function j2c() { | ||
var _instance = { | ||
at: at, | ||
global: global, | ||
kv: kv, | ||
names: {}, | ||
suffix: '__j2c-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36), | ||
use: function() { | ||
_use(emptyArray.slice.call(arguments)) | ||
return _instance | ||
}, | ||
$plugins: [] | ||
} | ||
// the buffer that accumulates the output. Initialized in `$sink.i()` | ||
var buf, err; | ||
var _streams = [] | ||
// the bottom of the 'codegen' stream. Mirrors the `$filter` plugin API. | ||
var $sink = { | ||
init: function(){buf=[], err=[];}, | ||
done: function (raw) { | ||
if (err.length != 0) throw new Error('j2c error(s): ' + JSON.stringify(err,null,2) + 'in context:\n' + buf.join('')) | ||
return raw ? buf : buf.join('') | ||
}, | ||
err: function(msg) { | ||
err.push(msg); | ||
buf.push('/* +++ ERROR +++ ' + msg + ' */\n'); | ||
}, | ||
atrule: function (rule, kind, param, takesBlock) { | ||
buf.push(rule, param && ' ', param, takesBlock ? ' {' : ';', _instance.endline); | ||
}, | ||
// close atrule | ||
_atrule: function () {buf.push('}', _instance.endline);}, | ||
rule: function (selector) {buf.push(selector, ' {', _instance.endline);}, | ||
// close rule | ||
_rule: function () {buf.push('}', _instance.endline);}, | ||
decl: function (prop, value) {buf.push(prop, prop && ':', value, ';', _instance.endline);} | ||
}; | ||
// The `state` (for the core) / `walker` (for the plugins) tables. | ||
// holds the `$filter` and `$at` handlers | ||
var $filters = [closeSelectors]; | ||
var $atHandlers = []; | ||
var _walkers = [ | ||
// for j2c.sheet | ||
{ | ||
// helpers for locaizing class and animation names | ||
L: _localizeReplacer, // second argument to String.prototype.replace | ||
l: _localize, // mangles local names | ||
n: _instance.names, // local => mangled mapping | ||
$a: $atHandlers, // extra at-rules | ||
// The core walker methods, to be provided to plugins | ||
a: atRules, | ||
d: declarations, | ||
r: rules | ||
}, | ||
// likewise, for j2c.inline (idem with `$a`, `a` and `s` removed) | ||
{ | ||
L: _localizeReplacer, | ||
l: _localize, | ||
n: _instance.names, | ||
d: declarations | ||
} | ||
] | ||
// The main API functions | ||
_instance.sheet = function(tree) { | ||
var emit = _getStream(0) | ||
emit.i() | ||
// the public API (see the main docs) | ||
var _instance = { | ||
at: at, | ||
global: global, | ||
kv: kv, | ||
names: {}, | ||
endline: '\n', | ||
suffix: '__j2c-' + | ||
// 128 bits of randomness | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36), | ||
$plugins: [], | ||
sheet: function(tree) { | ||
var emit = _createOrRetrieveStream(0); | ||
emit.init(); | ||
rules( | ||
_walkers[0], | ||
emit, | ||
'', // prefix | ||
'', // prefix | ||
tree, | ||
1, // local, by default | ||
0 // inAtRule | ||
) | ||
1, // local, by default | ||
0 // nesting depth | ||
); | ||
return emit.x() | ||
} | ||
_instance.inline = function (tree) { | ||
var emit = _getStream(1) | ||
emit.i() | ||
return emit.done() | ||
}, | ||
inline: function (tree, options) { | ||
var emit = _createOrRetrieveStream(1); | ||
emit.init(); | ||
declarations( | ||
_walkers[1], | ||
emit, | ||
'', // prefix | ||
'', // prefix | ||
tree, | ||
1 //local | ||
) | ||
return emit.x() | ||
!(options && options.global) // local, by default | ||
); | ||
return emit.done() | ||
} | ||
}; | ||
// inner helpers | ||
// The `state` (for the core functions) / `walker` (for the plugins) tables. | ||
var _walkers = [ | ||
// for j2c.sheet | ||
{ | ||
// helpers for locaizing class and animation names | ||
localizeReplacer: _localizeReplacer, // second argument to String.prototype.replace | ||
localize: _localize, // mangles local names | ||
names: _instance.names, // local => mangled mapping | ||
$atHandlers: $atHandlers, // extra at-rules | ||
// The core walker methods, to be provided to plugins | ||
atrule: atRules, | ||
decl: declarations, | ||
rule: rules | ||
}, | ||
// likewise, for j2c.inline (idem with `$a`, `a` and `s` removed) | ||
{ | ||
localizeReplacer: _localizeReplacer, | ||
localize: _localize, | ||
names: _instance.names, | ||
decl: declarations | ||
} | ||
]; | ||
var _use = flatIter(function(plugin) { | ||
// `~n` is falsy for `n === -1` and truthy otherwise. | ||
// Works well to turn the result of `a.indexOf(x)` | ||
// into a value that reflects the presence of `x` in | ||
// `a`. | ||
if (~_instance.$plugins.indexOf(plugin)) return | ||
_instance.$plugins.push(plugin) | ||
// inner helpers | ||
if (type.call(plugin) === FUNCTION) plugin = plugin(_instance) | ||
var _use = flatIter(function(plugin) { | ||
// `~n` is falsy for `n === -1` and truthy otherwise. | ||
// Works well to turn the result of `a.indexOf(x)` | ||
// into a value that reflects the presence of `x` in | ||
// `a`. | ||
if (~_instance.$plugins.indexOf(plugin)) return | ||
if (!plugin) return | ||
_instance.$plugins.push(plugin); | ||
flatIter(function(filter) { | ||
$filters.push(filter) | ||
})(plugin.$filter || emptyArray) | ||
if (type.call(plugin) === FUNCTION) plugin = plugin(_instance); | ||
flatIter(function(handler) { | ||
$atHandlers.push(handler) | ||
})(plugin.$at || emptyArray) | ||
if (!plugin) return | ||
Default(_instance.names, plugin.$names || emptyObject) | ||
flatIter(function(filter) { | ||
$filters.push(filter); | ||
})(plugin.$filter || emptyArray); | ||
_use(plugin.$plugins || emptyArray) | ||
flatIter(function(handler) { | ||
$atHandlers.push(handler); | ||
})(plugin.$at || emptyArray); | ||
$sink = plugin.$sink || $sink | ||
defaults(_instance.names, plugin.$names || emptyObject); | ||
Default(_instance, plugin) | ||
}) | ||
_use(plugin.$plugins || emptyArray); | ||
function _getStream(inline) { | ||
if (!_streams.length) { | ||
for(var i = 0; i < 2; i++){ | ||
$filters[$filters.length - i] = function(_, inline) {return inline ? {i:$sink.i, d:$sink.d, x:$sink.x} : $sink} | ||
for (var j = $filters.length; j--;) { | ||
_streams[i] = freeze(Default( | ||
$filters[j](_streams[i], !!i, _walkers[i]), | ||
$sink = plugin.$sink || $sink; | ||
defaults(_instance, plugin); | ||
}); | ||
var _streams = []; | ||
/** | ||
* returns the codegen streams, creating them if necessary | ||
* @param | ||
*/ | ||
function _createOrRetrieveStream(inline) { | ||
// build the stream processors if needed | ||
if (!_streams.length) { | ||
// append the $sink as the ultimate filter | ||
$filters.push(function(_, inline) {return inline ? {init:$sink.init, decl:$sink.decl, done:$sink.done, err: $sink.err} : $sink}); | ||
for(var i = 0; i < 2; i++){ // 0 for j2c.sheet, 1 for j2c.inline | ||
for (var j = $filters.length; j--;) { | ||
_streams[i] = freeze( | ||
defaults( | ||
$filters[j](_streams[i], !!i), | ||
_streams[i] | ||
)) | ||
} | ||
) | ||
); | ||
} | ||
} | ||
var res = _streams[inline] | ||
return res | ||
} | ||
return _streams[inline] | ||
} | ||
function _localize(name) { | ||
if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix | ||
return _instance.names[name].match(/^\S+/) | ||
} | ||
/** | ||
* Returns a localized version of a given name. | ||
* Registers the pair in `instnace.name` if needed. | ||
* | ||
* @param {string} name - the name to localize | ||
* @return {string} - the localized version | ||
*/ | ||
function _localize(name) { | ||
if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix; | ||
return _instance.names[name].match(/^\S+/) | ||
} | ||
function _localizeReplacer(match, string, global, dot, name) { | ||
if (string || global) return string || global | ||
return dot + _localize(name) | ||
} | ||
return _instance | ||
/** | ||
* Used as second argument for str.replace(localizeRegex, replacer) | ||
* `ignore`, `global` and `(dot, name)` are mutually exclusive | ||
* | ||
* @param {string} match - the whole match (ignored) | ||
* @param {string|null} ignore - a comment or a string literal | ||
* @param {string|null} global - a global name | ||
* @param {string|null} dot - either '.' for a local class name or the empty string otherwise | ||
* @param {string|null} name - the name to localize | ||
* @return {string} | ||
*/ | ||
function _localizeReplacer(match, ignore, global$$1, dot, name) { | ||
return ignore || global$$1 || dot + _localize(name) | ||
} | ||
var _j2c = j2c() | ||
'sheet|inline|names|at|global|kv|suffix'.split('|').map(function(m){j2c[m] = _j2c[m]}) | ||
_use(emptyArray.slice.call(arguments)); | ||
return _instance | ||
} | ||
return j2c; | ||
return j2c; | ||
}()); | ||
}()); |
@@ -1,1 +0,1 @@ | ||
var j2c=function(){"use strict";function n(n,t){for(var e in t)S.call(t,e)&&(!e.indexOf("$")||e in n||(n[e]=t[e]));return n}function t(n,t){var e,r,a=[];for(r in t)if(S.call(t,r))for(e in n)S.call(n,e)&&a.push(n[e]+t[r]);return a}function e(n){for(var t,e=[],r=[],a=0;t=x.exec(n);)switch(t[0]){case"(":a++;break;case")":a--;break;case",":if(a)break;e.push(t.index)}for(t=e.length;t--;)r.unshift(n.slice(e[t]+1)),n=n.slice(0,e[t]);return r.unshift(n),r}function r(n,e){for(var r,a,i=[],s=[];a=_.exec(n);)"&"==a[0]&&i.push(a.index);for(a=i.length;a--;)s.unshift(n.slice(i[a]+1)),n=n.slice(0,i[a]);for(s.unshift(n),r=[s[0]],a=1;a<s.length;a++)r=t(r,t(e,[s[a]]));return r.join(",")}function a(n){return function t(e){if(d.call(e)===$)for(var r=0;r<e.length;r++)t(e[r]);else n(e)}}function i(n){return"-"+n.toLowerCase()}function s(n,t,e,r,a){var o,l,u;if(null!=r)switch(d.call(r=r.valueOf())){case $:for(o=0;o<r.length;o++)s(n,t,e,r[o],a);break;case v:e=e&&e+"-";for(o in r)if(S.call(r,o))if(l=r[o],/\$/.test(o))for(u in o=o.split("$"))S.call(o,u)&&s(n,t,e+o[u],l,a);else s(n,t,e+o,l,a);break;default:o=e.replace(/_/g,"-").replace(/[A-Z]/g,i),!a||"animation-name"!=o&&"animation"!=o&&"list-style"!=o||(r=r.split(",").map(function(t){return t.replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,n.L)}).join(",")),t.d(o,r)}}function o(n,t,e,r,i,o,u){for(var f=0;f<n.$a.length;f++)if(n.$a[f](n,t,e,r,i,o,u))return;if(!e[3]&&/^global$/.test(e[2]))l(n,t,i,r,0,u);else if(!e[3]&&/^local$/.test(e[2]))l(n,t,i,r,1,u);else if(e[3]&&/^adopt$/.test(e[2])){if(!o||u)return t.a("@-error-bad-at-adopt-placement",JSON.stringify(e[0]),0);if(!/^\.?[_A-Za-z][-\w]*$/.test(e[3]))return t.a("@-error-bad-at-adopter",e[3],0);f=[],a(function(n,e){/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(e=n.toString())?f.push(e.replace(/\./g,"")):t.a("@-error-bad-at-adoptee",JSON.stringify(n),0)})(r),f.length&&(n.l(e[3]=e[3].replace(/\./g,"")),n.n[e[3]]+=" "+f.join(" "))}else!e[3]&&/^(?:namespace|import|charset)$/.test(e[2])?a(function(n){t.a(e[0],n)})(r):!e[3]&&/^(?:font-face|viewport)$/.test(e[2])?a(function(r){t.a(e[1],"",1),s(n,t,"",r,o),t.A(e[1],"")})(r):e[3]&&/^(?:media|supports|page|keyframes)$/.test(e[2])?(o&&"keyframes"==e[2]&&(e[3]=e[3].replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,n.L)),t.a(e[1],e[3],1),"page"==e[2]?s(n,t,"",r,o):l(n,t,"keyframes"==e[2]?"":i,r,o,1),t.A(e[1],e[3])):t.a("@-error-unsupported-at-rule",JSON.stringify(e[0]))}function l(n,t,a,i,u,f){var c,g,p,h;switch(d.call(i)){case v:for(c in i)if(S.call(i,c))if(g=i[c],a.length>0&&/^[-\w$]+$/.test(c))if(p||(p=1,t.s(a)),/\$/.test(c))for(h in c=c.split("$"))S.call(c,h)&&s(n,t,c[h],g,u);else s(n,t,c,g,u);else/^@/.test(c)?(p=0,o(n,t,/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(c)||[c,"@","",""],g,a,u,f)):(p=0,l(n,t,a.length>0&&(/,/.test(a)||/,/.test(c))?(h=e(a),e(u?c.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,n.L):c).map(function(n){return/&/.test(n)?r(n,h):h.map(function(t){return t+n}).join(",")}).join(",")):/&/.test(c)?r(u?c.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,n.L):c,[a]):a+(u?c.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,n.L):c),g,u,f));break;case $:for(c=0;c<i.length;c++)l(n,t,a,i[c],u,f);break;case b:t.s(a.length>0?a:":-error-no-selector"),s(n,t,"",i,u)}}function u(n,t){var e;return t?n:{i:function(){e=0,n.i()},x:function(t){return e&&(n.S(),e=0),n.x(t)},a:function(t,r,a){e&&(n.S(),e=0),n.a(t,r,a)},A:function(t){e&&(n.S(),e=0),n.A(t)},s:function(t){t!==e&&(e&&n.S(),n.s(t),e=t)},d:n.d}}function f(n){return":global("+n+")"}function c(n,t,e){return e={},e[n]=t,e}function g(n,t,e){if(arguments.length<3){var r=g.bind.apply(g,[null].concat([].slice.call(arguments,0)));return r.toString=function(){return"@"+n+" "+t},r}return c("@"+n+" "+t,e)}function p(){function t(t){if(!S.length)for(var e=0;2>e;e++){$[$.length-e]=function(n,t){return t?{i:p.i,d:p.d,x:p.x}:p};for(var r=$.length;r--;)S[e]=A(n($[r](S[e],!!e,x[e]),S[e]))}var a=S[t];return a}function e(n){return b.names[n]||(b.names[n]=n+b.suffix),b.names[n].match(/^\S+/)}function r(n,t,r,a,i){return t||r?t||r:a+e(i)}var i,p={i:function(){i=[]},x:function(n){return n?i:i.join("")},a:function(n,t,e){i.push(n,t&&" ",t,e?" {\n":";\n")},A:function(){i.push("}\n")},s:function(n){i.push(n," {\n")},S:function(){i.push("}\n")},d:function(n,t){i.push(n,n&&":",t,";\n")}},$=[u],v=[],b={at:g,global:f,kv:c,names:{},suffix:"__j2c-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36),use:function(){return _(h.slice.call(arguments)),b},$plugins:[]},S=[],x=[{L:r,l:e,n:b.names,$a:v,a:o,d:s,r:l},{L:r,l:e,n:b.names,d:s}];b.sheet=function(n){var e=t(0);return e.i(),l(x[0],e,"",n,1,0),e.x()},b.inline=function(n){var e=t(1);return e.i(),s(x[1],e,"",n,1),e.x()};var _=a(function(t){~b.$plugins.indexOf(t)||(b.$plugins.push(t),d.call(t)===w&&(t=t(b)),t&&(a(function(n){$.push(n)})(t.$filter||h),a(function(n){v.push(n)})(t.$at||h),n(b.names,t.$names||m),_(t.$plugins||h),p=t.$sink||p,n(b,t)))});return b}var h=[],m={},d=m.toString,$=d.call(h),v=d.call(m),b=d.call(""),w=d.call(d),S=m.hasOwnProperty,A=Object.freeze||function(n){return n},x=/[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,_=/&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,z=p();return"sheet|inline|names|at|global|kv|suffix".split("|").map(function(n){p[n]=z[n]}),p}(); | ||
var j2c=function(){"use strict";function e(e,n){for(var t in n)b.call(n,t)&&(!t.indexOf("$")||t in e||(e[t]=n[t]));return e}function n(e,n){var t,r,l=[];for(r in n)if(b.call(n,r))for(t in e)b.call(e,t)&&l.push(e[t]+n[r]);return l}function t(e){for(var n,t=[],r=[],l=0;n=A.exec(e);)switch(n[0]){case"(":l++;break;case")":l--;break;case",":if(l)break;t.push(n.index)}for(n=t.length;n--;)r.unshift(e.slice(t[n]+1)),e=e.slice(0,t[n]);return r.unshift(e),r}function r(e,t){for(var r,l,a=[],i=[];l=S.exec(e);)"&"==l[0]&&a.push(l.index);for(l=a.length;l--;)i.unshift(e.slice(a[l]+1)),e=e.slice(0,a[l]);for(i.unshift(e),1===i.length&&i.unshift(""),r=[i[0]],l=1;l<i.length;l++)r=n(r,n(t,[i[l]]));return r.join(",")}function l(e){return function n(t){if(m.call(t)===$)for(var r=0;r<t.length;r++)n(t[r]);else e(t)}}function a(e){return"-"+e.toLowerCase()}function i(e,n,t,r,l){var o,u,c;if(null!=r)switch(m.call(r=r.valueOf())){case $:for(o=0;o<r.length;o++)i(e,n,t,r[o],l);break;case _:t=t&&t+"-";for(o in r)if(b.call(r,o))if(u=r[o],/\$/.test(o))for(c in o=o.split("$"))b.call(o,c)&&i(e,n,t+o[c],u,l);else i(e,n,t+o,u,l);break;default:o=t.replace(/_/g,"-").replace(/[A-Z]/g,a),!l||"animation-name"!=o&&"animation"!=o&&"list-style"!=o||(r=r.split(",").map(function(n){return n.replace(/^\s*(?:(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*))/,e.localizeReplacer)}).join(",")),n.decl(o,r)}}function o(e,n,t,r,a,o,c){for(var s=0;s<e.$atHandlers.length;s++)if(e.$atHandlers[s](e,n,t,r,a,o,c))return;if(!t[3]&&/^global$/.test(t[2]))u(e,n,a,r,0,c);else if(!t[3]&&/^local$/.test(t[2]))u(e,n,a,r,1,c);else if(t[3]&&/^adopt$/.test(t[2])){if(!o||c)return n.err("@adopt global or nested: "+t[0]);if(!/^\.?[_A-Za-z][-\w]*$/.test(t[3]))return n.err("bad adopter "+JSON.stringify(t[3])+" in "+t[0]);s=[],l(function(e,r){null!=e&&/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(r=e+"")?s.push(r.replace(/\./g,"")):n.err("bad adoptee "+JSON.stringify(e)+" in "+t[0])})(r),s.length&&(e.localize(t[3]=t[3].replace(/\./g,"")),e.names[t[3]]+=" "+s.join(" "))}else!t[3]&&/^(?:namespace|import|charset)$/.test(t[2])?l(function(e){n.atrule(t[1],t[2],e)})(r):!t[3]&&/^(?:font-face|viewport)$/.test(t[2])?l(function(r){n.atrule(t[1],t[2],t[3],1),i(e,n,"",r,o),n._atrule()})(r):t[3]&&/^(?:media|supports|page|keyframes)$/.test(t[2])?(o&&"keyframes"==t[2]&&(t[3]=t[3].replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,e.localizeReplacer)),n.atrule(t[1],t[2],t[3],1),"page"==t[2]?i(e,n,"",r,o):u(e,n,"keyframes"==t[2]?"":a,r,o,c+1),n._atrule()):n.err("Unsupported at-rule: "+t[0])}function u(e,n,l,a,c,s){var f,p,h,g;switch(m.call(a)){case _:for(f in a)if(b.call(a,f))if(p=a[f],l.length>0&&/^[-\w$]+$/.test(f))if(h||(h=1,n.rule(l)),/\$/.test(f))for(g in f=f.split("$"))b.call(f,g)&&i(e,n,f[g],p,c);else i(e,n,f,p,c);else/^@/.test(f)?(h=0,o(e,n,/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(f)||[f,"@","",""],p,l,c,s)):(h=0,u(e,n,l.length>0&&(/,/.test(l)||/,/.test(f))?(g=t(l),t(c?f.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):f).map(function(e){return/&/.test(e)?r(e,g):g.map(function(n){return n+e}).join(",")}).join(",")):/&/.test(f)?r(c?f.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):f,[l]):l+(c?f.replace(/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g,e.localizeReplacer):f),p,c,s+1));break;case $:for(f=0;f<a.length;f++)u(e,n,l,a[f],c,s);break;case z:l.length||n.err("No selector"),n.rule(l||" "),i(e,n,"",a,c)}}function c(e,n){var t;return n?e:{init:function(){t=0,e.init()},done:function(n){return t&&(e._rule(),t=0),e.done(n)},atrule:function(n,r,l,a){t&&(e._rule(),t=0),e.atrule(n,r,l,a)},_atrule:function(n){t&&(e._rule(),t=0),e._atrule(n)},rule:function(n){n!==t&&(t&&e._rule(),e.rule(n),t=n)}}}function s(e){return":global("+e+")"}function f(e,n,t){return t={},t[e]=n,t}function p(e,n,t){if(arguments.length<3){var r=p.bind.apply(p,[null].concat([].slice.call(arguments,0)));return r.toString=function(){return"@"+e+" "+n},r}return f("@"+e+" "+n,t)}function h(){function n(n){if(!Z.length){_.push(function(e,n){return n?{init:$.init,decl:$.decl,done:$.done,err:$.err}:$});for(var t=0;t<2;t++)for(var r=_.length;r--;)Z[t]=v(e(_[r](Z[t],!!t),Z[t]))}return Z[n]}function t(e){return b.names[e]||(b.names[e]=e+b.suffix),b.names[e].match(/^\S+/)}function r(e,n,r,l,a){return n||r||l+t(a)}var a,h,$={init:function(){a=[],h=[]},done:function(e){if(0!=h.length)throw new Error("j2c error(s): "+JSON.stringify(h,null,2)+"in context:\n"+a.join(""));return e?a:a.join("")},err:function(e){h.push(e),a.push("/* +++ ERROR +++ "+e+" */\n")},atrule:function(e,n,t,r){a.push(e,t&&" ",t,r?" {":";",b.endline)},_atrule:function(){a.push("}",b.endline)},rule:function(e){a.push(e," {",b.endline)},_rule:function(){a.push("}",b.endline)},decl:function(e,n){a.push(e,e&&":",n,";",b.endline)}},_=[c],z=[],b={at:p,global:s,kv:f,names:{},endline:"\n",suffix:"__j2c-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36)+"-"+Math.floor(4294967296*Math.random()).toString(36),$plugins:[],sheet:function(e){var t=n(0);return t.init(),u(A[0],t,"",e,1,0),t.done()},inline:function(e,t){var r=n(1);return r.init(),i(A[1],r,"",e,!(t&&t.global)),r.done()}},A=[{localizeReplacer:r,localize:t,names:b.names,$atHandlers:z,atrule:o,decl:i,rule:u},{localizeReplacer:r,localize:t,names:b.names,decl:i}],S=l(function(n){~b.$plugins.indexOf(n)||(b.$plugins.push(n),m.call(n)===w&&(n=n(b)),n&&(l(function(e){_.push(e)})(n.$filter||g),l(function(e){z.push(e)})(n.$at||g),e(b.names,n.$names||d),S(n.$plugins||g),$=n.$sink||$,e(b,n)))}),Z=[];return S(g.slice.call(arguments)),b}var g=[],d={},m=d.toString,$=m.call(g),_=m.call(d),z=m.call(""),w=m.call(m),b=d.hasOwnProperty,v=Object.freeze||function(e){return e},A=/[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g,S=/&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g;return h}(); |
@@ -5,24 +5,2 @@ # Change log | ||
- Fix: Robust parsing of selectors. Comas, ampersands and class-like parts | ||
in strings are now ignored by the compiler. | ||
```JS | ||
j2c.sheet({'p':{'[foo="&,.bar"]': {color: 'red'}}}) | ||
``` | ||
produces | ||
```CSS | ||
p[foo="&,.bar"] {color:red} | ||
``` | ||
Whereas previous versions would produce | ||
```CSS | ||
[foo="p,p.bar_j2c_ubv4pc_knzcqw_ngjme7_1usit1c_9"] {color: red;} | ||
``` | ||
Likewise, `':not(p, a, ul, li)'` (a CSS4 addition) will not be split. | ||
- Local scope is now per instance rather than per sheet. | ||
@@ -47,4 +25,6 @@ - `j2c.sheet()` and `j2c.inline()` return plain strings rather than | ||
So: `j2c.sheet({'@adopt .foo': ['.bar']})` where foo is a local class that adopts the behavior of the global `.bar`. | ||
- Consecutive, identical selectors are deduped in the output. | ||
So: `j2c.sheet({'@adopt .foo': ['.bar']})` where foo is a local class that | ||
adopts the behavior of the global `.bar`. | ||
- Consecutive, identical selectors are deduped in the output. Using mixins | ||
won't cause duplicate selectors anymore. | ||
- Prefixed at-rules are treated like their unprefixed counterparts. | ||
@@ -55,19 +35,46 @@ - Added the `at()`, `global()` and `kv()` helpers. | ||
like SASS and LESS do. | ||
- Robust parsing of selectors. Comas, ampersands and class-like parts | ||
in strings are now ignored by the compiler. | ||
```JS | ||
j2c.sheet({'p':{'[foo="&,.bar"]': {color: 'red'}}}) | ||
``` | ||
produces | ||
```CSS | ||
p[foo="&,.bar"] {color:red} | ||
``` | ||
Whereas previous versions would produce | ||
```CSS | ||
[foo="p,p.bar_j2c_ubv4pc_knzcqw_ngjme7_1usit1c_9"] {color: red;} | ||
``` | ||
Likewise, `':not(p, a, ul, li)'` (a CSS4 addition) will not be split. | ||
- Added an extension mechanism. | ||
- 2.2Kb mingzipped (+ ~500 bytes). | ||
## v0.11.1 (2016-03-8) | ||
## v0.11.1 (2016-03-8) and v0.11.2 (2016-03-17) | ||
- Patch bump to fix what `npm` installs by default (I erronously published `v1.0.0-0` on without `--tag next`) | ||
- Patch bump to fix what `npm` installs by default (I erronously published ` | ||
v1.0.0-x` on without `--tag next`, twice) Note to self, don't publish in | ||
the wee hours. | ||
## v0.11.0 | ||
- Refactor the innards so that the source order is completely respected in the output, including conditional at-rules. | ||
- Refactor the innards so that the source order is completely respected in | ||
the output, including conditional at-rules. | ||
- Speed ++ | ||
- Autoprefix all animation-* and transition. | ||
- Some error messages are now inserted in the result as -error-prefixed at-rules and :pseudo-classes. | ||
- Some error messages are now inserted in the result as -error-prefixed | ||
at-rules and :pseudo-classes. | ||
## v0.10.0 | ||
- At long last allow element selectors without a prepended space at the top level | ||
- Autoprefix animation and animation-name with -webkit- too like we do for `@keyframes`. | ||
- At long last allow element selectors without a prepended space at the top | ||
level | ||
- Autoprefix animation and animation-name with -webkit- too like we do for | ||
`@keyframes`. | ||
- Tweaks and cleanup | ||
@@ -97,3 +104,4 @@ | ||
- classes and animations/@keyframes names are now localized by default in `j2c.sheet()`. | ||
- classes and animations/@keyframes names are now localized by default in | ||
`j2c.sheet()`. | ||
- introduced `@global{}` and `:global()` to reach global names | ||
@@ -104,11 +112,15 @@ - dropped `j2c.scoped()` which is obsoleted by the above. | ||
- support for autoDeCamelization of property-names. | ||
- New signature for `j2c.sheet([namespace1, namespace2, ] source)` where `namespace` is an object | ||
with plain -> localized names for classes and animations. | ||
- allow to create custom j2c instances that can be extended with plugins *[needs docs]*. | ||
- New signature for `j2c.sheet([namespace1, namespace2, ] source)` where | ||
`namespace` is an object with plain -> localized names for classes and | ||
animations. | ||
- allow to create custom j2c instances that can be extended with plugins | ||
*[needs docs]*. | ||
- Hardened the test suite. | ||
- Bug fix: the source order is now respected in the output, with the caveat that, for nested selector, the children appear in source before the parent. | ||
- Bug fix: the source order is now respected in the output, with the caveat | ||
that, for nested selector, the children appear in source before the parent. | ||
## v0.7.3 | ||
- Identical to `v0.7.2`. Somehow a bad commit ended up on NPM for that version. | ||
- Identical to `v0.7.2`. Somehow a bad commit ended up on NPM for that | ||
version. | ||
@@ -115,0 +127,0 @@ ## v0.7.2 |
{ | ||
"name": "j2c", | ||
"version": "1.0.0-3", | ||
"version": "1.0.0-4", | ||
"description": "A tiny CSS in JS solution.", | ||
"main": "dist/j2c.commonjs.js", | ||
"scripts": { | ||
"preversion": "npm run all", | ||
"preversion": "yarn run all", | ||
"prepublish": "(in-publish && git push --follow-tags) || not-in-publish", | ||
"all": "npm run build && npm run lint && npm run cover", | ||
"dev": "npm run build && npm run test", | ||
"all": "yarn run build && yarn run lint && yarn run cover", | ||
"dev": "yarn run build && yarn run test", | ||
"build": "rm -f dist/*.js && node scripts/build.js", | ||
"lint": "eslint --fix src/*.js test/test.js scripts/*.js", | ||
"test": "mocha --ui qunit", | ||
"cover": "istanbul cover _mocha -- -R nyan --ui qunit && npm run -s check-coverage", | ||
"lint": "eslint --fix .", | ||
"test": "ospec", | ||
"cover": "istanbul cover --print both node_modules/.bin/ospec && yarn run check-coverage", | ||
"check-coverage": "istanbul check-coverage --branches -2", | ||
"travis": "npm run build && istanbul cover _mocha --report lcovonly -- -R spec --ui qunit && (codecov || true) && npm run -s check-coverage" | ||
"travis": "yarn run build && istanbul cover --print both node_modules/.bin/ospec && (codecov || true) && yarn run check-coverage" | ||
}, | ||
@@ -33,12 +33,11 @@ "repository": { | ||
"devDependencies": { | ||
"cash-true": "0.0.2", | ||
"codecov": "^1.0.1", | ||
"commonmark": "^0.24.0", | ||
"commonmark": "^0.27.0", | ||
"compose-regexp": "^0.1.8", | ||
"eslint": "^2.2.0", | ||
"expect.js": "0.3.1", | ||
"eslint": "^3.12.0", | ||
"in-publish": "^2.0.0", | ||
"istanbul": "^0.4.2", | ||
"jsdom": "^8.1.0", | ||
"mocha": "^2.3.4", | ||
"mocha-lcov-reporter": "^1.0.0", | ||
"jsdom": "^9.8.3", | ||
"ospec": "^1.2.1", | ||
"perfectionist": "^2.1.2", | ||
@@ -48,6 +47,6 @@ "postcss": "^5.0.14", | ||
"postcss-minify-selectors": "^2.0.2", | ||
"rollup": "^0.25.2", | ||
"surgicate": "0.0.3", | ||
"uglify-js": "^2.6.0" | ||
"rollup": "^0.36.4", | ||
"uglify-js": "^2.6.0", | ||
"yarn": "^0.18.1" | ||
} | ||
} |
# `j2c` Plugin author notes | ||
A plugin can be an object, a function or an array of plugins (nested arrays are thus supported). | ||
Out of the box, `j2c` is made of a frontend that walks a JS objets/arrays tree and calls the backend when necessary to emit atrules, rules and declarations. | ||
The default backend fills a buffer with strings and `joins` them on completion. | ||
`j2c` plugin can either tap into the frontend (by implementing custom at-rules), replace the backend, and insert middleware filters in between. | ||
We'll process backwards and start by describing the backend, since understanding how it works is required to write filters and useful to write custom at-rules. | ||
## `$sink` plugins: replace the backend | ||
A `j2c` backend mus provide the following API: | ||
```JS | ||
_j2c = j2c().use( | ||
{ | ||
init() {}, | ||
// called on `j2c.sheet()/j2c.inline()` invocations before | ||
// the sheet is processed. | ||
done() {}, | ||
// called when the tree traversal is finished, to finalize | ||
// the style sheet | ||
err(message) {}, | ||
// called when an error is noticed, allows to display errors | ||
// in context. | ||
decl(property, value), | ||
// called to insert a declaration into the sheet | ||
rule(selector) {}, | ||
// called to open a rule with a given selector | ||
_rule() {}, | ||
// called to signal the end of a ruleset | ||
atrule(rule, kind, param, takesBlock) | ||
// called when an atrule is encountered. | ||
// `rule` is the rule name in full includin the '@' and the | ||
// prefix when there's one. e.g. `@-webkit-keyframes` | ||
// `kind` is the type of at-rule, without '@' nor prefix | ||
// e.g. `keyframes` | ||
// `param` is the optional parameter | ||
// `takesBlock` is a boolean that tells whether the rule | ||
// takes a block or not. false for `@namespace`, `@charset` | ||
// and `@import`, true otherwise. | ||
_atrule(){} | ||
// called to signal the end of an atrule block | ||
} | ||
``` | ||
`j2c.inline()` uses the same API but restricted to `init()`, `done()`, `err(msg)` and `decl(property, value)`. | ||
A plugin can be an object, a function or an array of zero or plugins (nested arrays are thus supported). | ||
```JS | ||
_j2c = j2c( | ||
{foo: 1}, | ||
@@ -8,0 +55,0 @@ [ |
@@ -12,2 +12,3 @@ # Warning, WIP: these docs haven't been updated to match the changes since v0.11 | ||
[![bitHound Score][bithound_img]][bithound_url] | ||
[![downloads][monthly_img]][monthly_url] | ||
@@ -29,3 +30,3 @@ [trav_img]: https://travis-ci.org/j2css/j2c.svg?branch=master | ||
A lean (2.0KB), no hassle CSS in JS solution. | ||
A lean (2.2KB), no hassle CSS in JS solution. | ||
@@ -75,2 +76,3 @@ `j2c`: | ||
### `j2c` is mostly done. | ||
@@ -86,3 +88,3 @@ | ||
- @ArthurClemens, @StephanHoyer, @der-On, @llambda, @dontwork, @futurist and @mithriljs-cn for the support and feedback. | ||
- @tivac for `@compose` which I stole from his [Modular CSS]() project. | ||
- @tivac for `compose` which I stole from his [Modular CSS]() project. | ||
@@ -93,3 +95,3 @@ ## Table of Contents | ||
- [Usage](#usage) | ||
- [For inline decalrations: `j2c.inline(declarations)`](#for-inline-decalrations-j2cinlinedeclarations) | ||
- [For inline declarations: `j2c.inline(declarations)`](#for-inline-declarations-j2cinlinedeclarations) | ||
- [Arrays](#arrays) | ||
@@ -180,3 +182,3 @@ - [Overloading properties](#overloading-properties) | ||
### For inline decalrations: `j2c.inline(declarations)` | ||
### For inline declarations: `j2c.inline(declarations)` | ||
@@ -209,3 +211,3 @@ The `j2c` function takes in JS objects and builds a `property:value;` list out of it. | ||
Combine (sub)properties who share the same value using `$` as a separator. It is useful to specify vendor prefixes. | ||
Combine (sub)properties who share the same value by using `$` as a separator. It is useful to specify vendor prefixes. | ||
@@ -378,3 +380,3 @@ #### Property ordering | ||
".block,.blockgroup":{ | ||
",:before,:after":{ // Notice the initial coma. | ||
",:before,:after":{ // Notice the initial comma. | ||
box_sizing:"border-box" | ||
@@ -647,6 +649,5 @@ } | ||
return m("style", { | ||
sheet: args.sheet | ||
config: function(el, isinit, vdom) { | ||
config: function(el, isinit) { | ||
if(!isinit) { | ||
stylize(el, vdom.attrs.sheet); | ||
stylize(el, args.sheet); | ||
} | ||
@@ -653,0 +654,0 @@ } |
@@ -28,3 +28,3 @@ #! /usr/bin/env node | ||
rollupOptions:{ | ||
format: 'es6' | ||
format: 'es' | ||
}, | ||
@@ -31,0 +31,0 @@ name: 'es6', |
/*eslint-env node*/ | ||
/*eslint no-console: 0*/ | ||
/*eslint no-undef: 0*/ | ||
/* global capture: false, either:false, flags: false, greedy:false, sequence: false*/ | ||
global.__proto__ = require('compose-regexp') | ||
var maybe = greedy.bind(null, '?') | ||
maybe() | ||
// var maybe = greedy.bind(null, '?') | ||
var animation = either( | ||
capture( | ||
'var(', | ||
/[^)]+/, | ||
')' | ||
), | ||
sequence( | ||
@@ -26,18 +29,51 @@ /:?/, | ||
var selector = flags('g', either( | ||
sequence( | ||
':global(', | ||
/\s*/, | ||
var selector = flags('g', | ||
either( | ||
capture( | ||
'.', | ||
/-?[_A-Za-z][-\w]*/ | ||
either( | ||
sequence( | ||
'"', | ||
greedy('*', | ||
either( | ||
/\\./, | ||
/[^"\n]/ | ||
) | ||
), | ||
'"' | ||
), | ||
sequence( | ||
"'", | ||
greedy('*', | ||
either( | ||
/\\./, | ||
/[^'\n]/ | ||
) | ||
), | ||
"'" | ||
), | ||
// This is both correct and faster than the W3C regexp. | ||
// https://jsperf.com/regexpcomment | ||
sequence( | ||
'/*', | ||
/[\s\S]*?/, | ||
'*/' | ||
) | ||
) | ||
), | ||
/\s*/, | ||
')' | ||
), | ||
sequence( | ||
capture('.'), | ||
capture(/-?[_A-Za-z][-\w]*/) | ||
sequence( | ||
':global(', | ||
/\s*/, | ||
capture( | ||
'.', | ||
/-?[_A-Za-z][-\w]*/ | ||
), | ||
/\s*/, | ||
')' | ||
), | ||
sequence( | ||
capture('.'), | ||
capture(/-?[_A-Za-z][-\w]*/) | ||
) | ||
) | ||
)) | ||
) | ||
@@ -44,0 +80,0 @@ console.log('selector / @global\n', selector) |
@@ -6,3 +6,3 @@ import {flatIter} from './helpers' | ||
/** | ||
* Hanldes at-rules | ||
* Handles a single at-rules | ||
* | ||
@@ -14,4 +14,8 @@ * @param {object} state - holds the localizer- and walker-related methods | ||
* if takes both parameters and a block. | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* k == [match, fullAtRule, atRuleType, params?] | ||
* So in `@-webkit-keyframes foo`, we have | ||
* - match = "@-webkit-keyframes foo" | ||
* - fullAtRule = "@-webkit-keyframes" | ||
* - atRuleType = "keyframes" | ||
* - params = "foo" | ||
* @param {string|string[]|object|object[]} v - Either parameters for | ||
@@ -21,11 +25,14 @@ * block-less rules or | ||
* for the others. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {string} prefix - the current selector or the selector prefix | ||
* in case of nested rules | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
* @param {string} nestingDepth - are we nested in an at-rule or a selector? | ||
*/ | ||
export function atRules(state, emit, k, v, prefix, local, inAtRule) { | ||
export function atRules(state, emit, k, v, prefix, local, nestingDepth) { | ||
for (var i = 0; i < state.$a.length; i++) { | ||
// First iterate over user-provided at-rules and return if one of them corresponds to the current one | ||
for (var i = 0; i < state.$atHandlers.length; i++) { | ||
if (state.$a[i](state, emit, k, v, prefix, local, inAtRule)) return | ||
if (state.$atHandlers[i](state, emit, k, v, prefix, local, nestingDepth)) return | ||
@@ -35,3 +42,3 @@ } | ||
// using `/^global$/.test(k[2])` rather that 'global' == k[2] gzips | ||
// slightly better because of the regexps test further down. | ||
// slightly better thanks to the regexps tests further down. | ||
// It is slightly less efficient but this isn't a critical path. | ||
@@ -41,3 +48,3 @@ | ||
rules(state, emit, prefix, v, 0, inAtRule) | ||
rules(state, emit, prefix, v, 0, nestingDepth) | ||
@@ -47,3 +54,3 @@ | ||
rules(state, emit, prefix, v, 1, inAtRule) | ||
rules(state, emit, prefix, v, 1, nestingDepth) | ||
@@ -53,5 +60,5 @@ | ||
if (!local || inAtRule) return emit.a('@-error-bad-at-adopt-placement' , JSON.stringify(k[0]), 0) | ||
if (!local || nestingDepth) return emit.err('@adopt global or nested: ' + k[0]) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.a('@-error-bad-at-adopter', k[3], 0) | ||
if (!/^\.?[_A-Za-z][-\w]*$/.test(k[3])) return emit.err('bad adopter ' + JSON.stringify(k[3]) + ' in ' + k[0]) | ||
@@ -61,3 +68,3 @@ i = [] | ||
if(!/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee.toString())) emit.a('@-error-bad-at-adoptee', JSON.stringify(adoptee), 0) | ||
if(adoptee == null || !/^\.?[_A-Za-z][-\w]*(?:\s+\.?[_A-Za-z][-\w]*)*$/.test(asString = adoptee + '')) emit.err('bad adoptee '+ JSON.stringify(adoptee) + ' in ' + k[0]) | ||
@@ -70,4 +77,4 @@ else i.push(asString.replace(/\./g, '')) | ||
if (i.length) { | ||
state.l(k[3] = k[3].replace(/\./g, '')) | ||
state.n[k[3]] += (' ' + i.join(' ')) | ||
state.localize(k[3] = k[3].replace(/\./g, '')) | ||
state.names[k[3]] += (' ' + i.join(' ')) | ||
} | ||
@@ -79,3 +86,3 @@ | ||
emit.a(k[0], v) | ||
emit.atrule(k[1], k[2], v) | ||
@@ -88,7 +95,7 @@ })(v) | ||
emit.a(k[1], '', 1) | ||
emit.atrule(k[1], k[2], k[3], 1) | ||
declarations(state, emit, '', v, local) | ||
emit.A(k[1], '') | ||
emit._atrule() | ||
@@ -103,3 +110,3 @@ })(v) | ||
/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, | ||
state.L | ||
state.localizeReplacer | ||
) | ||
@@ -109,3 +116,3 @@ } | ||
emit.a(k[1], k[3], 1) | ||
emit.atrule(k[1], k[2], k[3], 1) | ||
@@ -121,3 +128,3 @@ if ('page' == k[2]) { | ||
'keyframes' == k[2] ? '' : prefix, | ||
v, local, 1 | ||
v, local, nestingDepth + 1 | ||
) | ||
@@ -127,9 +134,9 @@ | ||
emit.A(k[1], k[3]) | ||
emit._atrule() | ||
} else { | ||
emit.a('@-error-unsupported-at-rule', JSON.stringify(k[0])) | ||
emit.err('Unsupported at-rule: ' + k[0]) | ||
} | ||
} |
@@ -65,3 +65,3 @@ import {own, type, ARRAY, OBJECT} from './helpers' | ||
return o.replace(/(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, state.L) | ||
return o.replace(/^\s*(?:(var\([^)]+\))|:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*))/, state.localizeReplacer) | ||
@@ -71,5 +71,5 @@ }).join(',') | ||
emit.d(k, o) | ||
emit.decl(k, o) | ||
} | ||
} |
@@ -13,3 +13,3 @@ var | ||
function Default(target, source) { | ||
function defaults(target, source) { | ||
for (var k in source) if (own.call(source, k)) { | ||
@@ -40,2 +40,3 @@ if (k.indexOf('$') && !(k in target)) target[k] = source[k] | ||
* ignoring comas in strings, comments and in :pseudo-selectors(parameter, lists). | ||
* | ||
* @param {string} selector | ||
@@ -64,4 +65,3 @@ * @return {string[]} | ||
// This is like the `selectorTokenizer`, but for the `&` operator | ||
// Like the `selectorTokenizer`, but for the `&` operator | ||
var ampersandTokenizer = /&|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g | ||
@@ -81,2 +81,3 @@ | ||
split.unshift(selector) | ||
if (split.length === 1) split.unshift('') | ||
res = [split[0]] | ||
@@ -98,3 +99,3 @@ for (o = 1; o < split.length; o++) { | ||
ARRAY, FUNCTION, OBJECT, STRING, | ||
ampersand, cartesian, Default, | ||
ampersand, cartesian, defaults, | ||
emptyArray, emptyObject, | ||
@@ -101,0 +102,0 @@ flatIter, freeze, own, |
187
src/main.js
@@ -1,2 +0,2 @@ | ||
import {Default, emptyArray, emptyObject, flatIter, freeze, type, FUNCTION} from './helpers' | ||
import {defaults, emptyArray, emptyObject, flatIter, freeze, type, FUNCTION} from './helpers' | ||
import {closeSelectors, rules} from './rules' | ||
@@ -10,28 +10,32 @@ import {declarations} from './declarations' | ||
// palceholder for the buffer used by the `$sink` handlers | ||
var buf | ||
// the buffer that accumulates the output. Initialized in `$sink.i()` | ||
var buf, err | ||
// the bottom of the 'codegen' stream. Mirrors the `$filter` plugin API. | ||
var $sink = { | ||
// Init | ||
i: function(){buf=[]}, | ||
// done (eXit) | ||
x: function (raw) {return raw ? buf : buf.join('')}, | ||
// start At-rule | ||
a: function (rule, argument, takesBlock) { | ||
buf.push(rule, argument && ' ',argument, takesBlock ? ' {\n' : ';\n') | ||
init: function(){buf=[], err=[]}, | ||
done: function (raw) { | ||
if (err.length != 0) throw new Error('j2c error(s): ' + JSON.stringify(err,null,2) + 'in context:\n' + buf.join('')) | ||
return raw ? buf : buf.join('') | ||
}, | ||
// end At-rule | ||
A: function () {buf.push('}\n')}, | ||
// start Selector | ||
s: function (selector) {buf.push(selector, ' {\n')}, | ||
// end Selector | ||
S: function () {buf.push('}\n')}, | ||
// declarations | ||
d: function (prop, value) {buf.push(prop, prop && ':', value, ';\n')} | ||
err: function(msg) { | ||
err.push(msg) | ||
buf.push('/* +++ ERROR +++ ' + msg + ' */\n') | ||
}, | ||
atrule: function (rule, kind, param, takesBlock) { | ||
buf.push(rule, param && ' ', param, takesBlock ? ' {' : ';', _instance.endline) | ||
}, | ||
// close atrule | ||
_atrule: function () {buf.push('}', _instance.endline)}, | ||
rule: function (selector) {buf.push(selector, ' {', _instance.endline)}, | ||
// close rule | ||
_rule: function () {buf.push('}', _instance.endline)}, | ||
decl: function (prop, value) {buf.push(prop, prop && ':', value, ';', _instance.endline)} | ||
} | ||
// holds the `$filter` and `$at` handlers | ||
var $filters = [closeSelectors] | ||
var $atHandlers = [] | ||
// the public API (see the main docs) | ||
var _instance = { | ||
@@ -42,3 +46,5 @@ at: at, | ||
names: {}, | ||
endline: '\n', | ||
suffix: '__j2c-' + | ||
// 128 bits of randomness | ||
Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
@@ -48,13 +54,32 @@ Math.floor(Math.random() * 0x100000000).toString(36) + '-' + | ||
Math.floor(Math.random() * 0x100000000).toString(36), | ||
use: function() { | ||
_use(emptyArray.slice.call(arguments)) | ||
return _instance | ||
$plugins: [], | ||
sheet: function(tree) { | ||
var emit = _createOrRetrieveStream(0) | ||
emit.init() | ||
rules( | ||
_walkers[0], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1, // local, by default | ||
0 // nesting depth | ||
) | ||
return emit.done() | ||
}, | ||
$plugins: [] | ||
inline: function (tree, options) { | ||
var emit = _createOrRetrieveStream(1) | ||
emit.init() | ||
declarations( | ||
_walkers[1], | ||
emit, | ||
'', // prefix | ||
tree, | ||
!(options && options.global) // local, by default | ||
) | ||
return emit.done() | ||
} | ||
} | ||
var _streams = [] | ||
// The `state` (for the core) / `walker` (for the plugins) tables. | ||
// The `state` (for the core functions) / `walker` (for the plugins) tables. | ||
var _walkers = [ | ||
@@ -64,17 +89,17 @@ // for j2c.sheet | ||
// helpers for locaizing class and animation names | ||
L: _localizeReplacer, // second argument to String.prototype.replace | ||
l: _localize, // mangles local names | ||
n: _instance.names, // local => mangled mapping | ||
$a: $atHandlers, // extra at-rules | ||
localizeReplacer: _localizeReplacer, // second argument to String.prototype.replace | ||
localize: _localize, // mangles local names | ||
names: _instance.names, // local => mangled mapping | ||
$atHandlers: $atHandlers, // extra at-rules | ||
// The core walker methods, to be provided to plugins | ||
a: atRules, | ||
d: declarations, | ||
r: rules | ||
atrule: atRules, | ||
decl: declarations, | ||
rule: rules | ||
}, | ||
// likewise, for j2c.inline (idem with `$a`, `a` and `s` removed) | ||
{ | ||
L: _localizeReplacer, | ||
l: _localize, | ||
n: _instance.names, | ||
d: declarations | ||
localizeReplacer: _localizeReplacer, | ||
localize: _localize, | ||
names: _instance.names, | ||
decl: declarations | ||
} | ||
@@ -84,32 +109,2 @@ ] | ||
// The main API functions | ||
_instance.sheet = function(tree) { | ||
var emit = _getStream(0) | ||
emit.i() | ||
rules( | ||
_walkers[0], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1, // local, by default | ||
0 // inAtRule | ||
) | ||
return emit.x() | ||
} | ||
_instance.inline = function (tree) { | ||
var emit = _getStream(1) | ||
emit.i() | ||
declarations( | ||
_walkers[1], | ||
emit, | ||
'', // prefix | ||
tree, | ||
1 //local | ||
) | ||
return emit.x() | ||
} | ||
// inner helpers | ||
@@ -138,3 +133,3 @@ | ||
Default(_instance.names, plugin.$names || emptyObject) | ||
defaults(_instance.names, plugin.$names || emptyObject) | ||
@@ -145,21 +140,37 @@ _use(plugin.$plugins || emptyArray) | ||
Default(_instance, plugin) | ||
defaults(_instance, plugin) | ||
}) | ||
function _getStream(inline) { | ||
var _streams = [] | ||
/** | ||
* returns the codegen streams, creating them if necessary | ||
* @param | ||
*/ | ||
function _createOrRetrieveStream(inline) { | ||
// build the stream processors if needed | ||
if (!_streams.length) { | ||
for(var i = 0; i < 2; i++){ | ||
$filters[$filters.length - i] = function(_, inline) {return inline ? {i:$sink.i, d:$sink.d, x:$sink.x} : $sink} | ||
// append the $sink as the ultimate filter | ||
$filters.push(function(_, inline) {return inline ? {init:$sink.init, decl:$sink.decl, done:$sink.done, err: $sink.err} : $sink}) | ||
for(var i = 0; i < 2; i++){ // 0 for j2c.sheet, 1 for j2c.inline | ||
for (var j = $filters.length; j--;) { | ||
_streams[i] = freeze(Default( | ||
$filters[j](_streams[i], !!i, _walkers[i]), | ||
_streams[i] | ||
)) | ||
_streams[i] = freeze( | ||
defaults( | ||
$filters[j](_streams[i], !!i), | ||
_streams[i] | ||
) | ||
) | ||
} | ||
} | ||
} | ||
var res = _streams[inline] | ||
return res | ||
return _streams[inline] | ||
} | ||
/** | ||
* Returns a localized version of a given name. | ||
* Registers the pair in `instnace.name` if needed. | ||
* | ||
* @param {string} name - the name to localize | ||
* @return {string} - the localized version | ||
*/ | ||
function _localize(name) { | ||
@@ -170,11 +181,19 @@ if (!_instance.names[name]) _instance.names[name] = name + _instance.suffix | ||
function _localizeReplacer(match, string, global, dot, name) { | ||
if (string || global) return string || global | ||
return dot + _localize(name) | ||
/** | ||
* Used as second argument for str.replace(localizeRegex, replacer) | ||
* `ignore`, `global` and `(dot, name)` are mutually exclusive | ||
* | ||
* @param {string} match - the whole match (ignored) | ||
* @param {string|null} ignore - a comment or a string literal | ||
* @param {string|null} global - a global name | ||
* @param {string|null} dot - either '.' for a local class name or the empty string otherwise | ||
* @param {string|null} name - the name to localize | ||
* @return {string} | ||
*/ | ||
function _localizeReplacer(match, ignore, global, dot, name) { | ||
return ignore || global || dot + _localize(name) | ||
} | ||
_use(emptyArray.slice.call(arguments)) | ||
return _instance | ||
} | ||
var _j2c = j2c() | ||
'sheet|inline|names|at|global|kv|suffix'.split('|').map(function(m){j2c[m] = _j2c[m]}) |
@@ -13,6 +13,6 @@ import {type, ARRAY, OBJECT, STRING, ampersand, own, splitSelector} from './helpers' | ||
* @param {array|string|object} tree - a source object or sub-object. | ||
* @param {string} inAtRule - are we nested in an at-rule? | ||
* @param {string} nestingDepth - are we nested in an at-rule? | ||
* @param {boolean} local - are we in @local or in @global scope? | ||
*/ | ||
export function rules(state, emit, prefix, tree, local, inAtRule) { | ||
export function rules(state, emit, prefix, tree, local, nestingDepth) { | ||
var k, v, inDeclaration, kk | ||
@@ -30,3 +30,3 @@ | ||
emit.s(prefix) | ||
emit.rule(prefix) | ||
@@ -52,3 +52,3 @@ } | ||
/^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(k) || [k,'@','',''], | ||
v, prefix, local, inAtRule | ||
v, prefix, local, nestingDepth | ||
) | ||
@@ -62,7 +62,7 @@ | ||
state, emit, | ||
// `prefix` ... Hefty. Ugly. Sadly necessary. | ||
// | ||
(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
// build the selector `prefix` for the next iteration. | ||
// ugly and full of redundant bits but so far the fastest/shortest.gz | ||
/*0 if*/(prefix.length > 0 && (/,/.test(prefix) || /,/.test(k))) ? | ||
/*0*/ (kk = splitSelector(prefix), splitSelector( | ||
/*0 then*/ (kk = splitSelector(prefix), splitSelector( | ||
local ? | ||
@@ -72,3 +72,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -83,5 +83,5 @@ | ||
/*0*/ /&/.test(k) ? | ||
/*0 else*/ /*1 if*/ /&/.test(k) ? | ||
/*1*/ ampersand( | ||
/*1 then*/ ampersand( | ||
local ? | ||
@@ -91,3 +91,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -99,3 +99,3 @@ | ||
/*1*/ prefix + ( | ||
/*1 else*/ prefix + ( | ||
local ? | ||
@@ -105,3 +105,3 @@ | ||
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\/)|:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, | ||
state.L | ||
state.localizeReplacer | ||
) : | ||
@@ -111,3 +111,3 @@ | ||
), | ||
v, local, inAtRule | ||
v, local, nestingDepth + 1 | ||
) | ||
@@ -123,3 +123,3 @@ | ||
rules(state, emit, prefix, tree[k], local, inAtRule) | ||
rules(state, emit, prefix, tree[k], local, nestingDepth) | ||
@@ -131,5 +131,5 @@ } | ||
// CSS hacks or ouptut of `j2c.inline`. | ||
if (!prefix.length) emit.err('No selector') | ||
emit.rule(prefix || ' ') | ||
emit.s(prefix.length > 0 ? prefix : ':-error-no-selector') | ||
declarations(state, emit, '', tree, local) | ||
@@ -147,3 +147,3 @@ | ||
// contains arrays. | ||
// There's no `S` handler, because the core compiler never | ||
// There's no `_rule` handler, because the core compiler never | ||
// calls it. | ||
@@ -153,24 +153,23 @@ export function closeSelectors(next, inline) { | ||
return inline ? next : { | ||
i: function(){lastSelector = 0; next.i()}, | ||
x: function (raw) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
return next.x(raw) | ||
init: function(){lastSelector = 0; next.init()}, | ||
done: function (raw) { | ||
if (lastSelector) {next._rule(); lastSelector = 0} | ||
return next.done(raw) | ||
}, | ||
a: function (rule, param, takesBlock) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.a(rule, param, takesBlock) | ||
atrule: function (rule, kind, param, takesBlock) { | ||
if (lastSelector) {next._rule(); lastSelector = 0} | ||
next.atrule(rule, kind, param, takesBlock) | ||
}, | ||
A: function (rule) { | ||
if (lastSelector) {next.S(); lastSelector = 0} | ||
next.A(rule) | ||
_atrule: function (rule) { | ||
if (lastSelector) {next._rule(); lastSelector = 0} | ||
next._atrule(rule) | ||
}, | ||
s: function (selector) { | ||
rule: function (selector) { | ||
if (selector !== lastSelector){ | ||
if (lastSelector) next.S() | ||
next.s(selector) | ||
if (lastSelector) next._rule() | ||
next.rule(selector) | ||
lastSelector = selector | ||
} | ||
}, | ||
d: next.d | ||
} | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
992685
16
139
14926
712
5
1