@lexho111/plainblog 0.5.23 → 0.5.25
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 +1 -1
- package/README.md +15 -0
- package/api-server.js +70 -0
- package/build-styles.js +2 -1
- package/model/PostgresAdapter.js +2 -1
- package/model/SequelizeAdapter.js +2 -1
- package/model/SqliteAdapter.js +2 -1
- package/package.json +10 -3
- package/public/print.min.css +1 -2
- package/public/styles.min.css +2 -1
- package/src/print.css +71 -0
- package/src/print.css.map +1 -0
- package/src/print.scss +2 -2
package/Blog.js
CHANGED
|
@@ -456,7 +456,7 @@ export default class Blog {
|
|
|
456
456
|
return new Promise((resolve, reject) => {
|
|
457
457
|
const errorHandler = (err) => reject(err);
|
|
458
458
|
this.#server.once("error", errorHandler);
|
|
459
|
-
this.#server.listen(port, "
|
|
459
|
+
this.#server.listen(port, "0.0.0.0", () => { // <-- for docker 0.0.0.0, localhost 127.0.0.1
|
|
460
460
|
this.#server.removeListener("error", errorHandler);
|
|
461
461
|
console.log(`server running at http://localhost:${port}/`);
|
|
462
462
|
resolve(); // Resolve the promise when the server is listening
|
package/README.md
CHANGED
|
@@ -74,6 +74,21 @@ await blog.init(); // load data from database
|
|
|
74
74
|
blog.startServer(8080);
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
The API should respond to GET-Requests (*http://example.com:5432/blog*) with json like this:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
{
|
|
81
|
+
"title": "My Remote Blog",
|
|
82
|
+
"articles": [
|
|
83
|
+
{
|
|
84
|
+
"title": "Welcome to the API Server",
|
|
85
|
+
"content": "This content is served from a separate API server.",
|
|
86
|
+
"createdAt": "2026-01-12T11:21:55.561Z"
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
77
92
|
### provide custom style sheets
|
|
78
93
|
|
|
79
94
|
```
|
package/api-server.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import http from "http";
|
|
2
|
+
|
|
3
|
+
const PORT = 5432;
|
|
4
|
+
|
|
5
|
+
// In-memory data store
|
|
6
|
+
const blogData = {
|
|
7
|
+
title: "My Remote Blog",
|
|
8
|
+
articles: [
|
|
9
|
+
{
|
|
10
|
+
title: "Welcome to the API Server",
|
|
11
|
+
content: "This content is served from a separate API server.",
|
|
12
|
+
createdAt: new Date().toISOString(),
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const server = http.createServer((req, res) => {
|
|
18
|
+
// Set CORS headers to allow requests from the blog application
|
|
19
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
20
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
21
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
22
|
+
|
|
23
|
+
// Handle preflight requests
|
|
24
|
+
if (req.method === "OPTIONS") {
|
|
25
|
+
res.writeHead(204);
|
|
26
|
+
res.end();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
31
|
+
|
|
32
|
+
if (url.pathname === "/blog") {
|
|
33
|
+
if (req.method === "GET") {
|
|
34
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
35
|
+
res.end(JSON.stringify(blogData));
|
|
36
|
+
} else if (req.method === "POST") {
|
|
37
|
+
let body = "";
|
|
38
|
+
req.on("data", (chunk) => (body += chunk.toString()));
|
|
39
|
+
req.on("end", () => {
|
|
40
|
+
try {
|
|
41
|
+
const newArticle = JSON.parse(body);
|
|
42
|
+
if (!newArticle.createdAt) {
|
|
43
|
+
newArticle.createdAt = new Date().toISOString();
|
|
44
|
+
}
|
|
45
|
+
// Add the new article to the beginning of the list
|
|
46
|
+
blogData.articles.unshift(newArticle);
|
|
47
|
+
|
|
48
|
+
console.log("New article received:", newArticle.title);
|
|
49
|
+
|
|
50
|
+
res.writeHead(201, { "Content-Type": "application/json" });
|
|
51
|
+
res.end(JSON.stringify(newArticle));
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error("Error parsing JSON:", error);
|
|
54
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
55
|
+
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
res.writeHead(405); // Method Not Allowed
|
|
60
|
+
res.end();
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
res.writeHead(404); // Not Found
|
|
64
|
+
res.end();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
server.listen(PORT, () => {
|
|
69
|
+
console.log(`API Server running at http://localhost:${PORT}/blog`);
|
|
70
|
+
});
|
package/build-styles.js
CHANGED
|
@@ -56,7 +56,8 @@ async function runPostcss(css) {
|
|
|
56
56
|
postcss = (await import("postcss")).default;
|
|
57
57
|
autoprefixer = (await import("autoprefixer")).default;
|
|
58
58
|
cssnano = (await import("cssnano")).default;
|
|
59
|
-
} catch (
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(err);
|
|
60
61
|
throw new Error("Missing optional dependencies");
|
|
61
62
|
}
|
|
62
63
|
} else {
|
package/model/PostgresAdapter.js
CHANGED
package/model/SqliteAdapter.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lexho111/plainblog",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.25",
|
|
4
4
|
"description": "A tool for creating and serving a minimalist, single-page blog.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -16,14 +16,21 @@
|
|
|
16
16
|
],
|
|
17
17
|
"author": "lexho111",
|
|
18
18
|
"license": "ISC",
|
|
19
|
-
"dependencies": {},
|
|
20
19
|
"devDependencies": {
|
|
21
20
|
"@eslint/js": "^9.39.2",
|
|
22
21
|
"@types/node": "^25.0.3",
|
|
22
|
+
"autoprefixer": "^10.4.23",
|
|
23
|
+
"cssnano": "^7.1.2",
|
|
23
24
|
"eslint": "^9.39.2",
|
|
24
25
|
"eslint-plugin-jest": "^28.6.0",
|
|
25
26
|
"globals": "^17.0.0",
|
|
26
27
|
"jest": "^29.7.0",
|
|
27
|
-
"
|
|
28
|
+
"pg": "^8.16.3",
|
|
29
|
+
"pg-hstore": "^2.3.4",
|
|
30
|
+
"postcss": "^8.5.6",
|
|
31
|
+
"sequelize": "^6.37.7",
|
|
32
|
+
"sqlite3": "^5.1.7",
|
|
33
|
+
"typescript": "^5.9.3",
|
|
34
|
+
"w3c-css-validator": "^1.4.1"
|
|
28
35
|
}
|
|
29
36
|
}
|
package/public/print.min.css
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
*{font-size:.
|
|
2
|
-
/*# sourceMappingURL=print-compiled.css.map */
|
|
1
|
+
*{font-size:.5rem}body{background-color:#fff;color:#000}h1{font:italic small-caps 700 2.5em/2.3em Verdana,sans-serif;letter-spacing:.1em;margin:0;padding:0}#wrapper{max-width:600px;width:100%}.grid{display:grid;grid-template-columns:1fr;grid-gap:.25rem;border:2px solid #d3d3d3;gap:.25rem}.grid article{border:0 solid #ccc;border-radius:4px;min-width:0;padding:.25rem;word-wrap:break-word}.grid article h2{color:#000;margin-bottom:2px}.grid article .datetime{font-style:italic;margin:0}.grid article p{margin-bottom:0;margin-top:10px}.grid article a,.grid article a:link a:visited,h1{color:#000}nav a{color:#3c3c3c;font-size:20px;-webkit-text-decoration:underline;text-decoration:underline}nav a[href*=login]{display:none}nav a:visited{color:#3c3c3c;text-decoration-color:#3c3c3c}
|
package/public/styles.min.css
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
body{font-family:Arial}.grid{border:0 solid #000;display:grid;
|
|
1
|
+
body{font-family:Arial;font-family:Arial,sans-serif}h1{color:#333}.grid{border:0 solid #000;display:grid;gap:.25rem;grid-template-columns:1fr}.grid article{border:0 solid #ccc;border-radius:4px;min-width:0;overflow-wrap:break-word;padding:.25rem}.grid article h2{color:#353535;margin-bottom:5px}.grid article .datetime{color:#757575;margin:0}.grid article p{margin-bottom:0;margin-top:10px}article a,article a:visited,h1{color:#696969}nav a{color:#3b40c1;font-size:20px;text-decoration:underline}nav a:visited{color:#3b40c1;text-decoration-color:#3b40c1}#wrapper{max-width:500px;width:100%}@media screen and (max-width:1000px){*{font-size:4vw}#wrapper{box-sizing:border-box;max-width:100%;padding:0 10px;width:100%}}
|
|
2
|
+
/* source-hash: a07f631befba4b6bc703f8709f5ef455faafeff4e5f00b62f835576eea7fb529 */
|
package/src/print.css
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
* {
|
|
2
|
+
font-size: 0.5rem; /* Forces every single element to this size */
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
body {
|
|
6
|
+
color: black;
|
|
7
|
+
background-color: white;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
h1 {
|
|
11
|
+
font: italic small-caps bold 2.5em/2.3em Verdana, sans-serif;
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
letter-spacing: 0.1em;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#wrapper {
|
|
18
|
+
max-width: 600px;
|
|
19
|
+
width: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.grid {
|
|
23
|
+
display: grid;
|
|
24
|
+
grid-template-columns: 1fr;
|
|
25
|
+
gap: 0.25rem;
|
|
26
|
+
border: 2px solid lightgray;
|
|
27
|
+
}
|
|
28
|
+
.grid article {
|
|
29
|
+
padding: 0.25rem;
|
|
30
|
+
border: 0px solid #ccc;
|
|
31
|
+
border-radius: 4px;
|
|
32
|
+
min-width: 0; /* Allow grid items to shrink */
|
|
33
|
+
overflow-wrap: break-word; /* Break long words */
|
|
34
|
+
}
|
|
35
|
+
.grid article h2 {
|
|
36
|
+
color: black;
|
|
37
|
+
margin-bottom: 2px;
|
|
38
|
+
}
|
|
39
|
+
.grid article .datetime {
|
|
40
|
+
margin: 0;
|
|
41
|
+
font-style: italic;
|
|
42
|
+
}
|
|
43
|
+
.grid article p {
|
|
44
|
+
margin-top: 10px;
|
|
45
|
+
margin-bottom: 0;
|
|
46
|
+
}
|
|
47
|
+
.grid article a {
|
|
48
|
+
color: black;
|
|
49
|
+
}
|
|
50
|
+
.grid article a:link a:visited {
|
|
51
|
+
color: black;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
h1 {
|
|
55
|
+
color: black;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
nav a {
|
|
59
|
+
text-decoration: underline;
|
|
60
|
+
color: rgb(60, 60, 60);
|
|
61
|
+
font-size: 20px;
|
|
62
|
+
}
|
|
63
|
+
nav a[href*=login] {
|
|
64
|
+
display: none;
|
|
65
|
+
}
|
|
66
|
+
nav a:visited {
|
|
67
|
+
color: rgb(60, 60, 60);
|
|
68
|
+
text-decoration-color: rgb(60, 60, 60);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/*# sourceMappingURL=print.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sourceRoot":"","sources":["print.scss"],"names":[],"mappings":"AAKA;EACE;;;AAIF;EACE,OAXQ;EAYR,kBATW;;;AAYb;EAAK;EACL;EAAW;EACX;;;AAGA;EACE;EAAkB;;;AAGpB;EACE;EACA;EACA;EACA;;AAEA;EAIE;EACA;EACA;EACA;EACA;;AAPA;EAAK,OA/BC;EAgCN;;AAOA;EACI;EACA;;AAEJ;EACI;EACF;;AAEF;EACI;;AAEJ;EACI;;;AAKR;EACE,OAzDQ;;;AA6DR;EACE;EACA,OA7DE;EA8DF;;AAGF;EACE;;AAGF;EACE,OAtEE;EAuEF,uBAvEE","file":"print.css"}
|
package/src/print.scss
CHANGED
|
@@ -29,7 +29,7 @@ letter-spacing: 0.1em;
|
|
|
29
29
|
border: 2px solid lightgray;
|
|
30
30
|
|
|
31
31
|
article {
|
|
32
|
-
h2 { color: primary;
|
|
32
|
+
h2 { color: $primary;
|
|
33
33
|
margin-bottom: 2px;
|
|
34
34
|
}
|
|
35
35
|
padding: 0.25rem;
|
|
@@ -55,7 +55,7 @@ letter-spacing: 0.1em;
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
h1 {
|
|
58
|
-
color: primary;
|
|
58
|
+
color: $primary;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
nav {
|