Commit 374fbbbc3071c93a1e6d1403f2621df1f193bc05
add table-of-contents component
Paul Frazee committed on 3/16/2016, 7:05:29 PMParent: bde700450bd40b72df90242bf3588a793f98aa13
Files changed
markdown.js | changed |
tmpl/com.part.js | changed |
tmpl/css/com.part.js | changed |
tmpl/docs/advanced/advanced-queries.md | changed |
tmpl/head.part.js | changed |
tmpl/js/table-of-contents.js | added |
markdown.js | ||
---|---|---|
@@ -15,12 +15,34 @@ | ||
15 | 15 | attributes: { class: 'anchor' }, |
16 | 16 | template: linkSvg |
17 | 17 | }) |
18 | 18 | .use(html) |
19 | + .use(injectTOC) | |
19 | 20 | .use(transformCodeExamples) |
20 | 21 | .process(text) |
21 | 22 | } |
22 | 23 | |
24 | +// find all h2s and create a dropdown table-of-contents | |
25 | +function injectTOC (remark, options) { | |
26 | + remark.Compiler.prototype.visitors.tableOfContents = renderTOC | |
27 | + return ast => { | |
28 | + var headings = ast.children.filter(node => node.type == 'heading' && node.depth == 2) | |
29 | + if (headings.length > 2) | |
30 | + createTOC(ast, headings) | |
31 | + return ast | |
32 | + } | |
33 | +} | |
34 | + | |
35 | +// add the tableOfContents node to the ast | |
36 | +function createTOC (ast, headings) { | |
37 | + ast.children.unshift({ type: 'tableOfContents', children: headings }) | |
38 | +} | |
39 | + | |
40 | +// render the tableOfContents widget | |
41 | +function renderTOC (node, root) { | |
42 | + return com.tableOfContents(node.children) | |
43 | +} | |
44 | + | |
23 | 45 | // find any <code> sections and group them together into our code-examples component |
24 | 46 | function transformCodeExamples (remark, options) { |
25 | 47 | remark.Compiler.prototype.visitors.codeExamples = renderCodeExamples |
26 | 48 | return ast => { |
@@ -60,16 +82,16 @@ | ||
60 | 82 | var len = end - start |
61 | 83 | ast.children.splice(start-offset, len, { |
62 | 84 | type: 'codeExamples', |
63 | 85 | children: ast.children.slice(start-offset, start-offset+len), |
64 | - position: false // TODO - what is this? | |
86 | + position: false // TODO - needed? doesnt look like it | |
65 | 87 | }) |
66 | 88 | offset += len - 1 |
67 | 89 | }) |
68 | 90 | } |
69 | 91 | |
70 | 92 | // convert from AST to html |
71 | -function renderCodeExamples (node, ast) { | |
93 | +function renderCodeExamples (node, root) { | |
72 | 94 | var codes = {} |
73 | 95 | node.children.forEach(node => { |
74 | 96 | if (node.type == 'code' && !!node.lang) |
75 | 97 | codes[node.lang] = node.value |
tmpl/com.part.js | ||
---|---|---|
@@ -10,8 +10,20 @@ | ||
10 | 10 | </div> |
11 | 11 | </div>` |
12 | 12 | } |
13 | 13 | |
14 | +module.exports.tableOfContents = items => { | |
15 | + items = items | |
16 | + .map(item => [item.children[0].url, item.children[1].value]) | |
17 | + .filter(item => item[0] && item[1]) | |
18 | + return `<div class="table-of-contents"> | |
19 | + <a href="#">Jump to...</a> | |
20 | + <ul> | |
21 | + ${ items.map(item => `<li><a href="${item[0]}">${item[1]}</a></li>`).join('') } | |
22 | + </ul> | |
23 | + </div>` | |
24 | +} | |
25 | + | |
14 | 26 | // enforce an order to the language tabs |
15 | 27 | function langPrioritySort (a, b) { |
16 | 28 | if (b == 'js' && a != 'js') |
17 | 29 | return 1 |
tmpl/css/com.part.js | ||
---|---|---|
@@ -77,5 +77,27 @@ | ||
77 | 77 | } |
78 | 78 | .code-examples pre.current { |
79 | 79 | display: block; |
80 | 80 | } |
81 | + | |
82 | +.table-of-contents ul { | |
83 | + display: none; | |
84 | + list-style: none; | |
85 | +} | |
86 | +.table-of-contents.expanded ul { | |
87 | + display: block; | |
88 | + padding: 0; | |
89 | + margin: 0; | |
90 | +} | |
91 | +.table-of-contents ul li:nth-child(even) { | |
92 | + background: #fafafa; | |
93 | +} | |
94 | +.table-of-contents ul li:hover { | |
95 | + background: #eee; | |
96 | +} | |
97 | +.table-of-contents ul li a { | |
98 | + display: block; | |
99 | + padding: 0.5em; | |
100 | + color: #555; | |
101 | + text-decoration: none; | |
102 | +} | |
81 | 103 | ` |
tmpl/docs/advanced/advanced-queries.md | ||
---|---|---|
@@ -1,5 +1,5 @@ | ||
1 | -## Get messages by timestamp, from newest to oldest | |
1 | +## Messages ordered by timestamp | |
2 | 2 | |
3 | 3 | ```js |
4 | 4 | var pull = require('pull-stream') |
5 | 5 | pull( |
@@ -17,9 +17,9 @@ | ||
17 | 17 | [→ createFeedStream API](/apis/scuttlebot/ssb.html#createfeedstream-source) |
18 | 18 | |
19 | 19 | --- |
20 | 20 | |
21 | -## Get messages by receive-time, from newest to oldest | |
21 | +## Messages ordered by receive-time | |
22 | 22 | |
23 | 23 | ```js |
24 | 24 | var pull = require('pull-stream') |
25 | 25 | pull( |
@@ -37,9 +37,9 @@ | ||
37 | 37 | [→ createLogStream API](/apis/scuttlebot/ssb.html#createlogstream-source) |
38 | 38 | |
39 | 39 | --- |
40 | 40 | |
41 | -## Get post-messages by receive-time | |
41 | +## Messages by type | |
42 | 42 | |
43 | 43 | ```js |
44 | 44 | var pull = require('pull-stream') |
45 | 45 | pull( |
@@ -56,9 +56,9 @@ | ||
56 | 56 | [→ messagesByType API](/apis/scuttlebot/ssb.html#messagesbytype-source) |
57 | 57 | |
58 | 58 | --- |
59 | 59 | |
60 | -## Get all messages from a user | |
60 | +## Messages by user | |
61 | 61 | |
62 | 62 | ```js |
63 | 63 | var pull = require('pull-stream') |
64 | 64 | pull( |
@@ -75,45 +75,45 @@ | ||
75 | 75 | [→ createUserStream API](/apis/scuttlebot/ssb.html#createuserstream-source) |
76 | 76 | |
77 | 77 | --- |
78 | 78 | |
79 | -## Watch for new messages from a user | |
79 | +## Watch for new messages | |
80 | 80 | |
81 | 81 | ```js |
82 | 82 | var pull = require('pull-stream') |
83 | 83 | pull( |
84 | - sbot.createUserStream({ id: userId, live: true }), | |
84 | + sbot.createLogStream({ live: true }), | |
85 | 85 | pull.drain(function (msg) { ... }) |
86 | 86 | ) |
87 | 87 | ``` |
88 | 88 | ```bash |
89 | -sbot createUserStream --id {userId} --live | |
89 | +sbot log --live | |
90 | 90 | ``` |
91 | 91 | |
92 | -Notice that `pull.drain` is used instead of `pull.collect`, so that new messages are handled immediately. | |
92 | +[→ createLogStream API](/apis/scuttlebot/ssb.html#createlogstream-source) | |
93 | 93 | |
94 | -[→ createUserStream API](/apis/scuttlebot/ssb.html#createuserstream-source) | |
95 | - | |
96 | 94 | --- |
97 | 95 | |
98 | -## Watch for new messages from anybody | |
96 | +## Watch for new messages by a user | |
99 | 97 | |
100 | 98 | ```js |
101 | 99 | var pull = require('pull-stream') |
102 | 100 | pull( |
103 | - sbot.createLogStream({ live: true }), | |
101 | + sbot.createUserStream({ id: userId, live: true }), | |
104 | 102 | pull.drain(function (msg) { ... }) |
105 | 103 | ) |
106 | 104 | ``` |
107 | 105 | ```bash |
108 | -sbot log --live | |
106 | +sbot createUserStream --id {userId} --live | |
109 | 107 | ``` |
110 | 108 | |
111 | -[→ createLogStream API](/apis/scuttlebot/ssb.html#createlogstream-source) | |
109 | +Notice that `pull.drain` is used instead of `pull.collect`, so that new messages are handled immediately. | |
112 | 110 | |
111 | +[→ createUserStream API](/apis/scuttlebot/ssb.html#createuserstream-source) | |
112 | + | |
113 | 113 | --- |
114 | 114 | |
115 | -## Get all about messages for a user | |
115 | +## About-user messages | |
116 | 116 | |
117 | 117 | ```js |
118 | 118 | var pull = require('pull-stream') |
119 | 119 | pull( |
@@ -131,9 +131,9 @@ | ||
131 | 131 | [→ links API](/apis/scuttlebot/ssb.html#links-source) |
132 | 132 | |
133 | 133 | --- |
134 | 134 | |
135 | -## Get all votes on a message | |
135 | +## Votes on a message | |
136 | 136 | |
137 | 137 | ```js |
138 | 138 | var pull = require('pull-stream') |
139 | 139 | pull( |
@@ -151,9 +151,9 @@ | ||
151 | 151 | [→ links API](/apis/scuttlebot/ssb.html#links-source) |
152 | 152 | |
153 | 153 | --- |
154 | 154 | |
155 | -## Get all files referenced by a user | |
155 | +## Files referenced by a user | |
156 | 156 | |
157 | 157 | ```js |
158 | 158 | var pull = require('pull-stream') |
159 | 159 | pull( |
@@ -164,13 +164,18 @@ | ||
164 | 164 | ```bash |
165 | 165 | sbot links --source {userId} --dest & |
166 | 166 | ``` |
167 | 167 | |
168 | +All IDs have a "sigil" character defining what type of object the ID references. | |
169 | +(Blobs start with "&", users start with "@", and messages start with "%"). | |
170 | + | |
171 | +In `links`, you can use the sigil to filter the source or dest by the ID type. | |
172 | + | |
168 | 173 | [→ links API](/apis/scuttlebot/ssb.html#links-source) |
169 | 174 | |
170 | 175 | --- |
171 | 176 | |
172 | -## Get all links from one user to another | |
177 | +## Links from one user to another | |
173 | 178 | |
174 | 179 | ```js |
175 | 180 | var pull = require('pull-stream') |
176 | 181 | pull( |
@@ -185,9 +190,9 @@ | ||
185 | 190 | [→ links API](/apis/scuttlebot/ssb.html#links-source) |
186 | 191 | |
187 | 192 | --- |
188 | 193 | |
189 | -## Get a full post-thread | |
194 | +## Full post-thread | |
190 | 195 | |
191 | 196 | ```js |
192 | 197 | sbot.relatedMessages({ id: messageId }, function (err, thread) { |
193 | 198 | ... |
tmpl/head.part.js | ||
---|---|---|
@@ -10,6 +10,7 @@ | ||
10 | 10 | <link rel="stylesheet" href="/css/index.css"> |
11 | 11 | <link rel="stylesheet" href="/css/prism.css"> |
12 | 12 | <script src="/js/prism.js"></script> |
13 | 13 | <script src="/js/code-examples.js"></script> |
14 | + <script src="/js/table-of-contents.js"></script> | |
14 | 15 | </head>` |
15 | 16 | } |
tmpl/js/table-of-contents.js | ||
---|---|---|
@@ -1,0 +1,24 @@ | ||
1 | +window.addEventListener('load', function () { | |
2 | + setupTOC(document.querySelector('.table-of-contents')) | |
3 | +}) | |
4 | + | |
5 | +function setupTOC (toc) { | |
6 | + // attach click handlers | |
7 | + toc.querySelector('a').addEventListener('click', function (e) { | |
8 | + e.preventDefault() | |
9 | + e.stopPropagation() | |
10 | + toc.classList.add('expanded') | |
11 | + }) | |
12 | + document.body.addEventListener('click', function () { | |
13 | + toc.classList.remove('expanded') | |
14 | + }) | |
15 | +} | |
16 | + | |
17 | +function selectTab (el, n) { | |
18 | + // deselect current | |
19 | + try { el.querySelector('pre.current').classList.remove('current') } catch (e) {} | |
20 | + try { el.querySelector('.tab.current').classList.remove('current') } catch (e) {} | |
21 | + // select new | |
22 | + el.querySelector('pre:nth-child('+n+')').classList.add('current') | |
23 | + el.querySelector('.tab:nth-child('+n+')').classList.add('current') | |
24 | +} |
Built with git-ssb-web