Skip to content

Commit cd3079c

Browse files
Add --mashlib-module flag for ES module data browser
Adds a new --mashlib-module <url> option that serves an ES module-based data browser instead of the classic script-based mashlib. Uses <script type="module"> and <div id="mashlib"> (self-initializing). Backwards compatible: existing --mashlib and --mashlib-cdn unchanged. Closes JavaScriptSolidServer#140
1 parent 787bc72 commit cd3079c

5 files changed

Lines changed: 38 additions & 8 deletions

File tree

bin/jss.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ program
5555
.option('--base-domain <domain>', 'Base domain for subdomain pods (e.g., "example.com")')
5656
.option('--mashlib', 'Enable Mashlib data browser (local mode, requires mashlib in node_modules)')
5757
.option('--mashlib-cdn', 'Enable Mashlib data browser (CDN mode, no local files needed)')
58+
.option('--mashlib-module <url>', 'Enable ES module data browser from a URL')
5859
.option('--no-mashlib', 'Disable Mashlib data browser')
5960
.option('--mashlib-version <version>', 'Mashlib version for CDN mode (default: 2.0.0)')
6061
.option('--solidos-ui', 'Enable modern Nextcloud-style UI (requires --mashlib)')
@@ -123,6 +124,7 @@ program
123124
mashlib: config.mashlib || config.mashlibCdn,
124125
mashlibCdn: config.mashlibCdn,
125126
mashlibVersion: config.mashlibVersion,
127+
mashlibModule: config.mashlibModule,
126128
solidosUi: config.solidosUi,
127129
git: config.git,
128130
nostr: config.nostr,
@@ -158,6 +160,7 @@ program
158160
} else if (config.mashlib) {
159161
console.log(` Mashlib: local (data browser enabled)`);
160162
}
163+
if (config.mashlibModule) console.log(` Mashlib module: ${config.mashlibModule}`);
161164
if (config.solidosUi) console.log(' SolidOS UI: enabled (modern interface)');
162165
if (config.git) console.log(' Git: enabled (clone/push support)');
163166
if (config.nostr) console.log(` Nostr: enabled (${config.nostrPath})`);

