├── .gitignore ├── .npmignore ├── History.md ├── Readme.md ├── assets.json ├── bin └── asset ├── index.js ├── lib ├── asset.js └── installer.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | public 2 | node_modules 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | support 2 | test 3 | examples 4 | public 5 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 0.4.12 / 2012-09-25 2 | ================== 3 | 4 | * fix to match README syntax (compression option) 5 | * added jade-runtime 6 | 7 | 0.4.11 / 2012-06-13 8 | ================== 9 | 10 | * removed engines 11 | 12 | 0.4.10 / 2011-12-10 13 | ================== 14 | 15 | * Updated move 16 | 17 | 0.4.9 / 2011-11-16 18 | ================== 19 | 20 | * Updated move.js 21 | 22 | 0.4.8 / 2011-09-13 23 | ================== 24 | 25 | * Added Twitter's bootstrap CSS toolkit in assets.json 26 | * Added mkdirp dependency 27 | 28 | 0.4.7 / 2011-08-20 29 | ================== 30 | 31 | * Updated caustic Updated superagent 32 | * Added EE2 33 | 34 | 0.4.6 / 2011-08-09 35 | ================== 36 | 37 | * Added superagent 38 | 39 | 0.4.5 / 2011-07-20 40 | ================== 41 | 42 | * Added `caustic` 43 | 44 | 0.4.4 / 2011-07-15 45 | ================== 46 | 47 | * Added `mustache.js` 48 | * Updated `jQuery` 49 | * Updated `underscore` 50 | * Updated `backbone` 51 | 52 | 0.4.3 / 2011-07-08 53 | ================== 54 | 55 | * Updated three.js 56 | 57 | 0.4.2 / 2011-07-02 58 | ================== 59 | 60 | * Added `resistance` 61 | * Added `pagie` 62 | * Added `str.js` 63 | * Added `fidel` 64 | 65 | 0.4.1 / 2011-06-04 66 | ================== 67 | 68 | * Added `move.js` 69 | 70 | 0.4.0 / 2011-05-30 71 | ================== 72 | 73 | * Added `asset` command to install from ./assets.json. Closes #18 74 | * Added `live.js` support 75 | * Added `iscroll` and `iscroll-lite` 76 | * Added `zepto` 77 | 78 | 0.3.2 / 2011-04-27 79 | ================== 80 | 81 | * Added Modernizr and Yepnope assets [Mike Cantelon] 82 | * Added iscroll and iscroll-lite [Mike Cantelon] 83 | * Added ellipsis to long descriptions within search 84 | 85 | 0.3.0 / 2011-04-14 86 | ================== 87 | 88 | * Added date.js support [caged] 89 | * Added support for polymaps [caged] 90 | * Added support for protovis [caged] 91 | * Added support for d3 [caged] 92 | 93 | 0.2.0 / 2011-04-09 94 | ================== 95 | 96 | * Added `jquery-mobile` 97 | * Added `processing.js` 98 | * Added `blueprint` 99 | * Added; assume arg with "/" is `--out `. closes #10 100 | * Added; search tags for search query 101 | * Added `tags` to all assets 102 | * Added basic "complex" support :) aka an array of files. Closes #4 103 | * Added `utils.mkdir()` 104 | * Fixed; create destination directory. Closes #8 105 | * Fixed several `{version}` substrings within the url 106 | 107 | 0.1.0 / 2011-04-05 108 | ================== 109 | 110 | * Added `underscore` 111 | * Added `mootools` 112 | * added mootools 113 | * Added `-c, --compress` to install compressed versions of the asset when possible 114 | * Added `:compress` modifier, ex `asset jquery@1.4.3:compress` 115 | * Added basic dependency mapping support. Closes #3 116 | * Added `info ` command 117 | * Added deps to `assets.json` 118 | * Changed; by default assets are not compressed 119 | 120 | 0.0.2 / 2011-04-04 121 | ================== 122 | 123 | * Added descriptions 124 | 125 | 0.0.1 / 2010-01-03 126 | ================== 127 | 128 | * Initial release 129 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Asset 2 | 3 | Asset manager for lazy people (think homebrew for assets). Somewhat defunct unless someone wants to maintain it, otherwise 4 | I recommend [component](http://github.com/component/component), a more robust successor. 5 | 6 | ## Installation 7 | 8 | $ npm install -g asset 9 | 10 | ## Usage 11 | 12 | Usage: asset [command] [options] 13 | 14 | Commands: 15 | 16 | install installs the given asset 17 | search [query] search available assets with optional [query] 18 | info display verbose information for the given asset 19 | none install dependencies from ./assets.json 20 | 21 | Options: 22 | 23 | -c, --compress compress assets 24 | -o, --out output directory defaulting to ./public 25 | -V, --version output program version 26 | -h, --help display help information 27 | 28 | 29 | 30 | ## Examples 31 | 32 | ### Installing Several Assets 33 | 34 | By default asset installs to `./public`. 35 | 36 | $ asset raphael jquery 37 | 38 | install : raphael@1.4.7 39 | install : jquery@1.5.2 40 | download : jquery@1.5.2 41 | complete : jquery@1.5.2 public/jquery.js 42 | download : raphael@1.4.7 43 | complete : raphael@1.4.7 public/raphael.js 44 | 45 | Asset names accept an optional version and modifiers, taking the form: 46 | 47 | ['@' version] [':' 'compress'] 48 | 49 | To install all assets (that support compression) as compressed, we can use 50 | the `--compress` flag: 51 | 52 | $ asset jquery raphael --compress 53 | 54 | However this can be done at the asset-level as well using the `:compress` modifier: 55 | 56 | $ asset jquery@1.4.3:compress raphael 57 | 58 | install : jquery@1.4.3 59 | install : raphael@1.4.7 60 | download : jquery@1.4.3 61 | complete : jquery@1.4.3 public/jquery.min.js 62 | download : raphael@1.4.7 63 | complete : raphael@1.4.7 public/raphael.js 64 | 65 | ### Install Destination 66 | 67 | Tweak the output directory with `-o, --out `. 68 | 69 | $ asset raphael g.raphael g.pie -o public/javascripts 70 | 71 | install : raphael@1.4.7 72 | install : g.raphael@0.4.1 73 | install : g.pie@0.4.1 74 | download : raphael@1.4.7 75 | complete : raphael@1.4.7 public/javascripts/raphael.js 76 | download : g.raphael@0.4.1 77 | complete : g.raphael@0.4.1 public/javascripts/g.raphael.js 78 | download : g.pie@0.4.1 79 | complete : g.pie@0.4.1 public/javascripts/g.pie.js 80 | 81 | Alternatively passing a directory name containing "/" will work as well, since `asset` knows this is not an asset, and becomes equivalent to `--out `: 82 | 83 | $ asset raphael jquery public/javascripts 84 | 85 | ### Dependency Resolution 86 | 87 | Asset currently supports extremely basic dependency mapping, for example below is the output of installing `g.pie`, which depends on `g.raphael`, which in turn depends on `raphael` itself. 88 | 89 | $ asset g.pie 90 | 91 | install : g.pie@0.4.1 92 | dependency : g.raphael@0.4.1 93 | install : g.raphael@0.4.1 94 | dependency : raphael@1.4.7 95 | install : raphael@1.4.7 96 | download : raphael@1.4.7 97 | complete : raphael@1.4.7 public/raphael.js 98 | download : g.raphael@0.4.1 99 | complete : g.raphael@0.4.1 public/g.raphael.js 100 | download : g.pie@0.4.1 101 | complete : g.pie@0.4.1 public/g.pie.js 102 | 103 | ### Asset Information 104 | 105 | Inspect verbose asset information: 106 | 107 | $ asset info jquery g.raphael 108 | 109 | name : jquery 110 | description : jquery core framework 111 | url : http://code.jquery.com/jquery-{version}.min.js 112 | version : 1.5.2 113 | filename : jquery.js 114 | 115 | name : g.raphael 116 | description : charting for raphael 117 | url : https://github.com/DmitryBaranovskiy/g.raphael/raw/v{version}/g.raphael-min.js 118 | version : 0.4.1 119 | filename : g.raphael.js 120 | dependencies : raphael 121 | 122 | 123 | ### Installation Destination 124 | 125 | To install a specific version, we can use the `@` character: 126 | 127 | $ asset jquery@1.5.0 128 | 129 | ### Search Repository 130 | 131 | We can search the repository with an optional query, listing 132 | available assets and their default versions: 133 | 134 | $ asset raphael 135 | 136 | install : raphael@1.4.7 137 | download : raphael@1.4.7 138 | complete : raphael@1.4.7 public/raphael.js 139 | 140 | ### assets.json 141 | 142 | By adding `./assets.json` you can store application dependencies, and install them quickly and easily with a single command `asset`. For example this file may contain one or more deps: 143 | 144 | { 145 | "g.raphael": "0.4.1" 146 | , "jquery": "1.5.2" 147 | , "modernizr": "1.7" 148 | } 149 | 150 | 151 | Installed with the command: 152 | 153 | $ asset 154 | 155 | install : g.raphael@0.4.1 156 | dependency : raphael@1.4.7 157 | install : raphael@1.4.7 158 | install : jquery@1.5.2 159 | install : modernizr@1.7 160 | download : jquery@1.5.2 161 | complete : jquery@1.5.2 public/jquery.js 162 | download : raphael@1.4.7 163 | complete : raphael@1.4.7 public/raphael.js 164 | download : g.raphael@0.4.1 165 | complete : g.raphael@0.4.1 public/g.raphael.js 166 | download : modernizr@1.7 167 | complete : modernizr@1.7 public/modernizr.js 168 | 169 | ### Configuration 170 | 171 | By default options must be passed via the CLI, however `asset` will also check the `./.asset` and `~/.asset` JSON configuration files, so for example a project may set `{ "out": "public/javascripts" }` if we are mainly working with javascript, however the CLI options will always take precedence. 172 | 173 | ### The Repository 174 | 175 | By default the repo bundled with `asset` is used, however the `~/.assets` configuration file is checked first. Perhaps down the road if/when asset becomes more flexible a repo will be hosted, for now simply fork the project edit `./assets.json`, and send a pull request. 176 | 177 | ## License 178 | 179 | (The MIT License) 180 | 181 | Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> 182 | 183 | Permission is hereby granted, free of charge, to any person obtaining 184 | a copy of this software and associated documentation files (the 185 | 'Software'), to deal in the Software without restriction, including 186 | without limitation the rights to use, copy, modify, merge, publish, 187 | distribute, sublicense, and/or sell copies of the Software, and to 188 | permit persons to whom the Software is furnished to do so, subject to 189 | the following conditions: 190 | 191 | The above copyright notice and this permission notice shall be 192 | included in all copies or substantial portions of the Software. 193 | 194 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 195 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 196 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 197 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 198 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 199 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 200 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "blueprint": { 3 | "base": "https://github.com/joshuaclayton/blueprint-css/raw/v{version}/blueprint", 4 | "description": "css framework", 5 | "tags": ["css"], 6 | "files": [ 7 | "ie.css", 8 | "print.css", 9 | "screen.css", 10 | "src/forms.css", 11 | "src/grid.css", 12 | "src/grid.png", 13 | "src/ie.css", 14 | "src/print.css", 15 | "src/reset.css", 16 | "src/typography.css" 17 | ], 18 | "version": "1.0" 19 | }, 20 | "bootstrap": { 21 | "url": "https://github.com/twitter/bootstrap/raw/v{version}/bootstrap-{version}.css", 22 | "compressed": "bootstrap-{version}.min.css", 23 | "description": "CSS toolkit from Twitter", 24 | "tags": ["css", "twitter"], 25 | "version": "1.1.1" 26 | }, 27 | "bootstrap-less": { 28 | "base": "https://github.com/twitter/bootstrap/raw/v{version}", 29 | "description": "CSS toolkit from Twitter (LESS Source)", 30 | "tags": ["css", "twitter", "less"], 31 | "files": [ 32 | "lib/bootstrap.less", 33 | "lib/forms.less", 34 | "lib/patterns.less", 35 | "lib/preboot.less", 36 | "lib/reset.less", 37 | "lib/scaffolding.less", 38 | "lib/tables.less", 39 | "lib/type.less" 40 | ], 41 | "version": "1.1.1" 42 | }, 43 | "eventemitter2": { 44 | "url": "https://github.com/hij1nx/EventEmitter2/blob/v{version}/lib/eventemitter2.js", 45 | "description": "nodejs-style event emitter with namespaces, wildcards, TTL etc", 46 | "tags": ["events", "emitter", "node"], 47 | "version": "0.4.1" 48 | }, 49 | "superagent": { 50 | "url": "https://raw.github.com/visionmedia/superagent/{version}/superagent.js", 51 | "description": "Ajax with less suck", 52 | "tags": ["request", "ajax"], 53 | "version": "0.1.1" 54 | }, 55 | "caustic": { 56 | "url": "https://github.com/visionmedia/caustic/raw/{version}/build/caustic.js", 57 | "description": "Experimental view system for jQuery", 58 | "tags": ["templates", "view"], 59 | "version": "0.0.5" 60 | }, 61 | "move.js": { 62 | "url": "https://github.com/visionmedia/move.js/raw/{version}/move.js", 63 | "description": "CSS3 JavaScript animation framework", 64 | "tags": ["css", "animation"], 65 | "version": "0.1.1" 66 | }, 67 | "jade": { 68 | "url": "https://github.com/visionmedia/jade/raw/{version}/jade.js", 69 | "description": "jade template engine", 70 | "tags": ["template"], 71 | "version": "0.10.4" 72 | }, 73 | "three.js": { 74 | "url": "https://github.com/mrdoob/three.js/raw/r{version}/build/Three.js", 75 | "description": "3d javascript engine", 76 | "tags": ["js", "3d"], 77 | "filename": "three.js", 78 | "version": "42" 79 | }, 80 | "underscore": { 81 | "url": "https://github.com/documentcloud/underscore/raw/{version}/underscore.js", 82 | "description": "javascript's utility belt", 83 | "compressed": "underscore-min.js", 84 | "tags": ["js", "utilities"], 85 | "version": "1.1.7" 86 | }, 87 | "mootools": { 88 | "url": "http://mootools.net/download/get/mootools-core-{version}-full-compat.js", 89 | "description": "mootools core javascript framework", 90 | "compressed": "mootools-core-{version}-full-compat-yc.js", 91 | "filename": "mootools.js", 92 | "tags": ["js"], 93 | "version": "1.3.1" 94 | }, 95 | "raphael": { 96 | "url": "https://github.com/DmitryBaranovskiy/raphael/raw/v{version}/raphael.js", 97 | "description": "raphael vector library", 98 | "compressed": "raphael-min.js", 99 | "tags": ["js"], 100 | "version": "1.4.7" 101 | }, 102 | "g.raphael": { 103 | "url": "https://github.com/DmitryBaranovskiy/g.raphael/raw/v{version}/g.raphael.js", 104 | "description": "charting for raphael", 105 | "compressed": "g.raphael-min.js", 106 | "tags": ["js", "raphael"], 107 | "version": "0.4.1", 108 | "dependencies": { 109 | "raphael": "1.4.7" 110 | } 111 | }, 112 | "g.bar": { 113 | "url": "https://github.com/DmitryBaranovskiy/g.raphael/raw/v{version}/g.bar.js", 114 | "description": "bar charting for raphael", 115 | "compressed": "g.bar-min.js", 116 | "tags": ["js", "raphael"], 117 | "version": "0.4.1", 118 | "dependencies": { 119 | "g.raphael": "0.4.1" 120 | } 121 | }, 122 | "g.dot": { 123 | "url": "https://github.com/DmitryBaranovskiy/g.raphael/raw/v{version}/g.dot.js", 124 | "description": "dot charting for raphael", 125 | "compressed": "g.dot-min.js", 126 | "tags": ["js", "raphael"], 127 | "version": "0.4.1", 128 | "dependencies": { 129 | "g.raphael": "0.4.1" 130 | } 131 | }, 132 | "g.line": { 133 | "url": "https://github.com/DmitryBaranovskiy/g.raphael/raw/v{version}/g.line.js", 134 | "description": "line charting for raphael", 135 | "compressed": "g.line-min.js", 136 | "tags": ["js", "raphael"], 137 | "version": "0.4.1", 138 | "dependencies": { 139 | "g.raphael": "0.4.1" 140 | } 141 | }, 142 | "g.pie": { 143 | "url": "https://github.com/DmitryBaranovskiy/g.raphael/raw/v{version}/g.pie.js", 144 | "description": "pie charting for raphael", 145 | "compressed": "g.pie-min.js", 146 | "tags": ["js", "raphael"], 147 | "version": "0.4.1", 148 | "dependencies": { 149 | "g.raphael": "0.4.1" 150 | } 151 | }, 152 | "jquery": { 153 | "url": "http://code.jquery.com/jquery-{version}.js", 154 | "description": "jquery core framework", 155 | "compressed": "jquery-{version}.min.js", 156 | "tags": ["js", "jquery"], 157 | "filename": "jquery.js", 158 | "version": "1.6.2" 159 | }, 160 | "jquery.validate": { 161 | "url":"http://ajax.aspnetcdn.com/ajax/jquery.validate/{version}/jquery.validate.js", 162 | "compressed": "jquery.validate.min.js", 163 | "description": "form validation for jquery", 164 | "tags": ["js", "jquery"], 165 | "version": "1.8", 166 | "dependencies": { 167 | "jquery": "1.5.1" 168 | } 169 | }, 170 | "prototype": { 171 | "url": "http://prototypejs.org/assets/2008/9/29/prototype-{version}.js", 172 | "description": "prototype core framework", 173 | "filename": "prototype.js", 174 | "tags": ["js"], 175 | "version": "1.6.0.3" 176 | }, 177 | "script.js": { 178 | "url": "https://github.com/ded/script.js/blob/master/dist/script.js", 179 | "description": "Asyncronous JavaScript loader and dependency manager", 180 | "tags": ["js"], 181 | "version": "1.3" 182 | }, 183 | "jquery-mobile": { 184 | "url": "http://code.jquery.com/mobile/{version}/jquery.mobile-{version}.js", 185 | "description": "touch-optimized web framework for smartphones & tablets", 186 | "filename": "jquery.mobile.js", 187 | "tags": ["js", "jquery"], 188 | "version": "1.0a4", 189 | "dependencies": { 190 | "jquery": "1.5.1" 191 | } 192 | }, 193 | "processing.js": { 194 | "url": "http://cloud.github.com/downloads/processing-js/processing-js/processing-{version}.js", 195 | "description": "a port of the Processing visualization language", 196 | "filename": "processing.js", 197 | "tags": ["js"], 198 | "version": "1.1.0" 199 | }, 200 | "d3": { 201 | "url": "https://github.com/mbostock/d3/raw/v{version}/d3.js", 202 | "description": "A JavaScript visualization library for HTML and SVG.", 203 | "filename": "d3.js", 204 | "tags": ["js", "svg"], 205 | "version": "1.17.0" 206 | }, 207 | "d3.behavior": { 208 | "url": "https://github.com/mbostock/d3/raw/v{version}/d3.behavior.js", 209 | "description": "Event module for d3. A JavaScript visualization library for HTML and SVG.", 210 | "tags": ["js", "svg"], 211 | "version": "1.11.0", 212 | "dependencies": { 213 | "d3": "1.17.0" 214 | } 215 | }, 216 | "d3.chart": { 217 | "url": "https://github.com/mbostock/d3/raw/v{version}/d3.chart.js", 218 | "description": "Chart module for d3. A JavaScript visualization library for HTML and SVG.", 219 | "tags": ["js", "svg"], 220 | "version": "1.11.0", 221 | "dependencies": { 222 | "d3": "1.17.0" 223 | } 224 | }, 225 | "d3.csv": { 226 | "url": "https://github.com/mbostock/d3/raw/v{version}/d3.csv.js", 227 | "description": "CSV parser module for d3. A JavaScript visualization library for HTML and SVG.", 228 | "tags": ["js", "svg"], 229 | "version": "1.11.0", 230 | "dependencies": { 231 | "d3": "1.17.0" 232 | } 233 | }, 234 | "d3.geo": { 235 | "url": "https://github.com/mbostock/d3/raw/v{version}/d3.geo.js", 236 | "description": "Geo module for d3. A JavaScript visualization library for HTML and SVG.", 237 | "tags": ["js", "svg"], 238 | "version": "1.11.0", 239 | "dependencies": { 240 | "d3": "1.17.0" 241 | } 242 | }, 243 | "d3.geom": { 244 | "url": "https://github.com/mbostock/d3/raw/v{version}/d3.geom.js", 245 | "description": "Geometry module for d3. A JavaScript visualization library for HTML and SVG.", 246 | "tags": ["js", "svg"], 247 | "version": "1.11.0", 248 | "dependencies": { 249 | "d3": "1.17.0" 250 | } 251 | }, 252 | "d3.layout": { 253 | "url": "https://github.com/mbostock/d3/raw/v{version}/d3.layout.js", 254 | "description": "Layout module for d3. A JavaScript visualization library for HTML and SVG.", 255 | "tags": ["js", "svg"], 256 | "version": "1.11.0", 257 | "dependencies": { 258 | "d3": "1.17.0" 259 | } 260 | }, 261 | "d3.time": { 262 | "url": "https://github.com/mbostock/d3/raw/v{version}/d3.time.js", 263 | "description": "Time module for d3. A JavaScript visualization library for HTML and SVG.", 264 | "tags": ["js", "svg"], 265 | "version": "1.11.0", 266 | "dependencies": { 267 | "d3": "1.17.0" 268 | } 269 | }, 270 | "protovis": { 271 | "url": "https://github.com/mbostock/protovis/raw/v{version}/protovis.js", 272 | "description": "A visualization toolkit for JavaScript using SVG.", 273 | "tags": ["js", "svg"], 274 | "version": "3.3.1" 275 | }, 276 | "polymaps": { 277 | "url": "https://github.com/simplegeo/polymaps/raw/v{version}/polymaps.js", 278 | "description": "Polymaps is a free JavaScript library for making dynamic, interactive maps in modern web browsers.", 279 | "tags": ["js", "maps", "mapping"], 280 | "version": "2.5.0" 281 | }, 282 | "date.js": { 283 | "url": "http://datejs.googlecode.com/files/date.js", 284 | "description": "Datejs is an open source JavaScript Date library for parsing, formatting and processing.", 285 | "tags": ["js", "date", "time"], 286 | "version": "1.0 Alpha-1" 287 | }, 288 | "backbone": { 289 | "url": "https://github.com/documentcloud/backbone/raw/{version}/backbone.js", 290 | "compressed": "backbone-min.js", 291 | "description": "Backbone supplies structure to Javascript Apps by providing models, views, collections, and events", 292 | "tags": ["js"], 293 | "version": "0.5.1" 294 | }, 295 | "zepto": { 296 | "url": "https://github.com/madrobby/zepto/raw/v{version}/src/zepto.js", 297 | "description": "zepto.js is a minimalist inlinable framework for mobile WebKit browsers, with a jQuery-like chaining syntax", 298 | "tags": ["js"], 299 | "version": "0.5" 300 | }, 301 | "iscroll": { 302 | "url": "https://github.com/cubiq/iscroll/raw/master/src/iscroll.js", 303 | "description": "Hardware accelerated scroll for mobile webkit", 304 | "tags": ["js"], 305 | "version": "4.0" 306 | }, 307 | "iscroll-lite": { 308 | "url": "https://github.com/cubiq/iscroll/raw/master/src/iscroll-lite.js", 309 | "description": "Hardware accelerated scroll for mobile webkit", 310 | "tags": ["js"], 311 | "version": "4.0" 312 | }, 313 | "modernizr": { 314 | "url": "https://github.com/Modernizr/Modernizr/raw/v{version}/modernizr.js", 315 | "description": "Feature detection to test browsers against upcoming features", 316 | "tags": ["js", "css", "detection"], 317 | "version": "1.7" 318 | }, 319 | "yepnope": { 320 | "url": "https://github.com/SlexAxton/yepnope.js/raw/v{version}/yepnope.js", 321 | "description": "Conditional loader for polyfills", 322 | "tags": ["js", "detection"], 323 | "version": "1.0.1" 324 | }, 325 | "live.js": { 326 | "url": "http://livejs.com/live.js", 327 | "description": "Live.js makes sure you're always looking at the latest version of the page you're working on, whether you're writing HTML, CSS or Javascript", 328 | "tags": ["js"], 329 | "version": "3.0" 330 | }, 331 | "fidel": { 332 | "url": "https://raw.github.com/jgallen23/fidel/master/dist/fidel.js", 333 | "compressed": "fidel.min.js", 334 | "description": "Fidel is a simple, lightweight ui controller library", 335 | "tags": ["js"], 336 | "version": "1.1.2" 337 | }, 338 | "str.js": { 339 | "url": "https://raw.github.com/jgallen23/str.js/master/str.js", 340 | "description": "A string utility library", 341 | "tags": ["js", "string", "template", "format"], 342 | "version": "1.0.3" 343 | }, 344 | "resistance": { 345 | "url": "https://raw.github.com/jgallen23/resistance/master/dist/resistance.js", 346 | "compressed": "resistance.min.js", 347 | "description": "A simple async flow control library", 348 | "tags": ["js", "flow", "async"], 349 | "version": "1.0.1" 350 | }, 351 | "pagie": { 352 | "url": "https://raw.github.com/jgallen23/pagie/master/pagie.js", 353 | "compressed": "pagie.min.js", 354 | "description": "A simple pagination class", 355 | "tags": ["js", "pagination"], 356 | "version": "0.0.1" 357 | }, 358 | "mustache.js": { 359 | "url": "https://raw.github.com/janl/mustache.js/{version}/mustache.js", 360 | "description": "Minimal templating with {{mustaches}} in JavaScript", 361 | "version": "0.3.0", 362 | "tags": ["js", "templates", "templating"] 363 | }, 364 | "jade-runtime": { 365 | "url": "https://github.com/visionmedia/jade/raw/{version}/runtime.js", 366 | "description": "jade template engine for client-side use", 367 | "compressed": "runtime.min.js", 368 | "tags": ["template"], 369 | "version": "0.27.4" 370 | } 371 | } 372 | -------------------------------------------------------------------------------- /bin/asset: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var asset = require('../') 8 | , exec = require('child_process').exec 9 | , tty = require('tty') 10 | , fs = require('fs'); 11 | 12 | /** 13 | * Arguments. 14 | */ 15 | 16 | var args = process.argv.slice(2); 17 | 18 | /** 19 | * Assets to install. 20 | */ 21 | 22 | var assets = []; 23 | 24 | /** 25 | * Default options. 26 | */ 27 | 28 | var options = { 29 | out: 'public' 30 | , compress: false 31 | }; 32 | 33 | /** 34 | * Usage information. 35 | */ 36 | 37 | var usage = [ 38 | '' 39 | , ' Usage: asset [command] [options]' 40 | , '' 41 | , ' Commands:' 42 | , '' 43 | , ' install installs the given asset ' 44 | , ' search [query] search available assets with optional [query]' 45 | , ' info display verbose information for the given asset ' 46 | , ' none install dependencies from ./assets.json' 47 | , '' 48 | , ' Options:' 49 | , '' 50 | , ' -c, --compress compress assets' 51 | , ' -o, --out output directory defaulting to ./public' 52 | , ' -V, --version output program version' 53 | , ' -h, --help display help information' 54 | , '' 55 | ].join('\n'); 56 | 57 | /** 58 | * Configuration. 59 | */ 60 | 61 | var config = readJSON(process.cwd() + '/.asset') 62 | || readJSON(process.env.HOME + '/.asset') 63 | || {}; 64 | 65 | /** 66 | * Repository. 67 | */ 68 | 69 | var repo = readJSON(process.env.HOME + '/.assets') 70 | || readJSON(__dirname + '/../assets.json') 71 | || {}; 72 | 73 | // merge config 74 | 75 | Object.keys(config).forEach(function(key){ 76 | options[key] = config[key]; 77 | }); 78 | 79 | // parse arguments 80 | 81 | var arg; 82 | while (args.length) { 83 | arg = args.shift(); 84 | switch (arg) { 85 | case '-h': 86 | case '--help': 87 | case 'help': 88 | console.log(usage); 89 | process.exit(); 90 | break; 91 | case '-V': 92 | case '--version': 93 | console.log(asset.version); 94 | process.exit(); 95 | break; 96 | case '-c': 97 | case '--compress': 98 | options.compress = true; 99 | break; 100 | case 'install': 101 | // ignore 102 | break; 103 | case 'search': 104 | console.log(); 105 | search(args.shift()); 106 | console.log(); 107 | process.exit(); 108 | break; 109 | case 'info': 110 | console.log(); 111 | while (args.length) { 112 | info(args.shift()); 113 | console.log(); 114 | } 115 | process.exit(); 116 | break; 117 | case '-o': 118 | case '--out': 119 | options.out = required(arg); 120 | break; 121 | default: 122 | if (~arg.indexOf('/')) { 123 | options.out = arg; 124 | } else { 125 | assets.push(arg); 126 | } 127 | } 128 | } 129 | 130 | // parse the asset strings or ./assets.json 131 | 132 | if (assets.length) { 133 | assets = assets.map(parse); 134 | } else { 135 | assets = assetsFromObject(readJSON('assets.json')); 136 | } 137 | 138 | // ensure we have assets 139 | 140 | if (!assets.length) abort('asset required'); 141 | 142 | // install the assets 143 | console.log(); 144 | mkdir(options.out, function(err){ 145 | if (err) abort(err.message); 146 | install(assets); 147 | }); 148 | process.on('exit', function(){ console.log(); }); 149 | 150 | /** 151 | * Install assets from JSON `obj`. 152 | * 153 | * @param {Object} obj 154 | */ 155 | 156 | function assetsFromObject(obj) { 157 | var arr = []; 158 | for (var asset in obj) { 159 | arr.push({ name: asset, version: obj[asset], compress: options.compress }); 160 | } 161 | return arr; 162 | } 163 | 164 | /** 165 | * Install the given `assets`. 166 | * 167 | * @param {Array} assets 168 | */ 169 | 170 | function install(assets) { 171 | var install = asset.install(assets, repo, options.out); 172 | 173 | install.on('unknown', function(asset){ 174 | abort('unregistered asset ' + asset.name); 175 | }); 176 | 177 | install.on('install', function(asset){ 178 | log('install', name(asset)); 179 | }); 180 | 181 | install.on('download', function(asset, res){ 182 | log('download', name(asset)); 183 | }); 184 | 185 | install.on('file download', function(asset, file, res){ 186 | log('download', name(asset) + ' ' + file); 187 | }); 188 | 189 | install.on('dependency', function(asset, dep){ 190 | log('dependency', name(dep)); 191 | }); 192 | 193 | install.on('complete', function(asset, path){ 194 | log('complete', name(asset) + ' ' + path); 195 | }); 196 | 197 | install.on('complete files', function(asset, files){ 198 | log('complete', name(asset) + ' ' + files.length + ' files'); 199 | }); 200 | 201 | install.on('error', function(err){ 202 | abort(err.message); 203 | }); 204 | } 205 | 206 | /** 207 | * Display info for asset `name`. 208 | * 209 | * @param {String} name 210 | */ 211 | 212 | function info(name){ 213 | var asset = repo[name]; 214 | if (!asset) abort('failed to lookup asset "' + name + '"'); 215 | log('name', name); 216 | log('description', asset.description); 217 | log('url', asset.url); 218 | if (asset.version) log('version', asset.version); 219 | if (asset.filename) log('filename', asset.filename); 220 | if (asset.dependencies) log('dependencies', Object.keys(asset.dependencies).join(', ')); 221 | } 222 | 223 | /** 224 | * Search using the given `query` string. 225 | * 226 | * @param {String} query 227 | */ 228 | 229 | function search(query) { 230 | var size = Array.isArray(tty.getWindowSize()) ? tty.getWindowSize().reverse() : process.stdout.getWindowSize() 231 | , padding = 30 232 | , width = size.shift() - padding 233 | , height = size.shift(); 234 | 235 | asset.search(repo, query, function(name, entry){ 236 | var desc = entry.description; 237 | if (desc.length > width) { 238 | desc = desc.substr(0, width - 3) + '...'; 239 | } 240 | 241 | desc = desc 242 | ? '\033[90m: ' + desc + '\033[0m' 243 | : ''; 244 | 245 | log(name, entry.version + ' ' + desc); 246 | }); 247 | } 248 | 249 | /** 250 | * Log key / val. 251 | * 252 | * @param {String} key 253 | * @param {String} val 254 | */ 255 | 256 | function log(key, val) { 257 | var width = 15 258 | , len = key.length; 259 | if (len < width) key = Array(width - len).join(' ') + key; 260 | console.log(' \033[90m%s :\033[0m \033[36m%s\033[0m', key, val); 261 | } 262 | 263 | /** 264 | * Normalize `asset` string, returning an object 265 | * representation of what is to be installed. 266 | * 267 | * Syntax: 268 | * 269 | * ['@' version] [':' 'compress'] 270 | * 271 | * @param {String} asset 272 | * @return {Object} 273 | */ 274 | 275 | function parse(asset) { 276 | var captures = asset.match(/([^:@]+)(?:@([^:]+))?((:\w+)*)/) 277 | , modifiers = captures[3].split(':').slice(1); 278 | 279 | return { 280 | name: captures[1] 281 | , version: captures[2] 282 | , compress: ~modifiers.indexOf('compress') || options.compress 283 | }; 284 | } 285 | 286 | /** 287 | * Require argument for `flag`. 288 | * 289 | * @param {String} flag 290 | * @return {String} 291 | */ 292 | 293 | function required(flag) { 294 | if (args.length) return args.shift(); 295 | abort(flag + ' argument required'); 296 | } 297 | 298 | /** 299 | * Abort with `msg`. 300 | * 301 | * @param {String} msg 302 | */ 303 | 304 | function abort(msg) { 305 | console.error(' \033[31m%s\033[0m', msg); 306 | process.exit(1); 307 | } 308 | 309 | /** 310 | * Return asset name/ 311 | * 312 | * @param {Object} asset 313 | * @return {String} 314 | */ 315 | 316 | function name(asset) { 317 | return asset.name + '@' + asset.version; 318 | } 319 | 320 | /** 321 | * Attempt to read config json at `path`. 322 | * 323 | * @param {String} path 324 | * @return {Object} 325 | */ 326 | 327 | function readJSON(path) { 328 | try { 329 | return JSON.parse(fs.readFileSync(path, 'utf8')); 330 | } catch (err) { 331 | // ignore 332 | } 333 | } 334 | 335 | /** 336 | * Mkdir -p. 337 | * 338 | * @param {String} path 339 | * @param {Function} fn 340 | */ 341 | 342 | function mkdir(path, fn) { 343 | exec('mkdir -p ' + path, fn); 344 | } 345 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = require('./lib/asset'); -------------------------------------------------------------------------------- /lib/asset.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * asset 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var Installer = require('./installer'); 13 | 14 | /** 15 | * Library version. 16 | */ 17 | 18 | exports.version = '0.4.13'; 19 | 20 | /** 21 | * Install `assets` with `repo` object, and `dest` directory. 22 | * 23 | * @param {Array} assets 24 | * @param {Object} repo 25 | * @param {String} dest 26 | * @return {Installer} 27 | * @api public 28 | */ 29 | 30 | exports.install = function(assets, repo, dest){ 31 | var installer = new Installer(repo, dest); 32 | assets.forEach(function(asset){ 33 | process.nextTick(function(){ 34 | installer.install(asset); 35 | }); 36 | }); 37 | return installer; 38 | }; 39 | 40 | /** 41 | * Search `repo` for `query`, invoking `fn(name, entry)` 42 | * per matching entry. 43 | * 44 | * @param {Object} repo 45 | * @param {String} query 46 | * @param {Function} fn 47 | * @api public 48 | */ 49 | 50 | exports.search = function(repo, query, fn){ 51 | var names = Object.keys(repo); 52 | names.forEach(function(name){ 53 | var entry = repo[name] 54 | , match = !query 55 | || ~name.indexOf(query) 56 | || ~entry.tags.indexOf(query); 57 | if (match) fn(name, entry); 58 | }); 59 | }; -------------------------------------------------------------------------------- /lib/installer.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * asset - Installer 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var EventEmitter = require('events').EventEmitter 13 | , dirname = require('path').dirname 14 | , basename = require('path').basename 15 | , extname = require('path').extname 16 | , mkdir = require('mkdirp').mkdirp 17 | , request = require('request') 18 | , fs = require('fs'); 19 | 20 | /** 21 | * Expose installer. 22 | */ 23 | 24 | module.exports = Installer; 25 | 26 | /** 27 | * Initialize a new `Installer`. 28 | * 29 | * @param {Object} repo 30 | * @api private 31 | */ 32 | 33 | function Installer(repo, dest) { 34 | this.assets = []; 35 | this.repo = repo; 36 | this.dest = dest; 37 | if (!repo) throw new Error('repository required'); 38 | this.queued = {}; 39 | } 40 | 41 | /** 42 | * Inherit from `EventEmitter.prototype`. 43 | */ 44 | 45 | Installer.prototype.__proto__ = EventEmitter.prototype; 46 | 47 | /** 48 | * Install the given `asset`. 49 | * 50 | * Asset: 51 | * 52 | * - `name` name of the asset 53 | * - `version` version of the asset 54 | * 55 | * @param {Object} asset 56 | * @api private 57 | */ 58 | 59 | Installer.prototype.install = function(asset){ 60 | var entry = this.lookup(asset); 61 | if (!entry) return this.emit('unknown', asset); 62 | asset.entry = entry; 63 | if (this.queued[asset.name]) return this.emit('queued', asset); 64 | this.emit('install', asset); 65 | this.queued[asset.name] = true; 66 | this.installDependencies(asset); 67 | 68 | // several files 69 | if (entry.files) { 70 | this.downloadFiles(asset, entry.files, this.dest); 71 | } else { 72 | this.download(asset, this.dest + '/' + entry.filename); 73 | } 74 | }; 75 | 76 | /** 77 | * Lookup and normalize repo entry for `asset`. 78 | * 79 | * @param {Object} asset 80 | * @return {Object} 81 | * @api private 82 | */ 83 | 84 | Installer.prototype.lookup = function(asset){ 85 | // invalid or not found 86 | if (!asset.name) throw new Error('asset name required'); 87 | var entry = this.repo[asset.name]; 88 | if (!entry) return; 89 | 90 | // normalize filename 91 | entry.filename = entry.filename || basename(entry.url); 92 | 93 | // normalize compressed url 94 | if (entry.compressed && !~entry.compressed.indexOf('://')) { 95 | entry.compressed = entry.url.replace(basename(entry.url), entry.compressed); 96 | } 97 | 98 | // default version 99 | if (!asset.version) asset.version = entry.version; 100 | 101 | // extension 102 | entry.ext = extname(entry.url); 103 | 104 | return entry; 105 | }; 106 | 107 | /** 108 | * Install the given `asset` dependencies when present. 109 | * 110 | * @param {Object} asset 111 | * @api private 112 | */ 113 | 114 | Installer.prototype.installDependencies = function(asset){ 115 | var version; 116 | for (var dep in asset.entry.dependencies) { 117 | version = asset.entry.dependencies[dep]; 118 | dep = { name: dep, version: version }; 119 | this.emit('dependency', asset, dep); 120 | this.install(dep); 121 | } 122 | }; 123 | 124 | /** 125 | * Download the given `files` to `dest`. 126 | * 127 | * @param {Object} asset 128 | * @param {Array} files 129 | * @param {String} dest 130 | * @api private 131 | */ 132 | 133 | Installer.prototype.downloadFiles = function(asset, files, dest){ 134 | var pending = files.length 135 | , self = this; 136 | 137 | files.forEach(function(file){ 138 | self.downloadFile(asset, file, dest, function(err){ 139 | if (err) return self.emit('error', err); 140 | --pending || self.emit('complete files', asset, files); 141 | }); 142 | }); 143 | }; 144 | 145 | /** 146 | * Download the given `asset`'s `file` to `dest`. 147 | * 148 | * @param {Object} asset 149 | * @param {String} file 150 | * @param {String} dest 151 | * @param {Function} fn 152 | * @api private 153 | */ 154 | 155 | Installer.prototype.downloadFile = function(asset, file, dest, fn){ 156 | var base = asset.entry.base.replace(/\{version\}/g, asset.version) 157 | , url = base + '/' + file 158 | , path = dest + '/' + file 159 | , dest = dest + '/' + dirname(file) 160 | , self = this; 161 | 162 | request({ url: url }, function(err, res, body){ 163 | if (err) return fn(err); 164 | if (res.statusCode >= 300) { 165 | var err = new Error('failed to download ' + url); 166 | fn(err); 167 | } else { 168 | self.emit('file download', asset, path, res); 169 | mkdir(dest, 0755, function(err){ 170 | if (err) return fn(err); 171 | fs.writeFile(path, body, function(err){ 172 | if (err) return fn(err); 173 | self.emit('file write', asset, path); 174 | fn(); 175 | }); 176 | }); 177 | } 178 | }); 179 | }; 180 | 181 | /** 182 | * Download the given `asset` to `path`. 183 | * 184 | * @param {Object} asset 185 | * @param {String} path 186 | * @api private 187 | */ 188 | 189 | Installer.prototype.download = function(asset, path){ 190 | var self = this 191 | , version = asset.version 192 | , url = asset.entry[asset.compress ? 'compressed' : 'url'] || asset.entry.url 193 | , url = url.replace(/\{version\}/g, version) 194 | , path = path.replace(/\{version\}/g, version); 195 | 196 | // compressed 197 | if (asset.compress && asset.entry.compressed) { 198 | switch (asset.entry.ext) { 199 | case '.js': 200 | path = path.replace(/\.js$/, '.min.js'); 201 | break; 202 | } 203 | } 204 | 205 | // request the data 206 | request({ url: url }, function(err, res, body){ 207 | if (err) return self.emit('error', err); 208 | if (res.statusCode >= 300) { 209 | var err = new Error('failed to download ' + url); 210 | self.emit('error', err); 211 | } else { 212 | self.emit('download', asset, res); 213 | fs.writeFile(path, body, function(err){ 214 | if (err) return self.emit('error', err); 215 | self.emit('complete', asset, path); 216 | }); 217 | } 218 | }); 219 | }; 220 | 221 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { "name": "asset" 2 | , "version": "0.4.13" 3 | , "description": "Asset manager" 4 | , "keywords": ["assets", "javascript", "css", "package manager"] 5 | , "author": "TJ Holowaychuk " 6 | , "dependencies": { "request": "1.9.5", "mkdirp": "0.3.x" } 7 | , "bin": { "asset": "./bin/asset" } 8 | , "main": "index" 9 | } 10 | --------------------------------------------------------------------------------