From 9e5c89bf0cb29f77c50f6cf94601ed418960d138 Mon Sep 17 00:00:00 2001 From: Dan Dascalescu Date: Fri, 28 Nov 2014 22:33:39 -0800 Subject: [PATCH 1/2] Add packaging for Meteor.js, http://meteor.com --- .gitignore | 1 + Gruntfile.js | 17 +++++++++++ meteor/README.md | 25 +++++++++++++++ meteor/export.js | 3 ++ meteor/package.js | 33 ++++++++++++++++++++ meteor/publish.sh | 76 ++++++++++++++++++++++++++++++++++++++++++++++ meteor/runtests.sh | 37 ++++++++++++++++++++++ meteor/test.js | 58 +++++++++++++++++++++++++++++++++++ package.json | 3 +- 9 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 meteor/README.md create mode 100644 meteor/export.js create mode 100644 meteor/package.js create mode 100755 meteor/publish.sh create mode 100755 meteor/runtests.sh create mode 100644 meteor/test.js diff --git a/.gitignore b/.gitignore index 0402acd7..c92d6eaa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ components/ bower_components/ node_modules/ sandbox/**/bundle.js +.build* diff --git a/Gruntfile.js b/Gruntfile.js index 4026fa2c..bfce21bf 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -54,6 +54,15 @@ module.exports = function( grunt ) { banner: banner } } + }, + + shell: { + 'meteor-test': { + command: 'meteor/runtests.sh' + }, + 'meteor-publish': { + command: 'meteor/publish.sh' + } } }); @@ -61,6 +70,7 @@ module.exports = function( grunt ) { grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-requirejs'); + grunt.loadNpmTasks('grunt-shell'); grunt.registerTask( 'pkgd-edit', function() { var outFile = grunt.config.get('requirejs.pkgd.options.out'); @@ -77,6 +87,13 @@ module.exports = function( grunt ) { grunt.log.writeln( 'Edited ' + outFile ); }); + grunt.registerTask('meteor-test', 'shell:meteor-test'); + grunt.registerTask('meteor-publish', 'shell:meteor-publish'); + // ideally we'd run tests before publishing, but the chances of tests breaking (given that + // Meteor is orthogonal to the library) are so small that it's not worth the maintainer's time + // grunt.regsterTask('meteor', ['shell:meteor-test', 'shell:meteor-publish']); + grunt.registerTask('meteor', 'shell:meteor-publish'); + grunt.registerTask( 'default', [ 'jshint', 'requirejs', diff --git a/meteor/README.md b/meteor/README.md new file mode 100644 index 00000000..f60a94e3 --- /dev/null +++ b/meteor/README.md @@ -0,0 +1,25 @@ +Packaging [Isotope](http://isotope.metafizzy.co/) for [Meteor.js](http://meteor.com). + + +# Meteor + +If you're new to Meteor, here's what the excitement is all about - +[watch the first two minutes](https://www.youtube.com/watch?v=fsi0aJ9yr2o); you'll be hooked by 1:28. + +That screencast is from 2012. In the meantime, Meteor has become a mature JavaScript-everywhere web +development framework. Read more at [Why Meteor](http://www.meteorpedia.com/read/Why_Meteor). + + +# Issues + +If you encounter an issue while using this package, please CC @dandv when you file it in this repo. + + +# DONE + +* Automated and visual test for the fitRows layout + + +# TODO + +* Add other tests; however, that is overkill, and the responsibiity of Isotope, not of the Meteor integration. diff --git a/meteor/export.js b/meteor/export.js new file mode 100644 index 00000000..9ff01af0 --- /dev/null +++ b/meteor/export.js @@ -0,0 +1,3 @@ +/*global Isotope:true*/ // Meteor.js creates a file-scope global for exporting. This comment prevents a potential JSHint warning. +Isotope = window.Isotope; +delete window.Isotope; diff --git a/meteor/package.js b/meteor/package.js new file mode 100644 index 00000000..280aa252 --- /dev/null +++ b/meteor/package.js @@ -0,0 +1,33 @@ +// package metadata file for Meteor.js +'use strict'; + +var packageName = 'isotope:isotope'; // http://atmospherejs.com/isotope/isotope +var where = 'client'; // where to install: 'client' or 'server'. For both, pass nothing. + +var packageJson = JSON.parse(Npm.require("fs").readFileSync('package.json')); + +Package.describe({ + name: packageName, + summary: 'Isotope (official): filter and sort magical layouts: fit rows, packery, masonry, fit columns etc.', // limited to 100 characters + version: packageJson.version, + git: 'https://github.com/metafizzy/isotope.git' +}); + +Package.onUse(function (api) { + api.versionsFrom('METEOR@1.0'); + api.export('Isotope'); + api.addFiles([ + 'dist/isotope.pkgd.js', + 'meteor/export.js' + ], where); +}); + +Package.onTest(function (api) { + api.use(packageName, where); + api.use(['tinytest', 'http'], where); + + api.addFiles([ + 'test/tests.css', + 'meteor/test.js' + ], where); +}); diff --git a/meteor/publish.sh b/meteor/publish.sh new file mode 100755 index 00000000..6969635c --- /dev/null +++ b/meteor/publish.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Publish package on Meteor's Atmosphere.js + +# Make sure Meteor is installed, per https://www.meteor.com/install. The curl'ed script is totally safe; takes 2 minutes to read its source and check. +type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; } + +# sanity check: make sure we're in the root directory of the checkout +cd "$( dirname "$0" )/.." + + +function cleanup() { + # we copied the file as package.js, regardless of its original name + rm package.js + + # temporary build files + rm -rf ".build.$PACKAGE_NAME" versions.json +} + + +# publish separately any package*.js files we have, e.g. package.js, package-compat.js +for PACKAGE_FILE in meteor/package*.js; do + + # Meteor expects package.js to be in the root directory of the checkout, so copy there our package file under that name, temporarily + cp $PACKAGE_FILE ./package.js + + # publish package, creating it if it's the first time we're publishing + PACKAGE_NAME=$(grep -i name $PACKAGE_FILE | head -1 | cut -d "'" -f 2) + ATMOSPHERE_NAME=${PACKAGE_NAME/://} + + echo "Publishing $PACKAGE_NAME..." + + # attempt to re-publish the package - the most common operation once the initial release has been made + OUTPUT=$( meteor publish 2>&1 ) + + if (( $? > 0 )); then + # there was an error + + if [[ $OUTPUT =~ "There is no package named" ]]; then + # actually this is the first time the package is created, so pass the special --create flag and congratulate the maintainer + echo "Thank you for creating the official Meteor package for this library!" + if meteor publish --create; then + echo "Please post the following to https://github.com/raix/Meteor-community-discussions/issues/14: + +--------------------------------------------- 8< -------------------------------------------------------- + +Happy to announce that I've published the official $PACKAGE_NAME to Atmosphere. Please star! +https://atmospherejs.com/$ATMOSPHERE_NAME + +--------------------------------------------- >8 -------------------------------------------------------- + +" + else + echo "We got an error. Please post it at https://github.com/raix/Meteor-community-discussions/issues/14" + cleanup + exit 1 + fi + else + # the error wasn't that the package didn't exist, so we need to ask for help + echo "We got an error. Please post it at https://github.com/raix/Meteor-community-discussions/issues/14: +--------------------------------------------- 8< -------------------------------------------------------- +$OUTPUT +--------------------------------------------- >8 -------------------------------------------------------- +" + cleanup + exit 1 + fi + else + # no error on the first `meteor publish` attempt + echo "$OUTPUT" # just in case meteor said something interesting + echo "Thanks for releasing a new version of $PACKAGE_NAME! You can see it at +https://atmospherejs.com/$ATMOSPHERE_NAME" + fi + + cleanup + +done diff --git a/meteor/runtests.sh b/meteor/runtests.sh new file mode 100755 index 00000000..400eee90 --- /dev/null +++ b/meteor/runtests.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Test Meteor package before publishing to Atmospherejs.com + +# Make sure Meteor is installed, per https://www.meteor.com/install. The curl'ed script is totally safe; takes 2 minutes to read its source and check. +type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; } + +# sanity check: make sure we're in the root directory of the checkout +cd "$( dirname "$0" )/.." + +# run tests and delete the temporary package.js even if Ctrl+C is pressed +int_trap() { + echo + printf "Tests interrupted. Hopefully you verified in the browser that tests pass?\n\n" +} + +trap int_trap INT + +# test any package*.js packages we may have, e.g. package.js, package-compat.js +for PACKAGE_FILE in meteor/package*.js; do + + PACKAGE_NAME=$(grep -i name $PACKAGE_FILE | head -1 | cut -d "'" -f 2) + + echo "Testing $PACKAGE_NAME..." + + # Meteor expects package.js to be in the root directory of the checkout, so copy there our package file under that name, temporarily + cp $PACKAGE_FILE ./package.js + + # provide an invalid MONGO_URL so Meteor doesn't bog us down with an empty Mongo database + MONGO_URL=mongodb:// meteor test-packages ./ + + rm -rf ".build.$PACKAGE_NAME" + rm -rf ".build.local-test:$PACKAGE_NAME" + rm versions.json 2>/dev/null + + rm package.js + +done diff --git a/meteor/test.js b/meteor/test.js new file mode 100644 index 00000000..c4793990 --- /dev/null +++ b/meteor/test.js @@ -0,0 +1,58 @@ +'use strict'; + +Tinytest.addAsync('Isotope - fitRows', function (test, done) { + var isotopeDropZone = document.createElement('div'); + document.body.appendChild(isotopeDropZone); + + // TODO ideally we'd get the htmls straight from this repo, but no idea how to do this from TinyTest - http://stackoverflow.com/questions/27180892/pull-an-html-file-into-a-tinytest + HTTP.get('https://rawgit.com/metafizzy/isotope/master/test/index.html', function callback(error, result) { + + // adapted from test/fit-rows.js + function checkPosition(item, x, y) { + var elem = item.element; + var left = parseInt(elem.style.left, 10); + var top = parseInt(elem.style.top, 10); + test.equal([ left, top ], [ x, y ], 'item position ' + x + ', ' + y); + } + + if (error) { + test.fail({message: 'Error getting the test file. Do we have an Internet connection to rawgit.com?'}); + } else { + // [^] matches across newlines. Stay within the , or else the fragment will attempt to load resources on its own. + isotopeDropZone.innerHTML = result.content.match(/

