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

Meteor integration #15376

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ validation-status.json
# Folders to ignore
bower_components
node_modules
.build*
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ install:
- npm install -g grunt-cli
- ./test-infra/s3_cache.py download npm-modules
- if [ "$TWBS_TEST" = validate-html ] && [ $TWBS_DO_VALIDATOR -ne 0 ]; then ./test-infra/s3_cache.py download rubygems; fi
# Install Meteor preemptively - https://github.com/MeteorPackaging/grunt-meteor#travisyml
- curl https://install.meteor.com | /bin/sh
after_script:
- if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ] && [ "$TWBS_TEST" = core ]; then ./test-infra/s3_cache.py upload npm-modules; fi
- if [ "$TRAVIS_REPO_SLUG" != twbs-savage/bootstrap ] && [ "$TWBS_TEST" = validate-html ] && [ $TWBS_DO_VALIDATOR -ne 0 ]; then ./test-infra/s3_cache.py upload rubygems; fi
Expand Down
18 changes: 17 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ module.exports = function (grunt) {
// Task configuration.
clean: {
dist: 'dist',
docs: 'docs/dist'
docs: 'docs/dist',
meteor: ['.build.*', 'versions.json', 'package.js']
},

jshint: {
Expand Down Expand Up @@ -372,6 +373,15 @@ module.exports = function (grunt) {
exec: {
npmUpdate: {
command: 'npm update'
},
// These tasks require Meteor to be installed: curl https://install.meteor.com/ | sh;
meteorTest: {
// the -noglyph(icons) package only runs a subset of the tests from package.js, so skip it
command: 'cp grunt/meteor/package.js .; node_modules/.bin/spacejam --mongo-url mongodb:// test-packages ./'
},
meteorPublish: {
// publish both packages
command: 'cp grunt/meteor/package.js .; meteor publish; cp grunt/meteor/package-noglyph.js package.js; meteor publish'
}
}
});
Expand Down Expand Up @@ -424,6 +434,11 @@ module.exports = function (grunt) {
grunt.registerTask('less-compile', ['less:compileCore', 'less:compileTheme']);
grunt.registerTask('dist-css', ['less-compile', 'autoprefixer:core', 'autoprefixer:theme', 'usebanner', 'csscomb:dist', 'cssmin:minifyCore', 'cssmin:minifyTheme']);

// Meteor tasks
grunt.registerTask('meteor-test', ['exec:meteorTest', 'clean:meteor']);
grunt.registerTask('meteor-publish', ['exec:meteorPublish', 'clean:meteor']);
grunt.registerTask('meteor', ['exec:meteorTest', 'exec:meteorPublish', 'clean:meteor']);

// Full distribution task.
grunt.registerTask('dist', ['clean:dist', 'dist-css', 'copy:fonts', 'dist-js']);

Expand Down Expand Up @@ -471,4 +486,5 @@ module.exports = function (grunt) {
done();
});
});

};
35 changes: 35 additions & 0 deletions grunt/meteor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Packaging [Bootstrap](http://getbootstrap.com) for [Meteor.js](http://meteor.com).
We'll be working with the Bootstrap team to include this integration in their repo
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence seems unnecessary since it will be in the repo if this PR is accepted.

and provide same-day updates on Atmosphere.

# Versions

There are two versions of this package:

* [twbs:bootstrap](https://atmospherejs.com/twbs/bootstrap) - Bootstrap.css, .js and the Glyphicons font are included.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we just add some of this info to the existing Getting Started docs, and then kill this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's been extended discussion about integrating Bootstrap with Meteor, so I felt that a level of Meteor-specific detail is necessary, hence a separate README.

This Meteor-specific README file is also referenced by the readme key in the Meteor package.js file (I've fixed the path there; it would become valid after the merge, but for now, I've set it to the fork's README).

If you'd like to kill it, I could submit a PR against the Getting Started doc, and perhaps link to it from the main README? Atmosphere packages must show a README, so if it's not the Meteor-specific one, it would have to be the main README.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough.

* [twbs:bootstrap-noglyph](https://atmospherejs.com/twbs/bootstrap-noglyph) - Only the Bootstrap .CSS and .JS files are
included. Useful if you plan to use a different icon set, such as [Font Awesome](https://atmospherejs.com/fortawesome/fontawesome)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we want to favor/endorse any particular third-party projects (Font Awesome, bootstrap-material-design) by mentioning them like this.
@mdo Thoughts?

or the one from [Bootstrap Material Design](https://atmospherejs.com/fezvrasta/bootstrap-material-design).

If you need more detailed control on the files, see [Nemo64's package](https://github.com/Nemo64/meteor-bootstrap).


# Issues

If you encounter a Meteor-related issue while using this package, please CC @dandv when you file it in this repo.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not clear what "this repo" refers to.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sending a revamped README in a bit.

If the issue is related to Bootstrap itself, please file it on [Bootstrap's GitHub](https://github.com/twbs/bootstrap/issues).


# DONE
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DONE & TODO sections don't seem appropriate in a user-facing document. (And there's only 1 TODO item anyway.)


* No need for CSS override files - Meteor will automatically "convert relative URLs to absolute URLs
when merging CSS files" [since v0.8.1](https://github.com/meteor/meteor/blob/b96c5d7962a9e59b9efaeb93eb81020e0548e378/History.md#v081)
so CSS `@font-face src url('../fonts/...')` will be resolved to the correct `/packages/.../fonts/...` path
* Tests that fonts are downloadable
* Plugin instantiation tests
* Visual checks for all plugins, including dropdown, popover, tooltip


# TODO

* For the sake of completeness, get the modal running
31 changes: 31 additions & 0 deletions grunt/meteor/package-noglyph.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// package metadata file for Meteor.js
'use strict'

var packageName = 'twbs:bootstrap-noglyph' // http://atmospherejs.com/twbs/bootstrap-noglyph
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: 'Bootstrap without the Glyphicons font (official): the most popular HTML/CSS/JS responsive framework', // limited to 100 characters
version: packageJson.version,
git: 'https://github.com/twbs/bootstrap.git',
readme: 'https://github.com/MeteorPackaging/bootstrap/blob/meteor-integration/grunt/meteor/README.md'
})

Package.onUse(function (api) {
api.versionsFrom(['[email protected]', '[email protected]'])
api.use('jquery') // required by Bootstrap's JavaScript
api.addFiles([
'dist/css/bootstrap.css',
'dist/js/bootstrap.js'
], where)
})

Package.onTest(function (api) {
api.use(packageName, where)
api.use(['tinytest', 'http'], where)

api.addFiles('grunt/meteor/test-noglyph.js', where)
})
37 changes: 37 additions & 0 deletions grunt/meteor/package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// package metadata file for Meteor.js
'use strict'

var packageName = 'twbs:bootstrap' // http://atmospherejs.com/twbs/bootstrap
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: 'Bootstrap (official): the most popular HTML/CSS/JS framework for responsive, mobile first projects', // limited to 100 characters
version: packageJson.version,
git: 'https://github.com/twbs/bootstrap.git',
readme: 'https://github.com/MeteorPackaging/bootstrap/blob/meteor-integration/grunt/meteor/README.md'
})

Package.onUse(function (api) {
api.versionsFrom(['[email protected]', '[email protected]'])
api.use('jquery') // required by Bootstrap's JavaScript
api.addFiles([
// we bundle all font files, but the client will request only one of them via the CSS @font-face rule
'dist/fonts/glyphicons-halflings-regular.eot', // IE8 or older
'dist/fonts/glyphicons-halflings-regular.svg', // SVG fallback for iOS < 5 - http://caniuse.com/#feat=svg-fonts, http://stackoverflow.com/a/11002874/1269037
'dist/fonts/glyphicons-halflings-regular.ttf', // Android Browers 4.1, 4.3 - http://caniuse.com/#feat=ttf
'dist/fonts/glyphicons-halflings-regular.woff', // Supported by all modern browsers
'dist/fonts/glyphicons-halflings-regular.woff2', // Most modern font format
'dist/css/bootstrap.css',
'dist/js/bootstrap.js'
], where)
})

Package.onTest(function (api) {
api.use(packageName, where)
api.use(['tinytest', 'http'], where)

api.addFiles('grunt/meteor/test.js', where)
})
42 changes: 42 additions & 0 deletions grunt/meteor/test-noglyph.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict'; // TWBS code style mandates no semicolons - https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#js
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove superfluous comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"No semicolons" is a rather unique coding style, which conflicts with the Meteor style guide, so I added a mention for future Meteor package maintainers to no start adding semicolons.


var plugins = ['affix', 'alert', 'button', 'carousel', 'collapse', 'dropdown', 'modal', 'popover', 'scrollspy', 'tab', 'tooltip']

// test plugins
plugins.forEach(function (plugin) {
Tinytest.add('Plugin - ' + plugin, function (test) {
test.instanceOf($(document.body)[plugin], Function, 'instantiated correctly')
})
})

// visual check
plugins.forEach(function (plugin) {

Tinytest.addAsync('Visual check - ' + plugin, function (test, done) {
var bootstrapDropZone = document.createElement('div')
document.body.appendChild(bootstrapDropZone)


// 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('http://rawgit.com/twbs/bootstrap/master/js/tests/visual/' + plugin + '.html', function callback(error, result) {
if (error) {
test.fail('Error getting the test file. Do we have an Internet connection to rawgit.com?')
} else {
// [^] matches across newlines. Stay within the container div, or else the fragment will attempt to load resources on its own.
bootstrapDropZone.innerHTML = result.content.match(/<div[^]+<\/div>/)
test.ok({message: 'Test passed if the display looks OK *and* clicking dropdowns/popovers/tooltips works.'})
// only does anything after loading the 'dropdown' plugin test
$('[data-toggle="dropdown"]').dropdown()
// only does anything after loading the 'popover' plugin test
$('[data-toggle="popover"]').popover()
// only does anything after loading the 'tooltip' plugin test
$('[data-toggle="tooltip"]').tooltip()
// don't initialize the modals because that messes up the Tinytest runner HTML
}

done()
})

})

})
83 changes: 83 additions & 0 deletions grunt/meteor/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
'use strict'; // TWBS code style mandates no semicolons - https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#js

var packageName // there seems to be no official way of finding out the name of the very package we're testing - http://stackoverflow.com/questions/27180709/in-a-tinytest-test-file-how-do-i-get-the-name-of-the-package

// Check that the font files are downloadable. Meteor places assets at /packages/<packageName>/.
['eot', 'svg', 'ttf', 'woff', 'woff2'].forEach(function (font) {
Tinytest.addAsync(font + ' fonts are shipped', function (test, done) {

// curiously enough, the 'local-test:...' package isn't loaded into Package before calling Tinytest, so we can't do this determination outside this loop
if (!packageName)
Object.keys(Package).forEach(function(p) {
if (p.search(/local-test/) > -1)
packageName = p.replace('local-test:', '') // we should stop the loop, but forEach can't do that
})

if (!packageName) {
test.exception({message: 'Package not quite loaded... go figure'})
return
}

var packagePath = packageName.replace(':', '_') // e.g. twbs_bootstrap

HTTP.get(
'/packages/' + packagePath + '/dist/fonts/glyphicons-halflings-regular.' + font,
{
headers: {
'Cache-Control': 'no-cache' // because Meteor has cached fonts even after they were removed from package.js (!) - https://github.com/meteor/meteor/issues/3196
}
},
function callback(error, result) {
if (error) {
test.fail({message: 'Font failed to load'})
} else {
// if the file is 404, Meteor will redirect to / and return the Meteor.js boilerplate
test.isTrue(result.content.length > 15000, font + ' font could not be downloaded')
}

done()
}
)
})
})

var plugins = ['affix', 'alert', 'button', 'carousel', 'collapse', 'dropdown', 'modal', 'popover', 'scrollspy', 'tab', 'tooltip']

// test plugins
plugins.forEach(function (plugin) {
Tinytest.add('Plugin - ' + plugin, function (test) {
test.instanceOf($(document.body)[plugin], Function, 'instantiated correctly')
})
})

// visual check
plugins.forEach(function (plugin) {

Tinytest.addAsync('Visual check - ' + plugin, function (test, done) {
var bootstrapDropZone = document.createElement('div')
document.body.appendChild(bootstrapDropZone)


// 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('http://rawgit.com/twbs/bootstrap/master/js/tests/visual/' + plugin + '.html', function callback(error, result) {
if (error) {
test.fail('Error getting the test file. Do we have an Internet connection to rawgit.com?')
} else {
// [^] matches across newlines. Stay within the container div, or else the fragment will attempt to load resources on its own.
bootstrapDropZone.innerHTML = result.content.match(/<div[^]+<\/div>/)
test.ok({message: 'Test passed if the display looks OK *and* clicking dropdowns/popovers/tooltips works.'})
// only does anything after loading the 'dropdown' plugin test
$('[data-toggle="dropdown"]').dropdown()
// only does anything after loading the 'popover' plugin test
$('[data-toggle="popover"]').popover()
// only does anything after loading the 'tooltip' plugin test
$('[data-toggle="tooltip"]').tooltip()
// don't initialize the modals because that messes up the Tinytest runner HTML
}

done()
})

})

})
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"grunt-jscs": "~0.8.1",
"grunt-saucelabs": "~8.3.2",
"grunt-sed": "~0.1.1",
"spacejam": "^1.1.1",
"load-grunt-tasks": "~1.0.0",
"npm-shrinkwrap": "5.0.0",
"remarkable": "~1.4.1",
Expand Down