Giter VIP home page Giter VIP logo

halirutan / wolfram-language-intellij-plugin-archive Goto Github PK

View Code? Open in Web Editor NEW
193.0 26.0 30.0 35.99 MB

Wolfram Language and Mathematica plugin for IntelliJ IDEA.

Home Page: https://wlplugin.halirutan.de/

License: Other

MATLAB 0.03% Mathematica 11.63% HTML 0.31% Java 68.22% Lex 0.57% Kotlin 7.25% Limbo 11.98% Objective-C 0.01%
mathematica wolfram-language intellij intellij-plugin intellij-platform

wolfram-language-intellij-plugin-archive's Introduction

Download Count Join the chat at https://gitter.im/Mathematica-IntelliJ/Lobby Build Status

Mathematica (Wolfram Language) support for IntelliJ IDEA

teaser

This is an easy to install plug-in for almost all IntelliJ based IDEs like IDEA or PyCharm. It will turn the IDE you love into into a powerful development tool for Mathematica and Wolfram Language code. Since the plug-in and the Community Edition of IDEA is open-source, you can use everything completely free of charge. People, who just want to use the plug-in should take a look at the official website wlplugin.halirutan.de.

For a very quick start just download and install the free Community Edition of IDEA. After you have done that, open the Settings by pressing Ctrl+Alt+S (Cmd+, on OS X) and navigate to Plugins in the right column. On the right side you find the button Browse repositories and there you use the search box to find the Mathematica Support. With a right-click you can install it and after the suggested restart of IDEA everything is set up.

If you like the plug-in, please leave a comment and a rating at the IntelliJ IDEA Plugins page.

DocsDocumentation

There are two kinds of documentation: For users there is the GitHub Wiki page that I will update regularely and a very detailed blog post on the official website. There, you will learn what features the plug-in provides and how you can use them.

For developers, the first action is to set up the build-environment to compile the code into an IDEA plug-in. There is a very detailed how-to on the official website that explains every step. Additionally, you will find a screen-cast there, where the procedure is shown step by step. The code itself contains java-documentation that is uploaded to the repository's IO page.

Finally, there I have posted information on stack exchange and the Wolfram Community. Here is a list of probably interesting readings:

dev image Development Build Status

Code

When you want to crawl through the code, you should know that the master branch only contains the latest stable release. The current development will (almost) always take place in feature or bugfix branches that derive from the develop branch. This kind of follows the GitFlow branching model.

Testing and Continuous Integration

Testing the plugin is not as simple as writing unit test since most features need the environment of the IDE. Currently, I'm still working on including tests in a separate branch that will soon be merged into the main develop line.

On each push the code is compiled and checked for errors by Travis CI. When a feature is finished or a bugfix ready, I will tag this commit and Travis CI will automatically create a release from this which can be installed and tested by everyone.

You want to help but don't know Java?

No problem. If you like to contribute something, then there are a lot more ways than just with code! Here is a small list:

  • We need people that heavily test the plug-in and report bugs. This can be as simple as just using the plug-in for your work, but when you come across weird behavior, you try to reproduce it and report it with a small example of what you expect.
  • Are you a design savant? Do you understand the beauty of carefully chosen colors and icons? Currently, I'm doing this by myself but neither do I have the time I would like to spend for this, nor do I have the experience. We need icons and syntax highlighting that fit perfectly into the Darcula and Default IDEA color schemes.
  • Are you a work-flow optimizer with a good feeling for how features should work to make them as intuitive as possible? Drop by and explain how we can make the plug-in even more awesome.

bug image Reporting issues

For issue- and bug-tracking GitHub Issues is used. If you find bugs, experience weird behavior or have feature suggestions please create a new issue.

Note that the plug-in itself contains a bug-reporter. When an unhandled exception is thrown, you are notified by IDEA and you can give as much details as possibles which are then automatically turned into a new issue in the bug-tracker.

contact image Credits, Contact and Licensing

Credits

A lot of people helped to bring this project to life. Without them, it would probably have died a long time ago. Especially 4 people supported the plug-in from its very buggy first version. They were never tired of discussing feature details, testing new stuff, reporting bugs and suggesting future improvements:

  • rsmenon: Provided parts of the Module and Color Scheme implementations, testing. Improvements of the parsing for Mathematica version 10.

  • Szabolcs Horvát: Heavy testing. Convinced me to implement a Structure View provider and discussed every detail, especially how it should work.

  • Leonid Shifrin: Most interesting discussions about implementation design and details.

  • Rolf Mertig: Testing and discussions about important features that are available in Wolfram Workbench.

