Skip to content

Commit 18b4fef

Browse files
committed
Improvend Editor & added emmet
1 parent 531c205 commit 18b4fef

File tree

10 files changed

+194
-18
lines changed

10 files changed

+194
-18
lines changed

build.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import { compile } from 'sass'
66
const result = await Bun.build({
77
entrypoints: ["./src/main.ts"],
88
outdir: "./dist",
9+
minify: {
10+
whitespace: true,
11+
syntax: true,
12+
},
913
});
1014

1115
// @ts-ignore

bun.lockb

0 Bytes
Binary file not shown.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"highlight.js": "^11.9.0",
1717
"hono": "^4.0.10",
1818
"jdomjs": "3.1.11",
19-
"petrel": "^1.0.7",
19+
"petrel": "1.0.8",
2020
"sass": "^1.71.1"
2121
}
2222
}

public/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
<meta name="twitter:description" content="Pastefy Codebox is an easy Code-Playground built on top of Pastefy." />
2323
<meta name="twitter:title" content="Pastefy Codebox" />
2424

25-
<link rel="stylesheet" href="/index.css?v=1">
25+
<link rel="stylesheet" href="/index.css?v=2">
2626
</head>
2727
<body>
28-
<script type="module" src="/main.js?v=1"></script>
28+
<script type="module" src="/main.js?v=2"></script>
2929
</body>
3030
</html>

src/routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ export default [
1212
{
1313
path: "/:paste",
1414
name: "editor",
15-
view: () => html`<${EditorView} test.attr="YOo" />`,
15+
view: () => html`<${EditorView} />`,
1616
},
1717
];

src/scss.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
import { compileString } from 'sass'
22

3+
const saved = {}
4+
5+
function hash(str) {
6+
let hash = 0, i, chr;
7+
if (str.length === 0) return hash;
8+
for (i = 0; i < str.length; i++) {
9+
chr = str.charCodeAt(i);
10+
hash = ((hash << 5) - hash) + chr;
11+
hash |= 0;
12+
}
13+
return hash;
14+
}
15+
316
export function scss(strings, ...values) {
417
let out = ''
518
let i = 0
@@ -10,5 +23,11 @@ export function scss(strings, ...values) {
1023
i++
1124
}
1225
}
13-
return compileString(out).css
26+
27+
const hashed = hash(out)
28+
if (!saved[hashed]) {
29+
saved[hashed] = compileString(out).css
30+
}
31+
32+
return saved[hashed]
1433
}

src/views/editor/CodeEditorPart.ts

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ import {CustomElement, State} from 'jdomjs/src/decorators.ts'
44

55
import { CodeEditor } from 'petrel/index.js'
66
import { JavaScriptAutoComplete, DockerfileAutoComplete, HTMLAutoComplete, JSONAutoComplete, JavaAutoComplete, MarkdownAutoComplete, PHPAutoComplete, SQLAutoComplete, YAMLAutoComplete } from 'petrel/autocompletions.js'
7+
import emmet from 'petrel/src/plugins/emmet.js'
78
import hljs from 'highlight.js'
89
import LANGUAGE_REPLACEMENTS from './langReplacements.ts'
10+
import importHelper from "./importHelper.ts";
911
const LANGUAGES = hljs.listLanguages()
1012

