node-escpos / driver Goto Github PK
View Code? Open in Web Editor NEW🖨️ ESC/POS Printer driver for Node.js.
License: Other
🖨️ ESC/POS Printer driver for Node.js.
License: Other
When passing the vid
and the pid
to USB constructor is printing in the latest connected printer.
你好:想請問如何使用你優化後的escpos?要如何安裝?
Hi! I'm trying to use a thermal printer Dascom DT-230 with the serialport adapter. Now the printer is connected to my PC using usb but the pc detects that as a serial port
In Windows as COM4
In Linux as /dev/ttyACM0
In both cases that return Error: Port is opening
It's the code that I was testing
import { Printer } from "@node-escpos/core";
import Serial from "@node-escpos/serialport-adapter";
const device = new Serial("/dev/ttyACM0", { // In Windows I was put "COM4"
baudRate: 115200,
stopBit: 1,
});
const options = {
encoding: "utf-8",
};
const printer = new Printer(device, options);
device.open((error) => {
if (error) {
console.error(error);
return;
}
let printer = new Printer(device, {});
printer
.font("a")
.align("ct")
.style("bu")
.size(1, 1)
.text("The quick brown fox jumps over the lazy dog");
printer.cut().close();
});
Someone can help me with that? I have been trying different packages to use escpos printers for months and I have not found any that give me results
i wish usb printer device detect printer device paper out. is visible ?
Hello,
I tried to load an image from a base64 data this way:
const buffer = Buffer.from(logo, 'base64')
const uint8Array = new Uint8Array(buffer)
const image = await Image.load(uint8Array)
printer = await printer.image(
image,
's8' // changing with image
)
but I get this error:
TypeError [ERR_INVALID_ARG_VALUE]: The argument 'path' must be a string or Uint8Array without null bytes. Received Uint8Array(6191)
printer.barcode(code : number, type : BarcodeType, options : BarcodeOptions);
to
printer.barcode(code : number | string, type : BarcodeType, options : BarcodeOptions);
The Code 39 specification defines 43 characters, consisting of uppercase letters (A through Z), numeric digits (0 through 9) and a number of special characters (-, ., $, /, +, %.
printer.qrimage("test") don't work and failed with:
UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received an instance of Buffer
Hey , great work !
I was wondring how to change the encoding for Arabic/hebrew language?
Could you please provide me with the right encoding ? I have tried all of them but still not working !
Thermal Model : HS-58HU
Printer commands: Supports ESC/POS
When I print the below code, the row items are not aligned to center with the column
printer.tableCustom(
[
{ text: "Tic tac 5", width: 0.4 },
{ text: "1, align: "CENTER", width: 0.1, style: 'b' },
{ text: "5", align: "CENTER", width: 0.166, style: 'b' },
{ text: "5", align: "CENTER", width: 0.166, style: 'b' },
{ text: "5", align: "CENTER", width: 0.166, style: 'b' }
],
[
{ text: "2 in 1 Agarbatti", width: 0.4 },
{ text: "1, align: "CENTER", width: 0.1, style: 'b' },
{ text: "15", align: "CENTER", width: 0.166, style: 'b' },
{ text: "15", align: "CENTER", width: 0.166, style: 'b' },
{ text: "30", align: "CENTER", width: 0.166, style: 'b' }
]
);
When to expect the first release on npm? I am eagerly waiting for a new release with all the latest PRs from the original repository.
`Hi! I'm getting an error that seemingly came out of nowhere, as it didn't happen during my testing phase, but did happen during my production phase.
When trying to print a receipt using my below code:
`app.post('/create/order', async (req, res) => {
// we're getting an order! let's print it!
console.log("printing order with id: #" + req.body.orderId)
console.log(req.body)
let foodString = "";
let drinksString = "";
let dessertsString = "";
if (req.body.items && Array.isArray(req.body.items) && req.body.items.length > 0) {
const donItems = req.body.items[0].don;
const drinkItems = req.body.items[0].drinks;
const dessertsItems = req.body.items[0].desserts;
if (donItems && Array.isArray(donItems)) {
const food = donItems.map(donItem => {
let itemString = donItem.name.replace(/[^\P{L}a-zA-Z]/g, '') + ` `;
// Check if extraToppings exist and is an array before adding the line
if (Array.isArray(donItem.selectedToppings) && donItem.selectedToppings.length > 0) {
const options = donItem.selectedToppings.map(topping => topping.name.replace(/[^\P{L}a-zA-Z\s]/g, ''));
itemString += `\n Options: (${options.join(', ')})`;
}
return itemString;
});
foodString = food.join("\n ");
}
if (drinkItems && Array.isArray(drinkItems)) {
const drinks = drinkItems.map(drinkItem => {
let itemString = drinkItem.name.replace(/[^\P{L}a-zA-Z]/g, '') + ``;
// Check if milkOptions exist before adding the line
// Check if extraToppings exist and is an array before adding the line
if (Array.isArray(drinkItem.selectedToppings) && drinkItem.selectedToppings.length > 0) {
const options = drinkItem.selectedToppings.map(topping => topping.name.replace(/[^\P{L}a-zA-Z\s]/g, ''));
itemString += `\n Options: (${options.join(', ')})`;
}
return itemString;
});
drinksString = drinks.join("\n ");
}
if (dessertsItems && Array.isArray(dessertsItems)) {
const desserts = dessertsItems.map(dessertItem => {
let itemString = dessertItem.name.replace(/[^\P{L}a-zA-Z]/g, '') + ``;
// Check if extraToppings exist and is an array before adding the line
if (Array.isArray(dessertItem.selectedToppings) && dessertItem.selectedToppings.length > 0) {
const options = dessertItem.selectedToppings.map(topping => topping.name.replace(/[^\P{L}a-zA-Z\s]/g, ''));
itemString += `\n Options: (${options.join(', ')})`;
}
return itemString;
});
dessertsString = desserts.join("\n ");
}
const separationLine = "-------------------------";
// Check if there are items for Food before adding the separation line
if (foodString && (drinksString || dessertsString)) {
foodString += `\n${separationLine}\n`;
}
// Check if there are items for Drinks before adding the separation line
if (drinksString && dessertsString) {
drinksString += `\n${separationLine}\n`;
}
}
try {
const separationLine = "-------------------------";
console.log("sending "
+ "Order ID: " + req.body.id
+ "Table: " + req.body.table
+ "Food: " + foodString
+ "Drinks: " + drinksString
+ "Desserts: " + dessertsString
+ "Total: " + req.body.priceTotal
+ "Date: " + req.body.datetime
+ "Notes: " + req.body.notes
+ "to printer")
device.open(async function(error){
await printer
.font('b')
.align('ct')
.size(1,1)
.text("Receipt 1 of 2")
.style('bu')
.size(2, 2)
.text('New order for Table: ' + req.body.table)
.text(`\n${separationLine}\n`)
.text('Food: ' + foodString)
.text('Drinks: ' + drinksString)
.text('Desserts: ' + dessertsString)
.text(`\n${separationLine}\n`)
.text('Notes: ' + req.body.notes)
.font('a')
.size(1, 1)
.text(`\n${separationLine}\n`)
.text('Total: ' + req.body.priceTotal)
.text('Date: ' + req.body.datetime)
.text('Order ID: ' + req.body.id)
.text(" ")
.cut()
.font('b')
.align('ct')
.size(1,1)
.text("Receipt 2 of 2")
.style('bu')
.size(2, 2)
.text('New order for Table: ' + req.body.table)
.text(`\n${separationLine}\n`)
.text('Food: ' + foodString)
.text('Drinks: ' + drinksString)
.text('Desserts: ' + dessertsString)
.text(`\n${separationLine}\n`)
.text('Notes: ' + req.body.notes)
.font('a')
.size(1, 1)
.text(`\n${separationLine}\n`)
.text('Total: ' + req.body.priceTotal)
.text('Date: ' + req.body.datetime)
.text('Order ID: ' + req.body.id)
.text(" ")
.cut()
.close()
if (error) {
console.log(error)
}
})
}
catch (error) {
console.log(error)
}
res.send("Order: " + req.body.id + " Printed on date: " + req.body.datetime)
})I get the following error:
Error [ERR_STREAM_DESTROYED] Cannot call write after a stream was destroyed`
See pictures below for full error:
Is there an issue with my code, is it my Node version? (v20.11.0) I can't seem to get it working.
i have installed this module using npm i @node-escpos/core
and npm i @node-escpos/usb-adapter
and try using sample script
import { Printer, Image } from "@node-escpos/core";
// install escpos-usb adapter module manually
import USB from "@node-escpos/usb-adapter";
// Select the adapter based on your printer type
import { join } from "path";
const device = new USB();
device.open(async function(err){
if(err){
// handle error
return
}
// encoding is optional
const options = { encoding: "GB18030" /* default */ }
let printer = new Printer(device, options);
// Path to png image
const filePath = join("/PATH/TO/IMAGE");
const image = await Image.load(filePath);
printer
.font("a")
.align("ct")
.style("bu")
.size(1, 1)
.text("May the gold fill your pocket")
.text("恭喜发财")
.barcode(112233445566, "EAN13", { width: 50, height: 50 })
.table(["One", "Two", "Three"])
.tableCustom(
[
{ text: "Left", align: "LEFT", width: 0.33, style: "B" },
{ text: "Center", align: "CENTER", width: 0.33 },
{ text: "Right", align: "RIGHT", width: 0.33 },
],
{ encoding: "cp857", size: [1, 1] }, // Optional
)
// inject qrimage to printer
printer = await printer.qrimage("https://github.com/node-escpos/driver")
// inject image to printer
printer = await printer.image(
image,
"s8" // changing with image
)
printer
.cut()
.close()
});
but when i execute this script, it's trow an error :
- error Error: No native build was found for platform=linux arch=x64 runtime=node abi=115 uv=1 libc=glibc node=20.5.0 webpack=true
loaded from: /home/aqeela/Projects/pradha-next/.next/server/app/api
at load.resolve.load.path (webpack-internal:///(rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/node-gyp-build/node-gyp-build.js:50:11)
at load (webpack-internal:///(rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/node-gyp-build/node-gyp-build.js:20:32)
at eval (webpack-internal:///(rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/usb/bindings.js:9:194)
at (rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/usb/bindings.js (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:2686:1)
at __webpack_require__ (/home/aqeela/Projects/pradha-next/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/usb/device.js:6:11)
at (rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/usb/device.js (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:2719:1)
at __webpack_require__ (/home/aqeela/Projects/pradha-next/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/usb/index.js:17:16)
at (rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/usb/index.js (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:2741:1)
at __webpack_require__ (/home/aqeela/Projects/pradha-next/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/webusb/index.js:185:11)
at (rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/webusb/index.js (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:2763:1)
at __webpack_require__ (/home/aqeela/Projects/pradha-next/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/index.js:158:16)
at (rsc)/./node_modules/@node-escpos/usb-adapter/node_modules/usb/dist/index.js (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:2675:1)
at __webpack_require__ (/home/aqeela/Projects/pradha-next/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(rsc)/./node_modules/@node-escpos/usb-adapter/dist/index.mjs:7:61)
at (rsc)/./node_modules/@node-escpos/usb-adapter/dist/index.mjs (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:3577:1)
at __webpack_require__ (/home/aqeela/Projects/pradha-next/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(rsc)/./src/app/api/queue/ticket/route.tsx:13:82)
at (rsc)/./src/app/api/queue/ticket/route.tsx (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:3467:1)
at __webpack_require__ (/home/aqeela/Projects/pradha-next/.next/server/webpack-runtime.js:33:43)
at eval (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?name=app%2Fapi%2Fqueue%2Fticket%2Froute&page=%2Fapi%2Fqueue%2Fticket%2Froute&appPaths=&pagePath=private-next-app-dir%2Fapi%2Fqueue%2Fticket%2Froute.tsx&appDir=%2Fhome%2Faqeela%2FProjects%2Fpradha-next%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Faqeela%2FProjects%2Fpradha-next&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D!:15:126)
at (rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?name=app%2Fapi%2Fqueue%2Fticket%2Froute&page=%2Fapi%2Fqueue%2Fticket%2Froute&appPaths=&pagePath=private-next-app-dir%2Fapi%2Fqueue%2Fticket%2Froute.tsx&appDir=%2Fhome%2Faqeela%2FProjects%2Fpradha-next%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Faqeela%2FProjects%2Fpradha-next&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D! (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:231:1)
at __webpack_require__ (/home/aqeela/Projects/pradha-next/.next/server/webpack-runtime.js:33:43)
at __webpack_exec__ (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:3939:39)
at /home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:3940:28
at Object.<anonymous> (/home/aqeela/Projects/pradha-next/.next/server/app/api/queue/ticket/route.js:3943:3)
at Module._compile (node:internal/modules/cjs/loader:1233:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1287:10)
at Module.load (node:internal/modules/cjs/loader:1091:32)
at Module._load (node:internal/modules/cjs/loader:938:12)
at Module.require (node:internal/modules/cjs/loader:1115:19)
at require (node:internal/modules/helpers:119:18)
at requirePage (/home/aqeela/Projects/pradha-next/node_modules/next/dist/server/require.js:112:75)
at /home/aqeela/Projects/pradha-next/node_modules/next/dist/server/load-components.js:80:84
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async loadComponentsImpl (/home/aqeela/Projects/pradha-next/node_modules/next/dist/server/load-components.js:80:26)
at async DevServer.findPageComponentsImpl (/home/aqeela/Projects/pradha-next/node_modules/next/dist/server/next-server.js:772:36) {
digest: undefined
}
null
Currently, I don't have any Bluetooth printer to test, so I can't implement this adapter. If you have a Bluetooth printer and want to help, welcome PR.
BTW, maybe
nouble
is a good choice for this part.
Unlike @escpos Parent Repository. i cannot set witdh and height barcode in paper 80 mm
if is a long number the barcode is long.
I hope the barcode scales left and right if the data number is short;
printer.text('The quick brown fox jumps over the lazy dog')
.barcode(65656556565,"CODE39", {
width : 50,
height : 50,
})
.cut()
.close()
Spacing between Barcode Rows functions so that the barcode can be seen clearly when scanned
I'll push an example that shows how to use this lib in the electron before the end of this weekend. 🌴
TypeError: Cannot read properties of undefined (reading 'font')
at Printer.barcode (/Users/sks/Desktop/My-Projects/printy/node_modules/@node-escpos/core/dist/index.cjs:887:28)
at /Users/sks/Desktop/My-Projects/printy/print.js:24:10
at Interface.<anonymous> (/Users/sks/Desktop/My-Projects/printy/node_modules/@node-escpos/usb-adapter/dist/index.cjs:93:27)
at Device.<anonymous> (/Users/sks/Desktop/My-Projects/printy/node_modules/usb/dist/usb/interface.js:117:26)
This is the error I get, when I am executing the following code:
const { Printer } = require('@node-escpos/core');
const USB = require("@node-escpos/usb-adapter");
const device = new USB(1110, 2056);
device.open(function(err) {
if(err) {
console.log(err);
return;
}
const printer = new Printer(device, {});
console.log(printer);
printer
.font('a')
.style('bu')
.align('ct')
.size(0, 0)
.barcode('123456789111', 'EAN13')
.size(0, 0)
.text("")
printer.cut().close().then(r => console.log(r));
})
The original library song940/node-escpos
works, but this library gives me this error. I have been at this for two days. Can't seem to figure out why.
As of version 0.4.0 of @node-escpos/core
, I can´t find a way to actually use printer.getStatus
due to the fact that the status classes are not exported.
Please Update This Pull Request #80 (comment) to NPM. i need this update
Metapace can understand ESC/POS but I cloud not change barcode width. Barcode is very small. Also QR code is not printed, only the value as text.
Are there any tricks to correct this?
Thanks for hints.
Hi, this is a great library. However, Im having a bit of a problem when importing this to my recent project (common js) which uses https://github.com/song940/node-escpos.
So my current implementation of node-escpos uses an import like this
// my printer vendorId
const vendorId = '0x0483'
//my printer product id
const ProductId = '0x5743'
const escpos = require("escpos");
const device = new escpos.USB(vendorId, productId);
let printer = new escpos.Printer(device);
if (device != null) {
device.open(function () {
printer
.font("a")
.align("ct")
.style("bu")
.size(1, 1)
.text("Testing Printer")
.text("The quick brown fox jumps over the lazy dog")
.barcode("6611235132450000000000", "CODE93", {
height: 35,
width: 1,
})
.control("lf");
printer.cut();
printer.close();
}
}
Here is what I've tried so far on import
"use strict";
var _core = require("@node-escpos/core");
var _usbAdapter = _interopRequireDefault(require("@node-escpos/usb-adapter"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
here is the error message being rendered on the console
node_modules\@node-escpos\core\dist\index.mjs:1
(function (exports, require, module, __filename, __dirname, process, global, Buffer) { return function (exports, require, module, __filename, __dirname) { import EventEmitter from 'eventemitter3';
The close function of the usb adapter removes all detach listeners from the USB event emitter when the close function of a printer is called. That's a really bad practice as all listeners are removed from the event even those which are created in other packages or libraries.
close(callback?: ((error: Error | null) => void) | undefined): this {
if (!this.device) callback?.(new Error("Device not found"));
try {
this.device?.close();
usb.removeAllListeners("detach");
As i am also listening for the usb.on('detach') event my code gets broken after a device close() was called... The detach event is used to remove the active printer if its linked device is detached:
usb.on("detach", (device) => {
if (device === self.device) {
self.emit("detach", device);
self.emit("disconnect", device);
self.device = null;
}
});
Expected behaviour: Only the single listener from this library should be removed if the close function is called
What is best practice? To keep the printer connection open all the time as long as the application is running / detached or to close the printer connection each time a print was finished?
I have just found an article from Zebra which indicates that the connection should be closed after each print as long as there are not multiple jobs to be printed in a short amount of time: https://techdocs.zebra.com/link-os/2-14/bestpractices/. Any suggestions?
In this library it would be possible for USB printers to close the connection, but that is not true for serialport printers as the device is thrown away after a close.
Can we use this package without installing the WinUSB driver or there is a way to silently install the WinUSB driver through code?
I tried using usb.useUsbDkBackend()
from the node-usb
package but no luck as mentioned in the readme.md section of https://github.com/node-usb/node-usb
Primarily, I don't want the client to do an extra WinUSB installation.
Is it possible to Open the cashdrawer?
i dont understand for use @node-escpos/server for bind print to remote over network
The available functions printer.marginBottom(), printer.marginLeft(), printer.marginRight() have no impact on my printer using Epson TM-T20. I am a little bit confused as setting the margin is specified different:
Can anyone give me a hint what settings are applied when using the build-in functions from this library?
export const MARGINS = {
BOTTOM: "\x1B\x4F", // Fix bottom size
LEFT: "\x1B\x6C", // Fix left size
RIGHT: "\x1B\x51", // Fix right size
};
I want to use getStatus function and when I call it as follows,
PrinterStatus and other classes not exported.
So, let printerStatus = printer.getStatus(PrinterStatus);
// class type can't work
or
let printerStatus = printer.getStatus("PrinterStatus");
// string type can't work
this code can be added
Or is there any other solution besides these ? How should I use getStatus() function ?
What are the prerequisites for bluetooth interface connection?
I have been able to successfully setup usb-adapter interface.
But having trouble with bluetooth-adapter as my Epsom TM m30 doesn't show up.
Can someone please guide on how to make this work with bluetooth connection.
First of all, thanks for the great work.
I am trying to migrate from escpos and escpos-usb to your driver.
I tried a simple test
async function test() { try { const image = await Image.load('./assets/Packback-black.png'); console.log(image); } catch (error) { console.error('Error loading image:', error); } }
And this successfully loads my image.
Then I tried with a callback function, but this doesn't work :
function test(callback) { Image.load('./assets/Packback-black.png', (err, image) => { if (err) { // Handle error console.error('Error loading image:', err); return; } // Image loaded successfully, call the callback function callback(image); }); }
I get the following error
`C:\Users\thoma\Documents\Computer Projects\LTNG-state-machine\xstate\node_modules\get-pixels\node-pixels.js:126
cb(new Error("Unsupported file type: " + mimeType))
^
Error: Unsupported file type: (err, image) => {
if (err) {
// Handle error
console.error('Error loading image:', err);
return;
}
// Image loaded successfully, call the callback function
callback(image);
}
at doParse (C:\Users\thoma\Documents\Computer Projects\LTNG-state-machine\xstate\node_modules\get-pixels\node-pixels.js:126:10)
at C:\Users\thoma\Documents\Computer Projects\LTNG-state-machine\xstate\node_modules\get-pixels\node-pixels.js:190:7
at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read/context:68:3)
`
Like the callback function is interpreted as the "type" parameter of the load function.
But I also tried to add a type but then nothing happens since I don't read the image output.
Any idea what might be the issue ? Do I use the new version wrong ?
Thanks for the help !
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.