Giter VIP home page Giter VIP logo

grunt-string-replace's Introduction

grunt-string-replace Build Status

Replaces strings on files by using string or regex patterns. Attempts to be a String.prototype.replace adapter task for your grunt project.

Getting Started

This plugin requires node >= 0.10.0, Grunt >= 0.4.0 and npm >= 1.4.15 (latest stable is recommended).

If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a Gruntfile as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:

npm install grunt-string-replace --save-dev

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:

grunt.loadNpmTasks("grunt-string-replace");

If you're still using grunt v0.3.x it's strongly recommended that you upgrade, but in case you can't please use v0.1.1-1.

Configuration

Inside your Gruntfile.js file add a section named string-replace. This section specifies the files to edit, destinations, patterns and replacements.

Parameters

files object

Defines what files this task will edit. Grunt itself has very powerful abstractions, so it is highly recommended you understand the different ways to specify them. Learn more at Gruntfile Files mapping, some options incude compact format, files object format and files array format.

options object

Controls how this task operates and should contain key:value pairs, see options below.

options.saveUnchanged boolean

By default true this flag will instruct grunt-string-replace to copy the files on options.replacements patterns even if there are no replacing matches.

By setting this flag to false files that have not changed (no replacements done) will not be saved on the new location. This will speed up the task if there is a large number of files.

options.replacements array

This option will hold all your pattern/replacement pairs. A pattern/replacement pair should contain key:value pairs containing:

  • pattern string or regex
  • replacement string
options: {
  replacements: [
    {
      pattern: /\/(asdf|qwer)\//gi,
      replacement: '"$1"',
    },
    {
      pattern: ",",
      replacement: ";",
    },
  ];
}

Notes

  • If the pattern is a string, only the first occurrence will be replaced, as stated on String.prototype.replace.
  • When using Grunt templates, be aware that some security checks are implemented by LoDash and may alter your content (mainly to avoid XSS). To avoid this, see the advanced example below.

Examples

Multiple files and multiple replacements

'string-replace': {
  dist: {
    files: {
      'dest/': 'src/**',
      'prod/': ['src/*.js', 'src/*.css'],
    },
    options: {
      replacements: [{
        pattern: /\/(asdf|qwer)\//ig,
        replacement: ''$1''
      }, {
        pattern: ',',
        replacement: ';'
      }]
    }
  }
}

Simple inline content

'string-replace': {
  inline: {
    files: {
      'dest/': 'src/**',
    },
    options: {
      replacements: [
        // place files inline example
        {
          pattern: '<script src='js/async.min.js'></script>',
          replacement: '<script><%= grunt.file.read('path/to/source/js/async.min.js') %></script>'
        }
      ]
    }
  }
}

Using files' expand options

For more details, see Grunt's documentation about dynamic files object.

'string-replace': {
  dist: {
    files: [{
      expand: true,
      cwd: 'src/',
      src: '**/*',
      dest: 'dist/'
    }],
    options: {
      replacements: [{
        pattern: 'hello',
        replacement: 'howdy'
      }]
    }
  }
}

Advanced inline

Since grunt-string-replace is basically a wrapper of String.prototype.replace you can also provide a function as a replacement pattern instead of a string or a template; as a nice added bonus to using a replacement function, grunt-string-replace will provide 2 extra arguments apart from the ones documented in the link below: src and dest. To get more details about how to use a function as replacement pattern I recommend you to read Specifying a function as a parameter.

We will be reading file names from HTML comments and use the paths later to fetch the content and insert it inside a resulting HTML. Assuming the following setup:

src/index.html

<!-- @import partials/header.html -->
content here
<!-- @import partials/footer.html -->

src/partials/header.html

<html>
  <head></head>
  <body></body>
</html>

src/partials/footer.html

</body></html>

Gruntfile.js

'use strict';

