My ChatGPT history is littered with nuggets of AI-generated wisdom. Here are some examples:
- Asia Cup 2023 Match Update
- Calvin channels his imagination
- D3 Bubble Chart Function
- Diverse Experiences in 15 Ways
- Nike's Pandemic Digital Shift
I wanted these chats as local Markdown documents for quick reference.
ChatGPT exports history as JSON or HTML.
I planned to publish an npm package that converts this JSON to Markdown documents -- but written entirely with ChatGPT.
1. Generate code
Given a JSON file like this:
```json
{
"title": "Style em and strong like Medium",
"create_time": 1695704992.160348,
// ~300 lines of JSON covering 2 full conversations
}
```
Write a JavaScript program to convert this to Markdown
It faithfully returned a script
const json = [
/* ... your JSON data ... */
];
function convertToMarkdown(json) {
return json
.map((conversation) => {
const title = `# ${conversation.title}\n`;
// ... more code here
return `${title}${metadata}${messages}`;
})
.join("\n---\n");
}
const markdown = convertToMarkdown(json);
console.log(markdown);
Delightfully, this worked!
2. Revise code
I needed this to work from a conversations.js
file rather than JSON embedded in the code. So I said:
Modify to read the file from the command line on Node.js
Sure enough, it said To read a file from the command line in Node.js, you can use the fs (File System) module... and revised the code.
I tried running node script.js conversations.json
but got this error:
c:\temp\script.js:11
const content = node.message.content.parts.join('\n');
^
TypeError: Cannot read properties of undefined (reading 'join')
at c:\temp\script.js:11:60
at Array.map ()
at c:\temp\script.js:7:62
at Array.map ()
at convertToMarkdown (c:\temp\script.js:4:17)
at c:\temp\script.js:32:22
at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3)
Node.js v18.4.0
That led me to the next approach.
3. Fix bugs
I just typed the relevant error snippet in the chat.
const content = node.message.content.parts.join('\n');
TypeError: Cannot read properties of undefined (reading 'join')
ChatGPT quickly caught on. The error you're encountering is because node.message.content.parts
is undefined for some nodes in your JSON data.
It revised the code, and that created a single large Markdown file from the JSON. It worked!
4. Add features
I asked for a number of new features.
- Create 1 file for each object.
File name should be the "{title}.md" --
replacing invalid file name characters with hyphen
- If there are any HTML tags (<...>) in headings,
wrap them in `backticks`.
- Skip timestamps except at the top of each message
- Use H2 (##) for each user message
5. Refactor code
I prefer using ES Modules to CommonJS. So I created a new chat, pasted the entire code, and asked ChatGPT:
[MY PASTED CODE]
Modify the above script to
- Convert from require to ESM
- Save files in the same directory as the
source file passed in the command line
This worked!
6. Package code
My next ask was:
I want to publish this as an npm package.
Improve the code quality to a library standard.
"Improve the code quality" is a fairly broad ask, but I loved the response. It said, "Here are some steps..."
- Modularization: Break down the code into smaller, reusable modules.
- Error Handling: Improve error handling to provide clear error messages and allow for error handling by the library users.
- Validation: Add validation for input parameters to ensure they meet the expected format.
- Documentation: Add JSDoc comments to functions to explain what they do, the parameters they accept, and what they return.
- Testing: Although not shown in the code below, you should create a suite of tests to ensure your library functions as expected.
- Package Configuration: Create a package.json file with the necessary configurations.
... and provided a much better code base:
// src/index.mjs
import { promises as fs } from 'fs';
import path from 'path';
/**
* Sanitizes a file name by replacing invalid characters with hyphens.
* @param {string} title - The title to sanitize.
* @returns {string} - The sanitized title.
*/
function sanitizeFileName(title) {
return title.replace(/[<>:"\/\\|?*\n]/g, '-');
}
...
// package.json
{
"name": "json-to-markdown-converter",
"version": "1.0.0",
"description": "A library to convert JSON to Markdown",
"main": "src/index.mjs",
"type": "module",
// ...
7. Add modules
I said:
Rename this package to "chatgpt-to-markdown".
I want to run `npx chatgpt-to-markdown` to run index.ms
Apart from modifying package.json
, it interestingly added a new file, cli.js
:
#!/usr/bin/env node
import path from 'path';
import { fileURLToPath } from 'url';
...
It's keeping track of 3 files now: package.json
, index.mjs
, and cli.js
.
8. Document
I said:
Write a README.md that is as good as the most popular npm packages.
Again, "as good as the most popular npm packages" is a sweeping statement, but it did a great job.
# ChatGPT to Markdown
Convert ChatGPT conversation JSON files to Markdown format with ease.
[](https://badge.fury.io/js/chatgpt-to-markdown)
...
9. Publish
The only manual tasks I had to do was to tweak a few lines (entering my name, code repo link, etc.) and run npm publish
.
The repository is live at chatgpt-to-markdown.
To run it, go to chat.openai.com > Settings > Data controls > Export data and export your data. Then unzip the file you're mailed and run:
npx chatgpt-to-markdown path/to/your/conversations.json
This will generate one Markdown file for each chat same directory as the conversations JSON file.
10. Test
I pasted the code for index.js
and said "Write detailed unit test cases for all functionality in index.js
using jest."
This was tougher than I expected, mainly because Jest ships with experimental support for ECMAScript Modules (ESM)..
- I knew I had to use
node --experimental-vm-modules node_modules/jest/bin/jest.js
- I didn't know how to mock modules in ESM -- which the code generated incorrectly
After a few hours of struggle and trying other libraries, I asked it to Rewrite without using mocks.
The test cases had several errors. I pasted the error messages back and it fixed them. Here's the full conversation
Lessons
It was a good experience learning that an entire package can be created without coding.
NOTE: I've written npm packages. I know what to ask for. Your mileage may vary. But it still saved me time.
More importantly, it made it possible. I would NOT have written the library if it would have taken twice as long. Not worth it.
I also learnt some ways in which you can use ChatGPT to code.
- Ask it to generate code.
- Copy-paste code and ask it to revise code.
- Copy-paste errors and ask it to fix bugs.
- Copy-paste code and ask it to add features and modules
- Copy-paste code and ask it to refactor code. Improve. Rewrite in a different style. Or language.
- Copy-paste code and ask it to document code -- inline and as a README.
- Copy-paste code and ask it to test code.
These are basic uses. I'm looking forward to exploring advanced uses like:
- Review code for flaws (vulnerabilities, complexity, performance, readability, edge cases)
- Refactor or optimize these flaws
- Identify useful features to add
- Code in the style of a library or person (e.g. write Pythonic code, or write D3 like Mike Bostock)