src/config.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const defaults = {
4141
mashlib: false,
4242
mashlibCdn: false,
4343
mashlibVersion: '2.0.0',
44+
mashlibModule: false,
4445

4546
// SolidOS UI (modern Nextcloud-style interface)
4647
solidosUi: false,
@@ -113,6 +114,7 @@ const envMap = {
113114
JSS_MASHLIB: 'mashlib',
114115
JSS_MASHLIB_CDN: 'mashlibCdn',
115116
JSS_MASHLIB_VERSION: 'mashlibVersion',
117+
JSS_MASHLIB_MODULE: 'mashlibModule',
116118
JSS_SOLIDOS_UI: 'solidosUi',
117119
JSS_GIT: 'git',
118120
JSS_NOSTR: 'nostr',
@@ -238,7 +240,7 @@ export async function loadConfig(cliOptions = {}, configFile = null) {
238240
}
239241

240242
// Mashlib requires content negotiation for Turtle support
241-
if (config.mashlib || config.mashlibCdn) {
243+
if (config.mashlib || config.mashlibCdn || config.mashlibModule) {
242244
config.conneg = true;
243245
}
244246

@@ -293,7 +295,7 @@ export function printConfig(config) {
293295
console.log(` Notifications: ${config.notifications}`);
294296
console.log(` IdP: ${config.idp ? (config.idpIssuer || 'enabled') : 'disabled'}`);
295297
console.log(` Subdomains: ${config.subdomains ? (config.baseDomain || 'enabled') : 'disabled'}`);
296-
console.log(` Mashlib: ${config.mashlibCdn ? `CDN v${config.mashlibVersion}` : config.mashlib ? 'local' : 'disabled'}`);
298+
console.log(` Mashlib: ${config.mashlibModule ? `module (${config.mashlibModule})` : config.mashlibCdn ? `CDN v${config.mashlibVersion}` : config.mashlib ? 'local' : 'disabled'}`);
297299
console.log(` SolidOS UI: ${config.solidosUi ? 'enabled' : 'disabled'}`);
298300
console.log('─'.repeat(40));
299301
}

src/handlers/resource.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
} from '../rdf/conneg.js';
1616
import { emitChange } from '../notifications/events.js';
1717
import { checkIfMatch, checkIfNoneMatchForGet, checkIfNoneMatchForWrite } from '../utils/conditional.js';
18-
import { generateDatabrowserHtml, generateSolidosUiHtml, shouldServeMashlib } from '../mashlib/index.js';
18+
import { generateDatabrowserHtml, generateModuleDatabrowserHtml, generateSolidosUiHtml, shouldServeMashlib } from '../mashlib/index.js';
1919

2020
/**
2121
* Live reload script - injected into HTML when --live-reload is enabled
@@ -230,10 +230,12 @@ export async function handleGet(request, reply) {
230230

231231
// Check if we should serve Mashlib data browser for containers
232232
if (shouldServeMashlib(request, request.mashlibEnabled, 'application/ld+json')) {
233-
// Use SolidOS UI if enabled, otherwise fallback to classic mashlib
233+
// Use SolidOS UI if enabled, ES module if configured, otherwise classic mashlib
234234
const html = request.solidosUiEnabled
235235
? generateSolidosUiHtml()
236-
: generateDatabrowserHtml(resourceUrl, request.mashlibCdn ? request.mashlibVersion : null);
236+
: request.mashlibModule
237+
? generateModuleDatabrowserHtml(request.mashlibModule)
238+
: generateDatabrowserHtml(resourceUrl, request.mashlibCdn ? request.mashlibVersion : null);
237239
const headers = getAllHeaders({
238240
isContainer: true,
239241
etag: stats.etag,
@@ -307,10 +309,12 @@ export async function handleGet(request, reply) {
307309
// Check if we should serve Mashlib data browser
308310
// Only for RDF resources when Accept: text/html is requested
309311
if (shouldServeMashlib(request, request.mashlibEnabled, storedContentType)) {
310-
// Use SolidOS UI if enabled, otherwise fallback to classic mashlib
312+
// Use SolidOS UI if enabled, ES module if configured, otherwise classic mashlib
311313
const html = request.solidosUiEnabled
312314
? generateSolidosUiHtml()
313-
: generateDatabrowserHtml(resourceUrl, request.mashlibCdn ? request.mashlibVersion : null);
315+
: request.mashlibModule
316+
? generateModuleDatabrowserHtml(request.mashlibModule)
317+
: generateDatabrowserHtml(resourceUrl, request.mashlibCdn ? request.mashlibVersion : null);
314318
const headers = getAllHeaders({
315319
isContainer: false,
316320
etag: stats.etag,

src/mashlib/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,23 @@ export function generateDatabrowserHtml(resourceUrl, cdnVersion = null) {
4040
})</script><script defer="defer" src="/mashlib.min.js"></script><link href="/mash.css" rel="stylesheet"></head><body id="PageBody"><header id="PageHeader"></header><div class="TabulatorOutline" id="DummyUUID" role="main"><table id="outline"></table><div id="GlobalDashboard"></div></div><footer id="PageFooter"></footer></body></html>`;
4141
}
4242

43+
/**
44+
* Generate ES module-based databrowser HTML
45+
*
46+
* @param {string} moduleUrl - URL to the ES module entry point
47+
* @returns {string} HTML content
48+
*/
49+
export function generateModuleDatabrowserHtml(moduleUrl) {
50+
const cssUrl = moduleUrl.replace(/\.js$/, '.css');
51+
return `<!doctype html><html lang="en"><head><meta charset="utf-8"/>
52+
<meta name="viewport" content="width=device-width, initial-scale=1">
53+
<title>Solid Data Browser</title>
54+
<link rel="stylesheet" href="${cssUrl}"></head>
55+
<body><div id="mashlib"></div>
56+
<script type="module" src="${moduleUrl}"></script>
57+
</body></html>`;
58+
}
59+
4360
/**
4461
* Check if request wants HTML and mashlib should handle it
4562
* @param {object} request - Fastify request

src/server.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ export function createServer(options = {}) {
5454
const baseDomain = options.baseDomain || null;
5555
// Mashlib data browser is OFF by default
5656
// mashlibCdn: if true, load from CDN; if false, serve locally
57-
const mashlibEnabled = options.mashlib ?? false;
57+
// mashlibModule: URL to ES module entry point (alternative to classic mashlib)
58+
const mashlibModule = options.mashlibModule ?? false;
59+
const mashlibEnabled = options.mashlib || !!mashlibModule;
5860
const mashlibCdn = options.mashlibCdn ?? false;
5961
const mashlibVersion = options.mashlibVersion ?? '2.0.0';
6062
// SolidOS UI (modern Nextcloud-style interface) - requires mashlib
@@ -147,6 +149,7 @@ export function createServer(options = {}) {
147149
fastify.decorateRequest('mashlibEnabled', null);
148150
fastify.decorateRequest('mashlibCdn', null);
149151
fastify.decorateRequest('mashlibVersion', null);
152+
fastify.decorateRequest('mashlibModule', null);
150153
fastify.decorateRequest('solidosUiEnabled', null);
151154
fastify.decorateRequest('defaultQuota', null);
152155
fastify.decorateRequest('config', null);
@@ -160,6 +163,7 @@ export function createServer(options = {}) {
160163
request.mashlibEnabled = mashlibEnabled;
161164
request.mashlibCdn = mashlibCdn;
162165
request.mashlibVersion = mashlibVersion;
166+
request.mashlibModule = mashlibModule;
163167
request.solidosUiEnabled = solidosUiEnabled;
164168
request.defaultQuota = defaultQuota;
165169
request.config = { public: options.public, readOnly: options.readOnly };

0 commit comments

Comments
 (0)