chatgpt-to-markdown 1.1.0 → 1.3.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/README.md +3 -1
- package/index.js +1 -0
- package/index.test.js +152 -0
- package/package.json +4 -3
package/README.md
CHANGED
@@ -97,7 +97,9 @@ git push --follow-tags
|
|
97
97
|
|
98
98
|
## Release notes
|
99
99
|
|
100
|
-
- 1.0
|
100
|
+
- 1.3.0: 29 Sep 2023. Set create and update dates from chat
|
101
|
+
- 1.2.0: 28 Sep 2023. Added test cases
|
102
|
+
- 1.1.0: 26 Sep 2023. Add date format option
|
101
103
|
- 1.0.0: 26 Sep 2023. Initial release
|
102
104
|
|
103
105
|
## License
|
package/index.js
CHANGED
@@ -108,6 +108,7 @@ async function chatgptToMarkdown(json, sourceDir, { dateFormat } = { dateFormat:
|
|
108
108
|
.join("");
|
109
109
|
const markdownContent = `${title}\n${metadata}\n${messages}`;
|
110
110
|
await fs.writeFile(filePath, markdownContent, "utf8");
|
111
|
+
await fs.utimes(filePath, conversation.update_time, conversation.create_time);
|
111
112
|
}
|
112
113
|
}
|
113
114
|
|
package/index.test.js
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
// index.test.js
|
2
|
+
|
3
|
+
import { promises as fs } from "fs";
|
4
|
+
import path from "path";
|
5
|
+
import os from "os";
|
6
|
+
import chatgptToMarkdown from "./index";
|
7
|
+
|
8
|
+
describe("chatgptToMarkdown", () => {
|
9
|
+
let tempDir;
|
10
|
+
|
11
|
+
beforeEach(async () => {
|
12
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "chatgptToMarkdown-"));
|
13
|
+
});
|
14
|
+
|
15
|
+
afterEach(async () => {
|
16
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
17
|
+
});
|
18
|
+
|
19
|
+
it("should write a markdown file for each conversation", async () => {
|
20
|
+
const json = [
|
21
|
+
{
|
22
|
+
title: "Test Conversation",
|
23
|
+
create_time: 1630454400,
|
24
|
+
update_time: 1630458000,
|
25
|
+
mapping: {
|
26
|
+
0: {
|
27
|
+
message: {
|
28
|
+
author: { role: "user", name: "John" },
|
29
|
+
content: { content_type: "text", parts: ["Hello"] },
|
30
|
+
},
|
31
|
+
},
|
32
|
+
},
|
33
|
+
},
|
34
|
+
];
|
35
|
+
|
36
|
+
await chatgptToMarkdown(json, tempDir);
|
37
|
+
|
38
|
+
const filePath = path.join(tempDir, "Test Conversation.md");
|
39
|
+
const fileContent = await fs.readFile(filePath, "utf8");
|
40
|
+
|
41
|
+
expect(fileContent).toBe(`# Test Conversation
|
42
|
+
|
43
|
+
- Created: 1 Sep 2021 5:30 AM
|
44
|
+
- Updated: 1 Sep 2021 6:30 AM
|
45
|
+
|
46
|
+
## user (John)
|
47
|
+
|
48
|
+
Hello
|
49
|
+
|
50
|
+
`);
|
51
|
+
});
|
52
|
+
|
53
|
+
it("should handle titles with HTML tags", async () => {
|
54
|
+
const json = [
|
55
|
+
{
|
56
|
+
title: "<h1>Test Conversation</h1>",
|
57
|
+
create_time: 1630454400,
|
58
|
+
update_time: 1630458000,
|
59
|
+
mapping: {},
|
60
|
+
},
|
61
|
+
];
|
62
|
+
await chatgptToMarkdown(json, tempDir);
|
63
|
+
const fileContent = await fs.readFile(path.join(tempDir, "h1 Test Conversation h1.md"), "utf8");
|
64
|
+
expect(fileContent).toContain("# `<h1>`Test Conversation`</h1>`\n");
|
65
|
+
});
|
66
|
+
|
67
|
+
it("should sanitize titles with invalid filename characters", async () => {
|
68
|
+
const json = [
|
69
|
+
{
|
70
|
+
title: ":/In\\<>*valid|?",
|
71
|
+
create_time: 1630454400,
|
72
|
+
update_time: 1630458000,
|
73
|
+
mapping: {},
|
74
|
+
},
|
75
|
+
];
|
76
|
+
await chatgptToMarkdown(json, tempDir);
|
77
|
+
// Check that the file exists with the sanitized title
|
78
|
+
await expect(fs.access(path.join(tempDir, "In valid.md"))).resolves.not.toThrow();
|
79
|
+
});
|
80
|
+
|
81
|
+
it("should handle custom date format functions", async () => {
|
82
|
+
const json = [
|
83
|
+
{
|
84
|
+
title: "Test Conversation",
|
85
|
+
create_time: 1630454400,
|
86
|
+
update_time: 1630458000,
|
87
|
+
mapping: {},
|
88
|
+
},
|
89
|
+
];
|
90
|
+
const customDateFormat = (date) => date.toISOString();
|
91
|
+
await chatgptToMarkdown(json, tempDir, { dateFormat: customDateFormat });
|
92
|
+
const fileContent = await fs.readFile(path.join(tempDir, "Test Conversation.md"), "utf8");
|
93
|
+
expect(fileContent).toContain("- Created: 2021-09-01T00:00:00.000Z\n");
|
94
|
+
});
|
95
|
+
|
96
|
+
it("should ignore messages with no content", async () => {
|
97
|
+
const json = [
|
98
|
+
{
|
99
|
+
title: "Test Conversation",
|
100
|
+
create_time: 1630454400,
|
101
|
+
update_time: 1630458000,
|
102
|
+
mapping: {
|
103
|
+
0: {
|
104
|
+
message: {
|
105
|
+
/* no content property */
|
106
|
+
},
|
107
|
+
},
|
108
|
+
},
|
109
|
+
},
|
110
|
+
];
|
111
|
+
await chatgptToMarkdown(json, tempDir);
|
112
|
+
const fileContent = await fs.readFile(path.join(tempDir, "Test Conversation.md"), "utf8");
|
113
|
+
expect(fileContent).not.toContain("## user (John)");
|
114
|
+
});
|
115
|
+
|
116
|
+
it("should ignore messages with empty content", async () => {
|
117
|
+
const json = [
|
118
|
+
{
|
119
|
+
title: "Test Conversation",
|
120
|
+
create_time: 1630454400,
|
121
|
+
update_time: 1630458000,
|
122
|
+
mapping: {
|
123
|
+
0: { message: { content: { content_type: "text", parts: [] } } },
|
124
|
+
},
|
125
|
+
},
|
126
|
+
];
|
127
|
+
await chatgptToMarkdown(json, tempDir);
|
128
|
+
const fileContent = await fs.readFile(path.join(tempDir, "Test Conversation.md"), "utf8");
|
129
|
+
expect(fileContent).not.toContain("## user (John)");
|
130
|
+
});
|
131
|
+
|
132
|
+
it("should indent messages with tool role that contain ``` fenced code blocks", async () => {
|
133
|
+
const json = [
|
134
|
+
{
|
135
|
+
title: "Test Conversation",
|
136
|
+
create_time: 1630454400,
|
137
|
+
update_time: 1630458000,
|
138
|
+
mapping: {
|
139
|
+
0: {
|
140
|
+
message: {
|
141
|
+
author: { role: "tool" },
|
142
|
+
content: { content_type: "code", language: "javascript", text: 'console.log("Hello, world!");' },
|
143
|
+
},
|
144
|
+
},
|
145
|
+
},
|
146
|
+
},
|
147
|
+
];
|
148
|
+
await chatgptToMarkdown(json, tempDir);
|
149
|
+
const fileContent = await fs.readFile(path.join(tempDir, "Test Conversation.md"), "utf8");
|
150
|
+
expect(fileContent).toContain('```javascript\nconsole.log("Hello, world!");\n```\n');
|
151
|
+
});
|
152
|
+
});
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "chatgpt-to-markdown",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.3.0",
|
4
4
|
"description": "Convert ChatGPT exported conversations.json to Markdown",
|
5
5
|
"main": "index.js",
|
6
6
|
"type": "module",
|
@@ -8,8 +8,8 @@
|
|
8
8
|
"chatgpt-to-markdown": "cli.js"
|
9
9
|
},
|
10
10
|
"scripts": {
|
11
|
-
"prepublishOnly": "npx prettier --write *.js *.md package.json",
|
12
|
-
"test": "
|
11
|
+
"prepublishOnly": "npx prettier --write *.js *.md package.json && npm test",
|
12
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
|
13
13
|
},
|
14
14
|
"keywords": [
|
15
15
|
"chatgpt",
|
@@ -22,6 +22,7 @@
|
|
22
22
|
"printWidth": 120
|
23
23
|
},
|
24
24
|
"devDependencies": {
|
25
|
+
"jest": "^29.7.0",
|
25
26
|
"prettier": "^3.0.3"
|
26
27
|
}
|
27
28
|
}
|