@aaqu/fromcubes-react 0.2.0 → 0.2.1
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/nodes/editor/file-tree.js +1 -1
- package/nodes/editor/format.js +1 -1
- package/nodes/editor/provider-settings.js +8 -8
- package/nodes/editor/workspace.js +5 -3
- package/nodes/lib/admin-api.js +33 -22
- package/nodes/portal-react.html +24 -8
- package/nodes/portal-react.js +6 -1
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* module is a pair of pure functions so it can be unit-tested under vitest and
|
|
8
8
|
* still be loaded as a plain browser script by the Node-RED editor.
|
|
9
9
|
*
|
|
10
|
-
* Loaded in the browser
|
|
10
|
+
* Loaded in the browser by the asset loader in portal-react.html (`<base>/editor/file-tree.js`)
|
|
11
11
|
* (exposes `window.__fcFileTree`) and in tests via `require()`.
|
|
12
12
|
*/
|
|
13
13
|
(function (root, factory) {
|
package/nodes/editor/format.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"use strict";
|
|
14
14
|
|
|
15
15
|
const PREFIX = "[FC-Format]";
|
|
16
|
-
const BASE = "fromcubes-react/prettier/";
|
|
16
|
+
const BASE = (window.__fcAssetBase || "fromcubes-react/") + "prettier/";
|
|
17
17
|
// UMD builds: each sets window.prettier / window.prettierPlugins.
|
|
18
18
|
const SCRIPTS = [
|
|
19
19
|
"standalone.js",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Settings → Fromcubes: choose the
|
|
2
|
+
* Settings → Fromcubes: choose the CSS engine and the identity provider.
|
|
3
3
|
*
|
|
4
4
|
* Exactly one provider per kind, shown as a radio list, so two can never be
|
|
5
5
|
* active at once. Reads and writes `/fromcubes-react/providers`; the server
|
|
6
6
|
* validates, persists to <userDir>/fromcubes/providers.json, and applies the
|
|
7
|
-
* change (
|
|
7
|
+
* change (css: every portal rebuilds; identity: every portal session reloads).
|
|
8
8
|
* A kind set in settings.js is shown locked.
|
|
9
9
|
*
|
|
10
10
|
* Node-RED shows a pane by the element id `red-ui-settings-tab-<pane id>`,
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
var URL = "fromcubes-react/providers";
|
|
19
19
|
|
|
20
20
|
var KINDS = [
|
|
21
|
-
{
|
|
22
|
-
kind: "identity",
|
|
23
|
-
title: "Identity provider",
|
|
24
|
-
hint: "Who is behind a portal session — used by Portal Auth, auth-cast and per-user delivery.",
|
|
25
|
-
setting: "identityProvider",
|
|
26
|
-
},
|
|
27
21
|
{
|
|
28
22
|
kind: "css",
|
|
29
23
|
title: "CSS engine",
|
|
30
24
|
hint: "Generates each portal's stylesheet at deploy. Changing it rebuilds every portal.",
|
|
31
25
|
setting: "cssEngine",
|
|
32
26
|
},
|
|
27
|
+
{
|
|
28
|
+
kind: "identity",
|
|
29
|
+
title: "Identity provider",
|
|
30
|
+
hint: "Who is behind a portal session — used by Portal Auth, auth-cast and per-user delivery.",
|
|
31
|
+
setting: "identityProvider",
|
|
32
|
+
},
|
|
33
33
|
];
|
|
34
34
|
|
|
35
35
|
function errorText(xhr) {
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
const EDITOR_NAME = "React Editor";
|
|
20
20
|
const FLUSH_DEBOUNCE_MS = 400;
|
|
21
21
|
const MIN_TREE_WIDTH = 150;
|
|
22
|
+
// Versioned asset path set by portal-react.html (see ASSET_BASE in lib/admin-api.js).
|
|
23
|
+
const ASSET_BASE = window.__fcAssetBase || "fromcubes-react/";
|
|
22
24
|
|
|
23
25
|
// ── Module state ────────────────────────────────────────────
|
|
24
26
|
|
|
@@ -636,7 +638,7 @@
|
|
|
636
638
|
* @returns {void}
|
|
637
639
|
*/
|
|
638
640
|
function injectIconSprite() {
|
|
639
|
-
$.ajax({ url: "
|
|
641
|
+
$.ajax({ url: ASSET_BASE + "editor/icons.svg", dataType: "text" })
|
|
640
642
|
.done(function (markup) {
|
|
641
643
|
$("<div>")
|
|
642
644
|
.attr("id", "fc-ws-icon-sprite")
|
|
@@ -1107,7 +1109,7 @@
|
|
|
1107
1109
|
const brand = $("<div>").addClass("fc-ws-brand").appendTo(header);
|
|
1108
1110
|
$("<img>")
|
|
1109
1111
|
.addClass("fc-ws-mark-logo")
|
|
1110
|
-
.attr("src", "
|
|
1112
|
+
.attr("src", ASSET_BASE + "editor/mark.svg")
|
|
1111
1113
|
.attr("alt", "fromcubes")
|
|
1112
1114
|
.appendTo(brand);
|
|
1113
1115
|
// One word split by colour — wrapped so the lockup's gap sits between the
|
|
@@ -1471,7 +1473,7 @@
|
|
|
1471
1473
|
});
|
|
1472
1474
|
$("<img>")
|
|
1473
1475
|
.addClass("fc-ws-statusbar-icon")
|
|
1474
|
-
.attr("src", "
|
|
1476
|
+
.attr("src", ASSET_BASE + "icons/fromcubes-react.svg")
|
|
1475
1477
|
.attr("alt", "")
|
|
1476
1478
|
.appendTo(el);
|
|
1477
1479
|
$("<span>").text(EDITOR_NAME).appendTo(el);
|
package/nodes/lib/admin-api.js
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Editor assets are also served under a path carrying the core's version
|
|
5
|
+
* (`fromcubes-react/0.2.0/editor/…`), and the editor template loads them from
|
|
6
|
+
* there. Every cache in between — the browser, a CDN, a reverse proxy — keys
|
|
7
|
+
* on the path, so a new release can never be handed an old file, nor a 404
|
|
8
|
+
* remembered from a moment the route did not exist yet. Query strings are not
|
|
9
|
+
* enough: some caches ignore them. The unversioned paths stay for anything
|
|
10
|
+
* that still points at them.
|
|
11
|
+
*/
|
|
12
|
+
const ASSET_VERSION = String(require("../../package.json").version).replace(
|
|
13
|
+
/[^0-9A-Za-z.+-]/g,
|
|
14
|
+
"",
|
|
15
|
+
);
|
|
16
|
+
/** Relative to the admin root, as the editor needs it (no leading slash). */
|
|
17
|
+
const ASSET_BASE = "fromcubes-react/" + ASSET_VERSION + "/";
|
|
18
|
+
|
|
3
19
|
/**
|
|
4
20
|
* Register editor/admin/public support routes for portal-react.
|
|
5
21
|
*
|
|
@@ -37,41 +53,36 @@ function registerAdminApi(RED, deps) {
|
|
|
37
53
|
onProviderChange,
|
|
38
54
|
} = deps;
|
|
39
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Mount one static directory at both its plain and its versioned path.
|
|
58
|
+
* @param {string} name
|
|
59
|
+
* @param {string} dir
|
|
60
|
+
* @returns {void}
|
|
61
|
+
*/
|
|
62
|
+
function serveStatic(name, dir) {
|
|
63
|
+
const files = express.static(dir);
|
|
64
|
+
RED.httpAdmin.use("/fromcubes-react/" + name, permRead, files);
|
|
65
|
+
RED.httpAdmin.use("/" + ASSET_BASE + name, permRead, files);
|
|
66
|
+
}
|
|
67
|
+
|
|
40
68
|
// Since 0.56 monaco-editor has an `exports` map that hides package.json;
|
|
41
69
|
// its CommonJS entry is min/vs/index.js, so the AMD build (loader.js and
|
|
42
70
|
// editor/editor.main.js) sits in the same directory.
|
|
43
|
-
|
|
44
|
-
RED.httpAdmin.use(
|
|
45
|
-
"/fromcubes-react/vs",
|
|
46
|
-
permRead,
|
|
47
|
-
express.static(monacoVsPath),
|
|
48
|
-
);
|
|
71
|
+
serveStatic("vs", path.dirname(require.resolve("monaco-editor")));
|
|
49
72
|
|
|
50
73
|
// Editor-side workspace plugin (tree + full-screen Monaco overlay). Served
|
|
51
74
|
// as static files instead of being inlined into portal-react.html so the
|
|
52
75
|
// node's editor template stays readable.
|
|
53
|
-
|
|
54
|
-
"/fromcubes-react/editor",
|
|
55
|
-
permRead,
|
|
56
|
-
express.static(path.join(__dirname, "..", "editor")),
|
|
57
|
-
);
|
|
76
|
+
serveStatic("editor", path.join(__dirname, "..", "editor"));
|
|
58
77
|
|
|
59
78
|
// The node icon doubles as the editor's status-bar mark. Serving the icons
|
|
60
79
|
// directory here keeps one copy on disk and spares the client from having to
|
|
61
80
|
// know the package name that Node-RED's own /icons route is keyed by.
|
|
62
|
-
|
|
63
|
-
"/fromcubes-react/icons",
|
|
64
|
-
permRead,
|
|
65
|
-
express.static(path.join(__dirname, "..", "icons")),
|
|
66
|
-
);
|
|
81
|
+
serveStatic("icons", path.join(__dirname, "..", "icons"));
|
|
67
82
|
|
|
68
83
|
// Prettier's browser builds, straight from node_modules — same arrangement
|
|
69
84
|
// as Monaco at /fromcubes-react/vs. Nothing is fetched until someone formats.
|
|
70
|
-
|
|
71
|
-
"/fromcubes-react/prettier",
|
|
72
|
-
permRead,
|
|
73
|
-
express.static(path.dirname(require.resolve("prettier/package.json"))),
|
|
74
|
-
);
|
|
85
|
+
serveStatic("prettier", path.dirname(require.resolve("prettier/package.json")));
|
|
75
86
|
|
|
76
87
|
const CSS_HASH_RE = /^[a-f0-9]{1,64}$/;
|
|
77
88
|
function findCssByHash(reqHash) {
|
|
@@ -235,4 +246,4 @@ function registerProviderRoutes(RED, deps) {
|
|
|
235
246
|
);
|
|
236
247
|
}
|
|
237
248
|
|
|
238
|
-
module.exports = { registerAdminApi };
|
|
249
|
+
module.exports = { registerAdminApi, ASSET_BASE };
|
package/nodes/portal-react.html
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
<!-- ============================================================
|
|
2
2
|
Portal Code Workspace — sidebar tab + full-screen editor overlay.
|
|
3
|
-
Served from nodes/editor/ via the /fromcubes-react
|
|
3
|
+
Served from nodes/editor/ via the /fromcubes-react/<version>/editor admin route.
|
|
4
4
|
============================================================ -->
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
<script type="text/javascript">
|
|
6
|
+
// Loaded from the versioned asset path the runtime exports (ASSET_BASE in
|
|
7
|
+
// lib/admin-api.js), so no cache — browser, CDN or proxy — can serve this
|
|
8
|
+
// template an older file, or a 404 it remembered. Execution order follows
|
|
9
|
+
// insertion order (async = false); every script waits for what it needs.
|
|
10
|
+
(function () {
|
|
11
|
+
const base = (RED.settings && RED.settings.portalReactAssetBase) || "fromcubes-react/";
|
|
12
|
+
window.__fcAssetBase = base;
|
|
13
|
+
const link = document.createElement("link");
|
|
14
|
+
link.rel = "stylesheet";
|
|
15
|
+
link.href = base + "editor/workspace.css";
|
|
16
|
+
document.head.appendChild(link);
|
|
17
|
+
["file-tree.js", "workspace.js", "format.js", "provider-settings.js"].forEach(function (file) {
|
|
18
|
+
const s = document.createElement("script");
|
|
19
|
+
s.src = base + "editor/" + file;
|
|
20
|
+
s.async = false;
|
|
21
|
+
document.head.appendChild(s);
|
|
22
|
+
});
|
|
23
|
+
})();
|
|
24
|
+
</script>
|
|
10
25
|
|
|
11
26
|
<!-- ============================================================
|
|
12
27
|
Shared: Monaco loader (used by both node editors)
|
|
@@ -1041,10 +1056,11 @@
|
|
|
1041
1056
|
return;
|
|
1042
1057
|
}
|
|
1043
1058
|
const s = document.createElement("script");
|
|
1044
|
-
|
|
1059
|
+
const base = window.__fcAssetBase || "fromcubes-react/";
|
|
1060
|
+
s.src = base + "vs/loader.js";
|
|
1045
1061
|
s.onload = function () {
|
|
1046
1062
|
console.log(PREFIX, "loader.js loaded, configuring require paths");
|
|
1047
|
-
require.config({ paths: { vs: "
|
|
1063
|
+
require.config({ paths: { vs: base + "vs" } });
|
|
1048
1064
|
require(["vs/editor/editor.main"], function () {
|
|
1049
1065
|
console.log(PREFIX, "editor.main loaded");
|
|
1050
1066
|
ensureJsxSetup();
|
package/nodes/portal-react.js
CHANGED
|
@@ -1629,12 +1629,17 @@ module.exports = function (RED) {
|
|
|
1629
1629
|
}); // end setImmediate
|
|
1630
1630
|
}
|
|
1631
1631
|
|
|
1632
|
+
const { registerAdminApi, ASSET_BASE } = require("./lib/admin-api");
|
|
1632
1633
|
RED.nodes.registerType("portal-react", PortalReactNode, {
|
|
1633
1634
|
dynamicModuleList: "libs",
|
|
1635
|
+
// Read by portal-react.html to load the editor assets from their
|
|
1636
|
+
// versioned path (see ASSET_BASE in lib/admin-api.js).
|
|
1637
|
+
settings: {
|
|
1638
|
+
portalReactAssetBase: { value: ASSET_BASE, exportable: true },
|
|
1639
|
+
},
|
|
1634
1640
|
});
|
|
1635
1641
|
|
|
1636
1642
|
const express = loadExpress();
|
|
1637
|
-
const { registerAdminApi } = require("./lib/admin-api");
|
|
1638
1643
|
registerAdminApi(RED, {
|
|
1639
1644
|
express,
|
|
1640
1645
|
permRead: PERM_READ,
|