151 lines
5.9 KiB
HTML
151 lines
5.9 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<title>{{ title }}</title>
|
|
<meta name="viewport" content="{{ viewport }}" />
|
|
<meta
|
|
id="nicegui-color-scheme"
|
|
name="color-scheme"
|
|
content="{{ ({'True': 'dark', 'False': 'light'}).get(dark, 'normal') }}"
|
|
/>
|
|
<link href="{{ favicon_url }}" rel="shortcut icon" />
|
|
<style>
|
|
@layer theme, base, quasar, nicegui, components, utilities, overrides, quasar_importants;
|
|
@import url("{{ prefix | safe }}/_nicegui/{{version}}/static/fonts.css") layer(base);
|
|
{% if prod_js %}
|
|
@import url("{{ prefix | safe }}/_nicegui/{{version}}/static/quasar.unimportant.prod.css") layer(quasar);
|
|
@import url("{{ prefix | safe }}/_nicegui/{{version}}/static/quasar.important.prod.css") layer(quasar_importants);
|
|
{% else %}
|
|
@import url("{{ prefix | safe }}/_nicegui/{{version}}/static/quasar.unimportant.css") layer(quasar);
|
|
@import url("{{ prefix | safe }}/_nicegui/{{version}}/static/quasar.important.css") layer(quasar_importants);
|
|
{% endif %}
|
|
@import url("{{ prefix | safe }}/_nicegui/{{version}}/static/nicegui.css") layer(nicegui);
|
|
@layer quasar {
|
|
blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {
|
|
margin: revert-layer; /* HACK: revert Quasar's margin styles */
|
|
}
|
|
}
|
|
@layer overrides {
|
|
{{ headwind_css | safe }}
|
|
.column.inline, .flex.inline, .row.inline {
|
|
display: inline-flex; /* HACK: re-apply Quasar's inline styles to override Tailwind */
|
|
}
|
|
.nicegui-dialog-open,
|
|
.nicegui-select-popup-open {
|
|
scroll-behavior: auto !important; /* HACK: avoid smooth-scrolling when dialogs or select popups close */
|
|
}
|
|
}
|
|
</style>
|
|
<script type="importmap">
|
|
{"imports": {{ imports | safe }}}
|
|
</script>
|
|
<script>
|
|
addStyle = (c) => document.head.append(Object.assign(document.createElement("style"), { textContent: c }));
|
|
</script>
|
|
{{ head_html | safe }}
|
|
<!-- prevent Prettier from removing this line -->
|
|
{% for url in js_imports_urls %}
|
|
<link rel="modulepreload" href="{{ url }}" />
|
|
{% endfor %}
|
|
<!-- prevent Prettier from removing this line -->
|
|
{% if tailwind %}
|
|
<style type="text/tailwindcss">
|
|
@custom-variant dark (&:where(body.body--dark, body.body--dark *));
|
|
</style>
|
|
{% endif %}
|
|
<!-- prevent Prettier from removing this line -->
|
|
{% if unocss %}
|
|
<script defer src="{{ prefix | safe }}/_nicegui/{{version}}/static/unocss/preset-{{unocss}}.global.js"></script>
|
|
<script>
|
|
window.__unocss = {
|
|
presets: [
|
|
() => window.__unocss_runtime.presets.preset{{unocss.title()}}({
|
|
dark: {
|
|
light: 'body.body--light',
|
|
dark: 'body.body--dark',
|
|
},
|
|
}),
|
|
],
|
|
runtime: { ready: () => false },
|
|
outputToCssLayers: {
|
|
cssLayerName: (layer) => {
|
|
if (layer === 'default') return 'utilities';
|
|
if (layer === 'preflights') return 'base';
|
|
return undefined;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
<script defer src="{{ prefix | safe }}/_nicegui/{{version}}/static/unocss/core.global.js"></script>
|
|
<style>
|
|
#app.nicegui-unocss-loading {
|
|
visibility: hidden;
|
|
}
|
|
</style>
|
|
{% endif %}
|
|
</head>
|
|
<body>
|
|
<script defer src="{{ prefix | safe }}/_nicegui/{{version}}/static/socket.io.min.js"></script>
|
|
{% if tailwind %}
|
|
<script defer src="{{ prefix | safe }}/_nicegui/{{version}}/static/tailwindcss.min.js"></script>
|
|
{% endif %}
|
|
<script type="module">
|
|
import * as Vue from "vue";
|
|
globalThis.Vue = Vue;
|
|
</script>
|
|
{% if prod_js %}
|
|
<script defer src="{{ prefix | safe }}/_nicegui/{{version}}/static/quasar.umd.prod.js"></script>
|
|
{% else %}
|
|
<script defer src="{{ prefix | safe }}/_nicegui/{{version}}/static/quasar.umd.js"></script>
|
|
{% endif %}
|
|
<script defer src="{{ prefix | safe }}/_nicegui/{{version}}/static/nicegui.js"></script>
|
|
|
|
<script defer src="{{ prefix | safe }}/_nicegui/{{version}}/static/lang/{{ language }}.umd.prod.js"></script>
|
|
{{ body_html | safe }}
|
|
|
|
<div id="app" {% if unocss %}class="nicegui-unocss-loading" {% endif %}></div>
|
|
<div id="popup" class="nicegui-error-popup" aria-hidden="true">
|
|
<span>{{ translations.connection_lost }}</span>
|
|
<span>{{ translations.trying_to_reconnect }}</span>
|
|
</div>
|
|
<div id="too_long_message_popup" class="nicegui-error-popup" aria-hidden="true">
|
|
<span>{{ translations.message_too_long }}</span>
|
|
<span>{{ translations.message_too_long_body }}</span>
|
|
</div>
|
|
<script type="module">
|
|
// Load DOMPurify for HTML sanitization, polyfill for browsers without native setHTML
|
|
if (typeof Element.prototype.setHTML !== "function") {
|
|
const { default: DOMPurify } = await import("dompurify");
|
|
Element.prototype.setHTML = function (html) {
|
|
this.innerHTML = DOMPurify.sanitize(html);
|
|
};
|
|
}
|
|
|
|
const app = createApp(parseElements(String.raw`{{ elements | safe }}`), {
|
|
version: "{{ version }}",
|
|
prefix: "{{ prefix | safe }}",
|
|
query: {{ socket_io_js_query_params | safe }},
|
|
extraHeaders: {{ socket_io_js_extra_headers | safe }},
|
|
transports: {{ socket_io_js_transports | safe }},
|
|
});
|
|
const dark = {{ dark }};
|
|
const language = "{{ language }}";
|
|
const vue_config = {{ vue_config | safe }};
|
|
{{ vue_config_script | safe }}
|
|
|
|
{{ js_imports | safe }}
|
|
{{ vue_scripts | safe }}
|
|
|
|
app.mount("#app");
|
|
|
|
// Scroll to fragment after Vue mounts (browser's native scroll may have failed if element wasn't ready)
|
|
if (window.location.hash) {
|
|
Vue.nextTick(() => {
|
|
const fragment = window.location.hash.substring(1);
|
|
(document.getElementById(fragment) || document.querySelector(`a[name="${fragment}"]`))?.scrollIntoView();
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|