@haroonwaves/blog-kit-core 0.0.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/README.md +35 -0
- package/dist/index.cjs +114 -0
- package/dist/index.d.cts +59 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +74 -0
- package/package.json +22 -0
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# @haroonwaves/blog-kit-core
|
|
2
|
+
|
|
3
|
+
Core utilities for parsing markdown blog files with frontmatter. Extract metadata, calculate reading
|
|
4
|
+
time, and manage blog content in Node and React applications.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install @haroonwaves/blog-kit-core
|
|
10
|
+
# or
|
|
11
|
+
pnpm add @haroonwaves/blog-kit-core
|
|
12
|
+
# or
|
|
13
|
+
yarn add @haroonwaves/blog-kit-core
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Documentation
|
|
17
|
+
|
|
18
|
+
For complete documentation, API reference, and examples, please visit the
|
|
19
|
+
[main documentation](https://github.com/haroonwaves/blog-kit).
|
|
20
|
+
|
|
21
|
+
## Quick Links
|
|
22
|
+
|
|
23
|
+
- [Core Package Usage](https://github.com/haroonwaves/blog-kit#core-package)
|
|
24
|
+
- [API Reference](https://github.com/haroonwaves/blog-kit#api-reference)
|
|
25
|
+
- [Blog File Format](https://github.com/haroonwaves/blog-kit#blog-file-format)
|
|
26
|
+
- [Type Definitions](https://github.com/haroonwaves/blog-kit#types)
|
|
27
|
+
|
|
28
|
+
## Related Packages
|
|
29
|
+
|
|
30
|
+
- [@haroonwaves/blog-kit-react](https://www.npmjs.com/package/@haroonwaves/blog-kit-react) - React
|
|
31
|
+
components for rendering blogs
|
|
32
|
+
|
|
33
|
+
## License
|
|
34
|
+
|
|
35
|
+
ISC
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
extractBlog: () => extractBlog,
|
|
34
|
+
extractBlogMeta: () => extractBlogMeta,
|
|
35
|
+
getAllBlogsMeta: () => getAllBlogsMeta,
|
|
36
|
+
getBlog: () => getBlog
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(src_exports);
|
|
39
|
+
|
|
40
|
+
// src/parser.ts
|
|
41
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
42
|
+
var import_path = __toESM(require("path"), 1);
|
|
43
|
+
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
44
|
+
var import_reading_time = __toESM(require("reading-time"), 1);
|
|
45
|
+
function extractBlogMeta(content, slug) {
|
|
46
|
+
const { data, content: markdownContent } = (0, import_gray_matter.default)(content);
|
|
47
|
+
const readingTimeText = (0, import_reading_time.default)(markdownContent).text;
|
|
48
|
+
return {
|
|
49
|
+
slug,
|
|
50
|
+
...data,
|
|
51
|
+
readingTime: readingTimeText
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function extractBlog(content, slug) {
|
|
55
|
+
const { data, content: markdownContent } = (0, import_gray_matter.default)(content);
|
|
56
|
+
const readingTimeText = (0, import_reading_time.default)(markdownContent).text;
|
|
57
|
+
return {
|
|
58
|
+
metadata: {
|
|
59
|
+
...data,
|
|
60
|
+
slug,
|
|
61
|
+
readingTime: readingTimeText
|
|
62
|
+
},
|
|
63
|
+
content: markdownContent,
|
|
64
|
+
readingTime: readingTimeText
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function getAllBlogsMeta(config) {
|
|
68
|
+
const blogDirectory = import_path.default.join(config.contentDirectory, config.blogSubdirectory || "blog");
|
|
69
|
+
if (!import_fs.default.existsSync(blogDirectory)) {
|
|
70
|
+
console.warn(`Blog directory not found: ${blogDirectory}`);
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
const files = import_fs.default.readdirSync(blogDirectory);
|
|
74
|
+
const blogs = files.filter((file) => file.endsWith(".md")).map((file) => {
|
|
75
|
+
const slug = file.replace(".md", "");
|
|
76
|
+
const filePath = import_path.default.join(blogDirectory, file);
|
|
77
|
+
const fileContent = import_fs.default.readFileSync(filePath, "utf8");
|
|
78
|
+
const { data, content } = (0, import_gray_matter.default)(fileContent);
|
|
79
|
+
const readingTimeText = (0, import_reading_time.default)(content).text;
|
|
80
|
+
return {
|
|
81
|
+
slug,
|
|
82
|
+
...data,
|
|
83
|
+
readingTime: readingTimeText
|
|
84
|
+
};
|
|
85
|
+
}).sort((a, b) => {
|
|
86
|
+
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
|
87
|
+
});
|
|
88
|
+
return blogs;
|
|
89
|
+
}
|
|
90
|
+
function getBlog(slug, config) {
|
|
91
|
+
const blogDirectory = import_path.default.join(config.contentDirectory, config.blogSubdirectory || "blog");
|
|
92
|
+
const filePath = import_path.default.join(blogDirectory, `${slug}.md`);
|
|
93
|
+
if (!import_fs.default.existsSync(filePath)) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const fileContent = import_fs.default.readFileSync(filePath, "utf8");
|
|
97
|
+
const { data, content } = (0, import_gray_matter.default)(fileContent);
|
|
98
|
+
const readingTimeText = (0, import_reading_time.default)(content).text;
|
|
99
|
+
return {
|
|
100
|
+
metadata: {
|
|
101
|
+
...data,
|
|
102
|
+
slug
|
|
103
|
+
},
|
|
104
|
+
content,
|
|
105
|
+
readingTime: readingTimeText
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
109
|
+
0 && (module.exports = {
|
|
110
|
+
extractBlog,
|
|
111
|
+
extractBlogMeta,
|
|
112
|
+
getAllBlogsMeta,
|
|
113
|
+
getBlog
|
|
114
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
interface BlogMeta {
|
|
2
|
+
title: string;
|
|
3
|
+
description: string;
|
|
4
|
+
date: string;
|
|
5
|
+
category?: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
readingTime: string;
|
|
8
|
+
}
|
|
9
|
+
interface Blog {
|
|
10
|
+
metadata: BlogMeta;
|
|
11
|
+
content: string;
|
|
12
|
+
readingTime: string;
|
|
13
|
+
}
|
|
14
|
+
interface BlogConfig {
|
|
15
|
+
contentDirectory: string;
|
|
16
|
+
blogSubdirectory?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Client-side compatible: Extract blog metadata from raw markdown content.
|
|
21
|
+
* This function works in browser environments (pure React) where you have
|
|
22
|
+
* the markdown content as a string (e.g., fetched from an API or imported).
|
|
23
|
+
*
|
|
24
|
+
* @param content - Raw markdown content string
|
|
25
|
+
* @param slug - Blog post slug/identifier
|
|
26
|
+
* @returns Parsed blog metadata
|
|
27
|
+
*/
|
|
28
|
+
declare function extractBlogMeta(content: string, slug: string): BlogMeta;
|
|
29
|
+
/**
|
|
30
|
+
* Client-side compatible: Extract blog data from raw markdown content.
|
|
31
|
+
* This function works in browser environments (pure React) where you have
|
|
32
|
+
* the markdown content as a string (e.g., fetched from an API or imported).
|
|
33
|
+
*
|
|
34
|
+
* @param content - Raw markdown content string
|
|
35
|
+
* @param slug - Blog post slug/identifier
|
|
36
|
+
* @returns Parsed blog data with metadata and content
|
|
37
|
+
*/
|
|
38
|
+
declare function extractBlog(content: string, slug: string): Blog;
|
|
39
|
+
/**
|
|
40
|
+
* SSR and SSG only: Get all blogs metadata from the filesystem.
|
|
41
|
+
* This function requires Node.js fs module and only works in server environments
|
|
42
|
+
* (Next.js SSR/SSG, Node.js scripts, etc.).
|
|
43
|
+
*
|
|
44
|
+
* @param config - Blog kit configuration
|
|
45
|
+
* @returns Array of blog metadata
|
|
46
|
+
*/
|
|
47
|
+
declare function getAllBlogsMeta(config: BlogConfig): BlogMeta[];
|
|
48
|
+
/**
|
|
49
|
+
* SSR and SSG only: Get blog from the filesystem.
|
|
50
|
+
* This function requires Node.js fs module and only works in server environments
|
|
51
|
+
* (Next.js SSR/SSG, Node.js scripts, etc.).
|
|
52
|
+
*
|
|
53
|
+
* @param slug - Blog post slug/identifier
|
|
54
|
+
* @param config - Blog kit configuration
|
|
55
|
+
* @returns Blog data or null if not found
|
|
56
|
+
*/
|
|
57
|
+
declare function getBlog(slug: string, config: BlogConfig): Blog | null;
|
|
58
|
+
|
|
59
|
+
export { type Blog, type BlogConfig, type BlogMeta, extractBlog, extractBlogMeta, getAllBlogsMeta, getBlog };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
interface BlogMeta {
|
|
2
|
+
title: string;
|
|
3
|
+
description: string;
|
|
4
|
+
date: string;
|
|
5
|
+
category?: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
readingTime: string;
|
|
8
|
+
}
|
|
9
|
+
interface Blog {
|
|
10
|
+
metadata: BlogMeta;
|
|
11
|
+
content: string;
|
|
12
|
+
readingTime: string;
|
|
13
|
+
}
|
|
14
|
+
interface BlogConfig {
|
|
15
|
+
contentDirectory: string;
|
|
16
|
+
blogSubdirectory?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Client-side compatible: Extract blog metadata from raw markdown content.
|
|
21
|
+
* This function works in browser environments (pure React) where you have
|
|
22
|
+
* the markdown content as a string (e.g., fetched from an API or imported).
|
|
23
|
+
*
|
|
24
|
+
* @param content - Raw markdown content string
|
|
25
|
+
* @param slug - Blog post slug/identifier
|
|
26
|
+
* @returns Parsed blog metadata
|
|
27
|
+
*/
|
|
28
|
+
declare function extractBlogMeta(content: string, slug: string): BlogMeta;
|
|
29
|
+
/**
|
|
30
|
+
* Client-side compatible: Extract blog data from raw markdown content.
|
|
31
|
+
* This function works in browser environments (pure React) where you have
|
|
32
|
+
* the markdown content as a string (e.g., fetched from an API or imported).
|
|
33
|
+
*
|
|
34
|
+
* @param content - Raw markdown content string
|
|
35
|
+
* @param slug - Blog post slug/identifier
|
|
36
|
+
* @returns Parsed blog data with metadata and content
|
|
37
|
+
*/
|
|
38
|
+
declare function extractBlog(content: string, slug: string): Blog;
|
|
39
|
+
/**
|
|
40
|
+
* SSR and SSG only: Get all blogs metadata from the filesystem.
|
|
41
|
+
* This function requires Node.js fs module and only works in server environments
|
|
42
|
+
* (Next.js SSR/SSG, Node.js scripts, etc.).
|
|
43
|
+
*
|
|
44
|
+
* @param config - Blog kit configuration
|
|
45
|
+
* @returns Array of blog metadata
|
|
46
|
+
*/
|
|
47
|
+
declare function getAllBlogsMeta(config: BlogConfig): BlogMeta[];
|
|
48
|
+
/**
|
|
49
|
+
* SSR and SSG only: Get blog from the filesystem.
|
|
50
|
+
* This function requires Node.js fs module and only works in server environments
|
|
51
|
+
* (Next.js SSR/SSG, Node.js scripts, etc.).
|
|
52
|
+
*
|
|
53
|
+
* @param slug - Blog post slug/identifier
|
|
54
|
+
* @param config - Blog kit configuration
|
|
55
|
+
* @returns Blog data or null if not found
|
|
56
|
+
*/
|
|
57
|
+
declare function getBlog(slug: string, config: BlogConfig): Blog | null;
|
|
58
|
+
|
|
59
|
+
export { type Blog, type BlogConfig, type BlogMeta, extractBlog, extractBlogMeta, getAllBlogsMeta, getBlog };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/parser.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import matter from "gray-matter";
|
|
5
|
+
import readingTime from "reading-time";
|
|
6
|
+
function extractBlogMeta(content, slug) {
|
|
7
|
+
const { data, content: markdownContent } = matter(content);
|
|
8
|
+
const readingTimeText = readingTime(markdownContent).text;
|
|
9
|
+
return {
|
|
10
|
+
slug,
|
|
11
|
+
...data,
|
|
12
|
+
readingTime: readingTimeText
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function extractBlog(content, slug) {
|
|
16
|
+
const { data, content: markdownContent } = matter(content);
|
|
17
|
+
const readingTimeText = readingTime(markdownContent).text;
|
|
18
|
+
return {
|
|
19
|
+
metadata: {
|
|
20
|
+
...data,
|
|
21
|
+
slug,
|
|
22
|
+
readingTime: readingTimeText
|
|
23
|
+
},
|
|
24
|
+
content: markdownContent,
|
|
25
|
+
readingTime: readingTimeText
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function getAllBlogsMeta(config) {
|
|
29
|
+
const blogDirectory = path.join(config.contentDirectory, config.blogSubdirectory || "blog");
|
|
30
|
+
if (!fs.existsSync(blogDirectory)) {
|
|
31
|
+
console.warn(`Blog directory not found: ${blogDirectory}`);
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
const files = fs.readdirSync(blogDirectory);
|
|
35
|
+
const blogs = files.filter((file) => file.endsWith(".md")).map((file) => {
|
|
36
|
+
const slug = file.replace(".md", "");
|
|
37
|
+
const filePath = path.join(blogDirectory, file);
|
|
38
|
+
const fileContent = fs.readFileSync(filePath, "utf8");
|
|
39
|
+
const { data, content } = matter(fileContent);
|
|
40
|
+
const readingTimeText = readingTime(content).text;
|
|
41
|
+
return {
|
|
42
|
+
slug,
|
|
43
|
+
...data,
|
|
44
|
+
readingTime: readingTimeText
|
|
45
|
+
};
|
|
46
|
+
}).sort((a, b) => {
|
|
47
|
+
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
|
48
|
+
});
|
|
49
|
+
return blogs;
|
|
50
|
+
}
|
|
51
|
+
function getBlog(slug, config) {
|
|
52
|
+
const blogDirectory = path.join(config.contentDirectory, config.blogSubdirectory || "blog");
|
|
53
|
+
const filePath = path.join(blogDirectory, `${slug}.md`);
|
|
54
|
+
if (!fs.existsSync(filePath)) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const fileContent = fs.readFileSync(filePath, "utf8");
|
|
58
|
+
const { data, content } = matter(fileContent);
|
|
59
|
+
const readingTimeText = readingTime(content).text;
|
|
60
|
+
return {
|
|
61
|
+
metadata: {
|
|
62
|
+
...data,
|
|
63
|
+
slug
|
|
64
|
+
},
|
|
65
|
+
content,
|
|
66
|
+
readingTime: readingTimeText
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
extractBlog,
|
|
71
|
+
extractBlogMeta,
|
|
72
|
+
getAllBlogsMeta,
|
|
73
|
+
getBlog
|
|
74
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@haroonwaves/blog-kit-core",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"module": "dist/index.mjs",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"gray-matter": "^4.0.3",
|
|
13
|
+
"reading-time": "^1.5.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"tsup": "^7.2.0"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
20
|
+
"type-check": "tsc --noEmit"
|
|
21
|
+
}
|
|
22
|
+
}
|