From d38244980c63e0a6be42823eb3977e221d0d0e20 Mon Sep 17 00:00:00 2001 From: Davor Hrg Date: Tue, 16 Aug 2022 23:56:44 +0200 Subject: [PATCH] editors testing, sync scroll, etc --- .prettierignore | 3 +- apps/repl/.prettierrc | 11 ++++ apps/repl/editor.css | 10 +++- apps/repl/editor.html | 7 ++- apps/repl/editor.jsx | 97 +++++++++++++++++++++++++++------- apps/repl/index.jsx | 13 +++-- apps/repl/main.css | 52 ++++++++++++------ apps/repl/src/FlipFrame.jsx | 47 ++++++++-------- apps/repl/src/MiniEditor.jsx | 78 +++++++++++++-------------- apps/repl/src/MonacoEditor.jsx | 30 ++++++----- 10 files changed, 224 insertions(+), 124 deletions(-) create mode 100644 apps/repl/.prettierrc diff --git a/.prettierignore b/.prettierignore index 819c117..7b69e1b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -77,7 +77,8 @@ common/autoinstallers/*/.npmrc .history esm cjs - +deploy +dist #------------------------------------------------------------------------------------------------------------------- # Prettier-specific overrides diff --git a/apps/repl/.prettierrc b/apps/repl/.prettierrc new file mode 100644 index 0000000..59eff3c --- /dev/null +++ b/apps/repl/.prettierrc @@ -0,0 +1,11 @@ +{ + "semi": false, + "arrowParens": "avoid", + "printWidth": 110, + + "endOfLine": "auto", + + "singleQuote": true, + + "trailingComma": "all" +} diff --git a/apps/repl/editor.css b/apps/repl/editor.css index 0163676..6aa3ba5 100644 --- a/apps/repl/editor.css +++ b/apps/repl/editor.css @@ -7,9 +7,15 @@ body, html{ } .c-iframe{ - width:300px; - height:300px; position: relative; border: solid 1px red; } +.c-left { + width: 300px; +} + +.c-main{ + display: grid; + grid-template-columns: minmax(25%, 300px) auto; +} \ No newline at end of file diff --git a/apps/repl/editor.html b/apps/repl/editor.html index fafd031..0ba4886 100644 --- a/apps/repl/editor.html +++ b/apps/repl/editor.html @@ -6,8 +6,7 @@ Jsx6 App Monaco editor - -
- + - \ No newline at end of file + + \ No newline at end of file diff --git a/apps/repl/editor.jsx b/apps/repl/editor.jsx index 09f2963..d23785e 100644 --- a/apps/repl/editor.jsx +++ b/apps/repl/editor.jsx @@ -4,39 +4,100 @@ import { appendChild, domWithScope, insertBefore, Jsx6, setVisible } from '@jsx6/jsx6' import { FlipFrame } from './src/FlipFrame' import { transform } from './src/transform' +import { MonacoEditor } from './src/MonacoEditor' import styles from './editor.css' -class Editor extends Jsx6{ +class Editor extends Jsx6 { + init() { + this.compiled.editor.updateOptions({ readOnly: true }) + function syncScroll(ed1, ed2) { + ed1.onDidScrollChange(e => ed2.setScrollTop(e.scrollTop)) + ed2.onDidScrollChange(e => ed1.setScrollTop(e.scrollTop)) + } + syncScroll(this.editor.editor, this.compiled.editor) + } + + tpl(h, state, $state) { + return ( + <> +
+ {/* ---------------- left side ----------------------- */} +
+

Title

+

Bla bla