In addition to that, a special thanks goes to Aliaksandr Dubrouski and Jakub Kuczmarski. The first on pointed me to Travis CI and explained how I can add support for it. The second one discussed details of the MUnit` support in Wolfram Workbench.

Contact

The easiest way to make contact is to write in the the dedicated stackexchange chat. There, you should ping me (@halirutan) so that I get notified. If you don't have enough reputation to talk there, feel free to write me an email. My address can be seen by evaluating this in Mathematica

Uncompress["1:eJxTTMoPChZhYGAoSCwpykzOdshIzMksKi1JzNNLSQUAgX0JmQ=="]

If you have specific feature questions, please don't hesitate to open a new issue in YouTrack.

Licensing

The general license for the IntelliJ IDEA Plugin is the MIT License. Users should note that Wolfram Research Inc. (WRI) has generously granted this project the right to use the internal documentation of Mathematica and make it available as part of the plugin. The only requirement was to put the legal information in a place where end-users find it. Therefore, please note that..

This software includes information that is Copyright © 2013 Wolfram Research, Inc. Such information is used with permission and for the limited purpose of enabling code completion and hints in the Mathematica IntelliJIDEA Plugin. Any other use requires written permission from the copyright holder.


Icons made by Freepik from www.flaticon.com is licensed by CC BY 3.0

wolfram-language-intellij-plugin-archive's People

Contributors

autuanliu avatar cbarbat avatar fordhurley avatar gitter-badger avatar halirutan avatar rsmenon avatar szhorvat 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wolfram-language-intellij-plugin-archive's Issues

Comment logic is buggy

Several things don't work as they should work:

  • opening a comment should insert the closing *) automatically
  • using SmartCompletion leaves wrong code

Review parsing of implicit multiplication

I find it very unfortunate, that you can simply write (missing comma)

{
    center = prop["Center"],
    centralHeith = prop["CentralHeightValue"]
    header = Import[file, {"Heyex", "FileHeader"}]
}

Note that this is correct synax (although not sematic)!! I'm not sure whether it isn't better to try to fix this. Currently it is even parsed not correctly!

Autocompletion for symbols mentioned at top level

Personally I would find it useful to enable autocompletion for all symbols mentioned at the top level. Example:

foo[x_] := (y=x^2; y)

bar

baz;

There will be no auto-completion at the top level for x, y, bar and baz. There will be for foo.

I would find it useful to also have it for bar and baz.

There are situations when some global symbols I use do not get defined at the top level for some reason. I want auto-completion for these. Example of how this can happen:

Conditional definition:

If[$OperatingSystem === "Windows",
  fun[] := ...
  ,
  fun[] := ...
]

Certain special initialization:

loadStuff[] := (various initializations; myGlobalVar=1;)

ReloadPackage[]:= (...; loadStuff[]; ...)

My typical use case for a function like ReloadPackage[] is to recompile LibraryLink stuff, and then re-do the necessary initialization.

Wrapping behavior on paste

When I paste in code from elsewhere (such as an existing .nb) into a .m I'm editing in Idea, it always seems to word-wrap (at 80 columns, I think).

Is there some way to disable this behavior, or, at least, to set the wrapping threshold to something much larger?

Expand selection(CTRL+W), navigation keymaps...

I'm just trying to use IntelliJ as Mathematica IDE.
However, ctrl + w is not working as described on the web site.
Or other navigation keys like ctrl+[, ctrl+]..
In fact, there's no key binding for these.

Please let me know how to define those key bindings.

I'm using Mac OS X 10.10.1 and IntelliJ 14.0.2

Thanks.

Suggestion: Add support for MathLink/WSTP .tm files

.tm files are processed by

"C:\Program Files\Wolfram Research\Mathematica\10.4\SystemFiles\Links\WSTP\DeveloperKit\Windows-x86-64\CompilerAdditions\mldev64\bin\wsprep.exe"

or

"C:\Program Files\Wolfram Research\Mathematica\10.4\SystemFiles\Links\MathLink\DeveloperKit\Windows-x86-64\CompilerAdditions\mldev64\bin\mprep.exe"

to produce .c code necessary to build an application that can be Install[]ed as an external program.

Here's an example of mine:

:Evaluate: BeginPackage["InfiniTAM`"]

