Giter Site home page Giter Site logo

hand-dot / labelmake Goto Github PK

View Code? Open in Web Editor NEW
355.0 6.0 30.0 157.39 MB

labelmake has moved and now available at pdfme / https://github.com/pdfme/pdfme

Home Page: https://labelmake.jp/javascript-pdf-generator-library

License: MIT License

TypeScript 99.99% HTML 0.01% JavaScript 0.01%
pdf pdf-generation pdf-document pdf-library pdf-lib document create typescript javascript umd

labelmake's Introduction

⚠️ labelmake has now stopped development. Please use pdfme. pdfme is a renewed version of labelmake which allows to use template designers as a UI library, improved documentation, etc. Of course, open source and MIT licensed.

Tweet npm NPM npm Unit Testing

top

labelmake is a declarative style PDF generation library for Node and the browser.

Other PDF generation libraries makes program complex by imperative operations. So, I developed this library aiming at a more simple declarative style PDF generation library. Finally, the layout engine and design & code generator tools make PDF generation so easy!

Learn more at official website


Installation

Use npm to install the latest version.

npm install labelmake

You can use Yarn, NuGet or other methods as well. You can load it directly from jsDelivr.

Features

  • Input data supports the following input types.
    • Text
      • Custom font
      • Styling(size, color, aliginment, etc.)
    • Image
      • JPG
      • PNG
    • Barcode
      • QR Code
      • Japan Post 4 State Customer Code
      • EAN-8, EAN-13
      • Code 39, Code 128
      • Codabar(NW-7)
      • UPC-E, UPC-A

example

template-design

Templates can be customized with design tools. and code can be generated with a generator.

api

Detailed specifications can be found in the api documentation.

production

labelmake.jp - variable data printing service.(Japanese)

Author

@hand-dot

labelmake is based on a amazing library pdf-lib(@Hopding).

Thanks to all contributors.

License

MIT

labelmake's People

Contributors

dependabot[bot] avatar hand-dot avatar iwag avatar tilman 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  avatar

labelmake's Issues

About using Korean.

Hi, I am so glad to say thank you for your efforts.
This is amazingly comfortable when I produce PDF file with prepared-PDF template.

However, I have had a trouble with input data in Korean.
I mean, whenever I have tried to set data written by Korean to the field, the error occured,
"(node:69032) UnhandledPromiseRejectionWarning: Error: WinAnsi cannot encode "왜" (0xc65c)"

I really want to discuss this issue with you.
I will share the code I have tried through github.

Error: WinAnsi cannot encode

初めまして。
こちらのライブラリを利用させていただきたくデモページを拝見しましたが、日本語を扱うと以下のエラーが出力されます。

Uncaught (in promise) Error: WinAnsi cannot encode "あ"

APIリファレンスを参考に、以下のようにArrayBufferをパラメータに与えても同様のエラーが発生するのですが、日本語フォントには対応していますでしょうか?
もしこちらの実装方法に誤りがありましたら、ご教示いただけますと幸いです。

const font = await fetch("https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFVZ0e.ttf").then((res) => res.arrayBuffer())
const pdf = await labelmake({ template, inputs, font });

basePDFの回転(縦・横)について

はじめまして。
ベースとなるPDFが横向きなのですが、MACのプレビューや以下のサービスを利用中は横向きになっているのですが、実際にコードをコピーして、node上で実行すると縦(90度回転した状態)になってしまいます。
https://labelmake.jp/javascript-pdf-generator-library/template-design/
何かオプション指定などで、横向きにすることは可能でしょうか?

node: v10.21.0
labelmake: 2.0.14

Unable to insert image using Labelmake

Unable to insert images using the image field property - no errors issued to the console, but supplying a base64 encoded PNG results in a corrupted PDF being generated.

Translate to JPG

Hi, I am much obliged to you for developing this kind of library.
It is very useful to make PDF from JS.

I have a question.
Can the library generate .jpg file through your library instead of PDF?
Sometimes my user requires the document with jpg type..!

Best wishes.

[2.0.19] Feature Request: Chaining fields

Description:

  • Add the ability to 'chain' fields so that vertical overflow can flow to the next in the chain

Use case:
There are many direct applications possible with this feature (similar to how text flows in Adobe Indesign), the main obvious one is to create columns.

  • Create columns by defining a chain across multiple parallel field boxes

Request:

  • Add a field to Schemas to declare chained text fields
