diff --git a/.gitignore b/.gitignore index 6df2256..af1005b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ node_modules/ /bin /dist /build +/src/lib yarn-error.log neutralinojs.log \ No newline at end of file diff --git a/build.js b/build.js index 1b9021e..8a02340 100644 --- a/build.js +++ b/build.js @@ -6,13 +6,20 @@ import { copyFile } from 'fs/promises' let [ platform, environment = 'dev' ] = process.argv.slice(2) let projectRoot = Path.dirname(new URL(import.meta.url).pathname) -const indexTemplate = scripts => `\ +const indexTemplate = scriptSources => { + let scripts = scriptSources.map(src => "") + + // if(platform == 'neutralino') + // scripts.unshift('') + + return `\
-${scripts.map(src => "").join('\n')} +${scripts.join('\n')} + + + + + diff --git a/src/qwe.js b/src/qwe.js new file mode 100644 index 0000000..1a26fa3 --- /dev/null +++ b/src/qwe.js @@ -0,0 +1,218 @@ +import Platform from './lib/platform.js' +import config from './config.js' +import cm from './lib/codemirror.js' +window.cm = cm + +function Editor() { + this.open = async () => { + if(config.statusBarAtTop) + document.body.appendChild(statusbar.element) + + console.log(cm, cm.EditorView) + + this.view = new cm.EditorView({ + state: await openToDocument() + .catch(console.error), + parent: document.body + }) + + if(!config.statusBarAtTop) + document.body.appendChild(statusbar.element) + + this.doc.setView(this.view) + this.view.focus() + } + + // this.updateFilename = () => { + // this.doc.path = Platform.dirname(this.doc.path) + '/' + statusbar.filename.value + // } + + const openToDocument = async () => { + let doc = new Doc(config.landingDocument.render(), config.landingDocument.name) + + this.doc = doc + statusbar.filename.value = config.landingDocument.name + return await doc.createState() + .catch(err => console.error("Could not open landing document", err)) + } + + this.doc = null +} + +function Statusbar() { + this.selectFilename = () => { + lastFilename = this.filename.value + + this.filename.value = editor.doc.getPath() + this.filename.select() + this.filename.selectionStart = editor.doc.getPath().lastIndexOf('/') + 1 + } + + this.element = document.createElement('nav') + this.filename = document.createElement('input') + let lastFilename = '' + + this.element.appendChild(this.filename) + + this.filename.addEventListener('click', this.selectFilename) + + this.filename.addEventListener('keydown', (event) => { + switch(event.key) { + case 'Enter': + case 'Escape': + event.preventDefault() + editor.view.focus() + break + } + }) + + this.filename.addEventListener('focusout', event => { + if(this.filename.value == '') { + this.filename.value = lastFilename + } else { + let path = this.filename.value + + editor.doc.setPath(path) + this.filename.value = Platform.filename(path) + } + }) +} + +function Doc(content, initialPath = '') { + // if(path) { + // let workspaces = Platform.storage.get('workspaces') + // } + + this.createState = async () => { + let extensions = [ + Doc.zen.of([ + cm.lineNumbers(), + cm.highlightActiveLine(), + cm.highlightActiveLineGutter(), + cm.highlightSpecialChars(), + ]), + cm.foldGutter(), + cm.drawSelection(), + cm.dropCursor(), + cm.EditorState.allowMultipleSelections.of(true), + cm.indentOnInput(), + cm.syntaxHighlighting(cm.defaultHighlightStyle, { fallback: true }), + cm.bracketMatching(), + cm.closeBrackets(), + cm.autocompletion(), + cm.rectangularSelection(), + cm.crosshairCursor(), + cm.highlightSelectionMatches(), + Keymaps.default + ] + + if(this.language) + extensions.push( + await langManager.resolveExtension(this.language) + .then(extension => Doc.language.of(extension)) + ) + + return cm.EditorState.create({ + extensions, + doc: content + }) + } + + this.setPath = newPath => { + path = newPath + this.setLanguage() + } + + this.getPath = () => + path + + this.setView = (newView) => { + view = newView + this.setLanguage() + } + + this.setLanguage = (newLanguage = getLanguage()) => { + let oldLanguage = this.language + this.language = newLanguage + + if(!view) + return + + if(this.language == null) { + setViewLanguageExtension([]) + } else if(oldLanguage == null || oldLanguage.name !== this.language.name) { + langManager.resolveExtension(this.language) + .then(setViewLanguageExtension) + .catch(err => console.error('Failed to set language extension', err)) + } + } + + const getLanguage = () => { + let ext = Platform.ext(path) + + if(ext) { + return langManager.exts[ext] + } + } + + const setViewLanguageExtension = (extension) => { + view.dispatch({ + effects: Doc.language.reconfigure(extension) + }) + } + + let path = initialPath + let view = null + this.language = getLanguage() +} + +Doc.open = async path => { + return new Doc() +} + +Doc.tabSize = new cm.Compartment +Doc.zen = new cm.Compartment +Doc.language = new cm.Compartment + +const Keymaps = { + default: cm.keymap.of([ + ...cm.closeBracketsKeymap, + ...cm.defaultKeymap, + ...cm.searchKeymap, + ...cm.foldKeymap, + ...cm.completionKeymap, + ...cm.lintKeymap, + cm.indentWithTab, + { + key: 'Ctrl-r', + run({ state }, event) { + event.preventDefault() + let mainSelection = state.selection.main + + if(!mainSelection.empty) + statusbar.filename.value = state.sliceDoc(mainSelection.from, mainSelection.to) + statusbar.selectFilename() + } + } + ]) +} + +function LanguageManager() { + this.resolveExtension = (language) => + import(language.import) + .then(mod => language.createExtension(mod.default)) + + this.exts = {} + + for(let language of config.languages) { + for(let ext of language.exts) + this.exts[ext] = language + } +} + +window.addEventListener('load', () => { + window.statusbar = new Statusbar() + window.editor = new Editor() + window.langManager = new LanguageManager() + editor.open() +}) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index ed7967d..72afd7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@codemirror/autocomplete@^6.0.0": +"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.7.1": version "6.11.1" resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.11.1.tgz#c733900eee58ac2de817317b9fd1e91b857c4329" integrity sha512-L5UInv8Ffd6BPw0P3EF7JLYAMeEbclY7+6Q11REt8vhih8RuLreKtPy/xk8wPxs4EQgYqzI7cdgpiYwWlbS/ow== @@ -22,7 +22,59 @@ "@codemirror/view" "^6.0.0" "@lezer/common" "^1.1.0" -"@codemirror/language@^6.0.0": +"@codemirror/lang-css@^6.0.0": + version "6.2.1" + resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-6.2.1.tgz#5dc0a43b8e3c31f6af7aabd55ff07fe9aef2a227" + integrity sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@lezer/common" "^1.0.2" + "@lezer/css" "^1.0.0" + +"@codemirror/lang-html@^6.0.0": + version "6.4.7" + resolved "https://registry.yarnpkg.com/@codemirror/lang-html/-/lang-html-6.4.7.tgz#e375e3c9ae898b5aca6e17b5055a3a76c7a8f5ff" + integrity sha512-y9hWSSO41XlcL4uYwWyk0lEgTHcelWWfRuqmvcAmxfCs0HNWZdriWo/EU43S63SxEZpc1Hd50Itw7ktfQvfkUg== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/lang-css" "^6.0.0" + "@codemirror/lang-javascript" "^6.0.0" + "@codemirror/language" "^6.4.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + "@lezer/css" "^1.1.0" + "@lezer/html" "^1.3.0" + +"@codemirror/lang-javascript@^6.0.0", "@codemirror/lang-javascript@^6.2.1": + version "6.2.1" + resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.2.1.tgz#8068d44365d13cdb044936fb4e3483301c12ef95" + integrity sha512-jlFOXTejVyiQCW3EQwvKH0m99bUYIw40oPmFjSX2VS78yzfe0HELZ+NEo9Yfo1MkGRpGlj3Gnu4rdxV1EnAs5A== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/language" "^6.6.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + "@lezer/javascript" "^1.0.0" + +"@codemirror/lang-markdown@^6.2.3": + version "6.2.3" + resolved "https://registry.yarnpkg.com/@codemirror/lang-markdown/-/lang-markdown-6.2.3.tgz#ce572230a872e8eef88bce40213f26e66a7e4497" + integrity sha512-wCewRLWpdefWi7uVkHIDiE8+45Fe4buvMDZkihqEom5uRUQrl76Zb13emjeK3W+8pcRgRfAmwelURBbxNEKCIg== + dependencies: + "@codemirror/autocomplete" "^6.7.1" + "@codemirror/lang-html" "^6.0.0" + "@codemirror/language" "^6.3.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + "@lezer/common" "^1.0.0" + "@lezer/markdown" "^1.0.0" + +"@codemirror/language@^6.0.0", "@codemirror/language@^6.3.0", "@codemirror/language@^6.4.0", "@codemirror/language@^6.6.0": version "6.9.3" resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.9.3.tgz#1c127dc43e025d4c9b1ba1b79f4b1ba081d5aeaa" integrity sha512-qq48pYzoi6ldYWV/52+Z9Ou6QouVI+8YwvxFbUypI33NbjG2UeRHKENRyhwljTTiOqjQ33FjyZj6EREQ9apAOQ== @@ -66,28 +118,57 @@ style-mod "^4.1.0" w3c-keyname "^2.2.4" -"@lezer/common@^1.0.0", "@lezer/common@^1.1.0": +"@lezer/common@^1.0.0", "@lezer/common@^1.0.2", "@lezer/common@^1.1.0": version "1.1.2" resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.1.2.tgz#2fc5cd6788094ffc816b539ab2bc55bafacd2abc" integrity sha512-V+GqBsga5+cQJMfM0GdnHmg4DgWvLzgMWjbldBg0+jC3k9Gu6nJNZDLJxXEBT1Xj8KhRN4jmbC5CY7SIL++sVw== -"@lezer/highlight@^1.0.0": +"@lezer/css@^1.0.0", "@lezer/css@^1.1.0": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@lezer/css/-/css-1.1.4.tgz#428923881b102ee55e3bdc1e169639c942e71c24" + integrity sha512-CuUwjidrU7FOBokqASRJc72SmJ9g1PsHXDOWMoKg4md6+2u/Zxzwx5YsYrAFxRDsLrjLlsIyEF1rZHK3gFEJbw== + dependencies: + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.0.0" + +"@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3": version "1.2.0" resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.0.tgz#e5898c3644208b4b589084089dceeea2966f7780" integrity sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA== dependencies: "@lezer/common" "^1.0.0" -"@lezer/lr@^1.0.0": +"@lezer/html@^1.3.0": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@lezer/html/-/html-1.3.7.tgz#d15fcdf441c8516bfe7411e283c1467a117fe9b1" + integrity sha512-Wo+rZ5UjLP0VqUTyXjzgmTYRW5bvTJUFn4Uw0K3HCQjX2/+f+zRo9GLN5BCAojwHQISPvaQk8BWSv2SSKx/UcQ== + dependencies: + "@lezer/common" "^1.0.0" + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.0.0" + +"@lezer/javascript@^1.0.0": + version "1.4.11" + resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.4.11.tgz#4ca7681e29fda6f960e15d958ee4f4ceaf577223" + integrity sha512-B5Y9EJF4BWiMgj4ufxUo2hrORnmMBDrMtR+L7dwIO5pocuSAahG6QBwXR6PbKJOjRywJczU2r2LJPg79ER91TQ== + dependencies: + "@lezer/highlight" "^1.1.3" + "@lezer/lr" "^1.3.0" + +"@lezer/lr@^1.0.0", "@lezer/lr@^1.3.0": version "1.3.14" resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.3.14.tgz#59d4a3b25698bdac0ef182fa6eadab445fc4f29a" integrity sha512-z5mY4LStlA3yL7aHT/rqgG614cfcvklS+8oFRFBYrs4YaWLJyKKM4+nN6KopToX0o9Hj6zmH6M5kinOYuy06ug== dependencies: "@lezer/common" "^1.0.0" -"@neutralinojs/lib@neutralinojs/neutralino.js": - version "3.13.0" - resolved "https://codeload.github.com/neutralinojs/neutralino.js/tar.gz/080900b7af3d79c6e387d213b437bdb62870f109" +"@lezer/markdown@^1.0.0": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@lezer/markdown/-/markdown-1.1.2.tgz#1570740bc18d75da1b3d9b12f44ebcd481630ae8" + integrity sha512-PCla4SVSoxw95QvznrvQxC8c5Gw/sv7sMWLwJMsHsvUl6jsWeU4UneK7gtOq/fY1BaDTQIbzzSlxVuGLTSRScA== + dependencies: + "@lezer/common" "^1.0.0" + "@lezer/highlight" "^1.0.0" "@neutralinojs/neu@^10.1.0": version "10.1.0"