mirror of
https://github.com/urbit/shrub.git
synced 2024-12-12 10:29:01 +03:00
Merge branch 'test' of https://github.com/urbit/urbit into test
This commit is contained in:
commit
647e5526c5
@ -234,8 +234,9 @@ li:before {
|
||||
vertical-align: top;
|
||||
}
|
||||
#nav #sibs {
|
||||
width: 9rem;
|
||||
width: 8rem;
|
||||
transition: margin-top 0.3s ease-in-out;
|
||||
overflow: hidden;
|
||||
}
|
||||
#nav #sibs > div {
|
||||
height: 20px;
|
||||
@ -251,6 +252,7 @@ li:before {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 200;
|
||||
letter-spacing: 1px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.list > li > a {
|
||||
border-bottom: none;
|
||||
@ -419,6 +421,33 @@ div.post p {
|
||||
div.post li p {
|
||||
display: inline;
|
||||
}
|
||||
div.toc {
|
||||
margin-top: 6rem;
|
||||
margin-bottom: 6rem;
|
||||
}
|
||||
div.toc h1,
|
||||
div.toc h2,
|
||||
div.toc h3,
|
||||
div.toc h4 {
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
div.toc h2 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
div.toc h3 {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
div.toc h4 {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
div.toc h1.t {
|
||||
font-weight: 500;
|
||||
font-size: 2rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
#body .CodeMirror {
|
||||
font-size: 0.8rem;
|
||||
line-height: 1rem;
|
||||
@ -498,6 +527,9 @@ div.post li p {
|
||||
#nav > div {
|
||||
padding-top: 0.6rem;
|
||||
}
|
||||
#nav #sibs {
|
||||
width: 18rem;
|
||||
}
|
||||
#nav #sibs > div {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
|
@ -161,8 +161,9 @@ li:before
|
||||
vertical-align top
|
||||
|
||||
#nav #sibs
|
||||
width 9rem
|
||||
width 8rem
|
||||
transition margin-top .3s ease-in-out
|
||||
overflow hidden
|
||||
|
||||
#nav #sibs > div
|
||||
height 20px
|
||||
@ -178,6 +179,7 @@ li:before
|
||||
font-size .7rem
|
||||
font-weight 200
|
||||
letter-spacing 1px
|
||||
white-space nowrap
|
||||
|
||||
.list > li > a
|
||||
border-bottom none
|
||||
@ -347,6 +349,33 @@ div.post
|
||||
li p
|
||||
display inline
|
||||
|
||||
div.toc
|
||||
margin-top 6rem
|
||||
margin-bottom 6rem
|
||||
|
||||
h1
|
||||
h2
|
||||
h3
|
||||
h4
|
||||
font-weight 400
|
||||
cursor pointer
|
||||
text-decoration underline
|
||||
font-size 1.2rem
|
||||
|
||||
h2
|
||||
margin-left 1rem
|
||||
|
||||
h3
|
||||
margin-left 2rem
|
||||
|
||||
h4
|
||||
margin-left 3rem
|
||||
|
||||
h1.t
|
||||
font-weight 500
|
||||
font-size 2rem
|
||||
text-decoration none
|
||||
|
||||
#body .CodeMirror
|
||||
font-size .8rem
|
||||
line-height 1rem
|
||||
|
@ -62,6 +62,9 @@
|
||||
|
||||
#nav > div
|
||||
padding-top .6rem
|
||||
|
||||
#nav #sibs
|
||||
width 18rem
|
||||
|
||||
#nav #sibs > div
|
||||
height 20px
|
||||
|
@ -20,7 +20,13 @@ Links = React.createFactory query {
|
||||
displayName: "Links"
|
||||
render: -> div {className:'links'}, @props.children, @_render()
|
||||
_render: ->
|
||||
keys = _(@props.kids).keys().sort()
|
||||
sorted = true
|
||||
keys = []
|
||||
for k,v of @props.kids
|
||||
if not v.meta?.sort? then sorted = false
|
||||
keys[Number(v.meta?.sort)] = k
|
||||
if sorted isnt true
|
||||
keys = _(@props.kids).keys().sort()
|
||||
style = {marginTop: -24 * (keys.indexOf @props.curr) + "px"}
|
||||
div {id:"sibs",style}, keys.map (key) =>
|
||||
href = window.tree.basepath @props.path+"/"+key
|
||||
|
@ -21,24 +21,50 @@ module.exports = query {
|
||||
posts: @props.dataType is 'post'
|
||||
default: @props['data-source'] is 'default'
|
||||
(ul {className:k}, @renderList())
|
||||
|
||||
renderList: ->
|
||||
_keys = _.keys(@props.kids).sort()
|
||||
# check if kids all have a sort meta tag
|
||||
sorted = true
|
||||
_keys = []
|
||||
for k,v of @props.kids
|
||||
if not v.meta?.sort? then sorted = false
|
||||
_keys[Number(v.meta?.sort)] = k
|
||||
if sorted isnt true
|
||||
_keys = _.keys(@props.kids).sort()
|
||||
if @props.dataType is 'post' then _keys=_keys.reverse()
|
||||
for item in _keys
|
||||
path = @props.path+"/"+item
|
||||
elem = @props.kids[item]
|
||||
href = window.tree.basepath path
|
||||
parts = []
|
||||
if elem.meta?.title
|
||||
title =
|
||||
gn: 'h1'
|
||||
c: [elem.meta.title]
|
||||
else title = elem.head
|
||||
parts.push title
|
||||
if @props.dataPreview
|
||||
if @props.dataType is 'post'
|
||||
parts.push (elem.snip.c.slice 0,2)...
|
||||
else
|
||||
parts.push elem.snip
|
||||
if @props.titlesOnly
|
||||
parts = elem.head
|
||||
li {key:item,className:@props.dataType ? ""},
|
||||
a {href,className:(clas preview: @props.dataPreview?)},
|
||||
if not @props.dataPreview? then (h1 {},item)
|
||||
else if @props.dataType is 'post'
|
||||
head =
|
||||
if elem.meta?.title
|
||||
gn: 'h1'
|
||||
c: [elem.meta.title]
|
||||
else elem.head
|
||||
reactify
|
||||
gn: 'div'
|
||||
c: [head, (elem.snip.c.slice 0,2)...]
|
||||
else if @props.titlesOnly? then reactify elem.head
|
||||
else div {}, (reactify elem.head), (reactify elem.snip)
|
||||
a {href,className:(clas preview: @props.dataPreview?)},
|
||||
reactify
|
||||
gn: 'div'
|
||||
c: parts
|
||||
|
||||
# if not @props.dataPreview? then (h1 {},item)
|
||||
# else if @props.dataType is 'post'
|
||||
# head =
|
||||
# if elem.meta?.title
|
||||
# gn: 'h1'
|
||||
# c: [elem.meta.title]
|
||||
# else elem.head
|
||||
# reactify
|
||||
# gn: 'div'
|
||||
# c: [head, (elem.snip.c.slice 0,2)...]
|
||||
# else if @props.titlesOnly? then reactify elem.head
|
||||
# else div {}, (reactify elem.head), (reactify elem.snip)
|
||||
|
@ -1,48 +1,71 @@
|
||||
TreeStore = require '../stores/TreeStore.coffee'
|
||||
query = require './Async.coffee'
|
||||
|
||||
recl = React.createClass
|
||||
{div} = React.DOM
|
||||
|
||||
module.exports = recl
|
||||
reactify = (manx)-> React.createElement window.tree.reactify, {manx}
|
||||
|
||||
module.exports = query {body:'t'}, recl
|
||||
hash:null
|
||||
displayName: "TableOfContents"
|
||||
|
||||
_onChangeStore: -> @setState tocs: @compute()
|
||||
_click: (e) ->
|
||||
console.log 'click'
|
||||
document.location.hash = @urlsafe $(e.target).text()
|
||||
|
||||
urlsafe: (str) ->
|
||||
str.toLowerCase().replace(/\ /g, "-").replace(/[^a-z0-9~_.-]/g,"")
|
||||
|
||||
componentDidMount: ->
|
||||
TreeStore.addChangeListener @_onChangeStore
|
||||
@int = setInterval @checkHash,100
|
||||
@setState tocs: @compute()
|
||||
@st = $(window).scrollTop()
|
||||
$(window).on 'scroll',@checkScroll
|
||||
@$headers = $('#toc h1, #toc h2, #toc h3, #toc h4')
|
||||
|
||||
checkScroll: ->
|
||||
st = $(window).scrollTop()
|
||||
if Math.abs(@st-st) > 10
|
||||
hash = null
|
||||
@st = st
|
||||
for k,v of @$headers
|
||||
continue if v.tagName is undefined
|
||||
$h = $ v
|
||||
hst = $h.offset().top-$h.outerHeight(true)+10
|
||||
if hst < st
|
||||
hash = @urlsafe $h.text()
|
||||
if hst > st and hash isnt @hash and hash isnt null
|
||||
@hash = "#"+hash
|
||||
document.location.hash = hash
|
||||
break
|
||||
|
||||
checkHash: ->
|
||||
if document.location.hash? and document.location.hash isnt @hash
|
||||
if document.location.hash?.length > 0 and document.location.hash isnt @hash
|
||||
hash = document.location.hash.slice(1)
|
||||
for k,v of @state.tocs
|
||||
if hash is @urlsafe v.t
|
||||
for k,v of @$headers
|
||||
$h = $ v
|
||||
if hash is @urlsafe $h.text()
|
||||
@hash = document.location.hash
|
||||
$(window).scrollTop v.e.offset().top
|
||||
offset = $h.offset().top - $h.outerHeight(true)
|
||||
setTimeout -> $(window).scrollTop offset
|
||||
, 10
|
||||
break
|
||||
|
||||
componentWillUnmount: ->
|
||||
TreeStore.removeChangeListener @_onChangeStore
|
||||
clearInterval @int
|
||||
|
||||
getInitialState: -> tocs: @compute()
|
||||
|
||||
compute: ->
|
||||
$headers = $('#toc h1, #toc h2, #toc h3, #toc h4')
|
||||
for h in $headers
|
||||
$h = $(h)
|
||||
{h:h.tagName.toLowerCase(),t:$h.text(),e:$h}
|
||||
|
||||
render: ->
|
||||
onClick = @_click
|
||||
(div {className:'toc'}, @state.tocs.map ({h,t},key) ->
|
||||
(React.DOM[h] {onClick,key}, t)
|
||||
)
|
||||
collectHeaders: (e) ->
|
||||
hs = [{gn:"h1", ga:{className:"t"}, c:["Table of contents"]}]
|
||||
for k,v of e
|
||||
if not v.gn then continue
|
||||
if v.gn[0] is 'h' and parseInt(v.gn[1]) isnt NaN
|
||||
hs.push v
|
||||
return hs
|
||||
|
||||
parseHeaders: ->
|
||||
if @props.body.c
|
||||
for k,v of @props.body.c
|
||||
if v.gn is 'div' and v.ga?.id is "toc"
|
||||
return {gn:"div", ga:{className:"toc",onClick:@_click}, c:@collectHeaders(v.c)}
|
||||
|
||||
render: -> reactify @parseHeaders()
|
||||
|
@ -68,8 +68,20 @@ Links = React.createFactory(query({
|
||||
}, this.props.children, this._render());
|
||||
},
|
||||
_render: function() {
|
||||
var keys, style;
|
||||
keys = _(this.props.kids).keys().sort();
|
||||
var k, keys, ref1, ref2, ref3, sorted, style, v;
|
||||
sorted = true;
|
||||
keys = [];
|
||||
ref1 = this.props.kids;
|
||||
for (k in ref1) {
|
||||
v = ref1[k];
|
||||
if (((ref2 = v.meta) != null ? ref2.sort : void 0) == null) {
|
||||
sorted = false;
|
||||
}
|
||||
keys[Number((ref3 = v.meta) != null ? ref3.sort : void 0)] = k;
|
||||
}
|
||||
if (sorted !== true) {
|
||||
keys = _(this.props.kids).keys().sort();
|
||||
}
|
||||
style = {
|
||||
marginTop: -24 * (keys.indexOf(this.props.curr)) + "px"
|
||||
};
|
||||
@ -461,8 +473,7 @@ module.exports = query({
|
||||
|
||||
|
||||
},{"./Async.coffee":3}],7:[function(require,module,exports){
|
||||
var a, clas, div, h1, li, query, reactify, recl, ref, ul,
|
||||
slice = [].slice;
|
||||
var a, clas, div, h1, li, query, reactify, recl, ref, ul;
|
||||
|
||||
clas = require('classnames');
|
||||
|
||||
@ -499,8 +510,20 @@ module.exports = query({
|
||||
}, this.renderList());
|
||||
},
|
||||
renderList: function() {
|
||||
var _keys, elem, head, href, i, item, len, path, ref1, ref2, results;
|
||||
_keys = _.keys(this.props.kids).sort();
|
||||
var _keys, elem, href, i, item, k, len, parts, path, ref1, ref2, ref3, ref4, ref5, results, sorted, title, v;
|
||||
sorted = true;
|
||||
_keys = [];
|
||||
ref1 = this.props.kids;
|
||||
for (k in ref1) {
|
||||
v = ref1[k];
|
||||
if (((ref2 = v.meta) != null ? ref2.sort : void 0) == null) {
|
||||
sorted = false;
|
||||
}
|
||||
_keys[Number((ref3 = v.meta) != null ? ref3.sort : void 0)] = k;
|
||||
}
|
||||
if (sorted !== true) {
|
||||
_keys = _.keys(this.props.kids).sort();
|
||||
}
|
||||
if (this.props.dataType === 'post') {
|
||||
_keys = _keys.reverse();
|
||||
}
|
||||
@ -510,21 +533,38 @@ module.exports = query({
|
||||
path = this.props.path + "/" + item;
|
||||
elem = this.props.kids[item];
|
||||
href = window.tree.basepath(path);
|
||||
parts = [];
|
||||
if ((ref4 = elem.meta) != null ? ref4.title : void 0) {
|
||||
title = {
|
||||
gn: 'h1',
|
||||
c: [elem.meta.title]
|
||||
};
|
||||
} else {
|
||||
title = elem.head;
|
||||
}
|
||||
parts.push(title);
|
||||
if (this.props.dataPreview) {
|
||||
if (this.props.dataType === 'post') {
|
||||
parts.push.apply(parts, elem.snip.c.slice(0, 2));
|
||||
} else {
|
||||
parts.push(elem.snip);
|
||||
}
|
||||
}
|
||||
if (this.props.titlesOnly) {
|
||||
parts = elem.head;
|
||||
}
|
||||
results.push(li({
|
||||
key: item,
|
||||
className: (ref1 = this.props.dataType) != null ? ref1 : ""
|
||||
className: (ref5 = this.props.dataType) != null ? ref5 : ""
|
||||
}, a({
|
||||
href: href,
|
||||
className: clas({
|
||||
preview: this.props.dataPreview != null
|
||||
})
|
||||
}, this.props.dataPreview == null ? h1({}, item) : this.props.dataType === 'post' ? (head = ((ref2 = elem.meta) != null ? ref2.title : void 0) ? {
|
||||
gn: 'h1',
|
||||
c: [elem.meta.title]
|
||||
} : elem.head, reactify({
|
||||
}, reactify({
|
||||
gn: 'div',
|
||||
c: [head].concat(slice.call(elem.snip.c.slice(0, 2)))
|
||||
})) : this.props.titlesOnly != null ? reactify(elem.head) : div({}, reactify(elem.head), reactify(elem.snip)))));
|
||||
c: parts
|
||||
}))));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
@ -629,47 +669,81 @@ module.exports = recl({
|
||||
|
||||
|
||||
},{"./CodeMirror.coffee":5,"./KidsComponent.coffee":6,"./ListComponent.coffee":7,"./LoadComponent.coffee":8,"./TocComponent.coffee":10}],10:[function(require,module,exports){
|
||||
var TreeStore, div, recl;
|
||||
var div, query, reactify, recl;
|
||||
|
||||
TreeStore = require('../stores/TreeStore.coffee');
|
||||
query = require('./Async.coffee');
|
||||
|
||||
recl = React.createClass;
|
||||
|
||||
div = React.DOM.div;
|
||||
|
||||
module.exports = recl({
|
||||
reactify = function(manx) {
|
||||
return React.createElement(window.tree.reactify, {
|
||||
manx: manx
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = query({
|
||||
body: 't'
|
||||
}, recl({
|
||||
hash: null,
|
||||
displayName: "TableOfContents",
|
||||
_onChangeStore: function() {
|
||||
return this.setState({
|
||||
tocs: this.compute()
|
||||
});
|
||||
},
|
||||
_click: function(e) {
|
||||
console.log('click');
|
||||
return document.location.hash = this.urlsafe($(e.target).text());
|
||||
},
|
||||
urlsafe: function(str) {
|
||||
return str.toLowerCase().replace(/\ /g, "-").replace(/[^a-z0-9~_.-]/g, "");
|
||||
},
|
||||
componentDidMount: function() {
|
||||
TreeStore.addChangeListener(this._onChangeStore);
|
||||
this.int = setInterval(this.checkHash, 100);
|
||||
return this.setState({
|
||||
tocs: this.compute()
|
||||
});
|
||||
this.st = $(window).scrollTop();
|
||||
$(window).on('scroll', this.checkScroll);
|
||||
return this.$headers = $('#toc h1, #toc h2, #toc h3, #toc h4');
|
||||
},
|
||||
checkHash: function() {
|
||||
var hash, k, ref, results, v;
|
||||
if ((document.location.hash != null) && document.location.hash !== this.hash) {
|
||||
hash = document.location.hash.slice(1);
|
||||
ref = this.state.tocs;
|
||||
checkScroll: function() {
|
||||
var $h, hash, hst, k, ref, results, st, v;
|
||||
st = $(window).scrollTop();
|
||||
if (Math.abs(this.st - st) > 10) {
|
||||
hash = null;
|
||||
this.st = st;
|
||||
ref = this.$headers;
|
||||
results = [];
|
||||
for (k in ref) {
|
||||
v = ref[k];
|
||||
if (hash === this.urlsafe(v.t)) {
|
||||
if (v.tagName === void 0) {
|
||||
continue;
|
||||
}
|
||||
$h = $(v);
|
||||
hst = $h.offset().top - $h.outerHeight(true) + 10;
|
||||
if (hst < st) {
|
||||
hash = this.urlsafe($h.text());
|
||||
}
|
||||
if (hst > st && hash !== this.hash && hash !== null) {
|
||||
this.hash = "#" + hash;
|
||||
document.location.hash = hash;
|
||||
break;
|
||||
} else {
|
||||
results.push(void 0);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
},
|
||||
checkHash: function() {
|
||||
var $h, hash, k, offset, ref, ref1, results, v;
|
||||
if (((ref = document.location.hash) != null ? ref.length : void 0) > 0 && document.location.hash !== this.hash) {
|
||||
hash = document.location.hash.slice(1);
|
||||
ref1 = this.$headers;
|
||||
results = [];
|
||||
for (k in ref1) {
|
||||
v = ref1[k];
|
||||
$h = $(v);
|
||||
if (hash === this.urlsafe($h.text())) {
|
||||
this.hash = document.location.hash;
|
||||
$(window).scrollTop(v.e.offset().top);
|
||||
offset = $h.offset().top - $h.outerHeight(true);
|
||||
setTimeout(function() {
|
||||
return $(window).scrollTop(offset, 10);
|
||||
});
|
||||
break;
|
||||
} else {
|
||||
results.push(void 0);
|
||||
@ -679,48 +753,57 @@ module.exports = recl({
|
||||
}
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
TreeStore.removeChangeListener(this._onChangeStore);
|
||||
return clearInterval(this.int);
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
tocs: this.compute()
|
||||
};
|
||||
},
|
||||
compute: function() {
|
||||
var $h, $headers, h, i, len, results;
|
||||
$headers = $('#toc h1, #toc h2, #toc h3, #toc h4');
|
||||
results = [];
|
||||
for (i = 0, len = $headers.length; i < len; i++) {
|
||||
h = $headers[i];
|
||||
$h = $(h);
|
||||
results.push({
|
||||
h: h.tagName.toLowerCase(),
|
||||
t: $h.text(),
|
||||
e: $h
|
||||
});
|
||||
collectHeaders: function(e) {
|
||||
var hs, k, v;
|
||||
hs = [
|
||||
{
|
||||
gn: "h1",
|
||||
ga: {
|
||||
className: "t"
|
||||
},
|
||||
c: ["Table of contents"]
|
||||
}
|
||||
];
|
||||
for (k in e) {
|
||||
v = e[k];
|
||||
if (!v.gn) {
|
||||
continue;
|
||||
}
|
||||
if (v.gn[0] === 'h' && parseInt(v.gn[1]) !== NaN) {
|
||||
hs.push(v);
|
||||
}
|
||||
}
|
||||
return hs;
|
||||
},
|
||||
parseHeaders: function() {
|
||||
var k, ref, ref1, v;
|
||||
if (this.props.body.c) {
|
||||
ref = this.props.body.c;
|
||||
for (k in ref) {
|
||||
v = ref[k];
|
||||
if (v.gn === 'div' && ((ref1 = v.ga) != null ? ref1.id : void 0) === "toc") {
|
||||
return {
|
||||
gn: "div",
|
||||
ga: {
|
||||
className: "toc",
|
||||
onClick: this._click
|
||||
},
|
||||
c: this.collectHeaders(v.c)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
render: function() {
|
||||
var onClick;
|
||||
onClick = this._click;
|
||||
return div({
|
||||
className: 'toc'
|
||||
}, this.state.tocs.map(function(arg, key) {
|
||||
var h, t;
|
||||
h = arg.h, t = arg.t;
|
||||
return React.DOM[h]({
|
||||
onClick: onClick,
|
||||
key: key
|
||||
}, t);
|
||||
}));
|
||||
return reactify(this.parseHeaders());
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
|
||||
},{"../stores/TreeStore.coffee":18}],11:[function(require,module,exports){
|
||||
},{"./Async.coffee":3}],11:[function(require,module,exports){
|
||||
var Dispatcher;
|
||||
|
||||
Dispatcher = require('flux').Dispatcher;
|
||||
|
Loading…
Reference in New Issue
Block a user