@kenjura/ursa 0.9.0 → 0.32.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/CHANGELOG.md +163 -0
- package/README.md +182 -19
- package/bin/ursa.js +208 -0
- package/lib/index.js +7 -2
- package/meta/character-sheet-template.html +2 -0
- package/meta/default-template.html +29 -5
- package/meta/default.css +451 -115
- package/meta/menu.js +371 -0
- package/meta/search.js +208 -0
- package/meta/sectionify.js +36 -0
- package/meta/sticky.js +73 -0
- package/meta/toc-generator.js +124 -0
- package/meta/toc.js +93 -0
- package/package.json +25 -4
- package/src/helper/WikiImage.js +138 -0
- package/src/helper/automenu.js +211 -55
- package/src/helper/contentHash.js +71 -0
- package/src/helper/fileExists.js +13 -0
- package/src/helper/findStyleCss.js +26 -0
- package/src/helper/linkValidator.js +246 -0
- package/src/helper/metadataExtractor.js +19 -8
- package/src/helper/whitelistFilter.js +66 -0
- package/src/helper/wikitextHelper.js +6 -3
- package/src/index.js +4 -3
- package/src/jobs/generate.js +366 -117
- package/src/serve.js +138 -37
- package/.nvmrc +0 -1
- package/.vscode/launch.json +0 -20
- package/TODO.md +0 -16
- package/nodemon.json +0 -16
package/src/serve.js
CHANGED
|
@@ -1,29 +1,135 @@
|
|
|
1
1
|
import express from "express";
|
|
2
2
|
import watch from "node-watch";
|
|
3
|
-
|
|
4
3
|
import { generate } from "./jobs/generate.js";
|
|
5
4
|
import { join, resolve } from "path";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import { promises } from "fs";
|
|
7
|
+
const { readdir } = promises;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configurable serve function for CLI and library use
|
|
11
|
+
*/
|
|
12
|
+
export async function serve({
|
|
13
|
+
_source,
|
|
14
|
+
_meta,
|
|
15
|
+
_output,
|
|
16
|
+
port = 8080,
|
|
17
|
+
_whitelist = null,
|
|
18
|
+
_clean = false
|
|
19
|
+
} = {}) {
|
|
20
|
+
const sourceDir = resolve(_source);
|
|
21
|
+
const metaDir = resolve(_meta);
|
|
22
|
+
const outputDir = resolve(_output);
|
|
6
23
|
|
|
7
|
-
|
|
8
|
-
const meta = resolve(process.env.META ?? join(process.cwd(), "meta"));
|
|
9
|
-
const output = resolve(process.env.OUTPUT ?? join(process.cwd(), "build"));
|
|
24
|
+
console.log({ source: sourceDir, meta: metaDir, output: outputDir, port, whitelist: _whitelist, clean: _clean });
|
|
10
25
|
|
|
11
|
-
|
|
26
|
+
// Initial generation (use _clean flag only for initial generation)
|
|
27
|
+
console.log("Generating initial site...");
|
|
28
|
+
await generate({ _source: sourceDir, _meta: metaDir, _output: outputDir, _whitelist, _clean });
|
|
29
|
+
console.log("Initial generation complete. Starting server...");
|
|
12
30
|
|
|
13
|
-
|
|
14
|
-
|
|
31
|
+
// Start file server
|
|
32
|
+
serveFiles(outputDir, port);
|
|
15
33
|
|
|
16
|
-
|
|
34
|
+
// Watch for changes
|
|
35
|
+
console.log("Watching for file changes...");
|
|
36
|
+
|
|
37
|
+
// Meta changes trigger full rebuild (templates, CSS, etc. affect all pages)
|
|
38
|
+
watch(metaDir, { recursive: true, filter: /\.(js|json|css|html|md|txt|yml|yaml)$/ }, async (evt, name) => {
|
|
39
|
+
console.log(`Meta files changed! Event: ${evt}, File: ${name}`);
|
|
40
|
+
console.log("Full rebuild required (meta files affect all pages)...");
|
|
41
|
+
try {
|
|
42
|
+
await generate({ _source: sourceDir, _meta: metaDir, _output: outputDir, _whitelist, _clean: true });
|
|
43
|
+
console.log("Regeneration complete.");
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error("Error during regeneration:", error.message);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
17
48
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
49
|
+
// Source changes use incremental mode (only regenerate changed files)
|
|
50
|
+
// Exception: CSS changes require full rebuild since they're embedded in all pages
|
|
51
|
+
watch(sourceDir, { recursive: true, filter: /\.(js|json|css|html|md|txt|yml|yaml)$/ }, async (evt, name) => {
|
|
52
|
+
console.log(`Source files changed! Event: ${evt}, File: ${name}`);
|
|
53
|
+
|
|
54
|
+
// CSS files affect all pages (embedded styles), so trigger full rebuild
|
|
55
|
+
const isCssChange = name && name.endsWith('.css');
|
|
56
|
+
if (isCssChange) {
|
|
57
|
+
console.log("CSS change detected - full rebuild required...");
|
|
58
|
+
try {
|
|
59
|
+
await generate({ _source: sourceDir, _meta: metaDir, _output: outputDir, _whitelist, _clean: true });
|
|
60
|
+
console.log("Regeneration complete.");
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error("Error during regeneration:", error.message);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.log("Incremental rebuild...");
|
|
66
|
+
try {
|
|
67
|
+
await generate({ _source: sourceDir, _meta: metaDir, _output: outputDir, _whitelist });
|
|
68
|
+
console.log("Regeneration complete.");
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error("Error during regeneration:", error.message);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
22
74
|
|
|
23
|
-
|
|
24
|
-
console.log("
|
|
25
|
-
|
|
26
|
-
|
|
75
|
+
console.log(`🚀 Development server running at http://localhost:${port}`);
|
|
76
|
+
console.log("📁 Serving files from:", outputDir);
|
|
77
|
+
console.log("👀 Watching for changes in:");
|
|
78
|
+
console.log(" Source:", sourceDir, "(incremental)");
|
|
79
|
+
console.log(" Meta:", metaDir, "(full rebuild)");
|
|
80
|
+
console.log("\nPress Ctrl+C to stop the server");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Start HTTP server to serve static files
|
|
85
|
+
*/
|
|
86
|
+
function serveFiles(outputDir, port = 8080) {
|
|
87
|
+
const app = express();
|
|
88
|
+
|
|
89
|
+
app.use(
|
|
90
|
+
express.static(outputDir, { extensions: ["html"], index: "index.html" })
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
app.get("/", async (req, res) => {
|
|
94
|
+
try {
|
|
95
|
+
console.log({ output: outputDir });
|
|
96
|
+
const dir = await readdir(outputDir);
|
|
97
|
+
const html = `
|
|
98
|
+
<!DOCTYPE html>
|
|
99
|
+
<html>
|
|
100
|
+
<head>
|
|
101
|
+
<title>Ursa Development Server</title>
|
|
102
|
+
<style>
|
|
103
|
+
body { font-family: Arial, sans-serif; margin: 40px; }
|
|
104
|
+
h1 { color: #333; }
|
|
105
|
+
ul { list-style-type: none; padding: 0; }
|
|
106
|
+
li { margin: 8px 0; }
|
|
107
|
+
a { color: #0066cc; text-decoration: none; }
|
|
108
|
+
a:hover { text-decoration: underline; }
|
|
109
|
+
</style>
|
|
110
|
+
</head>
|
|
111
|
+
<body>
|
|
112
|
+
<h1>Ursa Development Server</h1>
|
|
113
|
+
<p>Files in ${outputDir}:</p>
|
|
114
|
+
<ul>
|
|
115
|
+
${dir
|
|
116
|
+
.map((file) => `<li><a href="${file}">${file}</a></li>`)
|
|
117
|
+
.join("")}
|
|
118
|
+
</ul>
|
|
119
|
+
</body>
|
|
120
|
+
</html>
|
|
121
|
+
`;
|
|
122
|
+
res.setHeader("Content-Type", "text/html");
|
|
123
|
+
res.send(html);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
res.status(500).send("Error reading directory");
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
app.listen(port, () => {
|
|
130
|
+
console.log(`🌐 Server listening on port ${port}`);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
27
133
|
|
|
28
134
|
/**
|
|
29
135
|
* we're only interested in meta (and maybe, in the future, source)
|
|
@@ -39,31 +145,26 @@ function filter(filename, skip) {
|
|
|
39
145
|
return false;
|
|
40
146
|
}
|
|
41
147
|
|
|
42
|
-
|
|
43
|
-
import {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
148
|
+
// Default serve function for backward compatibility (only run when executed directly)
|
|
149
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
150
|
+
const source = resolve(process.env.SOURCE ?? join(process.cwd(), "source"));
|
|
151
|
+
const meta = resolve(process.env.META ?? join(process.cwd(), "meta"));
|
|
152
|
+
const output = resolve(process.env.OUTPUT ?? join(process.cwd(), "build"));
|
|
47
153
|
|
|
48
|
-
|
|
49
|
-
const app = express();
|
|
50
|
-
const port = process.env.PORT || 8080;
|
|
154
|
+
console.log({ source, meta, output });
|
|
51
155
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
);
|
|
156
|
+
await generate({ _source: source, _meta: meta, _output: output });
|
|
157
|
+
console.log("done generating. now serving...");
|
|
55
158
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.join("");
|
|
62
|
-
res.setHeader("Content-Type", "text/html");
|
|
63
|
-
res.send(html);
|
|
159
|
+
serveFiles(output);
|
|
160
|
+
|
|
161
|
+
watch(meta, { recursive: true }, async (evt, name) => {
|
|
162
|
+
console.log("meta files changed! generating output");
|
|
163
|
+
await generate({ _source: source, _meta: meta, _output: output });
|
|
64
164
|
});
|
|
65
165
|
|
|
66
|
-
|
|
67
|
-
console.log(
|
|
166
|
+
watch(source, { recursive: true }, async (evt, name) => {
|
|
167
|
+
console.log("source files changed! generating output");
|
|
168
|
+
await generate({ _source: source, _meta: meta, _output: output });
|
|
68
169
|
});
|
|
69
170
|
}
|
package/.nvmrc
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
16.18
|
package/.vscode/launch.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Use IntelliSense to learn about possible attributes.
|
|
3
|
-
// Hover to view descriptions of existing attributes.
|
|
4
|
-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
-
"version": "0.2.0",
|
|
6
|
-
"configurations": [
|
|
7
|
-
{
|
|
8
|
-
"type": "node",
|
|
9
|
-
"request": "launch",
|
|
10
|
-
"name": "Launch Program",
|
|
11
|
-
"skipFiles": [
|
|
12
|
-
"<node_internals>/**"
|
|
13
|
-
],
|
|
14
|
-
"env": {
|
|
15
|
-
"INCLUDE_FILTER": "Kaine",
|
|
16
|
-
},
|
|
17
|
-
"program": "${workspaceFolder}/src/serve.js"
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
}
|
package/TODO.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Basic Functionality
|
|
2
|
-
|
|
3
|
-
- [x] Enable static assets from meta in build (perhaps by copying them?)
|
|
4
|
-
- [x] Enable static assets from source in build
|
|
5
|
-
- [ ] Handle menus at different levels
|
|
6
|
-
- [x] Add a live-serve command that translates from source in real time (for testing)
|
|
7
|
-
- [ ] Deal with crashes when no menu file is found
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# Wikitext
|
|
11
|
-
- [ ] Support original site styles
|
|
12
|
-
- [ ] Support original menu
|
|
13
|
-
- [ ] Fix links
|
|
14
|
-
|
|
15
|
-
# Mobile UI
|
|
16
|
-
- [ ] Konsta UI
|
package/nodemon.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"restartable": "rs",
|
|
3
|
-
"ignore": [".git", "node_modules/**/node_modules", "build"],
|
|
4
|
-
"verbose": true,
|
|
5
|
-
"execMap": {
|
|
6
|
-
"js": "node --harmony"
|
|
7
|
-
},
|
|
8
|
-
"events": {
|
|
9
|
-
"restart": "osascript -e 'display notification \"App restarted due to:\n'$FILENAME'\" with title \"nodemon\"'"
|
|
10
|
-
},
|
|
11
|
-
"watch": ["src/", "docs/"],
|
|
12
|
-
"env": {
|
|
13
|
-
"NODE_ENV": "development"
|
|
14
|
-
},
|
|
15
|
-
"ext": "js,json,css,cjs,mjs,ts,tsx,html"
|
|
16
|
-
}
|