module.exports = function (grunt) {
  // Project configuration.
  grunt.initConfig({
    config: {
      src: 'src/*.html'
      dist: 'dist/'
    },
    'string-replace': {
      dist: {
        files: {
          '<%= config.dist %>': '<%= config.src %>'
        },
        options: {
          replacements: [{
            pattern: /<!-- @import (.*?) -->/ig,
            replacement: function (match, p1) {
              return grunt.file.read(grunt.config.get('config.dist') + p1);
            }
          }]
        }
      }
    }
  });

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-string-replace');

  // Default task.
  grunt.registerTask('default', ['string-replace']);
};

After executing grunt we get the following:

dist/index.html

<html>
  <head></head>
  <body>
    content here
  </body>
</html>

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using grunt.

Release History

1.3.3

  • Sync docs, travis settings and code with npm (made a mess between GitHub and npm on 1.3.2).

1.3.2

  • Updated several dependencies. Some updates require node >= 8. If you need node < 8 stay on 1.3.1. Thanks to anand-gopinath for flagging some of them.

1.3.1

  • Misc updates.

1.3.0

  • Fix #39, a typo in the documentation
  • Inject src and dest into the callback function when replacement is a function; this allows the replacement function to use the old and/or new file paths/names for further processing
  • Add total files modified and update file created logging to verbose. Contributed by tHBp

1.2.1

  • Update project URLs
  • Update dependencies

1.2.0

  • Add saveUnchanged option to control weather unmodified files are saved or not.
  • Add iojs to Travis CI.

1.1.1

  • Add Node.js v0.12 to Travis CI

1.1.0

  • Update dependencies
  • Add new log and debug messages
  • Improved file handling; grunt-string-replace will not copy files that are not modified (no replacements executed). Contributed by iabw

1.0.0

  • Update dependencies
  • Update README.md
  • Well deserved bump to 1.0.0 (its been stable for long enough now)

0.2.8

  • Added log message after file is succesfully created. Contributed by donaldpipowitch
  • Do not report error if one of the replacements resolves to a folder

0.2.7

  • External libraries are deprecated on Grunt 0.4.2

    • Remove grunt.util._ as it is not really required
    • Replace grunt.util.async with async

0.2.6

  • Update Getting Started section
  • Fix broken link to Gruntfile's File section (#18)

0.2.5

  • Fix for #16
  • Fix for Travis CI config file
  • Added error handling to finish the task if something did not work as expected instead of just fail silently
  • Updated dev dependencies to latest stable versions

0.2.4

  • Asynchronously loop files. Original idea contributed by maxnachlinger
  • Inline replacing example on README.md. Contributed by willfarrell

0.2.3

  • Removed dependency with grunt-lib-contrib due to deprecation of 'options' method in favor of Grunt's 'options' util.
  • Updated grunt-contrib-jshint version in package.json to 0.3.0
  • Updated grunt-contrib-watch version in package.json to 0.3.1
  • Updated grunt version in package.json to 0.4.1
  • Added Node.js v0.10 to Travis CI config file

0.2.2

  • Added support to be used as npm module. Contributed by thanpolas.

0.2.1

  • Updated dependencies for Grunt 0.4.0.

0.2.0

  • Added Support for grunt 0.4.0. This version will not support grunt 0.3.x, if you need to use it then npm install [email protected].

0.1.1-1

  • Added Clean task (and dev dependency) to remove test generated file before testing.
  • Added Sublime Text project files and test generated file to npm ignore list.

0.1.1

  • Fix dependency with grunt-lib-contrib.

0.1.0-1

  • Fixed a typo on package.json description.
  • Added a note about string pattern behavior.

0.1.0

  • Initial release.

License

Copyright (c) 2016 Erick Ruiz de Chavez. Licensed under the MIT license.

grunt-string-replace's People

Contributors

deepflame avatar donaldpipowitch avatar eruizdechavez avatar sercaneraslan avatar thanpolas avatar willfarrell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

grunt-string-replace's Issues

.kit regex replace