1113
const AUTOCOMPLETIONS = [
1214
{language: "javascript", file: JavaScriptAutoComplete},
15+
{language: "typescript", file: JavaScriptAutoComplete},
1316
{language: "dockerfile", file: DockerfileAutoComplete},
1417
{language: "html", file: HTMLAutoComplete},
1518
{language: "json", file: JSONAutoComplete},
@@ -26,6 +29,9 @@ export default class CodeEditorPart extends JDOMComponent {
2629
@State()
2730
selected = state<any>({})
2831

32+
@State()
33+
files = state<any[]>([])
34+
2935
codeEditor = new CodeEditor(null)
3036

3137
currentLanguage = ''
@@ -34,6 +40,9 @@ export default class CodeEditorPart extends JDOMComponent {
3440

3541
timer: number = null
3642

43+
lastName: string = null
44+
deleteEmmetPlugin: any = null
45+
3746
constructor() {
3847
super({
3948
shadowed: false
@@ -47,7 +56,6 @@ export default class CodeEditorPart extends JDOMComponent {
4756
}
4857

4958
updateEditorLang() {
50-
console.log('huh', this.selected.value.name)
5159
if (!this.selected.value.name || (this.selected.value.name instanceof Hook))
5260
return;
5361
let language;
@@ -74,11 +82,18 @@ export default class CodeEditorPart extends JDOMComponent {
7482
this.codeEditor.setHighlighter(c => hljs.highlight(language, c).value)
7583

7684
this.codeEditor.setAutoCompleteHandler(null)
77-
for (const autocompletion of AUTOCOMPLETIONS) {
78-
if (autocompletion.language == language || (autocompletion.language == "html" && isHTML)) {
79-
(async () => {
80-
this.codeEditor.setAutoCompleteHandler(new autocompletion.file)
81-
})()
85+
console.log({ language })
86+
87+
if (language === 'xml' && (
88+
this.selected.value?.name.endsWith('.vue')
89+
|| this.selected.value?.name.endsWith('.svelte')
90+
)) {
91+
this.codeEditor.setAutoCompleteHandler(new JavaScriptAutoComplete())
92+
} else {
93+
for (const autocompletion of AUTOCOMPLETIONS) {
94+
if (autocompletion.language == language || (autocompletion.language == "html" && isHTML)) {
95+
this.codeEditor.setAutoCompleteHandler(new autocompletion.file())
96+
}
8297
}
8398
}
8499
}
@@ -94,16 +109,72 @@ export default class CodeEditorPart extends JDOMComponent {
94109
}
95110
}
96111

112+
async updateLanguageAutocompletions() {
113+
console.log('Setting autocompletions')
114+
if (this.codeEditor.autoCompleteHandler instanceof JavaScriptAutoComplete) {
115+
this.codeEditor.autoCompleteHandler.importScripts = []
116+
this.files.value
117+
?.filter(f => f.name !== this.selected.value.name)
118+
?.filter(f => f.name.endsWith('.js') || f.name.endsWith('.jsx'))
119+
?.forEach(f => {
120+
const fHandler = new JavaScriptAutoComplete({ disableAutoLoad: true })
121+
fHandler.analyseCode(f.contents)
122+
this.codeEditor.autoCompleteHandler.importScripts.push(
123+
{
124+
file: './'+f.name,
125+
analysed: fHandler.analysed
126+
}
127+
)
128+
})
129+
130+
this.files.value
131+
?.filter(f => f.name !== this.selected.value.name)
132+
?.filter(f => f.name.endsWith('.svelte') || f.name.endsWith('.vue'))
133+
?.forEach(f => {
134+
const fHandler = new JavaScriptAutoComplete({ disableAutoLoad: true })
135+
fHandler.analyseCode(f.contents)
136+
this.codeEditor.autoCompleteHandler.importScripts.push(
137+
{
138+
file: './'+f.name,
139+
analysed: {
140+
defaultExport: f.name.replace('.vue', '').replace('.svelte', ''),
141+
exports: []
142+
}
143+
}
144+
)
145+
})
146+
147+
this.codeEditor.autoCompleteHandler.importScripts.push(...importHelper)
148+
console.log('ÖÖÖÖÖ', this.codeEditor.autoCompleteHandler.importScripts)
149+
}
150+
}
151+
97152
dettach() {
98153
this.selected.removeListener(this.selectListener)
99154
}
100155

101156
render() {
102157
const element = document.createElement('div')
103158
this.codeEditor.parentElement = element
159+
emmet(this.codeEditor, {
160+
preventer: () => {
161+
console.log(this.codeEditor.autoCompleteHandler instanceof HTMLAutoComplete)
162+
return !(
163+
this.codeEditor.autoCompleteHandler instanceof HTMLAutoComplete
164+
|| this.selected.value?.name?.endsWith('.vue')
165+
|| this.selected.value?.name?.endsWith('.svelte')
166+
|| this.selected.value?.name?.endsWith('.jsx')
167+
|| this.selected.value?.name?.endsWith('.tsx')
168+
)
169+
}
170+
})
104171

105172
this.selectListener = this.selected.addListener(v => {
106173
this.updateEditorLang()
174+
if (this.lastName !== v.name) {
175+
this.updateLanguageAutocompletions()
176+
this.lastName = v.name
177+
}
107178
if (this.codeEditor.value !== v.contents) {
108179
this.codeEditor.setValue(v.contents)
109180
}
@@ -138,6 +209,7 @@ export default class CodeEditorPart extends JDOMComponent {
138209
this.codeEditor.setAutoCompleteHandler(new JavaScriptAutoComplete())
139210
this.codeEditor.create()
140211
this.updateEditorLang()
212+
this.updateLanguageAutocompletions()
141213

142214
return html`${ element }`
143215
}

src/views/editor/EditorView.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
import {computed, css, html, JDOMComponent, state} from 'jdomjs'
1+
import { computed, html, JDOMComponent, state } from 'jdomjs'
22

3-
import {Attribute, Computed, CustomElement, State, Watch} from 'jdomjs/src/decorators.ts'
4-
import { Awaiting, ForEach } from 'jdomjs/src/template/helper/components.js'
5-
import {api, router} from "../../main.ts";
3+
import { CustomElement } from 'jdomjs/src/decorators.ts'
4+
import { ForEach } from 'jdomjs/src/template/helper/components.js'
5+
import { api, router } from "../../main.ts";
66
import { WebContainer } from '@webcontainer/api';
77
import {Terminal} from "@xterm/xterm";
88
import CodeEditorPart from "./CodeEditorPart.ts";
9-
import {login, user} from "../../user.ts";
9+
import { user } from "../../user.ts";
1010
import configs from "./configs";
1111
import Logo from "../../components/Logo.ts";
1212
import UserProfile from "../../components/UserProfile.ts";
13-
import TopBar from "../../components/TopBar.ts";
14-
import {scss} from "../../scss.ts";
13+
import { scss } from "../../scss.ts";
1514
import LoadingIndicator from "../../components/LoadingIndicator.ts";
1615

1716

@@ -32,6 +31,7 @@ export default class EditorView extends JDOMComponent.unshadowed {
3231
terminalLoading = state(false)
3332
containerError = state(false)
3433
savedIndicator = state(false)
34+
codeEditorComponent = state<CodeEditorPart>(null)
3535

3636
terminal: Terminal = new Terminal({
3737
convertEol: true,
@@ -192,10 +192,13 @@ export default class EditorView extends JDOMComponent.unshadowed {
192192
selectFile(index: number) {
193193
this.saveCurrent()
194194
this.selectedTabIndex.value = index
195+
195196
this.selectedFile.value = {
196197
name: this.files.value[index].name,
197198
contents: this.files.value[index].contents,
198199
}
200+
201+
this.codeEditorComponent.value?.dispatchEvent(new CustomEvent('changed_file', { detail: { file: this.selectedFile.value, files: this.files.value } }))
199202
}
200203

201204
detach() {
@@ -354,8 +357,10 @@ export default class EditorView extends JDOMComponent.unshadowed {
354357
355358
<${CodeEditorPart}
356359
selected=${this.selectedFile}
360+
files=${this.files}
357361
@changed=${() => this.saveCurrent()}
358362
@save_paste=${() => this.savePaste()}
363+
:ref=${this.codeEditorComponent}
359364
/>
360365
</div>
361366
<div class=${{'editor-preview': true, fullscreen: this.fullscreen}} :if=${this.previewShown}>

src/views/editor/importHelper.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
export default [
2+
{
3+
file: 'react',
4+
analysed: {
5+
defaultExport: 'React',
6+
exports: [
7+
'useState',
8+
'useEffect',
9+
'useContext',
10+
'useReducer',
11+
'useCallback',
12+
'useMemo',
13+
'useRef',
14+
'useImperativeHandle',
15+
'useLayoutEffect',
16+
'useDebugValue',
17+
'useDeferredValue',
18+
'useTransition',
19+
'startTransition',
20+
'useId',
21+
'useSyncExternalStore',
22+
'useInsertionEffect',
23+
'Component',
24+
'PureComponent',
25+
'lazy',
26+
'Suspense',
27+
'createRef',
28+
'forwardRef',
29+
'Fragment',
30+
'Children',
31+
'isValidElement',
32+
'cloneElement',
33+
'memo',
34+
]
35+
}
36+
},
37+
{
38+
file: 'vue',
39+
analysed: {
40+
defaultExport: 'Vue',
41+
exports: [
42+
'createApp',
43+
'createSSRApp',
44+
'nextTick',
45+
'defineComponent',
46+
'defineAsyncComponent',
47+
'defineCustomElement',
48+
]
49+
}
50+
},
51+
{
52+
file: 'jdomjs',
53+
analysed: {
54+
defaultExport: undefined,
55+
exports: [
56+
'$',
57+
'$n',
58+
'$h',
59+
'$escHTML',
60+
'$r',
61+
'$c',
62+
'JDOMComponent',
63+
'state',
64+
'watch',
65+
'computed',
66+
'bind',
67+
'html',
68+
'css',
69+
'comp',
70+
'Hook',
71+
'JDOM',
72+
]
73+
}
74+
}
75+
]

src/views/editor/langReplacements.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default {
1212
xhtml: 'xml',
1313
iml: 'xml',
1414
vue: 'xml',
15+
svelte: 'xml',
1516
yml: 'yaml',
1617
py: 'python',
1718
css: 'scss',

0 commit comments

Comments
 (0)