Skip to content

Commit

Permalink
Make $at plugins more powerful, cut back on esoteric at-rules, remo…
Browse files Browse the repository at this point in the history
…ve `j2c.compose`
  • Loading branch information
pygy committed Feb 23, 2016
1 parent faa8c07 commit b4a16ce
Show file tree
Hide file tree
Showing 13 changed files with 306 additions and 442 deletions.
115 changes: 58 additions & 57 deletions dist/j2c.amd.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,18 @@ define(function () { 'use strict';
* @param {string} prefix - the current property or a prefix in case of nested
* sub-properties.
* @param {boolean} local - are we in @local or in @global scope.
* @param {function} localize - @local helper.
* @param {function} state - @local helper.
*/

function declarations(o, emit, prefix, local, localize) {
function declarations(o, emit, prefix, local, state) {
var k, v, kk
if (o==null) return

switch ( type.call(o = o.valueOf()) ) {
case ARRAY:
for (k = 0; k < o.length; k++)

declarations(o[k], emit, prefix, local, localize)
declarations(o[k], emit, prefix, local, state)

break
case OBJECT:
Expand All @@ -115,12 +115,12 @@ define(function () { 'use strict';
if (/\$/.test(k)) {
for (kk in (k = k.split('$'))) if (own.call(k, kk)) {

declarations(v, emit, prefix + k[kk], local, localize)
declarations(v, emit, prefix + k[kk], local, state)

}
} else {

declarations(v, emit, prefix + k, local, localize)
declarations(v, emit, prefix + k, local, state)

}
}
Expand All @@ -138,10 +138,10 @@ define(function () { 'use strict';

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.
// We may 'state' a comment, but it's not a big deal.
o = o.split(',').map(function (o) {

return o.replace(/:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, localize)
return o.replace(/:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/, state.l)

}).join(',')
}
Expand All @@ -160,23 +160,19 @@ define(function () { 'use strict';
* @param {string[]} v - Either parameters for block-less rules or their block
* for the others.
* @param {string} prefix - the current selector or a prefix in case of nested rules
* @param {string} composes - the potential target of a @composes rule, if any
* @param {string} inAtRule - are we nested in an at-rule?
* @param {boolean} local - are we in @local or in @global scope?
* @param {function} localize - @local helper
* @param {function} state - @local helper
*/

function atRules(k, v, emit, prefix, composes, local, localize){
function atRules(k, v, emit, prefix, inAtRule, local, state) {
k = /^(.(?:-[\w]+-)?([_A-Za-z][-\w]*))\b\s*(.*?)\s*$/.exec(k) || ['@','@','','']
if (!k[3] && /^global$/.test(k[2])) {
sheet(v, emit, prefix, 1, 0, localize)
sheet(v, emit, prefix, inAtRule, 0, state)

} else if (!k[3] && /^local$/.test(k[2])) {

sheet(v, emit, prefix, 1, 1, localize)

} else if (!k[3] && /^mixin$/.test(k[2])) {

sheet(v, emit, prefix, composes, local, localize)
sheet(v, emit, prefix, inAtRule, 1, state)

} else if (!k[3] && /^(?:namespace|import|charset)$/.test(k[2])) {
flatIter(function(v) {
Expand All @@ -185,45 +181,45 @@ define(function () { 'use strict';

})(v)

} else if (!k[3] && /^(?:font-face|viewport|swash|ornaments|annotation|stylistic|styleset|character-variant)$/.test(k[2])) {
} else if (!k[3] && /^(?:font-face|viewport)$/.test(k[2])) {
flatIter(function(v) {

emit.a(k[1], '', '', ' {\n')

declarations(v, emit, '', local, localize)
declarations(v, emit, '', local, state)

emit.c('}\n')

})(v)

} else if (k[3] && /^(?:media|supports|document|page|keyframes|counter-style|font-feature-values)$/.test(k[2])) {
} else if (k[3] && /^(?:media|supports|page|keyframes)$/.test(k[2])) {

if (local && /^(?:keyframes|counter-style)$/.test(k[2])) {
if (local && 'keyframes' == k[2]) {
k[3] = k[3].replace(
// generated by script/regexps.js
/:?global\(\s*([_A-Za-z][-\w]*)\s*\)|()(-?[_A-Za-z][-\w]*)/,
localize
state.l
)
}


emit.a(k[1], ' ', k[3], ' {\n')

if (/^(?:page|counter-style)$/.test(k[2])) {
if ('page' == k[2]) {

declarations(v, emit, '', local, localize)
declarations(v, emit, '', local, state)

} else {

sheet(v, emit, prefix, 1, local, localize)
sheet(v, emit, prefix, 0, local, state)

}

emit.c('}\n')

} else {
for (var i = 0; i < localize.a.length; i++) {
if (localize.a[i](k, v, emit, prefix, composes, local, localize, sheet, declarations)) return
for (var i = 0; i < state.A.length; i++) {
if (state.A[i](k, v, emit, prefix, inAtRule, local, state)) return
}
emit.a('@-error-unsupported-at-rule', ' ', JSON.stringify(k[0]), ';\n')

Expand All @@ -236,19 +232,19 @@ define(function () { 'use strict';
* @param {array|string|object} statements - a source object or sub-object.
* @param {string[]} emit - the contextual emitters to the final buffer
* @param {string} prefix - the current selector or a prefix in case of nested rules
* @param {string} composes - the potential target of a @composes rule, if any
* @param {string} canCompose - are we allowed to @compose here?
* @param {boolean} local - are we in @local or in @global scope?
* @param {function} localize - @local helper
* @param {function} state - @local helper
*/
function sheet(statements, emit, prefix, composes, local, localize) {
function sheet(statements, emit, prefix, canCompose, local, state) {
var k, v, inDeclaration, kk

switch (type.call(statements)) {

case ARRAY:
for (k = 0; k < statements.length; k++){

sheet(statements[k], emit, prefix, composes, local, localize)
sheet(statements[k], emit, prefix, canCompose, local, state)

}
break
Expand All @@ -266,20 +262,20 @@ define(function () { 'use strict';
if (/\$/.test(k)) {
for (kk in (k = k.split('$'))) if (own.call(k, kk)) {

declarations(v, emit, k[kk], local, localize)
declarations(v, emit, k[kk], local, state)

}
} else {

declarations(v, emit, k, local, localize)
declarations(v, emit, k, local, state)

}
} else if (/^@/.test(k)) {
// Handle At-rules

inDeclaration = (inDeclaration && emit.c('}\n') && 0)

atRules(k, v, emit, prefix, composes, local, localize)
atRules(k, v, emit, prefix, canCompose, local, state)

} else {
// selector or nested sub-selectors
Expand All @@ -291,7 +287,7 @@ define(function () { 'use strict';
/*0*/ (kk = splitSelector(prefix), splitSelector( local ?

k.replace(
/:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, localize
/:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, state.l
) :

k
Expand All @@ -305,7 +301,7 @@ define(function () { 'use strict';
local ?

k.replace(
/:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, localize
/:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, state.l
) :

k,
Expand All @@ -315,13 +311,13 @@ define(function () { 'use strict';
local ?

k.replace(
/:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, localize
/:global\(\s*(\.-?[_A-Za-z][-\w]*)\s*\)|(\.)(-?[_A-Za-z][-\w]*)/g, state.l
) :

k
),
composes || prefix ? '' : k,
local, localize
canCompose,
local, state
)
}
}
Expand All @@ -334,7 +330,7 @@ define(function () { 'use strict';

emit.s(( prefix || ':-error-no-selector' ) , ' {\n')

declarations(statements, emit, '', local, localize)
declarations(statements, emit, '', local, state)

emit.c('}\n')
}
Expand Down Expand Up @@ -412,7 +408,7 @@ define(function () { 'use strict';
_default(instance, plugin)
})

function makeEmitter(inline) {
function makeEmitter(inline, state) {
var buf = []
function push() {
emptyArray.push.apply(buf, arguments)
Expand All @@ -424,21 +420,10 @@ define(function () { 'use strict';
d: push, // declaration
c: push // close
}
for (var i = filters.length; i--;) emit = filters[i](emit, inline)
for (var i = filters.length; i--;) emit = filters[i](emit, inline, state)
return emit
}

instance.compose = function(target, source) {
if(!/^-?[_A-Za-z][-\w]*$/.test(target))
throw new Error('Bad target class ' + JSON.stringify(target))

localize(0,0,0,target)

flatIter(function(source) {
instance.names[target] = instance.names[target] + ' ' + source
})(source)
}

function localize(match, global, dot, name) {
if (global) return global
if (!instance.names[name]) instance.names[name] = name + instance.suffix
Expand All @@ -449,24 +434,40 @@ define(function () { 'use strict';

/*/-statements-/*/
instance.sheet = function(statements, emit) {
var state = {
s: sheet,
a: atRules,
d: declarations,
A: atHandlers,
l: localize,
n: instance.names
}
sheet(
statements,
emit = makeEmitter(false),
emit = makeEmitter(false, state),
'', '', // prefix and compose
1, // local, by default
localize
state
)

return emit.x()
}
/*/-statements-/*/
instance.inline = function (_declarations, emit) {
var state = {
s: sheet,
a: atRules,
d: declarations,
A: atHandlers,
l: localize,
n: instance.names
}
declarations(
_declarations,
emit = makeEmitter(true),
emit = makeEmitter(true, state),
'', // prefix
1, //local
localize
state
)
return emit.x()
}
Expand All @@ -475,7 +476,7 @@ define(function () { 'use strict';
}

var _j2c = j2c()
'sheet|inline|names|at|global|kv|suffix|compose'.split('|').map(function(m){j2c[m] = _j2c[m]})
'sheet|inline|names|at|global|kv|suffix'.split('|').map(function(m){j2c[m] = _j2c[m]})

return j2c;

Expand Down
2 changes: 1 addition & 1 deletion dist/j2c.amd.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b4a16ce

Please sign in to comment.