wessberg / cjstoesm Goto Github PK
View Code? Open in Web Editor NEWA tool that can transform CommonJS to ESM
License: MIT License
A tool that can transform CommonJS to ESM
License: MIT License
Input:
module.exports = {
parse: require('./lib/parse'),
stringify: require('./lib/stringify')
};
Output:
export const parse = require('./lib/parse');
export const stringify = require('./lib/stringify');
export default {
parse,
stringify
};
The following file content throws TypeError: Cannot read property 'text' of undefined at transformSourceFile ([redacted]\node_modules\cjstoesm\dist\cli\index.js:3019:61)
function myFunction() {
console.log( 'lorem ipsum' );
}
module.exports = {
myFunction
};
cjstoesm creates invalid variable names beginning with numbers
// input
'use strict'
var low = require('./lib/core.js')
module.exports = low
low.registerLanguage('1c', require('highlight.js/lib/languages/1c'))
low.registerLanguage('abnf', require('highlight.js/lib/languages/abnf'))
// output
import * as low from "./lib/core.js";
import 1c from "highlight.js/lib/languages/1c";
import abnf from "highlight.js/lib/languages/abnf";
'use strict';
low.registerLanguage('1c', 1c);
low.registerLanguage('abnf', abnf);
export default low;
// output
import * as low from "./lib/core.js";
import _1c from "highlight.js/lib/languages/1c"; // use underscore for valid var name
import abnf from "highlight.js/lib/languages/abnf";
'use strict';
low.registerLanguage('1c', _1c);
low.registerLanguage('abnf', abnf);
export default low;
Tried to run it according to the docs, but got a failure for typescript:
npx -p typescript cjstoesm "server/util/**/*.*" server/util/esm/
npx: installed 1 in 1.844s
internal/modules/cjs/loader.js:883
throw err;
^
Error: Cannot find module 'typescript'
Require stack:
- /home/userA/code/proj/node_modules/cjstoesm/dist/cli/index.js
- /home/userA/code/proj/node_modules/cjstoesm/bin/cjstoesm
Hi there!
I am looking for a way to programmatically convert CJS to ESM for my new framework.
I like your package, but it definitely seems to have some bugs.
I am wondering what the status of this is - are you trying to achieve 100% correct performance? I am also not sure if there is something else out there that is doing this completely already? Could potentially support this project if this seems like to way to go for cjs to esm.
Let me know what's happening, cheers : )
Why you not explain how to use it from CLI?
We need a tool to convert all repo with CJS to ESM.
I'm using this script, which I adapted from the README:
const {transform} = require('cjstoesm');
async function main() {
const input = require.resolve('./fixtures');
console.log('Running on', input);
const result = await transform({
input
});
console.log(result);
}
main();
The output is:
$ node tools/codemod/cjs-to-esm/codemod.js
Running on /Users/nheiner/code/tvui/tools/codemod/cjs-to-esm/fixtures/index.js
{ files: [] }
When rewriting CJS require statements with .json extensions, include import assertions in the ESM output and add an option for customizing this behavior, such as potentially opting out of it.
Continuing this conversation here...
Great! You know, if you keep helping me enough I will at eventually hit an error in the software you wrote :-). I think I have. With the above config and v0.0.17
I now have the following error:
(!) Error when using sourcemap for reporting an error: Can't resolve original location of error.
node_modules/lru_map/lru.js: (1:9)
... (irrelevant)
[!] Error: Export 'LRUMap' is not defined
node_modules/lru_map/lru.js (1:9)
1: /**
^
2: * A doubly linked list-based Least Recently Used (LRU) cache. Will keep most
3: * recently used items while discarding least recently used items when its limit
Error: Export 'LRUMap' is not defined
at error (/Users/martien/Sync/Projects/alfred-workflow-todoist/node_modules/rollup/dist/shared/node-entry.js:5400:30)
at Module.error (/Users/martien/Sync/Projects/alfred-workflow-todoist/node_modules/rollup/dist/shared/node-entry.js:9820:16)
at tryParse (/Users/martien/Sync/Projects/alfred-workflow-todoist/node_modules/rollup/dist/shared/node-entry.js:9713:23)
at Module.setSource (/Users/martien/Sync/Projects/alfred-workflow-todoist/node_modules/rollup/dist/shared/node-entry.js:10076:33)
at /Users/martien/Sync/Projects/alfred-workflow-todoist/node_modules/rollup/dist/shared/node-entry.js:12362:20
at async Promise.all (index 2)
at async Promise.all (index 4)
at async Promise.all (index 2)
at async Promise.all (index 3)
at async Promise.all (index 0)
LRU map has a weird looking UMD factory, but I'm no expert. Is this something this library could/should fix?
Sometimes comments are lost. Make sure they are preserved by leveraging @wessberg/ts-clone-node
.
const { ModuleKind, transpileModule } = require('typescript');
const { cjsToEsm } = require('@wessberg/cjs-to-esm-transformer');
const result = transpileModule(
`
export const SomeLib = require('lib-2');
export const SomeLibVar = require('lib-2').someVar;
`,
{
transformers: cjsToEsm(),
compilerOptions: {
module: ModuleKind.ESNext,
target: ModuleKind.ESNext
}
}
);
console.log(result.outputText);
import SomeLib from "lib-2";
export const SomeLibVar = SomeLib.someVar;
import SomeLib from "lib-2";
export { SomeLib };
export const SomeLibVar = SomeLib.someVar;
I just installed your package: npm i cjstoesm -g
then run cjstoesm
in the console and got this error:
Error: Cannot find module 'typescript'
Require stack:
- /usr/local/lib/node_modules/cjstoesm/dist/cli/index.js
- /usr/local/lib/node_modules/cjstoesm/bin/cjstoesm
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
at Function.Module._load (internal/modules/cjs/loader.js:725:27)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
at Object.<anonymous> (/usr/local/lib/node_modules/cjstoesm/dist/cli/index.js:6:16)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Module.require (internal/modules/cjs/loader.js:952:19) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/usr/local/lib/node_modules/cjstoesm/dist/cli/index.js',
'/usr/local/lib/node_modules/cjstoesm/bin/cjstoesm'
]
}
Hi!
Thanks for providing with what seem to be a great tool!
I have been trying to use your Typescript transformer, but without success. It seems like the NPM package doesn't export it.
My code:
import {cjsToEsmTransformerFactory} from 'cjstoesm';
export default class TypescriptTranspiler {
public transpileModule(
code: string,
filepath: string,
): string {
const results = TypeScript.transpileModule(code, {
compilerOptions: COMPILER_OPTIONS,
fileName: filepath,
transformers: {
before: [cjsToEsmTransformerFactory()]
}
});
return results.outputText.toString();
}
}
Code in cjstoesm/dist/lib/esm/index.js:
import 'typescript';
import 'resolve';
import 'path';
import 'slash';
import '@wessberg/stringutil';
import 'reserved-words';
import 'fs';
import 'util';
import 'glob';
import 'chalk';
//# sourceMappingURL=index.js.map
The exports seems to be missing and I can't find the code for "cjsToEsmTransformerFactory" in the package.
Hi @wessberg, thank you for work on this library.
I want to ask you if it's any chance to add an option for specific exports module resolution.
I have a module that is exporting an object, like this:
const obj = {
foo () {
return 2 + 2
},
bar: 3,
baz: new RegExp('')
}
module.exports = obj
And in this particular case the resolution needs to be:
export function foo() {
return 2 + 2;
}
export const bar = 3;
export const baz = new RegExp("");
export default {foo, bar, baz};
but it's only export into:
const obj = {
foo () {
return 2 + 2
},
bar: 3,
baz: new RegExp('')
}
export default obj;
I have worked in a few large codebases, where due to difficulties with circular requires, the requires eventually were simply all added at the bottom of the file (unless used at top-level in the module, such as _.once
). It would be very helpful if there were an option to move all requires at the bottom of the file, to imports at the top. It doesn't need to try and position them correctly alongside other imports, comments, etc, but simply move all contiguous imports at the bottom of the file, to the top (possibly after existing block comments and requires/imports).
Example: cjstoesm --move-to-top ...
Before:
/**
* file block comment
**/
const _ = require('lodash')
module.exports = { ... }
const a = require('some-npm-package')
const b = require('some-local-package/a')
const c = require('./some-local-lib/c')
const d = require('./some-local-lib/d')
After:
/**
* file block comment
**/
import _ from 'lodash'
import a from 'some-npm-package'
import b from 'some-local-package/a'
import c from './some-local-lib/c'
import d from './some-local-lib/d'
export default { ... }
cjstoesm doesn't seem to work with TypeScript 5. Since TypeScript is a peer dependency, I don't think there is a way to provide cjstoesm with the right version, if a newer TypeScript is installed in the parent project. This workaround: #33 (comment) only works if it is not installed.
cjstoesm should work with projects that are using TypeScript 5.
C:\work\test\node_modules\typescript\lib\typescript.js:111514
Debug.fail(`Unhandled SyntaxKind: ${Debug.formatSyntaxKind(node.kind)}.`);
^
Error: Debug Failure. Unhandled SyntaxKind: Unknown.
at pipelineEmitWithHintWorker (C:\work\test\node_modules\typescript\lib\typescript.js:111514:13)
at pipelineEmitWithHint (C:\work\test\node_modules\typescript\lib\typescript.js:111058:9)
at pipelineEmitWithComments (C:\work\test\node_modules\typescript\lib\typescript.js:114842:7)
at pipelineEmit (C:\work\test\node_modules\typescript\lib\typescript.js:111007:7)
at emitExpression (C:\work\test\node_modules\typescript\lib\typescript.js:110991:7)
at emitExportAssignment (C:\work\test\node_modules\typescript\lib\typescript.js:113087:7)
at pipelineEmitWithHintWorker (C:\work\test\node_modules\typescript\lib\typescript.js:111270:20)
at pipelineEmitWithHint (C:\work\test\node_modules\typescript\lib\typescript.js:111058:9)
at pipelineEmitWithComments (C:\work\test\node_modules\typescript\lib\typescript.js:114842:7)
at pipelineEmit (C:\work\test\node_modules\typescript\lib\typescript.js:111007:7)
I've correctly installed cjstoesm with npm install cjstoesm
but every time I run cjstoesm
I got the error:
cjstoesm : Termine 'cjstoesm' non riconosciuto come nome di cmdlet, funzione, programma eseguibile o file script. Controllare l'ortografia del nome o verificare che il percorso sia incluso
e corretto, quindi riprovare.
In riga:1 car:1
+ cjstoesm --help
+ ~~~~~~~~
+ CategoryInfo : ObjectNotFound: (cjstoesm:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
what am I doing wrong?
I'm trying to follow the README instructions, and I get an error:
$ yarn cjstoesm -p tools/codemod/cjs-to-esm/fixtures/index.js dist
yarn run v1.22.10
$ /Users/nheiner/code/tvui/node_modules/.bin/cjstoesm -p tools/codemod/cjs-to-esm/fixtures/index.js dist
error: missing required argument 'outDir'
error Command failed with exit code 1.
First at all, thanks for thus transformer, it works in 99% scenarios.
But still there are some scenarios where it's not working.
For example
module.exports = {
'font-face': require('./font-face'),
};
will transform into the:
export const font-face = require('./font-face');
export default {
font-face,
};
Check font-face transform - assigned to the new const value but in incorrect syntax: "font-face"
export default
statement?While trying to transform the following file using the CLI command:
https://github.com/marijnh/orderedmap/blob/master/index.js
I get the following error:
$ yarn run cjstoesm transform index.js dist
yarn run v1.19.1
$ /home/X/Projects/prosemirror-esm/orderedmap/node_modules/.bin/cjstoesm transform src/index.js test
(node:20706) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'kind' of undefined
at Object.isExpressionNode (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/typescript/lib/typescript.js:11368:33)
at isExpression (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/@wessberg/cjs-to-esm-transformer/dist/cli/transform-task-29d3bc0d.js:1743:15)
at visitBinaryExpression (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/@wessberg/cjs-to-esm-transformer/dist/cli/transform-task-29d3bc0d.js:1898:97)
at visitNode (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/@wessberg/cjs-to-esm-transformer/dist/cli/transform-task-29d3bc0d.js:2117:16)
at ts.visitEachChild.cbNode (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/@wessberg/cjs-to-esm-transformer/dist/cli/transform-task-29d3bc0d.js:2388:37)
at visitNode (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/typescript/lib/typescript.js:70904:23)
at Object.visitEachChild (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/typescript/lib/typescript.js:71187:59)
at Object.childContinuation (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/@wessberg/cjs-to-esm-transformer/dist/cli/transform-task-29d3bc0d.js:2387:23)
at visitNode (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/@wessberg/cjs-to-esm-transformer/dist/cli/transform-task-29d3bc0d.js:2122:20)
at ts.visitEachChild.cbNode (/home/X/Projects/prosemirror-esm/orderedmap/node_modules/@wessberg/cjs-to-esm-transformer/dist/cli/transform-task-29d3bc0d.js:2388:37)
(node:20706) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:20706) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
hello,
Is it possible ? because it shrinks my code so much its hard to read the output.
i will be forced to create a shitty regexp replacer.
please.
I am building a bundle-less bundler using your wonderful project (thank you!), I have run into an issue with a case that looks like this:
const constants = exports.constants = require('./constants.js')
TypeError: Cannot read property 'kind' of undefined
at Object.isExpressionNode (/Users/me/Code/typescript/unpack/node_modules/typescript/lib/typescript.js:14615:33)
at isExpression (/Users/me/Code/typescript/unpack/node_modules/@wessberg/cjs-to-esm-transformer/src/transformer/util/is-expression.ts:8:81)
at visitBinaryExpression (/Users/me/Code/typescript/unpack/node_modules/@wessberg/cjs-to-esm-transformer/src/transformer/before/visitor/visit/visit-binary-expression.ts:295:76)
at visitNode (/Users/me/Code/typescript/unpack/node_modules/@wessberg/cjs-to-esm-transformer/src/transformer/before/visitor/visit/visit-node.ts:24:10)
at /Users/me/Code/typescript/unpack/node_modules/@wessberg/cjs-to-esm-transformer/src/transformer/before/transform-source-file.ts:212:26
at visitNode (/Users/me/Code/typescript/unpack/node_modules/typescript/lib/typescript.js:74775:23)
at Object.visitEachChild (/Users/me/Code/typescript/unpack/node_modules/typescript/lib/typescript.js:75140:224)
at childContinuation (/Users/me/Code/typescript/unpack/node_modules/@wessberg/cjs-to-esm-transformer/src/transformer/before/transform-source-file.ts:209:15)
at visitVariableDeclaration (/Users/me/Code/typescript/unpack/node_modules/@wessberg/cjs-to-esm-transformer/src/transformer/before/visitor/visit/visit-variable-declaration.ts:29:10)
at visitNode (/Users/me/Code/typescript/unpack/node_modules/@wessberg/cjs-to-esm-transformer/src/transformer/before/visitor/visit/visit-node.ts:22:10)
Id probably want to see an output fixed up like this:
export constants from './constants.js';
or even
import constants from './constants.js';
export constants;
What do you think, hope you are still active.
Does this tool handle replacement of old require/import syntax with the new one that requires file extensions?
I noticed that a every extra new-line (that we have for white-space as readability) in files was removed by the tool. Other than that it worked flawlessly!
This makes it impossible to use the tool, as line-breaks as white-space is important e.g. between functions so it does not become a big blob of text.
cjstoesm src/**/. src creates another src directory in src src/src
doing ejstoesm **/*.* .
in /src
directory does not work
or please add an option to copy other files such as .yml
, .json
files in the directory as well. I think I have to manually move those non js files for now
I was using this module to try to solve a pesky Error: 'default' is not exported by node_modules\<xyz>
problem. But it didn't go as planned, so in my desperation reaching here to double-check if this is a problem that in principle is what this module should solve. ๐ข
As it may be that I do not understand correctly that if this module indeed would solve, at least in some cases, such problems. It looks to be these are because of UMD -> ES6 export changes, but I may be wrong. The other things are that I think I should also use @rollup/plugin-node-resolve
to resolve paths. Is this right?
I have defined
import resolve from '@rollup/plugin-node-resolve';
import ts from "@wessberg/rollup-plugin-ts";
import {cjsToEsm} from "cjstoesm";
[...]
plugins: [
resolve({ browser: true, preferBuiltins: true }),
ts({ transformers: [cjsToEsm()] })
]
Another thing is, does this plugin pick up also the dependencies that are referenced by the libraries imported by the code?
(That config is at https://github.com/veikkoeeva/erc1155sample/blob/main/web/rollup.config.js#L27 if it matters, and strangely there is a difference in output if I move it from baseConfig to the merge section, though it's not related to this module).
can not transform: 'cc.ParticleAsset = module.exports = ParticleAsset;' to esm
In a npm project I'm trying to transform a library in node_modules from the CLI.
When I execute a command like this: cjstoesm node_modules/@something/some_library_name/dist/index.js target
the transformed output files are stored in target/node_modules/@something/some_library_name/dist
where I would expect to have the transformed files directly in target
.
The CLI is replicating the whole folder structure in the target dir.
This makes it a bit complicated to use the command from a top level directory.
I think this behaviour would be fine if I would run the command with a nonspecific glob like cjstoesm **/*.js target
because in this case of cause the tool would run into conflicting files.
Wouldn't it be better to start replicating the folder structure only at the point were the glob has it's wildcards, for example cjstoesm node_modules/@something/**/*.js
should replicate the folders below @something/
?
I tied to run the command using npx
but I get the following error:
โฏ npx -p typescript -p cjstoesm cjstoesm ./src/lib
Need to install the following packages:
[email protected]
[email protected]
Ok to proceed? (y)
/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:110792
Debug.fail(`Unhandled SyntaxKind: ${Debug.formatSyntaxKind(node.kind)}.`);
^
Error: Debug Failure. Unhandled SyntaxKind: ImportClause.
at pipelineEmitWithHintWorker (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:110792:13)
at pipelineEmitWithHint (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:110333:9)
at pipelineEmitWithComments (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:114112:7)
at pipelineEmit (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:110282:7)
at emitExpression (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:110266:7)
at emitImportDeclaration (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:112325:7)
at pipelineEmitWithHintWorker (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:110533:20)
at pipelineEmitWithHint (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:110333:9)
at pipelineEmitWithComments (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:114112:7)
at pipelineEmit (/home/ user/.npm/_npx/6ca627352432bfda/node_modules/typescript/lib/typescript.js:110282:7)
Seems like TypeScript is broken somehow but I don't understand why this happens. Any clues?
I've been trying to test out this program on one of my projects, but somehow I've been unable to succeed. I think I may be using it wrong but from the documentation I'm not entirely sure how this is happening.
My project uses Yarn workspaces, with the following structure:
package.json
packages\
packages\callisto-cli
packages\callisto-core
...
Each package has its own package.json.
My first intuition was to run cjstoesm packages/**/*.*
since that's what the first example shows. That somehow causes it to attempt to create a directory named after the first file, which crashes:
$ cjstoesm packages/**/*.*
node:fs:1385
handleErrorFromBinding(ctx);
^
Error: EEXIST: file already exists, mkdir '/Users/msikma/Projects/callisto-test/packages/callisto-cli/package.json'
at Object.mkdirSync (node:fs:1385:3)
at Object.writeFile (file:///usr/local/lib/node_modules/cjstoesm/dist/cli/index.js:3348:24)
at Object.writeFile (/usr/local/lib/node_modules/cjstoesm/node_modules/typescript/lib/typescript.js:18750:14)
at printSourceFileOrBundle (/usr/local/lib/node_modules/cjstoesm/node_modules/typescript/lib/typescript.js:111960:16)
at emitJsFileOrBundle (/usr/local/lib/node_modules/cjstoesm/node_modules/typescript/lib/typescript.js:111836:13)
at emitSourceFileOrBundle (/usr/local/lib/node_modules/cjstoesm/node_modules/typescript/lib/typescript.js:111757:13)
at forEachEmittedFile (/usr/local/lib/node_modules/cjstoesm/node_modules/typescript/lib/typescript.js:111498:34)
at Object.emitFiles (/usr/local/lib/node_modules/cjstoesm/node_modules/typescript/lib/typescript.js:111738:9)
at emitWorker (/usr/local/lib/node_modules/cjstoesm/node_modules/typescript/lib/typescript.js:119072:33)
at /usr/local/lib/node_modules/cjstoesm/node_modules/typescript/lib/typescript.js:119049:72 {
errno: -17,
syscall: 'mkdir',
code: 'EEXIST',
path: '/Users/msikma/Projects/callisto-test/packages/callisto-cli/package.json'
}
Node.js v18.3.0
Then I saw that in the animated example, the glob is encased in quotes, which means it passes on the glob literally instead of expanding it first, so I tried that:
cjstoesm "packages/**/*.*"
โ packages/callisto-cli/index.js
This worked on one package (although it killed all the empty lines in it and removed the copyright notice at the top for some reason, but that's a different issue), but somehow it failed to work on the callisto-core
package. It just didn't detect it somehow. Same if I use packages/**
.
I decided to try using the output directory option, so I ran cjstoesm "packages/**/*.*" "packages_new"
. Again this only worked for the callisto-cli
package (which has only one index.js file) and not for the callisto-core
package. It also did not replicate the package directory structure.
Is there some way I'm doing it wrong? What would be the appropriate invocation for my situation? Also, is there a way to prevent the converter from removing additional whitespace in my files? (Here's the old and new.) I appreciate any help!
The currently provided transform
method takes a path to a file (or an array of paths) and optionally writes the transformed file(s) to the file system.
It would be nice to provide another method which takes a source code string and returns a transformed source code string. For example:
import {transform} from 'cjstoesm'
const input = `
const {foo: bar} = require("./my-module")
module.exports = {baz: 3}
`
await transform({ input })
//=> 'import {foo as bar} from "./my-module.js"\nexport const baz = 3'
(The method name could be different.)
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.