|
|
@ -1,7 +1,6 @@
|
|
|
|
<script>
|
|
|
|
<script>
|
|
|
|
import { onMount, setContext } from 'svelte';
|
|
|
|
import { onMount, setContext } from 'svelte';
|
|
|
|
import { writable } from 'svelte/store';
|
|
|
|
import { writable } from 'svelte/store';
|
|
|
|
import * as fleece from 'golden-fleece';
|
|
|
|
|
|
|
|
import SplitPane from './SplitPane.svelte';
|
|
|
|
import SplitPane from './SplitPane.svelte';
|
|
|
|
import CodeMirror from './CodeMirror.svelte';
|
|
|
|
import CodeMirror from './CodeMirror.svelte';
|
|
|
|
import ComponentSelector from './Input/ComponentSelector.svelte';
|
|
|
|
import ComponentSelector from './Input/ComponentSelector.svelte';
|
|
|
@ -10,7 +9,6 @@
|
|
|
|
import InputOutputToggle from './InputOutputToggle.svelte';
|
|
|
|
import InputOutputToggle from './InputOutputToggle.svelte';
|
|
|
|
|
|
|
|
|
|
|
|
export let version = 'beta'; // TODO change this to latest when the time comes
|
|
|
|
export let version = 'beta'; // TODO change this to latest when the time comes
|
|
|
|
export let app;
|
|
|
|
|
|
|
|
export let embedded = false;
|
|
|
|
export let embedded = false;
|
|
|
|
export let orientation = 'columns';
|
|
|
|
export let orientation = 'columns';
|
|
|
|
export let show_props = true;
|
|
|
|
export let show_props = true;
|
|
|
@ -23,14 +21,37 @@
|
|
|
|
version; // workaround
|
|
|
|
version; // workaround
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
imports,
|
|
|
|
imports: $bundle.imports,
|
|
|
|
components: $components,
|
|
|
|
components: $components,
|
|
|
|
values: $values
|
|
|
|
values: $values
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function update(app) {
|
|
|
|
export function set(data) {
|
|
|
|
// TODO
|
|
|
|
components.set(data.components);
|
|
|
|
|
|
|
|
values.set(data.values);
|
|
|
|
|
|
|
|
selected.set(data.components[0]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module_editor.set($selected.source, $selected.type);
|
|
|
|
|
|
|
|
output.set($selected);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function update(data) {
|
|
|
|
|
|
|
|
const { name, type } = $selected || {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
components.set(data.components);
|
|
|
|
|
|
|
|
values.set(data.values);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const matched_component = data.components.find(file => file.name === name && file.type === type);
|
|
|
|
|
|
|
|
selected.set(matched_component || data.components[0]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (matched_component) {
|
|
|
|
|
|
|
|
module_editor.update(matched_component.source);
|
|
|
|
|
|
|
|
output.update(matched_component);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
module_editor.set(matched_component.source, matched_component.type);
|
|
|
|
|
|
|
|
output.set(matched_component);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const components = writable([]);
|
|
|
|
const components = writable([]);
|
|
|
@ -38,6 +59,9 @@
|
|
|
|
const selected = writable(null);
|
|
|
|
const selected = writable(null);
|
|
|
|
const bundle = writable(null);
|
|
|
|
const bundle = writable(null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let module_editor;
|
|
|
|
|
|
|
|
let output;
|
|
|
|
|
|
|
|
|
|
|
|
setContext('REPL', {
|
|
|
|
setContext('REPL', {
|
|
|
|
components,
|
|
|
|
components,
|
|
|
|
values,
|
|
|
|
values,
|
|
|
@ -52,6 +76,8 @@
|
|
|
|
const component = $components.find(c => c.name === name && c.type === type);
|
|
|
|
const component = $components.find(c => c.name === name && c.type === type);
|
|
|
|
selected.set(component);
|
|
|
|
selected.set(component);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output.set($selected);
|
|
|
|
|
|
|
|
|
|
|
|
// TODO select the line/column in question
|
|
|
|
// TODO select the line/column in question
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
@ -69,109 +95,59 @@
|
|
|
|
components.update(c => c);
|
|
|
|
components.update(c => c);
|
|
|
|
|
|
|
|
|
|
|
|
// recompile selected component
|
|
|
|
// recompile selected component
|
|
|
|
compile($selected, compile_options);
|
|
|
|
output.update($selected);
|
|
|
|
|
|
|
|
|
|
|
|
// regenerate bundle (TODO do this in a separate worker?)
|
|
|
|
// regenerate bundle (TODO do this in a separate worker?)
|
|
|
|
workers.bundler.postMessage({ type: 'bundle', components: $components });
|
|
|
|
workers.bundler.postMessage({ type: 'bundle', components: $components });
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
register_module_editor(editor) {
|
|
|
|
|
|
|
|
module_editor = editor;
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
register_output(handlers) {
|
|
|
|
|
|
|
|
output = handlers;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$: {
|
|
|
|
function handle_select(component) {
|
|
|
|
components.set(app.components);
|
|
|
|
selected.set(component);
|
|
|
|
values.set(app.values);
|
|
|
|
module_editor.set(component.source, component.type);
|
|
|
|
selected.set(app.components[0]);
|
|
|
|
output.set($selected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let workers;
|
|
|
|
let workers;
|
|
|
|
|
|
|
|
|
|
|
|
let imports = null;
|
|
|
|
let input;
|
|
|
|
let import_map = null;
|
|
|
|
|
|
|
|
let dom;
|
|
|
|
|
|
|
|
let ssr;
|
|
|
|
|
|
|
|
let sourceError = null;
|
|
|
|
|
|
|
|
let runtimeError = null;
|
|
|
|
|
|
|
|
let warnings = [];
|
|
|
|
|
|
|
|
let js = '';
|
|
|
|
|
|
|
|
let css = '';
|
|
|
|
|
|
|
|
let uid = 0;
|
|
|
|
|
|
|
|
let props = [];
|
|
|
|
|
|
|
|
let sourceErrorLoc;
|
|
|
|
let sourceErrorLoc;
|
|
|
|
let runtimeErrorLoc;
|
|
|
|
let runtimeErrorLoc; // TODO refactor this stuff — runtimeErrorLoc is unused
|
|
|
|
|
|
|
|
|
|
|
|
let compile_options = {
|
|
|
|
|
|
|
|
generate: 'dom',
|
|
|
|
|
|
|
|
dev: false,
|
|
|
|
|
|
|
|
css: false,
|
|
|
|
|
|
|
|
hydratable: false,
|
|
|
|
|
|
|
|
customElement: false,
|
|
|
|
|
|
|
|
immutable: false,
|
|
|
|
|
|
|
|
legacy: false
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let width = typeof window !== 'undefined' ? window.innerWidth : 300;
|
|
|
|
let width = typeof window !== 'undefined' ? window.innerWidth : 300;
|
|
|
|
let show_output = false;
|
|
|
|
let show_output = false;
|
|
|
|
|
|
|
|
|
|
|
|
onMount(async () => {
|
|
|
|
onMount(async () => {
|
|
|
|
workers = {
|
|
|
|
workers = {
|
|
|
|
compiler: new Worker('/workers/compiler.js'),
|
|
|
|
|
|
|
|
bundler: new Worker('/workers/bundler.js')
|
|
|
|
bundler: new Worker('/workers/bundler.js')
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
workers.compiler.postMessage({ type: 'init', version });
|
|
|
|
|
|
|
|
workers.compiler.onmessage = event => {
|
|
|
|
|
|
|
|
js = event.data.js;
|
|
|
|
|
|
|
|
css = event.data.css || `/* Add a <sty` + `le> tag to see compiled CSS */`;
|
|
|
|
|
|
|
|
if (event.data.props) props = event.data.props;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
workers.bundler.postMessage({ type: 'init', version });
|
|
|
|
workers.bundler.postMessage({ type: 'init', version });
|
|
|
|
workers.bundler.onmessage = event => {
|
|
|
|
workers.bundler.onmessage = event => {
|
|
|
|
bundle.set(event.data);
|
|
|
|
bundle.set(event.data);
|
|
|
|
({ imports, import_map, dom, ssr, warnings, error: sourceError } = event.data);
|
|
|
|
|
|
|
|
if (sourceError) console.error(sourceError);
|
|
|
|
|
|
|
|
runtimeError = null;
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
return () => {
|
|
|
|
workers.compiler.terminate();
|
|
|
|
|
|
|
|
workers.bundler.terminate();
|
|
|
|
workers.bundler.terminate();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function compile(component, options) {
|
|
|
|
$: if ($bundle && $bundle.error && $selected) {
|
|
|
|
if (component.type === 'svelte') {
|
|
|
|
sourceErrorLoc = $bundle.error.filename === `${$selected.name}.${$selected.type}`
|
|
|
|
workers.compiler.postMessage({
|
|
|
|
? $bundle.error.start
|
|
|
|
type: 'compile',
|
|
|
|
|
|
|
|
source: component.source,
|
|
|
|
|
|
|
|
options: Object.assign({
|
|
|
|
|
|
|
|
name: component.name,
|
|
|
|
|
|
|
|
filename: `${component.name}.svelte`
|
|
|
|
|
|
|
|
}, options),
|
|
|
|
|
|
|
|
entry: component === $components[0]
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
js = css = `/* Select a component to see its compiled code */`;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$: if (sourceError && $selected) {
|
|
|
|
|
|
|
|
sourceErrorLoc = sourceError.filename === `${$selected.name}.${$selected.type}`
|
|
|
|
|
|
|
|
? sourceError.start
|
|
|
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$: if (runtimeError && $selected) {
|
|
|
|
|
|
|
|
runtimeErrorLoc = runtimeError.filename === `${$selected.name}.${$selected.type}`
|
|
|
|
|
|
|
|
? runtimeError.start
|
|
|
|
|
|
|
|
: null;
|
|
|
|
: null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$: if (workers && app.components) {
|
|
|
|
$: if (workers && $components) {
|
|
|
|
workers.bundler.postMessage({ type: 'bundle', components: app.components });
|
|
|
|
workers.bundler.postMessage({ type: 'bundle', components: $components });
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$: if (workers && $selected) {
|
|
|
|
|
|
|
|
compile($selected, compile_options);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
@ -240,21 +216,12 @@
|
|
|
|
fixed_pos={50}
|
|
|
|
fixed_pos={50}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<section slot=a>
|
|
|
|
<section slot=a>
|
|
|
|
<ComponentSelector/>
|
|
|
|
<ComponentSelector {handle_select}/>
|
|
|
|
<ModuleEditor error={sourceError} errorLoc="{sourceErrorLoc || runtimeErrorLoc}" {warnings}/>
|
|
|
|
<ModuleEditor bind:this={input} errorLoc="{sourceErrorLoc || runtimeErrorLoc}"/>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<section slot=b style='height: 100%;'>
|
|
|
|
<section slot=b style='height: 100%;'>
|
|
|
|
<Output
|
|
|
|
<Output {version} {embedded} {show_props}/>
|
|
|
|
bind:compile_options
|
|
|
|
|
|
|
|
{version}
|
|
|
|
|
|
|
|
{js}
|
|
|
|
|
|
|
|
{css}
|
|
|
|
|
|
|
|
{props}
|
|
|
|
|
|
|
|
{runtimeError}
|
|
|
|
|
|
|
|
{embedded}
|
|
|
|
|
|
|
|
{show_props}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
</SplitPane>
|
|
|
|
</SplitPane>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|