Giter Club home page Giter Club logo

obsidian-import-json's Introduction

Welcome

farling42 github stats

Top Langs

obsidian-import-json's People

Contributors

farling42 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

Watchers

 avatar  avatar

obsidian-import-json's Issues

Request to incorporate two fields in note name

I have a bunch of data on legal cases, and I would ideally like to name my notes Case-Name_Year. Case-Name and Year are both fields in my csv file. Would it be possible to do this?

Also, this is such a wonderful and smooth-working plugin!

Silently fails on a JSON file that has entries per line

I have a JSON file that uses a json-object per line, so it does not use the [ and ] to start with.

Unfortunately, no error is returned from the UI and just returns. Only the non-whitespace issue is shown on the console.

Can't Import json

Hello,
I am trying to import a JSON file in to Obsidian using the plugin, I am following @josh Plunkett guide on handlebars, and after pressing import, it says "Import Finished" and nothing changes and nothing is showing up and I'm really lost. I tried to search for a solution but couldn't find anything

Can the importer import new notes while keeping old notes untouched?

I intend to use this JSON/CSV Importer to import the JSON file in the "Better CSL JSON" format that is exported from a Zotero library with the "Better BibTex" plugin. My Zotero library will expend gradually. This means the JSON file will contain both old and new references. I have experimented this JSON/CSV Importer and found it will overwrite the old note with the same name. Is there a way to use this Importer to import only the new contents in a growing JSON file with new reference feeds? Or, is there a way to bypass the over-writing of the existing notes? Thanks for considering this request or enhancement!

#match with a regexp doesn't seem to work

I'm loading TSV data and when I attempt to use match from Handlebar-Helpers I get errors. What I'm trying to do is process a field into an array using a regexp then process the element of the array into a list using #each. I get nothing but errors when I try to use the following code:

