Repository files navigation

stassets

A Static Asset Compiler


Compiling is so blase. Let it just happen.

Stassets is an express middleware for keeping your browser code up to date and ready to serve at a moment's notice. It watches your client directory structure, and performs the build steps in memory. When you ask for your files, they've already been compiled. Life is easy.

To start using an express server with stassets already configured, you should use Rupert.

stassets also minimizes the number of files you will transfer - it breaks the project into

.
├── index.html
├── application.js
├── templates.js
├── all.css
├── print.css
├── screen.css
├── vendors.css
└── vendors.js

And with a basic index.jade looking like

doctype html
html(ng-app="stassets.main")
head
title Test Fixture
link(rel="stylesheet", href="vendors.css")
link(rel="stylesheet", href="all.css")
link(rel="stylesheet", href="screen.css", media="screen")
link(rel="stylesheet", href="print.css", media="print")
body
main
script(src="vendors.js")
script(src="templates.js")
script(src="application.js")

your project is 7 files.

Usage

stassets is built as an express middleware. With the default project layout, the easiest server looks like this:

varexpress=require('express')varapp=express();varstasset=require('stasset')app.use(stasset({// The client directory is relative to this app.js fileroot: __dirname+"/client"// My vendors are loaded with bower, which is a directory up from here.vendors: {prefix: __dirname+"/../bower_components",// These files will be concatenated in order.// All this uses is angular and bootstrap, but these can grow as large// as you need.js: ['angular/angular.js'],css: ['bootstrap/dist/css/*']}}));app.listen(8989);

Recommended Layout

Group your code by component. It looks like this:

.
├── Gruntfile.coffee
├── index.jade
├── main
│ ├── all.styl
│ ├── footer
│ │ ├── footer-directive.coffee
│ │ ├── footer-template.jade
│ │ └── footer_test.coffee
│ ├── login
│ │ ├── login-all.styl
│ │ ├── login-directive.coffee
│ │ ├── login-template.jade
│ │ └── login_test.coffee
│ ├── main.coffee
│ ├── nav
│ │ ├── nav-directive.coffee
│ │ ├── nav-template.jade
│ │ └── nav_test.coffee
│ ├── main-print.styl
│ ├── main-screen.styl
│ └── main_test.coffee
├── scavenge
│ ├── gradebook
│ │ ├── gradebook-directive.coffee
│ │ ├── gradebook-service.coffee
│ │ ├── gradebook-service_mock.coffee
│ │ ├── gradebook-service_test.coffee
│ │ └── gradebook-template.jade
│ ├── hunts
│ │ ├── hunts-all.styl
│ │ ├── hunts-directive.coffee
│ │ ├── hunts-directive_test.coffee
│ │ ├── edit
│ │ │ ├── hunts-edit-directive.coffee
│ │ │ ├── hunts-edit-template.jade
│ │ │ └── hunts-edit_test.coffee
│ │ ├── hunts-service.coffee
│ │ ├── hunts-service_mock.coffee
│ │ ├── hunts-service_test.coffee
│ │ └── hunts-template.jade
│ ├── leaders
│ │ ├── leaders-all.styl
│ │ ├── leaders-directive.coffee
│ │ ├── leaders-template.jade
│ │ └── leaders_test.coffee
│ ├── students
│ │ ├── students-directive.coffee
│ │ ├── students-screen.styl
│ │ ├── students-service.coffee
│ │ ├── students-template.jade
│ │ └── students_test.coffee
│ └── submit
│ ├── submit-controller.coffee
│ ├── submit-controller_test.coffee
│ ├── submit-directive.coffee
│ ├── submit-directive_test.coffee
│ ├── grading
│ │ ├── submit-grading-controller.coffee
│ │ ├── submit-grading-directive.coffee
│ │ ├── submit-grading-screen.styl
│ │ └── submit-grading-template.jade
│ ├── submit-screen.styl
│ ├── submit-service.coffee
│ ├── submit-service_mock.coffee
│ ├── submit-service_test.coffee
│ └── submit-template.jade
├── stylus
│ └── definitions
│ ├── mixins.styl
│ └── variables.styl
└── util
├── fileInput
│ ├── fileInput-directive.coffee
│ ├── fileInput-service.coffee
│ └── fileInput-test.coffee
└── thsort
├── thsort-directive.coffee
├── thsort-screen.styl
└── thsort-template.jade

This is the client (in browser, Angular) codebase for a medium sized project, that manages a gradebook of student programming submissions. Notice that the controllers, templates, and tests are all next to one another. Don't drive five directories up and three over to get to a file for the same component. That's just crazy.

Stassets understands this directory layout, but can be configured to any other layout.

This is in line with current best practices for AngularJS.

Cascading File System

stassets has the concept of a Cascading File System. By creating a similar directory structure in several root directories, stassets users can quickly and easily implement a themeing or plugin system. To generate a cascading file system, stassets joins a list of root directories with a set of file patterns. Files in each root directory matching a pattern are joined, with files in higher priority root directories overwriting those with lower priority.

Configuration

WIP These configuration options are used to extend and customize at various places. Until 1.0, these may change subtly. They will not be stable until 1.0.

root

Required. String or Array. Specifies the cascading search order for watched files. Any file matching the same path in a later root directory will override any files at that path in a prior directory. Especially useful for creating themed systems.

./index.coffee:11: @config.root = [@config.root] unless @config.root instanceof Array

livereload

Optional. Boolean false or Object. Configure a livereload server. If not present, uses tiny-lr's default settings. If false, completely disable Live Reload. Otherwise, is passed as-is to tiny-lr's constructor.

./index.coffee:28: unless @config.livereload is no
./index.coffee:29: @livereload = new LR @config.livereload

scripts

Configure application script settings.

types

Optional. Array of script filename types. Files within the root folders that have a name matching *{type}.{ScriptTypes} will be loaded, in order defined in the array, to the application.js bundle. Type extensions are determined based on registered filetype handlers in ScriptWatcher.renderers[handler]. Default type list is ['main'].

./Watchers/Script.coffee:16: @config.scripts.types = @config.scripts.types || [

compress

Optional. Boolean to run bundled application.js through Uglify.

./Watchers/Script.coffee:63: res @minify res if @config.scripts.compress

styles

./Watchers/Style/Style.coffee:40: if @config.vendors?.stylus?
./Watchers/Style/Style.coffee:41: @config.vendors.stylus.map (_1)=>
./Watchers/Style/Style.coffee:42: @config.vendors.prefix + '/' + _1
./Watchers/Style/Style.coffee:48: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/variables")
./Watchers/Style/Style.coffee:49: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/mixins")

templates

Optional. Object configuring template rendering options.

baseModule

Optional string. If present, will prefix all template module names with baseModule.

./Watchers/Template.coffee:26: if moduleRoot = @config.templates.baseModule

vendors

vendors.prefix

./Watchers/Vendor/Vendor.coffee:15: @config.vendors or=
./Watchers/Vendor/Vendor.coffee:18: @config.vendors.prefix or= './'
./Watchers/Vendor/Vendor.coffee:19: unless @config.vendors.prefix.length? and @config.vendors.prefix.map?
./Watchers/Vendor/Vendor.coffee:20: @config.vendors.prefix = [@config.vendors.prefix]
./Watchers/Vendor/Vendor.coffee:22: @config.root = @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:23: @config.noRoot = true
./Watchers/Vendor/Vendor.coffee:30: for root in @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:40: smResolvedPath = Path.join @config.vendors.prefix, smPath

vendors.js

vendors.jsMaps

./Watchers/Vendor/Script.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Script.coffee:8: @config.vendors.js or= []
./Watchers/Vendor/Script.coffee:9: @config.vendors.jsMaps or= []
./Watchers/Vendor/Script.coffee:12: pattern: -> super @config.vendors.js
./Watchers/Vendor/Script.coffee:13: getMaps: -> @config.vendors.jsMaps

vendors.css

vendors.cssMaps

./Watchers/Vendor/Style.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Style.coffee:8: @config.vendors.css or= []
./Watchers/Vendor/Style.coffee:9: @config.vendors.cssMaps or= []
./Watchers/Vendor/Style.coffee:12: pattern: -> super @config.vendors.css
./Watchers/Vendor/Style.coffee:13: getMaps: -> @config.vendors.cssMaps

Changelog

  • 0.3.152015-06-15 Use better HTML minifier.
  • 0.3.142015-02-05 Fix bug with windows pathing outputting wrong.
  • 0.3.122015-02-02 Fix what was sort of a bug but is apparent as definitely a bug in Coffeescript 1.9
  • 0.3.112015-01-09 Bumped all outdated dependencies.
  • 0.3.102015-01-09 Bumped sane dependency to 1.0.0 (should be more stable).
  • 0.3.92014-12-31TemplateWatcher has new improved & better naming algorithm.
  • 0.3.82014-12-30this.meta to only pass fs.stats to render. Exposes Constructors.
  • 0.3.72014-12-29 Template js injection is more generic.
  • 0.3.62014-12-03 Streamline and improve sourcemap handling.
  • 0.3.52014-11-17 Only emit one error, when a vendor file is unavailable.
  • 0.3.42014-11-10 Back on track with a sane build and changelog.
  • 0.2.212014-11-01 Assets accept module prefix in file name.
  • 0.2.202014-10-28 Handle errors in generated sourcemaps.
  • 0.2.192014-10-26 Generate SourceMaps for unsourcemapped vendors.
  • 0.2.182014-10-17 Jade rendering issue.
  • 0.2.16, 172014-10-17 Less CSS compiler and vanilla HTML compiler.
  • 0.2.152014-10-06 Better reporting syntax errors.
  • 0.2.142014-09-11 Documentation pass (13) & Bugfix (14).
  • 0.2.122014-09-07 [debug][https://www.npmjs.org/package/debug] for logs.
  • 0.2.112014-09-05 Bug fixes. See commit log.
  • 0.2.72014-08-20 Sourcemaps for Stylus files.
  • 0.2.62014-08-12 Many small bugfixes in .2 through .6.
  • 0.2.12014-07-21 Replaced Gaze with Sane.
  • 0.2.02014-07-19 Implements Cascading File System.
  • 0.1.42014-06-16 Includes Grunt task to save compiled assets to disk, for pure static server (also great for tests). This is likely to move to grunt-stassets in the very near future!
  • 0.12014-06-12 Understands the basic project structure. Works great for rapid development.

About

Static Asset Compiling Express Middleware

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

stassets

A Static Asset Compiler


Compiling is so blase. Let it just happen.

Stassets is an express middleware for keeping your browser code up to date and ready to serve at a moment's notice. It watches your client directory structure, and performs the build steps in memory. When you ask for your files, they've already been compiled. Life is easy.

To start using an express server with stassets already configured, you should use Rupert.

stassets also minimizes the number of files you will transfer - it breaks the project into

.
├── index.html
├── application.js
├── templates.js
├── all.css
├── print.css
├── screen.css
├── vendors.css
└── vendors.js

And with a basic index.jade looking like

doctype html
html(ng-app="stassets.main")
head
title Test Fixture
link(rel="stylesheet", href="vendors.css")
link(rel="stylesheet", href="all.css")
link(rel="stylesheet", href="screen.css", media="screen")
link(rel="stylesheet", href="print.css", media="print")
body
main
script(src="vendors.js")
script(src="templates.js")
script(src="application.js")

your project is 7 files.

Usage

stassets is built as an express middleware. With the default project layout, the easiest server looks like this:

varexpress=require('express')varapp=express();varstasset=require('stasset')app.use(stasset({// The client directory is relative to this app.js fileroot: __dirname+"/client"// My vendors are loaded with bower, which is a directory up from here.vendors: {prefix: __dirname+"/../bower_components",// These files will be concatenated in order.// All this uses is angular and bootstrap, but these can grow as large// as you need.js: ['angular/angular.js'],css: ['bootstrap/dist/css/*']}}));app.listen(8989);

Recommended Layout

Group your code by component. It looks like this:

.
├── Gruntfile.coffee
├── index.jade
├── main
│ ├── all.styl
│ ├── footer
│ │ ├── footer-directive.coffee
│ │ ├── footer-template.jade
│ │ └── footer_test.coffee
│ ├── login
│ │ ├── login-all.styl
│ │ ├── login-directive.coffee
│ │ ├── login-template.jade
│ │ └── login_test.coffee
│ ├── main.coffee
│ ├── nav
│ │ ├── nav-directive.coffee
│ │ ├── nav-template.jade
│ │ └── nav_test.coffee
│ ├── main-print.styl
│ ├── main-screen.styl
│ └── main_test.coffee
├── scavenge
│ ├── gradebook
│ │ ├── gradebook-directive.coffee
│ │ ├── gradebook-service.coffee
│ │ ├── gradebook-service_mock.coffee
│ │ ├── gradebook-service_test.coffee
│ │ └── gradebook-template.jade
│ ├── hunts
│ │ ├── hunts-all.styl
│ │ ├── hunts-directive.coffee
│ │ ├── hunts-directive_test.coffee
│ │ ├── edit
│ │ │ ├── hunts-edit-directive.coffee
│ │ │ ├── hunts-edit-template.jade
│ │ │ └── hunts-edit_test.coffee
│ │ ├── hunts-service.coffee
│ │ ├── hunts-service_mock.coffee
│ │ ├── hunts-service_test.coffee
│ │ └── hunts-template.jade
│ ├── leaders
│ │ ├── leaders-all.styl
│ │ ├── leaders-directive.coffee
│ │ ├── leaders-template.jade
│ │ └── leaders_test.coffee
│ ├── students
│ │ ├── students-directive.coffee
│ │ ├── students-screen.styl
│ │ ├── students-service.coffee
│ │ ├── students-template.jade
│ │ └── students_test.coffee
│ └── submit
│ ├── submit-controller.coffee
│ ├── submit-controller_test.coffee
│ ├── submit-directive.coffee
│ ├── submit-directive_test.coffee
│ ├── grading
│ │ ├── submit-grading-controller.coffee
│ │ ├── submit-grading-directive.coffee
│ │ ├── submit-grading-screen.styl
│ │ └── submit-grading-template.jade
│ ├── submit-screen.styl
│ ├── submit-service.coffee
│ ├── submit-service_mock.coffee
│ ├── submit-service_test.coffee
│ └── submit-template.jade
├── stylus
│ └── definitions
│ ├── mixins.styl
│ └── variables.styl
└── util
├── fileInput
│ ├── fileInput-directive.coffee
│ ├── fileInput-service.coffee
│ └── fileInput-test.coffee
└── thsort
├── thsort-directive.coffee
├── thsort-screen.styl
└── thsort-template.jade

This is the client (in browser, Angular) codebase for a medium sized project, that manages a gradebook of student programming submissions. Notice that the controllers, templates, and tests are all next to one another. Don't drive five directories up and three over to get to a file for the same component. That's just crazy.

Stassets understands this directory layout, but can be configured to any other layout.

This is in line with current best practices for AngularJS.

Cascading File System

stassets has the concept of a Cascading File System. By creating a similar directory structure in several root directories, stassets users can quickly and easily implement a themeing or plugin system. To generate a cascading file system, stassets joins a list of root directories with a set of file patterns. Files in each root directory matching a pattern are joined, with files in higher priority root directories overwriting those with lower priority.

Configuration

WIP These configuration options are used to extend and customize at various places. Until 1.0, these may change subtly. They will not be stable until 1.0.

root

Required. String or Array. Specifies the cascading search order for watched files. Any file matching the same path in a later root directory will override any files at that path in a prior directory. Especially useful for creating themed systems.

./index.coffee:11: @config.root = [@config.root] unless @config.root instanceof Array

livereload

Optional. Boolean false or Object. Configure a livereload server. If not present, uses tiny-lr's default settings. If false, completely disable Live Reload. Otherwise, is passed as-is to tiny-lr's constructor.

./index.coffee:28: unless @config.livereload is no
./index.coffee:29: @livereload = new LR @config.livereload

scripts

Configure application script settings.

types

Optional. Array of script filename types. Files within the root folders that have a name matching *{type}.{ScriptTypes} will be loaded, in order defined in the array, to the application.js bundle. Type extensions are determined based on registered filetype handlers in ScriptWatcher.renderers[handler]. Default type list is ['main'].

./Watchers/Script.coffee:16: @config.scripts.types = @config.scripts.types || [

compress

Optional. Boolean to run bundled application.js through Uglify.

./Watchers/Script.coffee:63: res @minify res if @config.scripts.compress

styles

./Watchers/Style/Style.coffee:40: if @config.vendors?.stylus?
./Watchers/Style/Style.coffee:41: @config.vendors.stylus.map (_1)=>
./Watchers/Style/Style.coffee:42: @config.vendors.prefix + '/' + _1
./Watchers/Style/Style.coffee:48: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/variables")
./Watchers/Style/Style.coffee:49: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/mixins")

templates

Optional. Object configuring template rendering options.

baseModule

Optional string. If present, will prefix all template module names with baseModule.

./Watchers/Template.coffee:26: if moduleRoot = @config.templates.baseModule

vendors

vendors.prefix

./Watchers/Vendor/Vendor.coffee:15: @config.vendors or=
./Watchers/Vendor/Vendor.coffee:18: @config.vendors.prefix or= './'
./Watchers/Vendor/Vendor.coffee:19: unless @config.vendors.prefix.length? and @config.vendors.prefix.map?
./Watchers/Vendor/Vendor.coffee:20: @config.vendors.prefix = [@config.vendors.prefix]
./Watchers/Vendor/Vendor.coffee:22: @config.root = @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:23: @config.noRoot = true
./Watchers/Vendor/Vendor.coffee:30: for root in @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:40: smResolvedPath = Path.join @config.vendors.prefix, smPath

vendors.js

vendors.jsMaps

./Watchers/Vendor/Script.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Script.coffee:8: @config.vendors.js or= []
./Watchers/Vendor/Script.coffee:9: @config.vendors.jsMaps or= []
./Watchers/Vendor/Script.coffee:12: pattern: -> super @config.vendors.js
./Watchers/Vendor/Script.coffee:13: getMaps: -> @config.vendors.jsMaps

vendors.css

vendors.cssMaps

./Watchers/Vendor/Style.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Style.coffee:8: @config.vendors.css or= []
./Watchers/Vendor/Style.coffee:9: @config.vendors.cssMaps or= []
./Watchers/Vendor/Style.coffee:12: pattern: -> super @config.vendors.css
./Watchers/Vendor/Style.coffee:13: getMaps: -> @config.vendors.cssMaps

Changelog

  • 0.3.152015-06-15 Use better HTML minifier.
  • 0.3.142015-02-05 Fix bug with windows pathing outputting wrong.
  • 0.3.122015-02-02 Fix what was sort of a bug but is apparent as definitely a bug in Coffeescript 1.9
  • 0.3.112015-01-09 Bumped all outdated dependencies.
  • 0.3.102015-01-09 Bumped sane dependency to 1.0.0 (should be more stable).
  • 0.3.92014-12-31TemplateWatcher has new improved & better naming algorithm.
  • 0.3.82014-12-30this.meta to only pass fs.stats to render. Exposes Constructors.
  • 0.3.72014-12-29 Template js injection is more generic.
  • 0.3.62014-12-03 Streamline and improve sourcemap handling.
  • 0.3.52014-11-17 Only emit one error, when a vendor file is unavailable.
  • 0.3.42014-11-10 Back on track with a sane build and changelog.
  • 0.2.212014-11-01 Assets accept module prefix in file name.
  • 0.2.202014-10-28 Handle errors in generated sourcemaps.
  • 0.2.192014-10-26 Generate SourceMaps for unsourcemapped vendors.
  • 0.2.182014-10-17 Jade rendering issue.
  • 0.2.16, 172014-10-17 Less CSS compiler and vanilla HTML compiler.
  • 0.2.152014-10-06 Better reporting syntax errors.
  • 0.2.142014-09-11 Documentation pass (13) & Bugfix (14).
  • 0.2.122014-09-07 [debug][https://www.npmjs.org/package/debug] for logs.
  • 0.2.112014-09-05 Bug fixes. See commit log.
  • 0.2.72014-08-20 Sourcemaps for Stylus files.
  • 0.2.62014-08-12 Many small bugfixes in .2 through .6.
  • 0.2.12014-07-21 Replaced Gaze with Sane.
  • 0.2.02014-07-19 Implements Cascading File System.
  • 0.1.42014-06-16 Includes Grunt task to save compiled assets to disk, for pure static server (also great for tests). This is likely to move to grunt-stassets in the very near future!
  • 0.12014-06-12 Understands the basic project structure. Works great for rapid development.

About

Static Asset Compiling Express Middleware

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

stassets

A Static Asset Compiler


Compiling is so blase. Let it just happen.

Stassets is an express middleware for keeping your browser code up to date and ready to serve at a moment's notice. It watches your client directory structure, and performs the build steps in memory. When you ask for your files, they've already been compiled. Life is easy.

To start using an express server with stassets already configured, you should use Rupert.

stassets also minimizes the number of files you will transfer - it breaks the project into

.
├── index.html
├── application.js
├── templates.js
├── all.css
├── print.css
├── screen.css
├── vendors.css
└── vendors.js

And with a basic index.jade looking like

doctype html
html(ng-app="stassets.main")
head
title Test Fixture
link(rel="stylesheet", href="vendors.css")
link(rel="stylesheet", href="all.css")
link(rel="stylesheet", href="screen.css", media="screen")
link(rel="stylesheet", href="print.css", media="print")
body
main
script(src="vendors.js")
script(src="templates.js")
script(src="application.js")

your project is 7 files.

Usage

stassets is built as an express middleware. With the default project layout, the easiest server looks like this:

varexpress=require('express')varapp=express();varstasset=require('stasset')app.use(stasset({// The client directory is relative to this app.js fileroot: __dirname+"/client"// My vendors are loaded with bower, which is a directory up from here.vendors: {prefix: __dirname+"/../bower_components",// These files will be concatenated in order.// All this uses is angular and bootstrap, but these can grow as large// as you need.js: ['angular/angular.js'],css: ['bootstrap/dist/css/*']}}));app.listen(8989);

Recommended Layout

Group your code by component. It looks like this:

.
├── Gruntfile.coffee
├── index.jade
├── main
│ ├── all.styl
│ ├── footer
│ │ ├── footer-directive.coffee
│ │ ├── footer-template.jade
│ │ └── footer_test.coffee
│ ├── login
│ │ ├── login-all.styl
│ │ ├── login-directive.coffee
│ │ ├── login-template.jade
│ │ └── login_test.coffee
│ ├── main.coffee
│ ├── nav
│ │ ├── nav-directive.coffee
│ │ ├── nav-template.jade
│ │ └── nav_test.coffee
│ ├── main-print.styl
│ ├── main-screen.styl
│ └── main_test.coffee
├── scavenge
│ ├── gradebook
│ │ ├── gradebook-directive.coffee
│ │ ├── gradebook-service.coffee
│ │ ├── gradebook-service_mock.coffee
│ │ ├── gradebook-service_test.coffee
│ │ └── gradebook-template.jade
│ ├── hunts
│ │ ├── hunts-all.styl
│ │ ├── hunts-directive.coffee
│ │ ├── hunts-directive_test.coffee
│ │ ├── edit
│ │ │ ├── hunts-edit-directive.coffee
│ │ │ ├── hunts-edit-template.jade
│ │ │ └── hunts-edit_test.coffee
│ │ ├── hunts-service.coffee
│ │ ├── hunts-service_mock.coffee
│ │ ├── hunts-service_test.coffee
│ │ └── hunts-template.jade
│ ├── leaders
│ │ ├── leaders-all.styl
│ │ ├── leaders-directive.coffee
│ │ ├── leaders-template.jade
│ │ └── leaders_test.coffee
│ ├── students
│ │ ├── students-directive.coffee
│ │ ├── students-screen.styl
│ │ ├── students-service.coffee
│ │ ├── students-template.jade
│ │ └── students_test.coffee
│ └── submit
│ ├── submit-controller.coffee
│ ├── submit-controller_test.coffee
│ ├── submit-directive.coffee
│ ├── submit-directive_test.coffee
│ ├── grading
│ │ ├── submit-grading-controller.coffee
│ │ ├── submit-grading-directive.coffee
│ │ ├── submit-grading-screen.styl
│ │ └── submit-grading-template.jade
│ ├── submit-screen.styl
│ ├── submit-service.coffee
│ ├── submit-service_mock.coffee
│ ├── submit-service_test.coffee
│ └── submit-template.jade
├── stylus
│ └── definitions
│ ├── mixins.styl
│ └── variables.styl
└── util
├── fileInput
│ ├── fileInput-directive.coffee
│ ├── fileInput-service.coffee
│ └── fileInput-test.coffee
└── thsort
├── thsort-directive.coffee
├── thsort-screen.styl
└── thsort-template.jade

This is the client (in browser, Angular) codebase for a medium sized project, that manages a gradebook of student programming submissions. Notice that the controllers, templates, and tests are all next to one another. Don't drive five directories up and three over to get to a file for the same component. That's just crazy.

Stassets understands this directory layout, but can be configured to any other layout.

This is in line with current best practices for AngularJS.

Cascading File System

stassets has the concept of a Cascading File System. By creating a similar directory structure in several root directories, stassets users can quickly and easily implement a themeing or plugin system. To generate a cascading file system, stassets joins a list of root directories with a set of file patterns. Files in each root directory matching a pattern are joined, with files in higher priority root directories overwriting those with lower priority.

Configuration

WIP These configuration options are used to extend and customize at various places. Until 1.0, these may change subtly. They will not be stable until 1.0.

root

Required. String or Array. Specifies the cascading search order for watched files. Any file matching the same path in a later root directory will override any files at that path in a prior directory. Especially useful for creating themed systems.

./index.coffee:11: @config.root = [@config.root] unless @config.root instanceof Array

livereload

Optional. Boolean false or Object. Configure a livereload server. If not present, uses tiny-lr's default settings. If false, completely disable Live Reload. Otherwise, is passed as-is to tiny-lr's constructor.

./index.coffee:28: unless @config.livereload is no
./index.coffee:29: @livereload = new LR @config.livereload

scripts

Configure application script settings.

types

Optional. Array of script filename types. Files within the root folders that have a name matching *{type}.{ScriptTypes} will be loaded, in order defined in the array, to the application.js bundle. Type extensions are determined based on registered filetype handlers in ScriptWatcher.renderers[handler]. Default type list is ['main'].

./Watchers/Script.coffee:16: @config.scripts.types = @config.scripts.types || [

compress

Optional. Boolean to run bundled application.js through Uglify.

./Watchers/Script.coffee:63: res @minify res if @config.scripts.compress

styles

./Watchers/Style/Style.coffee:40: if @config.vendors?.stylus?
./Watchers/Style/Style.coffee:41: @config.vendors.stylus.map (_1)=>
./Watchers/Style/Style.coffee:42: @config.vendors.prefix + '/' + _1
./Watchers/Style/Style.coffee:48: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/variables")
./Watchers/Style/Style.coffee:49: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/mixins")

templates

Optional. Object configuring template rendering options.

baseModule

Optional string. If present, will prefix all template module names with baseModule.

./Watchers/Template.coffee:26: if moduleRoot = @config.templates.baseModule

vendors

vendors.prefix

./Watchers/Vendor/Vendor.coffee:15: @config.vendors or=
./Watchers/Vendor/Vendor.coffee:18: @config.vendors.prefix or= './'
./Watchers/Vendor/Vendor.coffee:19: unless @config.vendors.prefix.length? and @config.vendors.prefix.map?
./Watchers/Vendor/Vendor.coffee:20: @config.vendors.prefix = [@config.vendors.prefix]
./Watchers/Vendor/Vendor.coffee:22: @config.root = @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:23: @config.noRoot = true
./Watchers/Vendor/Vendor.coffee:30: for root in @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:40: smResolvedPath = Path.join @config.vendors.prefix, smPath

vendors.js

vendors.jsMaps

./Watchers/Vendor/Script.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Script.coffee:8: @config.vendors.js or= []
./Watchers/Vendor/Script.coffee:9: @config.vendors.jsMaps or= []
./Watchers/Vendor/Script.coffee:12: pattern: -> super @config.vendors.js
./Watchers/Vendor/Script.coffee:13: getMaps: -> @config.vendors.jsMaps

vendors.css

vendors.cssMaps

./Watchers/Vendor/Style.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Style.coffee:8: @config.vendors.css or= []
./Watchers/Vendor/Style.coffee:9: @config.vendors.cssMaps or= []
./Watchers/Vendor/Style.coffee:12: pattern: -> super @config.vendors.css
./Watchers/Vendor/Style.coffee:13: getMaps: -> @config.vendors.cssMaps

Changelog

  • 0.3.152015-06-15 Use better HTML minifier.
  • 0.3.142015-02-05 Fix bug with windows pathing outputting wrong.
  • 0.3.122015-02-02 Fix what was sort of a bug but is apparent as definitely a bug in Coffeescript 1.9
  • 0.3.112015-01-09 Bumped all outdated dependencies.
  • 0.3.102015-01-09 Bumped sane dependency to 1.0.0 (should be more stable).
  • 0.3.92014-12-31TemplateWatcher has new improved & better naming algorithm.
  • 0.3.82014-12-30this.meta to only pass fs.stats to render. Exposes Constructors.
  • 0.3.72014-12-29 Template js injection is more generic.
  • 0.3.62014-12-03 Streamline and improve sourcemap handling.
  • 0.3.52014-11-17 Only emit one error, when a vendor file is unavailable.
  • 0.3.42014-11-10 Back on track with a sane build and changelog.
  • 0.2.212014-11-01 Assets accept module prefix in file name.
  • 0.2.202014-10-28 Handle errors in generated sourcemaps.
  • 0.2.192014-10-26 Generate SourceMaps for unsourcemapped vendors.
  • 0.2.182014-10-17 Jade rendering issue.
  • 0.2.16, 172014-10-17 Less CSS compiler and vanilla HTML compiler.
  • 0.2.152014-10-06 Better reporting syntax errors.
  • 0.2.142014-09-11 Documentation pass (13) & Bugfix (14).
  • 0.2.122014-09-07 [debug][https://www.npmjs.org/package/debug] for logs.
  • 0.2.112014-09-05 Bug fixes. See commit log.
  • 0.2.72014-08-20 Sourcemaps for Stylus files.
  • 0.2.62014-08-12 Many small bugfixes in .2 through .6.
  • 0.2.12014-07-21 Replaced Gaze with Sane.
  • 0.2.02014-07-19 Implements Cascading File System.
  • 0.1.42014-06-16 Includes Grunt task to save compiled assets to disk, for pure static server (also great for tests). This is likely to move to grunt-stassets in the very near future!
  • 0.12014-06-12 Understands the basic project structure. Works great for rapid development.

About

Static Asset Compiling Express Middleware

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

stassets

A Static Asset Compiler


Compiling is so blase. Let it just happen.

Stassets is an express middleware for keeping your browser code up to date and ready to serve at a moment's notice. It watches your client directory structure, and performs the build steps in memory. When you ask for your files, they've already been compiled. Life is easy.

To start using an express server with stassets already configured, you should use Rupert.

stassets also minimizes the number of files you will transfer - it breaks the project into

.
├── index.html
├── application.js
├── templates.js
├── all.css
├── print.css
├── screen.css
├── vendors.css
└── vendors.js

And with a basic index.jade looking like

doctype html
html(ng-app="stassets.main")
head
title Test Fixture
link(rel="stylesheet", href="vendors.css")
link(rel="stylesheet", href="all.css")
link(rel="stylesheet", href="screen.css", media="screen")
link(rel="stylesheet", href="print.css", media="print")
body
main
script(src="vendors.js")
script(src="templates.js")
script(src="application.js")

your project is 7 files.

Usage

stassets is built as an express middleware. With the default project layout, the easiest server looks like this:

varexpress=require('express')varapp=express();varstasset=require('stasset')app.use(stasset({// The client directory is relative to this app.js fileroot: __dirname+"/client"// My vendors are loaded with bower, which is a directory up from here.vendors: {prefix: __dirname+"/../bower_components",// These files will be concatenated in order.// All this uses is angular and bootstrap, but these can grow as large// as you need.js: ['angular/angular.js'],css: ['bootstrap/dist/css/*']}}));app.listen(8989);

Recommended Layout

Group your code by component. It looks like this:

.
├── Gruntfile.coffee
├── index.jade
├── main
│ ├── all.styl
│ ├── footer
│ │ ├── footer-directive.coffee
│ │ ├── footer-template.jade
│ │ └── footer_test.coffee
│ ├── login
│ │ ├── login-all.styl
│ │ ├── login-directive.coffee
│ │ ├── login-template.jade
│ │ └── login_test.coffee
│ ├── main.coffee
│ ├── nav
│ │ ├── nav-directive.coffee
│ │ ├── nav-template.jade
│ │ └── nav_test.coffee
│ ├── main-print.styl
│ ├── main-screen.styl
│ └── main_test.coffee
├── scavenge
│ ├── gradebook
│ │ ├── gradebook-directive.coffee
│ │ ├── gradebook-service.coffee
│ │ ├── gradebook-service_mock.coffee
│ │ ├── gradebook-service_test.coffee
│ │ └── gradebook-template.jade
│ ├── hunts
│ │ ├── hunts-all.styl
│ │ ├── hunts-directive.coffee
│ │ ├── hunts-directive_test.coffee
│ │ ├── edit
│ │ │ ├── hunts-edit-directive.coffee
│ │ │ ├── hunts-edit-template.jade
│ │ │ └── hunts-edit_test.coffee
│ │ ├── hunts-service.coffee
│ │ ├── hunts-service_mock.coffee
│ │ ├── hunts-service_test.coffee
│ │ └── hunts-template.jade
│ ├── leaders
│ │ ├── leaders-all.styl
│ │ ├── leaders-directive.coffee
│ │ ├── leaders-template.jade
│ │ └── leaders_test.coffee
│ ├── students
│ │ ├── students-directive.coffee
│ │ ├── students-screen.styl
│ │ ├── students-service.coffee
│ │ ├── students-template.jade
│ │ └── students_test.coffee
│ └── submit
│ ├── submit-controller.coffee
│ ├── submit-controller_test.coffee
│ ├── submit-directive.coffee
│ ├── submit-directive_test.coffee
│ ├── grading
│ │ ├── submit-grading-controller.coffee
│ │ ├── submit-grading-directive.coffee
│ │ ├── submit-grading-screen.styl
│ │ └── submit-grading-template.jade
│ ├── submit-screen.styl
│ ├── submit-service.coffee
│ ├── submit-service_mock.coffee
│ ├── submit-service_test.coffee
│ └── submit-template.jade
├── stylus
│ └── definitions
│ ├── mixins.styl
│ └── variables.styl
└── util
├── fileInput
│ ├── fileInput-directive.coffee
│ ├── fileInput-service.coffee
│ └── fileInput-test.coffee
└── thsort
├── thsort-directive.coffee
├── thsort-screen.styl
└── thsort-template.jade

This is the client (in browser, Angular) codebase for a medium sized project, that manages a gradebook of student programming submissions. Notice that the controllers, templates, and tests are all next to one another. Don't drive five directories up and three over to get to a file for the same component. That's just crazy.

Stassets understands this directory layout, but can be configured to any other layout.

This is in line with current best practices for AngularJS.

Cascading File System

stassets has the concept of a Cascading File System. By creating a similar directory structure in several root directories, stassets users can quickly and easily implement a themeing or plugin system. To generate a cascading file system, stassets joins a list of root directories with a set of file patterns. Files in each root directory matching a pattern are joined, with files in higher priority root directories overwriting those with lower priority.

Configuration

WIP These configuration options are used to extend and customize at various places. Until 1.0, these may change subtly. They will not be stable until 1.0.

root

Required. String or Array. Specifies the cascading search order for watched files. Any file matching the same path in a later root directory will override any files at that path in a prior directory. Especially useful for creating themed systems.

./index.coffee:11: @config.root = [@config.root] unless @config.root instanceof Array

livereload

Optional. Boolean false or Object. Configure a livereload server. If not present, uses tiny-lr's default settings. If false, completely disable Live Reload. Otherwise, is passed as-is to tiny-lr's constructor.

./index.coffee:28: unless @config.livereload is no
./index.coffee:29: @livereload = new LR @config.livereload

scripts

Configure application script settings.

types

Optional. Array of script filename types. Files within the root folders that have a name matching *{type}.{ScriptTypes} will be loaded, in order defined in the array, to the application.js bundle. Type extensions are determined based on registered filetype handlers in ScriptWatcher.renderers[handler]. Default type list is ['main'].

./Watchers/Script.coffee:16: @config.scripts.types = @config.scripts.types || [

compress

Optional. Boolean to run bundled application.js through Uglify.

./Watchers/Script.coffee:63: res @minify res if @config.scripts.compress

styles

./Watchers/Style/Style.coffee:40: if @config.vendors?.stylus?
./Watchers/Style/Style.coffee:41: @config.vendors.stylus.map (_1)=>
./Watchers/Style/Style.coffee:42: @config.vendors.prefix + '/' + _1
./Watchers/Style/Style.coffee:48: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/variables")
./Watchers/Style/Style.coffee:49: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/mixins")

templates

Optional. Object configuring template rendering options.

baseModule

Optional string. If present, will prefix all template module names with baseModule.

./Watchers/Template.coffee:26: if moduleRoot = @config.templates.baseModule

vendors

vendors.prefix

./Watchers/Vendor/Vendor.coffee:15: @config.vendors or=
./Watchers/Vendor/Vendor.coffee:18: @config.vendors.prefix or= './'
./Watchers/Vendor/Vendor.coffee:19: unless @config.vendors.prefix.length? and @config.vendors.prefix.map?
./Watchers/Vendor/Vendor.coffee:20: @config.vendors.prefix = [@config.vendors.prefix]
./Watchers/Vendor/Vendor.coffee:22: @config.root = @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:23: @config.noRoot = true
./Watchers/Vendor/Vendor.coffee:30: for root in @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:40: smResolvedPath = Path.join @config.vendors.prefix, smPath

vendors.js

vendors.jsMaps

./Watchers/Vendor/Script.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Script.coffee:8: @config.vendors.js or= []
./Watchers/Vendor/Script.coffee:9: @config.vendors.jsMaps or= []
./Watchers/Vendor/Script.coffee:12: pattern: -> super @config.vendors.js
./Watchers/Vendor/Script.coffee:13: getMaps: -> @config.vendors.jsMaps

vendors.css

vendors.cssMaps

./Watchers/Vendor/Style.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Style.coffee:8: @config.vendors.css or= []
./Watchers/Vendor/Style.coffee:9: @config.vendors.cssMaps or= []
./Watchers/Vendor/Style.coffee:12: pattern: -> super @config.vendors.css
./Watchers/Vendor/Style.coffee:13: getMaps: -> @config.vendors.cssMaps

Changelog

  • 0.3.152015-06-15 Use better HTML minifier.
  • 0.3.142015-02-05 Fix bug with windows pathing outputting wrong.
  • 0.3.122015-02-02 Fix what was sort of a bug but is apparent as definitely a bug in Coffeescript 1.9
  • 0.3.112015-01-09 Bumped all outdated dependencies.
  • 0.3.102015-01-09 Bumped sane dependency to 1.0.0 (should be more stable).
  • 0.3.92014-12-31TemplateWatcher has new improved & better naming algorithm.
  • 0.3.82014-12-30this.meta to only pass fs.stats to render. Exposes Constructors.
  • 0.3.72014-12-29 Template js injection is more generic.
  • 0.3.62014-12-03 Streamline and improve sourcemap handling.
  • 0.3.52014-11-17 Only emit one error, when a vendor file is unavailable.
  • 0.3.42014-11-10 Back on track with a sane build and changelog.
  • 0.2.212014-11-01 Assets accept module prefix in file name.
  • 0.2.202014-10-28 Handle errors in generated sourcemaps.
  • 0.2.192014-10-26 Generate SourceMaps for unsourcemapped vendors.
  • 0.2.182014-10-17 Jade rendering issue.
  • 0.2.16, 172014-10-17 Less CSS compiler and vanilla HTML compiler.
  • 0.2.152014-10-06 Better reporting syntax errors.
  • 0.2.142014-09-11 Documentation pass (13) & Bugfix (14).
  • 0.2.122014-09-07 [debug][https://www.npmjs.org/package/debug] for logs.
  • 0.2.112014-09-05 Bug fixes. See commit log.
  • 0.2.72014-08-20 Sourcemaps for Stylus files.
  • 0.2.62014-08-12 Many small bugfixes in .2 through .6.
  • 0.2.12014-07-21 Replaced Gaze with Sane.
  • 0.2.02014-07-19 Implements Cascading File System.
  • 0.1.42014-06-16 Includes Grunt task to save compiled assets to disk, for pure static server (also great for tests). This is likely to move to grunt-stassets in the very near future!
  • 0.12014-06-12 Understands the basic project structure. Works great for rapid development.

About

Static Asset Compiling Express Middleware

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

stassets

A Static Asset Compiler


Compiling is so blase. Let it just happen.

Stassets is an express middleware for keeping your browser code up to date and ready to serve at a moment's notice. It watches your client directory structure, and performs the build steps in memory. When you ask for your files, they've already been compiled. Life is easy.

To start using an express server with stassets already configured, you should use Rupert.

stassets also minimizes the number of files you will transfer - it breaks the project into

.
├── index.html
├── application.js
├── templates.js
├── all.css
├── print.css
├── screen.css
├── vendors.css
└── vendors.js

And with a basic index.jade looking like

doctype html
html(ng-app="stassets.main")
head
title Test Fixture
link(rel="stylesheet", href="vendors.css")
link(rel="stylesheet", href="all.css")
link(rel="stylesheet", href="screen.css", media="screen")
link(rel="stylesheet", href="print.css", media="print")
body
main
script(src="vendors.js")
script(src="templates.js")
script(src="application.js")

your project is 7 files.

Usage

stassets is built as an express middleware. With the default project layout, the easiest server looks like this:

varexpress=require('express')varapp=express();varstasset=require('stasset')app.use(stasset({// The client directory is relative to this app.js fileroot: __dirname+"/client"// My vendors are loaded with bower, which is a directory up from here.vendors: {prefix: __dirname+"/../bower_components",// These files will be concatenated in order.// All this uses is angular and bootstrap, but these can grow as large// as you need.js: ['angular/angular.js'],css: ['bootstrap/dist/css/*']}}));app.listen(8989);

Recommended Layout

Group your code by component. It looks like this:

.
├── Gruntfile.coffee
├── index.jade
├── main
│ ├── all.styl
│ ├── footer
│ │ ├── footer-directive.coffee
│ │ ├── footer-template.jade
│ │ └── footer_test.coffee
│ ├── login
│ │ ├── login-all.styl
│ │ ├── login-directive.coffee
│ │ ├── login-template.jade
│ │ └── login_test.coffee
│ ├── main.coffee
│ ├── nav
│ │ ├── nav-directive.coffee
│ │ ├── nav-template.jade
│ │ └── nav_test.coffee
│ ├── main-print.styl
│ ├── main-screen.styl
│ └── main_test.coffee
├── scavenge
│ ├── gradebook
│ │ ├── gradebook-directive.coffee
│ │ ├── gradebook-service.coffee
│ │ ├── gradebook-service_mock.coffee
│ │ ├── gradebook-service_test.coffee
│ │ └── gradebook-template.jade
│ ├── hunts
│ │ ├── hunts-all.styl
│ │ ├── hunts-directive.coffee
│ │ ├── hunts-directive_test.coffee
│ │ ├── edit
│ │ │ ├── hunts-edit-directive.coffee
│ │ │ ├── hunts-edit-template.jade
│ │ │ └── hunts-edit_test.coffee
│ │ ├── hunts-service.coffee
│ │ ├── hunts-service_mock.coffee
│ │ ├── hunts-service_test.coffee
│ │ └── hunts-template.jade
│ ├── leaders
│ │ ├── leaders-all.styl
│ │ ├── leaders-directive.coffee
│ │ ├── leaders-template.jade
│ │ └── leaders_test.coffee
│ ├── students
│ │ ├── students-directive.coffee
│ │ ├── students-screen.styl
│ │ ├── students-service.coffee
│ │ ├── students-template.jade
│ │ └── students_test.coffee
│ └── submit
│ ├── submit-controller.coffee
│ ├── submit-controller_test.coffee
│ ├── submit-directive.coffee
│ ├── submit-directive_test.coffee
│ ├── grading
│ │ ├── submit-grading-controller.coffee
│ │ ├── submit-grading-directive.coffee
│ │ ├── submit-grading-screen.styl
│ │ └── submit-grading-template.jade
│ ├── submit-screen.styl
│ ├── submit-service.coffee
│ ├── submit-service_mock.coffee
│ ├── submit-service_test.coffee
│ └── submit-template.jade
├── stylus
│ └── definitions
│ ├── mixins.styl
│ └── variables.styl
└── util
├── fileInput
│ ├── fileInput-directive.coffee
│ ├── fileInput-service.coffee
│ └── fileInput-test.coffee
└── thsort
├── thsort-directive.coffee
├── thsort-screen.styl
└── thsort-template.jade

This is the client (in browser, Angular) codebase for a medium sized project, that manages a gradebook of student programming submissions. Notice that the controllers, templates, and tests are all next to one another. Don't drive five directories up and three over to get to a file for the same component. That's just crazy.

Stassets understands this directory layout, but can be configured to any other layout.

This is in line with current best practices for AngularJS.

Cascading File System

stassets has the concept of a Cascading File System. By creating a similar directory structure in several root directories, stassets users can quickly and easily implement a themeing or plugin system. To generate a cascading file system, stassets joins a list of root directories with a set of file patterns. Files in each root directory matching a pattern are joined, with files in higher priority root directories overwriting those with lower priority.

Configuration

WIP These configuration options are used to extend and customize at various places. Until 1.0, these may change subtly. They will not be stable until 1.0.

root

Required. String or Array. Specifies the cascading search order for watched files. Any file matching the same path in a later root directory will override any files at that path in a prior directory. Especially useful for creating themed systems.

./index.coffee:11: @config.root = [@config.root] unless @config.root instanceof Array

livereload

Optional. Boolean false or Object. Configure a livereload server. If not present, uses tiny-lr's default settings. If false, completely disable Live Reload. Otherwise, is passed as-is to tiny-lr's constructor.

./index.coffee:28: unless @config.livereload is no
./index.coffee:29: @livereload = new LR @config.livereload

scripts

Configure application script settings.

types

Optional. Array of script filename types. Files within the root folders that have a name matching *{type}.{ScriptTypes} will be loaded, in order defined in the array, to the application.js bundle. Type extensions are determined based on registered filetype handlers in ScriptWatcher.renderers[handler]. Default type list is ['main'].

./Watchers/Script.coffee:16: @config.scripts.types = @config.scripts.types || [

compress

Optional. Boolean to run bundled application.js through Uglify.

./Watchers/Script.coffee:63: res @minify res if @config.scripts.compress

styles

./Watchers/Style/Style.coffee:40: if @config.vendors?.stylus?
./Watchers/Style/Style.coffee:41: @config.vendors.stylus.map (_1)=>
./Watchers/Style/Style.coffee:42: @config.vendors.prefix + '/' + _1
./Watchers/Style/Style.coffee:48: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/variables")
./Watchers/Style/Style.coffee:49: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/mixins")

templates

Optional. Object configuring template rendering options.

baseModule

Optional string. If present, will prefix all template module names with baseModule.

./Watchers/Template.coffee:26: if moduleRoot = @config.templates.baseModule

vendors

vendors.prefix

./Watchers/Vendor/Vendor.coffee:15: @config.vendors or=
./Watchers/Vendor/Vendor.coffee:18: @config.vendors.prefix or= './'
./Watchers/Vendor/Vendor.coffee:19: unless @config.vendors.prefix.length? and @config.vendors.prefix.map?
./Watchers/Vendor/Vendor.coffee:20: @config.vendors.prefix = [@config.vendors.prefix]
./Watchers/Vendor/Vendor.coffee:22: @config.root = @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:23: @config.noRoot = true
./Watchers/Vendor/Vendor.coffee:30: for root in @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:40: smResolvedPath = Path.join @config.vendors.prefix, smPath

vendors.js

vendors.jsMaps

./Watchers/Vendor/Script.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Script.coffee:8: @config.vendors.js or= []
./Watchers/Vendor/Script.coffee:9: @config.vendors.jsMaps or= []
./Watchers/Vendor/Script.coffee:12: pattern: -> super @config.vendors.js
./Watchers/Vendor/Script.coffee:13: getMaps: -> @config.vendors.jsMaps

vendors.css

vendors.cssMaps

./Watchers/Vendor/Style.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Style.coffee:8: @config.vendors.css or= []
./Watchers/Vendor/Style.coffee:9: @config.vendors.cssMaps or= []
./Watchers/Vendor/Style.coffee:12: pattern: -> super @config.vendors.css
./Watchers/Vendor/Style.coffee:13: getMaps: -> @config.vendors.cssMaps

Changelog

  • 0.3.152015-06-15 Use better HTML minifier.
  • 0.3.142015-02-05 Fix bug with windows pathing outputting wrong.
  • 0.3.122015-02-02 Fix what was sort of a bug but is apparent as definitely a bug in Coffeescript 1.9
  • 0.3.112015-01-09 Bumped all outdated dependencies.
  • 0.3.102015-01-09 Bumped sane dependency to 1.0.0 (should be more stable).
  • 0.3.92014-12-31TemplateWatcher has new improved & better naming algorithm.
  • 0.3.82014-12-30this.meta to only pass fs.stats to render. Exposes Constructors.
  • 0.3.72014-12-29 Template js injection is more generic.
  • 0.3.62014-12-03 Streamline and improve sourcemap handling.
  • 0.3.52014-11-17 Only emit one error, when a vendor file is unavailable.
  • 0.3.42014-11-10 Back on track with a sane build and changelog.
  • 0.2.212014-11-01 Assets accept module prefix in file name.
  • 0.2.202014-10-28 Handle errors in generated sourcemaps.
  • 0.2.192014-10-26 Generate SourceMaps for unsourcemapped vendors.
  • 0.2.182014-10-17 Jade rendering issue.
  • 0.2.16, 172014-10-17 Less CSS compiler and vanilla HTML compiler.
  • 0.2.152014-10-06 Better reporting syntax errors.
  • 0.2.142014-09-11 Documentation pass (13) & Bugfix (14).
  • 0.2.122014-09-07 [debug][https://www.npmjs.org/package/debug] for logs.
  • 0.2.112014-09-05 Bug fixes. See commit log.
  • 0.2.72014-08-20 Sourcemaps for Stylus files.
  • 0.2.62014-08-12 Many small bugfixes in .2 through .6.
  • 0.2.12014-07-21 Replaced Gaze with Sane.
  • 0.2.02014-07-19 Implements Cascading File System.
  • 0.1.42014-06-16 Includes Grunt task to save compiled assets to disk, for pure static server (also great for tests). This is likely to move to grunt-stassets in the very near future!
  • 0.12014-06-12 Understands the basic project structure. Works great for rapid development.

About

Static Asset Compiling Express Middleware

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

stassets

A Static Asset Compiler


Compiling is so blase. Let it just happen.

Stassets is an express middleware for keeping your browser code up to date and ready to serve at a moment's notice. It watches your client directory structure, and performs the build steps in memory. When you ask for your files, they've already been compiled. Life is easy.

To start using an express server with stassets already configured, you should use Rupert.

stassets also minimizes the number of files you will transfer - it breaks the project into

.
├── index.html
├── application.js
├── templates.js
├── all.css
├── print.css
├── screen.css
├── vendors.css
└── vendors.js

And with a basic index.jade looking like

doctype html
html(ng-app="stassets.main")
head
title Test Fixture
link(rel="stylesheet", href="vendors.css")
link(rel="stylesheet", href="all.css")
link(rel="stylesheet", href="screen.css", media="screen")
link(rel="stylesheet", href="print.css", media="print")
body
main
script(src="vendors.js")
script(src="templates.js")
script(src="application.js")

your project is 7 files.

Usage

stassets is built as an express middleware. With the default project layout, the easiest server looks like this:

varexpress=require('express')varapp=express();varstasset=require('stasset')app.use(stasset({// The client directory is relative to this app.js fileroot: __dirname+"/client"// My vendors are loaded with bower, which is a directory up from here.vendors: {prefix: __dirname+"/../bower_components",// These files will be concatenated in order.// All this uses is angular and bootstrap, but these can grow as large// as you need.js: ['angular/angular.js'],css: ['bootstrap/dist/css/*']}}));app.listen(8989);

Recommended Layout

Group your code by component. It looks like this:

.
├── Gruntfile.coffee
├── index.jade
├── main
│ ├── all.styl
│ ├── footer
│ │ ├── footer-directive.coffee
│ │ ├── footer-template.jade
│ │ └── footer_test.coffee
│ ├── login
│ │ ├── login-all.styl
│ │ ├── login-directive.coffee
│ │ ├── login-template.jade
│ │ └── login_test.coffee
│ ├── main.coffee
│ ├── nav
│ │ ├── nav-directive.coffee
│ │ ├── nav-template.jade
│ │ └── nav_test.coffee
│ ├── main-print.styl
│ ├── main-screen.styl
│ └── main_test.coffee
├── scavenge
│ ├── gradebook
│ │ ├── gradebook-directive.coffee
│ │ ├── gradebook-service.coffee
│ │ ├── gradebook-service_mock.coffee
│ │ ├── gradebook-service_test.coffee
│ │ └── gradebook-template.jade
│ ├── hunts
│ │ ├── hunts-all.styl
│ │ ├── hunts-directive.coffee
│ │ ├── hunts-directive_test.coffee
│ │ ├── edit
│ │ │ ├── hunts-edit-directive.coffee
│ │ │ ├── hunts-edit-template.jade
│ │ │ └── hunts-edit_test.coffee
│ │ ├── hunts-service.coffee
│ │ ├── hunts-service_mock.coffee
│ │ ├── hunts-service_test.coffee
│ │ └── hunts-template.jade
│ ├── leaders
│ │ ├── leaders-all.styl
│ │ ├── leaders-directive.coffee
│ │ ├── leaders-template.jade
│ │ └── leaders_test.coffee
│ ├── students
│ │ ├── students-directive.coffee
│ │ ├── students-screen.styl
│ │ ├── students-service.coffee
│ │ ├── students-template.jade
│ │ └── students_test.coffee
│ └── submit
│ ├── submit-controller.coffee
│ ├── submit-controller_test.coffee
│ ├── submit-directive.coffee
│ ├── submit-directive_test.coffee
│ ├── grading
│ │ ├── submit-grading-controller.coffee
│ │ ├── submit-grading-directive.coffee
│ │ ├── submit-grading-screen.styl
│ │ └── submit-grading-template.jade
│ ├── submit-screen.styl
│ ├── submit-service.coffee
│ ├── submit-service_mock.coffee
│ ├── submit-service_test.coffee
│ └── submit-template.jade
├── stylus
│ └── definitions
│ ├── mixins.styl
│ └── variables.styl
└── util
├── fileInput
│ ├── fileInput-directive.coffee
│ ├── fileInput-service.coffee
│ └── fileInput-test.coffee
└── thsort
├── thsort-directive.coffee
├── thsort-screen.styl
└── thsort-template.jade

This is the client (in browser, Angular) codebase for a medium sized project, that manages a gradebook of student programming submissions. Notice that the controllers, templates, and tests are all next to one another. Don't drive five directories up and three over to get to a file for the same component. That's just crazy.

Stassets understands this directory layout, but can be configured to any other layout.

This is in line with current best practices for AngularJS.

Cascading File System

stassets has the concept of a Cascading File System. By creating a similar directory structure in several root directories, stassets users can quickly and easily implement a themeing or plugin system. To generate a cascading file system, stassets joins a list of root directories with a set of file patterns. Files in each root directory matching a pattern are joined, with files in higher priority root directories overwriting those with lower priority.

Configuration

WIP These configuration options are used to extend and customize at various places. Until 1.0, these may change subtly. They will not be stable until 1.0.

root

Required. String or Array. Specifies the cascading search order for watched files. Any file matching the same path in a later root directory will override any files at that path in a prior directory. Especially useful for creating themed systems.

./index.coffee:11: @config.root = [@config.root] unless @config.root instanceof Array

livereload

Optional. Boolean false or Object. Configure a livereload server. If not present, uses tiny-lr's default settings. If false, completely disable Live Reload. Otherwise, is passed as-is to tiny-lr's constructor.

./index.coffee:28: unless @config.livereload is no
./index.coffee:29: @livereload = new LR @config.livereload

scripts

Configure application script settings.

types

Optional. Array of script filename types. Files within the root folders that have a name matching *{type}.{ScriptTypes} will be loaded, in order defined in the array, to the application.js bundle. Type extensions are determined based on registered filetype handlers in ScriptWatcher.renderers[handler]. Default type list is ['main'].

./Watchers/Script.coffee:16: @config.scripts.types = @config.scripts.types || [

compress

Optional. Boolean to run bundled application.js through Uglify.

./Watchers/Script.coffee:63: res @minify res if @config.scripts.compress

styles

./Watchers/Style/Style.coffee:40: if @config.vendors?.stylus?
./Watchers/Style/Style.coffee:41: @config.vendors.stylus.map (_1)=>
./Watchers/Style/Style.coffee:42: @config.vendors.prefix + '/' + _1
./Watchers/Style/Style.coffee:48: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/variables")
./Watchers/Style/Style.coffee:49: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/mixins")

templates

Optional. Object configuring template rendering options.

baseModule

Optional string. If present, will prefix all template module names with baseModule.

./Watchers/Template.coffee:26: if moduleRoot = @config.templates.baseModule

vendors

vendors.prefix

./Watchers/Vendor/Vendor.coffee:15: @config.vendors or=
./Watchers/Vendor/Vendor.coffee:18: @config.vendors.prefix or= './'
./Watchers/Vendor/Vendor.coffee:19: unless @config.vendors.prefix.length? and @config.vendors.prefix.map?
./Watchers/Vendor/Vendor.coffee:20: @config.vendors.prefix = [@config.vendors.prefix]
./Watchers/Vendor/Vendor.coffee:22: @config.root = @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:23: @config.noRoot = true
./Watchers/Vendor/Vendor.coffee:30: for root in @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:40: smResolvedPath = Path.join @config.vendors.prefix, smPath

vendors.js

vendors.jsMaps

./Watchers/Vendor/Script.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Script.coffee:8: @config.vendors.js or= []
./Watchers/Vendor/Script.coffee:9: @config.vendors.jsMaps or= []
./Watchers/Vendor/Script.coffee:12: pattern: -> super @config.vendors.js
./Watchers/Vendor/Script.coffee:13: getMaps: -> @config.vendors.jsMaps

vendors.css

vendors.cssMaps

./Watchers/Vendor/Style.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Style.coffee:8: @config.vendors.css or= []
./Watchers/Vendor/Style.coffee:9: @config.vendors.cssMaps or= []
./Watchers/Vendor/Style.coffee:12: pattern: -> super @config.vendors.css
./Watchers/Vendor/Style.coffee:13: getMaps: -> @config.vendors.cssMaps

Changelog

  • 0.3.152015-06-15 Use better HTML minifier.
  • 0.3.142015-02-05 Fix bug with windows pathing outputting wrong.
  • 0.3.122015-02-02 Fix what was sort of a bug but is apparent as definitely a bug in Coffeescript 1.9
  • 0.3.112015-01-09 Bumped all outdated dependencies.
  • 0.3.102015-01-09 Bumped sane dependency to 1.0.0 (should be more stable).
  • 0.3.92014-12-31TemplateWatcher has new improved & better naming algorithm.
  • 0.3.82014-12-30this.meta to only pass fs.stats to render. Exposes Constructors.
  • 0.3.72014-12-29 Template js injection is more generic.
  • 0.3.62014-12-03 Streamline and improve sourcemap handling.
  • 0.3.52014-11-17 Only emit one error, when a vendor file is unavailable.
  • 0.3.42014-11-10 Back on track with a sane build and changelog.
  • 0.2.212014-11-01 Assets accept module prefix in file name.
  • 0.2.202014-10-28 Handle errors in generated sourcemaps.
  • 0.2.192014-10-26 Generate SourceMaps for unsourcemapped vendors.
  • 0.2.182014-10-17 Jade rendering issue.
  • 0.2.16, 172014-10-17 Less CSS compiler and vanilla HTML compiler.
  • 0.2.152014-10-06 Better reporting syntax errors.
  • 0.2.142014-09-11 Documentation pass (13) & Bugfix (14).
  • 0.2.122014-09-07 [debug][https://www.npmjs.org/package/debug] for logs.
  • 0.2.112014-09-05 Bug fixes. See commit log.
  • 0.2.72014-08-20 Sourcemaps for Stylus files.
  • 0.2.62014-08-12 Many small bugfixes in .2 through .6.
  • 0.2.12014-07-21 Replaced Gaze with Sane.
  • 0.2.02014-07-19 Implements Cascading File System.
  • 0.1.42014-06-16 Includes Grunt task to save compiled assets to disk, for pure static server (also great for tests). This is likely to move to grunt-stassets in the very near future!
  • 0.12014-06-12 Understands the basic project structure. Works great for rapid development.

About

Static Asset Compiling Express Middleware

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

stassets

A Static Asset Compiler


Compiling is so blase. Let it just happen.

Stassets is an express middleware for keeping your browser code up to date and ready to serve at a moment's notice. It watches your client directory structure, and performs the build steps in memory. When you ask for your files, they've already been compiled. Life is easy.

To start using an express server with stassets already configured, you should use Rupert.

stassets also minimizes the number of files you will transfer - it breaks the project into

.
├── index.html
├── application.js
├── templates.js
├── all.css
├── print.css
├── screen.css
├── vendors.css
└── vendors.js

And with a basic index.jade looking like

doctype html
html(ng-app="stassets.main")
head
title Test Fixture
link(rel="stylesheet", href="vendors.css")
link(rel="stylesheet", href="all.css")
link(rel="stylesheet", href="screen.css", media="screen")
link(rel="stylesheet", href="print.css", media="print")
body
main
script(src="vendors.js")
script(src="templates.js")
script(src="application.js")

your project is 7 files.

Usage

stassets is built as an express middleware. With the default project layout, the easiest server looks like this:

varexpress=require('express')varapp=express();varstasset=require('stasset')app.use(stasset({// The client directory is relative to this app.js fileroot: __dirname+"/client"// My vendors are loaded with bower, which is a directory up from here.vendors: {prefix: __dirname+"/../bower_components",// These files will be concatenated in order.// All this uses is angular and bootstrap, but these can grow as large// as you need.js: ['angular/angular.js'],css: ['bootstrap/dist/css/*']}}));app.listen(8989);

Recommended Layout

Group your code by component. It looks like this:

.
├── Gruntfile.coffee
├── index.jade
├── main
│ ├── all.styl
│ ├── footer
│ │ ├── footer-directive.coffee
│ │ ├── footer-template.jade
│ │ └── footer_test.coffee
│ ├── login
│ │ ├── login-all.styl
│ │ ├── login-directive.coffee
│ │ ├── login-template.jade
│ │ └── login_test.coffee
│ ├── main.coffee
│ ├── nav
│ │ ├── nav-directive.coffee
│ │ ├── nav-template.jade
│ │ └── nav_test.coffee
│ ├── main-print.styl
│ ├── main-screen.styl
│ └── main_test.coffee
├── scavenge
│ ├── gradebook
│ │ ├── gradebook-directive.coffee
│ │ ├── gradebook-service.coffee
│ │ ├── gradebook-service_mock.coffee
│ │ ├── gradebook-service_test.coffee
│ │ └── gradebook-template.jade
│ ├── hunts
│ │ ├── hunts-all.styl
│ │ ├── hunts-directive.coffee
│ │ ├── hunts-directive_test.coffee
│ │ ├── edit
│ │ │ ├── hunts-edit-directive.coffee
│ │ │ ├── hunts-edit-template.jade
│ │ │ └── hunts-edit_test.coffee
│ │ ├── hunts-service.coffee
│ │ ├── hunts-service_mock.coffee
│ │ ├── hunts-service_test.coffee
│ │ └── hunts-template.jade
│ ├── leaders
│ │ ├── leaders-all.styl
│ │ ├── leaders-directive.coffee
│ │ ├── leaders-template.jade
│ │ └── leaders_test.coffee
│ ├── students
│ │ ├── students-directive.coffee
│ │ ├── students-screen.styl
│ │ ├── students-service.coffee
│ │ ├── students-template.jade
│ │ └── students_test.coffee
│ └── submit
│ ├── submit-controller.coffee
│ ├── submit-controller_test.coffee
│ ├── submit-directive.coffee
│ ├── submit-directive_test.coffee
│ ├── grading
│ │ ├── submit-grading-controller.coffee
│ │ ├── submit-grading-directive.coffee
│ │ ├── submit-grading-screen.styl
│ │ └── submit-grading-template.jade
│ ├── submit-screen.styl
│ ├── submit-service.coffee
│ ├── submit-service_mock.coffee
│ ├── submit-service_test.coffee
│ └── submit-template.jade
├── stylus
│ └── definitions
│ ├── mixins.styl
│ └── variables.styl
└── util
├── fileInput
│ ├── fileInput-directive.coffee
│ ├── fileInput-service.coffee
│ └── fileInput-test.coffee
└── thsort
├── thsort-directive.coffee
├── thsort-screen.styl
└── thsort-template.jade

This is the client (in browser, Angular) codebase for a medium sized project, that manages a gradebook of student programming submissions. Notice that the controllers, templates, and tests are all next to one another. Don't drive five directories up and three over to get to a file for the same component. That's just crazy.

Stassets understands this directory layout, but can be configured to any other layout.

This is in line with current best practices for AngularJS.

Cascading File System

stassets has the concept of a Cascading File System. By creating a similar directory structure in several root directories, stassets users can quickly and easily implement a themeing or plugin system. To generate a cascading file system, stassets joins a list of root directories with a set of file patterns. Files in each root directory matching a pattern are joined, with files in higher priority root directories overwriting those with lower priority.

Configuration

WIP These configuration options are used to extend and customize at various places. Until 1.0, these may change subtly. They will not be stable until 1.0.

root

Required. String or Array. Specifies the cascading search order for watched files. Any file matching the same path in a later root directory will override any files at that path in a prior directory. Especially useful for creating themed systems.

./index.coffee:11: @config.root = [@config.root] unless @config.root instanceof Array

livereload

Optional. Boolean false or Object. Configure a livereload server. If not present, uses tiny-lr's default settings. If false, completely disable Live Reload. Otherwise, is passed as-is to tiny-lr's constructor.

./index.coffee:28: unless @config.livereload is no
./index.coffee:29: @livereload = new LR @config.livereload

scripts

Configure application script settings.

types

Optional. Array of script filename types. Files within the root folders that have a name matching *{type}.{ScriptTypes} will be loaded, in order defined in the array, to the application.js bundle. Type extensions are determined based on registered filetype handlers in ScriptWatcher.renderers[handler]. Default type list is ['main'].

./Watchers/Script.coffee:16: @config.scripts.types = @config.scripts.types || [

compress

Optional. Boolean to run bundled application.js through Uglify.

./Watchers/Script.coffee:63: res @minify res if @config.scripts.compress

styles

./Watchers/Style/Style.coffee:40: if @config.vendors?.stylus?
./Watchers/Style/Style.coffee:41: @config.vendors.stylus.map (_1)=>
./Watchers/Style/Style.coffee:42: @config.vendors.prefix + '/' + _1
./Watchers/Style/Style.coffee:48: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/variables")
./Watchers/Style/Style.coffee:49: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/mixins")

templates

Optional. Object configuring template rendering options.

baseModule

Optional string. If present, will prefix all template module names with baseModule.

./Watchers/Template.coffee:26: if moduleRoot = @config.templates.baseModule

vendors

vendors.prefix

./Watchers/Vendor/Vendor.coffee:15: @config.vendors or=
./Watchers/Vendor/Vendor.coffee:18: @config.vendors.prefix or= './'
./Watchers/Vendor/Vendor.coffee:19: unless @config.vendors.prefix.length? and @config.vendors.prefix.map?
./Watchers/Vendor/Vendor.coffee:20: @config.vendors.prefix = [@config.vendors.prefix]
./Watchers/Vendor/Vendor.coffee:22: @config.root = @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:23: @config.noRoot = true
./Watchers/Vendor/Vendor.coffee:30: for root in @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:40: smResolvedPath = Path.join @config.vendors.prefix, smPath

vendors.js

vendors.jsMaps

./Watchers/Vendor/Script.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Script.coffee:8: @config.vendors.js or= []
./Watchers/Vendor/Script.coffee:9: @config.vendors.jsMaps or= []
./Watchers/Vendor/Script.coffee:12: pattern: -> super @config.vendors.js
./Watchers/Vendor/Script.coffee:13: getMaps: -> @config.vendors.jsMaps

vendors.css

vendors.cssMaps

./Watchers/Vendor/Style.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Style.coffee:8: @config.vendors.css or= []
./Watchers/Vendor/Style.coffee:9: @config.vendors.cssMaps or= []
./Watchers/Vendor/Style.coffee:12: pattern: -> super @config.vendors.css
./Watchers/Vendor/Style.coffee:13: getMaps: -> @config.vendors.cssMaps

Changelog

  • 0.3.152015-06-15 Use better HTML minifier.
  • 0.3.142015-02-05 Fix bug with windows pathing outputting wrong.
  • 0.3.122015-02-02 Fix what was sort of a bug but is apparent as definitely a bug in Coffeescript 1.9
  • 0.3.112015-01-09 Bumped all outdated dependencies.
  • 0.3.102015-01-09 Bumped sane dependency to 1.0.0 (should be more stable).
  • 0.3.92014-12-31TemplateWatcher has new improved & better naming algorithm.
  • 0.3.82014-12-30this.meta to only pass fs.stats to render. Exposes Constructors.
  • 0.3.72014-12-29 Template js injection is more generic.
  • 0.3.62014-12-03 Streamline and improve sourcemap handling.
  • 0.3.52014-11-17 Only emit one error, when a vendor file is unavailable.
  • 0.3.42014-11-10 Back on track with a sane build and changelog.
  • 0.2.212014-11-01 Assets accept module prefix in file name.
  • 0.2.202014-10-28 Handle errors in generated sourcemaps.
  • 0.2.192014-10-26 Generate SourceMaps for unsourcemapped vendors.
  • 0.2.182014-10-17 Jade rendering issue.
  • 0.2.16, 172014-10-17 Less CSS compiler and vanilla HTML compiler.
  • 0.2.152014-10-06 Better reporting syntax errors.
  • 0.2.142014-09-11 Documentation pass (13) & Bugfix (14).
  • 0.2.122014-09-07 [debug][https://www.npmjs.org/package/debug] for logs.
  • 0.2.112014-09-05 Bug fixes. See commit log.
  • 0.2.72014-08-20 Sourcemaps for Stylus files.
  • 0.2.62014-08-12 Many small bugfixes in .2 through .6.
  • 0.2.12014-07-21 Replaced Gaze with Sane.
  • 0.2.02014-07-19 Implements Cascading File System.
  • 0.1.42014-06-16 Includes Grunt task to save compiled assets to disk, for pure static server (also great for tests). This is likely to move to grunt-stassets in the very near future!
  • 0.12014-06-12 Understands the basic project structure. Works great for rapid development.

About

Static Asset Compiling Express Middleware

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

stassets

A Static Asset Compiler


Compiling is so blase. Let it just happen.

Stassets is an express middleware for keeping your browser code up to date and ready to serve at a moment's notice. It watches your client directory structure, and performs the build steps in memory. When you ask for your files, they've already been compiled. Life is easy.

To start using an express server with stassets already configured, you should use Rupert.

stassets also minimizes the number of files you will transfer - it breaks the project into

.
├── index.html
├── application.js
├── templates.js
├── all.css
├── print.css
├── screen.css
├── vendors.css
└── vendors.js

And with a basic index.jade looking like

doctype html
html(ng-app="stassets.main")
head
title Test Fixture
link(rel="stylesheet", href="vendors.css")
link(rel="stylesheet", href="all.css")
link(rel="stylesheet", href="screen.css", media="screen")
link(rel="stylesheet", href="print.css", media="print")
body
main
script(src="vendors.js")
script(src="templates.js")
script(src="application.js")

your project is 7 files.

Usage

stassets is built as an express middleware. With the default project layout, the easiest server looks like this:

varexpress=require('express')varapp=express();varstasset=require('stasset')app.use(stasset({// The client directory is relative to this app.js fileroot: __dirname+"/client"// My vendors are loaded with bower, which is a directory up from here.vendors: {prefix: __dirname+"/../bower_components",// These files will be concatenated in order.// All this uses is angular and bootstrap, but these can grow as large// as you need.js: ['angular/angular.js'],css: ['bootstrap/dist/css/*']}}));app.listen(8989);

Recommended Layout

Group your code by component. It looks like this:

.
├── Gruntfile.coffee
├── index.jade
├── main
│ ├── all.styl
│ ├── footer
│ │ ├── footer-directive.coffee
│ │ ├── footer-template.jade
│ │ └── footer_test.coffee
│ ├── login
│ │ ├── login-all.styl
│ │ ├── login-directive.coffee
│ │ ├── login-template.jade
│ │ └── login_test.coffee
│ ├── main.coffee
│ ├── nav
│ │ ├── nav-directive.coffee
│ │ ├── nav-template.jade
│ │ └── nav_test.coffee
│ ├── main-print.styl
│ ├── main-screen.styl
│ └── main_test.coffee
├── scavenge
│ ├── gradebook
│ │ ├── gradebook-directive.coffee
│ │ ├── gradebook-service.coffee
│ │ ├── gradebook-service_mock.coffee
│ │ ├── gradebook-service_test.coffee
│ │ └── gradebook-template.jade
│ ├── hunts
│ │ ├── hunts-all.styl
│ │ ├── hunts-directive.coffee
│ │ ├── hunts-directive_test.coffee
│ │ ├── edit
│ │ │ ├── hunts-edit-directive.coffee
│ │ │ ├── hunts-edit-template.jade
│ │ │ └── hunts-edit_test.coffee
│ │ ├── hunts-service.coffee
│ │ ├── hunts-service_mock.coffee
│ │ ├── hunts-service_test.coffee
│ │ └── hunts-template.jade
│ ├── leaders
│ │ ├── leaders-all.styl
│ │ ├── leaders-directive.coffee
│ │ ├── leaders-template.jade
│ │ └── leaders_test.coffee
│ ├── students
│ │ ├── students-directive.coffee
│ │ ├── students-screen.styl
│ │ ├── students-service.coffee
│ │ ├── students-template.jade
│ │ └── students_test.coffee
│ └── submit
│ ├── submit-controller.coffee
│ ├── submit-controller_test.coffee
│ ├── submit-directive.coffee
│ ├── submit-directive_test.coffee
│ ├── grading
│ │ ├── submit-grading-controller.coffee
│ │ ├── submit-grading-directive.coffee
│ │ ├── submit-grading-screen.styl
│ │ └── submit-grading-template.jade
│ ├── submit-screen.styl
│ ├── submit-service.coffee
│ ├── submit-service_mock.coffee
│ ├── submit-service_test.coffee
│ └── submit-template.jade
├── stylus
│ └── definitions
│ ├── mixins.styl
│ └── variables.styl
└── util
├── fileInput
│ ├── fileInput-directive.coffee
│ ├── fileInput-service.coffee
│ └── fileInput-test.coffee
└── thsort
├── thsort-directive.coffee
├── thsort-screen.styl
└── thsort-template.jade

This is the client (in browser, Angular) codebase for a medium sized project, that manages a gradebook of student programming submissions. Notice that the controllers, templates, and tests are all next to one another. Don't drive five directories up and three over to get to a file for the same component. That's just crazy.

Stassets understands this directory layout, but can be configured to any other layout.

This is in line with current best practices for AngularJS.

Cascading File System

stassets has the concept of a Cascading File System. By creating a similar directory structure in several root directories, stassets users can quickly and easily implement a themeing or plugin system. To generate a cascading file system, stassets joins a list of root directories with a set of file patterns. Files in each root directory matching a pattern are joined, with files in higher priority root directories overwriting those with lower priority.

Configuration

WIP These configuration options are used to extend and customize at various places. Until 1.0, these may change subtly. They will not be stable until 1.0.

root

Required. String or Array. Specifies the cascading search order for watched files. Any file matching the same path in a later root directory will override any files at that path in a prior directory. Especially useful for creating themed systems.

./index.coffee:11: @config.root = [@config.root] unless @config.root instanceof Array

livereload

Optional. Boolean false or Object. Configure a livereload server. If not present, uses tiny-lr's default settings. If false, completely disable Live Reload. Otherwise, is passed as-is to tiny-lr's constructor.

./index.coffee:28: unless @config.livereload is no
./index.coffee:29: @livereload = new LR @config.livereload

scripts

Configure application script settings.

types

Optional. Array of script filename types. Files within the root folders that have a name matching *{type}.{ScriptTypes} will be loaded, in order defined in the array, to the application.js bundle. Type extensions are determined based on registered filetype handlers in ScriptWatcher.renderers[handler]. Default type list is ['main'].

./Watchers/Script.coffee:16: @config.scripts.types = @config.scripts.types || [

compress

Optional. Boolean to run bundled application.js through Uglify.

./Watchers/Script.coffee:63: res @minify res if @config.scripts.compress

styles

./Watchers/Style/Style.coffee:40: if @config.vendors?.stylus?
./Watchers/Style/Style.coffee:41: @config.vendors.stylus.map (_1)=>
./Watchers/Style/Style.coffee:42: @config.vendors.prefix + '/' + _1
./Watchers/Style/Style.coffee:48: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/variables")
./Watchers/Style/Style.coffee:49: .concat(@config.root.map (_1)-> "#{_1}/stylus/definitions/mixins")

templates

Optional. Object configuring template rendering options.

baseModule

Optional string. If present, will prefix all template module names with baseModule.

./Watchers/Template.coffee:26: if moduleRoot = @config.templates.baseModule

vendors

vendors.prefix

./Watchers/Vendor/Vendor.coffee:15: @config.vendors or=
./Watchers/Vendor/Vendor.coffee:18: @config.vendors.prefix or= './'
./Watchers/Vendor/Vendor.coffee:19: unless @config.vendors.prefix.length? and @config.vendors.prefix.map?
./Watchers/Vendor/Vendor.coffee:20: @config.vendors.prefix = [@config.vendors.prefix]
./Watchers/Vendor/Vendor.coffee:22: @config.root = @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:23: @config.noRoot = true
./Watchers/Vendor/Vendor.coffee:30: for root in @config.vendors.prefix
./Watchers/Vendor/Vendor.coffee:40: smResolvedPath = Path.join @config.vendors.prefix, smPath

vendors.js

vendors.jsMaps

./Watchers/Vendor/Script.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Script.coffee:8: @config.vendors.js or= []
./Watchers/Vendor/Script.coffee:9: @config.vendors.jsMaps or= []
./Watchers/Vendor/Script.coffee:12: pattern: -> super @config.vendors.js
./Watchers/Vendor/Script.coffee:13: getMaps: -> @config.vendors.jsMaps

vendors.css

vendors.cssMaps

./Watchers/Vendor/Style.coffee:7: @config.vendors or= {}
./Watchers/Vendor/Style.coffee:8: @config.vendors.css or= []
./Watchers/Vendor/Style.coffee:9: @config.vendors.cssMaps or= []
./Watchers/Vendor/Style.coffee:12: pattern: -> super @config.vendors.css
./Watchers/Vendor/Style.coffee:13: getMaps: -> @config.vendors.cssMaps

Changelog

  • 0.3.152015-06-15 Use better HTML minifier.
  • 0.3.142015-02-05 Fix bug with windows pathing outputting wrong.
  • 0.3.122015-02-02 Fix what was sort of a bug but is apparent as definitely a bug in Coffeescript 1.9
  • 0.3.112015-01-09 Bumped all outdated dependencies.
  • 0.3.102015-01-09 Bumped sane dependency to 1.0.0 (should be more stable).
  • 0.3.92014-12-31TemplateWatcher has new improved & better naming algorithm.
  • 0.3.82014-12-30this.meta to only pass fs.stats to render. Exposes Constructors.
  • 0.3.72014-12-29 Template js injection is more generic.
  • 0.3.62014-12-03 Streamline and improve sourcemap handling.
  • 0.3.52014-11-17 Only emit one error, when a vendor file is unavailable.
  • 0.3.42014-11-10 Back on track with a sane build and changelog.
  • 0.2.212014-11-01 Assets accept module prefix in file name.
  • 0.2.202014-10-28 Handle errors in generated sourcemaps.
  • 0.2.192014-10-26 Generate SourceMaps for unsourcemapped vendors.
  • 0.2.182014-10-17 Jade rendering issue.
  • 0.2.16, 172014-10-17 Less CSS compiler and vanilla HTML compiler.
  • 0.2.152014-10-06 Better reporting syntax errors.
  • 0.2.142014-09-11 Documentation pass (13) & Bugfix (14).
  • 0.2.122014-09-07 [debug][https://www.npmjs.org/package/debug] for logs.
  • 0.2.112014-09-05 Bug fixes. See commit log.
  • 0.2.72014-08-20 Sourcemaps for Stylus files.
  • 0.2.62014-08-12 Many small bugfixes in .2 through .6.
  • 0.2.12014-07-21 Replaced Gaze with Sane.
  • 0.2.02014-07-19 Implements Cascading File System.
  • 0.1.42014-06-16 Includes Grunt task to save compiled assets to disk, for pure static server (also great for tests). This is likely to move to grunt-stassets in the very near future!
  • 0.12014-06-12 Understands the basic project structure. Works great for rapid development.

About

Static Asset Compiling Express Middleware

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages