@standardnotes/markdown-minimal 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +3 -0
- package/CHANGELOG.md +63 -0
- package/Gruntfile.js +125 -0
- package/README.md +26 -0
- package/dist/app.css +143 -0
- package/dist/app.css.map +1 -0
- package/dist/app.js +118 -0
- package/dist/app.js.map +1 -0
- package/dist/dist.css +490 -0
- package/dist/dist.js +11214 -0
- package/dist/lib.js +11096 -0
- package/dist/sn-codemirror-search/dialog/dialog.css +46 -0
- package/dist/sn-codemirror-search/dialog/dialog.js +161 -0
- package/dist/sn-codemirror-search/search.js +258 -0
- package/dist/sn-codemirror-search/searchcursor.js +293 -0
- package/ext.json +8 -0
- package/index.html +23 -0
- package/min-markdown.jpg +0 -0
- package/package.json +41 -0
- package/src/main.js +110 -0
- package/src/main.scss +151 -0
- package/vendor/addon/modes/overlay.js +90 -0
- package/vendor/mark-selection.js +119 -0
- package/vendor/modes/gfm/gfm.js +130 -0
- package/vendor/modes/markdown/markdown.js +884 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
2
|
+
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
|
3
|
+
|
|
4
|
+
(function(mod) {
|
|
5
|
+
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
6
|
+
mod(require("../../lib/codemirror"))
|
|
7
|
+
else if (typeof define == "function" && define.amd) // AMD
|
|
8
|
+
define(["../../lib/codemirror"], mod)
|
|
9
|
+
else // Plain browser env
|
|
10
|
+
mod(CodeMirror)
|
|
11
|
+
})(function(CodeMirror) {
|
|
12
|
+
"use strict"
|
|
13
|
+
var Pos = CodeMirror.Pos
|
|
14
|
+
|
|
15
|
+
function regexpFlags(regexp) {
|
|
16
|
+
var flags = regexp.flags
|
|
17
|
+
return flags != null ? flags : (regexp.ignoreCase ? "i" : "")
|
|
18
|
+
+ (regexp.global ? "g" : "")
|
|
19
|
+
+ (regexp.multiline ? "m" : "")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function ensureFlags(regexp, flags) {
|
|
23
|
+
var current = regexpFlags(regexp), target = current
|
|
24
|
+
for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1)
|
|
25
|
+
target += flags.charAt(i)
|
|
26
|
+
return current == target ? regexp : new RegExp(regexp.source, target)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function maybeMultiline(regexp) {
|
|
30
|
+
return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function searchRegexpForward(doc, regexp, start) {
|
|
34
|
+
regexp = ensureFlags(regexp, "g")
|
|
35
|
+
for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) {
|
|
36
|
+
regexp.lastIndex = ch
|
|
37
|
+
var string = doc.getLine(line), match = regexp.exec(string)
|
|
38
|
+
if (match)
|
|
39
|
+
return {from: Pos(line, match.index),
|
|
40
|
+
to: Pos(line, match.index + match[0].length),
|
|
41
|
+
match: match}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function searchRegexpForwardMultiline(doc, regexp, start) {
|
|
46
|
+
if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start)
|
|
47
|
+
|
|
48
|
+
regexp = ensureFlags(regexp, "gm")
|
|
49
|
+
var string, chunk = 1
|
|
50
|
+
for (var line = start.line, last = doc.lastLine(); line <= last;) {
|
|
51
|
+
// This grows the search buffer in exponentially-sized chunks
|
|
52
|
+
// between matches, so that nearby matches are fast and don't
|
|
53
|
+
// require concatenating the whole document (in case we're
|
|
54
|
+
// searching for something that has tons of matches), but at the
|
|
55
|
+
// same time, the amount of retries is limited.
|
|
56
|
+
for (var i = 0; i < chunk; i++) {
|
|
57
|
+
if (line > last) break
|
|
58
|
+
var curLine = doc.getLine(line++)
|
|
59
|
+
string = string == null ? curLine : string + "\n" + curLine
|
|
60
|
+
}
|
|
61
|
+
chunk = chunk * 2
|
|
62
|
+
regexp.lastIndex = start.ch
|
|
63
|
+
var match = regexp.exec(string)
|
|
64
|
+
if (match) {
|
|
65
|
+
var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
|
|
66
|
+
var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length
|
|
67
|
+
return {from: Pos(startLine, startCh),
|
|
68
|
+
to: Pos(startLine + inside.length - 1,
|
|
69
|
+
inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
|
|
70
|
+
match: match}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function lastMatchIn(string, regexp) {
|
|
76
|
+
var cutOff = 0, match
|
|
77
|
+
for (;;) {
|
|
78
|
+
regexp.lastIndex = cutOff
|
|
79
|
+
var newMatch = regexp.exec(string)
|
|
80
|
+
if (!newMatch) return match
|
|
81
|
+
match = newMatch
|
|
82
|
+
cutOff = match.index + (match[0].length || 1)
|
|
83
|
+
if (cutOff == string.length) return match
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function searchRegexpBackward(doc, regexp, start) {
|
|
88
|
+
regexp = ensureFlags(regexp, "g")
|
|
89
|
+
for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
|
|
90
|
+
var string = doc.getLine(line)
|
|
91
|
+
if (ch > -1) string = string.slice(0, ch)
|
|
92
|
+
var match = lastMatchIn(string, regexp)
|
|
93
|
+
if (match)
|
|
94
|
+
return {from: Pos(line, match.index),
|
|
95
|
+
to: Pos(line, match.index + match[0].length),
|
|
96
|
+
match: match}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function searchRegexpBackwardMultiline(doc, regexp, start) {
|
|
101
|
+
regexp = ensureFlags(regexp, "gm")
|
|
102
|
+
var string, chunk = 1
|
|
103
|
+
for (var line = start.line, first = doc.firstLine(); line >= first;) {
|
|
104
|
+
for (var i = 0; i < chunk; i++) {
|
|
105
|
+
var curLine = doc.getLine(line--)
|
|
106
|
+
string = string == null ? curLine.slice(0, start.ch) : curLine + "\n" + string
|
|
107
|
+
}
|
|
108
|
+
chunk *= 2
|
|
109
|
+
|
|
110
|
+
var match = lastMatchIn(string, regexp)
|
|
111
|
+
if (match) {
|
|
112
|
+
var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
|
|
113
|
+
var startLine = line + before.length, startCh = before[before.length - 1].length
|
|
114
|
+
return {from: Pos(startLine, startCh),
|
|
115
|
+
to: Pos(startLine + inside.length - 1,
|
|
116
|
+
inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
|
|
117
|
+
match: match}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
var doFold, noFold
|
|
123
|
+
if (String.prototype.normalize) {
|
|
124
|
+
doFold = function(str) { return str.normalize("NFD").toLowerCase() }
|
|
125
|
+
noFold = function(str) { return str.normalize("NFD") }
|
|
126
|
+
} else {
|
|
127
|
+
doFold = function(str) { return str.toLowerCase() }
|
|
128
|
+
noFold = function(str) { return str }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Maps a position in a case-folded line back to a position in the original line
|
|
132
|
+
// (compensating for codepoints increasing in number during folding)
|
|
133
|
+
function adjustPos(orig, folded, pos, foldFunc) {
|
|
134
|
+
if (orig.length == folded.length) return pos
|
|
135
|
+
for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) {
|
|
136
|
+
if (min == max) return min
|
|
137
|
+
var mid = (min + max) >> 1
|
|
138
|
+
var len = foldFunc(orig.slice(0, mid)).length
|
|
139
|
+
if (len == pos) return mid
|
|
140
|
+
else if (len > pos) max = mid
|
|
141
|
+
else min = mid + 1
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function searchStringForward(doc, query, start, caseFold) {
|
|
146
|
+
// Empty string would match anything and never progress, so we
|
|
147
|
+
// define it to match nothing instead.
|
|
148
|
+
if (!query.length) return null
|
|
149
|
+
var fold = caseFold ? doFold : noFold
|
|
150
|
+
var lines = fold(query).split(/\r|\n\r?/)
|
|
151
|
+
|
|
152
|
+
search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) {
|
|
153
|
+
var orig = doc.getLine(line).slice(ch), string = fold(orig)
|
|
154
|
+
if (lines.length == 1) {
|
|
155
|
+
var found = string.indexOf(lines[0])
|
|
156
|
+
if (found == -1) continue search
|
|
157
|
+
var start = adjustPos(orig, string, found, fold) + ch
|
|
158
|
+
return {from: Pos(line, adjustPos(orig, string, found, fold) + ch),
|
|
159
|
+
to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)}
|
|
160
|
+
} else {
|
|
161
|
+
var cutFrom = string.length - lines[0].length
|
|
162
|
+
if (string.slice(cutFrom) != lines[0]) continue search
|
|
163
|
+
for (var i = 1; i < lines.length - 1; i++)
|
|
164
|
+
if (fold(doc.getLine(line + i)) != lines[i]) continue search
|
|
165
|
+
var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1]
|
|
166
|
+
if (endString.slice(0, lastLine.length) != lastLine) continue search
|
|
167
|
+
return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch),
|
|
168
|
+
to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function searchStringBackward(doc, query, start, caseFold) {
|
|
174
|
+
if (!query.length) return null
|
|
175
|
+
var fold = caseFold ? doFold : noFold
|
|
176
|
+
var lines = fold(query).split(/\r|\n\r?/)
|
|
177
|
+
|
|
178
|
+
search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) {
|
|
179
|
+
var orig = doc.getLine(line)
|
|
180
|
+
if (ch > -1) orig = orig.slice(0, ch)
|
|
181
|
+
var string = fold(orig)
|
|
182
|
+
if (lines.length == 1) {
|
|
183
|
+
var found = string.lastIndexOf(lines[0])
|
|
184
|
+
if (found == -1) continue search
|
|
185
|
+
return {from: Pos(line, adjustPos(orig, string, found, fold)),
|
|
186
|
+
to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))}
|
|
187
|
+
} else {
|
|
188
|
+
var lastLine = lines[lines.length - 1]
|
|
189
|
+
if (string.slice(0, lastLine.length) != lastLine) continue search
|
|
190
|
+
for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++)
|
|
191
|
+
if (fold(doc.getLine(start + i)) != lines[i]) continue search
|
|
192
|
+
var top = doc.getLine(line + 1 - lines.length), topString = fold(top)
|
|
193
|
+
if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search
|
|
194
|
+
return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)),
|
|
195
|
+
to: Pos(line, adjustPos(orig, string, lastLine.length, fold))}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function SearchCursor(doc, query, pos, options) {
|
|
201
|
+
this.atOccurrence = false
|
|
202
|
+
this.doc = doc
|
|
203
|
+
pos = pos ? doc.clipPos(pos) : Pos(0, 0)
|
|
204
|
+
this.pos = {from: pos, to: pos}
|
|
205
|
+
|
|
206
|
+
var caseFold
|
|
207
|
+
if (typeof options == "object") {
|
|
208
|
+
caseFold = options.caseFold
|
|
209
|
+
} else { // Backwards compat for when caseFold was the 4th argument
|
|
210
|
+
caseFold = options
|
|
211
|
+
options = null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (typeof query == "string") {
|
|
215
|
+
if (caseFold == null) caseFold = false
|
|
216
|
+
this.matches = function(reverse, pos) {
|
|
217
|
+
return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold)
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
query = ensureFlags(query, "gm")
|
|
221
|
+
if (!options || options.multiline !== false)
|
|
222
|
+
this.matches = function(reverse, pos) {
|
|
223
|
+
return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos)
|
|
224
|
+
}
|
|
225
|
+
else
|
|
226
|
+
this.matches = function(reverse, pos) {
|
|
227
|
+
return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
SearchCursor.prototype = {
|
|
233
|
+
findNext: function() {return this.find(false)},
|
|
234
|
+
findPrevious: function() {return this.find(true)},
|
|
235
|
+
|
|
236
|
+
find: function(reverse) {
|
|
237
|
+
var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to))
|
|
238
|
+
|
|
239
|
+
// Implements weird auto-growing behavior on null-matches for
|
|
240
|
+
// backwards-compatiblity with the vim code (unfortunately)
|
|
241
|
+
while (result && CodeMirror.cmpPos(result.from, result.to) == 0) {
|
|
242
|
+
if (reverse) {
|
|
243
|
+
if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1)
|
|
244
|
+
else if (result.from.line == this.doc.firstLine()) result = null
|
|
245
|
+
else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1)))
|
|
246
|
+
} else {
|
|
247
|
+
if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1)
|
|
248
|
+
else if (result.to.line == this.doc.lastLine()) result = null
|
|
249
|
+
else result = this.matches(reverse, Pos(result.to.line + 1, 0))
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (result) {
|
|
254
|
+
this.pos = result
|
|
255
|
+
this.atOccurrence = true
|
|
256
|
+
return this.pos.match || true
|
|
257
|
+
} else {
|
|
258
|
+
var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0)
|
|
259
|
+
this.pos = {from: end, to: end}
|
|
260
|
+
return this.atOccurrence = false
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
from: function() {if (this.atOccurrence) return this.pos.from},
|
|
265
|
+
to: function() {if (this.atOccurrence) return this.pos.to},
|
|
266
|
+
|
|
267
|
+
replace: function(newText, origin) {
|
|
268
|
+
if (!this.atOccurrence) return
|
|
269
|
+
var lines = CodeMirror.splitLines(newText)
|
|
270
|
+
this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin)
|
|
271
|
+
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
|
|
272
|
+
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0))
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
|
|
277
|
+
return new SearchCursor(this.doc, query, pos, caseFold)
|
|
278
|
+
})
|
|
279
|
+
CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
|
|
280
|
+
return new SearchCursor(this, query, pos, caseFold)
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
|
|
284
|
+
var ranges = []
|
|
285
|
+
var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold)
|
|
286
|
+
while (cur.findNext()) {
|
|
287
|
+
if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break
|
|
288
|
+
ranges.push({anchor: cur.from(), head: cur.to()})
|
|
289
|
+
}
|
|
290
|
+
if (ranges.length)
|
|
291
|
+
this.setSelections(ranges, 0)
|
|
292
|
+
})
|
|
293
|
+
});
|
package/ext.json
ADDED
package/index.html
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<base target="_blank">
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
|
|
7
|
+
<script src="dist/dist.js"></script>
|
|
8
|
+
|
|
9
|
+
<script src="dist/sn-codemirror-search/search.js"></script>
|
|
10
|
+
<script src="dist/sn-codemirror-search/searchcursor.js"></script>
|
|
11
|
+
<script src="dist/sn-codemirror-search/dialog/dialog.js"></script>
|
|
12
|
+
|
|
13
|
+
<link rel="stylesheet" media="all" href="dist/dist.css">
|
|
14
|
+
<link rel="stylesheet" media="all" href="dist/sn-codemirror-search/dialog/dialog.css">
|
|
15
|
+
</head>
|
|
16
|
+
|
|
17
|
+
<body>
|
|
18
|
+
<div id="wrapper">
|
|
19
|
+
<textarea id="code" name="code"></textarea>
|
|
20
|
+
<div>
|
|
21
|
+
|
|
22
|
+
</body>
|
|
23
|
+
</html>
|
package/min-markdown.jpg
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@standardnotes/markdown-minimal",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"version": "1.2.1",
|
|
7
|
+
"description": "A minimal Markdown editor for Standard Notes.",
|
|
8
|
+
"author": "Standard Notes Retired",
|
|
9
|
+
"main": "dist/dist.js",
|
|
10
|
+
"sn": {
|
|
11
|
+
"name": "Minimal Markdown",
|
|
12
|
+
"content_type": "SN|Component",
|
|
13
|
+
"main": "index.html",
|
|
14
|
+
"area": "editor-editor",
|
|
15
|
+
"spellcheckControl": true,
|
|
16
|
+
"note_type": "markdown",
|
|
17
|
+
"file_type": "txt"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "grunt",
|
|
21
|
+
"test": "echo \"Error: no test specified\" && exit 0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@babel/core": "^7.11.1",
|
|
25
|
+
"@babel/preset-env": "^7.11.0",
|
|
26
|
+
"@standardnotes/component-relay": "standardnotes/component-relay#839ff5db9bc92db9d42cad8d202ddc4df729597d",
|
|
27
|
+
"babel-cli": "^6.26.0",
|
|
28
|
+
"codemirror": "^5.56.0",
|
|
29
|
+
"grunt": "^1.2.1",
|
|
30
|
+
"grunt-babel": "^8.0.0",
|
|
31
|
+
"grunt-browserify": "^5.3.0",
|
|
32
|
+
"grunt-contrib-concat": "^1.0.1",
|
|
33
|
+
"grunt-contrib-copy": "^1.0.0",
|
|
34
|
+
"grunt-contrib-sass": "^1.0.0",
|
|
35
|
+
"grunt-contrib-watch": "^1.1.0",
|
|
36
|
+
"grunt-newer": "^1.3.0",
|
|
37
|
+
"sass": "*",
|
|
38
|
+
"sn-codemirror-search": "1.0.0",
|
|
39
|
+
"sn-stylekit": "2.1.0"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/main.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
document.addEventListener('DOMContentLoaded', function (event) {
|
|
2
|
+
let componentRelay
|
|
3
|
+
let workingNote, clientData
|
|
4
|
+
let lastValue, lastUUID
|
|
5
|
+
let editor
|
|
6
|
+
let ignoreTextChange = false
|
|
7
|
+
let initialLoad = true
|
|
8
|
+
|
|
9
|
+
function loadComponentRelay() {
|
|
10
|
+
const initialPermissions = [{ name: 'stream-context-item' }]
|
|
11
|
+
componentRelay = new ComponentRelay({
|
|
12
|
+
initialPermissions,
|
|
13
|
+
targetWindow: window,
|
|
14
|
+
onReady: function () {
|
|
15
|
+
const platform = componentRelay.platform
|
|
16
|
+
if (platform) {
|
|
17
|
+
document.body.classList.add(platform)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
loadEditor()
|
|
21
|
+
|
|
22
|
+
// only use CodeMirror selection color if we're not on mobile.
|
|
23
|
+
editor.setOption('styleSelectedText', !componentRelay.isMobile)
|
|
24
|
+
},
|
|
25
|
+
handleRequestForContentHeight: () => {
|
|
26
|
+
return undefined
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
componentRelay.streamContextItem((note) => {
|
|
31
|
+
onReceivedNote(note)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function saveNote() {
|
|
36
|
+
if (workingNote) {
|
|
37
|
+
// Be sure to capture this object as a variable, as this.note may be reassigned in `streamContextItem`, so by the time
|
|
38
|
+
// you modify it in the presave block, it may not be the same object anymore, so the presave values will not be applied to
|
|
39
|
+
// the right object, and it will save incorrectly.
|
|
40
|
+
let note = workingNote
|
|
41
|
+
|
|
42
|
+
componentRelay.saveItemWithPresave(note, () => {
|
|
43
|
+
lastValue = editor.getValue()
|
|
44
|
+
note.content.text = lastValue
|
|
45
|
+
note.clientData = clientData
|
|
46
|
+
|
|
47
|
+
// clear previews
|
|
48
|
+
note.content.preview_plain = null
|
|
49
|
+
note.content.preview_html = null
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function onReceivedNote(note) {
|
|
55
|
+
if (note.uuid !== lastUUID) {
|
|
56
|
+
// Note changed, reset last values
|
|
57
|
+
lastValue = null
|
|
58
|
+
initialLoad = true
|
|
59
|
+
lastUUID = note.uuid
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
workingNote = note
|
|
63
|
+
|
|
64
|
+
// Only update UI on non-metadata updates.
|
|
65
|
+
if (note.isMetadataUpdate) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
clientData = note.clientData
|
|
70
|
+
|
|
71
|
+
if (editor) {
|
|
72
|
+
if (note.content.text !== lastValue) {
|
|
73
|
+
ignoreTextChange = true
|
|
74
|
+
editor.getDoc().setValue(workingNote.content.text)
|
|
75
|
+
ignoreTextChange = false
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (initialLoad) {
|
|
79
|
+
initialLoad = false
|
|
80
|
+
editor.getDoc().clearHistory()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
editor.setOption('spellcheck', workingNote.content.spellcheck)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function loadEditor() {
|
|
88
|
+
editor = CodeMirror.fromTextArea(document.getElementById('code'), {
|
|
89
|
+
mode: 'gfm',
|
|
90
|
+
lineWrapping: true,
|
|
91
|
+
extraKeys: { 'Alt-F': 'findPersistent' },
|
|
92
|
+
inputStyle: getInputStyleForEnvironment(),
|
|
93
|
+
})
|
|
94
|
+
editor.setSize(undefined, '100%')
|
|
95
|
+
|
|
96
|
+
editor.on('change', function () {
|
|
97
|
+
if (ignoreTextChange) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
saveNote()
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getInputStyleForEnvironment() {
|
|
105
|
+
const environment = componentRelay.environment ?? 'web'
|
|
106
|
+
return environment === 'mobile' ? 'textarea' : 'contenteditable'
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
loadComponentRelay()
|
|
110
|
+
})
|
package/src/main.scss
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
body,
|
|
2
|
+
html {
|
|
3
|
+
font-family: sans-serif;
|
|
4
|
+
font-size: var(--sn-stylekit-base-font-size);
|
|
5
|
+
height: 100%;
|
|
6
|
+
margin: 0;
|
|
7
|
+
background-color: transparent;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
* {
|
|
11
|
+
// To prevent gray flash when focusing input on mobile Safari
|
|
12
|
+
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#wrapper {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
position: relative;
|
|
19
|
+
height: 100%;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
// padding-right: 20px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.CodeMirror-scroll {
|
|
25
|
+
padding: 8px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.CodeMirror {
|
|
29
|
+
background-color: var(--sn-stylekit-editor-background-color) !important;
|
|
30
|
+
color: var(--sn-stylekit-editor-foreground-color) !important;
|
|
31
|
+
border: 0 !important;
|
|
32
|
+
font-family: sans-serif;
|
|
33
|
+
|
|
34
|
+
-webkit-overflow-scrolling: touch;
|
|
35
|
+
|
|
36
|
+
flex: 1 1 auto;
|
|
37
|
+
height: 100%;
|
|
38
|
+
resize: none;
|
|
39
|
+
font-size: var(--sn-stylekit-font-size-editor);
|
|
40
|
+
padding: 0;
|
|
41
|
+
|
|
42
|
+
.CodeMirror-code .cm-comment {
|
|
43
|
+
background: var(--sn-stylekit-contrast-background-color);
|
|
44
|
+
color: var(--sn-stylekit-info-color);
|
|
45
|
+
font-family: Consolas, monaco, "Ubuntu Mono", courier, monospace !important;
|
|
46
|
+
font-size: 90%; // font-family makes font look a bit big
|
|
47
|
+
|
|
48
|
+
&.CodeMirror-selectedtext {
|
|
49
|
+
color: var(--sn-stylekit-info-contrast-color) !important;
|
|
50
|
+
background: var(--sn-stylekit-info-color) !important;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.cm-header {
|
|
55
|
+
color: var(--sn-stylekit-editor-foreground-color);
|
|
56
|
+
|
|
57
|
+
&.CodeMirror-selectedtext {
|
|
58
|
+
color: var(--sn-stylekit-info-contrast-color) !important;
|
|
59
|
+
background: var(--sn-stylekit-info-color) !important;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Faded Markdown syntax
|
|
64
|
+
.cm-formatting-header,
|
|
65
|
+
.cm-formatting-strong,
|
|
66
|
+
.cm-formatting-em {
|
|
67
|
+
opacity: 0.2;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.cm-variable-2, .cm-variable-3 {
|
|
71
|
+
color: var(--sn-stylekit-editor-foreground-color) !important;
|
|
72
|
+
|
|
73
|
+
&.CodeMirror-selectedtext {
|
|
74
|
+
color: var(--sn-stylekit-info-contrast-color) !important;
|
|
75
|
+
background: transparent;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
.cm-variable-3 {
|
|
79
|
+
color: var(--sn-stylekit-editor-foreground-color) !important;
|
|
80
|
+
|
|
81
|
+
&.CodeMirror-selectedtext {
|
|
82
|
+
color: var(--sn-stylekit-info-contrast-color) !important;
|
|
83
|
+
background: transparent;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.cm-link,
|
|
88
|
+
.cm-string {
|
|
89
|
+
color: var(--sn-stylekit-info-color) !important;
|
|
90
|
+
|
|
91
|
+
&.CodeMirror-selectedtext {
|
|
92
|
+
color: var(--sn-stylekit-info-contrast-color) !important;
|
|
93
|
+
background: var(--sn-stylekit-info-color) !important;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.CodeMirror-linenumber {
|
|
98
|
+
color: gray !important;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.CodeMirror-cursor {
|
|
103
|
+
border-color: var(--sn-stylekit-editor-foreground-color);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.CodeMirror-selected {
|
|
107
|
+
background: var(--sn-stylekit-info-color) !important;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.CodeMirror-selectedtext {
|
|
111
|
+
color: var(--sn-stylekit-info-contrast-color) !important;
|
|
112
|
+
background: var(--sn-stylekit-info-color) !important;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.CodeMirror-gutters {
|
|
116
|
+
background-color: var(--sn-stylekit-background-color) !important;
|
|
117
|
+
color: var(--sn-stylekit-editor-foreground-color) !important;
|
|
118
|
+
border-color: var(--sn-stylekit-border-color) !important;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.cm-header-1 {
|
|
122
|
+
font-size: 150%;
|
|
123
|
+
}
|
|
124
|
+
.cm-header-2 {
|
|
125
|
+
font-size: 130%;
|
|
126
|
+
}
|
|
127
|
+
.cm-header-3 {
|
|
128
|
+
font-size: 120%;
|
|
129
|
+
}
|
|
130
|
+
.cm-header-4 {
|
|
131
|
+
font-size: 110%;
|
|
132
|
+
}
|
|
133
|
+
.cm-header-5 {
|
|
134
|
+
font-size: 100%;
|
|
135
|
+
}
|
|
136
|
+
.cm-header-6 {
|
|
137
|
+
font-size: 90%;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.CodeMirror .cm-quote {
|
|
141
|
+
color: var(--sn-stylekit-foreground-color);
|
|
142
|
+
opacity: 0.6;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {
|
|
146
|
+
color: var(--sn-stylekit-success-color) !important;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.CodeMirror .cm-link, .CodeMirror .cm-string, .CodeMirror .cm-keyword {
|
|
150
|
+
color: var(--sn-stylekit-info-color);
|
|
151
|
+
}
|