Stellar: 
{{#each (match (Stars) (toRegex "[OBAFGKM]\d\s\w+|D|BD|BH|NS|PSR")) ~}}
- {{this}}
{{/each ~}}

The field Stars contains data like:

G0 V D
F1 V D
M3 V
K6 II M2 V

The regex is to unstring the multiple stars in the data field and put them on separate lines.

How to work with multiple tags?

I has a JSON file that is exported from Zotero with the "BetterBibTex JSON" format. For a reference, I have one or more tags.

With the following code, the Importer can import each tag in separative lines.
{{#each tags}}
#{{tag}}
{{/each}}

It will look like the following.
#tag1
#tag2
#tag3

If I want the tags to be arranged as the following, what code should I write?
#tag1, #tag2, #tag3

Thank you!

JSON-Handlebarjs helper math does not see variables with numeric values as numbers

Extracted values from JSON, even when they are number values, do not get passed to the math Handlebar Helpers as numbers. For example, pulling data from a Fantasy Map Generator JSON, the value at pack.burgs[x].population is a number that needs to be multiplied by 1000 to shift it to the correct value.

Using the mustache helper: {{multiply 1000 population}} in a template when importing fails with an error that population is not a number.

Even using a nested helper like: {{multiply 1000 (toFloat population)}} fails with the same error.

I've resorted to using a custom js helper, but is there a different method or way to force a value like population to be interpreted as a number?

Subfolder created despite unchecking 'Allow paths in Note name'

Hi, first of all thank you for this importer.
It works quite good, but it seems you are catching only the case of a single Slash / in a Name, not 2 Slashes.
Example:
I imported a File with this Value in the Name Column:

Miquel-/Adickesallee/Polizeipräsidium

This resulted in a Subfolder named U-Miquel-_Adickesallee with a File named Polizeipräsidium.md

Expected: a File named Miquel-_Adickesallee_Polizeipräsidium

Best Regards...

Basic Design

Read a JSON file, and use a handlebars template for the MD file.

Each entry in the JSON array will create a separate MD file using the specified template.

For Handlebars see https://handlebarsjs.com/

Basic function seems to be:

  // compile the template
  var template = Handlebars.compile("Handlebars <b>{{doesWhat}}</b>");
  // execute the compiled template and print the output to the console
  console.log(template({ doesWhat: "rocks!" }));

Support wildcards in table helper

It would be useful if we could use wildcards such as "?" and "*" in the {{table ...}} helper. I could also see the need for a new helper to be defined.

Proposed behavior:

Given data of ["F1", "G3"]

template:
{{table item "F?" "[[Stellar Class#F|F]]?" "G?" "[[Stellar Class#G|G]]?"}}

Produces:
[[Stellar Class#F|F]]1 [[Stellar Class#G|G]]3

Thanks.

add math helper?

Feature Request:

Could you add the "math" helper?

This StackOverflow seemed to have the same idea as I was thinking
https://stackoverflow.com/questions/22103989/adding-offset-to-index-when-looping-through-items-in-handlebars

relevant post:
Actual answer: https://stackoverflow.com/a/46317662/1549191

Register a math handlebar and perform all mathematical operations.

app.engine('handlebars', exphbs({
  helpers:{
    // Function to do basic mathematical operation in handlebar
    math: function(lvalue, operator, rvalue) {lvalue = parseFloat(lvalue);
        rvalue = parseFloat(rvalue);
        return {
            "+": lvalue + rvalue,
            "-": lvalue - rvalue,
            "*": lvalue * rvalue,
            "/": lvalue / rvalue,
            "%": lvalue % rvalue
        }[operator];
    }
}}));
app.set('view engine', 'handlebars');

Then you can directly perform operation in your view.

    {{#each myArray}}
        <span>{{math @index "+" 1}}</span>
    {{/each}}

Allow import button to run multiple times

While debugging my template file, I noticed that I needed to close out and reopen the import tool each time. I'd love it if I could just click Import again and have it run again.

Creating subfolders with "JSON name field"

Hi Martin,

Thanks for this awesome plugin. It saves us a lot of time when importing bulk data into Obsidian!

Now I faced a situation that I would like to ask you about: is it possible to make the plugin support subfolders inside the "JSON name field"? Suppose I'm going to import a lot of data from a CSV into a vault but I want to create a tree structure for that, with folders and subfolders. I already inserted the names of folders and subfolders on the "JSON name field", using '/' as folder separator (so Obsidian doesn't think I'm escaping anything).

Is is possible to do it?

Thanks!

Arnaldo

a wish to use several JSON file + Template pairings from a macro

Hi,
I am a fan of using this plugin. I use it frequently to import bibliography from Zotero.
I wonder whether it is possible to add the following two features.

  1. Is it possible to assign a hotkey for this plugin?
  2. This is related to my routine of using Zotero in the following steps.
    • I export my new bibliography in BetterBibTeX JSON file
    • From this same JSON file source, I need to use two different TEMPLATE files to import into two kinds of Notes that I need.
    • Each kind of Note uses the respective Destination Folder in Vault.
      As you can see from this procedure, I need to indicate the respective TEMPLATE files and Destination Folder in Vault for each kind of Note that I need from the same JSON file. These needs lots of clicking and switch between windows.

A feature in my wish list for my point 2:
Is it possible to indicate more than one template fileTEMPLATE files and its paired Destination Folder in Vault in order to import from the same JSON file?

I summarize my wish as the following:

  1. Setup a "parallel import" workflow
    Same JSON file source
    ---> template 1 ----> Folder 1
    ---> template 2 ----> Folder 2
    ---> template N ---> Folder N
  2. Save this workflow as a workflow file
  3. can assign a HotKey for the indicated workflow

The outcome of my wish is that as long as I export a JSON file, I simply use a HotKey for a particular workflow and then I will have more than one Note imported in the indicated folder simultaneously.

Thanks again for considering this.

Read CSV Headers in Template

Hi,

I would like to read all Column-Headers in the CSV and list each column and field as Tag in the Template.
How can I read the inside the the Handlebar template?

TIA

Importing .csv with no result

Hi there, I'm getting no results when trying to import my .csv files. Here are my steps:

download google sheet as .csv file
create note in obsidian with handlebar
create destination folder for import
use json/csv importer designating to each of the previous

The result is a "import finished" in the top right, but no new notes created.

Below is the .csv and .md handlebar note that I used

Mal'Gama Deities - Deities.csv

Handlebar Template (deity list).md

This is the Error in Console:

Missing helper: "Divine"
FOR ROW:
[object Object]

[Feature Enhancement] Ability to set property types during import

With Obsidian 1.4 around the corner (some that are already using it - not me, though), is there any way to import CSVs and have the property type set during import? I'm not sure how that property type works in the backend of things or how that might be exposed for plugins.

E.g. when importing a date or even a time column it should recognize it as such, when importing words that should be set as aliases or checkmark property type etc.

I'd be happy to test any pre-builds as I've already been testing your plugin the last few months with >800 rows of data and it works so beautifully :)

"Too many fields" Error

Hello,

The plugin repeatedly gives me this error:

Plugin:obsidian-import-json:20962 [
{
"type": "FieldMismatch",
"code": "TooManyFields",
"message": "Too many fields: expected 1 fields but parsed 7",
"row": 0
},
{
"type": "FieldMismatch",
"code": "TooManyFields",
"message": "Too many fields: expected 1 fields but parsed 7",
"row": 1
}
]
convertCsv @ plugin:obsidian-import-json:20962
eval @ plugin:obsidian-import-json:21328
eval @ plugin:obsidian-import-json:49
__async @ plugin:obsidian-import-json:33
input5.onclick @ plugin:obsidian-import-json:21306
plugin:obsidian-import-json:20964 {
"delimiter": ",",
"linebreak": "\n",
"aborted": false,
"truncated": false,
"cursor": 1370,
"fields": [
"Question|Answer|References"
]
}
plugin:obsidian-import-json:21121 generateNotes('[object File]', 'undefined', [object Object] )

I'm using a pipe delimiter in this file and I don't think it's decoding my file correctly. I could be wrong. Does anyone have a solution to this?

Thanks

Empty folders, no notes

Hello! :)
I know very little about coding and could be making a pretty obvious mistake! I keep getting a list of empty folders as opposed to notes. Any ideas for me to try? Thank you so much!
Leonie

Support nested name lookups

Hi thanks for great plugin.

Would it be possible to specify path to name in json import? It is useful when you are trying to import from files with several localisations e.g.

[
  {
    "en": { "name": "name_en" },
    "es": { "name": "name_es" }
  }
]

Also import files not always have array on top level of json file, and may have some meta information besides table data. It would be great to have option with path to data, so you don't need to manually edit json files before import.

Hotkeys

Hi,

I frequently use this plugin to import different JSON files. I wonder whether you could enable HotKeys to open this importer much faster.

Thanks!

Can multiple values in one cell work?

Say my CSV file is:

name,value
Alice,a
Bob, "b,c,d" 

And my template:

{{name}}:: [[{{value}}]] 

In Alice.md it returns Alice:: a as expected. But in Bob.md it returns Bob:: [[ &quot;b]]. Is it possible to have it return like this?

Bob:: b
Bob:: c
Bob:: d

Overwrite feature not working...?

Hi again @farling42 ,

I have also the overwrite feature is not working on my json imports. They do not overwrite the file... I get an error if teh files already exists?
Have attached screenshots of the import.
Screenshot 2023-02-28 at 10 37 21
Screenshot 2023-02-28 at 10 37 54

A question about "Field to use as Note name"

When opening the JSON CVS importer, I can define which field to use as Note name. However, how can I add @, for example, in front of the name?

The field in JSON is citationkey. But, I want the name of a note as @citationkey.

Importing JSON with apostrophes in obsidian

Hello,

I am trying to import beast from 5e.tools json. The description of one of the abilities has apostrophes and when imported into obsidian, apostrophes are replaced with ' which is unicode representation of '. Json in question is below

{
	"name": "Regeneration",
	"description": "The troll regains 10 hit points at the start of its turn. If the troll takes acid or fire damage, this trait doesn't function at the start of the troll's next turn. The troll dies only if it starts its turn with 0 hit points and doesn't regenerate."
}

And this is the imported text in Obsidian:

Regeneration: The troll regains 10 hit points at the start of its turn. If the troll takes acid or fire damage, this trait doesn't function at the start of the troll's next turn. The troll dies only if it starts its turn with 0 hit points and doesn't regenerate.

Is there any way to bypass this behavior? I was trying to reproduce it with javascript, but I think it's problem with communication between obsidian and plugin.

Thank you for any replies.

unable to import with a correct Note name

I attached an .json file in the text format.
4_test.txt

I want to import with the following template .md file to Obsidian.

---
aliases: {{#each items}}{{title}}{{/each}}
---

In "Field to use as Note name", I want to use 'citationKey' in the attached JSON file as my Note name. I got "[object Object]" as the Note name.

How can I make 'citationKey' as my Note name?

Thanks!

utils.createFrame is not a function

Thanks for the importer, I've finally got time to work through creating a template to import spells from 5etools. I'm attempting to use the forEach helper from handlebars-helpers library. During the import, I get the above error in the console. I've included the relevant block from my template below, as well as the json. Any ideas or suggestions as to what I'm doing wrong?

Uncaught (in promise) TypeError: utils.createFrame is not a function
    at Object.helpers.forEach (eval at <anonymous> (app.js:1), <anonymous>:8078:24)
    at Object.wrapper2 (eval at <anonymous> (app.js:1), <anonymous>:1351:23)
    at Object.eval [as main] (eval at createFunctionContext (eval at <anonymous> (app.js:1)), <anonymous>:37:108)
    at main (eval at <anonymous> (app.js:1), <anonymous>:1534:36)
    at ret (eval at <anonymous> (app.js:1), <anonymous>:1537:16)
    at ret (eval at <anonymous> (app.js:1), <anonymous>:3373:25)
    at JsonImport.eval (eval at <anonymous> (app.js:1), <anonymous>:44334:20)
    at Generator.next (<anonymous>)
    at fulfilled (eval at <anonymous> (app.js:1), <anonymous>:36:24)
{{#forEach entriesHigherLevel}}
## At Higher Levels

{{entriesHigherLevel.0.entries}}
{{/forEach}}
[
	{
		"name": "Intellect Fortress",
		"source": "TCE",
		"page": 107,
		"level": 3,
		"school": "A",
		"time": [
			{
				"number": 1,
				"unit": "action"
			}
		],
		"range": {
			"type": "point",
			"distance": {
				"type": "feet",
				"amount": 30
			}
		},
		"components": {
			"v": true
		},
		"duration": [
			{
				"type": "timed",
				"duration": {
					"type": "hour",
					"amount": 1
				},
				"concentration": true
			}
		],
		"entries": [
			"For the duration, you or one willing creature you can see within range has resistance to psychic damage, as well as advantage on Intelligence, Wisdom, and Charisma saving throws."
		],
		"entriesHigherLevel": [
			{
				"type": "entries",
				"name": "At Higher Levels",
				"entries": [
					"When you cast this spell using a spell slot of 4th level or higher, you can target one additional creature for each slot level above 3rd. The creatures must be within 30 feet of each other when you target them."
				]
			}
		],
		"damageResist": [
			"psychic"
		],
		"damageImmune": [
			"psychic"
		],
		"damageVulnerable": [
			"psychic"
		],
		"miscTags": [
			"SGT"
		],
		"classes": {
			"fromClassList": [
				{
					"name": "Artificer",
					"source": "TCE"
				}
			],
			"fromClassListVariant": [
				{
					"name": "Bard",
					"source": "PHB",
					"definedInSource": "TCE"
				},
				{
					"name": "Sorcerer",
					"source": "PHB",
					"definedInSource": "TCE"
				},
				{
					"name": "Warlock",
					"source": "PHB",
					"definedInSource": "TCE"
				},
				{
					"name": "Wizard",
					"source": "PHB",
					"definedInSource": "TCE"
				}
			]
		},
		"hasFluffImages": true
	}
]

FR: Public API for other plugin use

Hey! I was thinking about adding the ability to specify import templates using handlebars for the TTRPG Statblocks plugin, and realized that you already did the hard work :)

Would it be possible for you to create a generic method I could pass a json file and handlebars template file to, and get back the parsed file?

Plugin Just Not Doing Anything?

I have been attempting to import a CSV file into bsidian using this plugin. Even though I believe I'm doing everything correctly and the plugin says "Import Finished" whenever I execute it, it never does anything/creates any files and I'm not sure how to troubleshoot what I'm doing wrong since it doesn't throw any error.

JSON-Elements with no children (hence, no values) causes failure of import

Working with a JSON that has elements with no children causes the import process to fail.

(I'm fully willing to accept that I may not be addressing this correctly, from a programming standpoint; I will confess to knowing enough to be dangerous with javascript & handlebarjs).

Looking at a Fantasy Map Generator JSON, the pack.provinces[0] element or the pack.burgs[0] element both are simply represented as 0,, even though there are many more child elements after that first empty element(burgs[1],[2],[3], etc). Importing either of these branches causes an error: Cannot create property 'SourceIndex' on number '0'

Is this a bug of the importer? Or is this bad data construction within the JSON file (as in, should those items at least have some dummy child elements)?

Manually adding in a dummy entry at the 0 position allows the import to succeed, but is there a way to tell the importer to ignore entries like this?

I do have some error checking code within a custom helper that will fail if an element contains 0 or is undefined, but the importer fails and stops the import before any custom helper code is even run.

Iterate over all fields in the named JSON array.

Some json files have an object with multiple named entries, each containing the same structure, instead of an array.

Provide an option to have each field treated as a separate element in an array.

But we have to still support users who want to name the SINGLE object to be processed.

[Feature Request] Import JSON from URL

I'm looking for a way to import data from a JSON-file that's hosted on a URL, specifically the exported URLs created by PathBuilder2e, a character builder for Pathfinder Second Edition. Example: https://pathbuilder2e.com/json.php?id=178425

It'd be great if the process of importing this data could skip some steps, since you have to manually copy/paste the text on the webpage to a text file, then save it as JSON, and then you can use this tool to import it.

Use cases?

Sorry for opening an issue for my (simple) question/suggestion but the "discussion" module is not active for this repository. 🤷‍♂️

My suggestion is that you spend a sentence for the use case of your plugin in the README.md file.
That's because I thought I could use this plugin for my use case but I think I can't.

My use case would be: I have a single JSON file which basically contains one array. The array contains dictionaries and inside these are key/value pairs I'd like to read and transform into one single markdown table in one single note (i.e. markdown file).

Alas, in the README.md file I read about notes (plural) that get created from your plugin?!
So I was wondering what the initial use case for your plugin was and if my use case could make use of your plugin at all? 😳

table helper and regex substitution

I've been trying to work on some text replacement using regex in the body of an import, but I'm running into an issue. I've tried both of the below statements in my template, but neither of them works. They don't error, but the resulting text is not substituted. If I don't escape the single curly braces, I get an "incomplete quantifier" error in the console. Here is an example of the text as well as the regex find and substitute strings.

{{table this (toRegex "\{@spell.(.*?)\}") (toRegex "[[$1]]")}}
{{table this "\{@spell.(.*?)\}" "[[$1]]"}}

Any help would be greatly appreciated and thanks again for the importer!

Is there a way to import todos in Markdown format?

I'm currently trying to import cells that contain a markdown checkmark about whether there are notes on this book or so.

This is what the cells contain:
CleanShot 2023-08-19 at 21 59 43@2x

Part of my template file looks like this:

#### Available Notes

`=this.Printed`
`=this.BookHighlightsandNotes`
`=this.BookSummary`

The result I get though is this:

-
-
-

I would like the result to have the Obsidian style checkmarks. Any way to accomplish that?

Accents issue

I have a problem with the accents when i try to import some data
image

Request: QOL improvements

Is is possible to have/do the following...

  • ... select multiple files to import using the one template?
  • ... Use a numeric (non string) field as the note name? I have an ID field which is all numbers without any "

A wish to use import statements in the handlebars custom helper functions...?

I am attempting to simply require a file into that helper function but it seems to me that when it runs it is running from the "renderer" path location.
/Applications/Obsidian.app/Contents/Resources/electron.asar/renderer
The absolute path for requiring a file works but would be nice to have relative paths.
Not sure if this is doable with ease...?

//example file to require: planets.js

module.exports = {
  planet_symbol: {
    sun: '☉',
    earth: '⊗',
    moon: '☾',
    mars: '♂',
    venus: '♀',
    mercury: '☿',
    jupiter: '♃',
    saturn: '♄',
    neptune: '♆',
    uranus: '♅',
  }
}
// js 'require' with path relative to the helper function file...
const Planets = require('./planets.js');
console.log(Planets.planet_symbol[sun])

Problems with importing from json file

I have json files generated from a database program, e.g.

{
  
  "tags": [
    "Action & Adventure",
    "War & Military",
    "Genre Fiction",
    "Fantasy",
    "Epic",
    "Historical"
  ],
 "metadata": {
    "title": "The Blade Itself",
    "subtitle": null,
    "authors": [
      "Joe Abercrombie"
    ],
    "narrators": [
      "Steven Pacey"
    ],
    "series": [
      "First Law #1"
    ],
    "genres": [
      "Literature & Fiction",
      "Science Fiction & Fantasy"
    ],
    "publishedYear": "2015",
    "publishedDate": null,
    "publisher": "Hachette Audio",
    "description": "long text ",
  }
}

I can query metadata specifically by adding metadata to that field in your plugin, however, then I can't get other areas, like tags, or genres.

On that handlebars website it works

However, if I put the same thing in the template, it doesn't do anything.

Textarea to paste JSON from clipboard

Thanks for the good work!

What about a command to import from clipboard? Or a dialog with a text area to paste JSON (instead of choosing the JSON file)? This would simplify some two-step "export-import" workflows to bring data from other tools (like MS Outlook) to Obsidian...

Valid json with curly braces can cause import to fail

Valid json that includes a string like } { causes the import to fail. The splitting code here that attempts to process multiple json objects in a single file is the source of the issue.

Instead it might be best to check if the top level of the file is an array, or at least have an option to enable/disable this behavior.

Table helper issue

This may be user error, but I've run into an issue with the table helper.

{{table level "0" "cantrip" "1" "1st-level" "2" "2nd-level" "3" "3rd-level" "4" "4th-level" "5" "5th-level" "6" "6th-level" "7" "7th-level" "8" "8th-level" "9" "9th-level"}}

all of those will work except if the level is 0.

Any Idea on how I can get it to match 0?

Thanks for your time and for the great plugin.

How to access the nested input objects?

Hi,
Thanks for developing such a nice plugin. I have a question about accessing the nested input objects in JSON file. I want to import "path" into a Obsidian template.

I have tired {{attachments.path}}. But it doesn't work. Could you please tell me how to import "path" correctly?

Thanks!

  "attachments": [
    {
      "dateAdded": "2022-06-25T16:22:45Z",
      "dateModified": "2022-06-25T16:23:05Z",
      "itemType": "attachment",
      "path": "C:\\folder\\file.pdf",
      "relations": [],
      "tags": [],
      "title": "file.pdf",
      "uri": "http://zotero.org/users/8045138/items/BSI5IT99"
    }

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.