A Chrome browser extension that renders diagrams in the ChatGPT website inline:
Chrome Web Store: Install ChatGPT Diagrams
Clone, install dependencies and build the extension:
git clone git@github.com:dwmkerr/chatgpt-diagrams-extension.git
npm install
npm run build
Open Chrome Extensions, choose 'Load Unpacked' and select the ./dist
folder. Now open https://chat.openai.com/ and enter a prompt such as:
Use mermaid.js to create a sequence diagram showing how state can be persisted for a chrome extension, and how state can be passed between files.
Press the 'Show Diagram' button in the code sample to render the diagram inline:
Node Version Manager is recommended to ensure that you are using the latest long-term support version of node.
Ensure you are using Node LTS, then install dependencies:
nvm use --lts
npm install
To run in local development mode, which will automatically reload when changes are made, use:
npm start
Load the unpacked extension in your browser from the ./dist
folder.
The following commands can be used to help development:
Command | Description |
---|---|
npm start |
Run in development mode. Updates ./dist on changes to ./src . |
npm run build |
Build the production bundle to ./dist . |
npm run tsc |
Run the TypeScript compiler, verifies the correctness of the TypeScript code. |
-------------------------- | ------------------------------------------------------------------------------- |
npm test |
Run unit tests, output coverage to ./coverage . |
npm run test:watch |
Run unit tests, coverage only on files that test run on, watch mode. |
npm run test:debug |
Run unit tests, with the Chrome Inspector, initially 'break', watch mode. |
npm run prettier |
Check formatting of all files. |
npm run prettier:fix |
Fix formatting of all files. |
npm run lint |
Check linting of all files. |
npm run lint:fix |
Fix linting issues in all files. |
-------------------------- | ------------------------------------------------------------------------------- |
make build |
Create the release package. |
make test |
Validate the code, running tsc and unit tests. |
The code is structured in such a way that you should be able to immediately see the key files that make up the extension.
At root level are the essential files that make up an extension, all other code is kept in the ./lib
folder.
manifest.json # the extension definition and metadata
content.ts # the content script, runs on chatgpt browser tabs, renders the diagrams
options.html # the UI for the options page
options.ts # the logic for the options page
setup-jest.js # utility to configure testing environment
lib/ # bulk of the logic for the extension
When Mermaid.js encounters an error, it attempts to render error content visually in the DOM. It is possible to provide an HTML Element that will be the container for this output. However, it does not appear to be possible to set this container to an element created with the JSDOM virtual DOM.
This means that when Mermaid.js encounters rendering errors, we copy the raw HTML of the error content it writes from the global document object, and then move it into our own container - this works both in the browser and for unit tests.
You can see this approach by searching for the text 'Hack' in the ./src/lib/chatgpt-dom.ts
code. There may be a better way but this managed to solve some issues like #20 and others, quickly and without too much complexity in the tests.
The following command runs a local webserver, serving the content at ./samples
. This makes it easy to test locally, without internet connectivity and without having to regularly log into ChatGPT:
make serve-samples
The sample page is served at http://localhost:3000
.
Note that the version
field is omitted from manifest.json
. The version in the manifest file is set to the current value in the package.json
file as part of the build process.
Prettier is used for formatting. Pre-commit hooks are used to enforce code style.
ESLint is used for code-quality checks and rules.
To understand why both are used, check "Prettier vs Linters".
Husky and lint-staged are used to run formatting and code quality checks on staged changes before they are committed.
The configuration for lint-staged is in the package.json
file.
Jest is used as the testing framework. ChatGPT sample pages are loaded into the environment using js-dom and we then verify that the ChatGPT code elements are identified and processed correctly.
Check the Developer Commands section to see the various test commands that can be run. It is possible to watch tests, run tests in the debugger, and so on.
In development mode, open source maps by navigating to the "Sources > Content Scripts > chatgpt-diagrams" folder. These are inline source maps. You can also use "Command + P" and search for a file such as content.ts
.
In production mode, source maps are generated as standalone files in the ./dist
folder.
There is no 'live reload' on file changes. The fastest way to reload is to run locally with npm start
. Webpack will rebuild the extension on file changes. Then just press the "Refresh" button in the chrome://extensions
page and reload the site you are debugging.
To verify that the code builds, the tests pass and the release package can be created run the commands below:
make build
make test
make release
These commands will be executed for pull requests.
The version of the extension is defined in the package.json
file.
Releasing in managed via Release Please in the main.yaml
workflow file.
If you need to manually trigger a release, run:
git commit --allow-empty -m "chore: release 2.0.0" -m "Release-As: 2.0.0"
When uploading a new version, follow the steps below.
If needed, update the screenshots. Screenshots should be 1280x800 pixels, set this in the Developer Tools (which can also be used to capture the screenshot to the Downloads folder.
Currently screenshots do not include a browser frame.
Screenshots do not have the ChatGPT sidebar, avoiding distractions.
Screenshots after the first one do not have the code sample, avoiding distractions.
Open Developer Tools, use the 'device size' button to set the responsive screen size, adjust the size to 1280x800, delete the sidebar from the nodes view, press Command+Shift+P and select 'Capture Screenshot'.
Prompts for screenshots so far are:
- Render a flowchart showing how a browser makes a web request and a server responds. Use mermaid.js.
- Create a UML class diagram showing relationships for the data model for a simple food delivery database. Use mermaid.js.
- Create an architecture diagram that would show the key components in an instant messaging application, use mermaidjs.
- Create a sequence diagram showing how retry logic with retry queues is typically implemented when using Apache Kafka, use mermaidjs for the diagram
Resize screenshots with:
brew install imagemagick
new_width=1280
for input in ./docs/screenshots/*.png; do
[[ -f "$input" ]] || continue
output="${input/\.png/-${new_width}.png}"
echo "Convert: ${input} -> ${output}"
convert "${input}" -resize "${new_width}x" "${output}"
done
https://joshisa.ninja/2021/10/22/browser-extension-with-rollup-omnibox-chatter.html
A quick-and-dirty list of improvements and next steps:
- bug: button is inserted multiple times while chatgpt is writing (add the class to the dom element before start processing? note that the code language text (e.g. 'mermaid') is overwritten
- build: test to ensure that mermaid doesn't add error content - or if it does that we at least control it better.
- improvement: render DOM using this method: https://crxjs.dev/vite-plugin/getting-started/vanilla-js/content-script-hmr#vite-hmr-for-javascript
- build: slow bundling, debugging fails: #10
- bug: debugger doesn't work on chrome, seems to be a sourcemaps issue (raised as crxjs/chrome-extension-tools#691)
- build: basic test for DOM manipulation
- build: coverage badge
- build: eslint for code quality rules
- build: pipeline to create package
- build: prettier for formatting
- build: release please
- build: resolve test issues #6
- build: tests
- create a much more representative sample page, use the examples from the description, no sidebar, use as a fixture for tests, update queries to use selectors to find elements.
- docs: better icon - just a simple 50/50 split of the two logos down the middle, or diagonal
- docs: table of local commands
- refactor: change xpath queries to query selectors, add tests, fixtures
- testing: better sample that doesn't have sidebar and includes more representative group of diagrams
- build: commitlint
- bug: tab container is not initially hidden
- refactor: hide 'options' page
- feat: 'copy' button for diagrams
- feat: Lightbox for diagrams
- feat: more descriptive error messages and improved error presentation
- build: auto deploy to chrome webstore: https://jam.dev/blog/automating-chrome-extension-publishing/
- feat: share feedback link (GH issue, or Chrome Web Store, grab some content from the DOM?)
- feat: hints on the error screen (e.g. "Did you include "use mermaid.js" in the text")
- chore: issue template (prompt text, code output, screenshot)
- improvement: icon for 'show diagram' button
- consider webpack dev server to serve sample page in local dev mode
- build: Create script to open a new chrome window, with the appropriate command line flags to load the dist unpacked
- feat: start/stop/pause buttons
- improvement: use the mutation observer (see ./src/observe.js) to watch for new code samples, rather than scanning the DOM on a timer
- feat: options based, based on popup code extracted from options script
- check options UI works in extension screen as well as inline in tab
- feat: edit xpath queries via options page
- refactor: MD5 diagram text, use as a key for diagrams in a background page so that we don't recreate each time
- refactor: move rendering logic to background page (so error content is hidden in tabs)
- feat: counter for extension icon that shows number of diagrams processed