@mudlet/mudlet-web 0.3.0 → 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.
Files changed (111) hide show
  1. package/LICENSE +338 -338
  2. package/README.md +158 -150
  3. package/dist-lib/assets/qt-resources/index.d.ts +16 -0
  4. package/dist-lib/branding.d.ts +1 -1
  5. package/dist-lib/hooks/useMudSession.d.ts +1 -1
  6. package/dist-lib/hooks/useOutput.d.ts +3 -1
  7. package/dist-lib/import/defaultPackages.d.ts +35 -2
  8. package/dist-lib/import/defaults/generic_mapper/generic_mapper.mpackage +0 -0
  9. package/dist-lib/import/defaults/gui-drop/gui-drop.mpackage +0 -0
  10. package/dist-lib/import/defaults/{run-lua-code.mpackage → mudlet-base-ui/mudlet-base-ui.mpackage} +0 -0
  11. package/dist-lib/import/defaults/mudlet-mapper.xml +13023 -13023
  12. package/dist-lib/import/defaults/run-lua-code/run-lua-code.mpackage +0 -0
  13. package/dist-lib/import/packageExport.d.ts +71 -0
  14. package/dist-lib/import/packageInstaller.d.ts +4 -1
  15. package/dist-lib/index.js +45910 -39931
  16. package/dist-lib/logging/SessionLogger.d.ts +66 -1
  17. package/dist-lib/map/MapStore.d.ts +32 -4
  18. package/dist-lib/map/mapImageExport.d.ts +1 -1
  19. package/dist-lib/map/mapZoom.d.ts +71 -0
  20. package/dist-lib/mud/ItemIdSequence.d.ts +23 -0
  21. package/dist-lib/mud/MudSession.d.ts +113 -11
  22. package/dist-lib/mud/PatternEngine.d.ts +6 -1
  23. package/dist-lib/mud/commandSplit.d.ts +16 -0
  24. package/dist-lib/mud/connection/LineAssembler.d.ts +56 -0
  25. package/dist-lib/mud/connection/MudClient.d.ts +136 -19
  26. package/dist-lib/mud/connection/TelnetNegotiator.d.ts +39 -0
  27. package/dist-lib/mud/connection/telnetByteTags.d.ts +35 -0
  28. package/dist-lib/mud/events.d.ts +86 -4
  29. package/dist-lib/mud/games/bundledGames.d.ts +29 -0
  30. package/dist-lib/mud/games/gameIcons.d.ts +5 -0
  31. package/dist-lib/mud/keybindings/KeyEngine.d.ts +9 -2
  32. package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +5 -1
  33. package/dist-lib/mud/keybindings/keyEventTarget.d.ts +17 -0
  34. package/dist-lib/mud/keybindings/qtKeys.d.ts +2 -0
  35. package/dist-lib/mud/protocol/charLoginFlow.d.ts +68 -0
  36. package/dist-lib/mud/protocol/charset.d.ts +27 -5
  37. package/dist-lib/mud/protocol/constants.d.ts +1 -0
  38. package/dist-lib/mud/protocol/gmcp.d.ts +19 -3
  39. package/dist-lib/mud/protocol/index.d.ts +1 -1
  40. package/dist-lib/mud/protocol/msspTls.d.ts +54 -0
  41. package/dist-lib/mud/protocol/mxp.d.ts +28 -5
  42. package/dist-lib/mud/protocol/tlsCodes.d.ts +4 -0
  43. package/dist-lib/mud/replay/ReplayPlayer.d.ts +17 -0
  44. package/dist-lib/mud/text/Console.d.ts +64 -0
  45. package/dist-lib/mud/text/FormatState.d.ts +66 -3
  46. package/dist-lib/mud/text/hyperlinkVisibility.d.ts +35 -0
  47. package/dist-lib/mud/text/osc8Docs.d.ts +23 -0
  48. package/dist-lib/mud/text/serverWrap.d.ts +191 -0
  49. package/dist-lib/mud/timers/TimerEngine.d.ts +43 -12
  50. package/dist-lib/mud/triggers/TriggerEngine.d.ts +112 -3
  51. package/dist-lib/scripting/EngineHost.d.ts +56 -3
  52. package/dist-lib/scripting/IScriptingRuntime.d.ts +22 -0
  53. package/dist-lib/scripting/MxpFrameManager.d.ts +118 -0
  54. package/dist-lib/scripting/ScriptingAPI.d.ts +331 -54
  55. package/dist-lib/scripting/ScriptingEngine.d.ts +181 -24
  56. package/dist-lib/scripting/http/HttpService.d.ts +51 -1
  57. package/dist-lib/scripting/lua/LuaRuntime.d.ts +159 -2
  58. package/dist-lib/scripting/lua/bindings/map.d.ts +0 -12
  59. package/dist-lib/scripting/lua/utf8Patterns.d.ts +59 -0
  60. package/dist-lib/storage/index.d.ts +1 -1
  61. package/dist-lib/storage/persistentStorage.d.ts +10 -0
  62. package/dist-lib/storage/schema.d.ts +166 -4
  63. package/dist-lib/styles.css +1 -1
  64. package/dist-lib/ui/BundledGameGrid.d.ts +21 -0
  65. package/dist-lib/ui/CharLoginModal.d.ts +5 -1
  66. package/dist-lib/ui/CommandBar.d.ts +7 -1
  67. package/dist-lib/ui/ConnectionGrid.d.ts +4 -1
  68. package/dist-lib/ui/FileBrowserModal.d.ts +1 -0
  69. package/dist-lib/ui/FilePickerModal.d.ts +3 -3
  70. package/dist-lib/ui/HelpModal.d.ts +11 -0
  71. package/dist-lib/ui/LogBrowserModal.d.ts +4 -1
  72. package/dist-lib/ui/PlayerMarkerPreview.d.ts +20 -0
  73. package/dist-lib/ui/SettingsModal.d.ts +5 -1
  74. package/dist-lib/ui/TlsAlertBanner.d.ts +18 -0
  75. package/dist-lib/ui/TlsCertificateBox.d.ts +20 -0
  76. package/dist-lib/ui/TlsUpgradeModal.d.ts +16 -0
  77. package/dist-lib/ui/Toolbar.d.ts +2 -1
  78. package/dist-lib/ui/VfsPickerModal.d.ts +26 -0
  79. package/dist-lib/ui/components/FileSourceButton.d.ts +47 -0
  80. package/dist-lib/ui/components/index.d.ts +1 -0
  81. package/dist-lib/ui/components/useModalFocus.d.ts +6 -0
  82. package/dist-lib/ui/helpTopics.d.ts +19 -0
  83. package/dist-lib/ui/labels/LabelManager.d.ts +32 -0
  84. package/dist-lib/ui/labels/labelLinks.d.ts +52 -0
  85. package/dist-lib/ui/layout/ScriptWindow.d.ts +11 -2
  86. package/dist-lib/ui/markdown.d.ts +10 -1
  87. package/dist-lib/ui/output/OutputArea.d.ts +11 -1
  88. package/dist-lib/ui/output/OutputContextMenu.d.ts +3 -1
  89. package/dist-lib/ui/output/OutputRenderer.d.ts +7 -1
  90. package/dist-lib/ui/output/OutputSearchBar.d.ts +25 -0
  91. package/dist-lib/ui/output/StickyOutputPanel.d.ts +5 -1
  92. package/dist-lib/ui/output/linkNavigation.d.ts +22 -0
  93. package/dist-lib/ui/output/outputSearch.d.ts +130 -0
  94. package/dist-lib/ui/search/matcher.d.ts +15 -0
  95. package/dist-lib/ui/search/useDebounced.d.ts +3 -0
  96. package/dist-lib/ui/tts/TtsManager.d.ts +3 -0
  97. package/dist-lib/ui/useCommandHistory.d.ts +4 -2
  98. package/dist-lib/ui/useOpenProfiles.d.ts +26 -0
  99. package/dist-lib/ui/video/VideoManager.d.ts +17 -0
  100. package/dist-lib/ui/windows/WindowManager.d.ts +149 -2
  101. package/dist-lib/ui/windows/panels/MapPanel.d.ts +4 -1
  102. package/dist-lib/ui/windows/panels/PackageExportModal.d.ts +18 -0
  103. package/dist-lib/ui/windows/panels/TextPanel.d.ts +3 -1
  104. package/dist-lib/ui/windows/types.d.ts +35 -0
  105. package/dist-lib/utils/describeThrown.d.ts +22 -0
  106. package/dist-lib/utils/fontLoader.d.ts +5 -0
  107. package/dist-lib/vfs-sw.js +131 -131
  108. package/dist-lib/vite.js +22 -0
  109. package/package.json +97 -93
  110. package/dist-lib/scripting/lua/mudlet-lua/generic-mapper/generic_mapper.mpackage +0 -0
  111. package/dist-lib/ui/windows/panels/VfsModulePickerModal.d.ts +0 -8
