gulpjs / gulp Goto Github PK
View Code? Open in Web Editor NEWA toolkit to automate & enhance your workflow
Home Page: https://gulpjs.com
License: MIT License
A toolkit to automate & enhance your workflow
Home Page: https://gulpjs.com
License: MIT License
Hi is there a way to hook events within tasks, say:
var p = require('path);
var d = '';
gulp.task('coffee', function() {
gulp.src('./src/**.coffee')
.on(dirChange).valve(d)
.pipe(coffee())
.pipe(jshint())
.pipe(concat( p.basename(p.dirname(d)) + '.js'))
.pipe(gulp.dest('./static'))
})
where on() is the event and valve() creates a new pipe context with whatever semantics dirChange, etc impose. Although I dislike my syntax.
I'm exploring gulp as a replacement for gruntjs.
Here is my gulpfile.js.
I'm using gulp to watch and compile coffeescript files (with gulp-coffee). In addition, I'm using gulp.watch to only compile individual files instead of entire targeted globbed paths.
My issue is that if I purposely put incorrect coffeescript syntax, gulp exits:
events.js:72
throw er; // Unhandled 'error' event
< gulp-coffee error here >
< rest of stack trace >
How should I catch the error without having it stop gulp.watch? And perhaps re-initiate the default task?
I'm not familiar with streaming in node. I tried try-catch and checked if any callbacks are catching the error to no avail. Appreciate if someone point me in the right direction.
In lieu of gulp.src('*.js', {ignore:'**/lib/*.js'})
add a mechanism to pipe a selection to gulp.watch()
think grunt added this in 0.4.1, it is a nice to have.
It's not clear how errors should be handled in gulp. Should it be logged using the gulp-util logging, returned early in the callback as illustrated below, or both?
All it says:
If you encounter an error while processing a file, you should emit it to the stream or pass it to the callback if using es.map from event-stream.
Example:
module.exports = function () {
return es.map(function (file, cb) {
var ret = compile(file.contents.toString());
if (ret.error) {
return cb(error);
}
file.contents = new Buffer(ret.code);
cb(null, file);
});
};
If I do the above gulp will throw an unhandled error message:
events.js:72
throw er; // Unhandled 'error' event
^
Error: Some error
I would have assumed gulp would handle this and present it in a nice way. Like with color and prepending [gulp] and the plugin name.
Whatever the best practise. This needs to be clear in the docs.
These should verify that all of the plugin guidelines were followed.
Hi,
I'm trying to understand how to make a function run async.
Below is my gulp file, and in there I run a specific task called test
where I do nothing but immediately call the callback function and pass through some fake data.
My callback function gets called but the data isn't passed through?
So for example, it logs Response:undefined
so I know it's calling the callback but I'm not sure why the data isn't passed through?
Any ideas what I'm missing.
var gulp = require('gulp');
var size = require('gulp-filesize');
var styles = 'Assets/Styles';
var scripts = 'Assets/Scripts';
gulp.task('test', function(cb) {
cb(null, 'some data to pass through');
});
gulp.task('filesizes', function() {
gulp.src(styles + '/**/*.css').pipe(size());
gulp.src(styles + '/**/*.js').pipe(size());
});
gulp.task('default', function() {
gulp.watch([
styles + '/**/*.css',
scripts + '/**/*.js',
], function() {
gulp.run('test', doSomethingAsync);
gulp.run('filesizes');
});
});
function doSomethingAsync(err, res) {
if (err) console.log('Error: ' + err);
console.log('Response:' + res);
}
Hello,
I decided to give a try to gulp, it's looks very promising!
Unfortunatly, working on windows, it seems that the gulp binary wasn't available after the install. Not sure how I can fix it (I 'll' take a look at other npm binaries to see how they register)
Therefore, I can enjoy gulp launching it directly via node_modules/gulp/bin/gulp.js
This makes this use case possible
gulp = require 'gulp'
coffee = require 'gulp-coffee'
minify = require 'gulp-minify'
gulp.task 'reload', ->
# do some live reload stuff here
gulp.task 'coffee', ->
# compile, minify, and copy all coffee-script
gulp.files("./client/js/**", {ignore:["vendor"]})
.pipe(coffee)
.pipe(minify)
.pipe(gulp.folder("./public/js"))
.pipe(gulp.trigger('reload'))
gulp.task 'js', ->
# minify and copy all vendor files
gulp.files("./client/js/vendor/**")
.pipe(minify)
.pipe(gulp.folder("./public/js/vendor"))
.pipe(gulp.trigger('reload'))
gulp.task 'default', ->
gulp.run 'js', 'coffee'
gulp.watch "./client/js/**", ->
gulp.run 'js', 'coffee'
So really just an es.map stream that does nothing but trigger a task and passes the same file through when its done.
Say I do a copy task like :
gulp.src("../app/src/js/**/**/*.js")
.pipe(gulp.dest("./public/js/"));
This would copy the dirs as well, but the intent was to just copy the js files.
Something like : find ../app/src/js/ -iname '*.js' -exec cp {} public/js/ \;
So maybe a filer like :
gulp.src("../app/src/js/**/**/*.js")
.filter({isFile:true})
.pipe(gulp.dest("./public/js/"));
would be useful?
filter
might gupl even more file attributes to work upon.
I see in the roadmap that there are plans to create a gulp-www site with plugin search, sorting, and whatnot.
That's all fine and good, but I see no reason to have to write a web application when we can use github pages with some simple client-side js to create a fully functioning web site. The best place to hoist this site would be the already existing gulpjs organization as a user site, where it would site nicely under the domain gulpjs.github.io. Of course, github provides cname if the need comes to use a shorter domain like gulpjs.net.
In addition, since there already exists a 'gulpjs' user, I would recommend moving the main repo(wearefractal/gulp) and other plugins by wearefractal(wearefractal/gulp-coffee, wearefractal/gulp-concat) to gulpjs. Yes, this has its immediate drawbacks, but then all the repos related to gulp(like the site, artwork, and code) are with one user, in addition to any plugins made by the authors(just like gruntjs.
I'll work on a prototype for a client-side plugin search utility and host it on github pages just for demonstration.
I'm trying to understand how I would use a particular gulp plugin (in this instance gulp-filesize
which console.log
's the filesize of each file streamed to it) and then after the plugin is done, pass each file to my own writable Stream (e.g. I want to take the file and log out other stuff about it).
This is more a general Node question, but as it resolves around using Gulp I thought I'd check here first before hitting some Node forums/irc/community places.
Below is my code, you can see I'm creating a writable Stream (I'm fairly new to Streams so I assume my code is the correct way to create a new Stream) and all I'm doing is piping the file that gulp passes through to the plugin back out to my own writable Stream but I'm getting an error (also below) about Invalid non-string/buffer chunk
but I'm not sure how to resolve the issue.
Any help appreciated, or feel free to close the issue and tell me to go elsewhere (stackoverflow etc) for solution...
var gulp = require('gulp');
var size = require('gulp-filesize');
var stream = require('stream');
var util = require('util');
var styles = 'Assets/Styles';
var scripts = 'Assets/Scripts';
function aNewWritableStream() {
stream.Writable.call(this);
this.on('finish', function(){
console.log('finished writing');
});
}
util.inherits(aNewWritableStream, stream.Writable);
// Assume I have to overwrite the `_write` method of the writable Stream?
// Also assume this is where I'd put my additional code for console logging extra stuff about the file?
aNewWritableStream.prototype._write = function(chunk, encoding, next) {
console.log(chunk.toString(encoding));
next();
};
var writableStuff = new aNewWritableStream();
gulp.task('filesizes', function() {
gulp.src(styles + '/**/*.css').pipe(size()).pipe(writableStuff);
gulp.src(styles + '/**/*.js').pipe(size());
});
gulp.task('default', function() {
gulp.watch([
styles + '/**/*.css',
scripts + '/**/*.js',
'./gulpfile.js'
], function() {
gulp.run('filesizes');
});
});
/Users/markmcdonnell/Code/Gulp/node_modules/gulp-filesize/node_modules/event-stream/node_modules/map-stream/index.js:95
throw err
^
TypeError: Invalid non-string/buffer chunk
at validChunk (_stream_writable.js:150:14)
at aNewWritableStream.Writable.write (_stream_writable.js:179:12)
at Stream.ondata (stream.js:51:26)
at Stream.EventEmitter.emit (events.js:95:17)
at queueData (/Users/markmcdonnell/Code/Gulp/node_modules/gulp-filesize/node_modules/event-stream/node_modules/map-stream/ind$x.js:38:21)
at next (/Users/markmcdonnell/Code/Gulp/node_modules/gulp-filesize/node_modules/event-stream/node_modules/map-stream/index.js$68:5)
at /Users/markmcdonnell/Code/Gulp/node_modules/gulp-filesize/node_modules/event-stream/node_modules/map-stream/index.js:77:7
at /Users/markmcdonnell/Code/Gulp/node_modules/gulp-filesize/index.js:19:4
at wrappedMapper (/Users/markmcdonnell/Code/Gulp/node_modules/gulp-filesize/node_modules/event-stream/node_modules/map-stream$index.js:76:19)
at Stream.stream.write (/Users/markmcdonnell/Code/Gulp/node_modules/gulp-filesize/node_modules/event-stream/node_modules/map-s
tream/index.js:88:21)
What's gulp's equivalent of make clean? Also, it would be nice to put a note on the README file that says gulp looks for a file called [G|g]ulpfile.[js|coffee].
Some tasks will require to be run in series, I tried accepting a callback like what's in the README but it does not work:
var g = require('gulp');
var util = require('util');
g.task('clean', function(cb) {
setTimeout(function() {
util.log('clean task executed.');
cb(null);
}, 3000);
});
g.task('copy', function(cb) {
util.log('copy task executed.');
cb();
});
g.task('default', ['clean', 'copy'], function() {
util.log('default task executed.');
});
output with callback:
$ gulp
[gulp] Using file g:\www\test\Gulpfile.js
[gulp] Working directory changed to g:\www\test
[gulp] Running 'clean'...
[gulp] Running 'copy'...
23 Dec 00:32:44 - copy task executed.
[gulp] Finished 'copy' in 2.35 ms
23 Dec 00:32:47 - clean task executed.
[gulp] Finished 'clean' in 3.01 s
[gulp] Running 'default'...
23 Dec 00:32:47 - default task executed.
[gulp] Finished 'default' in 1.11 ms
output without callback:
$ gulp
[gulp] Using file g:\www\test\Gulpfile.js
[gulp] Working directory changed to g:\www\test
[gulp] Running 'clean'...
[gulp] Finished 'clean' in 489 ฮผs
[gulp] Running 'copy'...
23 Dec 00:31:54 - copy task executed.
[gulp] Finished 'copy' in 1.25 ms
[gulp] Running 'default'...
23 Dec 00:31:54 - default task executed.
[gulp] Finished 'default' in 419 ฮผs
23 Dec 00:31:57 - clean task executed.
I was expecting it to finish clean
before executing copy
.
$ gulp --version
[gulp] CLI version 3.2.0
[gulp] Local version 3.2.0
I believe this functionality deserves it's own package, the same way as you guys are reusing orchestrator
, event-stream
, glob-stream
, etc.
Even tho this feature is the core of gulp
, it could be used outside the task runner context. It could even become the de-facto standard for file manipulation. (so you would have file stream modifiers coded by more people).
I agree that there are benefits of bundling all the features into the same package (so you can simply do npm install --save-dev gulp
) but for me it feels like this tool is doing too much (too many responsibilities).
Cheers.
I believe that the lack of many things is good for gulp, however, if we don't have a standard string templating system quick, then there's going to be a problem.
Let's take gulp-exec vs gulp-header:
gulp.files('./**/**').pipe(exec('git checkout $file'));
gulp-exec uses $file
(hint hint) as a sort of templating string for receiving files.
var headerText = '' +
'/*! {{filename}} - '+
'Copyright {{year}} MyCompany - '+
'MIT License - '+
'generated {{now}} - {{foo}} */'+
'';
gulp.src('./lib/*.js')
.pipe(concat('merged.js'))
.pipe(header(headerText, {foo:'bar'}))
.pipe(gulp.dest('./dist/')
Notice that gulp-header uses templates like {{filename}}
(hint hint) as templates for receiving files.
I think this is going to become a problem very soon. Lots of gulp plugins need some form of templating, at least. Grunt got this solved just by using underscore templates, and I think if we also had something like that, we'd be way more happy.
What I propose: use underscore/lodash templates, along with adding a new function, gulp.define. Underscore/Lodash templates can be compiled when they are passed to a plugin, and define takes an object(or two values) and passes them on to the immediate next task(that is not a .define() call).
Then, The top two examples become:
gulp.files('./**/**').pipe(exec('git checkout <%= gulp.file.path %> '));
var headerText = '' +
'/*! <%= gulp.file.path %> - '+
'Copyright <%= year %> MyCompany - '+
'MIT License - '+
'generated <%= now %> - <%= foo %> */'+
'';
gulp.src('./lib/*.js')
.pipe(concat('merged.js'))
.pipe(gulp.define('year', '2013')) // we can use multiple define calls in sequence
.pipe(gulp.define({ // using an object to define properties
now: function () {
return new Date().toISOString();
},
foo: 'bar'
})
.pipe(header(headerText) // these properties are passed into the template
.pipe(gulp.dest('./dist/')
This is probably a very hacky and quick solution to this problem. I'm thinking of other ways to solve it right now.
It isn't very intuitive that .file()
creates a source stream and .folder()
creates a destination stream. "But I want all files in that directory." Perhaps consider renaming these to .src()
and .dest()
or .from()
and .to()
or .input()
and .output()
or .consume()
and .create()
or .gulp()
and .puke()
.
Tried to copy resources with the same syntax as the README and it doesn't copy anything (no error).
I love the plugin guidelines in the wiki. Some of those are a huge problem in the grunt ecosystem. One thing missing though is testing. There are too many grunt plugins without tests. Hopefully you can make sure gulp plugins are well-tested.
I suggest you add a point about testing being a requirement.
Test case.
gulp.task('negation', function(){
gulp.src(['.tmp', 'dist/*', '!dist/.gitignore'])
.pipe(es.map(function(data, cb){
console.log(data);
cb(null, data);
}));
});
If you remove the negation, it works
gulp.task('negation', function(){
gulp.src(['.tmp', 'dist/*'])
.pipe(es.map(function(data, cb){
console.log(data);
cb(null, data);
}));
});
The same functionality as grunt-cli provides.
What do you think?
I have two tasks, task one pipe to task two.
gulp.task('one', function(){
gulp.src('js/**/*.js')
.pipe(someplugin())
.pipe(gulp.tasks['two']);
});
gulp.task('two', ['one'], function() {
gulp.tasks['one']
.pipe(gulp.dest('dist/js'));
});
The README says to use gulp.log, but it is undefined.
Hi,
I just install the latest 3.2.1 version and execute a simple test, extracted from the readme
I just adds a console.log("inside copy");
inside the copy task and console.log("inside watch", arguments)
inside the watch task
var gulp = require('gulp');
gulp.task('copy', function() {
console.log("inside copy");
gulp.src('client/img/**')
.pipe(gulp.dest('build/img'));
});
gulp.task('default', function() {
gulp.run('copy');
gulp.watch([
'client/img/**',
], function(event) {
console.log("inside watch", arguments)
gulp.run('copy');
});
});
The copy operation works perfectly but the problem is:
If I add a file or directory outside the pattern filter, the watch task is also executed
I'm watching client/img/**
If I create the directory client/test
, the console log
[gulp] Finished 'copy' in 1.06 ms
inside watch { '0': { type: 'added', path: 'E:\\GULP\\client\\test\\' } }
[gulp] Running 'copy'...
inside copy
[gulp] Finished 'copy' in 1.06 ms
The watcher and the copy are executed, but it's wrong here
Plugins are things that "plug" into the gulp.src
stream, so they should accept a stream of files and do something with them.
Tasks are the actually tasks defined by gulp.task
. I created a simple gulp-task gist. Since gulp is a singleton, tasks can be queued in any module, as long as gulp is a peerDependency.
I propose there is a distinction made between the 2 in the readme, and possibly add guidelines for tasks.
I have the following gulp js code using the gulp-coffee plugin:
gulp.src('./**/*.coffee')
.pipe(coffee({bare: true}))
.on('error', gutil.log)
.on('error', gutil.beep)
.pipe(gulp.dest(destDir));
Whenever gulp-coffee throws an error (e.g. invalid coffee syntax), it stops the rest of valid coffee files from 'piping' through; even though the error is caught.
To clarify this, here is a sample file queued via gulp.src
:
A.coffee (processed)
B.coffee (error and stops the rest of the stream)
C.coffee (not processed)
Is there a way to 'continue' the stream?
Give ideas for plugins. If there is a grunt plugin include the link.
I will try to get to as many as possible. I will also possibly put a bounty on it for somebody else to do it (or you can just do it anyways)
Streams are great to deal with large(ish) files and/or when you need to handle too much concurrency (cause memory), but it increases complexity (easier to explain callbacks than streams).
For what I know, most node.js libs are currently built around plain callbacks (fn(data, callback)
) and doesn't benefit from Streams (whole data
needs to be in memory before processing it).
That got me thinking if writing and encouraging "plugins" is really the best way to go (which I don't think it is). For me it seems more useful to have a helper method that works as an adapter for existing tools than to force everyone to rewrite them as a plugin.
Thinking something like:
// these are regular methods not really meant to be used with Streams, so gulp
// can convert it into a format that works well (no need for custom plugins)
var prependLicense = require('./prepend-license');
var appendToFileName = require('./append-file-name');
gulp.src('src/*.js')
// `mapFileContent` converts a regular async method into a Stream it passes
// the second argument to `prependLicense` method (can be any type)
.pipe( gulp.mapFileContent(prependLicense, {type: 'mit'}) )
// converts regular method into a gulp file path stream mapper passes "_foo"
// as second arg to `appendToFileName`
.pipe( gulp.mapFilePathSync(appendToFileName, '_foo') )
.pipe( gulp.dest('dist') );
and modules would be just something like:
// append-file-name.js
module.exports = function appendToFileName(path, str, cb){
return path.replace(/(\.[^\.]+)$/, str + '$1');
};
and:
// prepend-license.js
module.exports = function prependLicense(fileContents, opts, cb){
fs.readFile('./licenses/'+ opts.type +'.txt', function(err, data){
if (err) return cb(err);
cb(null, prepend(fileContents, data));
});
};
function prepend(src, newData) {
if (isBuffer(src)) {
return new Buffer(newData + String(src));
}
return newData + src;
}
needs sync
and async
versions of these methods.
this is somewhat related to #28
When I use gulp.src
with an array of globs, like so
var gulp = require('gulp')
gulp.task('default', function() {
gulp.src(['*.js', 'js/**.js'])
})
I get the error Invalid or missing glob string
I tried debugging this myself, but I could not find where the error was coming from.
If you use a specific file name instead of a glob for gulp.src, it will break gulp.dest. I think this is because file.shortened and file.base are different. That causes problems in createOutputStream.js.
Example:
If you use the glob *.js:
gulp.src("*.js")
.pipe(gulp.dest("./output"));
The piped file looks like this:
{ shortened: 'test.js',
base: '.',
path: 'test.js',
contents: <Buffer 54 45 53 54 0a 54 45 53 54 0a 54 45 53 54 0a 54 45 53 54> }
But if you use the exact file name:
gulp.src("test.js")
.pipe(gulp.dest("./output"));
The piped file looks like this:
{shortened: '',
base: 'test.js',
path: 'test.js',
contents: <Buffer 54 45 53 54 0a 54 45 53 54 0a 54 45 53 54 0a 54 45 53 54> }
Hey all! I really miss autocompletion in this tools (trying to switch from makefile). Is there a way to add one to it?
Not everything needs the contents of the files. For example: gulp.src('/dist').pipe(gulp_rimraf())
. As a user I'd like to specify when file contents are loaded so the process runs faster.
Would it be possible to specify a different output file than the source file? For example, my project requires specifying a main.css
file, along with a minified version, main.min.css
.
gulp.task('minifycss', function() {
gulp.src('./dist/assets/css/main.css')
.pipe(minifycss())
.pipe(gulp.dest('./dist/assets/css/main.min.css'));
});
Obviously the above doesn't work โ it just creates a folder called main.min.css
then puts the output file inside, but something like the above would be great.
Cheers,
Mark
One strange thing when beginning with Gulp is to have to manage buffers AND streams. Indeed, what is a stream if it is not a succession of buffers ?
If my library support streams, why would i care of buffers ? It should be as simple as doing this:
module.exports = function(headerText) {
return es.map(function(file, cb) {
file.contents = file.pipe(myPluginTransform(headerText);
cb(null, file);
});
};
function myPluginTransform(headerText) {
var stream = new Stream.Transform();
stream.write(headerText)
return stream;
}
If my library support buffers, why would i care of streams ?
module.exports = function(headerText) {
return es.map(function(file, cb){
file.getContentsAsBuffer(function(err, buf) {
file.contents = Buffer.concat(Buffer(headerText), buf);
cb(null, file);
}
});
};
I've created a branch on gulp and vinyl repos. The deal is to keep in the File object a track of the buffer option set in the gulp.src method https://github.com/nfroidure/gulp/blob/master/lib/createInputStream/index.js#L15
Then, in the vinyl/File instances, managing conversions between buffers/streams in order to avoid the plugin maker to worry about that https://github.com/nfroidure/vinyl/blob/stream-buffer-help/index.js#L129
I've got a working branch of my gulp plugin using this code, it works. https://github.com/nfroidure/gulp-svgiconstosvgfont/tree/stream-buffer-abstract
Unfortunately, the original File object API is not made to manage its contents asynchronously. So, this is a big hack, but i think it could be interesting for future versions to review the File objects to get them working that way.
I think the only condition is to provide read/write access to contents asynchronously. Your input is welcome.
Running gulp as an npm script causes gulp process not to exit.
In package.json
{
"scripts": {
"static": "gulp"
}
}
and running npm run-script static
causes process to hang.
I have a file named Gulpfile.js
in my project, but getGulpFile
is returning gulpfile.js
Should work like this
gulp.src("./css/**/*.css", {ignore:"./css/vendor/*.css"})
or
gulp.src("./css/**/*.css", {ignore:["./css/vendor/*.css","./css/dev/*.css"]})
My module uses ES6/Harmony features and as such I need to run node like this:
node --harmony <app.js>
(There's no way of enabling Harmony features at runtime - see this).
So to get gulp working I'm doing this:
node --harmony `which gulp`
Not nice, but it works. Unfortunately even if the build fails the exit code for the run is 0. Is there any way of getting this working?
https://travis-ci.org/wearefractal/gulp/builds/13820036
@robrich this sprang up recently. Maybe something to do with orchestrator?
I have the following in my gulp file...
gulp.task('watch', ['build'], function () {
gulp.watch('./**/*.less', function (event) {
gulp.run('less');
});
});
gulp less
from a command line works
When I edit any of the less files, it doesn't work.
I am trying to port a plugin for gulp and i need some help with how globing patterns are handled.
More specifically i'd like to know how we are expected to handle a case where we need access to the raw arguments of the gulp.src()
method. Consider this case:
gulp.src(['foo/', 'bar/'])
.pipe(customPlugin());
This will cause the customPlugin
function to execute twice, having as a file
argument the first and second parts of the src
Array. If i expect to have the function execute once with the raw value of ['foo/', 'bar/']
what should i do? Move the src
value to an option / argument when invoking the customPlugin(['foo/', 'bar/'])
?
It's a little scary that it won't.
The resulting stream only emits data for the first stream. That is, file2.txt is never emitted.
Test case here: https://github.com/lazd/gulp/blob/globarr/test/src.js#L31-L51
I've filed an issue against glob-stream: gulpjs/glob-stream#5
Right now control flow is somewhat of a mess. All tasks are streams and asynchronous. If you want to run multiple tasks after another you have to do something like this:
var first = gulp.src("stuff").pipe(stuff()).pipe(gulp.dest("stuff"));
first.once('end', function(){
// do the second thing
// and so on
});
/cc @robrich @phated @terinjokes @ccowan @tracker1
Some ideas I've had:
gulp.run(task)
will return the stream from the task so you can gulp.run(task).once('end', fn)
. This makes things a little easier but doesn't solve the problem entirelygulp.run(task, cb)
and you could use it with standard async libsThoughts?
Should work like this
gulp.src("./css/**/*.css")
or
gulp.src(["./css/vendor/*.css", "./css/app/*.css"])
Have you thought about creating a github organization for gulp?
Could be a good place to centralize and maintain gulp plugins that are all up to date. (ie. gulp/gulp-less)
Thanks for gulp btw - it is great. Grunt makes me sad. I was planning starting something similar and then I found gulp, so thanks!
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.