Coder Social home page Coder Social logo

twig-extensions's Introduction

Twig Extensions Repository

WARNING: This repository is abandoned in favor of Twig Core Extra extensions.

  • ArrayExtension: shuffle filter -> no equivalent
  • DateExtension: time_diff filter -> no equivalent
  • I18nExtension: trans filter -> use the trans filter from the Symfony Translator extension (symfony/twig-bridge)
  • IntlExtension: localizeddate, localizednumber, localizedcurrency filters: use the Twig intl extra extension: format_date, format_number, format_currency, ...
  • TextExtension: truncate, wordwrap filters: use the Twig string extra extension: u filter

This repository hosts Twig Extensions that do not belong to the core but can be nonetheless interesting to share with other developers.

More Information

Read the documentation for more information.

twig-extensions's People

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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

twig-extensions's Issues

Problem with localizednumber('duration')

I have 'ru_RU' locale and I want to format duration: {{ 10240 | localizednumber('duration') }}
Expected result is 2:50:40, but i got 10 240.
I played with INTL PHP provider and see that NumberFormatter doesn't have full pattern for ru_RU:

$en_formatter = new \NumberFormatter('en_US', \NumberFormatter::DURATION);
var_dump($en_formatter->getPattern());
$ru_formatter = new \NumberFormatter('ru_RU', \NumberFormatter::DURATION);
var_dump($ru_formatter->getPattern());

And I got:

string(544) "%with-words:
    0: 0 seconds;
    1: 1 second;
    2: =#0= seconds;
    60/60: <%%min<;
    61/60: <%%min<, >%with-words>;
    3600/60: <%%hr<;
    3601/60: <%%hr<, >>>;
%%min:
    0: 0 minutes;
    1: 1 minute;
    2: =#0= minutes;
%%hr:
    0: 0 hours;
    1: 1 hour;
    2: =#0= hours;
%in-numerals:
    0: =#0= sec.;
    60: =%%min-sec=;
    3600: =%%hr-min-sec=;
%%min-sec:
    0: :=#00=;
    60/60: <#0<>%%min-sec>;
%%hr-min-sec:
    0: :=#00=;
    60/60: <#00<>%%hr-min-sec>;
    3600/60: <#,##0<:>>>;
%d
string(27) "%duration:
    0: =#,##0=;
"

As I see, ru_RU locale isn't full and don't support any of formats.
Maybe need force locale to en_US, if $style == 'duration' in Twig_Extensions_Extension_Intl?

Infinite Loop

Run the following code:

{% macro infiniteLoop(trial) %}
<input type="radio" id="{{ id ? id : name|toIdName }_yes" />
{% endmacro %}

I know one brakcet is missing but there sould be an error.

Please tag a new release

There have been some months without a release. Maybe another release might come in handy.

Also testing against the new HHVM runtime has been done and it might be quite interesting to some people to know a specific version of twig/extensions has been tested against HHVM.

url_decode?

I needed url_decode few days ago, but there is only url_encode in Twig.

Any reason not to have that? Can we have it in this project or in Twig?

Auto install doc

I noticed that doc is not synced with github repo.

It would be nice to schedule some cron to update it periodically.

Translating plurals

According to docs plural translations should be defined as:

{% trans %}
    I have one apple.
{% plural apple_count %}
    I have {{ count }} apples.
{% endtrans %}

I'm using Twig Gettext Extractor to extract translations (it just forces twig to loadTemplate), but for some reason, variables are extracted like %count% instead {{ count }}, which produces untranslated messages.

I tried changing template to:

{% trans %}
    I have one apple.
{% plural apple_count %}
    I have %coun% apples.
{% endtrans %}

but then %coun% is not replaced with actual variable value.

I used transhoice and it worked, but I like this plural tag more because it has better poedit integration.

More then that, when I enable Twig_Extensions_Extension_I18n in my Silex app $app['twig']->addExtension(new \Twig_Extensions_Extension_I18n()) I get:

Warning: gettext() expects exactly 1 parameter, 3 given in resources/cache/twig/70/d7/fd80c73ce0b5c01ac2dc57367f74.php on line 401

Part of d7/fd80c73ce0b5c01ac2dc57367f74.php:

echo ">";
echo twig_escape_filter($this->env, gettext($this->getContext($context, "label"), array(), $this->getContext($context, "translation_domain")), "html", null, true); // #401
echo "</label>

This warning happens for each label translated in my form.

LICENSE file missing

The file LICENSE is referred to from copyright notices but it is not included in the repo.

localized number formatter settings

