GithubHelp home page GithubHelp logo

bruderstein / pythonscript Goto Github PK

View Code? Open in Web Editor NEW
338.0 21.0 65.0 147.99 MB

Python Script plugin for Notepad++

Home Page: http://npppythonscript.sourceforge.net/

License: GNU General Public License v2.0

C++ 5.63% C 1.18% Python 81.71% Shell 0.01% Tcl 10.22% XSLT 0.02% CSS 0.01% Batchfile 0.08% HTML 0.36% Makefile 0.01% C# 0.04% PowerShell 0.11% GLSL 0.02% GSC 0.61%

pythonscript's Introduction

pythonscript's People

Contributors

bruderstein avatar chcg avatar dependabot[bot] avatar ekopalypse avatar joce avatar lucas-c avatar pryrt avatar shriprem avatar vinsworldcom avatar xomx 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

pythonscript's Issues

Unable to use tkinter with pythonscript because of missing TCL

when attempting to create a GUI with pythonscript an error is raised indicating that the TCL library is either missing or not correct version (if a different python version is installed)

import sys
del sys.path[:]
sys.path = ['C:\\PROGRA~1\\NOTEPA~1', 
'C:\\PROGRA~1\\NOTEPA~1\\plugins\\PythonScript\\lib',
'C:\\Program Files\\Notepad++\\plugins\\PythonScript\\lib\\lib-tk',
 'C:\\Users\\xxx\\AppData\\Roaming\\Notepad++\\plugins\\Config\\PythonScript\\lib',
 'C:\\PROGRA~1\\NOTEPA~1\\plugins\\PythonScript\\scripts',
 'C:\\Users\\xxx\\AppData\\Roaming\\Notepad++\\plugins\\Config\\PythonScript\\scripts']
sys.argv = ['']
from Tkinter import *

root = Tk()

the console shows the following error while trying to run this code:

SyntaxError: invalid syntax
Traceback (most recent call last):
  File "C:\Users\xxx\AppData\Roaming\Notepad++\plugins\Config\PythonScript\scripts\geth3.py", line 11, in <module>
    root = Tk()
  File "C:\Program Files\Notepad++\plugins\PythonScript\lib\lib-tk\Tkinter.py", line 1685, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: Can't find a usable init.tcl in the following directories: 
    {C:\Python27\tcl\tcl8.5} C:/PROGRA~1/lib/tcl8.5 C:/PROGRA~1/lib/tcl8.5 C:/lib/tcl8.5 C:/PROGRA~1/library C:/library C:/tcl8.5.9/library C:/tcl8.5.9/library

C:/Python27/tcl/tcl8.5/init.tcl: version conflict for package "Tcl": have 8.5.9, need exactly 8.5.2
version conflict for package "Tcl": have 8.5.9, need exactly 8.5.2
    while executing
"package require -exact Tcl 8.5.2"
    (file "C:/Python27/tcl/tcl8.5/init.tcl" line 20)
    invoked from within
"source C:/Python27/tcl/tcl8.5/init.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel #0 [list source $tclfile]"


This probably means that Tcl wasn't installed properly.

In my case I have another version of python from the one that tkinter is expecting, pythonscript doesn't come with its own TCL lib.

notepad++: 5.8.7
pythonscript: 0.9.2.0
os: win 7

Autostart of py script

What is the best way to make a script run upon every start of Notepad++?

I currently use the solution below:

# I added the following line in startup.py
exec(open("C:/Users/-----/AppData/Roaming/Notepad++/plugins/config/PythonScript/scripts/AutoTabSpace.py").read())

I don't consider it very elegant:

  1. It relies on a hard-coded path.
  2. It always loads from the user-wide set of scripts. Ideally, one would simply write loadScriptWithName(...) and a matching script would be dynamically loaded (either from the machine-wide or user-wide set of scripts).
  3. One must manually add a line to a file. It would be very nice if scripts could be shipped with configuration files.

Anyway, thanks for the great plugin! It really makes a difference if you don't have to worry about window events, handles or C strings :)


Edit
I've just came across the note in the documentation (Plugin Installation and Usage / Startup).
After having changed the initializing type to ATSTARTUP, my script still doesn't get run when Notepad++ starts (without the line in startup.py). It works however if I start it manually.

Plugin Manager never installs Python library

When you start n++ without PythonScript installed (and have removed any pre-existing library files), and then install PythonScript via the Plugin Manager, the Python standard library is not installed. More specifically, the following directories are either missing or empty: $(N++ directory)/plugins/PythonScript/lib and $(N++ directory)/plugins/PythonScript/scripts. It is the "lib" directory that holds the library files.

