mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge branch 'devel' into sso
Conflicts: tools/bundler.js
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
## v.NEXT
|
||||
|
||||
* XXX upgraded `less` from 1.3.3 to 1.6.1
|
||||
* XXX upgraded `stylus` from 0.37.0 to 0.42.2 and `nib` from `1.0.0` to `1.0.2`
|
||||
* XXX sourcemaps support for stylesheets, including less sourcemaps
|
||||
* XXX css linting (breaks on errors)
|
||||
* XXX css preprocessing to concatenate files correctly (pulls @imports to the
|
||||
beginning)
|
||||
* XXX supports `.import.less` and `.import.styl` to prevent Meteor processing
|
||||
stylesheets. `.lessimport` is deprecated
|
||||
|
||||
* Hash login tokens before storing them in the database.
|
||||
|
||||
* Add `clientAddress` and `httpHeaders` to `this.connection` in method
|
||||
|
||||
10
LICENSE.txt
10
LICENSE.txt
@@ -71,13 +71,6 @@ handlebars: https://github.com/wycats/handlebars.js/
|
||||
Copyright (C) 2011 by Yehuda Katz
|
||||
|
||||
|
||||
----------
|
||||
clean-css: https://github.com/GoalSmashers/clean-css
|
||||
----------
|
||||
|
||||
Copyright (c) 2011 GoalSmashers.com
|
||||
|
||||
|
||||
----------
|
||||
progress: https://github.com/visionmedia/node-progress
|
||||
qs: https://github.com/visionmedia/node-querystring
|
||||
@@ -91,11 +84,14 @@ pause: https://github.com/visionmedia/node-pause
|
||||
range-parser: https://github.com/visionmedia/node-range-parser
|
||||
send: https://github.com/visionmedia/send
|
||||
methods: https://github.com/visionmedia/node-methods
|
||||
css-parse: https://github.com/reworkcss/css-parse
|
||||
css-stringify: https://github.com/reworkcss/css-stringify
|
||||
----------
|
||||
|
||||
Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2013 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
|
||||
----------
|
||||
|
||||
@@ -11,7 +11,7 @@ automatically compiled to CSS and the results are included in the client CSS
|
||||
bundle.
|
||||
|
||||
{{#note}}
|
||||
If you want to `@import` a file, give it the extension `.lessimport`
|
||||
If you want to `@import` a file, give it the extension `.import.less`
|
||||
to prevent Meteor from processing it independently.
|
||||
{{/note}}
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@ The `stylus` package also includes `nib` support. Add `@import 'nib'` to
|
||||
your `.styl` files to enable cross-browser mixins such as
|
||||
`linear-gradient` and `border-radius`.
|
||||
|
||||
{{#note}}
|
||||
If you want to `@import` a file, give it the extension `.import.styl`
|
||||
to prevent Meteor from processing it independently.
|
||||
{{/note}}
|
||||
|
||||
See <http://visionmedia.github.com/nib> for documentation of the nib extensions of Stylus.
|
||||
|
||||
{{/better_markdown}}
|
||||
|
||||
4
meteor
4
meteor
@@ -1,9 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# danger will robinson! mother:config/download-dev-bundles.sh only goes up to
|
||||
# 0.3.30!
|
||||
|
||||
# Before you increment this again, fix the script listed above.
|
||||
BUNDLE_VERSION=0.3.30
|
||||
|
||||
# OS Check. Put here because here is where we download the precompiled
|
||||
|
||||
@@ -1,10 +1,110 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"less": {
|
||||
"version": "1.3.3",
|
||||
"version": "1.6.1",
|
||||
"dependencies": {
|
||||
"ycssmin": {
|
||||
"version": "1.0.1"
|
||||
"mime": {
|
||||
"version": "1.2.11"
|
||||
},
|
||||
"request": {
|
||||
"version": "2.33.0",
|
||||
"dependencies": {
|
||||
"qs": {
|
||||
"version": "0.6.6"
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.0"
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.5.0"
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.4.1"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "0.12.1",
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.2.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "0.1.2",
|
||||
"dependencies": {
|
||||
"combined-stream": {
|
||||
"version": "0.0.4",
|
||||
"dependencies": {
|
||||
"delayed-stream": {
|
||||
"version": "0.0.5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"async": {
|
||||
"version": "0.2.10"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.3.0"
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "0.10.0",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "0.1.2"
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.1.11"
|
||||
},
|
||||
"ctype": {
|
||||
"version": "0.5.2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.3.0"
|
||||
},
|
||||
"hawk": {
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"hoek": {
|
||||
"version": "0.9.1"
|
||||
},
|
||||
"boom": {
|
||||
"version": "0.4.2"
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "0.2.2"
|
||||
},
|
||||
"sntp": {
|
||||
"version": "0.2.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.5.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.3.5"
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "2.0.7",
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.1.31",
|
||||
"dependencies": {
|
||||
"amdefine": {
|
||||
"version": "0.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
packages/less/less_tests.import.less
vendored
Normal file
2
packages/less/less_tests.import.less
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// This should be @import'able into other .less files
|
||||
@important-border: double;
|
||||
@@ -10,6 +10,7 @@ Tinytest.add("less - presence", function(test) {
|
||||
|
||||
// test @import
|
||||
test.equal(getStyleProperty(p, 'border-right-style'), "dotted");
|
||||
test.equal(getStyleProperty(p, 'border-bottom-style'), "double");
|
||||
|
||||
d.kill();
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "less_tests_constants.lessimport";
|
||||
@import "less_tests.import.less";
|
||||
|
||||
#less-tests { zoom: 1; /* prop this rule open */ }
|
||||
|
||||
@@ -7,4 +8,5 @@
|
||||
.less-dashy-left-border {
|
||||
border-left: @dashy;
|
||||
border-right: @external-dotty;
|
||||
border-bottom: @important-border;
|
||||
}
|
||||
|
||||
@@ -8,11 +8,12 @@ Package._transitional_registerBuildPlugin({
|
||||
sources: [
|
||||
'plugin/compile-less.js'
|
||||
],
|
||||
npmDependencies: {"less": "1.3.3"}
|
||||
npmDependencies: {"less": "1.6.1"}
|
||||
});
|
||||
|
||||
Package.on_test(function (api) {
|
||||
api.use(['test-helpers', 'tinytest', 'less']);
|
||||
api.use(['spark']);
|
||||
api.add_files(['less_tests.less', 'less_tests.js'], 'client');
|
||||
api.add_files(['less_tests.less', 'less_tests.js', 'less_tests.import.less'],
|
||||
'client');
|
||||
});
|
||||
|
||||
@@ -23,13 +23,14 @@ Plugin.registerSourceHandler("less", function (compileStep) {
|
||||
paths: [path.dirname(compileStep._fullInputPath)] // for @import
|
||||
};
|
||||
|
||||
var f = new Future;
|
||||
var css;
|
||||
var parser = new less.Parser(options);
|
||||
var astFuture = new Future;
|
||||
var ast;
|
||||
try {
|
||||
less.render(source, options, f.resolver());
|
||||
css = f.wait();
|
||||
parser.parse(source, astFuture.resolver());
|
||||
ast = astFuture.wait();
|
||||
} catch (e) {
|
||||
// less.render() is supposed to report any errors via its
|
||||
// less.Parser.parse is supposed to report any errors via its
|
||||
// callback. But sometimes, it throws them instead. This is
|
||||
// probably a bug in less. Be prepared for either behavior.
|
||||
compileStep.error({
|
||||
@@ -41,14 +42,31 @@ Plugin.registerSourceHandler("less", function (compileStep) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cssFuture = new Future;
|
||||
var css = ast.toCSS({
|
||||
sourceMap: Boolean(true),
|
||||
writeSourceMap: function (sourceMap) {
|
||||
cssFuture.return(sourceMap);
|
||||
}
|
||||
});
|
||||
|
||||
var sourceMap = JSON.parse(cssFuture.wait());
|
||||
|
||||
sourceMap.sources = [compileStep.inputPath];
|
||||
sourceMap.sourcesContent = [source];
|
||||
|
||||
compileStep.addStylesheet({
|
||||
path: compileStep.inputPath + ".css",
|
||||
data: css
|
||||
data: css,
|
||||
sourceMap: JSON.stringify(sourceMap)
|
||||
});
|
||||
});;
|
||||
|
||||
// Register lessimport files with the dependency watcher, without actually
|
||||
// processing them.
|
||||
Plugin.registerSourceHandler("lessimport", function () {
|
||||
// Register import.less files with the dependency watcher, without actually
|
||||
// processing them. There is a similar rule in the stylus package.
|
||||
Plugin.registerSourceHandler("import.less", function () {
|
||||
// Do nothing
|
||||
});
|
||||
|
||||
// Backward compatibility with Meteor 0.7
|
||||
Plugin.registerSourceHandler("lessimport", function () {});
|
||||
|
||||
24
packages/minifiers/.npm/package/npm-shrinkwrap.json
generated
24
packages/minifiers/.npm/package/npm-shrinkwrap.json
generated
@@ -1,13 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"clean-css": {
|
||||
"version": "2.0.2",
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "2.4.7",
|
||||
"dependencies": {
|
||||
@@ -34,6 +26,22 @@
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"css-parse": {
|
||||
"version": "1.7.0"
|
||||
},
|
||||
"css-stringify": {
|
||||
"version": "1.4.1",
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.1.31",
|
||||
"dependencies": {
|
||||
"amdefine": {
|
||||
"version": "0.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
137
packages/minifiers/minification.js
Normal file
137
packages/minifiers/minification.js
Normal file
@@ -0,0 +1,137 @@
|
||||
|
||||
// Stringifier based on css-stringify
|
||||
var emit = function (str) {
|
||||
return str.toString();
|
||||
};
|
||||
|
||||
var visit = function (node, last) {
|
||||
return traverse[node.type](node, last);
|
||||
};
|
||||
|
||||
var mapVisit = function (nodes) {
|
||||
var buf = "";
|
||||
|
||||
for (var i = 0, length = nodes.length; i < length; i++) {
|
||||
buf += visit(nodes[i], i === length - 1);
|
||||
}
|
||||
|
||||
return buf;
|
||||
};
|
||||
|
||||
MinifyAst = function(node) {
|
||||
return node.stylesheet
|
||||
.rules.map(function (rule) { return visit(rule); })
|
||||
.join('');
|
||||
};
|
||||
|
||||
var traverse = {};
|
||||
|
||||
traverse.comment = function(node) {
|
||||
return emit('', node.position);
|
||||
};
|
||||
|
||||
traverse.import = function(node) {
|
||||
return emit('@import ' + node.import + ';', node.position);
|
||||
};
|
||||
|
||||
traverse.media = function(node) {
|
||||
return emit('@media ' + node.media, node.position, true)
|
||||
+ emit('{')
|
||||
+ mapVisit(node.rules)
|
||||
+ emit('}');
|
||||
};
|
||||
|
||||
traverse.document = function(node) {
|
||||
var doc = '@' + (node.vendor || '') + 'document ' + node.document;
|
||||
|
||||
return emit(doc, node.position, true)
|
||||
+ emit('{')
|
||||
+ mapVisit(node.rules)
|
||||
+ emit('}');
|
||||
};
|
||||
|
||||
traverse.charset = function(node) {
|
||||
return emit('@charset ' + node.charset + ';', node.position);
|
||||
};
|
||||
|
||||
traverse.namespace = function(node) {
|
||||
return emit('@namespace ' + node.namespace + ';', node.position);
|
||||
};
|
||||
|
||||
traverse.supports = function(node){
|
||||
return emit('@supports ' + node.supports, node.position, true)
|
||||
+ emit('{')
|
||||
+ mapVisit(node.rules)
|
||||
+ emit('}');
|
||||
};
|
||||
|
||||
traverse.keyframes = function(node) {
|
||||
return emit('@'
|
||||
+ (node.vendor || '')
|
||||
+ 'keyframes '
|
||||
+ node.name, node.position, true)
|
||||
+ emit('{')
|
||||
+ mapVisit(node.keyframes)
|
||||
+ emit('}');
|
||||
};
|
||||
|
||||
traverse.keyframe = function(node) {
|
||||
var decls = node.declarations;
|
||||
|
||||
return emit(node.values.join(','), node.position, true)
|
||||
+ emit('{')
|
||||
+ mapVisit(decls)
|
||||
+ emit('}');
|
||||
};
|
||||
|
||||
traverse.page = function(node) {
|
||||
var sel = node.selectors.length
|
||||
? node.selectors.join(', ')
|
||||
: '';
|
||||
|
||||
return emit('@page ' + sel, node.position, true)
|
||||
+ emit('{')
|
||||
+ mapVisit(node.declarations)
|
||||
+ emit('}');
|
||||
};
|
||||
|
||||
traverse.rule = function(node) {
|
||||
var decls = node.declarations;
|
||||
if (!decls.length) return '';
|
||||
|
||||
var selectors = node.selectors.map(function (selector) {
|
||||
// removes universal selectors like *.class => .class
|
||||
// removes optional whitespace around '>' and '+'
|
||||
return selector.replace(/\*\./, '.')
|
||||
.replace(/\s*>\s*/g, '>')
|
||||
.replace(/\s*\+\s*/g, '+');
|
||||
});
|
||||
return emit(selectors.join(','), node.position, true)
|
||||
+ emit('{')
|
||||
+ mapVisit(decls)
|
||||
+ emit('}');
|
||||
};
|
||||
|
||||
traverse.declaration = function(node, last) {
|
||||
var value = node.value;
|
||||
|
||||
// remove optional quotes around font name
|
||||
if (node.property === 'font') {
|
||||
value = value.replace(/\'[^\']+\'/g, function (m) {
|
||||
if (m.indexOf(' ') !== -1)
|
||||
return m;
|
||||
return m.replace(/\'/g, '');
|
||||
});
|
||||
value = value.replace(/\"[^\"]+\"/g, function (m) {
|
||||
if (m.indexOf(' ') !== -1)
|
||||
return m;
|
||||
return m.replace(/\"/g, '');
|
||||
});
|
||||
}
|
||||
// remove url quotes if possible
|
||||
// in case it is the last declaration, we can omit the semicolon
|
||||
return emit(node.property + ':' + value, node.position)
|
||||
+ (last ? '' : emit(';'));
|
||||
};
|
||||
|
||||
|
||||
21
packages/minifiers/minifiers-tests.js
Normal file
21
packages/minifiers/minifiers-tests.js
Normal file
@@ -0,0 +1,21 @@
|
||||
Tinytest.add("minifiers - simple css minification", function (test) {
|
||||
var t = function (css, expected, desc) {
|
||||
test.equal(CssTools.minifyCss(css), expected, desc);
|
||||
}
|
||||
|
||||
t('a \t\n{ color: red } \n', 'a{color:red}', 'whitespace check');
|
||||
t('a \t\n{ color: red; margin: 1; } \n', 'a{color:red;margin:1}', 'only last one loses semicolon');
|
||||
t('a \t\n{ color: red;;; margin: 1;;; } \n', 'a{color:red;margin:1}', 'more semicolons than needed');
|
||||
t('a , p \t\n{ color: red; } \n', 'a,p{color:red}', 'multiple selectors');
|
||||
t('body {}', '', 'removing empty rules');
|
||||
t('*.my-class { color: #fff; }', '.my-class{color:#fff}', 'removing universal selector');
|
||||
t('p > *.my-class { color: #fff; }', 'p>.my-class{color:#fff}', 'removing optional whitespace around ">" in selector');
|
||||
t('p + *.my-class { color: #fff; }', 'p+.my-class{color:#fff}', 'removing optional whitespace around "+" in selector');
|
||||
// XXX url parsing is difficult to support at the moment
|
||||
t('a {\n\
|
||||
font:12px \'Helvetica\',"Arial",\'Nautica\';\n\
|
||||
background:url("/some/nice/picture.png");\n}',
|
||||
'a{font:12px Helvetica,Arial,Nautica;background:url("/some/nice/picture.png")}', 'removing quotes in font and url (if possible)');
|
||||
t('/* no comments */ a { color: red; }', 'a{color:red}', 'remove comments');
|
||||
});
|
||||
|
||||
@@ -1,8 +1,76 @@
|
||||
var CleanCss = Npm.require('clean-css');
|
||||
UglifyJSMinify = Npm.require('uglify-js').minify;
|
||||
|
||||
CleanCSSProcess = function (source, options) {
|
||||
var instance = new CleanCss(options);
|
||||
return instance.minify(source);
|
||||
var cssParse = Npm.require('css-parse');
|
||||
var cssStringify = Npm.require('css-stringify');
|
||||
|
||||
CssTools = {
|
||||
parseCss: cssParse,
|
||||
stringifyCss: cssStringify,
|
||||
minifyCss: function (cssText) {
|
||||
return CssTools.minifyCssAst(cssParse(cssText));
|
||||
},
|
||||
minifyCssAst: function (cssAst) {
|
||||
return MinifyAst(cssAst);
|
||||
},
|
||||
mergeCssAsts: function (cssAsts, warnCb) {
|
||||
var rulesPredicate = function (rules) {
|
||||
if (! _.isArray(rules))
|
||||
rules = [rules];
|
||||
return function (node) {
|
||||
return _.contains(rules, node.type);
|
||||
}
|
||||
};
|
||||
|
||||
// Simple concatenation of CSS files would break @import rules
|
||||
// located in the beginning of a file. Before concatenation, pull them to
|
||||
// the beginning of a new syntax tree so they always precede other rules.
|
||||
var newAst = {
|
||||
type: 'stylesheet',
|
||||
stylesheet: { rules: [] }
|
||||
};
|
||||
|
||||
_.each(cssAsts, function (ast) {
|
||||
// Pick only the imports from the beginning of file ignoring @charset
|
||||
// rules as every file is assumed to be in UTF-8.
|
||||
var charsetRules = _.filter(ast.stylesheet.rules,
|
||||
rulesPredicate("charset"));
|
||||
|
||||
if (_.any(charsetRules, function (rule) {
|
||||
// According to MDN, only 'UTF-8' and "UTF-8" are the correct encoding
|
||||
// directives representing UTF-8.
|
||||
return ! /^(['"])UTF-8\1$/.test(rule.charset);
|
||||
})) {
|
||||
warnCb(ast.filename, "@charset rules in this file will be ignored as UTF-8 is the only encoding supported");
|
||||
}
|
||||
|
||||
ast.stylesheet.rules = _.reject(ast.stylesheet.rules,
|
||||
rulesPredicate("charset"));
|
||||
var importCount = 0;
|
||||
for (var i = 0; i < ast.stylesheet.rules.length; i++)
|
||||
if (! rulesPredicate(["import", "comment"])(ast.stylesheet.rules[i])) {
|
||||
importCount = i;
|
||||
break;
|
||||
}
|
||||
|
||||
var imports = ast.stylesheet.rules.splice(0, importCount);
|
||||
newAst.stylesheet.rules = newAst.stylesheet.rules.concat(imports);
|
||||
|
||||
// if there are imports left in the middle of file, warn user as it might
|
||||
// be a potential bug (imports are valid only in the beginning of file).
|
||||
if (_.any(ast.stylesheet.rules, rulesPredicate("import"))) {
|
||||
// XXX make this an error?
|
||||
warnCb(ast.filename, "there are some @import rules those are not taking effect as they are required to be in the beginning of the file");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Now we can put the rest of CSS rules into new AST
|
||||
_.each(cssAsts, function (ast) {
|
||||
newAst.stylesheet.rules =
|
||||
newAst.stylesheet.rules.concat(ast.stylesheet.rules);
|
||||
});
|
||||
|
||||
return newAst;
|
||||
}
|
||||
};
|
||||
|
||||
UglifyJSMinify = Npm.require('uglify-js').minify;
|
||||
|
||||
@@ -4,11 +4,20 @@ Package.describe({
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
"clean-css": "2.0.2",
|
||||
"uglify-js": "2.4.7"
|
||||
"uglify-js": "2.4.7",
|
||||
"css-parse": "1.7.0",
|
||||
"css-stringify": "1.4.1"
|
||||
});
|
||||
|
||||
Package.on_use(function (api) {
|
||||
api.export(['CleanCSSProcess', 'UglifyJSMinify']);
|
||||
api.add_files('minifiers.js', 'server');
|
||||
api.use('underscore', 'server');
|
||||
api.export(['CssTools', 'UglifyJSMinify']);
|
||||
api.add_files(['minification.js', 'minifiers.js'], 'server');
|
||||
});
|
||||
|
||||
Package.on_test(function (api) {
|
||||
api.use('minifiers', 'server');
|
||||
api.use('tinytest');
|
||||
api.add_files('minifiers-tests.js', 'server');
|
||||
});
|
||||
|
||||
|
||||
@@ -1,27 +1,46 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"stylus": {
|
||||
"version": "0.37.0",
|
||||
"version": "0.42.2",
|
||||
"dependencies": {
|
||||
"cssom": {
|
||||
"version": "0.2.5"
|
||||
"css-parse": {
|
||||
"version": "1.7.0"
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.3.5"
|
||||
},
|
||||
"debug": {
|
||||
"version": "0.7.2"
|
||||
"version": "0.7.4"
|
||||
},
|
||||
"sax": {
|
||||
"version": "0.5.4"
|
||||
"version": "0.5.8"
|
||||
},
|
||||
"glob": {
|
||||
"version": "3.2.8",
|
||||
"dependencies": {
|
||||
"minimatch": {
|
||||
"version": "0.2.14",
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "2.5.0"
|
||||
},
|
||||
"sigmund": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nib": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.2",
|
||||
"dependencies": {
|
||||
"stylus": {
|
||||
"version": "0.34.1",
|
||||
"version": "0.37.0",
|
||||
"dependencies": {
|
||||
"cssom": {
|
||||
"version": "0.2.5"
|
||||
@@ -30,7 +49,10 @@
|
||||
"version": "0.3.5"
|
||||
},
|
||||
"debug": {
|
||||
"version": "0.7.2"
|
||||
"version": "0.7.4"
|
||||
},
|
||||
"sax": {
|
||||
"version": "0.5.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,15 @@ Package._transitional_registerBuildPlugin({
|
||||
sources: [
|
||||
'plugin/compile-stylus.js'
|
||||
],
|
||||
npmDependencies: { stylus: "0.37.0", nib: "1.0.0" }
|
||||
npmDependencies: { stylus: "0.42.2", nib: "1.0.2" }
|
||||
});
|
||||
|
||||
Package.on_test(function (api) {
|
||||
api.use(['tinytest', 'stylus', 'test-helpers']);
|
||||
api.use('spark');
|
||||
api.add_files(['stylus_tests.styl', 'stylus_tests.js'], 'client');
|
||||
api.add_files([
|
||||
'stylus_tests.styl',
|
||||
'stylus_tests.import.styl',
|
||||
'stylus_tests.js'
|
||||
],'client');
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
var fs = Npm.require('fs');
|
||||
var stylus = Npm.require('stylus');
|
||||
var nib = Npm.require('nib');
|
||||
var path = Npm.require('path');
|
||||
var Future = Npm.require('fibers/future');
|
||||
|
||||
Plugin.registerSourceHandler("styl", function (compileStep) {
|
||||
@@ -17,6 +18,8 @@ Plugin.registerSourceHandler("styl", function (compileStep) {
|
||||
stylus(compileStep.read().toString('utf8'))
|
||||
.use(nib())
|
||||
.set('filename', compileStep.inputPath)
|
||||
// Include needed to allow relative @imports in stylus files
|
||||
.include(path.dirname(compileStep._fullInputPath))
|
||||
.render(f.resolver());
|
||||
|
||||
try {
|
||||
@@ -32,3 +35,10 @@ Plugin.registerSourceHandler("styl", function (compileStep) {
|
||||
data: css
|
||||
});
|
||||
});
|
||||
|
||||
// Register import.styl files with the dependency watcher, without actually
|
||||
// processing them. There is a similar rule in the less package.
|
||||
Plugin.registerSourceHandler("import.styl", function () {
|
||||
// Do nothing
|
||||
});
|
||||
|
||||
|
||||
5
packages/stylus/stylus_tests.import.styl
vendored
Normal file
5
packages/stylus/stylus_tests.import.styl
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// Variable used in stylus_test.styl
|
||||
importDashy = dashed
|
||||
|
||||
.stylus-overwrite-color
|
||||
font-size: 20px !important
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
Tinytest.add("stylus - presence", function(test) {
|
||||
|
||||
var d = OnscreenDiv(Meteor.render(function() {
|
||||
return '<p class="stylus-dashy-left-border"></p>'; }));
|
||||
d.node().style.display = 'block';
|
||||
@@ -10,5 +9,17 @@ Tinytest.add("stylus - presence", function(test) {
|
||||
test.equal(leftBorder, "dashed");
|
||||
|
||||
d.kill();
|
||||
|
||||
});
|
||||
|
||||
Tinytest.add("stylus - @import", function(test) {
|
||||
var d = OnscreenDiv(Meteor.render(function() {
|
||||
return '<p class="stylus-import-dashy-border stylus-overwrite-color"></p>';
|
||||
}));
|
||||
d.node().style.display = 'block';
|
||||
|
||||
var p = d.node().firstChild;
|
||||
test.equal(getStyleProperty(p, 'font-size'), "20px");
|
||||
test.equal(getStyleProperty(p, 'border-left-style'), "dashed");
|
||||
|
||||
d.kill();
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import "stylus_tests.import.styl"
|
||||
|
||||
#stylus-tests
|
||||
zoom: 1
|
||||
@@ -7,3 +8,9 @@ dashy = dashed
|
||||
.stylus-dashy-left-border
|
||||
border-left: 1px dashy black
|
||||
|
||||
.stylus-overwrite-size
|
||||
// This property is overwritten in stylus_test.import.styl
|
||||
font-size: 10px
|
||||
|
||||
.stylus-import-dashy-border
|
||||
border-left: 1px importDashy black
|
||||
|
||||
2193
packages/test-in-browser/diff_match_patch_uncompressed.js
Normal file
2193
packages/test-in-browser/diff_match_patch_uncompressed.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -132,3 +132,18 @@ body {
|
||||
top: 10px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.string_equal {
|
||||
line-height: 1.2;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.string_equal ins {
|
||||
text-decoration: none;
|
||||
}
|
||||
.string_equal_expected ins {
|
||||
background: #fe0;
|
||||
}
|
||||
.string_equal_actual ins {
|
||||
color: #d00;
|
||||
background: #fcc;
|
||||
}
|
||||
|
||||
@@ -458,46 +458,81 @@ Template.event.events({
|
||||
}
|
||||
});
|
||||
|
||||
Template.event.get_details = function() {
|
||||
|
||||
var prepare = function(details) {
|
||||
return _.compact(_.map(details, function(val, key) {
|
||||
|
||||
// You can end up with a an undefined value, e.g. using
|
||||
// isNull without providing a message attribute: isNull(1).
|
||||
// No need to display those.
|
||||
if (!_.isUndefined(val)) {
|
||||
return {
|
||||
key: key,
|
||||
val: val
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
};
|
||||
|
||||
var details = this.details;
|
||||
|
||||
if (! details) {
|
||||
return null;
|
||||
} else {
|
||||
|
||||
var type = details.type;
|
||||
var stack = details.stack;
|
||||
|
||||
details = _.clone(details);
|
||||
delete details.type;
|
||||
delete details.stack;
|
||||
|
||||
return {
|
||||
type: type,
|
||||
stack: stack,
|
||||
details: prepare(details)
|
||||
};
|
||||
}
|
||||
// e.g. doDiff('abc', 'bcd') => [[-1, 'a'], [0, 'bc'], [1, 'd']]
|
||||
var doDiff = function (str1, str2) {
|
||||
var D = new diff_match_patch();
|
||||
var pieces = D.diff_main(str1, str2, false);
|
||||
D.diff_cleanupSemantic(pieces);
|
||||
return pieces;
|
||||
};
|
||||
|
||||
Template.event.helpers({
|
||||
get_details: function() {
|
||||
|
||||
var details = this.details;
|
||||
|
||||
if (! details) {
|
||||
return null;
|
||||
} else {
|
||||
|
||||
var type = details.type;
|
||||
var stack = details.stack;
|
||||
|
||||
details = _.clone(details);
|
||||
delete details.type;
|
||||
delete details.stack;
|
||||
var prepare = function(details) {
|
||||
if (type === 'string_equal') {
|
||||
var diff = doDiff(details.actual,
|
||||
details.expected);
|
||||
}
|
||||
|
||||
return _.compact(_.map(details, function(val, key) {
|
||||
|
||||
// make test._stringEqual results print nicely,
|
||||
// in particular for multiline strings
|
||||
if (type === 'string_equal' &&
|
||||
(key === 'actual' || key === 'expected')) {
|
||||
var html = '<pre class="string_equal string_equal_'+key+'">';
|
||||
_.each(diff, function (piece) {
|
||||
var which = piece[0];
|
||||
var text = piece[1];
|
||||
if (which === 0 ||
|
||||
which === (key === 'actual' ? -1 : 1)) {
|
||||
var htmlBit = Handlebars._escape(text).replace(
|
||||
/\n/g, '<br>');
|
||||
if (which !== 0)
|
||||
htmlBit = '<ins>' + htmlBit + '</ins>';
|
||||
html += htmlBit;
|
||||
}
|
||||
});
|
||||
html += '</pre>';
|
||||
val = new Handlebars.SafeString(html);
|
||||
}
|
||||
|
||||
// You can end up with a an undefined value, e.g. using
|
||||
// isNull without providing a message attribute: isNull(1).
|
||||
// No need to display those.
|
||||
if (!_.isUndefined(val)) {
|
||||
return {
|
||||
key: key,
|
||||
val: val
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
};
|
||||
|
||||
return {
|
||||
type: type,
|
||||
stack: stack,
|
||||
details: prepare(details)
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.event.is_debuggable = function() {
|
||||
return !!this.cookie;
|
||||
};
|
||||
|
||||
@@ -16,6 +16,8 @@ Package.on_use(function (api) {
|
||||
|
||||
api.use(['spark', 'livedata', 'templating', 'deps'], 'client');
|
||||
|
||||
api.add_files('diff_match_patch_uncompressed.js', 'client');
|
||||
|
||||
api.add_files([
|
||||
'driver.css',
|
||||
'driver.html',
|
||||
|
||||
@@ -107,6 +107,13 @@ _.extend(TestCaseResults.prototype, {
|
||||
|
||||
// XXX eliminate 'message' and 'not' arguments
|
||||
equal: function (actual, expected, message, not) {
|
||||
|
||||
if ((! not) && (typeof actual === 'string') &&
|
||||
(typeof expected === 'string')) {
|
||||
this._stringEqual(actual, expected, message);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If expected is a DOM node, do a literal '===' comparison with
|
||||
* actual. Otherwise do a deep comparison, as implemented by _.isEqual.
|
||||
*/
|
||||
@@ -162,7 +169,7 @@ _.extend(TestCaseResults.prototype, {
|
||||
},
|
||||
|
||||
// XXX nodejs assert.throws can take an expected error, as a class,
|
||||
// regular expression, or predicate function. However, with its
|
||||
// regular expression, or predicate function. However, with its
|
||||
// implementation if a constructor (class) is passed in and `actual`
|
||||
// fails the instanceof test, the constructor is then treated as
|
||||
// a predicate and called with `actual` (!)
|
||||
@@ -269,8 +276,23 @@ _.extend(TestCaseResults.prototype, {
|
||||
else
|
||||
this.fail({type: "length", expected: expected_length,
|
||||
actual: obj.length});
|
||||
},
|
||||
|
||||
// EXPERIMENTAL way to compare two strings that results in
|
||||
// a nicer display in the test runner, e.g. for multiline
|
||||
// strings
|
||||
_stringEqual: function (actual, expected, message) {
|
||||
if (actual !== expected) {
|
||||
this.fail({type: "string_equal",
|
||||
message: message,
|
||||
expected: expected,
|
||||
actual: actual});
|
||||
} else {
|
||||
this.ok();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
102
tools/bundler.js
102
tools/bundler.js
@@ -159,9 +159,9 @@
|
||||
// wait until later.
|
||||
|
||||
var path = require('path');
|
||||
var util = require('util');
|
||||
var files = require(path.join(__dirname, 'files.js'));
|
||||
var packages = require(path.join(__dirname, 'packages.js'));
|
||||
var linker = require(path.join(__dirname, 'linker.js'));
|
||||
var Builder = require(path.join(__dirname, 'builder.js'));
|
||||
var archinfo = require(path.join(__dirname, 'archinfo.js'));
|
||||
var buildmessage = require('./buildmessage.js');
|
||||
@@ -457,6 +457,11 @@ _.extend(Target.prototype, {
|
||||
// Link JavaScript and set up self.js, etc.
|
||||
self._emitResources();
|
||||
|
||||
// Preprocess and concatenate CSS files for client targets.
|
||||
if (self instanceof ClientTarget) {
|
||||
self.mergeCss();
|
||||
}
|
||||
|
||||
// Minify, if requested
|
||||
if (options.minify) {
|
||||
var minifiers = unipackage.load({
|
||||
@@ -464,8 +469,11 @@ _.extend(Target.prototype, {
|
||||
packages: ['minifiers']
|
||||
}).minifiers;
|
||||
self.minifyJs(minifiers);
|
||||
if (self.minifyCss) // XXX a bit of a hack
|
||||
|
||||
// CSS is minified only for client targets.
|
||||
if (self instanceof ClientTarget) {
|
||||
self.minifyCss(minifiers);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.addCacheBusters) {
|
||||
@@ -669,7 +677,8 @@ _.extend(Target.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
if (resource.type === "js" && resource.sourceMap) {
|
||||
// Both CSS and JS files can have source maps
|
||||
if (resource.sourceMap) {
|
||||
f.setSourceMap(resource.sourceMap, path.dirname(relPath));
|
||||
}
|
||||
|
||||
@@ -753,9 +762,11 @@ var ClientTarget = function (options) {
|
||||
var self = this;
|
||||
Target.apply(this, arguments);
|
||||
|
||||
// CSS files. List of File. They will be loaded at page load in the
|
||||
// order given.
|
||||
// CSS files. List of File. They will be loaded in the order given.
|
||||
self.css = [];
|
||||
// Cached CSS AST. If non-null, self.css has one item in it, processed CSS
|
||||
// from merged input files, and this is its parse tree.
|
||||
self._cssAstCache = null;
|
||||
|
||||
// List of segments of additional HTML for <head>/<body>.
|
||||
self.head = [];
|
||||
@@ -768,17 +779,88 @@ var ClientTarget = function (options) {
|
||||
inherits(ClientTarget, Target);
|
||||
|
||||
_.extend(ClientTarget.prototype, {
|
||||
// Lints CSS files and merges them into one file, fixing up source maps and
|
||||
// pulling any @import directives up to the top since the CSS spec does not
|
||||
// allow them to appear in the middle of a file.
|
||||
mergeCss: function () {
|
||||
var self = this;
|
||||
var minifiers = unipackage.load({
|
||||
library: self.library,
|
||||
packages: ['minifiers']
|
||||
}).minifiers;
|
||||
var CssTools = minifiers.CssTools;
|
||||
|
||||
// Filenames passed to AST manipulator mapped to their original files
|
||||
var originals = {};
|
||||
|
||||
var cssAsts = _.map(self.css, function (file) {
|
||||
var filename = file.url.replace(/^\//, '');
|
||||
originals[filename] = file;
|
||||
try {
|
||||
var parseOptions = { source: filename, position: true };
|
||||
var ast = CssTools.parseCss(file.contents('utf8'), parseOptions);
|
||||
ast.filename = filename;
|
||||
} catch (e) {
|
||||
buildmessage.error(e.message, { file: filename });
|
||||
return { type: "stylesheet", stylesheet: { rules: [] },
|
||||
filename: filename };
|
||||
}
|
||||
|
||||
return ast;
|
||||
});
|
||||
|
||||
var warnCb = function (filename, msg) {
|
||||
// XXX make this a buildmessage.warning call rather than a random log
|
||||
console.log("%s: warn: %s", filename, msg);
|
||||
};
|
||||
|
||||
// Other build phases might need this AST later
|
||||
self._cssAstCache = CssTools.mergeCssAsts(cssAsts, warnCb);
|
||||
|
||||
// Overwrite the CSS files list with the new concatenated file
|
||||
var stringifiedCss = CssTools.stringifyCss(self._cssAstCache,
|
||||
{ sourcemap: true });
|
||||
self.css = [new File({ data: new Buffer(stringifiedCss.code, 'utf8') })];
|
||||
|
||||
// Add the contents of the input files to the source map of the new file
|
||||
stringifiedCss.map.sourcesContent =
|
||||
_.map(stringifiedCss.map.sources, function (filename) {
|
||||
return originals[filename].contents('utf8');
|
||||
});
|
||||
|
||||
// If any input files had source maps, apply them.
|
||||
// Ex.: less -> css source map should be composed with css -> css source map
|
||||
var newMap = sourcemap.SourceMapGenerator.fromSourceMap(
|
||||
new sourcemap.SourceMapConsumer(stringifiedCss.map));
|
||||
|
||||
_.each(originals, function (file, name) {
|
||||
if (! file.sourceMap)
|
||||
return;
|
||||
newMap.applySourceMap(
|
||||
new sourcemap.SourceMapConsumer(file.sourceMap), name);
|
||||
});
|
||||
|
||||
self.css[0].setSourceMap(JSON.stringify(newMap));
|
||||
self.css[0].setUrlToHash(".css");
|
||||
},
|
||||
// Minify the CSS in this target
|
||||
minifyCss: function (minifiers) {
|
||||
var self = this;
|
||||
var minifiedCss = '';
|
||||
|
||||
var allCss = _.map(self.css, function (file) {
|
||||
return file.contents('utf8');
|
||||
}).join('\n');
|
||||
// If there is an AST already calculated, don't waste time on parsing it
|
||||
// again.
|
||||
if (self._cssAstCache) {
|
||||
minifiedCss = minifiers.CssTools.minifyCssAst(self._cssAstCache);
|
||||
} else if (self.css) {
|
||||
var allCss = _.map(self.css, function (file) {
|
||||
return file.contents('utf8');
|
||||
}).join('\n');
|
||||
|
||||
allCss = minifiers.CleanCSSProcess(allCss);
|
||||
minifiedCss = minifiers.CssTools.minifyCss(allCss);
|
||||
}
|
||||
|
||||
self.css = [new File({ data: new Buffer(allCss, 'utf8') })];
|
||||
self.css = [new File({ data: new Buffer(minifiedCss, 'utf8') })];
|
||||
self.css[0].setUrlToHash(".css", "?meteor_css_resource=true");
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user