Hi Fabien,
Is it possible to add custom settings to the formatter used by the localizednumber filter?

For instance I would require to restrain the number of decimals between 0 and 2. The problem I have is that the Intl extension class uses functions outs of the class scope, which could not be overridden ( twig_localized_number_filter, and twig_get_number_formatter).

Maybe I'm mistaken, but can you tell me how to achieve this goal?

Regards,
Thierry

I18n: Option to specify alternatives for gettext / ngettext (extension config?)

As explained by me on php-gettext/Gettext#82 (comment):

I don't want to rely on the php gettext extension.
[...]
However the problem is that Twig_Extensions_Extension_I18n compiles twig nodes (trans, plural, notes) to use internal php gettext functions(gettext and ngettext), making Gettext\Translator unusable because Gettext\Translator::dpgettext is never being called inside Twig templates.

See I18n.php and Trans.php

FYI, Gettext/Gettext functions are located here:

https://github.com/oscarotero/Gettext/blob/master/src/translator_functions.php

Tag 1.2.0

I'd like to use the localizeddate and localizedcurrency as described in the docs. The last tag is from July, so is there any reason why there is no new stable tag yet?

Extraction of context information for I18n

The way the gettext function is supported using the trans tag is too limited. Specifically:

  1. Compiling the templates and running xgettext against them adds meaningless file names and line numbers to the extracted strings, which do not help at all.

  2. There's no way to add translator comments to the extracted strings, like:

    // Translators: This is "Update" as a noun, not as a verb.
    echo gettext("Update");
    

    xgettext is able to extract those, but there's no way to embed such comments when compiling a Twig template.

For complex projects with distributed translators, both these features are rather important. I'm afraid a native extractor that can parse Twig templates is necessary for this.

Ignoring whitespace in trans blocks

I want to translate a large chunk of text:

{% trans %}
    Some piece of<br>
    Text
{% endtrans %}

It gets recognized as the following key : \tSome piece of <br>\n\tText. Any way to make the trans block ignore the whitespace without having remove it all and sacrifice the visibility of my view ?

Further filter methods (substr, serialize, unserialize)

Hi.
It would be nice if you add some further filter methods in Twig_Extensions_Extension_Text.
The PHP functions substr, serialize and unserialize could be added very easily, because I think they are needed very often by the users, especially the substr function.

Thanks

localizeddate shortcuts

Let's say I don't wanna use neither, short, medium or long presetted formats. I just want to print localized week day. Today I'm having to make a long call to localizeddate method, like this:

{{ date|localizeddate('short', 'short', null, null, 'EEEE') }}

Shouldn't it have an easier way to accomplish this? Or I'm losing something?

Regards,

twig_localized_date_filter() not enoug flexible

It would be really nice if twig_localized_date_filter() could accept a generic format, other that Intl predefined ones. Just one more parameter is enough.
I omitted in the code the unchanged parts:

function twig_localized_date_filter(Twig_Environment $env, $date, $dateFormat = 'medium', $timeFormat = 'medium', $locale = null, $timezone = null, $format = null)
{
    $date = ... /* just the same as current implementation */

    $formatValues = ... /* see above */

    $formatter = IntlDateFormatter::create(
        $locale !== null ? $locale : Locale::getDefault(),
        $formatValues[$dateFormat],
        $formatValues[$timeFormat],
        $date->getTimezone()->getName(),
        IntlDateFormatter::GREGORIAN,
        $format
    );

    return ... /* see above */
}

As you can see, it's just one more parameter $format at the end, so the function is back-compatible. With this small change, you can use filter as follows:

{{ myDate|localizeddate('none', 'none', null, null, 'd MMMM Y HH:mm') }}

Autoload twig extensions

The twig doc says extensions should be autoloaded: http://www.twig-project.org/book/04-Extending-Twig

I can't achieve to autoload correctly the Debug extension using Symfony2 UniversalClassLoader. If I configure it this way:

$loader->registerPrefixes(array(
    'Twig_'  => __DIR__.'/vendor/twig-extensions',
));

Then Twig_Extension_Debug is autoloaded, but not Twig_Node_Debug, nor Twig_TokenParser_Debug. Because they live in an "Extension/" directory, and the class name doesn't contain "Extension".

How are we supposed to autoload these classes?

Don't work with the latest Twig version

