GithubHelp home page GithubHelp logo

twigjs / twig.js Goto Github PK

View Code? Open in Web Editor NEW
1.9K 56.0 273.0 11.63 MB

JS implementation of the Twig Templating Language

License: BSD 2-Clause "Simplified" License

JavaScript 98.54% HTML 0.31% Shell 0.04% Twig 1.12%
twig twigjs

twig.js's People

Contributors

adamdicarlo avatar ahtohbi4 avatar ajbdev avatar andresteenveld avatar antoineveldhoven avatar createvibe avatar d-simon avatar dave-irvine avatar dependabot[bot] avatar dethcount avatar drparanoia avatar egorshar avatar evgenius avatar iapain avatar jmealo avatar jorgenevens avatar justafish avatar justjohn avatar m-abs avatar masterodin avatar mauteri avatar plepe avatar polypik avatar rafaellyra avatar robloach avatar tbence94 avatar tgabi333 avatar toptalo avatar willrowe avatar zizaco 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  avatar  avatar  avatar  avatar  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.js's Issues

Impossible to have more than one elseif

{% if test %}
foo
{% elseif test2 %}
bar
{% elseif test3 %}
foo
{% else %}
bar
{% endif%}

doen't work : Twig.logic.type.elseif not expected after a Twig.logic.type.elseif

Generating Javascript code

It would be great if the Template.render were a plain Javascript function. At this moment if I'm not wrong it just interprets a set of nodes instead of creating a native javascript function with "eval".

Because of the overhead of that interpretation, it is a bit slow for me.

Here is a project that generates javascript code (thought it is generated by PHP):
https://github.com/schmittjoh/twig.js

But the idea is similar: the engine loads the template, compiles it into plain Javascript and then returns a javascript native function that can be executed directly.

I have done something similar for .NET: https://github.com/soywiz/csharputils/tree/master/CSharpUtils/CSharpUtils.Templates/Templates
https://github.com/soywiz/csharputils/blob/master/CSharpUtils/CSharpUtilsTests/Templates/TemplateTest.cs

If you want I can help you implementing the javascript dynarec for twig.js.

TypeError: Property 'twig' of object [object Window] is not a function

Hi There,
This is a really basic problem I fear but; I'm trying to use twig.min.js without node or express.

I include twig.min.js in the script tag and it's definitely there.

then (in view object):

