garetjax / phpbrowscap Goto Github PK
View Code? Open in Web Editor NEWStandalone replacement for php's native get_browser() function
License: MIT License
Standalone replacement for php's native get_browser() function
License: MIT License
The update URL has changed to http://browsers.garykeith.com/versions/version-date.asp
and should be updated in the code.
While the old one returns a 304 Moved header, that redirect is not always followed and an attempt to parse the redirection HTML below leads to strtotime()
failing and ultimately an exception.
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a HREF="https://browsers.garykeith.com/versions/version-date.asp">here</a></body>
Hi am facing this error, What is the path for cache directory.
Thanks for a great, particularly like the speed! 15x faster than get_browser (4ms vs 60ms!)
Motivation: We found that Googlebot-Mobile was not being identified as a crawler. The reason was Google prepends the identfying string with a random mobile UA (eg iPhone). Because the Googlebot-Mobile pattern is quite low down in the list in the current browscap.ini getBrowser() was matching the robot as a genuine iPhone.
Proposed solution: Rather then getting the author of browscap.ini to change the order of the patterns, which may take a long time or not be desirable for all users of that file. We wrote a class extending Browscap which allows the user of the class to specify some partial patterns as "priority". During _buildCache (so we only have do this once!) it matches for these partial patterns and move them to the front.
Here is our code, feel free to use/copy/include it if you think it's helpful.
$this->_patterns[$pattern]); unset($this->_patterns[$pattern]); $this->_patterns = $temp + $this->_patterns; } /** * */ protected function isProrityPattern($pattern) { foreach ($this->priority_patterns as $priority_pattern) { if (stripos($pattern, $priority_pattern) !== false) { return true; } } return false; } /** * */ protected function applyPrioritiesToPatterns() { foreach ($this->_patterns as $pattern => $pattern_data) { if ($this->isProrityPattern($pattern)) { $this->movePatternToTop($pattern); } } } /** * Parses the array to cache and creates the PHP string to write to disk * * @return string the PHP string to save into the cache file */ protected function _buildCache() { $this->applyPrioritiesToPatterns(); return parent::_buildCache(); } }
The version detection seems the off in some cases. I download the new 1.0 version.
Mozilla/5.0 (compatible; Yahoo! Slurp/3.0; http://help.yahoo.com/help/us/ysearch/slurp)
This useragent is detected als Yahoo! Slurp 0. While is should be Yahoo! Slurp 3.0
as it is on Gary Keiths website
http://browsers.garykeith.com/tools/ua-search.asp
Perhaps there are other situations in which this goes wrong. I just happen to come accross this example.
just ignore it - I have found my mistake
Because it shows notices.
See bug report browscap/browscap#8
It's a bug in the file, but it could be temporarily fixed / muted in phpbrowscap until they change the files.
Is this project still alive? Also how reliable is it in detecting search bots?
We will be releasing a new format of browscap.ini on Monday. We've maintained backward compatibility and don't anticipate any issues, but someone really needs to test it with phpbrowscap to be sure. Thanks. ~gary.
The logic in _getRemoteData()
is faulty. No matter which update style I choose all the update methods should be checked if my chosen way fails.
Either that or NONE (an option should be added).
There is a nice _getUpdateMethod()
method which can be used to fix this mess along with #15 issue.
browscap_obj->getBrowser()->Browser returns 'Default Browser'
I am using symfony and phpbrowscap as service defined in services.yml
.
currently, my definition in services.yml
look like this:
browscap:
class: phpbrowscap\Browscap
arguments:
- %browscap_cache_dir%
I'd like to set the property "localfile" initially, but thats not possible in services.yml
, because it only allows to inject variables in the constructor and/or additionally calling a certain setter.
having this setter would help here.
i personally don't see a reason for not having a setter.
I cannot find the const REGEX_DELIMITER in Browscap class
Browser Mozilla/5.0 (Mac OS X) AppleWebKit/ (KHTML, like Gecko, Safari/) Arora/0.9
should match (same as in get_browser()
)
[Mozilla/5.0 (*Mac OS X*) AppleWebKit/* (KHTML, like Gecko, Safari/*) *Arora/0.9*]
Parent=Arora 0.9
Platform="MacOSX"
Win32=false
but instead it matches
[Mozilla/5.0 (*Mac OS X*) AppleWebKit/* (KHTML, like Gecko, Safari/*) *Arora/0.?*]
Parent=Arora Generic
Platform="MacOSX"
Win32=false
because the order of regular expressions is diiferent than used by get_browser()
I was pretty surprised to find that when I instantiate Browscap, my timezone suddenly changed. It's correct that you need a timezone to be set, but doing it in the constructor (or anywhere in the library for that matter) is a bad approach.
Instead, you should rely on my app or the testing bootstrap code to handle dates and timezones.
I don't wanna know who wrote that code:
use \Exception as BaseException;
class Exception extends BaseException
{}
but that's some really terrible piece of code.
I'm gonna change the in-namespace exception to something like BrowscapException
, and update all the throw
s.
That can break someones code, but tbh it's a fair price for not keeping this monster alive.
This tablet shows the following output from getBrowser():
stdClass Object (
[browser_name] => Mozilla/5.0 (Linux; U; Android 3.2; en-us; A500 Build/HTJ85B) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13
[browser_name_regex] => ^mozilla/5.0 (.linux.) applewebkit/.* (khtml, like gecko) .version/4.. safari/.$
[browser_name_pattern] => Mozilla/5.0 (Linux) AppleWebKit/ (KHTML, like Gecko) Version/4. Safari/*
[Parent] => Safari 4.0
[Platform] => Linux
[Browser] => Safari
[Version] => 4.0
[MajorVer] => 4
[Win32] => 1
[Frames] => 1
[IFrames] => 1
[Tables] => 1
[Cookies] => 1
[JavaScript] => 1
[JavaApplets] => 1
[CssVersion] => 3
[MinorVer] => 0
[Alpha] =>
[Beta] =>
[Win16] =>
[Win64] =>
[BackgroundSounds] =>
[VBScript] =>
[ActiveXControls] =>
[isBanned] =>
[isMobileDevice] =>
[isSyndicationReader] =>
[Crawler] =>
[AolVersion] => 0 )
I'm testing phpbrowscap in an app and display empty "stdClass Object":
stdClass Object
(
)
How to get Maximum image width and height, tablet detection
file_get_contents(http://browscap.org/stream?q=Full_PHP_BrowsCapINI): failed to open stream: HTTP request failed! HTTP/1.1 403 Forbidden
Can still grab it in my browser, so it looks like they've blocked remote download/scraping.
I have the latest Browscap.php fine and it works with firefox 6
when using my T-Mobile G2 phone ts not identifying the browser or flagging it as mobile,
output from $bc->getBrowser() below
thanks
stdClass Object (
[browser_name] => Mozilla/5.0 (Linux; U; Android 2.2; en-us; T-Mobile G2 Build/FRF91) AppleWebKit/533.1(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
[browser_name_regex] => ^.*$
[browser_name_pattern] => *
[Browser] => Default Browser
[Version] => 0
[MajorVer] => 0
[MinorVer] => 0
[Platform] => unknown
[Alpha] =>
[Beta] =>
[Win16] =>
[Win32] =>
[Win64] =>
[Frames] =>
[IFrames] =>
[Tables] =>
[Cookies] =>
[BackgroundSounds] =>
[JavaScript] =>
[VBScript] =>
[JavaApplets] =>
[ActiveXControls] =>
[isBanned] =>
[isMobileDevice] =>
[isSyndicationReader] =>
[Crawler] =>
[CssVersion] => 0
[AolVersion] => 0
)
It would be useful to make the currently private methods protected to be able to overwrite functionality in child classes. Eg. I'd like to replace the _getRemoteData function to make use of my framework's HTTPClient.
Could you please implement a Do not Track Header Check?
This could be very useful.
So, I just decided to test out this little toy on my personal server, and I ran into a bit of an issue. This is the message I got:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 72 bytes) in /var/www/html/modules/Browscap.php on line 818
What exactly are you trying to do!? You may ask. Well, nothing more nor less than what was shown in the quick start guide.
On a likely related note, the cache folder. I'm not sure what it's supposed to do, but I created it, and directed the script to it, and unlocked it for full access (777), and yet nothing is filling it. I run the script, but I get the above error, and the folder remains empty.
Am I doing something wrong, or is this an error in the class?
Thank you for your time.
The v1 tag does not show up on the Packagist.org website (https://packagist.org/packages/garetjax/phpbrowscap).
Since the new changes (v2) are still beta, it would be great if there was an up to date v1 tag that was available to allow specifying the specific version in Composer.
php_browscap.ini
entry:
[GJK_Browscap_Version]
Version=5020
Released=Mon, 29 Jul 2013 22:22:31 -0000
[Der gro\xdfe BilderSauger*]
Parent=Image Crawlers
Browser="Gallery Grabber"
The user agent Der gro\xdfe BilderSauger 2.00u
is correctly parsed by get_browser()
but not by Browscap
.
The entry in cache says @^Der gro\\xdfe BilderSauger.*$@
so it looks ok... and yet it doesn't work.
Library can't properly handle some user agents strings and show this errors:
PHP Notice: Undefined index: in /var/www/vendor/garetjax/phpbrowscap/src/phpbrowscap/Browscap.php on line 355
PHP Fatal error: Unsupported operand types in /var/www/vendor/garetjax/phpbrowscap/src/phpbrowscap/Browscap.php on line 356
Some samples of user agents strings causing these errors
mozilla/5.0 (windows; u; windows nt 6.1; en-us) applewebkit/534.3 (khtml, like gecko) chrome/6.0.472.33 safari/534.3 se 2.x metasr 1.0
mozilla/5.0 (windows; u; windows nt 5.1; en-us) applewebkit/534.0 (khtml, like gecko) chrome/6.0.408.1 safari/534.0
Tested with latest lite php version of browscap.ini (5020 Jul 29 2013).
This error occurs in phpbrowsecap versions: 2.0b and dev-master.
Please let me know if you need additional details.
At Mac OS X version 10.9.4 prints only 10.9. and should print 10.9.4. See http://bit.ly/1wLQClq
Browscap v1.0; PHP v5.3.8
I'm using this for OS detection on the main download button in my current project, but both my Nexus 4 and Nexus 7 are being determined to be plain Linux instead of Android. Here is the output of getBrowser() through Chrome:-
stdClass Object
(
[browser_name] => Mozilla/5.0 (Linux; Android 4.2.2; Nexus 4 Build/JDQ39E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.90 Mobile Safari/537.36
[browser_name_regex] => ^mozilla/5\.0 \(.*linux.*\) applewebkit/.* \(khtml, like gecko\) .*safari/.*$
[browser_name_pattern] => Mozilla/5.0 (*Linux*) AppleWebKit/* (KHTML, like Gecko) *Safari/*
[Parent] => Safari Generic
[Platform] => Linux
[Comment] => Safari Generic
[Browser] => Safari
[Frames] => 1
[IFrames] => 1
[Tables] => 1
[Cookies] => 1
[JavaScript] => 1
[JavaApplets] => 1
[CssVersion] => 1
[Version] => 0.0
[MajorVer] => 0
[MinorVer] => 0
[Platform_Version] => unknown
[Alpha] =>
[Beta] =>
[Win16] =>
[Win32] =>
[Win64] =>
[BackgroundSounds] =>
[VBScript] =>
[ActiveXControls] =>
[isMobileDevice] =>
[isSyndicationReader] =>
[Crawler] =>
[AolVersion] => 0
)
Output of getBrowser() through stock Browser :-
stdClass Object
(
[browser_name] => Mozilla/5.0 (Linux; U; Android 4.2.2; en-gb; Nexus 4 Build/JDQ39E) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 CyanogenMod/10.1.0/mako
[browser_name_regex] => ^mozilla/5\.0 \(.*linux.*\) applewebkit/.* \(khtml, like gecko\) .*version/4\..* safari/.*$
[browser_name_pattern] => Mozilla/5.0 (*Linux*) AppleWebKit/* (KHTML, like Gecko) *Version/4.* Safari/*
[Parent] => Safari 4.0
[Platform] => Linux
[Comment] => Safari 4.0
[Browser] => Safari
[Version] => 4.0
[MajorVer] => 4
[MinorVer] => 0
[Frames] => 1
[IFrames] => 1
[Tables] => 1
[Cookies] => 1
[JavaScript] => 1
[JavaApplets] => 1
[CssVersion] => 3
[Platform_Version] => unknown
[Alpha] =>
[Beta] =>
[Win16] =>
[Win32] =>
[Win64] =>
[BackgroundSounds] =>
[VBScript] =>
[ActiveXControls] =>
[isMobileDevice] =>
[isSyndicationReader] =>
[Crawler] =>
[AolVersion] => 0
)
The README.markdown mentions that this is PHP 5 compatible.
As the code uses a namespace, it is 5.3.x+ compatible.
Has anyone made a modified version that is PHP 5 (or at least 5.2) compatible?
IMO lowecase option here will make the array values lower case, not the array keys.
The following UA
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.04 (lucid) Firefox/3.6.13
is being recognized as
Windows Firefox 3.6
Can you make the 'const VERSION' property public accessible? I would like to use your phpbrowscap as an unmodified library into my code. Making this property public enables me to test if the minimum version of phpbrowscap is being used.
I'm not sure if there is already an issue for this, but I am getting this every time browscap downloads an ini.
PHP Fatal error: Maximum execution time of 30 seconds exceeded in C:\\path\\to\\website\\vendor\\garetjax\\phpbrowscap\\src\\phpbrowscap\\Browscap.php on line 961
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 165 bytes) in C:\\path\\to\\website\\vendor\\vendor\\garetjax\\phpbrowscap\\src\\phpbrowscap\\Browscap.php on line 677
I've tried updating with Composer a few times, but it hasn't fixed it.
php_browscap.ini has an entry:
[12345]
Parent="Miscellaneous Browsers"
Browser="12345"
Unfortunately, probably due to change in http://www.php.net/manual/en/function.parse-ini-file.php (perhaps "5.2.4 - Keys and section names consisting of numbers are now evaluated as PHP integers"), this key is parsed to:
[0]=>
array(2) {
["Parent"]=>
string(22) "Miscellaneous Browsers"
["Browser"]=>
string(5) "12345"
}
Which means that you loose the preg match pattern and browser "12345" will never be matched correctly.
curl option can and have to use proxy settings too.
second case is if user force update method there is no validation of choosen option.
I'll write patch
The license in the header of the PHP appears to be LGPL, yet the license file and readme say MIT.
Which license does the package use?
Thanks
Hello, I am currently using the Browscap class within one of my projects and when installing it the first time, I was wondering why the default indexes where camelcase instead of lowercase.
Somehow I expected the indexes to be lowercase as the php get_browser() function returns them as lowercase too.
Is there a special reason why the default was chosen not to be lowercase?
If this propasal seems weird or senseless to you, please do not hesitate to trash it.
I'm following the suggestion to use composer in the quickstart, but it doesn't appear to work. My composer.json
file contains:
{
"require": {
"GaretJax/phpbrowscap": "*"
}
}
but running composer doesn't find it:
Loading composer repositories with package information
Installing dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- The requested package garetjax/phpbrowscap * could not be found.
Potential causes:
- A typo in the package name
- The package is not available in a stable-enough version according to your minimum-stability setting
see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.
Read <http://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
I see that in packagist it's tagged as dev-master
- does that not match *
? Is it the docs, the code or the package that's wrong? Either way, something needs fixing!
Hi,
I have been using composer for a while and it has worked perfectly. I have been able to avoid using namespaces and this is the first time I have been required to use one. After loading the composer autoload, I put this line below it:
use phpbrowscap\Browscap;
It does not work and in the log I get:
PHP Parse error: syntax error, unexpected 'use' (T_USE)
I tried not using the namespace, but it seems to be required. Is there any way to get this to work without altering any composer files? I don't want to have to re-edit anything after an update. I tried everything "General" on the composer troubleshooting page (http://getcomposer.org/doc/articles/troubleshooting.md), but that didn't change anything.
PHP 5.5.1
Apache 2.4.4
Windows 8 32-bit
I'm testing phpbrowscap in an app that displays the last 10 site visitors and their browsers.
But calling $browscap->getBrowser( $ua );
10 times in a row brings my CPU usage (2 x 2.4 GHz) to 100%, choking the rest of the system.
Am I missing something, or is this normal?
Clean up and reformat the main class code to fit more modern standards (read: fit standards that I like).
:)
getBrowser() takes 0.0349s to process a single User Agent string and appears to be dependent on the cache file, which for some reason, seems to keep getting reset (!$this->_cacheLoaded).
It's a problem with the ini files construction. See the bug report at browscap/browscap#3
Sometimes website stops working because of following errors. Is there a way to fix it?
apache error.log:
[error] PHP Warning: file_get_contents(http://browsers.garykeith.com/versions/version-date.asp): failed to open stream: Connection timed out in /var/www/production/library/Browser/Browscap.php on line 744, referer: http://10.250.34.105/
[error] PHP Warning: fsockopen(): unable to connect to browsers.garykeith.com:80 (Connection timed out) in /var/www/production/library/Browser/Browscap.php on line 751, referer: http://10.250.34.105/
[error] PHP Warning: fsockopen(): unable to connect to browsers.garykeith.com:80 (Connection timed out) in /var/www/production/library/Browser/Browscap.php on line 751, referer: http://10.250.34.105/
[error] PHP Warning: file_get_contents(http://browsers.garykeith.com/versions/version-date.asp): failed to open stream: Connection timed out in /var/www/production/library/Browser/Browscap.php on line 744, referer: http://10.250.34.105/
[error] PHP Warning: file_get_contents(http://browsers.garykeith.com/versions/version-date.asp): failed to open stream: Connection timed out in /var/www/production/library/Browser/Browscap.php on line 744, referer: http://10.250.34.105/
[error] PHP Warning: fsockopen(): unable to connect to browsers.garykeith.com:80 (Connection timed out) in /var/www/production/library/Browser/Browscap.php on line 751, referer: http://10.250.34.105/
[error] PHP Warning: file_get_contents(http://browsers.garykeith.com/versions/version-date.asp): failed to open stream: Connection timed out in /var/www/production/library/Browser/Browscap.php on line 744, referer: http://10.250.34.105/
[error] PHP Warning: fsockopen(): unable to connect to browsers.garykeith.com:80 (Connection timed out) in /var/www/production/library/Browser/Browscap.php on line 751, referer: http://10.250.34.105/
[error] PHP Warning: file_get_contents(http://browsers.garykeith.com/versions/version-date.asp): failed to open stream: Connection timed out in /var/www/production/library/Browser/Browscap.php on line 744, referer: http://10.250.34.105/
[error] PHP Warning: fsockopen(): unable to connect to browsers.garykeith.com:80 (Connection timed out) in /var/www/production/library/Browser/Browscap.php on line 751, referer: http://10.250.34.105/
The automatic updates are breaking. The cause for this is that the project is closed, however there are a few people that are trying to get it back up and going. Just thought I would let you know.
root@ams2-web-1:# cat /tmp/browscap.ini#
Rate limit exceeded. Please try again later.
root@ams2-web-1:
Any idea why this is happening?
Browscap shows a version 0 for Chrome Canary (current version, 34) and for Nexus phones' default browser.
This is the output of getBrowser() for Canary:
[browser_name] => Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1760.0 Safari/537.36
[browser_name_regex] => ^mozilla/5\.0 \(.*windows nt (\d)\.(\d).*\) applewebkit/.* \(khtml, like gecko\).*chrome/.*safari/.*$
[browser_name_pattern] => Mozilla/5.0 (*Windows NT 6.1*) AppleWebKit/* (KHTML, like Gecko)*Chrome/*Safari/*
[Parent] => Chrome Generic
[Platform] => Win7
[Platform_Version] => 6.1
[Platform_Description] => Windows 7
[Comment] => Chrome Generic
[Browser] => Chrome
[CssVersion] => 1
[RenderingEngine_Name] => WebKit
[Version] => 0.0
[MajorVer] => 0
[MinorVer] => 0
[Alpha] =>
[Beta] =>
[Win16] =>
[Win32] =>
[Win64] =>
[Frames] =>
[IFrames] =>
[Tables] =>
[Cookies] =>
[BackgroundSounds] =>
[JavaScript] =>
[VBScript] =>
[JavaApplets] =>
[ActiveXControls] =>
[isMobileDevice] =>
[isSyndicationReader] =>
[Crawler] =>
[AolVersion] => 0
[Device_Name] => unknown
[Device_Maker] => unknown
[RenderingEngine_Version] => unknown
And this is the output for a Nexus browser:
[browser_name] => Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19
[browser_name_regex] => ^mozilla/5\.0 \(.*linux.*\) applewebkit/.* \(khtml, like gecko\) .*safari/.*$
[browser_name_pattern] => Mozilla/5.0 (*Linux*) AppleWebKit/* (KHTML, like Gecko) *Safari/*
[Parent] => Safari Generic
[Platform] => Linux
[Comment] => Safari Generic
[Browser] => Safari
[Frames] => 1
[IFrames] => 1
[Tables] => 1
[Cookies] => 1
[JavaScript] => 1
[JavaApplets] => 1
[CssVersion] => 1
[RenderingEngine_Name] => WebKit
[Version] => 0.0
[MajorVer] => 0
[MinorVer] => 0
[Platform_Version] => unknown
[Platform_Description] => unknown
[Alpha] =>
[Beta] =>
[Win16] =>
[Win32] =>
[Win64] =>
[BackgroundSounds] =>
[VBScript] =>
[ActiveXControls] =>
[isMobileDevice] =>
[isSyndicationReader] =>
[Crawler] =>
[AolVersion] => 0
[Device_Name] => unknown
[Device_Maker] => unknown
[RenderingEngine_Version] => unknown
The size of browscap.ini has more than doubled in the last few months. Using v5024, the corresponding php cache file needs about 20M of RAM. We are using a stripped down version of that file in our WordPress plugin, wp SlimStat.
I was wondering if there was a way to split the cache into multiple files, and then loop through them to load only a subset of agents/browsers at a time.
Would you be able to explain the structure of _browsers and _patterns and how they work together to see if we can split them correctly?
I use Browscap to prevent crashes with native get_browser
https://bugs.php.net/bug.php?id=64934 , but have same errors
[notice] Parent: child process exited with status 3221225477 -- Restarting.
With 60 copies of test_get_browser.php Apache work ~30 sec and then crashes.
I don't wont to write my own User-Agent parser and status is the same, so may be someone here can fix Browscap.
Code looks like
// Loads the class
include_once './phpbrowscap/Browscap.php';
// The Browscap class is in the phpbrowscap namespace, so import it
use phpbrowscap\Browscap;
// Create a new Browscap object (loads or creates the cache)
$bc = new Browscap('./phpbrowscap/cache');
// Get information about the current browser's user agent
$browser = $bc->getBrowser();
Hello,
Currently to select the "standard", "full" etc. version, one has to enter the full file url. It is not the most convenient, and as we are seeing the URLs are subject to change.
I suggest adding a setting that would allow to do so:
$bc = new Browscap();
$bc->version = 'lite';
Details:
$remoteIniUrl
and $version
are defined, use $remoteIniUrl
$version
would be the best fit... I'm looking for suggestions ;-)Your opinion on this?
Regards
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.