From 43b65dd066588ddeab729ad0160c8d6ced7da9b1 Mon Sep 17 00:00:00 2001
From: Eric Martindale
Date: Sun, 5 Apr 2015 19:51:37 -0400
Subject: [PATCH 1/6] Add support for editing shows.
---
decentralize.js | 57 +++++++++++++++++++++++--------------------------
lib/Engine.js | 37 +++++++++++++++++++++++++++++---
package.json | 1 +
3 files changed, 62 insertions(+), 33 deletions(-)
diff --git a/decentralize.js b/decentralize.js
index 15c98a6..8a767fc 100644
--- a/decentralize.js
+++ b/decentralize.js
@@ -6,9 +6,9 @@ var procure = require('procure');
var Maki = require('maki');
var Soundcloud = require('./lib/Soundcloud');
var Engine = require('./lib/Engine');
-var WebSocket = require('ws');
+var Sessions = require('maki-sessions');
-var jsonpatch = require('fast-json-patch');
+var rest = require('restler');
var home = 'https://' + config.service.authority;
@@ -18,13 +18,16 @@ source.authority = source.host + (([80, 443].indexOf( parseInt(source.port) ) ==
var decentralize = new Maki( config );
var soundcloud = new Soundcloud( config.soundcloud );
+var sessions = new Sessions();
+decentralize.use( sessions );
+
Show = decentralize.define('Show', {
attributes: {
title: { type: String , slug: true },
slug: { type: String },
recorded: { type: Date },
released: { type: Date , default: Date.now , required: true },
- description: { type: String },
+ description: { type: String , format: 'markdown' },
audio: { type: String },
// TODO: replace with a sources list.
youtube: { type: String }
@@ -77,6 +80,25 @@ procure( source.proto + '://' + source.authority + '/shows/decentralize', functi
return next();
}
});
+ decentralize.app.get('/shows/:showSlug/edit', function(req, res, next) {
+ Show.get({ slug: req.param('showSlug') }, function(err, show) {
+ return res.render('show-edit', {
+ item: show
+ });
+ });
+ });
+ decentralize.app.post('/shows/:showSlug', function(req, res, next) {
+ rest.patch( source.proto + '://' + source.authority + '/recordings/' + req.param('showSlug') , {
+ headers: {
+ Accept: 'application/json'
+ },
+ data: req.body
+ }).on('complete', function(data, request) {
+ if (request.statusCode !== 200) return res.error('Editing failed');
+ req.flash('success', 'Content edited successfully!');
+ return res.redirect('/shows/' + req.param('showSlug'));
+ });
+ });
decentralize.app.get('/rss', function(req, res, next) {
res.redirect( 301 , '/feed' );
});
@@ -90,38 +112,13 @@ procure( source.proto + '://' + source.authority + '/shows/decentralize', functi
});
});
- // subscribe to updates to important things.
- // mainly, recordings
- var ws = new WebSocket(source.sockets + source.authority + '/recordings');
- ws.on('error', function(err) {
- console.error( err );
- });
- ws.on('message', function(data) {
- console.log('DATAGRAM:' , data );
- var msg = JSON.parse( data );
- if (msg.method === 'patch') {
- if (msg.params.channel === '/recordings') {
- jsonpatch.apply( decentralize.resources['Show'].data , msg.params.ops );
- }
-
- if (msg.params.channel.match(/\/recordings\/(.*)/)) {
- var recordings = decentralize.resources['Show'].data;
- for (var i = 0; i < recordings.length; i++) {
- if (msg.params.channel === '/recordings/' + recordings[ i ].slug ) {
- jsonpatch.apply( recordings[ i ] , msg.params.ops );
- }
- }
- }
-
- }
- });
-
- var engine = new Engine( config );
+ var engine = new Engine( config , decentralize );
setInterval(function() {
engine.sync();
}, /*/ 2500 /*/ 1 * 3600 * 1000 /**/ );
engine.sync();
+ engine.subscribe();
});
diff --git a/lib/Engine.js b/lib/Engine.js
index a4638c4..64d0cea 100644
--- a/lib/Engine.js
+++ b/lib/Engine.js
@@ -4,13 +4,44 @@ var request = require('request');
var jsonpatch = require('fast-json-patch');
var contentDisposition = require('content-disposition');
+var WebSocket = require('ws');
var Soundcloud = require('./Soundcloud');
var Form = require('form-data');
-function Engine( config ) {
+function Engine( config , decentralize ) {
this.config = config;
+ this.decentralize = decentralize;
this.soundcloud = new Soundcloud( config.soundcloud );
-}
+};
+
+Engine.prototype.subscribe = function( cb ) {
+ var self = this;
+ // subscribe to updates to important things.
+ // mainly, recordings
+ var ws = new WebSocket( self.config.source.sockets + self.config.source.authority + '/recordings');
+ ws.on('error', function(err) {
+ console.error( err );
+ });
+ ws.on('message', function(data) {
+ console.log('DATAGRAM:' , data );
+ var msg = JSON.parse( data );
+ if (msg.method === 'patch') {
+ if (msg.params.channel === '/recordings') {
+ jsonpatch.apply( self.decentralize.resources['Show'].data , msg.params.ops );
+ }
+
+ if (msg.params.channel.match(/\/recordings\/(.*)/)) {
+ var recordings = self.decentralize.resources['Show'].data;
+ for (var i = 0; i < recordings.length; i++) {
+ if (msg.params.channel === '/recordings/' + recordings[ i ].slug ) {
+ jsonpatch.apply( recordings[ i ] , msg.params.ops );
+ }
+ }
+ }
+
+ }
+ });
+};
Engine.prototype.sync = function( cb ) {
if (!cb) var cb = new Function();
@@ -90,6 +121,6 @@ Engine.prototype.sync = function( cb ) {
});
});
});
-}
+};
module.exports = Engine;
diff --git a/package.json b/package.json
index 25aa7e0..47d5fdb 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"form-data": "^0.2.0",
"lodash": "^3.3.0",
"maki": "git://github.com/martindale/maki",
+ "maki-sessions": "^0.1.0",
"node-torrent-stream": "git://github.com/unusualbob/node-torrent-stream",
"procure": "^0.1.3",
"request": "^2.53.0",
From 938bd4097bcd05fd18a6ff99fe7caebdc9a18e2f Mon Sep 17 00:00:00 2001
From: Eric Martindale
Date: Sun, 5 Apr 2015 20:00:51 -0400
Subject: [PATCH 2/6] Move resources into dedicated folder.
---
decentralize.js | 30 ++----------------------------
resources/Index.js | 12 ++++++++++++
resources/Show.js | 17 +++++++++++++++++
3 files changed, 31 insertions(+), 28 deletions(-)
create mode 100644 resources/Index.js
create mode 100644 resources/Show.js
diff --git a/decentralize.js b/decentralize.js
index 8a767fc..c24a6e8 100644
--- a/decentralize.js
+++ b/decentralize.js
@@ -21,34 +21,8 @@ var soundcloud = new Soundcloud( config.soundcloud );
var sessions = new Sessions();
decentralize.use( sessions );
-Show = decentralize.define('Show', {
- attributes: {
- title: { type: String , slug: true },
- slug: { type: String },
- recorded: { type: Date },
- released: { type: Date , default: Date.now , required: true },
- description: { type: String , format: 'markdown' },
- audio: { type: String },
- // TODO: replace with a sources list.
- youtube: { type: String }
- },
- names: { get: 'item' },
- source: source.proto + '://' + source.authority + '/recordings',
- icon: 'sound'
-});
-
-Index = decentralize.define('Index', {
- name: 'Index',
- routes: { query: '/' },
- templates: { query: 'index' },
- requires: {
- 'Show': {
- filter: {}
- }
- },
- static: true,
- internal: true
-});
+Show = decentralize.define('Show', require('./resources/Show') );
+Index = decentralize.define('Index', require('./resources/Index') );
procure( source.proto + '://' + source.authority + '/shows/decentralize', function(err, show) {
if (err) return console.error(err);
diff --git a/resources/Index.js b/resources/Index.js
new file mode 100644
index 0000000..a56349b
--- /dev/null
+++ b/resources/Index.js
@@ -0,0 +1,12 @@
+module.exports = {
+ name: 'Index',
+ routes: { query: '/' },
+ templates: { query: 'index' },
+ requires: {
+ 'Show': {
+ filter: {}
+ }
+ },
+ static: true,
+ internal: true
+};
diff --git a/resources/Show.js b/resources/Show.js
new file mode 100644
index 0000000..5996214
--- /dev/null
+++ b/resources/Show.js
@@ -0,0 +1,17 @@
+var source = require('../config').source;
+
+module.exports = {
+ attributes: {
+ title: { type: String , slug: true },
+ slug: { type: String },
+ recorded: { type: Date },
+ released: { type: Date , default: Date.now , required: true },
+ description: { type: String , format: 'markdown' },
+ audio: { type: String },
+ // TODO: replace with a sources list.
+ youtube: { type: String }
+ },
+ names: { get: 'item' },
+ source: source.proto + '://' + source.authority + '/recordings',
+ icon: 'sound'
+}
From 8d428194c5acc8ad32e6334ab1bf833fe4c80810 Mon Sep 17 00:00:00 2001
From: Eric Martindale
Date: Sun, 5 Apr 2015 21:54:17 -0400
Subject: [PATCH 3/6] Begin to add various auth items.
---
decentralize.js | 10 +++++++++-
package.json | 3 ++-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/decentralize.js b/decentralize.js
index c24a6e8..b77b3e9 100644
--- a/decentralize.js
+++ b/decentralize.js
@@ -6,19 +6,27 @@ var procure = require('procure');
var Maki = require('maki');
var Soundcloud = require('./lib/Soundcloud');
var Engine = require('./lib/Engine');
+
var Sessions = require('maki-sessions');
+var ProxAuth = require('maki-auth-proxy');
+var Policies = require('maki-auth-tokens');
var rest = require('restler');
var home = 'https://' + config.service.authority;
var source = config.source;
-source.authority = source.host + (([80, 443].indexOf( parseInt(source.port) ) === -1) ? ':' + source.port : '');
+source.authority = source.host;
+if ([80, 443].indexOf( parseInt(source.port) ) === -1) {
+ source.authority += ':' + source.port;
+}
var decentralize = new Maki( config );
var soundcloud = new Soundcloud( config.soundcloud );
+var policies = new Policies();
var sessions = new Sessions();
+
decentralize.use( sessions );
Show = decentralize.define('Show', require('./resources/Show') );
diff --git a/package.json b/package.json
index 47d5fdb..a39400b 100644
--- a/package.json
+++ b/package.json
@@ -23,10 +23,11 @@
"dependencies": {
"async": "^0.9.0",
"content-disposition": "^0.5.0",
- "fast-json-patch": "^0.5.1",
+ "fast-json-patch": "^0.5.2",
"form-data": "^0.2.0",
"lodash": "^3.3.0",
"maki": "git://github.com/martindale/maki",
+ "maki-auth-proxy": "0.0.0",
"maki-sessions": "^0.1.0",
"node-torrent-stream": "git://github.com/unusualbob/node-torrent-stream",
"procure": "^0.1.3",
From 4539b4acd770a845764396b4bbf55655026ebf58 Mon Sep 17 00:00:00 2001
From: Eric Martindale
Date: Sun, 5 Apr 2015 22:43:26 -0400
Subject: [PATCH 4/6] Add form for editing shows.
---
views/show-edit.jade | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 views/show-edit.jade
diff --git a/views/show-edit.jade b/views/show-edit.jade
new file mode 100644
index 0000000..7e87b2b
--- /dev/null
+++ b/views/show-edit.jade
@@ -0,0 +1,25 @@
+extends layouts/default
+
+block content
+ h2 Edit
+
+ form.ui.form(action="/shows/#{item.slug}", method="POST")
+ input(type="hidden", name="method", value="PATCH")
+
+ .field
+ label Description
+ textarea(name="description", rows="50") #{item.description}
+
+ .field
+ label YouTube Video ID
+ input(type="text", name="youtube", value="#{item.youtube || ''}")
+
+ .two.fields
+ .field
+ label decentral.fm Username
+ input(type="text", name="username")
+ .field
+ label decentral.fm Password
+ input(type="password", name="password")
+
+ button.ui.submit.button(type="submit") Edit »
From 6c2d19b64c883fd3014cf72697361f413f8e15a8 Mon Sep 17 00:00:00 2001
From: Eric Martindale
Date: Sun, 5 Apr 2015 23:03:57 -0400
Subject: [PATCH 5/6] Add support for markdown editing and preview.
---
public/js/marked.min.js | 6 ++++++
views/layouts/default.jade | 1 +
views/show-edit.jade | 18 +++++++++++++++++-
3 files changed, 24 insertions(+), 1 deletion(-)
create mode 100644 public/js/marked.min.js
diff --git a/public/js/marked.min.js b/public/js/marked.min.js
new file mode 100644
index 0000000..a5164c4
--- /dev/null
+++ b/public/js/marked.min.js
@@ -0,0 +1,6 @@
+/**
+ * marked - a markdown parser
+ * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
+ * https://github.com/chjj/marked
+ */
+(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script"||cap[1]==="style",text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(this.smartypants(cap[0]));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"—").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i.5){ch="x"+ch.toString(16)}out+=""+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return""+(escaped?code:escape(code,true))+"\n
"}return''+(escaped?code:escape(code,true))+"\n
\n"};Renderer.prototype.blockquote=function(quote){return"\n"+quote+"
\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+""+type+">\n"};Renderer.prototype.listitem=function(text){return""+text+"\n"};Renderer.prototype.paragraph=function(text){return""+text+"
\n"};Renderer.prototype.table=function(header,body){return"\n"+"\n"+header+"\n"+"\n"+body+"\n"+"
\n"};Renderer.prototype.tablerow=function(content){return"\n"+content+"
\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+""+type+">\n"};Renderer.prototype.strong=function(text){return""+text+""};Renderer.prototype.em=function(text){return""+text+""};Renderer.prototype.codespan=function(text){return""+text+""};Renderer.prototype.br=function(){return this.options.xhtml?"
":"
"};Renderer.prototype.del=function(text){return""+text+""};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0){return""}}var out='"+text+"";return out};Renderer.prototype.image=function(href,title,text){var out='
":">";return out};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i/g,">").replace(/"/g,""").replace(/'/g,"'")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;iAn error occured:
"+escape(e.message+"",true)+"
"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
\ No newline at end of file
diff --git a/views/layouts/default.jade b/views/layouts/default.jade
index 1a638ce..07d09f1 100644
--- a/views/layouts/default.jade
+++ b/views/layouts/default.jade
@@ -36,6 +36,7 @@ html.no-js
script(src="/js/highlight.pack.js")
script(src="/js/uuid.js")
script(src="/js/jsonrpc.js")
+ script(src="/js/marked.min.js")
script(src="/js/maki.js")
diff --git a/views/show-edit.jade b/views/show-edit.jade
index 7e87b2b..2d2a1a1 100644
--- a/views/show-edit.jade
+++ b/views/show-edit.jade
@@ -1,6 +1,12 @@
extends layouts/default
block content
+
+ h1 #{item.title}
+
+ h2 Preview
+ .preview !{ markdown( item.description ) }
+
h2 Edit
form.ui.form(action="/shows/#{item.slug}", method="POST")
@@ -8,7 +14,7 @@ block content
.field
label Description
- textarea(name="description", rows="50") #{item.description}
+ textarea(name="description", style="height: 20em;") #{item.description}
.field
label YouTube Video ID
@@ -23,3 +29,13 @@ block content
input(type="password", name="password")
button.ui.submit.button(type="submit") Edit »
+
+block scripts
+ script.
+ $('textarea[name=description]').keyup( renderPreview );
+
+ function renderPreview() {
+ var value = this.value;
+ var rendered = marked( value );
+ $('.preview').html( rendered );
+ }
From 662a42ed03185d7912215ac3cc7755fae90c966e Mon Sep 17 00:00:00 2001
From: Eric Martindale
Date: Sun, 5 Apr 2015 23:41:29 -0400
Subject: [PATCH 6/6] More robust socket handler.
---
lib/Engine.js | 43 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 40 insertions(+), 3 deletions(-)
diff --git a/lib/Engine.js b/lib/Engine.js
index 64d0cea..e437b74 100644
--- a/lib/Engine.js
+++ b/lib/Engine.js
@@ -8,21 +8,58 @@ var WebSocket = require('ws');
var Soundcloud = require('./Soundcloud');
var Form = require('form-data');
+var TRY_TIMES = [ 100 , 250 , 2500 , 10000 , 60 * 1000 , 5 * 60 * 1000 , 10 * 60 * 1000 , 60 * 60 * 1000 ];
+
function Engine( config , decentralize ) {
this.config = config;
this.decentralize = decentralize;
this.soundcloud = new Soundcloud( config.soundcloud );
+
+ this.tries = 0;
+
};
Engine.prototype.subscribe = function( cb ) {
var self = this;
// subscribe to updates to important things.
// mainly, recordings
- var ws = new WebSocket( self.config.source.sockets + self.config.source.authority + '/recordings');
- ws.on('error', function(err) {
+
+ console.log('initializing socket...');
+
+ try {
+ self.ws = new WebSocket( self.config.source.sockets + self.config.source.authority + '/recordings');
+ } catch (e) {
+ console.log('exception connecting');
+ }
+
+ self.ws.on('error', function(err) {
console.error( err );
});
- ws.on('message', function(data) {
+ self.ws.on('open', function() {
+ self.tries = 0;
+ console.log('socket now open.');
+ });
+ self.ws.on('close', function() {
+ console.log('socket closed wat');
+
+ function attemptReconnect() {
+ self.ws.removeAllListeners('open');
+ self.ws.removeAllListeners('close');
+ self.ws.removeAllListeners('error');
+ self.ws.removeAllListeners('message');
+
+ delete self.ws;
+
+ self.subscribe();
+
+ setTimeout( attemptReconnect , TRY_TIMES[ self.tries++ ] );
+
+ };
+
+ attemptReconnect();
+
+ });
+ self.ws.on('message', function(data) {
console.log('DATAGRAM:' , data );
var msg = JSON.parse( data );
if (msg.method === 'patch') {