Perhaps you have a philosophy that the Plugin Manager is only for PythonScript Lite, which lacks these directories. They take up only 10.7 MB on my installation. It seems unnecessary, IMHO, to exclude these just to save ~11MB, when teraByte drives are readily available and inexpensive these days. This is just my opinion, however. If you wish to have a PythonScript Lite, then it only seems fitting to have a PythonScript Full in the Plugin Manager.

Lacking the library is the only thing keeping Emmet from working through the Plugin Manager, see: Emmitio plugin issue 12. Emmit is the replacement for ZenCoding; which allows one to perform some repetitive HTML tasks much faster, and is customizable. Emmitio is its N++ plugin. You might call it a prestige feature - only the best text editors support Emmit. Without the standard library, when one attempts to expand an Emmit abbreviation into HTML, one gets only "python script plugin did not accept the script". I have found that a recent version of PythonScript Full with the library, when its contents are copied into the "plugins" directory, works just fine with Emmet. I can't say that I've tested it exhaustively, but I also can't say that they are using an old version of PythonScript for development, either. Lacking the standard Python library keeps Emmet from working via the Plugin Manager. This is to say, lacking the standard library is the only thing keeping N++ from supporting Emmit for anyone who hasn't gone so far as to install PythonScript Full by hand, from using Emmit.

When one chooses to install Emmitio from the Plugin Manager without PythonScript already installed and with the PythonScript directory removed, Plugin Manager prompts the user to install Python Script as a requirement. If you simply add the library files to the archive downloaded by Plugin Manager, Emmitio installed this way should begin working when installed with its requirement(s). If you opt for the Plugin Manager to have both a PythonScript Lite and PythonScript Full, then the dependency for Emmitio on PythonScript will have to be changed to PythonScript Full. Renaming PythonScript to PythonScript Lite may also break any other plugins that rely on it without the standard library. I wonder how many PythonScript users use Python without using at least some of its standard library anyway. Maybe a few, but I'm guessing not many; so I favor simply including them. Doing so will require no further action from the Emmitio team to get their plugin as well.

CRLF problem in console window

PythonScript Output:

console.write('Hello\rWorld\nFoo')
HelloWorld
Foo

Expected Output:

console.write('Hello\rWorld\nFoo')
World
Foo

Is the carriage return escape sequence ignored by the console window?

notepad.runMenuCommand in Hebrew

Hello Dave,

When Notpad++ Interface Language is set to English, the following script is executed successfully.

notepad.runMenuCommand("View", "Word wrap")

However, I couldn't find a way to run that script if the Interface Language is set to Hebrew.
I've tried various ".decode('utf8')" commands, but to no avail.

Thank you for this great plugin.

Unable to open console

I'm using npp 7.3.2 32bit
I've installed the python plugin via plugin manager but to console doesn't open

python version problem

