@lexho111/plainblog 0.4.2 → 0.5.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/.vscode/settings.json +2 -0
- package/Blog.js +117 -195
- package/Formatter.js +21 -13
- package/README.md +2 -38
- package/blog.db +0 -0
- package/blog.json +87 -1
- package/build-styles.js +3 -3
- package/model/DatabaseModel2.js +86 -0
- package/model/fileModel.js +15 -5
- package/package.json +11 -9
- package/public/print.min.css +2 -0
- package/{scripts.min.js → public/scripts.min.js} +1 -1
- package/public/styles.min.css +68 -0
- package/src/print.scss +76 -0
- package/src/styles.css +18 -0
- package/test/blog.test.js +24 -7
- package/test/model.test.js +7 -5
- package/test/server.test.js +2 -1
- package/test/styles.test.js +42 -44
- package/blog.db-journal +0 -0
- package/model/DatabaseModel.js +0 -139
- package/streams.js +0 -17
- package/styles.min.css +0 -1
- package/test_1767117403635.db +0 -0
- package/test_1767117781437.db +0 -0
- package/test_1767117944836.db +0 -0
- package/test_1767119505118.db +0 -0
- package/test_1767173684248.db +0 -0
- package/test_1767173763155.db +0 -0
- package/test_1767173821563.db +0 -0
- package/test_1767260493607.db +0 -0
- package/test_1767281040439.db +0 -0
- package/test_1767281442334.db +0 -0
- package/test_1767286038587.db +0 -0
- package/test_1767286127364.db +0 -0
- package/test_1767286366239.db +0 -0
- package/test_1767286503638.db +0 -0
- package/test_1767286637739.db +0 -0
- package/test_1767292219862.db +0 -0
- package/test_1767292355190.db +0 -0
- package/test_server_db.db +0 -0
- package/test_styles_1.db +0 -0
- package/test_styles_2.db +0 -0
- package/test_styles_3.db +0 -0
- package/test_styles_4.db +0 -0
- /package/{styles.min.css.map → public/styles.min.css.map} +0 -0
- /package/src/{loader.js → fetchData.js} +0 -0
package/test/styles.test.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Blog from "../Blog.js";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
|
-
import { parseFromString } from "dom-parser";
|
|
5
4
|
import fs from "node:fs";
|
|
6
5
|
|
|
7
|
-
const
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
const publicDir = path.join(__dirname, "../public");
|
|
8
9
|
|
|
9
10
|
describe("Blog Stylesheet Test", () => {
|
|
10
11
|
it("should load and compile the sass stylesheet (.scss) correctly", async () => {
|
|
@@ -15,12 +16,16 @@ describe("Blog Stylesheet Test", () => {
|
|
|
15
16
|
blog.stylesheetPath = "test/stylesheets/styles.scss";
|
|
16
17
|
|
|
17
18
|
await blog.init();
|
|
18
|
-
const html = await blog.toHTML();
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const publicCSS = await fs.promises.readFile(
|
|
21
|
+
path.join(publicDir, "styles.min.css"),
|
|
22
|
+
"utf8"
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
expect(publicCSS).toContain(".grid");
|
|
26
|
+
expect(publicCSS).toContain("article");
|
|
27
|
+
expect(publicCSS).toContain("nav");
|
|
28
|
+
expect(publicCSS).toContain("nav a:visited");
|
|
24
29
|
});
|
|
25
30
|
|
|
26
31
|
it("should load and compile the sass stylesheet (.scss) correctly [Array]", async () => {
|
|
@@ -31,12 +36,15 @@ describe("Blog Stylesheet Test", () => {
|
|
|
31
36
|
blog.stylesheetPath = ["test/stylesheets/styles.scss"];
|
|
32
37
|
|
|
33
38
|
await blog.init();
|
|
34
|
-
const
|
|
39
|
+
const publicCSS = await fs.promises.readFile(
|
|
40
|
+
path.join(publicDir, "styles.min.css"),
|
|
41
|
+
"utf8"
|
|
42
|
+
);
|
|
35
43
|
|
|
36
|
-
expect(
|
|
37
|
-
expect(
|
|
38
|
-
expect(
|
|
39
|
-
expect(
|
|
44
|
+
expect(publicCSS).toContain(".grid");
|
|
45
|
+
expect(publicCSS).toContain("article");
|
|
46
|
+
expect(publicCSS).toContain("nav");
|
|
47
|
+
expect(publicCSS).toContain("nav a:visited");
|
|
40
48
|
});
|
|
41
49
|
|
|
42
50
|
it("should load the stylesheet (.css) file", async () => {
|
|
@@ -57,25 +65,20 @@ describe("Blog Stylesheet Test", () => {
|
|
|
57
65
|
blog.database.dbname = "test_styles_3";
|
|
58
66
|
blog.stylesheetPath = "test/stylesheets/styles.css";
|
|
59
67
|
await blog.init();
|
|
60
|
-
const html = await blog.toHTML();
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"text/html"
|
|
69
|
+
const publicCSS = await fs.promises.readFile(
|
|
70
|
+
path.join(publicDir, "styles.min.css"),
|
|
71
|
+
"utf8"
|
|
66
72
|
);
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
expect(
|
|
74
|
-
expect(
|
|
75
|
-
expect(
|
|
76
|
-
expect(css).toContain(".datetime");
|
|
77
|
-
expect(css).toContain("font-style:normal");
|
|
78
|
-
expect(css).toContain("color:");
|
|
74
|
+
expect(publicCSS).not.toContain(
|
|
75
|
+
"<style>body { font-family: Arial; }</style>"
|
|
76
|
+
);
|
|
77
|
+
expect(publicCSS).toContain("body");
|
|
78
|
+
expect(publicCSS).toContain("nav a");
|
|
79
|
+
expect(publicCSS).toContain(".datetime");
|
|
80
|
+
expect(publicCSS).toContain("font-style: normal");
|
|
81
|
+
expect(publicCSS).toContain("color:");
|
|
79
82
|
});
|
|
80
83
|
|
|
81
84
|
it("should load and compile the stylesheet (.css) correctly [Array]", async () => {
|
|
@@ -84,24 +87,19 @@ describe("Blog Stylesheet Test", () => {
|
|
|
84
87
|
blog.database.dbname = "test_styles_4";
|
|
85
88
|
blog.stylesheetPath = ["test/stylesheets/styles.css"];
|
|
86
89
|
await blog.init();
|
|
87
|
-
const html = await blog.toHTML();
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"text/html"
|
|
91
|
+
const publicCSS = await fs.promises.readFile(
|
|
92
|
+
path.join(publicDir, "styles.min.css"),
|
|
93
|
+
"utf8"
|
|
93
94
|
);
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
expect(
|
|
101
|
-
expect(
|
|
102
|
-
expect(
|
|
103
|
-
expect(css).toContain(".datetime");
|
|
104
|
-
expect(css).toContain("font-style:normal");
|
|
105
|
-
expect(css).toContain("color:");
|
|
96
|
+
expect(publicCSS).not.toContain(
|
|
97
|
+
"<style>body { font-family: Arial; }</style>"
|
|
98
|
+
);
|
|
99
|
+
expect(publicCSS).toContain("body");
|
|
100
|
+
expect(publicCSS).toContain("nav a");
|
|
101
|
+
expect(publicCSS).toContain(".datetime");
|
|
102
|
+
expect(publicCSS).toContain("font-style: normal");
|
|
103
|
+
expect(publicCSS).toContain("color:");
|
|
106
104
|
});
|
|
107
105
|
});
|
package/blog.db-journal
DELETED
|
Binary file
|
package/model/DatabaseModel.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { Sequelize, DataTypes, Op } from "sequelize";
|
|
2
|
-
|
|
3
|
-
export default class DatabaseModel {
|
|
4
|
-
#username;
|
|
5
|
-
#password;
|
|
6
|
-
#host;
|
|
7
|
-
#dbport = 5432;
|
|
8
|
-
#dbname = "blog";
|
|
9
|
-
|
|
10
|
-
#sequelize;
|
|
11
|
-
#Article;
|
|
12
|
-
#BlogInfo;
|
|
13
|
-
|
|
14
|
-
constructor(options) {
|
|
15
|
-
const databasetype = options.type; // the database type defines
|
|
16
|
-
if (databasetype === "sqlite") {
|
|
17
|
-
// Use the full path for the database file from the options.
|
|
18
|
-
if (options.dbname) this.#dbname = options.dbname;
|
|
19
|
-
this.#sequelize = new Sequelize({
|
|
20
|
-
dialect: "sqlite",
|
|
21
|
-
storage: this.#dbname + ".db",
|
|
22
|
-
logging: false,
|
|
23
|
-
});
|
|
24
|
-
} else if (databasetype === "postgres") {
|
|
25
|
-
this.#username = options.username;
|
|
26
|
-
this.#password = options.password;
|
|
27
|
-
this.#host = options.host;
|
|
28
|
-
if (options.dbname) this.#dbname = options.dbname;
|
|
29
|
-
if (!this.#username || !this.#password || !this.#host) {
|
|
30
|
-
throw new Error(
|
|
31
|
-
"PostgreSQL credentials not set. Please provide 'username', 'password', and 'host' in the options."
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
console.log(
|
|
35
|
-
`postgres://${this.#username}:${this.#password}@${this.#host}:${
|
|
36
|
-
this.#dbport
|
|
37
|
-
}/${this.#dbname}`
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
this.#sequelize = new Sequelize(
|
|
41
|
-
`postgres://${this.#username}:${this.#password}@${this.#host}:${
|
|
42
|
-
this.#dbport
|
|
43
|
-
}/${this.#dbname}`,
|
|
44
|
-
{ logging: false }
|
|
45
|
-
);
|
|
46
|
-
} else {
|
|
47
|
-
throw new Error(`Error! ${databasetype} is an unknown database type.`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
this.#Article = this.#sequelize.define(
|
|
51
|
-
"Article",
|
|
52
|
-
{
|
|
53
|
-
title: DataTypes.STRING,
|
|
54
|
-
content: DataTypes.TEXT,
|
|
55
|
-
createdAt: {
|
|
56
|
-
type: DataTypes.DATE,
|
|
57
|
-
defaultValue: DataTypes.NOW,
|
|
58
|
-
},
|
|
59
|
-
updatedAt: {
|
|
60
|
-
type: DataTypes.DATE,
|
|
61
|
-
defaultValue: DataTypes.NOW,
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
timestamps: true,
|
|
66
|
-
}
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
this.#BlogInfo = this.#sequelize.define(
|
|
70
|
-
"BlogInfo",
|
|
71
|
-
{
|
|
72
|
-
title: DataTypes.STRING,
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
timestamps: false,
|
|
76
|
-
}
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async initialize() {
|
|
81
|
-
// This creates the tables if they don't exist.
|
|
82
|
-
await this.#sequelize.sync({ alter: true });
|
|
83
|
-
console.log("database tables synced and ready.");
|
|
84
|
-
|
|
85
|
-
// Check for and create the initial blog title right after syncing.
|
|
86
|
-
const blogInfoCount = await this.#BlogInfo.count();
|
|
87
|
-
if (blogInfoCount === 0) {
|
|
88
|
-
await this.#BlogInfo.create({ title: "My Default Blog Title" });
|
|
89
|
-
console.log("initialized blog title in database.");
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// model
|
|
94
|
-
async findAll(
|
|
95
|
-
limit = 4,
|
|
96
|
-
offset = 0,
|
|
97
|
-
startId = null,
|
|
98
|
-
endId = null,
|
|
99
|
-
order = "DESC"
|
|
100
|
-
) {
|
|
101
|
-
const where = {};
|
|
102
|
-
if (startId !== null && endId !== null) {
|
|
103
|
-
where.id = {
|
|
104
|
-
[Op.between]: [Math.min(startId, endId), Math.max(startId, endId)],
|
|
105
|
-
};
|
|
106
|
-
} else if (startId !== null) {
|
|
107
|
-
where.id = { [order === "DESC" ? Op.lte : Op.gte]: startId };
|
|
108
|
-
}
|
|
109
|
-
const options = {
|
|
110
|
-
where,
|
|
111
|
-
order: [
|
|
112
|
-
["createdAt", order],
|
|
113
|
-
["id", order],
|
|
114
|
-
],
|
|
115
|
-
limit,
|
|
116
|
-
offset,
|
|
117
|
-
};
|
|
118
|
-
const articles = await this.#Article.findAll(options);
|
|
119
|
-
return articles.map((article) => article.get({ plain: true }));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async save(newArticle) {
|
|
123
|
-
await this.#Article.create(newArticle);
|
|
124
|
-
console.log("Added new article:", newArticle);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async getBlogTitle() {
|
|
128
|
-
// Find the first (and only) entry in the BlogInfo table.
|
|
129
|
-
const blogInfo = await this.#BlogInfo.findOne();
|
|
130
|
-
|
|
131
|
-
return blogInfo.title;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async updateBlogTitle(newTitle) {
|
|
135
|
-
// Find the first (and only) entry and update its title.
|
|
136
|
-
// Using where: {} will always find the first row.
|
|
137
|
-
await this.#BlogInfo.update({ title: newTitle }, { where: {} });
|
|
138
|
-
}
|
|
139
|
-
}
|
package/streams.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Transform } from "stream";
|
|
2
|
-
|
|
3
|
-
export class MapTransform extends Transform {
|
|
4
|
-
constructor(fn) {
|
|
5
|
-
super({
|
|
6
|
-
objectMode: true,
|
|
7
|
-
transform: (chunk, encoding, callback) => {
|
|
8
|
-
try {
|
|
9
|
-
// Call the mapping function with the chunk
|
|
10
|
-
callback(null, fn(chunk));
|
|
11
|
-
} catch (err) {
|
|
12
|
-
callback(err);
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
}
|
package/styles.min.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.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}
|
package/test_1767117403635.db
DELETED
|
Binary file
|
package/test_1767117781437.db
DELETED
|
Binary file
|
package/test_1767117944836.db
DELETED
|
Binary file
|
package/test_1767119505118.db
DELETED
|
Binary file
|
package/test_1767173684248.db
DELETED
|
Binary file
|
package/test_1767173763155.db
DELETED
|
Binary file
|
package/test_1767173821563.db
DELETED
|
Binary file
|
package/test_1767260493607.db
DELETED
|
Binary file
|
package/test_1767281040439.db
DELETED
|
Binary file
|
package/test_1767281442334.db
DELETED
|
Binary file
|
package/test_1767286038587.db
DELETED
|
Binary file
|
package/test_1767286127364.db
DELETED
|
Binary file
|
package/test_1767286366239.db
DELETED
|
Binary file
|
package/test_1767286503638.db
DELETED
|
Binary file
|
package/test_1767286637739.db
DELETED
|
Binary file
|
package/test_1767292219862.db
DELETED
|
Binary file
|
package/test_1767292355190.db
DELETED
|
Binary file
|
package/test_server_db.db
DELETED
|
Binary file
|
package/test_styles_1.db
DELETED
|
Binary file
|
package/test_styles_2.db
DELETED
|
Binary file
|
package/test_styles_3.db
DELETED
|
Binary file
|
package/test_styles_4.db
DELETED
|
Binary file
|
|
File without changes
|
|
File without changes
|