gwchq-textjam 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +288 -201
- package/package.json +5 -9
package/dist/index.js
CHANGED
|
@@ -368644,7 +368644,7 @@ const editorListener_1 = __webpack_require__(41824);
|
|
|
368644
368644
|
const Loading_1 = __importDefault(__webpack_require__(34466));
|
|
368645
368645
|
const LeaveGuardController_1 = __webpack_require__(65240);
|
|
368646
368646
|
(0, editorListener_1.registerEditorListeners)();
|
|
368647
|
-
const TextJamEditor = ({ onLogoutClick = () => { }, onViewProfileClick = () => { }, onHomeClick = () => { }, saveProject, isSaving, projectContent = null, template, shareLinks = null, navigationGuardCoordinator, ...componentProps }) => {
|
|
368647
|
+
const TextJamEditor = ({ onLogoutClick = () => { }, onViewProfileClick = () => { }, onHomeClick = () => { }, saveProject, isSaving, projectContent = null, starterCodeContent = null, template, shareLinks = null, navigationGuardCoordinator, ...componentProps }) => {
|
|
368648
368648
|
// Default props that match the previous web-component defaults
|
|
368649
368649
|
const defaultProps = {
|
|
368650
368650
|
sidebarOptions: [
|
|
@@ -368665,6 +368665,7 @@ const TextJamEditor = ({ onLogoutClick = () => { }, onViewProfileClick = () => {
|
|
|
368665
368665
|
saveProject,
|
|
368666
368666
|
isSaving,
|
|
368667
368667
|
projectContent,
|
|
368668
|
+
starterCodeContent,
|
|
368668
368669
|
template,
|
|
368669
368670
|
shareLinks,
|
|
368670
368671
|
};
|
|
@@ -369196,6 +369197,7 @@ const node_html_parser_1 = __webpack_require__(36192);
|
|
|
369196
369197
|
const classnames_1 = __importDefault(__webpack_require__(46942));
|
|
369197
369198
|
const react_router_dom_1 = __webpack_require__(92648);
|
|
369198
369199
|
const EditorSlice_1 = __webpack_require__(68512);
|
|
369200
|
+
const externalLinkHelper_1 = __webpack_require__(31615);
|
|
369199
369201
|
const open_in_new_tab_svg_1 = __importDefault(__webpack_require__(86936));
|
|
369200
369202
|
const stores_1 = __webpack_require__(32132);
|
|
369201
369203
|
const ProjectTypes_1 = __webpack_require__(27130);
|
|
@@ -369206,7 +369208,6 @@ const preview_svg_1 = __importDefault(__webpack_require__(80417));
|
|
|
369206
369208
|
const OutputTabPanel_1 = __webpack_require__(25931);
|
|
369207
369209
|
const styles_module_scss_1 = __importDefault(__webpack_require__(12914));
|
|
369208
369210
|
const helpers_1 = __webpack_require__(1108);
|
|
369209
|
-
const projectPath_1 = __webpack_require__(95506);
|
|
369210
369211
|
const fileParsers_1 = __webpack_require__(26683);
|
|
369211
369212
|
const scripts_1 = __webpack_require__(57621);
|
|
369212
369213
|
const Errors_1 = __webpack_require__(20339);
|
|
@@ -369222,8 +369223,6 @@ const getConsoleKey = (message) => JSON.stringify({
|
|
|
369222
369223
|
method: message.method,
|
|
369223
369224
|
data: message.data,
|
|
369224
369225
|
});
|
|
369225
|
-
// A standalone preview view is flagged by `?preview=1` in the URL.
|
|
369226
|
-
const isPreviewSearch = (params) => params.get("preview") === "1";
|
|
369227
369226
|
function HtmlRunner() {
|
|
369228
369227
|
const [consoleLogs, setConsoleLogs] = (0, react_1.useState)([]);
|
|
369229
369228
|
const project = (0, stores_1.useAppSelector)((state) => state.editor.project);
|
|
@@ -369236,18 +369235,9 @@ function HtmlRunner() {
|
|
|
369236
369235
|
const isPreviewMode = (0, stores_1.useAppSelector)((state) => state.editor.isOutputOnly);
|
|
369237
369236
|
const dispatch = (0, react_redux_1.useDispatch)();
|
|
369238
369237
|
const output = (0, react_1.useRef)(null);
|
|
369239
|
-
const [searchParams] = (0, react_router_dom_1.useSearchParams)();
|
|
369238
|
+
const [searchParams, setSearchParams] = (0, react_router_dom_1.useSearchParams)();
|
|
369240
369239
|
// Using BroadcastChannel to communicate between the main app and the preview tab
|
|
369241
369240
|
const broadcastChannel = (0, react_1.useRef)(null);
|
|
369242
|
-
const shouldUseBrowserHistoryRef = (0, react_1.useRef)(false);
|
|
369243
|
-
const currentPageParam = searchParams.get("page");
|
|
369244
|
-
const isPreviewUrl = isPreviewSearch(searchParams);
|
|
369245
|
-
// In the standalone preview tab (and any ?preview=1 URL) the browser's
|
|
369246
|
-
// back/forward/refresh buttons must drive page navigation.
|
|
369247
|
-
const shouldUseBrowserHistory = isPreviewMode || isPreviewUrl;
|
|
369248
|
-
(0, react_1.useEffect)(() => {
|
|
369249
|
-
shouldUseBrowserHistoryRef.current = shouldUseBrowserHistory;
|
|
369250
|
-
}, [shouldUseBrowserHistory]);
|
|
369251
369241
|
(0, react_1.useEffect)(() => {
|
|
369252
369242
|
broadcastChannel.current = new BroadcastChannel(BROADCAST_CHANNEL);
|
|
369253
369243
|
return () => {
|
|
@@ -369267,58 +369257,18 @@ function HtmlRunner() {
|
|
|
369267
369257
|
defaultPreviewFilePath = page;
|
|
369268
369258
|
}
|
|
369269
369259
|
const [runningFilePath, setRunningFilePath] = (0, react_1.useState)(defaultPreviewFilePath);
|
|
369270
|
-
const writePreviewUrlToHistory = (path, replace = false) => {
|
|
369271
|
-
const normalizedPath = (0, projectPath_1.normalizePath)(path);
|
|
369272
|
-
const url = new URL(window.location.href);
|
|
369273
|
-
if (url.searchParams.get("page") === normalizedPath) {
|
|
369274
|
-
return false;
|
|
369275
|
-
}
|
|
369276
|
-
url.searchParams.set("preview", "1");
|
|
369277
|
-
url.searchParams.set("page", normalizedPath);
|
|
369278
|
-
if (replace) {
|
|
369279
|
-
window.history.replaceState({ __textJamPreview: true, page: normalizedPath }, "", url.toString());
|
|
369280
|
-
}
|
|
369281
|
-
else {
|
|
369282
|
-
window.history.pushState({ __textJamPreview: true, page: normalizedPath }, "", url.toString());
|
|
369283
|
-
}
|
|
369284
|
-
return true;
|
|
369285
|
-
};
|
|
369286
|
-
// Sync the initial preview page into the URL and kick off the first run.
|
|
369287
369260
|
(0, react_1.useEffect)(() => {
|
|
369288
|
-
if (
|
|
369289
|
-
return;
|
|
369290
|
-
const url = new URL(window.location.href);
|
|
369291
|
-
const pageFromUrl = url.searchParams.get("page");
|
|
369292
|
-
const initialPage = (0, projectPath_1.normalizePath)(pageFromUrl ?? page ?? helpers_1.DEFAULT_ENTRY_FILE_PATH);
|
|
369293
|
-
if (!pageFromUrl) {
|
|
369294
|
-
writePreviewUrlToHistory(initialPage, true);
|
|
369295
|
-
}
|
|
369296
|
-
else {
|
|
369297
|
-
const normalizedUrl = new URL(window.location.href);
|
|
369298
|
-
normalizedUrl.searchParams.set("page", initialPage);
|
|
369299
|
-
window.history.replaceState({ __textJamPreview: true, page: initialPage }, "", normalizedUrl.toString());
|
|
369300
|
-
}
|
|
369301
|
-
dispatch((0, EditorSlice_1.setPage)(initialPage));
|
|
369302
|
-
dispatch((0, EditorSlice_1.triggerCodeRun)());
|
|
369303
|
-
}, [shouldUseBrowserHistory]);
|
|
369304
|
-
// Browser back/forward: re-run the page encoded in the URL.
|
|
369305
|
-
(0, react_1.useEffect)(() => {
|
|
369306
|
-
if (!shouldUseBrowserHistory)
|
|
369307
|
-
return;
|
|
369308
|
-
const handlePopState = () => {
|
|
369309
|
-
const url = new URL(window.location.href);
|
|
369310
|
-
const pageFromUrl = url.searchParams.get("page");
|
|
369311
|
-
if (!pageFromUrl)
|
|
369312
|
-
return;
|
|
369313
|
-
const normalizedPage = (0, projectPath_1.normalizePath)(pageFromUrl);
|
|
369314
|
-
dispatch((0, EditorSlice_1.setPage)(normalizedPage));
|
|
369261
|
+
if (isPreviewMode) {
|
|
369315
369262
|
dispatch((0, EditorSlice_1.triggerCodeRun)());
|
|
369316
|
-
|
|
369317
|
-
|
|
369318
|
-
|
|
369319
|
-
|
|
369320
|
-
|
|
369321
|
-
|
|
369263
|
+
if (page) {
|
|
369264
|
+
setSearchParams((prevParams) => {
|
|
369265
|
+
const updatedParams = new URLSearchParams(prevParams);
|
|
369266
|
+
updatedParams.set("page", page);
|
|
369267
|
+
return updatedParams;
|
|
369268
|
+
}, { replace: true });
|
|
369269
|
+
}
|
|
369270
|
+
}
|
|
369271
|
+
}, [isPreviewMode, page, setSearchParams]);
|
|
369322
369272
|
(0, react_1.useEffect)(() => {
|
|
369323
369273
|
if (isPreviewMode) {
|
|
369324
369274
|
const handleMessage = (event) => {
|
|
@@ -369333,29 +369283,29 @@ function HtmlRunner() {
|
|
|
369333
369283
|
};
|
|
369334
369284
|
}
|
|
369335
369285
|
}, [isPreviewMode]);
|
|
369336
|
-
|
|
369337
|
-
|
|
369338
|
-
|
|
369339
|
-
|
|
369340
|
-
|
|
369341
|
-
|
|
369342
|
-
|
|
369343
|
-
|
|
369344
|
-
|
|
369345
|
-
|
|
369346
|
-
|
|
369347
|
-
|
|
369348
|
-
|
|
369349
|
-
|
|
369350
|
-
|
|
369351
|
-
|
|
369352
|
-
|
|
369353
|
-
|
|
369354
|
-
|
|
369355
|
-
}
|
|
369286
|
+
const showModal = () => {
|
|
369287
|
+
dispatch((0, EditorSlice_1.showErrorModal)());
|
|
369288
|
+
eventListener();
|
|
369289
|
+
};
|
|
369290
|
+
const { externalLink, setExternalLink, handleAllowedExternalLink, handleRegularExternalLink, handleExternalLinkError, } = (0, externalLinkHelper_1.useExternalLinkState)(showModal);
|
|
369291
|
+
const eventListener = () => {
|
|
369292
|
+
window.addEventListener("message", (event) => {
|
|
369293
|
+
if (typeof event.data?.msg === "string") {
|
|
369294
|
+
if (event.data?.msg === "ERROR: External link") {
|
|
369295
|
+
handleExternalLinkError();
|
|
369296
|
+
}
|
|
369297
|
+
else if (event.data?.msg === "Allowed external link") {
|
|
369298
|
+
handleAllowedExternalLink(event.data.payload.linkTo);
|
|
369299
|
+
}
|
|
369300
|
+
else {
|
|
369301
|
+
handleRegularExternalLink(event.data.payload.linkTo);
|
|
369302
|
+
}
|
|
369303
|
+
}
|
|
369304
|
+
});
|
|
369305
|
+
};
|
|
369356
369306
|
const iframeReload = () => {
|
|
369357
369307
|
const iframe = output.current?.contentDocument;
|
|
369358
|
-
const filePath = (0, helpers_1.getFilenameFromIFrame)(iframe);
|
|
369308
|
+
const filePath = (0, helpers_1.getFilenameFromIFrame)(iframe) ?? externalLink;
|
|
369359
369309
|
if (runningFilePath !== filePath) {
|
|
369360
369310
|
setRunningFilePath(filePath);
|
|
369361
369311
|
}
|
|
@@ -369365,11 +369315,9 @@ function HtmlRunner() {
|
|
|
369365
369315
|
linkElement.addEventListener("click", (e) => {
|
|
369366
369316
|
const href = linkElement.getAttribute("href");
|
|
369367
369317
|
const target = linkElement.getAttribute("target");
|
|
369368
|
-
|
|
369369
|
-
return;
|
|
369370
|
-
// block in-iframe navigation for internal html links with target="_blank"
|
|
369318
|
+
// block in-iframe navigation for links with target="_blank" and .html href
|
|
369371
369319
|
// and open them in a preview tab
|
|
369372
|
-
if (href?.includes(".html")) {
|
|
369320
|
+
if (target === "_blank" && href?.includes(".html")) {
|
|
369373
369321
|
e.preventDefault();
|
|
369374
369322
|
e.stopImmediatePropagation();
|
|
369375
369323
|
openPreview(`/${href}`);
|
|
@@ -369377,8 +369325,10 @@ function HtmlRunner() {
|
|
|
369377
369325
|
}, true);
|
|
369378
369326
|
});
|
|
369379
369327
|
}
|
|
369328
|
+
setExternalLink(null);
|
|
369380
369329
|
};
|
|
369381
369330
|
(0, react_1.useEffect)(() => {
|
|
369331
|
+
eventListener();
|
|
369382
369332
|
dispatch((0, EditorSlice_1.loadingRunner)(EditorTypes_1.RunnerType.HTML));
|
|
369383
369333
|
dispatch((0, EditorSlice_1.setLoadedRunner)(EditorTypes_1.RunnerType.HTML));
|
|
369384
369334
|
}, []);
|
|
@@ -369392,45 +369342,50 @@ function HtmlRunner() {
|
|
|
369392
369342
|
}
|
|
369393
369343
|
}
|
|
369394
369344
|
}, [codeRunTriggered, page, isPreviewMode]);
|
|
369345
|
+
const currentPageParam = searchParams.get("page");
|
|
369395
369346
|
(0, react_1.useEffect)(() => {
|
|
369396
|
-
if (
|
|
369397
|
-
|
|
369398
|
-
|
|
369399
|
-
|
|
369400
|
-
if (shouldUseBrowserHistory)
|
|
369401
|
-
return;
|
|
369402
|
-
dispatch((0, EditorSlice_1.setPage)(currentPageParam));
|
|
369403
|
-
}, [currentPageParam, shouldUseBrowserHistory, dispatch]);
|
|
369347
|
+
if (currentPageParam) {
|
|
369348
|
+
dispatch((0, EditorSlice_1.setPage)(currentPageParam));
|
|
369349
|
+
}
|
|
369350
|
+
}, [currentPageParam, dispatch]);
|
|
369404
369351
|
const runCode = async () => {
|
|
369405
369352
|
setConsoleLogs([]);
|
|
369406
369353
|
const fileToRun = page ?? defaultPreviewFilePath;
|
|
369407
369354
|
setRunningFilePath(fileToRun);
|
|
369408
369355
|
dispatch((0, EditorSlice_1.setError)(null));
|
|
369409
|
-
|
|
369410
|
-
|
|
369411
|
-
|
|
369412
|
-
|
|
369413
|
-
|
|
369414
|
-
|
|
369415
|
-
|
|
369416
|
-
|
|
369417
|
-
|
|
369418
|
-
|
|
369419
|
-
|
|
369420
|
-
|
|
369421
|
-
|
|
369422
|
-
|
|
369423
|
-
|
|
369424
|
-
|
|
369425
|
-
|
|
369426
|
-
|
|
369427
|
-
|
|
369428
|
-
|
|
369429
|
-
|
|
369430
|
-
|
|
369431
|
-
output.current
|
|
369356
|
+
if (!externalLink) {
|
|
369357
|
+
const entryPoint = (0, helpers_1.getEntryPoint)(projectComponents, fileToRun);
|
|
369358
|
+
if (!entryPoint) {
|
|
369359
|
+
dispatch((0, EditorSlice_1.setError)(fileToRun === helpers_1.DEFAULT_ENTRY_FILE_PATH && !isPreviewMode
|
|
369360
|
+
? {
|
|
369361
|
+
type: Errors_1.ErrorType.ENTRY_FILE_NOT_FOUND,
|
|
369362
|
+
details: {
|
|
369363
|
+
fileName: helpers_1.DEFAULT_ENTRY_FILE_NAME,
|
|
369364
|
+
},
|
|
369365
|
+
}
|
|
369366
|
+
: {
|
|
369367
|
+
type: Errors_1.ErrorType.PAGE_NOT_FOUND,
|
|
369368
|
+
}));
|
|
369369
|
+
dispatch((0, EditorSlice_1.codeRunHandled)());
|
|
369370
|
+
return;
|
|
369371
|
+
}
|
|
369372
|
+
const indexPage = (0, node_html_parser_1.parse)(entryPoint.content);
|
|
369373
|
+
const body = indexPage.querySelector("body") || indexPage;
|
|
369374
|
+
const htmlRoot = indexPage.querySelector("html") ?? indexPage;
|
|
369375
|
+
body.insertAdjacentHTML("afterbegin", scripts_1.disableLocalStorageScript);
|
|
369376
|
+
htmlRoot.insertAdjacentHTML("afterbegin", scripts_1.consoleOverrideScript);
|
|
369377
|
+
const { content } = await (0, fileParsers_1.resolveAndRewriteHtmlImports)(indexPage.toString(), projectComponents, entryPoint.path, page ?? entryPoint.path);
|
|
369378
|
+
if (output.current) {
|
|
369379
|
+
output.current.srcdoc = content;
|
|
369380
|
+
}
|
|
369381
|
+
if (codeRunTriggered) {
|
|
369382
|
+
dispatch((0, EditorSlice_1.codeRunHandled)());
|
|
369383
|
+
}
|
|
369432
369384
|
}
|
|
369433
|
-
|
|
369385
|
+
else {
|
|
369386
|
+
if (output.current) {
|
|
369387
|
+
output.current.src = externalLink;
|
|
369388
|
+
}
|
|
369434
369389
|
dispatch((0, EditorSlice_1.codeRunHandled)());
|
|
369435
369390
|
}
|
|
369436
369391
|
};
|
|
@@ -369470,7 +369425,7 @@ function HtmlRunner() {
|
|
|
369470
369425
|
const iframeClasses = (0, classnames_1.default)(styles_module_scss_1.default.iframe, {
|
|
369471
369426
|
[styles_module_scss_1.default.codeHasBeenRun]: codeHasBeenRun,
|
|
369472
369427
|
});
|
|
369473
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.htmlrunnerContainer, children: [(0, jsx_runtime_1.jsx)(OutputTabPanel_1.OutputTabPanel, { title: "Preview", icon: preview_svg_1.default, readOnly: readOnly, extraTabContent: codeHasBeenRun && openInNewTabLink, tabPanelClassName: styles_module_scss_1.default.previewHtml, children: error ? ((0, jsx_runtime_1.jsx)("div", { className: iframeClasses, children: (0, jsx_runtime_1.jsx)(NotFoundPage_1.NotFoundPage, {}) })) : ((0, jsx_runtime_1.jsx)("iframe", { className: iframeClasses, sandbox: "allow-scripts allow-same-origin allow-modals allow-popups
|
|
369428
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.htmlrunnerContainer, children: [(0, jsx_runtime_1.jsx)(OutputTabPanel_1.OutputTabPanel, { title: "Preview", icon: preview_svg_1.default, readOnly: readOnly, extraTabContent: codeHasBeenRun && openInNewTabLink, tabPanelClassName: styles_module_scss_1.default.previewHtml, children: error ? ((0, jsx_runtime_1.jsx)("div", { className: iframeClasses, children: (0, jsx_runtime_1.jsx)(NotFoundPage_1.NotFoundPage, {}) })) : ((0, jsx_runtime_1.jsx)("iframe", { className: iframeClasses, sandbox: "allow-scripts allow-same-origin allow-modals allow-popups", referrerPolicy: "strict-origin-when-cross-origin", allow: "\r\n accelerometer 'none';\r\n camera 'none';\r\n encrypted-media;\r\n fullscreen;\r\n picture-in-picture;\r\n geolocation 'none';\r\n gyroscope 'none';\r\n magnetometer 'none';\r\n microphone 'none';\r\n midi 'none';\r\n payment 'none';\r\n usb 'none';\r\n ", id: "output-frame", title: "HTML Output Preview", ref: output, onLoad: iframeReload })) }), !isPreviewMode && ((0, jsx_runtime_1.jsx)(ResizableWithHandle_1.default, { "data-testid": "proj-console-container", handleDirection: "top", defaultHeight: "50%", className: styles_module_scss_1.default.resizeContainer, handleClassName: styles_module_scss_1.default.resizeHandleContainer, children: (0, jsx_runtime_1.jsx)(OutputTabPanel_1.OutputTabPanel, { title: "Console", icon: console_svg_1.default, readOnly: readOnly, children: (0, jsx_runtime_1.jsx)(HtmlConsole_1.default, { consoleLogs: consoleLogs }) }) }))] }));
|
|
369474
369429
|
}
|
|
369475
369430
|
exports["default"] = HtmlRunner;
|
|
369476
369431
|
|
|
@@ -369549,7 +369504,6 @@ const node_html_parser_1 = __webpack_require__(36192);
|
|
|
369549
369504
|
const ProjectTypes_1 = __webpack_require__(27130);
|
|
369550
369505
|
const binaryStore_1 = __webpack_require__(5060);
|
|
369551
369506
|
const projectHelpers_1 = __webpack_require__(2610);
|
|
369552
|
-
const helpers_1 = __webpack_require__(1108);
|
|
369553
369507
|
/** Normalizes CSS paths
|
|
369554
369508
|
* Treats paths without leading / or ./ or ../ as relative to current file
|
|
369555
369509
|
* E.g. 'image.png' will be treated as './image.png'
|
|
@@ -369603,7 +369557,9 @@ const getMimeType = (filePath, fallback = "application/octet-stream") => {
|
|
|
369603
369557
|
};
|
|
369604
369558
|
/** Check if a URL is external, blob, or data */
|
|
369605
369559
|
const isExternalOrDataUrl = (url) => {
|
|
369606
|
-
return (url.startsWith("blob:") ||
|
|
369560
|
+
return (url.startsWith("blob:") ||
|
|
369561
|
+
/^(https?:)?\/\//.test(url) ||
|
|
369562
|
+
url.startsWith("data:"));
|
|
369607
369563
|
};
|
|
369608
369564
|
async function replaceAsync(input, regex, replacer) {
|
|
369609
369565
|
let result = "";
|
|
@@ -369780,12 +369736,7 @@ async function rewriteSources(indexPage, components, baseFilePath, propName, blo
|
|
|
369780
369736
|
const nodes = indexPage.querySelectorAll(`[${propName}]`);
|
|
369781
369737
|
for (const node of nodes) {
|
|
369782
369738
|
const raw = node.getAttribute(propName);
|
|
369783
|
-
if (!raw)
|
|
369784
|
-
continue;
|
|
369785
|
-
// For external links with target="_blank", add noopener and noreferrer for security
|
|
369786
|
-
if ((0, helpers_1.isExternalUrl)(raw) && node.getAttribute("target") === "_blank")
|
|
369787
|
-
node.setAttribute("rel", "noopener noreferrer");
|
|
369788
|
-
if (isExternalOrDataUrl(raw))
|
|
369739
|
+
if (!raw || isExternalOrDataUrl(raw))
|
|
369789
369740
|
continue;
|
|
369790
369741
|
if ((0, projectHelpers_1.parseFileName)(raw).extension === ProjectTypes_1.ProjectFileExtension.HTML &&
|
|
369791
369742
|
propName === "href") {
|
|
@@ -369838,7 +369789,7 @@ async function resolveAndRewriteHtmlImports(html, projectComponents, baseFilePat
|
|
|
369838
369789
|
|
|
369839
369790
|
|
|
369840
369791
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
369841
|
-
exports.
|
|
369792
|
+
exports.getFilenameFromIFrame = exports.getEntryPoint = exports.DEFAULT_ENTRY_FILE_PATH = exports.DEFAULT_ENTRY_FILE_NAME = void 0;
|
|
369842
369793
|
const ProjectTypes_1 = __webpack_require__(27130);
|
|
369843
369794
|
exports.DEFAULT_ENTRY_FILE_NAME = "index.html";
|
|
369844
369795
|
exports.DEFAULT_ENTRY_FILE_PATH = `/${exports.DEFAULT_ENTRY_FILE_NAME}`;
|
|
@@ -369849,10 +369800,6 @@ const getEntryPoint = (components, filePath) => {
|
|
|
369849
369800
|
exports.getEntryPoint = getEntryPoint;
|
|
369850
369801
|
const getFilenameFromIFrame = (iframe) => iframe?.querySelector("meta[filename]")?.getAttribute("filename") ?? null;
|
|
369851
369802
|
exports.getFilenameFromIFrame = getFilenameFromIFrame;
|
|
369852
|
-
const isExternalUrl = (url) => {
|
|
369853
|
-
return /^(https?:)?\/\//.test(url);
|
|
369854
|
-
};
|
|
369855
|
-
exports.isExternalUrl = isExternalUrl;
|
|
369856
369803
|
|
|
369857
369804
|
|
|
369858
369805
|
/***/ }),
|
|
@@ -373451,6 +373398,7 @@ const UserSlice_1 = __webpack_require__(86910);
|
|
|
373451
373398
|
const WebComponentProject_1 = __importDefault(__webpack_require__(42086));
|
|
373452
373399
|
const react_i18next_1 = __webpack_require__(56576);
|
|
373453
373400
|
const useProject_1 = __webpack_require__(54095);
|
|
373401
|
+
const useProjectStarterCode_1 = __webpack_require__(65529);
|
|
373454
373402
|
const useProjectPersistence_1 = __webpack_require__(72300);
|
|
373455
373403
|
const useProjectRemix_1 = __webpack_require__(35602);
|
|
373456
373404
|
const useProjectTabSync_1 = __webpack_require__(17299);
|
|
@@ -373467,7 +373415,7 @@ const stores_1 = __webpack_require__(32132);
|
|
|
373467
373415
|
const SaveBeforeLeave_1 = __webpack_require__(47318);
|
|
373468
373416
|
const selectors_1 = __webpack_require__(43551);
|
|
373469
373417
|
const WebComponentLoader = (props) => {
|
|
373470
|
-
const { locale = "en", projectNameEditable = true, readOnly = false, sidebarOptions = [], project: projectData, saveProject, isSaving, loadProjectContent, projectContent = null, isLoading = false, packageApiUrl, user, isCodeVisible = true, isSharedProject = false, shareLinks, isContentLoaded = null, isSaveSuccess = null, loadTemplateProjectData, isTemplateDataLoaded = false, } = props;
|
|
373418
|
+
const { locale = "en", projectNameEditable = true, readOnly = false, sidebarOptions = [], project: projectData, saveProject, isSaving, loadProjectContent, projectContent = null, starterCodeContent = null, isLoading = false, packageApiUrl, user, isCodeVisible = true, isSharedProject = false, shareLinks, isContentLoaded = null, isSaveSuccess = null, loadTemplateProjectData, isTemplateDataLoaded = false, } = props;
|
|
373471
373419
|
const dispatch = (0, react_redux_1.useDispatch)();
|
|
373472
373420
|
const { t } = (0, react_i18next_1.useTranslation)();
|
|
373473
373421
|
const [searchParams] = (0, react_router_dom_1.useSearchParams)();
|
|
@@ -373528,10 +373476,16 @@ const WebComponentLoader = (props) => {
|
|
|
373528
373476
|
isLoading,
|
|
373529
373477
|
isContentLoaded,
|
|
373530
373478
|
projectContent,
|
|
373479
|
+
starterCodeContent,
|
|
373531
373480
|
loadProjectContent,
|
|
373532
373481
|
loadTemplateProjectData,
|
|
373533
373482
|
isTemplateDataLoaded,
|
|
373534
373483
|
});
|
|
373484
|
+
(0, useProjectStarterCode_1.useProjectStarterCode)({
|
|
373485
|
+
projectData,
|
|
373486
|
+
starterCodeContent,
|
|
373487
|
+
isLoading,
|
|
373488
|
+
});
|
|
373535
373489
|
(0, useProjectRemix_1.useProjectRemix)({
|
|
373536
373490
|
projectData,
|
|
373537
373491
|
saveProject,
|
|
@@ -374225,10 +374179,10 @@ const getUniqueNameFromItem = (childrenNames, baseName, extension = "") => {
|
|
|
374225
374179
|
// if there is a conflict, use canonical lowercase for the duplicate
|
|
374226
374180
|
const normalizedBaseName = baseName.toLowerCase();
|
|
374227
374181
|
let counter = 1;
|
|
374228
|
-
let candidate = `${normalizedBaseName}
|
|
374182
|
+
let candidate = `${normalizedBaseName}(${counter})`;
|
|
374229
374183
|
while (existingNamesLower.has(fullName(candidate).toLowerCase())) {
|
|
374230
374184
|
counter++;
|
|
374231
|
-
candidate = `${normalizedBaseName}
|
|
374185
|
+
candidate = `${normalizedBaseName}(${counter})`;
|
|
374232
374186
|
}
|
|
374233
374187
|
return candidate;
|
|
374234
374188
|
};
|
|
@@ -374382,7 +374336,7 @@ const sendToast_1 = __webpack_require__(50068);
|
|
|
374382
374336
|
const useUnsavedDraftResolution_1 = __webpack_require__(61171);
|
|
374383
374337
|
const projectSnapshotHelpers_1 = __webpack_require__(22390);
|
|
374384
374338
|
const isFinalLoadingState = (state) => state === types_1.LoadingState.SUCCESS || state === types_1.LoadingState.FAILED;
|
|
374385
|
-
const useProject = ({ projectData, projectContent = null, isContentLoaded = null, isLoading = false, loadProjectContent, loadTemplateProjectData, isTemplateDataLoaded, }) => {
|
|
374339
|
+
const useProject = ({ projectData, projectContent = null, starterCodeContent = null, isContentLoaded = null, isLoading = false, loadProjectContent, loadTemplateProjectData, isTemplateDataLoaded, }) => {
|
|
374386
374340
|
const project = (0, stores_1.useAppSelector)((state) => state.editor.project);
|
|
374387
374341
|
const loadingState = (0, stores_1.useAppSelector)((state) => state.editor.loading);
|
|
374388
374342
|
const savingState = (0, stores_1.useAppSelector)((state) => state.editor.saving);
|
|
@@ -374504,6 +374458,10 @@ const useProject = ({ projectData, projectContent = null, isContentLoaded = null
|
|
|
374504
374458
|
}
|
|
374505
374459
|
// if no specific commitId provided and not preview, set default data
|
|
374506
374460
|
if (!projectData?.commitId) {
|
|
374461
|
+
// prefer the starter-code archive when one is provided
|
|
374462
|
+
if (starterCodeContent) {
|
|
374463
|
+
return;
|
|
374464
|
+
}
|
|
374507
374465
|
if (!loadTemplateProjectData || isTemplateDataLoaded) {
|
|
374508
374466
|
setProjectDataFromTemplate(projectData);
|
|
374509
374467
|
}
|
|
@@ -374537,6 +374495,7 @@ const useProject = ({ projectData, projectContent = null, isContentLoaded = null
|
|
|
374537
374495
|
project.commitId,
|
|
374538
374496
|
saveTriggered,
|
|
374539
374497
|
savingState,
|
|
374498
|
+
starterCodeContent,
|
|
374540
374499
|
]);
|
|
374541
374500
|
// Load commit data when commitIdLoadTriggered is set
|
|
374542
374501
|
(0, react_1.useEffect)(() => {
|
|
@@ -374999,6 +374958,119 @@ const useProjectRemix = ({ projectData, saveProject, }) => {
|
|
|
374999
374958
|
exports.useProjectRemix = useProjectRemix;
|
|
375000
374959
|
|
|
375001
374960
|
|
|
374961
|
+
/***/ }),
|
|
374962
|
+
|
|
374963
|
+
/***/ 65529:
|
|
374964
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
374965
|
+
|
|
374966
|
+
|
|
374967
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
374968
|
+
exports.useProjectStarterCode = void 0;
|
|
374969
|
+
const react_1 = __webpack_require__(51649);
|
|
374970
|
+
const react_redux_1 = __webpack_require__(14062);
|
|
374971
|
+
const EditorSlice_1 = __webpack_require__(68512);
|
|
374972
|
+
const stores_1 = __webpack_require__(32132);
|
|
374973
|
+
const loadProjectFromZip_1 = __webpack_require__(65404);
|
|
374974
|
+
const types_1 = __webpack_require__(92932);
|
|
374975
|
+
const useIsMounted_1 = __webpack_require__(76314);
|
|
374976
|
+
const useProjectCache_1 = __webpack_require__(69557);
|
|
374977
|
+
const useUnsavedDraftResolution_1 = __webpack_require__(61171);
|
|
374978
|
+
const projectSnapshotHelpers_1 = __webpack_require__(22390);
|
|
374979
|
+
const isFinalLoadingState = (state) => state === types_1.LoadingState.SUCCESS || state === types_1.LoadingState.FAILED;
|
|
374980
|
+
// unpacks a starter-code zip archive and applies it as the initial project
|
|
374981
|
+
const useProjectStarterCode = ({ projectData, starterCodeContent = null, isLoading = false, }) => {
|
|
374982
|
+
const dispatch = (0, react_redux_1.useDispatch)();
|
|
374983
|
+
const isMounted = (0, useIsMounted_1.useIsMounted)();
|
|
374984
|
+
const callIdRef = (0, react_1.useRef)(null);
|
|
374985
|
+
const loadingState = (0, stores_1.useAppSelector)((state) => state.editor.loading);
|
|
374986
|
+
const savingState = (0, stores_1.useAppSelector)((state) => state.editor.saving);
|
|
374987
|
+
const isPreview = (0, stores_1.useAppSelector)((state) => state.editor.isOutputOnly);
|
|
374988
|
+
const commitIdLoadTriggered = (0, stores_1.useAppSelector)((state) => state.editor.commitIdLoadTriggered);
|
|
374989
|
+
const saveTriggered = (0, stores_1.useAppSelector)((state) => state.editor.saveTriggered);
|
|
374990
|
+
const projectFromStore = (0, stores_1.useAppSelector)((state) => state.editor.project);
|
|
374991
|
+
const cacheKey = projectFromStore.identifier ?? projectData?.identifier;
|
|
374992
|
+
const { value: cachedProject, isLoading: isLoadingCache, isLoaded: isCacheLoaded, } = (0, useProjectCache_1.useProjectCache)(cacheKey);
|
|
374993
|
+
// eslint-disable-next-line eqeqeq
|
|
374994
|
+
const isCurrentOutdated = cachedProject?.commitId != projectData?.commitId;
|
|
374995
|
+
const { shouldBypassCachedDraft } = (0, useUnsavedDraftResolution_1.useUnsavedDraftResolution)({
|
|
374996
|
+
projectData,
|
|
374997
|
+
cachedProject,
|
|
374998
|
+
isCurrentOutdated,
|
|
374999
|
+
});
|
|
375000
|
+
(0, react_1.useEffect)(() => {
|
|
375001
|
+
if (!starterCodeContent || !projectData)
|
|
375002
|
+
return;
|
|
375003
|
+
if (isLoading || isLoadingCache)
|
|
375004
|
+
return;
|
|
375005
|
+
if (!isCacheLoaded && cacheKey)
|
|
375006
|
+
return;
|
|
375007
|
+
if (commitIdLoadTriggered)
|
|
375008
|
+
return;
|
|
375009
|
+
if (projectData.commitId)
|
|
375010
|
+
return;
|
|
375011
|
+
if (cachedProject)
|
|
375012
|
+
return;
|
|
375013
|
+
if (isPreview)
|
|
375014
|
+
return;
|
|
375015
|
+
if (saveTriggered || savingState === types_1.SavingState.PROCESS)
|
|
375016
|
+
return;
|
|
375017
|
+
if (isFinalLoadingState(loadingState) && !shouldBypassCachedDraft)
|
|
375018
|
+
return;
|
|
375019
|
+
const callId = Symbol("loadStarterCodeFromZip");
|
|
375020
|
+
callIdRef.current = callId;
|
|
375021
|
+
(0, loadProjectFromZip_1.loadProjectFromZip)({
|
|
375022
|
+
zipBlob: starterCodeContent,
|
|
375023
|
+
identifier: projectData.identifier,
|
|
375024
|
+
})
|
|
375025
|
+
.then((loadedProject) => {
|
|
375026
|
+
if (!isMounted.current)
|
|
375027
|
+
return;
|
|
375028
|
+
if (callIdRef.current !== callId)
|
|
375029
|
+
return;
|
|
375030
|
+
const { commits, ...rest } = projectData;
|
|
375031
|
+
const projectToSet = {
|
|
375032
|
+
...rest,
|
|
375033
|
+
commitId: null,
|
|
375034
|
+
components: loadedProject.components,
|
|
375035
|
+
rootDirId: loadedProject.rootDirId,
|
|
375036
|
+
};
|
|
375037
|
+
dispatch((0, EditorSlice_1.setProject)({
|
|
375038
|
+
...projectToSet,
|
|
375039
|
+
lastSavedSnapshot: (0, projectSnapshotHelpers_1.buildProjectSnapshot)(projectToSet),
|
|
375040
|
+
}));
|
|
375041
|
+
dispatch((0, EditorSlice_1.setCommits)({ commits: commits ?? [] }));
|
|
375042
|
+
})
|
|
375043
|
+
.catch((error) => {
|
|
375044
|
+
if (!isMounted.current)
|
|
375045
|
+
return;
|
|
375046
|
+
if (callIdRef.current !== callId)
|
|
375047
|
+
return;
|
|
375048
|
+
console.error("Error loading starter code from zip:", error);
|
|
375049
|
+
dispatch((0, EditorSlice_1.setLoading)(types_1.LoadingState.FAILED));
|
|
375050
|
+
});
|
|
375051
|
+
// trigger only on data/state changes that affect eligibility
|
|
375052
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
375053
|
+
}, [
|
|
375054
|
+
starterCodeContent,
|
|
375055
|
+
projectData,
|
|
375056
|
+
isLoading,
|
|
375057
|
+
isLoadingCache,
|
|
375058
|
+
isCacheLoaded,
|
|
375059
|
+
cacheKey,
|
|
375060
|
+
cachedProject,
|
|
375061
|
+
commitIdLoadTriggered,
|
|
375062
|
+
isPreview,
|
|
375063
|
+
loadingState,
|
|
375064
|
+
savingState,
|
|
375065
|
+
saveTriggered,
|
|
375066
|
+
shouldBypassCachedDraft,
|
|
375067
|
+
dispatch,
|
|
375068
|
+
isMounted,
|
|
375069
|
+
]);
|
|
375070
|
+
};
|
|
375071
|
+
exports.useProjectStarterCode = useProjectStarterCode;
|
|
375072
|
+
|
|
375073
|
+
|
|
375002
375074
|
/***/ }),
|
|
375003
375075
|
|
|
375004
375076
|
/***/ 17299:
|
|
@@ -375091,6 +375163,7 @@ exports.useUnsavedDraftResolution = void 0;
|
|
|
375091
375163
|
const react_1 = __webpack_require__(51649);
|
|
375092
375164
|
const react_redux_1 = __webpack_require__(14062);
|
|
375093
375165
|
const EditorSlice_1 = __webpack_require__(68512);
|
|
375166
|
+
const stores_1 = __webpack_require__(32132);
|
|
375094
375167
|
const types_1 = __webpack_require__(92932);
|
|
375095
375168
|
const projectSnapshotHelpers_1 = __webpack_require__(22390);
|
|
375096
375169
|
// check if incoming and cached projects are the same draft
|
|
@@ -375127,14 +375200,14 @@ const hasCachedDraftChanges = (cachedProject, incomingProject) => {
|
|
|
375127
375200
|
const useUnsavedDraftResolution = ({ projectData, cachedProject, isCurrentOutdated, }) => {
|
|
375128
375201
|
const dispatch = (0, react_redux_1.useDispatch)();
|
|
375129
375202
|
// flag to ignore cached draft after Start New
|
|
375130
|
-
const
|
|
375203
|
+
const shouldBypassCachedDraft = (0, stores_1.useAppSelector)((state) => state.editor.shouldBypassCachedDraft);
|
|
375131
375204
|
const isSameDraftType = (0, react_1.useMemo)(() => isSameDraftProjectType(projectData, cachedProject), [projectData, cachedProject]);
|
|
375132
375205
|
const hasDraftChanges = (0, react_1.useMemo)(() => hasCachedDraftChanges(cachedProject, projectData), [cachedProject, projectData]);
|
|
375133
375206
|
(0, react_1.useEffect)(() => {
|
|
375134
375207
|
if (projectData?.commitId && shouldBypassCachedDraft) {
|
|
375135
|
-
setShouldBypassCachedDraft(false);
|
|
375208
|
+
dispatch((0, EditorSlice_1.setShouldBypassCachedDraft)(false));
|
|
375136
375209
|
}
|
|
375137
|
-
}, [projectData?.commitId, shouldBypassCachedDraft]);
|
|
375210
|
+
}, [projectData?.commitId, shouldBypassCachedDraft, dispatch]);
|
|
375138
375211
|
// show modal only for matching draft when cache is valid and not bypassed
|
|
375139
375212
|
const shouldShowUnsavedDraftModal = !!cachedProject &&
|
|
375140
375213
|
!isCurrentOutdated &&
|
|
@@ -375146,8 +375219,8 @@ const useUnsavedDraftResolution = ({ projectData, cachedProject, isCurrentOutdat
|
|
|
375146
375219
|
modal: types_1.ModalType.DRAFT_UNSAVED_CHANGES,
|
|
375147
375220
|
args: {
|
|
375148
375221
|
type: types_1.ModalType.DRAFT_UNSAVED_CHANGES,
|
|
375149
|
-
onContinue: () => setShouldBypassCachedDraft(false),
|
|
375150
|
-
onStartNew: () => setShouldBypassCachedDraft(true),
|
|
375222
|
+
onContinue: () => dispatch((0, EditorSlice_1.setShouldBypassCachedDraft)(false)),
|
|
375223
|
+
onStartNew: () => dispatch((0, EditorSlice_1.setShouldBypassCachedDraft)(true)),
|
|
375151
375224
|
},
|
|
375152
375225
|
}));
|
|
375153
375226
|
}, [dispatch]);
|
|
@@ -375169,7 +375242,7 @@ exports.useUnsavedDraftResolution = useUnsavedDraftResolution;
|
|
|
375169
375242
|
var _a;
|
|
375170
375243
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
375171
375244
|
exports.setRemixTriggered = exports.setIsLoadingCommit = exports.setCommitIdLoadTriggered = exports.setShareLinks = exports.setCommits = exports.setSharedStatus = exports.setCodeVisibility = exports.applyComponentsPatch = exports.setSaving = exports.disableTheming = exports.hideSidebar = exports.showSidebar = exports.closeModal = exports.showModal = exports.closeErrorModal = exports.showErrorModal = exports.updateProjectName = exports.setProjectNameDraft = exports.setSaveTriggered = exports.triggerDraw = exports.triggerCodeRun = exports.stopDraw = exports.stopCodeRun = exports.setLoading = exports.setReadOnly = exports.updateProjectIdentifier = exports.updateProjectCommits = exports.updateProjectSnapshot = exports.setProject = exports.setHasShownSavePrompt = exports.setError = exports.setCascadeUpdate = exports.setIsOutputOnly = exports.setAutorunEnabled = exports.setPage = exports.setFocussedFileIndex = exports.addFilePanel = exports.setOpenedFiles = exports.openFile = exports.closeFile = exports.expireJustLoaded = exports.codeRunHandled = exports.resetRunner = exports.setLoadedRunner = exports.loadingRunner = exports.updateProjectComponent = exports.addProjectComponent = exports.resetState = exports.EditorSlice = exports.editorInitialState = void 0;
|
|
375172
|
-
exports.queueBinaryWrites = exports.revertProject = void 0;
|
|
375245
|
+
exports.queueBinaryWrites = exports.revertProject = exports.setShouldBypassCachedDraft = void 0;
|
|
375173
375246
|
const toolkit_1 = __webpack_require__(12069);
|
|
375174
375247
|
const ProjectTypes_1 = __webpack_require__(27130);
|
|
375175
375248
|
const types_1 = __webpack_require__(92932);
|
|
@@ -375218,6 +375291,7 @@ exports.editorInitialState = {
|
|
|
375218
375291
|
shareLinks: null,
|
|
375219
375292
|
remixTriggered: false,
|
|
375220
375293
|
projectNameDraft: null,
|
|
375294
|
+
shouldBypassCachedDraft: false,
|
|
375221
375295
|
};
|
|
375222
375296
|
exports.EditorSlice = (0, toolkit_1.createSlice)({
|
|
375223
375297
|
name: "editor",
|
|
@@ -375500,10 +375574,13 @@ exports.EditorSlice = (0, toolkit_1.createSlice)({
|
|
|
375500
375574
|
setRemixTriggered: (state, action) => {
|
|
375501
375575
|
state.remixTriggered = action.payload;
|
|
375502
375576
|
},
|
|
375577
|
+
setShouldBypassCachedDraft: (state, action) => {
|
|
375578
|
+
state.shouldBypassCachedDraft = action.payload;
|
|
375579
|
+
},
|
|
375503
375580
|
},
|
|
375504
375581
|
});
|
|
375505
375582
|
// Action creators are generated for each case reducer function
|
|
375506
|
-
_a = exports.EditorSlice.actions, exports.resetState = _a.resetState, exports.addProjectComponent = _a.addProjectComponent, exports.updateProjectComponent = _a.updateProjectComponent, exports.loadingRunner = _a.loadingRunner, exports.setLoadedRunner = _a.setLoadedRunner, exports.resetRunner = _a.resetRunner, exports.codeRunHandled = _a.codeRunHandled, exports.expireJustLoaded = _a.expireJustLoaded, exports.closeFile = _a.closeFile, exports.openFile = _a.openFile, exports.setOpenedFiles = _a.setOpenedFiles, exports.addFilePanel = _a.addFilePanel, exports.setFocussedFileIndex = _a.setFocussedFileIndex, exports.setPage = _a.setPage, exports.setAutorunEnabled = _a.setAutorunEnabled, exports.setIsOutputOnly = _a.setIsOutputOnly, exports.setCascadeUpdate = _a.setCascadeUpdate, exports.setError = _a.setError, exports.setHasShownSavePrompt = _a.setHasShownSavePrompt, exports.setProject = _a.setProject, exports.updateProjectSnapshot = _a.updateProjectSnapshot, exports.updateProjectCommits = _a.updateProjectCommits, exports.updateProjectIdentifier = _a.updateProjectIdentifier, exports.setReadOnly = _a.setReadOnly, exports.setLoading = _a.setLoading, exports.stopCodeRun = _a.stopCodeRun, exports.stopDraw = _a.stopDraw, exports.triggerCodeRun = _a.triggerCodeRun, exports.triggerDraw = _a.triggerDraw, exports.setSaveTriggered = _a.setSaveTriggered, exports.setProjectNameDraft = _a.setProjectNameDraft, exports.updateProjectName = _a.updateProjectName, exports.showErrorModal = _a.showErrorModal, exports.closeErrorModal = _a.closeErrorModal, exports.showModal = _a.showModal, exports.closeModal = _a.closeModal, exports.showSidebar = _a.showSidebar, exports.hideSidebar = _a.hideSidebar, exports.disableTheming = _a.disableTheming, exports.setSaving = _a.setSaving, exports.applyComponentsPatch = _a.applyComponentsPatch, exports.setCodeVisibility = _a.setCodeVisibility, exports.setSharedStatus = _a.setSharedStatus, exports.setCommits = _a.setCommits, exports.setShareLinks = _a.setShareLinks, exports.setCommitIdLoadTriggered = _a.setCommitIdLoadTriggered, exports.setIsLoadingCommit = _a.setIsLoadingCommit, exports.setRemixTriggered = _a.setRemixTriggered, exports.revertProject = _a.revertProject;
|
|
375583
|
+
_a = exports.EditorSlice.actions, exports.resetState = _a.resetState, exports.addProjectComponent = _a.addProjectComponent, exports.updateProjectComponent = _a.updateProjectComponent, exports.loadingRunner = _a.loadingRunner, exports.setLoadedRunner = _a.setLoadedRunner, exports.resetRunner = _a.resetRunner, exports.codeRunHandled = _a.codeRunHandled, exports.expireJustLoaded = _a.expireJustLoaded, exports.closeFile = _a.closeFile, exports.openFile = _a.openFile, exports.setOpenedFiles = _a.setOpenedFiles, exports.addFilePanel = _a.addFilePanel, exports.setFocussedFileIndex = _a.setFocussedFileIndex, exports.setPage = _a.setPage, exports.setAutorunEnabled = _a.setAutorunEnabled, exports.setIsOutputOnly = _a.setIsOutputOnly, exports.setCascadeUpdate = _a.setCascadeUpdate, exports.setError = _a.setError, exports.setHasShownSavePrompt = _a.setHasShownSavePrompt, exports.setProject = _a.setProject, exports.updateProjectSnapshot = _a.updateProjectSnapshot, exports.updateProjectCommits = _a.updateProjectCommits, exports.updateProjectIdentifier = _a.updateProjectIdentifier, exports.setReadOnly = _a.setReadOnly, exports.setLoading = _a.setLoading, exports.stopCodeRun = _a.stopCodeRun, exports.stopDraw = _a.stopDraw, exports.triggerCodeRun = _a.triggerCodeRun, exports.triggerDraw = _a.triggerDraw, exports.setSaveTriggered = _a.setSaveTriggered, exports.setProjectNameDraft = _a.setProjectNameDraft, exports.updateProjectName = _a.updateProjectName, exports.showErrorModal = _a.showErrorModal, exports.closeErrorModal = _a.closeErrorModal, exports.showModal = _a.showModal, exports.closeModal = _a.closeModal, exports.showSidebar = _a.showSidebar, exports.hideSidebar = _a.hideSidebar, exports.disableTheming = _a.disableTheming, exports.setSaving = _a.setSaving, exports.applyComponentsPatch = _a.applyComponentsPatch, exports.setCodeVisibility = _a.setCodeVisibility, exports.setSharedStatus = _a.setSharedStatus, exports.setCommits = _a.setCommits, exports.setShareLinks = _a.setShareLinks, exports.setCommitIdLoadTriggered = _a.setCommitIdLoadTriggered, exports.setIsLoadingCommit = _a.setIsLoadingCommit, exports.setRemixTriggered = _a.setRemixTriggered, exports.setShouldBypassCachedDraft = _a.setShouldBypassCachedDraft, exports.revertProject = _a.revertProject;
|
|
375507
375584
|
exports.queueBinaryWrites = (0, toolkit_1.createAction)("editor/queueBinaryWrites");
|
|
375508
375585
|
exports["default"] = exports.EditorSlice.reducer;
|
|
375509
375586
|
|
|
@@ -375643,7 +375720,6 @@ const utils_1 = __webpack_require__(33321);
|
|
|
375643
375720
|
const sendToast_1 = __webpack_require__(50068);
|
|
375644
375721
|
const constants_1 = __webpack_require__(16287);
|
|
375645
375722
|
const fileValidation_1 = __webpack_require__(59615);
|
|
375646
|
-
const macSystemFiles_1 = __webpack_require__(18213);
|
|
375647
375723
|
const selectComponents = (state) => {
|
|
375648
375724
|
return state.editor.project.components ?? [];
|
|
375649
375725
|
};
|
|
@@ -375715,27 +375791,23 @@ exports.fsRemove = fsRemove;
|
|
|
375715
375791
|
const fsImportFiles = ({ files, parentId }) => async (dispatch, getState) => {
|
|
375716
375792
|
const state = getState();
|
|
375717
375793
|
const components = selectComponents(state);
|
|
375718
|
-
|
|
375719
|
-
const importableFiles = (0, macSystemFiles_1.filterOutMacSystemFiles)(files);
|
|
375720
|
-
if (importableFiles.length === 0)
|
|
375721
|
-
return;
|
|
375722
|
-
if (!(0, utils_1.validateProjectFilesCount)(components, importableFiles.length)) {
|
|
375794
|
+
if (!(0, utils_1.validateProjectFilesCount)(components, files.length)) {
|
|
375723
375795
|
(0, sendToast_1.showError)(filesCountErrorMessage);
|
|
375724
375796
|
return;
|
|
375725
375797
|
}
|
|
375726
|
-
const { validFiles, importErrors } = (0, fileValidation_1.validateFiles)(
|
|
375798
|
+
const { validFiles, importErrors } = (0, fileValidation_1.validateFiles)(files);
|
|
375727
375799
|
const hasDuplicates = hasCaseInsensitiveDuplicateNames(validFiles);
|
|
375728
375800
|
for (const error of importErrors) {
|
|
375729
375801
|
(0, sendToast_1.showError)(error.reason);
|
|
375730
375802
|
}
|
|
375731
375803
|
if (validFiles.length > 0) {
|
|
375732
|
-
(0, sendToast_1.showSuccess)(`Selected files uploaded successfully. ${validFiles.length} of ${
|
|
375804
|
+
(0, sendToast_1.showSuccess)(`Selected files uploaded successfully. ${validFiles.length} of ${files.length} file(s) uploaded.`);
|
|
375733
375805
|
if (hasDuplicates) {
|
|
375734
375806
|
(0, sendToast_1.showInfo)(DUPLICATE_UPLOAD_TOAST);
|
|
375735
375807
|
}
|
|
375736
375808
|
}
|
|
375737
375809
|
else {
|
|
375738
|
-
(0, sendToast_1.showError)(`Selected files couldn’t be uploaded. ${
|
|
375810
|
+
(0, sendToast_1.showError)(`Selected files couldn’t be uploaded. ${files.length} file(s) failed to upload.`);
|
|
375739
375811
|
return;
|
|
375740
375812
|
}
|
|
375741
375813
|
const componentsMap = (0, utils_1.buildComponentsById)(components);
|
|
@@ -375752,28 +375824,24 @@ const fsImportFolder = ({ files, parentId }) => async (dispatch, getState) => {
|
|
|
375752
375824
|
return;
|
|
375753
375825
|
const state = getState();
|
|
375754
375826
|
const components = selectComponents(state);
|
|
375755
|
-
|
|
375756
|
-
const importableFiles = (0, macSystemFiles_1.filterOutMacSystemFiles)(files);
|
|
375757
|
-
if (importableFiles.length === 0)
|
|
375758
|
-
return;
|
|
375759
|
-
if (!(0, utils_1.validateProjectFilesCount)(components, importableFiles.length)) {
|
|
375827
|
+
if (!(0, utils_1.validateProjectFilesCount)(components, files.length)) {
|
|
375760
375828
|
(0, sendToast_1.showError)(filesCountErrorMessage);
|
|
375761
375829
|
return;
|
|
375762
375830
|
}
|
|
375763
|
-
const folderName =
|
|
375764
|
-
const { validFiles, importErrors } = (0, fileValidation_1.validateFiles)(
|
|
375831
|
+
const folderName = files[0]?.webkitRelativePath?.split("/")[0];
|
|
375832
|
+
const { validFiles, importErrors } = (0, fileValidation_1.validateFiles)(files);
|
|
375765
375833
|
const hasDuplicates = hasCaseInsensitiveDuplicateNames(validFiles);
|
|
375766
375834
|
for (const error of importErrors) {
|
|
375767
375835
|
(0, sendToast_1.showError)(error.reason);
|
|
375768
375836
|
}
|
|
375769
375837
|
if (validFiles.length > 0) {
|
|
375770
|
-
(0, sendToast_1.showSuccess)(`Folder '${folderName}' upload complete. ${validFiles.length} of ${
|
|
375838
|
+
(0, sendToast_1.showSuccess)(`Folder '${folderName}' upload complete. ${validFiles.length} of ${files.length} file(s) uploaded successfully.`);
|
|
375771
375839
|
if (hasDuplicates) {
|
|
375772
375840
|
(0, sendToast_1.showInfo)(DUPLICATE_UPLOAD_TOAST);
|
|
375773
375841
|
}
|
|
375774
375842
|
}
|
|
375775
375843
|
else {
|
|
375776
|
-
(0, sendToast_1.showError)(`'${folderName}' folder couldn't be uploaded. ${
|
|
375844
|
+
(0, sendToast_1.showError)(`'${folderName}' folder couldn't be uploaded. ${files.length} file(s) failed to upload.`);
|
|
375777
375845
|
return;
|
|
375778
375846
|
}
|
|
375779
375847
|
const componentsMap = (0, utils_1.buildComponentsById)(components);
|
|
@@ -376642,6 +376710,57 @@ const downloadProjectFile = async (file, fileName) => {
|
|
|
376642
376710
|
exports.downloadProjectFile = downloadProjectFile;
|
|
376643
376711
|
|
|
376644
376712
|
|
|
376713
|
+
/***/ }),
|
|
376714
|
+
|
|
376715
|
+
/***/ 31615:
|
|
376716
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
376717
|
+
|
|
376718
|
+
|
|
376719
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
376720
|
+
exports.matchingRegexes = exports.allowedInternalLinks = exports.allowedExternalLinks = exports.useExternalLinkState = void 0;
|
|
376721
|
+
const react_1 = __webpack_require__(51649);
|
|
376722
|
+
const react_redux_1 = __webpack_require__(14062);
|
|
376723
|
+
const EditorSlice_1 = __webpack_require__(68512);
|
|
376724
|
+
const Errors_1 = __webpack_require__(20339);
|
|
376725
|
+
const domain = "https://rpf.io/";
|
|
376726
|
+
const host = window?.location?.origin || "http://localhost:3011";
|
|
376727
|
+
const rpfDomain = new RegExp(`^${domain}`);
|
|
376728
|
+
const hostDomain = new RegExp(`^${host}`);
|
|
376729
|
+
const allowedInternalLinks = [new RegExp(`^#[a-zA-Z0-9]+`)];
|
|
376730
|
+
exports.allowedInternalLinks = allowedInternalLinks;
|
|
376731
|
+
const allowedExternalLinks = [rpfDomain, hostDomain];
|
|
376732
|
+
exports.allowedExternalLinks = allowedExternalLinks;
|
|
376733
|
+
const useExternalLinkState = (showModal) => {
|
|
376734
|
+
const dispatch = (0, react_redux_1.useDispatch)();
|
|
376735
|
+
const [externalLink, setExternalLink] = (0, react_1.useState)(null);
|
|
376736
|
+
const handleAllowedExternalLink = (linkTo) => {
|
|
376737
|
+
setExternalLink(linkTo);
|
|
376738
|
+
dispatch((0, EditorSlice_1.triggerCodeRun)());
|
|
376739
|
+
};
|
|
376740
|
+
const handleRegularExternalLink = (linkTo) => {
|
|
376741
|
+
setExternalLink(null);
|
|
376742
|
+
dispatch((0, EditorSlice_1.setPage)(linkTo));
|
|
376743
|
+
dispatch((0, EditorSlice_1.triggerCodeRun)());
|
|
376744
|
+
};
|
|
376745
|
+
const handleExternalLinkError = () => {
|
|
376746
|
+
dispatch((0, EditorSlice_1.setError)({ type: Errors_1.ErrorType.EXTERNAL_LINK }));
|
|
376747
|
+
showModal();
|
|
376748
|
+
};
|
|
376749
|
+
return {
|
|
376750
|
+
externalLink,
|
|
376751
|
+
setExternalLink,
|
|
376752
|
+
handleAllowedExternalLink,
|
|
376753
|
+
handleRegularExternalLink,
|
|
376754
|
+
handleExternalLinkError,
|
|
376755
|
+
};
|
|
376756
|
+
};
|
|
376757
|
+
exports.useExternalLinkState = useExternalLinkState;
|
|
376758
|
+
const matchingRegexes = (regexArray, testString) => {
|
|
376759
|
+
return regexArray.some((reg) => reg.test(testString));
|
|
376760
|
+
};
|
|
376761
|
+
exports.matchingRegexes = matchingRegexes;
|
|
376762
|
+
|
|
376763
|
+
|
|
376645
376764
|
/***/ }),
|
|
376646
376765
|
|
|
376647
376766
|
/***/ 65404:
|
|
@@ -376659,7 +376778,6 @@ const ProjectTypes_1 = __webpack_require__(27130);
|
|
|
376659
376778
|
const projectHelpers_1 = __webpack_require__(2610);
|
|
376660
376779
|
const binaryStore_1 = __webpack_require__(5060);
|
|
376661
376780
|
const projectBinaryIndex_1 = __webpack_require__(3044);
|
|
376662
|
-
const macSystemFiles_1 = __webpack_require__(18213);
|
|
376663
376781
|
function normPath(p) {
|
|
376664
376782
|
let s = (p || "").replace(/\\/g, "/").replace(/^\/+/, "");
|
|
376665
376783
|
// remove extra folder in zipball zip
|
|
@@ -376686,7 +376804,7 @@ function pushChild(parent, childId) {
|
|
|
376686
376804
|
parent.children.push(childId);
|
|
376687
376805
|
}
|
|
376688
376806
|
function getCommonRootFolder(entries) {
|
|
376689
|
-
const fileEntries = entries.filter((entry) => !entry.dir
|
|
376807
|
+
const fileEntries = entries.filter((entry) => !entry.dir);
|
|
376690
376808
|
const [firstFileEntry] = fileEntries;
|
|
376691
376809
|
if (!firstFileEntry)
|
|
376692
376810
|
return "";
|
|
@@ -376721,13 +376839,10 @@ async function loadProjectFromZip(opts) {
|
|
|
376721
376839
|
for (const entry of entries) {
|
|
376722
376840
|
if (entry.dir)
|
|
376723
376841
|
continue;
|
|
376724
|
-
|
|
376725
|
-
|
|
376726
|
-
|
|
376727
|
-
|
|
376728
|
-
const raw = rootPath && normalized.startsWith(rootPath)
|
|
376729
|
-
? normalized.slice(rootPath.length)
|
|
376730
|
-
: normalized;
|
|
376842
|
+
const normalizedEntryName = normPath(entry.name);
|
|
376843
|
+
const raw = rootPath
|
|
376844
|
+
? normPath(normalizedEntryName.slice(rootPath.length))
|
|
376845
|
+
: normalizedEntryName;
|
|
376731
376846
|
if (!raw)
|
|
376732
376847
|
continue;
|
|
376733
376848
|
const parts = raw.split("/").filter(Boolean);
|
|
@@ -376787,34 +376902,6 @@ async function loadProjectFromZip(opts) {
|
|
|
376787
376902
|
}
|
|
376788
376903
|
|
|
376789
376904
|
|
|
376790
|
-
/***/ }),
|
|
376791
|
-
|
|
376792
|
-
/***/ 18213:
|
|
376793
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
376794
|
-
|
|
376795
|
-
|
|
376796
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
376797
|
-
exports.filterOutMacSystemFiles = exports.isMacSystemFilePath = void 0;
|
|
376798
|
-
const normalizeSlashes = (p) => (p || "").replace(/\\/g, "/").trim();
|
|
376799
|
-
const isMacSystemFilePath = (rawEntryPath) => {
|
|
376800
|
-
const path = normalizeSlashes(rawEntryPath);
|
|
376801
|
-
if (!path)
|
|
376802
|
-
return false;
|
|
376803
|
-
const fileName = path.split("/").filter(Boolean).pop() || "";
|
|
376804
|
-
// skip mac system files
|
|
376805
|
-
if (path.startsWith("__MACOSX/") || path.includes("/__MACOSX/"))
|
|
376806
|
-
return true;
|
|
376807
|
-
if (fileName === ".DS_Store")
|
|
376808
|
-
return true;
|
|
376809
|
-
if (fileName.startsWith("._"))
|
|
376810
|
-
return true;
|
|
376811
|
-
return false;
|
|
376812
|
-
};
|
|
376813
|
-
exports.isMacSystemFilePath = isMacSystemFilePath;
|
|
376814
|
-
const filterOutMacSystemFiles = (files) => Array.from(files).filter((file) => !(0, exports.isMacSystemFilePath)(file.webkitRelativePath?.trim() || file.name));
|
|
376815
|
-
exports.filterOutMacSystemFiles = filterOutMacSystemFiles;
|
|
376816
|
-
|
|
376817
|
-
|
|
376818
376905
|
/***/ }),
|
|
376819
376906
|
|
|
376820
376907
|
/***/ 3044:
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gwchq-textjam",
|
|
3
3
|
"description": "Embeddable React editor used in Raspberry Pi text-based projects.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/GirlsFirst/gwchq-textjam",
|
|
7
7
|
"author": "Girls Who Code HQ",
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"lint:fix": "eslint --fix \"src/**/*.{js,jsx,json}\"",
|
|
22
22
|
"stylelint": "stylelint src/**/*.scss",
|
|
23
23
|
"test": "jest",
|
|
24
|
-
"test:coverage": "jest --coverage --json --outputFile=report.json",
|
|
25
24
|
"prepare": "husky"
|
|
26
25
|
},
|
|
27
26
|
"module": "./dist/index.js",
|
|
@@ -98,7 +97,7 @@
|
|
|
98
97
|
"react-refresh": "^0.8.3",
|
|
99
98
|
"react-responsive": "^9.0.2",
|
|
100
99
|
"react-router-dom": "^6.7.0",
|
|
101
|
-
"react-tabs": "^
|
|
100
|
+
"react-tabs": "^3.2.3",
|
|
102
101
|
"react-timer-hook": "^3.0.5",
|
|
103
102
|
"react-toastify": "^8.1.0",
|
|
104
103
|
"react-toggle": "^4.1.3",
|
|
@@ -123,6 +122,7 @@
|
|
|
123
122
|
"@babel/preset-env": "^7.17.10",
|
|
124
123
|
"@babel/preset-typescript": "^7.28.5",
|
|
125
124
|
"@pmmmwh/react-refresh-webpack-plugin": "0.4.3",
|
|
125
|
+
"@react-three/test-renderer": "8.2.1",
|
|
126
126
|
"@svgr/webpack": "5.5.0",
|
|
127
127
|
"@testing-library/jest-dom": "^5.16.5",
|
|
128
128
|
"@testing-library/react": "14.3.1",
|
|
@@ -165,7 +165,6 @@
|
|
|
165
165
|
"file-loader": "6.1.1",
|
|
166
166
|
"html-webpack-plugin": "5.6.0",
|
|
167
167
|
"husky": "^9.1.7",
|
|
168
|
-
"identity-obj-proxy": "^3.0.0",
|
|
169
168
|
"jest": "^29.1.2",
|
|
170
169
|
"jest-circus": "^29.1.2",
|
|
171
170
|
"jest-css-modules-transform": "^4.4.2",
|
|
@@ -274,9 +273,7 @@
|
|
|
274
273
|
"^utils/(.*)$": "<rootDir>/src/utils/$1",
|
|
275
274
|
"^components/(.*)$": "<rootDir>/src/components/$1",
|
|
276
275
|
"^assets/(.*)$": "<rootDir>/src/assets/$1",
|
|
277
|
-
"^store/(.*)$": "<rootDir>/src/redux/$1"
|
|
278
|
-
"^domain/(.*)$": "<rootDir>/src/domain/$1",
|
|
279
|
-
"^.+\\?url$": "<rootDir>/node_modules/jest-transform-stub"
|
|
276
|
+
"^store/(.*)$": "<rootDir>/src/redux/$1"
|
|
280
277
|
},
|
|
281
278
|
"moduleFileExtensions": [
|
|
282
279
|
"web.js",
|
|
@@ -294,8 +291,7 @@
|
|
|
294
291
|
"jest-watch-typeahead/filename",
|
|
295
292
|
"jest-watch-typeahead/testname"
|
|
296
293
|
],
|
|
297
|
-
"resetMocks": true
|
|
298
|
-
"coverageDirectory": "./coverage"
|
|
294
|
+
"resetMocks": true
|
|
299
295
|
},
|
|
300
296
|
"packageManager": "yarn@3.4.1"
|
|
301
297
|
}
|