Giter Site home page Giter Site logo

pionxzh / chatgpt-exporter Goto Github PK

View Code? Open in Web Editor NEW
1.1K 14.0 86.0 1.53 MB

Export and Share your ChatGPT conversation history

License: MIT License

JavaScript 0.23% Shell 0.09% HTML 11.19% TypeScript 83.50% CSS 4.98%
chatgpt exporter tampermonkey userscript ai markdown

chatgpt-exporter's Introduction

chatgpt-exporter's People

Contributors

14790897 avatar alex-rosenberg35 avatar evgenykochetkov avatar flaviut avatar ginixsan avatar github-actions[bot] avatar juho-creator avatar kyoyacchi avatar lugia19 avatar lwy123177 avatar notarin avatar okkidwi avatar pionxzh avatar sbmsr avatar srid avatar wolf-so avatar zetaloop avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chatgpt-exporter's Issues

Code block not export when appear inside list

image

Text:

You:
how to print hello world using python with notepad

ChatGPT:
To print "Hello, world!" using Python and Notepad, follow these steps:

1. Open Notepad.
2. Type the following code in Notepad:
3. Save the file as "hello_world.py" in any folder of your choice.
4. Open the Command Prompt on your computer.
5. Navigate to the folder where you saved the "hello_world.py" file using the cd command.
6. Type the following command to run the Python script:
7. Press Enter. The output "Hello, world!" should be displayed in the Command Prompt window.

Congratulations, you have successfully printed "Hello, world!" using Python and Notepad!

Missing some text in list item when export

image

Text: (the list item only code get extracted)

You:
Show me what this function does in step-by-step form:

def say(text):
  print('...')
  print(text)

ChatGPT:
Sure, here's a step-by-step breakdown of what this function `say(text)` does:

1. say
text
2. say
text
...
text
3. say

So, if you were to call the `say` function like this:

```perl
say("Hello, World!")
```

The output would be:

```python-repl
...
Hello, World!
```

I hope that helps!

Screenshot font issue for user messages

Hi! Thank you for the great work! I am using Firefox 111.0 (64-bit) and MacOS Ventura 13.2.1.

I find when I export the dialog into screenshots, the font for user messages look wired, the spaces seem not properly display.
tt

大佬求帮帮忙ヾ(✿゚▽゚)ノ

Support image in chat

Problems

You can teach ChatGPT to send out an image with Unsplash API.
https://www.reddit.com/r/OpenAI/comments/zh4kf4/did_you_know_you_can_make_chatgpt_send_images/

Current behavior

Text

The image will be shown as [image].

Markdown

The image will be shown as a markdown image ![alt](url).

Screenshot

The image will disappear.

HTML

The image size in not been handled correctly.

Expected behavior

Text

Use the markdown image ![alt](url).
Fallback to [image] if the URL is too long (like base64 encoded URL) to prevent cluttering the output.

Markdown

Remain the same

Screenshot

I should be able to see the image.

HTML

Make sure the image will stay inside chat.

Export not working due to missing access token

Starting today, the userscript has stopped working. I have version 2.0.0 installed. The following error is produced in the console:

Uncaught (in promise) Error: No access token found.
    at getAccessToken (userscript.html?name=ChatGPT%2520Exporter.user.js&id=ef67c343-7099-4fcc-a2ea-1ce0313c18dc:3413:13)
    at fetchApi (userscript.html?name=ChatGPT%2520Exporter.user.js&id=ef67c343-7099-4fcc-a2ea-1ce0313c18dc:3475:25)
    at fetchConversation (userscript.html?name=ChatGPT%2520Exporter.user.js&id=ef67c343-7099-4fcc-a2ea-1ce0313c18dc:3464:32)
    at async getConversations (userscript.html?name=ChatGPT%2520Exporter.user.js&id=ef67c343-7099-4fcc-a2ea-1ce0313c18dc:3495:26)
    at async exportToMarkdown (userscript.html?name=ChatGPT%2520Exporter.user.js&id=ef67c343-7099-4fcc-a2ea-1ce0313c18dc:22920:9)
    at async MenuItem.handleClick [as clickfalse] (userscript.html?name=ChatGPT%2520Exporter.user.js&id=ef67c343-7099-4fcc-a2ea-1ce0313c18dc:23611:22)