const schemas = {
  imageField,
  titleField,
  leftColumnTextField,
  centerColumnTextField,
  rightColumnTextField,
  chainedTextFields: [
    {
      chainName: "main-columns",
      fields: [
        leftColumnTextField,
        centerColumnTextField,
        rightColumnTextField
      ]
    }
  ]
}
  • Implementation could happen in series:
  • 1 For the first field, create text with regular methods
  • 2 Determine if there is vertical overflow (can be simplified to lineheight × fontheight ×lineBreakcount > height)
  • 3 If no overflow, next fields in chain are created with empty text
  • 4 if there is overflow, split text at the line break before overflow, use that text for the next field in the chain

日本語が動きません

お世話になります。
日本語フォントですとこの様なエラーが出ますが対処方法ありますでしょうか?

スクリーンショット 2021-07-23 14 15 06

コード上ではこんなエラーが出ます。

const labelmake = require('labelmake');
const fs = require('fs');

(async () => {
  // You can also use Uint8Array or ArrayBuffer as a basePdf
  const basePdf = fs.readFileSync("./template/tmp.pdf")
  // const basePdf = await fetch("path/to/your.pdf").then((res) => res.arrayBuffer());
  const template = {
	"basePdf": basePdf,
	"schemas": [
		{},
		{
			"name": {
				"type": "text",
				"position": {
					"x": 122.24,
					"y": 136.02
				},
				"width": 68.6,
				"height": 7,
				"alignment": "left",
				"fontSize": 12,
				"characterSpacing": 0,
				"lineHeight": 1
			}
		}
	]
};
  const inputs = [{"name":"東京都中野区"}];
  const pdf = await labelmake({ template, inputs });
  // Node
  fs.writeFileSync('./output/new.pdf', pdf);
  // Browser
  // const blob = new Blob([pdf.buffer], { type: "application/pdf" });
  // document.getElementById("iframe").src = URL.createObjectURL(blob);
})();
debug> c
< (node:17516) UnhandledPromiseRejectionWarning: Error: WinAnsi cannot encode "京" (0x4eac)
<     at tr.encodeUnicodeCodePoint (/Users/username/workspace/test/cloudsign/node_modules/labelmake/dist/labelmake.min.js:15:180806)
<     at e.encodeTextAsGlyphs (/Users/username/workspace/test/cloudsign/node_modules/labelmake/dist/labelmake.min.js:15:229123)
<     at e.widthOfTextAtSize (/Users/username/workspace/test/cloudsign/node_modules/labelmake/dist/labelmake.min.js:15:228148)
<     at e.widthOfTextAtSize (/Users/username/workspace/test/cloudsign/node_modules/labelmake/dist/labelmake.min.js:15:353823)
<     at /Users/username/workspace/test/cloudsign/node_modules/labelmake/dist/labelmake.min.js:15:1869920
<     at Array.reduce (<anonymous>)
<     at r (/Users/username/workspace/test/cloudsign/node_modules/labelmake/dist/labelmake.min.js:15:1869880)
<     at /Users/username/workspace/test/cloudsign/node_modules/labelmake/dist/labelmake.min.js:15:1870087
<     at Array.forEach (<anonymous>)
<     at /Users/username/workspace/test/cloudsign/node_modules/labelmake/dist/labelmake.min.js:15:1869795
< (node:17516) 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: 1)
< (node:17516) [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.
< Waiting for the debugger to disconnect...

compatibility with node >14

Hi!

How you have

  "engines": {
    "node": "14.x"
  },

Does this mean that the package is incompatible with other versions?

If not, is it possible to replace the entry with ">=14" or at least "14.x 16.x"?

2.0.21 fails to create document on browser

Updating from v 2.0.17 causes an error trying to generate PDFs on browser using typescript + webpack5.

Error got from browser console:

labelmake default.toBuffer is not a function

[2.0.19] Feature Request: Schema/Page repeat for overflowing boxes

Related to #50

Description:

  • Add the option to repeat a schema/page when given fields overflow

Use cases:

  • Long text spanning across pages
  • Article template

Request:

  • Add a property to field schemas which marks them as triggers to repeat the page when overflown
  • Add a property to field schemas which marks them as removed from repeat pages. This property has to be exclusive of the previous.
  • To give the example of an article with the title above and a page number below, we may flag the article columns as overflowing and the title as being removed. The pages after the first would not display the title, but display the text continuation and keep incrementing the page number.
const schemas = [{
  mainTextField: {
    overflowOnNextPage: {Boolean},
    removeFromNextPage: {Boolean},
    type,
    width, // required to work
    height, // required to work
    position,
    rotate,
    alignment,
    fontName,
    fontSize,
    fontColor,
    backgroundColor,
    characterSpacing,
    lineHeight
  }
}];
  • Add a property to schema which toggles this functionality
const schemas = [{
  enableOverflowOnNextPage: {Boolean},
  mainTextField
}];

Similar to #50, labelmake does not necessery need to be aware that there is a relationship between pages. Processing each page in series, after processing page A and finding out that mainTextField is overflown with overflowOnNextPage set to true, then, label make can copy the source schema, remove the fields with removeFromNextPage==true, replace the text with the remaining overflowing text and add this copied modified schema next in the queue. This will repeat until there is no overflow.

Line wrapping bug

When creating a label with the below definition, the last char of a couple of lines wraps to the next line, with the next line overlapping that last/first char.

        basePdf: {width: 50, height: 25},
        schemas: [
            {
                'order_name': {
                    'type': 'text',
                    'position': {'x': 0, 'y': 1},
                    'width': 49,
                    'height': 2,
                    'alignment': 'right',
                    'fontSize': 5,
                    'characterSpacing': 0,
                    'lineHeight': 1,
                },
                'message': {
                    'type': 'text',
                    'position': {'x': 2, 'y': 3},
                    'width': 46,
                    'height': 17,
                    'alignment': 'left',
                    'fontSize': 10,
                    'characterSpacing': 0,
                    'lineHeight': 1,
                }
            }],
    };
    inputs = rows.map(row => ({
        order_name: row.order_name,
        message: row.message,
    }));