(sorry, i can't english well)

I'm use py2.7.5. it installed in 'C:\Python27'. so, py PYTHONPATH contain C:\Python27\Lib.

but pythonscript use py2.7.1. it must change PYTHONPATH or python version.

Temporalily, I changed startup.py and fixed this problem.

solution. add 3 lines before 'sys.stderr = console'

for i, name in enumerate(sys.path):
if name.startswith('C:\Python27'):
del sys.path[i]

I think this solution is not good. but i have no idea about checking python's installed drive.

console.run() can cause a crash when used in a callback function

I am using PythonScript 1.0.8.0 with Notepad++ v6.8.6 on Windows 10. I have found that use of console.run() from a callback function can cause Notepad++ to crash when triggered. The following example causes a crash, but the same command works when called directly.

test.py:

def fileBeforeCloseCallback(args):
    console.run('cmd.exe /?')
notepad.callback(fileBeforeCloseCallback, [NOTIFICATION.FILEBEFORECLOSE])
  1. Create a new file or open a file
  2. Run test.py
  3. Close a file
  4. Notepad++ locks up

Default "print" to output to console

Currently a "print" statement executed during the running of a script will cause text to be inserted into the current document at the caret location. I find that "print" is better used for showing debug messages in the PS console window, and editor.insertText() the preferred method for text insertion into the current document.

Any objection to setting up "print" to output to the PS console window right out of the box?

Is anyone in the habit of using "print" to insert text into a document? If this is "ingrained" into many people's brains to do it this way, then I retract the suggestion.

if any editor.replace() takes place undo action list never ends after (ver. 9.0.1)

I have the following script:

editor.pyreplace('','',0)

If I add:
editor.replace('

  • &nbsp
  • ','')

    and later on type and undo it; it will go back to the state before the script. I tried putting everything in between:

    editor.beginUndoAction()
    editor.replace('

  • &nbsp
  • ','')
    editor.pyreplace('','',0)
    editor.endUndoAction()

    But it does the same thing.

    To reproduce, close and open notepad++ because it will somehow retain the behavior of previously executed script.

    System info:

    windows7
    notepad++ 5.8.7
    Pythonscript: 9.0.1 (Python 2.7.1 (release27-maint-npp, Feb 6 2011, 16:58:20))

    Thanks :)

    Toolbar Icons Tooltip

    When Python Scripts are added to the toolbar they seem to get added with a Tooltip of "Python Script 1", "Python Script 2" etc, would it be possible to change the Tooltip to the script name as it appears correctly in the menu,

    [Enhancement] "Run Previous Script" menu item -> hold Ctrl to EDIT script source file

    I have several levels of folders to organize my Pythonscripts into different categories. As such, it can be a bit of a chore to navigate to one nested a bit down from the top (that I use infrequently enough to not bind a keystroke combo to it). It is even more disheartening when the script errors out and I need to see its source to determine what went wrong, and I realize I have to do that folder menu navigation again. Okay, it's not that big of a deal, but...

    Wouldn't it be nice if the "Run Previous Script" had the same functionality as the scripts themselves do, namely hold Ctrl down while choosing "Run Previous Script" and it will open that script into an editor tab (or simply activate the editor tab if by some odd chance it is already open)?

    Single python script does not appear in Shortcut Mapper

    If the installation only has a single python User Script added as a menu item, that menu item does not appear in the Shortcut Mapper.

    Once a second python User Script is added (or the first one is added twice, thus creating two menu items), then they will appear in the Shortcut Mapper.

    Extend help with editor.flash

    Yes, I simply forgot to add it but in case you find some undocumented function one way which
    should always work is using help from within console

    >>> help(notepad.flashWindow)
    Help on method flashWindow:
    
    flashWindow(...) method of Npp.Notepad instance
        flashWindow( (Notepad)arg1, (int)count, (int)timeout) -> None :
            Flashes notepad++ for the given count and timeout
    
    >>> help(editor.flash)
    Help on method flash:
    
    flash(...) method of Npp.Editor instance
        flash( (Editor)arg1) -> None :
            Flash the editor by reversing the foreground and background colours briefly
        
        flash( (Editor)arg1, (int)milliseconds) -> None :
            Flash the editor by reversing the foreground and background colours briefly
    
    

    Nevertheless, it should be added to chm file

    See #57

    Buttons with relative paths

    Hi,
    first i love this plugin, thanks for the great work!

    I have a problem assigning the toolbar icons for scripts.
    I replaced the absolute paths in "PythonScriptStartup.cnf" to relative ones to keep the notepad++ installation portable.
    Then it comes to a strage behavior. I can click the icon only one time. A new start of the script is then only over the menu or after a restart possible.

    [Suggestion] Display Console on Error

    When testing a script, you want to know if there's any error and what it is.
    You manually open the Console.

    I think it would be very helpful if the Console should be automatically displayed on error.

    Thank you.

    shorcut doesnt work out of the box

    hey
    ctrl+alt+enter is not working after a clean installation of notepad and the plugin
    any extra configs need be done? the shorcut is assigned, ive checked
    cheers

    64 bit plugin wanted

    How is this compiled? Is it just a Python project?
    The installer makes a 32 bit plugin and puts it in Program Files(x86)
    It puts python27.dll in the notepad++ folder (which is 32 bits)
    and pythonScripts.dll (which I'm not sure how created and whether 32 bit specific)

    Copying the files to the 64 bit Program Files just says it can't be run.

    I know almost every computer language existing and can compile it for that. So just tell me and I'll give it a try, if I get the time. I just don't want to waste my time tinkering with the code...

    Thanks! Moshe

    editor.rereplace() not escaping backslash

    Trying this:

    editor.replace("Path=\"Source\\MySecretProject\\obj\\Debug\\MySecretProject.dll", "Path=\"Source\\%ProjectName%\\obj\\%Configuration%\\%TargetFileName%")
    editor.replace("Path=\"Source\\MySecretProject\\bin\\Debug\\MySecretProject.dll", "Path=\"Source\\%ProjectName%\\bin\\%Configuration%\\%TargetFileName%")
    

    However result in the replacement when I run the macro ends up as:

    Path="Source%ProjectName%obj%Configuration%%TargetFileName%"

    Unfortunately I'm limited to having to replace strings with backslashes in them as there are other strings with word 'Debug' which I DON'T want to replace (these ones are not part of msbuild I am using to replace with env vars). And I don't think editor.replace() comes with a way to replace 'whole word only'. Therefore, I am qualifying with a rather large string with backslashes. Hmm..Still thinking of a way.

    Maybe a way out of this with a regex replace. Let me know if you can think of a good workaround, I'm new to python.

    sys path not set as the pythonscript path if there's an existing python install

    Hello it seems that if there's a version of python installed already; the path of any python scripts inside of notepad++ will use that one, instead of the one with pythonscript.

    the way i've been able to get around it like this:

    import sys
    del sys.path[:]
    sys.path = ['C:\\PROGRA~1\\NOTEPA~1', 'C:\\PROGRA~1\\NOTEPA~1\\plugins\\PythonScript\\lib', 'C:\\Users\\xxx\\AppData 
    \\Roaming\\Notepad++\\plugins\\Config\\PythonScript\\lib', 'C:\\PROGRA~1\\NOTEPA~1\\plugins\\PythonScript\\scripts',
     'C:\\Users \\xxx\\AppData\\Roaming\\Notepad++\\plugins\\Config\\PythonScript\\scripts']
    

    I'm not sure if this causes an issue with different versions of python or not, i had an issue using urllib and json libs.

    os: windows 7
    pythonscript: 0.9.2.0
    npp: 5.8.7

    Doc Format - class clase

    In the documentation, can you modify the case of the class/function so that it's directly executable in the python console ?

    Example Editor.addText(text) would be editor.addText(text)

    Thank you

    Move to Python 3.8

    Python 2.7 is about to become obsolete. Could the scripting host be upgraded?

    Problem with Windows 64bit, Python 64bit preinstall

    Dear Dave,
    I have python 64bit preinstall in my C:\Python27 directory and ofcourse a 64bit version of python27.dll in system dir. When I select PythonScript/Console it first say Unknown error, then an empty console window and can not get anyresult. How can we fix this. I really dont want to remove my python because some dependencies. Please help

    notepad.getFiles() returns incorrect results.

    As per issue title, getFiles() sometimes returns incorrect results. See here: https://sourceforge.net/p/npppythonscript/discussion/1188886/thread/bc28b0dd/

    I believe the issue has to do with the implementation here: https://github.com/bruderstein/PythonScript/blob/master/PythonScript/src/NotepadPlusWrapper.cpp#L268, specifically:

    for(int view = 0; view <= 1; view++)
        {
            count = (idx_t)callNotepad(NPPM_GETNBOPENFILES, 0, view);
    

    The NPP documentation about the above message (at http://docs.notepad-plus-plus.org/index.php/Messages_And_Notifications), states that the message requires the constants PRIMARY_VIEW or SECOND_VIEW, which do not appear to equate to 0 and 1 respectively. (They are, I think, 1 and 2).

    The call needs to be something like:

    count = (idx_t)callNotepad(NPPM_GETNBOPENFILES, 0, view ? SECOND_VIEW : PRIMARY_VIEW);
    

    I believe that would fix the issue, though I have done no testing. (I don't have a build environment - not just being lazy!)

    Some troubles with installing plugins to userdata folder (AppData/Roaming/Notepad++/)

    Hi!

    I had a problem when tried to install plugin(PythonScript 1.0.8.0 Full) to userdata folder. The plugin manager show notification error "unknown exeption" at attempt to call "Show Console".
    If remove plugin to "Program Files (x86)/ Notepad++/" it working fine.
    But another problem appears with Emmet plugin(it in the userdata folder). To fix it help the next line at the end of startup.py (Program Files (x86)/ Notepad++/plugins/PythonScript/scripts/): sys.path.insert(0, r'C:\Users\Andy\AppData\Roaming\Notepad++\plugins\EmmetNPP').

    Resume

    If people keep their plugins in "AppData/Roaming/Notepad++/" and use Emmet they must:

    • remove PythonScript plugin to "Program Files (x86)/ Notepad++/" ;
    • insert line sys.path.insert(0, r'C:\Users\Andy\AppData\Roaming\Notepad++\plugins\EmmetNPP') at the end of startup.py (Program Files (x86)/ Notepad++/plugins/PythonScript/scripts/) .

    notepad.prompt() input control won't accept input

    The notepad.prompt() input area control has a bug. It appears to be capable of five lines of input. So try the following by entering it at the PS console's >>> prompt:

    notepad.prompt('','','a\r\nb\r\nc\r\nd\r\ne\r\n')

    The dialog box appears and a/b/c/d/e lines appear (pre-selected) within it. Now use the up-arrow key to move the caret up to the top line (before the 'a'). Now type some alphanumeric characters, which should be inserted before the 'a'...but they are not; nothing appears.

    New script -> SaveAs remembers wrong folder

    I have two portable installs of N++ and PS:

    N++ 7.2.2 with PS 1.0.8.0 (32-bit)
    N++ 7.5.6 with PS 1.1.0.0 (64-bit)

    From the 64-bit version, when I execute Plugins -> Python Script -> New Script, it brings up a SaveAs box with the default folder shown being the ...\plugins\Config\Pythonscript\scripts\ folder from the 32-bit version. I expect it to be the equivalent folder underneath the 64-bit version's folder structure.

    If, in the 64-bit version, I navigate to its "correct" (the one in the 64-bit folder hierarchy) scripts\ folder, complete my SaveAs, continue working, etc., then when I need to make another new script it remembers the correct scripts\ folder to use. I can restart the 64-bit N++ and it still remembers...all good.

    However, if I go back to the 32-bit version and make a new script there (it ALWAYS knows its "correct" scripts\ folder), then the NEXT time I come back to the 64-bit version and make a new script, it is back suggesting a default new script folder from the 32-bit version's folder hierarchy again.

    Kinda minor...but also kinda annoying. I guess it goes away when I am fully ported to 64-bit and I erase the 32-bit version...

    User Hotspot Notification in Console

    Since it is possible to create hotspot styles in the console, would it be possible to have a console hotspot click callback?

    For example, I can write a hostspot using:

    def write_styled(txt):
        mask = 7
        style = 2
        cons_ed = console.editor
        pos = console.editor.getLength()
        console.write(txt)
        cons_ed.setReadOnly(0)
        cons_ed.startStyling(pos, mask)
        cons_ed.setStyling(len(txt), style)

    Then I tried:

    console.editor.callback(myHotSpotFunc, [SCINTILLANOTIFICATION.HOTSPOTCLICK])

    But this does not appear to be supported.

    wrong escape management in user data path

    the user name I use on my winxp64 machine is rdeve

    if I load the PythonScript plugin and into the python console I ask to print the value of sys.path I expect to see among the others:

    L:\Documents and Settings\rdeve\Application Data\Notepad++\plugins\Config\PythonScript\scripts

    instead what I get is the following:

    'L:\Documents and Settings\rdeve\Application Data\Notepad++\plugins\Config\PythonScript\scripts'

    that is not defining a valid path infact trying to put a script into that folder, the python loader could not load it.

    I'm using PythonScript 0.7.0.0

    [Question] Is "To Input" command useful?

    Is the console output's context-menu command To Input useful?

    Using the mouse, you can simply click in the Input field.
    Using the keyboard, you can press Tab and the focus moves to Input.

    Thank you.

    Problem with Python Script: npp + windows 8

    Hi!
    At first, sorry for my english.
    Sergey Chikuyonok has sent me to you as developer of python script.
    I've got a problem with it - it doesn't respond on any actions from Sergey's plugin Emmet and doesn't show scripts Python Script > Scripts . Console is empty
    It was installed through Plugin Manager.
    I've got notepad 6.3.1 version
    So if you can, please help me to solve the problem!
    Thanks

    64 bit build

    Hi, are there any plans to make a 64 bit build for notepad++ 64 bit? Are there build instructions available anywhere, I would like to participate on the PythonScript repository.

    [Enhancement] Add "Input History" navigation buttons to Console

    Currently the only way to navigate through "Input History" is via the Up/Down arrows.

    1. New users may not be aware of this functionality.
    2. "Mouse-Oriented" users would prefer navigating with the mouse.

    How about adding << and >> buttons to the console?
    A ComboBox/Drop-down List would be even better.

    Thank you.

    Can't have dir with no .py files in menuing "path" to .py file

    Not a great issue title. :)
    But here's the thing:

    Make a folder under ...\plugins\Config\PythonScript\scripts\ and call it test1\.
    (Manually) create a file called test3.py in the test1\ folder.
    Restart Notepad++ and see that you can see test3 (the .py file) in the menus:

    image

    That is all well and good and is expected behavior; it is just creating a "testbed" for the following:

    Now use Windows Explorer to make a folder under ...\plugins\Config\PythonScript\scripts\test1\ and call it test2\.
    Move test3.py from test1\ to test2\.
    Note test1\ now has no other files or dirs besides the dir called test2\
    Restart Notepad++ and see that you cannot access test3 via the menus:

    image

    Suspect that this is because test1\ has no .py files in it. In fact, picking up from the previous step, creating test4.py in the test1\ folder results in correct behavior (after N++ restart):

    image

    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.