git ssb

2+

mixmix / ticktack



Tree: 909b4b2756a7aaa99f6114938b240b53beb129c8

Files: 909b4b2756a7aaa99f6114938b240b53beb129c8 / app / page / blogNew.js

5628 bytesRaw
1const nest = require('depnest')
2const { h, Struct, Value } = require('mutant')
3const addSuggest = require('suggest-box')
4const pull = require('pull-stream')
5const marksum = require('markdown-summary')
6const MediumEditor = require('medium-editor').MediumEditor
7const MediumToMD = require('medium-editor-markdown')
8const CustomHtml = require('medium-editor-custom-async')
9
10exports.gives = nest('app.page.blogNew')
11
12exports.needs = nest({
13 'app.html.sideNav': 'first',
14 'channel.async.suggest': 'first',
15 'history.sync.push': 'first',
16 'message.html.compose': 'first',
17 'translations.sync.strings': 'first',
18 'sbot.async.addBlob': 'first'
19})
20
21exports.create = (api) => {
22 var contentHtmlObs
23
24 return nest('app.page.blogNew', blogNew)
25
26 function blogNew (location) {
27 const strings = api.translations.sync.strings()
28 const getChannelSuggestions = api.channel.async.suggest()
29
30 const meta = Struct({
31 type: 'blog',
32 channel: Value(),
33 title: Value(),
34 summary: Value(),
35 text: Value('')
36 })
37
38 const mediumComposer = h('div.editor', {
39 'ev-input': e => {
40 }
41 })
42 const composer = api.message.html.compose(
43 {
44 meta,
45 placeholder: strings.blogNew.actions.writeBlog,
46 shrink: false,
47 prepublish: function (content, cb) {
48 var m = /\!\[[^]+\]\(([^\)]+)\)/.exec(marksum.image(content.text))
49 content.thumbnail = m && m[1]
50 // content.summary = marksum.summary(content.text) // Need a summary whihch doesn't trim the start
51
52 var stream = pull.values([content.text])
53 delete content.text
54 api.sbot.async.addBlob(stream, function (err, hash) {
55 if (err) return cb(err)
56 if (!hash) throw new Error('missing hash')
57 content.blog = hash
58 cb(null, content)
59 })
60 }
61 },
62 (err, msg) => api.history.sync.push(err || { page: 'blogIndex' })
63 )
64
65 const channelInput = h('input', {
66 'ev-input': e => meta.channel.set(e.target.value),
67 value: meta.channel,
68 placeholder: strings.channel
69 })
70
71 var page = h('Page -blogNew', [
72 api.app.html.sideNav(location),
73 h('div.content', [
74 h('div.container', [
75 h('div.field -channel', [
76 h('div.label', strings.channel),
77 channelInput
78 ]),
79 h('div.field -title', [
80 h('div.label', strings.blogNew.field.title),
81 h('input', {
82 'ev-input': e => meta.title.set(e.target.value),
83 placeholder: strings.blogNew.field.title
84 })
85 ]),
86 h('div.field -summary', [
87 h('div.label', strings.blogNew.field.summary),
88 h('input', {
89 'ev-input': e => meta.summary.set(e.target.value),
90 placeholder: strings.blogNew.field.summary
91 })
92 ]),
93 mediumComposer,
94 h('Button', {
95 'ev-click': () => {
96 var img = h('img', { src: 'http://localhost:8989/blobs/get/%264TKyoyZmjjtpPvwiSR%2BGQIgrJs8o6XmzfUDZ5p1PP30%3D.sha256' })
97 // var e = MediumEditor.getEditorFromElement(mediumComposer)
98 // e.serialize()['element-0'].value
99 mediumComposer.appendChild(img)
100 }
101 }, 'Add Image'),
102 composer
103 ])
104 ])
105 ])
106
107 function initialiseMedium () {
108 new MediumEditor(mediumComposer, {
109 elementsContainer: page,
110 toolbar: {
111 allowMultiParagraphSelection: true,
112 buttons: ['bold', 'italic', 'underline', 'anchor', 'h2', 'h3', 'quote'],
113 diffLeft: 0,
114 diffTop: -10,
115 firstButtonClass: 'medium-editor-button-first',
116 lastButtonClass: 'medium-editor-button-last',
117 relativeContainer: null,
118 standardizeSelectionStart: false,
119 static: false,
120 /* options which only apply when static is true */
121 align: 'center',
122 sticky: false,
123 updateOnEmptySelection: false
124 },
125 extensions: {
126 markdown: new MediumToMD (
127 {
128 toMarkdownOptions: {
129 converters: [{
130 filter: 'img',
131 replacement: (content, node) => {
132 var blob = decodeURIComponent(node.src.replace('http://localhost:8989/blobs/get/', ''))
133 return `![](${blob})`
134 }
135 }]
136 },
137 events: ['input', 'change', 'DOMNodeInserted']
138 },
139 md => meta.text.set(md)
140 )
141 }
142 })
143 }
144 initialiseMedium()
145
146 addSuggest(channelInput, (inputText, cb) => {
147 inputText = inputText.replace(/^#/, '')
148 var suggestions = getChannelSuggestions(inputText)
149 .map(s => {
150 s.value = s.value.replace(/^#/, '') // strip the defualt # prefix here
151 return s
152 })
153 .map(s => {
154 if (s.subtitle === 'subscribed') { s.subtitle = h('i.fa.fa-heart') } // TODO - translation-friendly subscribed
155 return s
156 })
157
158 // HACK add the input text if it's not an option already
159 if (!suggestions.some(s => s.title === inputText)) {
160 suggestions.push({
161 title: inputText,
162 subtitle: h('i.fa.fa-plus-circle'),
163 value: inputText
164 })
165 }
166
167 cb(null, suggestions)
168 }, {cls: 'PatchSuggest.-channelHorizontal'}) // WARNING hacking suggest-box cls
169
170 channelInput.addEventListener('suggestselect', (e) => {
171 meta.channel.set(e.detail.value)
172 })
173
174 return page
175 }
176}
177

Built with git-ssb-web