+
+ + {/* ---------------- right side ----------------------- */} +
+ {/* right top */} +
+ + +
- tpl(h, state, $state){ - return <> - - + {/* right bottom */} +
+
+
+
+
+
+ + ) } } -const editor = self.APP = insertBefore(document.body,) +const editor = (self.APP = insertBefore(document.body, )) -self.doTest2 = ()=>{ +self.doTest2 = () => { let time = performance.now() APP.iframe.counter = (APP.iframe.counter || 0) + 1 - APP.iframe.waitNext().then(iframe=>{ + APP.iframe.waitNext().then(iframe => { console.log('reloaded', performance.now() - time, iframe.__mark) - insertBefore(iframe.contentWindow.document.body,

Hello iframe {iframe.loadCounter} / {APP.iframe.counter}

) - }); + insertBefore( + iframe.contentWindow.document.body, +

+ Hello iframe {iframe.loadCounter} / {APP.iframe.counter} +

, + ) + }) } -const code = `import { h, Jsx6, appendChild } from '@jsx6/jsx6' - const hello2 =
Hello {name}!
- const hello3 =
Hello {name}!
- export const hello =
Hello {name}!
-` -// console.log(code) -// console.log(transform(code, {}).code,) -// console.log(transform(code, {},{plugins:['transform-modules-commonjs']}).code,) + +const code = `import { h, Jsx6, insertBefore } from '@jsx6/jsx6' + +insertBefore(document.body,

Hello World!{/* comment in jsx*/}

) +console.log('aaaaa') +console.log('aaaaa') +` +editor.editor.setValue(code) + +applyCodeChange(code) + +let changeTimer +editor.editor.editor.getModel().onDidChangeContent(event => { + console.log('code change', event) + clearTimeout(changeTimer) + changeTimer = setTimeout(() => { + applyCodeChange(editor.editor.getValue()) + }, 300) +}) +function applyCodeChange(code) { + let time = performance.now() + const codeTransformed = transform(code, {}).code + let timeTransform1 = performance.now() + const codeToRun = transform(code, {}, { plugins: ['transform-modules-commonjs'] }).code + let timeTransform2 = performance.now() + + editor.compiled.setValue(codeTransformed + '\n') + console.log(code) + console.log(timeTransform1 - time, codeTransformed) + console.log(timeTransform2 - time, codeToRun) +} diff --git a/apps/repl/index.jsx b/apps/repl/index.jsx index 8b990b8..2990925 100644 --- a/apps/repl/index.jsx +++ b/apps/repl/index.jsx @@ -5,8 +5,11 @@ import { appendChild, insertBefore, insertHtml } from '@jsx6/jsx6' import { Editor } from './src/MonacoEditor' import './main.css' -insertHtml(document.body,null,Hello world. -
- -
-
) +insertHtml( + document.body, + null, + + Hello world. +
+
, +) diff --git a/apps/repl/main.css b/apps/repl/main.css index dbf6c7d..b334bb5 100644 --- a/apps/repl/main.css +++ b/apps/repl/main.css @@ -2,29 +2,47 @@ .bl{ display: block; } .bli{ display: inline-block; } - /* flex */ +/* flex */ .fx { display: flex; } .fxi { display: inline-flex; } -.fx1 { flex: 1; } +.fx1, .fxs1, .fxc1 { flex: 1; } +.fx2 {flex: 2;} .fx3 {flex: 3;} .fx4 {flex: 4;} .fx5 {flex: 5;} .fx6 {flex: 6;} +.fx7 {flex: 7;} .fx8 {flex: 8;} .fx9 {flex: 9;} .fx10 {flex: 10;} .fx11 {flex: 11;} .fx12 {flex: 12;} /* default is row, so class for column is needed */ -.fx-fc { display: flex; flex-flow: column;} - /* flex with everything stretched */ -.fxc { display: flex; justify-content: center; align-items: center;} - /* flex with everything centered */ -.fxs { display: flex; justify-content: stretch; align-items: stretch;} +.fxfc { display: flex; flex-flow: column;} + + /* STRETCH flex with everything stretched (fxs1 is with flex:1) */ +.fxs, .fxs1 { display: flex; justify-content: stretch; align-items: stretch;} + /* CENTER flex with everything centered (fxc1 is with flex:1) */ +.fxc, .fxc1 { display: flex; justify-content: center; align-items: center;} + /* flex justify tweaks */ -.fx-jc { justify-content: center; } -.fx-ac { align-items: center; } -.fx-js { justify-content: flex-start; } -.fx-as { align-items: flex-start; } -.fx-je { justify-content: flex-end; } -.fx-ae { align-items: flex-end; } - -/* some very common sizes */ +.fxjc { justify-content: center; } +.fxjs { justify-content: flex-start; } +.fxje { justify-content: flex-end; } + /* flex justify tweaks */ +.fxsa { justify-content: space-around; } +.fxsb { justify-content: space-between; } +.fxse { justify-content: space-evenly; } + + /* flex align tweaks */ +.fxac { align-items: center; } +.fxas { align-items: flex-start; } +.fxae { align-items: flex-end; } + + /* SIZE ... very common sizes */ .wa { width: auto; } .w100 { width: 100%; } .w50 { width: 50%; } .h100 { height: 100%; } -/* often needed owerflow */ +.h50 { width: 50%; } + + /* OVERFLOW common */ .owh{ overflow: hidden;} -.owa{ overflow: auto;} \ No newline at end of file +.owa{ overflow: auto;} + + +/* PADIING */ +.pad{ + padding: 20px; +} \ No newline at end of file diff --git a/apps/repl/src/FlipFrame.jsx b/apps/repl/src/FlipFrame.jsx index 42a3f4d..aa6dfc1 100644 --- a/apps/repl/src/FlipFrame.jsx +++ b/apps/repl/src/FlipFrame.jsx @@ -1,34 +1,31 @@ -import { Jsx6 } from '@jsx6/jsx6'; -import { Defered } from './async/Defered'; +import { Jsx6 } from '@jsx6/jsx6' +import { Defered } from './async/Defered' export class FlipFrame extends Jsx6 { constructor(...args) { super(...args) const [attr] = args const iframeAttr = { - sandbox: attr?.sandbox || 'allow-same-origin', + sandbox: attr?.sandbox || 'allow-same-origin', src: attr?.src || 'about:blank', - style: 'position:absolute; width:100%; height:100%; display:none; border:none' + style: 'position:absolute; width:100%; height:100%; display:none; border:none', } - this.iframes = [ - h('iframe', iframeAttr), - h('iframe', iframeAttr), - ] + this.iframes = [h('iframe', iframeAttr), h('iframe', iframeAttr)] this.frameIndex = 0 } reloadFrame(cb) { - cb(this.next()); + cb(this.next()) } waitNext() { - this.promise?.reject('skipped'); - const next = this.next(); + this.promise?.reject('skipped') + const next = this.next() if (next.__loading) { - this.promise = new Defered(); - return this.promise.promise; + this.promise = new Defered() + return this.promise.promise } else { - return Promise.resolve(next); + return Promise.resolve(next) } } @@ -36,28 +33,28 @@ export class FlipFrame extends Jsx6 { const old = this.iframes[this.frameIndex] this.frameIndex = (this.frameIndex + 1) % this.iframes.length const next = this.iframes[this.frameIndex] - old.__loading = true; - old.contentWindow.document.location.reload(); + old.__loading = true + old.contentWindow.document.location.reload() old.style.display = 'none' next.style.display = '' - return next; + return next } onload(evt) { - const iframe = evt.target; - evt.target.loadCounter = (evt.target.loadCounter || 0) + 1; - evt.target.__loading = false; - this.promise?.resolve(iframe); - this.promise = null; + const iframe = evt.target + evt.target.loadCounter = (evt.target.loadCounter || 0) + 1 + evt.target.__loading = false + this.promise?.resolve(iframe) + this.promise = null } - tpl(){ + tpl() { return this.iframes } init() { - this.iframes.forEach((iframe,i) =>{ - iframe.onload = evt => this.onload(evt); + this.iframes.forEach((iframe, i) => { + iframe.onload = evt => this.onload(evt) }) } } diff --git a/apps/repl/src/MiniEditor.jsx b/apps/repl/src/MiniEditor.jsx index 475d616..edc81b4 100644 --- a/apps/repl/src/MiniEditor.jsx +++ b/apps/repl/src/MiniEditor.jsx @@ -4,10 +4,10 @@ import { Jsx6 } from '@jsx6/jsx6' // https://zserge.com/posts/js-editor/ // https://jsfiddle.net/zserge/gkbjv47n/ -export class Editor extends Jsx6{ - cName='MiniEditor' - init(){ - this.el.setAttribute('contenteditable','true') +export class Editor extends Jsx6 { + cName = 'MiniEditor' + init() { + this.el.setAttribute('contenteditable', 'true') editor(this.el) } } @@ -21,63 +21,63 @@ const js = el => { '$1', ) .replace(/(".*?"|'.*?'|`.*?`)/g, '$1') - .replace(/\b(\d+)/g, '$1'); - node.innerHTML = s.split('\n').join('
'); + .replace(/\b(\d+)/g, '$1') + node.innerHTML = s.split('\n').join('
') } -}; +} const editor = (el, highlight = js, tab = ' ') => { const caret = () => { - const range = window.getSelection().getRangeAt(0); - const prefix = range.cloneRange(); - prefix.selectNodeContents(el); - prefix.setEnd(range.endContainer, range.endOffset); - return prefix.toString().length; - }; + const range = window.getSelection().getRangeAt(0) + const prefix = range.cloneRange() + prefix.selectNodeContents(el) + prefix.setEnd(range.endContainer, range.endOffset) + return prefix.toString().length + } const setCaret = (pos, parent = el) => { for (const node of parent.childNodes) { if (node.nodeType == Node.TEXT_NODE) { if (node.length >= pos) { - const range = document.createRange(); - const sel = window.getSelection(); - range.setStart(node, pos); - range.collapse(true); - sel.removeAllRanges(); - sel.addRange(range); - return -1; + const range = document.createRange() + const sel = window.getSelection() + range.setStart(node, pos) + range.collapse(true) + sel.removeAllRanges() + sel.addRange(range) + return -1 } else { - pos = pos - node.length; + pos = pos - node.length } } else { - pos = setCaret(pos, node); + pos = setCaret(pos, node) if (pos < 0) { - return pos; + return pos } } } - return pos; - }; + return pos + } - highlight(el); + highlight(el) el.addEventListener('keydown', e => { if (e.which === 9) { - const pos = caret() + tab.length; - const range = window.getSelection().getRangeAt(0); - range.deleteContents(); - range.insertNode(document.createTextNode(tab)); - highlight(el); - setCaret(pos); - e.preventDefault(); + const pos = caret() + tab.length + const range = window.getSelection().getRangeAt(0) + range.deleteContents() + range.insertNode(document.createTextNode(tab)) + highlight(el) + setCaret(pos) + e.preventDefault() } - }); + }) el.addEventListener('keyup', e => { if (e.keyCode >= 0x30 || e.keyCode == 0x20) { - const pos = caret(); - highlight(el); - setCaret(pos); + const pos = caret() + highlight(el) + setCaret(pos) } - }); -}; + }) +} diff --git a/apps/repl/src/MonacoEditor.jsx b/apps/repl/src/MonacoEditor.jsx index 6b69a75..f04ccd2 100644 --- a/apps/repl/src/MonacoEditor.jsx +++ b/apps/repl/src/MonacoEditor.jsx @@ -2,19 +2,23 @@ import { Jsx6 } from '@jsx6/jsx6' import { monaco } from './customMonaco' // import * as monaco from 'monaco-editor' -console.log('monaco', monaco) +export class MonacoEditor extends Jsx6 { + setValue(value) { + this.editor.getModel().setValue(value) + } -export class Editor extends Jsx6{ - init(){ - setTimeout(() => { - monaco.editor.create(this.el, { - value: "function hello() {\n\talert('Hello world!');\n}", - language: 'javascript', - minimap: { - enabled: false - } - }) - }, 0); + getValue() { + return this.editor.getModel().getValue() } -} + init() { + this.editor = monaco.editor.create(this.el, { + value: '', + language: 'javascript', + automaticLayout: true, + minimap: { + enabled: false, + }, + }) + } +}