diff --git a/ape/hood.hoon b/ape/hood.hoon index 479517163..9432d9d28 100644 --- a/ape/hood.hoon +++ b/ape/hood.hoon @@ -127,6 +127,7 @@ ++ poke-kiln-overload (wrap poke-overload):from-kiln ++ poke-kiln-unmount (wrap poke-unmount):from-kiln ++ poke-kiln-unsync (wrap poke-unsync):from-kiln +++ poke-write-comment (wrap poke-comment):from-write ++ poke-write-paste (wrap poke-paste):from-write ++ poke-write-tree (wrap poke-tree):from-write ++ poke-write-wipe (wrap poke-wipe):from-write diff --git a/lib/write.hoon b/lib/write.hoon index 83013eed7..15278529b 100644 --- a/lib/write.hoon +++ b/lib/write.hoon @@ -48,6 +48,12 @@ |= [typ=?(%hoon %md %txt) txt=@t] ^+ abet (poke--data [`typ /web/paste/(scot %da now)] %mime / (taco txt)) :: +++ poke-comment + |= [pax=path txt=@t] ^+ abet + =. pax [%web (welp pax /(scot %da now))] + =. txt (rap 3 (scot %p src) ': ' txt ~) + (poke--data [`%comment-md pax] %mime / (taco txt)) +:: ++ poke--data |= [[ext=(unit ,@t) pax=path] dat=data] ^+ abet ?~ ext $(ext [~ -.dat]) @@ -59,8 +65,8 @@ :: ++ made |= [pax=wire @ res=gage] ^+ abet - ?. =(our src) - ~|(foreign-write/[our=our src=src] !!) + :: ?. =(our src) + :: ~|(foreign-write/[our=our src=src] !!) ?+ -.res ~|(gage/-.res !!) %| (mean p.res) %& =- abet:(emit %info write/~ our -) diff --git a/mar/comment-md.hoon b/mar/comment-md.hoon new file mode 100644 index 000000000..820866bf3 --- /dev/null +++ b/mar/comment-md.hoon @@ -0,0 +1,6 @@ +:: +:::: /hoon/core/md/pro + :: +/? 314 +:: +// /===/mar/md :: alias diff --git a/mar/write/comment.hoon b/mar/write/comment.hoon new file mode 100644 index 000000000..e1592f0d1 --- /dev/null +++ b/mar/write/comment.hoon @@ -0,0 +1,12 @@ +:: +:::: /hoon/core/save/mar + :: +!: +|_ [pax=path txt=@t] +++ grab + |% + ++ noun ,[path @t] + ++ json + (corl need =>(jo (ot pax/(su fel:stab) txt/so ~))) + -- +-- diff --git a/ren/tree/combine.hoon b/ren/tree/combine.hoon index 49676d178..e463fb97c 100644 --- a/ren/tree/combine.hoon +++ b/ren/tree/combine.hoon @@ -2,11 +2,20 @@ /= mime /mime/ /= body /tree-elem/ /= sect /tree-index/ -/= meta /|(/front/ /~[~]) /= snip /&snip&elem&/tree-elem/ +/= meta /^ (map span cord) /|(/front/ /~[~]) +/= comt /^ (list (pair time manx)) + /@ /&elem&md&mime&/comment-md/ !: ^- tree-include =+ rj=react-to-json:react -=+ fj=|=(atr=(map span span) [%o (~(run by atr) |=(a=span s/a))]) =+ ij=(map-to-json:tree |=(a=path (crip (spud a))) |=(a=marl [%a (turn a rj)])) -[mime (rj body) (rj /h1 hed.snip) (rj /div tal.snip) (fj meta) (ij sect)] +=+ cj=|=([a=time b=manx] (jobe time/(jode a) body/(rj b) ~)) +:* mime + (rj body) + (rj /h1 hed.snip) :: head + (rj /div tal.snip) :: snip + [%o (~(run by meta) |=(a=span s/a))] + (ij sect) + [%a (turn (sort comt lor) cj)] +== diff --git a/ren/tree/hymn.hoon b/ren/tree/hymn.hoon index 4deb12433..150b3c859 100644 --- a/ren/tree/hymn.hoon +++ b/ren/tree/hymn.hoon @@ -3,8 +3,11 @@ /- tree-include /= dat /% /tree-json/ :: default include /= tub /$ |=([bem=beam *] (flop s.bem)) -/= aut /; |=(gas=epic (~(has ju aut.ced.gas) %$ (scot %p p.bem.gas))) - /$ fuel +/= aut + /$ %+ cork fuel :: after parsing params, + |= gas=epic ^- ? :: check that the fcgi + %+ lien (~(tap in (~(get ju aut.ced.gas) %$))) :: has an identity + |=(a=span !=(%pawn (slav %p a))) :: which isn't a comet :: !: :::: @@ -31,8 +34,8 @@ ;script(type "text/javascript", src "/tree/main.js"); ;script(type "text/javascript", src "//cdnjs.cloudflare.com/ajax/libs/". "codemirror/4.3.0/mode/markdown/markdown.min.js"); - ;* ?. aut ~ - [;script(type "text/javascript", src "/~/as/own/~/at/lib/js/urb.js");]~ + ;script(type "text/javascript", src "{?.(aut "" "/~~")}". + "/~/at/lib/js/urb.js"); == ;body ;script(type "text/javascript"): window.tree = {(pojo (joba %data dat))} @@ -43,4 +46,4 @@ == == == -== \ No newline at end of file +== diff --git a/ren/tree/json.hoon b/ren/tree/json.hoon index f1df613e7..a2a4666e8 100644 --- a/ren/tree/json.hoon +++ b/ren/tree/json.hoon @@ -18,9 +18,11 @@ [%name %t] [%path %t] [%spur %t] + :: + [%comt %j] + [%head %r] [%sect %j] [%snip %r] - [%head %r] [%body %r] [%meta %j] [%mime %m] @@ -52,6 +54,7 @@ %name (from-type +.a ?^(s.bem i.s.bem q.bem)) %path (from-type +.a (crip (spud (flop s.bem)))) %spur (from-type +.a (crip (spud s.bem))) + %comt (from-type +.a comt.dat) %head (from-type +.a head.dat) %snip (from-type +.a snip.dat) %sect (from-type +.a sect.dat) @@ -69,7 +72,8 @@ :: [tree .] ^- json +=+ default='spur.t_mime.m_body.r_comt.j_kids.name.t' =+ ^= schem - =+ seh=(fall (~(get by qix.gas) 'q') 'spur.t_mime.m_body.r_kids.name.t') + =+ seh=(fall (~(get by qix.gas) 'q') default) ~|(bad-noun/seh ;;(schema (rash seh read-schem))) (from-queries bem.gas(s but.gas) (to-queries schem)) diff --git a/sur/tree-include.hoon b/sur/tree-include.hoon index e8733ef6d..b0330376d 100644 --- a/sur/tree-include.hoon +++ b/sur/tree-include.hoon @@ -5,4 +5,5 @@ $: mime=mime snip=json meta=json sect=json + comt=json == diff --git a/web/lib/js/urb.js b/web/lib/js/urb.js index 9cf5d2004..948831446 100644 --- a/web/lib/js/urb.js +++ b/web/lib/js/urb.js @@ -282,14 +282,12 @@ window.urb.util = { if(spur === '/') spur = '' pathname = pathname || window.location.pathname if(pathname[0] == '/') pathname = pathname.slice(1) - if(pathname[0] != '~' && pathname[0] != '='){ - return spur - } pathname = pathname.split("/") var pref, pred, prec, base = "" - while(base += "/"+(pref = pathname.shift()), pathname.length>0){ - if(pref[0] !== '~') break; + while(pref = pathname.shift(), pathname.length>0){ + if(pref[0] != '~' && pref[0] != '=') break; + base += "/"+pref; if(pref === "~~") continue; base += "/"+(pred = pathname.shift()) if(/[a-z\-]+/.test(pref.slice(1))){ diff --git a/web/tree/main.js b/web/tree/main.js index aa3d533f0..7b957e570 100644 --- a/web/tree/main.js +++ b/web/tree/main.js @@ -43,6 +43,9 @@ module.exports = { components: components }); }, + addComment: function(path, text) { + return TreePersistence.put("write-comment", path, text); + }, setCurr: function(path) { return TreeDispatcher.handleViewAction({ type: "setCurr", @@ -73,6 +76,7 @@ module.exports = { }; + },{"../dispatcher/Dispatcher.coffee":18,"../persistence/TreePersistence.coffee":20}],2:[function(require,module,exports){ var BodyComponent, Dpad, Nav, Sibs, TreeActions, TreeStore, a, button, clas, div, li, query, reactify, recl, ref, rend, ul, util; @@ -338,6 +342,7 @@ module.exports = query({ })); + },{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":21,"../utils/util.coffee":23,"./Async.coffee":3,"./BodyComponent.coffee":4,"./DpadComponent.coffee":7,"./Reactify.coffee":13,"./SibsComponent.coffee":16,"classnames":24}],3:[function(require,module,exports){ var TreeActions, TreeStore, _load, code, div, recl, ref, span; @@ -448,22 +453,33 @@ module.exports = function(queries, Child, load) { }; + },{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":21,"./LoadComponent.coffee":11}],4:[function(require,module,exports){ -var a, clas, div, extras, img, p, query, reactify, recl, ref, rele, util; +var Comment, TreeActions, a, clas, div, extras, img, input, load, p, query, reactify, recl, ref, rele, util; clas = require('classnames'); +load = require('./LoadComponent.coffee'); + query = require('./Async.coffee'); reactify = require('./Reactify.coffee'); +TreeActions = require('../actions/TreeActions.coffee'); + util = require('../utils/util.coffee'); recl = React.createClass; rele = React.createElement; -ref = React.DOM, div = ref.div, p = ref.p, img = ref.img, a = ref.a; +ref = React.DOM, div = ref.div, p = ref.p, img = ref.img, a = ref.a, input = ref.input; + +Comment = function(arg) { + var body, time; + time = arg.time, body = arg.body; + return div({}, "" + (new Date(time)), reactify(body)); +}; extras = { spam: recl({ @@ -523,17 +539,46 @@ extras = { if (next) { return div({ className: "link-next" - }, [ - a({ - href: this.props.path + "/" + next.name - }, "Next: " + next.meta.title) - ]); + }, a({ + href: this.props.path + "/" + next.name + }, "Next: " + next.meta.title)); } } } return div({}, ""); } })), + comments: query({ + comt: 'j', + path: 't' + }, recl({ + displayName: "Comments", + getInitialState: function() { + return { + loading: false + }; + }, + onKeyDown: function(e) { + if ("Enter" === e.key) { + this.setState({ + loading: true + }); + return TreeActions.addComment(this.props.path, this.refs["in"].value); + } + }, + render: function() { + return div({}, "Add comment:", (this.state.loading ? rele(load) : input({ + className: "comment", + type: "text", + ref: "in", + onKeyDown: this.onKeyDown + })), this.props.comt.map(function(props, key) { + return rele(Comment, _.extend({ + key: key + }, props)); + })); + } + })), footer: recl({ displayName: "Footer", render: function() { @@ -576,13 +621,14 @@ module.exports = query({ }), reactify(this.props.body), extra('next', { dataPath: this.props.sein, curr: this.props.name - }), extra('footer')) + }), extra('comments'), extra('footer')) ]); } })); -},{"../utils/util.coffee":23,"./Async.coffee":3,"./Reactify.coffee":13,"classnames":24}],5:[function(require,module,exports){ + +},{"../actions/TreeActions.coffee":1,"../utils/util.coffee":23,"./Async.coffee":3,"./LoadComponent.coffee":11,"./Reactify.coffee":13,"classnames":24}],5:[function(require,module,exports){ var div, recl, ref, textarea; recl = React.createClass; @@ -605,6 +651,7 @@ module.exports = recl({ }); + },{}],6:[function(require,module,exports){ var div, recl; @@ -629,6 +676,7 @@ module.exports = { }; + },{"./CodeMirror.coffee":5,"./EmailComponent.coffee":8,"./KidsComponent.coffee":9,"./ListComponent.coffee":10,"./ModuleComponent.coffee":12,"./ScriptComponent.coffee":14,"./SearchComponent.coffee":15,"./TocComponent.coffee":17}],7:[function(require,module,exports){ var a, div, recl, ref, util; @@ -682,11 +730,12 @@ module.exports = React.createFactory(recl({ return div({ className: 'dpad', key: 'dpad' - }, [this.renderUp(), this.renderArrows()]); + }, this.renderUp(), this.renderArrows()); } })); + },{"../utils/util.coffee":23}],8:[function(require,module,exports){ var button, div, input, p, reactify, recl, ref; @@ -768,6 +817,7 @@ module.exports = recl({ }); + },{"./Reactify.coffee":13}],9:[function(require,module,exports){ var a, div, hr, li, query, reactify, recl, ref, ul; @@ -849,6 +899,7 @@ module.exports = query({ })); + },{"./Async.coffee":3,"./Reactify.coffee":13}],10:[function(require,module,exports){ var a, clas, div, h1, li, pre, query, reactify, recl, ref, span, ul, util; @@ -1006,6 +1057,7 @@ module.exports = query({ })); + },{"../utils/util.coffee":23,"./Async.coffee":3,"./Reactify.coffee":13,"classnames":24}],11:[function(require,module,exports){ var div, recl, ref, span; @@ -1044,6 +1096,7 @@ module.exports = recl({ }); + },{}],12:[function(require,module,exports){ var TreeActions, div, recl; @@ -1078,6 +1131,7 @@ module.exports = recl({ }); + },{"../actions/TreeActions.coffee":1}],13:[function(require,module,exports){ var TreeStore, Virtual, div, load, reactify, recl, ref, rele, span, walk; @@ -1148,7 +1202,7 @@ Virtual = recl({ gn = arg.gn, ga = arg.ga, c = arg.c; return rele((ref1 = components[gn]) != null ? ref1 : gn, _.extend({ key: key - }, ga), c); + }, ga), c.length ? c : void 0); }); } }); @@ -1166,6 +1220,7 @@ module.exports = _.extend(reactify, { }); + },{"../stores/TreeStore.coffee":21,"./LoadComponent.coffee":11}],14:[function(require,module,exports){ var recl, rele; @@ -1192,6 +1247,7 @@ module.exports = recl({ }); + },{}],15:[function(require,module,exports){ var a, div, input, query, reactify, recl, ref, slice = [].slice; @@ -1330,6 +1386,7 @@ module.exports = query({ })); + },{"./Async.coffee":3,"./Reactify.coffee":13}],16:[function(require,module,exports){ var a, clas, li, reactify, recl, ref, ul, util; @@ -1391,6 +1448,7 @@ module.exports = React.createFactory(recl({ })); + },{"../utils/util.coffee":23,"./Reactify.coffee":13,"classnames":24}],17:[function(require,module,exports){ var div, query, reactify, recl, slice = [].slice; @@ -1519,6 +1577,7 @@ module.exports = query({ })); + },{"./Async.coffee":3,"./Reactify.coffee":13}],18:[function(require,module,exports){ module.exports = _.extend(new Flux.Dispatcher(), { handleServerAction: function(action) { @@ -1536,6 +1595,7 @@ module.exports = _.extend(new Flux.Dispatcher(), { }); + },{}],19:[function(require,module,exports){ var rend; @@ -1557,6 +1617,7 @@ $(function() { }); + },{"./actions/TreeActions.coffee":1,"./components/AnchorComponent.coffee":2,"./components/BodyComponent.coffee":4,"./components/Components.coffee":6,"./utils/scroll.coffee":22,"./utils/util.coffee":23}],20:[function(require,module,exports){ var dedup, util; @@ -1575,12 +1636,22 @@ module.exports = { return; } dedup[url] = true; - return $.get(url, {}, function(data) { + return $.get(url, {}, function(data, status, xhr) { + urb.waspLoadedXHR.call(xhr); if (cb) { return cb(null, data); } }); }, + put: function(mark, pax, txt) { + return urb.send({ + pax: pax, + txt: txt + }, { + mark: mark, + appl: 'hood' + }); + }, encode: function(obj) { var _encode, delim; delim = function(n) { @@ -1617,6 +1688,7 @@ module.exports = { }; + },{"../utils/util.coffee":23}],21:[function(require,module,exports){ var EventEmitter, MessageDispatcher, QUERIES, TreeStore, _curr, _data, _nav, _tree, _virt, clog; @@ -1641,7 +1713,8 @@ QUERIES = { head: 'r', snip: 'r', sect: 'j', - meta: 'j' + meta: 'j', + comt: 'j' }; TreeStore = _.extend(new EventEmitter, { @@ -1881,6 +1954,7 @@ TreeStore.dispatchToken = MessageDispatcher.register(function(p) { module.exports = TreeStore; + },{"../dispatcher/Dispatcher.coffee":18,"events":25}],22:[function(require,module,exports){ var scroll; @@ -1973,6 +2047,7 @@ scroll.init(); module.exports = scroll; + },{}],23:[function(require,module,exports){ var _basepath; @@ -2022,6 +2097,7 @@ module.exports = { }; + },{}],24:[function(require,module,exports){ /*! Copyright (c) 2016 Jed Watson. @@ -2156,11 +2232,18 @@ EventEmitter.prototype.emit = function(type) { break; // slower default: - args = Array.prototype.slice.call(arguments, 1); + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; handler.apply(this, args); } } else if (isObject(handler)) { - args = Array.prototype.slice.call(arguments, 1); + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) @@ -2198,6 +2281,7 @@ EventEmitter.prototype.addListener = function(type, listener) { // Check for listener leak if (isObject(this._events[type]) && !this._events[type].warned) { + var m; if (!isUndefined(this._maxListeners)) { m = this._maxListeners; } else { @@ -2319,7 +2403,7 @@ EventEmitter.prototype.removeAllListeners = function(type) { if (isFunction(listeners)) { this.removeListener(type, listeners); - } else if (listeners) { + } else { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); @@ -2340,20 +2424,15 @@ EventEmitter.prototype.listeners = function(type) { return ret; }; -EventEmitter.prototype.listenerCount = function(type) { - if (this._events) { - var evlistener = this._events[type]; - - if (isFunction(evlistener)) - return 1; - else if (evlistener) - return evlistener.length; - } - return 0; -}; - EventEmitter.listenerCount = function(emitter, type) { - return emitter.listenerCount(type); + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; }; function isFunction(arg) {