I'm trying to do a regex replace, but getting Warning: An error occurred while processing a template ($1 is not defined). Use --force to continue.

// .kit compiler
{
    pattern: /<!-- @import (.*?) -->/ig,
    replacement: '<%= grunt.file.read(yeoman.dist+$1) %>'
}

I've tried a few combos, do you know what I'm missing? Is this even possible with the current code?

Causing EPERM error on windows

I've noticed that when string Replace creates directories funny permission errors are created on Windows 8.1.

Running "string-replace:dist" (string-replace task)
Warning: EPERM: operation not permited, scandir 'c:\Users\...\projects\project\src/js'

Regex Negative lookbehind

Javascript doesn't support the regex negative lookbehind and seems there is not an easy work around , and this seems to be esencial ? any ideas on how to implement that in this plugin.

I guess I will need some how grunt call some task of python or php to support the lookbehind

It seems the file counting is cumulative?

image
Each of the tasks matches exactly one file, but the "files created" counter keeps increasing.

The output should have "1 file created" each time (and it does only create one file).

configuration sample:

'string-replace': {
    [moduleName]: {
        files: {
            [baseIntDir + moduleName + '/tsconfig.json']: moduleName + '/tsconfig.json'
        },
        options: {
            replacements: [
                {
                    pattern: /\"\.\./gi,
                    replacement: '"../../..'
                }
            ]
        }
    },
    [moduleName + "-package"]: {
        files: {
            [baseOutDir + moduleName + '/package.json']: moduleName + '/package.json'
        },
        options: {
            replacements: [
                {
                    pattern: /0\.0\.0-PLACEHOLDER/gi,
                    replacement: pkg.version
                }
            ]
        }
    }
}

node version path different

I use this on node 4.x works:

    'string-replace': {
      'remove': {
        files: {
          'public/lib/css/': 'public/lib/css/*.css'
        },
        options: {
          replacements: [
            {
              pattern: /(\@font\-face[^\}]+})/gm,
              replacement: ''
            }
          ]
        }
      }
    },

but did not work properly on 5.x. it will create public/lib/css/public/lib/css/ ... path on folders ... do0uh !!!

this will work on node 5.x

'string-replace': {
  'remove': {
    files: {
      './': 'public/lib/css/*.css'
    },
    options: {
      replacements: [
        {
          pattern: /(\@font\-face[^\}]+})/gm,
          replacement: ''
        }
      ]
    }
  }
},

Doesn't take into account the directories and files created at runtime.

I have a grunt default task which calls multiple tasks, like creating a temporary directory and then in the same default task, I call the string-replace.
For example, grunt.registerTask('default', ['copy','string-replace']);
String replace doesn't throw any errors but doesn't replace anything.
If I call grunt string-replace after the task has ended, then it works as expected.
In short, the string-replace task doesn't work on the copied files from the copy task but after the grunt exits, then if I call grunt string-replace, then it replaces the values.

_.pluck is not a function error on v 1.3.0

I installed version 1.3.0 and getting this error:

Verifying property string-replace.development exists in config...OK
Reading src/index.html...OK
Warning: An error occurred while processing a template (_.pluck is not a function). Use --force to continue

Lodash is on 4.16.1 and what I can see _pluck is removed from lodash

Can you please fix this issue?

String Pattern not really a "pattern"

It seems that the string pattern is only replacing the first occurrence of the matched string, rather than being a true pattern match and replace.

string-replace replacing unmatched characters

'string-replace' logged that it had 'created' all of the files in my specified directory, even though none of the files actually matched my replacement config.

In some of those files, this saving process over-wrote some characters in my files with some other character that's showing up in my text editor as �, despite my config for string-replace specifying a specific string to replace. The replaced characters included smart quotes and a copyright symbol. It is still showing up "correctly" in the browser, so maybe it's just different flavors of unicode or something? I'm not an expert on this topic.

