h5p / h5p-php-library Goto Github PK
View Code? Open in Web Editor NEWLicense: GNU General Public License v3.0
License: GNU General Public License v3.0
Now that #6 has been merged, would it also be possible to submit the library to https://packagist.org/?
This way a project that uses the library as a dependency wouldn't have to explicitly define the vcs URL in its own composer.json, but composer would automatically find the package from Packagist.
I noticed that there isn't yet 'h5p' namespace in Packagist. When submittin the package, please note that the first user to submit a package to a namespace automatically becomes it's owner for all eternity (or at least Packagist currently does not have a feature to allow changing the ownership.)
Hi, I am trying to integrate this library with a component of mine. Now I'm having trouble displaying the content after it is created because the preloaded dependencies are missing - they are not loaded.
The window.H5P doesn't contain the proper functions, therefore the content cannot be displayed.
The errors that are showing:
Could anyone point me to where the bug would be?
It would be helpful to group H5P interactions that occur on a single page together with a context activity grouping. Is there any way we can fetch the id (or url) of the current CMS page and use that as a grouping context activity?
I'm guessing it would go in this function.
It appears there is a bug with iOS devices changing orientation from landscape to portrait where the IFrame width sizing reads the landscape view when set to width: 100% instead of the portrait width. This can be seen on https://h5p.org/image-hotspots by being in portrait view, changing to landscape view and then changing back.
https://bugs.webkit.org/show_bug.cgi?id=155198
I've opened a pull request at: #36 that fixes this bug.
If you enter text in the field "Autor comments" and hit Enter a new line is generated, like here
In the JSON is then
"authorComments":"Test\nTest"
As long as the h5p stays in your LMS no problem, but when you try to import in another sytem it fails
I think the error is in https://github.com/h5p/h5p-php-library/blob/master/h5p.classes.php
'authorComments' => '/^.{1,5000}$/',
When you try it here https://regex101.com/r/IS3lUT/1 it finds no match. When you remove the second line, it matches again.
I've tried in course presentation and Find the words, in both this error occurs.
While trying to get the integration data for an InteractiveVideo content (with one Single Choice Set) the following error occurs:
property_exists(): Argument #1 ($object_or_class) must be of type object|string, array given
While investing further into this error I found that an unused if statement is causing this. https://github.com/h5p/h5p-php-library/blob/1.24.3/h5p.classes.php#L4037
Commenting out the if solves the error and everything is working as intended.
Here my patch:
--- /dev/null
+++ ../h5p.classes.php
@@ -4034,9 +4034,9 @@
foreach ($semantics->fields as $field) {
if (!(isset($field->optional) && $field->optional)) {
// Check if field is in group.
- if (! property_exists($group, $field->name)) {
+ //if (! property_exists($group, $field->name)) {
//$this->h5pF->setErrorMessage($this->h5pF->t('No value given for mandatory field ' . $field->name));
- }
+ //}
}
}
}
Not sure that this is the best place to record this issue, but the h5p.org site (where the docs used to be) has been down for the last 14 hours (at least). The google cached version is pretty hard to use, so it'd be great to have an estimate on when we can expect to have the site back up. Thank you!
Some ideas for future versions of the library:
Currently many of the methods take arbitrary arrays as parameters. This makes it difficult to understand what exact data each function is expecting. I think in the long-term the integration library should be refactored to pass objects instead of arrays as function arguments.
That way:
// Fails if passed anything else but an object that implements the
// \H5P\Content interface. Therefore developers know exactly
// what they are supposed to pass into the method.
public function filterParameters(\H5P\Content $content) {
// Also you now have easy access to content methods:
if ($content->isFiltered()) {
// Some logic here
}
}
Currently the library requires a framework to implement only one interface: H5PFrameworkInterface
.
This causes too much unrelated logic to be inserted into the same class. Splitting the implementation to multiple different interfaces would:
I think that in branch master the extraction of the zip file in isValidPackage() function is omitted. When I'm trying to upgrade nothing happens and I found no trace to zip extract in the code.
Thank you.
H5P's tracking does not support the result.success and result.completion properties, which are important properties used by most quiz authoring tools and LRSs that report on quiz data (e.g. Watershed).
It looks like these could easily be added in as additional optional properties to setScoredResult.
Would I be right in assuming that if this library is updated that this would also be reflected in the next release of the WordPress plugin?
Would it be helpful for me to make a PR?
Short array syntax is only allowed since PHP 5.4
h5p-php-library/h5p.classes.php
Line 3958 in 4599291
Posted issue here: h5p/h5p-wordpress-plugin#58 instead.
This has been discussed shortly earlier, but I add it here again so there's a place for conversation.
There's apparently the need to support quite a wide range of platforms and PHP versions, so I think the project would benefit from adopting branches that would be compatible with Semver (http://semver.org/).
Each incompatible library version would get it's own git branch.
Or perhaps the two first ones could use the same branch, so that only distinction between branches would be the incompatible changes:
This way a framework plugin that uses, say, version 2.1.4 of the library could safely upgrade directly to 2.6.0 without worrying about the integration getting broken.
This would also allow developing for multiple PHP versions at the time, as the supported version could be different for each branch. E.g:
PHP Deprecated: Array and string offset access syntax with curly braces is deprecated in /h5p-app/vendor/h5p/h5p-core/h5p.classes.php on line 2747
seems fixed on master but it needs to be tagged
Hi There,
First of all; great work guys, really like your elements and components. We hope to contribute in the near future. A customer was reporting issues with Safari 10 and fullscreen. After debugging I also came across this drupal website, where a user has found the root cause and solution.
https://www.drupal.org/node/2805311
The problem is the detection of the Safari version. As they now have version 10 (2 digits), your regular expression is only taking 1 digit, so it sees it as Safari < 7 and no real full screen is enabled. But is also not enabling the semi full screen modus (as @paalj there is asking), thus the button is not doing anything.
Version 8 and 9 of Safari are working fine, as I just checked it with Browserstack.
Can you please fix this in your main h5p.org distribution as embeds from H5P are not working with full screen in Safari 10?
If I can assist in any way, let me know.
Peter
Some content types allow the user to re-attempt a question and send a statement after each one. Here, the duration is calculated as the time between when the learner accessed the question first and when they submitted the attempt, rather than between when they started and submitted an attempt. This will cause inaccuracies for systems reporting on the data that add durations to calculate total time.
I suggest adding something here to either reset instance.activityStartTime or store another variable such as attemptStartTime. Presumably that's be a new property of instance? Can we modify instance in this context?
First of all, thanks for creating H5P and sharing it with the world!
Now the issue:
The docs (https://h5p.org/creating-your-own-h5p-plugin) state that the intention is to enable the development of H5P integrations in any programming language, and that as much as possible of the core library is JavaScript. This is great, but it's not reflected in the code structure yet. Instead, this repo with the core JS library has 'php' in its name and mixes PHP and JS parts (also subjecting them to the same license, see #16).
Moving the JS parts out of here would enable people to more easily build integrations for non-PHP platforms, and also reduce the impact of viral licensing for those who cannot accommodate such restrictions. A low-barrier first step could be to create a new repo, put the JS code there, and e.g. link it here as a git submodule so it can still be used as before.
What do you think?
To make the code easier to work with, we should put each class into separate file. We should also add or create some sort of default autoloader.
Zip files may contain records for directories as well as files. For example, if our tree is
h5p.json
Mylib/
|- semantics.json
|- library.json
the records present in our zip file might be
h5p.json
Mylib/
Mylib/semantics.json
Mylib/library.json
or
h5p.json
Mylib/semantics.json
Mylib/library.json
ie, the Mylib/
entry may or may not be present.
Currently, the HP5Validator
class rejects the first case while checking for invalid file extensions. Worse, it provides no specific error message that directory records are not allowed, and instead complains about the directory name having a bogus file extension.
The relevant code was introduced here:
366d8f2#diff-5ca86cd0514d58be6708beff914aba66R829
On UN*X systems, the most straightforward way to create a .h5p file from a directory tree is using the zip
utility. For example: $ zip ../mylib.h5p -r .
might be used to create the .h5p file from the tree in our previous example. This invokation, however, will create a record for the Mylib/
directory as described above, and the resulting .h5p file will be rejected.
A possible fix might include checking for directories by checking whether the file name ends with a slash. The following additions make the validation succeed for me:
elseif ($canInstall && strpos($fileName, '/') !== FALSE) {
+ // directory record
+ if (substr($fileName, -1) === '/') {
+ continue;
+ }
// This is a library file, check that the file type is allowed
if ($this->h5pC->disableFileCheck !== TRUE && !preg_match($libraryRegExp, $fileName)) {
I'm not submitting a pull request for this yet because I assume there are probably other sanity checks that would make sense here.
A user has recently opened an issue reporting that fullscreen in interactive videos doesn't work in the Moodle mobile app. I looked at it and I found two different issues depending on the platform, and they're both related to this part of the h5p code.
iOS
In Safari for iOS, document.documentElement.webkitRequestFullScreen exists, but it doesn't exist in the WebView used by the app. For this reason the full screen doesn't work in the app. Maybe the library should hide the full screen button if the function to request fullscreen doesn't exist?
Android
If the userAgent contains the word "version", H5P assumes it's a Safari browser. However, the Android WebView contains the word "version" but it isn't Safari. The H5P library thinks it's an old Safari version and doesn't let you use full screen. I tried commenting the safariBrowser check and the full screen started working, although I couldn't see the video (it was a black screen) so there's another problem besides this one.
Here are some user agent in mobile devices so you can see how they look like:
Android WebView: Mozilla/5.0 (Linux; Android 9; Android SDK built for x86_64 Build/PSR1.180720.093; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 Mobile Safari/537.36 MoodleMobile
Chrome for Android: Mozilla/5.0 (Linux; Android 9; Android SDK built for x86_64 Build/PSR1.180720.093) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36
iOS WebView: Mozilla/5.0 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MoodleMobile
Safari for iOS: Mozilla/5.0 (iPad; CPU OS 12_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Mobile/15E148 Safari/604.
As you can see, in Android WebView the userAgent contains the word "version" while the browser doesn't, and in iOS it's the opposite way.
Hi
I made the mistake of up grading exiting content to new libraries. Now none of the content works and I get these messages
The version of the H5P library H5P.MultiChoice used in this content is not valid. Content contains H5P.MultiChoice 1.8, but it should be H5P.MultiChoice 1.9.
The version of the H5P library H5P.MultiChoice used in this content is not valid. Content contains H5P.MultiChoice 1.8, but it should be H5P.MultiChoice 1.9.
The version of the H5P library H5P.TrueFalse used in this content is not valid. Content contains H5P.TrueFalse 1.0, but it should be H5P.TrueFalse 1.1.
The version of the H5P library H5P.Summary used in this content is not valid. Content contains H5P.Summary 1.6, but it should be H5P.Summary 1.7.
and nothing displayed ?
Moodle 3.1
php7
Just upgraded to the lastest version of h5p
User-entered textual H5P content is saved as a string in the database. So theoretically it could be translated to another language on server side before sending it to browser, right?
How difficult would this be to implement? Are the strings too mingled up to the technical structure that it would be difficult to extract and replace them with a translation?
If not, how crazy would it be to e.g. insert the strings within some kind of wrapper that would signify them being translatable?
The line 2770 in h5p.classes.php references an invalid parameter (there is an extra e which can be removed): $library->machineName
$this->h5pF->setLibraryTutorialUrl($library->machineNamee, $library->tutorialUrl);
Hi,
I'm working on an implementation of H5P for Symfony.
The bundle that i use works fine in 1.17.
But to migrate to 1.19 I need to implement loadAddons()
and getLibraryConfig()
( see this issue ).
So my question is simple : have you a documentation that describe what this methods must return ?
I looked at the Wordpress implementation and saw that i need a add_to
field in my libraries table.
What is that field, where can i find a documentation that describe the table, the fields types...
Thank you.
(And happy new year 😄 )
Console errors every time H5P object embedded into Canvas LMS. (caused by iframe resize messages)
H5P embedded iframes send messages to the window.parent and these messages cause console errors with Canvas LMS' own resizing system in the file messages.js. Canvas attempts to parse the data object from the H5P message as a JSON string causing an exception.
I have not located when this incompatibility was introduced.
Copy the embed code from any h5p.org (or self-hosted) H5P activity. Paste the embed code into Canvas LMS. Open up the developer console and see the error from messages.js.
Line 90 in h5peditor-select.js
is this:
html += E.createOption(options[i].value, options[i].label, options[i].value === selected);
I would like to make a simple change to turn ===
into the more flexible ==
, as I have a few cases where the correct option is not selected.
html += E.createOption(options[i].value, options[i].label, options[i].value == selected);
If you agree I will create the simple pull request. Kind regards
The return value from the function H5PExport::createExportFile
is silently ignored when called from H5PCore::filterParameters
. If the export directory has wrong permissions, or if something else fails, this will mean that it will just fail silently. In my opinion, this should cause an error that is shown to the user when he saves the content. In the same was as an error is shown if the content directory would have wrong permissions (or if writing to it fails).
I would be happy to submit a PR, just want to check first what you think. I think failing should be as loud as possible and as soon as anything goes wrong, do you agree?
Hi,
You're saying in documentation that if I want to use h5p on my website I have to install plugin for wordpress/moodle/drupal... and I'm confused :P - Can I integrate h5p with my framework in php (creating h5p files, integrate plugins like flashcards etc.) ? or it's only for wordpress/moodle/drupal?
Expected behavior:
Content package requires library version 4.1. The system has 4.5.2, so everything should work.
Actual behavior:
I'm getting the error:
Missing required library foo 4.1
Is this working as intended?
Hi there:
I've just discovered the H5P project, and it looks AWESOME! Thanks for sharing such project with a MIT-license.
I'm a project admin at Tiki Wiki CMS Groupware ( https://tiki.org ), which is LGPL'd and compatible with MIT-license libraries, and we might consider re-using h5p for our software in some projects.
However, we have noticed that some part of your code seem to be GPL'd, as indicated here:
https://github.com/h5p/h5p-php-library/blob/master/LICENSE.txt
Was that intended? Is this an unintended conflict?
We ask because GPL'd code can't be bundled in LGPL'd applications, such as Tiki, while MIT code can.
By the way, in case that GPL'd license was intended, do you know that you can also double license your GPL'd libraries with the MIT license, also? (so that all FLOSS projects can use your libraries, regardless of GPL or LGPL license they have, for instance).
It seems that browsers have made changes what sort of APIs are allowed to be used from within an <iframe>
. Disabling everything by default as described here.
This in term raises issues with any H5P type that requires usage of certain API's. The one that allows user to use a microphone and save the result as a file fails dues to that when being embedded. The error shown to the enduser is Access to microphone is not allowed due to page not being loaded using HTTPS
(current working is not 100% correct but is something along those lines.
Chrome itself shown no errors or warning in the developer console, though Safari does mention that getUserMedia was called from a frame without correct 'allow' attribute
.
The solution for this case is simple enough, adding allow="microphone; midi"
to the iframe code. It might not be enough to cover the needs for all of the H5P content types (either current or one that could be created in future). Using allow="*"
would allow everything and from any context. yet that could be considered a bit too permissive.
Currently the repo has multiple branches that do not really make sense:
Based on the names these seem like feature branches. Branches in the main repo should* instead be used for telling apart versions that are not compatible with each other:
Or at least it should be documented somewhere, what each of the current branches is used for. (What would be the best place for this kind of documentation?)
*Absolute Truth™ ;)
Currently there is no information of the required PHP version.
Make sure to add it at least to the require
section in composer.json, for example:
{
"require" : {
"php" : "^5.5"
}
}
This way composer automatically checks the version when the library is being installed to a project.
I want to prequalify a pull request related to the following:
I want to keep track of the ContentUpgrade process from outside the encapsulated code it resides in today. The reason I want to do this is that I want to replace the existing out-of-the-box UI that's currently generated when including the h5p-content-upgrade.js script with my own UI. In order to update my UI I need the ContentUpgrade script to trigger events that I can listen to.
The changes does not have any affect on current UX and accessibility.
To be able to start the upgrade process from my own UI I want to make the ContentUpgrade object accessible from outside the encapsulated code it resides in today. To achieve this I want to add it to the H5P object. In addition I want to keep track of the upgrade process so I need to be able to add a object with event callbacks to ContentUpgrade. As the upgrade process goes along different events are triggered from within ContentUpgrade that the provided events can listen to. This way I can trigger changes and update my UI accordingly.
While building our Neos platform integration for H5P, I noticed that the way export filenames for contents are built is handled inconsistently, and there are three places where and export method is called, each time with a different interface.
At
https://github.com/h5p/h5p-php-library/blob/master/h5p.classes.php#L1950
we have
$this->fs->hasExport($content['slug'] . '-' . $content['id'] . '.h5p')
At
https://github.com/h5p/h5p-php-library/blob/master/h5p.classes.php#L1979
we have
$this->fs->deleteExport($content['id'] . '.h5p')
, which is a bug since sends a filename that can never exist, as the filename is built differently in H5PExporter->createExportFile()
.
At
https://github.com/h5p/h5p-php-library/blob/master/h5p.classes.php#L1985
we have
$exporter->createExportFile($content);
, which is imho the best way to handle this as generating the filename should be a concern of the H5PExporter.
I will provide a PR which fixes the bug. Note that this will be breaking, since it touches public API.
If admins have set the saveContentState
option, H5P is supposed to store the current content's state for the user
saveFreq
seconds,completed
or progressed
unload
, beforeunload
, pagehide
event.The latter is pretty unreliable. There's no guarantee that either of those three events will fire and it may depend on the browser policy. It might help to use visibilitychange
(https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilitychange_event) in addition to pagehide
. (https://github.com/h5p/h5p-php-library/blob/master/js/h5p.js#L2868 and https://github.com/h5p/h5p-php-library/blob/master/js/h5p.js#L2872)
Still, unload
, beforeunload
are unreliable. There's no guarantee that these will be triggered and users might complete an exercise and close the tab without the state being stored. Most content types do not use the xAPI verb completed
, but answered
when they are checked, so it might be a good idea to add answered
as well (https://github.com/h5p/h5p-php-library/blob/master/js/h5p.js#L246). There's still that 3 seconds delay set in H5P core, so if people close the tab within 2999 milliseconds after completing an exercise the state would not be saved - but still better than it is now.
Those new triggers would only cause an AJAX request to the server if the state actually changed, because H5P checks, so these two additions should not have a performance impact server-side.
I'm asking beause I want to use ah5p-Quiz at moodle as a more comfortable replacement of the internal quizzes in moodle. I asked this before at the code for the moodle-Plugin.
At the moment the user can start a quiz as often as they want. Even if I turn of repetition of the single questions (I my case "single-choice")
It would be nice to define the max number of trials that it behaves like tests in moodle. I was asked to post this question here for the core library. I'm not sure if it is the right place, for me it does not make sense for "not-controlled" quizzes like at the h5p.org pages, because you can reload the quiz again.
But at moodle you need a special moodle-setting to enable the user only to do the quiz once, and the close the windows with the quiz, automatically go to the course-page oder make the quiz unvisible.
Thanks!
Saving the token for users in the session will prevent Drupal sites to serve pages from cache for anonymous users.
Use a cookie to save the token instead.
Hey gang:
I've been trying to hunt down the source of a series of PHP Warnings I get that targets the h5p.classes.php file of the H5p dependency. The warning I get is:
PHP Deprecated: Array and string offset access syntax with curly braces is deprecated in /vendor/h5p/h5p-core/h5p.classes.php on line 2747
Deprecated: Array and string offset access syntax with curly braces is deprecated in /vendor/h5p/h5p-core/h5p.classes.php on line 2747
Where is my site's directory.
I was able to track this warning's root cause down to how it works with PHP 7.4. This warning appears to have been patched last year:
https://github.com/h5p/h5p-php-library/commits?author=stronk7
However, that fix was not included in the 1.24.0 release, but it is in master.
I'm hoping that you can cut a 1.24.1 so I can get rid of this nuisance.
On the release version, this part of the code
h5p-php-library/h5p.classes.php
Lines 4025 to 4032 in 5d7b480
yields
Warning: First parameter must either be an object or the name of an existing class in /foo/h5p/h5p-php-library/h5p.classes.php on line 3893
if there's a group that contains only one item and the optional property is not set.
I think that's actually a problem with core turning a one item group from an array with one object into just an object. The default property then has to be set on the group, not on the item, in order to be used correctly by the editor. The code referenced above, however, doesn't use that one leading to the error message if the optional property is not set for the item.
Lines 107 to 137 in 22115c0
The call to H5P.getUserData
is supposed to populate library.userDatas
with the previous state, so it can be used in in the call to H5P.newRunnable
in
Line 137 in 22115c0
This works fine if the previous state is set in the H5PIntegration object and fetched in
Line 2402 in 22115c0
Otherwise. however H5P.getUserData
will not resolve before the asynchronous call to contentUserDataAjax
in
Line 2338 in 22115c0
library.userDatas
may be set after H5P.newRunnable
wants to use the parameter.
This is currently not an issue, because all the H5P plugins set the contentUserData
property in the H5PIntegration
object, but it will not work otherwise although the code suggests it would.
In h5p.js, export is used as a variable-name. This is a reserved js-word.
Hi team,
I'm working on MDL-70323 Moodle tracker to have a same config as the plugin has. It would be good to have it documented in config-dist.php
with same wordings as $CFG->mod_hvp_crossorigin
. However, I cound't find any docs for $CFG->mod_hvp_crossorigin
. Could somebody please point me to the right place?
Kind regards,
Mikhail
When using mkdir(), the permissions are always set to 0777, or example:
h5p-php-library/h5p.classes.php
Line 1778 in 4c973c3
If the second argument is made configurable, then in Moodle plugin the setting:
$CFG->directorypermissions
Could be used for the permissions.
Hi!
I've used the H5P PHP Library to implement an integration of H5P on a multi tenant Laravel application. The system can manage libraries on a shared base and contents (database and storage) are fully separated between tenants.
Each tenant's admin have access to the editor and manage his own h5p contents, available for all users attached to this tenant.
Despite some less important details, I am now trying to get statistics (xAPI) and save user's state.
If I did understand, H5P sends a post request to contentUserData url to save user's data, and it does that on a time interval base saveFreq setting.
Is there trigger that request on every click or at least on every answered question, whatever the library?
Thanks for the help.
jquery library included is at v1.9.1 version:
https://github.com/h5p/h5p-php-library/blob/master/js/jquery.js
Security alert
Your app contains one or more libraries with known security issues. Please see this Google Help Center article for details.
Vulnerable JavaScript libraries:
Name Version Known issues Identified files
jquery 1.9.1 SNYK-npm:jquery:20110606
SNYK-npm:jquery:20150627
SNYK-JS-JQUERY-174006 assets/www/h5p/js/jquery.js
Affects APK version 30801.
Error in Moodle Mobile App 3.8.1
Hola! @falcon-git has created a ZenHub account for the h5p organization. ZenHub is the leading team collaboration and project management solution built for GitHub.
To get set up with ZenHub, all you have to do is download the browser extension and log in with your GitHub account. Once you do, you’ll get access to ZenHub’s complete feature-set immediately.
ZenHub adds a series of enhancements directly inside the GitHub UI:
Still curious? See more ZenHub features or read user reviews. This issue was written by your friendly ZenHub bot, posted by request from @falcon-git.
Hello,
we recognized, that this part of the mod_hvp-Plugin uses Google APIs in the following files:
As for European sites, this causes an infringement of the GDPR. Would it be possible to fix that?
Kind 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.