@lexho111/plainblog 0.3.3 → 0.3.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/Blog.js CHANGED
@@ -2,10 +2,7 @@ import http from "http";
2
2
  import crypto from "crypto";
3
3
  import fs from "fs";
4
4
  import { URLSearchParams } from "url";
5
- import { Readable, Transform, Writable, pipeline } from "stream";
6
5
  import { MapTransform } from "./streams.js";
7
- import { fromEvent, firstValueFrom } from "rxjs";
8
- import { map, scan, takeUntil, last, defaultIfEmpty } from "rxjs/operators";
9
6
  import Article from "./Article.js";
10
7
  import DatabaseModel from "./model/DatabaseModel.js";
11
8
  import { fetchData, postData } from "./model/APIModel.js";
@@ -16,8 +13,7 @@ import path from "path";
16
13
  import { fileURLToPath } from "url";
17
14
  import { exec } from "child_process";
18
15
  import { promisify } from "util";
19
- import Vinyl from "vinyl";
20
- import { compileStyles, compileScripts } from "./gulp_frontend/gulpfile.js";
16
+ import { compileStyles } from "./build-styles.js";
21
17
 
22
18
  const execPromise = promisify(exec);
23
19
 
@@ -144,14 +140,12 @@ export default class Blog {
144
140
  }
145
141
 