Interestingly, svn revert isn't fixing this character difference, so whatever 'string-replace' did to the smart-quote, svn doesn't seem to know it's different for revert purposes, although it DOES know it's different for saying the file has been modified ( which it shouldn't have been in the first place ).

my config looked like this -

"string-replace": {
        velocity: {
            files: [{
                expand: true,
                cwd: "templates/velocity/",
                src: ['**/*.vm'],
                dest: 'templates/velocity/'
            }],
            options: {
                replacements: [{
                    pattern: "#set($template_version =",
                    replacement: '"#set($templateVersion ="'
                }]
            }
        }
    }

I would think that, ideally, grunt-string-replace would not save a file that it didn't think it was performing a replacement in. I saw it trigger my grunt-watch on my templates/velocity folder, and it seems like it would also not interact properly with grunt-newer.

Output status when task is run

It would be very helpful if this plugin would report something to the console when it runs and does replacement.

Two reasons for this:

  1. All other plugins I've used do this, and it is helpful
  2. For awhile, I thought no output from this plugin meant that it didn't match anything and that my config was not working correctly. Turns out it was fine and I was incorrectly assuming that based on no console output.

Regardless, thanks for providing this solution to my grunt scripts!

Wildcard file source/destinations does not work or not as expected.

In your documentation you have two examples for wildcard file source/destination.

The folder wildcard does not copy the files where I would expect them to.

Here is my config:
'<%= dirs.build %>/rails/less/base/': '<%= dirs.build %>/less/base/*'

However, the files from build/less/base end up in build/rails/less/base/build/less/base instead of where I would expect them to: build/rails/less/base.

The multi-source option does not work at all.
'<%= dirs.build %>/rails/less/': '<%= dirs.build %>/less/**'

In that case I get:
Warning: Unable to read "build/less" file (Error code: EISDIR). Use --force to continue.

New dependencies in PATCH v1.3.2+ caused a break in v6.2.0 of Node

I understand that the new dependency upgrades in 1.3.2+ have pushed out the support for Node v6, etc.

I have a project that is (unfortunately) stuck on v6.2.0 and we use this module. We had our package.json set up with "grunt-string-replace": ^1.3.1 and the new update broke our build. We resolved this by removing the carrot and staying at 1.3.1.

We were expecting this module to conform to semantic versioning thus didn't expect a PATCH version update to cause a break in v6.2.0. In my opinion, your change should have been a major version update in order to not break projects still on old Node versions.

Can you provide more examples and information?

At first, thanks for your great job!

I feel confused when I setting the files directory with the examples, and I setting as follow:

prod: {
    files: {
        './production/html/': '*.html'
    },
    options: {
        replacements: [{
            pattern: '<link rel="stylesheet" href="../style.dev.css" >',
            replacement: '<link rel="stylesheet" href="../style.css" >'
        }]
    }
}

there are no error display, but no file change. So I find the question at stackoverflow and the answer witch selected help me to figure out this problem:

files: {
    './': 'production/html/*.html'
}

But I don't know why. So I hope you can give more examples or informations for people to avoid error.

Thanks again!

better documentation for files

can you better explain what these are?

    files: {
      'path/to/directory/': 'path/to/source/*', // includes files in dir
      'path/to/directory/': 'path/to/source/**', // includes files in dir and subdirs
      'path/to/project-<%= pkg.version %>/': 'path/to/source/**', // variables in destination
      'path/to/directory/': ['path/to/sources/*.js', 'path/to/more/*.js'], // include JS files in two diff dirs
      'path/to/filename.ext': 'path/to/source.ext'
    },

what is destination and what is source?

How can I kown if match failed?

I need to do something when matching failed? but I don't know how to do. whether it will trigger some events, I wish you can help me recently.

Fail when replacement not found

I'm using grunt-string-replace to modify some connection parameters in javascript depending on the deployment endpoint. I'd like grunt to error out if no matches were found because the application will fail if the replacement doesn't happen.

Thanks

Cannot read property 'expand' of undefined

This could be my newbness showing here, but I updated packages after the grunt 0.4 update and now I'm getting this.

Here's an example of the Gruntfile.js...

'string-replace': {
  test: {
    files: {
      'dist/index.html': ['dist/index.html']
    },
    options: {
      replacements: [{
        pattern: /\s*<script src=".*.dev.js"><\/script>/,
        replacement: ''
      },{
        pattern: /src="scripts/g,
        replacement: 'src="/scripts',
      }]
    }
  }
},

I looked through some examples of other Gruntfiles but I'm not seeing a solution to this error. Any ideas?

Issues with node 5.7.0

Hi guys,

I tested in node 5.7.0 and it didn't work properly. It created some directories instead of updating the files. I am going to find a good example to show you. Just a heads up for now.

Name is not defined ?

When I run the following in Grunt with string-replace, I get an error which keeps the rest of my grunt tasks from firing.

dist: {
    files: {
        'dist/www/index.html': 'index.html'
    },
    options: {
        replacements: [
            {
                pattern: '<!-- templates (replaced with grunt) -->',
                replacement: grunt.file.read("dev/js/build/templates.html")
            }
        ]
    }
}

Produces the following error when ran:

Running "string-replace:dev" (string-replace) task
Warning: An error occurred while processing a template (Name is not defined).� Use --force to continue.

Aborted due to warnings.
Process finished with exit code 4

This may be a Grunt issue or me not understanding Grunt and may not fall into this specific plugin, but I don't have this issue with others. The strange part is that it seems to correctly replace that HTML comment with the contents of templates.html... the error just stops the rest of the task from being fired.

Need to replace multiple instances of a pattern.

Hello @erickrdch!

I have a multiple instances (5) of a pattern in a file (app.yaml). When I run the grunt command, it only replaces the first instance of that pattern. Is there anything I am missing in the code?

Here's the code I have.

'string-replace' : {
            dist: {
                options: {
                    replacements: [
                        {
                            pattern: '@appName',
                            replacement: 'helloWorld'
                        }
                    ]
                },
                files: [
                    {
                        expand: true,
                        src: [
                          'app.yaml'
                        ]
                    }
                ]
            }
        }

Error with replace string containing a '>' character

Hi Erick , I ran into a problem with '<' and '>' characters in the replacement string. If the closing tag is not escaped (Ex 1) the task throws an error of:

Warning: An error occurred while processing a template (Unexpected string).

Example 1:

pattern: /:(\s*)url\((img)(.+?)\)/ig, replacement: ':$1url(\<%= asset_path \'$2$3\' %>)'

I tried escaping the last '>' as well, but no luck with this either.

pattern: /:(\s*)url\((img)(.+?)\)/ig, replacement: ':$1url(\<%= asset_path \'$2$3\' %\>)'

There was also one case where the last '%>' would just be ignored, but I can't reproduce it anymore. The only way I got this to work is to run 2 passes:

options: { replacements: [{ pattern: /:(\s*)url\((img)(.+?)\)/ig, replacement: ':$1url(\<%= asset_path \'$2$3\' CLOSE)' }, { pattern: /CLOSE/g, replacement: '%>' }] }

In the usage examples I found this, which might be the explanation why this doesn't work? Reserved characters for config?

files: { '<%= config.dist %>': '<%= config.src %>' }

EISDIR when attempting to replace strings in files in subdirectories

Every time I try to run this task I get the following error:

Running "string-replace:predeploy" (string-replace) task
Warning: Unable to read "temp/assets/compiled" file (Error code: EISDIR). Use --force to continue.

Here's my configuration:

{
...
'string-replace': {
    predeploy: {
        files: {
            'temp/assets/': 'temp/assets/**/*'
        },
        options: {
            replacements: [{
                pattern: /\{\{assets\}\}/ig,
                replacement: S3_URL + deploy_time +'/'
            }]
        }
    }
}
}

Destination Folder Adds Source Directory

When using:

config: {
    dist: 'dist/',
    prod: 'prod/'
}
files: {
      '<%= config.prod %>': '<%= config.dist %>*'
},

The result gives a folder structure of:

dist
--filename.html
prod
--dist
-----filename.html

Is there any way to prevent it from creating the source directory as a subdirectory to the destination folder?

Not working with folders of files

Hi,

I have this working with single files, but not when targeting all files of a type in a directory.

Working:

files: {
    '<%= project.dev.html_prototypes %>/index.html': '<%= project.dev.html_prototypes %>/index.html',
}

Not working:

files: {
      '<%= project.build.styles %>/': '<%= project.build.styles %>/*.css',
}

In the second example, replacement occurs, but the path to the file is duplicated with the file, i.e. /path/to/foo becomes /path/to/foo/path/to/foo:

Reading wp-content/themes/myproject/resources/build/styles/at.css...OK
Writing wp-content/themes/myproject/resources/build/styles/wp-content/themes/myproject/resources/build/styles/at.css...OK

Is there something obvious that I'm missing here (such as a 'flatten' option)?

Thanks,
Dan

Use package version in replacement

I'm trying to replace some references and append the package version at the same time. Is this supported? Using the the following options the references are changed but the version number is ignored.

options: {
          replacements: [{
            pattern     : 'modernizr-dev.js',
            replacement : "modernizr-custom.min.js?<%= pkg.version %>"
          },
          {
            pattern     : 'concat.css',
            replacement : "concat.min.css?<%= pkg.version %>"
          },
          {
            pattern     : 'site.js',
            replacement : "site.min.js?<%= pkg.version %>"
          },
          {
            pattern     : 'plugins.js',
            replacement : "plugins.min.js?<%= pkg.version %>"
          }]
        }

0.4.x support?

Het @erickrdch

Does this plugin work in the 0.4.0 environemnt yet? If not, any plans to move it that way?

Thanks!

Grunt 0.4 Release

I'm posting this issue to let you know that we will be publishing Grunt 0.4 on Monday, February 18th.

If your plugin is not already Grunt 0.4 compatible, would you please consider updating it? For an overview of what's changed, please see our migration guide.

If you'd like to develop against the final version of Grunt before Monday, please specify "grunt": "0.4.0rc8" as a devDependency in your project. After Monday's release, you'll be able to use "grunt": "~0.4.0" to actually publish your plugin. If you depend on any plugins from the grunt-contrib series, please see our list of release candidates for compatible versions. All of these will be updated to final status when Grunt 0.4 is published.

Also, in an effort to reduce duplication of effort and fragmentation in the developer community, could you review the grunt-contrib series of plugins to see if any of your functionality overlaps significantly with them? Grunt-contrib is community maintained with 40+ contributors—we'd love to discuss any additions you'd like to make.

Finally, we're working on a new task format that doesn't depend on Grunt: it's called node-task. Once this is complete, there will be one more conversion, and then we'll never ask you to upgrade your plugins to support our changes again. Until that happens, thanks for bearing with us!

If you have any questions about how to proceed, please respond here, or join us in #grunt on irc.freenode.net.

Thanks, we really appreciate your work!

Access to the current file from the `replacement` function

Can a replacement function access the file-name/file-path of the file that is currently being processed?

E.g.

    replacements: [{
        pattern: /<img src=["']([^"']*?)["']/ig,
        replacement: function(match, p1, offset, wholeString) {
            var newPath = derivePathFrom(CURRENT_SOURCE_FILE);
            return '<img src="' + newPath + '/' + p1 + '"';
        }
    }]

If not, can this be added?

support variables..

Hi.
It seems that 'files' doesn't support variables, ex

files: { path.join(x,y):path.join(z) }

var filepath = something, filepath2 = something2
...

files: {filepath: filepath2}

Would you please consider supporting them? thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.