diff --git a/lib/tree.hoon b/lib/tree.hoon index d422db0fb..96f40dd67 100644 --- a/lib/tree.hoon +++ b/lib/tree.hoon @@ -4,7 +4,8 @@ ++ baff |*([a=(unit) b=(trap)] ?^(a a *b)) ++ find-in-tree |* [paz=fist:jo fun=$+(* (unit))] - |= a=(list json) + |= jon=json + =+ a=`(list json)`~[jon] |^ (try) ++ try |. ^+ *fun @@ -17,7 +18,7 @@ ++ json-front |= a=json ^- json =- (fall `(unit json)`- ~) - %+ biff ((ar some):jo a) + %. a %+ find-in-tree (ot c/(ar some) gn/so ga/(om so) ~):jo |= [nom=span atr=(map span cord)] ^- (unit json) ?. (~(has by atr) 'urb:front') ~ diff --git a/mar/headers.hoon b/mar/headers.hoon new file mode 100644 index 000000000..8cf3bd693 --- /dev/null +++ b/mar/headers.hoon @@ -0,0 +1,31 @@ +:: +:::: /hoon/core/elem/mar + :: +/? 314 +!: +|% +++ getall + |= tag=mane + |= ele=manx ^- marl + ?: =(tag n.g.ele) ~[ele] + (zing (turn c.ele ..$)) +-- +:: +!: +|_ hed=marl +:: +++ grow :: convert to + |% + ++ mime + =< mime + |% + ++ elem ;div:"*{hed}" + ++ hymn ;html:(head:title:"headers" body:"+{elem}") :: convert to %hymn + ++ html (crip (poxo hymn)) :: convert to %html + ++ mime [/text/html (taco html)] :: convert to %mime + -- + -- +++ grab |% :: convert from + ++ noun marl :: clam from %noun + ++ elem (getall %h1) +-- -- diff --git a/mar/react-headers.hoon b/mar/react-headers.hoon new file mode 100644 index 000000000..5ea607627 --- /dev/null +++ b/mar/react-headers.hoon @@ -0,0 +1,20 @@ +:: +:::: /hoon/core/react-headers/mar + :: +/? 314 +/+ react +!: +:::: + :: +|_ hed=marl +:: +++ grow :: convert to + |% + ++ mime [/application/json (tact tape)] + ++ tape (pojo react-headers-json) + ++ react-headers-json (react-to-json ;div:"*{hed}") + -- +++ grab |% :: convert from + ++ noun marl + ++ headers |=(a=marl a) +-- -- diff --git a/pub/doc/tree.md b/pub/doc/tree.md index da8119bfa..fa6f071f0 100644 --- a/pub/doc/tree.md +++ b/pub/doc/tree.md @@ -14,12 +14,12 @@ a `getPath` method, if present (defaulting to current url), is used to determine something something coffeescript ## `/[desk]/tree/{path}.json` -tree/json.hook accepts a query string schema `q` in light noun encoding¹ +tree/json.hook accepts a query string schema `q` in light noun encoding ++ schema (dict ,[term $|(mark schema)]) ++ dict |*(a=_,* $&([a (dict a)] a)) -which is normalized and type-checked(request types are `%t` text, `%r` html-derived tree, and `%j` arbitrary json) to a `query` list of +which is normalized and type-checked to a `query` list of - `[%kids query]`, the only recursive value, which executes for all subpaths XX descent is only currently supported to a single level as a performance optimization - `[%name %t]`, the node name @@ -29,26 +29,6 @@ which is normalized and type-checked(request types are `%t` text, `%r` html-deri - `[%body %r]`, the `react-json` body - `[%meta %j]`, json frontmatter per the `mdy` mark definition -Per this specification, the current access points will be migrated: -- (json.hook)`""` to `body:'r' kids:{name:'t'}` `"?body.r__kids_name.t"` -- `"?kids"` to `kids:{name:'t' body:'r'}` `"?kids_name.t_body.r"` -- `"?snip"` to `kids:{name:'t' snip:'r' head:'r' meta:'j'}` `"?kids_name.t_snip.r_head.r_meta.j"` - -¹In the examples, - - =< (cook to-noun (cook to-tree apex)) - |% - ++ data $|(term [n=@ l=data r=data]) - ++ apex ;~(plug sym (star ;~(plug delim sym))) - ++ delim ;~(pose (cold 0 dot) (cook lent (plus cab))) - ++ to-noun |=(a=data ?@(a a [$(a l.a) $(a r.a)])) - ++ to-tree - |= [acc=data a=(list ,[p=@u q=term])] - %+ roll a =< .(acc ^acc) - |= [[n=@u v=term] acc=data] - ?@ acc [n acc v] - ?: (gth n n.acc) [n acc v] - acc(r $(acc r.acc)) - -- - -XX Curtis, this can be full coin `%many` if you wish. +The request types above are `%t` text, `%r` html-derived tree, and `%j` +arbitrary json; an example query, used by the main content renderer, is +`"q=body.r__kids_name.t"` (`body:'r' kids:{name:'t'}` ) diff --git a/pub/tree/src/js/components/AnchorComponent.coffee b/pub/tree/src/js/components/AnchorComponent.coffee index 28d8009a2..b3202d320 100644 --- a/pub/tree/src/js/components/AnchorComponent.coffee +++ b/pub/tree/src/js/components/AnchorComponent.coffee @@ -2,6 +2,7 @@ clas = require 'classnames' BodyComponent = React.createFactory require './BodyComponent.coffee' query = require './Async.coffee' +reactify = require './Reactify.coffee' TreeStore = require '../stores/TreeStore.coffee' TreeActions = require '../actions/TreeActions.coffee' @@ -37,12 +38,10 @@ Links = React.createFactory query { className = clas active: key is @props.curr (div {className,key}, (a {href,onClick:@props.onClick}, head)) - toText: (elem)-> switch - # manx: {fork: ["string", {gn:"string" ga:{dict:"string"} c:{list:"manx"}}]} - when !elem? then "" - when typeof elem == "string" then elem - when elem.gn? then (elem.c ? []).map(@toText).join "" - else throw "Bad react-json #{JSON.stringify elem}" + toText: (elem)-> reactify.walk elem, + ()->'' + (s)->s + ({c})->(c ? []).join '' ), recl displayName: "Links_loading" render: -> div {className:'links'}, @props.children, @_render() @@ -60,8 +59,8 @@ module.exports = query {sein:'t',path:'t',name:'t',next:'t',prev:'t'},recl toggleFocus: (state) -> $(@getDOMNode()).toggleClass 'focus',state - componentDidUpdate: -> @setTitle() componentWillUnmount: -> clearInterval @interval; $('body').off 'click', 'a' + componentDidUpdate: -> @setTitle() componentDidMount: -> @setTitle() @interval = setInterval @checkURL,100 diff --git a/pub/tree/src/js/components/Async.coffee b/pub/tree/src/js/components/Async.coffee index 6f1f6cc6b..1437b2fb5 100644 --- a/pub/tree/src/js/components/Async.coffee +++ b/pub/tree/src/js/components/Async.coffee @@ -51,5 +51,5 @@ module.exports = (queries, Child, load=_load)-> recl if @filterQueries()? React.createElement load, @props else React.createElement Child, - (_.merge {}, @props, @state.got), + (_.extend {}, @props, @state.got), @props.children diff --git a/pub/tree/src/js/components/BodyComponent.coffee b/pub/tree/src/js/components/BodyComponent.coffee index 62c91785a..2757ff4b1 100644 --- a/pub/tree/src/js/components/BodyComponent.coffee +++ b/pub/tree/src/js/components/BodyComponent.coffee @@ -1,10 +1,9 @@ -reactify = React.createFactory require './Reactify.coffee' -query = require './Async.coffee' +query = require './Async.coffee' +reactify = require './Reactify.coffee' -recl = React.createClass +recl = React.createClass {div} = React.DOM module.exports = query {body:'r',path:'t'}, recl displayName: "Body" - render: -> (div {}, (div {id:'body',key:"body"+@props.path}, - (reactify manx: @props.body))) + render: -> (div {}, (div {id:'body',key:"body"+@props.path}, reactify @props.body)) diff --git a/pub/tree/src/js/components/Components.coffee b/pub/tree/src/js/components/Components.coffee new file mode 100644 index 000000000..e169fd194 --- /dev/null +++ b/pub/tree/src/js/components/Components.coffee @@ -0,0 +1,9 @@ +recl = React.createClass + +module.exports = + codemirror: require './CodeMirror.coffee' + search: require './SearchComponent.coffee' + list: require './ListComponent.coffee' + kids: require './KidsComponent.coffee' + toc: require './TocComponent.coffee' + lost: recl render: -> (div {}, "lost") diff --git a/pub/tree/src/js/components/KidsComponent.coffee b/pub/tree/src/js/components/KidsComponent.coffee index 54d127622..e9e206f1f 100644 --- a/pub/tree/src/js/components/KidsComponent.coffee +++ b/pub/tree/src/js/components/KidsComponent.coffee @@ -1,4 +1,4 @@ -reactify = (manx)-> React.createElement window.tree.reactify, {manx} +reactify = require './Reactify.coffee' query = require './Async.coffee' recl = React.createClass diff --git a/pub/tree/src/js/components/ListComponent.coffee b/pub/tree/src/js/components/ListComponent.coffee index bf45ae7b2..f00859272 100644 --- a/pub/tree/src/js/components/ListComponent.coffee +++ b/pub/tree/src/js/components/ListComponent.coffee @@ -1,6 +1,6 @@ clas = require 'classnames' -reactify = (manx)-> React.createElement window.tree.reactify, {manx} +reactify = require './Reactify.coffee' query = require './Async.coffee' recl = React.createClass @@ -49,7 +49,7 @@ module.exports = query { else parts.push elem.snip if @props.titlesOnly - parts = elem.head + parts = [elem.head] li {key:item,className:@props.dataType ? ""}, a {href,className:(clas preview: @props.dataPreview?)}, reactify diff --git a/pub/tree/src/js/components/Reactify.coffee b/pub/tree/src/js/components/Reactify.coffee index bbd83cd84..f4157b55f 100644 --- a/pub/tree/src/js/components/Reactify.coffee +++ b/pub/tree/src/js/components/Reactify.coffee @@ -1,28 +1,30 @@ recl = React.createClass +rele = React.createElement {div,span} = React.DOM -load = React.createFactory require './LoadComponent.coffee' +load = React.createFactory require './LoadComponent.coffee' -codemirror = require './CodeMirror.coffee' -list = require './ListComponent.coffee' -kids = require './KidsComponent.coffee' -toc = require './TocComponent.coffee' -lost = recl render: -> (div {}, "lost") -components = - kids:kids - list:list - lost:lost - toc:toc - codemirror:codemirror - -module.exports = recl - displayName: "Virtual" - render: -> @walk @props.manx - walk: (elem,key) -> switch - # manx: {fork: ["string", {gn:"string" ga:{dict:"string"} c:{list:"manx"}}]} - when !elem? then (load {}, "") - when typeof elem == "string" then elem +walk = (root,_nil,_str,_comp)-> + # manx: {fork: ["string", {gn:"string" ga:{dict:"string"} c:{list:"manx"}}]} + _walk = (elem,key)-> switch + when !elem? then _nil() + when typeof elem == "string" then _str elem when elem.gn? - React.createElement components[elem.gn] ? elem.gn, - $.extend {key}, elem.ga - elem.c?.map @walk + {gn,ga,c} = elem + c = c?.map _walk ? [] + _comp.call elem, {gn,ga,c}, key else throw "Bad react-json #{JSON.stringify elem}" + _walk root + +Virtual = recl + displayName: "Virtual" + render: -> + {components} = window.tree + walk @props.manx, + ()-> (load {},"") + (str)-> str + ({gn,ga,c},key)-> rele (components[gn] ? gn), + (_.extend {key}, ga), + c + +reactify = (manx,key)-> rele Virtual, {manx,key} +module.exports = _.extend reactify, {walk,Virtual} diff --git a/pub/tree/src/js/components/SearchComponent.coffee b/pub/tree/src/js/components/SearchComponent.coffee new file mode 100644 index 000000000..153efa564 --- /dev/null +++ b/pub/tree/src/js/components/SearchComponent.coffee @@ -0,0 +1,34 @@ +query = require './Async.coffee' +reactify = require './Reactify.coffee' + +recl = React.createClass +{div,input} = React.DOM + + +module.exports = query {kids: sect:'r'}, recl + hash:null + displayName: "Search" + getInitialState: -> search: 'dva' + onKeyUp: (e)-> @setState search: e.target.value + render: -> div {}, + input {@onKeyUp,ref:'inp',defaultValue:'dva'} + _(c for x,{sect:{c}} of @props.kids) + .flatten() + .map(@highlight) + .filter() + .map(reactify) + .value() + + highlight: (e)-> + return e unless @state.search + got = false + res = reactify.walk e, + ()-> null + (s)=> + m = s.split @state.search + return [s] unless m[1]? + lit = gn:'span',c:[@state.search],ga:style:background: '#ff6' + got = true + [m[0], _.flatten([lit,s] for s in m[1..])...] + ({gn,ga,c})->{gn,ga,c:_.flatten c} + res if got diff --git a/pub/tree/src/js/components/TocComponent.coffee b/pub/tree/src/js/components/TocComponent.coffee index 7f68b5b91..7f41bf37d 100644 --- a/pub/tree/src/js/components/TocComponent.coffee +++ b/pub/tree/src/js/components/TocComponent.coffee @@ -1,11 +1,11 @@ query = require './Async.coffee' +reactify = require './Reactify.coffee' recl = React.createClass {div} = React.DOM -reactify = (manx)-> React.createElement window.tree.reactify, {manx} -module.exports = query {body:'t'}, recl +module.exports = query {body:'r'}, recl hash:null displayName: "TableOfContents" diff --git a/pub/tree/src/js/main.coffee b/pub/tree/src/js/main.coffee index 617667963..b3a27a245 100644 --- a/pub/tree/src/js/main.coffee +++ b/pub/tree/src/js/main.coffee @@ -7,7 +7,7 @@ $ -> head = React.createFactory require './components/AnchorComponent.coffee' body = React.createFactory require './components/BodyComponent.coffee' - window.tree.reactify = require './components/Reactify.coffee' # sigh + window.tree.components = require './components/Components.coffee' # sigh window.tree._basepath = window.urb.util.basepath("/") window.tree._basepath += diff --git a/pub/tree/src/js/main.js b/pub/tree/src/js/main.js index 9e65a9d32..6e12b7697 100644 --- a/pub/tree/src/js/main.js +++ b/pub/tree/src/js/main.js @@ -36,8 +36,8 @@ module.exports = { -},{"../dispatcher/Dispatcher.coffee":11,"../persistence/TreePersistence.coffee":17}],2:[function(require,module,exports){ -var BodyComponent, Links, TreeActions, TreeStore, a, clas, div, query, recl, ref; +},{"../dispatcher/Dispatcher.coffee":13,"../persistence/TreePersistence.coffee":19}],2:[function(require,module,exports){ +var BodyComponent, Links, TreeActions, TreeStore, a, clas, div, query, reactify, recl, ref; clas = require('classnames'); @@ -45,6 +45,8 @@ BodyComponent = React.createFactory(require('./BodyComponent.coffee')); query = require('./Async.coffee'); +reactify = require('./Reactify.coffee'); + TreeStore = require('../stores/TreeStore.coffee'); TreeActions = require('../actions/TreeActions.coffee'); @@ -114,17 +116,15 @@ Links = React.createFactory(query({ })(this))); }, toText: function(elem) { - var ref1; - switch (false) { - case !(elem == null): - return ""; - case typeof elem !== "string": - return elem; - case elem.gn == null: - return ((ref1 = elem.c) != null ? ref1 : []).map(this.toText).join(""); - default: - throw "Bad react-json " + (JSON.stringify(elem)); - } + return reactify.walk(elem, function() { + return ''; + }, function(s) { + return s; + }, function(arg) { + var c; + c = arg.c; + return (c != null ? c : []).join(''); + }); } }), recl({ displayName: "Links_loading", @@ -174,13 +174,13 @@ module.exports = query({ toggleFocus: function(state) { return $(this.getDOMNode()).toggleClass('focus', state); }, - componentDidUpdate: function() { - return this.setTitle(); - }, componentWillUnmount: function() { clearInterval(this.interval); return $('body').off('click', 'a'); }, + componentDidUpdate: function() { + return this.setTitle(); + }, componentDidMount: function() { this.setTitle(); this.interval = setInterval(this.checkURL, 100); @@ -285,7 +285,7 @@ module.exports = query({ -},{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":18,"./Async.coffee":3,"./BodyComponent.coffee":4,"classnames":13}],3:[function(require,module,exports){ +},{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":20,"./Async.coffee":3,"./BodyComponent.coffee":4,"./Reactify.coffee":10,"classnames":15}],3:[function(require,module,exports){ var TreeActions, TreeStore, _load, code, div, recl, ref, span; _load = require('./LoadComponent.coffee'); @@ -369,20 +369,20 @@ module.exports = function(queries, Child, load) { } }, render: function() { - return div({}, this.filterQueries() != null ? React.createElement(load, this.props) : React.createElement(Child, _.merge({}, this.props, this.state.got), this.props.children)); + return div({}, this.filterQueries() != null ? React.createElement(load, this.props) : React.createElement(Child, _.extend({}, this.props, this.state.got), this.props.children)); } }); }; -},{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":18,"./LoadComponent.coffee":8}],4:[function(require,module,exports){ +},{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":20,"./LoadComponent.coffee":9}],4:[function(require,module,exports){ var div, query, reactify, recl; -reactify = React.createFactory(require('./Reactify.coffee')); - query = require('./Async.coffee'); +reactify = require('./Reactify.coffee'); + recl = React.createClass; div = React.DOM.div; @@ -396,15 +396,13 @@ module.exports = query({ return div({}, div({ id: 'body', key: "body" + this.props.path - }, reactify({ - manx: this.props.body - }))); + }, reactify(this.props.body))); } })); -},{"./Async.coffee":3,"./Reactify.coffee":9}],5:[function(require,module,exports){ +},{"./Async.coffee":3,"./Reactify.coffee":10}],5:[function(require,module,exports){ var div, recl, ref, textarea; recl = React.createClass; @@ -429,13 +427,29 @@ module.exports = recl({ },{}],6:[function(require,module,exports){ +var recl; + +recl = React.createClass; + +module.exports = { + codemirror: require('./CodeMirror.coffee'), + search: require('./SearchComponent.coffee'), + list: require('./ListComponent.coffee'), + kids: require('./KidsComponent.coffee'), + toc: require('./TocComponent.coffee'), + lost: recl({ + render: function() { + return div({}, "lost"); + } + }) +}; + + + +},{"./CodeMirror.coffee":5,"./KidsComponent.coffee":7,"./ListComponent.coffee":8,"./SearchComponent.coffee":11,"./TocComponent.coffee":12}],7:[function(require,module,exports){ var a, div, hr, li, query, reactify, recl, ref, ul; -reactify = function(manx) { - return React.createElement(window.tree.reactify, { - manx: manx - }); -}; +reactify = require('./Reactify.coffee'); query = require('./Async.coffee'); @@ -472,16 +486,12 @@ module.exports = query({ -},{"./Async.coffee":3}],7:[function(require,module,exports){ +},{"./Async.coffee":3,"./Reactify.coffee":10}],8:[function(require,module,exports){ var a, clas, div, h1, li, query, reactify, recl, ref, ul; clas = require('classnames'); -reactify = function(manx) { - return React.createElement(window.tree.reactify, { - manx: manx - }); -}; +reactify = require('./Reactify.coffee'); query = require('./Async.coffee'); @@ -551,7 +561,7 @@ module.exports = query({ } } if (this.props.titlesOnly) { - parts = elem.head; + parts = [elem.head]; } results.push(li({ key: item, @@ -572,7 +582,7 @@ module.exports = query({ -},{"./Async.coffee":3,"classnames":13}],8:[function(require,module,exports){ +},{"./Async.coffee":3,"./Reactify.coffee":10,"classnames":15}],9:[function(require,module,exports){ var div, input, recl, ref, textarea; recl = React.createClass; @@ -613,78 +623,186 @@ module.exports = recl({ -},{}],9:[function(require,module,exports){ -var codemirror, components, div, kids, list, load, lost, recl, ref, span, toc; +},{}],10:[function(require,module,exports){ +var Virtual, div, load, reactify, recl, ref, rele, span, walk; recl = React.createClass; +rele = React.createElement; + ref = React.DOM, div = ref.div, span = ref.span; load = React.createFactory(require('./LoadComponent.coffee')); -codemirror = require('./CodeMirror.coffee'); - -list = require('./ListComponent.coffee'); - -kids = require('./KidsComponent.coffee'); - -toc = require('./TocComponent.coffee'); - -lost = recl({ - render: function() { - return div({}, "lost"); - } -}); - -components = { - kids: kids, - list: list, - lost: lost, - toc: toc, - codemirror: codemirror -}; - -module.exports = recl({ - displayName: "Virtual", - render: function() { - return this.walk(this.props.manx); - }, - walk: function(elem, key) { - var ref1, ref2; +walk = function(root, _nil, _str, _comp) { + var _walk; + _walk = function(elem, key) { + var c, ga, gn; switch (false) { case !(elem == null): - return load({}, ""); + return _nil(); case typeof elem !== "string": - return elem; + return _str(elem); case elem.gn == null: - return React.createElement((ref1 = components[elem.gn]) != null ? ref1 : elem.gn, $.extend({ - key: key - }, elem.ga), (ref2 = elem.c) != null ? ref2.map(this.walk) : void 0); + gn = elem.gn, ga = elem.ga, c = elem.c; + c = c != null ? c.map(_walk != null ? _walk : []) : void 0; + return _comp.call(elem, { + gn: gn, + ga: ga, + c: c + }, key); default: throw "Bad react-json " + (JSON.stringify(elem)); } + }; + return _walk(root); +}; + +Virtual = recl({ + displayName: "Virtual", + render: function() { + var components; + components = window.tree.components; + return walk(this.props.manx, function() { + return load({}, ""); + }, function(str) { + return str; + }, function(arg, key) { + var c, ga, gn, ref1; + gn = arg.gn, ga = arg.ga, c = arg.c; + return rele((ref1 = components[gn]) != null ? ref1 : gn, _.extend({ + key: key + }, ga), c); + }); } }); +reactify = function(manx, key) { + return rele(Virtual, { + manx: manx, + key: key + }); +}; + +module.exports = _.extend(reactify, { + walk: walk, + Virtual: Virtual +}); + -},{"./CodeMirror.coffee":5,"./KidsComponent.coffee":6,"./ListComponent.coffee":7,"./LoadComponent.coffee":8,"./TocComponent.coffee":10}],10:[function(require,module,exports){ +},{"./LoadComponent.coffee":9}],11:[function(require,module,exports){ +var div, input, query, reactify, recl, ref, + slice = [].slice; + +query = require('./Async.coffee'); + +reactify = require('./Reactify.coffee'); + +recl = React.createClass; + +ref = React.DOM, div = ref.div, input = ref.input; + +module.exports = query({ + kids: { + sect: 'r' + } +}, recl({ + hash: null, + displayName: "Search", + getInitialState: function() { + return { + search: 'dva' + }; + }, + onKeyUp: function(e) { + return this.setState({ + search: e.target.value + }); + }, + render: function() { + var c, x; + return div({}, input({ + onKeyUp: this.onKeyUp, + ref: 'inp', + defaultValue: 'dva' + }), _((function() { + var ref1, results; + ref1 = this.props.kids; + results = []; + for (x in ref1) { + c = ref1[x].sect.c; + results.push(c); + } + return results; + }).call(this)).flatten().map(this.highlight).filter().map(reactify).value()); + }, + highlight: function(e) { + var got, res; + if (!this.state.search) { + return e; + } + got = false; + res = reactify.walk(e, function() { + return null; + }, (function(_this) { + return function(s) { + var lit, m; + m = s.split(_this.state.search); + if (m[1] == null) { + return [s]; + } + lit = { + gn: 'span', + c: [_this.state.search], + ga: { + style: { + background: '#ff6' + } + } + }; + got = true; + return [m[0]].concat(slice.call(_.flatten((function() { + var i, len, ref1, results; + ref1 = m.slice(1); + results = []; + for (i = 0, len = ref1.length; i < len; i++) { + s = ref1[i]; + results.push([lit, s]); + } + return results; + })()))); + }; + })(this), function(arg) { + var c, ga, gn; + gn = arg.gn, ga = arg.ga, c = arg.c; + return { + gn: gn, + ga: ga, + c: _.flatten(c) + }; + }); + if (got) { + return res; + } + } +})); + + + +},{"./Async.coffee":3,"./Reactify.coffee":10}],12:[function(require,module,exports){ var div, query, reactify, recl; query = require('./Async.coffee'); +reactify = require('./Reactify.coffee'); + recl = React.createClass; div = React.DOM.div; -reactify = function(manx) { - return React.createElement(window.tree.reactify, { - manx: manx - }); -}; - module.exports = query({ - body: 't' + body: 'r' }, recl({ hash: null, displayName: "TableOfContents", @@ -803,7 +921,7 @@ module.exports = query({ -},{"./Async.coffee":3}],11:[function(require,module,exports){ +},{"./Async.coffee":3,"./Reactify.coffee":10}],13:[function(require,module,exports){ var Dispatcher; Dispatcher = require('flux').Dispatcher; @@ -825,7 +943,7 @@ module.exports = _.extend(new Dispatcher(), { -},{"flux":14}],12:[function(require,module,exports){ +},{"flux":16}],14:[function(require,module,exports){ var rend; rend = React.render; @@ -836,7 +954,7 @@ $(function() { React.initializeTouchEvents(true); head = React.createFactory(require('./components/AnchorComponent.coffee')); body = React.createFactory(require('./components/BodyComponent.coffee')); - window.tree.reactify = require('./components/Reactify.coffee'); + window.tree.components = require('./components/Components.coffee'); window.tree._basepath = window.urb.util.basepath("/"); window.tree._basepath += (window.location.pathname.replace(window.tree._basepath, "")).split("/")[0]; window.tree.basepath = function(path) { @@ -972,7 +1090,7 @@ $(function() { -},{"./actions/TreeActions.coffee":1,"./components/AnchorComponent.coffee":2,"./components/BodyComponent.coffee":4,"./components/Reactify.coffee":9,"./persistence/TreePersistence.coffee":17}],13:[function(require,module,exports){ +},{"./actions/TreeActions.coffee":1,"./components/AnchorComponent.coffee":2,"./components/BodyComponent.coffee":4,"./components/Components.coffee":6,"./persistence/TreePersistence.coffee":19}],15:[function(require,module,exports){ /*! Copyright (c) 2015 Jed Watson. Licensed under the MIT License (MIT), see @@ -1023,7 +1141,7 @@ $(function() { }()); -},{}],14:[function(require,module,exports){ +},{}],16:[function(require,module,exports){ /** * Copyright (c) 2014-2015, Facebook, Inc. * All rights reserved. @@ -1035,7 +1153,7 @@ $(function() { module.exports.Dispatcher = require('./lib/Dispatcher') -},{"./lib/Dispatcher":15}],15:[function(require,module,exports){ +},{"./lib/Dispatcher":17}],17:[function(require,module,exports){ /* * Copyright (c) 2014, Facebook, Inc. * All rights reserved. @@ -1287,7 +1405,7 @@ var _prefix = 'ID_'; module.exports = Dispatcher; -},{"./invariant":16}],16:[function(require,module,exports){ +},{"./invariant":18}],18:[function(require,module,exports){ /** * Copyright (c) 2014, Facebook, Inc. * All rights reserved. @@ -1342,7 +1460,7 @@ var invariant = function(condition, format, a, b, c, d, e, f) { module.exports = invariant; -},{}],17:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ module.exports = { get: function(path, query, cb) { var url; @@ -1393,8 +1511,8 @@ module.exports = { -},{}],18:[function(require,module,exports){ -var EventEmitter, MessageDispatcher, TreeStore, _curr, _data, _tree, clog; +},{}],20:[function(require,module,exports){ +var EventEmitter, MessageDispatcher, QUERIES, TreeStore, _curr, _data, _tree, clog; EventEmitter = require('events').EventEmitter; @@ -1408,6 +1526,14 @@ _data = {}; _curr = ""; +QUERIES = { + body: 'r', + head: 'r', + snip: 'r', + sect: 'r', + meta: 'j' +}; + TreeStore = _.extend(EventEmitter.prototype, { addChangeListener: function(cb) { return this.on('change', cb); @@ -1425,14 +1551,17 @@ TreeStore = _.extend(EventEmitter.prototype, { return this.fulfillAt(this.getTree(path.split('/')), path, query); }, fulfillAt: function(tree, path, query) { - var data, i, k, len, ref, ref1, sub; + var data, k, ref, sub, t; data = this.fulfillLocal(path, query); - ref = ["body", "head", "snip", "meta"]; - for (i = 0, len = ref.length; i < len; i++) { - k = ref[i]; - if (query[k]) { - data[k] = (ref1 = _data[path]) != null ? ref1[k] : void 0; + for (k in query) { + t = query[k]; + if (!QUERIES[k]) { + continue; } + if (t !== QUERIES[k]) { + throw TypeError("Wrong query type: " + k + ", '" + t + "'"); + } + data[k] = (ref = _data[path]) != null ? ref[k] : void 0; } if (query.kids) { data.kids = {}; @@ -1475,18 +1604,16 @@ TreeStore = _.extend(EventEmitter.prototype, { return this.loadValues(this.getTree(path.split('/'), true), path, data); }, loadValues: function(tree, path, data) { - var i, k, len, old, ref, ref1, ref2, v; + var k, old, ref, ref1, v; old = (ref = _data[path]) != null ? ref : {}; - ref1 = ["body", "head", "snip", "meta"]; - for (i = 0, len = ref1.length; i < len; i++) { - k = ref1[i]; - if (data[k] !== void 0) { + for (k in data) { + if (QUERIES[k]) { old[k] = data[k]; } } - ref2 = data.kids; - for (k in ref2) { - v = ref2[k]; + ref1 = data.kids; + for (k in ref1) { + v = ref1[k]; if (tree[k] == null) { tree[k] = {}; } @@ -1620,7 +1747,7 @@ module.exports = TreeStore; -},{"../dispatcher/Dispatcher.coffee":11,"events":19}],19:[function(require,module,exports){ +},{"../dispatcher/Dispatcher.coffee":13,"events":21}],21:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -1923,4 +2050,4 @@ function isUndefined(arg) { return arg === void 0; } -},{}]},{},[12]); +},{}]},{},[14]); diff --git a/pub/tree/src/js/stores/TreeStore.coffee b/pub/tree/src/js/stores/TreeStore.coffee index 85f480c30..4976a8bc2 100644 --- a/pub/tree/src/js/stores/TreeStore.coffee +++ b/pub/tree/src/js/stores/TreeStore.coffee @@ -7,6 +7,8 @@ _tree = {} _data = {} _curr = "" +QUERIES = {body:'r', head:'r', snip:'r', sect:'r', meta:'j'} + TreeStore = _.extend EventEmitter.prototype, { addChangeListener: (cb) -> @on 'change', cb @@ -19,8 +21,9 @@ TreeStore = _.extend EventEmitter.prototype, { fulfill: (path,query) -> @fulfillAt (@getTree path.split '/'),path,query fulfillAt: (tree,path,query)-> data = @fulfillLocal path, query - for k in ["body", "head" ,"snip" ,"meta"] - data[k] = _data[path]?[k] if query[k] + for k,t of query when QUERIES[k] + if t isnt QUERIES[k] then throw TypeError "Wrong query type: #{k}, '#{t}'" + data[k] = _data[path]?[k] if query.kids data.kids = {} for k,sub of tree @@ -43,8 +46,8 @@ TreeStore = _.extend EventEmitter.prototype, { @loadValues (@getTree (path.split '/'),true), path, data loadValues: (tree,path,data) -> old = _data[path] ? {} - for k in ["body", "head" ,"snip" ,"meta"] - old[k] = data[k] if data[k] isnt undefined + for k of data when QUERIES[k] + old[k] = data[k] for k,v of data.kids tree[k] ?= {} diff --git a/sur/tree-include.hoon b/sur/tree-include.hoon index 9b3c9bccc..3e6337595 100644 --- a/sur/tree-include.hoon +++ b/sur/tree-include.hoon @@ -3,4 +3,5 @@ $: body=json head=json snip=json meta=json + sect=json == diff --git a/tree-gen/tree-include.hook b/tree-gen/tree-include.hook index def41f95d..ee15ea769 100644 --- a/tree-gen/tree-include.hook +++ b/tree-gen/tree-include.hook @@ -2,6 +2,7 @@ /= body /: /=== /% /react-json/ /= head /: /=== /% /react-head-json/ /= snip /: /=== /% /react-snip-json/ +/= sect /: /=== /% /react-headers-json/ /= meta /: /=== /% /; json-front /react-snip-json/ ^- tree-include -[body head snip meta] +[body head snip meta sect] diff --git a/tree/json.hook b/tree/json.hook index f49a22078..892ff179d 100644 --- a/tree/json.hook +++ b/tree/json.hook @@ -21,6 +21,7 @@ $% [%kids p=(list query)] [%name %t] [%path %t] + [%sect %r] [%snip %r] [%head %r] [%body %r] @@ -53,13 +54,14 @@ %path (from-type +.a (crip (spud (flop s.bem)))) %head (from-type +.a head.dat) %snip (from-type +.a snip.dat) + %sect (from-type +.a sect.dat) %meta (from-type +.a meta.dat) %body (from-type +.a body.dat) %kids ?< (~(has by (mo p.a)) %kids) :: XX recursion? =< o/(~(urn by kid) .) |= [dir=span dak=tree-include] ^^$(quy p.a, s.bem [dir s.bem], dat dak, kid ~) - == + == -- !: ::::