git ssb

16+

Dominic / patchbay



Commit ba7439117c4a64cf7928c63d64fd58acd9898993

add tests for module deps, and mov emodules till it passes

mix irving committed on 1/19/2017, 9:18:40 AM
Parent: 3c201fb3cd2ad22f338850c91b72818022074849

Files changed

modules_basic/index.jschanged
modules_basic/message/confirm.jsadded
modules_basic/message/confirm.mcssadded
modules_basic/emoji.jsadded
modules_basic/index.test.jsadded
modules_basic/names.jsdeleted
modules_basic/search-box.jsdeleted
modules_basic/suggest-mentions.jsdeleted
modules_core/index.jschanged
modules_core/menu.jschanged
modules_core/sbot.jschanged
modules_core/index.test.jsadded
modules_core/message/confirm.jsdeleted
modules_core/message/confirm.mcssdeleted
modules_core/names.jsadded
modules_core/search-box.jsadded
modules_core/suggest-mentions.jsadded
modules_extra/index.jschanged
modules_extra/emoji.jsdeleted
modules_extra/index.test.jsadded
package.jsonchanged
modules_basic/index.jsView
@@ -8,30 +8,29 @@
88 'profile': require('./avatar/profile'),
99 'avatar': require('./avatar/avatar')
1010 },
1111 'compose': require('./compose'),
12 + 'emoji': require('./emoji'),
1213 'feed': require('./feed'),
1314 'follow': require('./follow'),
1415 'invite': require('./invite'),
1516 'like': require('./like'),
1617 'markdown': require('./markdown'),
1718 'message': {
1819 'author': require('./message/author'),
1920 'backlinks': require('./message/backlinks'),
21 + 'confirm': require('./message/confirm'),
2022 'link': require('./message/link'),
2123 'name': require('./message/name'),
2224 'render': require('./message/render'),
2325 },
24- 'names': require('./names'),
2526 'post': require('./post'),
2627 'private': require('./private'),
2728 'pub': require('./pub'),
2829 'public': require('./public'),
2930 'relationships': require('./relationships'),
3031 'reply': require('./reply'),
31- 'search-box': require('./search-box'),
3232 'setup': require('./setup'),
33- 'suggest-mentions': require('./suggest-mentions'),
3433 'thread': require('./thread'),
3534 'timestamp': require('./timestamp')
3635 }
3736
modules_basic/message/confirm.jsView
@@ -1,0 +1,73 @@
1 +var fs = require('fs')
2 +var lightbox = require('hyperlightbox')
3 +var h = require('../../h')
4 +var self_id = require('../../keys').id
5 +//publish or add
6 +
7 +exports.needs = {
8 + publish: 'first',
9 + message_render: 'first',
10 + avatar: 'first',
11 + message_meta: 'map'
12 +}
13 +
14 +exports.gives = {
15 + message_confirm: true,
16 + mcss: true
17 +}
18 +
19 +exports.create = function (api) {
20 + return {
21 + message_confirm,
22 + mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
23 + }
24 +
25 + function message_confirm (content, cb) {
26 +
27 + cb = cb || function () {}
28 +
29 + var lb = lightbox()
30 + document.body.appendChild(lb)
31 +
32 + var msg = {
33 + key: "DRAFT",
34 + value: {
35 + author: self_id,
36 + previous: null,
37 + sequence: null,
38 + timestamp: Date.now(),
39 + content: content
40 + }
41 + }
42 +
43 + var okay = h('button', {
44 + 'ev-click': () => {
45 + lb.remove()
46 + api.publish(content, cb)
47 + }},
48 + 'okay'
49 + )
50 +
51 + var cancel = h('button', {
52 + 'ev-click': () => {
53 + lb.remove()
54 + cb(null)
55 + }},
56 + 'Cancel'
57 + )
58 +
59 + okay.addEventListener('keydown', function (ev) {
60 + if(ev.keyCode === 27) cancel.click() //escape
61 + })
62 +
63 + lb.show(h('MessageConfirm', [
64 + h('header -preview_description', h('h1', 'Preview')),
65 + h('section -message_preview', api.message_render(msg)),
66 + h('section -actions', [okay, cancel])
67 + ]
68 + ))
69 +
70 + okay.focus()
71 + }
72 +}
73 +
modules_basic/message/confirm.mcssView
@@ -1,0 +1,39 @@
1 +MessageConfirm {
2 + section {
3 + -preview_description {
4 + }
5 +
6 + -message_preview {
7 + background-color: white
8 +
9 + div {
10 + border: none
11 +
12 + header.author {
13 + div {
14 + section {
15 + -timestamp {
16 + display: none
17 + }
18 + }
19 + }
20 + }
21 +
22 + section.action {
23 + display: none
24 + }
25 + }
26 + }
27 +
28 + -actions {
29 + margin-top: 1rem
30 + display: flex
31 + justify-content: flex-end
32 +
33 + button {
34 + margin: 0 0 0 1rem
35 + }
36 + }
37 + }
38 +}
39 +
modules_basic/emoji.jsView
@@ -1,0 +1,18 @@
1 +var emojis = require('emoji-named-characters')
2 +var emojiNames = Object.keys(emojis)
3 +
4 +exports.needs = { blob_url: 'first' }
5 +exports.gives = { emoji_names: true, emoji_url: true }
6 +
7 +exports.create = function (api) {
8 + return {
9 + emoji_names: function () {
10 + return emojiNames
11 + },
12 + emoji_url: function (emoji) {
13 + return emoji in emojis &&
14 + api.blob_url(emoji).replace(/\/blobs\/get/, '/img/emoji') + '.png'
15 + }
16 + }
17 +}
18 +
modules_basic/index.test.jsView
@@ -1,0 +1,11 @@
1 +const test = require('tape')
2 +const combine = require('depject')
3 +
4 +const core = require('../modules_core')
5 +const basic = require('./')
6 +
7 +test('modules_basic has no outside deps', t => {
8 + t.ok(combine(basic, core))
9 + t.end()
10 +})
11 +
modules_basic/names.jsView
@@ -1,179 +1,0 @@
1-var pull = require('pull-stream')
2-var many = require('pull-many')
3-var mfr = require('map-filter-reduce')
4-
5-function all(stream, cb) {
6- pull(stream, pull.collect(cb))
7-}
8-
9-exports.needs = {
10- sbot_links2: 'first',
11- sbot_query: 'first'
12-}
13-
14-exports.gives = {
15- connection_status: true,
16- signifier: true,
17- signified: true,
18-}
19-
20-/*
21- filter(rel: ['mentions', prefix('@')]) | reduce(name: rel[1], value: count())
22-*/
23-
24-var filter = {
25- $filter: {
26- rel: ["mentions", {$prefix: "@"}]
27- }
28-}
29-var map = {
30- $map: {
31- name: ['rel', 1],
32- id: 'dest',
33- ts: 'ts',
34- }
35-}
36-
37-var reduce = {
38- $reduce: {
39- name: 'name',
40- id: 'id',
41- rank: {$count: true},
42- ts: {$max: 'ts'}
43- }
44-}
45-
46-var filter2 = {
47- $filter: {
48- value: {
49- content: {
50- type: "about",
51- name: {"$prefix": ""},
52- about: {"$prefix": ""}
53- }
54- }
55- }
56-}
57-
58-var map2 = {
59- $map: {
60- name: ["value", "content", "name"],
61- id: ['value', 'content', 'about'],
62- ts: "timestamp"
63- }
64-}
65-
66-//union with this query...
67-
68-var names = NAMES = []
69-function update(name) {
70- var n = names.find(function (e) {
71- return e.id == name.id && e.name == e.name
72- })
73- if(!n) {
74- name.rank = 1
75- //this should be inserted at the right place...
76- names.push(name)
77- }
78- else
79- n.rank = n.rank += (name.rank || 1)
80-}
81-
82-var ready = false, waiting = []
83-
84-var merge = {
85- $reduce: {
86- name: 'name',
87- id: 'id',
88- rank: {$sum: 'rank'},
89- ts: {$max: 'ts'}
90- }
91-}
92-
93-function add_sigil(stream) {
94- return pull(stream, pull.map(function (e) {
95- if (e && e.id && e.name && e.id[0] !== e.name[0])
96- e.name = e.id[0] + e.name
97- return e
98- })
99- )
100-}
101-
102-var queryNamedGitRepos = [
103- {$filter: {
104- value: {
105- content: {
106- type: "git-repo",
107- name: {"$prefix": ""}
108- }
109- }
110- }},
111- {$map: {
112- name: ["value", "content", "name"],
113- id: ['key'],
114- ts: "timestamp"
115- }},
116- reduce
117-]
118-exports.create = function (api) {
119-
120- var exports = {}
121- exports.connection_status = function (err) {
122- if(!err) {
123- pull(
124- many([
125- api.sbot_links2({query: [filter, map, reduce]}),
126- add_sigil(api.sbot_query({query: [filter2, map2, reduce]})),
127- add_sigil(api.sbot_query({query: queryNamedGitRepos}))
128- ]),
129- //reducing also ensures order by the lookup properties
130- //in this case: [name, id]
131- mfr.reduce(merge),
132- pull.collect(function (err, ary) {
133- if(!err) {
134- NAMES = names = ary
135- ready = true
136- while(waiting.length) waiting.shift()()
137- }
138- })
139- )
140-
141- pull(many([
142- api.sbot_links2({query: [filter, map], old: false}),
143- add_sigil(api.sbot_query({query: [filter2, map2], old: false})),
144- add_sigil(api.sbot_query({query: queryNamedGitRepos, old: false}))
145- ]),
146- pull.drain(update))
147- }
148- }
149-
150- function async(fn) {
151- return function (value, cb) {
152- function go () { cb(null, fn(value)) }
153- if(ready) go()
154- else waiting.push(go)
155- }
156- }
157-
158- function rank(ary) {
159- //sort by most used, or most recently used
160- return ary.sort(function (a, b) { return b.rank - a.rank || b.ts - a.ts })
161- }
162-
163- //we are just iterating over the entire array.
164- //if this becomes a problem, maintain two arrays
165- //one of each sort order, but do not duplicate the objects.
166- //that should mean the space required is just 2x object references,
167- //not 2x objects, and we can use binary search to find matches.
168-
169- exports.signifier = async(function (id) {
170- return rank(names.filter(function (e) { return e.id == id}))
171- })
172-
173- exports.signified = async(function (name) {
174- var rx = new RegExp('^'+name)
175- return rank(names.filter(function (e) { return rx.test(e.name) }))
176- })
177-
178- return exports
179-}
modules_basic/search-box.jsView
@@ -1,68 +1,0 @@
1-'use strict'
2-var cont = require('cont')
3-var h = require('hyperscript')
4-var suggest = require('suggest-box')
5-
6-exports.needs = {
7- sbot_query: 'first', sbot_links2: 'first',
8- suggest_search: 'map' //REWRITE
9-}
10-
11-exports.gives = 'search_box'
12-
13-exports.create = function (api) {
14-
15- return function (go) {
16-
17- var suggestBox
18- var search = h('input.searchprompt', {
19- type: 'search',
20- placeholder: 'Commands',
21- onkeydown: function (ev) {
22- switch (ev.keyCode) {
23- case 13: // enter
24- if (suggestBox && suggestBox.active) {
25- suggestBox.complete()
26- ev.stopPropagation()
27- }
28- if (go(search.value.trim(), !ev.ctrlKey))
29- search.blur()
30- return
31- case 27: // escape
32- ev.preventDefault()
33- search.blur()
34- return
35- }
36- }
37- })
38-
39- search.activate = function (sigil, ev) {
40- search.focus()
41- ev.preventDefault()
42- if (search.value[0] === sigil) {
43- search.selectionStart = 1
44- search.selectionEnd = search.value.length
45- } else {
46- search.value = sigil
47- }
48- }
49-
50- // delay until the element has a parent
51- setTimeout(function () {
52- suggestBox = suggest(search, function (word, cb) {
53- cont.para(api.suggest_search(word))
54- (function (err, ary) {
55- if(err) return cb(err)
56-
57- cb(null, ary.filter(Boolean).reduce(function (a, b) {
58- return a.concat(b)
59- }, []))
60- })
61- }, {})
62- }, 10)
63-
64- return search
65- }
66-
67-}
68-
modules_basic/suggest-mentions.jsView
@@ -1,63 +1,0 @@
1-
2-exports.needs = {
3- sbot_links2: 'first',
4- blob_url: 'first',
5- signified: 'first',
6- builtin_tabs: 'map'
7-}
8-
9-exports.gives = {
10- suggest_mentions: true,
11- suggest_search: true
12-}
13-
14-exports.create = function (api) {
15-
16- return {
17- suggest_mentions: function (word) {
18- return function (cb) {
19- if(!/^[%&@]\w/.test(word)) return cb()
20-
21- api.signified(word, function (err, names) {
22- if(err) cb(err)
23- else cb(null, names.map(function (e) {
24- return {
25- title: e.name + ': ' + e.id.substring(0,10)+' ('+e.rank+')',
26- value: '['+e.name+']('+e.id+')',
27- rank: e.rank,
28- //TODO: avatar images...
29- }
30- }))
31- })
32- }
33- },
34-
35- suggest_search: function (query) {
36- return function (cb) {
37- if(/^[@%]\w/.test(query)) {
38- api.signified(query, function (_, names) {
39- cb(null, names.map(function (e) {
40- return {
41- title: e.name + ':'+e.id.substring(0, 10),
42- value: e.id,
43- subtitle: e.rank,
44- rank: e.rank
45- }
46- }))
47- })
48-
49- } else if(/^\//.test(query)) {
50- var tabs = [].concat.apply([], api.builtin_tabs())
51- cb(null, tabs.filter(function (name) {
52- return name.substr(0, query.length) === query
53- }).map(function (name) {
54- return {
55- title: name,
56- value: name,
57- }
58- }))
59- } else cb()
60- }
61- }
62- }
63-}
modules_core/index.jsView
@@ -4,15 +4,15 @@
44 'crypto': require('./crypto'),
55 'external-confirm': require('./external-confirm'),
66 'file-input': require('./file-input'),
77 'menu': require('./menu'),
8- 'message': {
9- 'confirm': require('./message/confirm')
10- },
11- 'tabs': require('./tabs'),
12- 'sbot': require('./sbot'),
8 + 'names': require('./names'),
9 + 'tabs': require('./tabs'),
10 + 'sbot': require('./sbot'),
11 + 'search-box': require('./search-box'),
1312 'style': {
1413 'styles': require('./style/styles'),
1514 'mixins': require('./style/mixins')
16- }
15 + },
16 + 'suggest-mentions': require('./suggest-mentions')
1717 }
1818
modules_core/menu.jsView
@@ -1,23 +1,28 @@
1-var h = require('hyperscript')
1 +const h = require('hyperscript')
22
33 module.exports = {
4- needs: {menu_items: 'map'},
5- gives: {connection_status: true, menu: true},
4 + needs: {
5 + menu_items: 'map'
6 + },
7 + gives: {
8 + connection_status: true,
9 + menu: true,
10 + menu_items: true
11 + },
612 create: function (api) {
13 + const { menu_items } = api
714
8- var menu_items = api.menu_items
9-
1015 var status = h('div.status.error') //start off disconnected
1116 var list = h('div.menu.column', {style: 'display: none;'})
1217
13- var menu = h('div.column', status, list , {
14- onmouseover: function (e) {
15- list.style.display = 'flex'
16- }, onmouseout: function () {
17- list.style.display = 'none'
18- }
19- })
18 + var menu = h('div.column', {
19 + onmouseover: () => list.style.display = 'flex',
20 + onmouseout: () => list.style.display = 'none'
21 + }, [
22 + status,
23 + list
24 + ])
2025
2126 setTimeout(function () {
2227 menu_items().forEach(function (el) {
2328 if(el)
@@ -25,15 +30,14 @@
2530 })
2631 }, 0)
2732
2833 return {
29- connection_status: function (err) {
34 + connection_status: (err) => {
3035 if(err) status.classList.add('error')
3136 else status.classList.remove('error')
3237 },
33- menu: function () {
34- return menu
35- }
38 + menu: () => menu,
39 + menu_items: () => null
3640 }
3741 }
3842 }
3943
modules_core/sbot.jsView
@@ -59,8 +59,14 @@
5959 var opts = createConfig()
6060 var sbot = null
6161 var connection_status = []
6262
63 + var rec = {
64 + sync: () => {},
65 + async: () => {},
66 + source: () => {},
67 + }
68 +
6369 var rec = Reconnect(function (isConn) {
6470 function notify (value) {
6571 isConn(value); api.connection_status(value) //.forEach(function (fn) { fn(value) })
6672 }
modules_core/index.test.jsView
@@ -1,0 +1,10 @@
1 +const test = require('tape')
2 +const combine = require('depject')
3 +
4 +const core = require('./')
5 +
6 +test('modules_core has no outside deps', t => {
7 + t.ok(combine(core))
8 + t.end()
9 +})
10 +
modules_core/message/confirm.jsView
@@ -1,73 +1,0 @@
1-var fs = require('fs')
2-var lightbox = require('hyperlightbox')
3-var h = require('../../h')
4-var self_id = require('../../keys').id
5-//publish or add
6-
7-exports.needs = {
8- publish: 'first',
9- message_render: 'first',
10- avatar: 'first',
11- message_meta: 'map'
12-}
13-
14-exports.gives = {
15- message_confirm: true,
16- mcss: true
17-}
18-
19-exports.create = function (api) {
20- return {
21- message_confirm,
22- mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
23- }
24-
25- function message_confirm (content, cb) {
26-
27- cb = cb || function () {}
28-
29- var lb = lightbox()
30- document.body.appendChild(lb)
31-
32- var msg = {
33- key: "DRAFT",
34- value: {
35- author: self_id,
36- previous: null,
37- sequence: null,
38- timestamp: Date.now(),
39- content: content
40- }
41- }
42-
43- var okay = h('button', {
44- 'ev-click': () => {
45- lb.remove()
46- api.publish(content, cb)
47- }},
48- 'okay'
49- )
50-
51- var cancel = h('button', {
52- 'ev-click': () => {
53- lb.remove()
54- cb(null)
55- }},
56- 'Cancel'
57- )
58-
59- okay.addEventListener('keydown', function (ev) {
60- if(ev.keyCode === 27) cancel.click() //escape
61- })
62-
63- lb.show(h('MessageConfirm', [
64- h('header -preview_description', h('h1', 'Preview')),
65- h('section -message_preview', api.message_render(msg)),
66- h('section -actions', [okay, cancel])
67- ]
68- ))
69-
70- okay.focus()
71- }
72-}
73-
modules_core/message/confirm.mcssView
@@ -1,39 +1,0 @@
1-MessageConfirm {
2- section {
3- -preview_description {
4- }
5-
6- -message_preview {
7- background-color: white
8-
9- div {
10- border: none
11-
12- header.author {
13- div {
14- section {
15- -timestamp {
16- display: none
17- }
18- }
19- }
20- }
21-
22- section.action {
23- display: none
24- }
25- }
26- }
27-
28- -actions {
29- margin-top: 1rem
30- display: flex
31- justify-content: flex-end
32-
33- button {
34- margin: 0 0 0 1rem
35- }
36- }
37- }
38-}
39-
modules_core/names.jsView
@@ -1,0 +1,179 @@
1 +var pull = require('pull-stream')
2 +var many = require('pull-many')
3 +var mfr = require('map-filter-reduce')
4 +
5 +function all(stream, cb) {
6 + pull(stream, pull.collect(cb))
7 +}
8 +
9 +exports.needs = {
10 + sbot_links2: 'first',
11 + sbot_query: 'first'
12 +}
13 +
14 +exports.gives = {
15 + connection_status: true,
16 + signifier: true,
17 + signified: true,
18 +}
19 +
20 +/*
21 + filter(rel: ['mentions', prefix('@')]) | reduce(name: rel[1], value: count())
22 +*/
23 +
24 +var filter = {
25 + $filter: {
26 + rel: ["mentions", {$prefix: "@"}]
27 + }
28 +}
29 +var map = {
30 + $map: {
31 + name: ['rel', 1],
32 + id: 'dest',
33 + ts: 'ts',
34 + }
35 +}
36 +
37 +var reduce = {
38 + $reduce: {
39 + name: 'name',
40 + id: 'id',
41 + rank: {$count: true},
42 + ts: {$max: 'ts'}
43 + }
44 +}
45 +
46 +var filter2 = {
47 + $filter: {
48 + value: {
49 + content: {
50 + type: "about",
51 + name: {"$prefix": ""},
52 + about: {"$prefix": ""}
53 + }
54 + }
55 + }
56 +}
57 +
58 +var map2 = {
59 + $map: {
60 + name: ["value", "content", "name"],
61 + id: ['value', 'content', 'about'],
62 + ts: "timestamp"
63 + }
64 +}
65 +
66 +//union with this query...
67 +
68 +var names = NAMES = []
69 +function update(name) {
70 + var n = names.find(function (e) {
71 + return e.id == name.id && e.name == e.name
72 + })
73 + if(!n) {
74 + name.rank = 1
75 + //this should be inserted at the right place...
76 + names.push(name)
77 + }
78 + else
79 + n.rank = n.rank += (name.rank || 1)
80 +}
81 +
82 +var ready = false, waiting = []
83 +
84 +var merge = {
85 + $reduce: {
86 + name: 'name',
87 + id: 'id',
88 + rank: {$sum: 'rank'},
89 + ts: {$max: 'ts'}
90 + }
91 +}
92 +
93 +function add_sigil(stream) {
94 + return pull(stream, pull.map(function (e) {
95 + if (e && e.id && e.name && e.id[0] !== e.name[0])
96 + e.name = e.id[0] + e.name
97 + return e
98 + })
99 + )
100 +}
101 +
102 +var queryNamedGitRepos = [
103 + {$filter: {
104 + value: {
105 + content: {
106 + type: "git-repo",
107 + name: {"$prefix": ""}
108 + }
109 + }
110 + }},
111 + {$map: {
112 + name: ["value", "content", "name"],
113 + id: ['key'],
114 + ts: "timestamp"
115 + }},
116 + reduce
117 +]
118 +exports.create = function (api) {
119 +
120 + var exports = {}
121 + exports.connection_status = function (err) {
122 + if(!err) {
123 + pull(
124 + many([
125 + api.sbot_links2({query: [filter, map, reduce]}),
126 + add_sigil(api.sbot_query({query: [filter2, map2, reduce]})),
127 + add_sigil(api.sbot_query({query: queryNamedGitRepos}))
128 + ]),
129 + //reducing also ensures order by the lookup properties
130 + //in this case: [name, id]
131 + mfr.reduce(merge),
132 + pull.collect(function (err, ary) {
133 + if(!err) {
134 + NAMES = names = ary
135 + ready = true
136 + while(waiting.length) waiting.shift()()
137 + }
138 + })
139 + )
140 +
141 + pull(many([
142 + api.sbot_links2({query: [filter, map], old: false}),
143 + add_sigil(api.sbot_query({query: [filter2, map2], old: false})),
144 + add_sigil(api.sbot_query({query: queryNamedGitRepos, old: false}))
145 + ]),
146 + pull.drain(update))
147 + }
148 + }
149 +
150 + function async(fn) {
151 + return function (value, cb) {
152 + function go () { cb(null, fn(value)) }
153 + if(ready) go()
154 + else waiting.push(go)
155 + }
156 + }
157 +
158 + function rank(ary) {
159 + //sort by most used, or most recently used
160 + return ary.sort(function (a, b) { return b.rank - a.rank || b.ts - a.ts })
161 + }
162 +
163 + //we are just iterating over the entire array.
164 + //if this becomes a problem, maintain two arrays
165 + //one of each sort order, but do not duplicate the objects.
166 + //that should mean the space required is just 2x object references,
167 + //not 2x objects, and we can use binary search to find matches.
168 +
169 + exports.signifier = async(function (id) {
170 + return rank(names.filter(function (e) { return e.id == id}))
171 + })
172 +
173 + exports.signified = async(function (name) {
174 + var rx = new RegExp('^'+name)
175 + return rank(names.filter(function (e) { return rx.test(e.name) }))
176 + })
177 +
178 + return exports
179 +}
modules_core/search-box.jsView
@@ -1,0 +1,68 @@
1 +'use strict'
2 +var cont = require('cont')
3 +var h = require('hyperscript')
4 +var suggest = require('suggest-box')
5 +
6 +exports.needs = {
7 + sbot_query: 'first', sbot_links2: 'first',
8 + suggest_search: 'map' //REWRITE
9 +}
10 +
11 +exports.gives = 'search_box'
12 +
13 +exports.create = function (api) {
14 +
15 + return function (go) {
16 +
17 + var suggestBox
18 + var search = h('input.searchprompt', {
19 + type: 'search',
20 + placeholder: 'Commands',
21 + onkeydown: function (ev) {
22 + switch (ev.keyCode) {
23 + case 13: // enter
24 + if (suggestBox && suggestBox.active) {
25 + suggestBox.complete()
26 + ev.stopPropagation()
27 + }
28 + if (go(search.value.trim(), !ev.ctrlKey))
29 + search.blur()
30 + return
31 + case 27: // escape
32 + ev.preventDefault()
33 + search.blur()
34 + return
35 + }
36 + }
37 + })
38 +
39 + search.activate = function (sigil, ev) {
40 + search.focus()
41 + ev.preventDefault()
42 + if (search.value[0] === sigil) {
43 + search.selectionStart = 1
44 + search.selectionEnd = search.value.length
45 + } else {
46 + search.value = sigil
47 + }
48 + }
49 +
50 + // delay until the element has a parent
51 + setTimeout(function () {
52 + suggestBox = suggest(search, function (word, cb) {
53 + cont.para(api.suggest_search(word))
54 + (function (err, ary) {
55 + if(err) return cb(err)
56 +
57 + cb(null, ary.filter(Boolean).reduce(function (a, b) {
58 + return a.concat(b)
59 + }, []))
60 + })
61 + }, {})
62 + }, 10)
63 +
64 + return search
65 + }
66 +
67 +}
68 +
modules_core/suggest-mentions.jsView
@@ -1,0 +1,68 @@
1 +
2 +exports.needs = {
3 + sbot_links2: 'first',
4 + blob_url: 'first',
5 + signified: 'first',
6 + builtin_tabs: 'map'
7 +}
8 +
9 +exports.gives = {
10 + suggest_mentions: true,
11 + suggest_search: true,
12 + builtin_tabs: true
13 +}
14 +
15 +exports.create = function (api) {
16 +
17 + return {
18 + suggest_mentions,
19 + suggest_search,
20 + builtin_tabs: () => null
21 + }
22 +
23 + function suggest_mentions (word) {
24 + return function (cb) {
25 + if(!/^[%&@]\w/.test(word)) return cb()
26 +
27 + api.signified(word, function (err, names) {
28 + if(err) cb(err)
29 + else cb(null, names.map(function (e) {
30 + return {
31 + title: e.name + ': ' + e.id.substring(0,10)+' ('+e.rank+')',
32 + value: '['+e.name+']('+e.id+')',
33 + rank: e.rank,
34 + //TODO: avatar images...
35 + }
36 + }))
37 + })
38 + }
39 + }
40 +
41 + function suggest_search (query) {
42 + return function (cb) {
43 + if(/^[@%]\w/.test(query)) {
44 + api.signified(query, function (_, names) {
45 + cb(null, names.map(function (e) {
46 + return {
47 + title: e.name + ':'+e.id.substring(0, 10),
48 + value: e.id,
49 + subtitle: e.rank,
50 + rank: e.rank
51 + }
52 + }))
53 + })
54 +
55 + } else if(/^\//.test(query)) {
56 + var tabs = [].concat.apply([], api.builtin_tabs())
57 + cb(null, tabs.filter(function (name) {
58 + return name.substr(0, query.length) === query
59 + }).map(function (name) {
60 + return {
61 + title: name,
62 + value: name,
63 + }
64 + }))
65 + } else cb()
66 + }
67 + }
68 +}
modules_extra/index.jsView
@@ -1,9 +1,8 @@
11 module.exports = {
22 // 'audio-mp3': require('./audio-mp3'),
33 'blob': require('./blob'),
44 'channel': require('./channel'),
5- 'emoji': require('./emoji'),
65 'suggest-emoji': require('./suggest-emoji'),
76 'dns': require('./dns'),
87 'git': require('./git'),
98 'git-ssb': require('./git-ssb'),
modules_extra/emoji.jsView
@@ -1,18 +1,0 @@
1-var emojis = require('emoji-named-characters')
2-var emojiNames = Object.keys(emojis)
3-
4-exports.needs = { blob_url: 'first' }
5-exports.gives = { emoji_names: true, emoji_url: true }
6-
7-exports.create = function (api) {
8- return {
9- emoji_names: function () {
10- return emojiNames
11- },
12- emoji_url: function (emoji) {
13- return emoji in emojis &&
14- api.blob_url(emoji).replace(/\/blobs\/get/, '/img/emoji') + '.png'
15- }
16- }
17-}
18-
modules_extra/index.test.jsView
@@ -1,0 +1,20 @@
1 +const test = require('tape')
2 +const jsdom = require('jsdom')
3 +const combine = require('depject')
4 +
5 +var window = {}
6 +
7 +const core = require('../modules_core')
8 +const basic = require('../modules_basic')
9 +const extra = require('./')
10 +
11 +// jsdom.env('<body></body>', (err, window) => {
12 +
13 + test('modules_extra has no outside deps', t => {
14 + t.ok(combine(extra, basic, core))
15 + t.end()
16 + // window.close()
17 + })
18 +// })
19 +
20 +
package.jsonView
@@ -6,14 +6,22 @@
66 "repository": {
77 "type": "git",
88 "url": "git://github.com/dominictarr/patchbay.git"
99 },
10 + "scripts": {
11 + "lite": "mkdir -p build && browserify index.js | indexhtmlify --title patchbay > build/index.html",
12 + "start": "electro index.js",
13 + "bundle": "mkdir -p build && browselectrify index.js > build/bundle.js",
14 + "rebuild": "npm rebuild --runtime=electron --target=$(electron -v) --abi=$(electron --abi) --disturl=https://atom.io/download/atom-shell",
15 + "graph": "node index.js | dot -Tsvg > graph.svg",
16 + "test": "browserify modules_*/index.test.js | tape-run"
17 + },
1018 "dependencies": {
1119 "@mmckegg/mutant": "^3.12.0",
1220 "brfs": "^1.4.3",
1321 "cont": "^1.0.3",
1422 "dataurl-": "^0.1.0",
15- "depject": "^3.1.0",
23 + "depject": "^3.1.4",
1624 "es2040": "^1.2.4",
1725 "hjson": "^2.0.3",
1826 "human-time": "0.0.1",
1927 "hypercombo": "0.1.0",
@@ -64,23 +72,17 @@
6472 "devDependencies": {
6573 "browselectrify": "^1.0.1",
6674 "electro": "^2.0.3",
6775 "electron": "^1.4.10",
68- "indexhtmlify": "^1.3.1"
76 + "indexhtmlify": "^1.3.1",
77 + "tape": "^4.6.3",
78 + "tape-run": "^2.1.5"
6979 },
7080 "browserify": {
7181 "transform": [
7282 "brfs",
7383 "es2040"
7484 ]
7585 },
76- "scripts": {
77- "lite": "mkdir -p build && browserify index.js | indexhtmlify --title patchbay > build/index.html",
78- "start": "electro index.js",
79- "bundle": "mkdir -p build && browselectrify index.js > build/bundle.js",
80- "rebuild": "npm rebuild --runtime=electron --target=$(electron -v) --abi=$(electron --abi) --disturl=https://atom.io/download/atom-shell",
81- "graph": "node index.js | dot -Tsvg > graph.svg",
82- "test": "set -e; for t in test/*.js; do node $t; done"
83- },
8486 "author": "Dominic Tarr <dominic.tarr@gmail.com> (http://dominictarr.com)",
8587 "license": "MIT"
8688 }

Built with git-ssb-web