@lexho111/plainblog 0.0.11 → 0.1.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/Blog.js +56 -7
- package/Formatter.js +4 -19
- package/README.md +3 -3
- 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/test_1766402245020.db +0 -0
- package/test_1766404090067.db +0 -0
- package/test_1766404289775.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,42 @@ 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
|
+
this.scripts = fs.readFileSync(
|
|
49
|
+
path.join(__dirname, "scripts.min.js"),
|
|
50
|
+
"utf-8"
|
|
51
|
+
);
|
|
52
|
+
} catch(err) {
|
|
53
|
+
console.error("no scripts.min.js file found")
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
loadStyles() {
|
|
58
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
59
|
+
const __dirname = path.dirname(__filename);
|
|
60
|
+
try {
|
|
61
|
+
this.styles = fs.readFileSync(
|
|
62
|
+
path.join(__dirname, "styles.min.css"), "utf-8");
|
|
63
|
+
} catch(err) {
|
|
64
|
+
console.error("no styles.min.css file found")
|
|
65
|
+
}
|
|
27
66
|
}
|
|
28
67
|
|
|
29
68
|
// Private fields
|
|
@@ -41,7 +80,7 @@ export default class Blog {
|
|
|
41
80
|
}
|
|
42
81
|
|
|
43
82
|
setStyle(style) {
|
|
44
|
-
this.
|
|
83
|
+
this.styles = style;
|
|
45
84
|
}
|
|
46
85
|
|
|
47
86
|
/** initializes database */
|
|
@@ -126,6 +165,8 @@ export default class Blog {
|
|
|
126
165
|
} else if (req.method === "GET" && req.url === "/") {
|
|
127
166
|
// load articles
|
|
128
167
|
|
|
168
|
+
//this.loadScripts(); this.loadStyles();
|
|
169
|
+
|
|
129
170
|
const html = await this.toHTML(); // render this blog to HTML
|
|
130
171
|
res.writeHead(200, { "Content-Type": "text/html; charset=UTF-8" });
|
|
131
172
|
res.end(html);
|
|
@@ -199,8 +240,16 @@ export default class Blog {
|
|
|
199
240
|
// controller
|
|
200
241
|
/** everything that happens in /api */
|
|
201
242
|
async #jsonAPI(req, res) {
|
|
243
|
+
if(req.method === "GET") {
|
|
244
|
+
if(req.url === "/api" || req.url === "/api/") {
|
|
245
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
246
|
+
const data = {
|
|
247
|
+
title: this.title
|
|
248
|
+
}
|
|
249
|
+
res.end(JSON.stringify(data));
|
|
250
|
+
}
|
|
202
251
|
// GET all blog data
|
|
203
|
-
if (req.
|
|
252
|
+
if (req.url === "/api/articles") {
|
|
204
253
|
// controller
|
|
205
254
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
206
255
|
const dbArticles = await this.#databaseModel.findAll();
|
|
@@ -213,7 +262,7 @@ export default class Blog {
|
|
|
213
262
|
}
|
|
214
263
|
|
|
215
264
|
// POST a new article
|
|
216
|
-
|
|
265
|
+
} else if (req.method === "POST" && req.url === "/api/articles") {
|
|
217
266
|
let body = "";
|
|
218
267
|
req.on("data", (chunk) => (body += chunk.toString()));
|
|
219
268
|
req.on("end", async () => {
|
|
@@ -249,10 +298,10 @@ export default class Blog {
|
|
|
249
298
|
toHTML() {
|
|
250
299
|
const data = {
|
|
251
300
|
title: this.title,
|
|
252
|
-
style: this.style,
|
|
253
301
|
articles: this.articles,
|
|
254
302
|
};
|
|
255
|
-
|
|
303
|
+
|
|
304
|
+
const html = formatHTML(data, this.scripts, this.styles);
|
|
256
305
|
if (validate(html)) return html;
|
|
257
306
|
else throw new Error("Error. Invalid HTML!");
|
|
258
307
|
}
|
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/README.md
CHANGED
|
@@ -33,7 +33,7 @@ import Blog from "@lexho111/plainblog";
|
|
|
33
33
|
|
|
34
34
|
const blog = new Blog();
|
|
35
35
|
blog.database.type = "postgres";
|
|
36
|
-
blog.database.
|
|
36
|
+
blog.database.username = "user";
|
|
37
37
|
blog.database.password = "password";
|
|
38
38
|
blog.database.host = "localhost";
|
|
39
39
|
blog.setStyle("body { font-family: Arial, sans-serif; } h1 { color: #333; }");
|
|
@@ -67,9 +67,9 @@ blog.setStyle("body { font-family: Arial, sans-serif; } h1 { color: #333; }");
|
|
|
67
67
|
const article = new Article("hello", "hello world!");
|
|
68
68
|
blog.addArticle(article);
|
|
69
69
|
|
|
70
|
-
blog.save("
|
|
70
|
+
blog.save("myblog.json");
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
// load data from 'myblog.json'
|
|
73
73
|
await blog.load("myblog.json");
|
|
74
74
|
```
|
|
75
75
|
|
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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|