fix and wrap the output string into pre tag, Node/Debug.php Line 40~62

    if (null === $this->nodes['expr']) {
        // remove embedded templates (macros) from the context
        $compiler
            ->write("\$vars = array();\n")
            ->write("foreach (\$context as \$key => \$value) {\n")
            ->indent()
            ->write("if (!\$value instanceof Twig_Template) {\n")
            ->indent()
            ->write("\$vars[\$key] = \$value;\n")
            ->outdent()
            ->write("}\n")
            ->outdent()
            ->write("}\n")
            ->write("echo '< pre>';print_r(\$vars);echo '</ pre>';\n")
        ;
    } else {
        $compiler
            ->write("echo '< pre>';print_r(")
            ->subcompile($this->nodes['expr'])
            ->raw(");echo '</ pre>';\n")
        ;
    }

Better i18n extension (based on Symfony)?

I created the Twi18n extension that uses Symfony's Translation component with PHP's get text as data source. See the documentation for more information on the functionality.

Is this something you guys would like to see in this extension repository? If yes, I'd be happy to make a fork and add the required files.

No license informations

e.g. https://github.com/fabpot/Twig-extensions/blob/master/lib/Twig/Extensions/Autoloader.php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

But no "LICENSE" files in this repository. (Do you tell about "LICENSE" file in Twig repository?)

What's license of this repository? Have all contributors understood about its hidden license?

i18n with Twig 1.0

Fatal error: Declaration of Twig_Extensions_Node_Trans::compile() must be compatible with that of Twig_NodeInterface::compile() in /media/DATA/Main/Dropbox/Chas/Perrong/Billboo/prototype/lib/Twig/Extensions/Node/Trans.php on line 124

I get that error running Twig 1.0 on PHP 5.3.3. It appears to be fixed by adding the parameter type Twig_Compiler to the Twig_Extensions_Node_Trans::compile() method. This might be to do with how my PHP is configured, just though you should know.

[RFC] Pre filter

Hello.

