tedious / jshrink Goto Github PK
View Code? Open in Web Editor NEWJavascript Minifier built in PHP
Home Page: http://www.tedivm.com
License: BSD 3-Clause "New" or "Revised" License
Javascript Minifier built in PHP
Home Page: http://www.tedivm.com
License: BSD 3-Clause "New" or "Revised" License
JShrink takes this:
var hello = 'hi ' + 'there';
and turns it into:
var hello='hi '+'there';
It is unnecessary in javascript minification to join strings with concatenation operators (plus signs). Proper minification would produce:
var hello='hi there';
Do you have any plan for minifying variable name?
On line 613, I get Uncaught SyntaxError: Unexpected token ,
https://gist.github.com/2947611
Any idea what could be the issue?
This may be a corner case but JSMin handles it so I figured I'd document it.
Input:
//@cc_on/*
statement;
//@cc_on*/
So basically in IE6 this should cause the statement to be seen as commented out. But JShrink moves the statement into the comment for all browsers:
//@cc_on/*statement;
//@cc_on*/
Uncaught exception 'RuntimeException' with message 'Unclosed multiline comment at position: 305485' in /home/website/vendor/tedivm/jshrink/src/JShrink/Minifier.php:397
The cause of this error is a blank multiline comment /**/
but this isn't flagged by JSHint as being invalid.
I've come across an issue with the latest update (1.3.2) with moment.js including locales version 2.17.1. In your version 1.3.1 there is no issue. The issue came to light during a Magento 2 deployment (for which this is a dependency).
The following string code causes the issue: /-MMM-/
from the following
monthsShort: {
return /-MMM-/.test(b) ? Mg[a.month()] : Lg[a.month()]
}
PHP Fatal error: Uncaught RuntimeException: Unclosed regex pattern at position: 111357 in E:\dir\git\vendor\tedivm\jshrink\src\JShrink\Minifier.php:530
Stack trace:
#0 E:\dir\git\vendor\tedivm\jshrink\src\JShrink\Minifier.php(247): JShrink\Minifier->saveRegex()
#1 E:\dir\git\vendor\tedivm\jshrink\src\JShrink\Minifier.php(147): JShrink\Minifier->loop()
#2 E:\dir\git\vendor\tedivm\jshrink\src\JShrink\Minifier.php(115): JShrink\Minifier->minifyDirectToOutput('!function (a, b...', Array)
#3 E:\dir\git\test.php(6): JShrink\Minifier::minify('!function (a, b...')
#4 {main}
thrown in E:\dir\git\vendor\tedivm\jshrink\src\JShrink\Minifier.php on line 530
I've realized that if I minify the jquery plugin qtip2 (nightly built) with JShrink by using $js = JShrink\Minifier::minify($js); this will corrupt the file and its execution.
Here is the problematic part:
Original:
(i.innerHTML="<!--[if gt IE "+ ++t+"]><i></i><![endif]-->")&&
i.getElementsByTagName("i")[0];
will be:
(i.innerHTML="<!--[if gt IE "+++t+"]><i></i><![endif]-->")&&
i.getElementsByTagName("i")[0];
(!) it is the missing space after the first plus.
Any ideas how to solve this?
If JavaScript code starts with a strict mode declaration:
"use strict";
var foo=22;
... we get this error message when calling minify()
:
Unclosed string at position: 12
Workaround: prepend a comment:
//
"use strict";
var foo=22;
Considering you compress JS files on the fly, the main question here is: does the time gain achieved by compressing the JS file, overcome the time span taken to the server to compress the JS file? Obviously it depends either on the server processing capability and on the link between server and client, but I have my doubts. Could you kindly clarify? Thank you.
JShrink doesn't appear to be removing line breaks after the end of a function.
Example:
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
...becomes...
window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}
gtag('js',new Date());
Notice the line break not removed after the }
character.
This examples causes an error "Unclosed string at position: 2955", referring to "יי" in the regex of the isPM function.
\JShrink\Minifier::minify(file_get_contents('https://raw.githubusercontent.com/moment/moment/develop/locale/he.js'));
I don't know any Hebrew, but as far as I can tell, the regex is valid.
In both cases JShrink treats these as division followed by unterminated string:
return /'/;
typeof /'/;
also statement like this:
template = '' +
'<div class="row">' +
'<h1>{{TITLE}}</h1>' +
'</div>' +
'<div class="row">' +
'<div class="alert alert-warning" role="alert">{{RESPONSE_TEXT}}</div>' +
'</div>';
into
template = '<div class="row"><h1>{{TITLE}}</h1></div><div class="row"><div class="alert alert-warning" role="alert">{{RESPONSE_TEXT}}</div></div>';
I used the shrinker inside a framework we use, and it worked fine at first but now it started failing a lot and it is taking a very long time to do the shrinking i mean minutes.
I suspected the error was comming from somne javascript that had utf8 characters in it since lal string functions are not utf8 compatible.
I changed the functions(substr, strpos) to (mb_strpos, mb_substr) but this did not help. Any ideas as to what is causing the script to run so slow?
This is a request for a usage example:
Thank you.
Hello
kindly
in the usage you state
<?php
include('vendor/autoload.php');
// Basic (default) usage.
$minifiedCode = \JShrink\Minifier::minify($js);
// Disable YUI style comment preservation.
$minifiedCode = \JShrink\Minifier::minify($js, array('flaggedComments' => false));
where is the file autoload.php ?
Thank you
js: var sth = "sth"; //comment
minified: var sth="sth";comment
js: var sth = "sth"; /comment/
during min.: var sth="sth" Fatal error: Uncaught exception 'RuntimeException' with message 'Stray comment.
ugly temp. solution: $minJs = JShrink\Minifier::minify($js."\n");
other problem with this "solution":
js: var sth = "sth";/!comment/
minified:
var sth="sth"
/!comment/
;
Thank you for the fix, Martin
This example generates a "Unclosed string at position" error:
\JShrink\Minifier::minify( "return /^\sdata:([a-z]+/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()+;=-._~:@/?%\s])\s$/i;" );
Hi!
We would like to include JShrink in our Javascript Optimization plugin for WordPress however it is currently impossible because JShrink is based on ob_start
.
Most websites apply minification of assets based on a output buffer that for example extracts scripts from the HTML. It is impossible to start a new output buffer within the callback of an output buffer so this is likely an issue that prevents usage for many applications.
We hereby want to suggest to change the output buffer concept.
Hello.
This example causes an error "Unclosed regex pattern at position: 54468"
\JShrink\Minifier::minify(file_get_contents('http://demos.krajee.com/assets/c4d9a2f2/js/bootstrap-datetimepicker.js'));
Here is a simplified example, a string from a file.
\JShrink\Minifier::minify("return /t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g;\n");
Is there anything you can do to get rid of the error?
The following js snippet causes the minifier to fail:
var list = [
1,
2,
/***//**
*/
3,
4
];
The following message is returned
Fatal error: Uncaught exception 'RuntimeException' with message 'Unclosed regex pattern at position: 467212' in vendor\tedivm\jshrink\src\JShrink\Minifier.php:525
Stack trace:
#0 vendor\tedivm\jshrink\src\JShrink\Minifier.php(240): JShrink\Minifier->saveRegex()
#1 vendor\tedivm\jshrink\src\JShrink\Minifier.php(144): JShrink\Minifier->loop()
#2 vendor\tedivm\jshrink\src\JShrink\Minifier.php(110): JShrink\Minifier->minifyDirectToOutput('\n\n/* XXXXXXXXXX...', Array)
#3 script.php(89): JShrink\Minifier::minify('\n\n/* XXXXXXXXXX...')
#4 script.php(29): js_out()
#5 {main}
thrown in vendor\tedivm\jshrink\src\JShrink\Minifier.php on line 525
I still don't understand why are those \n before and after each { } there's any way to remove it?
...
else if(dtMonth<1||dtMonth>12)
{return false;}
else if(dtDay<1||dtDay>31)
{return false;}
else if((dtMonth===4||dtMonth===6||dtMonth===9||dtMonth===11)&&dtDay===31)
{return false;}
else if(dtMonth===2)
{var isleap=(dtYear%4===0&&(dtYear%100!==0||dtYear%400===0));if(dtDay>29||(dtDay===29&&!isleap))
{return false;}}
return true;}}
else
...
Greetings,
I am wanting to use your library inside my own using Composer and it would be great if you could put a version tag so I can use that instead of dev-master
. At the moment, I have to put my minimum-stability
to dev
so I can include your library.
Cheers,
cody
Hello Good evening, I was checking your library which I think is very good option, but when I was testing it on a project I saw something that caught my attention, other than marking me error code javascript.
So I explain the situation well so you can understand the details.
When I schedule sometimes javascript code sometimes under certain lines with /**/
to highlight that part I should check then sometimes I take sometimes not remove.
In a snippet so is the original.
html+= this.header();
html+= this.cabeceras();
/**/
var prevmes = this.fecha.mesPrevio();
var previo = year;
if(prevmes == 11){previo--;}
previo = new Date(previo, prevmes, 1);
dias = previo.mesDias();
previo = previo.mesDias() - (inicio - 1);
/**/
html+= ' <div class="row">';
for(var a = previo; a <= dias; a++){
html+= '<div class="cell noActivo"><div><div><span>'+ a +'</span></div></div></div>';
}
Now when I compile your library skips the code that is between /**/
and I compiled this way.
html+=this.header();html+=this.cabeceras();html+=' <div class="row">';for(var a=previo;a<=dias;a++){html+=' <div class="cell noActivo"><div><div><span>'+a+'</span></div></div></div>';}
As you can see I removed the code that is /**/
[CODE]/**/
Now if I delete the /**/
I compile it in a good way.
Regarding this change:
Getting an error with this code and a regex.
function() {
return /test?/g;
};
If you try to use a string literal (' or ") within a template literal ( Backticks / https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals ) it throws an error.
Example:
<?php
echo \JShrink\Minifier::minify("let x = `I'm here`;");
Consider this code:
if (document.fonts && document.fonts.load) {alert("ok");}
which gets minified into:
if(document.fonts&document.fonts.load){alert("ok");}
the &&
operator is replaced with &
, which breaks the code.
(rev:b3d0a82) Cannot detect this regex and fails with 'Stray Regex Pattern' error.
return /\?/ .test( url ) ? "&" : "?";
Hello,
I've this javascript code
_pwgRatingAutoQueue.push( {rootUrl: '', image_id: 292,
onSuccess : function(rating) {
e = document.getElementById("ratingCount");
if (e) {
if (rating.count == 1)
e.innerHTML = "(%d rate)".replace( "%d", rating.count);
else
e.innerHTML = "(%d rates)".replace( "%d", rating.count);
}
}} );
as you can see the last "if else" doesn't have accolades (I know it's bad)
the result JS is :
_pwgRatingAutoQueue.push( {rootUrl: '', image_id: 292,onSuccess : function(rating) {e = document.getElementById("ratingCount");if (e) {if (rating.count == 1)e.innerHTML = "(%d note)".replace( "%d", rating.count);elsee.innerHTML = "(%d notes)".replace( "%d", rating.count);}}} );
the "else" has been merged with the following "e" (juste before the last "innerHTML")
I tried to find witch part of the minifier delete spaces but I failed
Ideally I would like to keep spaces (but not multiple spaces of course)
thanks
It this poject maintained?
It looks like the only modern JS minificator in PHP.
$ phpunit
PHPUnit 6.5.13 by Sebastian Bergmann and contributors.
E....E...E....E......EEE.EE.. 29 / 29 (100%)
Time: 275 ms, Memory: 6.00MB
There were 9 errors:
1) JShrink\Test\JShrinkTest::testUnclosedCommentException
"continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"?
/home/morozov/JShrink/src/JShrink/Minifier.php:234
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:24
2) JShrink\Test\JShrinkTest::testJShrink with data set #2 ('prefix_increment.js', 'do{div.innerHTML="<!--[if gt ...ile(1)', 'do{div.innerHTML="<!--[if gt ...ile(1)')
strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
/home/morozov/JShrink/src/JShrink/Minifier.php:186
/home/morozov/JShrink/src/JShrink/Minifier.php:147
/home/morozov/JShrink/src/JShrink/Minifier.php:115
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:52
3) JShrink\Test\JShrinkTest::testJShrink with data set #6 ('remove-brace-lines.js', 'if ( dtMonth < 1 || dtMonth >... }\n', 'if(dtMonth<1||dtMonth>12){ret...alse;}')
strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
/home/morozov/JShrink/src/JShrink/Minifier.php:186
/home/morozov/JShrink/src/JShrink/Minifier.php:147
/home/morozov/JShrink/src/JShrink/Minifier.php:115
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:52
4) JShrink\Test\JShrinkTest::testJShrink with data set #11 ('utf_chars.js', 'var π = Math.PI,\n ε = 1e-... 0;\n}', 'var π=Math.PI,ε=1e-6,radians=...-1:0;}')
strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
/home/morozov/JShrink/src/JShrink/Minifier.php:186
/home/morozov/JShrink/src/JShrink/Minifier.php:147
/home/morozov/JShrink/src/JShrink/Minifier.php:115
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:52
5) JShrink\Test\JShrinkTest::testUglify with data set #6 ('empty-blocks.js', 'var x = 5;\nfunction bar() { ...); }\n', 'var x=5;function bar(){return...(;;);}')
strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
/home/morozov/JShrink/src/JShrink/Minifier.php:186
/home/morozov/JShrink/src/JShrink/Minifier.php:147
/home/morozov/JShrink/src/JShrink/Minifier.php:115
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:61
6) JShrink\Test\JShrinkTest::testUglify with data set #7 ('forstatement.js', 'a=func();\nb=z;\nfor (a++; i ...); }\n', 'a=func();b=z;for(a++;i<10;i++...t(i);}')
strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
/home/morozov/JShrink/src/JShrink/Minifier.php:186
/home/morozov/JShrink/src/JShrink/Minifier.php:147
/home/morozov/JShrink/src/JShrink/Minifier.php:115
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:61
7) JShrink\Test\JShrinkTest::testUglify with data set #8 ('if.js', 'var a = 1;\r\nif (a == 1) {\r...n}\r\n', 'var a=1;if(a==1){a=2;}else{a=17;}')
strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
/home/morozov/JShrink/src/JShrink/Minifier.php:186
/home/morozov/JShrink/src/JShrink/Minifier.php:147
/home/morozov/JShrink/src/JShrink/Minifier.php:115
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:61
8) JShrink\Test\JShrinkTest::testUglify with data set #10 ('null_string.js', 'var nullString = "\0"', 'var nullString="\0"')
strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
/home/morozov/JShrink/src/JShrink/Minifier.php:186
/home/morozov/JShrink/src/JShrink/Minifier.php:147
/home/morozov/JShrink/src/JShrink/Minifier.php:115
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:61
9) JShrink\Test\JShrinkTest::testUglify with data set #11 ('strict-equals.js', 'typeof a === 'string'\nb + ""... < g\n', 'typeof a==='string'\nb+""!==c...===f<g')
strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior
/home/morozov/JShrink/src/JShrink/Minifier.php:186
/home/morozov/JShrink/src/JShrink/Minifier.php:147
/home/morozov/JShrink/src/JShrink/Minifier.php:115
/home/morozov/JShrink/tests/JShrink/Test/JShrinkTest.php:61
ERRORS!
Tests: 29, Assertions: 22, Errors: 9.
Not sure if this is more of a tinyMCE thing or a JShrink thing. When loading up content that loads tinyMCE.init(), a couple requests are made to:
www.(baseurl).com//langs/en.js
When the proper URL is something like:
www.(baseurl).com/en/asset/js/tinyMCE/langs/en.js
I don't mind the fact that it's making a request, as much as it's making a request to the wrong place. There are a pair of slashes and the directory is off. Maybe I'll need to hack the tinyMCE code to fix this? I've read in other places that people have had issues minifying tinyMCE.
Anyways, very good work. We're running a javascript-heavy site, and tinyMCE is the only thing that broke as a result of JShrink! ;)
Is the project currently dead!?
Copied and pasted the usage code, but Jshrink could not be found. The issue was namespacing.
$minifiedCode = JShrink::minify($js);
Fixed with
$minifiedCode = \JShrink\Minifier::minify($js);
Minifier can't handle a new line after quote and double-quote. It wasn't a case with ES5, b/c it will generate not valid code, but with template literals, we can do this i.e. writing HTML code.
Simple example:
var test =`"
test
"`;
Real-life example:
return template(`
<div class="
${classNames.item}
${classNames.itemChoice}
${data.disabled ? classNames.itemDisabled : classNames.itemSelectable}
"
data-select-text="${this.config.itemSelectText}"
data-id="${data.id}"
data-value="${data.value}"
data-sku="${data.sku}"
data-choice
${data.groupId > 0 ? 'role="treeitem"' : 'role="option"'}
${data.disabled ? 'data-choice-disabled aria-disabled="true"' : 'data-choice-selectable'}
>
${data.label}
</div>
`);
In order to get the class to work I had to change line 129 from:
self::$jshrink = new JShrink();
into:
self::$jshrink = new Minifier();
This may be because I am not using namespaces in my code... but I'm not sure.
Minify of file
https://github.com/marijnh/CodeMirror/blob/master/lib/codemirror.js
say error: Unclosed string at position: 226318
Hi @tedivm,
Could you please enable this repository in Travis-CI? (http://travis-ci.org/profile)
Thanks!
Most of the scripts that have ` character in code hangs or provides "Unclosed string at position" error. One example is Moment.js
Minifier should detect if a file is already minified and just return it without minifying it a second time. Processing an already minified js file sometimes leads to a:
ErrorException in Minifier.php line 476: Unclosed string at position
The error is thrown in vendor/tedivm/jshrink/src/JShrink/Minifier.php around line 471:
// New lines in strings without line delimiters are bad- actual
// new lines will be represented by the string \n and not the actual
// character, so those will be treated just fine using the switch
// block below.
case "\n":
throw new \RuntimeException('Unclosed string at position: ' . $startpos );
break;
Any ideas how this could be mitigated on JShrink side or is this something which should be checked before calling minify()?
It dies with: Uncaught exception 'RuntimeException' with message 'Unclosed string at position: 59'
given this string:
"var regEx = /[a-z0-9!#$%&'+/=?^{|}~-]+(?:.[a-z0-9!#$%&'_+/=?^_
{|}~-]+)@(?:a-z0-9?.)+(?:[A-Z])\b/;"
EDIT:
The regEx is wrong, and shouldn't be like this. The start is /[a-z0-9!#$%&'+/ which normally completes a regex. The question is, I guess, whether JSShrink should still die or not.
Hi,
Many thanks for fixing the 7.3 warning.
I just tried updating the library, but composer only installs 1.1
.
I think this is because you mention here that the library is not compatible with 7.1+:
Line 15 in 2125405
It would be really great if you could update this to 5.6-7.3 and release a new version.
When i turn my server to PHP7.3 i get the following error:
Deprecated: strpos(): Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior in .../minifier.php on line 184
Hi!
When I shrink this file: https://gist.github.com/fredw/4756686
Returns the following error when running the plugin: Uncaught ReferenceError: Invalid left-hand side expression in postfix operation
Thanks in advance
https://github.com/mrclay/minify/blob/master/min_unit_tests/_test_files/js/issue144.js
https://github.com/mrclay/minify/blob/master/min_unit_tests/_test_files/js/condcomm.js
https://github.com/mrclay/minify/blob/master/min_unit_tests/_test_files/js/issue132.js
https://github.com/mrclay/minify/blob/master/min_unit_tests/_test_files/js/issue74.js
Supporting things like a - ++b
required quite a patch in JSMin.
I'm still open to using this in Minify if it can handle all the same content and (ideall) faster.
Hi
The minifier thows an error when I use following multiline comment:
var d = 1; /* test comment /**/ var d = 2;
This is a valid comment but not correctly handled by the shrinker.
BR
Referred here by: DevFactoryCH/minify#5
We're using the Plupload library by @moxiecode and have found an error when integrating it with Plupload 2.1.2 in it's minified version.
When we run:
{!! Minify::javascript('/assets/js/plupload/plupload-2.1.2/plupload.full.min.js')->withFullUrl() !!}
We get the following Errors:
ErrorException in Minifier.php line 476: Unclosed string at position: 67069
We know:
But when we put the .full.min.js file through Minify, the error is produced.
Here's the package link: https://github.com/moxiecode/plupload
I just bumped into an issue with JShrink when minifying/combining JS code that is using core-js.
The issue comes e.g. form these lines in the core-js version 2 code:
https://github.com/zloirock/core-js/blob/6a3fe85136aaae0e3b099c96a05a5ceb1f515a50/modules/es7.string.pad-end.js#L8-L10
There are popular JS modules using core-js (particularly version 2), such as @babel/polyfill.
To simplify the line in the core-js code, these types of JavaScript source strings will produce the same error:
var test = a * /regtest\//.test(userAgent);
var test = a + /regtest\//.test(userAgent);
var test = a - /regtest\//.test(userAgent);
The last part after the two slashes is stripped out and the output for each of the strings is respectively as follows:
var test = a * /regtest\
var test = a + /regtest\
var test = a - /regtest\
This will obviously break any JS code that comes after that.
To further outline the issue here, each of the test strings above work correctly if you take out the calculation in front of the regular expression (i.e. a *
, a +
, a -
or a /
in the examples above).
Create a sample project using the packagist version (the same issue is also at the GitHub repo's latest code):
$ mkdir jshrinktest && cd jshrinktest && composer require tedivm/jshrink
Then, create a test script to run the examples:
<?php
require "vendor/autoload.php";
function test($js) {
echo JShrink\Minifier::minify($js);
echo PHP_EOL;
}
echo "This does NOT work:" . PHP_EOL;
test('var test = a * /regtest\//.test(userAgent);');
test('var test = a + /regtest\//.test(userAgent);');
test('var test = a - /regtest\//.test(userAgent);');
echo "This works OK:" . PHP_EOL;
test('var test = /regtest\//.test(userAgent);');
You can test it out with this: http://platform.twitter.com/widgets.js
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.