@lexho111/plainblog 0.0.3 → 0.0.5
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/Article.js +10 -0
- package/Blog.js +79 -5
- package/README.md +9 -1
- package/package.json +1 -1
package/Article.js
CHANGED
|
@@ -3,4 +3,14 @@ export default class Article {
|
|
|
3
3
|
this.title = title;
|
|
4
4
|
this.content = content;
|
|
5
5
|
}
|
|
6
|
+
|
|
7
|
+
getContent() {
|
|
8
|
+
return this.content;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
getContentShort() {
|
|
12
|
+
let contentShort = this.content.substring(0, 400);
|
|
13
|
+
contentShort += "...";
|
|
14
|
+
return contentShort;
|
|
15
|
+
}
|
|
6
16
|
}
|
package/Blog.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import http from "http";
|
|
2
|
+
import { promises as fs } from "fs";
|
|
3
|
+
import { URLSearchParams } from "url";
|
|
4
|
+
import Article from "./Article.js";
|
|
2
5
|
|
|
3
6
|
export default class Blog {
|
|
4
7
|
constructor() {
|
|
5
8
|
this.title = "";
|
|
6
9
|
this.articles = [];
|
|
7
10
|
this.style = "body { font-family: Arial; }";
|
|
11
|
+
this.filename = null;
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
setTitle(title) {
|
|
@@ -21,8 +25,32 @@ export default class Blog {
|
|
|
21
25
|
|
|
22
26
|
startServer(port = 8080) {
|
|
23
27
|
const server = http.createServer((req, res) => {
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
if (req.method === "POST") {
|
|
29
|
+
let body = "";
|
|
30
|
+
req.on("data", (chunk) => {
|
|
31
|
+
body += chunk.toString();
|
|
32
|
+
});
|
|
33
|
+
req.on("end", async () => {
|
|
34
|
+
const params = new URLSearchParams(body);
|
|
35
|
+
const title = params.get("title");
|
|
36
|
+
const content = params.get("content");
|
|
37
|
+
|
|
38
|
+
if (title && content) {
|
|
39
|
+
this.addArticle(new Article(title, content));
|
|
40
|
+
// Auto-save if a file has been loaded or saved before
|
|
41
|
+
if (this.filename) {
|
|
42
|
+
await this.save();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Redirect to the homepage to show the new article
|
|
47
|
+
res.writeHead(303, { Location: "/" });
|
|
48
|
+
res.end();
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=UTF-8" });
|
|
52
|
+
res.end(this.toHTML());
|
|
53
|
+
}
|
|
26
54
|
});
|
|
27
55
|
|
|
28
56
|
server.listen(port, () => {
|
|
@@ -30,6 +58,33 @@ export default class Blog {
|
|
|
30
58
|
});
|
|
31
59
|
}
|
|
32
60
|
|
|
61
|
+
async save(filename = this.filename) {
|
|
62
|
+
if (!filename) {
|
|
63
|
+
console.error("Error: Filename not provided and not set previously.");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.filename = filename;
|
|
67
|
+
const data = {
|
|
68
|
+
title: this.title,
|
|
69
|
+
articles: this.articles,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
await fs.writeFile(filename, JSON.stringify(data, null, 2));
|
|
74
|
+
console.log(`Blog data saved to ${filename}`);
|
|
75
|
+
} catch (err) {
|
|
76
|
+
console.error("Error saving blog data:", err);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async load(filename) {
|
|
81
|
+
this.filename = filename;
|
|
82
|
+
const data = await fs.readFile(filename, "utf8");
|
|
83
|
+
const { title, articles } = JSON.parse(data);
|
|
84
|
+
this.title = title;
|
|
85
|
+
this.articles = articles;
|
|
86
|
+
}
|
|
87
|
+
|
|
33
88
|
print() {
|
|
34
89
|
console.log(`# ${this.title}`);
|
|
35
90
|
for (const article of this.articles) {
|
|
@@ -39,17 +94,36 @@ export default class Blog {
|
|
|
39
94
|
}
|
|
40
95
|
|
|
41
96
|
toHTML() {
|
|
42
|
-
let html =
|
|
43
|
-
html
|
|
97
|
+
let html = `
|
|
98
|
+
<!DOCTYPE html>
|
|
99
|
+
<html lang="de">
|
|
100
|
+
<head>
|
|
101
|
+
<meta charset="UTF-8">
|
|
102
|
+
<title>${this.title}</title>
|
|
103
|
+
<style>${this.style}</style>
|
|
104
|
+
</head>
|
|
105
|
+
<body>`;
|
|
106
|
+
html += `<h1>${this.title}</h1><div style="width: 500px;">`;
|
|
107
|
+
|
|
108
|
+
html += `
|
|
109
|
+
<form action="/" method="POST">
|
|
110
|
+
<h3>Add a New Article</h3>
|
|
111
|
+
<input type="text" name="title" placeholder="Article Title" required style="display: block; width: 300px; margin-bottom: 10px;">
|
|
112
|
+
<textarea name="content" placeholder="Article Content" required style="display: block; width: 300px; height: 100px; margin-bottom: 10px;"></textarea>
|
|
113
|
+
<button type="submit">Add Article</button>
|
|
114
|
+
</form>
|
|
115
|
+
<hr>`;
|
|
44
116
|
|
|
45
117
|
for (const article of this.articles) {
|
|
46
118
|
html += `
|
|
47
119
|
<article>
|
|
48
120
|
<h2>${article.title}</h2>
|
|
49
|
-
<p>${article.
|
|
121
|
+
<p>${article.getContentShort()}</p>
|
|
50
122
|
</article>`;
|
|
51
123
|
}
|
|
52
124
|
|
|
125
|
+
html += `</div></body></html>`;
|
|
126
|
+
|
|
53
127
|
return html;
|
|
54
128
|
}
|
|
55
129
|
}
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
```
|
|
2
2
|
import { Blog, Article } from "@lexho111/plainblog";
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const bl og = new Blog();
|
|
5
5
|
blog.setTitle("My Blog");
|
|
6
6
|
blog.setStyle("body { font-family: Arial, sans-serif; } h1 { color: #333; }");
|
|
7
7
|
|
|
@@ -15,3 +15,11 @@ const article2 = new Article(
|
|
|
15
15
|
blog.addArticle(article2);
|
|
16
16
|
blog.startServer(8080);
|
|
17
17
|
```
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
# save your blog to 'myblog.json'
|
|
21
|
+
await blog.save("myblog.json");
|
|
22
|
+
|
|
23
|
+
# load data from 'myblog.json'
|
|
24
|
+
await blog.load("myblog.json");
|
|
25
|
+
```
|