Quite often, I have to write documentation with pre section.
But because of spaceless managment of twig, we have to write something like:

                        {# yes, it's super indented on purpose #}
                        <pre>
My first line of doc
Another line of doc
They all have to start at the very begining of the template line
    This line is indented on purpose
                        </pre>

In chef/ruby (sorry), they have something to automatically remove leading space.
With that we can write:

                        {# yes, it's super indented on purpose #}
                        <pre>
                            {% filter pre %}
                                My first line of doc
                                Another line of doc
                                They all have to start at the very begining of the template line
                                    This line is indented on purpose
                            {% endfilter %}
                        </pre>

What do you think ?

Uncaught exception 'Twig_Error_Runtime' with message 'Attribute "data" does not exist for Node "Twig_Node"

Fatal error: Uncaught exception 'Twig_Error_Runtime' with message 'Attribute "data" does not exist for Node "Twig_Node" in "store/product.html".' in /path/Twig/lib/Twig/Node.php:142
Stack trace:
#0 /path/Twig-extensions/lib/Twig/Extensions/Node/Trans.php(121): Twig_Node->getAttribute('data')
#1 /path/Twig-extensions/lib/Twig/Extensions/Node/Trans.php(34): Twig_Extensions_Node_Trans->compileString(Object(Twig_Node))
#2 /path/Twig/lib/Twig/Node.php(106): Twig_Extensions_Node_Trans->compile(Object(Twig_Compiler))
#3 /path/Twig/lib/Twig/Compiler.php(81): Twig_Node->compile(Object(Twig_Compiler))
#4 /path/Twig/lib/Twig/Node/If.php(50): Twig_Compiler->subcompile(Object(Twig_Node))
#5 /path/Twig/lib/Twig/Node.php(106): Twig_Node_If->compile(Object(Twig_Compiler))
#6 /path/Twig/lib/Twig/Node.php(106): Twig_Node->compile(Object(Twig_Compiler))
#7 /path/Twig/lib/Twig/Node.php(106): Twig_Node->compile(Object(Twig_Compiler))
#8 /path/Twig/lib/Twig/Compiler.php(81): Twig_Node->compile(Object(Twig_Compiler))
#9 /path/Twig/lib/Twig/Node/Macro.php(71): Twig_Compiler->subcompile(Object(Twig_Node_Body))
#10 /path/Twig/lib/Twig/Node.php(106): Twig_Node_Macro->compile(Object(Twig_Compiler))
#11 /path/Twig/lib/Twig/Compiler.php(81): Twig_Node->compile(Object(Twig_Compiler))
#12 /path/Twig/lib/Twig/Node/Module.php(233): Twig_Compiler->subcompile(Object(Twig_Node))
#13 /path/Twig/lib/Twig/Node/Module.php(54): Twig_Node_Module->compileMacros(Object(Twig_Compiler))
#14 /path/Twig/lib/Twig/Node/Module.php(33): Twig_Node_Module->compileTemplate(Object(Twig_Compiler))
#15 /path/Twig/lib/Twig/Compiler.php(70): Twig_Node_Module->compile(Object(Twig_Compiler))
#16 /path/Twig/lib/Twig/Environment.php(509): Twig_Compiler->compile(Object(Twig_Node_Module))
#17 /path/Twig/lib/Twig/Environment.php(523): Twig_Environment->compile(Object(Twig_Node_Module))
#18 /path/Twig/lib/Twig/Environment.php(317): Twig_Environment->compileSource('{% extends "sto...', 'store/product.h...')
Twig_Environment->loadTemplate('store/product.h...')
#23 {main}
  thrown in /path/Twig/lib/Twig/Node.php on line 142

Attribute "data" does not exist for Node "Twig_Node"

With the current version of twig there is a bug using this syntax.

{% set c = "world" %}
{% trans %} hello {{ c }} {% endtrans %}

Stack trace:

PHP Fatal error:  Uncaught exception 'Twig_Error_Runtime' with message 'Attribute "data" does not exist for Node    "Twig_Node" in "member.html".' in /var/www/.../Kinaf/libs/Twig/lib/Twig/Node.php:142

Stack trace:
#0 /var/www/.../Kinaf/libs/Twig-extensions/lib/Twig/Extensions/Node/Trans.php(121): Twig_Node->getAttribute('data')
#1 /var/www/.../Kinaf/libs/Twig-extensions/lib/Twig/Extensions/Node/Trans.php(34): Twig_Extensions_Node_Trans->compileString(Object(Twig_Node))
#2 /var/www/.../Kinaf/libs/Twig/lib/Twig/Node.php(106): Twig_Extensions_Node_Trans->compile(Object(Twig_Compiler))
#3 /var/www/.../Kinaf/libs/Twig/lib/Twig/Compiler.php(81): Twig_Node->compile(Object(Twig_Compiler))
#4 /var/www/.../Kinaf/libs/Twig/lib/Twig/Node/Block.php(40): Twig_Compiler->subcompile(Object(Twig_Node))
#5 /var/www/.../Kinaf/libs/Twig/lib/Twig/Node.php(106): Twig_Node_Block->compile(Object(Twig_Compiler))
#6 /var/www/.../Kinaf/libs/Twig/lib/Twig/Node.php in /var/www/.../Kinaf/libs/Twig/lib/Twig/Node.php on line 142, referer: http://.../

see https://github.com/fabpot/Twig/issues/470

Twig extension : a new filter

There is a filter called date using php DateTime Object but it doesn't allow formatting as the locale of the user. That's why I wanted to created a new filter using the extension "Intl". This works fine when I put the finction in "core.php" but when I want to extend twig extension with "Twig_Filter_Method()", no php native functions and classes is recognized. I can't use php function inside the new function created by me.

For example : "Fatal error: Class 'Application\BlogBundle\Twig\DateTime' not found" or "Fatal error: Class 'Application\BlogBundle\Twig\IntlDateFormatter' not found".

What's wrong ? et why twig doesn't use a filter for convert the date about locale.

How to install it ?

Hi,

I installed this using composer but i don't know where to put :
$twig = new Twig_Environment($loader);
$twig->addExtension(new Twig_Extensions_Extension_Intl());

And i don't find it in the documentation !

Help me please !

Translation of Empty String

Example

{% set foo = "" %}
{% trans foo %}

This returns the header information of the gettext mo file. Although this is standard behavior for gettext it may not be desirable. Suggest modifying to just return an empty string.

add a base64 encoding filter

this can be convenient for inlining images. the filter should accept a variable containing a binary string, a stream resource and maybe also just a filename.

Confused about installation

I can't find any information about how to install these extensions.

The Readme doesn't say, Twig documentation seems to be silent on the matter too.
It would be nice if the Readme contained install instructions (hence this issue).

So how do I install these? Do I just copy all the files to the Twig folder (possibly overwriting any already existing files)?

I prefer not to use Composer, if that matters.

Updating PO file from cache causes git trouble

Hi,

I'm having trouble with a project that uses the i18n extension and gettext in the Twig views for translations. These are the steps we follow:

  • Add text in Twig views using the trans filters/tags
  • Run a PHP script to compile all views so the cache folder is generated/updated
  • Run Poedit to update the PO file by scanning the Twig cache folder
  • Add translations to the newly added keys
  • Finally, we commit and push to a Git repo

The problem is that the order of all labels in the PO file is changed every time we update it from the Twig cache. I believe this is because Twig uses some kind of hashing to generate folders and filenames in the cache folder. So, if you change something in a view, the hash changes and the compiled version ends up in a different place in the cache folder.

As a result, we're having trouble maintaining the PO file in a Git repository because of impossible merge conflicts as the file is changed entirely.
Does anyone know of a workaround for this issue ?

I found a PHP library that extracts translation labels directly from Twig but I didn't get it to work...

Adding "with" keyword to i18n

When using complex translations with parameters, we currently need to declare temporary variables for each parameter.

Example :

{% set name = name|capitalize %}
{% set site_url = '<a href="http://www.mysite.com" alt="mysite">my website</a>' %}
{% trans %}
    Hello {{ name }}! Welcome to {{ site_url }}.
{% endtrans %}

Using a "with" syntax similar to "include" tag could be an enhancement for this :

{% trans with {'name': name|capitalize, 'site_url':'<a href="http://www.mysite.com" alt="mysite">my website</a>'} %}
    Hello {{ name }}! Welcome to {{ site_url }}
{% endtrans %}

That would also enable to have a restrict context for translation (through the "only" keyword) , in the case we do not want to give access to other variables.

Translation of block buggy?

Hello!

I have this html code:

<div>
  <p>Trans as Block:</p>
  {% trans %}
  Hello World!
  {% endtrans %}
</div>

The part between "trans" and "endtrans" is not translated. The compiled template looks like this:

<div>
  <p>Trans as Block:</p>
  ";
    // line 11
    echo gettext("");        // line 14
    echo "</div>
";

The string is not "Hello World!" but empty. I tested this with the current version of Twig and the il8n extension. Pulled it fresh from github just hours ago.
{% trans "Hello World!" %}
works as expected and even a
{% trans %}
...
{% plural %}
...
{% endtrans %}
block!?

Catchable Fatal Error: Argument 2 passed to Psr\Log\LoggerInterface

[ErrorException]
Catchable Fatal Error: Argument 2 passed to Assetic\Extension\Twig\TwigFormulaLoader::construct() must be an instance of Psr\Log\LoggerInterface, instance of Sym
fony\Bridge\Monolog\Logger given, called in /var/www/html/releases/cf-6-25-2013/app/cache/dev_new/appDevDebugProjectContainer__536c7c25476b0
.php on line 76 and d
efined in /var/www/html/releases/cf-6-25-2013/vendor/kriswallsmith/assetic/src/Assetic/Extension/Twig/TwigFormulaLoader.php line 28

Facing this issue while clearing the cache in symfony 2.1

Project versioning

Hello,

I was wondering if the last version of Twig-extensions work with any version of Twig ?

I think that we need stable versions for this project that supports different versions of Twig.

What do you think ?

Installing?

Hi,

I use Twig for a while now, and I would like to start extending it.
I transfered the file in my Twig folder, but the filters are not recognized.

How do I install those extensions?

It would be great if you could add an INSTALL file. It would be useful for a lot of people.

Thanks.

trans with key value and variable

Hi,
I use Twig and Twig Extensions (in a non Symfon2 env) and I use key value for my translation.

So I have done this :

{{ "auth.loggedAs"|trans({'%userName%' : user.name}) }}

But it doesn't work :

gettext() expects exactly 1 parameter, 2 given

I check the extension and I guess it's because variable are change in a string, but there is no way to translate using placeholder.
Am I wrong?
(and if you know an extension that can do this?)

Thanks.

Bug in function localizeddate for date 31 december

Hi, i have a recent issue with the localizeddate function on every date 31 december, the function return the next year instead current year.

For example with the date 31/12/2015, pass to the function:

date|localizeddate('long', 'none', "fr_FR", null,"dd MMMM Y")

The function return 2016 for year.

When i use

date|format_date

The output is right.

Regards,
Alexis

Broken tests

Debug and Trans tests extend a non-existent class (Twig_Test_NodeTestCase).

Add template name metadata as comments for xgettext in Translation Nodes

Playing around with xggettext and the generated nodes, I see the following output:

#: f/3/f3de578967f55fbcff5ef47f81f851bfc6c1b0ed1833423817ccddb6e5ed86c0.php:20
msgid "Sugoi! Amaze. Much wow!"
msgstr ""

For my use case, I'd like to get the name of the original template as well by embedding it as additional comment like so:

#. source: some/module/module/test.twig:1
#: f/3/f3de578967f55fbcff5ef47f81f851bfc6c1b0ed1833423817ccddb6e5ed86c0.php:20
msgid "Sugoi! Amaze. Much wow!"
msgstr ""

I can create a pull request for this. Thoughts?

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.