@standardnotes/classic-code-editor 1.5.5
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/.eslintrc.js +19 -0
- package/CHANGELOG.md +94 -0
- package/LICENSE +661 -0
- package/README.md +47 -0
- package/code_editor_preview.png +0 -0
- package/index.html +62 -0
- package/package.json +40 -0
- package/src/main.js +283 -0
- package/src/main.scss +105 -0
- package/webpack.config.js +61 -0
- package/webpack.dev.js +11 -0
- package/webpack.prod.js +7 -0
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Code Editor
|
|
2
|
+
|
|
3
|
+
The Code Editor is a Standard Notes derived editor that provides syntax highlighting and keyboard shortcuts for over 120 programming languages.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Quickstart
|
|
8
|
+
|
|
9
|
+
Use your browser to see the Code Editor in action.
|
|
10
|
+
|
|
11
|
+
1. Clone the [code-editor](https://github.com/standardnotes/code-editor) repository from GitHub.
|
|
12
|
+
|
|
13
|
+
2. Run `yarn` to install required dependencies.
|
|
14
|
+
|
|
15
|
+
3. Open `index.html` in your browser where the editor will be running.
|
|
16
|
+
|
|
17
|
+
## Local Installation
|
|
18
|
+
|
|
19
|
+
See the editor in the desktop app and make changes to the code.
|
|
20
|
+
|
|
21
|
+
1. Clone the [code-editor](https://github.com/standardnotes/code-editor) repository from GitHub.
|
|
22
|
+
|
|
23
|
+
2. Run `yarn` to install required dependencies.
|
|
24
|
+
|
|
25
|
+
3. Ensure that either the Standard Notes desktop app is available for use or the web app is accessible. Use both locally or with an Extended account (or the extension will not load).
|
|
26
|
+
|
|
27
|
+
4. Follow the instructions [here](https://docs.standardnotes.org/extensions/local-setup) to setup the extension locally.
|
|
28
|
+
|
|
29
|
+
5. Begin development! Upon making any changes to the code, run `yarn build` to build the files to the `dist` folder.
|
|
30
|
+
|
|
31
|
+
## Contributing
|
|
32
|
+
|
|
33
|
+
Feel free to create a pull request, we welcome your enthusiasm!
|
|
34
|
+
|
|
35
|
+
## Support
|
|
36
|
+
|
|
37
|
+
Please open a new issue and the Standard Notes team will take a look as soon as we can. For more information on editors, refer to the following link:
|
|
38
|
+
|
|
39
|
+
- Standard Notes Help: [What are editors?](https://standardnotes.org/help/77/what-are-editors)
|
|
40
|
+
|
|
41
|
+
We are also reachable on our forum, Slack, Reddit, Twitter, and through email:
|
|
42
|
+
|
|
43
|
+
- Standard Notes Help and Support: [Get Help](https://standardnotes.org/help)
|
|
44
|
+
|
|
45
|
+
## License
|
|
46
|
+
|
|
47
|
+
[GNU AGPL v3.0](https://choosealicense.com/licenses/agpl-3.0/)
|
|
Binary file
|
package/index.html
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<base target="_blank">
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
|
7
|
+
<link rel="stylesheet" href="dist/codemirror/lib/codemirror.css">
|
|
8
|
+
<link rel="stylesheet" href="dist/main.css">
|
|
9
|
+
<link rel="stylesheet" href="dist/stylekit.css">
|
|
10
|
+
<script src="dist/codemirror/lib/codemirror.js"></script>
|
|
11
|
+
<!-- Required for gfm mode -->
|
|
12
|
+
<script src="dist/codemirror/addon/mode/overlay.js"></script>
|
|
13
|
+
<script src="dist/codemirror/addon/mode/simple.js"></script>
|
|
14
|
+
<script src="dist/codemirror/addon/mode/loadmode.js"></script>
|
|
15
|
+
<script src="dist/codemirror/mode/meta.js"></script>
|
|
16
|
+
<!-- Vim key bindings -->
|
|
17
|
+
<script src="dist/codemirror/keymap/vim.js"></script>
|
|
18
|
+
<!-- Required for search -->
|
|
19
|
+
<script src="dist/codemirror/addon/search/jump-to-line.js"></script>
|
|
20
|
+
<script src="dist/codemirror/addon/search/match-highlighter.js"></script>
|
|
21
|
+
<script src="dist/codemirror/addon/search/matchesonscrollbar.js"></script>
|
|
22
|
+
<script src="dist/codemirror/addon/search/search.js"></script>
|
|
23
|
+
<script src="dist/codemirror/addon/search/searchcursor.js"></script>
|
|
24
|
+
<script src="dist/codemirror/addon/dialog/dialog.js"></script>
|
|
25
|
+
<script src="dist/codemirror/addon/scroll/annotatescrollbar.js"></script>
|
|
26
|
+
<link rel="stylesheet" href="dist/codemirror/addon/search/matchesonscrollbar.css" />
|
|
27
|
+
<link rel="stylesheet" href="dist/codemirror/addon/dialog/dialog.css" />
|
|
28
|
+
<script src="dist/lib/component-relay.js"></script>
|
|
29
|
+
<!-- Required for styling selected text -->
|
|
30
|
+
<script src="dist/codemirror/addon/selection/mark-selection.js"></script>
|
|
31
|
+
<script>
|
|
32
|
+
CodeMirror.modeURL = "dist/codemirror/mode/%N/%N.js";
|
|
33
|
+
</script>
|
|
34
|
+
</head>
|
|
35
|
+
|
|
36
|
+
<body class="sn-component">
|
|
37
|
+
<div class="wrapper">
|
|
38
|
+
<textarea id="code" name="code"></textarea>
|
|
39
|
+
<div>
|
|
40
|
+
<div class="sk-app-bar no-edges no-bottom-edge" style="width: inherit;">
|
|
41
|
+
<div class="left">
|
|
42
|
+
<div class="sk-app-bar-item no-pointer">
|
|
43
|
+
<span class="sk-p">Language:</span>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="sk-app-bar-item no-pointer">
|
|
46
|
+
<select id="language-select" onchange="onLanguageSelect(event)"></select>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="sk-app-bar-item">
|
|
49
|
+
<span id="default-label" class="sk-label" onclick="setDefaultLanguage(event)">Set as Default</span>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="center"></div>
|
|
53
|
+
<div class="right">
|
|
54
|
+
<div class="sk-app-bar-item no-pointer border"></div>
|
|
55
|
+
<div class="sk-app-bar-item">
|
|
56
|
+
<span id="toggle-vim-mode-button" class="sk-label" onclick="toggleVimMode()">Enable Vim mode</span>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
<script src="dist/main.js"></script>
|
|
61
|
+
</body>
|
|
62
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@standardnotes/classic-code-editor",
|
|
3
|
+
"version": "1.5.5",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "A code editor for Standard Notes",
|
|
8
|
+
"main": "dist/main.js",
|
|
9
|
+
"author": "Standard Notes",
|
|
10
|
+
"license": "AGPL-3.0",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "http-server . --cors -p8001 & webpack --progress --config webpack.dev.js",
|
|
13
|
+
"build": "webpack --config webpack.prod.js",
|
|
14
|
+
"skip:lint": "eslint src/ --ext .js",
|
|
15
|
+
"lint:fix": "eslint src/ --ext .js --fix",
|
|
16
|
+
"clean": "rm -rf ./vendor",
|
|
17
|
+
"test": "echo \"Error: no test specified\" && exit 0"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@standardnotes/component-relay": "standardnotes/component-relay#839ff5db9bc92db9d42cad8d202ddc4df729597d"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@babel/cli": "^7.12.10",
|
|
24
|
+
"@babel/core": "^7.12.10",
|
|
25
|
+
"@babel/preset-env": "^7.12.11",
|
|
26
|
+
"codemirror": "5.65.2",
|
|
27
|
+
"copy-webpack-plugin": "*",
|
|
28
|
+
"css-loader": "^5.0.1",
|
|
29
|
+
"eslint": "*",
|
|
30
|
+
"http-server": "^0.12.3",
|
|
31
|
+
"mini-css-extract-plugin": "^1.3.5",
|
|
32
|
+
"sass": "*",
|
|
33
|
+
"sass-loader": "^10.1.1",
|
|
34
|
+
"sn-stylekit": "^2.1.1",
|
|
35
|
+
"webpack": "*",
|
|
36
|
+
"webpack-cli": "*",
|
|
37
|
+
"webpack-merge": "^5.8.0"
|
|
38
|
+
},
|
|
39
|
+
"gitHead": "6806ecada49ab7e617d6c03787fb7b68e0e89933"
|
|
40
|
+
}
|
package/src/main.js
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
2
|
+
const modeByModeMode = CodeMirror.modeInfo.reduce(function (acc, m) {
|
|
3
|
+
if (acc[m.mode]) {
|
|
4
|
+
acc[m.mode].push(m)
|
|
5
|
+
} else {
|
|
6
|
+
acc[m.mode] = [m]
|
|
7
|
+
}
|
|
8
|
+
return acc
|
|
9
|
+
}, {})
|
|
10
|
+
|
|
11
|
+
const modeModeAndMimeByName = CodeMirror.modeInfo.reduce(function (acc, m) {
|
|
12
|
+
acc[m.name] = { mode: m.mode, mime: m.mime }
|
|
13
|
+
return acc
|
|
14
|
+
}, {})
|
|
15
|
+
|
|
16
|
+
const modes = Object.keys(modeModeAndMimeByName)
|
|
17
|
+
|
|
18
|
+
let componentRelay
|
|
19
|
+
let workingNote, clientData
|
|
20
|
+
let lastValue, lastUUID
|
|
21
|
+
let editor, select
|
|
22
|
+
let ignoreTextChange = false
|
|
23
|
+
let initialLoad = true
|
|
24
|
+
|
|
25
|
+
function loadComponentRelay() {
|
|
26
|
+
componentRelay = new ComponentRelay({
|
|
27
|
+
targetWindow: window,
|
|
28
|
+
onReady: () => {
|
|
29
|
+
const platform = componentRelay.platform
|
|
30
|
+
if (platform) {
|
|
31
|
+
document.body.classList.add(platform)
|
|
32
|
+
}
|
|
33
|
+
loadEditor()
|
|
34
|
+
},
|
|
35
|
+
handleRequestForContentHeight: () => {
|
|
36
|
+
const baseHeight = 50
|
|
37
|
+
const scrollHeight = document.getElementsByClassName('CodeMirror-code')[0]?.scrollHeight
|
|
38
|
+
return baseHeight + scrollHeight
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
componentRelay.streamContextItem((note) => {
|
|
43
|
+
onReceivedNote(note)
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function saveNote() {
|
|
48
|
+
if (workingNote) {
|
|
49
|
+
// Be sure to capture this object as a variable, as this.note may be reassigned in `streamContextItem`, so by the time
|
|
50
|
+
// you modify it in the presave block, it may not be the same object anymore, so the presave values will not be applied to
|
|
51
|
+
// the right object, and it will save incorrectly.
|
|
52
|
+
let note = workingNote
|
|
53
|
+
|
|
54
|
+
componentRelay.saveItemWithPresave(note, () => {
|
|
55
|
+
lastValue = editor.getValue()
|
|
56
|
+
note.content.text = lastValue
|
|
57
|
+
note.clientData = clientData
|
|
58
|
+
|
|
59
|
+
note.content.preview_plain = null
|
|
60
|
+
note.content.preview_html = null
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function onReceivedNote(note) {
|
|
66
|
+
if (note.uuid !== lastUUID) {
|
|
67
|
+
// Note changed, reset last values
|
|
68
|
+
lastValue = null
|
|
69
|
+
initialLoad = true
|
|
70
|
+
lastUUID = note.uuid
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
workingNote = note
|
|
74
|
+
// Only update UI on non-metadata updates.
|
|
75
|
+
if (note.isMetadataUpdate) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
clientData = note.clientData
|
|
80
|
+
let mode = clientData.mode
|
|
81
|
+
|
|
82
|
+
if (!mode) {
|
|
83
|
+
// Assign editor's default mode from component settings
|
|
84
|
+
mode = componentRelay.getComponentDataValueForKey('language') ?? 'JavaScript'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
changeMode(mode)
|
|
88
|
+
|
|
89
|
+
if (editor) {
|
|
90
|
+
if (note.content.text !== lastValue) {
|
|
91
|
+
ignoreTextChange = true
|
|
92
|
+
editor.getDoc().setValue(workingNote.content.text)
|
|
93
|
+
ignoreTextChange = false
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (initialLoad) {
|
|
97
|
+
initialLoad = false
|
|
98
|
+
editor.getDoc().clearHistory()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
editor.setOption('spellcheck', workingNote.content.spellcheck)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function loadEditor() {
|
|
106
|
+
// Handler for the save command that is mapped to the :w (write) Vim key binding.
|
|
107
|
+
CodeMirror.commands.save = function () {
|
|
108
|
+
saveNote()
|
|
109
|
+
}
|
|
110
|
+
editor = CodeMirror.fromTextArea(document.getElementById('code'), {
|
|
111
|
+
extraKeys: {
|
|
112
|
+
'Alt-F': 'findPersistent',
|
|
113
|
+
},
|
|
114
|
+
lineNumbers: true,
|
|
115
|
+
styleSelectedText: true,
|
|
116
|
+
lineWrapping: true,
|
|
117
|
+
inputStyle: getInputStyleForEnvironment(),
|
|
118
|
+
})
|
|
119
|
+
editor.setSize('100%', '100%')
|
|
120
|
+
|
|
121
|
+
createSelectElements()
|
|
122
|
+
|
|
123
|
+
editor.on('change', function () {
|
|
124
|
+
if (ignoreTextChange) {
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
saveNote()
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Scrolls the cursor into view, so the soft keyboard on mobile devices
|
|
132
|
+
* doesn't overlap the cursor. A short delay is added to prevent scrolling
|
|
133
|
+
* before the keyboard is shown.
|
|
134
|
+
*/
|
|
135
|
+
const scrollCursorIntoView = (editor) => {
|
|
136
|
+
setTimeout(() => editor.scrollIntoView(), 200)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
editor.on('cursorActivity', function (editor) {
|
|
140
|
+
if (componentRelay.environment !== 'mobile') {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
scrollCursorIntoView(editor)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
const initialKeyMap = componentRelay.getComponentDataValueForKey('keyMap') ?? 'default'
|
|
147
|
+
window.setKeyMap(initialKeyMap)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function createSelectElements() {
|
|
151
|
+
select = document.getElementById('language-select')
|
|
152
|
+
for (let index = 0; index < modes.length; index++) {
|
|
153
|
+
const option = document.createElement('option')
|
|
154
|
+
option.value = index
|
|
155
|
+
option.innerHTML = modes[index]
|
|
156
|
+
select.appendChild(option)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Editor Modes
|
|
161
|
+
window.setKeyMap = function (keymap) {
|
|
162
|
+
editor.setOption('keyMap', keymap)
|
|
163
|
+
updateVimStatus(keymap)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
window.onLanguageSelect = function () {
|
|
167
|
+
const language = modes[select.selectedIndex]
|
|
168
|
+
changeMode(language)
|
|
169
|
+
saveNote()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
window.setDefaultLanguage = function () {
|
|
173
|
+
const language = modes[select.selectedIndex]
|
|
174
|
+
|
|
175
|
+
// assign default language for this editor when entering notes
|
|
176
|
+
componentRelay.setComponentDataValueForKey('language', language)
|
|
177
|
+
|
|
178
|
+
// show a confirmation message
|
|
179
|
+
const message = document.getElementById('default-label')
|
|
180
|
+
const original = message.innerHTML
|
|
181
|
+
message.innerHTML = 'Success'
|
|
182
|
+
message.classList.add('success')
|
|
183
|
+
|
|
184
|
+
setTimeout(function () {
|
|
185
|
+
message.classList.remove('success')
|
|
186
|
+
message.innerHTML = original
|
|
187
|
+
}, 750)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function inputModeToMode(inputMode) {
|
|
191
|
+
const convertCodeMirrorMode = function (codeMirrorMode) {
|
|
192
|
+
if (codeMirrorMode) {
|
|
193
|
+
return {
|
|
194
|
+
name: codeMirrorMode.name,
|
|
195
|
+
mode: codeMirrorMode.mode,
|
|
196
|
+
mime: codeMirrorMode.mime,
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
return null
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const extension = /.+\.([^.]+)$/.exec(inputMode)
|
|
204
|
+
const mime = /\//.test(inputMode)
|
|
205
|
+
|
|
206
|
+
if (extension) {
|
|
207
|
+
return convertCodeMirrorMode(CodeMirror.findModeByExtension(extension[1]))
|
|
208
|
+
} else if (mime) {
|
|
209
|
+
return convertCodeMirrorMode(CodeMirror.findModeByMIME(mime[1]))
|
|
210
|
+
} else if (modeModeAndMimeByName[inputMode]) {
|
|
211
|
+
return {
|
|
212
|
+
name: inputMode,
|
|
213
|
+
mode: modeModeAndMimeByName[inputMode].mode,
|
|
214
|
+
mime: modeModeAndMimeByName[inputMode].mime,
|
|
215
|
+
}
|
|
216
|
+
} else if (modeByModeMode[inputMode]) {
|
|
217
|
+
const firstMode = modeByModeMode[inputMode][0]
|
|
218
|
+
return {
|
|
219
|
+
name: firstMode.name,
|
|
220
|
+
mode: firstMode.mode,
|
|
221
|
+
mime: firstMode.mime,
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
return {
|
|
225
|
+
name: inputMode,
|
|
226
|
+
mode: inputMode,
|
|
227
|
+
mime: inputMode,
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function changeMode(inputMode) {
|
|
233
|
+
if (!inputMode) {
|
|
234
|
+
return
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const mode = inputModeToMode(inputMode)
|
|
238
|
+
|
|
239
|
+
if (mode) {
|
|
240
|
+
editor.setOption('mode', mode.mime)
|
|
241
|
+
CodeMirror.autoLoadMode(editor, mode.mode)
|
|
242
|
+
if (clientData) {
|
|
243
|
+
clientData.mode = mode.name
|
|
244
|
+
}
|
|
245
|
+
document.getElementById('language-select').selectedIndex = modes.indexOf(mode.name)
|
|
246
|
+
} else {
|
|
247
|
+
console.error('Could not find a mode corresponding to ' + inputMode)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function updateVimStatus(keyMap) {
|
|
252
|
+
const toggleButton = document.getElementById('toggle-vim-mode-button')
|
|
253
|
+
|
|
254
|
+
const newAction = keyMap === 'vim' ? 'Disable' : 'Enable'
|
|
255
|
+
const buttonClass = keyMap === 'vim' ? 'danger' : 'success'
|
|
256
|
+
|
|
257
|
+
toggleButton.innerHTML = `${newAction} Vim mode`
|
|
258
|
+
toggleButton.classList.remove('danger')
|
|
259
|
+
toggleButton.classList.remove('success')
|
|
260
|
+
toggleButton.classList.add(buttonClass)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
window.toggleVimMode = function () {
|
|
264
|
+
let newKeyMap
|
|
265
|
+
|
|
266
|
+
const currentKeyMap = componentRelay.getComponentDataValueForKey('keyMap') ?? 'default'
|
|
267
|
+
if (currentKeyMap === 'default') {
|
|
268
|
+
newKeyMap = 'vim'
|
|
269
|
+
} else {
|
|
270
|
+
newKeyMap = 'default'
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
window.setKeyMap(newKeyMap)
|
|
274
|
+
componentRelay.setComponentDataValueForKey('keyMap', newKeyMap)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function getInputStyleForEnvironment() {
|
|
278
|
+
const environment = componentRelay.environment ?? 'web'
|
|
279
|
+
return environment === 'mobile' ? 'textarea' : 'contenteditable'
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
loadComponentRelay()
|
|
283
|
+
})
|
package/src/main.scss
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
body, html {
|
|
2
|
+
font-family: sans-serif;
|
|
3
|
+
height: 100%;
|
|
4
|
+
margin: 0;
|
|
5
|
+
font-size: var(--sn-stylekit-base-font-size);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.wrapper {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
position: relative;
|
|
12
|
+
height: 100%;
|
|
13
|
+
|
|
14
|
+
// Fixes unnecessary horizontal scrolling on Windows
|
|
15
|
+
overflow-x: hidden;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.CodeMirror {
|
|
19
|
+
background-color: var(--sn-stylekit-editor-background-color) !important;
|
|
20
|
+
color: var(--sn-stylekit-editor-foreground-color) !important;
|
|
21
|
+
border: 0 !important;
|
|
22
|
+
font-family: var(--sn-stylekit-monospace-font);
|
|
23
|
+
-webkit-overflow-scrolling: touch;
|
|
24
|
+
|
|
25
|
+
// code doesn't look good at normal text size, better to be a bit smaller
|
|
26
|
+
font-size: calc(var(--sn-stylekit-font-size-editor) - 0.1rem);
|
|
27
|
+
|
|
28
|
+
flex: 1 1 auto;
|
|
29
|
+
width: 100%;
|
|
30
|
+
height: 100%;
|
|
31
|
+
resize: none;
|
|
32
|
+
|
|
33
|
+
.cm-header {
|
|
34
|
+
color: var(--sn-stylekit-editor-foreground-color);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Faded Markdown syntax
|
|
38
|
+
.cm-formatting-header, .cm-formatting-strong, .cm-formatting-em {
|
|
39
|
+
opacity: 0.2;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.cm-variable, .cm-variable-1, .cm-variable-2, .cm-variable-3, .cm-string-2 {
|
|
43
|
+
color: var(--sn-stylekit-info-color) !important;
|
|
44
|
+
|
|
45
|
+
&.CodeMirror-selectedtext {
|
|
46
|
+
color: var(--sn-stylekit-info-contrast-color) !important;
|
|
47
|
+
background: transparent;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.cm-qualifier, .cm-meta {
|
|
52
|
+
color: var(--sn-stylekit-neutral-color) !important;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.cm-error {
|
|
56
|
+
color: var(--sn-stylekit-danger-color) !important;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.cm-property {
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.cm-def, .cm-atom {
|
|
64
|
+
color: var(--sn-stylekit-success-color);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.CodeMirror-linenumber {
|
|
68
|
+
color: var(--sn-stylekit-neutral-color) !important;
|
|
69
|
+
opacity: 0.5;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.CodeMirror-cursor {
|
|
74
|
+
border-color: var(--sn-stylekit-info-color) !important;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.CodeMirror-cursors {
|
|
78
|
+
z-index: 10 !important; // In Markdown mode, cursor is hidden behind code blocks
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.CodeMirror-selected {
|
|
82
|
+
background: var(--sn-stylekit-info-color) !important;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.CodeMirror-gutters {
|
|
86
|
+
background-color: var(--sn-stylekit-background-color) !important;
|
|
87
|
+
color: var(--sn-stylekit-editor-foreground-color) !important;
|
|
88
|
+
border-color: var(--sn-stylekit-border-color) !important;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.cm-header-1 { font-size: 150%; }
|
|
92
|
+
.cm-header-2 { font-size: 130%; }
|
|
93
|
+
.cm-header-3 { font-size: 120%; }
|
|
94
|
+
.cm-header-4 { font-size: 110%; }
|
|
95
|
+
.cm-header-5 { font-size: 100%; }
|
|
96
|
+
.cm-header-6 { font-size: 90%; }
|
|
97
|
+
|
|
98
|
+
.CodeMirror .cm-quote {
|
|
99
|
+
color: var(--sn-stylekit-foreground-color);
|
|
100
|
+
opacity: 0.6;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.cm-fat-cursor .CodeMirror-line > span[role="presentation"] {
|
|
104
|
+
caret-color: transparent;
|
|
105
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const CopyPlugin = require('copy-webpack-plugin')
|
|
3
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
entry: [path.resolve(__dirname, 'src', 'main.js'), path.resolve(__dirname, 'src', 'main.scss')],
|
|
7
|
+
output: {
|
|
8
|
+
path: path.join(__dirname, 'dist'),
|
|
9
|
+
filename: '[name].js',
|
|
10
|
+
},
|
|
11
|
+
module: {
|
|
12
|
+
rules: [
|
|
13
|
+
{
|
|
14
|
+
test: /\.s[ac]ss$/i,
|
|
15
|
+
use: [
|
|
16
|
+
MiniCssExtractPlugin.loader,
|
|
17
|
+
'css-loader',
|
|
18
|
+
{
|
|
19
|
+
loader: 'sass-loader',
|
|
20
|
+
options: {
|
|
21
|
+
sassOptions: {
|
|
22
|
+
includePaths: ['src/main.scss'],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
plugins: [
|
|
31
|
+
new CopyPlugin({
|
|
32
|
+
patterns: [
|
|
33
|
+
{
|
|
34
|
+
from: path.resolve(__dirname, 'node_modules/codemirror/lib'),
|
|
35
|
+
to: path.resolve(__dirname, 'dist/codemirror/lib'),
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
from: path.resolve(__dirname, 'node_modules/codemirror/mode'),
|
|
39
|
+
to: path.resolve(__dirname, 'dist/codemirror/mode'),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
from: path.resolve(__dirname, 'node_modules/codemirror/addon'),
|
|
43
|
+
to: path.resolve(__dirname, 'dist/codemirror/addon'),
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
from: path.resolve(__dirname, 'node_modules/codemirror/keymap/vim.js'),
|
|
47
|
+
to: path.resolve(__dirname, 'dist/codemirror/keymap'),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
from: require.resolve('@standardnotes/component-relay/dist/dist.js'),
|
|
51
|
+
to: path.resolve(__dirname, 'dist/lib/component-relay.js'),
|
|
52
|
+
},
|
|
53
|
+
{ from: require.resolve('sn-stylekit/dist/stylekit.css'), to: path.resolve(__dirname, 'dist/stylekit.css') },
|
|
54
|
+
],
|
|
55
|
+
}),
|
|
56
|
+
new MiniCssExtractPlugin({
|
|
57
|
+
filename: '[name].css',
|
|
58
|
+
chunkFilename: '[id].css',
|
|
59
|
+
}),
|
|
60
|
+
],
|
|
61
|
+
}
|
package/webpack.dev.js
ADDED