Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added unscoped mode #53

Merged
merged 1 commit into from
Aug 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

var csjs = require('./csjs');

module.exports = csjs;
module.exports.csjs = csjs;
module.exports = csjs();
module.exports.csjs = csjs();
module.exports.noScope = csjs({ noscope: true });
module.exports.getCss = require('./get-css');
14 changes: 13 additions & 1 deletion lib/composition.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

module.exports = {
makeComposition: makeComposition,
isComposition: isComposition
isComposition: isComposition,
ignoreComposition: ignoreComposition
};

/**
Expand Down Expand Up @@ -60,6 +61,17 @@ function isComposition(value) {
return value instanceof Composition;
}

function ignoreComposition(values) {
return values.reduce(function(acc, val) {
if (isComposition(val)) {
val.classNames.forEach(function(name, i) {
acc[name] = val.unscoped[i];
});
}
return acc;
}, {});
}

/**
* Private constructor for use in `instanceof` checks
*/
Expand Down
61 changes: 33 additions & 28 deletions lib/csjs.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
'use strict';

var extractExtends = require('./css-extract-extends');
var isComposition = require('./composition').isComposition;
var composition = require('./composition');
var isComposition = composition.isComposition;
var ignoreComposition = composition.ignoreComposition;
var buildExports = require('./build-exports');
var scopify = require('./scopeify');
var cssKey = require('./css-key');
var extractExports = require('./extract-exports');

module.exports = function csjsHandler(strings) {
// Fast path to prevent arguments deopt
var values = Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++) {
values[i - 1] = arguments[i];
}
var css = joiner(strings, values.map(selectorize));
module.exports = function csjsTemplate(opts) {
opts = (typeof opts === 'undefined') ? {} : opts;
var noscope = (typeof opts.noscope === 'undefined') ? false : opts.noscope;

var ignores = values.reduce(function(acc, val) {
if (isComposition(val)) {
val.classNames.forEach(function(name, i) {
acc[name] = val.unscoped[i];
});
return function csjsHandler(strings, values) {
// Fast path to prevent arguments deopt
var values = Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++) {
values[i - 1] = arguments[i];
}
return acc;
}, {});
var css = joiner(strings, values.map(selectorize));
var ignores = ignoreComposition(values);

var scoped = scopify(css, ignores);
var extracted = extractExtends(scoped.css);
var scope;
if (noscope) {
scope = extractExports(css);
} else {
scope = scopify(css, ignores);
}

var localClasses = without(scoped.classes, ignores);
var localKeyframes = without(scoped.keyframes, ignores);
var compositions = extracted.compositions;
var extracted = extractExtends(scope.css);
var localClasses = without(scope.classes, ignores);
var localKeyframes = without(scope.keyframes, ignores);
var compositions = extracted.compositions;

var exports = buildExports(localClasses, localKeyframes, compositions);
var exports = buildExports(localClasses, localKeyframes, compositions);

return Object.defineProperty(exports, cssKey, {
enumerable: false,
configurable: false,
writeable: false,
value: extracted.css
});
};
return Object.defineProperty(exports, cssKey, {
enumerable: false,
configurable: false,
writeable: false,
value: extracted.css
});
}
}

/**
* Replaces class compositions with comma seperated class selectors
Expand Down
26 changes: 26 additions & 0 deletions lib/extract-exports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

var replaceAnimations = require('./replace-animations');
var regex = require('./regex');
var classRegex = regex.classRegex;
var keyframesRegex = regex.keyframesRegex;

module.exports = extractExports;

function extractExports(css) {
return replaceAnimations({
css: css,
keyframes: getExport(css, keyframesRegex),
classes: getExport(css, classRegex)
});
}

function getExport(css, regex) {
var prop = {};
var match;
while((match = regex.exec(css)) !== null) {
var name = match[2];
prop[name] = name;
}
return prop;
}
14 changes: 14 additions & 0 deletions lib/regex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

var findClasses = /(\.)(?!\d)([^\s\.,{\[>+~#:)]*)(?![^{]*})/.source;
var findKeyframes = /(@\S*keyframes\s*)([^{\s]*)/.source;
var ignoreComments = /(?!(?:[^*/]|\*[^/]|\/[^*])*\*+\/)/.source;

var classRegex = new RegExp(findClasses + ignoreComments, 'g');
var keyframesRegex = new RegExp(findKeyframes + ignoreComments, 'g');

module.exports = {
classRegex: classRegex,
keyframesRegex: keyframesRegex,
ignoreComments: ignoreComments,
};
29 changes: 29 additions & 0 deletions lib/replace-animations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
var ignoreComments = require('./regex').ignoreComments;

module.exports = replaceAnimations;

function replaceAnimations(result) {
var animations = Object.keys(result.keyframes).reduce(function(acc, key) {
acc[result.keyframes[key]] = key;
return acc;
}, {});
var unscoped = Object.keys(animations);

if (unscoped.length) {
var regexStr = '((?:animation|animation-name)\\s*:[^};]*)('
+ unscoped.join('|') + ')([;\\s])' + ignoreComments;
var regex = new RegExp(regexStr, 'g');

var replaced = result.css.replace(regex, function(match, preamble, name, ending) {
return preamble + animations[name] + ending;
});

return {
css: replaced,
keyframes: result.keyframes,
classes: result.classes
}
}

return result;
}
37 changes: 4 additions & 33 deletions lib/scopeify.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
'use strict';

