Skip to content

Commit

Permalink
Load scripts by URL query
Browse files Browse the repository at this point in the history
  • Loading branch information
graphemecluster committed Oct 4, 2024
1 parent e3c31fe commit 28c9878
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 2 deletions.
62 changes: 61 additions & 1 deletion src/Components/SchemaEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import actions from "../actions";
import Swal from "../Classes/SwalReact";
import { codeFontFamily, invalidCharsRegex, noop } from "../consts";
import "../editor/setup";
import { memoize, normalizeFileName, notifyError } from "../utils";
import { memoize, normalizeFileName, notifyError, showLoadingDialog } from "../utils";

import type { UseMainState, ReactNode } from "../consts";
import type { MouseEvent, MutableRefObject } from "react";
Expand Down Expand Up @@ -281,6 +281,66 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH
[schemas, setState, getDefaultFileNameWithSchemaNames],
);

useEffect(() => {
async function fetchQueryFiles() {
const query = new URLSearchParams(location.search);
history.replaceState(null, document.title, location.pathname); // Remove query
const hrefs = query.getAll("script");
if (!hrefs.length) return;
const abortController = new AbortController();
const { signal } = abortController;
showLoadingDialog("正在載入檔案,請稍候……", abortController);
const names = query.getAll("name");
let i = 0;
const fetchResults = await Promise.allSettled(
hrefs.map(async href => {
// Adds a protocol if the input seems to lack one
// This also prevents `example.com:` from being treated as a protocol if the input is `example.com:8080`
const url = new URL(/^[a-z]+:/i.test(href) ? href : `https://${href}`);
const name =
i < names.length
? names[i++] // Use user-specified name
: url.protocol === "data:"
? "" // Let `getDefaultFileName` name it
: /([^/]*)\/*$/.exec(url.pathname)![1]; // Use the last segment of the path as name
if (url.hostname === "github.com") {
url.searchParams.append("raw", "true"); // Fetch raw file content for GitHub files
} else if (url.hostname === "gist.github.com") {
url.pathname += "/raw"; // Fetch raw file content for GitHub gists
}
const response = await fetch(url, {
headers: {
Accept: "text/javascript, text/plain", // githubusercontent.com always responses with `Content-Type: text/plain`
},
cache: "no-cache",
signal,
});
const blob = await response.blob();
return new File([blob], name);
}),
);
const files: File[] = [];
const errors: unknown[] = [];
for (const result of fetchResults) {
if (result.status === "fulfilled") {
files.push(result.value);
} else {
errors.push(result.reason);
}
}
await addFilesToSchema(files);
Swal.close();
if (!signal.aborted) {
if (errors.length > 1) {
notifyError(`${errors.length} 個檔案無法載入`, new AggregateError(errors));
} else if (errors.length === 1) {
notifyError(fetchResults.length === 1 ? "無法載入檔案" : "1 個檔案無法載入", errors[0]);
}
}
}
fetchQueryFiles();
}, [addFilesToSchema]);

const deleteSchema = useCallback(
async (name: string) => {
if (
Expand Down
29 changes: 29 additions & 0 deletions src/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
import { css as stylesheet } from "@emotion/css";

import Swal from "./Classes/SwalReact";
import Spinner from "./Components/Spinner";

import type { SweetAlertOptions } from "sweetalert2";

const loadingModal = stylesheet`
display: flex !important;
flex-direction: column;
align-items: center;
gap: 2rem;
margin: 1rem;
overflow: unset;
`;

export function showLoadingDialog(msg: string, abortController: AbortController) {
Swal.fire({
title: "載入中",
html: (
<>
<div>{msg}</div>
<Spinner />
</>
),
customClass: {
htmlContainer: loadingModal,
},
allowOutsideClick: false,
showConfirmButton: false,
showCancelButton: true,
cancelButtonText: "取消",
}).then(result => result.dismiss === Swal.DismissReason.cancel && abortController.abort());
}

const errorModal = stylesheet`
width: 60vw;
display: block !important;
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ES2020", "ES2022.Error"],
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"module": "ESNext",
"moduleResolution": "Bundler",
"moduleDetection": "force",
Expand Down
1 change: 1 addition & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function makeConfig(assetLocation = base) {
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
},
build: {
target: "esnext",
chunkSizeWarningLimit: 8192,
outDir: "build",
},
Expand Down

0 comments on commit 28c9878

Please sign in to comment.