:Evaluate: << numerics`;
    poseMatrixQ[x_] := numericMatrixQ[x, {4, 4}];
    IntrinsicsPattern[] := {fx_?NumericQ, fy_?NumericQ, cx_?NumericQ, cy_?NumericQ, w_Integer, h_Integer};
    NamelessIntrinsicsPattern[] := {_?NumericQ, _?NumericQ, _?NumericQ, _?NumericQ, _Integer, _Integer};

:Begin:
:Function:       createScene
:Pattern:        createScene[voxelSize_Real]
:Arguments:      { voxelSize }
:ArgumentTypes:  { Real }
:ReturnType:     Integer
:End:

:Evaluate: EndPackage[]

It would be nice if the plugin recognized these files (basically just the tags) and could act accordingly.
Even just highlighting/autocompleting the keywords and not counting them as syntax errors would be enough, it doesn't need to recognize that after :Function: there should be a C identifier.

Reference

https://reference.wolfram.com/language/tutorial/WSTPDeveloperGuide-Windows.html
https://reference.wolfram.com/language/ref/file/file.tm.html
https://reference.wolfram.com/language/tutorial/SettingUpExternalFunctionsToBeCalledFromTheWolframLanguage.html

See

C:\Program Files\Wolfram Research\Mathematica\10.4\SystemFiles\Links\MathLink\DeveloperKit\Windows-x86-64\MathLinkExamples

or

C:\Program Files\Wolfram Research\Mathematica\10.4\SystemFiles\Links\WSTP\DeveloperKit\Windows-x86-64\WSTPExamples

subfolders for some examples.

Enhancement: `With[{x=0},{y = x}, ...]` support

An undocumented feature of With is that it allows for constructs like

With[{x = 1}, {y = x + 1}, {x, y, x + y}]

where it is possible to define variables like y using earlier defined variables. However neither this nor the official IDE or Mathematica support this. In Mathematica this construct evaluates correctly but the syntax-highlighting suggests an error:

Mathematica graphics

greek letter in comment

It looks like that "Collapse all [Name] sections" works for greek letters in the usage message but not for greek letters in the comments.

For example:

snip20151012_4

Help for exporting function names

When writing a function it would be nice if there was a simple way to export the symbol from the package by e.g. creating a usage message at the right place.

Spellchecking for comments and strings

Feature request: activate spell checking for comments and strings. Will help produce higher quality documentation. Also, thank you for making this plugin!

Pretty printing/exporting of Mathematica code

The copy-on-steroids plugin rocks like hell, because you can copy and past source code as RTF or HTML with all highlighting included. If we could work this logic into the Mathematica plugin, you could export fully highlighted and indented Mathematica code (probably as PDF for publications).

Unfortunately, in its current state the copy-on-steroids don't work with the Mathematica plugin.

.WolframResources file support

Workbench 3 (beta) seems to create projects with a resource file called .WolframResources instead of .MathematicaResources. Not critical, but it would be nice if that would also be detected as a IntelliJ Mathematica project.

Make SmartCompletion for Check[..,..,mess::age]

In

Check[expr,failExpr, sym::tag]

it should be possible to complete the message automatically. Additionally, it should be considered to do something similar for Quiet and Throw and Catch.

Multiple click to extend selection

Thanks for the great work on this plugin! I really like it!
However, it's missing one feature that's very important to me: Multiple click to extend selection.

I am aware that the editor already supports Ctrl + W to do this, but it's much easier (and more like the Mathematica Front End and Wolfram Workbench) if it were handled via multiple click.

I was able to work around it a little bit by adding a mouse shortcut to "Extend selection" for double-click, but it isn't quite the same.

Consider the following code:

foo[n_Integer] := With[{},
	Partition[Range[1, n], 2, 1]
]

Double-clicking on the head of an expression (e.g. Range) will highlight the entire expression, but in Mathematica it only highlights the head.
Similarly, multiple-clicking on the head of an expression will highlight the whole line and stop there. In Mathematica, it will continue to extend the selection (e.g. triple clicking Range will highlight the whole Range expression).

This is very useful when copying/pasting code, determining precedence, and even seeing how the code will parsed/evaluated.

Would it be possible to add this feature?
So far, it looks like 3+ clicks will only select the entire line, and there is no way to add a triple-click mouse shortcut.

I'd really like it, as the formatting in this IDE and this plugin (Ctrl + Alt + L) is very, very much preferable to the one built into the Wolfram Workbench plugin.

Again, thanks for the great work!

Repeated is not recognized

In the following code

Fun[1, 0.., {m___}, OptionsPattern[]] := 1;

the Repeated statement seems to confuse the plugin. The code is flagged as an error with the description "More input expected". I'm using Idea 2016.1.1 with the Plugin Version: 1.3.4 on Fedora Linux 22.

Smart completion of Options does not work

Smart completion of Options - not work (after Ctrl+Shift+Space - red box 'No suggestions')

14.04.1-Ubuntu
IntelliJ IDEA 2016.1
Build #IC-145.258, built on March 17, 2016
JRE: 1.8.0_76-release-b18 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o

same situation on Windows on other machine
same in PyCharm

screenshot_1

coloring non built-in symbols

Works, can be done with setting a color for "Identifier", but:

  • Identifier is not the best name (maybe Other symbols)
  • In an example "Module" is colored too and that is completely confusing (it works ok in editor though)

Indentation of <| ... |>

It would be an improvement if the indentation of <| worked in the same way as {.
For multiline <|s the current behavior looks ugly as it is regarded as normal operator with continuation indent.

Drop support for *.nb

After installation of the plugin the first thing to do is to drop *.nb from supported files and associate files with MMA executable.

I don't know if the latter is possible from plugin perspective but the former should be relatively easy to change.

p.s. Sometimes I want to open *.m files with MMA, I had to add MMA executable to external tools and I can open .m file from context menu. Maybe that could be automated too during installation?

Implicit Times inspection uses 100% CPU

When there is an error in the file and the implicit times inspection (missing comma, missing semicolon) is turned on, then the CPU usage increases dramatically.

screenshot

Refactoring: change text in usage messages

This is a feature suggestion.

When renaming symbol f to g using the refactoring tools,

f::usage = "f..."

should change to

g::usage = "g..."

provided that the usage string starts exactly with f.

Refactoring is broken

I have 2.0.11. There is something wrong with symbol renaming. While editing the name of a symbol, it updates all occurrences. But after pressing Enter to finalize the edit, only a single occurrance of the name changes. The rest reverts to the original form.

Here's a screen recording:

untitled3

Completion inside strings

It would be extremely helpful if one could (actively) autocomplete function names inside strings. In addition one could provide further help which only makes sense in strings.

Pattern not highlighted properly

The following pattern isn't highlighted properly:

image

Replace[result, HoldComplete[ReturnPacket[{_ :> expr_}]] :> HoldComplete[expr]]

Compare the Front End:

image

Support of (* ::Subsection::Closed:: *)

Support of the structures like
(* ::Subsubsection::Closed:: *)
(Section Title)
is highly appreciated!

Was reported by a guest here.

Sidenote: The smart completion in comments doesn't work as advertised. I need to look over this anyway.

Variable resolve in With idiom

In the very convenient idiom

With[{var = var},
    var + 1
]

the rhs of the assignment is a reference to the lhs which is wrong. It should have a reference outside of the With

Complete support for named slots

Currently, only this kind of named-slots are supported: #name
I knew that there was another form like #["name"] that is still not included into the plugin, but apparently even the form #"name" is valid. See this discussion on stackexchange for more information.

Not possible to create SDK on Windows

On Windows the installation directory structure is different from Unix and therefore, it is not possible to select an installation directory when creating a Mathematica SDK. It always returns "no valid installation path"

Does not support greek letters

screen shot 2015-07-07 at 8 30 48 pm

As I am working with .m (instead of .nb) files directly, I really hope that I can use greek letters like μ, other than Mathematica notations like [Mu]. However, it seems that Mathematica-IntelliJ-Plugin does not think greek letters are valid letters -- it refuses to auto reformat the code snippet and shows red lines on the scroll bar.

Is there anyway to enable the use of greek letters in source code?

Thanks!

Incorrect string recognition after Put

The line FullDefinition[output] >> "mathematicaHILLS.m" gets the feedback "Could not parse right hand side of Put or PutAppend expression" as well as essentially missing the first quote symbol. It interprets it as opening a string at the end of the line that is then never closed.

The code runs just fine in Mathematica.
I do not know if this is an issue with the plugin or something from Mathematica, though I suspect more the latter, with no evidence.

screen shot 2015-07-06 at 5 14 35 pm

Nitpicks on stringifying operators

These are nitpicks, and not worth spending time on. But since I found some documentation on how << & friends work (and how they differ from # and ::), I might as well put the link here.

<<, >>, >>>, :: and # turn the following unquoted text into a string.

The first three are designed to be used with file names. The characters that can terminate the string are described here.

They are a bit different from # and :: in that

In[3]:= FullForm[Hold[<<asd[]]]                                                 
Out[3]//FullForm= Hold[Get["asd[]"]]

while

In[4]:= FullForm[Hold[#asd[]]]                                                  
Out[4]//FullForm= Hold[Slot["asd"][]]

Notice that [ was not a terminator in the first case. The documentation (linked above) describes precisely which characters are terminators. The IDEA plugin doesn't handle this case correctly.

Another nitpick is that ::foo is an incomplete expressions (syntax error), yet it is not flagged by IDEA.

Move to the definition (Workbench's F3)

I think it is useful to have a shortcut for doing this:

having selected a symbol, or a cursor inside/right after, move to the line where the first definition of that symbol is found.

  • the definition can be in different file from the project,
  • when selected e.g. Context`symbol, or right after, it doesn't need to be able to find a definition which isn't using a full name (e.g. symbol[x_]:=x^2), it is a user's duty to select only a symbol before search (that's how it is done in WB, probably because it was faster to implement)

