mirror of
https://github.com/heyman/heynote.git
synced 2025-02-16 10:19:55 +01:00
Integrate Editor into Vue app
Add status bar that shows the current line number, column and block language
This commit is contained in:
parent
51e89ad55c
commit
6dee4f81f2
@ -14,11 +14,11 @@
|
||||
<!--<div id="app"></div>-->
|
||||
<!--<script type="module" src="/src/main.ts"></script>-->
|
||||
|
||||
<!--<div id="app"></div>
|
||||
<script type="module" src="src/main.js"></script>-->
|
||||
<div id="app"></div>
|
||||
<script type="module" src="src/main.js"></script>
|
||||
|
||||
<div id="editor" class="editor"></div>
|
||||
<script type="module" src="src/editor/index.js"></script>
|
||||
<!--<div id="editor" class="editor"></div>
|
||||
<script type="module" src="src/editor/index.js"></script>-->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
184
package-lock.json
generated
184
package-lock.json
generated
@ -28,6 +28,7 @@
|
||||
"codemirror": "^6.0.1",
|
||||
"electron": "^22.0.0",
|
||||
"electron-builder": "^23.6.0",
|
||||
"sass": "^1.57.1",
|
||||
"typescript": "^4.9.4",
|
||||
"vite": "^4.0.3",
|
||||
"vite-plugin-electron": "^0.11.1",
|
||||
@ -1436,6 +1437,19 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-bin": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz",
|
||||
@ -1633,6 +1647,15 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
@ -1665,6 +1688,18 @@
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
@ -1864,6 +1899,33 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
@ -2662,6 +2724,18 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
@ -2799,6 +2873,18 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/global-agent": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
|
||||
@ -3050,6 +3136,12 @@
|
||||
],
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz",
|
||||
"integrity": "sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
@ -3066,6 +3158,18 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-builtin-module": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz",
|
||||
@ -3105,6 +3209,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
@ -3114,12 +3227,33 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isbinaryfile": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz",
|
||||
@ -3421,6 +3555,15 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-url": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
|
||||
@ -3602,6 +3745,18 @@
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
@ -3710,6 +3865,23 @@
|
||||
"truncate-utf8-bytes": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.57.1",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz",
|
||||
"integrity": "sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
"immutable": "^4.0.0",
|
||||
"source-map-js": ">=0.6.2 <2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"sass": "sass.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
@ -4018,6 +4190,18 @@
|
||||
"tmp": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/truncate-utf8-bytes": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
|
||||
|
@ -46,6 +46,7 @@
|
||||
"codemirror": "^6.0.1",
|
||||
"electron": "^22.0.0",
|
||||
"electron-builder": "^23.6.0",
|
||||
"sass": "^1.57.1",
|
||||
"typescript": "^4.9.4",
|
||||
"vite": "^4.0.3",
|
||||
"vite-plugin-electron": "^0.11.1",
|
||||
|
95
src/App.vue
95
src/App.vue
@ -1,51 +1,58 @@
|
||||
<script setup lang="ts">
|
||||
import HelloWorld from './components/HelloWorld.vue'
|
||||
<script>
|
||||
import HelloWorld from './components/HelloWorld.vue'
|
||||
import StatusBar from './components/StatusBar.vue'
|
||||
import Editor from './components/Editor.vue'
|
||||
|
||||
console.log("[App.vue]", `Hello world from Electron ${process.versions.electron}!`)
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HelloWorld,
|
||||
Editor,
|
||||
StatusBar,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
line: 1,
|
||||
column: 1,
|
||||
language: "plaintext",
|
||||
languageAuto: true,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onCursorChange(e) {
|
||||
//console.log("onCursorChange:", e)
|
||||
this.line = e.cursorLine.line
|
||||
this.column = e.cursorLine.col
|
||||
this.language = e.language
|
||||
this.languageAuto = e.languageAuto
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
console.log("[App.vue]", `Hello world from Electron ${process.versions.electron}!`)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<a href="https://www.electronjs.org/" target="_blank">
|
||||
<img src="./assets/electron.svg" class="logo electron" alt="Electron logo" />
|
||||
</a>
|
||||
<a href="https://vitejs.dev/" target="_blank">
|
||||
<img src="/vite.svg" class="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://vuejs.org/" target="_blank">
|
||||
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
|
||||
</a>
|
||||
</div>
|
||||
<HelloWorld msg="Electron + Vite + Vue" />
|
||||
<div class="flex-center">
|
||||
Place static files into the <code>/public</code> folder
|
||||
<img style="width:5em;" src="/node.svg" alt="Node logo">
|
||||
</div>
|
||||
<Editor
|
||||
@cursorChange="onCursorChange"
|
||||
class="editor"
|
||||
/>
|
||||
<StatusBar
|
||||
:line="line"
|
||||
:column="column"
|
||||
:language="language"
|
||||
:languageAuto="languageAuto"
|
||||
class="status"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.flex-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: filter 300ms;
|
||||
}
|
||||
|
||||
.logo.electron:hover {
|
||||
filter: drop-shadow(0 0 2em #9FEAF9);
|
||||
}
|
||||
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
|
||||
.logo.vue:hover {
|
||||
filter: drop-shadow(0 0 2em #42b883aa);
|
||||
}
|
||||
<style scoped lang="sass">
|
||||
.editor
|
||||
height: calc(100% - 21px)
|
||||
.status
|
||||
position: absolute
|
||||
bottom: 0
|
||||
left: 0
|
||||
</style>
|
||||
|
35
src/components/Editor.vue
Normal file
35
src/components/Editor.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<script>
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import { HeynoteEditor } from '../editor/editor.js'
|
||||
import initialData from "../editor/fixture.js"
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
this.$refs.editor.addEventListener("selectionChange", (e) => {
|
||||
//console.log("selectionChange:", e)
|
||||
this.$emit("cursorChange", {
|
||||
cursorLine: e.cursorLine,
|
||||
language: e.language,
|
||||
languageAuto: e.languageAuto,
|
||||
})
|
||||
})
|
||||
|
||||
const editor = new HeynoteEditor({
|
||||
element: this.$refs.editor,
|
||||
//content: "\n∞∞∞text\n",
|
||||
content: initialData,
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="editor" ref="editor"></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.editor {
|
||||
width: 100%;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
</style>
|
77
src/components/StatusBar.vue
Normal file
77
src/components/StatusBar.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<script>
|
||||
const LANGUAGE_NAMES = {
|
||||
"text": "Plain Text",
|
||||
"javascript": "JavaScript",
|
||||
"json": "JSON",
|
||||
"python": "Python",
|
||||
"html": "HTML",
|
||||
"sql": "SQL",
|
||||
"markdown": "Markdown",
|
||||
"java": "Java",
|
||||
"lezer": "Lezer",
|
||||
"php": "PHP",
|
||||
}
|
||||
|
||||
export default {
|
||||
props: [
|
||||
"line",
|
||||
"column",
|
||||
"language",
|
||||
"languageAuto",
|
||||
],
|
||||
|
||||
mounted() {
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
languageName() {
|
||||
return LANGUAGE_NAMES[this.language] || this.language
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="status">
|
||||
<div class="status-block line-number">
|
||||
Ln <span class="num">{{ line }}</span>
|
||||
Col <span class="num">{{ column }}</span>
|
||||
</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="status-block lang">
|
||||
{{ languageName }}
|
||||
<span v-if="languageAuto" class="auto">(auto)</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="sass">
|
||||
.status
|
||||
box-sizing: border-box
|
||||
height: 22px
|
||||
width: 100%
|
||||
background-color: #48b57e
|
||||
color: #fff
|
||||
font-family: "Open Sans"
|
||||
font-size: 12px
|
||||
padding-left: 7px
|
||||
padding-right: 7px
|
||||
display: flex
|
||||
flex-direction: row
|
||||
|
||||
.spacer
|
||||
flex-grow: 1
|
||||
|
||||
.status-block
|
||||
padding: 2px 5px
|
||||
cursor: default
|
||||
&.line-number
|
||||
color: rgba(255, 255, 255, 0.7)
|
||||
.num
|
||||
color: rgba(255, 255, 255, 1.0)
|
||||
&.lang
|
||||
.auto
|
||||
color: rgba(255, 255, 255, 0.7)
|
||||
|
||||
</style>
|
@ -6,6 +6,7 @@ import { syntaxTree, ensureSyntaxTree } from "@codemirror/language"
|
||||
import { Note, Document, NoteDelimiter } from "../lang-heynote/parser.terms.js"
|
||||
import { IterMode } from "@lezer/common";
|
||||
import { heynoteEvent, LANGUAGE_CHANGE } from "../annotation.js";
|
||||
import { SelectionChangeEvent } from "../event.js"
|
||||
|
||||
|
||||
// tracks the size of the first delimiter
|
||||
@ -246,22 +247,49 @@ const preventSelectionBeforeFirstBlock = EditorState.transactionFilter.of((tr) =
|
||||
return tr
|
||||
})
|
||||
|
||||
export function getBlockLineFromPos(state, pos) {
|
||||
const line = state.doc.lineAt(pos)
|
||||
const block = state.facet(blockState).find(block => block.content.from <= line.from && block.content.to >= line.from)
|
||||
if (block) {
|
||||
const firstBlockLine = state.doc.lineAt(block.content.from).number
|
||||
return {
|
||||
line: line.number - firstBlockLine + 1,
|
||||
col: pos - line.from + 1,
|
||||
length: line.length,
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const blockLineNumbers = lineNumbers({
|
||||
formatNumber(lineNo, state) {
|
||||
if (state.doc.lines >= lineNo) {
|
||||
const lineOffset = state.doc.line(lineNo).from
|
||||
const block = state.facet(blockState).find(block => block.content.from <= lineOffset && block.content.to >= lineOffset)
|
||||
if (block) {
|
||||
const firstBlockLine = state.doc.lineAt(block.content.from).number
|
||||
return lineNo - firstBlockLine + 1
|
||||
const lineInfo = getBlockLineFromPos(state, state.doc.line(lineNo).from)
|
||||
if (lineInfo !== null) {
|
||||
return lineInfo.line
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
})
|
||||
|
||||
export const noteBlockExtension = () => {
|
||||
const emitCursorChange = (element) => ViewPlugin.fromClass(
|
||||
class {
|
||||
update(update) {
|
||||
if (update.selectionSet) {
|
||||
const cursorLine = getBlockLineFromPos(update.state, update.state.selection.main.head)
|
||||
const block = getActiveNoteBlock(update.state)
|
||||
element.dispatchEvent(new SelectionChangeEvent({
|
||||
cursorLine,
|
||||
language: block?.language.name,
|
||||
languageAuto: block?.language.auto,
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export const noteBlockExtension = (element) => {
|
||||
return [
|
||||
blockState,
|
||||
noteBlockWidget(),
|
||||
@ -270,5 +298,6 @@ export const noteBlockExtension = () => {
|
||||
preventFirstBlockFromBeingDeleted,
|
||||
preventSelectionBeforeFirstBlock,
|
||||
blockLineNumbers,
|
||||
emitCursorChange(element),
|
||||
]
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Annotation, EditorState, Compartment } from "@codemirror/state"
|
||||
import { EditorView, keymap, drawSelection } from "@codemirror/view"
|
||||
import { EditorView, keymap, drawSelection, ViewPlugin } from "@codemirror/view"
|
||||
import { indentUnit, forceParsing } from "@codemirror/language"
|
||||
|
||||
import { heynoteLight } from "./theme/light.js"
|
||||
@ -12,10 +12,6 @@ import { heynoteKeymap } from "./keymap.js"
|
||||
import { languageDetection } from "./language-detection/autodetect.js"
|
||||
|
||||
|
||||
// hide loading screen
|
||||
postMessage({ payload: 'removeLoading' }, '*')
|
||||
|
||||
|
||||
export class HeynoteEditor {
|
||||
constructor({element, content, focus=true}) {
|
||||
this.state = EditorState.create({
|
||||
@ -35,7 +31,7 @@ export class HeynoteEditor {
|
||||
return {top: 80, bottom: 80}
|
||||
}),
|
||||
heynoteLang(),
|
||||
noteBlockExtension(),
|
||||
noteBlockExtension(element),
|
||||
languageDetection(() => this.view),
|
||||
|
||||
// set cursor blink rate to 1 second
|
||||
|
8
src/editor/event.js
Normal file
8
src/editor/event.js
Normal file
@ -0,0 +1,8 @@
|
||||
export class SelectionChangeEvent extends Event {
|
||||
constructor({cursorLine, language, languageAuto}) {
|
||||
super("selectionChange")
|
||||
this.cursorLine = cursorLine
|
||||
this.language = language
|
||||
this.languageAuto = languageAuto
|
||||
}
|
||||
}
|
@ -10,13 +10,19 @@ body {
|
||||
overscroll-behavior-y: none;
|
||||
}
|
||||
|
||||
#editor {
|
||||
#app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.editor {
|
||||
height: 100%;
|
||||
}
|
||||
#editor .cm-editor {
|
||||
.editor .cm-editor {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
#syntaxTree {
|
||||
height: 20%;
|
||||
overflow-y: auto;
|
||||
|
@ -2,6 +2,9 @@ import { EditorView } from '@codemirror/view';
|
||||
|
||||
|
||||
export const heynoteBase = EditorView.theme({
|
||||
"&.cm-editor.cm-focused": {
|
||||
outline: "none",
|
||||
},
|
||||
".cm-content": {
|
||||
paddingTop: 4,
|
||||
},
|
||||
|
@ -2,8 +2,7 @@ import { EditorView } from "@codemirror/view";
|
||||
|
||||
export const heynoteLight = EditorView.theme({
|
||||
"&": {
|
||||
//color: base04,
|
||||
backgroundColor: "#dfdfdf",
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
".cm-cursor, .cm-dropCursor": {
|
||||
borderLeftColor: "#000",
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { createApp } from 'vue'
|
||||
import "./style.css"
|
||||
import App from './App.vue'
|
||||
import './samples/node-api'
|
||||
|
||||
createApp(App)
|
||||
.mount('#app')
|
||||
.$nextTick(() => {
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.mount('#app').$nextTick(() => {
|
||||
// hide loading screen
|
||||
postMessage({ payload: 'removeLoading' }, '*')
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user