Skip to content

Latest commit

 

History

History
292 lines (219 loc) · 8.56 KB

contributing.md

File metadata and controls

292 lines (219 loc) · 8.56 KB

@page guides.Contributing Contributing @parent StealJS.about

Thank you for contributing!

Bugs and Feature Requests

Bugs and feature requests should be submitted to steal for issues with module loading and steal-tools for issues building.

The best issues are those submitted with tests. Learn about how to setup a test in the "Developing" sections below.

Developing steal

To develop steal, fork and clone steal. Make sure you have NodeJS installed. Then:

  1. Install npm modules

     > npm install
    
  2. Install bower modules

     > bower install
    
  3. Run tests (this will run other scripts needed to set up tests correctly)

     > npm test
    
  4. Setup grunt watch

     > grunt watch
    

This will automatically build steal.js and steal.production.js when anything in src changes.

Understanding steal's code

steal.js core files are located in the src folder, two important folders are:

  • src/loader - which Provides the ES6ModuleLoader Polyfill.
  • src/base - Provides most steal.js extensions like [config.paths], [config.map], [syntax.amd AMD] and [syntax.CommonJS CommonJS] syntaxes.

Other core extensions can be found in this folder:

  • src/json - Provides the JSON module format definition
  • src/env - Adds some special environment functions to the loader

Each of this folders is self contained, meaning, each folder include their own test files; in order to run the tests just find the test html page which should be located at the root of the folder and open it in your browser.

E.g: to run the tests of the src/base extension just open src/base/base_test.html and make sure everything passes.

Please note that when running invidivual test pages you might need to re-build some files to see your changes, run grunt build after saving your changes to update the files.

On a high level, steal.js is organized like:

/* ES6ModuleLoader */
    /* - Promise polyfill */
!function(e){"object"==typeof ...}

/* StealJS core extensions */
(function(__$global) {
  /* meta, register, core, global, cjs, amd, map, 
     plugins, bundles, versions, depCache extensions */
});

/* start.js
 * - wraps everything in a closure
 * - helpers that are useful everywhere
 */
(function(global){
    // helpers
    var camelize, each, map, isString, extend, parseURI;
/* normalize.js
 * - standalone normalize function
 */
    var normalize = function(){}
/* core.js
 * - starts `makeSteal` that makes `steal`.
 */
    var makeSteal = function( System ){
        var steal = function(){ ... }
/* system-extension-ext.js
 * - the System.ext extension
 */
        var addExt = function(loader) { .. };
        addExt(System);
/* system-extension-forward-slash.js
 * - module names that end in /
 */
        var addForwardSlash = function(loader) { ... };
        addForwardSlash(System);
/* config.js
 * - overwrites System.config
 * - sets up System.env, System.stealPath, System.bundlesPath
 */
        var setterConfig = function(...){...}
        setterConfig(System,{ ... });
/* startup.js
 * - defines startup code
 */
        var getScriptOptions = function () { ... }
        steal.startup = function(config){ ... }
/* make-steal-end.js
 * - closes `makeSteal`
 */
    };
/* system-format-steal.js
 * - a System extension that adds the `steal` syntax
 */
    function addSteal(loader) { ... }
    addSteal(System);
/* end.js
 * - 
 */
    if (typeof window != 'undefined') {
        window.steal = makeSteal(System);
        window.steal.startup( oldSteal );
        ...
    } else {
        require('systemjs');
        global.steal = makeSteal(System);
        ...
    }
})(typeof window == "undefined" ? global : window);

Writing a steal test

Most tests create an iframe that opens another page like:

QUnit.test("test description", function(assert) {
    makeIframe("path/to/page.html", assert);
});

That page typically uses steal to import some modules and when complete calls to the parent window's QUnit assertion methods. For example:

<!-- page.html -->
<html>
   <script src="../../steal/steal.js"
           main="test-module">
   </script>
</html>

// test-module.js
window.parent.assert.ok(true, "test-module-loaded");
window.parent.done();

Developing steal-tools

To develop steal, fork and clone steal-tools. Make sure you have NodeJS installed. Then:

  1. Install npm modules

    > npm install
    
  2. Install bower modules

     > bower install
    
  3. Install mocha

     > npm install -g mocha
    

To test, run:

    > mocha test/test.js

Windows

Note that if you are using Windows you first need to install a couple of things before you npm install.

  1. Install Python 2.7. You'll want to add the directory to your PATHS (likely C:\Python27).

  2. Install Microsoft Build Tools or Visual Studio Express 2013 depending on which version of Windows you are using. Try the Build Tools but VSE might be needed.

See the [guides.ContributingWindows] guide for full instructions.

Understanding steal-tools code

On a high level, [steal-tools steal-tools] uses lib/trace.js to figure out all of the dependencies for a module and arange them into a graph. It then transforms that graph into bundles and finally writes out the bundles so they can be loaded by the client in production.

A dependency graph that trace.js produces looks like:

{
  moduleName: Node({
    load: Load({
      name: moduleName,
      source: SOURCE
    }),
    dependencies: [moduleName,...],
    // which [System.bundle] moduleNames this module is a dependency of.
    bundles: [bundleName,...],
  })
}

Here's an example:

{
  "jquery": {
    load: {
      name: "jquery",
      source: "jQuery = function(){ ... }"
    },
    dependencies: [],
    bundles: ["profile","settings","login", ...]
  },
  "can/util": {
    load: {
      name: "can/util",
      source: "define(['jquery'], function($){ ... })" 
    },
    dependencies: ["jquery"],
    bundles: ["profile", "login"]
  }
}

A Load is a ES6 load record.

A Node is an object that contains the load and other useful information like the modules:

  • dependencies
  • bundles
  • transformed and/or minified source

The build tools only write to Node to keep Load from being changed. They manipulate this graph and eventually creates "bundle" graphs. Bundle graphs look like:

 {
   // How many bytes this bundle is minified
   size: 231231,
   // The Nodes (and therefore modules) this bundle contains
   nodes: [node1, node2, ...],
   // The [System.bundle] moduleNames this bundle is a dependency of
   bundles: [bundleName1, bundleName2]	
 }

[steal-tools steal-tools] code is organized in folders around certain concepts:

  • build - high level build modules like the multi build and pluginify.
  • buildTypes - utitlies for specific buildTypes (like CSS or JS).
  • bundle - transformations around bundle objects.
  • configuration - utility for getting derived configuration values.
  • graph - graph creation and transformation utilities.
  • node - utilities around a node in a graph

Website and Documentation

steal's gh-pages branch contains stealjs.com's code. It uses DocumentJS to produce the website. To edit the docs:

  1. Edit markdown files in steal/docs or steal-tools/doc

  2. Fork/Clone https://github.com/stealjs/stealjs:

     > git clone https://github.com/stealjs/stealjs.git
    
  3. Install npm dependencies:

     > npm install
    
  4. Regenerate site and check changes

     > npm run document
    
  5. Checkin and push gh-pages branch changes.

This workflow requires that the markdown changes to steal or steal-tools made in the first step were published to npm; if the changes are only local, you could use npm link to use the steal with the updated markdown files.