Request for Contribution Guidelines

I would greatly appreciate it if guidelines for contributing were defined in the README.md or in a new file called CONTRIBUTING.md.

Clear guidelines can greatly improve the efficiency and effectiveness of contributions by providing information on how to properly submit changes, what files should be included, and how commit messages should be formatted. This is especially important when working with new technologies and projects. I believe that having defined guidelines would help streamline the contribution process for all involved. Thank you for considering this request.

Windows Firefox: Button, but no menu

On Windows Firefox 110.0 with Tampermonkey 4.18.1 and chatgpt-exporter 1.8.0 the button is correctly added to the sidebar, but when I mouse over it, no menu appears, just a little triangle pointing left. There is nothing to click that would bring up the menu.
I've tried disabling all other extensions, but that didn't help either.
Anything I can do to help debug that?

Support for Heading, Bold and Italic

Prompts

Please output a markdown text

CleanShot 2023-01-13 at 09 58 03

Outputs

# is missing

CleanShot 2023-01-13 at 09 58 37

There are also minor issues with bold and italic. 😂

Thanks for providing such a great tool!

New lines are missing in questions in HTML exports

Thanks for this nice script!

I just want to report a minor bug. When exporting to HTML files, it seems that the new lines are missing from questions. It would be nice if it retains the new lines.

Original:
Screen Shot 2022-12-07 at 19 59 33

Exported HTML:
Screen Shot 2022-12-07 at 19 59 45

Discussion: UI Improvement

After adding markdown support #29 in v1.4.0, we have 4 items in the sidebar which occupied a lot of space.
I'm thinking about improving the UI.

image

  1. The first idea that came to my mind was to create a popover on hover which would show all the export formats.
  2. The second one is from #28 which adds the button beside "Regenerate". But we still need solutions like the first one to prevent scattering 4 long buttons.

And I also want to shorten the text on buttons 😄
Feel free to share your idea ✨

Support for table parsing

This script is really Amazing !

Just having a minor issue where the format of a table would not carry over to the HTML, images for comparison:

image

image

Hopefully not a hassle to fix.

Thanks !

When exporting Markdown with code blocks, ^M line endings are intermittent

I guess this is ChatGPT not really caring about line endings. I ended up with a document which was neither Unix \n or Windows \r\n, but a mixture of the two.

(In VIM on Linux, this manifests as some lines having ^M on the end, and some not.)

I would suggest chatgpt-exporter do a final pass over the document, to ensure every line ends in \r\n, to produce a DOS/Windows-style file which will also work fine on *nix.

My issue was with Markdown files. I don't know if HTML and TXT modes have the same issue, but I guess the same approach for them wouldn't hurt.

Export is missing some backticks for code

When ChatGPT generates inline code, it surrounds it with backticks, Markdown-style. But some of them (not all) are lost when exported to HTML or Markdown. It would be perfect if the backticks are kept, specially for Markdown. I think this example will make it clear:

In ChatGPT webpage:

image

Export to HTML using ChatGPT Exporter:

Pasted_Image_08_02_23_11_13_AM

And thanks a lot for making ChatGPT Exporter, it's really useful!

Misleading meta information (mostly just layout and wording)

