Permalink
Browse files

Merge branch 'master' of github.com:socketstream/socketstream

Conflicts:
	README.md
  • Loading branch information...
paulbjensen committed Jul 1, 2011
2 parents f520c9f + 36fa7f4 commit 33c2d260c10ce8c1920d549de9692b7c5d8d94a3
View
@@ -1,8 +1,21 @@
-0.1.01 / 2011-06-24
-===================
+0.1.2 / 2011-06-30
+==================
+
+* Added a new client-side helper file (think ActiveSupport in Rails). Checkout the README for full details (addyosmani, paulbjensen)
+
+Bug fixes:
+
+* Multi-byte UTF8 characters now supported by asset packer (elisee)
+* We now ensure /public/assets exists on startup (pusewicz)
+* OS X Dashboard 'WebClip' user agent now recognised as friendly by the browser_check middleware (paulbjensen)
+
+
+0.1.1 / 2011-06-24
+==================
* Fixed bug in the browser check middleware (was not able to handle headless browsers)
+
0.1.00 / 2011-06-23
===================
View
@@ -1,9 +1,9 @@
![SocketStream!](https://github.com/socketstream/socketstream/raw/master/new_project/public/images/logo.png)
-Latest release: 0.1.01 ([view changelog](https://github.com/socketstream/socketstream/blob/master/HISTORY.md))
+Latest release: 0.1.2 ([view changelog](https://github.com/socketstream/socketstream/blob/master/HISTORY.md))
-Twitter: socketstream - Google Group: http://groups.google.com/group/socketstream
+Twitter: [@socketstream](http://twitter.com/#!/socketstream) - Google Group: http://groups.google.com/group/socketstream
### Introduction
@@ -12,8 +12,7 @@ SocketStream is a new full stack web framework built around the [Single-page App
Project status: Highly experimental but usable. Improving almost every day.
-Follow @socketstream for the latest developments and thinking. Website coming soon.
-
+Follow [@socketstream](http://twitter.com/#!/socketstream) for the latest developments and thinking. Website coming soon.
### Features
@@ -407,6 +406,11 @@ All Shared code is pre-loaded and added to the SS.shared API tree which may be i
**Warning** All code within /app/shared will be compressed and transmitted to the client upon initial connection. So make sure you don't include any proprietary secret sauce or use any database/filesystem calls.
+### Helpers
+
+As of 1.0.2 SocketStream comes with a number of suggested JavaScript prototype helper methods, created automatically when you make a new project. The concept is very similar to ActiveSupport in Rails; however in SocketStream client-side helpers are entirely optional. Don't want them? Just delete /lib/client/3.helpers.js and they won't come back. In the near future we will have the same set of helpers in the back-end so you can feel free to use them in shared/server code.
+
+
### Sessions
SocketStream creates a new session when a browser connects to the server for the first time, storing a session cookie on the client and the details in Redis. When the same visitor returns (or presses refresh in the browser), the session is instantly retrieved.
@@ -672,7 +676,7 @@ Right now we don't have a definitive answer, but we have a number of innovative
### Tests
-Yes, we know. At the moment there are no tests. This is bad. We are currently evaluating testing frameworks in the hope of finding one we truly like. After all, we're likely to be stuck with it for a good many years, so we need to choose carefully. We will then begin writing unit and integration tests for parts of SocketStream which are unlikely to change in the near future. Right now, any help and contributions in this area would be very much appreciated.
+Yes, we know. At the moment there are very few tests. This is bad. We are currently evaluating testing frameworks in the hope of finding one we truly like. After all, we're likely to be stuck with it for a good many years, so we need to choose carefully. We will then begin writing unit and integration tests for parts of SocketStream which are unlikely to change in the near future. Right now, any help and contributions in this area would be very much appreciated.
### Known Issues
@@ -732,11 +736,15 @@ Q: Will websockets work in Opera?
A: As of this writing websockets is supported but turned off by default in Opera. In order for Opera 11 to run websockets apps you need to turn it on in the settings. Do "opera:config#Enable%20WebSockets" in the address field and hit enter. Check "Enable websockets" Save and you are good to go.
+### Core Team
-### Contributors
-
-* Owen Barnes (socketstream)
+* Owen Barnes (socketstream & owenb)
* Paul Jensen (paulbjensen)
+* Alan Milford (alz)
+* Addy Osmani (addyosmani)
+
+
+### Contributing
We welcome contributions from forward-thinking hackers keen to redefine what's possible on the web. Big, bold ideas, unconstrained by frameworks and concepts from the past will always be welcome.
@@ -749,7 +757,7 @@ If you wish to discuss an idea, or want to chat about anything else, email us at
### Credits
-Thanks to Guillermo Rauch (Socket.IO), TJ Holowaychuk (Stylus, Jade), Jeremy Ashkenas (CoffeeScript), Mihai Bazon (UglifyJS), Isaac Schlueter (NPM), Salvatore Sanfilippo (Redis) and the many others who's amazing work has made SocketStream possible.
+Thanks to Guillermo Rauch (Socket.IO), TJ Holowaychuk (Stylus, Jade), Jeremy Ashkenas (CoffeeScript), Mihai Bazon (UglifyJS), Isaac Schlueter (NPM), Salvatore Sanfilippo (Redis) and the many others who's amazing work has made SocketStream possible. Special thanks to Ryan Dahl (creator of node.js) for the inspiration to do things differently.
### Thanks!
View
@@ -17,6 +17,8 @@ watch_dirs = [
["#{__dirname}/../client", 'js', 'system'],
]
+default_directory_mode = 0755
+
# Load Asset sub-modules
exports.pack = require('./pack.coffee').init(@).pack
exports.compile = require('./compile.coffee').init(@).compile
@@ -62,6 +64,7 @@ ensureAssetsExist = ->
unless exports.files.js.lib? and exports.files.css.lib?
util.log "Generating essential asset files to get you started..."
try
+ ensurePublicPathExists()
exports.pack.libs()
SS.internal.state.save()
SS.internal.state.last_known = SS.internal.state.current()
@@ -88,4 +91,9 @@ findAssets = (cb) ->
f = exports.files[ext]
f[type] = file
cb()
-
+
+ensurePublicPathExists = ->
+ try
+ fs.mkdirSync(exports.public_path, default_directory_mode)
+ catch e
+ throw(e) unless e.code == 'EEXIST'

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -1,9 +1,3 @@
-// These extensions affect ALL client side objects. Be very careful about introducing new ones as they may break existing client-side libraries
-
-Array.prototype.include = function(value){ return(this.indexOf(value) != -1); };
-Array.prototype.any = function(){ return(this.length > 0); };
-
-
// Helper methods used by SocketStream to get and set session cookies
// Cookies are set by the browser, not via the server in HTTP headers to allow full caching of the static index.html file
@@ -0,0 +1,20 @@
+Copyright (c) 2008-2011 Pivotal Labs
+
+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.
@@ -0,0 +1,190 @@
+jasmine.TrivialReporter = function(doc) {
+ this.document = doc || document;
+ this.suiteDivs = {};
+ this.logRunningSpecs = false;
+};
+
+jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
+ var el = document.createElement(type);
+
+ for (var i = 2; i < arguments.length; i++) {
+ var child = arguments[i];
+
+ if (typeof child === 'string') {
+ el.appendChild(document.createTextNode(child));
+ } else {
+ if (child) { el.appendChild(child); }
+ }
+ }
+
+ for (var attr in attrs) {
+ if (attr == "className") {
+ el[attr] = attrs[attr];
+ } else {
+ el.setAttribute(attr, attrs[attr]);
+ }
+ }
+
+ return el;
+};
+
+jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
+ var showPassed, showSkipped;
+
+ this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
+ this.createDom('div', { className: 'banner' },
+ this.createDom('div', { className: 'logo' },
+ this.createDom('span', { className: 'title' }, "Jasmine"),
+ this.createDom('span', { className: 'version' }, runner.env.versionString())),
+ this.createDom('div', { className: 'options' },
+ "Show ",
+ showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
+ showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
+ )
+ ),
+
+ this.runnerDiv = this.createDom('div', { className: 'runner running' },
+ this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
+ this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
+ this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
+ );
+
+ this.document.body.appendChild(this.outerDiv);
+
+ var suites = runner.suites();
+ for (var i = 0; i < suites.length; i++) {
+ var suite = suites[i];
+ var suiteDiv = this.createDom('div', { className: 'suite' },
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
+ this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
+ this.suiteDivs[suite.id] = suiteDiv;
+ var parentDiv = this.outerDiv;
+ if (suite.parentSuite) {
+ parentDiv = this.suiteDivs[suite.parentSuite.id];
+ }
+ parentDiv.appendChild(suiteDiv);
+ }
+
+ this.startedAt = new Date();
+
+ var self = this;
+ showPassed.onclick = function(evt) {
+ if (showPassed.checked) {
+ self.outerDiv.className += ' show-passed';
+ } else {
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
+ }
+ };
+
+ showSkipped.onclick = function(evt) {
+ if (showSkipped.checked) {
+ self.outerDiv.className += ' show-skipped';
+ } else {
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
+ }
+ };
+};
+
+jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
+ var results = runner.results();
+ var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
+ this.runnerDiv.setAttribute("class", className);
+ //do it twice for IE
+ this.runnerDiv.setAttribute("className", className);
+ var specs = runner.specs();
+ var specCount = 0;
+ for (var i = 0; i < specs.length; i++) {
+ if (this.specFilter(specs[i])) {
+ specCount++;
+ }
+ }
+ var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
+ message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
+ this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
+
+ this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
+};
+
+jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
+ var results = suite.results();
+ var status = results.passed() ? 'passed' : 'failed';
+ if (results.totalCount === 0) { // todo: change this to check results.skipped
+ status = 'skipped';
+ }
+ this.suiteDivs[suite.id].className += " " + status;
+};
+
+jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
+ if (this.logRunningSpecs) {
+ this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
+ }
+};
+
+jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
+ var results = spec.results();
+ var status = results.passed() ? 'passed' : 'failed';
+ if (results.skipped) {
+ status = 'skipped';
+ }
+ var specDiv = this.createDom('div', { className: 'spec ' + status },
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
+ this.createDom('a', {
+ className: 'description',
+ href: '?spec=' + encodeURIComponent(spec.getFullName()),
+ title: spec.getFullName()
+ }, spec.description));
+
+
+ var resultItems = results.getItems();
+ var messagesDiv = this.createDom('div', { className: 'messages' });
+ for (var i = 0; i < resultItems.length; i++) {
+ var result = resultItems[i];
+
+ if (result.type == 'log') {
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
+ } else if (result.type == 'expect' && result.passed && !result.passed()) {
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
+
+ if (result.trace.stack) {
+ messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
+ }
+ }
+ }
+
+ if (messagesDiv.childNodes.length > 0) {
+ specDiv.appendChild(messagesDiv);
+ }
+
+ this.suiteDivs[spec.suite.id].appendChild(specDiv);
+};
+
+jasmine.TrivialReporter.prototype.log = function() {
+ var console = jasmine.getGlobal().console;
+ if (console && console.log) {
+ if (console.log.apply) {
+ console.log.apply(console, arguments);
+ } else {
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
+ }
+ }
+};
+
+jasmine.TrivialReporter.prototype.getLocation = function() {
+ return this.document.location;
+};
+
+jasmine.TrivialReporter.prototype.specFilter = function(spec) {
+ var paramMap = {};
+ var params = this.getLocation().search.substring(1).split('&');
+ for (var i = 0; i < params.length; i++) {
+ var p = params[i].split('=');
+ paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
+ }
+
+ if (!paramMap.spec) {
+ return true;
+ }
+ return spec.getFullName().indexOf(paramMap.spec) === 0;
+};
Oops, something went wrong.

0 comments on commit 33c2d26

Please sign in to comment.