115 lines
2.9 KiB
TypeScript
Raw Normal View History

2020-06-14 16:18:50 +08:00
/* eslint-disable no-console */
// eslint-disable-next-line import/no-unresolved
2020-09-05 21:58:07 +08:00
import * as m from 'monaco-editor';
2021-03-03 23:58:09 +08:00
import { watchEffect } from 'vue';
2020-06-13 11:23:47 +08:00
import { transform } from '@babel/core';
2020-09-05 21:58:07 +08:00
import babelPluginJsx from '../../babel-plugin-jsx/src';
import { initOptions, compilerOptions, VueJSXPluginOptions } from './options';
2020-06-13 11:23:47 +08:00
import './index.css';
2020-09-05 21:58:07 +08:00
declare global {
interface Window {
monaco: typeof m
init: () => void
}
2020-06-13 11:23:47 +08:00
}
interface PersistedState {
src: string
options: VueJSXPluginOptions
}
2020-09-05 21:58:07 +08:00
window.init = () => {
const { monaco } = window;
2020-06-13 11:23:47 +08:00
const persistedState: PersistedState = JSON.parse(
decodeURIComponent(window.location.hash.slice(1))
|| localStorage.getItem('state')
|| '{}',
);
Object.assign(compilerOptions, persistedState.options);
2020-09-05 21:58:07 +08:00
const sharedEditorOptions: m.editor.IStandaloneEditorConstructionOptions = {
theme: 'vs-dark',
fontSize: 14,
wordWrap: 'on',
scrollBeyondLastLine: false,
renderWhitespace: 'selection',
contextmenu: false,
minimap: {
enabled: false,
},
};
2020-06-13 11:23:47 +08:00
2020-09-05 21:58:07 +08:00
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
allowJs: true,
allowNonTsExtensions: true,
jsx: monaco.languages.typescript.JsxEmit.Preserve,
2020-09-05 21:58:07 +08:00
target: monaco.languages.typescript.ScriptTarget.Latest,
});
2020-06-13 11:23:47 +08:00
2020-09-05 21:58:07 +08:00
const editor = monaco.editor.create(document.getElementById('source')!, {
value: decodeURIComponent(window.location.hash.slice(1)) || persistedState.src || 'const App = () => <div>Hello World</div>',
language: 'typescript',
2020-09-05 21:58:07 +08:00
tabSize: 2,
...sharedEditorOptions,
});
2020-06-13 11:23:47 +08:00
2020-09-05 21:58:07 +08:00
const output = monaco.editor.create(document.getElementById('output')!, {
value: '',
language: 'javascript',
readOnly: true,
tabSize: 2,
...sharedEditorOptions,
2020-06-13 11:23:47 +08:00
});
2021-03-03 23:58:09 +08:00
const reCompile = () => {
2020-09-05 21:58:07 +08:00
const src = editor.getValue();
2021-03-03 23:58:09 +08:00
const state = JSON.stringify(compilerOptions);
localStorage.setItem('state', state);
2020-09-05 21:58:07 +08:00
window.location.hash = encodeURIComponent(src);
console.clear();
transform(src, {
babelrc: false,
2021-03-03 23:58:09 +08:00
plugins: [[babelPluginJsx, compilerOptions]],
2020-09-05 21:58:07 +08:00
ast: true,
}, (err, result = {}) => {
const res = result!;
if (!err) {
console.log('AST', res.ast!);
output.setValue(res.code!);
} else {
output.setValue(err.message!);
}
});
};
2020-06-13 11:23:47 +08:00
2020-09-05 21:58:07 +08:00
// handle resize
window.addEventListener('resize', () => {
editor.layout();
output.layout();
});
2021-03-03 23:58:09 +08:00
initOptions();
watchEffect(reCompile);
2020-06-13 11:23:47 +08:00
2020-09-05 21:58:07 +08:00
// update compile output when input changes
2021-03-03 23:58:09 +08:00
editor.onDidChangeModelContent(debounce(reCompile));
2020-09-05 21:58:07 +08:00
};
2020-06-13 11:23:47 +08:00
function debounce<T extends(...args: any[]) => any>(
fn: T,
delay = 300): T {
let prevTimer: number | null = null;
return ((...args: any[]) => {
2020-06-13 11:23:47 +08:00
if (prevTimer) {
clearTimeout(prevTimer);
2020-06-13 11:23:47 +08:00
}
prevTimer = window.setTimeout(() => {
fn(...args);
prevTimer = null;
}, delay);
}) as any;
2020-06-13 11:23:47 +08:00
}