For testing:
row.order_name = ABC-1234
row.message = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec posuere nulla risus, eu suscipit ex imperdiet sed. Nam consectetur ullamcorper nibh, non.'

Resultant pdf: messages (7).pdf

Note that if font size is dropped to 9 then the issue doesn't appear, so I'm guessing it's just a magical combination of character line length and font size vs box width.

Barcode doesn't works on browser with CDN

Hello, Thanks for this package. It's very useful.

I have a problem with barcode when use plain JS with CDN.

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'toBuffer')

Code to reproduce error.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Labelmake QRCODE</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/labelmake.min.js"></script>
</head>
<body>
    <iframe id="iframe" src="" frameborder="0" style="width: 100%; height: 100vh;"></iframe>

    <script>
        (async () => {
            const template = {
                basePdf: { width: 210, height: 297 },
                schemas: [
                    {
                        qrcode: {
                            type: "qrcode",
                            position: { x: 5, y: 5 },
                            width: 30,
                            height: 30
                        }
                    }
                ]
            };
            // Please omit the barcode checksum.
            const inputs = [
                { qrcode: "test" }
            ];
            const pdf = await labelmake({ template, inputs });
            const blob = new Blob([pdf.buffer], { type: "application/pdf" });
            document.getElementById("iframe").src = URL.createObjectURL(blob);
        })();
    </script>
</body>
</html>

I tested on chrome/firefox/safari, same error.
This environment work perfectly with type text.

Thanks

export types

to use some types, you have to import them from dist, which is not correct.

eg:

import type { TemplateSchema } from 'labelmake/dist/types/type';

Could you export the utility types outside so they can be used?

Personally, types TemplateSchema and Template are important to us.

About generating PDF file name automatically.

