Ind.ie is now Small Technology Foundation.
Commit 493efb4a authored by Oskar Kalbag's avatar Oskar Kalbag

Removed the hybrid mode. Refactored the examples into modules. Moved the...

Removed the hybrid mode. Refactored the examples into modules. Moved the hardcoded formatter out of Tally-Express and into the sample. Changed the namespace for communicating with Tally in the DOM to __tally. Moved the profiled version into its own module and route.
parent d5b16674
// CoffeeScript bootstrap for use with (e.g.) node --debug
require("coffee-script");
require("./index");
......@@ -3,11 +3,6 @@ tally = require './lib/tally-express.coffee'
superagent = require 'superagent'
timer = require './lib/timer.coffee'
# Time the app startup
timer.reset()
#
# Set up Express with Tally as the templating engine.
#
......@@ -19,31 +14,7 @@ app.use express.static('views')
#
# Simple template example (with static data)
#
# Sample data
data =
title: 'Tally sample'
name: 'Tally'
content: 'This is a simple example to demonstrate Tally, a templating engine for Express 3 and client‐side JavaScript built on Distal, a JavaScript implementation of TAL from the Zope framework.'
newURL: 'http://aralbalkan.com'
correctURLFragment: 'moderniosdevelopment'
aralImageURL: 'http://aralbalkan.com/images/aral.jpg'
friends:
[
{name: 'Laura', skills: 'design, development, illustration, speaking'},
{name: 'Seb', skills: 'particles, games, JavaScript, C++'},
{name: 'Natalie', skills: 'HTML, CSS'}
]
# Pure Tally call.
app.get '/', (request, response) ->
data.hybrid = no
response.render 'index.html', data
# Hybrid Tally call.
app.get '/hybrid', (request, response) ->
data.hybrid = yes
response.render 'hybrid.html', data
app.get '/simple', require('./simple.coffee').simple
#
# App.net global timeline example.
......@@ -51,31 +22,24 @@ app.get '/hybrid', (request, response) ->
app.get '/posts', (request, response) ->
# Time the data call
timer.reset()
superagent.get('https://alpha-api.app.net/stream/0/posts/stream/global')
.end (globalTimelineResponse) ->
timer.elapsedTime('Data transfer from App.net')
if globalTimelineResponse.body
# Attach a custom function to the data to count the number of posts
globalTimelineResponse.body.numberOfPosts = ->
return this.data.length
# Time the template render
timer.reset()
response.render 'posts.html', globalTimelineResponse.body
timer.elapsedTime('Template render')
else
response.render 'posts.html', {error: 'Bad response from Twitter'}
# App.net global timeline example with profiling.
app.get '/profile', require('./profile.coffee').profile
app.listen 3000
console.log 'The Tally sample is listening on port 3000…'
timer.elapsedTime('Server start')
// Generated by CoffeeScript 1.4.0
(function() {
var app, data, express, superagent, tally, timer;
var app, express, superagent, tally;
express = require('express');
......@@ -8,10 +8,6 @@
superagent = require('superagent');
timer = require('./lib/timer.coffee');
timer.reset();
app = express();
app.engine('html', tally.__express);
......@@ -20,48 +16,15 @@
app.use(express["static"]('views'));
data = {
title: 'Tally sample',
name: 'Tally',
content: 'This is a simple example to demonstrate Tally, a templating engine for Express 3 and client‐side JavaScript built on Distal, a JavaScript implementation of TAL from the Zope framework.',
newURL: 'http://aralbalkan.com',
correctURLFragment: 'moderniosdevelopment',
aralImageURL: 'http://aralbalkan.com/images/aral.jpg',
friends: [
{
name: 'Laura',
skills: 'design, development, illustration, speaking'
}, {
name: 'Seb',
skills: 'particles, games, JavaScript, C++'
}, {
name: 'Natalie',
skills: 'HTML, CSS'
}
]
};
app.get('/', function(request, response) {
data.hybrid = false;
return response.render('index.html', data);
});
app.get('/hybrid', function(request, response) {
data.hybrid = true;
return response.render('hybrid.html', data);
});
app.get('/simple', require('./simple.coffee').simple);
app.get('/posts', function(request, response) {
timer.reset();
return superagent.get('https://alpha-api.app.net/stream/0/posts/stream/global').end(function(globalTimelineResponse) {
timer.elapsedTime('Data transfer from App.net');
if (globalTimelineResponse.body) {
globalTimelineResponse.body.numberOfPosts = function() {
return this.data.length;
};
timer.reset();
response.render('posts.html', globalTimelineResponse.body);
return timer.elapsedTime('Template render');
return response.render('posts.html', globalTimelineResponse.body);
} else {
return response.render('posts.html', {
error: 'Bad response from Twitter'
......@@ -70,10 +33,10 @@
});
});
app.get('/profile', require('./profile.coffee').profile);
app.listen(3000);
console.log('The Tally sample is listening on port 3000…');
timer.elapsedTime('Server start');
}).call(this);
jsdom = require 'jsdom'
fs = require 'fs'
handlebars = require 'handlebars'
# Load the Tally engine.
tally = (fs.readFileSync __dirname + '/tally.js', 'utf8').toString()
# The Express 3 export.
exports.__express = (path, data, callback) ->
fs.readFile path, 'utf8', (error, template) ->
if error
......@@ -14,20 +15,26 @@ exports.__express = (path, data, callback) ->
window = document.createWindow()
window.console = console
# Flag so Tally knows it is running under Tally-Express
# server side so that it knows to remove nodes that
# don’t satisfy conditionals (data-qif) instead of
# setting their display to none as makes sense on the client.
data.aralbalkan = {tallyRunningInNode: yes}
# Create a private member in the data to communicate with the Tally engine in the DOM.
data.__tally = {} unless data.__tally
# console.log data
# Flag so Tally knows it is running on the server
# and will remove nodes that don’t satisfy conditionals
# (data-qif) instead of setting them to display: none
# like it does when running on the client.
data.__tally['server'] = yes;
window.data = data
# Create Tally in the DOM.
window.run tally
# Custom formatter
window.tally.format['fullURL'] = (value) ->
return 'http://' + value + '.com'
# If the user has added custom formatters to the data object,
# copy them over to Tally.
customFormatters = data.__tally['formatters']
if customFormatters
window.tally.format[customFormatter] = customFormatters[customFormatter] for customFormatter of customFormatters
# Save the data on the DOM and run Tally.
window.data = data
# NB. window.document is tracing out as [ null ] in the function itself
# === although window.document.innerHTML works. window.document.documentElement
......@@ -36,11 +43,4 @@ exports.__express = (path, data, callback) ->
html = window.document.innerHTML;
if data.hybrid == yes
console.log 'Hybrid'
# Hybrid: now, let’s run it through handlebars
handleBarsTemplate = handlebars.compile(html)
html = handleBarsTemplate(data)
# console.log(html)
callback(null, html)
// Generated by CoffeeScript 1.4.0
(function() {
var fs, handlebars, jsdom, tally;
jsdom = require('jsdom');
fs = require('fs');
handlebars = require('handlebars');
tally = (fs.readFileSync(__dirname + '/tally.js', 'utf8')).toString();
exports.__express = function(path, data, callback) {
return fs.readFile(path, 'utf8', function(error, template) {
var document, handleBarsTemplate, html, window;
if (error) {
return callback(error);
}
document = jsdom.jsdom(template, '2');
window = document.createWindow();
window.console = console;
data.aralbalkan = {
tallyRunningInNode: true
};
window.data = data;
window.run(tally);
window.tally.format['fullURL'] = function(value) {
return 'http://' + value + '.com';
};
window.run('tally(window.document.documentElement, window.data);');
html = window.document.innerHTML;
if (data.hybrid === true) {
console.log('Hybrid');
handleBarsTemplate = handlebars.compile(html);
html = handleBarsTemplate(data);
}
return callback(null, html);
});
};
}).call(this);
(function(){var e,t,n;t=require("jsdom");e=require("fs");n=e.readFileSync(__dirname+"/tally.js","utf8").toString();exports.__express=function(r,i,s){return e.readFile(r,"utf8",function(e,r){var o,u,a,f,l;if(e)return s(e);a=t.jsdom(r,"2");l=a.createWindow();l.console=console;i.__tally||(i.__tally={});i.__tally.server=!0;l.run(n);u=i.__tally.formatters;if(u)for(o in u)l.tally.format[o]=u[o];l.data=i;l.run("tally(window.document.documentElement, window.data);");f=l.document.innerHTML;return s(null,f)})}}).call(this);
\ No newline at end of file
......@@ -102,8 +102,11 @@ tally = (root, obj) ->
list = root.querySelectorAll("*[" + qdup + "]")
node.parentNode.removeChild node while (node = list[pos++])
pos = 0
listStack = [(if querySelectorAll then root.querySelectorAll(TAL) else root.getElementsByTagName("*"))]
list = [root]
loop
node = list[pos++]
......@@ -112,7 +115,7 @@ tally = (root, obj) ->
while not node and (list = listStack.pop())
pos = posStack.pop()
node = list[pos++]
break unless node
break unless node
#creates a shortcut to an object
#e.g., <section qdef="feeds main.sidebar.feeds">
......@@ -175,7 +178,7 @@ tally = (root, obj) ->
pos += node.querySelectorAll(TAL).length
else
pos += node.getElementsByTagName("*").length
if obj.aralbalkan isnt `undefined` and obj.aralbalkan.tallyRunningInNode
if obj.__tally isnt `undefined` and obj.__tally.server
node.parentNode.removeChild node
else
node.style.display = "none"
......@@ -188,6 +191,7 @@ tally = (root, obj) ->
#of the loop.
#e.g., <div qrepeat="item feeds.items">
attr = node.getAttribute(qrepeat)
if attr
attr2 = attr.split(" ")
......@@ -202,7 +206,7 @@ tally = (root, obj) ->
if objList and objList.length
# Don’t set the style if on the server (as we don’t on anything)
node.style.display = "" if obj.aralbalkan is `undefined`
node.style.display = "" if obj.__tally is `undefined` or obj.__tally.server is no
#allow this node to be treated as index zero in the repeat list
#we do this by setting the shortcut variable to array[0]
......@@ -212,7 +216,7 @@ tally = (root, obj) ->
# Handling hiding differently depending on whether this is running on the
# client or as part of Tally on the server.
if obj.aralbalkan isnt `undefined` and obj.aralbalkan.tallyRunningInNode
if obj.__tally isnt `undefined` and obj.__tally.server
# Running in Tally as part of Express.
# Delete the node
......
......@@ -170,7 +170,7 @@ Forked from Distal by mocking@gmail.com (https://code.google.com/p/distal/)
} else {
pos += node.getElementsByTagName("*").length;
}
if (obj.aralbalkan !== undefined && obj.aralbalkan.tallyRunningInNode) {
if (obj.__tally !== undefined && obj.__tally.server) {
node.parentNode.removeChild(node);
} else {
node.style.display = "none";
......@@ -192,13 +192,13 @@ Forked from Distal by mocking@gmail.com (https://code.google.com/p/distal/)
}
objList = resolve(obj, attr2[1]);
if (objList && objList.length) {
if (obj.aralbalkan === undefined) {
if (obj.__tally === undefined || obj.__tally.server === false) {
node.style.display = "";
}
obj[attr2[0]] = objList[0];
obj["#"] = 1;
} else {
if (obj.aralbalkan !== undefined && obj.aralbalkan.tallyRunningInNode) {
if (obj.__tally !== undefined && obj.__tally.server) {
if (querySelectorAll) {
pos += node.querySelectorAll(TAL).length;
} else {
......
../coffee-script/bin/cake
\ No newline at end of file
../coffee-script/bin/coffee
\ No newline at end of file
*.coffee
*.html
.DS_Store
.git*
Cakefile
documentation/
examples/
extras/coffee-script.js
raw/
src/
test/
coffeescript.org
\ No newline at end of file
## How to contribute to CoffeeScript
* Before you open a ticket or send a pull request, [search](https://github.com/jashkenas/coffee-script/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one.
* Before sending a pull request for a feature, be sure to have [tests](https://github.com/jashkenas/coffee-script/tree/master/test).
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffee-script/tree/master/src). If you're just getting started with CoffeeScript, there's a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide).
* In your pull request, do not add documentation to `index.html` or re-build the minified `coffee-script.js` file. We'll do those things before cutting a new release.
\ No newline at end of file
Copyright (c) 2009-2012 Jeremy Ashkenas
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
{
} } {
{ { } }
} }{ {
{ }{ } } _____ __ __
( }{ }{ { ) / ____| / _|/ _|
.- { { } { }} -. | | ___ | |_| |_ ___ ___
( ( } { } { } } ) | | / _ \| _| _/ _ \/ _ \
|`-..________ ..-'| | |___| (_) | | | || __/ __/
| | \_____\___/|_| |_| \___|\___|
| ;--.
| (__ \ _____ _ _
| | ) ) / ____| (_) | |
| |/ / | (___ ___ _ __ _ _ __ | |_
| ( / \___ \ / __| '__| | '_ \| __|
| |/ ____) | (__| | | | |_) | |_
| | |_____/ \___|_| |_| .__/ \__|
`-.._________..-' | |
|_|
CoffeeScript is a little language that compiles into JavaScript.
Install Node.js, and then the CoffeeScript compiler:
sudo bin/cake install
Or, if you have the Node Package Manager installed:
npm install -g coffee-script
(Leave off the -g if you don't wish to install globally.)
Execute a script:
coffee /path/to/script.coffee
Compile a script:
coffee -c /path/to/script.coffee
For documentation, usage, and examples, see:
http://coffeescript.org/
To suggest a feature, report a bug, or general discussion:
http://github.com/jashkenas/coffee-script/issues/
If you'd like to chat, drop by #coffeescript on Freenode IRC,
or on webchat.freenode.net.
The source repository:
git://github.com/jashkenas/coffee-script.git
All contributors are listed here:
http://github.com/jashkenas/coffee-script/contributors
require 'rubygems'
require 'erb'
require 'fileutils'
require 'rake/testtask'
require 'json'
desc "Build the documentation page"
task :doc do
source = 'documentation/index.html.erb'
child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" }
at_exit { Process.kill("INT", child) }
Signal.trap("INT") { exit }
loop do
mtime = File.stat(source).mtime
if !@mtime || mtime > @mtime
rendered = ERB.new(File.read(source)).result(binding)
File.open('index.html', 'w+') {|f| f.write(rendered) }
end
@mtime = mtime
sleep 1
end
end
desc "Build coffee-script-source gem"
task :gem do
require 'rubygems'
require 'rubygems/package'
gemspec = Gem::Specification.new do |s|
s.name = 'coffee-script-source'
s.version = JSON.parse(File.read('package.json'))["version"]
s.date = Time.now.strftime("%Y-%m-%d")
s.homepage = "http://jashkenas.github.com/coffee-script/"
s.summary = "The CoffeeScript Compiler"
s.description = <<-EOS
CoffeeScript is a little language that compiles into JavaScript.
Underneath all of those embarrassing braces and semicolons,
JavaScript has always had a gorgeous object model at its heart.
CoffeeScript is an attempt to expose the good parts of JavaScript
in a simple way.
EOS
s.files = [
'lib/coffee_script/coffee-script.js',
'lib/coffee_script/source.rb'
]
s.authors = ['Jeremy Ashkenas']
s.email = 'jashkenas@gmail.com'
s.rubyforge_project = 'coffee-script-source'
s.license = "MIT"
end
file = File.open("coffee-script-source.gem", "w")
Gem::Package.open(file, 'w') do |pkg|
pkg.metadata = gemspec.to_yaml
path = "lib/coffee_script/source.rb"
contents = <<-ERUBY
module CoffeeScript
module Source
def self.bundled_path
File.expand_path("../coffee-script.js", __FILE__)
end
end
end
ERUBY
pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
tar_io.write(contents)
end
contents = File.read("extras/coffee-script.js")
path = "lib/coffee_script/coffee-script.js"
pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
tar_io.write(contents)
end
end
end
#!/usr/bin/env node
var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
require(lib + '/coffee-script/cake').run();
#!/usr/bin/env node
var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
require(lib + '/coffee-script/command').run();
# JavaScriptLint configuration file for CoffeeScript.
+no_return_value # function {0} does not always return a value
+duplicate_formal # duplicate formal argument {0}
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
+var_hides_arg # variable {0} hides argument
+redeclared_var # redeclaration of {0} {1}
-anon_no_return_value # anonymous function does not always return a value
+missing_semicolon # missing semicolon
+meaningless_block # meaningless block; curly braces have no impact
-comma_separated_stmts # multiple statements separated by commas (use semicolons?)
+unreachable_code # unreachable code
+missing_break # missing break statement
-missing_break_for_last_case # missing break statement for last case in switch
-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
-useless_void # use of the void type may be unnecessary (void is always undefined)
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
+use_of_label # use of label
-block_without_braces # block statement without curly braces
+leading_decimal_point # leading decimal point may indicate a number or an object member
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
+octal_number # leading zeros make an octal number
+nested_comment # nested comment
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
+empty_statement # empty statement or extra semicolon
-missing_option_explicit # the "option explicit" control comment is missing
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
+dup_option_explicit # duplicate "option explicit" control comment
+useless_assign # useless assignment
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
-missing_default_case # missing default case in switch statement
+duplicate_case_in_switch # duplicate case in switch statements
+default_not_at_end # the default case is not at the end of the switch statement
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
+useless_comparison # useless comparison; comparing identical expressions
+with_statement # with statement hides undeclared variables; use temporary variable instead
+trailing_comma_in_array # extra comma is not recommended in array initializers
+assign_to_function_call # assignment to a function call
+parseint_missing_radix # parseInt missing radix parameter
+lambda_assign_requires_semicolon
// Generated by CoffeeScript 1.6.1
(function() {
var CoffeeScript, runScripts,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
CoffeeScript = require('./coffee-script');
CoffeeScript.require = require;
CoffeeScript["eval"] = function(code, options) {
var _ref;
if (options == null) {
options = {};
}
if ((_ref = options.bare) == null) {
options.bare = true;
}
return eval(CoffeeScript.compile(code, options));
};
CoffeeScript.run = function(code, options) {
if (options == null) {
options = {};
}
options.bare = true;
return Function(CoffeeScript.compile(code, options))();
};
if (typeof window === "undefined" || window === null) {
return;
}
CoffeeScript.load = function(url, callback, options) {
var xhr;
if (options == null) {
options = {};
}
xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) {
xhr.overrideMimeType('text/plain');
}
xhr.onreadystatechange = function() {
var _ref;
if (xhr.readyState === 4) {
if ((_ref = xhr.status) === 0 || _ref === 200) {
CoffeeScript.run(xhr.responseText, options);
} else {
throw new Error("Could not load " + url);
}
if (callback) {
return callback();
}
}
};
return xhr.send(null);
};
runScripts = function() {
var coffees, coffeetypes, execute, index, length, s, scripts;
scripts = document.getElementsByTagName('script');
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
coffees = (function() {
var _i, _len, _ref, _results;
_results = [];
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
s = scripts[_i];
if (_ref = s.type, __indexOf.call(coffeetypes, _ref) >= 0) {
_results.push(s);
}
}
return _results;
})();
index = 0;
length = coffees.length;
(execute = function() {
var mediatype, options, script;
script = coffees[index++];
mediatype = script != null ? script.type : void 0;
if (__indexOf.call(coffeetypes, mediatype) >= 0) {
options = {
literate: mediatype === 'text/literate-coffeescript'
};
if (script.src) {
return CoffeeScript.load(script.src, execute, options);
} else {
CoffeeScript.run(script.innerHTML, options);
return execute();
}
}
})();
return null;
};
if (window.addEventListener) {
addEventListener('DOMContentLoaded', runScripts, false);
} else {
attachEvent('onload', runScripts);
}
}).call(this);
// Generated by CoffeeScript 1.6.1
(function() {
var CoffeeScript, cakefileDirectory, existsSync, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
fs = require('fs');
path = require('path');
helpers = require('./helpers');