diff --git a/packages/accounts-ui-unstyled/login_buttons.less b/packages/accounts-ui-unstyled/login_buttons.import.less similarity index 100% rename from packages/accounts-ui-unstyled/login_buttons.less rename to packages/accounts-ui-unstyled/login_buttons.import.less diff --git a/packages/accounts-ui-unstyled/package.js b/packages/accounts-ui-unstyled/package.js index 9311fd6928..d2556b11ca 100644 --- a/packages/accounts-ui-unstyled/package.js +++ b/packages/accounts-ui-unstyled/package.js @@ -33,10 +33,10 @@ Package.onUse(function (api) { // The less source defining the default style for accounts-ui. Just adding // this package doesn't actually apply these styles; they need to be - // `@import`ed from some *.main.less file. The accounts-ui package does that - // for you, or you can do it in your app. + // `@import`ed from some non-import less file. The accounts-ui package does + // that for you, or you can do it in your app. api.use('less'); - api.addFiles('login_buttons.less'); + api.addFiles('login_buttons.import.less'); }); Package.onTest(function (api) { diff --git a/packages/accounts-ui/login_buttons.main.less b/packages/accounts-ui/login_buttons.less similarity index 100% rename from packages/accounts-ui/login_buttons.main.less rename to packages/accounts-ui/login_buttons.less diff --git a/packages/accounts-ui/package.js b/packages/accounts-ui/package.js index 9dc4cd09ac..91a0dbcf14 100644 --- a/packages/accounts-ui/package.js +++ b/packages/accounts-ui/package.js @@ -9,5 +9,5 @@ Package.onUse(function (api) { api.use('accounts-ui-unstyled', 'client'); api.use('less', 'client'); - api.addFiles(['login_buttons.main.less'], 'client'); + api.addFiles(['login_buttons.less'], 'client'); }); diff --git a/packages/less/package.js b/packages/less/package.js index cc241f05bd..491e0cf293 100644 --- a/packages/less/package.js +++ b/packages/less/package.js @@ -25,13 +25,14 @@ Package.onUse(function (api) { Package.onTest(function(api) { api.use('less'); api.use(['tinytest', 'test-helpers']); - api.addFiles(['tests/top.less', - 'tests/top2.less', - 'tests/top3.less', - 'tests/not-included.less', - 'tests/dir/in-dir.less', - 'tests/dir/in-dir2.less', - 'tests/dir/root.main.less', - 'tests/dir/subdir/in-subdir.less']); + api.addFiles(['tests/top.import.less', + 'tests/top3.import.less', + 'tests/import/not-included.less', + 'tests/dir/in-dir.import.less', + 'tests/dir/in-dir2.import.less', + 'tests/dir/root.less', + 'tests/dir/subdir/in-subdir.import.less']); + api.addFiles('tests/top2.less', 'client', {isImport: true}); + api.addFiles('less_tests.js', 'client'); }); diff --git a/packages/less/plugin/compile-less.js b/packages/less/plugin/compile-less.js index 73c2321d8d..d4ec8cb0b8 100644 --- a/packages/less/plugin/compile-less.js +++ b/packages/less/plugin/compile-less.js @@ -6,7 +6,9 @@ var Future = Npm.require('fibers/future'); var LRU = Npm.require('lru-cache'); Plugin.registerCompiler({ - extensions: ['less'], + // *.lessimport has been deprecated since 0.7.1, but it still works. We + // *recommend *.import.less or the import subdirectory instead. + extensions: ['less', 'lessimport'], archMatching: 'web' }, function () { return new LessCompiler(); @@ -35,7 +37,7 @@ _.extend(LessCompiler.prototype, { processFilesForTarget: function (inputFiles) { var self = this; var filesByAbsoluteImportPath = {}; - var mains = []; + var roots = []; var cacheMisses = []; function decodeFilePath (filePath) { @@ -54,20 +56,32 @@ _.extend(LessCompiler.prototype, { inputFiles.forEach(function (inputFile) { var packageName = inputFile.getPackageName(); var pathInPackage = inputFile.getPathInPackage(); + var fileOptions = inputFile.getFileOptions(); var absoluteImportPath = packageName === null ? ('{}/' + pathInPackage) : ('{' + packageName + '}/' + pathInPackage); filesByAbsoluteImportPath[absoluteImportPath] = inputFile; + + // The heuristic is that a file is an import (ie, is not itself processed + // as a root) if it is in a subdirectory named 'import' or if it matches + // *.import.less. This can be overridden in either direction via an + // explicit `isImport` file option in apiaddFiles. + var filenameSaysImport = + /\.import\.less$/.test(pathInPackage) || + /\.lessimport$/.test(pathInPackage) || + /(?:^|\/)import\//.test(pathInPackage); + var isImport = fileOptions.hasOwnProperty('isImport') + ? fileOptions.isImport : filenameSaysImport; // Match files named `main.less` or with a `.main.less` extension - if (pathInPackage.match(/(^|\/|\.)main\.less$/)) { - mains.push({inputFile: inputFile, + if (! isImport) { + roots.push({inputFile: inputFile, absoluteImportPath: absoluteImportPath}); } }); var importPlugin = new MeteorImportLessPlugin(filesByAbsoluteImportPath); - mains.forEach(function (main) { + roots.forEach(function (main) { var inputFile = main.inputFile; var absoluteImportPath = main.absoluteImportPath; diff --git a/packages/less/tests/dir/in-dir.less b/packages/less/tests/dir/in-dir.import.less similarity index 100% rename from packages/less/tests/dir/in-dir.less rename to packages/less/tests/dir/in-dir.import.less diff --git a/packages/less/tests/dir/in-dir2.less b/packages/less/tests/dir/in-dir2.import.less similarity index 100% rename from packages/less/tests/dir/in-dir2.less rename to packages/less/tests/dir/in-dir2.import.less diff --git a/packages/less/tests/dir/root.main.less b/packages/less/tests/dir/root.less similarity index 65% rename from packages/less/tests/dir/root.main.less rename to packages/less/tests/dir/root.less index 809f28eaba..192beba072 100644 --- a/packages/less/tests/dir/root.main.less +++ b/packages/less/tests/dir/root.less @@ -1,8 +1,8 @@ -@import "/tests/top.less"; +@import "/tests/top.import.less"; @import "{local-test:less}/tests/top2.less"; -@import "in-dir.less"; -@import "./in-dir2.less"; -@import "subdir/in-subdir.less"; +@import "in-dir.import.less"; +@import "./in-dir2.import.less"; +@import "subdir/in-subdir.import.less"; .el1 { border-style: @el1-style; } diff --git a/packages/less/tests/dir/subdir/in-subdir.less b/packages/less/tests/dir/subdir/in-subdir.import.less similarity index 100% rename from packages/less/tests/dir/subdir/in-subdir.less rename to packages/less/tests/dir/subdir/in-subdir.import.less diff --git a/packages/less/tests/not-included.less b/packages/less/tests/import/not-included.less similarity index 100% rename from packages/less/tests/not-included.less rename to packages/less/tests/import/not-included.less diff --git a/packages/less/tests/top.less b/packages/less/tests/top.import.less similarity index 76% rename from packages/less/tests/top.less rename to packages/less/tests/top.import.less index 1f80ae5349..4d9828eecd 100644 --- a/packages/less/tests/top.less +++ b/packages/less/tests/top.import.less @@ -2,4 +2,4 @@ /* Test that package-relative imports work from within a * package-relative-imported file */ -@import "/tests/top3.less"; +@import "/tests/top3.import.less"; diff --git a/packages/less/tests/top3.less b/packages/less/tests/top3.import.less similarity index 100% rename from packages/less/tests/top3.less rename to packages/less/tests/top3.import.less diff --git a/tools/compiler-plugin.js b/tools/compiler-plugin.js index ebfca06fc2..f0f16ff7fd 100644 --- a/tools/compiler-plugin.js +++ b/tools/compiler-plugin.js @@ -134,7 +134,7 @@ _.extend(InputFile.prototype, { var self = this; // XXX fileOptions only exists on some resources (of type "source"). The JS // resources might not have this property. - return self._resourceSlot.inputResource.fileOptions; + return self._resourceSlot.inputResource.fileOptions || {}; }, getArch: function () { return this._resourceSlot.packageSourceBatch.processor.arch; diff --git a/tools/tests/apps/coffee-and-less/dotdot.less b/tools/tests/apps/coffee-and-less/import/dotdot.less similarity index 100% rename from tools/tests/apps/coffee-and-less/dotdot.less rename to tools/tests/apps/coffee-and-less/import/dotdot.less diff --git a/tools/tests/apps/coffee-and-less/packages/local-pack/package.js b/tools/tests/apps/coffee-and-less/packages/local-pack/package.js index 3574e4e155..4f0df7b7b1 100644 --- a/tools/tests/apps/coffee-and-less/packages/local-pack/package.js +++ b/tools/tests/apps/coffee-and-less/packages/local-pack/package.js @@ -1,5 +1,6 @@ Package.onUse(function (api) { api.use(['coffeescript', 'less']); - api.addFiles(['p.coffee', 'p.less']); + api.addFiles(['p.coffee']); + api.addFiles('p.less', 'client', {isImport: true}); api.export('FromPackage'); }); diff --git a/tools/tests/apps/coffee-and-less/subdir/foo.import.less b/tools/tests/apps/coffee-and-less/subdir/foo.import.less new file mode 100644 index 0000000000..c3505dfd93 --- /dev/null +++ b/tools/tests/apps/coffee-and-less/subdir/foo.import.less @@ -0,0 +1,2 @@ +@el2-style: solid; +@import "../import/dotdot.less"; diff --git a/tools/tests/apps/coffee-and-less/subdir/foo.less b/tools/tests/apps/coffee-and-less/subdir/foo.less deleted file mode 100644 index 2261e8cc30..0000000000 --- a/tools/tests/apps/coffee-and-less/subdir/foo.less +++ /dev/null @@ -1,2 +0,0 @@ -@el2-style: solid; -@import "../dotdot.less"; diff --git a/tools/tests/apps/coffee-and-less/subdir/nested-root.main.less b/tools/tests/apps/coffee-and-less/subdir/nested-root.less similarity index 100% rename from tools/tests/apps/coffee-and-less/subdir/nested-root.main.less rename to tools/tests/apps/coffee-and-less/subdir/nested-root.less diff --git a/tools/tests/apps/coffee-and-less/top.main.less b/tools/tests/apps/coffee-and-less/top.less similarity index 85% rename from tools/tests/apps/coffee-and-less/top.main.less rename to tools/tests/apps/coffee-and-less/top.less index 3ce4459c9c..3d9f6da5a8 100644 --- a/tools/tests/apps/coffee-and-less/top.main.less +++ b/tools/tests/apps/coffee-and-less/top.less @@ -1,5 +1,5 @@ @first-style: dotted; -@import "subdir/foo.less"; +@import "subdir/foo.import.less"; .el1 { border-style: @first-style; } .el2 { border-style: @el2-style; } diff --git a/tools/tests/compiler-plugins.js b/tools/tests/compiler-plugins.js index 6d58981ebe..ecc7c9a74e 100644 --- a/tools/tests/compiler-plugins.js +++ b/tools/tests/compiler-plugins.js @@ -34,7 +34,7 @@ selftest.define("compiler plugin caching - coffee/less", function () { ['/f1.coffee', '/f2.coffee', '/f3.coffee', '/packages/local-pack/p.coffee'] )); run.match('Ran less.render (#1) on: ' + JSON.stringify( - ["/subdir/nested-root.main.less", "/top.main.less"])); + ["/subdir/nested-root.less", "/top.less"])); // Second program doesn't need to compile anything because compilation works // the same on both programs. (Note that there is no less.render execution in // the second program, because it has archMatching: 'web'. We'll see this @@ -97,26 +97,26 @@ selftest.define("compiler plugin caching - coffee/less", function () { s.write('packages/local-pack/p.less', '@el4-style: inset;\n'); expectedBorderStyles.el4 = 'inset'; run.match('Ran coffee.compile (#9) on: []'); - run.match('Ran less.render (#5) on: ["/top.main.less"]'); + run.match('Ran less.render (#5) on: ["/top.less"]'); // Note that since this was a client-only change, we're smart enough to not // rebuild the server at all. So the next coffee.compile will be #10. run.match("Client modified -- refreshing"); checkCSS(expectedBorderStyles); // This works for changing a root too. - s.write('subdir/nested-root.main.less', '.el0 { border-style: double; }\n'); + s.write('subdir/nested-root.less', '.el0 { border-style: double; }\n'); expectedBorderStyles.el0 = 'double'; // Only #10, not #11, because client-only changes don't rebuild the server! run.match('Ran coffee.compile (#10) on: []'); - run.match('Ran less.render (#6) on: ["/subdir/nested-root.main.less"]'); + run.match('Ran less.render (#6) on: ["/subdir/nested-root.less"]'); run.match("Client modified -- refreshing"); checkCSS(expectedBorderStyles); // Adding a new root works too. - s.write('yet-another-root.main.less', '.el6 { border-style: solid; }\n'); + s.write('yet-another-root.less', '.el6 { border-style: solid; }\n'); expectedBorderStyles.el6 = 'solid'; run.match('Ran coffee.compile (#11) on: []'); - run.match('Ran less.render (#7) on: ["/yet-another-root.main.less"]'); + run.match('Ran less.render (#7) on: ["/yet-another-root.less"]'); run.match("Client modified -- refreshing"); checkCSS(expectedBorderStyles); @@ -137,15 +137,15 @@ selftest.define("compiler plugin caching - coffee/less", function () { run.match('Loaded less cache'); // And we only need to re-compiler the changed file, even though we restarted. run.match('Ran coffee.compile (#1) on: ["/f2.coffee"]'); - run.match('Ran less.render (#1) on: ["/top.main.less"]'); + run.match('Ran less.render (#1) on: ["/top.less"]'); run.match('Ran coffee.compile (#2) on: []'); run.match('Coffeescript X is 2 Y is edited FromPackage is 5'); checkCSS(expectedBorderStyles); - s.write('bad-import.main.less', '@import "/foo/bad.less";\n'); + s.write('bad-import.less', '@import "/foo/bad.less";\n'); run.match('Errors prevented startup'); - run.match('bad-import.main.less:1: Unknown import: /foo/bad.less'); + run.match('bad-import.less:1: Unknown import: /foo/bad.less'); run.match('Waiting for file change'); run.stop(); diff --git a/tools/upgraders.js b/tools/upgraders.js index 41a1955f3a..9d8c0ddd2e 100644 --- a/tools/upgraders.js +++ b/tools/upgraders.js @@ -134,8 +134,6 @@ var upgradersByName = { projectContext.projectConstraintsFile.writeIfModified(); } - // XXX #BBPLessUpgrader Write an upgrader explaining the changes to less. - //////////// // PLEASE. When adding new upgraders that print mesasges, follow the // examples for 0.9.0 and 0.9.1 above. Specifically, formatting