In the heading of the HTML exports (I didn't check other options), the two lines

Time: 2023-02-26T12:29:19.649Z
Generated by ChatGPT Exporter

... can lead to confusion, because

  • the timestamp indicates the export time
  • the word generated could be misunderstood, it's only the HTML output that was generated.

What about putting both information it in one line with slight modifications like this:

Exported by ChatGPT Exporter at 2023-02-26T12:29:19.649Z

Request: options for dark mode default

Currently, when you open the exported HTML, it defaults to light mode. It would be nice if there was an option to export it as dark mode by default, or be able to pass in a query string to switch it to dark mode (e.g. ChatGPT-2023....html?theme=dark)

Content in ordered list is incorrectly truncated

<div class="markdown prose w-full break-words dark:prose-invert dark">
   <h2>Backend Configuration</h2>
   <p><code>Backend</code> is the environment configuration for experiments and challenges, and must be an official name provided. Currently supported environments include:</p>
   <ul>
      <li><code>vnc-ubuntu:2204</code></li>
      <li><code>webide-ubuntu:2204</code></li>
      <li><code>vnc-instance-ubuntu:2204</code></li>
      <li><code>webide-instance-ubuntu:2204</code></li>
   </ul>
   <p>Environment explanations are as follows:</p>
   <ol>
      <li><code>vnc</code> refers to an environment that defaults to a GUI desktop after startup, and <code>webide</code> refers to an environment that defaults to VS Code after startup. The two are essentially the same, with only different default views after startup.</li>
      <li><code>instance</code> refers to a new virtual machine instance (cloud host) after startup, and does not include <code>instance</code> which refers to a new container instance (Docker).</li>
      <li><code>ubuntu:2204</code> refers to the operating system being Ubuntu 22.04 after startup, and currently only Ubuntu 22.04 is supported.</li>
   </ol>
   <p>The recommended selections are as follows:</p>
   <ol>
      <li>If the experiment/challenge requires a GUI environment, or <strong>will not involve a lot of code file editing operations</strong> (writing a lot of code in VNC has a poor experience), it is recommended to use the <code>vnc</code> desktop environment.</li>
      <li>If the experiment/challenge does not require a GUI environment, or <strong>will involve a lot of code file editing operations</strong>, it is recommended to use the <code>webide</code> code editor environment.</li>
      <li>In most cases, the default is to use a non-cloud host environment, that is, without <code>instance</code>, because the startup time of the cloud host environment is longer and the cost of the cloud host environment is high, which is not suitable for a large number of experiments/challenges.</li>
      <li>If the experiment/challenge does not support running in a container environment, or requires using the <code>instance</code> cloud host environment. For example, Docker-related experiments/challenges cannot be completed in a Docker container environment and require a cloud host.</li>
   </ol>
</div>

CleanShot 2023-03-06 at 11 14 13@2x

CleanShot 2023-03-06 at 11 15 06@2x

Request: Option to include Timestamps for prompts and responses

I noticed that in the xhr reponse for loading a chat conversation, it has a create_time key for the main object, and every child object. It would be neat if we could have a toggle option to "include timestamps" to show on the page, and maybe even include it in the filename (instead of the current timestamp).


Progress Tracking

  • Add timestamp in HTML export
  • Option to toggle timestamp on the response
  • Add create_time variable to filename format

Chat names can be used as a titles and file names for exported chats

Now that ChatGPT supports multiple chats, chat names can be used as file names (instead of "chatgpt+date") and as titles with header tag within the file. Let's say the chat in named "Patching KDE2 on FreeBSD", then the markdown file can be exported with this text:

# Patching KDE2 on FreeBSD

You:
How does one patch KDE2 under FreeBSD?

ChatGPT:
To patch KDE2 under FreeBSD, you will need to follow these steps:
(...)

and the file itself can be named Patching_KDE2_on_FreeBSD.md (I'd say the current date is unnecessary because it's stored in the metadata within the file system, but it's up to you).

The same with copied text and HTML exports.

Export to webpage does not work

Hi! Thank you for the great work! Export to webpage seem do not work now. This is also mentioned by other uses here. I am using Firefox 111.0 (64-bit), not sure whether this is related to browser~

Use new icon for GPT-4 in exported HTML

Currently, when I export the conversation using the GPT-4 model, it still displays the GPT-3.5 icon (the green one). It would be helpful if a new GPT-4 icon (the black one) could be provided for clarity.

Note: The screenshot output is correct; only the HTML export needs to be updated.

Exporter is not working after 2.0 release

Or it takes an extremely long time.

Downgrading back to 1.9.1 worked immediately


Words from maintainer

v2.1.1 has been released to rollback the plugin to 1.9.1.

We rewrote the plugin to use the API provided by ChatGPT for providing richer features. (See #64)
However, the history API has been temporarily disabled by OpenAI.
We will continue to work on this plugin and release a new version when the API is available again.

WebPage export fails silently on CORS error

In v 2.1.2 running via Tampermonkey on Firefox 110.0.1, WebPage export silently fails. In the console the following error is present:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://s.gravatar.com/avatar/0c181e86176a1f93abd43da1d429bc55?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fop.png. (Reason: CORS request did not succeed). Status code: (null).

Commenting out the contents of the getUserAvatar function here such that it returns defaultAvatar without attempting loadImage resolves the problem:

async function getUserAvatar() {
    /*const {
      picture
    } = getUserProfile();
    if (picture)
      return getBase64FromImageUrl(picture);*/
    return defaultAvatar;
  }

Previously WebPage export worked without modifying the script.

Content warnings are handled incorrectly

In case of a user message, a warning on it results in only the warning being exported:

You:
This content may violate our [content policy](https://beta.openai.com/docs/usage-policies/content-policy). If you believe this to be in error, please [submit your feedback](https://forms.gle/3gyAMj5r5rTEcgbs5) — your input will aid our research in this area.

Expected:

You:
USER MESSAGE

In case of ChatGPT's message, a warning results in the message being wrapped in backticks, also the warning is exported too:

ChatGPT:
`CHATGPT MESSAGE P1``CHATGPT MESSAGE P2``CHATGPT MESSAGE P3``CHATGPT MESSAGE P4`

This content may violate our [content policy](https://beta.openai.com/docs/usage-policies/content-policy). If you believe this to be in error, please [submit your feedback](https://forms.gle/3gyAMj5r5rTEcgbs5) — your input will aid our research in this area.

Expected:

ChatGPT:
CHATGPT MESSAGE P1

CHATGPT MESSAGE P2

CHATGPT MESSAGE P3

CHATGPT MESSAGE P4

It's really easy to trigger the warnings, but just in case, here's how HTML hierarchies look in both cases:

image

image

Is there a way to add the syntax highligting the original chat had?

When exporting code to html the result contais following:

<pre><code class="language-javascript">// define a function named "add" that takes in two parameters
function add(a, b) {
  // add the two parameters together and return the result
  return a + b;
}

// call the add function, passing in the numbers 2 and 3 as arguments
let result = add(2, 3);

// log the result to the console
console.log(result); // Output: 5
</code></pre>

in chatgpt it looks like this:
image

in the export like this:
image

Request: export JSON format

Not sure if this is what you mean by json in the readme, but it looks like the API version you're working on can get the whole tree, and you're just getting to the current one.

I'd like a raw dump of all of what comes out of the API, should be really easy, once that's working.

I can get it from the XHR manually in the webpage, but it'd be nice to have a button.

line-break is not being respected in HTML export.

This is what I see in the original ChatGPT web interface (after reloading an old chat):

grafik

And this is what I see in the export of chatgpt-exporter version 1.9.1

grafik

The HTML node for the poem (via copy outer HTML in Developer Tools) looks exactly the same in both cases:

<p>A machine tried to pass the test,
But failed to impress with its best,
Its answers were too quick,
Its humor too slick,
The machine's true nature laid to rest.</p>

I tried to find the CSS responsible for rendering \n as line breaks, but I couldn't.

Sidebar links don't appear when installing in ViolentMonkey

ViolentMonkey successfully installs chatgpt-exporter on Firefox 105.0.2 and shows it activaled on the ChatGPT page. However, the sidebar links don't appear. In the JavaScript console I get:

TypeError: document.head is null
    VMincre66i9sg6yvj0th moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/ ChatGPT Exporter.user.js#1:13
    VMincre66i9sg6yvj0th moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/ ChatGPT Exporter.user.js#1:13
    VMincre66i9sg6yvj0th moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/ ChatGPT Exporter.user.js#1:7934
    a moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    Lt moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    set moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    <anonymous> moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/ ChatGPT Exporter.user.js#1:1
    $e moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    post moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    ScriptData moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    onHandle moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    Ae moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
ChatGPT Exporter.user.js:7934:35
    VMincre66i9sg6yvj0th moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/ ChatGPT Exporter.user.js#1:7934
    a moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    Lt moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    set moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    <anonymous> moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/ ChatGPT Exporter.user.js#1:1
    ut moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    ft moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    onHandle moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    Ce moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    $e moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    post moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    ScriptData moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    onHandle moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    Ae moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/sandbox/injected-web.js:1
    ke moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    post moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    pt moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    lt moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    Ie moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    Ie moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    lt moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    qt moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    <anonymous> moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    <anonymous> moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1
    <anonymous> moz-extension://e9088199-ee38-4519-a1ac-17a64186cfb3/injected.js:1

Export conversation as PDF

Would be great if you add the option to export a conversation as PDF
And it would be a lot more user friendly for a lot of situations
Thank you

Mobile version support

I'd like to use it on mobile version too , but it looks like this;
Screenshot_20230214-190220
I can barely click them and can't see texts.

Can you improve it for mobile version? I'm using Kiwi Browser, (Violentmonkey ext.)

Didn't work in firefox

Tried:
-Tampermonkey
-Violentmonkey

Tried to debug it, but the plugin is super huge, and it tries to log in to some thing, not sure, I gave up.

The sidebar does not appear unless refreshing the webpage. (Chrome, MacOS)

I am using MacOS 13.0.1.
For Chrome, the script sidebar does not appear at the first time when opening ChatGPT webpage, unless refreshing it again.
For Safari, the sidebar does not appear even I refresh many times. It is weird that whenever I refreshed the page, the sidebar flashed about 0.1s but disappeared immediately. In order to use this script, I have to restart Safari and reopen the webpage several times. I guess it is not stable enough with MacOS.

Request: Feature to download ALL chats

First of all, thank you for the great user script, it is very helpful.

I have a feature request: could you implement an option to export all available chats?
I just installed the script and I want to export/save all my existing chats, but I have a lot of them, so it would take a long time to export each file individually. So I thought an option to download all the previous chats and maybe pack them into a zip file would be useful.

When copy chat conversations, it does NOT include user post

function getConversation(): ConversationItem[] {
const items: ConversationItem[] = []
document.querySelectorAll('main .group').forEach((item) => {
const avatarEl = item.querySelector<HTMLImageElement>('span img:not([aria-hidden="true"])')
// actually we can get the name from the avatar's alt
// but let's keep it anonymous for privacy reasons
const name = avatarEl?.getAttribute('alt') ? 'You' : 'ChatGPT'
const avatar = avatarEl ? getBase64FromImg(avatarEl) : ''
const textNode = <HTMLDivElement>item.querySelector('.markdown') ?? item.querySelector('.w-full > .whitespace-pre-wrap')
if (!textNode) return
const lines = parseTextNode(textNode)
items.push({ author: { name, avatar }, lines })
})
return items
}

Neither selector '.markdown' nor '.w-full > .whitespace-pre-wrap' exists for user input.

This only export ChatGPT: only, like

ChatGPT:
Hello! How can I help you today?

image

image

Script menu unstable on Safari

Hi, I still have the issue that the menu didn't show consistently whenever I refresh the ChatGPT webpage using Safari. Does it have something to do with any incompatibility between Tampermonkey and Safari? The menu blinks once whenever refreshed but finally disappeared, though the Tampermonkey extension itself says the script has been enabled normally.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.