var fileScoper = require('./scoped-name');

var findClasses = /(\.)(?!\d)([^\s\.,{\[>+~#:)]*)(?![^{]*})/.source;
var findKeyframes = /(@\S*keyframes\s*)([^{\s]*)/.source;
var ignoreComments = /(?!(?:[^*/]|\*[^/]|\/[^*])*\*+\/)/.source;

var classRegex = new RegExp(findClasses + ignoreComments, 'g');
var keyframesRegex = new RegExp(findKeyframes + ignoreComments, 'g');
var replaceAnimations = require('./replace-animations');
var regex = require('./regex');
var classRegex = regex.classRegex;
var keyframesRegex = regex.keyframesRegex;

module.exports = scopify;

Expand Down Expand Up @@ -40,29 +37,3 @@ function scopify(css, ignores) {

return replaceAnimations(result);
}

function replaceAnimations(result) {
var animations = Object.keys(result.keyframes).reduce(function(acc, key) {
acc[result.keyframes[key]] = key;
return acc;
}, {});
var unscoped = Object.keys(animations);

if (unscoped.length) {
var regexStr = '((?:animation|animation-name)\\s*:[^};]*)('
+ unscoped.join('|') + ')([;\\s])' + ignoreComments;
var regex = new RegExp(regexStr, 'g');

var replaced = result.css.replace(regex, function(match, preamble, name, ending) {
return preamble + animations[name] + ending;
});

return {
css: replaced,
keyframes: result.keyframes,
classes: result.classes
}
}

return result;
}
13 changes: 13 additions & 0 deletions test/animation-as-pseudo.noscope.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@


@keyframes hover {
0% { opacity: 0.0; }
100% { opacity: 0.5; }
}

@media (max-width: 480px) {
.animation:hover {
background: green;
}
}

4 changes: 4 additions & 0 deletions test/animation-as-pseudo.noscope.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"animation": "animation",
"hover": "hover"
}
16 changes: 16 additions & 0 deletions test/animation-as-pseudo.noscope.source.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const csjs = require('../').noScope;

module.exports = csjs`

@keyframes hover {
0% { opacity: 0.0; }
100% { opacity: 0.5; }
}

@media (max-width: 480px) {
.animation:hover {
background: green;
}
}

`;
6 changes: 6 additions & 0 deletions test/basic.noscope.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@


.foo {
color: red;
}

3 changes: 3 additions & 0 deletions test/basic.noscope.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"foo": "foo"
}
9 changes: 9 additions & 0 deletions test/basic.noscope.source.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const csjs = require('../').noScope;

module.exports = csjs`

.foo {
color: red;
}

`;
38 changes: 38 additions & 0 deletions test/comments.noscope.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

/* Here's a comment */
/*squishedcomment*/
/********crazycomment********/
/* A comment with a period at the end. */
/* A comment with a period followed by numbers v1.2.3 */
/* A comment with a .className */
/*
* Here's a comment
* A comment with a period at the end.
* A comment with a period followed by numbers v1.2.3
* A comment with a .className
*/
/* .inlineCss { color: red; } */
/*
.commentedOutCss {
color: blue;
}
*/
.foo {
color: red; /* comment on a line */
animation-name: wow;
}

@keyframes wow {}

/*
@keyframes bam {}
*/

/* .woot {
animation-name: bam;
} */

/* .hmm {
animation-name: wow;
} */

4 changes: 4 additions & 0 deletions test/comments.noscope.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"foo": "foo_1LMZVZ",
"wow": "wow_1LMZVZ"
}
41 changes: 41 additions & 0 deletions test/comments.source.noscope.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const csjs = require('../').noScope;

module.exports = csjs`
/* Here's a comment */
/*squishedcomment*/
/********crazycomment********/
/* A comment with a period at the end. */
/* A comment with a period followed by numbers v1.2.3 */
/* A comment with a .className */
/*
* Here's a comment
* A comment with a period at the end.
* A comment with a period followed by numbers v1.2.3
* A comment with a .className
*/
/* .inlineCss { color: red; } */
/*
.commentedOutCss {
color: blue;
}
*/
.foo {
color: red; /* comment on a line */
animation-name: wow;
}

@keyframes wow {}

/*
@keyframes bam {}
*/

/* .woot {
animation-name: bam;
} */

/* .hmm {
animation-name: wow;
} */

`;
8 changes: 8 additions & 0 deletions test/dot-in-values.noscope.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@


.foo {
font-size: 1.3em;
}

.bar { font-size: 12.5px; } .baz { width: 33.3% }

5 changes: 5 additions & 0 deletions test/dot-in-values.noscope.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"foo": "foo",
"baz": "baz",
"bar": "bar"
}