@lexho111/plainblog 0.0.11 → 0.0.12
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/Blog.js +65 -7
- package/Formatter.js +4 -19
- package/blog +0 -0
- package/blog.db +0 -0
- package/model/DatabaseModel.js +3 -1
- package/package.json +1 -1
- package/scripts.min.js +2 -0
- package/styles.min.css +1 -0
- package/test/server.test.js +1 -1
- package/test_1766398288732 +0 -0
- package/test_1766400137370.db +0 -0
- package/test_1766400274284.db +0 -0
- package/test_1766400505629.db +0 -0
- package/test_1766400546097.db +0 -0
- package/test_1766400566357.db +0 -0
- package/test_1766400610192.db +0 -0
package/Blog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import http from "http";
|
|
2
|
-
import
|
|
2
|
+
import fs from "fs";
|
|
3
3
|
import { URLSearchParams } from "url";
|
|
4
4
|
import { fromEvent, firstValueFrom } from "rxjs";
|
|
5
5
|
import { map, scan, takeUntil, last, defaultIfEmpty } from "rxjs/operators";
|
|
@@ -8,12 +8,15 @@ import DatabaseModel from "./model/DatabaseModel.js";
|
|
|
8
8
|
import { fetchData, postData } from "./model/APIModel.js";
|
|
9
9
|
import { save as saveToFile, load as loadFromFile } from "./model/fileModel.js";
|
|
10
10
|
import { formatHTML, formatMarkdown, validate } from "./Formatter.js";
|
|
11
|
+
import pkg from "./package.json" with { type: "json" };;
|
|
12
|
+
import path from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
11
14
|
|
|
12
15
|
export default class Blog {
|
|
13
16
|
constructor() {
|
|
14
17
|
this.title = "";
|
|
15
18
|
this.articles = [];
|
|
16
|
-
this.
|
|
19
|
+
this.styles = "";
|
|
17
20
|
this.filename = null;
|
|
18
21
|
this.#server = null;
|
|
19
22
|
|
|
@@ -24,6 +27,43 @@ export default class Blog {
|
|
|
24
27
|
host: "localhost",
|
|
25
28
|
dbname: "blog",
|
|
26
29
|
};
|
|
30
|
+
|
|
31
|
+
const version = pkg.version;
|
|
32
|
+
console.log(`version: ${version}`);
|
|
33
|
+
|
|
34
|
+
this.loadScripts();
|
|
35
|
+
|
|
36
|
+
if(this.styles.length == 0) { // no style override specified via index.js
|
|
37
|
+
this.styles = "body { font-family: Arial; }"; // apply default style
|
|
38
|
+
this.loadStyles();
|
|
39
|
+
}
|
|
40
|
+
//console.log(styles)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
loadScripts() {
|
|
44
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
45
|
+
const __dirname = path.dirname(__filename);
|
|
46
|
+
this.scripts = "";
|
|
47
|
+
try {
|
|
48
|
+
console.log("load scripts")
|
|
49
|
+
this.scripts = fs.readFileSync(
|
|
50
|
+
path.join(__dirname, "scripts.min.js"),
|
|
51
|
+
"utf-8"
|
|
52
|
+
);
|
|
53
|
+
} catch(err) {
|
|
54
|
+
console.error("no scripts.min.js file found")
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
loadStyles() {
|
|
59
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
60
|
+
const __dirname = path.dirname(__filename);
|
|
61
|
+
try {
|
|
62
|
+
this.styles = fs.readFileSync(
|
|
63
|
+
path.join(__dirname, "styles.min.css"), "utf-8");
|
|
64
|
+
} catch(err) {
|
|
65
|
+
console.error("no styles.min.css file found")
|
|
66
|
+
}
|
|
27
67
|
}
|
|
28
68
|
|
|
29
69
|
// Private fields
|
|
@@ -41,11 +81,19 @@ export default class Blog {
|
|
|
41
81
|
}
|
|
42
82
|
|
|
43
83
|
setStyle(style) {
|
|
44
|
-
this.
|
|
84
|
+
this.styles = style;
|
|
45
85
|
}
|
|
46
86
|
|
|
47
87
|
/** initializes database */
|
|
48
88
|
async init() {
|
|
89
|
+
try {
|
|
90
|
+
this.styles = fs.readFileSync(
|
|
91
|
+
new URL("./styles.min.css", import.meta.url),
|
|
92
|
+
"utf-8"
|
|
93
|
+
);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
console.error("Failed to load styles.min.css:", err);
|
|
96
|
+
}
|
|
49
97
|
if (this.#isExternalAPI) {
|
|
50
98
|
console.log("external API");
|
|
51
99
|
await this.loadFromAPI();
|
|
@@ -126,6 +174,8 @@ export default class Blog {
|
|
|
126
174
|
} else if (req.method === "GET" && req.url === "/") {
|
|
127
175
|
// load articles
|
|
128
176
|
|
|
177
|
+
this.loadScripts(); this.loadStyles();
|
|
178
|
+
|
|
129
179
|
const html = await this.toHTML(); // render this blog to HTML
|
|
130
180
|
res.writeHead(200, { "Content-Type": "text/html; charset=UTF-8" });
|
|
131
181
|
res.end(html);
|
|
@@ -199,8 +249,16 @@ export default class Blog {
|
|
|
199
249
|
// controller
|
|
200
250
|
/** everything that happens in /api */
|
|
201
251
|
async #jsonAPI(req, res) {
|
|
252
|
+
if(req.method === "GET") {
|
|
253
|
+
if(req.url === "/api" || req.url === "/api/") {
|
|
254
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
255
|
+
const data = {
|
|
256
|
+
title: this.title
|
|
257
|
+
}
|
|
258
|
+
res.end(JSON.stringify(data));
|
|
259
|
+
}
|
|
202
260
|
// GET all blog data
|
|
203
|
-
if (req.
|
|
261
|
+
if (req.url === "/api/articles") {
|
|
204
262
|
// controller
|
|
205
263
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
206
264
|
const dbArticles = await this.#databaseModel.findAll();
|
|
@@ -213,7 +271,7 @@ export default class Blog {
|
|
|
213
271
|
}
|
|
214
272
|
|
|
215
273
|
// POST a new article
|
|
216
|
-
|
|
274
|
+
} else if (req.method === "POST" && req.url === "/api/articles") {
|
|
217
275
|
let body = "";
|
|
218
276
|
req.on("data", (chunk) => (body += chunk.toString()));
|
|
219
277
|
req.on("end", async () => {
|
|
@@ -249,10 +307,10 @@ export default class Blog {
|
|
|
249
307
|
toHTML() {
|
|
250
308
|
const data = {
|
|
251
309
|
title: this.title,
|
|
252
|
-
style: this.style,
|
|
253
310
|
articles: this.articles,
|
|
254
311
|
};
|
|
255
|
-
|
|
312
|
+
|
|
313
|
+
const html = formatHTML(data, this.scripts, this.styles);
|
|
256
314
|
if (validate(html)) return html;
|
|
257
315
|
else throw new Error("Error. Invalid HTML!");
|
|
258
316
|
}
|
package/Formatter.js
CHANGED
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
/** format content to html */
|
|
2
|
-
export function formatHTML(data) {
|
|
3
|
-
|
|
4
|
-
let str = "";
|
|
5
|
-
const char = "A";
|
|
6
|
-
for (let i = 0; i < length; i++) {
|
|
7
|
-
const rnd = Math.random() * ("z".charCodeAt(0) - "A".charCodeAt(0)); // A z.charCodeAt(0)"
|
|
8
|
-
const char1 = String.fromCharCode(char.charCodeAt(0) + rnd);
|
|
9
|
-
str += char1;
|
|
10
|
-
}
|
|
11
|
-
return str;
|
|
12
|
-
}
|
|
13
|
-
function fillWithContent() {
|
|
14
|
-
let title = document.getElementById("title");
|
|
15
|
-
let cont = document.getElementById("content");
|
|
16
|
-
cont.value = generateRandomContent(200);
|
|
17
|
-
title.value = generateRandomContent(50);
|
|
18
|
-
}`;
|
|
2
|
+
export function formatHTML(data, script, style) {
|
|
3
|
+
//export function formatHTML(data) {
|
|
19
4
|
const button = `<button type="button" onClick="fillWithContent();" style="margin: 4px;">generate random text</button>`;
|
|
20
5
|
return `<!DOCTYPE html>
|
|
21
6
|
<html lang="de">
|
|
22
7
|
<head>
|
|
23
8
|
<meta charset="UTF-8">
|
|
24
9
|
<title>${data.title}</title>
|
|
25
|
-
<style>${
|
|
10
|
+
<style>${style}</style>
|
|
26
11
|
</head>
|
|
27
12
|
<body>
|
|
28
13
|
<h1>${data.title}</h1>
|
|
@@ -31,7 +16,7 @@ export function formatHTML(data) {
|
|
|
31
16
|
<h3>Add a New Article</h3>
|
|
32
17
|
<input type="text" id="title" name="title" placeholder="Article Title" required style="display: block; width: 300px; margin-bottom: 10px;">
|
|
33
18
|
<textarea id="content" name="content" placeholder="Article Content" required style="display: block; width: 300px; height: 100px; margin-bottom: 10px;"></textarea>
|
|
34
|
-
<button type="submit">Add Article</button
|
|
19
|
+
<button type="submit">Add Article</button>${button}
|
|
35
20
|
<script>
|
|
36
21
|
${script}
|
|
37
22
|
</script>
|
package/blog
ADDED
|
Binary file
|
package/blog.db
CHANGED
|
Binary file
|
package/model/DatabaseModel.js
CHANGED
|
@@ -14,9 +14,11 @@ export default class DatabaseModel {
|
|
|
14
14
|
constructor(options) {
|
|
15
15
|
const databasetype = options.type; // the database type defines
|
|
16
16
|
if (databasetype === "sqlite") {
|
|
17
|
+
// Use the full path for the database file from the options.
|
|
18
|
+
if (options.dbname) this.#dbname = options.dbname;
|
|
17
19
|
this.#sequelize = new Sequelize({
|
|
18
20
|
dialect: "sqlite",
|
|
19
|
-
storage:
|
|
21
|
+
storage: this.#dbname + ".db",
|
|
20
22
|
logging: false,
|
|
21
23
|
});
|
|
22
24
|
} else if (databasetype === "postgres") {
|
package/package.json
CHANGED
package/scripts.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! gruntproject 2025-12-21 */
|
|
2
|
+
function generateRandomContent(t){let n="";for(let e=0;e<t;e++){var o=Math.random()*("z".charCodeAt(0)-"A".charCodeAt(0)),o=String.fromCharCode("A".charCodeAt(0)+o);n+=o}return n}function fillWithContent(){var e=document.getElementById("title");document.getElementById("content").value=generateRandomContent(200),e.value=generateRandomContent(50)}
|
package/styles.min.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
body{font-family:Courier;background-color:#d3d3d3}div{color:#000;width:500px}h1,h2,h3{font-weight:700}
|
package/test/server.test.js
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|