Hi, I really want to appreciate your help last time(#59).
I'd like to share my current point that I've been curious about and get your tips if possible.

The point is about generating Pdf file name depending on the request.
Do you think it is possible to change Pdf file name in accordance with changes that I intend to?

For example, in my code, the file name is fixed as "index(1, 2, ......).pdf".
My intention is to generate Pdf files having different name, every time to do "npm run generatePdf.js", automatically.

If you think the question above is not defined clearly, please feel free to require me more information.
Thanks!

스크린샷 2021-12-26 11 11 55

`TemplateSchema`をexportしてほしい

https://github.com/hand-dot/labelmake/blob/v2.0.15/src/type.ts#L17-L30
↑をexportしてもらいたいです。

理由は
typescriptで下記のような形で定義する場合にエラーとなるため。

import labelmake from 'labelmake'
import type { Template } from 'labelmake/dist/types/type'
import opentype from 'opentype.js'

const generatePdf = async (): Promise<Blob> => {
  const fontFamilyName = 'NotoSansCJKjp'
  const fontStyleName = 'Medium'

  const [font, basePdf] = await Promise.all([
    fetch(`/fonts/otf/${fontFamilyName}-${fontStyleName}.otf`).then((res) =>
      res.arrayBuffer(),
    ),
    fetch('/base.pdf').then((res) => res.arrayBuffer()),
  ])

  const schemas = [
    {
      顧客名: {
        type: 'text',
        position: {
          x: 17,
          y: 32.49,
        },
        width: 82.75,
        height: 7.55,
        alignment: 'center',
        fontSize: 11,
        characterSpacing: 0,
        lineHeight: 1,
      },
      見積No: {
        type: 'text',
        position: {
          x: 37,
          y: 62.5,
        },
        width: 75.13,
        height: 5.58,
        alignment: 'left',
        fontSize: 10,
        characterSpacing: 0,
        lineHeight: 1,
      },
      納期: {
        type: 'text',
        position: {
          x: 37,
          y: 68.5,
        },
        width: 75.13,
        height: 5.58,
        alignment: 'left',
        fontSize: 10,
        characterSpacing: 0,
        lineHeight: 1,
      },
      納品場所: {
        type: 'text',
        position: {
          x: 37,
          y: 74.5,
        },
        width: 75.13,
        height: 5.58,
        alignment: 'left',
        fontSize: 10,
        characterSpacing: 0,
        lineHeight: 1,
      },
      取引方法: {
        type: 'text',
        position: {
          x: 37,
          y: 80.5,
        },
        width: 75.13,
        height: 5.58,
        alignment: 'left',
        fontSize: 10,
        characterSpacing: 0,
        lineHeight: 1,
      },
      有効期限: {
        type: 'text',
        position: {
          x: 37,
          y: 86.5,
        },
        width: 75.13,
        height: 5.58,
        alignment: 'left',
        fontSize: 10,
        characterSpacing: 0,
        lineHeight: 1,
      },
    },
  ]

  const inputs: Record<string, string>[] = [
    {
      見積No: '1234567890',
      顧客名: 'テスト会社',
      納期: 'データ入稿日より3営業日',
      納品場所: '北海道',
      取引方法: '原則としてご⼊⾦確認後の納品となります。',
      有効期限: '2020年 2⽉ 29⽇',
    },
  ]

  const allStrings = inputs.reduce((acc, cur) => {
    Object.keys(cur).forEach((key) => {
      cur[key].split('').forEach((str) => {
        acc.add(str)
      })
      return acc
    }, acc)
    return acc
  }, new Set<string>())

  const subset = generateSubsetFont(
    { font, familyName: fontFamilyName, styleName: fontStyleName },
    allStrings,
  )

  const template: Template = {
    schemas,
    basePdf,
    fontName: fontFamilyName,
  }

  const { buffer } = await labelmake({
    template,
    inputs,
    font: {
      [`${fontFamilyName}`]: {
        data: subset,
        subset: false,
      },
    },
  })

  const blob = new Blob([buffer], { type: 'application/pdf' })

  return blob
}

const generateSubsetFont = (
  fontObj: { font: ArrayBuffer; familyName: string; styleName: string },
  useStrings: Set<string>,
): ArrayBuffer => {
  const font = opentype.parse(fontObj.font)
  const subsetGlyphs = font.stringToGlyphs([...useStrings].join(''))
  const subset = new opentype.Font({
    familyName: fontObj.familyName,
    styleName: fontObj.styleName,
    unitsPerEm: font.unitsPerEm,
    ascender: font.ascender,
    descender: font.descender,
    glyphs: subsetGlyphs,
  })
  return subset.toArrayBuffer()
}

上記で発生するエラー

  const template: Template = {
    schemas, // <- Type Error: The expected type comes from property 'schemas' which is declared here on type 'Template'
    basePdf,
    fontName: fontFamilyName,
  }

該当部分のコードを下記のようにすればエラーは回避出来るけれども、

  const template: Template = {
    schemas,
    basePdf,
    fontName: fontFamilyName,
  } as Template

schemasの定義に型追加して、下記のように出来たほうが好ましいので。

import type { Template, TemplateSchema } from 'labelmake/dist/types/type'
...
  const schemas: Record<string, TemplateSchema>[] = [
  ...
  ]
...
  const template: Template = {
    schemas,
    basePdf,
    fontName: fontFamilyName,
  }
...

[2.0.19] Feature Request: allow basePDF declaration per Schema page (in addition to per Template)

Description:

  • Current version 2.0.19 supports a basePDF in its Template
  • When the number of pages can vary, a new basePDF has to be provided with the exact page number and order

Use case 1:

  • Generating a document with two distinct page layouts
  • One of the layouts has to be repeated a variable amount of time
  • Example: A report or article with a front page layout, regular page layout (and more: appendix page layout...)

Use case 2:

  • Generate multiple documents as one
  • Example: Generate a yearly report made of different monthly reports

Request:

  • Add the ability to declare a basePDF per "schema" of the template
const schemas = [
  {
    basePDF:frontPageLayout,
    fieldOne,
    fieldTwo
  },
  {
    basePDF:regularPageLayout,
    fieldThree,
    fieldFour,
    fieldFive
  }
];
const template = {[basePdf,] schemas,  fontName};
labelmake({template, inputs, font})

Image aspect ratio

Is it possible to provide an option to maintain aspect ratio of an image?
image

Subset Font Embedding

Hey! Thanks for this awesome library. Unfortunately there's a bug in fontkit when subset embedding certain fonts. I've created an issue on the "pdf-lib" repository (Hopding/pdf-lib#664) but it looks like it's not likely to be fixed anytime soon. Could you provide an option to not subset the font when embedding it? That would really help us out.

How to insert a local image in the Input?

I was having a schemas of

"schemas": [
            {
                "Logo": {
                    "type": "image",
                    "position": {
                        "x": 130,
                        "y": 45.25
                    },
                    "width": 30,
                    "height": 30,
                    "alignment": "center",
                    "fontSize": 14,
                    "characterSpacing": 0,
                    "lineHeight": 1,
                    "fontColor": ""
                }
]

const inputs = [{"Logo": }]

And I am trying to add a file in the local folder. How should I put the field of Logo in the inputs, so that I can put a local image into it?

2.0.21 causes create-react-app based app to crash on start

Using the simple demo from the official webside:

import labelmake from "labelmake"
import { Template } from "labelmake/dist/types/type"

export const makePdf = async () => {
  const template: Template = {
    basePdf: { width: 210, height: 297 },
    schemas: [
      {
        field1: {
          position: { x: 20, y: 20 },
          width: 50,
          height: 50,
          fontSize: 30,
          type: "text"
        },
        field2: {
          position: { x: 20, y: 35 },
          width: 50,
          height: 50,
          fontSize: 20,
          type: "text"
        }
      }
    ]
  }
  const inputs = [
    { field1: "aa", field2: "aaaaaaaaaaaa" },
    { field1: "bb", field2: "bbbbbbbbbbbb" }
  ]
  const pdf = await labelmake({ template, inputs })
}

When running npm start:

Starting the development server...


<--- Last few GCs --->

[19636:0000020587757D70]    32697 ms: Scavenge 4043.8 (4135.2) -> 4036.8 (4135.5) MB, 4.5 / 0.0 ms  (average mu = 0.225, current mu = 0.149) allocation failure 
[19636:0000020587757D70]    35426 ms: Mark-sweep 4046.1 (4137.5) -> 4037.4 (4137.5) MB, 2724.3 / 0.0 ms  (average mu = 0.138, current mu = 0.045) allocation failure scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 00007FF7D33C401F v8::internal::CodeObjectRegistry::~CodeObjectRegistry+112511
 2: 00007FF7D3353146 DSA_meth_get_flags+65542
 3: 00007FF7D3353FFD node::OnFatalError+301
 4: 00007FF7D3C85ADE v8::Isolate::ReportExternalAllocationLimitReached+94
 5: 00007FF7D3C7000D v8::SharedArrayBuffer::Externalize+781
 6: 00007FF7D3B135FC v8::internal::Heap::EphemeronKeyWriteBarrierFromCode+1468
 7: 00007FF7D3B202A9 v8::internal::Heap::PublishPendingAllocations+1129
 8: 00007FF7D3B1D27A v8::internal::Heap::PageFlagsAreConsistent+2842
 9: 00007FF7D3B0FEF9 v8::internal::Heap::CollectGarbage+2137
10: 00007FF7D3B0E0B0 v8::internal::Heap::AllocateExternalBackingStore+2000
11: 00007FF7D3B329E6 v8::internal::Factory::NewFillerObject+214
12: 00007FF7D3865C25 v8::internal::DateCache::Weekday+1797
13: 00007FF7D3D134B1 v8::internal::SetupIsolateDelegate::SetupHeap+494417
14: 0000020589D45C4B
  • The makePdf function is located in a module that is imported, but the function itself is never called, yet it still causes the crash.
  • Removing const pdf = await labelmake({ template, inputs }) (but keeping the import) avoids the crash and allows the app to compile.
  • The code works fine in 2.0.20.

Not sure if the error is related to create-react-app or to webpack 5 in general.

Feature Request: Inserting circles, lines.

I would like to be able to add checks, enclosures, etc. to PDF items from boolean values, etc.
For this purpose, I was hoping to have the ability to add circles and lines by specifying their coordinates.
(You may be able to use images instead).

cannot see edit panel

hi, I have my own case running successfully, but on the page I cannot see the edit panel.

  • [ ]

  • [ ]

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.