It is done with F3 in Workbench.

Reference in blank head not found

In this code

myHead = Boing;
f[x_myHead] := x^2;

myHead in the pattern is not highlighted when you are over the myHead in the first line, although the first reference is highlighted.

Enhancement: `{x = 5}~With~x` support

I sometimes write With statements like this, but the plugin unfortunately does not recognize them (meaning the x is not properly highlighted on the rhs).
A more uniform handling of binary operators should allow doing this.

Interestingly, not even the MM 11 notebook interface supports this.

Not used local variables indicator

I must say I find it useful, yet not essential. If it is easy to add it would be nice.

Here is a screenshot with WWB enchanced Eclipse editor:

image

definitions inside lists are not recognized/cataloged by the plugin.

I just noticed that if you define a variable/function inside a list, it is not recognized by the plugin. For example:
{
var = "var";
f[]:="function";
}
both var and f will not be cataloged by the plugin.
Notice that although its not common practice to define variables like this, it is perfectly fine to do so in the notebook interface.

On a side note, I cant thank you enough halirutan for the plugin. It is so useful and gets updates all the time.
Cheers

Built-in symbol highlighting broken in 1.3.3

Built-in symbol highlighting got broken in 1.3.3.

image

Module, If, While, True, etc. should be blue but they are white.