146
142
  async handleLogin(req, res) {
147
- const body$ = fromEvent(req, "data").pipe(
148
- map((chunk) => chunk.toString()),
149
- scan((acc, chunk) => acc + chunk, ""),
150
- takeUntil(fromEvent(req, "end")),
151
- last(),
152
- defaultIfEmpty("")
153
- );
154
- const body = await firstValueFrom(body$);
143
+ const body = await new Promise((resolve, reject) => {
144
+ let data = "";
145
+ req.on("data", (chunk) => (data += chunk.toString()));
146
+ req.on("end", () => resolve(data));
147
+ req.on("error", reject);
148
+ });
155
149
  const params = new URLSearchParams(body);
156
150
 
157
151
  if (params.get("password") === this.#password) {
@@ -219,22 +213,12 @@ export default class Blog {
219
213
 
220
214
  /** post a blog article */
221
215
  async postArticle(req, res) {
222
- // OLD CODE
223
- /*let body = "";
224
- req.on("data", (chunk) => {
225
- body += chunk.toString();
226
- });*/
227
- // NEW CODE
228
- // Create a stream of the body string
229
- const body$ = fromEvent(req, "data").pipe(
230
- map((chunk) => chunk.toString()),
231
- scan((acc, chunk) => acc + chunk, ""), // Accumulate chunks
232
- takeUntil(fromEvent(req, "end")), // Stop when 'end' emits
233
- last(), // Emit only the final full string
234
- defaultIfEmpty("") // Handle empty bodies
235
- );
236
-
237
- const body = await firstValueFrom(body$);
216
+ const body = await new Promise((resolve, reject) => {
217
+ let data = "";
218
+ req.on("data", (chunk) => (data += chunk.toString()));
219
+ req.on("end", () => resolve(data));
220
+ req.on("error", reject);
221
+ });
238
222
 
239
223
  //req.on("end", async () => {
240
224
  const params = new URLSearchParams(body);
@@ -523,20 +507,10 @@ export default class Blog {
523
507
  if (currentHash !== this.#stylesHash) {
524
508
  console.log("Style assets have changed. Recompiling...");
525
509
  this.#stylesHash = currentHash;
526
-
527
- const vinyls = fileData.map(
528
- (f) =>
529
- new Vinyl({
530
- cwd: process.cwd(),
531
- base: path.dirname(f.path),
532
- path: f.path,
533
- contents: f.content,
534
- })
535
- );
536
-
537
- const stream = Readable.from(vinyls);
538
- const outputStream = compileStyles(stream);
539
- this.compiledStyles = await this.#streamToString(outputStream);
510
+
511
+ // Compile styles using the standalone script
512
+ this.compiledStyles = await compileStyles();
513
+
540
514
  await fs.promises.writeFile(
541
515
  path.join(__dirname, "styles.min.css"),
542
516
  this.compiledStyles + `\n/* source-hash: ${currentHash} */`
@@ -547,17 +521,6 @@ export default class Blog {
547
521
  }
548
522
  }
549
523
 
550
- #streamToString(stream) {
551
- return new Promise((resolve, reject) => {
552
- let data = "";
553
- stream.on("data", (file) => {
554
- if (file.contents) data += file.contents.toString();
555
- });
556
- stream.on("end", () => resolve(data));
557
- stream.on("error", reject);
558
- });
559
- }
560
-
561
524
  async #findAssetFiles() {
562
525
  const __filename = fileURLToPath(import.meta.url);
563
526
  const __dirname = path.dirname(__filename);
package/blog.db ADDED
Binary file
@@ -0,0 +1,61 @@
1
+ import { promises as fs } from "fs";
2
+ import path from "path";
3
+ import * as sass from "sass";
4
+ import postcss from "postcss";
5
+ import autoprefixer from "autoprefixer";
6
+ import cssnano from "cssnano";
7
+
8
+ // Configuration
9
+ const srcDir = path.join("gulp_frontend", "src");
10
+
11
+ // Helper to find files recursively
12
+ async function getFiles(dir) {
13
+ const dirents = await fs.readdir(dir, { withFileTypes: true });
14
+ const files = await Promise.all(
15
+ dirents.map((dirent) => {
16
+ const res = path.resolve(dir, dirent.name);
17
+ return dirent.isDirectory() ? getFiles(res) : res;
18
+ })
19
+ );
20
+ return Array.prototype.concat(...files);
21
+ }
22
+
23
+ export async function compileStyles() {
24
+ try {
25
+ const allFiles = await getFiles(srcDir);
26
+
27
+ // Filter for .scss files and exclude partials (files starting with _)
28
+ // Sort them to ensure consistent concatenation order
29
+ const scssFiles = allFiles
30
+ .filter((f) => f.endsWith(".scss") && !path.basename(f).startsWith("_"))
31
+ .sort();
32
+
33
+ let combinedCss = "";
34
+
35
+ // 1. Compile Sass
36
+ for (const file of scssFiles) {
37
+ try {
38
+ const result = sass.compile(file, {
39
+ loadPaths: [srcDir],
40
+ style: "expanded",
41
+ });
42
+ combinedCss += result.css + "\n";
43
+ } catch (err) {
44
+ console.error(`Error compiling ${path.basename(file)}:`, err.message);
45
+ }
46
+ }
47
+
48
+ // 2. PostCSS (Autoprefixer + CSSNano)
49
+ if (combinedCss) {
50
+ const plugins = [autoprefixer(), cssnano()];
51
+ const result = await postcss(plugins).process(combinedCss, {
52
+ from: undefined,
53
+ });
54
+ return result.css;
55
+ }
56
+ return "";
57
+ } catch (error) {
58
+ console.error("Build failed:", error);
59
+ return "";
60
+ }
61
+ }
@@ -15,14 +15,7 @@
15
15
  "@babel/preset-env": "^7.28.5",
16
16
  "autoprefixer": "^10.4.23",
17
17
  "cssnano": "^7.1.2",
18
- "gulp": "^5.0.1",
19
- "gulp-babel": "^8.0.0",
20
- "gulp-concat": "^2.6.1",
21
- "gulp-postcss": "^10.0.0",
22
- "gulp-rename": "^2.1.0",
23
- "gulp-sass": "^6.0.1",
24
- "gulp-sourcemaps": "^3.0.0",
25
- "gulp-uglify": "^3.0.2",
18
+ "postcss": "^8.4.35",
26
19
  "sass": "^1.97.1"
27
20
  }
28
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lexho111/plainblog",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "A tool for creating and serving a minimalist, single-page blog.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -19,22 +19,11 @@
19
19
  "node-fetch": "^3.3.2",
20
20
  "pg": "^8.16.3",
21
21
  "pg-hstore": "^2.3.4",
22
- "rxjs": "^7.8.2",
23
22
  "sequelize": "^6.37.7",
24
23
  "sqlite3": "^5.1.7",
25
- "vinyl": "^3.0.1",
26
- "@babel/core": "^7.28.5",
27
- "@babel/preset-env": "^7.28.5",
28
24
  "autoprefixer": "^10.4.23",
29
25
  "cssnano": "^7.1.2",
30
- "gulp": "^5.0.1",
31
- "gulp-babel": "^8.0.0",
32
- "gulp-concat": "^2.6.1",
33
- "gulp-postcss": "^10.0.0",
34
- "gulp-rename": "^2.1.0",
35
- "gulp-sass": "^6.0.1",
36
- "gulp-sourcemaps": "^3.0.0",
37
- "gulp-uglify": "^3.0.2",
26
+ "postcss": "^8.4.35",
38
27
  "sass": "^1.97.1"
39
28
  },
40
29
  "devDependencies": {
Binary file
Binary file
Binary file