mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
This PR move codes from main.ts into two new plugins: - splashscreen (formerly known as py-loader) - importmap The old setting config.autoclose_loader is still supported but deprecated; the new setting is config.splashscreen.autoclose. Moreover, it does a small refactoring around UserError: now UserErrors are correctly caught even if they are raised from within afterRuntimeLoad.
121 lines
3.9 KiB
TypeScript
121 lines
3.9 KiB
TypeScript
import { _createAlertBanner, UserError } from "./exceptions"
|
|
|
|
export function addClasses(element: HTMLElement, classes: string[]) {
|
|
for (const entry of classes) {
|
|
element.classList.add(entry);
|
|
}
|
|
}
|
|
|
|
export function removeClasses(element: HTMLElement, classes: string[]) {
|
|
for (const entry of classes) {
|
|
element.classList.remove(entry);
|
|
}
|
|
}
|
|
|
|
export function escape(str: string): string {
|
|
return str.replace(/</g, '<').replace(/>/g, '>');
|
|
}
|
|
|
|
export function htmlDecode(input: string): string | null {
|
|
const doc = new DOMParser().parseFromString(ltrim(escape(input)), 'text/html');
|
|
return doc.documentElement.textContent;
|
|
}
|
|
|
|
export function ltrim(code: string): string {
|
|
const lines = code.split('\n');
|
|
if (lines.length == 0) return code;
|
|
|
|
const lengths = lines
|
|
.filter(line => line.trim().length != 0)
|
|
.map(line => {
|
|
return line.match(/^\s*/)?.pop()?.length;
|
|
});
|
|
|
|
const k = Math.min(...lengths);
|
|
|
|
return k != 0 ? lines.map(line => line.substring(k)).join('\n') : code;
|
|
}
|
|
|
|
let _uniqueIdCounter = 0;
|
|
export function ensureUniqueId(el: HTMLElement) {
|
|
if (el.id === '') el.id = `py-internal-${_uniqueIdCounter++}`;
|
|
}
|
|
|
|
export function showWarning(msg: string, messageType: "text" | "html" = "text"): void {
|
|
_createAlertBanner(msg, "warning", messageType);
|
|
}
|
|
|
|
export function handleFetchError(e: Error, singleFile: string) {
|
|
// XXX: inspecting the error message to understand what happened is very
|
|
// fragile. We need a better solution.
|
|
let errorContent: string;
|
|
if (e.message.includes('Failed to fetch')) {
|
|
errorContent = `<p>PyScript: Access to local files
|
|
(using "Paths:" in <py-config>)
|
|
is not available when directly opening a HTML file;
|
|
you must use a webserver to serve the additional files.
|
|
See <a style="text-decoration: underline;" href="https://github.com/pyscript/pyscript/issues/257#issuecomment-1119595062">this reference</a>
|
|
on starting a simple webserver with Python.</p>`;
|
|
} else if (e.message.includes('404')) {
|
|
errorContent =
|
|
`<p>PyScript: Loading from file <u>` +
|
|
singleFile +
|
|
`</u> failed with error 404 (File not Found). Are your filename and path are correct?</p>`;
|
|
} else {
|
|
errorContent = `<p>PyScript encountered an error while loading from file: ${e.message} </p>`;
|
|
}
|
|
throw new UserError(errorContent, "html");
|
|
}
|
|
|
|
export function readTextFromPath(path: string) {
|
|
const request = new XMLHttpRequest();
|
|
request.open('GET', path, false);
|
|
request.send();
|
|
const returnValue = request.responseText;
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
export function inJest(): boolean {
|
|
return typeof process === 'object' && process.env.JEST_WORKER_ID !== undefined;
|
|
}
|
|
|
|
export function globalExport(name: string, obj: object) {
|
|
// attach the given object to the global object, so that it is globally
|
|
// visible everywhere. Should be used very sparingly!
|
|
|
|
globalThis[name] = obj;
|
|
}
|
|
|
|
export function getAttribute(el: Element, attr: string): string | null {
|
|
if (el.hasAttribute(attr)) {
|
|
const value = el.getAttribute(attr);
|
|
if (value) {
|
|
return value;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function joinPaths(parts: string[], separator = '/') {
|
|
const res = parts.map(function(part) { return part.trim().replace(/(^[/]*|[/]*$)/g, ''); }).filter(p => p!== "").join(separator || '/');
|
|
if (parts[0].startsWith('/'))
|
|
{
|
|
return '/'+res;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
export function createDeprecationWarning(msg: string, elementName: string): void {
|
|
const banners = document.getElementsByClassName('alert-banner py-warning');
|
|
let bannerCount = 0;
|
|
for (const banner of banners) {
|
|
if (banner.innerHTML.includes(elementName)) {
|
|
bannerCount++;
|
|
}
|
|
}
|
|
if (bannerCount == 0) {
|
|
_createAlertBanner(msg, "warning");
|
|
}
|
|
}
|