@lexho111/plainblog 0.2.2 → 0.2.4

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 CHANGED
@@ -1,7 +1,8 @@
1
1
  export default class Article {
2
- constructor(title, content) {
2
+ constructor(title, content, createdAt) {
3
3
  this.title = title;
4
4
  this.content = content;
5
+ this.createdAt = createdAt;
5
6
  }
6
7
 
7
8
  getContent() {
@@ -14,4 +15,22 @@ export default class Article {
14
15
  contentShort += "...";
15
16
  return contentShort;
16
17
  }
18
+
19
+ getFormattedDate() {
20
+ const date = new Date(this.createdAt);
21
+ const year = date.getFullYear();
22
+ const month = String(date.getMonth() + 1).padStart(2, "0");
23
+ const day = String(date.getDate()).padStart(2, "0");
24
+ const hours = String(date.getHours()).padStart(2, "0");
25
+ const minutes = String(date.getMinutes()).padStart(2, "0");
26
+ return `${year}/${month}/${day} ${hours}:${minutes}`;
27
+ }
28
+
29
+ toHTML() {
30
+ return ` <article>
31
+ <h2>${this.title}</h2>
32
+ <span class="datetime">${this.getFormattedDate()}</span>
33
+ <p>${this.getContentShort()}</p>
34
+ </article>`;
35
+ }
17
36
  }
package/Blog.js CHANGED
@@ -146,6 +146,9 @@ export default class Blog {
146
146
  await this.#databaseModel.initialize();
147
147
  const dbTitle = await this.#databaseModel.getBlogTitle();
148
148
  const dbArticles = await this.#databaseModel.findAll();
149
+ //console.log(`articles: ${JSON.stringify(dbarticles)}`)
150
+ this.reloadScriptsStylesOnGET = false;
151
+ if(this.reloadScriptsStylesOnGET) console.log("reload scripts and styles on GET-Request");
149
152
  let title = "";
150
153
  if (this.title.length > 0) title = this.title; // use blog title if set
151
154
  else title = dbTitle;
@@ -185,7 +188,7 @@ export default class Blog {
185
188
  if (this.#databaseModel) await this.#databaseModel.save(newArticleData);
186
189
  if (this.#isExternalAPI) await postData(this.#apiUrl, newArticleData);
187
190
  // Add the article to the local list for immediate display
188
- this.addArticle(new Article(title, content));
191
+ this.articles.unshift(new Article(title, content));
189
192
  } catch (error) {
190
193
  console.error("Failed to post new article to API:", error);
191
194
  }
@@ -239,7 +242,7 @@ export default class Blog {
239
242
  // load articles
240
243
 
241
244
  // reload styles and scripts on (every) request
242
- //this.loadScripts(); this.loadStyles();
245
+ if(this.reloadScriptsStylesOnGET) this.loadScripts(); this.loadStyles();
243
246
 
244
247
  let loggedin = false;
245
248
  if (!this.isAuthenticated(req)) {
@@ -296,7 +299,7 @@ export default class Blog {
296
299
  // Assuming the API returns an array of objects with title and content
297
300
  if (data.articles && Array.isArray(data.articles)) {
298
301
  for (const articleData of data.articles) {
299
- this.addArticle(new Article(articleData.title, articleData.content));
302
+ this.addArticle(new Article(articleData.title, articleData.content, articleData.createdAt));
300
303
  }
301
304
  }
302
305
  }
package/Formatter.js CHANGED
@@ -32,15 +32,7 @@ export function formatHTML(data, script, style) {
32
32
  <div style="width: 500px;">
33
33
  ${form}
34
34
  <section class="grid">
35
- ${data.articles
36
- .map(
37
- (article) => `
38
- <article>
39
- <h2>${article.title}</h2>
40
- <p>${article.getContentShort()}</p>
41
- </article>`
42
- )
43
- .join("")}
35
+ ${data.articles.map((article) => article.toHTML()).join("")}
44
36
  </section>
45
37
  </div>
46
38
  </body>
@@ -52,9 +52,17 @@ export default class DatabaseModel {
52
52
  {
53
53
  title: DataTypes.STRING,
54
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
+ },
55
63
  },
56
64
  {
57
- timestamps: false, // Assuming you don't need createdAt/updatedAt for this simple model
65
+ timestamps: true,
58
66
  }
59
67
  );
60
68
 
@@ -83,8 +91,16 @@ export default class DatabaseModel {
83
91
  }
84
92
 
85
93
  // model
86
- async findAll() {
87
- return this.#Article.findAll();
94
+ async findAll(limit = 10, offset = 0) {
95
+ const options = {
96
+ order: [
97
+ ["createdAt", "DESC"],
98
+ ["id", "DESC"],
99
+ ],
100
+ limit,
101
+ offset,
102
+ };
103
+ return this.#Article.findAll(options);
88
104
  }
89
105
 
90
106
  async save(newArticle) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lexho111/plainblog",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "A tool for creating and serving a minimalist, single-page blog.",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/styles.min.css CHANGED
@@ -1,2 +1,2 @@
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}nav a:visited{color:#3b40c1;text-decoration-color:#3b40c1}body{background-color:#fdfdfd;font-family:Arial}nav a{color:#3b40c1;font-size:20px;text-decoration:underline}
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}nav a:visited{color:#3b40c1;text-decoration-color:#3b40c1}body{background-color:#fdfdfd;font-family:Arial}nav a{color:#3b40c1;font-size:20px;text-decoration:underline}.datetime{color:#434343;font-style:italic}
2
2
  /*# sourceMappingURL=styles.min.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["styles-compiled.css","styles.css"],"names":[],"mappings":"AAAA,MAIA,mBAAA,CAHA,YAAA,CAEA,UAAA,CADA,yBAGA,CACA,cAEA,mBAAA,CACA,iBAAA,CACA,WAAA,CACA,wBAAA,CAJA,cAKA,CAOA,cACA,aAAA,CACA,6BACA,CCtBA,KACA,wBAAA,CACA,iBACA,CAEA,MAEA,aAAA,CACA,cAAA,CAFA,yBAGA","file":"styles.min.css","sourcesContent":[".grid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.25rem;\n border: 0px solid black;\n}\n.grid article {\n padding: 0.25rem;\n border: 0px solid #ccc;\n border-radius: 4px;\n min-width: 0; /* Allow grid items to shrink */\n overflow-wrap: break-word; /* Break long words */\n}\n\nnav a {\n text-decoration: underline;\n color: rgb(59, 64, 193);\n font-size: 20px;\n}\nnav a:visited {\n color: rgb(59, 64, 193);\n text-decoration-color: rgb(59, 64, 193);\n}","body {\n background-color: rgb(253, 253, 253);\n font-family: Arial;\n}\n\nnav a {\n text-decoration: underline;\n color: rgb(59, 64, 193);\n font-size: 20px;\n}\n"]}
1
+ {"version":3,"sources":["styles-compiled.css","styles.css"],"names":[],"mappings":"AAAA,MAIA,mBAAA,CAHA,YAAA,CAEA,UAAA,CADA,yBAGA,CACA,cAEA,mBAAA,CACA,iBAAA,CACA,WAAA,CACA,wBAAA,CAJA,cAKA,CAOA,cACA,aAAA,CACA,6BACA,CCtBA,KACA,wBAAA,CACA,iBACA,CAEA,MAEA,aAAA,CACA,cAAA,CAFA,yBAGA,CAEA,UAEA,aAAA,CADA,iBAEA","file":"styles.min.css","sourcesContent":[".grid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.25rem;\n border: 0px solid black;\n}\n.grid article {\n padding: 0.25rem;\n border: 0px solid #ccc;\n border-radius: 4px;\n min-width: 0; /* Allow grid items to shrink */\n overflow-wrap: break-word; /* Break long words */\n}\n\nnav a {\n text-decoration: underline;\n color: rgb(59, 64, 193);\n font-size: 20px;\n}\nnav a:visited {\n color: rgb(59, 64, 193);\n text-decoration-color: rgb(59, 64, 193);\n}","body {\n background-color: rgb(253, 253, 253);\n font-family: Arial;\n}\n\nnav a {\n text-decoration: underline;\n color: rgb(59, 64, 193);\n font-size: 20px;\n}\n\n.datetime {\n font-style: italic;\n color: rgb(67, 67, 67);\n}\n"]}