Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

shipyard doc, makes the doc pages

  • Loading branch information...
commit 210721104b38adfef858907d06d714616c06db77 1 parent 1460820
@seanmonstar authored
View
1  .gitignore
@@ -1,2 +1,3 @@
node_modules*
+out*
*-min.js
View
167 README.md
@@ -1,165 +1,21 @@
Shipyard
-===========
+========
A Javascript [MVC][mvc] application framework. For when you have a full-on application sitting on a web page. So much is going on, you should be able to focus on making the application working, not worrying about XmlHttpRequests and the DOM.
-What Shipyard is
---------------
+Getting the Code
+----------------
-An application framework that covers all the common things any JavaScript application would need to deal with: interacting with a server, storing data, rendering said data in the browser, and responding to user actions. An application built on Shipyard should only have to write that pulls all those things together.
-
-If you're application is going to have 1000 lines of JavaScript, would you rather write all those yourself, or have 900 of them be in a framework that is tested and used by others?
-
-When starting a web application, you would reach for Django, or CakePHP, or Rails; never would you decide to use just he language itself. Why shouldn't you do the same when the target language is JavaScript?
-
-Goals
------
-
-### Framework-wide Goals
-
-1. Be able to declare dependencies inside the code, and not be bothered with managing them during development or deployment.
-2. Be easily testable, using a node test runner.
-3. Not reliant on any other language. Build scripts will use JavaScript. The End.
-
-### Model Goals
-
-1. Provide fields that can convert properties from useful JavaScript objects to serialized values when persisting, and vice versa.
-2. Fire `change` events, so that Views bound to a model can automatically update what they are displaying.
-3. Allow persistance mixins to easily attach to sync methods, allowing one to easily store data in multiple places by simpling mixing in a new persistance service.
-4. Ability to add in Validation rules easily.
-
-### View Goals
-
-1. Be abstract view classes, allowing the developer to not worry about the underlying DOM and how much it sucks.
-2. Be able to fire meaningful events, and not worry about DOM events and which one's are important, or whether you should use event delegation, etc.
-3. Be extendable, such that there is very little DRY: TreeView extends ListView.
-4. Be able to bind to a model, and update (re-render) parts of itself when the underlying data changes, with no work from the developer.
-5. Use a templating language underneath, so that experienced developers can write their own custom View classes with the utmost control.
-
-### Controller Goals
-
-1. A controller should be concerned with a general area of the webapp, adding Views.
-2. Can listen to Views events, and decide what models should change and when.
-
-Getting Started
----------------
-
-1. Checkout the repo.
+1. Checkout the repo: git://github.com/seanmonstar/Shipyard.git
2. `npm link`
3. `shipyard test`
4. Woo!
-Afterwards, to use it with one of your apps, especially when running
-tests, you'll want to add the path to Shipyard/lib to your `NODE_PATH`,
-since node 0.6 removed the ability for me to push onto the path with
-code.
-
-How to use
-----------
-
-### Models
-
-Your application revolves around data, not the DOM. Models allow you to easily define rules, and setup methods to persist your data via various persistence schemas, such as to a server, or using localStorage.
-
- var Class = require('shipyard/Class'),
- model = require('shipyard/model'),
- Syncable = require('shipyard/sync/Syncable'),
- XHR = require('shipyard/sync/Server'),
- localStorage = require('shipyard/sync/Browser');
-
- var Recipe = module.exports = new Class({
-
- Extends: model.Model,
-
- Implements: Syncable,
-
- Sync: {
- 'default': {
- driver: XHR,
- route: '/api/recipes'
- },
- 'local': {
- driver: localStorage,
- table: 'recipes'
- }
- },
-
- fields: {
- id: model.Fields.NumberField(),
- title: model.Fields.TextField({ length: 64, required: true}),
- ingredients: model.Fields.TextField()
- },
-
- toString: function() {
- return this.get('title');
- }
-
- });
-
-And then use it like so:
-
- var Recipe = require('./models/Recipe');
- var rec = new Recipe({ title: 'Curry', ingredients: 'coconut' });
- rec.save(); // saves using 'default' Sync.
- rec.save({using: 'local'}); // or save to another Sync.
+Documentation
+-------------
+Available at http://seanmonstar.github.com/Shipyard
-### Views
-
-The browser just happens to be where you application resides, but manipulating the DOM is something you shouldn't have to think about. Shipyard provides an extensible view system that abstracts away the DOM elements and events, and lets you think in terms of UI elements instead.
-
- var View = require('shipyard/view/View');
-
- var recipe = new Recipe({ title: 'Cookies' });
- var titleView = new View({
- data: recipe
- });
- titleView.attach();
-
-Or, you can create your own views, extending them when you need
-something custom:
-
- var Class = require('shipyard/Class'),
- ListView = require('shipyard/view/ListView');
-
- var RecipesView = module.exports = new Class({
-
- Extends: ListView
-
- //override getRenderOptions or something
-
- });
-
-However, this should only be necessary for changing the inherent
-behavior of a View. Simply adding events to views does not require
-creating a new class.
-
-### Controllers
-
-Controllers build the views, pass them data from the models, and then interpret events in order to modify the models back again.
-
- var Class = require('shipyard/Class'),
- ListController = require('shipyard/controller/ListController'),
- RecipeView = require('../view/RecipeView'),
- Recipe = require('../model/Recipe');
-
- var RecipesController = modules.export = new Class({
-
- Extends: ListController,
-
- list: RecipeView,
-
- model: Recipe
-
- });
-
-
-Relies On
---------
-
-[CommonJS modules][cjs]. `require` will load the modules automatically during development, to make development more sane.
-
-When a push is needed, [DryIce][di] can be use to compile the whole project into a single compressed file.
Credit
------
@@ -168,7 +24,12 @@ Major credit goes to [MooTools][moo], for much of the core of Shipyard is __heav
While it has mostly been modified slightly to fit better into a Module setting,
huge thanks to MooTools.
+Copyright
+---------
+
+MIT License. Copyright 2012 [Sean McArthur](http://seanmonstar.com).
+
+
+
[mvc]: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
-[di]: https://github.com/mozilla/dryice
-[cjs]: http://wiki.commonjs.org/wiki/Modules/1.1
[moo]: http://mootools.net
View
14 bin/shipyard
@@ -11,6 +11,11 @@ var program = require('commander'),
shell = require('../scripts/shell').shell,
test = require('../scripts/test');
+var marked = false;
+try {
+ marked = require('marked');
+} catch(requireError) {}
+
function uncaughtException(e) {
if (program.debug) {
console.error(e.stack);
@@ -97,6 +102,15 @@ program
shell();
});
+if (marked) {
+ program
+ .command('doc')
+ .description('Build the Shipyard docs.')
+ .action(function() {
+ require('../scripts/doc').build();
+ });
+}
+
if (process.argv.length == 2) {
process.argv.push('-h');
}
View
44 doc/_template/page.ejs
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Shipyard JS: <%=title%></title>
+ <link rel="stylesheet" type="text/css" href="/Shipyard/style.css">
+ </head>
+ <body>
+ <header>
+ <div>
+ <h1><a href="/Shipyard">Shipyard</a></h1>
+ <p>A modular JavaScript MVC framework</p>
+ </div>
+ </header>
+ <div id="container">
+ <article id="main">
+ <%- main %>
+ </article>
+ <aside id="nav">
+ <p><em>v<%=version%></em></p>
+ <nav>
+ <ul>
+ <li>
+ Topics
+ <ul>
+ <% topics.forEach(function(link) { %>
+ <li><%- linkify(link, 'topics') %></li>
+ <% }); %>
+ </ul>
+ </li>
+ <li>
+ API Reference
+ <ul>
+ <% api.forEach(function(link) { %>
+ <li><%- linkify(link, 'api') %></li>
+ <% }); %>
+ </ul>
+ </li>
+ </ul>
+ </nav>
+ </aside>
+ <footer>&copy; 2012 <a href="http://seanmonstar.com">Sean McArthur</a>. Source available on <a href="https://github.com/seanmonstar/Shipyard">GitHub</a>.</footer>
+ </div>
+ </body>
+</html>
View
4 doc/api/model.md
@@ -9,7 +9,7 @@ ignorant.
### Extends
-Syncable
+[Syncable](./sync.md#Syncable)
## Mutator: fields
@@ -25,7 +25,7 @@ Model, using `Field` classes.
created_at: fields.DateField(),
is_done: fields.BooleanField()
}
- });)
+ });
## Mutator: Sync
View
55 doc/index.md
@@ -0,0 +1,55 @@
+Shipyard
+===========
+
+A Javascript [MVC][mvc] application framework. For when you have a full-on application sitting on a web page. So much is going on, you should be able to focus on making the application working, not worrying about XmlHttpRequests and the DOM.
+
+What Shipyard is
+--------------
+
+An application framework that covers all the common things any JavaScript application would need to deal with: interacting with a server, storing data, rendering said data in the browser, and responding to user actions. An application built on Shipyard should only have to write that pulls all those things together.
+
+If you're application is going to have 1000 lines of JavaScript, would you rather write all those yourself, or have 900 of them be in a framework that is tested and used by others?
+
+When starting a web application, you would reach for Django, or CakePHP, or Rails; never would you decide to use just he language itself. Why shouldn't you do the same when the target language is JavaScript?
+
+Goals
+-----
+
+### Framework-wide Goals
+
+1. __Modularity__: Be able to declare dependencies inside the code, and not be bothered with managing them during development or deployment.
+2. __Testability__: Be easily testable, using a node test runner.
+3. __JavaScript__: Not reliant on any other language. Build scripts will use JavaScript. The End.
+
+### Model Goals
+
+1. __Fields__: Powerful fields come alive from simple JSON.
+2. __Sync__: Easily specify multiple locations the data should sync to.
+
+### View Goals
+
+1. __Binding__: Views can automatically update themselves when related
+ properties change in a Controller or Model.
+2. __DRY__: Views are easily extendable.
+3. __DOMs Away__: The DOM is a layer away. Instead, you get a nice
+ interface, with contextual events.
+4. __Templates__: The underlying layer of Views uses Templates to
+ render, if you're a control freak.
+
+### Controller Goals
+
+1. __Boilerplate__: Attempt to remove typical boilerplate of attaching
+ Models to Views with validation in between.
+
+Getting Started
+---------------
+
+ $ git clone git://github.com/seanmonstar/Shipyard.git
+ $ cd Shipyard
+ $ npm link
+ $ shipyard test
+
+Take a look at the [tutorial](./topics/tutorial.md) to make your first
+application.
+
+[mvc]: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
View
278 doc/style.css
@@ -0,0 +1,278 @@
+body {
+ background:#f5f5f5;
+ font-size:75%;
+ font-family:Helvetica, Arial, sans-serif;
+ line-height:1.5;
+ margin:0;
+ padding:0;
+}
+
+a {
+ color:#d66;
+ text-decoration:none;
+ border-bottom:1px solid #faa;
+}
+
+a:visited {
+ color:#977;
+ border-color:#977;
+}
+
+pre {
+ background:#fff;
+ border-color:#ddd;
+ border-style:solid;
+ border-width:1px 1px 1px 7px;
+ font-size:1.25em;
+ padding:1em;
+}
+
+p {
+ font-size:1.2em;
+}
+
+p code, li code {
+ border:1px solid #ddd;
+ background:#fff;
+ padding:1px 3px;
+}
+
+li {
+ font-size:1.1em;
+}
+li li {
+ font-size:1em;
+}
+
+header {
+ background:#ddd;
+ background:-moz-linear-gradient(270deg, #fff, #eee);
+ border-bottom:1px solid #fff;
+ margin:0;
+ width:100%;
+ box-shadow: 0 5px 5px 0 #aaa;
+ z-index:11;
+}
+ header div {
+ position:relative;
+ max-width:1000px;
+ margin:0 auto;
+ }
+ header h1 {
+ font-size:3em;
+ margin:0;
+ padding:0.25em 0;
+ }
+
+ header h1 a {
+ border:none;
+ }
+
+ header p {
+ color: #666;
+ font-style:italic;
+ text-transform:lowercase;
+ position:absolute;
+ top:1em;
+ left:34%;
+ }
+
+
+#container {
+ max-width:1000px;
+ margin:3em auto;
+}
+#main {
+ width:66%;
+ float:right;
+}
+
+ #main h1 {
+ border-bottom:1px solid #ddd;
+ color:#d66;
+ font-size:2.5em;
+ padding-bottom:10px;
+ }
+
+ #main h2 {
+ border-bottom:1px solid #ddd;
+ color:#66d;
+ font-size:2em;
+ padding-bottom:5px;
+ }
+
+ #main h3 {
+ color:#555;
+ font-size:1.75em;
+ }
+
+ #main .permalink {
+ border:none;
+ color:#aaa;
+ padding-left:10px;
+ }
+
+ #main h1:hover .permalink,
+ #main h2:hover .permalink {
+ color:#555;
+ }
+
+#nav {
+ float: left;
+ width:33%;
+}
+
+ #nav ul {
+ list-style:none;
+ padding:0;
+ }
+
+ #nav ul ul {
+ padding:3px 0 3px 10px;
+ }
+
+ #nav li {
+ text-transform: uppercase;
+ font-weight:bold;
+ }
+
+ #nav li li {
+ font-weight:normal;
+ }
+
+ #nav a {
+ border:none;
+ }
+
+ #nav a:hover, #nav a.active {
+ color:#fff;
+ background:#d66;
+ }
+
+
+footer {
+ clear:both;
+ text-align:center;
+ padding:6em 0 2em;
+}
+/* code highlighting
+ * ==========================================
+ */
+/*
+
+Intellij Idea-like styling (c) Vasily Polovnyov <vast@whiteants.net>
+
+*/
+
+pre code {
+ display: block; padding: 0.5em;
+ color: #000;
+ background: #fff;
+}
+
+pre .subst,
+pre .title {
+ font-weight: normal;
+ color: #000;
+}
+
+pre .comment,
+pre .template_comment,
+pre .javadoc,
+pre .diff .header {
+ color: #808080;
+ font-style: italic;
+}
+
+pre .annotation,
+pre .decorator,
+pre .preprocessor,
+pre .doctype,
+pre .pi,
+pre .chunk,
+pre .shebang,
+pre .apache .cbracket,
+pre .input_number {
+ color: #808000;
+}
+
+pre .tag,
+pre .pi {
+ background: #efefef;
+}
+
+pre .tag .title,
+pre .id,
+pre .attr_selector,
+pre .pseudo,
+pre .literal,
+pre .keyword,
+pre .hexcolor,
+pre .css .function,
+pre .ini .title,
+pre .css .class,
+pre .list .title,
+pre .tex .command {
+ font-weight: bold;
+ color: #b44;
+}
+
+pre .attribute,
+pre .rules .keyword,
+pre .number,
+pre .date,
+pre .regexp,
+pre .tex .special {
+ font-weight: bold;
+ color: brown;
+}
+
+pre .number,
+pre .regexp {
+ /*font-weight: normal;*/
+}
+
+pre .string,
+pre .value,
+pre .filter .argument,
+pre .css .function .params,
+pre .apache .tag {
+ color: #008000;
+ font-weight: bold;
+}
+
+pre .symbol,
+pre .ruby .symbol .string,
+pre .ruby .symbol .keyword,
+pre .ruby .symbol .keymethods,
+pre .char,
+pre .tex .formula {
+ color: #000;
+ background: #d0eded;
+ font-style: italic;
+}
+
+pre .phpdoc,
+pre .yardoctag,
+pre .javadoctag {
+ text-decoration: underline;
+}
+
+pre .variable,
+pre .envvar,
+pre .apache .sqbracket,
+pre .nginx .built_in {
+ color: #660e7a;
+}
+
+pre .addition {
+ background: #baeeba;
+}
+
+pre .deletion {
+ background: #ffc8bd;
+}
+
+pre .diff .change {
+ background: #bccff9;
+}
View
2  doc/topics/installation.md
@@ -41,4 +41,4 @@ Excellent. Now you can proceed with the [tutorial][3].
[1]: http://nodejs.org/#download
[2]: https://github.com/seanmonstar/Shipyard
-[3]: ./tutorial
+[3]: ./tutorial.md
View
2  doc/topics/tutorial.md
@@ -287,4 +287,4 @@ Shipyard. The concepts are the same as you scale to a full application,
but you can always read up more about specific parts if you like the
details.
-[1]: ./installation
+[1]: ./installation.md
View
5 package.json
@@ -24,7 +24,10 @@
"dryice": "git://github.com/seanmonstar/dryice.git",
"commander": "0.x"
},
- "devDependencies": {},
+ "devDependencies": {
+ "marked": "0.x",
+ "highlight": ">=0.2"
+ },
"shipyard": {
"test": "./test/unit"
View
151 scripts/doc.js
@@ -0,0 +1,151 @@
+/*global __dirname,console*/
+var fs = require('fs'),
+ path = require('path'),
+ existsSync = fs.existsSync || path.existsSync,
+ EJS = require('../lib/shipyard/template/ejs/Template'),
+ pageTemplate = require('../doc/_template/page.ejs'),
+ shipyard = require('../'),
+ dom = require('../lib/shipyard/dom'),
+ string = require('../lib/shipyard/utils/string'),
+ marked = require('marked'),
+ highlight = require('highlight').Highlight;
+
+var docDir = path.join(__dirname, '../doc');
+var DEST = path.join(__dirname, '../out/doc');
+var URL_ROOT = '/Shipyard';
+
+function mktree(pathname) {
+ var parts = pathname.replace('C:', '').replace(/\\/g, '/').split('/');
+ var curr = '/';
+ parts.forEach(function(part) {
+ curr = path.join(curr, part);
+ if (!existsSync(curr)) {
+ fs.mkdirSync(curr);
+ }
+ });
+}
+
+function page(filename, dir, nav) {
+ var content = fs.readFileSync(path.join(docDir, dir, filename));
+ var output = pageTemplate(nav, {
+ main: markdown(String(content)),
+ title: filename.replace(/\.md$/, ''),
+ version: shipyard.version,
+ linkify: function(name, folder) {
+ var link = name.replace(/\.md$/, '');
+ var url = path.join(folder, link + '.html');
+ return string.substitute('<a href="{url}" {class}>{link}</a>', {
+ url: url,
+ link: link,
+ 'class': filename === name ? 'class="active"' : ''
+ });
+ }
+ });
+ var outname = path.join(DEST, dir, filename.replace(/\.md$/, '.html'));
+ fs.writeFileSync(outname, output);
+}
+
+function buildDir(dir, nav) {
+ var names = nav[dir];
+
+ mktree(path.join(DEST, dir));
+ names.forEach(function(name) {
+ page(name, dir, nav);
+ });
+}
+
+function getID(element) {
+ var anchor = element.getElement('.permalink');
+ if (anchor) {
+ return anchor.get('id');
+ } else {
+ var id = element.get('text').replace(/(Class|Method|Property|Mutator):/, '');
+ id = id.trim();
+ id = id.replace(/[^a-zA-Z0-9]+/g, '_');
+ return id;
+ }
+}
+
+function markdown(original) {
+ var html = marked(original);
+ var el = new dom.Element('div');
+ el.set('html', html);
+
+ // highlight all <pre> tags
+ el.getElements('pre code').forEach(function (pre) {
+ pre.set('html', highlight(pre.get('html')));
+ });
+
+ // add a link to all headings
+ el.getElements('h1').forEach(function(h1) {
+ var id = getID(h1);
+
+ var anchor = new dom.Element('a', {
+ 'class': 'permalink',
+ 'id': id,
+ 'href': '#'+id,
+ 'title': "Permalink to '" + h1.get('text') + "'",
+ 'text': '#'
+ });
+ h1.appendChild(anchor);
+ });
+ el.getElements('h2').forEach(function(h2) {
+ var h1 = h2.getPrevious('h1');
+ var id = getID(h1) + ':' + getID(h2);
+
+ var anchor = new dom.Element('a', {
+ 'class': 'permalink',
+ 'id': id,
+ 'href': '#'+id,
+ 'title': "Permalink to '" + h2.get('text') + "'",
+ 'text': '#'
+ });
+ h2.appendChild(anchor);
+ });
+
+ // replace all .md links to .html
+ el.getElements('a').forEach(function(a) {
+ el.set('href', el.get('href').replace('.md', '.html'));
+ });
+
+ return el.get('html');
+}
+
+function arr_remove(arr, value) {
+ var index = arr.indexOf(value);
+ if (index !== -1) {
+ arr.splice(index, 1);
+ }
+}
+
+exports.build = function build() {
+ var apis = fs.readdirSync(path.join(docDir, 'api'));
+ var topics = fs.readdirSync(path.join(docDir, 'topics'));
+ // fix the order of topics
+ arr_remove(topics, 'tutorial.md');
+ arr_remove(topics, 'installation.md');
+ topics.unshift('installation.md');
+ topics.unshift('tutorial.md');
+
+
+ var data = { topics: topics, api: apis };
+
+ // TODO make homepage
+ page('index.md', null, data);
+
+ // move assets
+ mktree(DEST);
+ fs.writeFileSync(path.join(DEST, 'style.css'), fs.readFileSync(path.join(docDir, 'style.css')));
+
+ // make topics pages
+ buildDir('topics', data);
+
+ // make api pages
+ buildDir('api', data);
+
+ console.log('Docs built to "out" directory.');
+};
+
+if (require.main === module) {
+ exports.build();
+}
Please sign in to comment.
Something went wrong with that request. Please try again.