However, explicitly writing the context name highlights them again.

image

Color-settings-panel is missing some colors

The colorsettings panel does not represent all possible colors that can be adjusted. For instance the local variables of Module/Block are missing. We need to adjust the demo-text at

Mathematica-IntelliJ-Plugin/resources/colors/demoText.txt 

and then fix the code at de.halirutan.mathematica.codeinsight.highlighting.MathematicaSyntaxHighlighterColors. To include all color-settings we need to support

public final static TextAttributesKey COMMENT = TextAttributesKey.createTextAttributesKey("MMA.COMMENT");
public final static TextAttributesKey STRING = TextAttributesKey.createTextAttributesKey("MMA.STRING");
public final static TextAttributesKey OPERATORS = TextAttributesKey.createTextAttributesKey("MMA.OPERATORS");
public final static TextAttributesKey LITERAL = TextAttributesKey.createTextAttributesKey("MMA.LITERAL");
public final static TextAttributesKey IDENTIFIER = TextAttributesKey.createTextAttributesKey("MMA.IDENTIFIER");
public final static TextAttributesKey BUILTIN_FUNCTION = TextAttributesKey.createTextAttributesKey("MMA.BUILTIN_FUNCTION");
public final static TextAttributesKey BRACE = TextAttributesKey.createTextAttributesKey("MMA.BRACE");
public final static TextAttributesKey PATTERN = TextAttributesKey.createTextAttributesKey("MMA.PATTERN");
public final static TextAttributesKey SLOT = TextAttributesKey.createTextAttributesKey("MMA.SLOT");
public final static TextAttributesKey ANONYMOUS_FUNCTION = TextAttributesKey.createTextAttributesKey("MMA.ANONYMOUS_FUNCTION");
public final static TextAttributesKey MESSAGE = TextAttributesKey.createTextAttributesKey("MMA.MESSAGE");
public final static TextAttributesKey USAGE_MESSAGE = TextAttributesKey.createTextAttributesKey("MMA.USAGE_MESSAGE");
public final static TextAttributesKey MODULE_LOCALIZED = TextAttributesKey.createTextAttributesKey("MMA.MODULE_LOCALIZED");
public final static TextAttributesKey BLOCK_LOCALIZED = TextAttributesKey.createTextAttributesKey("MMA.BLOCK_LOCALIZED");
public final static TextAttributesKey BAD_CHARACTER = HighlighterColors.BAD_CHARACTER;

Enhancement: code folding for sections

It would be great if code folding were supported for the standard section, subsection, etc comments:

(* ::Section:: *)
(*section title*)
...code...
(* ::Section:: *)
(*section title*)

Or it might require adding an "end section" comment, like this?

(* ::Section:: *)
(*section title*)
...code...
(* ::End Section:: *)
(* ::Section:: *)
(*section title*)

Failing that, is there a way to get the built-in custom folding regions, e.g.,

//region Description
...
//endregion

to work in a Mathematica package file?

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.