You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
bandolier-website/admin/bando/Djenterator.svelte

152 lines
3.9 KiB

<script>
import template from "lodash/template";
import Icon from "$/client/components/Icon.svelte";
import Toasts from "$/client/components/Toasts.svelte";
import Code from "$/client/components/Code.svelte";
import { log } from "$/client/logging.js";
import Layout from "../Layout.svelte";
import api from '$/client/api.js';
import { onMount } from "svelte";
export let selected_template;
let showing_rendered = false;
let results = "";
let source = "";
let variable_json = "{ }";
let generators = [];
let variables = {};
let renderer = () => source;
let notice = "";
let last_good = "";
let send_toast;
let language = "javascript";
const language_list = {
"html": "html",
"svelte": "javascript",
"sh": "shell",
"js": "javascript"
}
const list_generators = async () => {
let [status, data] = await api.get('/api/devtools/djenterator');
if(status == 200) {
generators = data;
selected_template = generators[0];
} else {
log.debug("failed to load generators", status);
}
}
const render_template = () => {
try {
// avoid rendering when the current template doesn't match the renderer
if(selected_template == renderer._template) {
variables = variable_json ? JSON.parse(variable_json): {};
results = renderer(variables);
notice = "";
last_good = results;
}
return true;
} catch(err) {
log.error(err);
notice = err.message;
results = last_good;
return false;
}
}
const load_variables = async (template_name) => {
let res = await fetch(`/djenterator/${template_name}.vars`);
if(res.status == 200) {
variable_json = await res.text();
} else {
variable_json = '{}';
notice = `No ${template_name}.vars file found. ${res.status}`;
}
}
const detect_language = (name) => {
const ext = name.split(".")[1];
language = language_list[ext];
}
const load_template = async (template_name) => {
let res = await fetch(`/djenterator/${template_name}`);
if(res.status == 200) {
source = await res.text();
last_good = source;
detect_language(template_name);
try {
renderer = template(source);
// tag this template renderer so that we don't try to render it against the wrong one
renderer._template = template_name;
render_template();
} catch(error) {
log.error(error);
notice = `${error.message}`;
results = source;
}
} else {
notice = `Error loading ${template_name}: ${res.status}`;
}
}
const copy_code = () => {
navigator.clipboard.writeText(results).then(() => {
notice = "Code copied to clipboard.";
}, () => {
notice = "Failed copying to clipboard.";
});
}
$: if(variable_json) render_template();
// this reload the templates when you click on a new one
const re_render = async (what) => {
await load_variables(what);
await load_template(what);
}
$: if(selected_template) re_render(selected_template);
onMount(async () => await list_generators());
</script>
<style>
textarea.editor {
height: 15em;
background-color: var(--value0);
color: var(--value9);
}
</style>
<Layout fullscreen={ true } header={ false } footer={ false } testid="page-bando-djenterator">
<blockstart style="width: 100%">
<block style="--w: 100%">
<select bind:value={ selected_template }>
{#each generators as template}
<option value={ template }>{ template }</option>
{/each}
</select>
<textarea class="editor" bind:value={ variable_json }></textarea>
{#if notice}
<callout class="error">{notice}</callout>
{/if}
{#if results}
<Code on:copy={ send_toast("Copied to clipboard!") } content={ results } language={ language } />
{/if}
</block>
</blockstart>
<Toasts bind:send_toast fade_after={ 10000 } orientation="bottom right" />
</Layout>