this.template: twig({data:'

{{whatever}}
'});
this.html = this.template.render({whatever:"hello"});

throws the error:

TypeError: Property 'twig' of object [object Window] is not a function

however I can console.log(twig) // returns Object -- so it's there

Any ideas?

Implement macros

The approach I would take to implementing macros is as follows:

{% macro %}

look at the {% block %} implementation as a guide for {% macro %}

compiling

You'll need to write a regular expression and some code to match the {% macro fnName(var1, var2, ...) %} syntax and extract the function name and the argument names. The regular expression matches are provided to the compile function as token.match

parsing

This is the important part you need for parsing a macro with a context:

Twig.parse.apply(this, [token.output, context])

token.output represents the tokenized version of everything between the block and endblock - this is what you need to store for parsing every time the macro is called.

I would wrap token.output in a function like this and store it in the Twig.Template object (this):

var template = this; // keep access to template object in closure
this.macros[macroName] = function() {
   var macroContext = {
      // build from the function argument names parsed from the regex
      // and the JS arguments object from invoking this function.

      // provide access to other macros in this file
      _self: this.macros
   }

   return Twig.parse.apply(template, [token.output, macroContext])
}

{% from %}

Look at the {% extends %} implementation as a guide to the {% from ... %} implementation

compile

You'll need to write a regex to extract the file name and the context name from the {% from ... %} tag

parse

You're going to need code like this to load the remote template with the macros:

url = relativePath(this, fileName);

// load remote template
var remoteTemplate = Twig.Templates.loadRemote(url, {
    output: 'macros', // return the template macros, not parsed output
    method: this.url?'ajax':'fs',
    async: false,
    id:     url
});

// make the macros available in the template render context 
// under the name provided by the {% from fileName as contextName %}
context[contextName] = remoteTemplate.render({});

Because the macros are wrapped in a function, calling them from the template should cause the macro wrapper function to be invoked which will return the parsed macro.

You'll also need to update Twig.render in twig.core.js to return the macros object when the output param is set to macros. There's currently a check for output == 'blocks' you can model this change after.

This is mostly off the top of my head, so you're likely going to run into issues implementing, when you do just post a comment and I'll try and clarify.

Most of the Twig.filters-functions crashes if you pass an undefined value to them.

I discovered this by accident (misspelled a var-name). :)

But if you pass a undefined value to the "escape"/"e" filter twig.js crashes, because the function assumes the value is a string and just calls .replace(...) on the value.

From what I can see most of the filters will have this problem.

I can easily fix most of the filter functions so they handle an undefined value, but I'm confused about how best to handle those that don't return a string, like "reverse", "sort", "key", "join" and "merge".

Promises with functions/filters?

Perhaps this is the wrong place to put this, but I was curious about soliciting input on this request...

Suppose I have a route like /:page that will simply res.render(page + '.twig'). These views utilized lots of API information from services like Github, Basecamp, etc.

Suppose I have in my templates:

{{ github_api('total_issues') }}

Would it be possible, if github_api return s a Promise, for the rendering engine to continue compilation & processing once the callback is called?

When our designers & developers write templates with Twig (PHP), the synchronous nature allows lazy-loading of resources without the controllers having to expose dozens if not hundreds of data-points that are mostly not used.

With Twig.js, the asynchronous nature means that the immediate return value is only what's available, and these data points would have to be pre-fetched, which would mean hundreds of unnecessary API calls.

I'm willing to code this functionality in, but as evident in my last ticket & PR, I'd need someone to point me to the pertinent sections to adjust (otherwise I'll be floundering).

Thanks!

Express3 Support

Howdy,

I'm new to Node.js and Express. It was cool to find some Twig ports, but then I installed Express3 without knowing it was new/alpha.

There is a new interface to implement :(

Json Filter does not work for variables named "notes"

Hi,
me again. Found a strange bug (possible name clash with twig.js src ?)

Code:

var template = '{{notes|length}}:{{notes|json_encode()}}';
Twig.twig({data: template}).render({notes:['a', 'b', 'c']});

Expected Output:

3:["a","b","c"]

Actual Result:

TypeError: can't convert undefined to object
delete value._keys; (line 3627)

I've put debug statements into the json encode filter and the value passed to the function is "undefined" and not the values of the variable. But {{notes|length}} works.

Containment operator: if STRING in ARRAY throws exception

The following exception is thrown if one tries to search an array using a string with the IN operator.

Some example code:

{% if 'INACTIVE' in user.attributes%}
<button class="btn btn-danger"><i class="icon-ban-circle icon-white"></i> Account expired</button>
{% endif %}

Throws:
Uncaught TwigException: Twig.expression.type.variable cannot follow a Twig.expression.type.string at template:15 near 'in...'

Should return a deferred object when fetching template asynchronously

Not sure what the timeline for this is or if it's worthy of an issue at the present moment.

But, it looks like it was thought of at some point:

        if (async === false) {
            return template;
        } else {
            // placeholder for now, should eventually return a deferred object.
            return true;
        }

The deferred object would make rendering logic a lot more readable in frameworks like Backbone.js.

Can't test a function another one

{% if MyFunction('test') or MyFunction('truc') %}
    foo
{% endif %}

=>

Twig.expression.type.expression cannot follow a Twig.expression.type.variable at template:24 near '('truc')...' OR Twig.expression.type.parameter.start cannot follow a Twig.expression.type.variable at template:24 near '(...'

date filter has incompatible behaviour to twig php function

The javascript twig implementation expects dates to have millisecond resolution, but the php version expects a second resolution.

{{1348047737|date("d.m.Y")}}

twig-php: 19.09.2012
twig.js:  16.01.1970

Solution: simply multiply the unix timestamp by 1000 before creating a javascript date-object

res.locals from within filter/function?

Hi! Not sure if this is an issue (yet :D), but several filters we use in PHP (and would like to use within Express as well) behave slightly different based on res.locals as well as app.locals.

For example, the former may automatically add the right class to a navigation element depending on the current request's route, while the latter may automatically add a debug flag when the app.settings.env === 'dev' or something.

In short, I'm wondering can twig.js functions and/or filters have access to the app or local view variables, and if so, how?

Thanks!

Nested variables not supported

{{ tilesWidget.getActiveTile().title }}

fails with uncaught exception: TwigException: Twig.expression.type.key.period cannot follow a Twig.expression.type.parameter.end at template:27 near '.title...'

Bug: Ending multiple objects in an output tag

This causes the parser to close the output tag before it's actually ended since it looks for a closing output tags "}}" before it parses expressions:
{{ {"key":{"i_key": "value"}} }}

The workaround is to add a space between the two closing object braces like so:
{{ {"key":{"i_key": "value"} } }}

Bug difficult to explain :/

Hi,

I updated to last tag recently to get the bugfix you made for me a month ago, and it added a new bug very difficult to isolate. The bug has been introduced by the commit 99d343f ("#46 set parent context in nested for loops correctly").

I'll give you all that I can to reproduce it, and I hope you'll find it. Meanwhile, we keep to the 0.4.5 tag.

This is the data we give to twig.js compilator : https://gist.github.com/hadrienl/adb88760ada9ad4285a2

This is the twig code to be compiled : https://gist.github.com/hadrienl/cfaf5e1cb64260174ba3

The first loop is ok, but the second is not. Posts returns an array of Data.__Posts items such as Blog.Posts. But in the second case, Post are arrays instead of objects : https://dl.dropbox.com/u/8352589/Scrinechoutes/Capture%20d%E2%80%99%C3%A9cran%202013-03-15%20%C3%A0%2010.41.47.png

Compile issue in a specific case

Hi,

I've a compilation issue with this code :

{% if (Custom('gra')) %}
bla
{% endif %}

=> Expected filter or function before parameters, got Twig.expression.type.string

Custom is a function wich return the attribute. The issue appears when the function is inside parenthesis. Don't tell me to remove them, because we need them in some case ;) for exemple :

{% if (Custom('foo') or Custom('bar')) and foobar == 1 %}

Problems with "if" tag with "and"

I haven't permissions to open #27 again, so create new ticket. Looks like it not completly fixed.

{% if mapController and mapController.hasWidget('route') and  if mapController.getWidget('route').options.editable %}
{# object and false and undefined.options.editable #}

caused invalid 'in' operand object. But it should stop executing other expressions on first false

loop.index not works correctly

    {% for category in placesWidget.categories %}
        {% if loop.index % 2 == 0 %}
            <li><label><input type="checkbox" value="{{ category.alias }}" checked="checked" /><span class="text"><i class="icon place-{{ category.alias }}"></i>{{ category.title }}</span></label></li>
        {% endif %}
    {% endfor %}

throws uncaught exception: TwigException: Can't access a key index on an null or undefined object. but

    {% set i = 1 %}
    {% for category in placesWidget.categories %}
         {% if i % 2 == 1 %}
            <li><label><input type="checkbox" value="{{ category.alias }}" checked="checked" /><span class="text"><i class="icon place-{{ category.alias }}"></i>{{ category.title }}</span></label></li>
        {% endif %}
        {% set i = i + 1 %}
    {% endfor %}

works ok

Do not use `hasOwnProperty` for getting data from context

There are cases, when ViewModels are too complex and have inheritance. So hasOwnProperty would return wrong data (null in most cases)

                // Get the variable from the context
                if (object.hasOwnProperty(key)) {
                    value = object[key];
                } else if (object.hasOwnProperty("get"+capitalize(key))) {
                    value = object["get"+capitalize(key)];
                } else if (object.hasOwnProperty("is"+capitalize(key))) {
                    value = object["is"+capitalize(key)];
                } else {
                    value = null;
                }
// -->
                // Get the variable from the context
                if (key in object) {
                    value = object[key];
                } else if (object[("get"+capitalize(key)]) {
                    value = object["get"+capitalize(key)];
                } else if (object["is"+capitalize(key)]) {
                    value = object["is"+capitalize(key)];
                } else {
                    value = null;
                }

Parent loop index for nested loop is wrong

Hi, me again. Sorry for finding all those bugs ;)

Template:

{% set values = [['a', 'a', 'a'], ['b', 'b', 'b']] %}

{% for val_1 in values %}
  {% for val_2 in val_1 %}
    {{val_2}}: loop={{loop.index0}}, parent_loop={{loop.parent.loop.index0}}
  {% endfor %}
{% endfor %}

Expected Output:

a: loop=0, parent_loop=0
a: loop=1, parent_loop=0
a: loop=2, parent_loop=0
b: loop=0, parent_loop=1
b: loop=1, parent_loop=1
b: loop=2, parent_loop=1

Actual Output:

a: loop=0, parent_loop=0
a: loop=1, parent_loop=1
a: loop=2, parent_loop=2
b: loop=0, parent_loop=0
b: loop=1, parent_loop=1
b: loop=2, parent_loop=2 

Possible use of twig.js without Express ?

Hi,

I'm new to Node, and before I go any further with existing frameworks I'd like to handle Node itself.

I've been trying to use twig.js without Express by looking at the code but I can't seem to figure it out. Is it possible (without becoming an overwhelm), and if yes, may I ask you to give me some hints about it ?

Thanks a lot anyway, I'm a huge Twig fan and really appreciate this JS implementation :-)

Regards,

Mention version in source

You should mention the version in twig.js and twig.min.js, it's always usefull.

//     Twig.js - 0.5.4
//     Copyright (c) 2011-2012 John Roepke
//     Available under the BSD 2-Clause License
//     https://github.com/justjohn/twig.js

Extends but no block?

Hi, how can extends be used in twig.js if block and parent are not supported?

Is there another way?

My use case is something like this:

{# panel.twig #}
<div class="panel">
{% block contents %}
{% endblock %}
</div>
{# child.twig #}
{% extends 'panel.twig' %}

{% block contents %}
{{ parent() }}
I'm in a .panel!
{% endblock %}

url() doesn't seem working

Hi Author,

I'm using twig.js into my symfony2 framework.
With non-AJAX request, my TWIG templates render successfully and being shown in my browser correctly.

Now I'm trying to use twig.js so that the AJAX part (the javascript code) and the PHP code share the same TWIG template. (As we know code sharing is very important for code maintenance).

In my template file, it contains some call to url() function, which uses a route identifier to re-construct the URL. But twig seems to be broken on this:

Error: uncaught exception: TwigException: Twig.expression.type.expression cannot follow a Twig.expression.type.variable at template:3 near '('_kuulabu_home_page...' OR Twig.expression.type.parameter.start cannot follow a Twig.expression.type.variable at template:3 near '(...'

(where _kuulabu_home_page is a route identifier)

Do you have any idea to help me solve the problem? Many thanks.

Simon

Issue with parser.

When parsing existing and working twig template i get this

ic.tokenize: ","Matched a ",e," regular expression of ",i),c}}throw new a.Erro
^
TwigException: Unable to parse 'for x in R'

Loosing data with functions

This bug is very specific. There is what I have :

  • Posts is an array of Post objects
  • Blog.Posts() is a method which returns an array of another Posts objects

I list them in two differents places :

{% for Post in Posts %}
    <h2>{{ Post.Title}}</h2>
{% endfor %}

{% for Post in Blog.Posts(10) %}
    <h1>{{ Post.Title }}</h1>
{% endfor %}

No problem with that, everything is working fine.

Now, we inverse the blocks :

{% for Post in Blog.Posts(10) %}
    <h1>{{ Post.Title }}</h1>
{% endfor %}

{% for Post in Posts %}
    <h2>{{ Post.Title}}</h2>
{% endfor %}

Now, the Posts block is empty. Only the

are displayed.

TypeError on undefined variables when parsing included files.

Hey, I've spottet an issue.

If you include a file and use a property on a non-existant object, twig.js crashed on line 2879 because this.options is undefined.

header.twig

<!DOCTYPE html>
<html>
  <head>
    <title>{{ page.title }}</title>
  </head>
  <body>

footer.twig

  </body>
</html>

index.twig

{% include 'header.twig' %}

<p>Hello World</p>

{% include 'footer.twig' %}

If the page isn't defined I get this error:


TypeError: Cannot read property 'strict_variables' of undefined
at Twig.expression.definitions.parse (/Users/m_abs/project/kostplan/node_modules/twig/twig.min.js:2879:37)
at Twig.expression.parse (/Users/m_abs/project/kostplan/node_modules/twig/twig.min.js:3227:58)
at Array.forEach (native)
at Twig.expression.parse (/Users/m_abs/project/kostplan/node_modules/twig/twig.min.js:3224:16)
at Twig.parse (/Users/m_abs/project/kostplan/node_modules/twig/twig.min.js:425:55)
at Array.forEach (native)
at Twig.parse (/Users/m_abs/project/kostplan/node_modules/twig/twig.min.js:396:16)
at Twig.Template.render (/Users/m_abs/project/kostplan/node_modules/twig/twig.min.js:726:29)
at Twig.logic.definitions.parse (/Users/m_abs/project/kostplan/node_modules/twig/twig.min.js:2098:38)
at Twig.logic.parse (/Users/m_abs/project/kostplan/node_modules/twig/twig.min.js:2260:43)


From what I can see looking at the source code at that line, this.options is undefined which of cause means that the line 2879 fails:

2879                     if (this.options.strict_variables) {

I'm running node.js v0.8.16, express.js v3.0.5 and twig.js v0.4.6

Chaining functions

I've implemented {{function()}} expression, but it's always impossible to chain functions and filter. For exemple :

{{ MyFunction('foo') | default('bar') }}

I'll try to do something, but it seems more complicated now :/

Add function on the fly (after new twig object)

Hi, i found your job really usefull for me ty for that ;)

but i would like do something like this :

var template = twig({
data: "{{ field('azerty') }}"
});

template.extendFunction("field", function(name) {
return(name);
});

but exactly like this it's not possible.
Have u an another solution for assign a new function to only one instance for a temporary need

ty ^^

For tag does not support condition

Hi,
me again. You've done great work but i've found another bug. The twig manual describes how to use a condition inside a for loop. The implementation notes page for twig.js states that the for tag is "supported" but it does not support conditions inside a for tag.

Testcode:

var template = '{% for value in values if value == "a" %}{{value}}{% endfor %}';
Twig.twig({data: template}).render({values: ['a', 'a', 'b', 'b']});

Expected output:

aa

Real behaviour:

TwigException: Twig.expression.type.variable cannot follow a Twig.expression.type.variable at template:6 near 'if...' { message="Twig.expression.type.va...template:6 near 'if...'", name="TwigException", type="TwigException"}

Blocks in children views

Hi,

Blocks in children views do not get their contents replaced as they should.

Example : I render the test.twig file.

test.twig :

{% extends 'apps/admin/views/test_layout2.twig' %}

{% block block2 %}
    content overloaded for block 2 (test.twig)
{% endblock %}

test_layout2.twig :

{% extends 'test_layout1.twig' %}

{% block block1 %}
    overloaded content for block1 (test_layout2.twig)
    <br>
    below is block2<br>
    <div id="block2" style="padding: 10px; border: 1px solid black; background: #CCCCFF">{% block block2 %}default content for block2{% endblock %}</div>
    end block2
{% endblock %}

test_layout1.twig :

<html>
    <head>
    </head>
    <body>
        <h1>blocks and extends test</h1>
        below is block1 (test_layout1.twig)<br>
        <div id="block1" style="padding: 10px; border: 1px solid black; background: #CCFFCC">
            {% block block1 %}
                default content for block1
            {% endblock %}
        </div>
        end block1
    </body>
</html>

I'm sorry I'm new to git and node.js, so I figured it would be enough to put my example code and my fix proposal here.

I fixed this by removing the condition "if ( this.extend === null )" in twig.logic.js line 439. I hope I did not break anything, but it seems to work fine now.

Thank you for any input on this one justjohn !

PS : I got several errors when minifying the twig.js file because of missing semicolon ";"

Extending a view does not pass in custom options

Reproducible by using express 3.0.x and extending a template via {% extends 'xxx.twig' %}

Result:

                if (this.options.strict_variables) {
                                ^

TypeError: Cannot read property 'strict_variables' of undefined
at Twig.expression.definitions.parse (/usr/share/www/search/dashionista/node_modules/twig/twig.js:2890:37)
at Twig.expression.parse (/usr/share/www/search/dashionista/node_modules/twig/twig.js:3238:58)
at Array.forEach (native)
at Twig.expression.parse (/usr/share/www/search/dashionista/node_modules/twig/twig.js:3235:16)
at Twig.parse (/usr/share/www/search/dashionista/node_modules/twig/twig.js:425:55)
at Array.forEach (native)
at Twig.parse (/usr/share/www/search/dashionista/node_modules/twig/twig.js:396:16)
at Twig.Template.render (/usr/share/www/search/dashionista/node_modules/twig/twig.js:722:29)
at Twig.Template.render (/usr/share/www/search/dashionista/node_modules/twig/twig.js:736:32)
at Twig.exports.renderFile.params.load (/usr/share/www/search/dashionista/node_modules/twig/twig.js:4213:39)

Easy fix in twig.js:

Line 733

// This template extends another, load it with this template's blocks
this.parent = Twig.Templates.loadRemote(url, {
method: this.url?'ajax':'fs',
base: this.base,
async: false,
id: url
});

Replace with

// This template extends another, load it with this template's blocks
this.parent = Twig.Templates.loadRemote(url, {
method: this.url?'ajax':'fs',
base: this.base,
async: false,
id: url,
options: this.options
});

Sorry for not submitting a pull request, but I'm tied up at the moment

include tag support ?

I noticed that include tag is not supported yet. Are you planning to implement it?

Problems with "if" tag with "and"

{% set at = null %}
{% if at and at.tile == 1 %} active{% endif %}

fails with uncaught exception: TwigException: Can't access a key tile on an undefined object.

if foo and not bar

Hello,

If I use this kind of syntax :

{% - if 1 and not 2 %}{% endif %}

I've got this exception :

Uncaught TwigException: Twig.expression.type.number cannot follow a Twig.expression.type.variable at template:8 near '2...'

But {% if not 2 %} works.

Ideas on "raw" function?

Hi There,
I have some twig templates which use 'raw' only to output raw html into a template from a cms/database.

I'm curious as to why this is not a feature in this library as Mustache/jQuery templates etc all can handle this with ease.

Have you any ideas as to how I can use 'raw'? perhaps just mix-in a function/filter which just returns the template with injected html content?

Thanks very much

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.