fitRows[^]+<\/div>/); + + test.ok({message: 'Visual test passed if the fitRows look like two towers, and failed if they look like a rotated L'}); + + var iso = new Isotope('#fitrows-gutter', { + layoutMode: 'fitRows', + itemSelector: '.item', + transitionDuration: 0 + }); + + checkPosition(iso.items[0], 0, 0); + checkPosition(iso.items[1], 60, 0); + + // check gutter + iso.options.fitRows = { + gutter: 10 + }; + iso.layout(); + + checkPosition(iso.items[0], 0, 0); + checkPosition(iso.items[1], 70, 0); + + // check gutter, with element sizing + iso.options.fitRows = { + gutter: '.gutter-sizer' + }; + iso.layout(); + + checkPosition(iso.items[0], 0, 0); + checkPosition(iso.items[1], 78, 0); + } + + done(); + + }); + +}); diff --git a/package.json b/package.json index b78407ef..4270dd27 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "grunt": "~0.4.0", "grunt-contrib-jshint": "~0.4.1", "grunt-contrib-uglify": "~0.1.1", - "grunt-requirejs": "~0.4.0" + "grunt-requirejs": "~0.4.0", + "grunt-shell": "*" }, "repository": { "type": "git", From 0b49834e689d85c33fbd2b08c13e1a73fe40c6a6 Mon Sep 17 00:00:00 2001 From: Dan Dascalescu Date: Sun, 30 Nov 2014 00:45:23 -0800 Subject: [PATCH 2/2] Remove Meteor .sh files, automate testing --- Gruntfile.js | 34 ++++++++++++++------- meteor/package.js | 2 +- meteor/publish.sh | 76 ---------------------------------------------- meteor/runtests.sh | 37 ---------------------- meteor/test.js | 2 +- package.json | 3 +- 6 files changed, 27 insertions(+), 127 deletions(-) delete mode 100755 meteor/publish.sh delete mode 100755 meteor/runtests.sh diff --git a/Gruntfile.js b/Gruntfile.js index bfce21bf..6e497ca1 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -56,12 +56,26 @@ module.exports = function( grunt ) { } }, - shell: { + exec: { + 'meteor-init': { + command: [ + // Make sure Meteor is installed, per https://meteor.com/install. + // The curl'ed script is safe; takes 2 minutes to read source & check. + 'type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; }', + // Meteor expects package.js to be in the root directory of + // the checkout, so copy it there temporarily + 'cp meteor/package.js .' + ].join(';') + }, + 'meteor-cleanup': { + // remove build files and package.js + command: 'rm -rf .build.* versions.json package.js' + }, 'meteor-test': { - command: 'meteor/runtests.sh' + command: 'spacejam --mongo-url mongodb:// test-packages ./' }, 'meteor-publish': { - command: 'meteor/publish.sh' + command: 'meteor publish' } } @@ -70,7 +84,7 @@ module.exports = function( grunt ) { grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-requirejs'); - grunt.loadNpmTasks('grunt-shell'); + grunt.loadNpmTasks('grunt-exec'); grunt.registerTask( 'pkgd-edit', function() { var outFile = grunt.config.get('requirejs.pkgd.options.out'); @@ -87,13 +101,11 @@ module.exports = function( grunt ) { grunt.log.writeln( 'Edited ' + outFile ); }); - grunt.registerTask('meteor-test', 'shell:meteor-test'); - grunt.registerTask('meteor-publish', 'shell:meteor-publish'); - // ideally we'd run tests before publishing, but the chances of tests breaking (given that - // Meteor is orthogonal to the library) are so small that it's not worth the maintainer's time - // grunt.regsterTask('meteor', ['shell:meteor-test', 'shell:meteor-publish']); - grunt.registerTask('meteor', 'shell:meteor-publish'); - + // Meteor tasks + grunt.registerTask('meteor-test', ['exec:meteor-init', 'exec:meteor-test', 'exec:meteor-cleanup']); + grunt.registerTask('meteor-publish', ['exec:meteor-init', 'exec:meteor-publish', 'exec:meteor-cleanup']); + grunt.registerTask('meteor', ['exec:meteor-init', 'exec:meteor-test', 'exec:meteor-publish', 'exec:meteor-cleanup']); + grunt.registerTask( 'default', [ 'jshint', 'requirejs', diff --git a/meteor/package.js b/meteor/package.js index 280aa252..49210ebf 100644 --- a/meteor/package.js +++ b/meteor/package.js @@ -14,7 +14,7 @@ Package.describe({ }); Package.onUse(function (api) { - api.versionsFrom('METEOR@1.0'); + api.versionsFrom(['METEOR@0.9.0', 'METEOR@1.0']); api.export('Isotope'); api.addFiles([ 'dist/isotope.pkgd.js', diff --git a/meteor/publish.sh b/meteor/publish.sh deleted file mode 100755 index 6969635c..00000000 --- a/meteor/publish.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash -# Publish package on Meteor's Atmosphere.js - -# Make sure Meteor is installed, per https://www.meteor.com/install. The curl'ed script is totally safe; takes 2 minutes to read its source and check. -type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; } - -# sanity check: make sure we're in the root directory of the checkout -cd "$( dirname "$0" )/.." - - -function cleanup() { - # we copied the file as package.js, regardless of its original name - rm package.js - - # temporary build files - rm -rf ".build.$PACKAGE_NAME" versions.json -} - - -# publish separately any package*.js files we have, e.g. package.js, package-compat.js -for PACKAGE_FILE in meteor/package*.js; do - - # Meteor expects package.js to be in the root directory of the checkout, so copy there our package file under that name, temporarily - cp $PACKAGE_FILE ./package.js - - # publish package, creating it if it's the first time we're publishing - PACKAGE_NAME=$(grep -i name $PACKAGE_FILE | head -1 | cut -d "'" -f 2) - ATMOSPHERE_NAME=${PACKAGE_NAME/://} - - echo "Publishing $PACKAGE_NAME..." - - # attempt to re-publish the package - the most common operation once the initial release has been made - OUTPUT=$( meteor publish 2>&1 ) - - if (( $? > 0 )); then - # there was an error - - if [[ $OUTPUT =~ "There is no package named" ]]; then - # actually this is the first time the package is created, so pass the special --create flag and congratulate the maintainer - echo "Thank you for creating the official Meteor package for this library!" - if meteor publish --create; then - echo "Please post the following to https://github.com/raix/Meteor-community-discussions/issues/14: - ---------------------------------------------- 8< -------------------------------------------------------- - -Happy to announce that I've published the official $PACKAGE_NAME to Atmosphere. Please star! -https://atmospherejs.com/$ATMOSPHERE_NAME - ---------------------------------------------- >8 -------------------------------------------------------- - -" - else - echo "We got an error. Please post it at https://github.com/raix/Meteor-community-discussions/issues/14" - cleanup - exit 1 - fi - else - # the error wasn't that the package didn't exist, so we need to ask for help - echo "We got an error. Please post it at https://github.com/raix/Meteor-community-discussions/issues/14: ---------------------------------------------- 8< -------------------------------------------------------- -$OUTPUT ---------------------------------------------- >8 -------------------------------------------------------- -" - cleanup - exit 1 - fi - else - # no error on the first `meteor publish` attempt - echo "$OUTPUT" # just in case meteor said something interesting - echo "Thanks for releasing a new version of $PACKAGE_NAME! You can see it at -https://atmospherejs.com/$ATMOSPHERE_NAME" - fi - - cleanup - -done diff --git a/meteor/runtests.sh b/meteor/runtests.sh deleted file mode 100755 index 400eee90..00000000 --- a/meteor/runtests.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# Test Meteor package before publishing to Atmospherejs.com - -# Make sure Meteor is installed, per https://www.meteor.com/install. The curl'ed script is totally safe; takes 2 minutes to read its source and check. -type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; } - -# sanity check: make sure we're in the root directory of the checkout -cd "$( dirname "$0" )/.." - -# run tests and delete the temporary package.js even if Ctrl+C is pressed -int_trap() { - echo - printf "Tests interrupted. Hopefully you verified in the browser that tests pass?\n\n" -} - -trap int_trap INT - -# test any package*.js packages we may have, e.g. package.js, package-compat.js -for PACKAGE_FILE in meteor/package*.js; do - - PACKAGE_NAME=$(grep -i name $PACKAGE_FILE | head -1 | cut -d "'" -f 2) - - echo "Testing $PACKAGE_NAME..." - - # Meteor expects package.js to be in the root directory of the checkout, so copy there our package file under that name, temporarily - cp $PACKAGE_FILE ./package.js - - # provide an invalid MONGO_URL so Meteor doesn't bog us down with an empty Mongo database - MONGO_URL=mongodb:// meteor test-packages ./ - - rm -rf ".build.$PACKAGE_NAME" - rm -rf ".build.local-test:$PACKAGE_NAME" - rm versions.json 2>/dev/null - - rm package.js - -done diff --git a/meteor/test.js b/meteor/test.js index c4793990..5612c048 100644 --- a/meteor/test.js +++ b/meteor/test.js @@ -5,7 +5,7 @@ Tinytest.addAsync('Isotope - fitRows', function (test, done) { document.body.appendChild(isotopeDropZone); // TODO ideally we'd get the htmls straight from this repo, but no idea how to do this from TinyTest - http://stackoverflow.com/questions/27180892/pull-an-html-file-into-a-tinytest - HTTP.get('https://rawgit.com/metafizzy/isotope/master/test/index.html', function callback(error, result) { + HTTP.get('http://rawgit.com/metafizzy/isotope/master/test/index.html', function callback(error, result) { // adapted from test/fit-rows.js function checkPosition(item, x, y) { diff --git a/package.json b/package.json index 4270dd27..a901bf2a 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "grunt-contrib-jshint": "~0.4.1", "grunt-contrib-uglify": "~0.1.1", "grunt-requirejs": "~0.4.0", - "grunt-shell": "*" + "grunt-exec": "^0.4.6", + "spacejam": "^1.1.1" }, "repository": { "type": "git",