@@ -1,131 +1,131 @@
1
- // Service worker that serves ProfileVFS-backed assets at /__vfs/<connectionId>/<path>.
2
- // The page is the source of truth for VFS contents (the SW can't share folder
3
- // handles or always-open the same IDB store), so each request round-trips to
4
- // the client via MessageChannel.
5
-
6
- const CACHE_NAME = 'mudix-vfs-v1';
7
- // Scope path always ends with '/'. On a root-served deploy this is '/'; on
8
- // GitHub Pages or any subpath deploy it's '/<repo>/'. The intercept prefix is
9
- // '<scope>__vfs/' so SW-controlled URLs stay inside scope.
10
- const SCOPE_PATH = new URL(self.registration.scope).pathname;
11
- const PREFIX = `${SCOPE_PATH}__vfs/`;
12
- const READ_TIMEOUT_MS = 5000;
13
-
14
- self.addEventListener('install', () => self.skipWaiting());
15
- self.addEventListener('activate', (e) => e.waitUntil(self.clients.claim()));
16
-
17
- self.addEventListener('fetch', (event) => {
18
- const url = new URL(event.request.url);
19
- if (url.origin !== self.location.origin) return;
20
- if (!url.pathname.startsWith(PREFIX)) return;
21
- event.respondWith(handle(event, url));
22
- });
23
-
24
- async function handle(event, url) {
25
- const rest = url.pathname.slice(PREFIX.length).split('/').filter(Boolean);
26
- if (rest.length < 2) return new Response('Bad request', { status: 400 });
27
- const connectionId = decodeURIComponent(rest[0]);
28
- const filePath = '/' + rest.slice(1).map(decodeURIComponent).join('/');
29
-
30
- const cache = await caches.open(CACHE_NAME);
31
- const cached = await cache.match(event.request);
32
- if (cached) return cached;
33
-
34
- const client = await pickClient(event);
35
- if (!client) {
36
- // Either there's no app tab loaded (direct URL hit in fresh tab) or
37
- // the only candidate is the tab currently navigating to this URL.
38
- return new Response('No app tab loaded; open mudix first', { status: 503 });
39
- }
40
-
41
- const reply = await ask(client, { type: 'vfs:read', connectionId, path: filePath });
42
- if (!reply || !reply.ok) {
43
- return new Response(reply?.error ?? 'Not found', { status: 404 });
44
- }
45
-
46
- const headers = new Headers();
47
- headers.set('Content-Type', reply.contentType || 'application/octet-stream');
48
- // no-store keeps this response out of the browser's own HTTP cache, which
49
- // has no validator to revalidate against (we set none) and would otherwise
50
- // race our explicit Cache Storage entry above — that race is what produced
51
- // stale 304-with-no-body responses for cached images. The Cache Storage
52
- // entry (invalidated on writes via postMessage) is the only cache that
53
- // should own this decision.
54
- headers.set('Cache-Control', 'no-store');
55
- const response = new Response(reply.bytes, { headers });
56
- cache.put(event.request, response.clone()).catch(() => {});
57
- return response;
58
- }
59
-
60
- async function pickClient(event) {
61
- // Prefer the client that issued this request — for sub-resource fetches
62
- // that's the loaded app page, which can reply immediately.
63
- const requestingId = event.clientId || event.resultingClientId || '';
64
- if (requestingId) {
65
- const c = await self.clients.get(requestingId);
66
- if (c && isUsable(c)) return c;
67
- }
68
- const all = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });
69
- const usable = all.filter(isUsable);
70
- return usable.find((c) => c.focused) ?? usable[0] ?? null;
71
- }
72
-
73
- // Skip clients that are themselves navigating to a /__vfs/ URL — those are
74
- // fresh tabs in the middle of loading the SW response; they have no JS running
75
- // and can't reply, so picking one guarantees a timeout.
76
- function isUsable(client) {
77
- try {
78
- return !new URL(client.url).pathname.startsWith(PREFIX);
79
- } catch {
80
- return false;
81
- }
82
- }
83
-
84
- function ask(client, message) {
85
- return new Promise((resolve) => {
86
- const channel = new MessageChannel();
87
- const timer = setTimeout(() => {
88
- channel.port1.close();
89
- resolve({ ok: false, error: 'timeout' });
90
- }, READ_TIMEOUT_MS);
91
- channel.port1.onmessage = (e) => {
92
- clearTimeout(timer);
93
- channel.port1.close();
94
- resolve(e.data);
95
- };
96
- client.postMessage(message, [channel.port2]);
97
- });
98
- }
99
-
100
- self.addEventListener('message', (event) => {
101
- const data = event.data;
102
- if (!data) return;
103
- if (data.type === 'vfs:invalidate') {
104
- event.waitUntil(invalidate(data));
105
- }
106
- });
107
-
108
- async function invalidate({ connectionId, path }) {
109
- if (!connectionId) {
110
- await caches.delete(CACHE_NAME);
111
- return;
112
- }
113
- const cache = await caches.open(CACHE_NAME);
114
- const connPrefix = `${PREFIX}${encodeURIComponent(connectionId)}/`;
115
- const keys = await cache.keys();
116
- if (path) {
117
- const segs = path.split('/').filter(Boolean).map(encodeURIComponent).join('/');
118
- const target = `${connPrefix}${segs}`;
119
- await Promise.all(
120
- keys
121
- .filter((req) => new URL(req.url).pathname === target)
122
- .map((req) => cache.delete(req)),
123
- );
124
- return;
125
- }
126
- await Promise.all(
127
- keys
128
- .filter((req) => new URL(req.url).pathname.startsWith(connPrefix))
129
- .map((req) => cache.delete(req)),
130
- );
131
- }
1
+ // Service worker that serves ProfileVFS-backed assets at /__vfs/<connectionId>/<path>.
2
+ // The page is the source of truth for VFS contents (the SW can't share folder
3
+ // handles or always-open the same IDB store), so each request round-trips to
4
+ // the client via MessageChannel.
5
+
6
+ const CACHE_NAME = 'mudix-vfs-v1';
7
+ // Scope path always ends with '/'. On a root-served deploy this is '/'; on
8
+ // GitHub Pages or any subpath deploy it's '/<repo>/'. The intercept prefix is
9
+ // '<scope>__vfs/' so SW-controlled URLs stay inside scope.
10
+ const SCOPE_PATH = new URL(self.registration.scope).pathname;
11
+ const PREFIX = `${SCOPE_PATH}__vfs/`;
12
+ const READ_TIMEOUT_MS = 5000;
13
+
14
+ self.addEventListener('install', () => self.skipWaiting());
15
+ self.addEventListener('activate', (e) => e.waitUntil(self.clients.claim()));
16
+
17
+ self.addEventListener('fetch', (event) => {
18
+ const url = new URL(event.request.url);
19
+ if (url.origin !== self.location.origin) return;
20
+ if (!url.pathname.startsWith(PREFIX)) return;
21
+ event.respondWith(handle(event, url));
22
+ });
23
+
24
+ async function handle(event, url) {
25
+ const rest = url.pathname.slice(PREFIX.length).split('/').filter(Boolean);
26
+ if (rest.length < 2) return new Response('Bad request', { status: 400 });
27
+ const connectionId = decodeURIComponent(rest[0]);
28
+ const filePath = '/' + rest.slice(1).map(decodeURIComponent).join('/');
29
+
30
+ const cache = await caches.open(CACHE_NAME);
31
+ const cached = await cache.match(event.request);
32
+ if (cached) return cached;
33
+
34
+ const client = await pickClient(event);
35
+ if (!client) {
36
+ // Either there's no app tab loaded (direct URL hit in fresh tab) or
37
+ // the only candidate is the tab currently navigating to this URL.
38
+ return new Response('No app tab loaded; open mudix first', { status: 503 });
39
+ }
40
+
41
+ const reply = await ask(client, { type: 'vfs:read', connectionId, path: filePath });
42
+ if (!reply || !reply.ok) {
43
+ return new Response(reply?.error ?? 'Not found', { status: 404 });
44
+ }
45
+
46
+ const headers = new Headers();
47
+ headers.set('Content-Type', reply.contentType || 'application/octet-stream');
48
+ // no-store keeps this response out of the browser's own HTTP cache, which
49
+ // has no validator to revalidate against (we set none) and would otherwise
50
+ // race our explicit Cache Storage entry above — that race is what produced
51
+ // stale 304-with-no-body responses for cached images. The Cache Storage
52
+ // entry (invalidated on writes via postMessage) is the only cache that
53
+ // should own this decision.
54
+ headers.set('Cache-Control', 'no-store');
55
+ const response = new Response(reply.bytes, { headers });
56
+ cache.put(event.request, response.clone()).catch(() => {});
57
+ return response;
58
+ }
59
+
60
+ async function pickClient(event) {
61
+ // Prefer the client that issued this request — for sub-resource fetches
62
+ // that's the loaded app page, which can reply immediately.
63
+ const requestingId = event.clientId || event.resultingClientId || '';
64
+ if (requestingId) {
65
+ const c = await self.clients.get(requestingId);
66
+ if (c && isUsable(c)) return c;
67
+ }
68
+ const all = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });
69
+ const usable = all.filter(isUsable);
70
+ return usable.find((c) => c.focused) ?? usable[0] ?? null;
71
+ }
72
+
73
+ // Skip clients that are themselves navigating to a /__vfs/ URL — those are
74
+ // fresh tabs in the middle of loading the SW response; they have no JS running
75
+ // and can't reply, so picking one guarantees a timeout.
76
+ function isUsable(client) {
77
+ try {
78
+ return !new URL(client.url).pathname.startsWith(PREFIX);
79
+ } catch {
80
+ return false;
81
+ }
82
+ }
83
+
84
+ function ask(client, message) {
85
+ return new Promise((resolve) => {
86
+ const channel = new MessageChannel();
87
+ const timer = setTimeout(() => {
88
+ channel.port1.close();
89
+ resolve({ ok: false, error: 'timeout' });
90
+ }, READ_TIMEOUT_MS);
91
+ channel.port1.onmessage = (e) => {
92
+ clearTimeout(timer);
93
+ channel.port1.close();
94
+ resolve(e.data);
95
+ };
96
+ client.postMessage(message, [channel.port2]);
97
+ });
98
+ }
99
+
100
+ self.addEventListener('message', (event) => {
101
+ const data = event.data;
102
+ if (!data) return;
103
+ if (data.type === 'vfs:invalidate') {
104
+ event.waitUntil(invalidate(data));
105
+ }
106
+ });
107
+
108
+ async function invalidate({ connectionId, path }) {
109
+ if (!connectionId) {
110
+ await caches.delete(CACHE_NAME);
111
+ return;
112
+ }
113
+ const cache = await caches.open(CACHE_NAME);
114
+ const connPrefix = `${PREFIX}${encodeURIComponent(connectionId)}/`;
115
+ const keys = await cache.keys();
116
+ if (path) {
117
+ const segs = path.split('/').filter(Boolean).map(encodeURIComponent).join('/');
118
+ const target = `${connPrefix}${segs}`;
119
+ await Promise.all(
120
+ keys
121
+ .filter((req) => new URL(req.url).pathname === target)
122
+ .map((req) => cache.delete(req)),
123
+ );
124
+ return;
125
+ }
126
+ await Promise.all(
127
+ keys
128
+ .filter((req) => new URL(req.url).pathname.startsWith(connPrefix))
129
+ .map((req) => cache.delete(req)),
130
+ );
131
+ }
package/dist-lib/vite.js CHANGED
@@ -95,6 +95,28 @@ export default function mudix() {
95
95
  {
96
96
  name: 'mudix:config',
97
97
  config: () => ({
98
+ resolve: {
99
+ // Exactly one React instance, always. `mudlet-map-editor`
100
+ // declares react/react-dom as plain *dependencies* (not
101
+ // peers), so the moment its range outruns the range the
102
+ // app resolved, the package manager nests a second copy
103
+ // under the editor. The editor's `App` is then rendered by
104
+ // mudix's React while its hooks come from the nested one,
105
+ // whose dispatcher is null — "Invalid hook call", and with
106
+ // no error boundary above the lazy boundary the throw
107
+ // unmounts the whole root, so opening the map editor
108
+ // blanked the entire UI in dev and in production alike.
109
+ // Deduping is the structural fix: it survives the next
110
+ // version skew, and consumers of the library (which
111
+ // externalizes react) get it through this plugin too.
112
+ dedupe: ['react', 'react-dom'],
113
+ },
114
+ // A Mudlet package archive is a zip, not source. `?url` imports
115
+ // get away without this (the explicit query short-circuits
116
+ // import analysis), but `?inline` — which the busted fixtures
117
+ // use to carry an archive into the VFS — reaches the asset
118
+ // pipeline and needs the extension declared.
119
+ assetsInclude: ['**/*.mpackage'],
98
120
  optimizeDeps: {
99
121
  // 'mudix': the library entry carries relative `?url` asset
100
122
  // imports (external in the lib build); the dep optimizer's
package/package.json CHANGED
@@ -1,93 +1,97 @@
1
- {
2
- "name": "@mudlet/mudlet-web",
3
- "version": "0.3.0",
4
- "type": "module",
5
- "description": "Mudlet Web — Mudlet in the browser, usable standalone or as a library for branded builds",
6
- "license": "GPL-2.0-or-later",
7
- "keywords": [
8
- "mud",
9
- "mudlet",
10
- "mud-client",
11
- "telnet",
12
- "lua",
13
- "game"
14
- ],
15
- "homepage": "https://github.com/Mudlet/mudlet-web",
16
- "repository": {
17
- "url": "git+https://github.com/Mudlet/mudlet-web.git"
18
- },
19
- "publishConfig": {
20
- "access": "public"
21
- },
22
- "exports": {
23
- ".": {
24
- "types": "./dist-lib/index.d.ts",
25
- "import": "./dist-lib/index.js"
26
- },
27
- "./vite": {
28
- "types": "./dist-lib/vite.d.ts",
29
- "import": "./dist-lib/vite.js"
30
- },
31
- "./styles.css": "./dist-lib/styles.css"
32
- },
33
- "main": "./dist-lib/index.js",
34
- "types": "./dist-lib/index.d.ts",
35
- "files": [
36
- "dist-lib"
37
- ],
38
- "scripts": {
39
- "dev": "vite",
40
- "build": "tsc && vite build",
41
- "build:lib": "vite build --config vite.lib.config.ts && tsc -p tsconfig.lib.json && tsc -p tsconfig.vite-plugin.json && node scripts/copy-lib-assets.mjs",
42
- "prepublishOnly": "yarn build:lib",
43
- "preview": "vite preview",
44
- "typecheck": "tsc -p tsconfig.test.json",
45
- "test": "vitest run",
46
- "test:watch": "vitest",
47
- "dev:busted": "vite --mode busted --port 5174 --strictPort",
48
- "pretest:e2e": "npm run gen:busted-manifest",
49
- "test:e2e": "playwright test",
50
- "gen:busted-manifest": "playwright test -c playwright.manifest.config.ts",
51
- "sync:mudlet-specs": "node scripts/sync-mudlet-specs.mjs"
52
- },
53
- "dependencies": {
54
- "@codemirror/autocomplete": "^6.20.1",
55
- "@codemirror/commands": "^6.10.3",
56
- "@codemirror/lang-json": "^6.0.2",
57
- "@codemirror/language": "^6.12.3",
58
- "@codemirror/legacy-modes": "^6.5.2",
59
- "@codemirror/state": "^6.6.0",
60
- "@codemirror/theme-one-dark": "^6.1.3",
61
- "@codemirror/view": "^6.41.1",
62
- "@sqlite.org/sqlite-wasm": "^3.53.0-build1",
63
- "@types/dompurify": "^3.0.5",
64
- "@zenfs/core": "^2.5.6",
65
- "@zenfs/dom": "^1.2.9",
66
- "dompurify": "^3.4.12",
67
- "fflate": "^0.8.2",
68
- "lucide-react": "^1.14.0",
69
- "marked": "^18.0.4",
70
- "mudlet-map-binary-reader": "^1.2.0",
71
- "mudlet-map-editor": "^1.3.1",
72
- "mudlet-map-renderer": "^2.6.1",
73
- "pako": "^2.1.0",
74
- "pcre2-wasm-universal": "^1.0.0",
75
- "react": "^19.2.0",
76
- "react-dom": "^19.2.0",
77
- "vite-plugin-node-polyfills": "^0.26.0",
78
- "wasmoon-lua5.1": "^1.18.10",
79
- "zustand": "^5.0.12"
80
- },
81
- "devDependencies": {
82
- "@playwright/test": "^1.61.1",
83
- "@types/node": "^25.6.0",
84
- "@types/pako": "^2.0.0",
85
- "@types/react": "^19.2.0",
86
- "@types/react-dom": "^19.2.0",
87
- "@vitejs/plugin-react": "^6.0.1",
88
- "happy-dom": "^20.9.0",
89
- "typescript": "^5.0.0",
90
- "vite": "8.0.16",
91
- "vitest": "^4.1.7"
92
- }
93
- }
1
+ {
2
+ "name": "@mudlet/mudlet-web",
3
+ "version": "0.4.0",
4
+ "type": "module",
5
+ "description": "Mudlet Web — Mudlet in the browser, usable standalone or as a library for branded builds",
6
+ "license": "GPL-2.0-or-later",
7
+ "keywords": [
8
+ "mud",
9
+ "mudlet",
10
+ "mud-client",
11
+ "telnet",
12
+ "lua",
13
+ "game"
14
+ ],
15
+ "homepage": "https://github.com/Mudlet/mudlet-web",
16
+ "repository": {
17
+ "url": "git+https://github.com/Mudlet/mudlet-web.git"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist-lib/index.d.ts",
25
+ "import": "./dist-lib/index.js"
26
+ },
27
+ "./vite": {
28
+ "types": "./dist-lib/vite.d.ts",
29
+ "import": "./dist-lib/vite.js"
30
+ },
31
+ "./styles.css": "./dist-lib/styles.css"
32
+ },
33
+ "main": "./dist-lib/index.js",
34
+ "types": "./dist-lib/index.d.ts",
35
+ "files": [
36
+ "dist-lib"
37
+ ],
38
+ "scripts": {
39
+ "dev": "vite",
40
+ "build": "tsc && vite build",
41
+ "build:lib": "vite build --config vite.lib.config.ts && tsc -p tsconfig.lib.json && tsc -p tsconfig.vite-plugin.json && node scripts/copy-lib-assets.mjs",
42
+ "prepublishOnly": "yarn build:lib",
43
+ "preview": "vite preview",
44
+ "typecheck": "tsc -p tsconfig.test.json",
45
+ "test": "vitest run",
46
+ "test:watch": "vitest",
47
+ "dev:busted": "vite --mode busted --port 5174 --strictPort",
48
+ "test:e2e": "playwright test",
49
+ "busted:failures": "playwright test -c playwright.failures.config.ts",
50
+ "sync:mudlet-specs": "node scripts/sync-mudlet-specs.mjs",
51
+ "sync:mudlet-lua": "node scripts/sync-mudlet-lua.mjs",
52
+ "sync:mudlet-games": "node scripts/sync-mudlet-games.mjs"
53
+ },
54
+ "dependencies": {
55
+ "@codemirror/autocomplete": "^6.20.1",
56
+ "@codemirror/commands": "^6.10.3",
57
+ "@codemirror/lang-json": "^6.0.2",
58
+ "@codemirror/language": "^6.12.3",
59
+ "@codemirror/legacy-modes": "^6.5.2",
60
+ "@codemirror/state": "^6.6.0",
61
+ "@codemirror/theme-one-dark": "^6.1.3",
62
+ "@codemirror/view": "^6.41.1",
63
+ "@sqlite.org/sqlite-wasm": "^3.53.0-build1",
64
+ "@types/dompurify": "^3.0.5",
65
+ "@zenfs/core": "^2.5.6",
66
+ "@zenfs/dom": "^1.2.9",
67
+ "dompurify": "^3.4.14",
68
+ "fflate": "^0.8.2",
69
+ "lucide-react": "^1.14.0",
70
+ "marked": "^18.0.4",
71
+ "mudlet-map-binary-reader": "^1.2.0",
72
+ "mudlet-map-editor": "^1.3.2",
73
+ "mudlet-map-renderer": "^2.6.1",
74
+ "pako": "^2.1.0",
75
+ "pcre2-wasm-universal": "^1.0.0",
76
+ "react": "^19.2.0",
77
+ "react-dom": "^19.2.0",
78
+ "vite-plugin-node-polyfills": "^0.26.0",
79
+ "wasmoon-lua5.1": "^1.18.10",
80
+ "zustand": "^5.0.12"
81
+ },
82
+ "devDependencies": {
83
+ "@playwright/test": "^1.61.1",
84
+ "@types/node": "^25.6.0",
85
+ "@types/pako": "^2.0.0",
86
+ "@types/react": "^19.2.0",
87
+ "@types/react-dom": "^19.2.0",
88
+ "@vitejs/plugin-react": "^6.0.1",
89
+ "happy-dom": "^20.9.0",
90
+ "typescript": "^5.0.0",
91
+ "vite": "8.0.16",
92
+ "vitest": "^4.1.7"
93
+ },
94
+ "resolutions": {
95
+ "dompurify": "^3.4.14"
96
+ }
97
+ }
@@ -1,8 +0,0 @@
1
- import type { ProfileVFS } from '../../../scripting/vfs/ProfileVFS';
2
- interface Props {
3
- vfs: ProfileVFS;
4
- onClose: () => void;
5
- onPick: (absolutePath: string) => void;
6
- }
7
- export declare function VfsModulePickerModal({ vfs, onClose, onPick }: Props): import("react/jsx-runtime").JSX.Element;
8
- export {};