Commit 71285982 71285982c4c894750e2b7b1c0b7927ca01735f69 by zhanghao

commit

1 parent cc1d2bfe
Showing 125 changed files with 15187 additions and 11 deletions
1 /// <reference types="node"/>
2 import {IncomingMessage} from 'http';
3
4 /**
5 Decompress a HTTP response if needed.
6
7 @param response - The HTTP incoming stream with compressed data.
8 @returns The decompressed HTTP response stream.
9
10 @example
11 ```
12 import {http} from 'http';
13 import decompressResponse = require('decompress-response');
14
15 http.get('https://sindresorhus.com', response => {
16 response = decompressResponse(response);
17 });
18 ```
19 */
20 declare function decompressResponse(response: IncomingMessage): IncomingMessage;
21
22 export = decompressResponse;
1 'use strict';
2 const {Transform, PassThrough} = require('stream');
3 const zlib = require('zlib');
4 const mimicResponse = require('mimic-response');
5
6 module.exports = response => {
7 const contentEncoding = (response.headers['content-encoding'] || '').toLowerCase();
8
9 if (!['gzip', 'deflate', 'br'].includes(contentEncoding)) {
10 return response;
11 }
12
13 // TODO: Remove this when targeting Node.js 12.
14 const isBrotli = contentEncoding === 'br';
15 if (isBrotli && typeof zlib.createBrotliDecompress !== 'function') {
16 response.destroy(new Error('Brotli is not supported on Node.js < 12'));
17 return response;
18 }
19
20 let isEmpty = true;
21
22 const checker = new Transform({
23 transform(data, _encoding, callback) {
24 isEmpty = false;
25
26 callback(null, data);
27 },
28
29 flush(callback) {
30 callback();
31 }
32 });
33
34 const finalStream = new PassThrough({
35 autoDestroy: false,
36 destroy(error, callback) {
37 response.destroy();
38
39 callback(error);
40 }
41 });
42
43 const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip();
44
45 decompressStream.once('error', error => {
46 if (isEmpty && !response.readable) {
47 finalStream.end();
48 return;
49 }
50
51 finalStream.destroy(error);
52 });
53
54 mimicResponse(response, finalStream);
55 response.pipe(checker).pipe(decompressStream).pipe(finalStream);
56
57 return finalStream;
58 };
1 MIT License
2
3 Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
7 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 {
2 "_from": "decompress-response@^6.0.0",
3 "_id": "decompress-response@6.0.0",
4 "_inBundle": false,
5 "_integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
6 "_location": "/decompress-response",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "decompress-response@^6.0.0",
12 "name": "decompress-response",
13 "escapedName": "decompress-response",
14 "rawSpec": "^6.0.0",
15 "saveSpec": null,
16 "fetchSpec": "^6.0.0"
17 },
18 "_requiredBy": [
19 "/simple-get"
20 ],
21 "_resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz",
22 "_shasum": "ca387612ddb7e104bd16d85aab00d5ecf09c66fc",
23 "_spec": "decompress-response@^6.0.0",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/simple-get",
25 "author": {
26 "name": "Sindre Sorhus",
27 "email": "sindresorhus@gmail.com",
28 "url": "https://sindresorhus.com"
29 },
30 "bugs": {
31 "url": "https://github.com/sindresorhus/decompress-response/issues"
32 },
33 "bundleDependencies": false,
34 "dependencies": {
35 "mimic-response": "^3.1.0"
36 },
37 "deprecated": false,
38 "description": "Decompress a HTTP response if needed",
39 "devDependencies": {
40 "@types/node": "^14.0.1",
41 "ava": "^2.2.0",
42 "get-stream": "^5.0.0",
43 "pify": "^5.0.0",
44 "tsd": "^0.11.0",
45 "xo": "^0.30.0"
46 },
47 "engines": {
48 "node": ">=10"
49 },
50 "files": [
51 "index.js",
52 "index.d.ts"
53 ],
54 "funding": "https://github.com/sponsors/sindresorhus",
55 "homepage": "https://github.com/sindresorhus/decompress-response#readme",
56 "keywords": [
57 "decompress",
58 "response",
59 "http",
60 "https",
61 "zlib",
62 "gzip",
63 "zip",
64 "deflate",
65 "unzip",
66 "ungzip",
67 "incoming",
68 "message",
69 "stream",
70 "compressed",
71 "brotli"
72 ],
73 "license": "MIT",
74 "name": "decompress-response",
75 "repository": {
76 "type": "git",
77 "url": "git+https://github.com/sindresorhus/decompress-response.git"
78 },
79 "scripts": {
80 "test": "xo && ava && tsd"
81 },
82 "version": "6.0.0",
83 "xo": {
84 "rules": {
85 "@typescript-eslint/prefer-readonly-parameter-types": "off"
86 }
87 }
88 }
1 # decompress-response [![Build Status](https://travis-ci.com/sindresorhus/decompress-response.svg?branch=master)](https://travis-ci.com/sindresorhus/decompress-response)
2
3 > Decompress a HTTP response if needed
4
5 Decompresses the [response](https://nodejs.org/api/http.html#http_class_http_incomingmessage) from [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback) if it's gzipped, deflated or compressed with Brotli, otherwise just passes it through.
6
7 Used by [`got`](https://github.com/sindresorhus/got).
8
9 ## Install
10
11 ```
12 $ npm install decompress-response
13 ```
14
15 ## Usage
16
17 ```js
18 const http = require('http');
19 const decompressResponse = require('decompress-response');
20
21 http.get('https://sindresorhus.com', response => {
22 response = decompressResponse(response);
23 });
24 ```
25
26 ## API
27
28 ### decompressResponse(response)
29
30 Returns the decompressed HTTP response stream.
31
32 #### response
33
34 Type: [`http.IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
35
36 The HTTP incoming stream with compressed data.
37
38 ---
39
40 <div align="center">
41 <b>
42 <a href="https://tidelift.com/subscription/pkg/npm-decompress-response?utm_source=npm-decompress-response&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
43 </b>
44 <br>
45 <sub>
46 Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
47 </sub>
48 </div>
1 {
2 "presets": ["@babel/preset-env"]
3 }
1 {
2 "singleQuote": true,
3 "write": true,
4 "semi": false,
5 "tabWidth": 2,
6 "printWidth": 80
7 }
1 The MIT License (MIT)
2
3 Copyright (c) 2015 Matt Way
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 SOFTWARE.
22
1 # js Binary Schema Parser
2
3 Parse binary files in javascript using a schema to convert to plain objects.
4
5 Years ago I needed to parse GIF images for our **[Ruffle][1]** messaging app. While this readme describes how to parse binary files in general, our _[GIF Parser][2]_ library exhibits a full use of this library (including a _[demo][2]_). I suggest looking at the other library for a quick understanding.
6
7 Basically, you provide a schema object and some data, and it will step through the binary data, and convert it into the object defined by your schema. Included in this library is a parser for the `Uint8TypedArray`, but it is easy to add them for your own types if necessary. It can parse bytes, arrays, chunks, conditionals, loops, etc.
8
9 ### How to Use
10
11 _Installation:_
12
13 npm install js-binary-schema-parser
14
15 _Create a schema and parse a file:_
16
17 import { parse, conditional } from 'js-binary-schema-parser'
18 import { buildStream, readByte } from 'js-binary-schema-parser/lib/parsers/uint8'
19
20 const schema = [
21 // part definitions...
22 { someKey: readByte() }
23 ];
24
25 // get the input file data
26 const data = new Uint8Array(fileArrayBuffer);
27 // create a stream object and parse it
28 const parsedObject = parse(buildStream(data), schema)
29
30 ### Schemas
31
32 So far in this library there is only one built in schema, which is for the GIF format. You can import included schemas like:
33
34 import GIF from 'js-binary-schema-parser/lib/schemas/gif'
35
36 Schemas are an array of _parts_, which are objects containing a single key label, and the parser to use at that point in time. This format was chosen to ensure parse ordering was consistent. _Parts_ can also contain other parts internally, and include syntax for loops, and conditionals. You can also include your own custom functions for parsing, providing direct access to the given data stream. Below is an example of a schema using the `Uint8TypedArray` parser provided to parse the GIF format header. You can also see a full example [here][2] of parsing entire GIF files.
37
38 ### Example
39
40 var gifSchema = [
41 {
42 label: 'header', // gif header
43 parts: [
44 { label: 'signature', parser: Parsers.readString(3) },
45 { label: 'version', parser: Parsers.readString(3) }
46 ]
47 },{
48 label: 'lsd', // local screen descriptor
49 parts: [
50 { label: 'width', parser: Parsers.readUnsigned(true) },
51 { label: 'height', parser: Parsers.readUnsigned(true) },
52 { label: 'gct', bits: {
53 exists: { index: 0 },
54 resolution: { index: 1, length: 3 },
55 sort: { index: 4 },
56 size: { index: 5, length: 3 }
57 }},
58 { label: 'backgroundColorIndex', parser: Parsers.readByte() },
59 { label: 'pixelAspectRatio', parser: Parsers.readByte() }
60 ]
61 }
62 ];
63
64 ### Why this parser?
65
66 There are other good parsers around, like [jBinary][4], but we weren't a fan of relying on object key ordering, and defining parser types as strings. This one is also extremely small, and easily exstensible in any way you want.
67
68 ### Demo
69
70 You can see a full demo **[here][2]** which uses this lib to parse GIF files for manipulation.
71
72 ### Who are we?
73
74 [Matt Way][3] & [Nick Drewe][5]
75
76 [Wethrift.com][6]
77
78 [1]: https://www.producthunt.com/posts/ruffle
79 [2]: https://github.com/matt-way/gifuct-js
80 [3]: https://twitter.com/_MattWay
81 [4]: https://github.com/jDataView/jBinary
82 [5]: https://twitter.com/nickdrewe
83 [6]: https://wethrift.com
1 import fs from 'fs'
2 import { parse } from '../src'
3 import { buildStream } from '../src/parsers/uint8'
4 import { GIF } from '../src/schemas'
5
6 debugger
7
8 const data = fs.readFileSync('./example/dog.gif')
9 const result = parse(buildStream(new Uint8Array(data)), GIF)
10 console.log(result)
1 "use strict";
2
3 Object.defineProperty(exports, "__esModule", {
4 value: true
5 });
6 exports.loop = exports.conditional = exports.parse = void 0;
7
8 var parse = function parse(stream, schema) {
9 var result = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
10 var parent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : result;
11
12 if (Array.isArray(schema)) {
13 schema.forEach(function (partSchema) {
14 return parse(stream, partSchema, result, parent);
15 });
16 } else if (typeof schema === 'function') {
17 schema(stream, result, parent, parse);
18 } else {
19 var key = Object.keys(schema)[0];
20
21 if (Array.isArray(schema[key])) {
22 parent[key] = {};
23 parse(stream, schema[key], result, parent[key]);
24 } else {
25 parent[key] = schema[key](stream, result, parent, parse);
26 }
27 }
28
29 return result;
30 };
31
32 exports.parse = parse;
33
34 var conditional = function conditional(schema, conditionFunc) {
35 return function (stream, result, parent, parse) {
36 if (conditionFunc(stream, result, parent)) {
37 parse(stream, schema, result, parent);
38 }
39 };
40 };
41
42 exports.conditional = conditional;
43
44 var loop = function loop(schema, continueFunc) {
45 return function (stream, result, parent, parse) {
46 var arr = [];
47 var lastStreamPos = stream.pos;
48
49 while (continueFunc(stream, result, parent)) {
50 var newParent = {};
51 parse(stream, schema, result, newParent); // cases when whole file is parsed but no termination is there and stream position is not getting updated as well
52 // it falls into infinite recursion, null check to avoid the same
53
54 if (stream.pos === lastStreamPos) {
55 break;
56 }
57
58 lastStreamPos = stream.pos;
59 arr.push(newParent);
60 }
61
62 return arr;
63 };
64 };
65
66 exports.loop = loop;
...\ No newline at end of file ...\ No newline at end of file
1 "use strict";
2
3 Object.defineProperty(exports, "__esModule", {
4 value: true
5 });
6 exports.readBits = exports.readArray = exports.readUnsigned = exports.readString = exports.peekBytes = exports.readBytes = exports.peekByte = exports.readByte = exports.buildStream = void 0;
7
8 // Default stream and parsers for Uint8TypedArray data type
9 var buildStream = function buildStream(uint8Data) {
10 return {
11 data: uint8Data,
12 pos: 0
13 };
14 };
15
16 exports.buildStream = buildStream;
17
18 var readByte = function readByte() {
19 return function (stream) {
20 return stream.data[stream.pos++];
21 };
22 };
23
24 exports.readByte = readByte;
25
26 var peekByte = function peekByte() {
27 var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
28 return function (stream) {
29 return stream.data[stream.pos + offset];
30 };
31 };
32
33 exports.peekByte = peekByte;
34
35 var readBytes = function readBytes(length) {
36 return function (stream) {
37 return stream.data.subarray(stream.pos, stream.pos += length);
38 };
39 };
40
41 exports.readBytes = readBytes;
42
43 var peekBytes = function peekBytes(length) {
44 return function (stream) {
45 return stream.data.subarray(stream.pos, stream.pos + length);
46 };
47 };
48
49 exports.peekBytes = peekBytes;
50
51 var readString = function readString(length) {
52 return function (stream) {
53 return Array.from(readBytes(length)(stream)).map(function (value) {
54 return String.fromCharCode(value);
55 }).join('');
56 };
57 };
58
59 exports.readString = readString;
60
61 var readUnsigned = function readUnsigned(littleEndian) {
62 return function (stream) {
63 var bytes = readBytes(2)(stream);
64 return littleEndian ? (bytes[1] << 8) + bytes[0] : (bytes[0] << 8) + bytes[1];
65 };
66 };
67
68 exports.readUnsigned = readUnsigned;
69
70 var readArray = function readArray(byteSize, totalOrFunc) {
71 return function (stream, result, parent) {
72 var total = typeof totalOrFunc === 'function' ? totalOrFunc(stream, result, parent) : totalOrFunc;
73 var parser = readBytes(byteSize);
74 var arr = new Array(total);
75
76 for (var i = 0; i < total; i++) {
77 arr[i] = parser(stream);
78 }
79
80 return arr;
81 };
82 };
83
84 exports.readArray = readArray;
85
86 var subBitsTotal = function subBitsTotal(bits, startIndex, length) {
87 var result = 0;
88
89 for (var i = 0; i < length; i++) {
90 result += bits[startIndex + i] && Math.pow(2, length - i - 1);
91 }
92
93 return result;
94 };
95
96 var readBits = function readBits(schema) {
97 return function (stream) {
98 var _byte = readByte()(stream); // convert the byte to bit array
99
100
101 var bits = new Array(8);
102
103 for (var i = 0; i < 8; i++) {
104 bits[7 - i] = !!(_byte & 1 << i);
105 } // convert the bit array to values based on the schema
106
107
108 return Object.keys(schema).reduce(function (res, key) {
109 var def = schema[key];
110
111 if (def.length) {
112 res[key] = subBitsTotal(bits, def.index, def.length);
113 } else {
114 res[key] = bits[def.index];
115 }
116
117 return res;
118 }, {});
119 };
120 };
121
122 exports.readBits = readBits;
...\ No newline at end of file ...\ No newline at end of file
1 "use strict";
2
3 Object.defineProperty(exports, "__esModule", {
4 value: true
5 });
6 exports["default"] = void 0;
7
8 var _ = require("../");
9
10 var _uint = require("../parsers/uint8");
11
12 // a set of 0x00 terminated subblocks
13 var subBlocksSchema = {
14 blocks: function blocks(stream) {
15 var terminator = 0x00;
16 var chunks = [];
17 var streamSize = stream.data.length;
18 var total = 0;
19
20 for (var size = (0, _uint.readByte)()(stream); size !== terminator; size = (0, _uint.readByte)()(stream)) {
21 // size becomes undefined for some case when file is corrupted and terminator is not proper
22 // null check to avoid recursion
23 if (!size) break; // catch corrupted files with no terminator
24
25 if (stream.pos + size >= streamSize) {
26 var availableSize = streamSize - stream.pos;
27 chunks.push((0, _uint.readBytes)(availableSize)(stream));
28 total += availableSize;
29 break;
30 }
31
32 chunks.push((0, _uint.readBytes)(size)(stream));
33 total += size;
34 }
35
36 var result = new Uint8Array(total);
37 var offset = 0;
38
39 for (var i = 0; i < chunks.length; i++) {
40 result.set(chunks[i], offset);
41 offset += chunks[i].length;
42 }
43
44 return result;
45 }
46 }; // global control extension
47
48 var gceSchema = (0, _.conditional)({
49 gce: [{
50 codes: (0, _uint.readBytes)(2)
51 }, {
52 byteSize: (0, _uint.readByte)()
53 }, {
54 extras: (0, _uint.readBits)({
55 future: {
56 index: 0,
57 length: 3
58 },
59 disposal: {
60 index: 3,
61 length: 3
62 },
63 userInput: {
64 index: 6
65 },
66 transparentColorGiven: {
67 index: 7
68 }
69 })
70 }, {
71 delay: (0, _uint.readUnsigned)(true)
72 }, {
73 transparentColorIndex: (0, _uint.readByte)()
74 }, {
75 terminator: (0, _uint.readByte)()
76 }]
77 }, function (stream) {
78 var codes = (0, _uint.peekBytes)(2)(stream);
79 return codes[0] === 0x21 && codes[1] === 0xf9;
80 }); // image pipeline block
81
82 var imageSchema = (0, _.conditional)({
83 image: [{
84 code: (0, _uint.readByte)()
85 }, {
86 descriptor: [{
87 left: (0, _uint.readUnsigned)(true)
88 }, {
89 top: (0, _uint.readUnsigned)(true)
90 }, {
91 width: (0, _uint.readUnsigned)(true)
92 }, {
93 height: (0, _uint.readUnsigned)(true)
94 }, {
95 lct: (0, _uint.readBits)({
96 exists: {
97 index: 0
98 },
99 interlaced: {
100 index: 1
101 },
102 sort: {
103 index: 2
104 },
105 future: {
106 index: 3,
107 length: 2
108 },
109 size: {
110 index: 5,
111 length: 3
112 }
113 })
114 }]
115 }, (0, _.conditional)({
116 lct: (0, _uint.readArray)(3, function (stream, result, parent) {
117 return Math.pow(2, parent.descriptor.lct.size + 1);
118 })
119 }, function (stream, result, parent) {
120 return parent.descriptor.lct.exists;
121 }), {
122 data: [{
123 minCodeSize: (0, _uint.readByte)()
124 }, subBlocksSchema]
125 }]
126 }, function (stream) {
127 return (0, _uint.peekByte)()(stream) === 0x2c;
128 }); // plain text block
129
130 var textSchema = (0, _.conditional)({
131 text: [{
132 codes: (0, _uint.readBytes)(2)
133 }, {
134 blockSize: (0, _uint.readByte)()
135 }, {
136 preData: function preData(stream, result, parent) {
137 return (0, _uint.readBytes)(parent.text.blockSize)(stream);
138 }
139 }, subBlocksSchema]
140 }, function (stream) {
141 var codes = (0, _uint.peekBytes)(2)(stream);
142 return codes[0] === 0x21 && codes[1] === 0x01;
143 }); // application block
144
145 var applicationSchema = (0, _.conditional)({
146 application: [{
147 codes: (0, _uint.readBytes)(2)
148 }, {
149 blockSize: (0, _uint.readByte)()
150 }, {
151 id: function id(stream, result, parent) {
152 return (0, _uint.readString)(parent.blockSize)(stream);
153 }
154 }, subBlocksSchema]
155 }, function (stream) {
156 var codes = (0, _uint.peekBytes)(2)(stream);
157 return codes[0] === 0x21 && codes[1] === 0xff;
158 }); // comment block
159
160 var commentSchema = (0, _.conditional)({
161 comment: [{
162 codes: (0, _uint.readBytes)(2)
163 }, subBlocksSchema]
164 }, function (stream) {
165 var codes = (0, _uint.peekBytes)(2)(stream);
166 return codes[0] === 0x21 && codes[1] === 0xfe;
167 });
168 var schema = [{
169 header: [{
170 signature: (0, _uint.readString)(3)
171 }, {
172 version: (0, _uint.readString)(3)
173 }]
174 }, {
175 lsd: [{
176 width: (0, _uint.readUnsigned)(true)
177 }, {
178 height: (0, _uint.readUnsigned)(true)
179 }, {
180 gct: (0, _uint.readBits)({
181 exists: {
182 index: 0
183 },
184 resolution: {
185 index: 1,
186 length: 3
187 },
188 sort: {
189 index: 4
190 },
191 size: {
192 index: 5,
193 length: 3
194 }
195 })
196 }, {
197 backgroundColorIndex: (0, _uint.readByte)()
198 }, {
199 pixelAspectRatio: (0, _uint.readByte)()
200 }]
201 }, (0, _.conditional)({
202 gct: (0, _uint.readArray)(3, function (stream, result) {
203 return Math.pow(2, result.lsd.gct.size + 1);
204 })
205 }, function (stream, result) {
206 return result.lsd.gct.exists;
207 }), // content frames
208 {
209 frames: (0, _.loop)([gceSchema, applicationSchema, commentSchema, imageSchema, textSchema], function (stream) {
210 var nextCode = (0, _uint.peekByte)()(stream); // rather than check for a terminator, we should check for the existence
211 // of an ext or image block to avoid infinite loops
212 //var terminator = 0x3B;
213 //return nextCode !== terminator;
214
215 return nextCode === 0x21 || nextCode === 0x2c;
216 })
217 }];
218 var _default = schema;
219 exports["default"] = _default;
...\ No newline at end of file ...\ No newline at end of file
1 {
2 "_from": "js-binary-schema-parser@^2.0.2",
3 "_id": "js-binary-schema-parser@2.0.3",
4 "_inBundle": false,
5 "_integrity": "sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==",
6 "_location": "/js-binary-schema-parser",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "js-binary-schema-parser@^2.0.2",
12 "name": "js-binary-schema-parser",
13 "escapedName": "js-binary-schema-parser",
14 "rawSpec": "^2.0.2",
15 "saveSpec": null,
16 "fetchSpec": "^2.0.2"
17 },
18 "_requiredBy": [
19 "/vue-qr"
20 ],
21 "_resolved": "https://registry.npmmirror.com/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz",
22 "_shasum": "3d7848748e8586e63b34e8911b643f59cfb6396e",
23 "_spec": "js-binary-schema-parser@^2.0.2",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr",
25 "author": {
26 "name": "Matt Way"
27 },
28 "bugs": {
29 "url": "https://github.com/matt-way/jsBinarySchemaParser/issues"
30 },
31 "bundleDependencies": false,
32 "dependencies": {},
33 "deprecated": false,
34 "description": "Parse binary files with a schema into nicely readable objects",
35 "devDependencies": {
36 "@babel/cli": "^7.8.4",
37 "@babel/core": "^7.8.4",
38 "@babel/node": "^7.8.4",
39 "@babel/preset-env": "^7.8.4"
40 },
41 "homepage": "https://github.com/matt-way/jsBinarySchemaParser",
42 "keywords": [
43 "javascript",
44 "binary",
45 "file",
46 "parser",
47 "schema"
48 ],
49 "license": "MIT",
50 "main": "lib/index.js",
51 "name": "js-binary-schema-parser",
52 "repository": {
53 "type": "git",
54 "url": "git+https://github.com/matt-way/jsBinarySchemaParser.git"
55 },
56 "scripts": {
57 "build": "babel src --out-dir lib",
58 "example": "babel-node ./example/index.js",
59 "example-debug": "babel-node --inspect-brk ./example/index.js"
60 },
61 "version": "2.0.3"
62 }
1 export const parse = (stream, schema, result = {}, parent = result) => {
2 if (Array.isArray(schema)) {
3 schema.forEach(partSchema => parse(stream, partSchema, result, parent))
4 } else if (typeof schema === 'function') {
5 schema(stream, result, parent, parse)
6 } else {
7 const key = Object.keys(schema)[0]
8 if (Array.isArray(schema[key])) {
9 parent[key] = {}
10 parse(stream, schema[key], result, parent[key])
11 } else {
12 parent[key] = schema[key](stream, result, parent, parse)
13 }
14 }
15 return result
16 }
17
18 export const conditional = (schema, conditionFunc) => (
19 stream,
20 result,
21 parent,
22 parse
23 ) => {
24 if (conditionFunc(stream, result, parent)) {
25 parse(stream, schema, result, parent)
26 }
27 }
28
29 export const loop = (schema, continueFunc) => (
30 stream,
31 result,
32 parent,
33 parse
34 ) => {
35 const arr = []
36 let lastStreamPos = stream.pos;
37 while (continueFunc(stream, result, parent)) {
38 const newParent = {}
39 parse(stream, schema, result, newParent)
40 // cases when whole file is parsed but no termination is there and stream position is not getting updated as well
41 // it falls into infinite recursion, null check to avoid the same
42 if(stream.pos === lastStreamPos) {
43 break
44 }
45 lastStreamPos = stream.pos
46 arr.push(newParent)
47 }
48 return arr
49 }
1 // Default stream and parsers for Uint8TypedArray data type
2
3 export const buildStream = uint8Data => ({
4 data: uint8Data,
5 pos: 0
6 })
7
8 export const readByte = () => stream => {
9 return stream.data[stream.pos++]
10 }
11
12 export const peekByte = (offset = 0) => stream => {
13 return stream.data[stream.pos + offset]
14 }
15
16 export const readBytes = length => stream => {
17 return stream.data.subarray(stream.pos, (stream.pos += length))
18 }
19
20 export const peekBytes = length => stream => {
21 return stream.data.subarray(stream.pos, stream.pos + length)
22 }
23
24 export const readString = length => stream => {
25 return Array.from(readBytes(length)(stream))
26 .map(value => String.fromCharCode(value))
27 .join('')
28 }
29
30 export const readUnsigned = littleEndian => stream => {
31 const bytes = readBytes(2)(stream)
32 return littleEndian ? (bytes[1] << 8) + bytes[0] : (bytes[0] << 8) + bytes[1]
33 }
34
35 export const readArray = (byteSize, totalOrFunc) => (
36 stream,
37 result,
38 parent
39 ) => {
40 const total =
41 typeof totalOrFunc === 'function'
42 ? totalOrFunc(stream, result, parent)
43 : totalOrFunc
44
45 const parser = readBytes(byteSize)
46 const arr = new Array(total)
47 for (var i = 0; i < total; i++) {
48 arr[i] = parser(stream)
49 }
50 return arr
51 }
52
53 const subBitsTotal = (bits, startIndex, length) => {
54 var result = 0
55 for (var i = 0; i < length; i++) {
56 result += bits[startIndex + i] && 2 ** (length - i - 1)
57 }
58 return result
59 }
60
61 export const readBits = schema => stream => {
62 const byte = readByte()(stream)
63 // convert the byte to bit array
64 const bits = new Array(8)
65 for (var i = 0; i < 8; i++) {
66 bits[7 - i] = !!(byte & (1 << i))
67 }
68 // convert the bit array to values based on the schema
69 return Object.keys(schema).reduce((res, key) => {
70 const def = schema[key]
71 if (def.length) {
72 res[key] = subBitsTotal(bits, def.index, def.length)
73 } else {
74 res[key] = bits[def.index]
75 }
76 return res
77 }, {})
78 }
1 import { conditional, loop } from '../'
2 import {
3 readByte,
4 peekByte,
5 readBytes,
6 peekBytes,
7 readString,
8 readUnsigned,
9 readArray,
10 readBits,
11 } from '../parsers/uint8'
12
13 // a set of 0x00 terminated subblocks
14 var subBlocksSchema = {
15 blocks: (stream) => {
16 const terminator = 0x00
17 const chunks = []
18 const streamSize = stream.data.length
19 var total = 0
20 for (
21 var size = readByte()(stream);
22 size !== terminator;
23 size = readByte()(stream)
24 ) {
25 // size becomes undefined for some case when file is corrupted and terminator is not proper
26 // null check to avoid recursion
27 if(!size) break;
28 // catch corrupted files with no terminator
29 if (stream.pos + size >= streamSize) {
30 const availableSize = streamSize - stream.pos
31 chunks.push(readBytes(availableSize)(stream))
32 total += availableSize
33 break
34 }
35 chunks.push(readBytes(size)(stream))
36 total += size
37 }
38 const result = new Uint8Array(total)
39 var offset = 0
40 for (var i = 0; i < chunks.length; i++) {
41 result.set(chunks[i], offset)
42 offset += chunks[i].length
43 }
44 return result
45 },
46 }
47
48 // global control extension
49 const gceSchema = conditional(
50 {
51 gce: [
52 { codes: readBytes(2) },
53 { byteSize: readByte() },
54 {
55 extras: readBits({
56 future: { index: 0, length: 3 },
57 disposal: { index: 3, length: 3 },
58 userInput: { index: 6 },
59 transparentColorGiven: { index: 7 },
60 }),
61 },
62 { delay: readUnsigned(true) },
63 { transparentColorIndex: readByte() },
64 { terminator: readByte() },
65 ],
66 },
67 (stream) => {
68 var codes = peekBytes(2)(stream)
69 return codes[0] === 0x21 && codes[1] === 0xf9
70 }
71 )
72
73 // image pipeline block
74 const imageSchema = conditional(
75 {
76 image: [
77 { code: readByte() },
78 {
79 descriptor: [
80 { left: readUnsigned(true) },
81 { top: readUnsigned(true) },
82 { width: readUnsigned(true) },
83 { height: readUnsigned(true) },
84 {
85 lct: readBits({
86 exists: { index: 0 },
87 interlaced: { index: 1 },
88 sort: { index: 2 },
89 future: { index: 3, length: 2 },
90 size: { index: 5, length: 3 },
91 }),
92 },
93 ],
94 },
95 conditional(
96 {
97 lct: readArray(3, (stream, result, parent) => {
98 return Math.pow(2, parent.descriptor.lct.size + 1)
99 }),
100 },
101 (stream, result, parent) => {
102 return parent.descriptor.lct.exists
103 }
104 ),
105 { data: [{ minCodeSize: readByte() }, subBlocksSchema] },
106 ],
107 },
108 (stream) => {
109 return peekByte()(stream) === 0x2c
110 }
111 )
112
113 // plain text block
114 const textSchema = conditional(
115 {
116 text: [
117 { codes: readBytes(2) },
118 { blockSize: readByte() },
119 {
120 preData: (stream, result, parent) =>
121 readBytes(parent.text.blockSize)(stream),
122 },
123 subBlocksSchema,
124 ],
125 },
126 (stream) => {
127 var codes = peekBytes(2)(stream)
128 return codes[0] === 0x21 && codes[1] === 0x01
129 }
130 )
131
132 // application block
133 const applicationSchema = conditional(
134 {
135 application: [
136 { codes: readBytes(2) },
137 { blockSize: readByte() },
138 { id: (stream, result, parent) => readString(parent.blockSize)(stream) },
139 subBlocksSchema,
140 ],
141 },
142 (stream) => {
143 var codes = peekBytes(2)(stream)
144 return codes[0] === 0x21 && codes[1] === 0xff
145 }
146 )
147
148 // comment block
149 const commentSchema = conditional(
150 {
151 comment: [{ codes: readBytes(2) }, subBlocksSchema],
152 },
153 (stream) => {
154 var codes = peekBytes(2)(stream)
155 return codes[0] === 0x21 && codes[1] === 0xfe
156 }
157 )
158
159 const schema = [
160 { header: [{ signature: readString(3) }, { version: readString(3) }] },
161 {
162 lsd: [
163 { width: readUnsigned(true) },
164 { height: readUnsigned(true) },
165 {
166 gct: readBits({
167 exists: { index: 0 },
168 resolution: { index: 1, length: 3 },
169 sort: { index: 4 },
170 size: { index: 5, length: 3 },
171 }),
172 },
173 { backgroundColorIndex: readByte() },
174 { pixelAspectRatio: readByte() },
175 ],
176 },
177 conditional(
178 {
179 gct: readArray(3, (stream, result) =>
180 Math.pow(2, result.lsd.gct.size + 1)
181 ),
182 },
183 (stream, result) => result.lsd.gct.exists
184 ),
185 // content frames
186 {
187 frames: loop(
188 [gceSchema, applicationSchema, commentSchema, imageSchema, textSchema],
189 (stream) => {
190 var nextCode = peekByte()(stream)
191 // rather than check for a terminator, we should check for the existence
192 // of an ext or image block to avoid infinite loops
193 //var terminator = 0x3B;
194 //return nextCode !== terminator;
195 return nextCode === 0x21 || nextCode === 0x2c
196 }
197 ),
198 },
199 ]
200
201 export default schema
1 import {IncomingMessage} from 'http';
2
3 /**
4 Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
5
6 Makes `toStream` include the properties from `fromStream`.
7
8 @param fromStream - The stream to copy the properties from.
9 @param toStream - The stream to copy the properties to.
10 @return The same object as `toStream`.
11 */
12 declare function mimicResponse<T extends NodeJS.ReadableStream>(
13 fromStream: IncomingMessage, // eslint-disable-line @typescript-eslint/prefer-readonly-parameter-types
14 toStream: T,
15 ): T & IncomingMessage;
16
17 export = mimicResponse;
1 'use strict';
2
3 // We define these manually to ensure they're always copied
4 // even if they would move up the prototype chain
5 // https://nodejs.org/api/http.html#http_class_http_incomingmessage
6 const knownProperties = [
7 'aborted',
8 'complete',
9 'headers',
10 'httpVersion',
11 'httpVersionMinor',
12 'httpVersionMajor',
13 'method',
14 'rawHeaders',
15 'rawTrailers',
16 'setTimeout',
17 'socket',
18 'statusCode',
19 'statusMessage',
20 'trailers',
21 'url'
22 ];
23
24 module.exports = (fromStream, toStream) => {
25 if (toStream._readableState.autoDestroy) {
26 throw new Error('The second stream must have the `autoDestroy` option set to `false`');
27 }
28
29 const fromProperties = new Set(Object.keys(fromStream).concat(knownProperties));
30
31 const properties = {};
32
33 for (const property of fromProperties) {
34 // Don't overwrite existing properties.
35 if (property in toStream) {
36 continue;
37 }
38
39 properties[property] = {
40 get() {
41 const value = fromStream[property];
42 const isFunction = typeof value === 'function';
43
44 return isFunction ? value.bind(fromStream) : value;
45 },
46 set(value) {
47 fromStream[property] = value;
48 },
49 enumerable: true,
50 configurable: false
51 };
52 }
53
54 Object.defineProperties(toStream, properties);
55
56 fromStream.once('aborted', () => {
57 toStream.destroy();
58
59 toStream.emit('aborted');
60 });
61
62 fromStream.once('close', () => {
63 if (fromStream.complete) {
64 if (toStream.readable) {
65 toStream.once('end', () => {
66 toStream.emit('close');
67 });
68 } else {
69 toStream.emit('close');
70 }
71 } else {
72 toStream.emit('close');
73 }
74 });
75
76 return toStream;
77 };
1 MIT License
2
3 Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
7 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 {
2 "_from": "mimic-response@^3.1.0",
3 "_id": "mimic-response@3.1.0",
4 "_inBundle": false,
5 "_integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
6 "_location": "/mimic-response",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "mimic-response@^3.1.0",
12 "name": "mimic-response",
13 "escapedName": "mimic-response",
14 "rawSpec": "^3.1.0",
15 "saveSpec": null,
16 "fetchSpec": "^3.1.0"
17 },
18 "_requiredBy": [
19 "/decompress-response"
20 ],
21 "_resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz",
22 "_shasum": "2d1d59af9c1b129815accc2c46a022a5ce1fa3c9",
23 "_spec": "mimic-response@^3.1.0",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/decompress-response",
25 "author": {
26 "name": "Sindre Sorhus",
27 "email": "sindresorhus@gmail.com",
28 "url": "https://sindresorhus.com"
29 },
30 "bugs": {
31 "url": "https://github.com/sindresorhus/mimic-response/issues"
32 },
33 "bundleDependencies": false,
34 "deprecated": false,
35 "description": "Mimic a Node.js HTTP response stream",
36 "devDependencies": {
37 "@types/node": "^14.0.1",
38 "ava": "^2.4.0",
39 "create-test-server": "^2.4.0",
40 "p-event": "^4.1.0",
41 "pify": "^5.0.0",
42 "tsd": "^0.11.0",
43 "xo": "^0.30.0"
44 },
45 "engines": {
46 "node": ">=10"
47 },
48 "files": [
49 "index.d.ts",
50 "index.js"
51 ],
52 "funding": "https://github.com/sponsors/sindresorhus",
53 "homepage": "https://github.com/sindresorhus/mimic-response#readme",
54 "keywords": [
55 "mimic",
56 "response",
57 "stream",
58 "http",
59 "https",
60 "request",
61 "get",
62 "core"
63 ],
64 "license": "MIT",
65 "name": "mimic-response",
66 "repository": {
67 "type": "git",
68 "url": "git+https://github.com/sindresorhus/mimic-response.git"
69 },
70 "scripts": {
71 "test": "xo && ava && tsd"
72 },
73 "version": "3.1.0"
74 }
1 # mimic-response [![Build Status](https://travis-ci.com/sindresorhus/mimic-response.svg?branch=master)](https://travis-ci.com/sindresorhus/mimic-response)
2
3 > Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
4
5 ## Install
6
7 ```
8 $ npm install mimic-response
9 ```
10
11 ## Usage
12
13 ```js
14 const stream = require('stream');
15 const mimicResponse = require('mimic-response');
16
17 const responseStream = getHttpResponseStream();
18 const myStream = new stream.PassThrough();
19
20 mimicResponse(responseStream, myStream);
21
22 console.log(myStream.statusCode);
23 //=> 200
24 ```
25
26 ## API
27
28 ### mimicResponse(from, to)
29
30 **Note #1:** The `from.destroy(error)` function is not proxied. You have to call it manually:
31
32 ```js
33 const stream = require('stream');
34 const mimicResponse = require('mimic-response');
35
36 const responseStream = getHttpResponseStream();
37
38 const myStream = new stream.PassThrough({
39 destroy(error, callback) {
40 responseStream.destroy();
41
42 callback(error);
43 }
44 });
45
46 myStream.destroy();
47 ```
48
49 Please note that `myStream` and `responseStream` never throws. The error is passed to the request instead.
50
51 #### from
52
53 Type: `Stream`
54
55 [Node.js HTTP response stream.](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
56
57 #### to
58
59 Type: `Stream`
60
61 Any stream.
62
63 ## Related
64
65 - [mimic-fn](https://github.com/sindresorhus/mimic-fn) - Make a function mimic another one
66 - [clone-response](https://github.com/lukechilds/clone-response) - Clone a Node.js response stream
67
68 ---
69
70 <div align="center">
71 <b>
72 <a href="https://tidelift.com/subscription/pkg/npm-mimic-response?utm_source=npm-mimic-response&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
73 </b>
74 <br>
75 <sub>
76 Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
77 </sub>
78 </div>
1 The MIT License (MIT)
2 Copyright © 2016 Dmitry Ivanov
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
6 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
8 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 # parenthesis [![Build Status](https://travis-ci.org/dy/parenthesis.svg?branch=master)](https://travis-ci.org/dy/parenthesis)
2
3 Parse parentheses from a string, return folded arrays.
4
5 [![npm install parenthesis](https://nodei.co/npm/parenthesis.png?mini=true)](https://npmjs.org/package/parenthesis/)
6
7
8 ```js
9 var parse = require('parenthesis')
10
11 // Parse into nested format
12 parse('a(b[c{d}])')
13 // ['a(', ['b[', ['c{', ['d'], '}'], ']'], ')']
14
15 // Parse into flat format with cross-references
16 parse('a(b[c{d}])', {
17 brackets: ['()'],
18 escape: '\\',
19 flat: true
20 })
21 // ['a(\\1)', 'b[c{d}]']
22
23
24 // Stringify nested format
25 parse.stringify(['a(', ['b[', ['c{', ['d'], '}'], ']'], ')'])
26 // 'a(b[c{d}])'
27
28 // Stringify flat format with cross-references
29 parse.stringify(['a(\\1)', 'b[c{d}]'], {flat: true, escape: '\\'})
30 // 'a(b[c{d}])'
31 ```
32
33 ## API
34
35 ### tokens = paren.parse(string, brackets|opts?)
36
37 Return array with tokens.
38
39 Option | Default | Meaning
40 ---|---|---
41 `brackets` | `['{}', '[]', '()']` | Single brackets string or list of strings to detect brackets. Can be repeating brackets eg. `"" or ''`.
42 `escape` | `'___'` | Escape prefix for flat references.
43 `flat` | `false` | Return flat array instead of nested arrays.
44
45 ### str = paren.stringify(tokens, {flat}?)
46
47 Stringify tokens back. Pass `{flat: true}` flag for flat tokens array.
48
49 ## Related
50
51 * [balanced-match](http://npmjs.org/package/balanced-match)
52
53
54 ## License
55
56 © 2018 Dmitry Yv. MIT License
1 declare module "parenthesis" {
2 namespace parens {
3 // One entry in the returned nested array
4 type Node = string | ArrayTree;
5 // A nested array of strings
6 interface ArrayTree extends Array<Node> {}
7 // Second-argument options used by the function
8 interface Opts {
9 // Single brackets string or list of strings to detect brackets. Can be repeating brackets eg. "" or ''.
10 brackets?: string | string[],
11 // Escape prefix for flat references.
12 escape?: string,
13 // `flat` is a boolean but since it affects return type, it's explicitly specified below
14 }
15
16 // Parse parentheses from a string, return folded arrays
17 function parse(
18 str: string,
19 opts?: string | string[] | (parens.Opts & { flat?: false })
20 ): parens.ArrayTree;
21 // Parse parentheses from a string, return flat array
22 function parse(
23 str: string,
24 opts: (parens.Opts & { flat: true })
25 ): string[];
26
27 // Stringify tokens back. Pass {flat: true} flag for flat tokens array.
28 function stringify(tokens: ArrayTree, opts?: {flat: boolean}): string;
29 }
30
31 // Parse parentheses from a string, return folded arrays
32 function parens(
33 str: string,
34 opts?: string | string[] | (parens.Opts & { flat?: false })
35 ): parens.ArrayTree;
36 // Parse parentheses from a string, return flat array
37 function parens(
38 str: string,
39 opts: (parens.Opts & { flat: true })
40 ): string[];
41 function parens(tokens: parens.ArrayTree, opts?: {flat: boolean}): string;
42
43 // imports via `import paren from "parenthesis", can call the export
44 // directly or use `paren.parse` / `paren.stringify`.
45 export = parens;
46 }
1 'use strict'
2
3 /**
4 * @module parenthesis
5 */
6
7 function parse (str, opts) {
8 // pretend non-string parsed per-se
9 if (typeof str !== 'string') return [str]
10
11 var res = [str]
12
13 if (typeof opts === 'string' || Array.isArray(opts)) {
14 opts = {brackets: opts}
15 }
16 else if (!opts) opts = {}
17
18 var brackets = opts.brackets ? (Array.isArray(opts.brackets) ? opts.brackets : [opts.brackets]) : ['{}', '[]', '()']
19
20 var escape = opts.escape || '___'
21
22 var flat = !!opts.flat
23
24 brackets.forEach(function (bracket) {
25 // create parenthesis regex
26 var pRE = new RegExp(['\\', bracket[0], '[^\\', bracket[0], '\\', bracket[1], ']*\\', bracket[1]].join(''))
27
28 var ids = []
29
30 function replaceToken(token, idx, str){
31 // save token to res
32 var refId = res.push(token.slice(bracket[0].length, -bracket[1].length)) - 1
33
34 ids.push(refId)
35
36 return escape + refId + escape
37 }
38
39 res.forEach(function (str, i) {
40 var prevStr
41
42 // replace paren tokens till there’s none
43 var a = 0
44 while (str != prevStr) {
45 prevStr = str
46 str = str.replace(pRE, replaceToken)
47 if (a++ > 10e3) throw Error('References have circular dependency. Please, check them.')
48 }
49
50 res[i] = str
51 })
52
53 // wrap found refs to brackets
54 ids = ids.reverse()
55 res = res.map(function (str) {
56 ids.forEach(function (id) {
57 str = str.replace(new RegExp('(\\' + escape + id + '\\' + escape + ')', 'g'), bracket[0] + '$1' + bracket[1])
58 })
59 return str
60 })
61 })
62
63 var re = new RegExp('\\' + escape + '([0-9]+)' + '\\' + escape)
64
65 // transform references to tree
66 function nest (str, refs, escape) {
67 var res = [], match
68
69 var a = 0
70 while (match = re.exec(str)) {
71 if (a++ > 10e3) throw Error('Circular references in parenthesis')
72
73 res.push(str.slice(0, match.index))
74
75 res.push(nest(refs[match[1]], refs))
76
77 str = str.slice(match.index + match[0].length)
78 }
79
80 res.push(str)
81
82 return res
83 }
84
85 return flat ? res : nest(res[0], res)
86 }
87
88 function stringify (arg, opts) {
89 if (opts && opts.flat) {
90 var escape = opts && opts.escape || '___'
91
92 var str = arg[0], prevStr
93
94 // pretend bad string stringified with no parentheses
95 if (!str) return ''
96
97
98 var re = new RegExp('\\' + escape + '([0-9]+)' + '\\' + escape)
99
100 var a = 0
101 while (str != prevStr) {
102 if (a++ > 10e3) throw Error('Circular references in ' + arg)
103 prevStr = str
104 str = str.replace(re, replaceRef)
105 }
106
107 return str
108 }
109
110 return arg.reduce(function f (prev, curr) {
111 if (Array.isArray(curr)) {
112 curr = curr.reduce(f, '')
113 }
114 return prev + curr
115 }, '')
116
117 function replaceRef(match, idx){
118 if (arg[idx] == null) throw Error('Reference ' + idx + 'is undefined')
119 return arg[idx]
120 }
121 }
122
123 function parenthesis (arg, opts) {
124 if (Array.isArray(arg)) {
125 return stringify(arg, opts)
126 }
127 else {
128 return parse(arg, opts)
129 }
130 }
131
132 parenthesis.parse = parse
133 parenthesis.stringify = stringify
134
135 module.exports = parenthesis
1 {
2 "_from": "parenthesis@^3.1.5",
3 "_id": "parenthesis@3.1.8",
4 "_inBundle": false,
5 "_integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==",
6 "_location": "/parenthesis",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "parenthesis@^3.1.5",
12 "name": "parenthesis",
13 "escapedName": "parenthesis",
14 "rawSpec": "^3.1.5",
15 "saveSpec": null,
16 "fetchSpec": "^3.1.5"
17 },
18 "_requiredBy": [
19 "/string-split-by"
20 ],
21 "_resolved": "https://registry.npmmirror.com/parenthesis/-/parenthesis-3.1.8.tgz",
22 "_shasum": "3457fccb8f05db27572b841dad9d2630b912f125",
23 "_spec": "parenthesis@^3.1.5",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/string-split-by",
25 "author": {
26 "name": "Dmitry Yv",
27 "email": "df.creative@gmail.com",
28 "url": "http://github.com/dy"
29 },
30 "bugs": {
31 "url": "https://github.com/dy/parenthesis/issues"
32 },
33 "bundleDependencies": false,
34 "dependencies": {},
35 "deprecated": false,
36 "description": "Parse parentheses from a string",
37 "devDependencies": {
38 "tape": "^4.9.0"
39 },
40 "files": [
41 "index.js",
42 "index.d.ts"
43 ],
44 "homepage": "https://github.com/dy/parenthesis",
45 "keywords": [
46 "paren",
47 "parenthesis",
48 "parse",
49 "brackets",
50 "parser",
51 "regexp",
52 "stringify",
53 "tokenizer",
54 "replace",
55 "csv",
56 "string"
57 ],
58 "license": "MIT",
59 "main": "index.js",
60 "name": "parenthesis",
61 "repository": {
62 "type": "git",
63 "url": "git://github.com/dy/parenthesis.git"
64 },
65 "scripts": {
66 "test": "node test.js",
67 "test:browser": "budo test.js"
68 },
69 "types": "index.d.ts",
70 "version": "3.1.8"
71 }
1 language: node_js
2 node_js:
3 - lts/*
1 The MIT License (MIT)
2
3 Copyright (c) Feross Aboukhadijeh
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy of
6 this software and associated documentation files (the "Software"), to deal in
7 the Software without restriction, including without limitation the rights to
8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 the Software, and to permit persons to whom the Software is furnished to do so,
10 subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 # simple-concat [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
2
3 [travis-image]: https://img.shields.io/travis/feross/simple-concat/master.svg
4 [travis-url]: https://travis-ci.org/feross/simple-concat
5 [npm-image]: https://img.shields.io/npm/v/simple-concat.svg
6 [npm-url]: https://npmjs.org/package/simple-concat
7 [downloads-image]: https://img.shields.io/npm/dm/simple-concat.svg
8 [downloads-url]: https://npmjs.org/package/simple-concat
9 [standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
10 [standard-url]: https://standardjs.com
11
12 ### Super-minimalist version of [`concat-stream`](https://github.com/maxogden/concat-stream). Less than 15 lines!
13
14 ## install
15
16 ```
17 npm install simple-concat
18 ```
19
20 ## usage
21
22 This example is longer than the implementation.
23
24 ```js
25 var s = new stream.PassThrough()
26 concat(s, function (err, buf) {
27 if (err) throw err
28 console.error(buf)
29 })
30 s.write('abc')
31 setTimeout(function () {
32 s.write('123')
33 }, 10)
34 setTimeout(function () {
35 s.write('456')
36 }, 20)
37 setTimeout(function () {
38 s.end('789')
39 }, 30)
40 ```
41
42 ## license
43
44 MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org).
1 /*! simple-concat. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
2 module.exports = function (stream, cb) {
3 var chunks = []
4 stream.on('data', function (chunk) {
5 chunks.push(chunk)
6 })
7 stream.once('end', function () {
8 if (cb) cb(null, Buffer.concat(chunks))
9 cb = null
10 })
11 stream.once('error', function (err) {
12 if (cb) cb(err)
13 cb = null
14 })
15 }
1 {
2 "_from": "simple-concat@^1.0.0",
3 "_id": "simple-concat@1.0.1",
4 "_inBundle": false,
5 "_integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
6 "_location": "/simple-concat",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "simple-concat@^1.0.0",
12 "name": "simple-concat",
13 "escapedName": "simple-concat",
14 "rawSpec": "^1.0.0",
15 "saveSpec": null,
16 "fetchSpec": "^1.0.0"
17 },
18 "_requiredBy": [
19 "/simple-get"
20 ],
21 "_resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz",
22 "_shasum": "f46976082ba35c2263f1c8ab5edfe26c41c9552f",
23 "_spec": "simple-concat@^1.0.0",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/simple-get",
25 "author": {
26 "name": "Feross Aboukhadijeh",
27 "email": "feross@feross.org",
28 "url": "https://feross.org"
29 },
30 "bugs": {
31 "url": "https://github.com/feross/simple-concat/issues"
32 },
33 "bundleDependencies": false,
34 "dependencies": {},
35 "deprecated": false,
36 "description": "Super-minimalist version of `concat-stream`. Less than 15 lines!",
37 "devDependencies": {
38 "standard": "*",
39 "tape": "^5.0.1"
40 },
41 "funding": [
42 {
43 "type": "github",
44 "url": "https://github.com/sponsors/feross"
45 },
46 {
47 "type": "patreon",
48 "url": "https://www.patreon.com/feross"
49 },
50 {
51 "type": "consulting",
52 "url": "https://feross.org/support"
53 }
54 ],
55 "homepage": "https://github.com/feross/simple-concat",
56 "keywords": [
57 "concat",
58 "concat-stream",
59 "concat stream"
60 ],
61 "license": "MIT",
62 "main": "index.js",
63 "name": "simple-concat",
64 "repository": {
65 "type": "git",
66 "url": "git://github.com/feross/simple-concat.git"
67 },
68 "scripts": {
69 "test": "standard && tape test/*.js"
70 },
71 "version": "1.0.1"
72 }
1 var concat = require('../')
2 var stream = require('stream')
3 var test = require('tape')
4
5 test('basic', function (t) {
6 t.plan(2)
7 var s = new stream.PassThrough()
8 concat(s, function (err, buf) {
9 t.error(err)
10 t.deepEqual(buf, Buffer.from('abc123456789'))
11 })
12 s.write('abc')
13 setTimeout(function () {
14 s.write('123')
15 }, 10)
16 setTimeout(function () {
17 s.write('456')
18 }, 20)
19 setTimeout(function () {
20 s.end('789')
21 }, 30)
22 })
23
24 test('error', function (t) {
25 t.plan(2)
26 var s = new stream.PassThrough()
27 concat(s, function (err, buf) {
28 t.ok(err, 'got expected error')
29 t.ok(!buf)
30 })
31 s.write('abc')
32 setTimeout(function () {
33 s.write('123')
34 }, 10)
35 setTimeout(function () {
36 s.write('456')
37 }, 20)
38 setTimeout(function () {
39 s.emit('error', new Error('error'))
40 }, 30)
41 })
1 version: 2
2 updates:
3 - package-ecosystem: npm
4 directory: /
5 schedule:
6 interval: daily
7 labels:
8 - dependency
9 versioning-strategy: increase-if-necessary
10 - package-ecosystem: github-actions
11 directory: /
12 schedule:
13 interval: daily
14 labels:
15 - dependency
1 name: ci
2 'on':
3 - push
4 - pull_request
5 jobs:
6 test:
7 name: Node ${{ matrix.node }} / ${{ matrix.os }}
8 runs-on: ${{ matrix.os }}
9 strategy:
10 fail-fast: false
11 matrix:
12 os:
13 - ubuntu-latest
14 node:
15 - '14'
16 steps:
17 - uses: actions/checkout@v2
18 - uses: actions/setup-node@v2
19 with:
20 node-version: ${{ matrix.node }}
21 - run: npm install
22 - run: npm run build --if-present
23 - run: npm test
1 The MIT License (MIT)
2
3 Copyright (c) Feross Aboukhadijeh
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy of
6 this software and associated documentation files (the "Software"), to deal in
7 the Software without restriction, including without limitation the rights to
8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 the Software, and to permit persons to whom the Software is furnished to do so,
10 subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 # simple-get [![ci][ci-image]][ci-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
2
3 [ci-image]: https://img.shields.io/github/workflow/status/feross/simple-get/ci/master
4 [ci-url]: https://github.com/feross/simple-get/actions
5 [npm-image]: https://img.shields.io/npm/v/simple-get.svg
6 [npm-url]: https://npmjs.org/package/simple-get
7 [downloads-image]: https://img.shields.io/npm/dm/simple-get.svg
8 [downloads-url]: https://npmjs.org/package/simple-get
9 [standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
10 [standard-url]: https://standardjs.com
11
12 ### Simplest way to make http get requests
13
14 ## features
15
16 This module is the lightest possible wrapper on top of node.js `http`, but supporting these essential features:
17
18 - follows redirects
19 - automatically handles gzip/deflate responses
20 - supports HTTPS
21 - supports specifying a timeout
22 - supports convenience `url` key so there's no need to use `url.parse` on the url when specifying options
23 - composes well with npm packages for features like cookies, proxies, form data, & OAuth
24
25 All this in < 100 lines of code.
26
27 ## install
28
29 ```
30 npm install simple-get
31 ```
32
33 ## usage
34
35 Note, all these examples also work in the browser with [browserify](http://browserify.org/).
36
37 ### simple GET request
38
39 Doesn't get easier than this:
40
41 ```js
42 const get = require('simple-get')
43
44 get('http://example.com', function (err, res) {
45 if (err) throw err
46 console.log(res.statusCode) // 200
47 res.pipe(process.stdout) // `res` is a stream
48 })
49 ```
50
51 ### even simpler GET request
52
53 If you just want the data, and don't want to deal with streams:
54
55 ```js
56 const get = require('simple-get')
57
58 get.concat('http://example.com', function (err, res, data) {
59 if (err) throw err
60 console.log(res.statusCode) // 200
61 console.log(data) // Buffer('this is the server response')
62 })
63 ```
64
65 ### POST, PUT, PATCH, HEAD, DELETE support
66
67 For `POST`, call `get.post` or use option `{ method: 'POST' }`.
68
69 ```js
70 const get = require('simple-get')
71
72 const opts = {
73 url: 'http://example.com',
74 body: 'this is the POST body'
75 }
76 get.post(opts, function (err, res) {
77 if (err) throw err
78 res.pipe(process.stdout) // `res` is a stream
79 })
80 ```
81
82 #### A more complex example:
83
84 ```js
85 const get = require('simple-get')
86
87 get({
88 url: 'http://example.com',
89 method: 'POST',
90 body: 'this is the POST body',
91
92 // simple-get accepts all options that node.js `http` accepts
93 // See: http://nodejs.org/api/http.html#http_http_request_options_callback
94 headers: {
95 'user-agent': 'my cool app'
96 }
97 }, function (err, res) {
98 if (err) throw err
99
100 // All properties/methods from http.IncomingResponse are available,
101 // even if a gunzip/inflate transform stream was returned.
102 // See: http://nodejs.org/api/http.html#http_http_incomingmessage
103 res.setTimeout(10000)
104 console.log(res.headers)
105
106 res.on('data', function (chunk) {
107 // `chunk` is the decoded response, after it's been gunzipped or inflated
108 // (if applicable)
109 console.log('got a chunk of the response: ' + chunk)
110 }))
111
112 })
113 ```
114
115 ### JSON
116
117 You can serialize/deserialize request and response with JSON:
118
119 ```js
120 const get = require('simple-get')
121
122 const opts = {
123 method: 'POST',
124 url: 'http://example.com',
125 body: {
126 key: 'value'
127 },
128 json: true
129 }
130 get.concat(opts, function (err, res, data) {
131 if (err) throw err
132 console.log(data.key) // `data` is an object
133 })
134 ```
135
136 ### Timeout
137
138 You can set a timeout (in milliseconds) on the request with the `timeout` option.
139 If the request takes longer than `timeout` to complete, then the entire request
140 will fail with an `Error`.
141
142 ```js
143 const get = require('simple-get')
144
145 const opts = {
146 url: 'http://example.com',
147 timeout: 2000 // 2 second timeout
148 }
149
150 get(opts, function (err, res) {})
151 ```
152
153 ### One Quick Tip
154
155 It's a good idea to set the `'user-agent'` header so the provider can more easily
156 see how their resource is used.
157
158 ```js
159 const get = require('simple-get')
160 const pkg = require('./package.json')
161
162 get('http://example.com', {
163 headers: {
164 'user-agent': `my-module/${pkg.version} (https://github.com/username/my-module)`
165 }
166 })
167 ```
168
169 ### Proxies
170
171 You can use the [`tunnel`](https://github.com/koichik/node-tunnel) module with the
172 `agent` option to work with proxies:
173
174 ```js
175 const get = require('simple-get')
176 const tunnel = require('tunnel')
177
178 const opts = {
179 url: 'http://example.com',
180 agent: tunnel.httpOverHttp({
181 proxy: {
182 host: 'localhost'
183 }
184 })
185 }
186
187 get(opts, function (err, res) {})
188 ```
189
190 ### Cookies
191
192 You can use the [`cookie`](https://github.com/jshttp/cookie) module to include
193 cookies in a request:
194
195 ```js
196 const get = require('simple-get')
197 const cookie = require('cookie')
198
199 const opts = {
200 url: 'http://example.com',
201 headers: {
202 cookie: cookie.serialize('foo', 'bar')
203 }
204 }
205
206 get(opts, function (err, res) {})
207 ```
208
209 ### Form data
210
211 You can use the [`form-data`](https://github.com/form-data/form-data) module to
212 create POST request with form data:
213
214 ```js
215 const fs = require('fs')
216 const get = require('simple-get')
217 const FormData = require('form-data')
218 const form = new FormData()
219
220 form.append('my_file', fs.createReadStream('/foo/bar.jpg'))
221
222 const opts = {
223 url: 'http://example.com',
224 body: form
225 }
226
227 get.post(opts, function (err, res) {})
228 ```
229
230 #### Or, include `application/x-www-form-urlencoded` form data manually:
231
232 ```js
233 const get = require('simple-get')
234
235 const opts = {
236 url: 'http://example.com',
237 form: {
238 key: 'value'
239 }
240 }
241 get.post(opts, function (err, res) {})
242 ```
243
244 ### Specifically disallowing redirects
245
246 ```js
247 const get = require('simple-get')
248
249 const opts = {
250 url: 'http://example.com/will-redirect-elsewhere',
251 followRedirects: false
252 }
253 // res.statusCode will be 301, no error thrown
254 get(opts, function (err, res) {})
255 ```
256
257 ### Basic Auth
258
259 ```js
260 const user = 'someuser'
261 const pass = 'pa$$word'
262 const encodedAuth = Buffer.from(`${user}:${pass}`).toString('base64')
263
264 get('http://example.com', {
265 headers: {
266 authorization: `Basic ${encodedAuth}`
267 }
268 })
269 ```
270
271 ### OAuth
272
273 You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) module to create
274 a signed OAuth request:
275
276 ```js
277 const get = require('simple-get')
278 const crypto = require('crypto')
279 const OAuth = require('oauth-1.0a')
280
281 const oauth = OAuth({
282 consumer: {
283 key: process.env.CONSUMER_KEY,
284 secret: process.env.CONSUMER_SECRET
285 },
286 signature_method: 'HMAC-SHA1',
287 hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
288 })
289
290 const token = {
291 key: process.env.ACCESS_TOKEN,
292 secret: process.env.ACCESS_TOKEN_SECRET
293 }
294
295 const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json'
296
297 const opts = {
298 url: url,
299 headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
300 json: true
301 }
302
303 get(opts, function (err, res) {})
304 ```
305
306 ### Throttle requests
307
308 You can use [limiter](https://github.com/jhurliman/node-rate-limiter) to throttle requests. This is useful when calling an API that is rate limited.
309
310 ```js
311 const simpleGet = require('simple-get')
312 const RateLimiter = require('limiter').RateLimiter
313 const limiter = new RateLimiter(1, 'second')
314
315 const get = (opts, cb) => limiter.removeTokens(1, () => simpleGet(opts, cb))
316 get.concat = (opts, cb) => limiter.removeTokens(1, () => simpleGet.concat(opts, cb))
317
318 var opts = {
319 url: 'http://example.com'
320 }
321
322 get.concat(opts, processResult)
323 get.concat(opts, processResult)
324
325 function processResult (err, res, data) {
326 if (err) throw err
327 console.log(data.toString())
328 }
329 ```
330
331 ## license
332
333 MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org).
1 /*! simple-get. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
2 module.exports = simpleGet
3
4 const concat = require('simple-concat')
5 const decompressResponse = require('decompress-response') // excluded from browser build
6 const http = require('http')
7 const https = require('https')
8 const once = require('once')
9 const querystring = require('querystring')
10 const url = require('url')
11
12 const isStream = o => o !== null && typeof o === 'object' && typeof o.pipe === 'function'
13
14 function simpleGet (opts, cb) {
15 opts = Object.assign({ maxRedirects: 10 }, typeof opts === 'string' ? { url: opts } : opts)
16 cb = once(cb)
17
18 if (opts.url) {
19 const { hostname, port, protocol, auth, path } = url.parse(opts.url) // eslint-disable-line node/no-deprecated-api
20 delete opts.url
21 if (!hostname && !port && !protocol && !auth) opts.path = path // Relative redirect
22 else Object.assign(opts, { hostname, port, protocol, auth, path }) // Absolute redirect
23 }
24
25 const headers = { 'accept-encoding': 'gzip, deflate' }
26 if (opts.headers) Object.keys(opts.headers).forEach(k => (headers[k.toLowerCase()] = opts.headers[k]))
27 opts.headers = headers
28
29 let body
30 if (opts.body) {
31 body = opts.json && !isStream(opts.body) ? JSON.stringify(opts.body) : opts.body
32 } else if (opts.form) {
33 body = typeof opts.form === 'string' ? opts.form : querystring.stringify(opts.form)
34 opts.headers['content-type'] = 'application/x-www-form-urlencoded'
35 }
36
37 if (body) {
38 if (!opts.method) opts.method = 'POST'
39 if (!isStream(body)) opts.headers['content-length'] = Buffer.byteLength(body)
40 if (opts.json && !opts.form) opts.headers['content-type'] = 'application/json'
41 }
42 delete opts.body; delete opts.form
43
44 if (opts.json) opts.headers.accept = 'application/json'
45 if (opts.method) opts.method = opts.method.toUpperCase()
46
47 const originalHost = opts.hostname // hostname before potential redirect
48 const protocol = opts.protocol === 'https:' ? https : http // Support http/https urls
49 const req = protocol.request(opts, res => {
50 if (opts.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
51 opts.url = res.headers.location // Follow 3xx redirects
52 delete opts.headers.host // Discard `host` header on redirect (see #32)
53 res.resume() // Discard response
54
55 const redirectHost = url.parse(opts.url).hostname // eslint-disable-line node/no-deprecated-api
56 // If redirected host is different than original host, drop headers to prevent cookie leak (#73)
57 if (redirectHost !== null && redirectHost !== originalHost) {
58 delete opts.headers.cookie
59 delete opts.headers.authorization
60 }
61
62 if (opts.method === 'POST' && [301, 302].includes(res.statusCode)) {
63 opts.method = 'GET' // On 301/302 redirect, change POST to GET (see #35)
64 delete opts.headers['content-length']; delete opts.headers['content-type']
65 }
66
67 if (opts.maxRedirects-- === 0) return cb(new Error('too many redirects'))
68 else return simpleGet(opts, cb)
69 }
70
71 const tryUnzip = typeof decompressResponse === 'function' && opts.method !== 'HEAD'
72 cb(null, tryUnzip ? decompressResponse(res) : res)
73 })
74 req.on('timeout', () => {
75 req.abort()
76 cb(new Error('Request timed out'))
77 })
78 req.on('error', cb)
79
80 if (isStream(body)) body.on('error', cb).pipe(req)
81 else req.end(body)
82
83 return req
84 }
85
86 simpleGet.concat = (opts, cb) => {
87 return simpleGet(opts, (err, res) => {
88 if (err) return cb(err)
89 concat(res, (err, data) => {
90 if (err) return cb(err)
91 if (opts.json) {
92 try {
93 data = JSON.parse(data.toString())
94 } catch (err) {
95 return cb(err, res, data)
96 }
97 }
98 cb(null, res, data)
99 })
100 })
101 }
102
103 ;['get', 'post', 'put', 'patch', 'head', 'delete'].forEach(method => {
104 simpleGet[method] = (opts, cb) => {
105 if (typeof opts === 'string') opts = { url: opts }
106 return simpleGet(Object.assign({ method: method.toUpperCase() }, opts), cb)
107 }
108 })
1 {
2 "_from": "simple-get@^4.0.1",
3 "_id": "simple-get@4.0.1",
4 "_inBundle": false,
5 "_integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
6 "_location": "/simple-get",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "simple-get@^4.0.1",
12 "name": "simple-get",
13 "escapedName": "simple-get",
14 "rawSpec": "^4.0.1",
15 "saveSpec": null,
16 "fetchSpec": "^4.0.1"
17 },
18 "_requiredBy": [
19 "/vue-qr"
20 ],
21 "_resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-4.0.1.tgz",
22 "_shasum": "4a39db549287c979d352112fa03fd99fd6bc3543",
23 "_spec": "simple-get@^4.0.1",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr",
25 "author": {
26 "name": "Feross Aboukhadijeh",
27 "email": "feross@feross.org",
28 "url": "https://feross.org"
29 },
30 "browser": {
31 "decompress-response": false
32 },
33 "bugs": {
34 "url": "https://github.com/feross/simple-get/issues"
35 },
36 "bundleDependencies": false,
37 "dependencies": {
38 "decompress-response": "^6.0.0",
39 "once": "^1.3.1",
40 "simple-concat": "^1.0.0"
41 },
42 "deprecated": false,
43 "description": "Simplest way to make http get requests. Supports HTTPS, redirects, gzip/deflate, streams in < 100 lines.",
44 "devDependencies": {
45 "self-signed-https": "^1.0.5",
46 "standard": "*",
47 "string-to-stream": "^3.0.0",
48 "tape": "^5.0.0"
49 },
50 "funding": [
51 {
52 "type": "github",
53 "url": "https://github.com/sponsors/feross"
54 },
55 {
56 "type": "patreon",
57 "url": "https://www.patreon.com/feross"
58 },
59 {
60 "type": "consulting",
61 "url": "https://feross.org/support"
62 }
63 ],
64 "homepage": "https://github.com/feross/simple-get",
65 "keywords": [
66 "request",
67 "http",
68 "GET",
69 "get request",
70 "http.get",
71 "redirects",
72 "follow redirects",
73 "gzip",
74 "deflate",
75 "https",
76 "http-https",
77 "stream",
78 "simple request",
79 "simple get"
80 ],
81 "license": "MIT",
82 "main": "index.js",
83 "name": "simple-get",
84 "repository": {
85 "type": "git",
86 "url": "git://github.com/feross/simple-get.git"
87 },
88 "scripts": {
89 "test": "standard && tape test/*.js"
90 },
91 "version": "4.0.1"
92 }
1 {
2 "env": {
3 "browser": true,
4 "node": true,
5 "commonjs": true,
6 "es6": true
7 },
8 "extends": "eslint:recommended",
9 "rules": {
10 "strict": 2,
11 "indent": 0,
12 "linebreak-style": 0,
13 "quotes": 0,
14 "semi": 0,
15 "no-cond-assign": 1,
16 "no-constant-condition": 1,
17 "no-duplicate-case": 1,
18 "no-empty": 1,
19 "no-ex-assign": 1,
20 "no-extra-boolean-cast": 1,
21 "no-extra-semi": 1,
22 "no-fallthrough": 1,
23 "no-func-assign": 1,
24 "no-global-assign": 1,
25 "no-implicit-globals": 2,
26 "no-inner-declarations": ["error", "functions"],
27 "no-irregular-whitespace": 2,
28 "no-loop-func": 1,
29 "no-magic-numbers": ["warn", { "ignore": [1, 0, -1], "ignoreArrayIndexes": true}],
30 "no-multi-str": 1,
31 "no-mixed-spaces-and-tabs": 1,
32 "no-proto": 1,
33 "no-sequences": 1,
34 "no-throw-literal": 1,
35 "no-unmodified-loop-condition": 1,
36 "no-useless-call": 1,
37 "no-void": 1,
38 "no-with": 2,
39 "wrap-iife": 1,
40 "no-redeclare": 1,
41 "no-unused-vars": ["error", { "vars": "all", "args": "none" }],
42 "no-sparse-arrays": 1
43 }
44 }
1 language: node_js
2 node_js:
3 - '6'
4 - '5'
5 - '4'
1 'use strict'
2
3 var paren = require('parenthesis')
4
5 module.exports = function splitBy (string, separator, o) {
6 if (string == null) throw Error('First argument should be a string')
7 if (separator == null) throw Error('Separator should be a string or a RegExp')
8
9 if (!o) o = {}
10 else if (typeof o === 'string' || Array.isArray(o)) {
11 o = {ignore: o}
12 }
13
14 if (o.escape == null) o.escape = true
15 if (o.ignore == null) o.ignore = ['[]', '()', '{}', '<>', '""', "''", '``', '“”', '«»']
16 else {
17 if (typeof o.ignore === 'string') {o.ignore = [o.ignore]}
18
19 o.ignore = o.ignore.map(function (pair) {
20 // '"' → '""'
21 if (pair.length === 1) pair = pair + pair
22 return pair
23 })
24 }
25
26 var tokens = paren.parse(string, {flat: true, brackets: o.ignore})
27 var str = tokens[0]
28
29 var parts = str.split(separator)
30
31 // join parts separated by escape
32 if (o.escape) {
33 var cleanParts = []
34 for (var i = 0; i < parts.length; i++) {
35 var prev = parts[i]
36 var part = parts[i + 1]
37
38 if (prev[prev.length - 1] === '\\' && prev[prev.length - 2] !== '\\') {
39 cleanParts.push(prev + separator + part)
40 i++
41 }
42 else {
43 cleanParts.push(prev)
44 }
45 }
46 parts = cleanParts
47 }
48
49 // open parens pack & apply unquotes, if any
50 for (var i = 0; i < parts.length; i++) {
51 tokens[0] = parts[i]
52 parts[i] = paren.stringify(tokens, {flat: true})
53 }
54
55 return parts
56 }
1 {
2 "_from": "string-split-by@^1.0.0",
3 "_id": "string-split-by@1.0.0",
4 "_inBundle": false,
5 "_integrity": "sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==",
6 "_location": "/string-split-by",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "string-split-by@^1.0.0",
12 "name": "string-split-by",
13 "escapedName": "string-split-by",
14 "rawSpec": "^1.0.0",
15 "saveSpec": null,
16 "fetchSpec": "^1.0.0"
17 },
18 "_requiredBy": [
19 "/vue-qr"
20 ],
21 "_resolved": "https://registry.npmmirror.com/string-split-by/-/string-split-by-1.0.0.tgz",
22 "_shasum": "53895fb3397ebc60adab1f1e3a131f5372586812",
23 "_spec": "string-split-by@^1.0.0",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr",
25 "author": {
26 "name": "Dmitry Yv",
27 "email": "dfcreative@gmail.com"
28 },
29 "bugs": {
30 "url": "https://github.com/dy/string-split-by/issues"
31 },
32 "bundleDependencies": false,
33 "dependencies": {
34 "parenthesis": "^3.1.5"
35 },
36 "deprecated": false,
37 "description": "Split string by any separator excluding brackets, quotes and escaped characters",
38 "devDependencies": {
39 "tape": "^4.9.0"
40 },
41 "homepage": "https://github.com/dy/string-split-by#readme",
42 "keywords": [
43 "split-string",
44 "string-split",
45 "split-stirng-words",
46 "space",
47 "string",
48 "split"
49 ],
50 "license": "MIT",
51 "main": "index.js",
52 "name": "string-split-by",
53 "repository": {
54 "type": "git",
55 "url": "git+https://github.com/dy/string-split-by.git"
56 },
57 "scripts": {
58 "test": "node test.js"
59 },
60 "version": "1.0.0"
61 }
1 # string-split-by [![unstable](https://img.shields.io/badge/stability-unstable-orange.svg)](http://github.com/badges/stability-badges) [![Build Status](https://img.shields.io/travis/dy/string-split-by.svg)](https://travis-ci.org/dy/string-split-by)
2
3 Split string by a separator with respect to brackets, quotes and escape markers. Optimized version of [string-split](https://github.com/jonschlinkert/split-string).
4
5 ## Usage
6
7 [![npm install string-split-by](https://nodei.co/npm/string-split-by.png?mini=true)](https://npmjs.org/package/string-split-by/)
8
9
10 ```js
11 var split = require('string-split-by')
12
13 split('a."b.c".d.{.e.f.g.}.h', '.')
14 // ['a', '"b.c"', 'd', '{.e.f.g.}', 'h']
15
16 split('a."b.c".d.{.e.f.g.}.h', '.', {ignore: '""'})
17 // ['a', '"b.c"', 'd', '{', 'e', 'f', 'g', '}', 'h']
18 ```
19
20 ## API
21
22 ### parts = splitBy(string, separator, options?)
23
24 Return array with parts split from string by a separator, which can be whether _String_ or _RegExp_. Options can define:
25
26 Option | Default | Meaning
27 ---|---|---
28 `ignore` | ``['"', "'", '`', '“”', '«»', '[]', '()', '{}']`` | Avoid splitting content enclosed in the character pairs. Can be a string or a list of strings.
29 `escape` | `true` | Avoid splitting at the escaped separator, eg. `\.` won't be separated by `'.'` separator.
30
31
32 ## Related
33
34 * [parenthesis](http://npmjs.org/package/parenthesis)
35
36 ## License
37
38 © 2018 Dmitry Yv. MIT License
1 'use strict';
2
3 var t = require('tape')
4 var split = require('.');
5
6 t('should throw an error when arguments are invalid', t => {
7 t.throws(() => split());
8 t.end()
9 });
10
11 t('readme', t => {
12
13 t.deepEqual(
14 split('a."b.c".d.{.e.f.g.}.h', '.'),
15 ['a', '"b.c"', 'd', '{.e.f.g.}', 'h']
16 )
17
18 t.deepEqual(
19 split('a."b.c".d.{.e.f.g.}.h', '.', {ignore: '""'}),
20 ['a', '"b.c"', 'd', '{', 'e', 'f', 'g', '}', 'h']
21 )
22 t.end()
23 })
24
25 t('should not split on escaped dots:', t => {
26 t.deepEqual(split('a.b.c\\.d', '.'), ['a', 'b', 'c\\.d']);
27 t.deepEqual(split('a.b.c\\.d.e', '.'), ['a', 'b', 'c\\.d', 'e']);
28 t.end()
29 });
30
31 t('should keep escaping when followed by a backslash:', t => {
32 t.deepEqual(split('a.b.c\\\\.d', '.'), ['a', 'b', 'c\\\\', 'd']);
33 t.deepEqual(split('a.b.c\\\\d', '.'), ['a', 'b', 'c\\\\d']);
34 t.end()
35 });
36
37 t('should split a string on dots by default:', t => {
38 t.deepEqual(split('a.b.c', '.'), ['a', 'b', 'c']);
39 t.end()
40 });
41
42 t('should respect double-quoted strings', t => {
43 t.deepEqual(split('"b.c"', '.'), ['"b.c"']);
44 t.deepEqual(split('a."b.c"', '.'), ['a', '"b.c"']);
45 t.deepEqual(split('a".b.c"', '.'), ['a".b.c"']);
46 t.deepEqual(split('a."b.c".d', '.'), ['a', '"b.c"', 'd']);
47 t.deepEqual(split('a."b.c".d.".e.f.g.".h', '.'), ['a', '"b.c"', 'd', '".e.f.g."', 'h']);
48 t.end()
49 });
50
51 t('should respect singlequoted strings', t => {
52 t.deepEqual(split('\'b.c\'', '.'), ['\'b.c\'']);
53 t.deepEqual(split('a.\'b.c\'', '.'), ['a', '\'b.c\'']);
54 t.deepEqual(split('a.\'b.c\'.d', '.'), ['a', '\'b.c\'', 'd']);
55 t.deepEqual(split('a.\'b.c\'.d.\'.e.f.g.\'.h', '.'), ['a', '\'b.c\'', 'd', '\'.e.f.g.\'', 'h']);
56 t.end()
57 });
58
59 t('should respect strings in backticks', t => {
60 t.deepEqual(split('`b.c`', '.'), ['`b.c`']);
61 t.deepEqual(split('a.`b.c`', '.'), ['a', '`b.c`']);
62 t.deepEqual(split('a.`b.c`.d', '.'), ['a', '`b.c`', 'd']);
63 t.deepEqual(split('a.`b.c`.d.`.e.f.g.`.h', '.'), ['a', '`b.c`', 'd', '`.e.f.g.`', 'h']);
64 t.end()
65 });
66
67 t('should respect strings in double smart-quotes: “”', t => {
68 t.deepEqual(split('“b.c”', '.'), ['“b.c”']);
69 t.deepEqual(split('a.“b.c”', '.'), ['a', '“b.c”']);
70 t.deepEqual(split('a.“b.c”.d', '.'), ['a', '“b.c”', 'd']);
71 t.deepEqual(split('a.“b.c”.d.“.e.f.g.”.h', '.'), ['a', '“b.c”', 'd', '“.e.f.g.”', 'h']);
72 t.end()
73 });
74
75 t('should retain unclosed double quotes in the results', t => {
76 t.deepEqual(split('a."b.c', '.'), ['a', '"b', 'c']);
77 t.end()
78 });
79
80 t('should retain unclosed single quotes in the results', t => {
81 t.deepEqual(split('brian\'s', '.'), ['brian\'s']);
82 t.deepEqual(split('a.\'b.c', '.'), ['a', '\'b', 'c']);
83 t.end()
84 });
85
86
87
88 t('should split on a custom separator', t => {
89 t.deepEqual(split('a/b/c', '/'), ['a', 'b', 'c']);
90 t.deepEqual(split('a,b,c', ','), ['a', 'b', 'c']);
91 t.end()
92 });
93
94 t('should not split on an escaped custom separator:', t => {
95 t.deepEqual(split('a/b/c\\/d', '/'), ['a', 'b', 'c\\/d']);
96 t.end()
97 });
98
99 t('should disable quotes support', t => {
100 t.deepEqual(split('a.\'b.c\'."d"', '.', {ignore: '"'}), ['a', '\'b', 'c\'', '"d"']);
101 t.end()
102 });
103
104 t('should keep single quotes', t => {
105 t.deepEqual(split('a.\'b.c\'."d"', '.', {ignore: '\''}), ['a', '\'b.c\'', '"d"']);
106 t.end()
107 });
108
109 t('should keep double quotes', t => {
110 t.deepEqual(split('a."b.c".d', '.', '"'), ['a', '"b.c"', 'd']);
111 t.end()
112 });
113
114 t('should keep “” double quotes', t => {
115 t.deepEqual(split('a.“b.c”.d', '.', '“”'), ['a', '“b.c”', 'd']);
116 t.end()
117 });
118
119 t('should keep backticks', t => {
120 t.deepEqual(split('a.`b.c`.d', '.', {ignore: '`'}), ['a', '`b.c`', 'd']);
121 t.end()
122 });
123
124 t('should allow custom quotes object', t => {
125 t.deepEqual(split('a.^b.c$', '.', {ignore: '^$'}), ['a', '^b.c$']);
126 t.deepEqual(split('a.^b.c^', '.', {ignore: '^^'}), ['a', '^b.c^']);
127 t.deepEqual(split('a.~b.c~', '.', {ignore: '~~'}), ['a', '~b.c~']);
128 t.end()
129 });
130
131 t('should keep escape characters', t => {
132 t.deepEqual(split('a.b\\.c', '.', {escape: true}), ['a', 'b\\.c']);
133 t.end()
134 });
135
136 t.skip('should throw when brackets are unclosed', t => {
137 t.throws(function() {
138 }, /unclosed/);
139 t.end()
140 });
141
142 t('should not split inside brackets', t => {
143 t.deepEqual(split('a.(b.c).d', '.'), ['a', '(b.c)', 'd']);
144 t.deepEqual(split('a.[(b.c)].d', '.'), ['a', '[(b.c)]', 'd']);
145 t.deepEqual(split('a.[b.c].d', '.'), ['a', '[b.c]', 'd']);
146 t.deepEqual(split('a.{b.c}.d', '.'), ['a', '{b.c}', 'd']);
147 t.deepEqual(split('a.<b.c>.d', '.'), ['a', '<b.c>', 'd']);
148 t.end()
149 });
150
151 t('should support nested brackets', t => {
152 t.deepEqual(split('a.{b.{c}.d}.e', '.'), ['a', '{b.{c}.d}', 'e']);
153 t.deepEqual(split('a.{b.{c.d}.e}.f', '.'), ['a', '{b.{c.d}.e}', 'f']);
154 t.deepEqual(split('a.{[b.{{c.d}}.e]}.f', '.'), ['a', '{[b.{{c.d}}.e]}', 'f']);
155 t.end()
156 });
157
158 t.skip('should support escaped brackets', t => {
159 t.deepEqual(split('a.\\{b.{c.c}.d}.e', '.'), ['a', '{b', '{c.c}', 'd}', 'e']);
160 t.deepEqual(split('a.{b.c}.\\{d.e}.f', '.'), ['a', '{b.c}', '{d', 'e}', 'f']);
161 t.end()
162 });
163
164 t('should support quoted brackets', t => {
165 t.deepEqual(split('a.{b.c}."{d.e}".f', '.'), ['a', '{b.c}', '"{d.e}"', 'f']);
166 t.deepEqual(split('a.{b.c}.{"d.e"}.f', '.'), ['a', '{b.c}', '{"d.e"}', 'f']);
167 t.end()
168 });
169
170 t('should ignore imbalanced brackets', t => {
171 t.deepEqual(split('a.{b.c', '.'), ['a', '{b', 'c']);
172 t.deepEqual(split('a.{a.{b.c}.d', '.'), ['a', '{a', '{b.c}', 'd']);
173 t.end()
174 });
175
1 {
2 "presets": [
3 [
4 "@babel/preset-env",
5 {
6 "modules": false
7 }
8 ]
9 ],
10 "plugins": [
11 [
12 "@babel/plugin-transform-runtime",
13 {}
14 ],
15 "@babel/plugin-proposal-class-properties"
16 ]
17 }
1 root = true
2
3 [*]
4 charset = utf-8
5 indent_style = space
6 indent_size = 2
7 end_of_line = lf
8 insert_final_newline = true
9 trim_trailing_whitespace = true
1 module.exports = {
2 plugins: {
3 autoprefixer: {}
4 }
5 }
...\ No newline at end of file ...\ No newline at end of file
1 # Changelog
2 ## 4.0.9 | 2022.05.24
3 - Fix `path-browserify` export error
4
5 ## 4.0.6 | 2022.04.14
6 - Fix dependency error position
7
8 ## 4.0.5 | 2022.04.13
9 - Remove `canvas` dependency
10
11 ## 3.2.4 | 2022.01.19
12 - Update `canvas` version
13
14 ## 3.2.2 | 2021.10.13
15 - Bugfix: components default value [#100](https://github.com/Binaryify/vue-qr/pull/100)
16
17 - Update `components` default value
18
19 ## 3.2.0 | 2021.10.12
20 - Add `components` params [#98](https://github.com/Binaryify/vue-qr/issues/98)
21
22 ## 3.1.0 | 2021.10.05
23 - Support Vite [#90](https://github.com/Binaryify/vue-qr/issues/90) [#96](https://github.com/Binaryify/vue-qr/issues/96)
24
25 ## 3.0.0 | 2021.10.02
26 - Using Awesome-qr.js v2.0
27
28 - Support Vue v3.0(not support Vite yet) [#82](https://github.com/Binaryify/vue-qr/issues/82)
29
30 ## 2.3.1 | 2021.05.03
31 - Fixed [#86](https://github.com/Binaryify/vue-qr/issues/86)
32
33 ## 2.3.0 | 2020.10.05
34 - Support SSR
35
36 ## 2.2.0
37 - Fixed [#65](https://github.com/Binaryify/vue-qr/issues/65) [#68](https://github.com/Binaryify/vue-qr/issues/68)
38
39 - Set `dotScale` default value to 1
40
41 ## 2.1.0
42 - Fixed qr margin offset when logo is added (via:[https://github.com/SumiMakito/Awesome-qr.js/pull/38](https://github.com/SumiMakito/Awesome-qr.js/pull/38))
43
44
45 ## 2.0.7
46 - Improve image load function
47
48 ## 2.0.6
49 - Remove babel-polyfill [#53](https://github.com/Binaryify/vue-qr/issues/53)
50 - add .npmignore
51
52 ## 2.0.4
53 - Fix dotScale defalut value bug
54
55 ## 2.0.2
56 - Fix bug
57
58 ## 2.0.2
59 - Update README.MD
60
61 ## 2.0.1
62 - Fix colorLight can't set bug
63 - Support background color and logo background
64
65
66 ## 2.0.0
67 - Refactoring
68 - Support gif background
1 The MIT License (MIT)
2
3 Copyright (c) 2013-2022 Binaryify
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
1 # vue-qr
2 <a href="https://www.npmjs.com/package/vue-qr"><img src="https://img.shields.io/npm/v/vue-qr.svg" alt="Version"></a>
3 <a href="https://www.npmjs.com/package/vue-qr"><img src="https://img.shields.io/npm/l/vue-qr.svg" alt="License"></a>
4
5
6 The Vue Component for [SumiMakito's Awesome-qr.js](https://github.com/SumiMakito/Awesome-qr.js). Support Vue2/Vue3/Vite
7
8 The only one qr code component for Vue.js you need !
9
10 ### Notice
11 Not support IE 不支持IE浏览器
12
13 ### Examples, 样例
14
15 > Try to scan these QR codes below with your smart phone.
16
17 Example 1|Example 2|Example 3|Example 4
18 ------------ | ------------- | -------------| -------------
19 <img src="https://raw.githubusercontent.com/Binaryify/vue-qr/master/src/assets/result1.png" width="300"> | <img src="https://raw.githubusercontent.com/Binaryify/vue-qr/master/src/assets/result2.png" width="300"> | <img src="https://raw.githubusercontent.com/Binaryify/vue-qr/master/src/assets/result3.png" width="300"> | <img src="https://raw.githubusercontent.com/Binaryify/vue-qr/master/src/assets/result4.gif" width="300">
20
21 ### Demo
22 Run `npm run dev` or `yarn dev`
23
24 运行 `npm run dev` or `yarn dev`
25
26 ## Installation
27 **install with NPM**
28 ```bash
29 npm install vue-qr --save
30 ```
31 **Import**
32 ```js
33 // vue2.0
34 import VueQr from 'vue-qr'
35
36 // vue3.0 (support vite)
37 import vueQr from 'vue-qr/src/packages/vue-qr.vue'
38 ...
39 {
40 components: {VueQr}
41 }
42 ```
43 ## Usage
44 **In template**
45
46 ```html
47 <vue-qr :bgSrc='src' :logoSrc="src2" text="Hello world!" :size="200"></vue-qr>
48 <vue-qr text="Hello world!" :callback="test" qid="testid"></vue-qr>
49 ```
50
51 ```js
52 export default {
53 methods:{
54 test(dataUrl,id){
55 console.log(url, id)
56 }
57 }
58 }
59 ```
60 Parameter | Explanation
61 ----|----
62 text | Contents to encode. 欲编码的内容
63 correctLevel| Correct Level 0-3 容错级别 0-3
64 size | Width as well as the height of the output QR code, includes margin. 尺寸, 长宽一致, 包含外边距
65 margin | Margin to add around the QR code, default 20px. 二维码图像的外边距, 默认 20px
66 colorDark | Color of "true" blocks. Works only when both colorDark and colorLight are set. (BYTE_DTA, BYTE_POS, BYTE_AGN, BYTE_TMG) 实点的颜色
67 colorLight | Color of empty space, or "false" blocks. Works only when both colorDark and colorLight are set. (BYTE_EPT) 空白区的颜色
68 components | Controls the appearances of parts in the QR code. Read section [ComponentOptions](#componentoptions) to learn more. 阅读 [ComponentOptions](#componentoptions) 了解更多信息。
69 bgSrc | Background url to embed in the QR code. 欲嵌入的背景图地址
70 gifBgSrc | Gif background url to embed in the QR code, If gifBackground is set, backgroundImage will be ignored. This option will affects performance. 欲嵌入的背景图 gif 地址,设置后普通的背景图将失效。设置此选项会影响性能
71 backgroundColor | Background color 背景色
72 backgroundDimming | Color mask to add above the background image. Helpful when having problems with decoding. 叠加在背景图上的颜色, 在解码有难度的时有一定帮助
73 logoSrc | Logo url to embed at the center of generated QR code 嵌入至二维码中心的 LOGO 地址
74 logoScale | Value used to scale the logo image. Larger value may result in decode failure. Size of the logo equals to `logoScale*(size-2*margin)`. Default is 0.2. 用于计算 LOGO 大小的值, 过大将导致解码失败, LOGO 尺寸计算公式 `logoScale*(size-2*margin)`, 默认 0.2
75 logoMargin | White margin that appears around the logo image. Default is 0. LOGO 标识周围的空白边框, 默认为0
76 logoBackgroundColor | Logo background color, need set logo margin. Logo 背景色,需要设置 logo margin
77 logoCornerRadius | Radius of the logo's corners.Default is 0 LOGO 标识及其边框的圆角半径, 默认为0
78 whiteMargin | If set to true, a white border will appear around the background image. Default is true. 若设为 true, 背景图外将绘制白色边框
79 dotScale | Value used to scale down the data dots' size. (0 < scale < 1.0) default 1 数据区域点缩小比例,默认为1
80 autoColor | If set to true, the dominant color of backgroundImage will be used as colorDark. Default is true. 若为 true, 背景图的主要颜色将作为实点的颜色, 即 colorDark,默认 true
81 binarize | If set to true, the whole image will be binarized with the given threshold, or default threshold if not specified. Default is false. 若为 true, 图像将被二值化处理, 未指定阈值则使用默认值
82 binarizeThreshold | Threshold used to binarize the whole image. Default is 128. (0 < threshold < 255) 二值化处理的阈值
83 callback | Data URI of the generated QR code will be available here. 生成的二维码 Data URI 可以在回调中取得,第一个参数为二维码 data URL, 第二个参数为 props 传过来的 qid(因为二维码生成是异步的,所以加个 id 用于排序)
84 bindElement | If set to true, the generated QR will bind to a HTML element automatically. Default is true. 指定是否需要自动将生成的二维码绑定到HTML上, 默认是true
85
86 ## ComponentOptions
87
88 > _ComponentOptions_ controls the appearances of parts in the QR code.组件选项控制二维码中零件的外观。
89
90 ```ts
91 type ComponentOptions = {
92 data?: {
93 scale?: number;
94 };
95 timing?: {
96 scale?: number;
97 protectors?: boolean;
98 };
99 alignment?: {
100 scale?: number;
101 protectors?: boolean;
102 };
103 cornerAlignment?: {
104 scale?: number;
105 protectors?: boolean;
106 };
107 };
108 ```
109
110 ```ts
111 // default ComponentOptions
112
113 {
114 data: {
115 scale: 1,
116 },
117 timing: {
118 scale: 1,
119 protectors: false,
120 },
121 alignment: {
122 scale: 1,
123 protectors: false,
124 },
125 cornerAlignment: {
126 scale: 1,
127 protectors: true,
128 },
129 }
130 ```
131
132 ### scale 比例尺
133 Type number?
134
135 Scale factor for blocks in the specified area of the QR code.
136 在 QR 码指定区域的块的比例。
137
138 ### protectors
139
140 **Type** `boolean?`
141
142 Controls whether or not to draw the translucent protectors under the specified area in the QR code.控制是否在 QR 码的指定区域下绘制半透明保护器。
143
144
145 For more details you should definitely check out [Awesome-qr.js ](https://github.com/SumiMakito/Awesome-qr.js)
1 !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("vue-qr",[],e):"object"==typeof exports?exports["vue-qr"]=e():t["vue-qr"]=e()}(this,(function(){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="/dist/",r(r.s=13)}([function(t,e){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},t.exports.__esModule=!0,t.exports.default=t.exports},function(t,e){function r(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}t.exports=function(t,e,n){return e&&r(t.prototype,e),n&&r(t,n),Object.defineProperty(t,"prototype",{writable:!1}),t},t.exports.__esModule=!0,t.exports.default=t.exports},function(t,e){function r(e){return t.exports=r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,r(e)}t.exports=r,t.exports.__esModule=!0,t.exports.default=t.exports},function(t,e,r){t.exports=r(14)()},function(t,e,r){"use strict";r.d(e,"a",(function(){return l})),r.d(e,"b",(function(){return c})),r.d(e,"c",(function(){return p}));var n=r(0),o=r.n(n),i=r(1),a=r.n(i);function s(t){var e=encodeURI(t).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return e.length+(e.length!=Number(t)?3:0)}var u=function(){function t(e){o()(this,t),this.mode=h.MODE_8BIT_BYTE,this.parsedData=[],this.data=e;for(var r=[],n=0,i=this.data.length;n<i;n++){var a=[],s=this.data.charCodeAt(n);s>65536?(a[0]=240|(1835008&s)>>>18,a[1]=128|(258048&s)>>>12,a[2]=128|(4032&s)>>>6,a[3]=128|63&s):s>2048?(a[0]=224|(61440&s)>>>12,a[1]=128|(4032&s)>>>6,a[2]=128|63&s):s>128?(a[0]=192|(1984&s)>>>6,a[1]=128|63&s):a[0]=s,r.push(a)}this.parsedData=Array.prototype.concat.apply([],r),this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}return a()(t,[{key:"getLength",value:function(){return this.parsedData.length}},{key:"write",value:function(t){for(var e=0,r=this.parsedData.length;e<r;e++)t.put(this.parsedData[e],8)}}]),t}(),l=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:-1,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:c.L;o()(this,t),this.moduleCount=0,this.dataList=[],this.typeNumber=e,this.errorCorrectLevel=r,this.moduleCount=0,this.dataList=[]}return a()(t,[{key:"addData",value:function(t){if(this.typeNumber<=0)this.typeNumber=function(t,e){for(var r=1,n=s(t),o=0,i=m.length;o<i;o++){var a=0;switch(e){case c.L:a=m[o][0];break;case c.M:a=m[o][1];break;case c.Q:a=m[o][2];break;case c.H:a=m[o][3]}if(n<=a)break;r++}if(r>m.length)throw new Error("Too long data");return r}(t,this.errorCorrectLevel);else{if(this.typeNumber>40)throw new Error("Invalid QR version: ".concat(this.typeNumber));if(!function(t,e,r){var n=s(e),o=t-1,i=0;switch(r){case c.L:i=m[o][0];break;case c.M:i=m[o][1];break;case c.Q:i=m[o][2];break;case c.H:i=m[o][3]}return n<=i}(this.typeNumber,t,this.errorCorrectLevel))throw new Error("Data is too long for QR version: ".concat(this.typeNumber))}var e=new u(t);this.dataList.push(e),this.dataCache=void 0}},{key:"isDark",value:function(t,e){if(t<0||this.moduleCount<=t||e<0||this.moduleCount<=e)throw new Error("".concat(t,",").concat(e));return this.modules[t][e]}},{key:"getModuleCount",value:function(){return this.moduleCount}},{key:"make",value:function(){this.makeImpl(!1,this.getBestMaskPattern())}},{key:"makeImpl",value:function(e,r){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var n=0;n<this.moduleCount;n++){this.modules[n]=new Array(this.moduleCount);for(var o=0;o<this.moduleCount;o++)this.modules[n][o]=null}this.setupPositionProbePattern(0,0),this.setupPositionProbePattern(this.moduleCount-7,0),this.setupPositionProbePattern(0,this.moduleCount-7),this.setupPositionAdjustPattern(),this.setupTimingPattern(),this.setupTypeInfo(e,r),this.typeNumber>=7&&this.setupTypeNumber(e),null==this.dataCache&&(this.dataCache=t.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,r)}},{key:"setupPositionProbePattern",value:function(t,e){for(var r=-1;r<=7;r++)if(!(t+r<=-1||this.moduleCount<=t+r))for(var n=-1;n<=7;n++)e+n<=-1||this.moduleCount<=e+n||(this.modules[t+r][e+n]=0<=r&&r<=6&&(0==n||6==n)||0<=n&&n<=6&&(0==r||6==r)||2<=r&&r<=4&&2<=n&&n<=4)}},{key:"getBestMaskPattern",value:function(){if(Number.isInteger(this.maskPattern)&&Object.values(f).includes(this.maskPattern))return this.maskPattern;for(var t=0,e=0,r=0;r<8;r++){this.makeImpl(!0,r);var n=p.getLostPoint(this);(0==r||t>n)&&(t=n,e=r)}return e}},{key:"setupTimingPattern",value:function(){for(var t=8;t<this.moduleCount-8;t++)null==this.modules[t][6]&&(this.modules[t][6]=t%2==0);for(var e=8;e<this.moduleCount-8;e++)null==this.modules[6][e]&&(this.modules[6][e]=e%2==0)}},{key:"setupPositionAdjustPattern",value:function(){for(var t=p.getPatternPosition(this.typeNumber),e=0;e<t.length;e++)for(var r=0;r<t.length;r++){var n=t[e],o=t[r];if(null==this.modules[n][o])for(var i=-2;i<=2;i++)for(var a=-2;a<=2;a++)this.modules[n+i][o+a]=-2==i||2==i||-2==a||2==a||0==i&&0==a}}},{key:"setupTypeNumber",value:function(t){for(var e=p.getBCHTypeNumber(this.typeNumber),r=0;r<18;r++){var n=!t&&1==(e>>r&1);this.modules[Math.floor(r/3)][r%3+this.moduleCount-8-3]=n}for(r=0;r<18;r++){n=!t&&1==(e>>r&1);this.modules[r%3+this.moduleCount-8-3][Math.floor(r/3)]=n}}},{key:"setupTypeInfo",value:function(t,e){for(var r=this.errorCorrectLevel<<3|e,n=p.getBCHTypeInfo(r),o=0;o<15;o++){var i=!t&&1==(n>>o&1);o<6?this.modules[o][8]=i:o<8?this.modules[o+1][8]=i:this.modules[this.moduleCount-15+o][8]=i}for(o=0;o<15;o++){i=!t&&1==(n>>o&1);o<8?this.modules[8][this.moduleCount-o-1]=i:o<9?this.modules[8][15-o-1+1]=i:this.modules[8][15-o-1]=i}this.modules[this.moduleCount-8][8]=!t}},{key:"mapData",value:function(t,e){for(var r=-1,n=this.moduleCount-1,o=7,i=0,a=this.moduleCount-1;a>0;a-=2)for(6==a&&a--;;){for(var s=0;s<2;s++)if(null==this.modules[n][a-s]){var u=!1;i<t.length&&(u=1==(t[i]>>>o&1)),p.getMask(e,n,a-s)&&(u=!u),this.modules[n][a-s]=u,-1==--o&&(i++,o=7)}if((n+=r)<0||this.moduleCount<=n){n-=r,r=-r;break}}}}],[{key:"createData",value:function(e,r,n){for(var o=y.getRSBlocks(e,r),i=new v,a=0;a<n.length;a++){var s=n[a];i.put(s.mode,4),i.put(s.getLength(),p.getLengthInBits(s.mode,e)),s.write(i)}var u=0;for(a=0;a<o.length;a++)u+=o[a].dataCount;if(i.getLengthInBits()>8*u)throw new Error("code length overflow. (".concat(i.getLengthInBits(),">").concat(8*u,")"));for(i.getLengthInBits()+4<=8*u&&i.put(0,4);i.getLengthInBits()%8!=0;)i.putBit(!1);for(;!(i.getLengthInBits()>=8*u||(i.put(t.PAD0,8),i.getLengthInBits()>=8*u));)i.put(t.PAD1,8);return t.createBytes(i,o)}},{key:"createBytes",value:function(t,e){for(var r=0,n=0,o=0,i=new Array(e.length),a=new Array(e.length),s=0;s<e.length;s++){var u=e[s].dataCount,l=e[s].totalCount-u;n=Math.max(n,u),o=Math.max(o,l),i[s]=new Array(u);for(var c=0;c<i[s].length;c++)i[s][c]=255&t.buffer[c+r];r+=u;var h=p.getErrorCorrectPolynomial(l),f=new d(i[s],h.getLength()-1).mod(h);a[s]=new Array(h.getLength()-1);for(c=0;c<a[s].length;c++){var g=c+f.getLength()-a[s].length;a[s][c]=g>=0?f.get(g):0}}var y=0;for(c=0;c<e.length;c++)y+=e[c].totalCount;var v=new Array(y),m=0;for(c=0;c<n;c++)for(s=0;s<e.length;s++)c<i[s].length&&(v[m++]=i[s][c]);for(c=0;c<o;c++)for(s=0;s<e.length;s++)c<a[s].length&&(v[m++]=a[s][c]);return v}}]),t}();l.PAD0=236,l.PAD1=17;var c={L:1,M:0,Q:3,H:2},h={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8},f={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},p=function(){function t(){o()(this,t)}return a()(t,null,[{key:"getBCHTypeInfo",value:function(e){for(var r=e<<10;t.getBCHDigit(r)-t.getBCHDigit(t.G15)>=0;)r^=t.G15<<t.getBCHDigit(r)-t.getBCHDigit(t.G15);return(e<<10|r)^t.G15_MASK}},{key:"getBCHTypeNumber",value:function(e){for(var r=e<<12;t.getBCHDigit(r)-t.getBCHDigit(t.G18)>=0;)r^=t.G18<<t.getBCHDigit(r)-t.getBCHDigit(t.G18);return e<<12|r}},{key:"getBCHDigit",value:function(t){for(var e=0;0!=t;)e++,t>>>=1;return e}},{key:"getPatternPosition",value:function(e){return t.PATTERN_POSITION_TABLE[e-1]}},{key:"getMask",value:function(t,e,r){switch(t){case f.PATTERN000:return(e+r)%2==0;case f.PATTERN001:return e%2==0;case f.PATTERN010:return r%3==0;case f.PATTERN011:return(e+r)%3==0;case f.PATTERN100:return(Math.floor(e/2)+Math.floor(r/3))%2==0;case f.PATTERN101:return e*r%2+e*r%3==0;case f.PATTERN110:return(e*r%2+e*r%3)%2==0;case f.PATTERN111:return(e*r%3+(e+r)%2)%2==0;default:throw new Error("bad maskPattern:".concat(t))}}},{key:"getErrorCorrectPolynomial",value:function(t){for(var e=new d([1],0),r=0;r<t;r++)e=e.multiply(new d([1,g.gexp(r)],0));return e}},{key:"getLengthInBits",value:function(t,e){if(1<=e&&e<10)switch(t){case h.MODE_NUMBER:return 10;case h.MODE_ALPHA_NUM:return 9;case h.MODE_8BIT_BYTE:case h.MODE_KANJI:return 8;default:throw new Error("mode:".concat(t))}else if(e<27)switch(t){case h.MODE_NUMBER:return 12;case h.MODE_ALPHA_NUM:return 11;case h.MODE_8BIT_BYTE:return 16;case h.MODE_KANJI:return 10;default:throw new Error("mode:".concat(t))}else{if(!(e<41))throw new Error("type:".concat(e));switch(t){case h.MODE_NUMBER:return 14;case h.MODE_ALPHA_NUM:return 13;case h.MODE_8BIT_BYTE:return 16;case h.MODE_KANJI:return 12;default:throw new Error("mode:".concat(t))}}}},{key:"getLostPoint",value:function(t){for(var e=t.getModuleCount(),r=0,n=0;n<e;n++)for(var o=0;o<e;o++){for(var i=0,a=t.isDark(n,o),s=-1;s<=1;s++)if(!(n+s<0||e<=n+s))for(var u=-1;u<=1;u++)o+u<0||e<=o+u||0==s&&0==u||a==t.isDark(n+s,o+u)&&i++;i>5&&(r+=3+i-5)}for(n=0;n<e-1;n++)for(o=0;o<e-1;o++){var l=0;t.isDark(n,o)&&l++,t.isDark(n+1,o)&&l++,t.isDark(n,o+1)&&l++,t.isDark(n+1,o+1)&&l++,0!=l&&4!=l||(r+=3)}for(n=0;n<e;n++)for(o=0;o<e-6;o++)t.isDark(n,o)&&!t.isDark(n,o+1)&&t.isDark(n,o+2)&&t.isDark(n,o+3)&&t.isDark(n,o+4)&&!t.isDark(n,o+5)&&t.isDark(n,o+6)&&(r+=40);for(o=0;o<e;o++)for(n=0;n<e-6;n++)t.isDark(n,o)&&!t.isDark(n+1,o)&&t.isDark(n+2,o)&&t.isDark(n+3,o)&&t.isDark(n+4,o)&&!t.isDark(n+5,o)&&t.isDark(n+6,o)&&(r+=40);var c=0;for(o=0;o<e;o++)for(n=0;n<e;n++)t.isDark(n,o)&&c++;return r+=10*(Math.abs(100*c/e/e-50)/5)}}]),t}();p.PATTERN_POSITION_TABLE=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],p.G15=1335,p.G18=7973,p.G15_MASK=21522;var g=function(){function t(){o()(this,t)}return a()(t,null,[{key:"glog",value:function(e){if(e<1)throw new Error("glog(".concat(e,")"));return t.LOG_TABLE[e]}},{key:"gexp",value:function(e){for(;e<0;)e+=255;for(;e>=256;)e-=255;return t.EXP_TABLE[e]}}]),t}();g.EXP_TABLE=new Array(256),g.LOG_TABLE=new Array(256),g._constructor=function(){for(var t=0;t<8;t++)g.EXP_TABLE[t]=1<<t;for(t=8;t<256;t++)g.EXP_TABLE[t]=g.EXP_TABLE[t-4]^g.EXP_TABLE[t-5]^g.EXP_TABLE[t-6]^g.EXP_TABLE[t-8];for(t=0;t<255;t++)g.LOG_TABLE[g.EXP_TABLE[t]]=t}();var d=function(){function t(e,r){if(o()(this,t),null==e.length)throw new Error("".concat(e.length,"/").concat(r));for(var n=0;n<e.length&&0==e[n];)n++;this.num=new Array(e.length-n+r);for(var i=0;i<e.length-n;i++)this.num[i]=e[i+n]}return a()(t,[{key:"get",value:function(t){return this.num[t]}},{key:"getLength",value:function(){return this.num.length}},{key:"multiply",value:function(e){for(var r=new Array(this.getLength()+e.getLength()-1),n=0;n<this.getLength();n++)for(var o=0;o<e.getLength();o++)r[n+o]^=g.gexp(g.glog(this.get(n))+g.glog(e.get(o)));return new t(r,0)}},{key:"mod",value:function(e){if(this.getLength()-e.getLength()<0)return this;for(var r=g.glog(this.get(0))-g.glog(e.get(0)),n=new Array(this.getLength()),o=0;o<this.getLength();o++)n[o]=this.get(o);for(o=0;o<e.getLength();o++)n[o]^=g.gexp(g.glog(e.get(o))+r);return new t(n,0).mod(e)}}]),t}(),y=function(){function t(e,r){o()(this,t),this.totalCount=e,this.dataCount=r}return a()(t,null,[{key:"getRSBlocks",value:function(e,r){var n=t.getRsBlockTable(e,r);if(null==n)throw new Error("bad rs block @ typeNumber:".concat(e,"/errorCorrectLevel:").concat(r));for(var o=n.length/3,i=[],a=0;a<o;a++)for(var s=n[3*a+0],u=n[3*a+1],l=n[3*a+2],c=0;c<s;c++)i.push(new t(u,l));return i}},{key:"getRsBlockTable",value:function(e,r){switch(r){case c.L:return t.RS_BLOCK_TABLE[4*(e-1)+0];case c.M:return t.RS_BLOCK_TABLE[4*(e-1)+1];case c.Q:return t.RS_BLOCK_TABLE[4*(e-1)+2];case c.H:return t.RS_BLOCK_TABLE[4*(e-1)+3];default:return}}}]),t}();y.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];var v=function(){function t(){o()(this,t),this.buffer=[],this.length=0}return a()(t,[{key:"get",value:function(t){var e=Math.floor(t/8);return 1==(this.buffer[e]>>>7-t%8&1)}},{key:"put",value:function(t,e){for(var r=0;r<e;r++)this.putBit(1==(t>>>e-r-1&1))}},{key:"getLengthInBits",value:function(){return this.length}},{key:"putBit",value:function(t){var e=Math.floor(this.length/8);this.buffer.length<=e&&this.buffer.push(0),t&&(this.buffer[e]|=128>>>this.length%8),this.length++}}]),t}(),m=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]]},function(t,e,r){"use strict";(function(t){r.d(e,"b",(function(){return u})),r.d(e,"a",(function(){return l}));var n=r(2),o=r.n(n);function i(t){if("string"!=typeof t)throw new TypeError("Path must be a string. Received "+JSON.stringify(t))}function a(t,e){for(var r,n="",o=0,i=-1,a=0,s=0;s<=t.length;++s){if(s<t.length)r=t.charCodeAt(s);else{if(47===r)break;r=47}if(47===r){if(i===s-1||1===a);else if(i!==s-1&&2===a){if(n.length<2||2!==o||46!==n.charCodeAt(n.length-1)||46!==n.charCodeAt(n.length-2))if(n.length>2){var u=n.lastIndexOf("/");if(u!==n.length-1){-1===u?(n="",o=0):o=(n=n.slice(0,u)).length-1-n.lastIndexOf("/"),i=s,a=0;continue}}else if(2===n.length||1===n.length){n="",o=0,i=s,a=0;continue}e&&(n.length>0?n+="/..":n="..",o=2)}else n.length>0?n+="/"+t.slice(i+1,s):n=t.slice(i+1,s),o=s-i-1;i=s,a=0}else 46===r&&-1!==a?++a:a=-1}return n}var s={resolve:function(){for(var e,r="",n=!1,o=arguments.length-1;o>=-1&&!n;o--){var s;o>=0?s=arguments[o]:(void 0===e&&(e=t.cwd()),s=e),i(s),0!==s.length&&(r=s+"/"+r,n=47===s.charCodeAt(0))}return r=a(r,!n),n?r.length>0?"/"+r:"/":r.length>0?r:"."},normalize:function(t){if(i(t),0===t.length)return".";var e=47===t.charCodeAt(0),r=47===t.charCodeAt(t.length-1);return 0!==(t=a(t,!e)).length||e||(t="."),t.length>0&&r&&(t+="/"),e?"/"+t:t},isAbsolute:function(t){return i(t),t.length>0&&47===t.charCodeAt(0)},join:function(){if(0===arguments.length)return".";for(var t,e=0;e<arguments.length;++e){var r=arguments[e];i(r),r.length>0&&(void 0===t?t=r:t+="/"+r)}return void 0===t?".":s.normalize(t)},relative:function(t,e){if(i(t),i(e),t===e)return"";if((t=s.resolve(t))===(e=s.resolve(e)))return"";for(var r=1;r<t.length&&47===t.charCodeAt(r);++r);for(var n=t.length,o=n-r,a=1;a<e.length&&47===e.charCodeAt(a);++a);for(var u=e.length-a,l=o<u?o:u,c=-1,h=0;h<=l;++h){if(h===l){if(u>l){if(47===e.charCodeAt(a+h))return e.slice(a+h+1);if(0===h)return e.slice(a+h)}else o>l&&(47===t.charCodeAt(r+h)?c=h:0===h&&(c=0));break}var f=t.charCodeAt(r+h);if(f!==e.charCodeAt(a+h))break;47===f&&(c=h)}var p="";for(h=r+c+1;h<=n;++h)h!==n&&47!==t.charCodeAt(h)||(0===p.length?p+="..":p+="/..");return p.length>0?p+e.slice(a+c):(a+=c,47===e.charCodeAt(a)&&++a,e.slice(a))},_makeLong:function(t){return t},dirname:function(t){if(i(t),0===t.length)return".";for(var e=t.charCodeAt(0),r=47===e,n=-1,o=!0,a=t.length-1;a>=1;--a)if(47===(e=t.charCodeAt(a))){if(!o){n=a;break}}else o=!1;return-1===n?r?"/":".":r&&1===n?"//":t.slice(0,n)},basename:function(t,e){if(void 0!==e&&"string"!=typeof e)throw new TypeError('"ext" argument must be a string');i(t);var r,n=0,o=-1,a=!0;if(void 0!==e&&e.length>0&&e.length<=t.length){if(e.length===t.length&&e===t)return"";var s=e.length-1,u=-1;for(r=t.length-1;r>=0;--r){var l=t.charCodeAt(r);if(47===l){if(!a){n=r+1;break}}else-1===u&&(a=!1,u=r+1),s>=0&&(l===e.charCodeAt(s)?-1==--s&&(o=r):(s=-1,o=u))}return n===o?o=u:-1===o&&(o=t.length),t.slice(n,o)}for(r=t.length-1;r>=0;--r)if(47===t.charCodeAt(r)){if(!a){n=r+1;break}}else-1===o&&(a=!1,o=r+1);return-1===o?"":t.slice(n,o)},extname:function(t){i(t);for(var e=-1,r=0,n=-1,o=!0,a=0,s=t.length-1;s>=0;--s){var u=t.charCodeAt(s);if(47!==u)-1===n&&(o=!1,n=s+1),46===u?-1===e?e=s:1!==a&&(a=1):-1!==e&&(a=-1);else if(!o){r=s+1;break}}return-1===e||-1===n||0===a||1===a&&e===n-1&&e===r+1?"":t.slice(e,n)},format:function(t){if(null===t||"object"!==o()(t))throw new TypeError('The "pathObject" argument must be of type Object. Received type '+o()(t));return function(t,e){var r=e.dir||e.root,n=e.base||(e.name||"")+(e.ext||"");return r?r===e.root?r+n:r+t+n:n}("/",t)},parse:function(t){i(t);var e={root:"",dir:"",base:"",ext:"",name:""};if(0===t.length)return e;var r,n=t.charCodeAt(0),o=47===n;o?(e.root="/",r=1):r=0;for(var a=-1,s=0,u=-1,l=!0,c=t.length-1,h=0;c>=r;--c)if(47!==(n=t.charCodeAt(c)))-1===u&&(l=!1,u=c+1),46===n?-1===a?a=c:1!==h&&(h=1):-1!==a&&(h=-1);else if(!l){s=c+1;break}return-1===a||-1===u||0===h||1===h&&a===u-1&&a===s+1?-1!==u&&(e.base=e.name=0===s&&o?t.slice(1,u):t.slice(s,u)):(0===s&&o?(e.name=t.slice(1,a),e.base=t.slice(1,u)):(e.name=t.slice(s,a),e.base=t.slice(s,u)),e.ext=t.slice(a,u)),s>0?e.dir=t.slice(0,s-1):o&&(e.dir="/"),e},sep:"/",delimiter:":",win32:null,posix:null};s.posix=s;var u=s.extname,l=s.basename}).call(this,r(19))},function(t,e){function r(t,e,r,n,o,i,a){try{var s=t[i](a),u=s.value}catch(t){return void r(t)}s.done?e(u):Promise.resolve(u).then(n,o)}t.exports=function(t){return function(){var e=this,n=arguments;return new Promise((function(o,i){var a=t.apply(e,n);function s(t){r(a,o,i,s,u,"next",t)}function u(t){r(a,o,i,s,u,"throw",t)}s(void 0)}))}},t.exports.__esModule=!0,t.exports.default=t.exports},function(t,e,r){"use strict";r.d(e,"b",(function(){return w})),r.d(e,"a",(function(){return x}));const n=(t,e,r={},o=r)=>{if(Array.isArray(e))e.forEach(e=>n(t,e,r,o));else if("function"==typeof e)e(t,r,o,n);else{const i=Object.keys(e)[0];Array.isArray(e[i])?(o[i]={},n(t,e[i],r,o[i])):o[i]=e[i](t,r,o,n)}return r},o=(t,e)=>(r,n,o,i)=>{e(r,n,o)&&i(r,t,n,o)},i=(t=0)=>e=>e.data[e.pos+t],a=t=>e=>e.data.subarray(e.pos,e.pos+=t),s=t=>e=>e.data.subarray(e.pos,e.pos+t),u=t=>e=>Array.from(a(t)(e)).map(t=>String.fromCharCode(t)).join(""),l=t=>e=>{const r=a(2)(e);return t?(r[1]<<8)+r[0]:(r[0]<<8)+r[1]},c=(t,e)=>(r,n,o)=>{const i="function"==typeof e?e(r,n,o):e,s=a(t),u=new Array(i);for(var l=0;l<i;l++)u[l]=s(r);return u},h=t=>e=>{const r=(t=>t.data[t.pos++])(e),n=new Array(8);for(var o=0;o<8;o++)n[7-o]=!!(r&1<<o);return Object.keys(t).reduce((e,r)=>{const o=t[r];return o.length?e[r]=((t,e,r)=>{for(var n=0,o=0;o<r;o++)n+=t[e+o]&&2**(r-o-1);return n})(n,o.index,o.length):e[r]=n[o.index],e},{})};var f={blocks:t=>{const e=[],r=t.data.length;for(var n=0,o=(t=>t.data[t.pos++])(t);0!==o&&o;o=(t=>t.data[t.pos++])(t)){if(t.pos+o>=r){const o=r-t.pos;e.push(a(o)(t)),n+=o;break}e.push(a(o)(t)),n+=o}const i=new Uint8Array(n);for(var s=0,u=0;u<e.length;u++)i.set(e[u],s),s+=e[u].length;return i}};const p=o({gce:[{codes:a(2)},{byteSize:t=>t.data[t.pos++]},{extras:h({future:{index:0,length:3},disposal:{index:3,length:3},userInput:{index:6},transparentColorGiven:{index:7}})},{delay:l(!0)},{transparentColorIndex:t=>t.data[t.pos++]},{terminator:t=>t.data[t.pos++]}]},t=>{var e=s(2)(t);return 33===e[0]&&249===e[1]}),g=o({image:[{code:t=>t.data[t.pos++]},{descriptor:[{left:l(!0)},{top:l(!0)},{width:l(!0)},{height:l(!0)},{lct:h({exists:{index:0},interlaced:{index:1},sort:{index:2},future:{index:3,length:2},size:{index:5,length:3}})}]},o({lct:c(3,(t,e,r)=>Math.pow(2,r.descriptor.lct.size+1))},(t,e,r)=>r.descriptor.lct.exists),{data:[{minCodeSize:t=>t.data[t.pos++]},f]}]},t=>44===i()(t)),d=o({text:[{codes:a(2)},{blockSize:t=>t.data[t.pos++]},{preData:(t,e,r)=>a(r.text.blockSize)(t)},f]},t=>{var e=s(2)(t);return 33===e[0]&&1===e[1]}),y=o({application:[{codes:a(2)},{blockSize:t=>t.data[t.pos++]},{id:(t,e,r)=>u(r.blockSize)(t)},f]},t=>{var e=s(2)(t);return 33===e[0]&&255===e[1]}),v=o({comment:[{codes:a(2)},f]},t=>{var e=s(2)(t);return 33===e[0]&&254===e[1]});var m=[{header:[{signature:u(3)},{version:u(3)}]},{lsd:[{width:l(!0)},{height:l(!0)},{gct:h({exists:{index:0},resolution:{index:1,length:3},sort:{index:4},size:{index:5,length:3}})},{backgroundColorIndex:t=>t.data[t.pos++]},{pixelAspectRatio:t=>t.data[t.pos++]}]},o({gct:c(3,(t,e)=>Math.pow(2,e.lsd.gct.size+1))},(t,e)=>e.lsd.gct.exists),{frames:((t,e)=>(r,n,o,i)=>{const a=[];let s=r.pos;for(;e(r,n,o);){const e={};if(i(r,t,n,e),r.pos===s)break;s=r.pos,a.push(e)}return a})([p,y,v,g,d],t=>{var e=i()(t);return 33===e||44===e})}],w=function(t){var e=new Uint8Array(t);return n({data:e,pos:0},m)},b=function(t,e,r){if(t.image){var n=t.image,o=n.descriptor.width*n.descriptor.height,i=function(t,e,r){var n,o,i,a,s,u,l,c,h,f,p,g,d,y,v,m,w=r,b=new Array(r),x=new Array(4096),A=new Array(4096),E=new Array(4097);for(s=(o=1<<(f=t))+1,n=o+2,l=-1,i=(1<<(a=f+1))-1,c=0;c<o;c++)x[c]=0,A[c]=c;for(p=g=d=y=v=m=0,h=0;h<w;){if(0===y){if(g<a){p+=e[m]<<g,g+=8,m++;continue}if(c=p&i,p>>=a,g-=a,c>n||c==s)break;if(c==o){i=(1<<(a=f+1))-1,n=o+2,l=-1;continue}if(-1==l){E[y++]=A[c],l=c,d=c;continue}for(u=c,c==n&&(E[y++]=d,c=l);c>o;)E[y++]=A[c],c=x[c];d=255&A[c],E[y++]=d,n<4096&&(x[n]=l,A[n]=d,0==(++n&i)&&n<4096&&(a++,i+=n)),l=u}y--,b[v++]=E[y],h++}for(h=v;h<w;h++)b[h]=0;return b}(n.data.minCodeSize,n.data.blocks,o);n.descriptor.lct.interlaced&&(i=function(t,e){for(var r=new Array(t.length),n=t.length/e,o=function(n,o){var i=t.slice(o*e,(o+1)*e);r.splice.apply(r,[n*e,e].concat(i))},i=[0,4,2,1],a=[8,8,4,2],s=0,u=0;u<4;u++)for(var l=i[u];l<n;l+=a[u])o(l,s),s++;return r}(i,n.descriptor.width));var a={pixels:i,dims:{top:t.image.descriptor.top,left:t.image.descriptor.left,width:t.image.descriptor.width,height:t.image.descriptor.height}};return n.descriptor.lct&&n.descriptor.lct.exists?a.colorTable=n.lct:a.colorTable=e,t.gce&&(a.delay=10*(t.gce.delay||10),a.disposalType=t.gce.extras.disposal,t.gce.extras.transparentColorGiven&&(a.transparentIndex=t.gce.transparentColorIndex)),r&&(a.patch=function(t){for(var e=t.pixels.length,r=new Uint8ClampedArray(4*e),n=0;n<e;n++){var o=4*n,i=t.pixels[n],a=t.colorTable[i];r[o]=a[0],r[o+1]=a[1],r[o+2]=a[2],r[o+3]=i!==t.transparentIndex?255:0}return r}(a)),a}console.warn("gif frame does not have associated image.")},x=function(t,e){return t.frames.filter((function(t){return t.image})).map((function(r){return b(r,t.gct,e)}))}},function(t,e){var r;r=function(){return this}();try{r=r||new Function("return this")()}catch(t){"object"==typeof window&&(r=window)}t.exports=r},function(t,e,r){"use strict";(function(t){r.d(e,"a",(function(){return m}));var n=r(2),o=r.n(n),i=r(0),a=r.n(i),s=r(1),u=r.n(s),l=r(3),c=r.n(l),h=r(10),f=r(7),p=r(4),g=r(12),d=function(t,e,r,n){return new(r||(r=Promise))((function(o,i){function a(t){try{u(n.next(t))}catch(t){i(t)}}function s(t){try{u(n.throw(t))}catch(t){i(t)}}function u(t){var e;t.done?o(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(a,s)}u((n=n.apply(t,e||[])).next())}))},y=h.a.Canvas;function v(t){if(t)return new Promise((function(r,n){if("data"==t.slice(0,4)){var o=new Image;return o.onload=function(){r(o),e(o)},o.onerror=function(){n("Image load error"),e(o)},void(o.src=t)}var i=new Image;i.setAttribute("crossOrigin","Anonymous"),i.onload=function(){r(i)},i.onerror=function(){n("Image load error")},i.src=t}));function e(t){t.onload=null,t.onerror=null}}var m=function(){function e(t){a()(this,e);var r=Object.assign({},t);if(Object.keys(e.defaultOptions).forEach((function(t){t in r||Object.defineProperty(r,t,{value:e.defaultOptions[t],enumerable:!0,writable:!0})})),r.components?"object"===o()(r.components)&&Object.keys(e.defaultComponentOptions).forEach((function(t){t in r.components?Object.defineProperty(r.components,t,{value:Object.assign(Object.assign({},e.defaultComponentOptions[t]),r.components[t]),enumerable:!0,writable:!0}):Object.defineProperty(r.components,t,{value:e.defaultComponentOptions[t],enumerable:!0,writable:!0})})):r.components=e.defaultComponentOptions,null!==r.dotScale&&void 0!==r.dotScale){if(r.dotScale<=0||r.dotScale>1)throw new Error("dotScale should be in range (0, 1].");r.components.data.scale=r.dotScale,r.components.timing.scale=r.dotScale,r.components.alignment.scale=r.dotScale}this.options=r,this.canvas=new y(t.size,t.size),this.canvasContext=this.canvas.getContext("2d"),this.qrCode=new p.a(-1,this.options.correctLevel),Number.isInteger(this.options.maskPattern)&&(this.qrCode.maskPattern=this.options.maskPattern),Number.isInteger(this.options.version)&&(this.qrCode.typeNumber=this.options.version),this.qrCode.addData(this.options.text),this.qrCode.make()}return u()(e,[{key:"draw",value:function(){var t=this;return new Promise((function(e){return t._draw().then(e)}))}},{key:"_clear",value:function(){this.canvasContext.clearRect(0,0,this.canvas.width,this.canvas.height)}},{key:"_draw",value:function(){var r,n,o,i,a,s,u,l,h,m,b,x,A,E,C,k,P,_,T;return d(this,void 0,void 0,c.a.mark((function d(){var B,R,S,D,L,M,I,O,U,N,j,F,Y,z,G,H,q,$,X,Q,K,V,J,Z,W,tt,et,rt,nt,ot,it,at,st,ut,lt,ct,ht,ft,pt,gt,dt,yt,vt,mt,wt,bt,xt,At,Et,Ct,kt,Pt,_t,Tt,Bt,Rt,St,Dt,Lt,Mt,It,Ot,Ut,Nt,jt,Ft,Yt,zt,Gt,Ht,qt,$t;return c.a.wrap((function(c){for(;;)switch(c.prev=c.next){case 0:if(B=null===(r=this.qrCode)||void 0===r?void 0:r.moduleCount,R=this.options.size,((S=this.options.margin)<0||2*S>=R)&&(S=0),D=Math.ceil(S),L=R-2*S,M=this.options.whiteMargin,I=this.options.backgroundDimming,O=Math.ceil(L/B),j=new y(N=(U=O*B)+2*D,N),F=j.getContext("2d"),this._clear(),F.save(),F.translate(D,D),Y=new y(N,N),z=Y.getContext("2d"),G=null,H=[],!this.options.gifBackground){c.next=47;break}if(q=Object(f.b)(this.options.gifBackground),G=q,H=Object(f.a)(q,!0),!this.options.autoColor){c.next=45;break}$=0,X=0,Q=0,K=0,V=0;case 28:if(!(V<H[0].colorTable.length)){c.next=41;break}if(!((J=H[0].colorTable[V])[0]>200||J[1]>200||J[2]>200)){c.next=32;break}return c.abrupt("continue",38);case 32:if(0!==J[0]||0!==J[1]||0!==J[2]){c.next=34;break}return c.abrupt("continue",38);case 34:K++,$+=J[0],X+=J[1],Q+=J[2];case 38:V++,c.next=28;break;case 41:$=~~($/K),X=~~(X/K),Q=~~(Q/K),this.options.colorDark="rgb(".concat($,",").concat(X,",").concat(Q,")");case 45:c.next=61;break;case 47:if(!this.options.backgroundImage){c.next=58;break}return c.next=50,v(this.options.backgroundImage);case 50:Z=c.sent,this.options.autoColor&&(W=e._getAverageRGB(Z),this.options.colorDark="rgb(".concat(W.r,",").concat(W.g,",").concat(W.b,")")),z.drawImage(Z,0,0,Z.width,Z.height,0,0,N,N),z.rect(0,0,N,N),z.fillStyle=I,z.fill(),c.next=61;break;case 58:z.rect(0,0,N,N),z.fillStyle=this.options.colorLight,z.fill();case 61:for(tt=p.c.getPatternPosition(this.qrCode.typeNumber),et=(null===(o=null===(n=this.options.components)||void 0===n?void 0:n.data)||void 0===o?void 0:o.scale)||.4,rt=.5*(1-et),nt=0;nt<B;nt++)for(ot=0;ot<B;ot++){for(it=this.qrCode.isDark(nt,ot),at=6==nt&&ot>=8&&ot<=B-8||6==ot&&nt>=8&&nt<=B-8,st=ot<8&&(nt<8||nt>=B-8)||ot>=B-8&&nt<8||at,ut=1;ut<tt.length-1;ut++)st=st||nt>=tt[ut]-2&&nt<=tt[ut]+2&&ot>=tt[ut]-2&&ot<=tt[ut]+2;lt=ot*O+(st?0:rt*O),ct=nt*O+(st?0:rt*O),F.strokeStyle=it?this.options.colorDark:this.options.colorLight,F.lineWidth=.5,F.fillStyle=it?this.options.colorDark:this.options.colorLight,0===tt.length?st||F.fillRect(lt,ct,(st?1:et)*O,(st?1:et)*O):(ht=ot<B-4&&ot>=B-4-5&&nt<B-4&&nt>=B-4-5,st||ht||F.fillRect(lt,ct,(st?1:et)*O,(st?1:et)*O))}if(ft=tt[tt.length-1],pt=this.options.colorLight,F.fillStyle=pt,F.fillRect(0,0,8*O,8*O),F.fillRect(0,(B-8)*O,8*O,8*O),F.fillRect((B-8)*O,0,8*O,8*O),(null===(a=null===(i=this.options.components)||void 0===i?void 0:i.timing)||void 0===a?void 0:a.protectors)&&(F.fillRect(8*O,6*O,(B-8-8)*O,O),F.fillRect(6*O,8*O,O,(B-8-8)*O)),(null===(u=null===(s=this.options.components)||void 0===s?void 0:s.cornerAlignment)||void 0===u?void 0:u.protectors)&&e._drawAlignProtector(F,ft,ft,O),!(null===(h=null===(l=this.options.components)||void 0===l?void 0:l.alignment)||void 0===h?void 0:h.protectors)){c.next=99;break}gt=0;case 75:if(!(gt<tt.length)){c.next=99;break}dt=0;case 77:if(!(dt<tt.length)){c.next=96;break}if(yt=tt[dt],vt=tt[gt],6!==yt||6!==vt&&vt!==ft){c.next=84;break}return c.abrupt("continue",93);case 84:if(6!==vt||6!==yt&&yt!==ft){c.next=88;break}return c.abrupt("continue",93);case 88:if(yt!==ft||vt!==ft){c.next=92;break}return c.abrupt("continue",93);case 92:e._drawAlignProtector(F,yt,vt,O);case 93:dt++,c.next=77;break;case 96:gt++,c.next=75;break;case 99:for(F.fillStyle=this.options.colorDark,F.fillRect(0,0,7*O,O),F.fillRect((B-7)*O,0,7*O,O),F.fillRect(0,6*O,7*O,O),F.fillRect((B-7)*O,6*O,7*O,O),F.fillRect(0,(B-7)*O,7*O,O),F.fillRect(0,(B-7+6)*O,7*O,O),F.fillRect(0,0,O,7*O),F.fillRect(6*O,0,O,7*O),F.fillRect((B-7)*O,0,O,7*O),F.fillRect((B-7+6)*O,0,O,7*O),F.fillRect(0,(B-7)*O,O,7*O),F.fillRect(6*O,(B-7)*O,O,7*O),F.fillRect(2*O,2*O,3*O,3*O),F.fillRect((B-7+2)*O,2*O,3*O,3*O),F.fillRect(2*O,(B-7+2)*O,3*O,3*O),mt=(null===(b=null===(m=this.options.components)||void 0===m?void 0:m.timing)||void 0===b?void 0:b.scale)||.4,wt=.5*(1-mt),bt=0;bt<B-8;bt+=2)e._drawDot(F,8+bt,6,O,wt,mt),e._drawDot(F,6,8+bt,O,wt,mt);xt=(null===(A=null===(x=this.options.components)||void 0===x?void 0:x.cornerAlignment)||void 0===A?void 0:A.scale)||.4,At=.5*(1-xt),e._drawAlign(F,ft,ft,O,At,xt,this.options.colorDark,(null===(C=null===(E=this.options.components)||void 0===E?void 0:E.cornerAlignment)||void 0===C?void 0:C.protectors)||!1),Et=(null===(P=null===(k=this.options.components)||void 0===k?void 0:k.alignment)||void 0===P?void 0:P.scale)||.4,Ct=.5*(1-Et),kt=0;case 124:if(!(kt<tt.length)){c.next=148;break}Pt=0;case 126:if(!(Pt<tt.length)){c.next=145;break}if(_t=tt[Pt],Tt=tt[kt],6!==_t||6!==Tt&&Tt!==ft){c.next=133;break}return c.abrupt("continue",142);case 133:if(6!==Tt||6!==_t&&_t!==ft){c.next=137;break}return c.abrupt("continue",142);case 137:if(_t!==ft||Tt!==ft){c.next=141;break}return c.abrupt("continue",142);case 141:e._drawAlign(F,_t,Tt,O,Ct,Et,this.options.colorDark,(null===(T=null===(_=this.options.components)||void 0===_?void 0:_.alignment)||void 0===T?void 0:T.protectors)||!1);case 142:Pt++,c.next=126;break;case 145:kt++,c.next=124;break;case 148:if(M&&(F.fillStyle=this.options.backgroundColor,F.fillRect(-D,-D,N,D),F.fillRect(-D,U,N,D),F.fillRect(U,-D,D,N),F.fillRect(-D,-D,D,N)),!this.options.logoImage){c.next=179;break}return c.next=152,v(this.options.logoImage);case 152:Bt=c.sent,Rt=this.options.logoScale,St=this.options.logoMargin,Dt=this.options.logoCornerRadius,(Rt<=0||Rt>=1)&&(Rt=.2),St<0&&(St=0),Dt<0&&(Dt=0),It=Mt=.5*(N-(Lt=U*Rt)),F.restore(),F.fillStyle=this.options.logoBackgroundColor,F.save(),e._prepareRoundedCornerClip(F,Mt-St,It-St,Lt+2*St,Lt+2*St,Dt+St),F.clip(),Ot=F.globalCompositeOperation,F.globalCompositeOperation="destination-out",F.fill(),F.globalCompositeOperation=Ot,F.restore(),F.save(),e._prepareRoundedCornerClip(F,Mt,It,Lt,Lt,Dt),F.clip(),F.drawImage(Bt,Mt,It,Lt,Lt),F.restore(),F.save(),F.translate(D,D);case 179:if(!G){c.next=191;break}if(H.forEach((function(t){Ut||((Ut=new g.a(R,R)).setDelay(t.delay),Ut.setRepeat(0));var e=t.dims,r=e.width,n=e.height;Nt||(Nt=new y(r,n),(jt=Nt.getContext("2d")).rect(0,0,Nt.width,Nt.height),jt.fillStyle="#ffffff",jt.fill()),Ft&&zt&&r===Ft.width&&n===Ft.height||(Ft=new y(r,n),Yt=Ft.getContext("2d"),zt=Yt.createImageData(r,n)),zt.data.set(t.patch),Yt.putImageData(zt,0,0),jt.drawImage(Ft.getContext("2d").canvas,t.dims.left,t.dims.top);var o=new y(N,N),i=o.getContext("2d");i.drawImage(Nt.getContext("2d").canvas,0,0,N,N),i.rect(0,0,N,N),i.fillStyle=I,i.fill(),i.drawImage(j.getContext("2d").canvas,0,0,N,N);var a=new y(R,R),s=a.getContext("2d");s.drawImage(o.getContext("2d").canvas,0,0,R,R),Ut.addFrame(s.getImageData(0,0,a.width,a.height).data)})),Ut){c.next=183;break}throw new Error("No frames.");case 183:if(Ut.finish(),!w(this.canvas)){c.next=188;break}return Gt=Ut.stream().toFlattenUint8Array(),Ht=Gt.reduce((function(t,e){return t+String.fromCharCode(e)}),""),c.abrupt("return",Promise.resolve("data:image/gif;base64,".concat(window.btoa(Ht))));case 188:return c.abrupt("return",Promise.resolve(t.from(Ut.stream().toFlattenUint8Array())));case 191:if(z.drawImage(j.getContext("2d").canvas,0,0,N,N),F.drawImage(Y.getContext("2d").canvas,-D,-D,N,N),qt=new y(R,R),qt.getContext("2d").drawImage(j.getContext("2d").canvas,0,0,R,R),this.canvas=qt,$t=this.options.gifBackground?"gif":"png",!w(this.canvas)){c.next=200;break}return c.abrupt("return",Promise.resolve(this.canvas.toDataURL($t)));case 200:return c.abrupt("return",Promise.resolve(this.canvas.toBuffer($t)));case 201:case"end":return c.stop()}}),d,this)})))}}],[{key:"_prepareRoundedCornerClip",value:function(t,e,r,n,o,i){t.beginPath(),t.moveTo(e,r),t.arcTo(e+n,r,e+n,r+o,i),t.arcTo(e+n,r+o,e,r+o,i),t.arcTo(e,r+o,e,r,i),t.arcTo(e,r,e+n,r,i),t.closePath()}},{key:"_getAverageRGB",value:function(t){var e,r,n={r:0,g:0,b:0},o=-4,i={r:0,g:0,b:0},a=0;r=t.naturalHeight||t.height,e=t.naturalWidth||t.width;var s,u=new y(e,r).getContext("2d");if(!u)return n;u.drawImage(t,0,0);try{s=u.getImageData(0,0,e,r)}catch(t){return n}for(;(o+=20)<s.data.length;)s.data[o]>200||s.data[o+1]>200||s.data[o+2]>200||(++a,i.r+=s.data[o],i.g+=s.data[o+1],i.b+=s.data[o+2]);return i.r=~~(i.r/a),i.g=~~(i.g/a),i.b=~~(i.b/a),i}},{key:"_drawDot",value:function(t,e,r,n){var o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,i=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1;t.fillRect((e+o)*n,(r+o)*n,i*n,i*n)}},{key:"_drawAlignProtector",value:function(t,e,r,n){t.clearRect((e-2)*n,(r-2)*n,5*n,5*n),t.fillRect((e-2)*n,(r-2)*n,5*n,5*n)}},{key:"_drawAlign",value:function(t,r,n,o){var i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1,s=arguments.length>6?arguments[6]:void 0,u=arguments.length>7?arguments[7]:void 0,l=t.fillStyle;t.fillStyle=s,new Array(4).fill(0).map((function(s,u){e._drawDot(t,r-2+u,n-2,o,i,a),e._drawDot(t,r+2,n-2+u,o,i,a),e._drawDot(t,r+2-u,n+2,o,i,a),e._drawDot(t,r-2,n+2-u,o,i,a)})),e._drawDot(t,r,n,o,i,a),u||(t.fillStyle="rgba(255, 255, 255, 0.6)",new Array(2).fill(0).map((function(s,u){e._drawDot(t,r-1+u,n-1,o,i,a),e._drawDot(t,r+1,n-1+u,o,i,a),e._drawDot(t,r+1-u,n+1,o,i,a),e._drawDot(t,r-1,n+1-u,o,i,a)}))),t.fillStyle=l}}]),e}();function w(t){try{return t instanceof HTMLElement}catch(e){return"object"===o()(t)&&1===t.nodeType&&"object"===o()(t.style)&&"object"===o()(t.ownerDocument)}}m.CorrectLevel=p.b,m.defaultComponentOptions={data:{scale:.4},timing:{scale:.5,protectors:!1},alignment:{scale:.5,protectors:!1},cornerAlignment:{scale:.5,protectors:!0}},m.defaultOptions={text:"",size:400,margin:20,colorDark:"#000000",colorLight:"rgba(255, 255, 255, 0.6)",correctLevel:p.b.M,backgroundImage:void 0,backgroundDimming:"rgba(0,0,0,0)",logoImage:void 0,logoScale:.2,logoMargin:4,logoCornerRadius:8,whiteMargin:!0,components:m.defaultComponentOptions,autoColor:!0,logoBackgroundColor:"#ffffff",backgroundColor:"#ffffff"}}).call(this,r(15).Buffer)},function(t,e,r){"use strict";var n=r(11);const{asBuffer:o,asDownload:i,asZipDownload:a,atScale:s,options:u}=n.a,l=Symbol.for("toDataURL");const{CanvasRenderingContext2D:c,CanvasGradient:h,CanvasPattern:f,Image:p,ImageData:g,Path2D:d,DOMMatrix:y,DOMRect:v,DOMPoint:m}=window,w={Canvas:class{constructor(t,e){let r=document.createElement("canvas"),n=[];for(var[c,h]of(Object.defineProperty(r,"async",{value:!0,writable:!1,enumerable:!0}),Object.entries({png:()=>o(r,"image/png"),jpg:()=>o(r,"image/jpeg"),pages:()=>n.concat(r).map(t=>t.getContext("2d"))})))Object.defineProperty(r,c,{get:h});return Object.assign(r,{width:t,height:e,newPage(...t){var{width:e,height:o}=r,i=Object.assign(document.createElement("canvas"),{width:e,height:o});i.getContext("2d").drawImage(r,0,0),n.push(i);var[e,o]=t.length?t:[e,o];return Object.assign(r,{width:e,height:o}).getContext("2d")},saveAs(t,e){e="number"==typeof e?{quality:e}:e;let r=u(this.pages,{filename:t,e}),{pattern:n,padding:o,mime:l,quality:c,matte:h,density:f,archive:p}=r,g=s(r.pages,f);return null==o?i(g[0],l,c,h,t):a(g,l,c,h,p,n,o)},toBuffer(t="png",e={}){e="number"==typeof e?{quality:e}:e;let r=u(this.pages,{extension:t,e}),{mime:n,quality:i,matte:a,pages:l,density:c}=r,h=s(l,c,a)[0];return o(h,n,i,a)},[l]:r.toDataURL.bind(r),toDataURL(t="png",e={}){e="number"==typeof e?{quality:e}:e;let n=u(this.pages,{extension:t,e}),{mime:o,quality:i,matte:a,pages:c,density:h}=n,f=s(c,h,a)[0],p=f[f===r?l:"toDataURL"](o,i);return Promise.resolve(p)}})}},loadImage:t=>new Promise((e,r)=>Object.assign(new p,{crossOrigin:"Anonymous",onload:e,onerror:r,src:t})),CanvasRenderingContext2D:c,CanvasGradient:h,CanvasPattern:f,Image:p,ImageData:g,Path2D:d,DOMMatrix:y,DOMRect:v,DOMPoint:m};e.a=w},function(t,e,r){"use strict";(function(t){var n=r(5);class o{constructor(){let e=void 0===t,r="image/png",n="image/jpeg",o="application/pdf",i="image/svg+xml";Object.assign(this,{toMime:this.toMime.bind(this),fromMime:this.fromMime.bind(this),expected:e?'"png", "jpg", or "webp"':'"png", "jpg", "pdf", or "svg"',formats:e?{png:r,jpg:n,jpeg:"image/jpeg",webp:"image/webp"}:{png:r,jpg:n,jpeg:"image/jpeg",pdf:o,svg:i},mimes:e?{[r]:"png",[n]:"jpg","image/webp":"webp"}:{[r]:"png",[n]:"jpg",[o]:"pdf",[i]:"svg"}})}toMime(t){return this.formats[(t||"").replace(/^\./,"").toLowerCase()]}fromMime(t){return this.mimes[t]}}class i{static for(t){return(new i).append(t).get()}constructor(){this.crc=-1}get(){return~this.crc}append(t){for(var e=0|this.crc,r=this.table,n=0,o=0|t.length;n<o;n++)e=e>>>8^r[255&(e^t[n])];return this.crc=e,this}}function a(t){let e=new Uint8Array(t),r=new DataView(e.buffer),n={array:e,view:r,size:t,set8:(t,e)=>(r.setUint8(t,e),n),set16:(t,e)=>(r.setUint16(t,e,!0),n),set32:(t,e)=>(r.setUint32(t,e,!0),n),bytes:(t,r)=>(e.set(r,t),n)};return n}i.prototype.table=(()=>{var t,e,r,n=[];for(t=0;t<256;t++){for(r=t,e=0;e<8;e++)r=1&r?r>>>1^3988292384:r>>>1;n[t]=r}return n})();class s{constructor(t){let e=new Date;Object.assign(this,{directory:t,offset:0,files:[],time:(e.getHours()<<6|e.getMinutes())<<5|e.getSeconds()/2,date:(e.getFullYear()-1980<<4|e.getMonth()+1)<<5|e.getDate()}),this.add(t)}async add(t,e){let r=!e,n=s.encoder.encode(`${this.directory}/${r?"":t}`),o=new Uint8Array(r?0:await e.arrayBuffer()),u=30+n.length,l=u+o.length,{offset:c}=this,h=a(26).set32(0,134742036).set16(6,this.time).set16(8,this.date).set32(10,i.for(o)).set32(14,o.length).set32(18,o.length).set16(22,n.length);c+=u;let f=a(u+o.length+16).set32(0,67324752).bytes(4,h.array).bytes(30,n).bytes(u,o);c+=o.length,f.set32(l,134695760).bytes(l+4,h.array.slice(10,22)),c+=16,this.files.push({offset:c,folder:r,name:n,header:h,payload:f}),this.offset=c}toBuffer(){let t=this.files.reduce((t,{name:e})=>46+e.length+t,0),e=a(t+22),r=0;for(var{offset:n,name:o,header:i,folder:s}of this.files)e.set32(r,33639248).set16(r+4,20).bytes(r+6,i.array).set8(r+38,s?16:0).set32(r+42,n).bytes(r+46,o),r+=46+o.length;e.set32(r,101010256).set16(r+8,this.files.length).set16(r+10,this.files.length).set32(r+12,t).set32(r+16,this.offset);let u=new Uint8Array(this.offset+e.size),l=0;for(var{payload:c}of this.files)u.set(c.array,l),l+=c.size;return u.set(e.array,l),u}get blob(){return new Blob([this.toBuffer()],{type:"application/zip"})}}s.encoder=new TextEncoder;const u=(t,e,r,n)=>{if(n){let{width:e,height:r}=t,o=Object.assign(document.createElement("canvas"),{width:e,height:r}),i=o.getContext("2d");i.fillStyle=n,i.fillRect(0,0,e,r),i.drawImage(t,0,0),t=o}return new Promise((n,o)=>t.toBlob(n,e,r))},l=(t,e)=>{const r=window.URL.createObjectURL(e),n=document.createElement("a");n.style.display="none",n.href=r,n.setAttribute("download",t),void 0===n.download&&n.setAttribute("target","_blank"),document.body.appendChild(n),n.click(),document.body.removeChild(n),setTimeout(()=>window.URL.revokeObjectURL(r),100)},c={asBuffer:(...t)=>u(...t).then(t=>t.arrayBuffer()),asDownload:async(t,e,r,n,o)=>{l(o,await u(t,e,r,n))},asZipDownload:async(t,e,r,o,i,a,c)=>{let h=Object(n.a)(i,".zip")||"archive",f=new s(h);await Promise.all(t.map(async(t,n)=>{let i=(t=>a.replace("{}",String(t+1).padStart(c,"0")))(n);await f.add(i,await u(t,e,r,o))})),l(h+".zip",f.blob)},atScale:(t,e,r)=>t.map(t=>{if(1==e&&!r)return t.canvas;let n=document.createElement("canvas"),o=n.getContext("2d"),i=t.canvas?t.canvas:t;return n.width=i.width*e,n.height=i.height*e,r&&(o.fillStyle=r,o.fillRect(0,0,n.width,n.height)),o.scale(e,e),o.drawImage(i,0,0),n}),options:function(t,{filename:e="",extension:r="",format:i,page:a,quality:s,matte:u,density:l,outline:c,archive:h}={}){var{fromMime:f,toMime:p,expected:g}=new o,d=(h=h||"canvas",i||r.replace(/@\d+x$/i,"")||Object(n.b)(e)),y=(i=f(p(d)||d),p(i)),v=t.length;if(!d)throw new Error("Cannot determine image format (use a filename extension or 'format' argument)");if(!i)throw new Error(`Unsupported file format "${d}" (expected ${g})`);if(!v)throw new RangeError("Canvas has no associated contexts (try calling getContext or newPage first)");let m,w,b=e.replace(/{(\d*)}/g,(t,e)=>(w=!0,e=parseInt(e,10),m=isFinite(e)?e:isFinite(m)?m:-1,"{}")),x=a>0?a-1:a<0?v+a:void 0;if(isFinite(x)&&x<0||x>=v)throw new RangeError(1==v?`Canvas only has a ‘page 1’ (${x} is out of bounds)`:`Canvas has pages 1–${v} (${x} is out of bounds)`);if(t=isFinite(x)?[t[x]]:w||"pdf"==i?t:t.slice(-1),void 0===s)s=.92;else if("number"!=typeof s||!isFinite(s)||s<0||s>1)throw new TypeError("The quality option must be an number in the 0.0–1.0 range");if(void 0===l){let t=(r||Object(n.a)(e,d)).match(/@(\d+)x$/i);l=t?parseInt(t[1],10):1}else if("number"!=typeof l||!Number.isInteger(l)||l<1)throw new TypeError("The density option must be a non-negative integer");return void 0===c?c=!0:"svg"==i&&(c=!!c),{filename:e,pattern:b,format:i,mime:y,pages:t,padding:m,quality:s,matte:u,density:l,outline:c,archive:h}}};e.a=c}).call(this,r(8))},function(t,e,r){"use strict";var n=function(t,e){var r,n,o,i,a;function s(t,e,n,o,i){r[e][0]-=t*(r[e][0]-n)/1024,r[e][1]-=t*(r[e][1]-o)/1024,r[e][2]-=t*(r[e][2]-i)/1024}function u(t,e,n,o,i){for(var s,u,l=Math.abs(e-t),c=Math.min(e+t,256),h=e+1,f=e-1,p=1;h<c||f>l;)u=a[p++],h<c&&((s=r[h++])[0]-=u*(s[0]-n)/(1<<18),s[1]-=u*(s[1]-o)/(1<<18),s[2]-=u*(s[2]-i)/(1<<18)),f>l&&((s=r[f--])[0]-=u*(s[0]-n)/(1<<18),s[1]-=u*(s[1]-o)/(1<<18),s[2]-=u*(s[2]-i)/(1<<18))}function l(t,e,n){var a,s,u,l,c,h=~(1<<31),f=h,p=-1,g=p;for(a=0;a<256;a++)s=r[a],(u=Math.abs(s[0]-t)+Math.abs(s[1]-e)+Math.abs(s[2]-n))<h&&(h=u,p=a),(l=u-(o[a]>>12))<f&&(f=l,g=a),c=i[a]>>10,i[a]-=c,o[a]+=c<<10;return i[p]+=64,o[p]-=65536,g}this.buildColormap=function(){!function(){var t,e;for(r=[],n=new Int32Array(256),o=new Int32Array(256),i=new Int32Array(256),a=new Int32Array(32),t=0;t<256;t++)e=(t<<12)/256,r[t]=new Float64Array([e,e,e,0]),i[t]=256,o[t]=0}(),function(){var r,n,o,i,c,h,f=t.length,p=30+(e-1)/3,g=f/(3*e),d=~~(g/100),y=1024,v=2048,m=v>>6;for(m<=1&&(m=0),r=0;r<m;r++)a[r]=y*(256*(m*m-r*r)/(m*m));f<1509?(e=1,n=3):n=f%499!=0?1497:f%491!=0?1473:f%487!=0?1461:1509;var w=0;for(r=0;r<g;)if(s(y,h=l(o=(255&t[w])<<4,i=(255&t[w+1])<<4,c=(255&t[w+2])<<4),o,i,c),0!==m&&u(m,h,o,i,c),(w+=n)>=f&&(w-=f),0===d&&(d=1),++r%d==0)for(y-=y/p,(m=(v-=v/30)>>6)<=1&&(m=0),h=0;h<m;h++)a[h]=y*(256*(m*m-h*h)/(m*m))}(),function(){for(var t=0;t<256;t++)r[t][0]>>=4,r[t][1]>>=4,r[t][2]>>=4,r[t][3]=t}(),function(){var t,e,o,i,a,s,u=0,l=0;for(t=0;t<256;t++){for(a=t,s=(o=r[t])[1],e=t+1;e<256;e++)(i=r[e])[1]<s&&(a=e,s=i[1]);if(i=r[a],t!=a&&(e=i[0],i[0]=o[0],o[0]=e,e=i[1],i[1]=o[1],o[1]=e,e=i[2],i[2]=o[2],o[2]=e,e=i[3],i[3]=o[3],o[3]=e),s!=u){for(n[u]=l+t>>1,e=u+1;e<s;e++)n[e]=t;u=s,l=t}}for(n[u]=l+255>>1,e=u+1;e<256;e++)n[e]=255}()},this.getColormap=function(){for(var t=[],e=[],n=0;n<256;n++)e[r[n][3]]=n;for(var o=0,i=0;i<256;i++){var a=e[i];t[o++]=r[a][0],t[o++]=r[a][1],t[o++]=r[a][2]}return t},this.lookupRGB=function(t,e,o){for(var i,a,s,u=1e3,l=-1,c=n[e],h=c-1;c<256||h>=0;)c<256&&((s=(a=r[c])[1]-e)>=u?c=256:(c++,s<0&&(s=-s),(i=a[0]-t)<0&&(i=-i),(s+=i)<u&&((i=a[2]-o)<0&&(i=-i),(s+=i)<u&&(u=s,l=a[3])))),h>=0&&((s=e-(a=r[h])[1])>=u?h=-1:(h--,s<0&&(s=-s),(i=a[0]-t)<0&&(i=-i),(s+=i)<u&&((i=a[2]-o)<0&&(i=-i),(s+=i)<u&&(u=s,l=a[3]))));return l}},o=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];var i=function(t,e,r,n){var i,a,s,u,l,c,h,f,p,g=Math.max(2,n),d=new Uint8Array(256),y=new Int32Array(5003),v=new Int32Array(5003),m=0,w=0,b=!1;function x(t,e){d[a++]=t,a>=254&&C(e)}function A(t){E(5003),w=l+2,b=!0,_(l,t)}function E(t){for(var e=0;e<t;++e)y[e]=-1}function C(t){a>0&&(t.writeByte(a),t.writeBytes(d,0,a),a=0)}function k(t){return(1<<t)-1}function P(){return 0===h?-1:(--h,255&r[f++])}function _(t,e){for(i&=o[m],m>0?i|=t<<m:i=t,m+=p;m>=8;)x(255&i,e),i>>=8,m-=8;if((w>s||b)&&(b?(s=k(p=u),b=!1):(++p,s=12==p?4096:k(p))),t==c){for(;m>0;)x(255&i,e),i>>=8,m-=8;C(e)}}this.encode=function(r){r.writeByte(g),h=t*e,f=0,function(t,e){var r,n,o,i,h,f;for(b=!1,s=k(p=u=t),c=(l=1<<t-1)+1,w=l+2,a=0,i=P(),f=0,r=5003;r<65536;r*=2)++f;f=8-f,E(5003),_(l,e);t:for(;-1!=(n=P());)if(r=(n<<12)+i,y[o=n<<f^i]!==r){if(y[o]>=0){h=5003-o,0===o&&(h=1);do{if((o-=h)<0&&(o+=5003),y[o]===r){i=v[o];continue t}}while(y[o]>=0)}_(i,e),i=n,w<4096?(v[o]=w++,y[o]=r):A(e)}else i=v[o];_(i,e),_(c,e)}(g+1,r),r.writeByte(0)}};function a(){this.page=-1,this.pages=[],this.newPage()}a.pageSize=4096,a.charMap={};for(var s=0;s<256;s++)a.charMap[s]=String.fromCharCode(s);function u(t,e){this.width=~~t,this.height=~~e,this.transparent=null,this.transIndex=0,this.repeat=-1,this.delay=0,this.image=null,this.pixels=null,this.indexedPixels=null,this.colorDepth=null,this.colorTab=null,this.neuQuant=null,this.usedEntry=new Array,this.palSize=7,this.dispose=-1,this.firstFrame=!0,this.sample=10,this.dither=!1,this.globalPalette=!1,this.out=new a}a.prototype.newPage=function(){this.pages[++this.page]=new Uint8Array(a.pageSize),this.cursor=0},a.prototype.getData=function(){for(var t="",e=0;e<this.pages.length;e++)for(var r=0;r<a.pageSize;r++)t+=a.charMap[this.pages[e][r]];return t},a.prototype.toFlattenUint8Array=function(){for(var t=[],e=0;e<this.pages.length;e++)if(e===this.pages.length-1){var r=Uint8Array.from(this.pages[e].slice(0,this.cursor));t.push(r)}else t.push(this.pages[e]);var n=new Uint8Array(t.reduce((function(t,e){return t+e.length}),0));return t.reduce((function(t,e){return n.set(e,t),t+e.length}),0),n},a.prototype.writeByte=function(t){this.cursor>=a.pageSize&&this.newPage(),this.pages[this.page][this.cursor++]=t},a.prototype.writeUTFBytes=function(t){for(var e=t.length,r=0;r<e;r++)this.writeByte(t.charCodeAt(r))},a.prototype.writeBytes=function(t,e,r){for(var n=r||t.length,o=e||0;o<n;o++)this.writeByte(t[o])},u.prototype.setDelay=function(t){this.delay=Math.round(t/10)},u.prototype.setFrameRate=function(t){this.delay=Math.round(100/t)},u.prototype.setDispose=function(t){t>=0&&(this.dispose=t)},u.prototype.setRepeat=function(t){this.repeat=t},u.prototype.setTransparent=function(t){this.transparent=t},u.prototype.addFrame=function(t){this.image=t,this.colorTab=this.globalPalette&&this.globalPalette.slice?this.globalPalette:null,this.getImagePixels(),this.analyzePixels(),!0===this.globalPalette&&(this.globalPalette=this.colorTab),this.firstFrame&&(this.writeHeader(),this.writeLSD(),this.writePalette(),this.repeat>=0&&this.writeNetscapeExt()),this.writeGraphicCtrlExt(),this.writeImageDesc(),this.firstFrame||this.globalPalette||this.writePalette(),this.writePixels(),this.firstFrame=!1},u.prototype.finish=function(){this.out.writeByte(59)},u.prototype.setQuality=function(t){t<1&&(t=1),this.sample=t},u.prototype.setDither=function(t){!0===t&&(t="FloydSteinberg"),this.dither=t},u.prototype.setGlobalPalette=function(t){this.globalPalette=t},u.prototype.getGlobalPalette=function(){return this.globalPalette&&this.globalPalette.slice&&this.globalPalette.slice(0)||this.globalPalette},u.prototype.writeHeader=function(){this.out.writeUTFBytes("GIF89a")},u.prototype.analyzePixels=function(){this.colorTab||(this.neuQuant=new n(this.pixels,this.sample),this.neuQuant.buildColormap(),this.colorTab=this.neuQuant.getColormap()),this.dither?this.ditherPixels(this.dither.replace("-serpentine",""),null!==this.dither.match(/-serpentine/)):this.indexPixels(),this.pixels=null,this.colorDepth=8,this.palSize=7,null!==this.transparent&&(this.transIndex=this.findClosest(this.transparent,!0))},u.prototype.indexPixels=function(t){var e=this.pixels.length/3;this.indexedPixels=new Uint8Array(e);for(var r=0,n=0;n<e;n++){var o=this.findClosestRGB(255&this.pixels[r++],255&this.pixels[r++],255&this.pixels[r++]);this.usedEntry[o]=!0,this.indexedPixels[n]=o}},u.prototype.ditherPixels=function(t,e){var r={FalseFloydSteinberg:[[3/8,1,0],[3/8,0,1],[2/8,1,1]],FloydSteinberg:[[7/16,1,0],[3/16,-1,1],[5/16,0,1],[1/16,1,1]],Stucki:[[8/42,1,0],[4/42,2,0],[2/42,-2,1],[4/42,-1,1],[8/42,0,1],[4/42,1,1],[2/42,2,1],[1/42,-2,2],[2/42,-1,2],[4/42,0,2],[2/42,1,2],[1/42,2,2]],Atkinson:[[1/8,1,0],[1/8,2,0],[1/8,-1,1],[1/8,0,1],[1/8,1,1],[1/8,0,2]]};if(!t||!r[t])throw"Unknown dithering kernel: "+t;var n=r[t],o=0,i=this.height,a=this.width,s=this.pixels,u=e?-1:1;this.indexedPixels=new Uint8Array(this.pixels.length/3);for(var l=0;l<i;l++){e&&(u*=-1);for(var c=1==u?0:a-1,h=1==u?a:0;c!==h;c+=u){var f=3*(o=l*a+c),p=s[f],g=s[f+1],d=s[f+2];f=this.findClosestRGB(p,g,d),this.usedEntry[f]=!0,this.indexedPixels[o]=f,f*=3;for(var y=p-this.colorTab[f],v=g-this.colorTab[f+1],m=d-this.colorTab[f+2],w=1==u?0:n.length-1,b=1==u?n.length:0;w!==b;w+=u){var x=n[w][1],A=n[w][2];if(x+c>=0&&x+c<a&&A+l>=0&&A+l<i){var E=n[w][0];f=o+x+A*a,s[f*=3]=Math.max(0,Math.min(255,s[f]+y*E)),s[f+1]=Math.max(0,Math.min(255,s[f+1]+v*E)),s[f+2]=Math.max(0,Math.min(255,s[f+2]+m*E))}}}}},u.prototype.findClosest=function(t,e){return this.findClosestRGB((16711680&t)>>16,(65280&t)>>8,255&t,e)},u.prototype.findClosestRGB=function(t,e,r,n){if(null===this.colorTab)return-1;if(this.neuQuant&&!n)return this.neuQuant.lookupRGB(t,e,r);for(var o=0,i=16777216,a=this.colorTab.length,s=0,u=0;s<a;u++){var l=t-(255&this.colorTab[s++]),c=e-(255&this.colorTab[s++]),h=r-(255&this.colorTab[s++]),f=l*l+c*c+h*h;(!n||this.usedEntry[u])&&f<i&&(i=f,o=u)}return o},u.prototype.getImagePixels=function(){var t=this.width,e=this.height;this.pixels=new Uint8Array(t*e*3);for(var r=this.image,n=0,o=0,i=0;i<e;i++)for(var a=0;a<t;a++)this.pixels[o++]=r[n++],this.pixels[o++]=r[n++],this.pixels[o++]=r[n++],n++},u.prototype.writeGraphicCtrlExt=function(){var t,e;this.out.writeByte(33),this.out.writeByte(249),this.out.writeByte(4),null===this.transparent?(t=0,e=0):(t=1,e=2),this.dispose>=0&&(e=7&this.dispose),e<<=2,this.out.writeByte(0|e|t),this.writeShort(this.delay),this.out.writeByte(this.transIndex),this.out.writeByte(0)},u.prototype.writeImageDesc=function(){this.out.writeByte(44),this.writeShort(0),this.writeShort(0),this.writeShort(this.width),this.writeShort(this.height),this.firstFrame||this.globalPalette?this.out.writeByte(0):this.out.writeByte(128|this.palSize)},u.prototype.writeLSD=function(){this.writeShort(this.width),this.writeShort(this.height),this.out.writeByte(240|this.palSize),this.out.writeByte(0),this.out.writeByte(0)},u.prototype.writeNetscapeExt=function(){this.out.writeByte(33),this.out.writeByte(255),this.out.writeByte(11),this.out.writeUTFBytes("NETSCAPE2.0"),this.out.writeByte(3),this.out.writeByte(1),this.writeShort(this.repeat),this.out.writeByte(0)},u.prototype.writePalette=function(){this.out.writeBytes(this.colorTab);for(var t=768-this.colorTab.length,e=0;e<t;e++)this.out.writeByte(0)},u.prototype.writeShort=function(t){this.out.writeByte(255&t),this.out.writeByte(t>>8&255)},u.prototype.writePixels=function(){new i(this.width,this.height,this.indexedPixels,this.colorDepth).encode(this.out)},u.prototype.stream=function(){return this.out};e.a=u},function(t,e,r){t.exports=r(20)},function(t,e,r){var n=r(2).default;function o(){"use strict";
2 /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */t.exports=o=function(){return e},t.exports.__esModule=!0,t.exports.default=t.exports;var e={},r=Object.prototype,i=r.hasOwnProperty,a="function"==typeof Symbol?Symbol:{},s=a.iterator||"@@iterator",u=a.asyncIterator||"@@asyncIterator",l=a.toStringTag||"@@toStringTag";function c(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{c({},"")}catch(t){c=function(t,e,r){return t[e]=r}}function h(t,e,r,n){var o=e&&e.prototype instanceof g?e:g,i=Object.create(o.prototype),a=new P(n||[]);return i._invoke=function(t,e,r){var n="suspendedStart";return function(o,i){if("executing"===n)throw new Error("Generator is already running");if("completed"===n){if("throw"===o)throw i;return T()}for(r.method=o,r.arg=i;;){var a=r.delegate;if(a){var s=E(a,r);if(s){if(s===p)continue;return s}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if("suspendedStart"===n)throw n="completed",r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);n="executing";var u=f(t,e,r);if("normal"===u.type){if(n=r.done?"completed":"suspendedYield",u.arg===p)continue;return{value:u.arg,done:r.done}}"throw"===u.type&&(n="completed",r.method="throw",r.arg=u.arg)}}}(t,r,a),i}function f(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=h;var p={};function g(){}function d(){}function y(){}var v={};c(v,s,(function(){return this}));var m=Object.getPrototypeOf,w=m&&m(m(_([])));w&&w!==r&&i.call(w,s)&&(v=w);var b=y.prototype=g.prototype=Object.create(v);function x(t){["next","throw","return"].forEach((function(e){c(t,e,(function(t){return this._invoke(e,t)}))}))}function A(t,e){var r;this._invoke=function(o,a){function s(){return new e((function(r,s){!function r(o,a,s,u){var l=f(t[o],t,a);if("throw"!==l.type){var c=l.arg,h=c.value;return h&&"object"==n(h)&&i.call(h,"__await")?e.resolve(h.__await).then((function(t){r("next",t,s,u)}),(function(t){r("throw",t,s,u)})):e.resolve(h).then((function(t){c.value=t,s(c)}),(function(t){return r("throw",t,s,u)}))}u(l.arg)}(o,a,r,s)}))}return r=r?r.then(s,s):s()}}function E(t,e){var r=t.iterator[e.method];if(void 0===r){if(e.delegate=null,"throw"===e.method){if(t.iterator.return&&(e.method="return",e.arg=void 0,E(t,e),"throw"===e.method))return p;e.method="throw",e.arg=new TypeError("The iterator does not provide a 'throw' method")}return p}var n=f(r,t.iterator,e.arg);if("throw"===n.type)return e.method="throw",e.arg=n.arg,e.delegate=null,p;var o=n.arg;return o?o.done?(e[t.resultName]=o.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=void 0),e.delegate=null,p):o:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,p)}function C(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function k(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function P(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(C,this),this.reset(!0)}function _(t){if(t){var e=t[s];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var r=-1,n=function e(){for(;++r<t.length;)if(i.call(t,r))return e.value=t[r],e.done=!1,e;return e.value=void 0,e.done=!0,e};return n.next=n}}return{next:T}}function T(){return{value:void 0,done:!0}}return d.prototype=y,c(b,"constructor",y),c(y,"constructor",d),d.displayName=c(y,l,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===d||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,y):(t.__proto__=y,c(t,l,"GeneratorFunction")),t.prototype=Object.create(b),t},e.awrap=function(t){return{__await:t}},x(A.prototype),c(A.prototype,u,(function(){return this})),e.AsyncIterator=A,e.async=function(t,r,n,o,i){void 0===i&&(i=Promise);var a=new A(h(t,r,n,o),i);return e.isGeneratorFunction(r)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},x(b),c(b,l,"Generator"),c(b,s,(function(){return this})),c(b,"toString",(function(){return"[object Generator]"})),e.keys=function(t){var e=[];for(var r in t)e.push(r);return e.reverse(),function r(){for(;e.length;){var n=e.pop();if(n in t)return r.value=n,r.done=!1,r}return r.done=!0,r}},e.values=_,P.prototype={constructor:P,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=void 0,this.done=!1,this.delegate=null,this.method="next",this.arg=void 0,this.tryEntries.forEach(k),!t)for(var e in this)"t"===e.charAt(0)&&i.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=void 0)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function r(r,n){return a.type="throw",a.arg=t,e.next=r,n&&(e.method="next",e.arg=void 0),!!n}for(var n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n],a=o.completion;if("root"===o.tryLoc)return r("end");if(o.tryLoc<=this.prev){var s=i.call(o,"catchLoc"),u=i.call(o,"finallyLoc");if(s&&u){if(this.prev<o.catchLoc)return r(o.catchLoc,!0);if(this.prev<o.finallyLoc)return r(o.finallyLoc)}else if(s){if(this.prev<o.catchLoc)return r(o.catchLoc,!0)}else{if(!u)throw new Error("try statement without catch or finally");if(this.prev<o.finallyLoc)return r(o.finallyLoc)}}}},abrupt:function(t,e){for(var r=this.tryEntries.length-1;r>=0;--r){var n=this.tryEntries[r];if(n.tryLoc<=this.prev&&i.call(n,"finallyLoc")&&this.prev<n.finallyLoc){var o=n;break}}o&&("break"===t||"continue"===t)&&o.tryLoc<=e&&e<=o.finallyLoc&&(o=null);var a=o?o.completion:{};return a.type=t,a.arg=e,o?(this.method="next",this.next=o.finallyLoc,p):this.complete(a)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),p},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),k(r),p}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;k(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,r){return this.delegate={iterator:_(t),resultName:e,nextLoc:r},"next"===this.method&&(this.arg=void 0),p}},e}t.exports=o,t.exports.__esModule=!0,t.exports.default=t.exports},function(t,e,r){"use strict";(function(t){
3 /*!
4 * The buffer module from node.js, for the browser.
5 *
6 * @author Feross Aboukhadijeh <http://feross.org>
7 * @license MIT
8 */
9 var n=r(16),o=r(17),i=r(18);function a(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(t,e){if(a()<e)throw new RangeError("Invalid typed array length");return u.TYPED_ARRAY_SUPPORT?(t=new Uint8Array(e)).__proto__=u.prototype:(null===t&&(t=new u(e)),t.length=e),t}function u(t,e,r){if(!(u.TYPED_ARRAY_SUPPORT||this instanceof u))return new u(t,e,r);if("number"==typeof t){if("string"==typeof e)throw new Error("If encoding is specified then the first argument must be a string");return h(this,t)}return l(this,t,e,r)}function l(t,e,r,n){if("number"==typeof e)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer?function(t,e,r,n){if(e.byteLength,r<0||e.byteLength<r)throw new RangeError("'offset' is out of bounds");if(e.byteLength<r+(n||0))throw new RangeError("'length' is out of bounds");e=void 0===r&&void 0===n?new Uint8Array(e):void 0===n?new Uint8Array(e,r):new Uint8Array(e,r,n);u.TYPED_ARRAY_SUPPORT?(t=e).__proto__=u.prototype:t=f(t,e);return t}(t,e,r,n):"string"==typeof e?function(t,e,r){"string"==typeof r&&""!==r||(r="utf8");if(!u.isEncoding(r))throw new TypeError('"encoding" must be a valid string encoding');var n=0|g(e,r),o=(t=s(t,n)).write(e,r);o!==n&&(t=t.slice(0,o));return t}(t,e,r):function(t,e){if(u.isBuffer(e)){var r=0|p(e.length);return 0===(t=s(t,r)).length||e.copy(t,0,0,r),t}if(e){if("undefined"!=typeof ArrayBuffer&&e.buffer instanceof ArrayBuffer||"length"in e)return"number"!=typeof e.length||(n=e.length)!=n?s(t,0):f(t,e);if("Buffer"===e.type&&i(e.data))return f(t,e.data)}var n;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(t,e)}function c(t){if("number"!=typeof t)throw new TypeError('"size" argument must be a number');if(t<0)throw new RangeError('"size" argument must not be negative')}function h(t,e){if(c(e),t=s(t,e<0?0:0|p(e)),!u.TYPED_ARRAY_SUPPORT)for(var r=0;r<e;++r)t[r]=0;return t}function f(t,e){var r=e.length<0?0:0|p(e.length);t=s(t,r);for(var n=0;n<r;n+=1)t[n]=255&e[n];return t}function p(t){if(t>=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|t}function g(t,e){if(u.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var r=t.length;if(0===r)return 0;for(var n=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return F(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return Y(t).length;default:if(n)return F(t).length;e=(""+e).toLowerCase(),n=!0}}function d(t,e,r){var n=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return B(this,e,r);case"utf8":case"utf-8":return P(this,e,r);case"ascii":return _(this,e,r);case"latin1":case"binary":return T(this,e,r);case"base64":return k(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return R(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function y(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function v(t,e,r,n,o){if(0===t.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),r=+r,isNaN(r)&&(r=o?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(o)return-1;r=t.length-1}else if(r<0){if(!o)return-1;r=0}if("string"==typeof e&&(e=u.from(e,n)),u.isBuffer(e))return 0===e.length?-1:m(t,e,r,n,o);if("number"==typeof e)return e&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):m(t,[e],r,n,o);throw new TypeError("val must be string, number or Buffer")}function m(t,e,r,n,o){var i,a=1,s=t.length,u=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return-1;a=2,s/=2,u/=2,r/=2}function l(t,e){return 1===a?t[e]:t.readUInt16BE(e*a)}if(o){var c=-1;for(i=r;i<s;i++)if(l(t,i)===l(e,-1===c?0:i-c)){if(-1===c&&(c=i),i-c+1===u)return c*a}else-1!==c&&(i-=i-c),c=-1}else for(r+u>s&&(r=s-u),i=r;i>=0;i--){for(var h=!0,f=0;f<u;f++)if(l(t,i+f)!==l(e,f)){h=!1;break}if(h)return i}return-1}function w(t,e,r,n){r=Number(r)||0;var o=t.length-r;n?(n=Number(n))>o&&(n=o):n=o;var i=e.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var a=0;a<n;++a){var s=parseInt(e.substr(2*a,2),16);if(isNaN(s))return a;t[r+a]=s}return a}function b(t,e,r,n){return z(F(e,t.length-r),t,r,n)}function x(t,e,r,n){return z(function(t){for(var e=[],r=0;r<t.length;++r)e.push(255&t.charCodeAt(r));return e}(e),t,r,n)}function A(t,e,r,n){return x(t,e,r,n)}function E(t,e,r,n){return z(Y(e),t,r,n)}function C(t,e,r,n){return z(function(t,e){for(var r,n,o,i=[],a=0;a<t.length&&!((e-=2)<0);++a)r=t.charCodeAt(a),n=r>>8,o=r%256,i.push(o),i.push(n);return i}(e,t.length-r),t,r,n)}function k(t,e,r){return 0===e&&r===t.length?n.fromByteArray(t):n.fromByteArray(t.slice(e,r))}function P(t,e,r){r=Math.min(t.length,r);for(var n=[],o=e;o<r;){var i,a,s,u,l=t[o],c=null,h=l>239?4:l>223?3:l>191?2:1;if(o+h<=r)switch(h){case 1:l<128&&(c=l);break;case 2:128==(192&(i=t[o+1]))&&(u=(31&l)<<6|63&i)>127&&(c=u);break;case 3:i=t[o+1],a=t[o+2],128==(192&i)&&128==(192&a)&&(u=(15&l)<<12|(63&i)<<6|63&a)>2047&&(u<55296||u>57343)&&(c=u);break;case 4:i=t[o+1],a=t[o+2],s=t[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(u=(15&l)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&u<1114112&&(c=u)}null===c?(c=65533,h=1):c>65535&&(c-=65536,n.push(c>>>10&1023|55296),c=56320|1023&c),n.push(c),o+=h}return function(t){var e=t.length;if(e<=4096)return String.fromCharCode.apply(String,t);var r="",n=0;for(;n<e;)r+=String.fromCharCode.apply(String,t.slice(n,n+=4096));return r}(n)}e.Buffer=u,e.SlowBuffer=function(t){+t!=t&&(t=0);return u.alloc(+t)},e.INSPECT_MAX_BYTES=50,u.TYPED_ARRAY_SUPPORT=void 0!==t.TYPED_ARRAY_SUPPORT?t.TYPED_ARRAY_SUPPORT:function(){try{var t=new Uint8Array(1);return t.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===t.foo()&&"function"==typeof t.subarray&&0===t.subarray(1,1).byteLength}catch(t){return!1}}(),e.kMaxLength=a(),u.poolSize=8192,u._augment=function(t){return t.__proto__=u.prototype,t},u.from=function(t,e,r){return l(null,t,e,r)},u.TYPED_ARRAY_SUPPORT&&(u.prototype.__proto__=Uint8Array.prototype,u.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&u[Symbol.species]===u&&Object.defineProperty(u,Symbol.species,{value:null,configurable:!0})),u.alloc=function(t,e,r){return function(t,e,r,n){return c(e),e<=0?s(t,e):void 0!==r?"string"==typeof n?s(t,e).fill(r,n):s(t,e).fill(r):s(t,e)}(null,t,e,r)},u.allocUnsafe=function(t){return h(null,t)},u.allocUnsafeSlow=function(t){return h(null,t)},u.isBuffer=function(t){return!(null==t||!t._isBuffer)},u.compare=function(t,e){if(!u.isBuffer(t)||!u.isBuffer(e))throw new TypeError("Arguments must be Buffers");if(t===e)return 0;for(var r=t.length,n=e.length,o=0,i=Math.min(r,n);o<i;++o)if(t[o]!==e[o]){r=t[o],n=e[o];break}return r<n?-1:n<r?1:0},u.isEncoding=function(t){switch(String(t).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},u.concat=function(t,e){if(!i(t))throw new TypeError('"list" argument must be an Array of Buffers');if(0===t.length)return u.alloc(0);var r;if(void 0===e)for(e=0,r=0;r<t.length;++r)e+=t[r].length;var n=u.allocUnsafe(e),o=0;for(r=0;r<t.length;++r){var a=t[r];if(!u.isBuffer(a))throw new TypeError('"list" argument must be an Array of Buffers');a.copy(n,o),o+=a.length}return n},u.byteLength=g,u.prototype._isBuffer=!0,u.prototype.swap16=function(){var t=this.length;if(t%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var e=0;e<t;e+=2)y(this,e,e+1);return this},u.prototype.swap32=function(){var t=this.length;if(t%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var e=0;e<t;e+=4)y(this,e,e+3),y(this,e+1,e+2);return this},u.prototype.swap64=function(){var t=this.length;if(t%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var e=0;e<t;e+=8)y(this,e,e+7),y(this,e+1,e+6),y(this,e+2,e+5),y(this,e+3,e+4);return this},u.prototype.toString=function(){var t=0|this.length;return 0===t?"":0===arguments.length?P(this,0,t):d.apply(this,arguments)},u.prototype.equals=function(t){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===u.compare(this,t)},u.prototype.inspect=function(){var t="",r=e.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,r).match(/.{2}/g).join(" "),this.length>r&&(t+=" ... ")),"<Buffer "+t+">"},u.prototype.compare=function(t,e,r,n,o){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===r&&(r=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),e<0||r>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&e>=r)return 0;if(n>=o)return-1;if(e>=r)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),a=(r>>>=0)-(e>>>=0),s=Math.min(i,a),l=this.slice(n,o),c=t.slice(e,r),h=0;h<s;++h)if(l[h]!==c[h]){i=l[h],a=c[h];break}return i<a?-1:a<i?1:0},u.prototype.includes=function(t,e,r){return-1!==this.indexOf(t,e,r)},u.prototype.indexOf=function(t,e,r){return v(this,t,e,r,!0)},u.prototype.lastIndexOf=function(t,e,r){return v(this,t,e,r,!1)},u.prototype.write=function(t,e,r,n){if(void 0===e)n="utf8",r=this.length,e=0;else if(void 0===r&&"string"==typeof e)n=e,r=this.length,e=0;else{if(!isFinite(e))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");e|=0,isFinite(r)?(r|=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var o=this.length-e;if((void 0===r||r>o)&&(r=o),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return w(this,t,e,r);case"utf8":case"utf-8":return b(this,t,e,r);case"ascii":return x(this,t,e,r);case"latin1":case"binary":return A(this,t,e,r);case"base64":return E(this,t,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,t,e,r);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function _(t,e,r){var n="";r=Math.min(t.length,r);for(var o=e;o<r;++o)n+=String.fromCharCode(127&t[o]);return n}function T(t,e,r){var n="";r=Math.min(t.length,r);for(var o=e;o<r;++o)n+=String.fromCharCode(t[o]);return n}function B(t,e,r){var n=t.length;(!e||e<0)&&(e=0),(!r||r<0||r>n)&&(r=n);for(var o="",i=e;i<r;++i)o+=j(t[i]);return o}function R(t,e,r){for(var n=t.slice(e,r),o="",i=0;i<n.length;i+=2)o+=String.fromCharCode(n[i]+256*n[i+1]);return o}function S(t,e,r){if(t%1!=0||t<0)throw new RangeError("offset is not uint");if(t+e>r)throw new RangeError("Trying to access beyond buffer length")}function D(t,e,r,n,o,i){if(!u.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||e<i)throw new RangeError('"value" argument is out of bounds');if(r+n>t.length)throw new RangeError("Index out of range")}function L(t,e,r,n){e<0&&(e=65535+e+1);for(var o=0,i=Math.min(t.length-r,2);o<i;++o)t[r+o]=(e&255<<8*(n?o:1-o))>>>8*(n?o:1-o)}function M(t,e,r,n){e<0&&(e=4294967295+e+1);for(var o=0,i=Math.min(t.length-r,4);o<i;++o)t[r+o]=e>>>8*(n?o:3-o)&255}function I(t,e,r,n,o,i){if(r+n>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function O(t,e,r,n,i){return i||I(t,0,r,4),o.write(t,e,r,n,23,4),r+4}function U(t,e,r,n,i){return i||I(t,0,r,8),o.write(t,e,r,n,52,8),r+8}u.prototype.slice=function(t,e){var r,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(e=void 0===e?n:~~e)<0?(e+=n)<0&&(e=0):e>n&&(e=n),e<t&&(e=t),u.TYPED_ARRAY_SUPPORT)(r=this.subarray(t,e)).__proto__=u.prototype;else{var o=e-t;r=new u(o,void 0);for(var i=0;i<o;++i)r[i]=this[i+t]}return r},u.prototype.readUIntLE=function(t,e,r){t|=0,e|=0,r||S(t,e,this.length);for(var n=this[t],o=1,i=0;++i<e&&(o*=256);)n+=this[t+i]*o;return n},u.prototype.readUIntBE=function(t,e,r){t|=0,e|=0,r||S(t,e,this.length);for(var n=this[t+--e],o=1;e>0&&(o*=256);)n+=this[t+--e]*o;return n},u.prototype.readUInt8=function(t,e){return e||S(t,1,this.length),this[t]},u.prototype.readUInt16LE=function(t,e){return e||S(t,2,this.length),this[t]|this[t+1]<<8},u.prototype.readUInt16BE=function(t,e){return e||S(t,2,this.length),this[t]<<8|this[t+1]},u.prototype.readUInt32LE=function(t,e){return e||S(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},u.prototype.readUInt32BE=function(t,e){return e||S(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},u.prototype.readIntLE=function(t,e,r){t|=0,e|=0,r||S(t,e,this.length);for(var n=this[t],o=1,i=0;++i<e&&(o*=256);)n+=this[t+i]*o;return n>=(o*=128)&&(n-=Math.pow(2,8*e)),n},u.prototype.readIntBE=function(t,e,r){t|=0,e|=0,r||S(t,e,this.length);for(var n=e,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*e)),i},u.prototype.readInt8=function(t,e){return e||S(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},u.prototype.readInt16LE=function(t,e){e||S(t,2,this.length);var r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},u.prototype.readInt16BE=function(t,e){e||S(t,2,this.length);var r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},u.prototype.readInt32LE=function(t,e){return e||S(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},u.prototype.readInt32BE=function(t,e){return e||S(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},u.prototype.readFloatLE=function(t,e){return e||S(t,4,this.length),o.read(this,t,!0,23,4)},u.prototype.readFloatBE=function(t,e){return e||S(t,4,this.length),o.read(this,t,!1,23,4)},u.prototype.readDoubleLE=function(t,e){return e||S(t,8,this.length),o.read(this,t,!0,52,8)},u.prototype.readDoubleBE=function(t,e){return e||S(t,8,this.length),o.read(this,t,!1,52,8)},u.prototype.writeUIntLE=function(t,e,r,n){(t=+t,e|=0,r|=0,n)||D(this,t,e,r,Math.pow(2,8*r)-1,0);var o=1,i=0;for(this[e]=255&t;++i<r&&(o*=256);)this[e+i]=t/o&255;return e+r},u.prototype.writeUIntBE=function(t,e,r,n){(t=+t,e|=0,r|=0,n)||D(this,t,e,r,Math.pow(2,8*r)-1,0);var o=r-1,i=1;for(this[e+o]=255&t;--o>=0&&(i*=256);)this[e+o]=t/i&255;return e+r},u.prototype.writeUInt8=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,1,255,0),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},u.prototype.writeUInt16LE=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):L(this,t,e,!0),e+2},u.prototype.writeUInt16BE=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):L(this,t,e,!1),e+2},u.prototype.writeUInt32LE=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):M(this,t,e,!0),e+4},u.prototype.writeUInt32BE=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):M(this,t,e,!1),e+4},u.prototype.writeIntLE=function(t,e,r,n){if(t=+t,e|=0,!n){var o=Math.pow(2,8*r-1);D(this,t,e,r,o-1,-o)}var i=0,a=1,s=0;for(this[e]=255&t;++i<r&&(a*=256);)t<0&&0===s&&0!==this[e+i-1]&&(s=1),this[e+i]=(t/a>>0)-s&255;return e+r},u.prototype.writeIntBE=function(t,e,r,n){if(t=+t,e|=0,!n){var o=Math.pow(2,8*r-1);D(this,t,e,r,o-1,-o)}var i=r-1,a=1,s=0;for(this[e+i]=255&t;--i>=0&&(a*=256);)t<0&&0===s&&0!==this[e+i+1]&&(s=1),this[e+i]=(t/a>>0)-s&255;return e+r},u.prototype.writeInt8=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,1,127,-128),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},u.prototype.writeInt16LE=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):L(this,t,e,!0),e+2},u.prototype.writeInt16BE=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):L(this,t,e,!1),e+2},u.prototype.writeInt32LE=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):M(this,t,e,!0),e+4},u.prototype.writeInt32BE=function(t,e,r){return t=+t,e|=0,r||D(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):M(this,t,e,!1),e+4},u.prototype.writeFloatLE=function(t,e,r){return O(this,t,e,!0,r)},u.prototype.writeFloatBE=function(t,e,r){return O(this,t,e,!1,r)},u.prototype.writeDoubleLE=function(t,e,r){return U(this,t,e,!0,r)},u.prototype.writeDoubleBE=function(t,e,r){return U(this,t,e,!1,r)},u.prototype.copy=function(t,e,r,n){if(r||(r=0),n||0===n||(n=this.length),e>=t.length&&(e=t.length),e||(e=0),n>0&&n<r&&(n=r),n===r)return 0;if(0===t.length||0===this.length)return 0;if(e<0)throw new RangeError("targetStart out of bounds");if(r<0||r>=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-e<n-r&&(n=t.length-e+r);var o,i=n-r;if(this===t&&r<e&&e<n)for(o=i-1;o>=0;--o)t[o+e]=this[o+r];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)t[o+e]=this[o+r];else Uint8Array.prototype.set.call(t,this.subarray(r,r+i),e);return i},u.prototype.fill=function(t,e,r,n){if("string"==typeof t){if("string"==typeof e?(n=e,e=0,r=this.length):"string"==typeof r&&(n=r,r=this.length),1===t.length){var o=t.charCodeAt(0);o<256&&(t=o)}if(void 0!==n&&"string"!=typeof n)throw new TypeError("encoding must be a string");if("string"==typeof n&&!u.isEncoding(n))throw new TypeError("Unknown encoding: "+n)}else"number"==typeof t&&(t&=255);if(e<0||this.length<e||this.length<r)throw new RangeError("Out of range index");if(r<=e)return this;var i;if(e>>>=0,r=void 0===r?this.length:r>>>0,t||(t=0),"number"==typeof t)for(i=e;i<r;++i)this[i]=t;else{var a=u.isBuffer(t)?t:F(new u(t,n).toString()),s=a.length;for(i=0;i<r-e;++i)this[i+e]=a[i%s]}return this};var N=/[^+\/0-9A-Za-z-_]/g;function j(t){return t<16?"0"+t.toString(16):t.toString(16)}function F(t,e){var r;e=e||1/0;for(var n=t.length,o=null,i=[],a=0;a<n;++a){if((r=t.charCodeAt(a))>55295&&r<57344){if(!o){if(r>56319){(e-=3)>-1&&i.push(239,191,189);continue}if(a+1===n){(e-=3)>-1&&i.push(239,191,189);continue}o=r;continue}if(r<56320){(e-=3)>-1&&i.push(239,191,189),o=r;continue}r=65536+(o-55296<<10|r-56320)}else o&&(e-=3)>-1&&i.push(239,191,189);if(o=null,r<128){if((e-=1)<0)break;i.push(r)}else if(r<2048){if((e-=2)<0)break;i.push(r>>6|192,63&r|128)}else if(r<65536){if((e-=3)<0)break;i.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;i.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return i}function Y(t){return n.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(N,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function z(t,e,r,n){for(var o=0;o<n&&!(o+r>=e.length||o>=t.length);++o)e[o+r]=t[o];return o}}).call(this,r(8))},function(t,e,r){"use strict";e.byteLength=function(t){var e=l(t),r=e[0],n=e[1];return 3*(r+n)/4-n},e.toByteArray=function(t){var e,r,n=l(t),a=n[0],s=n[1],u=new i(function(t,e,r){return 3*(e+r)/4-r}(0,a,s)),c=0,h=s>0?a-4:a;for(r=0;r<h;r+=4)e=o[t.charCodeAt(r)]<<18|o[t.charCodeAt(r+1)]<<12|o[t.charCodeAt(r+2)]<<6|o[t.charCodeAt(r+3)],u[c++]=e>>16&255,u[c++]=e>>8&255,u[c++]=255&e;2===s&&(e=o[t.charCodeAt(r)]<<2|o[t.charCodeAt(r+1)]>>4,u[c++]=255&e);1===s&&(e=o[t.charCodeAt(r)]<<10|o[t.charCodeAt(r+1)]<<4|o[t.charCodeAt(r+2)]>>2,u[c++]=e>>8&255,u[c++]=255&e);return u},e.fromByteArray=function(t){for(var e,r=t.length,o=r%3,i=[],a=0,s=r-o;a<s;a+=16383)i.push(c(t,a,a+16383>s?s:a+16383));1===o?(e=t[r-1],i.push(n[e>>2]+n[e<<4&63]+"==")):2===o&&(e=(t[r-2]<<8)+t[r-1],i.push(n[e>>10]+n[e>>4&63]+n[e<<2&63]+"="));return i.join("")};for(var n=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,u=a.length;s<u;++s)n[s]=a[s],o[a.charCodeAt(s)]=s;function l(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var r=t.indexOf("=");return-1===r&&(r=e),[r,r===e?0:4-r%4]}function c(t,e,r){for(var o,i,a=[],s=e;s<r;s+=3)o=(t[s]<<16&16711680)+(t[s+1]<<8&65280)+(255&t[s+2]),a.push(n[(i=o)>>18&63]+n[i>>12&63]+n[i>>6&63]+n[63&i]);return a.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(t,e){
10 /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
11 e.read=function(t,e,r,n,o){var i,a,s=8*o-n-1,u=(1<<s)-1,l=u>>1,c=-7,h=r?o-1:0,f=r?-1:1,p=t[e+h];for(h+=f,i=p&(1<<-c)-1,p>>=-c,c+=s;c>0;i=256*i+t[e+h],h+=f,c-=8);for(a=i&(1<<-c)-1,i>>=-c,c+=n;c>0;a=256*a+t[e+h],h+=f,c-=8);if(0===i)i=1-l;else{if(i===u)return a?NaN:1/0*(p?-1:1);a+=Math.pow(2,n),i-=l}return(p?-1:1)*a*Math.pow(2,i-n)},e.write=function(t,e,r,n,o,i){var a,s,u,l=8*i-o-1,c=(1<<l)-1,h=c>>1,f=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=n?0:i-1,g=n?1:-1,d=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,a=c):(a=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-a))<1&&(a--,u*=2),(e+=a+h>=1?f/u:f*Math.pow(2,1-h))*u>=2&&(a++,u/=2),a+h>=c?(s=0,a=c):a+h>=1?(s=(e*u-1)*Math.pow(2,o),a+=h):(s=e*Math.pow(2,h-1)*Math.pow(2,o),a=0));o>=8;t[r+p]=255&s,p+=g,s/=256,o-=8);for(a=a<<o|s,l+=o;l>0;t[r+p]=255&a,p+=g,a/=256,l-=8);t[r+p-g]|=128*d}},function(t,e){var r={}.toString;t.exports=Array.isArray||function(t){return"[object Array]"==r.call(t)}},function(t,e){var r,n,o=t.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(t){if(r===setTimeout)return setTimeout(t,0);if((r===i||!r)&&setTimeout)return r=setTimeout,setTimeout(t,0);try{return r(t,0)}catch(e){try{return r.call(null,t,0)}catch(e){return r.call(this,t,0)}}}!function(){try{r="function"==typeof setTimeout?setTimeout:i}catch(t){r=i}try{n="function"==typeof clearTimeout?clearTimeout:a}catch(t){n=a}}();var u,l=[],c=!1,h=-1;function f(){c&&u&&(c=!1,u.length?l=u.concat(l):h=-1,l.length&&p())}function p(){if(!c){var t=s(f);c=!0;for(var e=l.length;e;){for(u=l,l=[];++h<e;)u&&u[h].run();h=-1,e=l.length}u=null,c=!1,function(t){if(n===clearTimeout)return clearTimeout(t);if((n===a||!n)&&clearTimeout)return n=clearTimeout,clearTimeout(t);try{n(t)}catch(e){try{return n.call(null,t)}catch(e){return n.call(this,t)}}}(t)}}function g(t,e){this.fun=t,this.array=e}function d(){}o.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)e[r-1]=arguments[r];l.push(new g(t,e)),1!==l.length||c||s(p)},g.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=d,o.addListener=d,o.once=d,o.off=d,o.removeListener=d,o.removeAllListeners=d,o.emit=d,o.prependListener=d,o.prependOnceListener=d,o.listeners=function(t){return[]},o.binding=function(t){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(t){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},function(t,e,r){"use strict";r.r(e);var n=r(6),o=r.n(n),i=r(3),a=r.n(i);function s(t){return""===t?t:"true"===t||"1"==t}var u=function(t,e){return new Promise((function(e,r){var n=new XMLHttpRequest;n.responseType="blob",n.onload=function(){var t=new FileReader;t.onloadend=function(){e(t.result)},t.readAsArrayBuffer(n.response)},n.open("GET",t),n.send()}))},l=r(9);var c=function(t,e,r,n,o,i,a,s){var u,l="function"==typeof t?t.options:t;if(e&&(l.render=e,l.staticRenderFns=r,l._compiled=!0),n&&(l.functional=!0),i&&(l._scopeId="data-v-"+i),a?(u=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},l._ssrRegister=u):o&&(u=s?function(){o.call(this,(l.functional?this.parent:this).$root.$options.shadowRoot)}:o),u)if(l.functional){l._injectStyles=u;var c=l.render;l.render=function(t,e){return u.call(e),c(t,e)}}else{var h=l.beforeCreate;l.beforeCreate=h?[].concat(h,u):[u]}return{exports:t,options:l}}({props:{text:{type:String,required:!0},qid:{type:String},correctLevel:{type:Number,default:1},size:{type:Number,default:200},margin:{type:Number,default:20},colorDark:{type:String,default:"#000000"},colorLight:{type:String,default:"#FFFFFF"},bgSrc:{type:String,default:void 0},background:{type:String,default:"rgba(0,0,0,0)"},backgroundDimming:{type:String,default:"rgba(0,0,0,0)"},logoSrc:{type:String,default:void 0},logoBackgroundColor:{type:String,default:"rgba(255,255,255,1)"},gifBgSrc:{type:String,default:void 0},logoScale:{type:Number,default:.2},logoMargin:{type:Number,default:0},logoCornerRadius:{type:Number,default:8},whiteMargin:{type:[Boolean,String],default:!0},dotScale:{type:Number,default:1},autoColor:{type:[Boolean,String],default:!0},binarize:{type:[Boolean,String],default:!1},binarizeThreshold:{type:Number,default:128},callback:{type:Function,default:function(){}},bindElement:{type:Boolean,default:!0},backgroundColor:{type:String,default:"#FFFFFF"},components:{default:function(){return{data:{scale:1},timing:{scale:1,protectors:!1},alignment:{scale:1,protectors:!1},cornerAlignment:{scale:1,protectors:!0}}}}},name:"vue-qr",data:function(){return{imgUrl:""}},watch:{$props:{deep:!0,handler:function(){this.main()}}},mounted:function(){this.main()},methods:{main:function(){var t=this;return o()(a.a.mark((function e(){var r,n,o,i;return a.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!t.gifBgSrc){e.next=7;break}return e.next=3,u(t.gifBgSrc);case 3:return r=e.sent,n=t.logoSrc,t.render(void 0,n,r),e.abrupt("return");case 7:o=t.bgSrc,i=t.logoSrc,t.render(o,i);case 10:case"end":return e.stop()}}),e)})))()},render:function(t,e,r){var n=this;return o()(a.a.mark((function o(){var i;return a.a.wrap((function(o){for(;;)switch(o.prev=o.next){case 0:i=n,new l.a({gifBackground:r,text:i.text,size:i.size,margin:i.margin,colorDark:i.colorDark,colorLight:i.colorLight,backgroundColor:i.backgroundColor,backgroundImage:t,backgroundDimming:i.backgroundDimming,logoImage:e,logoScale:i.logoScale,logoBackgroundColor:i.logoBackgroundColor,correctLevel:i.correctLevel,logoMargin:i.logoMargin,logoCornerRadius:i.logoCornerRadius,whiteMargin:s(i.whiteMargin),dotScale:i.dotScale,autoColor:s(i.autoColor),binarize:s(i.binarize),binarizeThreshold:i.binarizeThreshold,components:i.components}).draw().then((function(t){n.imgUrl=t,i.callback&&i.callback(t,i.qid)}));case 2:case"end":return o.stop()}}),o)})))()}}},(function(){var t=this.$createElement,e=this._self._c||t;return this.bindElement?e("img",{staticStyle:{display:"inline-block"},attrs:{src:this.imgUrl}}):this._e()}),[],!1,null,null,null).exports;c.install=function(t){return t.component(c.name,c)};var h=c,f=[h];"undefined"!=typeof window&&window.Vue&&function(t){f.map((function(e){t.component(e.name,e)}))}(window.Vue);e.default=h}])}));
12 //# sourceMappingURL=vue-qr.js.map
This diff could not be displayed because it is too large.
1 <div id="app">
2
3 </div>
4 <script src="./node_modules/vue/dist/vue.js"></script>
5 <script src="/dist/vue-qr.js"></script>
6
1 tidelift: "npm/brace-expansion"
2 patreon: juliangruber
1 MIT License
2
3 Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 SOFTWARE.
1 # brace-expansion
2
3 [Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
4 as known from sh/bash, in JavaScript.
5
6 [![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion)
7 [![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion)
8 [![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/)
9
10 [![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion)
11
12 ## Example
13
14 ```js
15 var expand = require('brace-expansion');
16
17 expand('file-{a,b,c}.jpg')
18 // => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
19
20 expand('-v{,,}')
21 // => ['-v', '-v', '-v']
22
23 expand('file{0..2}.jpg')
24 // => ['file0.jpg', 'file1.jpg', 'file2.jpg']
25
26 expand('file-{a..c}.jpg')
27 // => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
28
29 expand('file{2..0}.jpg')
30 // => ['file2.jpg', 'file1.jpg', 'file0.jpg']
31
32 expand('file{0..4..2}.jpg')
33 // => ['file0.jpg', 'file2.jpg', 'file4.jpg']
34
35 expand('file-{a..e..2}.jpg')
36 // => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
37
38 expand('file{00..10..5}.jpg')
39 // => ['file00.jpg', 'file05.jpg', 'file10.jpg']
40
41 expand('{{A..C},{a..c}}')
42 // => ['A', 'B', 'C', 'a', 'b', 'c']
43
44 expand('ppp{,config,oe{,conf}}')
45 // => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
46 ```
47
48 ## API
49
50 ```js
51 var expand = require('brace-expansion');
52 ```
53
54 ### var expanded = expand(str)
55
56 Return an array of all possible and valid expansions of `str`. If none are
57 found, `[str]` is returned.
58
59 Valid expansions are:
60
61 ```js
62 /^(.*,)+(.+)?$/
63 // {a,b,...}
64 ```
65
66 A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
67
68 ```js
69 /^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
70 // {x..y[..incr]}
71 ```
72
73 A numeric sequence from `x` to `y` inclusive, with optional increment.
74 If `x` or `y` start with a leading `0`, all the numbers will be padded
75 to have equal length. Negative numbers and backwards iteration work too.
76
77 ```js
78 /^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
79 // {x..y[..incr]}
80 ```
81
82 An alphabetic sequence from `x` to `y` inclusive, with optional increment.
83 `x` and `y` must be exactly one character, and if given, `incr` must be a
84 number.
85
86 For compatibility reasons, the string `${` is not eligible for brace expansion.
87
88 ## Installation
89
90 With [npm](https://npmjs.org) do:
91
92 ```bash
93 npm install brace-expansion
94 ```
95
96 ## Contributors
97
98 - [Julian Gruber](https://github.com/juliangruber)
99 - [Isaac Z. Schlueter](https://github.com/isaacs)
100
101 ## Sponsors
102
103 This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
104
105 Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
106
107 ## Security contact information
108
109 To report a security vulnerability, please use the
110 [Tidelift security contact](https://tidelift.com/security).
111 Tidelift will coordinate the fix and disclosure.
112
113 ## License
114
115 (MIT)
116
117 Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
118
119 Permission is hereby granted, free of charge, to any person obtaining a copy of
120 this software and associated documentation files (the "Software"), to deal in
121 the Software without restriction, including without limitation the rights to
122 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
123 of the Software, and to permit persons to whom the Software is furnished to do
124 so, subject to the following conditions:
125
126 The above copyright notice and this permission notice shall be included in all
127 copies or substantial portions of the Software.
128
129 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
130 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
132 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
133 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
134 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
135 SOFTWARE.
1 var balanced = require('balanced-match');
2
3 module.exports = expandTop;
4
5 var escSlash = '\0SLASH'+Math.random()+'\0';
6 var escOpen = '\0OPEN'+Math.random()+'\0';
7 var escClose = '\0CLOSE'+Math.random()+'\0';
8 var escComma = '\0COMMA'+Math.random()+'\0';
9 var escPeriod = '\0PERIOD'+Math.random()+'\0';
10
11 function numeric(str) {
12 return parseInt(str, 10) == str
13 ? parseInt(str, 10)
14 : str.charCodeAt(0);
15 }
16
17 function escapeBraces(str) {
18 return str.split('\\\\').join(escSlash)
19 .split('\\{').join(escOpen)
20 .split('\\}').join(escClose)
21 .split('\\,').join(escComma)
22 .split('\\.').join(escPeriod);
23 }
24
25 function unescapeBraces(str) {
26 return str.split(escSlash).join('\\')
27 .split(escOpen).join('{')
28 .split(escClose).join('}')
29 .split(escComma).join(',')
30 .split(escPeriod).join('.');
31 }
32
33
34 // Basically just str.split(","), but handling cases
35 // where we have nested braced sections, which should be
36 // treated as individual members, like {a,{b,c},d}
37 function parseCommaParts(str) {
38 if (!str)
39 return [''];
40
41 var parts = [];
42 var m = balanced('{', '}', str);
43
44 if (!m)
45 return str.split(',');
46
47 var pre = m.pre;
48 var body = m.body;
49 var post = m.post;
50 var p = pre.split(',');
51
52 p[p.length-1] += '{' + body + '}';
53 var postParts = parseCommaParts(post);
54 if (post.length) {
55 p[p.length-1] += postParts.shift();
56 p.push.apply(p, postParts);
57 }
58
59 parts.push.apply(parts, p);
60
61 return parts;
62 }
63
64 function expandTop(str) {
65 if (!str)
66 return [];
67
68 // I don't know why Bash 4.3 does this, but it does.
69 // Anything starting with {} will have the first two bytes preserved
70 // but *only* at the top level, so {},a}b will not expand to anything,
71 // but a{},b}c will be expanded to [a}c,abc].
72 // One could argue that this is a bug in Bash, but since the goal of
73 // this module is to match Bash's rules, we escape a leading {}
74 if (str.substr(0, 2) === '{}') {
75 str = '\\{\\}' + str.substr(2);
76 }
77
78 return expand(escapeBraces(str), true).map(unescapeBraces);
79 }
80
81 function embrace(str) {
82 return '{' + str + '}';
83 }
84 function isPadded(el) {
85 return /^-?0\d/.test(el);
86 }
87
88 function lte(i, y) {
89 return i <= y;
90 }
91 function gte(i, y) {
92 return i >= y;
93 }
94
95 function expand(str, isTop) {
96 var expansions = [];
97
98 var m = balanced('{', '}', str);
99 if (!m) return [str];
100
101 // no need to expand pre, since it is guaranteed to be free of brace-sets
102 var pre = m.pre;
103 var post = m.post.length
104 ? expand(m.post, false)
105 : [''];
106
107 if (/\$$/.test(m.pre)) {
108 for (var k = 0; k < post.length; k++) {
109 var expansion = pre+ '{' + m.body + '}' + post[k];
110 expansions.push(expansion);
111 }
112 } else {
113 var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
114 var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
115 var isSequence = isNumericSequence || isAlphaSequence;
116 var isOptions = m.body.indexOf(',') >= 0;
117 if (!isSequence && !isOptions) {
118 // {a},b}
119 if (m.post.match(/,.*\}/)) {
120 str = m.pre + '{' + m.body + escClose + m.post;
121 return expand(str);
122 }
123 return [str];
124 }
125
126 var n;
127 if (isSequence) {
128 n = m.body.split(/\.\./);
129 } else {
130 n = parseCommaParts(m.body);
131 if (n.length === 1) {
132 // x{{a,b}}y ==> x{a}y x{b}y
133 n = expand(n[0], false).map(embrace);
134 if (n.length === 1) {
135 return post.map(function(p) {
136 return m.pre + n[0] + p;
137 });
138 }
139 }
140 }
141
142 // at this point, n is the parts, and we know it's not a comma set
143 // with a single entry.
144 var N;
145
146 if (isSequence) {
147 var x = numeric(n[0]);
148 var y = numeric(n[1]);
149 var width = Math.max(n[0].length, n[1].length)
150 var incr = n.length == 3
151 ? Math.abs(numeric(n[2]))
152 : 1;
153 var test = lte;
154 var reverse = y < x;
155 if (reverse) {
156 incr *= -1;
157 test = gte;
158 }
159 var pad = n.some(isPadded);
160
161 N = [];
162
163 for (var i = x; test(i, y); i += incr) {
164 var c;
165 if (isAlphaSequence) {
166 c = String.fromCharCode(i);
167 if (c === '\\')
168 c = '';
169 } else {
170 c = String(i);
171 if (pad) {
172 var need = width - c.length;
173 if (need > 0) {
174 var z = new Array(need + 1).join('0');
175 if (i < 0)
176 c = '-' + z + c.slice(1);
177 else
178 c = z + c;
179 }
180 }
181 }
182 N.push(c);
183 }
184 } else {
185 N = [];
186
187 for (var j = 0; j < n.length; j++) {
188 N.push.apply(N, expand(n[j], false));
189 }
190 }
191
192 for (var j = 0; j < N.length; j++) {
193 for (var k = 0; k < post.length; k++) {
194 var expansion = pre + N[j] + post[k];
195 if (!isTop || isSequence || expansion)
196 expansions.push(expansion);
197 }
198 }
199 }
200
201 return expansions;
202 }
203
1 {
2 "_from": "brace-expansion@^2.0.1",
3 "_id": "brace-expansion@2.0.1",
4 "_inBundle": false,
5 "_integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
6 "_location": "/vue-qr/brace-expansion",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "brace-expansion@^2.0.1",
12 "name": "brace-expansion",
13 "escapedName": "brace-expansion",
14 "rawSpec": "^2.0.1",
15 "saveSpec": null,
16 "fetchSpec": "^2.0.1"
17 },
18 "_requiredBy": [
19 "/vue-qr/minimatch"
20 ],
21 "_resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
22 "_shasum": "1edc459e0f0c548486ecf9fc99f2221364b9a0ae",
23 "_spec": "brace-expansion@^2.0.1",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr/node_modules/minimatch",
25 "author": {
26 "name": "Julian Gruber",
27 "email": "mail@juliangruber.com",
28 "url": "http://juliangruber.com"
29 },
30 "bugs": {
31 "url": "https://github.com/juliangruber/brace-expansion/issues"
32 },
33 "bundleDependencies": false,
34 "dependencies": {
35 "balanced-match": "^1.0.0"
36 },
37 "deprecated": false,
38 "description": "Brace expansion as known from sh/bash",
39 "devDependencies": {
40 "@c4312/matcha": "^1.3.1",
41 "tape": "^4.6.0"
42 },
43 "homepage": "https://github.com/juliangruber/brace-expansion",
44 "keywords": [],
45 "license": "MIT",
46 "main": "index.js",
47 "name": "brace-expansion",
48 "repository": {
49 "type": "git",
50 "url": "git://github.com/juliangruber/brace-expansion.git"
51 },
52 "scripts": {
53 "bench": "matcha test/perf/bench.js",
54 "gentest": "bash test/generate.sh",
55 "test": "tape test/*.js"
56 },
57 "testling": {
58 "files": "test/*.js",
59 "browsers": [
60 "ie/8..latest",
61 "firefox/20..latest",
62 "firefox/nightly",
63 "chrome/25..latest",
64 "chrome/canary",
65 "opera/12..latest",
66 "opera/next",
67 "safari/5.1..latest",
68 "ipad/6.0..latest",
69 "iphone/6.0..latest",
70 "android-browser/4.2..latest"
71 ]
72 },
73 "version": "2.0.1"
74 }
1 The ISC License
2
3 Copyright (c) 2009-2022 Isaac Z. Schlueter and Contributors
4
5 Permission to use, copy, modify, and/or distribute this software for any
6 purpose with or without fee is hereby granted, provided that the above
7 copyright notice and this permission notice appear in all copies.
8
9 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1 # Glob
2
3 Match files using the patterns the shell uses, like stars and stuff.
4
5 [![Build Status](https://travis-ci.org/isaacs/node-glob.svg?branch=master)](https://travis-ci.org/isaacs/node-glob/) [![Build Status](https://ci.appveyor.com/api/projects/status/kd7f3yftf7unxlsx?svg=true)](https://ci.appveyor.com/project/isaacs/node-glob) [![Coverage Status](https://coveralls.io/repos/isaacs/node-glob/badge.svg?branch=master&service=github)](https://coveralls.io/github/isaacs/node-glob?branch=master)
6
7 This is a glob implementation in JavaScript. It uses the `minimatch`
8 library to do its matching.
9
10 ![a fun cartoon logo made of glob characters](logo/glob.png)
11
12 ## Usage
13
14 Install with npm
15
16 ```
17 npm i glob
18 ```
19
20 ```javascript
21 var glob = require("glob")
22
23 // options is optional
24 glob("**/*.js", options, function (er, files) {
25 // files is an array of filenames.
26 // If the `nonull` option is set, and nothing
27 // was found, then files is ["**/*.js"]
28 // er is an error object or null.
29 })
30 ```
31
32 ## Glob Primer
33
34 "Globs" are the patterns you type when you do stuff like `ls *.js` on
35 the command line, or put `build/*` in a `.gitignore` file.
36
37 Before parsing the path part patterns, braced sections are expanded
38 into a set. Braced sections start with `{` and end with `}`, with any
39 number of comma-delimited sections within. Braced sections may contain
40 slash characters, so `a{/b/c,bcd}` would expand into `a/b/c` and `abcd`.
41
42 The following characters have special magic meaning when used in a
43 path portion:
44
45 * `*` Matches 0 or more characters in a single path portion
46 * `?` Matches 1 character
47 * `[...]` Matches a range of characters, similar to a RegExp range.
48 If the first character of the range is `!` or `^` then it matches
49 any character not in the range.
50 * `!(pattern|pattern|pattern)` Matches anything that does not match
51 any of the patterns provided.
52 * `?(pattern|pattern|pattern)` Matches zero or one occurrence of the
53 patterns provided.
54 * `+(pattern|pattern|pattern)` Matches one or more occurrences of the
55 patterns provided.
56 * `*(a|b|c)` Matches zero or more occurrences of the patterns provided
57 * `@(pattern|pat*|pat?erN)` Matches exactly one of the patterns
58 provided
59 * `**` If a "globstar" is alone in a path portion, then it matches
60 zero or more directories and subdirectories searching for matches.
61 It does not crawl symlinked directories.
62
63 ### Dots
64
65 If a file or directory path portion has a `.` as the first character,
66 then it will not match any glob pattern unless that pattern's
67 corresponding path part also has a `.` as its first character.
68
69 For example, the pattern `a/.*/c` would match the file at `a/.b/c`.
70 However the pattern `a/*/c` would not, because `*` does not start with
71 a dot character.
72
73 You can make glob treat dots as normal characters by setting
74 `dot:true` in the options.
75
76 ### Basename Matching
77
78 If you set `matchBase:true` in the options, and the pattern has no
79 slashes in it, then it will seek for any file anywhere in the tree
80 with a matching basename. For example, `*.js` would match
81 `test/simple/basic.js`.
82
83 ### Empty Sets
84
85 If no matching files are found, then an empty array is returned. This
86 differs from the shell, where the pattern itself is returned. For
87 example:
88
89 $ echo a*s*d*f
90 a*s*d*f
91
92 To get the bash-style behavior, set the `nonull:true` in the options.
93
94 ### See Also:
95
96 * `man sh`
97 * `man bash` (Search for "Pattern Matching")
98 * `man 3 fnmatch`
99 * `man 5 gitignore`
100 * [minimatch documentation](https://github.com/isaacs/minimatch)
101
102 ## glob.hasMagic(pattern, [options])
103
104 Returns `true` if there are any special characters in the pattern, and
105 `false` otherwise.
106
107 Note that the options affect the results. If `noext:true` is set in
108 the options object, then `+(a|b)` will not be considered a magic
109 pattern. If the pattern has a brace expansion, like `a/{b/c,x/y}`
110 then that is considered magical, unless `nobrace:true` is set in the
111 options.
112
113 ## glob(pattern, [options], cb)
114
115 * `pattern` `{String}` Pattern to be matched
116 * `options` `{Object}`
117 * `cb` `{Function}`
118 * `err` `{Error | null}`
119 * `matches` `{Array<String>}` filenames found matching the pattern
120
121 Perform an asynchronous glob search.
122
123 ## glob.sync(pattern, [options])
124
125 * `pattern` `{String}` Pattern to be matched
126 * `options` `{Object}`
127 * return: `{Array<String>}` filenames found matching the pattern
128
129 Perform a synchronous glob search.
130
131 ## Class: glob.Glob
132
133 Create a Glob object by instantiating the `glob.Glob` class.
134
135 ```javascript
136 var Glob = require("glob").Glob
137 var mg = new Glob(pattern, options, cb)
138 ```
139
140 It's an EventEmitter, and starts walking the filesystem to find matches
141 immediately.
142
143 ### new glob.Glob(pattern, [options], [cb])
144
145 * `pattern` `{String}` pattern to search for
146 * `options` `{Object}`
147 * `cb` `{Function}` Called when an error occurs, or matches are found
148 * `err` `{Error | null}`
149 * `matches` `{Array<String>}` filenames found matching the pattern
150
151 Note that if the `sync` flag is set in the options, then matches will
152 be immediately available on the `g.found` member.
153
154 ### Properties
155
156 * `minimatch` The minimatch object that the glob uses.
157 * `options` The options object passed in.
158 * `aborted` Boolean which is set to true when calling `abort()`. There
159 is no way at this time to continue a glob search after aborting, but
160 you can re-use the statCache to avoid having to duplicate syscalls.
161 * `cache` Convenience object. Each field has the following possible
162 values:
163 * `false` - Path does not exist
164 * `true` - Path exists
165 * `'FILE'` - Path exists, and is not a directory
166 * `'DIR'` - Path exists, and is a directory
167 * `[file, entries, ...]` - Path exists, is a directory, and the
168 array value is the results of `fs.readdir`
169 * `statCache` Cache of `fs.stat` results, to prevent statting the same
170 path multiple times.
171 * `symlinks` A record of which paths are symbolic links, which is
172 relevant in resolving `**` patterns.
173 * `realpathCache` An optional object which is passed to `fs.realpath`
174 to minimize unnecessary syscalls. It is stored on the instantiated
175 Glob object, and may be re-used.
176
177 ### Events
178
179 * `end` When the matching is finished, this is emitted with all the
180 matches found. If the `nonull` option is set, and no match was found,
181 then the `matches` list contains the original pattern. The matches
182 are sorted, unless the `nosort` flag is set.
183 * `match` Every time a match is found, this is emitted with the specific
184 thing that matched. It is not deduplicated or resolved to a realpath.
185 * `error` Emitted when an unexpected error is encountered, or whenever
186 any fs error occurs if `options.strict` is set.
187 * `abort` When `abort()` is called, this event is raised.
188
189 ### Methods
190
191 * `pause` Temporarily stop the search
192 * `resume` Resume the search
193 * `abort` Stop the search forever
194
195 ### Options
196
197 All the options that can be passed to Minimatch can also be passed to
198 Glob to change pattern matching behavior. Also, some have been added,
199 or have glob-specific ramifications.
200
201 All options are false by default, unless otherwise noted.
202
203 All options are added to the Glob object, as well.
204
205 If you are running many `glob` operations, you can pass a Glob object
206 as the `options` argument to a subsequent operation to shortcut some
207 `stat` and `readdir` calls. At the very least, you may pass in shared
208 `symlinks`, `statCache`, `realpathCache`, and `cache` options, so that
209 parallel glob operations will be sped up by sharing information about
210 the filesystem.
211
212 * `cwd` The current working directory in which to search. Defaults
213 to `process.cwd()`.
214 * `root` The place where patterns starting with `/` will be mounted
215 onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
216 systems, and `C:\` or some such on Windows.)
217 * `dot` Include `.dot` files in normal matches and `globstar` matches.
218 Note that an explicit dot in a portion of the pattern will always
219 match dot files.
220 * `nomount` By default, a pattern starting with a forward-slash will be
221 "mounted" onto the root setting, so that a valid filesystem path is
222 returned. Set this flag to disable that behavior.
223 * `mark` Add a `/` character to directory matches. Note that this
224 requires additional stat calls.
225 * `nosort` Don't sort the results.
226 * `stat` Set to true to stat *all* results. This reduces performance
227 somewhat, and is completely unnecessary, unless `readdir` is presumed
228 to be an untrustworthy indicator of file existence.
229 * `silent` When an unusual error is encountered when attempting to
230 read a directory, a warning will be printed to stderr. Set the
231 `silent` option to true to suppress these warnings.
232 * `strict` When an unusual error is encountered when attempting to
233 read a directory, the process will just continue on in search of
234 other matches. Set the `strict` option to raise an error in these
235 cases.
236 * `cache` See `cache` property above. Pass in a previously generated
237 cache object to save some fs calls.
238 * `statCache` A cache of results of filesystem information, to prevent
239 unnecessary stat calls. While it should not normally be necessary
240 to set this, you may pass the statCache from one glob() call to the
241 options object of another, if you know that the filesystem will not
242 change between calls. (See "Race Conditions" below.)
243 * `symlinks` A cache of known symbolic links. You may pass in a
244 previously generated `symlinks` object to save `lstat` calls when
245 resolving `**` matches.
246 * `sync` DEPRECATED: use `glob.sync(pattern, opts)` instead.
247 * `nounique` In some cases, brace-expanded patterns can result in the
248 same file showing up multiple times in the result set. By default,
249 this implementation prevents duplicates in the result set. Set this
250 flag to disable that behavior.
251 * `nonull` Set to never return an empty set, instead returning a set
252 containing the pattern itself. This is the default in glob(3).
253 * `debug` Set to enable debug logging in minimatch and glob.
254 * `nobrace` Do not expand `{a,b}` and `{1..3}` brace sets.
255 * `noglobstar` Do not match `**` against multiple filenames. (Ie,
256 treat it as a normal `*` instead.)
257 * `noext` Do not match `+(a|b)` "extglob" patterns.
258 * `nocase` Perform a case-insensitive match. Note: on
259 case-insensitive filesystems, non-magic patterns will match by
260 default, since `stat` and `readdir` will not raise errors.
261 * `matchBase` Perform a basename-only match if the pattern does not
262 contain any slash characters. That is, `*.js` would be treated as
263 equivalent to `**/*.js`, matching all js files in all directories.
264 * `nodir` Do not match directories, only files. (Note: to match
265 *only* directories, simply put a `/` at the end of the pattern.)
266 * `ignore` Add a pattern or an array of glob patterns to exclude matches.
267 Note: `ignore` patterns are *always* in `dot:true` mode, regardless
268 of any other settings.
269 * `follow` Follow symlinked directories when expanding `**` patterns.
270 Note that this can result in a lot of duplicate references in the
271 presence of cyclic links.
272 * `realpath` Set to true to call `fs.realpath` on all of the results.
273 In the case of a symlink that cannot be resolved, the full absolute
274 path to the matched entry is returned (though it will usually be a
275 broken symlink)
276 * `absolute` Set to true to always receive absolute paths for matched
277 files. Unlike `realpath`, this also affects the values returned in
278 the `match` event.
279 * `fs` File-system object with Node's `fs` API. By default, the built-in
280 `fs` module will be used. Set to a volume provided by a library like
281 `memfs` to avoid using the "real" file-system.
282
283 ## Comparisons to other fnmatch/glob implementations
284
285 While strict compliance with the existing standards is a worthwhile
286 goal, some discrepancies exist between node-glob and other
287 implementations, and are intentional.
288
289 The double-star character `**` is supported by default, unless the
290 `noglobstar` flag is set. This is supported in the manner of bsdglob
291 and bash 4.3, where `**` only has special significance if it is the only
292 thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
293 `a/**b` will not.
294
295 Note that symlinked directories are not crawled as part of a `**`,
296 though their contents may match against subsequent portions of the
297 pattern. This prevents infinite loops and duplicates and the like.
298
299 If an escaped pattern has no matches, and the `nonull` flag is set,
300 then glob returns the pattern as-provided, rather than
301 interpreting the character escapes. For example,
302 `glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
303 `"*a?"`. This is akin to setting the `nullglob` option in bash, except
304 that it does not resolve escaped pattern characters.
305
306 If brace expansion is not disabled, then it is performed before any
307 other interpretation of the glob pattern. Thus, a pattern like
308 `+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
309 **first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
310 checked for validity. Since those two are valid, matching proceeds.
311
312 ### Comments and Negation
313
314 Previously, this module let you mark a pattern as a "comment" if it
315 started with a `#` character, or a "negated" pattern if it started
316 with a `!` character.
317
318 These options were deprecated in version 5, and removed in version 6.
319
320 To specify things that should not match, use the `ignore` option.
321
322 ## Windows
323
324 **Please only use forward-slashes in glob expressions.**
325
326 Though windows uses either `/` or `\` as its path separator, only `/`
327 characters are used by this glob implementation. You must use
328 forward-slashes **only** in glob expressions. Back-slashes will always
329 be interpreted as escape characters, not path separators.
330
331 Results from absolute patterns such as `/foo/*` are mounted onto the
332 root setting using `path.join`. On windows, this will by default result
333 in `/foo/*` matching `C:\foo\bar.txt`.
334
335 ## Race Conditions
336
337 Glob searching, by its very nature, is susceptible to race conditions,
338 since it relies on directory walking and such.
339
340 As a result, it is possible that a file that exists when glob looks for
341 it may have been deleted or modified by the time it returns the result.
342
343 As part of its internal implementation, this program caches all stat
344 and readdir calls that it makes, in order to cut down on system
345 overhead. However, this also makes it even more susceptible to races,
346 especially if the cache or statCache objects are reused between glob
347 calls.
348
349 Users are thus advised not to use a glob result as a guarantee of
350 filesystem state in the face of rapid changes. For the vast majority
351 of operations, this is never a problem.
352
353 ## Glob Logo
354 Glob's logo was created by [Tanya Brassie](http://tanyabrassie.com/). Logo files can be found [here](https://github.com/isaacs/node-glob/tree/master/logo).
355
356 The logo is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/).
357
358 ## Contributing
359
360 Any change to behavior (including bugfixes) must come with a test.
361
362 Patches that fail tests or reduce performance will be rejected.
363
364 ```
365 # to run tests
366 npm test
367
368 # to re-generate test fixtures
369 npm run test-regen
370
371 # to benchmark against bash/zsh
372 npm run bench
373
374 # to profile javascript
375 npm run prof
376 ```
377
378 ![](oh-my-glob.gif)
1 exports.setopts = setopts
2 exports.ownProp = ownProp
3 exports.makeAbs = makeAbs
4 exports.finish = finish
5 exports.mark = mark
6 exports.isIgnored = isIgnored
7 exports.childrenIgnored = childrenIgnored
8
9 function ownProp (obj, field) {
10 return Object.prototype.hasOwnProperty.call(obj, field)
11 }
12
13 var fs = require("fs")
14 var path = require("path")
15 var minimatch = require("minimatch")
16 var isAbsolute = require("path").isAbsolute
17 var Minimatch = minimatch.Minimatch
18
19 function alphasort (a, b) {
20 return a.localeCompare(b, 'en')
21 }
22
23 function setupIgnores (self, options) {
24 self.ignore = options.ignore || []
25
26 if (!Array.isArray(self.ignore))
27 self.ignore = [self.ignore]
28
29 if (self.ignore.length) {
30 self.ignore = self.ignore.map(ignoreMap)
31 }
32 }
33
34 // ignore patterns are always in dot:true mode.
35 function ignoreMap (pattern) {
36 var gmatcher = null
37 if (pattern.slice(-3) === '/**') {
38 var gpattern = pattern.replace(/(\/\*\*)+$/, '')
39 gmatcher = new Minimatch(gpattern, { dot: true })
40 }
41
42 return {
43 matcher: new Minimatch(pattern, { dot: true }),
44 gmatcher: gmatcher
45 }
46 }
47
48 function setopts (self, pattern, options) {
49 if (!options)
50 options = {}
51
52 // base-matching: just use globstar for that.
53 if (options.matchBase && -1 === pattern.indexOf("/")) {
54 if (options.noglobstar) {
55 throw new Error("base matching requires globstar")
56 }
57 pattern = "**/" + pattern
58 }
59
60 self.silent = !!options.silent
61 self.pattern = pattern
62 self.strict = options.strict !== false
63 self.realpath = !!options.realpath
64 self.realpathCache = options.realpathCache || Object.create(null)
65 self.follow = !!options.follow
66 self.dot = !!options.dot
67 self.mark = !!options.mark
68 self.nodir = !!options.nodir
69 if (self.nodir)
70 self.mark = true
71 self.sync = !!options.sync
72 self.nounique = !!options.nounique
73 self.nonull = !!options.nonull
74 self.nosort = !!options.nosort
75 self.nocase = !!options.nocase
76 self.stat = !!options.stat
77 self.noprocess = !!options.noprocess
78 self.absolute = !!options.absolute
79 self.fs = options.fs || fs
80
81 self.maxLength = options.maxLength || Infinity
82 self.cache = options.cache || Object.create(null)
83 self.statCache = options.statCache || Object.create(null)
84 self.symlinks = options.symlinks || Object.create(null)
85
86 setupIgnores(self, options)
87
88 self.changedCwd = false
89 var cwd = process.cwd()
90 if (!ownProp(options, "cwd"))
91 self.cwd = path.resolve(cwd)
92 else {
93 self.cwd = path.resolve(options.cwd)
94 self.changedCwd = self.cwd !== cwd
95 }
96
97 self.root = options.root || path.resolve(self.cwd, "/")
98 self.root = path.resolve(self.root)
99
100 // TODO: is an absolute `cwd` supposed to be resolved against `root`?
101 // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
102 self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd)
103 self.nomount = !!options.nomount
104
105 if (process.platform === "win32") {
106 self.root = self.root.replace(/\\/g, "/")
107 self.cwd = self.cwd.replace(/\\/g, "/")
108 self.cwdAbs = self.cwdAbs.replace(/\\/g, "/")
109 }
110
111 // disable comments and negation in Minimatch.
112 // Note that they are not supported in Glob itself anyway.
113 options.nonegate = true
114 options.nocomment = true
115 // always treat \ in patterns as escapes, not path separators
116 options.allowWindowsEscape = true
117
118 self.minimatch = new Minimatch(pattern, options)
119 self.options = self.minimatch.options
120 }
121
122 function finish (self) {
123 var nou = self.nounique
124 var all = nou ? [] : Object.create(null)
125
126 for (var i = 0, l = self.matches.length; i < l; i ++) {
127 var matches = self.matches[i]
128 if (!matches || Object.keys(matches).length === 0) {
129 if (self.nonull) {
130 // do like the shell, and spit out the literal glob
131 var literal = self.minimatch.globSet[i]
132 if (nou)
133 all.push(literal)
134 else
135 all[literal] = true
136 }
137 } else {
138 // had matches
139 var m = Object.keys(matches)
140 if (nou)
141 all.push.apply(all, m)
142 else
143 m.forEach(function (m) {
144 all[m] = true
145 })
146 }
147 }
148
149 if (!nou)
150 all = Object.keys(all)
151
152 if (!self.nosort)
153 all = all.sort(alphasort)
154
155 // at *some* point we statted all of these
156 if (self.mark) {
157 for (var i = 0; i < all.length; i++) {
158 all[i] = self._mark(all[i])
159 }
160 if (self.nodir) {
161 all = all.filter(function (e) {
162 var notDir = !(/\/$/.test(e))
163 var c = self.cache[e] || self.cache[makeAbs(self, e)]
164 if (notDir && c)
165 notDir = c !== 'DIR' && !Array.isArray(c)
166 return notDir
167 })
168 }
169 }
170
171 if (self.ignore.length)
172 all = all.filter(function(m) {
173 return !isIgnored(self, m)
174 })
175
176 self.found = all
177 }
178
179 function mark (self, p) {
180 var abs = makeAbs(self, p)
181 var c = self.cache[abs]
182 var m = p
183 if (c) {
184 var isDir = c === 'DIR' || Array.isArray(c)
185 var slash = p.slice(-1) === '/'
186
187 if (isDir && !slash)
188 m += '/'
189 else if (!isDir && slash)
190 m = m.slice(0, -1)
191
192 if (m !== p) {
193 var mabs = makeAbs(self, m)
194 self.statCache[mabs] = self.statCache[abs]
195 self.cache[mabs] = self.cache[abs]
196 }
197 }
198
199 return m
200 }
201
202 // lotta situps...
203 function makeAbs (self, f) {
204 var abs = f
205 if (f.charAt(0) === '/') {
206 abs = path.join(self.root, f)
207 } else if (isAbsolute(f) || f === '') {
208 abs = f
209 } else if (self.changedCwd) {
210 abs = path.resolve(self.cwd, f)
211 } else {
212 abs = path.resolve(f)
213 }
214
215 if (process.platform === 'win32')
216 abs = abs.replace(/\\/g, '/')
217
218 return abs
219 }
220
221
222 // Return true, if pattern ends with globstar '**', for the accompanying parent directory.
223 // Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
224 function isIgnored (self, path) {
225 if (!self.ignore.length)
226 return false
227
228 return self.ignore.some(function(item) {
229 return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
230 })
231 }
232
233 function childrenIgnored (self, path) {
234 if (!self.ignore.length)
235 return false
236
237 return self.ignore.some(function(item) {
238 return !!(item.gmatcher && item.gmatcher.match(path))
239 })
240 }
1 // Approach:
2 //
3 // 1. Get the minimatch set
4 // 2. For each pattern in the set, PROCESS(pattern, false)
5 // 3. Store matches per-set, then uniq them
6 //
7 // PROCESS(pattern, inGlobStar)
8 // Get the first [n] items from pattern that are all strings
9 // Join these together. This is PREFIX.
10 // If there is no more remaining, then stat(PREFIX) and
11 // add to matches if it succeeds. END.
12 //
13 // If inGlobStar and PREFIX is symlink and points to dir
14 // set ENTRIES = []
15 // else readdir(PREFIX) as ENTRIES
16 // If fail, END
17 //
18 // with ENTRIES
19 // If pattern[n] is GLOBSTAR
20 // // handle the case where the globstar match is empty
21 // // by pruning it out, and testing the resulting pattern
22 // PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
23 // // handle other cases.
24 // for ENTRY in ENTRIES (not dotfiles)
25 // // attach globstar + tail onto the entry
26 // // Mark that this entry is a globstar match
27 // PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
28 //
29 // else // not globstar
30 // for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
31 // Test ENTRY against pattern[n]
32 // If fails, continue
33 // If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
34 //
35 // Caveat:
36 // Cache all stats and readdirs results to minimize syscall. Since all
37 // we ever care about is existence and directory-ness, we can just keep
38 // `true` for files, and [children,...] for directories, or `false` for
39 // things that don't exist.
40
41 module.exports = glob
42
43 var rp = require('fs.realpath')
44 var minimatch = require('minimatch')
45 var Minimatch = minimatch.Minimatch
46 var inherits = require('inherits')
47 var EE = require('events').EventEmitter
48 var path = require('path')
49 var assert = require('assert')
50 var isAbsolute = require('path').isAbsolute
51 var globSync = require('./sync.js')
52 var common = require('./common.js')
53 var setopts = common.setopts
54 var ownProp = common.ownProp
55 var inflight = require('inflight')
56 var util = require('util')
57 var childrenIgnored = common.childrenIgnored
58 var isIgnored = common.isIgnored
59
60 var once = require('once')
61
62 function glob (pattern, options, cb) {
63 if (typeof options === 'function') cb = options, options = {}
64 if (!options) options = {}
65
66 if (options.sync) {
67 if (cb)
68 throw new TypeError('callback provided to sync glob')
69 return globSync(pattern, options)
70 }
71
72 return new Glob(pattern, options, cb)
73 }
74
75 glob.sync = globSync
76 var GlobSync = glob.GlobSync = globSync.GlobSync
77
78 // old api surface
79 glob.glob = glob
80
81 function extend (origin, add) {
82 if (add === null || typeof add !== 'object') {
83 return origin
84 }
85
86 var keys = Object.keys(add)
87 var i = keys.length
88 while (i--) {
89 origin[keys[i]] = add[keys[i]]
90 }
91 return origin
92 }
93
94 glob.hasMagic = function (pattern, options_) {
95 var options = extend({}, options_)
96 options.noprocess = true
97
98 var g = new Glob(pattern, options)
99 var set = g.minimatch.set
100
101 if (!pattern)
102 return false
103
104 if (set.length > 1)
105 return true
106
107 for (var j = 0; j < set[0].length; j++) {
108 if (typeof set[0][j] !== 'string')
109 return true
110 }
111
112 return false
113 }
114
115 glob.Glob = Glob
116 inherits(Glob, EE)
117 function Glob (pattern, options, cb) {
118 if (typeof options === 'function') {
119 cb = options
120 options = null
121 }
122
123 if (options && options.sync) {
124 if (cb)
125 throw new TypeError('callback provided to sync glob')
126 return new GlobSync(pattern, options)
127 }
128
129 if (!(this instanceof Glob))
130 return new Glob(pattern, options, cb)
131
132 setopts(this, pattern, options)
133 this._didRealPath = false
134
135 // process each pattern in the minimatch set
136 var n = this.minimatch.set.length
137
138 // The matches are stored as {<filename>: true,...} so that
139 // duplicates are automagically pruned.
140 // Later, we do an Object.keys() on these.
141 // Keep them as a list so we can fill in when nonull is set.
142 this.matches = new Array(n)
143
144 if (typeof cb === 'function') {
145 cb = once(cb)
146 this.on('error', cb)
147 this.on('end', function (matches) {
148 cb(null, matches)
149 })
150 }
151
152 var self = this
153 this._processing = 0
154
155 this._emitQueue = []
156 this._processQueue = []
157 this.paused = false
158
159 if (this.noprocess)
160 return this
161
162 if (n === 0)
163 return done()
164
165 var sync = true
166 for (var i = 0; i < n; i ++) {
167 this._process(this.minimatch.set[i], i, false, done)
168 }
169 sync = false
170
171 function done () {
172 --self._processing
173 if (self._processing <= 0) {
174 if (sync) {
175 process.nextTick(function () {
176 self._finish()
177 })
178 } else {
179 self._finish()
180 }
181 }
182 }
183 }
184
185 Glob.prototype._finish = function () {
186 assert(this instanceof Glob)
187 if (this.aborted)
188 return
189
190 if (this.realpath && !this._didRealpath)
191 return this._realpath()
192
193 common.finish(this)
194 this.emit('end', this.found)
195 }
196
197 Glob.prototype._realpath = function () {
198 if (this._didRealpath)
199 return
200
201 this._didRealpath = true
202
203 var n = this.matches.length
204 if (n === 0)
205 return this._finish()
206
207 var self = this
208 for (var i = 0; i < this.matches.length; i++)
209 this._realpathSet(i, next)
210
211 function next () {
212 if (--n === 0)
213 self._finish()
214 }
215 }
216
217 Glob.prototype._realpathSet = function (index, cb) {
218 var matchset = this.matches[index]
219 if (!matchset)
220 return cb()
221
222 var found = Object.keys(matchset)
223 var self = this
224 var n = found.length
225
226 if (n === 0)
227 return cb()
228
229 var set = this.matches[index] = Object.create(null)
230 found.forEach(function (p, i) {
231 // If there's a problem with the stat, then it means that
232 // one or more of the links in the realpath couldn't be
233 // resolved. just return the abs value in that case.
234 p = self._makeAbs(p)
235 rp.realpath(p, self.realpathCache, function (er, real) {
236 if (!er)
237 set[real] = true
238 else if (er.syscall === 'stat')
239 set[p] = true
240 else
241 self.emit('error', er) // srsly wtf right here
242
243 if (--n === 0) {
244 self.matches[index] = set
245 cb()
246 }
247 })
248 })
249 }
250
251 Glob.prototype._mark = function (p) {
252 return common.mark(this, p)
253 }
254
255 Glob.prototype._makeAbs = function (f) {
256 return common.makeAbs(this, f)
257 }
258
259 Glob.prototype.abort = function () {
260 this.aborted = true
261 this.emit('abort')
262 }
263
264 Glob.prototype.pause = function () {
265 if (!this.paused) {
266 this.paused = true
267 this.emit('pause')
268 }
269 }
270
271 Glob.prototype.resume = function () {
272 if (this.paused) {
273 this.emit('resume')
274 this.paused = false
275 if (this._emitQueue.length) {
276 var eq = this._emitQueue.slice(0)
277 this._emitQueue.length = 0
278 for (var i = 0; i < eq.length; i ++) {
279 var e = eq[i]
280 this._emitMatch(e[0], e[1])
281 }
282 }
283 if (this._processQueue.length) {
284 var pq = this._processQueue.slice(0)
285 this._processQueue.length = 0
286 for (var i = 0; i < pq.length; i ++) {
287 var p = pq[i]
288 this._processing--
289 this._process(p[0], p[1], p[2], p[3])
290 }
291 }
292 }
293 }
294
295 Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
296 assert(this instanceof Glob)
297 assert(typeof cb === 'function')
298
299 if (this.aborted)
300 return
301
302 this._processing++
303 if (this.paused) {
304 this._processQueue.push([pattern, index, inGlobStar, cb])
305 return
306 }
307
308 //console.error('PROCESS %d', this._processing, pattern)
309
310 // Get the first [n] parts of pattern that are all strings.
311 var n = 0
312 while (typeof pattern[n] === 'string') {
313 n ++
314 }
315 // now n is the index of the first one that is *not* a string.
316
317 // see if there's anything else
318 var prefix
319 switch (n) {
320 // if not, then this is rather simple
321 case pattern.length:
322 this._processSimple(pattern.join('/'), index, cb)
323 return
324
325 case 0:
326 // pattern *starts* with some non-trivial item.
327 // going to readdir(cwd), but not include the prefix in matches.
328 prefix = null
329 break
330
331 default:
332 // pattern has some string bits in the front.
333 // whatever it starts with, whether that's 'absolute' like /foo/bar,
334 // or 'relative' like '../baz'
335 prefix = pattern.slice(0, n).join('/')
336 break
337 }
338
339 var remain = pattern.slice(n)
340
341 // get the list of entries.
342 var read
343 if (prefix === null)
344 read = '.'
345 else if (isAbsolute(prefix) ||
346 isAbsolute(pattern.map(function (p) {
347 return typeof p === 'string' ? p : '[*]'
348 }).join('/'))) {
349 if (!prefix || !isAbsolute(prefix))
350 prefix = '/' + prefix
351 read = prefix
352 } else
353 read = prefix
354
355 var abs = this._makeAbs(read)
356
357 //if ignored, skip _processing
358 if (childrenIgnored(this, read))
359 return cb()
360
361 var isGlobStar = remain[0] === minimatch.GLOBSTAR
362 if (isGlobStar)
363 this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
364 else
365 this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
366 }
367
368 Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
369 var self = this
370 this._readdir(abs, inGlobStar, function (er, entries) {
371 return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
372 })
373 }
374
375 Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
376
377 // if the abs isn't a dir, then nothing can match!
378 if (!entries)
379 return cb()
380
381 // It will only match dot entries if it starts with a dot, or if
382 // dot is set. Stuff like @(.foo|.bar) isn't allowed.
383 var pn = remain[0]
384 var negate = !!this.minimatch.negate
385 var rawGlob = pn._glob
386 var dotOk = this.dot || rawGlob.charAt(0) === '.'
387
388 var matchedEntries = []
389 for (var i = 0; i < entries.length; i++) {
390 var e = entries[i]
391 if (e.charAt(0) !== '.' || dotOk) {
392 var m
393 if (negate && !prefix) {
394 m = !e.match(pn)
395 } else {
396 m = e.match(pn)
397 }
398 if (m)
399 matchedEntries.push(e)
400 }
401 }
402
403 //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
404
405 var len = matchedEntries.length
406 // If there are no matched entries, then nothing matches.
407 if (len === 0)
408 return cb()
409
410 // if this is the last remaining pattern bit, then no need for
411 // an additional stat *unless* the user has specified mark or
412 // stat explicitly. We know they exist, since readdir returned
413 // them.
414
415 if (remain.length === 1 && !this.mark && !this.stat) {
416 if (!this.matches[index])
417 this.matches[index] = Object.create(null)
418
419 for (var i = 0; i < len; i ++) {
420 var e = matchedEntries[i]
421 if (prefix) {
422 if (prefix !== '/')
423 e = prefix + '/' + e
424 else
425 e = prefix + e
426 }
427
428 if (e.charAt(0) === '/' && !this.nomount) {
429 e = path.join(this.root, e)
430 }
431 this._emitMatch(index, e)
432 }
433 // This was the last one, and no stats were needed
434 return cb()
435 }
436
437 // now test all matched entries as stand-ins for that part
438 // of the pattern.
439 remain.shift()
440 for (var i = 0; i < len; i ++) {
441 var e = matchedEntries[i]
442 var newPattern
443 if (prefix) {
444 if (prefix !== '/')
445 e = prefix + '/' + e
446 else
447 e = prefix + e
448 }
449 this._process([e].concat(remain), index, inGlobStar, cb)
450 }
451 cb()
452 }
453
454 Glob.prototype._emitMatch = function (index, e) {
455 if (this.aborted)
456 return
457
458 if (isIgnored(this, e))
459 return
460
461 if (this.paused) {
462 this._emitQueue.push([index, e])
463 return
464 }
465
466 var abs = isAbsolute(e) ? e : this._makeAbs(e)
467
468 if (this.mark)
469 e = this._mark(e)
470
471 if (this.absolute)
472 e = abs
473
474 if (this.matches[index][e])
475 return
476
477 if (this.nodir) {
478 var c = this.cache[abs]
479 if (c === 'DIR' || Array.isArray(c))
480 return
481 }
482
483 this.matches[index][e] = true
484
485 var st = this.statCache[abs]
486 if (st)
487 this.emit('stat', e, st)
488
489 this.emit('match', e)
490 }
491
492 Glob.prototype._readdirInGlobStar = function (abs, cb) {
493 if (this.aborted)
494 return
495
496 // follow all symlinked directories forever
497 // just proceed as if this is a non-globstar situation
498 if (this.follow)
499 return this._readdir(abs, false, cb)
500
501 var lstatkey = 'lstat\0' + abs
502 var self = this
503 var lstatcb = inflight(lstatkey, lstatcb_)
504
505 if (lstatcb)
506 self.fs.lstat(abs, lstatcb)
507
508 function lstatcb_ (er, lstat) {
509 if (er && er.code === 'ENOENT')
510 return cb()
511
512 var isSym = lstat && lstat.isSymbolicLink()
513 self.symlinks[abs] = isSym
514
515 // If it's not a symlink or a dir, then it's definitely a regular file.
516 // don't bother doing a readdir in that case.
517 if (!isSym && lstat && !lstat.isDirectory()) {
518 self.cache[abs] = 'FILE'
519 cb()
520 } else
521 self._readdir(abs, false, cb)
522 }
523 }
524
525 Glob.prototype._readdir = function (abs, inGlobStar, cb) {
526 if (this.aborted)
527 return
528
529 cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
530 if (!cb)
531 return
532
533 //console.error('RD %j %j', +inGlobStar, abs)
534 if (inGlobStar && !ownProp(this.symlinks, abs))
535 return this._readdirInGlobStar(abs, cb)
536
537 if (ownProp(this.cache, abs)) {
538 var c = this.cache[abs]
539 if (!c || c === 'FILE')
540 return cb()
541
542 if (Array.isArray(c))
543 return cb(null, c)
544 }
545
546 var self = this
547 self.fs.readdir(abs, readdirCb(this, abs, cb))
548 }
549
550 function readdirCb (self, abs, cb) {
551 return function (er, entries) {
552 if (er)
553 self._readdirError(abs, er, cb)
554 else
555 self._readdirEntries(abs, entries, cb)
556 }
557 }
558
559 Glob.prototype._readdirEntries = function (abs, entries, cb) {
560 if (this.aborted)
561 return
562
563 // if we haven't asked to stat everything, then just
564 // assume that everything in there exists, so we can avoid
565 // having to stat it a second time.
566 if (!this.mark && !this.stat) {
567 for (var i = 0; i < entries.length; i ++) {
568 var e = entries[i]
569 if (abs === '/')
570 e = abs + e
571 else
572 e = abs + '/' + e
573 this.cache[e] = true
574 }
575 }
576
577 this.cache[abs] = entries
578 return cb(null, entries)
579 }
580
581 Glob.prototype._readdirError = function (f, er, cb) {
582 if (this.aborted)
583 return
584
585 // handle errors, and cache the information
586 switch (er.code) {
587 case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
588 case 'ENOTDIR': // totally normal. means it *does* exist.
589 var abs = this._makeAbs(f)
590 this.cache[abs] = 'FILE'
591 if (abs === this.cwdAbs) {
592 var error = new Error(er.code + ' invalid cwd ' + this.cwd)
593 error.path = this.cwd
594 error.code = er.code
595 this.emit('error', error)
596 this.abort()
597 }
598 break
599
600 case 'ENOENT': // not terribly unusual
601 case 'ELOOP':
602 case 'ENAMETOOLONG':
603 case 'UNKNOWN':
604 this.cache[this._makeAbs(f)] = false
605 break
606
607 default: // some unusual error. Treat as failure.
608 this.cache[this._makeAbs(f)] = false
609 if (this.strict) {
610 this.emit('error', er)
611 // If the error is handled, then we abort
612 // if not, we threw out of here
613 this.abort()
614 }
615 if (!this.silent)
616 console.error('glob error', er)
617 break
618 }
619
620 return cb()
621 }
622
623 Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
624 var self = this
625 this._readdir(abs, inGlobStar, function (er, entries) {
626 self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
627 })
628 }
629
630
631 Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
632 //console.error('pgs2', prefix, remain[0], entries)
633
634 // no entries means not a dir, so it can never have matches
635 // foo.txt/** doesn't match foo.txt
636 if (!entries)
637 return cb()
638
639 // test without the globstar, and with every child both below
640 // and replacing the globstar.
641 var remainWithoutGlobStar = remain.slice(1)
642 var gspref = prefix ? [ prefix ] : []
643 var noGlobStar = gspref.concat(remainWithoutGlobStar)
644
645 // the noGlobStar pattern exits the inGlobStar state
646 this._process(noGlobStar, index, false, cb)
647
648 var isSym = this.symlinks[abs]
649 var len = entries.length
650
651 // If it's a symlink, and we're in a globstar, then stop
652 if (isSym && inGlobStar)
653 return cb()
654
655 for (var i = 0; i < len; i++) {
656 var e = entries[i]
657 if (e.charAt(0) === '.' && !this.dot)
658 continue
659
660 // these two cases enter the inGlobStar state
661 var instead = gspref.concat(entries[i], remainWithoutGlobStar)
662 this._process(instead, index, true, cb)
663
664 var below = gspref.concat(entries[i], remain)
665 this._process(below, index, true, cb)
666 }
667
668 cb()
669 }
670
671 Glob.prototype._processSimple = function (prefix, index, cb) {
672 // XXX review this. Shouldn't it be doing the mounting etc
673 // before doing stat? kinda weird?
674 var self = this
675 this._stat(prefix, function (er, exists) {
676 self._processSimple2(prefix, index, er, exists, cb)
677 })
678 }
679 Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
680
681 //console.error('ps2', prefix, exists)
682
683 if (!this.matches[index])
684 this.matches[index] = Object.create(null)
685
686 // If it doesn't exist, then just mark the lack of results
687 if (!exists)
688 return cb()
689
690 if (prefix && isAbsolute(prefix) && !this.nomount) {
691 var trail = /[\/\\]$/.test(prefix)
692 if (prefix.charAt(0) === '/') {
693 prefix = path.join(this.root, prefix)
694 } else {
695 prefix = path.resolve(this.root, prefix)
696 if (trail)
697 prefix += '/'
698 }
699 }
700
701 if (process.platform === 'win32')
702 prefix = prefix.replace(/\\/g, '/')
703
704 // Mark this as a match
705 this._emitMatch(index, prefix)
706 cb()
707 }
708
709 // Returns either 'DIR', 'FILE', or false
710 Glob.prototype._stat = function (f, cb) {
711 var abs = this._makeAbs(f)
712 var needDir = f.slice(-1) === '/'
713
714 if (f.length > this.maxLength)
715 return cb()
716
717 if (!this.stat && ownProp(this.cache, abs)) {
718 var c = this.cache[abs]
719
720 if (Array.isArray(c))
721 c = 'DIR'
722
723 // It exists, but maybe not how we need it
724 if (!needDir || c === 'DIR')
725 return cb(null, c)
726
727 if (needDir && c === 'FILE')
728 return cb()
729
730 // otherwise we have to stat, because maybe c=true
731 // if we know it exists, but not what it is.
732 }
733
734 var exists
735 var stat = this.statCache[abs]
736 if (stat !== undefined) {
737 if (stat === false)
738 return cb(null, stat)
739 else {
740 var type = stat.isDirectory() ? 'DIR' : 'FILE'
741 if (needDir && type === 'FILE')
742 return cb()
743 else
744 return cb(null, type, stat)
745 }
746 }
747
748 var self = this
749 var statcb = inflight('stat\0' + abs, lstatcb_)
750 if (statcb)
751 self.fs.lstat(abs, statcb)
752
753 function lstatcb_ (er, lstat) {
754 if (lstat && lstat.isSymbolicLink()) {
755 // If it's a symlink, then treat it as the target, unless
756 // the target does not exist, then treat it as a file.
757 return self.fs.stat(abs, function (er, stat) {
758 if (er)
759 self._stat2(f, abs, null, lstat, cb)
760 else
761 self._stat2(f, abs, er, stat, cb)
762 })
763 } else {
764 self._stat2(f, abs, er, lstat, cb)
765 }
766 }
767 }
768
769 Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
770 if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
771 this.statCache[abs] = false
772 return cb()
773 }
774
775 var needDir = f.slice(-1) === '/'
776 this.statCache[abs] = stat
777
778 if (abs.slice(-1) === '/' && stat && !stat.isDirectory())
779 return cb(null, false, stat)
780
781 var c = true
782 if (stat)
783 c = stat.isDirectory() ? 'DIR' : 'FILE'
784 this.cache[abs] = this.cache[abs] || c
785
786 if (needDir && c === 'FILE')
787 return cb()
788
789 return cb(null, c, stat)
790 }
1 {
2 "_from": "glob@^8.0.1",
3 "_id": "glob@8.0.3",
4 "_inBundle": false,
5 "_integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
6 "_location": "/vue-qr/glob",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "glob@^8.0.1",
12 "name": "glob",
13 "escapedName": "glob",
14 "rawSpec": "^8.0.1",
15 "saveSpec": null,
16 "fetchSpec": "^8.0.1"
17 },
18 "_requiredBy": [
19 "/vue-qr"
20 ],
21 "_resolved": "https://registry.npmmirror.com/glob/-/glob-8.0.3.tgz",
22 "_shasum": "415c6eb2deed9e502c68fa44a272e6da6eeca42e",
23 "_spec": "glob@^8.0.1",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr",
25 "author": {
26 "name": "Isaac Z. Schlueter",
27 "email": "i@izs.me",
28 "url": "http://blog.izs.me/"
29 },
30 "bugs": {
31 "url": "https://github.com/isaacs/node-glob/issues"
32 },
33 "bundleDependencies": false,
34 "dependencies": {
35 "fs.realpath": "^1.0.0",
36 "inflight": "^1.0.4",
37 "inherits": "2",
38 "minimatch": "^5.0.1",
39 "once": "^1.3.0"
40 },
41 "deprecated": false,
42 "description": "a little globber",
43 "devDependencies": {
44 "memfs": "^3.2.0",
45 "mkdirp": "0",
46 "rimraf": "^2.2.8",
47 "tap": "^16.0.1",
48 "tick": "0.0.6"
49 },
50 "engines": {
51 "node": ">=12"
52 },
53 "files": [
54 "glob.js",
55 "sync.js",
56 "common.js"
57 ],
58 "funding": {
59 "url": "https://github.com/sponsors/isaacs"
60 },
61 "homepage": "https://github.com/isaacs/node-glob#readme",
62 "license": "ISC",
63 "main": "glob.js",
64 "name": "glob",
65 "repository": {
66 "type": "git",
67 "url": "git://github.com/isaacs/node-glob.git"
68 },
69 "scripts": {
70 "bench": "bash benchmark.sh",
71 "benchclean": "node benchclean.js",
72 "prepublish": "npm run benchclean",
73 "prof": "bash prof.sh && cat profile.txt",
74 "profclean": "rm -f v8.log profile.txt",
75 "test": "tap",
76 "test-regen": "npm run profclean && TEST_REGEN=1 node test/00-setup.js"
77 },
78 "tap": {
79 "before": "test/00-setup.js",
80 "after": "test/zz-cleanup.js",
81 "statements": 90,
82 "branches": 90,
83 "functions": 90,
84 "lines": 90,
85 "jobs": 1
86 },
87 "version": "8.0.3"
88 }
1 module.exports = globSync
2 globSync.GlobSync = GlobSync
3
4 var rp = require('fs.realpath')
5 var minimatch = require('minimatch')
6 var Minimatch = minimatch.Minimatch
7 var Glob = require('./glob.js').Glob
8 var util = require('util')
9 var path = require('path')
10 var assert = require('assert')
11 var isAbsolute = require('path').isAbsolute
12 var common = require('./common.js')
13 var setopts = common.setopts
14 var ownProp = common.ownProp
15 var childrenIgnored = common.childrenIgnored
16 var isIgnored = common.isIgnored
17
18 function globSync (pattern, options) {
19 if (typeof options === 'function' || arguments.length === 3)
20 throw new TypeError('callback provided to sync glob\n'+
21 'See: https://github.com/isaacs/node-glob/issues/167')
22
23 return new GlobSync(pattern, options).found
24 }
25
26 function GlobSync (pattern, options) {
27 if (!pattern)
28 throw new Error('must provide pattern')
29
30 if (typeof options === 'function' || arguments.length === 3)
31 throw new TypeError('callback provided to sync glob\n'+
32 'See: https://github.com/isaacs/node-glob/issues/167')
33
34 if (!(this instanceof GlobSync))
35 return new GlobSync(pattern, options)
36
37 setopts(this, pattern, options)
38
39 if (this.noprocess)
40 return this
41
42 var n = this.minimatch.set.length
43 this.matches = new Array(n)
44 for (var i = 0; i < n; i ++) {
45 this._process(this.minimatch.set[i], i, false)
46 }
47 this._finish()
48 }
49
50 GlobSync.prototype._finish = function () {
51 assert.ok(this instanceof GlobSync)
52 if (this.realpath) {
53 var self = this
54 this.matches.forEach(function (matchset, index) {
55 var set = self.matches[index] = Object.create(null)
56 for (var p in matchset) {
57 try {
58 p = self._makeAbs(p)
59 var real = rp.realpathSync(p, self.realpathCache)
60 set[real] = true
61 } catch (er) {
62 if (er.syscall === 'stat')
63 set[self._makeAbs(p)] = true
64 else
65 throw er
66 }
67 }
68 })
69 }
70 common.finish(this)
71 }
72
73
74 GlobSync.prototype._process = function (pattern, index, inGlobStar) {
75 assert.ok(this instanceof GlobSync)
76
77 // Get the first [n] parts of pattern that are all strings.
78 var n = 0
79 while (typeof pattern[n] === 'string') {
80 n ++
81 }
82 // now n is the index of the first one that is *not* a string.
83
84 // See if there's anything else
85 var prefix
86 switch (n) {
87 // if not, then this is rather simple
88 case pattern.length:
89 this._processSimple(pattern.join('/'), index)
90 return
91
92 case 0:
93 // pattern *starts* with some non-trivial item.
94 // going to readdir(cwd), but not include the prefix in matches.
95 prefix = null
96 break
97
98 default:
99 // pattern has some string bits in the front.
100 // whatever it starts with, whether that's 'absolute' like /foo/bar,
101 // or 'relative' like '../baz'
102 prefix = pattern.slice(0, n).join('/')
103 break
104 }
105
106 var remain = pattern.slice(n)
107
108 // get the list of entries.
109 var read
110 if (prefix === null)
111 read = '.'
112 else if (isAbsolute(prefix) ||
113 isAbsolute(pattern.map(function (p) {
114 return typeof p === 'string' ? p : '[*]'
115 }).join('/'))) {
116 if (!prefix || !isAbsolute(prefix))
117 prefix = '/' + prefix
118 read = prefix
119 } else
120 read = prefix
121
122 var abs = this._makeAbs(read)
123
124 //if ignored, skip processing
125 if (childrenIgnored(this, read))
126 return
127
128 var isGlobStar = remain[0] === minimatch.GLOBSTAR
129 if (isGlobStar)
130 this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
131 else
132 this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
133 }
134
135
136 GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
137 var entries = this._readdir(abs, inGlobStar)
138
139 // if the abs isn't a dir, then nothing can match!
140 if (!entries)
141 return
142
143 // It will only match dot entries if it starts with a dot, or if
144 // dot is set. Stuff like @(.foo|.bar) isn't allowed.
145 var pn = remain[0]
146 var negate = !!this.minimatch.negate
147 var rawGlob = pn._glob
148 var dotOk = this.dot || rawGlob.charAt(0) === '.'
149
150 var matchedEntries = []
151 for (var i = 0; i < entries.length; i++) {
152 var e = entries[i]
153 if (e.charAt(0) !== '.' || dotOk) {
154 var m
155 if (negate && !prefix) {
156 m = !e.match(pn)
157 } else {
158 m = e.match(pn)
159 }
160 if (m)
161 matchedEntries.push(e)
162 }
163 }
164
165 var len = matchedEntries.length
166 // If there are no matched entries, then nothing matches.
167 if (len === 0)
168 return
169
170 // if this is the last remaining pattern bit, then no need for
171 // an additional stat *unless* the user has specified mark or
172 // stat explicitly. We know they exist, since readdir returned
173 // them.
174
175 if (remain.length === 1 && !this.mark && !this.stat) {
176 if (!this.matches[index])
177 this.matches[index] = Object.create(null)
178
179 for (var i = 0; i < len; i ++) {
180 var e = matchedEntries[i]
181 if (prefix) {
182 if (prefix.slice(-1) !== '/')
183 e = prefix + '/' + e
184 else
185 e = prefix + e
186 }
187
188 if (e.charAt(0) === '/' && !this.nomount) {
189 e = path.join(this.root, e)
190 }
191 this._emitMatch(index, e)
192 }
193 // This was the last one, and no stats were needed
194 return
195 }
196
197 // now test all matched entries as stand-ins for that part
198 // of the pattern.
199 remain.shift()
200 for (var i = 0; i < len; i ++) {
201 var e = matchedEntries[i]
202 var newPattern
203 if (prefix)
204 newPattern = [prefix, e]
205 else
206 newPattern = [e]
207 this._process(newPattern.concat(remain), index, inGlobStar)
208 }
209 }
210
211
212 GlobSync.prototype._emitMatch = function (index, e) {
213 if (isIgnored(this, e))
214 return
215
216 var abs = this._makeAbs(e)
217
218 if (this.mark)
219 e = this._mark(e)
220
221 if (this.absolute) {
222 e = abs
223 }
224
225 if (this.matches[index][e])
226 return
227
228 if (this.nodir) {
229 var c = this.cache[abs]
230 if (c === 'DIR' || Array.isArray(c))
231 return
232 }
233
234 this.matches[index][e] = true
235
236 if (this.stat)
237 this._stat(e)
238 }
239
240
241 GlobSync.prototype._readdirInGlobStar = function (abs) {
242 // follow all symlinked directories forever
243 // just proceed as if this is a non-globstar situation
244 if (this.follow)
245 return this._readdir(abs, false)
246
247 var entries
248 var lstat
249 var stat
250 try {
251 lstat = this.fs.lstatSync(abs)
252 } catch (er) {
253 if (er.code === 'ENOENT') {
254 // lstat failed, doesn't exist
255 return null
256 }
257 }
258
259 var isSym = lstat && lstat.isSymbolicLink()
260 this.symlinks[abs] = isSym
261
262 // If it's not a symlink or a dir, then it's definitely a regular file.
263 // don't bother doing a readdir in that case.
264 if (!isSym && lstat && !lstat.isDirectory())
265 this.cache[abs] = 'FILE'
266 else
267 entries = this._readdir(abs, false)
268
269 return entries
270 }
271
272 GlobSync.prototype._readdir = function (abs, inGlobStar) {
273 var entries
274
275 if (inGlobStar && !ownProp(this.symlinks, abs))
276 return this._readdirInGlobStar(abs)
277
278 if (ownProp(this.cache, abs)) {
279 var c = this.cache[abs]
280 if (!c || c === 'FILE')
281 return null
282
283 if (Array.isArray(c))
284 return c
285 }
286
287 try {
288 return this._readdirEntries(abs, this.fs.readdirSync(abs))
289 } catch (er) {
290 this._readdirError(abs, er)
291 return null
292 }
293 }
294
295 GlobSync.prototype._readdirEntries = function (abs, entries) {
296 // if we haven't asked to stat everything, then just
297 // assume that everything in there exists, so we can avoid
298 // having to stat it a second time.
299 if (!this.mark && !this.stat) {
300 for (var i = 0; i < entries.length; i ++) {
301 var e = entries[i]
302 if (abs === '/')
303 e = abs + e
304 else
305 e = abs + '/' + e
306 this.cache[e] = true
307 }
308 }
309
310 this.cache[abs] = entries
311
312 // mark and cache dir-ness
313 return entries
314 }
315
316 GlobSync.prototype._readdirError = function (f, er) {
317 // handle errors, and cache the information
318 switch (er.code) {
319 case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
320 case 'ENOTDIR': // totally normal. means it *does* exist.
321 var abs = this._makeAbs(f)
322 this.cache[abs] = 'FILE'
323 if (abs === this.cwdAbs) {
324 var error = new Error(er.code + ' invalid cwd ' + this.cwd)
325 error.path = this.cwd
326 error.code = er.code
327 throw error
328 }
329 break
330
331 case 'ENOENT': // not terribly unusual
332 case 'ELOOP':
333 case 'ENAMETOOLONG':
334 case 'UNKNOWN':
335 this.cache[this._makeAbs(f)] = false
336 break
337
338 default: // some unusual error. Treat as failure.
339 this.cache[this._makeAbs(f)] = false
340 if (this.strict)
341 throw er
342 if (!this.silent)
343 console.error('glob error', er)
344 break
345 }
346 }
347
348 GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
349
350 var entries = this._readdir(abs, inGlobStar)
351
352 // no entries means not a dir, so it can never have matches
353 // foo.txt/** doesn't match foo.txt
354 if (!entries)
355 return
356
357 // test without the globstar, and with every child both below
358 // and replacing the globstar.
359 var remainWithoutGlobStar = remain.slice(1)
360 var gspref = prefix ? [ prefix ] : []
361 var noGlobStar = gspref.concat(remainWithoutGlobStar)
362
363 // the noGlobStar pattern exits the inGlobStar state
364 this._process(noGlobStar, index, false)
365
366 var len = entries.length
367 var isSym = this.symlinks[abs]
368
369 // If it's a symlink, and we're in a globstar, then stop
370 if (isSym && inGlobStar)
371 return
372
373 for (var i = 0; i < len; i++) {
374 var e = entries[i]
375 if (e.charAt(0) === '.' && !this.dot)
376 continue
377
378 // these two cases enter the inGlobStar state
379 var instead = gspref.concat(entries[i], remainWithoutGlobStar)
380 this._process(instead, index, true)
381
382 var below = gspref.concat(entries[i], remain)
383 this._process(below, index, true)
384 }
385 }
386
387 GlobSync.prototype._processSimple = function (prefix, index) {
388 // XXX review this. Shouldn't it be doing the mounting etc
389 // before doing stat? kinda weird?
390 var exists = this._stat(prefix)
391
392 if (!this.matches[index])
393 this.matches[index] = Object.create(null)
394
395 // If it doesn't exist, then just mark the lack of results
396 if (!exists)
397 return
398
399 if (prefix && isAbsolute(prefix) && !this.nomount) {
400 var trail = /[\/\\]$/.test(prefix)
401 if (prefix.charAt(0) === '/') {
402 prefix = path.join(this.root, prefix)
403 } else {
404 prefix = path.resolve(this.root, prefix)
405 if (trail)
406 prefix += '/'
407 }
408 }
409
410 if (process.platform === 'win32')
411 prefix = prefix.replace(/\\/g, '/')
412
413 // Mark this as a match
414 this._emitMatch(index, prefix)
415 }
416
417 // Returns either 'DIR', 'FILE', or false
418 GlobSync.prototype._stat = function (f) {
419 var abs = this._makeAbs(f)
420 var needDir = f.slice(-1) === '/'
421
422 if (f.length > this.maxLength)
423 return false
424
425 if (!this.stat && ownProp(this.cache, abs)) {
426 var c = this.cache[abs]
427
428 if (Array.isArray(c))
429 c = 'DIR'
430
431 // It exists, but maybe not how we need it
432 if (!needDir || c === 'DIR')
433 return c
434
435 if (needDir && c === 'FILE')
436 return false
437
438 // otherwise we have to stat, because maybe c=true
439 // if we know it exists, but not what it is.
440 }
441
442 var exists
443 var stat = this.statCache[abs]
444 if (!stat) {
445 var lstat
446 try {
447 lstat = this.fs.lstatSync(abs)
448 } catch (er) {
449 if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
450 this.statCache[abs] = false
451 return false
452 }
453 }
454
455 if (lstat && lstat.isSymbolicLink()) {
456 try {
457 stat = this.fs.statSync(abs)
458 } catch (er) {
459 stat = lstat
460 }
461 } else {
462 stat = lstat
463 }
464 }
465
466 this.statCache[abs] = stat
467
468 var c = true
469 if (stat)
470 c = stat.isDirectory() ? 'DIR' : 'FILE'
471
472 this.cache[abs] = this.cache[abs] || c
473
474 if (needDir && c === 'FILE')
475 return false
476
477 return c
478 }
479
480 GlobSync.prototype._mark = function (p) {
481 return common.mark(this, p)
482 }
483
484 GlobSync.prototype._makeAbs = function (f) {
485 return common.makeAbs(this, f)
486 }
1 The ISC License
2
3 Copyright (c) 2011-2022 Isaac Z. Schlueter and Contributors
4
5 Permission to use, copy, modify, and/or distribute this software for any
6 purpose with or without fee is hereby granted, provided that the above
7 copyright notice and this permission notice appear in all copies.
8
9 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1 # minimatch
2
3 A minimal matching utility.
4
5 [![Build Status](https://travis-ci.org/isaacs/minimatch.svg?branch=master)](http://travis-ci.org/isaacs/minimatch)
6
7
8 This is the matching library used internally by npm.
9
10 It works by converting glob expressions into JavaScript `RegExp`
11 objects.
12
13 ## Usage
14
15 ```javascript
16 var minimatch = require("minimatch")
17
18 minimatch("bar.foo", "*.foo") // true!
19 minimatch("bar.foo", "*.bar") // false!
20 minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
21 ```
22
23 ## Features
24
25 Supports these glob features:
26
27 * Brace Expansion
28 * Extended glob matching
29 * "Globstar" `**` matching
30
31 See:
32
33 * `man sh`
34 * `man bash`
35 * `man 3 fnmatch`
36 * `man 5 gitignore`
37
38 ## Windows
39
40 **Please only use forward-slashes in glob expressions.**
41
42 Though windows uses either `/` or `\` as its path separator, only `/`
43 characters are used by this glob implementation. You must use
44 forward-slashes **only** in glob expressions. Back-slashes in patterns
45 will always be interpreted as escape characters, not path separators.
46
47 Note that `\` or `/` _will_ be interpreted as path separators in paths on
48 Windows, and will match against `/` in glob expressions.
49
50 So just always use `/` in patterns.
51
52 ## Minimatch Class
53
54 Create a minimatch object by instantiating the `minimatch.Minimatch` class.
55
56 ```javascript
57 var Minimatch = require("minimatch").Minimatch
58 var mm = new Minimatch(pattern, options)
59 ```
60
61 ### Properties
62
63 * `pattern` The original pattern the minimatch object represents.
64 * `options` The options supplied to the constructor.
65 * `set` A 2-dimensional array of regexp or string expressions.
66 Each row in the
67 array corresponds to a brace-expanded pattern. Each item in the row
68 corresponds to a single path-part. For example, the pattern
69 `{a,b/c}/d` would expand to a set of patterns like:
70
71 [ [ a, d ]
72 , [ b, c, d ] ]
73
74 If a portion of the pattern doesn't have any "magic" in it
75 (that is, it's something like `"foo"` rather than `fo*o?`), then it
76 will be left as a string rather than converted to a regular
77 expression.
78
79 * `regexp` Created by the `makeRe` method. A single regular expression
80 expressing the entire pattern. This is useful in cases where you wish
81 to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
82 * `negate` True if the pattern is negated.
83 * `comment` True if the pattern is a comment.
84 * `empty` True if the pattern is `""`.
85
86 ### Methods
87
88 * `makeRe` Generate the `regexp` member if necessary, and return it.
89 Will return `false` if the pattern is invalid.
90 * `match(fname)` Return true if the filename matches the pattern, or
91 false otherwise.
92 * `matchOne(fileArray, patternArray, partial)` Take a `/`-split
93 filename, and match it against a single row in the `regExpSet`. This
94 method is mainly for internal use, but is exposed so that it can be
95 used by a glob-walker that needs to avoid excessive filesystem calls.
96
97 All other methods are internal, and will be called as necessary.
98
99 ### minimatch(path, pattern, options)
100
101 Main export. Tests a path against the pattern using the options.
102
103 ```javascript
104 var isJS = minimatch(file, "*.js", { matchBase: true })
105 ```
106
107 ### minimatch.filter(pattern, options)
108
109 Returns a function that tests its
110 supplied argument, suitable for use with `Array.filter`. Example:
111
112 ```javascript
113 var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
114 ```
115
116 ### minimatch.match(list, pattern, options)
117
118 Match against the list of
119 files, in the style of fnmatch or glob. If nothing is matched, and
120 options.nonull is set, then return a list containing the pattern itself.
121
122 ```javascript
123 var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})
124 ```
125
126 ### minimatch.makeRe(pattern, options)
127
128 Make a regular expression object from the pattern.
129
130 ## Options
131
132 All options are `false` by default.
133
134 ### debug
135
136 Dump a ton of stuff to stderr.
137
138 ### nobrace
139
140 Do not expand `{a,b}` and `{1..3}` brace sets.
141
142 ### noglobstar
143
144 Disable `**` matching against multiple folder names.
145
146 ### dot
147
148 Allow patterns to match filenames starting with a period, even if
149 the pattern does not explicitly have a period in that spot.
150
151 Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
152 is set.
153
154 ### noext
155
156 Disable "extglob" style patterns like `+(a|b)`.
157
158 ### nocase
159
160 Perform a case-insensitive match.
161
162 ### nonull
163
164 When a match is not found by `minimatch.match`, return a list containing
165 the pattern itself if this option is set. When not set, an empty list
166 is returned if there are no matches.
167
168 ### matchBase
169
170 If set, then patterns without slashes will be matched
171 against the basename of the path if it contains slashes. For example,
172 `a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
173
174 ### nocomment
175
176 Suppress the behavior of treating `#` at the start of a pattern as a
177 comment.
178
179 ### nonegate
180
181 Suppress the behavior of treating a leading `!` character as negation.
182
183 ### flipNegate
184
185 Returns from negate expressions the same as if they were not negated.
186 (Ie, true on a hit, false on a miss.)
187
188 ### partial
189
190 Compare a partial path to a pattern. As long as the parts of the path that
191 are present are not contradicted by the pattern, it will be treated as a
192 match. This is useful in applications where you're walking through a
193 folder structure, and don't yet have the full path, but want to ensure that
194 you do not walk down paths that can never be a match.
195
196 For example,
197
198 ```js
199 minimatch('/a/b', '/a/*/c/d', { partial: true }) // true, might be /a/b/c/d
200 minimatch('/a/b', '/**/d', { partial: true }) // true, might be /a/b/.../d
201 minimatch('/x/y/z', '/a/**/z', { partial: true }) // false, because x !== a
202 ```
203
204 ### windowsPathsNoEscape
205
206 Use `\\` as a path separator _only_, and _never_ as an escape
207 character. If set, all `\\` characters are replaced with `/` in
208 the pattern. Note that this makes it **impossible** to match
209 against paths containing literal glob pattern characters, but
210 allows matching with patterns constructed using `path.join()` and
211 `path.resolve()` on Windows platforms, mimicking the (buggy!)
212 behavior of earlier versions on Windows. Please use with
213 caution, and be mindful of [the caveat about Windows
214 paths](#windows).
215
216 For legacy reasons, this is also set if
217 `options.allowWindowsEscape` is set to the exact value `false`.
218
219 ## Comparisons to other fnmatch/glob implementations
220
221 While strict compliance with the existing standards is a worthwhile
222 goal, some discrepancies exist between minimatch and other
223 implementations, and are intentional.
224
225 If the pattern starts with a `!` character, then it is negated. Set the
226 `nonegate` flag to suppress this behavior, and treat leading `!`
227 characters normally. This is perhaps relevant if you wish to start the
228 pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
229 characters at the start of a pattern will negate the pattern multiple
230 times.
231
232 If a pattern starts with `#`, then it is treated as a comment, and
233 will not match anything. Use `\#` to match a literal `#` at the
234 start of a line, or set the `nocomment` flag to suppress this behavior.
235
236 The double-star character `**` is supported by default, unless the
237 `noglobstar` flag is set. This is supported in the manner of bsdglob
238 and bash 4.1, where `**` only has special significance if it is the only
239 thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
240 `a/**b` will not.
241
242 If an escaped pattern has no matches, and the `nonull` flag is set,
243 then minimatch.match returns the pattern as-provided, rather than
244 interpreting the character escapes. For example,
245 `minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
246 `"*a?"`. This is akin to setting the `nullglob` option in bash, except
247 that it does not resolve escaped pattern characters.
248
249 If brace expansion is not disabled, then it is performed before any
250 other interpretation of the glob pattern. Thus, a pattern like
251 `+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
252 **first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
253 checked for validity. Since those two are valid, matching proceeds.
254
255 Note that `fnmatch(3)` in libc is an extremely naive string comparison
256 matcher, which does not do anything special for slashes. This library is
257 designed to be used in glob searching and file walkers, and so it does do
258 special things with `/`. Thus, `foo*` will not match `foo/bar` in this
259 library, even though it would in `fnmatch(3)`.
1 const isWindows = typeof process === 'object' &&
2 process &&
3 process.platform === 'win32'
4 module.exports = isWindows ? { sep: '\\' } : { sep: '/' }
1 const minimatch = module.exports = (p, pattern, options = {}) => {
2 assertValidPattern(pattern)
3
4 // shortcut: comments match nothing.
5 if (!options.nocomment && pattern.charAt(0) === '#') {
6 return false
7 }
8
9 return new Minimatch(pattern, options).match(p)
10 }
11
12 module.exports = minimatch
13
14 const path = require('./lib/path.js')
15 minimatch.sep = path.sep
16
17 const GLOBSTAR = Symbol('globstar **')
18 minimatch.GLOBSTAR = GLOBSTAR
19 const expand = require('brace-expansion')
20
21 const plTypes = {
22 '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
23 '?': { open: '(?:', close: ')?' },
24 '+': { open: '(?:', close: ')+' },
25 '*': { open: '(?:', close: ')*' },
26 '@': { open: '(?:', close: ')' }
27 }
28
29 // any single thing other than /
30 // don't need to escape / when using new RegExp()
31 const qmark = '[^/]'
32
33 // * => any number of characters
34 const star = qmark + '*?'
35
36 // ** when dots are allowed. Anything goes, except .. and .
37 // not (^ or / followed by one or two dots followed by $ or /),
38 // followed by anything, any number of times.
39 const twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
40
41 // not a ^ or / followed by a dot,
42 // followed by anything, any number of times.
43 const twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
44
45 // "abc" -> { a:true, b:true, c:true }
46 const charSet = s => s.split('').reduce((set, c) => {
47 set[c] = true
48 return set
49 }, {})
50
51 // characters that need to be escaped in RegExp.
52 const reSpecials = charSet('().*{}+?[]^$\\!')
53
54 // characters that indicate we have to add the pattern start
55 const addPatternStartSet = charSet('[.(')
56
57 // normalizes slashes.
58 const slashSplit = /\/+/
59
60 minimatch.filter = (pattern, options = {}) =>
61 (p, i, list) => minimatch(p, pattern, options)
62
63 const ext = (a, b = {}) => {
64 const t = {}
65 Object.keys(a).forEach(k => t[k] = a[k])
66 Object.keys(b).forEach(k => t[k] = b[k])
67 return t
68 }
69
70 minimatch.defaults = def => {
71 if (!def || typeof def !== 'object' || !Object.keys(def).length) {
72 return minimatch
73 }
74
75 const orig = minimatch
76
77 const m = (p, pattern, options) => orig(p, pattern, ext(def, options))
78 m.Minimatch = class Minimatch extends orig.Minimatch {
79 constructor (pattern, options) {
80 super(pattern, ext(def, options))
81 }
82 }
83 m.Minimatch.defaults = options => orig.defaults(ext(def, options)).Minimatch
84 m.filter = (pattern, options) => orig.filter(pattern, ext(def, options))
85 m.defaults = options => orig.defaults(ext(def, options))
86 m.makeRe = (pattern, options) => orig.makeRe(pattern, ext(def, options))
87 m.braceExpand = (pattern, options) => orig.braceExpand(pattern, ext(def, options))
88 m.match = (list, pattern, options) => orig.match(list, pattern, ext(def, options))
89
90 return m
91 }
92
93
94
95
96
97 // Brace expansion:
98 // a{b,c}d -> abd acd
99 // a{b,}c -> abc ac
100 // a{0..3}d -> a0d a1d a2d a3d
101 // a{b,c{d,e}f}g -> abg acdfg acefg
102 // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
103 //
104 // Invalid sets are not expanded.
105 // a{2..}b -> a{2..}b
106 // a{b}c -> a{b}c
107 minimatch.braceExpand = (pattern, options) => braceExpand(pattern, options)
108
109 const braceExpand = (pattern, options = {}) => {
110 assertValidPattern(pattern)
111
112 // Thanks to Yeting Li <https://github.com/yetingli> for
113 // improving this regexp to avoid a ReDOS vulnerability.
114 if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
115 // shortcut. no need to expand.
116 return [pattern]
117 }
118
119 return expand(pattern)
120 }
121
122 const MAX_PATTERN_LENGTH = 1024 * 64
123 const assertValidPattern = pattern => {
124 if (typeof pattern !== 'string') {
125 throw new TypeError('invalid pattern')
126 }
127
128 if (pattern.length > MAX_PATTERN_LENGTH) {
129 throw new TypeError('pattern is too long')
130 }
131 }
132
133 // parse a component of the expanded set.
134 // At this point, no pattern may contain "/" in it
135 // so we're going to return a 2d array, where each entry is the full
136 // pattern, split on '/', and then turned into a regular expression.
137 // A regexp is made at the end which joins each array with an
138 // escaped /, and another full one which joins each regexp with |.
139 //
140 // Following the lead of Bash 4.1, note that "**" only has special meaning
141 // when it is the *only* thing in a path portion. Otherwise, any series
142 // of * is equivalent to a single *. Globstar behavior is enabled by
143 // default, and can be disabled by setting options.noglobstar.
144 const SUBPARSE = Symbol('subparse')
145
146 minimatch.makeRe = (pattern, options) =>
147 new Minimatch(pattern, options || {}).makeRe()
148
149 minimatch.match = (list, pattern, options = {}) => {
150 const mm = new Minimatch(pattern, options)
151 list = list.filter(f => mm.match(f))
152 if (mm.options.nonull && !list.length) {
153 list.push(pattern)
154 }
155 return list
156 }
157
158 // replace stuff like \* with *
159 const globUnescape = s => s.replace(/\\(.)/g, '$1')
160 const regExpEscape = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
161
162 class Minimatch {
163 constructor (pattern, options) {
164 assertValidPattern(pattern)
165
166 if (!options) options = {}
167
168 this.options = options
169 this.set = []
170 this.pattern = pattern
171 this.windowsPathsNoEscape = !!options.windowsPathsNoEscape ||
172 options.allowWindowsEscape === false
173 if (this.windowsPathsNoEscape) {
174 this.pattern = this.pattern.replace(/\\/g, '/')
175 }
176 this.regexp = null
177 this.negate = false
178 this.comment = false
179 this.empty = false
180 this.partial = !!options.partial
181
182 // make the set of regexps etc.
183 this.make()
184 }
185
186 debug () {}
187
188 make () {
189 const pattern = this.pattern
190 const options = this.options
191
192 // empty patterns and comments match nothing.
193 if (!options.nocomment && pattern.charAt(0) === '#') {
194 this.comment = true
195 return
196 }
197 if (!pattern) {
198 this.empty = true
199 return
200 }
201
202 // step 1: figure out negation, etc.
203 this.parseNegate()
204
205 // step 2: expand braces
206 let set = this.globSet = this.braceExpand()
207
208 if (options.debug) this.debug = (...args) => console.error(...args)
209
210 this.debug(this.pattern, set)
211
212 // step 3: now we have a set, so turn each one into a series of path-portion
213 // matching patterns.
214 // These will be regexps, except in the case of "**", which is
215 // set to the GLOBSTAR object for globstar behavior,
216 // and will not contain any / characters
217 set = this.globParts = set.map(s => s.split(slashSplit))
218
219 this.debug(this.pattern, set)
220
221 // glob --> regexps
222 set = set.map((s, si, set) => s.map(this.parse, this))
223
224 this.debug(this.pattern, set)
225
226 // filter out everything that didn't compile properly.
227 set = set.filter(s => s.indexOf(false) === -1)
228
229 this.debug(this.pattern, set)
230
231 this.set = set
232 }
233
234 parseNegate () {
235 if (this.options.nonegate) return
236
237 const pattern = this.pattern
238 let negate = false
239 let negateOffset = 0
240
241 for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
242 negate = !negate
243 negateOffset++
244 }
245
246 if (negateOffset) this.pattern = pattern.substr(negateOffset)
247 this.negate = negate
248 }
249
250 // set partial to true to test if, for example,
251 // "/a/b" matches the start of "/*/b/*/d"
252 // Partial means, if you run out of file before you run
253 // out of pattern, then that's fine, as long as all
254 // the parts match.
255 matchOne (file, pattern, partial) {
256 var options = this.options
257
258 this.debug('matchOne',
259 { 'this': this, file: file, pattern: pattern })
260
261 this.debug('matchOne', file.length, pattern.length)
262
263 for (var fi = 0,
264 pi = 0,
265 fl = file.length,
266 pl = pattern.length
267 ; (fi < fl) && (pi < pl)
268 ; fi++, pi++) {
269 this.debug('matchOne loop')
270 var p = pattern[pi]
271 var f = file[fi]
272
273 this.debug(pattern, p, f)
274
275 // should be impossible.
276 // some invalid regexp stuff in the set.
277 /* istanbul ignore if */
278 if (p === false) return false
279
280 if (p === GLOBSTAR) {
281 this.debug('GLOBSTAR', [pattern, p, f])
282
283 // "**"
284 // a/**/b/**/c would match the following:
285 // a/b/x/y/z/c
286 // a/x/y/z/b/c
287 // a/b/x/b/x/c
288 // a/b/c
289 // To do this, take the rest of the pattern after
290 // the **, and see if it would match the file remainder.
291 // If so, return success.
292 // If not, the ** "swallows" a segment, and try again.
293 // This is recursively awful.
294 //
295 // a/**/b/**/c matching a/b/x/y/z/c
296 // - a matches a
297 // - doublestar
298 // - matchOne(b/x/y/z/c, b/**/c)
299 // - b matches b
300 // - doublestar
301 // - matchOne(x/y/z/c, c) -> no
302 // - matchOne(y/z/c, c) -> no
303 // - matchOne(z/c, c) -> no
304 // - matchOne(c, c) yes, hit
305 var fr = fi
306 var pr = pi + 1
307 if (pr === pl) {
308 this.debug('** at the end')
309 // a ** at the end will just swallow the rest.
310 // We have found a match.
311 // however, it will not swallow /.x, unless
312 // options.dot is set.
313 // . and .. are *never* matched by **, for explosively
314 // exponential reasons.
315 for (; fi < fl; fi++) {
316 if (file[fi] === '.' || file[fi] === '..' ||
317 (!options.dot && file[fi].charAt(0) === '.')) return false
318 }
319 return true
320 }
321
322 // ok, let's see if we can swallow whatever we can.
323 while (fr < fl) {
324 var swallowee = file[fr]
325
326 this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
327
328 // XXX remove this slice. Just pass the start index.
329 if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
330 this.debug('globstar found match!', fr, fl, swallowee)
331 // found a match.
332 return true
333 } else {
334 // can't swallow "." or ".." ever.
335 // can only swallow ".foo" when explicitly asked.
336 if (swallowee === '.' || swallowee === '..' ||
337 (!options.dot && swallowee.charAt(0) === '.')) {
338 this.debug('dot detected!', file, fr, pattern, pr)
339 break
340 }
341
342 // ** swallows a segment, and continue.
343 this.debug('globstar swallow a segment, and continue')
344 fr++
345 }
346 }
347
348 // no match was found.
349 // However, in partial mode, we can't say this is necessarily over.
350 // If there's more *pattern* left, then
351 /* istanbul ignore if */
352 if (partial) {
353 // ran out of file
354 this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
355 if (fr === fl) return true
356 }
357 return false
358 }
359
360 // something other than **
361 // non-magic patterns just have to match exactly
362 // patterns with magic have been turned into regexps.
363 var hit
364 if (typeof p === 'string') {
365 hit = f === p
366 this.debug('string match', p, f, hit)
367 } else {
368 hit = f.match(p)
369 this.debug('pattern match', p, f, hit)
370 }
371
372 if (!hit) return false
373 }
374
375 // Note: ending in / means that we'll get a final ""
376 // at the end of the pattern. This can only match a
377 // corresponding "" at the end of the file.
378 // If the file ends in /, then it can only match a
379 // a pattern that ends in /, unless the pattern just
380 // doesn't have any more for it. But, a/b/ should *not*
381 // match "a/b/*", even though "" matches against the
382 // [^/]*? pattern, except in partial mode, where it might
383 // simply not be reached yet.
384 // However, a/b/ should still satisfy a/*
385
386 // now either we fell off the end of the pattern, or we're done.
387 if (fi === fl && pi === pl) {
388 // ran out of pattern and filename at the same time.
389 // an exact hit!
390 return true
391 } else if (fi === fl) {
392 // ran out of file, but still had pattern left.
393 // this is ok if we're doing the match as part of
394 // a glob fs traversal.
395 return partial
396 } else /* istanbul ignore else */ if (pi === pl) {
397 // ran out of pattern, still have file left.
398 // this is only acceptable if we're on the very last
399 // empty segment of a file with a trailing slash.
400 // a/* should match a/b/
401 return (fi === fl - 1) && (file[fi] === '')
402 }
403
404 // should be unreachable.
405 /* istanbul ignore next */
406 throw new Error('wtf?')
407 }
408
409 braceExpand () {
410 return braceExpand(this.pattern, this.options)
411 }
412
413 parse (pattern, isSub) {
414 assertValidPattern(pattern)
415
416 const options = this.options
417
418 // shortcuts
419 if (pattern === '**') {
420 if (!options.noglobstar)
421 return GLOBSTAR
422 else
423 pattern = '*'
424 }
425 if (pattern === '') return ''
426
427 let re = ''
428 let hasMagic = !!options.nocase
429 let escaping = false
430 // ? => one single character
431 const patternListStack = []
432 const negativeLists = []
433 let stateChar
434 let inClass = false
435 let reClassStart = -1
436 let classStart = -1
437 let cs
438 let pl
439 let sp
440 // . and .. never match anything that doesn't start with .,
441 // even when options.dot is set.
442 const patternStart = pattern.charAt(0) === '.' ? '' // anything
443 // not (start or / followed by . or .. followed by / or end)
444 : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
445 : '(?!\\.)'
446
447 const clearStateChar = () => {
448 if (stateChar) {
449 // we had some state-tracking character
450 // that wasn't consumed by this pass.
451 switch (stateChar) {
452 case '*':
453 re += star
454 hasMagic = true
455 break
456 case '?':
457 re += qmark
458 hasMagic = true
459 break
460 default:
461 re += '\\' + stateChar
462 break
463 }
464 this.debug('clearStateChar %j %j', stateChar, re)
465 stateChar = false
466 }
467 }
468
469 for (let i = 0, c; (i < pattern.length) && (c = pattern.charAt(i)); i++) {
470 this.debug('%s\t%s %s %j', pattern, i, re, c)
471
472 // skip over any that are escaped.
473 if (escaping) {
474 /* istanbul ignore next - completely not allowed, even escaped. */
475 if (c === '/') {
476 return false
477 }
478
479 if (reSpecials[c]) {
480 re += '\\'
481 }
482 re += c
483 escaping = false
484 continue
485 }
486
487 switch (c) {
488 /* istanbul ignore next */
489 case '/': {
490 // Should already be path-split by now.
491 return false
492 }
493
494 case '\\':
495 clearStateChar()
496 escaping = true
497 continue
498
499 // the various stateChar values
500 // for the "extglob" stuff.
501 case '?':
502 case '*':
503 case '+':
504 case '@':
505 case '!':
506 this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
507
508 // all of those are literals inside a class, except that
509 // the glob [!a] means [^a] in regexp
510 if (inClass) {
511 this.debug(' in class')
512 if (c === '!' && i === classStart + 1) c = '^'
513 re += c
514 continue
515 }
516
517 // if we already have a stateChar, then it means
518 // that there was something like ** or +? in there.
519 // Handle the stateChar, then proceed with this one.
520 this.debug('call clearStateChar %j', stateChar)
521 clearStateChar()
522 stateChar = c
523 // if extglob is disabled, then +(asdf|foo) isn't a thing.
524 // just clear the statechar *now*, rather than even diving into
525 // the patternList stuff.
526 if (options.noext) clearStateChar()
527 continue
528
529 case '(':
530 if (inClass) {
531 re += '('
532 continue
533 }
534
535 if (!stateChar) {
536 re += '\\('
537 continue
538 }
539
540 patternListStack.push({
541 type: stateChar,
542 start: i - 1,
543 reStart: re.length,
544 open: plTypes[stateChar].open,
545 close: plTypes[stateChar].close
546 })
547 // negation is (?:(?!js)[^/]*)
548 re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
549 this.debug('plType %j %j', stateChar, re)
550 stateChar = false
551 continue
552
553 case ')':
554 if (inClass || !patternListStack.length) {
555 re += '\\)'
556 continue
557 }
558
559 clearStateChar()
560 hasMagic = true
561 pl = patternListStack.pop()
562 // negation is (?:(?!js)[^/]*)
563 // The others are (?:<pattern>)<type>
564 re += pl.close
565 if (pl.type === '!') {
566 negativeLists.push(pl)
567 }
568 pl.reEnd = re.length
569 continue
570
571 case '|':
572 if (inClass || !patternListStack.length) {
573 re += '\\|'
574 continue
575 }
576
577 clearStateChar()
578 re += '|'
579 continue
580
581 // these are mostly the same in regexp and glob
582 case '[':
583 // swallow any state-tracking char before the [
584 clearStateChar()
585
586 if (inClass) {
587 re += '\\' + c
588 continue
589 }
590
591 inClass = true
592 classStart = i
593 reClassStart = re.length
594 re += c
595 continue
596
597 case ']':
598 // a right bracket shall lose its special
599 // meaning and represent itself in
600 // a bracket expression if it occurs
601 // first in the list. -- POSIX.2 2.8.3.2
602 if (i === classStart + 1 || !inClass) {
603 re += '\\' + c
604 continue
605 }
606
607 // handle the case where we left a class open.
608 // "[z-a]" is valid, equivalent to "\[z-a\]"
609 // split where the last [ was, make sure we don't have
610 // an invalid re. if so, re-walk the contents of the
611 // would-be class to re-translate any characters that
612 // were passed through as-is
613 // TODO: It would probably be faster to determine this
614 // without a try/catch and a new RegExp, but it's tricky
615 // to do safely. For now, this is safe and works.
616 cs = pattern.substring(classStart + 1, i)
617 try {
618 RegExp('[' + cs + ']')
619 } catch (er) {
620 // not a valid class!
621 sp = this.parse(cs, SUBPARSE)
622 re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
623 hasMagic = hasMagic || sp[1]
624 inClass = false
625 continue
626 }
627
628 // finish up the class.
629 hasMagic = true
630 inClass = false
631 re += c
632 continue
633
634 default:
635 // swallow any state char that wasn't consumed
636 clearStateChar()
637
638 if (reSpecials[c] && !(c === '^' && inClass)) {
639 re += '\\'
640 }
641
642 re += c
643 break
644
645 } // switch
646 } // for
647
648 // handle the case where we left a class open.
649 // "[abc" is valid, equivalent to "\[abc"
650 if (inClass) {
651 // split where the last [ was, and escape it
652 // this is a huge pita. We now have to re-walk
653 // the contents of the would-be class to re-translate
654 // any characters that were passed through as-is
655 cs = pattern.substr(classStart + 1)
656 sp = this.parse(cs, SUBPARSE)
657 re = re.substr(0, reClassStart) + '\\[' + sp[0]
658 hasMagic = hasMagic || sp[1]
659 }
660
661 // handle the case where we had a +( thing at the *end*
662 // of the pattern.
663 // each pattern list stack adds 3 chars, and we need to go through
664 // and escape any | chars that were passed through as-is for the regexp.
665 // Go through and escape them, taking care not to double-escape any
666 // | chars that were already escaped.
667 for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
668 let tail
669 tail = re.slice(pl.reStart + pl.open.length)
670 this.debug('setting tail', re, pl)
671 // maybe some even number of \, then maybe 1 \, followed by a |
672 tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
673 /* istanbul ignore else - should already be done */
674 if (!$2) {
675 // the | isn't already escaped, so escape it.
676 $2 = '\\'
677 }
678
679 // need to escape all those slashes *again*, without escaping the
680 // one that we need for escaping the | character. As it works out,
681 // escaping an even number of slashes can be done by simply repeating
682 // it exactly after itself. That's why this trick works.
683 //
684 // I am sorry that you have to see this.
685 return $1 + $1 + $2 + '|'
686 })
687
688 this.debug('tail=%j\n %s', tail, tail, pl, re)
689 const t = pl.type === '*' ? star
690 : pl.type === '?' ? qmark
691 : '\\' + pl.type
692
693 hasMagic = true
694 re = re.slice(0, pl.reStart) + t + '\\(' + tail
695 }
696
697 // handle trailing things that only matter at the very end.
698 clearStateChar()
699 if (escaping) {
700 // trailing \\
701 re += '\\\\'
702 }
703
704 // only need to apply the nodot start if the re starts with
705 // something that could conceivably capture a dot
706 const addPatternStart = addPatternStartSet[re.charAt(0)]
707
708 // Hack to work around lack of negative lookbehind in JS
709 // A pattern like: *.!(x).!(y|z) needs to ensure that a name
710 // like 'a.xyz.yz' doesn't match. So, the first negative
711 // lookahead, has to look ALL the way ahead, to the end of
712 // the pattern.
713 for (let n = negativeLists.length - 1; n > -1; n--) {
714 const nl = negativeLists[n]
715
716 const nlBefore = re.slice(0, nl.reStart)
717 const nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
718 let nlAfter = re.slice(nl.reEnd)
719 const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter
720
721 // Handle nested stuff like *(*.js|!(*.json)), where open parens
722 // mean that we should *not* include the ) in the bit that is considered
723 // "after" the negated section.
724 const openParensBefore = nlBefore.split('(').length - 1
725 let cleanAfter = nlAfter
726 for (let i = 0; i < openParensBefore; i++) {
727 cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
728 }
729 nlAfter = cleanAfter
730
731 const dollar = nlAfter === '' && isSub !== SUBPARSE ? '$' : ''
732 re = nlBefore + nlFirst + nlAfter + dollar + nlLast
733 }
734
735 // if the re is not "" at this point, then we need to make sure
736 // it doesn't match against an empty path part.
737 // Otherwise a/* will match a/, which it should not.
738 if (re !== '' && hasMagic) {
739 re = '(?=.)' + re
740 }
741
742 if (addPatternStart) {
743 re = patternStart + re
744 }
745
746 // parsing just a piece of a larger pattern.
747 if (isSub === SUBPARSE) {
748 return [re, hasMagic]
749 }
750
751 // skip the regexp for non-magical patterns
752 // unescape anything in it, though, so that it'll be
753 // an exact match against a file etc.
754 if (!hasMagic) {
755 return globUnescape(pattern)
756 }
757
758 const flags = options.nocase ? 'i' : ''
759 try {
760 return Object.assign(new RegExp('^' + re + '$', flags), {
761 _glob: pattern,
762 _src: re,
763 })
764 } catch (er) /* istanbul ignore next - should be impossible */ {
765 // If it was an invalid regular expression, then it can't match
766 // anything. This trick looks for a character after the end of
767 // the string, which is of course impossible, except in multi-line
768 // mode, but it's not a /m regex.
769 return new RegExp('$.')
770 }
771 }
772
773 makeRe () {
774 if (this.regexp || this.regexp === false) return this.regexp
775
776 // at this point, this.set is a 2d array of partial
777 // pattern strings, or "**".
778 //
779 // It's better to use .match(). This function shouldn't
780 // be used, really, but it's pretty convenient sometimes,
781 // when you just want to work with a regex.
782 const set = this.set
783
784 if (!set.length) {
785 this.regexp = false
786 return this.regexp
787 }
788 const options = this.options
789
790 const twoStar = options.noglobstar ? star
791 : options.dot ? twoStarDot
792 : twoStarNoDot
793 const flags = options.nocase ? 'i' : ''
794
795 // coalesce globstars and regexpify non-globstar patterns
796 // if it's the only item, then we just do one twoStar
797 // if it's the first, and there are more, prepend (\/|twoStar\/)? to next
798 // if it's the last, append (\/twoStar|) to previous
799 // if it's in the middle, append (\/|\/twoStar\/) to previous
800 // then filter out GLOBSTAR symbols
801 let re = set.map(pattern => {
802 pattern = pattern.map(p =>
803 typeof p === 'string' ? regExpEscape(p)
804 : p === GLOBSTAR ? GLOBSTAR
805 : p._src
806 ).reduce((set, p) => {
807 if (!(set[set.length - 1] === GLOBSTAR && p === GLOBSTAR)) {
808 set.push(p)
809 }
810 return set
811 }, [])
812 pattern.forEach((p, i) => {
813 if (p !== GLOBSTAR || pattern[i-1] === GLOBSTAR) {
814 return
815 }
816 if (i === 0) {
817 if (pattern.length > 1) {
818 pattern[i+1] = '(?:\\\/|' + twoStar + '\\\/)?' + pattern[i+1]
819 } else {
820 pattern[i] = twoStar
821 }
822 } else if (i === pattern.length - 1) {
823 pattern[i-1] += '(?:\\\/|' + twoStar + ')?'
824 } else {
825 pattern[i-1] += '(?:\\\/|\\\/' + twoStar + '\\\/)' + pattern[i+1]
826 pattern[i+1] = GLOBSTAR
827 }
828 })
829 return pattern.filter(p => p !== GLOBSTAR).join('/')
830 }).join('|')
831
832 // must match entire pattern
833 // ending in a * or ** will make it less strict.
834 re = '^(?:' + re + ')$'
835
836 // can match anything, as long as it's not this.
837 if (this.negate) re = '^(?!' + re + ').*$'
838
839 try {
840 this.regexp = new RegExp(re, flags)
841 } catch (ex) /* istanbul ignore next - should be impossible */ {
842 this.regexp = false
843 }
844 return this.regexp
845 }
846
847 match (f, partial = this.partial) {
848 this.debug('match', f, this.pattern)
849 // short-circuit in the case of busted things.
850 // comments, etc.
851 if (this.comment) return false
852 if (this.empty) return f === ''
853
854 if (f === '/' && partial) return true
855
856 const options = this.options
857
858 // windows: need to use /, not \
859 if (path.sep !== '/') {
860 f = f.split(path.sep).join('/')
861 }
862
863 // treat the test path as a set of pathparts.
864 f = f.split(slashSplit)
865 this.debug(this.pattern, 'split', f)
866
867 // just ONE of the pattern sets in this.set needs to match
868 // in order for it to be valid. If negating, then just one
869 // match means that we have failed.
870 // Either way, return on the first hit.
871
872 const set = this.set
873 this.debug(this.pattern, 'set', set)
874
875 // Find the basename of the path by looking for the last non-empty segment
876 let filename
877 for (let i = f.length - 1; i >= 0; i--) {
878 filename = f[i]
879 if (filename) break
880 }
881
882 for (let i = 0; i < set.length; i++) {
883 const pattern = set[i]
884 let file = f
885 if (options.matchBase && pattern.length === 1) {
886 file = [filename]
887 }
888 const hit = this.matchOne(file, pattern, partial)
889 if (hit) {
890 if (options.flipNegate) return true
891 return !this.negate
892 }
893 }
894
895 // didn't get any hits. this is success if it's a negative
896 // pattern, failure otherwise.
897 if (options.flipNegate) return false
898 return this.negate
899 }
900
901 static defaults (def) {
902 return minimatch.defaults(def).Minimatch
903 }
904 }
905
906 minimatch.Minimatch = Minimatch
1 {
2 "_from": "minimatch@^5.0.1",
3 "_id": "minimatch@5.1.0",
4 "_inBundle": false,
5 "_integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
6 "_location": "/vue-qr/minimatch",
7 "_phantomChildren": {},
8 "_requested": {
9 "type": "range",
10 "registry": true,
11 "raw": "minimatch@^5.0.1",
12 "name": "minimatch",
13 "escapedName": "minimatch",
14 "rawSpec": "^5.0.1",
15 "saveSpec": null,
16 "fetchSpec": "^5.0.1"
17 },
18 "_requiredBy": [
19 "/vue-qr/glob"
20 ],
21 "_resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.0.tgz",
22 "_shasum": "1717b464f4971b144f6aabe8f2d0b8e4511e09c7",
23 "_spec": "minimatch@^5.0.1",
24 "_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr/node_modules/glob",
25 "author": {
26 "name": "Isaac Z. Schlueter",
27 "email": "i@izs.me",
28 "url": "http://blog.izs.me"
29 },
30 "bugs": {
31 "url": "https://github.com/isaacs/minimatch/issues"
32 },
33 "bundleDependencies": false,
34 "dependencies": {
35 "brace-expansion": "^2.0.1"
36 },
37 "deprecated": false,
38 "description": "a glob matcher in javascript",
39 "devDependencies": {
40 "tap": "^15.1.6"
41 },
42 "engines": {
43 "node": ">=10"
44 },
45 "files": [
46 "minimatch.js",
47 "lib"
48 ],
49 "homepage": "https://github.com/isaacs/minimatch#readme",
50 "license": "ISC",
51 "main": "minimatch.js",
52 "name": "minimatch",
53 "repository": {
54 "type": "git",
55 "url": "git://github.com/isaacs/minimatch.git"
56 },
57 "scripts": {
58 "postversion": "npm publish",
59 "prepublishOnly": "git push origin --follow-tags",
60 "preversion": "npm test",
61 "snap": "tap",
62 "test": "tap"
63 },
64 "version": "5.1.0"
65 }
1 {
2 "_from": "vue-qr",
3 "_id": "vue-qr@4.0.9",
4 "_inBundle": false,
5 "_integrity": "sha512-pAISV94T0MNEYA3NGjykUpsXRE2QfaNxlu9ZhEL6CERgqNc21hJYuP3hRVzAWfBQlgO18DPmZTbrFerJC3+Ikw==",
6 "_location": "/vue-qr",
7 "_phantomChildren": {
8 "balanced-match": "1.0.0",
9 "fs.realpath": "1.0.0",
10 "inflight": "1.0.6",
11 "inherits": "2.0.4",
12 "once": "1.4.0"
13 },
14 "_requested": {
15 "type": "tag",
16 "registry": true,
17 "raw": "vue-qr",
18 "name": "vue-qr",
19 "escapedName": "vue-qr",
20 "rawSpec": "",
21 "saveSpec": null,
22 "fetchSpec": "latest"
23 },
24 "_requiredBy": [
25 "#USER",
26 "/"
27 ],
28 "_resolved": "https://registry.npmmirror.com/vue-qr/-/vue-qr-4.0.9.tgz",
29 "_shasum": "6cb965dd0c5a0dff947e6ef582ef149b0780b986",
30 "_spec": "vue-qr",
31 "_where": "/Users/zhanghao/brcode/br-client",
32 "author": {
33 "name": "Binaryify"
34 },
35 "browserslist": [
36 "> 1%",
37 "last 2 versions",
38 "not ie <= 8"
39 ],
40 "bugs": {
41 "url": "https://github.com/Binaryify/vue-qr/issues"
42 },
43 "bundleDependencies": false,
44 "dependencies": {
45 "glob": "^8.0.1",
46 "js-binary-schema-parser": "^2.0.2",
47 "simple-get": "^4.0.1",
48 "string-split-by": "^1.0.0"
49 },
50 "deprecated": false,
51 "description": "The Vue 2.x component of Awesome-qr.js",
52 "devDependencies": {
53 "@babel/cli": "^7.11.6",
54 "@babel/core": "^7.11.6",
55 "@babel/plugin-proposal-class-properties": "^7.16.7",
56 "@babel/plugin-transform-runtime": "^7.11.5",
57 "@babel/preset-env": "^7.11.5",
58 "@babel/preset-stage-0": "^7.8.3",
59 "babel-loader": "^8.1.0",
60 "babel-plugin-lodash": "^3.3.4",
61 "cross-env": "^7.0.2",
62 "css-loader": "^4.3.0",
63 "file-loader": "^6.1.0",
64 "uuid": "^8.3.1",
65 "vue": "^2.6.12",
66 "vue-loader": "^15.9.3",
67 "vue-template-compiler": "^2.6.12",
68 "webpack": "^4.44.2",
69 "webpack-cli": "^3.3.12",
70 "webpack-dev-server": "^3.11.0"
71 },
72 "homepage": "https://github.com/Binaryify/vue-qr#readme",
73 "keywords": [
74 "vue-qr",
75 "vue qr",
76 "vue qrcode",
77 "qr",
78 "vue"
79 ],
80 "license": "MIT",
81 "main": "dist/vue-qr.js",
82 "name": "vue-qr",
83 "repository": {
84 "type": "git",
85 "url": "git+https://github.com/Binaryify/vue-qr.git"
86 },
87 "scripts": {
88 "build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
89 "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot --host 0.0.0.0"
90 },
91 "version": "4.0.9"
92 }
1 // 'path' module extracted from Node.js v8.11.1 (only the posix part)
2 // transplited with Babel
3
4 // Copyright Joyent, Inc. and other Node contributors.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to permit
11 // persons to whom the Software is furnished to do so, subject to the
12 // following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included
15 // in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 // USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 'use strict';
26
27 function assertPath(path) {
28 if (typeof path !== 'string') {
29 throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
30 }
31 }
32
33 // Resolves . and .. elements in a path with directory names
34 function normalizeStringPosix(path, allowAboveRoot) {
35 var res = '';
36 var lastSegmentLength = 0;
37 var lastSlash = -1;
38 var dots = 0;
39 var code;
40 for (var i = 0; i <= path.length; ++i) {
41 if (i < path.length)
42 code = path.charCodeAt(i);
43 else if (code === 47 /*/*/)
44 break;
45 else
46 code = 47 /*/*/;
47 if (code === 47 /*/*/) {
48 if (lastSlash === i - 1 || dots === 1) {
49 // NOOP
50 } else if (lastSlash !== i - 1 && dots === 2) {
51 if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {
52 if (res.length > 2) {
53 var lastSlashIndex = res.lastIndexOf('/');
54 if (lastSlashIndex !== res.length - 1) {
55 if (lastSlashIndex === -1) {
56 res = '';
57 lastSegmentLength = 0;
58 } else {
59 res = res.slice(0, lastSlashIndex);
60 lastSegmentLength = res.length - 1 - res.lastIndexOf('/');
61 }
62 lastSlash = i;
63 dots = 0;
64 continue;
65 }
66 } else if (res.length === 2 || res.length === 1) {
67 res = '';
68 lastSegmentLength = 0;
69 lastSlash = i;
70 dots = 0;
71 continue;
72 }
73 }
74 if (allowAboveRoot) {
75 if (res.length > 0)
76 res += '/..';
77 else
78 res = '..';
79 lastSegmentLength = 2;
80 }
81 } else {
82 if (res.length > 0)
83 res += '/' + path.slice(lastSlash + 1, i);
84 else
85 res = path.slice(lastSlash + 1, i);
86 lastSegmentLength = i - lastSlash - 1;
87 }
88 lastSlash = i;
89 dots = 0;
90 } else if (code === 46 /*.*/ && dots !== -1) {
91 ++dots;
92 } else {
93 dots = -1;
94 }
95 }
96 return res;
97 }
98
99 function _format(sep, pathObject) {
100 var dir = pathObject.dir || pathObject.root;
101 var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');
102 if (!dir) {
103 return base;
104 }
105 if (dir === pathObject.root) {
106 return dir + base;
107 }
108 return dir + sep + base;
109 }
110
111 var posix = {
112 // path.resolve([from ...], to)
113 resolve: function resolve() {
114 var resolvedPath = '';
115 var resolvedAbsolute = false;
116 var cwd;
117
118 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
119 var path;
120 if (i >= 0)
121 path = arguments[i];
122 else {
123 if (cwd === undefined)
124 cwd = process.cwd();
125 path = cwd;
126 }
127
128 assertPath(path);
129
130 // Skip empty entries
131 if (path.length === 0) {
132 continue;
133 }
134
135 resolvedPath = path + '/' + resolvedPath;
136 resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;
137 }
138
139 // At this point the path should be resolved to a full absolute path, but
140 // handle relative paths to be safe (might happen when process.cwd() fails)
141
142 // Normalize the path
143 resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
144
145 if (resolvedAbsolute) {
146 if (resolvedPath.length > 0)
147 return '/' + resolvedPath;
148 else
149 return '/';
150 } else if (resolvedPath.length > 0) {
151 return resolvedPath;
152 } else {
153 return '.';
154 }
155 },
156
157 normalize: function normalize(path) {
158 assertPath(path);
159
160 if (path.length === 0) return '.';
161
162 var isAbsolute = path.charCodeAt(0) === 47 /*/*/;
163 var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;
164
165 // Normalize the path
166 path = normalizeStringPosix(path, !isAbsolute);
167
168 if (path.length === 0 && !isAbsolute) path = '.';
169 if (path.length > 0 && trailingSeparator) path += '/';
170
171 if (isAbsolute) return '/' + path;
172 return path;
173 },
174
175 isAbsolute: function isAbsolute(path) {
176 assertPath(path);
177 return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;
178 },
179
180 join: function join() {
181 if (arguments.length === 0)
182 return '.';
183 var joined;
184 for (var i = 0; i < arguments.length; ++i) {
185 var arg = arguments[i];
186 assertPath(arg);
187 if (arg.length > 0) {
188 if (joined === undefined)
189 joined = arg;
190 else
191 joined += '/' + arg;
192 }
193 }
194 if (joined === undefined)
195 return '.';
196 return posix.normalize(joined);
197 },
198
199 relative: function relative(from, to) {
200 assertPath(from);
201 assertPath(to);
202
203 if (from === to) return '';
204
205 from = posix.resolve(from);
206 to = posix.resolve(to);
207
208 if (from === to) return '';
209
210 // Trim any leading backslashes
211 var fromStart = 1;
212 for (; fromStart < from.length; ++fromStart) {
213 if (from.charCodeAt(fromStart) !== 47 /*/*/)
214 break;
215 }
216 var fromEnd = from.length;
217 var fromLen = fromEnd - fromStart;
218
219 // Trim any leading backslashes
220 var toStart = 1;
221 for (; toStart < to.length; ++toStart) {
222 if (to.charCodeAt(toStart) !== 47 /*/*/)
223 break;
224 }
225 var toEnd = to.length;
226 var toLen = toEnd - toStart;
227
228 // Compare paths to find the longest common path from root
229 var length = fromLen < toLen ? fromLen : toLen;
230 var lastCommonSep = -1;
231 var i = 0;
232 for (; i <= length; ++i) {
233 if (i === length) {
234 if (toLen > length) {
235 if (to.charCodeAt(toStart + i) === 47 /*/*/) {
236 // We get here if `from` is the exact base path for `to`.
237 // For example: from='/foo/bar'; to='/foo/bar/baz'
238 return to.slice(toStart + i + 1);
239 } else if (i === 0) {
240 // We get here if `from` is the root
241 // For example: from='/'; to='/foo'
242 return to.slice(toStart + i);
243 }
244 } else if (fromLen > length) {
245 if (from.charCodeAt(fromStart + i) === 47 /*/*/) {
246 // We get here if `to` is the exact base path for `from`.
247 // For example: from='/foo/bar/baz'; to='/foo/bar'
248 lastCommonSep = i;
249 } else if (i === 0) {
250 // We get here if `to` is the root.
251 // For example: from='/foo'; to='/'
252 lastCommonSep = 0;
253 }
254 }
255 break;
256 }
257 var fromCode = from.charCodeAt(fromStart + i);
258 var toCode = to.charCodeAt(toStart + i);
259 if (fromCode !== toCode)
260 break;
261 else if (fromCode === 47 /*/*/)
262 lastCommonSep = i;
263 }
264
265 var out = '';
266 // Generate the relative path based on the path difference between `to`
267 // and `from`
268 for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
269 if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {
270 if (out.length === 0)
271 out += '..';
272 else
273 out += '/..';
274 }
275 }
276
277 // Lastly, append the rest of the destination (`to`) path that comes after
278 // the common path parts
279 if (out.length > 0)
280 return out + to.slice(toStart + lastCommonSep);
281 else {
282 toStart += lastCommonSep;
283 if (to.charCodeAt(toStart) === 47 /*/*/)
284 ++toStart;
285 return to.slice(toStart);
286 }
287 },
288
289 _makeLong: function _makeLong(path) {
290 return path;
291 },
292
293 dirname: function dirname(path) {
294 assertPath(path);
295 if (path.length === 0) return '.';
296 var code = path.charCodeAt(0);
297 var hasRoot = code === 47 /*/*/;
298 var end = -1;
299 var matchedSlash = true;
300 for (var i = path.length - 1; i >= 1; --i) {
301 code = path.charCodeAt(i);
302 if (code === 47 /*/*/) {
303 if (!matchedSlash) {
304 end = i;
305 break;
306 }
307 } else {
308 // We saw the first non-path separator
309 matchedSlash = false;
310 }
311 }
312
313 if (end === -1) return hasRoot ? '/' : '.';
314 if (hasRoot && end === 1) return '//';
315 return path.slice(0, end);
316 },
317
318 basename: function basename(path, ext) {
319 if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string');
320 assertPath(path);
321
322 var start = 0;
323 var end = -1;
324 var matchedSlash = true;
325 var i;
326
327 if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
328 if (ext.length === path.length && ext === path) return '';
329 var extIdx = ext.length - 1;
330 var firstNonSlashEnd = -1;
331 for (i = path.length - 1; i >= 0; --i) {
332 var code = path.charCodeAt(i);
333 if (code === 47 /*/*/) {
334 // If we reached a path separator that was not part of a set of path
335 // separators at the end of the string, stop now
336 if (!matchedSlash) {
337 start = i + 1;
338 break;
339 }
340 } else {
341 if (firstNonSlashEnd === -1) {
342 // We saw the first non-path separator, remember this index in case
343 // we need it if the extension ends up not matching
344 matchedSlash = false;
345 firstNonSlashEnd = i + 1;
346 }
347 if (extIdx >= 0) {
348 // Try to match the explicit extension
349 if (code === ext.charCodeAt(extIdx)) {
350 if (--extIdx === -1) {
351 // We matched the extension, so mark this as the end of our path
352 // component
353 end = i;
354 }
355 } else {
356 // Extension does not match, so our result is the entire path
357 // component
358 extIdx = -1;
359 end = firstNonSlashEnd;
360 }
361 }
362 }
363 }
364
365 if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;
366 return path.slice(start, end);
367 } else {
368 for (i = path.length - 1; i >= 0; --i) {
369 if (path.charCodeAt(i) === 47 /*/*/) {
370 // If we reached a path separator that was not part of a set of path
371 // separators at the end of the string, stop now
372 if (!matchedSlash) {
373 start = i + 1;
374 break;
375 }
376 } else if (end === -1) {
377 // We saw the first non-path separator, mark this as the end of our
378 // path component
379 matchedSlash = false;
380 end = i + 1;
381 }
382 }
383
384 if (end === -1) return '';
385 return path.slice(start, end);
386 }
387 },
388
389 extname: function extname(path) {
390 assertPath(path);
391 var startDot = -1;
392 var startPart = 0;
393 var end = -1;
394 var matchedSlash = true;
395 // Track the state of characters (if any) we see before our first dot and
396 // after any path separator we find
397 var preDotState = 0;
398 for (var i = path.length - 1; i >= 0; --i) {
399 var code = path.charCodeAt(i);
400 if (code === 47 /*/*/) {
401 // If we reached a path separator that was not part of a set of path
402 // separators at the end of the string, stop now
403 if (!matchedSlash) {
404 startPart = i + 1;
405 break;
406 }
407 continue;
408 }
409 if (end === -1) {
410 // We saw the first non-path separator, mark this as the end of our
411 // extension
412 matchedSlash = false;
413 end = i + 1;
414 }
415 if (code === 46 /*.*/) {
416 // If this is our first dot, mark it as the start of our extension
417 if (startDot === -1)
418 startDot = i;
419 else if (preDotState !== 1)
420 preDotState = 1;
421 } else if (startDot !== -1) {
422 // We saw a non-dot and non-path separator before our dot, so we should
423 // have a good chance at having a non-empty extension
424 preDotState = -1;
425 }
426 }
427
428 if (startDot === -1 || end === -1 ||
429 // We saw a non-dot character immediately before the dot
430 preDotState === 0 ||
431 // The (right-most) trimmed path component is exactly '..'
432 preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
433 return '';
434 }
435 return path.slice(startDot, end);
436 },
437
438 format: function format(pathObject) {
439 if (pathObject === null || typeof pathObject !== 'object') {
440 throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
441 }
442 return _format('/', pathObject);
443 },
444
445 parse: function parse(path) {
446 assertPath(path);
447
448 var ret = { root: '', dir: '', base: '', ext: '', name: '' };
449 if (path.length === 0) return ret;
450 var code = path.charCodeAt(0);
451 var isAbsolute = code === 47 /*/*/;
452 var start;
453 if (isAbsolute) {
454 ret.root = '/';
455 start = 1;
456 } else {
457 start = 0;
458 }
459 var startDot = -1;
460 var startPart = 0;
461 var end = -1;
462 var matchedSlash = true;
463 var i = path.length - 1;
464
465 // Track the state of characters (if any) we see before our first dot and
466 // after any path separator we find
467 var preDotState = 0;
468
469 // Get non-dir info
470 for (; i >= start; --i) {
471 code = path.charCodeAt(i);
472 if (code === 47 /*/*/) {
473 // If we reached a path separator that was not part of a set of path
474 // separators at the end of the string, stop now
475 if (!matchedSlash) {
476 startPart = i + 1;
477 break;
478 }
479 continue;
480 }
481 if (end === -1) {
482 // We saw the first non-path separator, mark this as the end of our
483 // extension
484 matchedSlash = false;
485 end = i + 1;
486 }
487 if (code === 46 /*.*/) {
488 // If this is our first dot, mark it as the start of our extension
489 if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;
490 } else if (startDot !== -1) {
491 // We saw a non-dot and non-path separator before our dot, so we should
492 // have a good chance at having a non-empty extension
493 preDotState = -1;
494 }
495 }
496
497 if (startDot === -1 || end === -1 ||
498 // We saw a non-dot character immediately before the dot
499 preDotState === 0 ||
500 // The (right-most) trimmed path component is exactly '..'
501 preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
502 if (end !== -1) {
503 if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);
504 }
505 } else {
506 if (startPart === 0 && isAbsolute) {
507 ret.name = path.slice(1, startDot);
508 ret.base = path.slice(1, end);
509 } else {
510 ret.name = path.slice(startPart, startDot);
511 ret.base = path.slice(startPart, end);
512 }
513 ret.ext = path.slice(startDot, end);
514 }
515
516 if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';
517
518 return ret;
519 },
520
521 sep: '/',
522 delimiter: ':',
523 win32: null,
524 posix: null
525 };
526
527 posix.posix = posix;
528
529 export const extname = posix.extname;
530 export const basename = posix.basename;
531 export default posix;
1 "use strict";
2
3 // const {asBuffer, asDownload, asZipDownload, atScale, options} = require('./io')
4 import io from "./io";
5 const { asBuffer, asDownload, asZipDownload, atScale, options } = io;
6 //
7 // Browser equivalents of the skia-canvas convenience initializers and polyfills for
8 // the Canvas object’s newPage & export methods
9 //
10
11 const _toURL_ = Symbol.for("toDataURL");
12
13 const loadImage = src =>
14 new Promise((onload, onerror) =>
15 Object.assign(new Image(), {
16 crossOrigin: "Anonymous",
17 onload,
18 onerror,
19 src
20 })
21 );
22
23 class Canvas {
24 constructor(width, height) {
25 // alert(1)
26 let elt = document.createElement("canvas"),
27 pages = [];
28
29 Object.defineProperty(elt, "async", {
30 value: true,
31 writable: false,
32 enumerable: true
33 });
34
35 for (var [prop, get] of Object.entries({
36 png: () => asBuffer(elt, "image/png"),
37 jpg: () => asBuffer(elt, "image/jpeg"),
38 pages: () => pages.concat(elt).map(c => c.getContext("2d"))
39 }))
40 Object.defineProperty(elt, prop, { get });
41
42 return Object.assign(elt, {
43 width,
44 height,
45
46 newPage(...size) {
47 var { width, height } = elt,
48 page = Object.assign(document.createElement("canvas"), {
49 width,
50 height
51 });
52 page.getContext("2d").drawImage(elt, 0, 0);
53 pages.push(page);
54
55 var [width, height] = size.length ? size : [width, height];
56 return Object.assign(elt, { width, height }).getContext("2d");
57 },
58
59 saveAs(filename, args) {
60 args = typeof args == "number" ? { quality: args } : args;
61 let opts = options(this.pages, { filename, ...args }),
62 { pattern, padding, mime, quality, matte, density, archive } = opts,
63 pages = atScale(opts.pages, density);
64 return padding == undefined
65 ? asDownload(pages[0], mime, quality, matte, filename)
66 : asZipDownload(
67 pages,
68 mime,
69 quality,
70 matte,
71 archive,
72 pattern,
73 padding
74 );
75 },
76
77 toBuffer(extension = "png", args = {}) {
78 args = typeof args == "number" ? { quality: args } : args;
79 let opts = options(this.pages, { extension, ...args }),
80 { mime, quality, matte, pages, density } = opts,
81 canvas = atScale(pages, density, matte)[0];
82 return asBuffer(canvas, mime, quality, matte);
83 },
84
85 [_toURL_]: elt.toDataURL.bind(elt),
86 toDataURL(extension = "png", args = {}) {
87 args = typeof args == "number" ? { quality: args } : args;
88 let opts = options(this.pages, { extension, ...args }),
89 { mime, quality, matte, pages, density } = opts,
90 canvas = atScale(pages, density, matte)[0],
91 url = canvas[canvas === elt ? _toURL_ : "toDataURL"](mime, quality);
92 return Promise.resolve(url);
93 }
94 });
95 }
96 }
97
98 const {
99 CanvasRenderingContext2D,
100 CanvasGradient,
101 CanvasPattern,
102 Image,
103 ImageData,
104 Path2D,
105 DOMMatrix,
106 DOMRect,
107 DOMPoint
108 } = window;
109
110 // module.exports = {
111 // Canvas,
112 // loadImage,
113 // CanvasRenderingContext2D,
114 // CanvasGradient,
115 // CanvasPattern,
116 // Image,
117 // ImageData,
118 // Path2D,
119 // DOMMatrix,
120 // DOMRect,
121 // DOMPoint
122 // };
123
124 const obj = {
125 Canvas,
126 loadImage,
127 CanvasRenderingContext2D,
128 CanvasGradient,
129 CanvasPattern,
130 Image,
131 ImageData,
132 Path2D,
133 DOMMatrix,
134 DOMRect,
135 DOMPoint
136 };
137 export default obj;
1 "use strict";
2
3 //
4 // Parsers for properties that take CSS-style strings as values
5 //
6
7 // -- Font & Variant --------------------------------------------------------------------
8 // https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant
9 // https://www.w3.org/TR/css-fonts-3/#font-size-prop
10 import splitBy from "string-split-by";
11 var m,
12 cache = { font: {}, variant: {} };
13
14 const styleRE = /^(normal|italic|oblique)$/,
15 smallcapsRE = /^(normal|small-caps)$/,
16 stretchRE = /^(normal|(semi-|extra-|ultra-)?(condensed|expanded))$/,
17 namedSizeRE = /(?:xx?-)?small|smaller|medium|larger|(?:xx?-)?large|normal/,
18 numSizeRE = /^([\d\.]+)(px|pt|pc|in|cm|mm|%|em|ex|ch|rem|q)/,
19 namedWeightRE = /^(normal|bold(er)?|lighter)$/,
20 numWeightRE = /^(1000|\d{1,3})$/,
21 parameterizedRE = /([\w\-]+)\((.*?)\)/,
22 unquote = s => s.replace(/^(['"])(.*?)\1$/, "$2"),
23 isSize = s => namedSizeRE.test(s) || numSizeRE.test(s),
24 isWeight = s => namedWeightRE.test(s) || numWeightRE.test(s);
25
26 function parseFont(str) {
27 if (cache.font[str] === undefined) {
28 try {
29 if (typeof str !== "string")
30 throw new Error("Font specification must be a string");
31 if (!str) throw new Error("Font specification cannot be an empty string");
32
33 let font = {
34 style: "normal",
35 variant: "normal",
36 weight: "normal",
37 stretch: "normal"
38 },
39 value = str.replace(/\s*\/\*s/, "/"),
40 tokens = splitBy(value, /\s+/),
41 token;
42
43 while ((token = tokens.shift())) {
44 let match = styleRE.test(token)
45 ? "style"
46 : smallcapsRE.test(token)
47 ? "variant"
48 : stretchRE.test(token)
49 ? "stretch"
50 : isWeight(token)
51 ? "weight"
52 : isSize(token)
53 ? "size"
54 : null;
55
56 switch (match) {
57 case "style":
58 case "variant":
59 case "stretch":
60 case "weight":
61 font[match] = token;
62 break;
63
64 case "size":
65 // size is the pivot point between the style fields and the family name stack,
66 // so start processing what's been collected
67 let [emSize, leading] = splitBy(token, "/"),
68 size = parseSize(emSize),
69 lineHeight = parseSize(
70 (leading || "1.2").replace(/(\d)$/, "$1em"),
71 size
72 ),
73 weight = parseWeight(font.weight),
74 family = splitBy(tokens.join(" "), /\s*,\s*/).map(unquote),
75 features =
76 font.variant == "small-caps" ? { on: ["smcp", "onum"] } : {},
77 { style, stretch, variant } = font;
78
79 // make sure all the numeric fields have legitimate values
80 let invalid = !isFinite(size)
81 ? `font size "${emSize}"`
82 : !isFinite(lineHeight)
83 ? `line height "${leading}"`
84 : !isFinite(weight)
85 ? `font weight "${font.weight}"`
86 : family.length == 0
87 ? `font family "${tokens.join(", ")}"`
88 : false;
89
90 if (!invalid) {
91 // include a re-stringified version of the decoded/absified values
92 return (cache.font[str] = Object.assign(font, {
93 size,
94 lineHeight,
95 weight,
96 family,
97 features,
98 canonical: [
99 style,
100 variant !== style && variant,
101 [variant, style].indexOf(weight) == -1 && weight,
102 [variant, style, weight].indexOf(stretch) == -1 && stretch,
103 `${size}px/${lineHeight}px`,
104 family.map(nm => (nm.match(/\s/) ? `"${nm}"` : nm)).join(", ")
105 ]
106 .filter(Boolean)
107 .join(" ")
108 }));
109 }
110 throw new Error(`Invalid ${invalid}`);
111
112 default:
113 throw new Error(`Unrecognized font attribute "${token}"`);
114 }
115 }
116 throw new Error("Could not find a font size value");
117 } catch (e) {
118 // console.warn(Object.assign(e, {name:"Warning"}))
119 cache.font[str] = null;
120 }
121 }
122 return cache.font[str];
123 }
124
125 function parseSize(str, emSize = 16) {
126 if ((m = numSizeRE.exec(str))) {
127 let [size, unit] = [parseFloat(m[1]), m[2]];
128 return (
129 size *
130 (unit == "px"
131 ? 1
132 : unit == "pt"
133 ? 1 / 0.75
134 : unit == "%"
135 ? emSize / 100
136 : unit == "pc"
137 ? 16
138 : unit == "in"
139 ? 96
140 : unit == "cm"
141 ? 96.0 / 2.54
142 : unit == "mm"
143 ? 96.0 / 25.4
144 : unit == "q"
145 ? 96 / 25.4 / 4
146 : unit.match("r?em")
147 ? emSize
148 : NaN)
149 );
150 }
151
152 if ((m = namedSizeRE.exec(str))) {
153 return emSize * (sizeMap[m[0]] || 1.0);
154 }
155
156 return NaN;
157 }
158
159 function parseWeight(str) {
160 return (m = numWeightRE.exec(str))
161 ? parseInt(m[0]) || NaN
162 : (m = namedWeightRE.exec(str))
163 ? weightMap[m[0]]
164 : NaN;
165 }
166
167 function parseVariant(str) {
168 if (cache.variant[str] === undefined) {
169 let variants = [],
170 features = { on: [], off: [] };
171
172 for (let token of splitBy(str, /\s+/)) {
173 if (token == "normal") {
174 return { variants: [token], features: { on: [], off: [] } };
175 } else if (token in featureMap) {
176 featureMap[token].forEach(feat => {
177 if (feat[0] == "-") features.off.push(feat.slice(1));
178 else features.on.push(feat);
179 });
180 variants.push(token);
181 } else if ((m = parameterizedRE.exec(token))) {
182 let subPattern = alternatesMap[m[1]],
183 subValue = Math.max(0, Math.min(99, parseInt(m[2], 10))),
184 [feat, val] = subPattern
185 .replace(/##/, subValue < 10 ? "0" + subValue : subValue)
186 .replace(/#/, Math.min(9, subValue))
187 .split(" ");
188 if (typeof val == "undefined") features.on.push(feat);
189 else features[feat] = parseInt(val, 10);
190 variants.push(`${m[1]}(${subValue})`);
191 } else {
192 throw new Error(`Invalid font variant "${token}"`);
193 }
194 }
195
196 cache.variant[str] = { variant: variants.join(" "), features: features };
197 }
198
199 return cache.variant[str];
200 }
201
202 // -- Image Filters -----------------------------------------------------------------------
203 // https://developer.mozilla.org/en-US/docs/Web/CSS/filter
204
205 var plainFilterRE = /(blur|hue-rotate|brightness|contrast|grayscale|invert|opacity|saturate|sepia)\((.*?)\)/,
206 shadowFilterRE = /drop-shadow\((.*)\)/,
207 percentValueRE = /^(\+|-)?\d+%$/,
208 angleValueRE = /([\d\.]+)(deg|g?rad|turn)/;
209
210 function parseFilter(str) {
211 let filters = {};
212 let canonical = [];
213
214 for (var spec of splitBy(str, /\s+/) || []) {
215 if ((m = shadowFilterRE.exec(spec))) {
216 let kind = "drop-shadow",
217 args = m[1].trim().split(/\s+/),
218 lengths = args.slice(0, 3),
219 color = args.slice(3).join(" "),
220 dims = lengths.map(s => parseSize(s)).filter(isFinite);
221 if (dims.length == 3 && !!color) {
222 filters[kind] = [...dims, color];
223 canonical.push(
224 `${kind}(${lengths.join(" ")} ${color.replace(/ /g, "")})`
225 );
226 }
227 } else if ((m = plainFilterRE.exec(spec))) {
228 let [kind, arg] = m.slice(1);
229 let val =
230 kind == "blur"
231 ? parseSize(arg)
232 : kind == "hue-rotate"
233 ? parseAngle(arg)
234 : parsePercentage(arg);
235 if (isFinite(val)) {
236 filters[kind] = val;
237 canonical.push(`${kind}(${arg.trim()})`);
238 }
239 }
240 }
241
242 return str.trim() == "none"
243 ? { canonical: "none", filters }
244 : canonical.length
245 ? { canonical: canonical.join(" "), filters }
246 : null;
247 }
248
249 function parsePercentage(str) {
250 return percentValueRE.test(str.trim()) ? parseInt(str, 10) / 100 : NaN;
251 }
252
253 function parseAngle(str) {
254 if ((m = angleValueRE.exec(str.trim()))) {
255 let [amt, unit] = [parseFloat(m[1]), m[2]];
256 return unit == "deg"
257 ? amt
258 : unit == "rad"
259 ? (360 * amt) / (2 * Math.PI)
260 : unit == "grad"
261 ? (360 * amt) / 400
262 : unit == "turn"
263 ? 360 * amt
264 : NaN;
265 }
266 }
267
268 //
269 // Font attribute keywords & corresponding values
270 //
271
272 const weightMap = {
273 lighter: 300,
274 normal: 400,
275 bold: 700,
276 bolder: 800
277 };
278
279 const sizeMap = {
280 "xx-small": 3 / 5,
281 "x-small": 3 / 4,
282 small: 8 / 9,
283 smaller: 8 / 9,
284 large: 6 / 5,
285 larger: 6 / 5,
286 "x-large": 3 / 2,
287 "xx-large": 2 / 1,
288 normal: 1.2 // special case for lineHeight
289 };
290
291 const featureMap = {
292 normal: [],
293
294 // font-variant-ligatures
295 "common-ligatures": ["liga", "clig"],
296 "no-common-ligatures": ["-liga", "-clig"],
297 "discretionary-ligatures": ["dlig"],
298 "no-discretionary-ligatures": ["-dlig"],
299 "historical-ligatures": ["hlig"],
300 "no-historical-ligatures": ["-hlig"],
301 contextual: ["calt"],
302 "no-contextual": ["-calt"],
303
304 // font-variant-position
305 super: ["sups"],
306 sub: ["subs"],
307
308 // font-variant-caps
309 "small-caps": ["smcp"],
310 "all-small-caps": ["c2sc", "smcp"],
311 "petite-caps": ["pcap"],
312 "all-petite-caps": ["c2pc", "pcap"],
313 unicase: ["unic"],
314 "titling-caps": ["titl"],
315
316 // font-variant-numeric
317 "lining-nums": ["lnum"],
318 "oldstyle-nums": ["onum"],
319 "proportional-nums": ["pnum"],
320 "tabular-nums": ["tnum"],
321 "diagonal-fractions": ["frac"],
322 "stacked-fractions": ["afrc"],
323 ordinal: ["ordn"],
324 "slashed-zero": ["zero"],
325
326 // font-variant-east-asian
327 jis78: ["jp78"],
328 jis83: ["jp83"],
329 jis90: ["jp90"],
330 jis04: ["jp04"],
331 simplified: ["smpl"],
332 traditional: ["trad"],
333 "full-width": ["fwid"],
334 "proportional-width": ["pwid"],
335 ruby: ["ruby"],
336
337 // font-variant-alternates (non-parameterized)
338 "historical-forms": ["hist"]
339 };
340
341 const alternatesMap = {
342 stylistic: "salt #",
343 styleset: "ss##",
344 "character-variant": "cv##",
345 swash: "swsh #",
346 ornaments: "ornm #",
347 annotation: "nalt #"
348 };
349
350 // module.exports = {
351 // font: parseFont,
352 // variant: parseVariant,
353 // size: parseSize,
354 // filter: parseFilter
355 // };
356 export default {
357 font: parseFont,
358 variant: parseVariant,
359 size: parseSize,
360 filter: parseFilter
361 };
1 "use strict";
2 import { inspect } from "util";
3 // const { inspect } = require("util");
4 /*
5 * vendored in order to fix its dependence on the window global [cds 2020/08/04]
6 * otherwise unchanged from https://github.com/jarek-foksa/geometry-polyfill/tree/f36bbc8f4bc43539d980687904ce46c8e915543d
7 */
8
9 // @info
10 // DOMPoint polyfill
11 // @src
12 // https://drafts.fxtf.org/geometry/#DOMPoint
13 // https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/geometry/dom_point_read_only.cc
14 class DOMPoint {
15 constructor(x = 0, y = 0, z = 0, w = 1) {
16 this.x = x;
17 this.y = y;
18 this.z = z;
19 this.w = w;
20 }
21
22 static fromPoint(otherPoint) {
23 return new DOMPoint(
24 otherPoint.x,
25 otherPoint.y,
26 otherPoint.z !== undefined ? otherPoint.z : 0,
27 otherPoint.w !== undefined ? otherPoint.w : 1
28 );
29 }
30
31 matrixTransform(matrix) {
32 if (
33 (matrix.is2D || matrix instanceof SVGMatrix) &&
34 this.z === 0 &&
35 this.w === 1
36 ) {
37 return new DOMPoint(
38 this.x * matrix.a + this.y * matrix.c + matrix.e,
39 this.x * matrix.b + this.y * matrix.d + matrix.f,
40 0,
41 1
42 );
43 } else {
44 return new DOMPoint(
45 this.x * matrix.m11 +
46 this.y * matrix.m21 +
47 this.z * matrix.m31 +
48 this.w * matrix.m41,
49 this.x * matrix.m12 +
50 this.y * matrix.m22 +
51 this.z * matrix.m32 +
52 this.w * matrix.m42,
53 this.x * matrix.m13 +
54 this.y * matrix.m23 +
55 this.z * matrix.m33 +
56 this.w * matrix.m43,
57 this.x * matrix.m14 +
58 this.y * matrix.m24 +
59 this.z * matrix.m34 +
60 this.w * matrix.m44
61 );
62 }
63 }
64
65 toJSON() {
66 return {
67 x: this.x,
68 y: this.y,
69 z: this.z,
70 w: this.w
71 };
72 }
73 }
74
75 // @info
76 // DOMRect polyfill
77 // @src
78 // https://drafts.fxtf.org/geometry/#DOMRect
79 // https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/geometry/dom_rect_read_only.cc
80
81 class DOMRect {
82 constructor(x = 0, y = 0, width = 0, height = 0) {
83 this.x = x;
84 this.y = y;
85 this.width = width;
86 this.height = height;
87 }
88
89 static fromRect(otherRect) {
90 return new DOMRect(
91 otherRect.x,
92 otherRect.y,
93 otherRect.width,
94 otherRect.height
95 );
96 }
97
98 get top() {
99 return this.y;
100 }
101
102 get left() {
103 return this.x;
104 }
105
106 get right() {
107 return this.x + this.width;
108 }
109
110 get bottom() {
111 return this.y + this.height;
112 }
113
114 toJSON() {
115 return {
116 x: this.x,
117 y: this.y,
118 width: this.width,
119 height: this.height,
120 top: this.top,
121 left: this.left,
122 right: this.right,
123 bottom: this.bottom
124 };
125 }
126 }
127
128 for (let propertyName of ["top", "right", "bottom", "left"]) {
129 let propertyDescriptor = Object.getOwnPropertyDescriptor(
130 DOMRect.prototype,
131 propertyName
132 );
133 propertyDescriptor.enumerable = true;
134 Object.defineProperty(DOMRect.prototype, propertyName, propertyDescriptor);
135 }
136
137 // @info
138 // DOMMatrix polyfill (SVG 2)
139 // @src
140 // https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc
141 // https://github.com/tocharomera/generativecanvas/blob/master/node-canvas/lib/DOMMatrix.js
142
143 const M11 = 0,
144 M12 = 1,
145 M13 = 2,
146 M14 = 3;
147 const M21 = 4,
148 M22 = 5,
149 M23 = 6,
150 M24 = 7;
151 const M31 = 8,
152 M32 = 9,
153 M33 = 10,
154 M34 = 11;
155 const M41 = 12,
156 M42 = 13,
157 M43 = 14,
158 M44 = 15;
159
160 const A = M11,
161 B = M12;
162 const C = M21,
163 D = M22;
164 const E = M41,
165 F = M42;
166
167 const DEGREE_PER_RAD = 180 / Math.PI;
168 const RAD_PER_DEGREE = Math.PI / 180;
169
170 const $values = Symbol();
171 const $is2D = Symbol();
172
173 let parseMatrix = init => {
174 let parsed = init.replace(/matrix\(/, "");
175 parsed = parsed.split(/,/, 7);
176
177 if (parsed.length !== 6) {
178 throw new Error(`Failed to parse ${init}`);
179 }
180
181 parsed = parsed.map(parseFloat);
182
183 return [
184 parsed[0],
185 parsed[1],
186 0,
187 0,
188 parsed[2],
189 parsed[3],
190 0,
191 0,
192 0,
193 0,
194 1,
195 0,
196 parsed[4],
197 parsed[5],
198 0,
199 1
200 ];
201 };
202
203 let parseMatrix3d = init => {
204 let parsed = init.replace(/matrix3d\(/, "");
205 parsed = parsed.split(/,/, 17);
206
207 if (parsed.length !== 16) {
208 throw new Error(`Failed to parse ${init}`);
209 }
210
211 return parsed.map(parseFloat);
212 };
213
214 let parseTransform = tform => {
215 let type = tform.split(/\(/, 1)[0];
216
217 if (type === "matrix") {
218 return parseMatrix(tform);
219 } else if (type === "matrix3d") {
220 return parseMatrix3d(tform);
221 } else {
222 throw new Error(`${type} parsing not implemented`);
223 }
224 };
225
226 let setNumber2D = (receiver, index, value) => {
227 if (typeof value !== "number") {
228 throw new TypeError("Expected number");
229 }
230
231 receiver[$values][index] = value;
232 };
233
234 let setNumber3D = (receiver, index, value) => {
235 if (typeof value !== "number") {
236 throw new TypeError("Expected number");
237 }
238
239 if (index === M33 || index === M44) {
240 if (value !== 1) {
241 receiver[$is2D] = false;
242 }
243 } else if (value !== 0) {
244 receiver[$is2D] = false;
245 }
246
247 receiver[$values][index] = value;
248 };
249
250 let newInstance = values => {
251 let instance = Object.create(DOMMatrix.prototype);
252 instance.constructor = DOMMatrix;
253 instance[$is2D] = true;
254 instance[$values] = values;
255
256 return instance;
257 };
258
259 let multiply = (first, second) => {
260 let dest = new Float64Array(16);
261
262 for (let i = 0; i < 4; i++) {
263 for (let j = 0; j < 4; j++) {
264 let sum = 0;
265
266 for (let k = 0; k < 4; k++) {
267 sum += first[i * 4 + k] * second[k * 4 + j];
268 }
269
270 dest[i * 4 + j] = sum;
271 }
272 }
273
274 return dest;
275 };
276
277 class DOMMatrix {
278 get m11() {
279 return this[$values][M11];
280 }
281 set m11(value) {
282 setNumber2D(this, M11, value);
283 }
284 get m12() {
285 return this[$values][M12];
286 }
287 set m12(value) {
288 setNumber2D(this, M12, value);
289 }
290 get m13() {
291 return this[$values][M13];
292 }
293 set m13(value) {
294 setNumber3D(this, M13, value);
295 }
296 get m14() {
297 return this[$values][M14];
298 }
299 set m14(value) {
300 setNumber3D(this, M14, value);
301 }
302 get m21() {
303 return this[$values][M21];
304 }
305 set m21(value) {
306 setNumber2D(this, M21, value);
307 }
308 get m22() {
309 return this[$values][M22];
310 }
311 set m22(value) {
312 setNumber2D(this, M22, value);
313 }
314 get m23() {
315 return this[$values][M23];
316 }
317 set m23(value) {
318 setNumber3D(this, M23, value);
319 }
320 get m24() {
321 return this[$values][M24];
322 }
323 set m24(value) {
324 setNumber3D(this, M24, value);
325 }
326 get m31() {
327 return this[$values][M31];
328 }
329 set m31(value) {
330 setNumber3D(this, M31, value);
331 }
332 get m32() {
333 return this[$values][M32];
334 }
335 set m32(value) {
336 setNumber3D(this, M32, value);
337 }
338 get m33() {
339 return this[$values][M33];
340 }
341 set m33(value) {
342 setNumber3D(this, M33, value);
343 }
344 get m34() {
345 return this[$values][M34];
346 }
347 set m34(value) {
348 setNumber3D(this, M34, value);
349 }
350 get m41() {
351 return this[$values][M41];
352 }
353 set m41(value) {
354 setNumber2D(this, M41, value);
355 }
356 get m42() {
357 return this[$values][M42];
358 }
359 set m42(value) {
360 setNumber2D(this, M42, value);
361 }
362 get m43() {
363 return this[$values][M43];
364 }
365 set m43(value) {
366 setNumber3D(this, M43, value);
367 }
368 get m44() {
369 return this[$values][M44];
370 }
371 set m44(value) {
372 setNumber3D(this, M44, value);
373 }
374
375 get a() {
376 return this[$values][A];
377 }
378 set a(value) {
379 setNumber2D(this, A, value);
380 }
381 get b() {
382 return this[$values][B];
383 }
384 set b(value) {
385 setNumber2D(this, B, value);
386 }
387 get c() {
388 return this[$values][C];
389 }
390 set c(value) {
391 setNumber2D(this, C, value);
392 }
393 get d() {
394 return this[$values][D];
395 }
396 set d(value) {
397 setNumber2D(this, D, value);
398 }
399 get e() {
400 return this[$values][E];
401 }
402 set e(value) {
403 setNumber2D(this, E, value);
404 }
405 get f() {
406 return this[$values][F];
407 }
408 set f(value) {
409 setNumber2D(this, F, value);
410 }
411
412 get is2D() {
413 return this[$is2D];
414 }
415
416 get isIdentity() {
417 let values = this[$values];
418
419 return (
420 values[M11] === 1 &&
421 values[M12] === 0 &&
422 values[M13] === 0 &&
423 values[M14] === 0 &&
424 values[M21] === 0 &&
425 values[M22] === 1 &&
426 values[M23] === 0 &&
427 values[M24] === 0 &&
428 values[M31] === 0 &&
429 values[M32] === 0 &&
430 values[M33] === 1 &&
431 values[M34] === 0 &&
432 values[M41] === 0 &&
433 values[M42] === 0 &&
434 values[M43] === 0 &&
435 values[M44] === 1
436 );
437 }
438
439 static fromMatrix(init) {
440 if (init instanceof DOMMatrix) {
441 return new DOMMatrix(init[$values]);
442 } else if (init instanceof SVGMatrix) {
443 return new DOMMatrix([init.a, init.b, init.c, init.d, init.e, init.f]);
444 } else {
445 throw new TypeError("Expected DOMMatrix");
446 }
447 }
448
449 static fromFloat32Array(init) {
450 if (!(init instanceof Float32Array))
451 throw new TypeError("Expected Float32Array");
452 return new DOMMatrix(init);
453 }
454
455 static fromFloat64Array(init) {
456 if (!(init instanceof Float64Array))
457 throw new TypeError("Expected Float64Array");
458 return new DOMMatrix(init);
459 }
460
461 // @type
462 // (Float64Array) => void
463 constructor(init) {
464 this[$is2D] = true;
465
466 this[$values] = new Float64Array([
467 1,
468 0,
469 0,
470 0,
471 0,
472 1,
473 0,
474 0,
475 0,
476 0,
477 1,
478 0,
479 0,
480 0,
481 0,
482 1
483 ]);
484
485 // Parse CSS transformList
486 if (typeof init === "string") {
487 if (init === "") {
488 return;
489 } else {
490 let tforms = init.split(/\)\s+/, 20).map(parseTransform);
491
492 if (tforms.length === 0) {
493 return;
494 }
495
496 init = tforms[0];
497
498 for (let i = 1; i < tforms.length; i++) {
499 init = multiply(tforms[i], init);
500 }
501 }
502 }
503
504 let i = 0;
505
506 if (init && init.length === 6) {
507 setNumber2D(this, A, init[i++]);
508 setNumber2D(this, B, init[i++]);
509 setNumber2D(this, C, init[i++]);
510 setNumber2D(this, D, init[i++]);
511 setNumber2D(this, E, init[i++]);
512 setNumber2D(this, F, init[i++]);
513 } else if (init && init.length === 16) {
514 setNumber2D(this, M11, init[i++]);
515 setNumber2D(this, M12, init[i++]);
516 setNumber3D(this, M13, init[i++]);
517 setNumber3D(this, M14, init[i++]);
518 setNumber2D(this, M21, init[i++]);
519 setNumber2D(this, M22, init[i++]);
520 setNumber3D(this, M23, init[i++]);
521 setNumber3D(this, M24, init[i++]);
522 setNumber3D(this, M31, init[i++]);
523 setNumber3D(this, M32, init[i++]);
524 setNumber3D(this, M33, init[i++]);
525 setNumber3D(this, M34, init[i++]);
526 setNumber2D(this, M41, init[i++]);
527 setNumber2D(this, M42, init[i++]);
528 setNumber3D(this, M43, init[i++]);
529 setNumber3D(this, M44, init[i]);
530 } else if (init !== undefined) {
531 throw new TypeError("Expected string or array.");
532 }
533 }
534
535 dump() {
536 let mat = this[$values];
537 console.log([
538 mat.slice(0, 4),
539 mat.slice(4, 8),
540 mat.slice(8, 12),
541 mat.slice(12, 16)
542 ]);
543 }
544
545 [inspect.custom](depth, options) {
546 if (depth < 0) return "[DOMMatrix]";
547
548 let { a, b, c, d, e, f, is2D, isIdentity } = this;
549 if (this.is2D) {
550 return `DOMMatrix ${inspect(
551 { a, b, c, d, e, f, is2D, isIdentity },
552 { colors: true }
553 )}`;
554 } else {
555 let {
556 m11,
557 m12,
558 m13,
559 m14,
560 m21,
561 m22,
562 m23,
563 m24,
564 m31,
565 m32,
566 m33,
567 m34,
568 m41,
569 m42,
570 m43,
571 m44,
572 is2D,
573 isIdentity
574 } = this;
575 return `DOMMatrix ${inspect(
576 {
577 a,
578 b,
579 c,
580 d,
581 e,
582 f,
583 m11,
584 m12,
585 m13,
586 m14,
587 m21,
588 m22,
589 m23,
590 m24,
591 m31,
592 m32,
593 m33,
594 m34,
595 m41,
596 m42,
597 m43,
598 m44,
599 is2D,
600 isIdentity
601 },
602 { colors: true }
603 )}`;
604 }
605 }
606
607 multiply(other) {
608 return newInstance(this[$values]).multiplySelf(other);
609 }
610
611 multiplySelf(other) {
612 this[$values] = multiply(other[$values], this[$values]);
613
614 if (!other.is2D) {
615 this[$is2D] = false;
616 }
617
618 return this;
619 }
620
621 preMultiplySelf(other) {
622 this[$values] = multiply(this[$values], other[$values]);
623
624 if (!other.is2D) {
625 this[$is2D] = false;
626 }
627
628 return this;
629 }
630
631 translate(tx, ty, tz) {
632 return newInstance(this[$values]).translateSelf(tx, ty, tz);
633 }
634
635 translateSelf(tx = 0, ty = 0, tz = 0) {
636 this[$values] = multiply(
637 [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1],
638 this[$values]
639 );
640
641 if (tz !== 0) {
642 this[$is2D] = false;
643 }
644
645 return this;
646 }
647
648 scale(scaleX, scaleY, scaleZ, originX, originY, originZ) {
649 return newInstance(this[$values]).scaleSelf(
650 scaleX,
651 scaleY,
652 scaleZ,
653 originX,
654 originY,
655 originZ
656 );
657 }
658
659 scale3d(scale, originX, originY, originZ) {
660 return newInstance(this[$values]).scale3dSelf(
661 scale,
662 originX,
663 originY,
664 originZ
665 );
666 }
667
668 scale3dSelf(scale, originX, originY, originZ) {
669 return this.scaleSelf(scale, scale, scale, originX, originY, originZ);
670 }
671
672 scaleSelf(scaleX, scaleY, scaleZ, originX, originY, originZ) {
673 // Not redundant with translate's checks because we need to negate the values later.
674 if (typeof originX !== "number") originX = 0;
675 if (typeof originY !== "number") originY = 0;
676 if (typeof originZ !== "number") originZ = 0;
677
678 this.translateSelf(originX, originY, originZ);
679
680 if (typeof scaleX !== "number") scaleX = 1;
681 if (typeof scaleY !== "number") scaleY = scaleX;
682 if (typeof scaleZ !== "number") scaleZ = 1;
683
684 this[$values] = multiply(
685 [scaleX, 0, 0, 0, 0, scaleY, 0, 0, 0, 0, scaleZ, 0, 0, 0, 0, 1],
686 this[$values]
687 );
688
689 this.translateSelf(-originX, -originY, -originZ);
690
691 if (scaleZ !== 1 || originZ !== 0) {
692 this[$is2D] = false;
693 }
694
695 return this;
696 }
697
698 rotateFromVector(x, y) {
699 return newInstance(this[$values]).rotateFromVectorSelf(x, y);
700 }
701
702 rotateFromVectorSelf(x = 0, y = 0) {
703 let theta = x === 0 && y === 0 ? 0 : Math.atan2(y, x) * DEGREE_PER_RAD;
704 return this.rotateSelf(theta);
705 }
706
707 rotate(rotX, rotY, rotZ) {
708 return newInstance(this[$values]).rotateSelf(rotX, rotY, rotZ);
709 }
710
711 rotateSelf(rotX, rotY, rotZ) {
712 if (rotY === undefined && rotZ === undefined) {
713 rotZ = rotX;
714 rotX = rotY = 0;
715 }
716
717 if (typeof rotY !== "number") rotY = 0;
718 if (typeof rotZ !== "number") rotZ = 0;
719
720 if (rotX !== 0 || rotY !== 0) {
721 this[$is2D] = false;
722 }
723
724 rotX *= RAD_PER_DEGREE;
725 rotY *= RAD_PER_DEGREE;
726 rotZ *= RAD_PER_DEGREE;
727
728 let c = Math.cos(rotZ);
729 let s = Math.sin(rotZ);
730
731 this[$values] = multiply(
732 [c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
733 this[$values]
734 );
735
736 c = Math.cos(rotY);
737 s = Math.sin(rotY);
738
739 this[$values] = multiply(
740 [c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1],
741 this[$values]
742 );
743
744 c = Math.cos(rotX);
745 s = Math.sin(rotX);
746
747 this[$values] = multiply(
748 [1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1],
749 this[$values]
750 );
751
752 return this;
753 }
754
755 rotateAxisAngle(x, y, z, angle) {
756 return newInstance(this[$values]).rotateAxisAngleSelf(x, y, z, angle);
757 }
758
759 rotateAxisAngleSelf(x = 0, y = 0, z = 0, angle = 0) {
760 let length = Math.sqrt(x * x + y * y + z * z);
761
762 if (length === 0) {
763 return this;
764 }
765
766 if (length !== 1) {
767 x /= length;
768 y /= length;
769 z /= length;
770 }
771
772 angle *= RAD_PER_DEGREE;
773
774 let c = Math.cos(angle);
775 let s = Math.sin(angle);
776 let t = 1 - c;
777 let tx = t * x;
778 let ty = t * y;
779
780 this[$values] = multiply(
781 [
782 tx * x + c,
783 tx * y + s * z,
784 tx * z - s * y,
785 0,
786 tx * y - s * z,
787 ty * y + c,
788 ty * z + s * x,
789 0,
790 tx * z + s * y,
791 ty * z - s * x,
792 t * z * z + c,
793 0,
794 0,
795 0,
796 0,
797 1
798 ],
799 this[$values]
800 );
801
802 if (x !== 0 || y !== 0) {
803 this[$is2D] = false;
804 }
805
806 return this;
807 }
808
809 skewX(sx) {
810 return newInstance(this[$values]).skewXSelf(sx);
811 }
812
813 skewXSelf(sx) {
814 if (typeof sx !== "number") {
815 return this;
816 }
817
818 let t = Math.tan(sx * RAD_PER_DEGREE);
819
820 this[$values] = multiply(
821 [1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
822 this[$values]
823 );
824
825 return this;
826 }
827
828 skewY(sy) {
829 return newInstance(this[$values]).skewYSelf(sy);
830 }
831
832 skewYSelf(sy) {
833 if (typeof sy !== "number") {
834 return this;
835 }
836
837 let t = Math.tan(sy * RAD_PER_DEGREE);
838
839 this[$values] = multiply(
840 [1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
841 this[$values]
842 );
843
844 return this;
845 }
846
847 flipX() {
848 return newInstance(
849 multiply([-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], this[$values])
850 );
851 }
852
853 flipY() {
854 return newInstance(
855 multiply([1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], this[$values])
856 );
857 }
858
859 inverse() {
860 return newInstance(this[$values]).invertSelf();
861 }
862
863 invertSelf() {
864 if (this[$is2D]) {
865 let det =
866 this[$values][A] * this[$values][D] -
867 this[$values][B] * this[$values][C];
868
869 // Invertable
870 if (det !== 0) {
871 let result = new DOMMatrix();
872
873 result.a = this[$values][D] / det;
874 result.b = -this[$values][B] / det;
875 result.c = -this[$values][C] / det;
876 result.d = this[$values][A] / det;
877 result.e =
878 (this[$values][C] * this[$values][F] -
879 this[$values][D] * this[$values][E]) /
880 det;
881 result.f =
882 (this[$values][B] * this[$values][E] -
883 this[$values][A] * this[$values][F]) /
884 det;
885
886 return result;
887 }
888
889 // Not invertable
890 else {
891 this[$is2D] = false;
892
893 this[$values] = [
894 NaN,
895 NaN,
896 NaN,
897 NaN,
898 NaN,
899 NaN,
900 NaN,
901 NaN,
902 NaN,
903 NaN,
904 NaN,
905 NaN,
906 NaN,
907 NaN,
908 NaN,
909 NaN
910 ];
911 }
912 } else {
913 throw new Error("3D matrix inversion is not implemented.");
914 }
915 }
916
917 setMatrixValue(transformList) {
918 let temp = new DOMMatrix(transformList);
919
920 this[$values] = temp[$values];
921 this[$is2D] = temp[$is2D];
922
923 return this;
924 }
925
926 transformPoint(point) {
927 let x = point.x;
928 let y = point.y;
929 let z = point.z;
930 let w = point.w;
931
932 let values = this[$values];
933
934 let nx =
935 values[M11] * x + values[M21] * y + values[M31] * z + values[M41] * w;
936 let ny =
937 values[M12] * x + values[M22] * y + values[M32] * z + values[M42] * w;
938 let nz =
939 values[M13] * x + values[M23] * y + values[M33] * z + values[M43] * w;
940 let nw =
941 values[M14] * x + values[M24] * y + values[M34] * z + values[M44] * w;
942
943 return new DOMPoint(nx, ny, nz, nw);
944 }
945
946 toFloat32Array() {
947 return Float32Array.from(this[$values]);
948 }
949
950 toFloat64Array() {
951 return this[$values].slice(0);
952 }
953
954 toJSON() {
955 return {
956 a: this.a,
957 b: this.b,
958 c: this.c,
959 d: this.d,
960 e: this.e,
961 f: this.f,
962 m11: this.m11,
963 m12: this.m12,
964 m13: this.m13,
965 m14: this.m14,
966 m21: this.m21,
967 m22: this.m22,
968 m23: this.m23,
969 m24: this.m24,
970 m31: this.m31,
971 m32: this.m32,
972 m33: this.m33,
973 m34: this.m34,
974 m41: this.m41,
975 m42: this.m42,
976 m43: this.m43,
977 m44: this.m44,
978 is2D: this.is2D,
979 isIdentity: this.isIdentity
980 };
981 }
982
983 toString() {
984 if (this.is2D) {
985 return `matrix(${this.a}, ${this.b}, ${this.c}, ${this.d}, ${this.e}, ${this.f})`;
986 } else {
987 return `matrix3d(${this[$values].join(", ")})`;
988 }
989 }
990 }
991
992 for (let propertyName of [
993 "a",
994 "b",
995 "c",
996 "d",
997 "e",
998 "f",
999 "m11",
1000 "m12",
1001 "m13",
1002 "m14",
1003 "m21",
1004 "m22",
1005 "m23",
1006 "m24",
1007 "m31",
1008 "m32",
1009 "m33",
1010 "m34",
1011 "m41",
1012 "m42",
1013 "m43",
1014 "m44",
1015 "is2D",
1016 "isIdentity"
1017 ]) {
1018 let propertyDescriptor = Object.getOwnPropertyDescriptor(
1019 DOMMatrix.prototype,
1020 propertyName
1021 );
1022 propertyDescriptor.enumerable = true;
1023 Object.defineProperty(DOMMatrix.prototype, propertyName, propertyDescriptor);
1024 }
1025
1026 // module.exports = {DOMPoint, DOMMatrix, DOMRect}
1027
1028 const obj = { DOMPoint, DOMMatrix, DOMRect };
1029 export default obj;
1 /// <reference lib="dom"/>
2 /// <reference types="node" />
3
4 export function loadImage(src: string | Buffer): Promise<Image>
5 export class DOMMatrix extends globalThis.DOMMatrix {}
6 export class DOMPoint extends globalThis.DOMPoint {}
7 export class DOMRect extends globalThis.DOMRect {}
8 export class Image extends globalThis.Image {}
9 export class ImageData extends globalThis.ImageData {}
10 export class CanvasGradient extends globalThis.CanvasGradient {}
11 export class CanvasPattern extends globalThis.CanvasPattern {}
12 export class CanvasTexture {}
13
14 //
15 // Canvas
16 //
17
18 export type ExportFormat = "png" | "jpg" | "jpeg" | "pdf" | "svg";
19
20 export interface RenderOptions {
21 /** Page to export: Defaults to 1 (i.e., first page) */
22 page?: number
23
24 /** Background color to draw beneath transparent parts of the canvas */
25 matte?: string
26
27 /** Number of pixels per grid ‘point’ (defaults to 1) */
28 density?: number
29
30 /** Quality for lossy encodings like JPEG (0.0–1.0) */
31 quality?: number
32
33 /** Convert text to paths for SVG exports */
34 outline?: boolean
35 }
36
37 export interface SaveOptions extends RenderOptions {
38 /** Image format to use */
39 format?: ExportFormat
40 }
41
42 export class Canvas {
43 /** @internal */
44 constructor(width?: number, height?: number)
45 static contexts: WeakMap<Canvas, readonly CanvasRenderingContext2D[]>
46
47 /**
48 * @deprecated Use the saveAsSync, toBufferSync, and toDataURLSync methods
49 * instead of setting the async property to false
50 */
51 async: boolean
52 width: number
53 height: number
54
55 getContext(type?: "2d"): CanvasRenderingContext2D
56 newPage(width?: number, height?: number): CanvasRenderingContext2D
57 readonly pages: CanvasRenderingContext2D[]
58
59 saveAs(filename: string, options?: SaveOptions): Promise<void>
60 toBuffer(format: ExportFormat, options?: RenderOptions): Promise<Buffer>
61 toDataURL(format: ExportFormat, options?: RenderOptions): Promise<string>
62
63 saveAsSync(filename: string, options?: SaveOptions): void
64 toBufferSync(format: ExportFormat, options?: RenderOptions): Buffer
65 toDataURLSync(format: ExportFormat, options?: RenderOptions): string
66
67 get pdf(): Promise<Buffer>
68 get svg(): Promise<Buffer>
69 get jpg(): Promise<Buffer>
70 get png(): Promise<Buffer>
71 }
72
73 //
74 // Context
75 //
76
77 type Offset = [x: number, y: number] | number
78
79 export interface CreateTextureOptions {
80 /** The 2D shape to be drawn in a repeating grid with the specified spacing (if omitted, parallel lines will be used) */
81 path?: Path2D
82
83 /** The lineWidth with which to stroke the path (if omitted, the path will be filled instead) */
84 line?: number
85
86 /** The color to use for stroking/filling the path */
87 color?: string
88
89 /** The orientation of the pattern grid in radians */
90 angle?: number
91
92 /** The amount by which to shift the pattern relative to the canvas origin */
93 offset?: Offset
94 }
95
96 export type CanvasImageSource = Canvas | Image;
97
98 interface CanvasDrawImage {
99 drawImage(image: CanvasImageSource, dx: number, dy: number): void;
100 drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
101 drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;
102 drawCanvas(image: Canvas, dx: number, dy: number): void;
103 drawCanvas(image: Canvas, dx: number, dy: number, dw: number, dh: number): void;
104 drawCanvas(image: Canvas, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;
105 }
106
107 interface CanvasFillStrokeStyles {
108 fillStyle: string | CanvasGradient | CanvasPattern | CanvasTexture;
109 strokeStyle: string | CanvasGradient | CanvasPattern | CanvasTexture;
110 createConicGradient(startAngle: number, x: number, y: number): CanvasGradient;
111 createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;
112 createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;
113 createPattern(image: CanvasImageSource, repetition: string | null): CanvasPattern | null;
114 createTexture(spacing: Offset, options?: CreateTextureOptions): CanvasTexture
115 }
116
117 type QuadOrRect = [x1:number, y1:number, x2:number, y2:number, x3:number, y3:number, x4:number, y4:number] |
118 [left:number, top:number, right:number, bottom:number] | [width:number, height:number]
119
120 export interface CanvasRenderingContext2D extends CanvasCompositing, CanvasDrawImage, CanvasDrawPath, CanvasFillStrokeStyles, CanvasFilters, CanvasImageData, CanvasImageSmoothing, CanvasPath, CanvasPathDrawingStyles, CanvasRect, CanvasShadowStyles, CanvasState, CanvasText, CanvasTextDrawingStyles, CanvasTransform, CanvasUserInterface {
121 readonly canvas: Canvas;
122 fontVariant: string;
123 textTracking: number;
124 textWrap: boolean;
125 lineDashMarker: Path2D | null;
126 lineDashFit: "move" | "turn" | "follow";
127
128 get currentTransform(): DOMMatrix
129 set currentTransform(matrix: DOMMatrix)
130 createProjection(quad: QuadOrRect, basis?: QuadOrRect): DOMMatrix
131
132 conicCurveTo(cpx: number, cpy: number, x: number, y: number, weight: number): void
133 // getContextAttributes(): CanvasRenderingContext2DSettings;
134
135 fillText(text: string, x: number, y:number, maxWidth?: number): void
136 strokeText(text: string, x: number, y:number, maxWidth?: number): void
137 measureText(text: string, maxWidth?: number): TextMetrics
138 outlineText(text: string): Path2D
139 }
140
141 //
142 // Bézier Paths
143 //
144
145 export interface Path2DBounds {
146 readonly top: number
147 readonly left: number
148 readonly bottom: number
149 readonly right: number
150 readonly width: number
151 readonly height: number
152 }
153
154 export type Path2DEdge = [verb: string, ...args: number[]]
155
156 export class Path2D extends globalThis.Path2D {
157 d: string
158 readonly bounds: Path2DBounds
159 readonly edges: readonly Path2DEdge[]
160
161 contains(x: number, y: number): boolean
162 conicCurveTo(
163 cpx: number,
164 cpy: number,
165 x: number,
166 y: number,
167 weight: number
168 ): void
169
170 complement(otherPath: Path2D): Path2D
171 difference(otherPath: Path2D): Path2D
172 intersect(otherPath: Path2D): Path2D
173 union(otherPath: Path2D): Path2D
174 xor(otherPath: Path2D): Path2D
175 interpolate(otherPath: Path2D, weight: number): Path2D
176
177 jitter(segmentLength: number, amount: number, seed?: number): Path2D
178 offset(dx: number, dy: number): Path2D
179 points(step?: number): readonly [x: number, y: number][]
180 round(radius: number): Path2D
181 simplify(rule?: "nonzero" | "evenodd"): Path2D
182 transform(...args: [matrix: DOMMatrix] | [a: number, b: number, c: number, d: number, e: number, f: number]): Path2D;
183 trim(start: number, end: number, inverted?: boolean): Path2D;
184 trim(start: number, inverted?: boolean): Path2D;
185
186 unwind(): Path2D
187 }
188
189 //
190 // Typography
191 //
192
193 export interface TextMetrics extends globalThis.TextMetrics {
194 lines: TextMetricsLine[]
195 }
196
197 export interface TextMetricsLine {
198 readonly x: number
199 readonly y: number
200 readonly width: number
201 readonly height: number
202 readonly baseline: number
203 readonly startIndex: number
204 readonly endIndex: number
205 }
206
207 export interface FontFamily {
208 family: string
209 weights: number[]
210 widths: string[]
211 styles: string[]
212 }
213
214 export interface Font {
215 family: string
216 weight: number
217 style: string
218 width: string
219 file: string
220 }
221
222 export interface FontLibrary {
223 families: readonly string[]
224 family(name: string): FontFamily | undefined
225 has(familyName: string): boolean
226
227 use(familyName: string, fontPaths?: string | readonly string[]): Font[]
228 use(fontPaths: readonly string[]): Font[]
229 use(
230 families: Record<string, readonly string[] | string>
231 ): Record<string, Font[] | Font>
232 }
233
234 export const FontLibrary: FontLibrary
1 "use strict";
2 import fs from "fs";
3 import { EventEmitter } from "events";
4 import { inspect } from "util";
5 import { sync as glob, hasMagic } from "glob";
6 import get from "simple-get";
7 import geometry from "./geometry";
8 import css from "./css";
9 import io from "./io";
10 const REPR = inspect.custom;
11 // const fs = require("fs"),
12 // { EventEmitter } = require("events"),
13 // { inspect } = require("util"),
14 // { sync: glob, hasMagic } = require("glob"),
15 // get = require("simple-get"),
16 // geometry = require("./geometry"),
17 // css = require("./css"),
18 // io = require("./io"),
19 // REPR = inspect.custom;
20
21 //
22 // Neon <-> Node interface
23 //
24
25 const ø = Symbol.for("📦"), // the attr containing the boxed struct
26 core = obj => (obj || {})[ø], // dereference the boxed struct
27 wrap = (type, struct) => {
28 // create new instance for struct
29 let obj = internal(Object.create(type.prototype), ø, struct);
30 return struct && internal(obj, "native", neon[type.name]);
31 },
32 neon = Object.entries(require("./v6")).reduce((api, [name, fn]) => {
33 let [_, struct, getset, attr] = name.match(/(.*?)_(?:([sg]et)_)?(.*)/),
34 cls = api[struct] || (api[struct] = {}),
35 slot = getset ? cls[attr] || (cls[attr] = {}) : cls;
36 slot[getset || attr] = fn;
37 return api;
38 }, {});
39
40 class RustClass {
41 constructor(type) {
42 internal(this, "native", neon[type.name]);
43 }
44
45 alloc(...args) {
46 return this.init("new", ...args);
47 }
48
49 init(fn, ...args) {
50 return internal(this, ø, this.native[fn](null, ...args));
51 }
52
53 ref(key, val) {
54 return arguments.length > 1
55 ? (this[Symbol.for(key)] = val)
56 : this[Symbol.for(key)];
57 }
58
59 prop(attr, val) {
60 let getset = arguments.length > 1 ? "set" : "get";
61 return this.native[attr][getset](this[ø], val);
62 }
63
64 ƒ(fn, ...args) {
65 try {
66 return this.native[fn](this[ø], ...args);
67 } catch (error) {
68 Error.captureStackTrace(error, this.ƒ);
69 throw error;
70 }
71 }
72 }
73
74 // shorthands for attaching read-only attributes
75 const readOnly = (obj, attr, value) =>
76 Object.defineProperty(obj, attr, {
77 value,
78 writable: false,
79 enumerable: true
80 });
81
82 const internal = (obj, attr, value) =>
83 Object.defineProperty(obj, attr, {
84 value,
85 writable: false,
86 enumerable: false
87 });
88
89 // convert arguments list to a string of type abbreviations
90 function signature(args) {
91 return args
92 .map(v =>
93 Array.isArray(v)
94 ? "a"
95 : { string: "s", number: "n", object: "o" }[typeof v] || "x"
96 )
97 .join("");
98 }
99
100 const toString = val =>
101 typeof val == "string" ? val : new String(val).toString();
102
103 //
104 // Helpers to reconcile Skia and DOMMatrix’s disagreement about row/col orientation
105 //
106
107 function toSkMatrix(jsMatrix) {
108 if (Array.isArray(jsMatrix) && jsMatrix.length == 6) {
109 var [a, b, c, d, e, f, m14, m24, m44] = jsMatrix.concat(0, 0, 1);
110 } else if (jsMatrix instanceof geometry.DOMMatrix) {
111 var { a, b, c, d, e, f, m14, m24, m44 } = jsMatrix;
112 }
113 return [a, c, e, b, d, f, m14, m24, m44];
114 }
115
116 function fromSkMatrix(skMatrix) {
117 let [a, b, c, d, e, f, p0, p1, p2] = skMatrix;
118 return new geometry.DOMMatrix([
119 a,
120 d,
121 0,
122 p0,
123 b,
124 e,
125 0,
126 p1,
127 0,
128 0,
129 1,
130 0,
131 c,
132 f,
133 0,
134 p2
135 ]);
136 }
137
138 //
139 // The Canvas API
140 //
141
142 class Canvas extends RustClass {
143 static parent = new WeakMap();
144 static contexts = new WeakMap();
145
146 constructor(width, height) {
147 super(Canvas).alloc();
148 Canvas.contexts.set(this, []);
149 Object.assign(this, { width, height });
150 }
151
152 getContext(kind) {
153 return kind == "2d" ? Canvas.contexts.get(this)[0] || this.newPage() : null;
154 }
155
156 get width() {
157 return this.prop("width");
158 }
159 set width(w) {
160 this.prop(
161 "width",
162 typeof w == "number" && !Number.isNaN(w) && w >= 0 ? w : 300
163 );
164 if (Canvas.contexts.get(this)[0])
165 this.getContext("2d").ƒ("resetSize", core(this));
166 }
167
168 get height() {
169 return this.prop("height");
170 }
171 set height(h) {
172 this.prop(
173 "height",
174 (h = typeof h == "number" && !Number.isNaN(h) && h >= 0 ? h : 150)
175 );
176 if (Canvas.contexts.get(this)[0])
177 this.getContext("2d").ƒ("resetSize", core(this));
178 }
179
180 newPage(width, height) {
181 let ctx = new CanvasRenderingContext2D(core(this));
182 Canvas.parent.set(ctx, this);
183 Canvas.contexts.get(this).unshift(ctx);
184 if (arguments.length == 2) {
185 Object.assign(this, { width, height });
186 }
187 return ctx;
188 }
189
190 get pages() {
191 return Canvas.contexts
192 .get(this)
193 .slice()
194 .reverse();
195 }
196
197 get png() {
198 return this.toBuffer("png");
199 }
200 get jpg() {
201 return this.toBuffer("jpg");
202 }
203 get pdf() {
204 return this.toBuffer("pdf");
205 }
206 get svg() {
207 return this.toBuffer("svg");
208 }
209
210 get async() {
211 return this.prop("async");
212 }
213 set async(flag) {
214 if (!flag) {
215 process.emitWarning(
216 "Use the saveAsSync, toBufferSync, and toDataURLSync methods instead of setting the Canvas `async` property to false",
217 "DeprecationWarning"
218 );
219 }
220 this.prop("async", flag);
221 }
222
223 saveAs(filename, opts = {}) {
224 if (!this.async) return this.saveAsSync(...arguments); // support while deprecated
225
226 opts = typeof opts == "number" ? { quality: opts } : opts;
227 let {
228 format,
229 quality,
230 pages,
231 padding,
232 pattern,
233 density,
234 outline,
235 matte
236 } = io.options(this.pages, { filename, ...opts }),
237 args = [
238 pages.map(core),
239 pattern,
240 padding,
241 format,
242 quality,
243 density,
244 outline,
245 matte
246 ],
247 worker = new EventEmitter();
248 this.ƒ("save", (result, msg) => worker.emit(result, msg), ...args);
249 return new Promise((res, rej) =>
250 worker.once("ok", res).once("err", msg => rej(new Error(msg)))
251 );
252 }
253
254 saveAsSync(filename, opts = {}) {
255 opts = typeof opts == "number" ? { quality: opts } : opts;
256 let {
257 format,
258 quality,
259 pages,
260 padding,
261 pattern,
262 density,
263 outline,
264 matte
265 } = io.options(this.pages, { filename, ...opts });
266 this.ƒ(
267 "saveSync",
268 pages.map(core),
269 pattern,
270 padding,
271 format,
272 quality,
273 density,
274 outline,
275 matte
276 );
277 }
278
279 toBuffer(extension = "png", opts = {}) {
280 if (!this.async) return this.toBufferSync(...arguments); // support while deprecated
281
282 opts = typeof opts == "number" ? { quality: opts } : opts;
283 let { format, quality, pages, density, outline, matte } = io.options(
284 this.pages,
285 { extension, ...opts }
286 ),
287 args = [pages.map(core), format, quality, density, outline, matte],
288 worker = new EventEmitter();
289 this.ƒ("toBuffer", (result, msg) => worker.emit(result, msg), ...args);
290 return new Promise((res, rej) =>
291 worker.once("ok", res).once("err", msg => rej(new Error(msg)))
292 );
293 }
294
295 toBufferSync(extension = "png", opts = {}) {
296 opts = typeof opts == "number" ? { quality: opts } : opts;
297 let { format, quality, pages, density, outline, matte } = io.options(
298 this.pages,
299 { extension, ...opts }
300 );
301 return this.ƒ(
302 "toBufferSync",
303 pages.map(core),
304 format,
305 quality,
306 density,
307 outline,
308 matte
309 );
310 }
311
312 toDataURL(extension = "png", opts = {}) {
313 if (!this.async) return this.toDataURLSync(...arguments); // support while deprecated
314
315 opts = typeof opts == "number" ? { quality: opts } : opts;
316 let { mime } = io.options(this.pages, { extension, ...opts }),
317 buffer = this.toBuffer(extension, opts);
318 return buffer.then(
319 data => `data:${mime};base64,${data.toString("base64")}`
320 );
321 }
322
323 toDataURLSync(extension = "png", opts = {}) {
324 opts = typeof opts == "number" ? { quality: opts } : opts;
325 let { mime } = io.options(this.pages, { extension, ...opts }),
326 buffer = this.toBufferSync(extension, opts);
327 return `data:${mime};base64,${buffer.toString("base64")}`;
328 }
329
330 [REPR](depth, options) {
331 let { width, height, async, pages } = this;
332 return `Canvas ${inspect({ width, height, async, pages }, options)}`;
333 }
334 }
335
336 class CanvasGradient extends RustClass {
337 constructor(style, ...coords) {
338 super(CanvasGradient);
339 style = (style || "").toLowerCase();
340 if (["linear", "radial", "conic"].includes(style))
341 this.init(style, ...coords);
342 else
343 throw new Error(
344 `Function is not a constructor (use CanvasRenderingContext2D's "createConicGradient", "createLinearGradient", and "createRadialGradient" methods instead)`
345 );
346 }
347
348 addColorStop(offset, color) {
349 if (offset >= 0 && offset <= 1) this.ƒ("addColorStop", offset, color);
350 else throw new Error("Color stop offsets must be between 0.0 and 1.0");
351 }
352
353 [REPR](depth, options) {
354 return `CanvasGradient (${this.ƒ("repr")})`;
355 }
356 }
357
358 class CanvasPattern extends RustClass {
359 constructor(src, repeat) {
360 super(CanvasPattern);
361 if (src instanceof Image) {
362 this.init("from_image", core(src), repeat);
363 } else if (src instanceof Canvas) {
364 let ctx = src.getContext("2d");
365 this.init("from_canvas", core(ctx), repeat);
366 } else {
367 throw new Error("CanvasPatterns require a source Image or a Canvas");
368 }
369 }
370
371 setTransform(matrix) {
372 if (arguments.length > 1) matrix = [...arguments];
373 this.ƒ("setTransform", toSkMatrix(matrix));
374 }
375
376 [REPR](depth, options) {
377 return `CanvasPattern (${this.ƒ("repr")})`;
378 }
379 }
380
381 class CanvasTexture extends RustClass {
382 constructor(spacing, { path, line, color, angle, offset = 0 } = {}) {
383 super(CanvasTexture);
384 let [x, y] =
385 typeof offset == "number" ? [offset, offset] : offset.slice(0, 2);
386 let [h, v] =
387 typeof spacing == "number" ? [spacing, spacing] : spacing.slice(0, 2);
388 path = core(path);
389 line = line != null ? line : path ? 0 : 1;
390 angle = angle != null ? angle : path ? 0 : -Math.PI / 4;
391 this.alloc(path, color, line, angle, h, v, x, y);
392 }
393
394 [REPR](depth, options) {
395 return `CanvasTexture (${this.ƒ("repr")})`;
396 }
397 }
398
399 class CanvasRenderingContext2D extends RustClass {
400 constructor(canvas) {
401 try {
402 super(CanvasRenderingContext2D).alloc(canvas);
403 } catch (e) {
404 throw new TypeError(
405 `Function is not a constructor (use Canvas's "getContext" method instead)`
406 );
407 }
408 }
409
410 get canvas() {
411 return Canvas.parent.get(this);
412 }
413
414 // -- grid state ------------------------------------------------------------
415 save() {
416 this.ƒ("save");
417 }
418 restore() {
419 this.ƒ("restore");
420 }
421
422 get currentTransform() {
423 return fromSkMatrix(this.prop("currentTransform"));
424 }
425 set currentTransform(matrix) {
426 this.prop("currentTransform", toSkMatrix(matrix));
427 }
428
429 resetTransform() {
430 this.ƒ("resetTransform");
431 }
432 getTransform() {
433 return this.currentTransform;
434 }
435 setTransform(matrix) {
436 this.currentTransform = arguments.length > 1 ? [...arguments] : matrix;
437 }
438
439 transform(a, b, c, d, e, f) {
440 this.ƒ("transform", ...arguments);
441 }
442 translate(x, y) {
443 this.ƒ("translate", ...arguments);
444 }
445 scale(x, y) {
446 this.ƒ("scale", ...arguments);
447 }
448 rotate(angle) {
449 this.ƒ("rotate", ...arguments);
450 }
451
452 createProjection(quad, basis) {
453 return fromSkMatrix(
454 this.ƒ("createProjection", [quad].flat(), [basis].flat())
455 );
456 }
457
458 // -- bézier paths ----------------------------------------------------------
459 beginPath() {
460 this.ƒ("beginPath");
461 }
462 rect(x, y, width, height) {
463 this.ƒ("rect", ...arguments);
464 }
465 arc(x, y, radius, startAngle, endAngle, isCCW) {
466 this.ƒ("arc", ...arguments);
467 }
468 ellipse(x, y, xRadius, yRadius, rotation, startAngle, endAngle, isCCW) {
469 this.ƒ("ellipse", ...arguments);
470 }
471 moveTo(x, y) {
472 this.ƒ("moveTo", ...arguments);
473 }
474 lineTo(x, y) {
475 this.ƒ("lineTo", ...arguments);
476 }
477 arcTo(x1, y1, x2, y2, radius) {
478 this.ƒ("arcTo", ...arguments);
479 }
480 bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
481 this.ƒ("bezierCurveTo", ...arguments);
482 }
483 quadraticCurveTo(cpx, cpy, x, y) {
484 this.ƒ("quadraticCurveTo", ...arguments);
485 }
486 conicCurveTo(cpx, cpy, x, y, weight) {
487 this.ƒ("conicCurveTo", ...arguments);
488 }
489 closePath() {
490 this.ƒ("closePath");
491 }
492 isPointInPath(x, y) {
493 return this.ƒ("isPointInPath", ...arguments);
494 }
495 isPointInStroke(x, y) {
496 return this.ƒ("isPointInStroke", ...arguments);
497 }
498
499 // -- using paths -----------------------------------------------------------
500 fill(path, rule) {
501 if (path instanceof Path2D) this.ƒ("fill", core(path), rule);
502 else this.ƒ("fill", path); // 'path' is the optional winding-rule
503 }
504
505 stroke(path, rule) {
506 if (path instanceof Path2D) this.ƒ("stroke", core(path), rule);
507 else this.ƒ("stroke", path); // 'path' is the optional winding-rule
508 }
509
510 clip(path, rule) {
511 if (path instanceof Path2D) this.ƒ("clip", core(path), rule);
512 else this.ƒ("clip", path); // 'path' is the optional winding-rule
513 }
514
515 // -- shaders ---------------------------------------------------------------
516 createPattern(image, repetition) {
517 return new CanvasPattern(...arguments);
518 }
519 createLinearGradient(x0, y0, x1, y1) {
520 return new CanvasGradient("Linear", ...arguments);
521 }
522 createRadialGradient(x0, y0, r0, x1, y1, r1) {
523 return new CanvasGradient("Radial", ...arguments);
524 }
525 createConicGradient(startAngle, x, y) {
526 return new CanvasGradient("Conic", ...arguments);
527 }
528
529 createTexture(spacing, options) {
530 return new CanvasTexture(spacing, options);
531 }
532
533 // -- fill & stroke ---------------------------------------------------------
534 fillRect(x, y, width, height) {
535 this.ƒ("fillRect", ...arguments);
536 }
537 strokeRect(x, y, width, height) {
538 this.ƒ("strokeRect", ...arguments);
539 }
540 clearRect(x, y, width, height) {
541 this.ƒ("clearRect", ...arguments);
542 }
543
544 set fillStyle(style) {
545 let isShader =
546 style instanceof CanvasPattern ||
547 style instanceof CanvasGradient ||
548 style instanceof CanvasTexture,
549 [ref, val] = isShader ? [style, core(style)] : [null, style];
550 this.ref("fill", ref);
551 this.prop("fillStyle", val);
552 }
553
554 get fillStyle() {
555 let style = this.prop("fillStyle");
556 return style === null ? this.ref("fill") : style;
557 }
558
559 set strokeStyle(style) {
560 let isShader =
561 style instanceof CanvasPattern ||
562 style instanceof CanvasGradient ||
563 style instanceof CanvasTexture,
564 [ref, val] = isShader ? [style, core(style)] : [null, style];
565 this.ref("stroke", ref);
566 this.prop("strokeStyle", val);
567 }
568
569 get strokeStyle() {
570 let style = this.prop("strokeStyle");
571 return style === null ? this.ref("stroke") : style;
572 }
573
574 // -- line style ------------------------------------------------------------
575 getLineDash() {
576 return this.ƒ("getLineDash");
577 }
578 setLineDash(segments) {
579 this.ƒ("setLineDash", segments);
580 }
581 get lineCap() {
582 return this.prop("lineCap");
583 }
584 set lineCap(style) {
585 this.prop("lineCap", style);
586 }
587 get lineDashFit() {
588 return this.prop("lineDashFit");
589 }
590 set lineDashFit(style) {
591 this.prop("lineDashFit", style);
592 }
593 get lineDashMarker() {
594 return wrap(Path2D, this.prop("lineDashMarker"));
595 }
596 set lineDashMarker(path) {
597 this.prop("lineDashMarker", path instanceof Path2D ? core(path) : path);
598 }
599 get lineDashOffset() {
600 return this.prop("lineDashOffset");
601 }
602 set lineDashOffset(offset) {
603 this.prop("lineDashOffset", offset);
604 }
605 get lineJoin() {
606 return this.prop("lineJoin");
607 }
608 set lineJoin(style) {
609 this.prop("lineJoin", style);
610 }
611 get lineWidth() {
612 return this.prop("lineWidth");
613 }
614 set lineWidth(width) {
615 this.prop("lineWidth", width);
616 }
617 get miterLimit() {
618 return this.prop("miterLimit");
619 }
620 set miterLimit(limit) {
621 this.prop("miterLimit", limit);
622 }
623
624 // -- imagery ---------------------------------------------------------------
625 get imageSmoothingEnabled() {
626 return this.prop("imageSmoothingEnabled");
627 }
628 set imageSmoothingEnabled(flag) {
629 this.prop("imageSmoothingEnabled", !!flag);
630 }
631 get imageSmoothingQuality() {
632 return this.prop("imageSmoothingQuality");
633 }
634 set imageSmoothingQuality(level) {
635 this.prop("imageSmoothingQuality", level);
636 }
637 putImageData(imageData, ...coords) {
638 this.ƒ("putImageData", imageData, ...coords);
639 }
640 createImageData(width, height) {
641 return new ImageData(width, height);
642 }
643
644 getImageData(x, y, width, height) {
645 let w = Math.floor(width),
646 h = Math.floor(height),
647 buffer = this.ƒ("getImageData", x, y, w, h);
648 return new ImageData(buffer, w, h);
649 }
650
651 drawImage(image, ...coords) {
652 if (image instanceof Canvas) {
653 this.ƒ("drawImage", core(image.getContext("2d")), ...coords);
654 } else if (image instanceof Image) {
655 this.ƒ("drawImage", core(image), ...coords);
656 } else {
657 throw new Error("Expected an Image or a Canvas argument");
658 }
659 }
660
661 drawCanvas(image, ...coords) {
662 if (image instanceof Canvas) {
663 this.ƒ("drawCanvas", core(image.getContext("2d")), ...coords);
664 } else {
665 this.drawImage(image, ...coords);
666 }
667 }
668
669 // -- typography ------------------------------------------------------------
670 get font() {
671 return this.prop("font");
672 }
673 set font(str) {
674 this.prop("font", css.font(str));
675 }
676 get textAlign() {
677 return this.prop("textAlign");
678 }
679 set textAlign(mode) {
680 this.prop("textAlign", mode);
681 }
682 get textBaseline() {
683 return this.prop("textBaseline");
684 }
685 set textBaseline(mode) {
686 this.prop("textBaseline", mode);
687 }
688 get direction() {
689 return this.prop("direction");
690 }
691 set direction(mode) {
692 this.prop("direction", mode);
693 }
694
695 measureText(text, maxWidth) {
696 text = this.textWrap ? text : text + "\u200b"; // include trailing whitespace by default
697 let [metrics, ...lines] = this.ƒ("measureText", toString(text), maxWidth);
698 return new TextMetrics(metrics, lines);
699 }
700
701 fillText(text, x, y, maxWidth) {
702 this.ƒ("fillText", toString(text), x, y, maxWidth);
703 }
704
705 strokeText(text, x, y, maxWidth) {
706 this.ƒ("strokeText", toString(text), x, y, maxWidth);
707 }
708
709 outlineText(text) {
710 let path = this.ƒ("outlineText", toString(text));
711 return path ? wrap(Path2D, path) : null;
712 }
713
714 // -- non-standard typography extensions --------------------------------------------
715 get fontVariant() {
716 return this.prop("fontVariant");
717 }
718 set fontVariant(str) {
719 this.prop("fontVariant", css.variant(str));
720 }
721 get textTracking() {
722 return this.prop("textTracking");
723 }
724 set textTracking(ems) {
725 this.prop("textTracking", ems);
726 }
727 get textWrap() {
728 return this.prop("textWrap");
729 }
730 set textWrap(flag) {
731 this.prop("textWrap", !!flag);
732 }
733
734 // -- effects ---------------------------------------------------------------
735 get globalCompositeOperation() {
736 return this.prop("globalCompositeOperation");
737 }
738 set globalCompositeOperation(blend) {
739 this.prop("globalCompositeOperation", blend);
740 }
741 get globalAlpha() {
742 return this.prop("globalAlpha");
743 }
744 set globalAlpha(alpha) {
745 this.prop("globalAlpha", alpha);
746 }
747 get shadowBlur() {
748 return this.prop("shadowBlur");
749 }
750 set shadowBlur(level) {
751 this.prop("shadowBlur", level);
752 }
753 get shadowColor() {
754 return this.prop("shadowColor");
755 }
756 set shadowColor(color) {
757 this.prop("shadowColor", color);
758 }
759 get shadowOffsetX() {
760 return this.prop("shadowOffsetX");
761 }
762 set shadowOffsetX(x) {
763 this.prop("shadowOffsetX", x);
764 }
765 get shadowOffsetY() {
766 return this.prop("shadowOffsetY");
767 }
768 set shadowOffsetY(y) {
769 this.prop("shadowOffsetY", y);
770 }
771 get filter() {
772 return this.prop("filter");
773 }
774 set filter(str) {
775 this.prop("filter", css.filter(str));
776 }
777
778 [REPR](depth, options) {
779 let props = [
780 "canvas",
781 "currentTransform",
782 "fillStyle",
783 "strokeStyle",
784 "font",
785 "fontVariant",
786 "direction",
787 "textAlign",
788 "textBaseline",
789 "textTracking",
790 "textWrap",
791 "globalAlpha",
792 "globalCompositeOperation",
793 "imageSmoothingEnabled",
794 "imageSmoothingQuality",
795 "filter",
796 "shadowBlur",
797 "shadowColor",
798 "shadowOffsetX",
799 "shadowOffsetY",
800 "lineCap",
801 "lineDashOffset",
802 "lineJoin",
803 "lineWidth",
804 "miterLimit"
805 ];
806 let info = {};
807 if (depth > 0) {
808 for (var prop of props) {
809 try {
810 info[prop] = this[prop];
811 } catch {
812 info[prop] = undefined;
813 }
814 }
815 }
816 return `CanvasRenderingContext2D ${inspect(info, options)}`;
817 }
818 }
819
820 const _expand = paths =>
821 [paths]
822 .flat(2)
823 .map(pth => (hasMagic(pth) ? glob(pth) : pth))
824 .flat();
825
826 class FontLibrary extends RustClass {
827 constructor() {
828 super(FontLibrary);
829 }
830
831 get families() {
832 return this.prop("families");
833 }
834
835 has(familyName) {
836 return this.ƒ("has", familyName);
837 }
838
839 family(name) {
840 return this.ƒ("family", name);
841 }
842
843 use(...args) {
844 let sig = signature(args);
845 if (sig == "o") {
846 let results = {};
847 for (let [alias, paths] of Object.entries(args.shift())) {
848 results[alias] = this.ƒ("addFamily", alias, _expand(paths));
849 }
850 return results;
851 } else if (sig.match(/^s?[as]$/)) {
852 let fonts = _expand(args.pop());
853 let alias = args.shift();
854 return this.ƒ("addFamily", alias, fonts);
855 } else {
856 throw new Error(
857 "Expected an array of file paths or an object mapping family names to font files"
858 );
859 }
860 }
861 }
862
863 class Image extends RustClass {
864 constructor() {
865 super(Image).alloc();
866 }
867
868 get complete() {
869 return this.prop("complete");
870 }
871 get height() {
872 return this.prop("height");
873 }
874 get width() {
875 return this.prop("width");
876 }
877
878 get src() {
879 return this.prop("src");
880 }
881 set src(src) {
882 var noop = () => {},
883 onload = img => fetch.emit("ok", img),
884 onerror = err => fetch.emit("err", err),
885 passthrough = fn => arg => {
886 (fn || noop)(arg);
887 delete this._fetch;
888 },
889 data;
890
891 if (this._fetch) this._fetch.removeAllListeners();
892 let fetch = (this._fetch = new EventEmitter()
893 .once("ok", passthrough(this.onload))
894 .once("err", passthrough(this.onerror)));
895
896 if (Buffer.isBuffer(src)) {
897 [data, src] = [src, ""];
898 } else if (typeof src != "string") {
899 return;
900 } else if (/^\s*data:/.test(src)) {
901 // data URI
902 let split = src.indexOf(","),
903 enc = src.lastIndexOf("base64", split) !== -1 ? "base64" : "utf8",
904 content = src.slice(split + 1);
905 data = Buffer.from(content, enc);
906 } else if (/^\s*https?:\/\//.test(src)) {
907 // remote URL
908 get.concat(src, (err, res, data) => {
909 let code = (res || {}).statusCode;
910 if (err) onerror(err);
911 else if (code < 200 || code >= 300) {
912 onerror(
913 new Error(`Failed to load image from "${src}" (error ${code})`)
914 );
915 } else {
916 if (this.prop("data", data)) onload(this);
917 else onerror(new Error("Could not decode image data"));
918 }
919 });
920 } else {
921 // local file path
922 data = fs.readFileSync(src);
923 }
924
925 this.prop("src", src);
926 if (data) {
927 if (this.prop("data", data)) onload(this);
928 else onerror(new Error("Could not decode image data"));
929 }
930 }
931
932 decode() {
933 return this._fetch
934 ? new Promise((res, rej) => this._fetch.once("ok", res).once("err", rej))
935 : this.complete
936 ? Promise.resolve(this)
937 : Promise.reject(new Error("Missing Source URL"));
938 }
939
940 [REPR](depth, options) {
941 let { width, height, complete, src } = this;
942 options.maxStringLength = src.match(/^data:/) ? 128 : Infinity;
943 return `Image ${inspect({ width, height, complete, src }, options)}`;
944 }
945 }
946
947 class ImageData {
948 constructor(...args) {
949 if (args[0] instanceof ImageData) {
950 var { data, width, height } = args[0];
951 } else if (
952 args[0] instanceof Uint8ClampedArray ||
953 args[0] instanceof Buffer
954 ) {
955 var [data, width, height] = args;
956 height = height || data.length / width / 4;
957 if (data.length / 4 != width * height) {
958 throw new Error("ImageData dimensions must match buffer length");
959 }
960 } else {
961 var [width, height] = args;
962 }
963
964 if (
965 !Number.isInteger(width) ||
966 !Number.isInteger(height) ||
967 width < 0 ||
968 height < 0
969 ) {
970 throw new Error("ImageData dimensions must be positive integers");
971 }
972
973 readOnly(this, "width", width);
974 readOnly(this, "height", height);
975 readOnly(
976 this,
977 "data",
978 new Uint8ClampedArray((data && data.buffer) || width * height * 4)
979 );
980 }
981
982 [REPR](depth, options) {
983 let { width, height, data } = this;
984 return `ImageData ${inspect({ width, height, data }, options)}`;
985 }
986 }
987
988 class Path2D extends RustClass {
989 static op(operation, path, other) {
990 return wrap(Path2D, path.ƒ("op", core(other), operation));
991 }
992
993 static interpolate(path, other, weight) {
994 return wrap(Path2D, path.ƒ("interpolate", core(other), weight));
995 }
996
997 static effect(effect, path, ...args) {
998 return wrap(Path2D, path.ƒ(effect, ...args));
999 }
1000
1001 constructor(source) {
1002 super(Path2D);
1003 if (source instanceof Path2D) this.init("from_path", core(source));
1004 else if (typeof source == "string") this.init("from_svg", source);
1005 else this.alloc();
1006 }
1007
1008 // dimensions & contents
1009 get bounds() {
1010 return this.ƒ("bounds");
1011 }
1012 get edges() {
1013 return this.ƒ("edges");
1014 }
1015 get d() {
1016 return this.prop("d");
1017 }
1018 set d(svg) {
1019 return this.prop("d", svg);
1020 }
1021 contains(x, y) {
1022 return this.ƒ("contains", x, y);
1023 }
1024
1025 points(step = 1) {
1026 return this.jitter(step, 0)
1027 .edges.map(([verb, ...pts]) => pts.slice(-2))
1028 .filter(pt => pt.length);
1029 }
1030
1031 // concatenation
1032 addPath(path, matrix) {
1033 if (!(path instanceof Path2D)) throw new Error("Expected a Path2D object");
1034 if (matrix) matrix = toSkMatrix(matrix);
1035 this.ƒ("addPath", core(path), matrix);
1036 }
1037
1038 // line segments
1039 moveTo(x, y) {
1040 this.ƒ("moveTo", ...arguments);
1041 }
1042 lineTo(x, y) {
1043 this.ƒ("lineTo", ...arguments);
1044 }
1045 closePath() {
1046 this.ƒ("closePath");
1047 }
1048 arcTo(x1, y1, x2, y2, radius) {
1049 this.ƒ("arcTo", ...arguments);
1050 }
1051 bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
1052 this.ƒ("bezierCurveTo", ...arguments);
1053 }
1054 quadraticCurveTo(cpx, cpy, x, y) {
1055 this.ƒ("quadraticCurveTo", ...arguments);
1056 }
1057 conicCurveTo(cpx, cpy, x, y, weight) {
1058 this.ƒ("conicCurveTo", ...arguments);
1059 }
1060
1061 // shape primitives
1062 ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, isCCW) {
1063 this.ƒ("ellipse", ...arguments);
1064 }
1065 rect(x, y, width, height) {
1066 this.ƒ("rect", ...arguments);
1067 }
1068 arc(x, y, radius, startAngle, endAngle) {
1069 this.ƒ("arc", ...arguments);
1070 }
1071
1072 // tween similar paths
1073 interpolate(path, weight) {
1074 return Path2D.interpolate(this, path, weight);
1075 }
1076
1077 // boolean operations
1078 complement(path) {
1079 return Path2D.op("complement", this, path);
1080 }
1081 difference(path) {
1082 return Path2D.op("difference", this, path);
1083 }
1084 intersect(path) {
1085 return Path2D.op("intersect", this, path);
1086 }
1087 union(path) {
1088 return Path2D.op("union", this, path);
1089 }
1090 xor(path) {
1091 return Path2D.op("xor", this, path);
1092 }
1093
1094 // path effects
1095 jitter(len, amt, seed) {
1096 return Path2D.effect("jitter", this, ...arguments);
1097 }
1098 simplify(rule) {
1099 return Path2D.effect("simplify", this, rule);
1100 }
1101 unwind() {
1102 return Path2D.effect("unwind", this);
1103 }
1104 round(radius) {
1105 return Path2D.effect("round", this, radius);
1106 }
1107 offset(dx, dy) {
1108 return Path2D.effect("offset", this, dx, dy);
1109 }
1110
1111 transform(matrix) {
1112 let terms = arguments.length > 1 ? [...arguments] : matrix;
1113 return Path2D.effect("transform", this, toSkMatrix(terms));
1114 }
1115
1116 trim(...rng) {
1117 if (typeof rng[1] != "number") {
1118 if (rng[0] > 0) rng.unshift(0);
1119 else if (rng[0] < 0) rng.splice(1, 0, 1);
1120 }
1121 if (rng[0] < 0) rng[0] = Math.max(-1, rng[0]) + 1;
1122 if (rng[1] < 0) rng[1] = Math.max(-1, rng[1]) + 1;
1123 return Path2D.effect("trim", this, ...rng);
1124 }
1125
1126 [REPR](depth, options) {
1127 let { d, bounds, edges } = this;
1128 return `Path2D ${inspect({ d, bounds, edges }, options)}`;
1129 }
1130 }
1131
1132 class TextMetrics {
1133 constructor(
1134 [
1135 width,
1136 left,
1137 right,
1138 ascent,
1139 descent,
1140 fontAscent,
1141 fontDescent,
1142 emAscent,
1143 emDescent,
1144 hanging,
1145 alphabetic,
1146 ideographic
1147 ],
1148 lines
1149 ) {
1150 readOnly(this, "width", width);
1151 readOnly(this, "actualBoundingBoxLeft", left);
1152 readOnly(this, "actualBoundingBoxRight", right);
1153 readOnly(this, "actualBoundingBoxAscent", ascent);
1154 readOnly(this, "actualBoundingBoxDescent", descent);
1155 readOnly(this, "fontBoundingBoxAscent", fontAscent);
1156 readOnly(this, "fontBoundingBoxDescent", fontDescent);
1157 readOnly(this, "emHeightAscent", emAscent);
1158 readOnly(this, "emHeightDescent", emDescent);
1159 readOnly(this, "hangingBaseline", hanging);
1160 readOnly(this, "alphabeticBaseline", alphabetic);
1161 readOnly(this, "ideographicBaseline", ideographic);
1162 readOnly(
1163 this,
1164 "lines",
1165 lines.map(([x, y, width, height, baseline, startIndex, endIndex]) => ({
1166 x,
1167 y,
1168 width,
1169 height,
1170 baseline,
1171 startIndex,
1172 endIndex
1173 }))
1174 );
1175 }
1176 }
1177
1178 const loadImage = src => Object.assign(new Image(), { src }).decode();
1179
1180 // module.exports = {
1181 // Canvas,
1182 // CanvasGradient,
1183 // CanvasPattern,
1184 // CanvasRenderingContext2D,
1185 // CanvasTexture,
1186 // TextMetrics,
1187 // Image,
1188 // ImageData,
1189 // Path2D,
1190 // loadImage,
1191 // ...geometry,
1192 // FontLibrary: new FontLibrary()
1193 // };
1194 const obj = {
1195 Canvas,
1196 CanvasGradient,
1197 CanvasPattern,
1198 CanvasRenderingContext2D,
1199 CanvasTexture,
1200 TextMetrics,
1201 Image,
1202 ImageData,
1203 Path2D,
1204 loadImage,
1205 ...geometry,
1206 FontLibrary: new FontLibrary()
1207 };
1208 export default obj;
1 "use strict";
2
3 // const { basename, extname } = require("path");
4 import { basename, extname } from "../../path-browserify/index.js";
5 //
6 // Mime type <-> File extension mappings
7 //
8
9 class Format {
10 constructor() {
11 let isWeb = (() => typeof global == "undefined")(),
12 png = "image/png",
13 jpg = "image/jpeg",
14 jpeg = "image/jpeg",
15 webp = "image/webp",
16 pdf = "application/pdf",
17 svg = "image/svg+xml";
18
19 Object.assign(this, {
20 toMime: this.toMime.bind(this),
21 fromMime: this.fromMime.bind(this),
22 expected: isWeb
23 ? `"png", "jpg", or "webp"`
24 : `"png", "jpg", "pdf", or "svg"`,
25 formats: isWeb ? { png, jpg, jpeg, webp } : { png, jpg, jpeg, pdf, svg },
26 mimes: isWeb
27 ? { [png]: "png", [jpg]: "jpg", [webp]: "webp" }
28 : { [png]: "png", [jpg]: "jpg", [pdf]: "pdf", [svg]: "svg" }
29 });
30 }
31
32 toMime(ext) {
33 return this.formats[(ext || "").replace(/^\./, "").toLowerCase()];
34 }
35
36 fromMime(mime) {
37 return this.mimes[mime];
38 }
39 }
40
41 //
42 // Validation of the options dict shared by the Canvas saveAs, toBuffer, and toDataURL methods
43 //
44
45 function options(
46 pages,
47 {
48 filename = "",
49 extension = "",
50 format,
51 page,
52 quality,
53 matte,
54 density,
55 outline,
56 archive
57 } = {}
58 ) {
59 var { fromMime, toMime, expected } = new Format(),
60 archive = archive || "canvas",
61 ext = format || extension.replace(/@\d+x$/i, "") || extname(filename),
62 format = fromMime(toMime(ext) || ext),
63 mime = toMime(format),
64 pp = pages.length;
65
66 if (!ext)
67 throw new Error(
68 `Cannot determine image format (use a filename extension or 'format' argument)`
69 );
70 if (!format)
71 throw new Error(`Unsupported file format "${ext}" (expected ${expected})`);
72 if (!pp)
73 throw new RangeError(
74 `Canvas has no associated contexts (try calling getContext or newPage first)`
75 );
76
77 let padding,
78 isSequence,
79 pattern = filename.replace(/{(\d*)}/g, (_, width) => {
80 isSequence = true;
81 width = parseInt(width, 10);
82 padding = isFinite(width) ? width : isFinite(padding) ? padding : -1;
83 return "{}";
84 });
85
86 // allow negative indexing if a specific page is specified
87 let idx = page > 0 ? page - 1 : page < 0 ? pp + page : undefined;
88
89 if ((isFinite(idx) && idx < 0) || idx >= pp)
90 throw new RangeError(
91 pp == 1
92 ? `Canvas only has a ‘page 1’ (${idx} is out of bounds)`
93 : `Canvas has pages 1–${pp} (${idx} is out of bounds)`
94 );
95
96 pages = isFinite(idx)
97 ? [pages[idx]]
98 : isSequence || format == "pdf"
99 ? pages
100 : pages.slice(-1); // default to the 'current' context
101
102 if (quality === undefined) {
103 quality = 0.92;
104 } else {
105 if (
106 typeof quality != "number" ||
107 !isFinite(quality) ||
108 quality < 0 ||
109 quality > 1
110 ) {
111 throw new TypeError(
112 "The quality option must be an number in the 0.0–1.0 range"
113 );
114 }
115 }
116
117 if (density === undefined) {
118 let m = (extension || basename(filename, ext)).match(/@(\d+)x$/i);
119 density = m ? parseInt(m[1], 10) : 1;
120 } else if (
121 typeof density != "number" ||
122 !Number.isInteger(density) ||
123 density < 1
124 ) {
125 throw new TypeError("The density option must be a non-negative integer");
126 }
127
128 if (outline === undefined) {
129 outline = true;
130 } else if (format == "svg") {
131 outline = !!outline;
132 }
133
134 return {
135 filename,
136 pattern,
137 format,
138 mime,
139 pages,
140 padding,
141 quality,
142 matte,
143 density,
144 outline,
145 archive
146 };
147 }
148
149 //
150 // Zip (pace Phil Katz & q.v. https://github.com/jimmywarting/StreamSaver.js)
151 //
152
153 class Crc32 {
154 static for(data) {
155 return new Crc32().append(data).get();
156 }
157
158 constructor() {
159 this.crc = -1;
160 }
161
162 get() {
163 return ~this.crc;
164 }
165
166 append(data) {
167 var crc = this.crc | 0,
168 table = this.table;
169 for (var offset = 0, len = data.length | 0; offset < len; offset++) {
170 crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xff];
171 }
172 this.crc = crc;
173 return this;
174 }
175 }
176
177 Crc32.prototype.table = (() => {
178 var i,
179 j,
180 t,
181 table = [];
182 for (i = 0; i < 256; i++) {
183 t = i;
184 for (j = 0; j < 8; j++) {
185 t = t & 1 ? (t >>> 1) ^ 0xedb88320 : t >>> 1;
186 }
187 table[i] = t;
188 }
189 return table;
190 })();
191
192 function calloc(size) {
193 let array = new Uint8Array(size),
194 view = new DataView(array.buffer),
195 buf = {
196 array,
197 view,
198 size,
199 set8(at, to) {
200 view.setUint8(at, to);
201 return buf;
202 },
203 set16(at, to) {
204 view.setUint16(at, to, true);
205 return buf;
206 },
207 set32(at, to) {
208 view.setUint32(at, to, true);
209 return buf;
210 },
211 bytes(at, to) {
212 array.set(to, at);
213 return buf;
214 }
215 };
216 return buf;
217 }
218 // const TextEncoder=require('util').TextEncoder
219
220 class Zip {
221 constructor(directory) {
222 let now = new Date();
223 Object.assign(this, {
224 directory,
225 offset: 0,
226 files: [],
227 time:
228 (((now.getHours() << 6) | now.getMinutes()) << 5) |
229 (now.getSeconds() / 2),
230 date:
231 ((((now.getFullYear() - 1980) << 4) | (now.getMonth() + 1)) << 5) |
232 now.getDate()
233 });
234 this.add(directory);
235 }
236
237 async add(filename, blob) {
238 let folder = !blob,
239 name = Zip.encoder.encode(`${this.directory}/${folder ? "" : filename}`),
240 data = new Uint8Array(folder ? 0 : await blob.arrayBuffer()),
241 preamble = 30 + name.length,
242 descriptor = preamble + data.length,
243 postamble = 16,
244 { offset } = this;
245
246 let header = calloc(26)
247 .set32(0, 0x08080014) // zip version
248 .set16(6, this.time) // time
249 .set16(8, this.date) // date
250 .set32(10, Crc32.for(data)) // checksum
251 .set32(14, data.length) // compressed size (w/ zero compression)
252 .set32(18, data.length) // un-compressed size
253 .set16(22, name.length); // filename length (utf8 bytes)
254 offset += preamble;
255
256 let payload = calloc(preamble + data.length + postamble)
257 .set32(0, 0x04034b50) // local header signature
258 .bytes(4, header.array) // ...header fields...
259 .bytes(30, name) // filename
260 .bytes(preamble, data); // blob bytes
261 offset += data.length;
262
263 payload
264 .set32(descriptor, 0x08074b50) // signature
265 .bytes(descriptor + 4, header.array.slice(10, 22)); // length & filemame
266 offset += postamble;
267
268 this.files.push({ offset, folder, name, header, payload });
269 this.offset = offset;
270 }
271
272 toBuffer() {
273 // central directory record
274 let length = this.files.reduce(
275 (len, { name }) => 46 + name.length + len,
276 0
277 ),
278 cdr = calloc(length + 22),
279 index = 0;
280
281 for (var { offset, name, header, folder } of this.files) {
282 cdr
283 .set32(index, 0x02014b50) // archive file signature
284 .set16(index + 4, 0x0014) // version
285 .bytes(index + 6, header.array) // ...header fields...
286 .set8(index + 38, folder ? 0x10 : 0) // is_dir flag
287 .set32(index + 42, offset) // file offset
288 .bytes(index + 46, name); // filename
289 index += 46 + name.length;
290 }
291 cdr
292 .set32(index, 0x06054b50) // signature
293 .set16(index + 8, this.files.length) // № files per-segment
294 .set16(index + 10, this.files.length) // № files this segment
295 .set32(index + 12, length) // central directory length
296 .set32(index + 16, this.offset); // file-offset of directory
297
298 // concatenated zipfile data
299 let output = new Uint8Array(this.offset + cdr.size),
300 cursor = 0;
301
302 for (var { payload } of this.files) {
303 output.set(payload.array, cursor);
304 cursor += payload.size;
305 }
306 output.set(cdr.array, cursor);
307
308 return output;
309 }
310
311 get blob() {
312 return new Blob([this.toBuffer()], { type: "application/zip" });
313 }
314 }
315 Zip.encoder = new TextEncoder();
316
317 //
318 // Browser helpers for converting canvas elements to blobs/buffers/files/zips
319 //
320
321 const asBlob = (canvas, mime, quality, matte) => {
322 if (matte) {
323 let { width, height } = canvas,
324 comp = Object.assign(document.createElement("canvas"), { width, height }),
325 ctx = comp.getContext("2d");
326 ctx.fillStyle = matte;
327 ctx.fillRect(0, 0, width, height);
328 ctx.drawImage(canvas, 0, 0);
329 canvas = comp;
330 }
331
332 return new Promise((res, rej) => canvas.toBlob(res, mime, quality));
333 };
334
335 const asBuffer = (...args) => asBlob(...args).then(b => b.arrayBuffer());
336
337 const asDownload = async (canvas, mime, quality, matte, filename) => {
338 _download(filename, await asBlob(canvas, mime, quality, matte));
339 };
340
341 const asZipDownload = async (
342 pages,
343 mime,
344 quality,
345 matte,
346 archive,
347 pattern,
348 padding
349 ) => {
350 let filenames = i =>
351 pattern.replace("{}", String(i + 1).padStart(padding, "0")),
352 folder = basename(archive, ".zip") || "archive",
353 zip = new Zip(folder);
354
355 await Promise.all(
356 pages.map(async (page, i) => {
357 let filename = filenames(i); // serialize filename(s) before awaiting
358 await zip.add(filename, await asBlob(page, mime, quality, matte));
359 })
360 );
361
362 _download(`${folder}.zip`, zip.blob);
363 };
364
365 const _download = (filename, blob) => {
366 const href = window.URL.createObjectURL(blob),
367 link = document.createElement("a");
368 link.style.display = "none";
369 link.href = href;
370 link.setAttribute("download", filename);
371 if (typeof link.download === "undefined") {
372 link.setAttribute("target", "_blank");
373 }
374 document.body.appendChild(link);
375 link.click();
376 document.body.removeChild(link);
377 setTimeout(() => window.URL.revokeObjectURL(href), 100);
378 };
379
380 const atScale = (pages, density, matte) =>
381 pages.map(page => {
382 if (density == 1 && !matte) return page.canvas;
383
384 let scaled = document.createElement("canvas"),
385 ctx = scaled.getContext("2d"),
386 src = page.canvas ? page.canvas : page;
387 scaled.width = src.width * density;
388 scaled.height = src.height * density;
389 if (matte) {
390 ctx.fillStyle = matte;
391 ctx.fillRect(0, 0, scaled.width, scaled.height);
392 }
393 ctx.scale(density, density);
394 ctx.drawImage(src, 0, 0);
395 return scaled;
396 });
397 const obj = { asBuffer, asDownload, asZipDownload, atScale, options };
398 export default obj;
399 // module.exports = { asBuffer, asDownload, asZipDownload, atScale, options };
1 {
2 "name": "skia-canvas",
3 "version": "0.9.29",
4 "description": "A canvas environment for Node",
5 "author": "Christian Swinehart <drafting@samizdat.co>",
6 "license": "MIT",
7 "repository": {
8 "type": "git",
9 "url": "git+https://github.com/samizdatco/skia-canvas.git"
10 },
11 "bugs": {
12 "url": "https://github.com/samizdatco/skia-canvas/issues"
13 },
14 "homepage": "https://github.com/samizdatco/skia-canvas#readme",
15 "main": "lib",
16 "browser": {
17 "lib": "./lib/browser.js",
18 "path": "path-browserify"
19 },
20 "scripts": {
21 "build": "cargo-cp-artifact -nc lib/v6/index.node -- cargo build --message-format=json-render-diagnostics",
22 "install": "node-pre-gyp install || npm run build -- --release",
23 "package": "node-pre-gyp package",
24 "upload": "node-pre-gyp publish",
25 "test": "jest"
26 },
27 "dependencies": {
28 "@mapbox/node-pre-gyp": "^1.0.8",
29 "cargo-cp-artifact": "^0.1",
30 "glob": "^7.2.0",
31 "path-browserify": "^1.0.1",
32 "simple-get": "^4.0.1",
33 "string-split-by": "^1.0.0"
34 },
35 "devDependencies": {
36 "@types/jest": "^27.4.0",
37 "@types/node": "^17.0.15",
38 "aws-sdk": "^2.1069.0",
39 "express": "^4.17.2",
40 "jest": "^27.5.0",
41 "lodash": "^4.17.21",
42 "nodemon": "^2.0.15",
43 "tmp": "^0.2.1"
44 },
45 "files": [
46 "lib"
47 ],
48 "binary": {
49 "module_name": "index",
50 "module_path": "./lib/v{napi_build_version}",
51 "remote_path": "./v{version}",
52 "package_name": "{platform}-{arch}-{node_napi_label}-{libc}.tar.gz",
53 "host": "https://skia-canvas.s3.us-east-1.amazonaws.com",
54 "napi_versions": [
55 6
56 ]
57 },
58 "keywords": [
59 "skia",
60 "canvas",
61 "offscreen",
62 "headless",
63 "graphic",
64 "graphics",
65 "image",
66 "images",
67 "compositing",
68 "render",
69 "pdf",
70 "svg",
71 "rust"
72 ]
73 }
1 <template>
2 <div>
3 <vue-qr
4 text="123456789012345"
5 :components="{
6 cornerAlignment: {
7 scale: 0.5,
8 protectors: true
9 }
10 }"
11 ></vue-qr>
12 <vue-qr
13 text="123456789012345"
14 :components="{
15 cornerAlignment: {
16 scale: 1,
17 protectors: true
18 }
19 }"
20 ></vue-qr>
21 <vue-qr
22 text="test"
23 colorDark="#28D905"
24 colorLight="#EB0303"
25 backgroundColor="#EB0303"
26 :margin="0"
27 :bindElement="true"
28 :callback="test"
29 ></vue-qr>
30 <vue-qr
31 text="hello world"
32 :correctLevel="0"
33 backgroundColor="rgb(255,0,0)"
34 ></vue-qr>
35 <vue-qr
36 text="hello world"
37 :correctLevel="1"
38 colorLight="rgb(255,0,0)"
39 ></vue-qr>
40 <vue-qr
41 text="hello world"
42 :correctLevel="1"
43 colorLight="rgb(0,255,0)"
44 ></vue-qr>
45 <vue-qr text="hello world" :correctLevel="2"></vue-qr>
46 <vue-qr
47 :bgSrc="src"
48 :logoSrc="src2"
49 text="Hello world!"
50 :size="260"
51 :margin="0"
52 :dotScale="0.5"
53 ></vue-qr>
54 <vue-qr
55 :bgSrc="src"
56 :logoSrc="src2"
57 text="Hello world!"
58 :size="260"
59 :margin="50"
60 :dotScale="0.5"
61 ></vue-qr>
62 <vue-qr
63 :bgSrc="src"
64 :logoSrc="src2"
65 text="Hello world!"
66 :size="260"
67 :margin="0"
68 :dotScale="0.5"
69 logoBackgroundColor="rgb(255,0,0)"
70 :logoMargin="10"
71 ></vue-qr>
72
73 <vue-qr text="testdsfhsidufhiusdhfi" :bgSrc="src"></vue-qr>
74 <vue-qr :text="time + ''"></vue-qr>
75 <vue-qr
76 :bgSrc="src3"
77 text="Hello world!"
78 :size="260"
79 :margin="0"
80 :dotScale="0.6"
81 ></vue-qr>
82 <vue-qr
83 :bgSrc="src4"
84 text="Hello world!"
85 :size="300"
86 :dotScale="0.5"
87 ></vue-qr>
88 <vue-qr
89 text="Hello world!"
90 :callback="test"
91 qid="testid"
92 :size="300"
93 ></vue-qr>
94 <vue-qr
95 text="test test test test test test "
96 :gifBgSrc="gifBgSrc1"
97 :size="300"
98 :dotScale="0.4"
99 :logoSrc="src2"
100 ></vue-qr>
101 <vue-qr
102 text="test test test test test test "
103 :gifBgSrc="gifBgSrc2"
104 :size="300"
105 ></vue-qr>
106 <vue-qr
107 text="test test test test test "
108 :gifBgSrc="gifBgSrc2"
109 :size="300"
110 backgroundDimming="rgb(255,0,0)"
111 colorDark="rgb(0,0,0)"
112 :dotScale="0.5"
113 ></vue-qr>
114 <vue-qr text="test"></vue-qr>
115 </div>
116 </template>
117
118 <script>
119 import vueQr from "./packages/vue-qr";
120 import src from "./assets/bg1.png";
121 import src2 from "./assets/avatar.png";
122 import src3 from "./assets/bg2.jpg";
123 import src4 from "./assets/bg3.jpg";
124 import gifBgSrc1 from "./assets/dog.gif";
125 import gifBgSrc2 from "./assets/scare.gif";
126
127 export default {
128 mounted() {
129 setInterval(() => {
130 this.time++;
131 }, 1000);
132 },
133 data() {
134 return {
135 src,
136 src2,
137 src3,
138 src4,
139 time: 0,
140 gifBgSrc1,
141 gifBgSrc2
142 };
143 },
144 components: {
145 vueQr
146 },
147 methods: {
148 test(url, id) {
149 console.log(url, id);
150 }
151 }
152 };
153 </script>
1 import vueQr from './packages/index.js';
2 const components = [
3 vueQr
4 ]
5
6 const install = function(Vue, opts = {}) {
7 components.map(component => {
8 Vue.component(component.name, component);
9 })
10 }
11
12 /* 支持使用标签的方式引入 */
13 if (typeof window !== 'undefined' && window.Vue) {
14 install(window.Vue);
15 }
16
17 export default vueQr
18
1 /// <reference types="node" />
2 export declare type ComponentOptions = {
3 /**
4 * Component options for data/ECC.
5 */
6 data?: {
7 /**
8 * Scale factor for data/ECC dots.
9 * @default 0.4
10 */
11 scale?: number;
12 };
13 /**
14 * Component options for timing patterns.
15 */
16 timing?: {
17 /**
18 * Scale factor for timing patterns.
19 * @default 0.5
20 */
21 scale?: number;
22 /**
23 * Protector for timing patterns.
24 * @default false
25 */
26 protectors?: boolean;
27 };
28 /**
29 * Component options for alignment patterns.
30 */
31 alignment?: {
32 /**
33 * Scale factor for alignment patterns.
34 * @default 0.5
35 */
36 scale?: number;
37 /**
38 * Protector for alignment patterns.
39 * @default false
40 */
41 protectors?: boolean;
42 };
43 /**
44 * Component options for alignment pattern on the bottom-right corner.
45 */
46 cornerAlignment?: {
47 /**
48 * Scale factor for alignment pattern on the bottom-right corner.
49 * @default 0.5
50 */
51 scale?: number;
52 /**
53 * Protector for alignment pattern on the bottom-right corner.
54 * @default true
55 */
56 protectors?: boolean;
57 };
58 };
59 export declare type Options = {
60 /**
61 * Text to be encoded in the QR code.
62 */
63 text: string;
64 /**
65 * Size of the QR code in pixel.
66 *
67 * @defaultValue 400
68 */
69 size?: number;
70 /**
71 * Size of margins around the QR code body in pixel.
72 *
73 * @defaultValue 20
74 */
75 margin?: number;
76 /**
77 * Error correction level of the QR code.
78 *
79 * Accepts a value provided by _QRErrorCorrectLevel_.
80 *
81 * For more information, please refer to [https://www.qrcode.com/en/about/error_correction.html](https://www.qrcode.com/en/about/error_correction.html).
82 *
83 * @defaultValue 0
84 */
85 correctLevel?: number;
86 /**
87 * **This is an advanced option.**
88 *
89 * Specify the mask pattern to be used in QR code encoding.
90 *
91 * Accepts a value provided by _QRMaskPattern_.
92 *
93 * To find out all eight mask patterns, please refer to [https://en.wikipedia.org/wiki/File:QR_Code_Mask_Patterns.svg](https://en.wikipedia.org/wiki/File:QR_Code_Mask_Patterns.svg)
94 *
95 * For more information, please refer to [https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Masking](https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Masking).
96 */
97 maskPattern?: number;
98 /**
99 * **This is an advanced option.**
100 *
101 * Specify the version to be used in QR code encoding.
102 *
103 * Accepts an integer in range [1, 40].
104 *
105 * For more information, please refer to [https://www.qrcode.com/en/about/version.html](https://www.qrcode.com/en/about/version.html).
106 */
107 version?: number;
108 /**
109 * Options to control components in the QR code.
110 *
111 * @deafultValue undefined
112 */
113 components?: ComponentOptions;
114 /**
115 * Color of the blocks on the QR code.
116 *
117 * Accepts a CSS &lt;color&gt;.
118 *
119 * For more information about CSS &lt;color&gt;, please refer to [https://developer.mozilla.org/en-US/docs/Web/CSS/color_value](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
120 *
121 * @defaultValue "#000000"
122 */
123 colorDark?: string;
124 /**
125 * Color of the empty areas on the QR code.
126 *
127 * Accepts a CSS &lt;color&gt;.
128 *
129 * For more information about CSS &lt;color&gt;, please refer to [https://developer.mozilla.org/en-US/docs/Web/CSS/color_value](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
130 *
131 * @defaultValue "#ffffff"
132 */
133 colorLight?: string;
134 /**
135 * Automatically calculate the _colorLight_ value from the QR code's background.
136 *
137 * @defaultValue true
138 */
139 autoColor?: boolean;
140 /**
141 * Background image to be used in the QR code.
142 *
143 * Accepts a `data:` string in web browsers or a Buffer in Node.js.
144 *
145 * @defaultValue undefined
146 */
147 backgroundImage?: string | Buffer;
148 /**
149 * Color of the dimming mask above the background image.
150 *
151 * Accepts a CSS &lt;color&gt;.
152 *
153 * For more information about CSS &lt;color&gt;, please refer to [https://developer.mozilla.org/en-US/docs/Web/CSS/color_value](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
154 *
155 * @defaultValue "rgba(0, 0, 0, 0)"
156 */
157 backgroundDimming?: string;
158 /**
159 * GIF background image to be used in the QR code.
160 *
161 * @defaultValue undefined
162 */
163 gifBackground?: ArrayBuffer;
164 /**
165 * Use a white margin instead of a transparent one which reveals the background of the QR code on margins.
166 *
167 * @defaultValue true
168 */
169 whiteMargin?: boolean;
170 /**
171 * Logo image to be displayed at the center of the QR code.
172 *
173 * Accepts a `data:` string in web browsers or a Buffer in Node.js.
174 *
175 * When set to `undefined` or `null`, the logo is disabled.
176 *
177 * @defaultValue undefined
178 */
179 logoImage?: string | Buffer;
180 /**
181 * Ratio of the logo size to the QR code size.
182 *
183 * @defaultValue 0.2
184 */
185 logoScale?: number;
186 /**
187 * Size of margins around the logo image in pixels.
188 *
189 * @defaultValue 6
190 */
191 logoMargin?: number;
192 /**
193 * Corner radius of the logo image in pixels.
194 *
195 * @defaultValue 8
196 */
197 logoCornerRadius?: number;
198 /**
199 * @deprecated
200 *
201 * Ratio of the real size to the full size of the blocks.
202 *
203 * This can be helpful when you want to make more parts of the background visible.
204 *
205 * @deafultValue 0.4
206 */
207 dotScale?: number;
208 logoBackgroundColor: string;
209 backgroundColor: string;
210 };
211 export declare class AwesomeQR {
212 private canvas;
213 private canvasContext;
214 private qrCode?;
215 private options;
216 static CorrectLevel: {
217 L: number;
218 M: number;
219 Q: number;
220 H: number;
221 };
222 private static defaultComponentOptions;
223 static defaultOptions: Options;
224 constructor(options: Partial<Options>);
225 draw(): Promise<Buffer | ArrayBuffer | string | undefined>;
226 private _clear;
227 private static _prepareRoundedCornerClip;
228 private static _getAverageRGB;
229 private static _drawDot;
230 private static _drawAlignProtector;
231 private static _drawAlign;
232 private _draw;
233 }
1 var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9 };
10 import canvas from "../../packages/skia-canvas-lib/lib/browser";
11 const { Canvas } = canvas;
12 import { decompressFrames, parseGIF } from "./gifuct-js/index";
13 import { QRCodeModel, QRErrorCorrectLevel, QRUtil } from "./qrcode";
14 import GIFEncoder from "./gif.js/GIFEncoder";
15 const defaultScale = 0.4;
16 function loadImage(url) {
17 if (!url) {
18 return undefined;
19 }
20 function cleanup(img) {
21 img.onload = null;
22 img.onerror = null;
23 }
24 return new Promise(function (resolve, reject) {
25 if (url.slice(0, 4) == 'data') {
26 let img = new Image();
27 img.onload = function () {
28 resolve(img);
29 cleanup(img);
30 };
31 img.onerror = function () {
32 reject('Image load error');
33 cleanup(img);
34 };
35 img.src = url;
36 return;
37 }
38 let img = new Image();
39 img.setAttribute("crossOrigin", 'Anonymous');
40 img.onload = function () {
41 resolve(img);
42 };
43 img.onerror = function () {
44 reject('Image load error');
45 };
46 img.src = url;
47 });
48 }
49 export class AwesomeQR {
50 constructor(options) {
51 const _options = Object.assign({}, options);
52 Object.keys(AwesomeQR.defaultOptions).forEach((k) => {
53 if (!(k in _options)) {
54 Object.defineProperty(_options, k, { value: AwesomeQR.defaultOptions[k], enumerable: true, writable: true });
55 }
56 });
57 if (!_options.components) {
58 _options.components = AwesomeQR.defaultComponentOptions;
59 }
60 else if (typeof _options.components === "object") {
61 Object.keys(AwesomeQR.defaultComponentOptions).forEach((k) => {
62 if (!(k in _options.components)) {
63 Object.defineProperty(_options.components, k, {
64 value: AwesomeQR.defaultComponentOptions[k],
65 enumerable: true,
66 writable: true,
67 });
68 }
69 else {
70 Object.defineProperty(_options.components, k, {
71 value: Object.assign(Object.assign({}, AwesomeQR.defaultComponentOptions[k]), _options.components[k]),
72 enumerable: true,
73 writable: true,
74 });
75 }
76 });
77 }
78 if (_options.dotScale !== null && _options.dotScale !== undefined) {
79 if (_options.dotScale <= 0 || _options.dotScale > 1) {
80 throw new Error("dotScale should be in range (0, 1].");
81 }
82 _options.components.data.scale = _options.dotScale;
83 _options.components.timing.scale = _options.dotScale;
84 _options.components.alignment.scale = _options.dotScale;
85 }
86 this.options = _options;
87 this.canvas = new Canvas(options.size, options.size);
88 this.canvasContext = this.canvas.getContext("2d");
89 this.qrCode = new QRCodeModel(-1, this.options.correctLevel);
90 if (Number.isInteger(this.options.maskPattern)) {
91 this.qrCode.maskPattern = this.options.maskPattern;
92 }
93 if (Number.isInteger(this.options.version)) {
94 this.qrCode.typeNumber = this.options.version;
95 }
96 this.qrCode.addData(this.options.text);
97 this.qrCode.make();
98 }
99 draw() {
100 return new Promise((resolve) => this._draw().then(resolve));
101 }
102 _clear() {
103 this.canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height);
104 }
105 static _prepareRoundedCornerClip(canvasContext, x, y, w, h, r) {
106 canvasContext.beginPath();
107 canvasContext.moveTo(x, y);
108 canvasContext.arcTo(x + w, y, x + w, y + h, r);
109 canvasContext.arcTo(x + w, y + h, x, y + h, r);
110 canvasContext.arcTo(x, y + h, x, y, r);
111 canvasContext.arcTo(x, y, x + w, y, r);
112 canvasContext.closePath();
113 }
114 static _getAverageRGB(image) {
115 const blockSize = 5;
116 const defaultRGB = {
117 r: 0,
118 g: 0,
119 b: 0,
120 };
121 let width, height;
122 let i = -4;
123 const rgb = {
124 r: 0,
125 g: 0,
126 b: 0,
127 };
128 let count = 0;
129 height = image.naturalHeight || image.height;
130 width = image.naturalWidth || image.width;
131 const canvas = new Canvas(width, height);
132 const context = canvas.getContext("2d");
133 if (!context) {
134 return defaultRGB;
135 }
136 context.drawImage(image, 0, 0);
137 let data;
138 try {
139 data = context.getImageData(0, 0, width, height);
140 }
141 catch (e) {
142 return defaultRGB;
143 }
144 while ((i += blockSize * 4) < data.data.length) {
145 if (data.data[i] > 200 || data.data[i + 1] > 200 || data.data[i + 2] > 200)
146 continue;
147 ++count;
148 rgb.r += data.data[i];
149 rgb.g += data.data[i + 1];
150 rgb.b += data.data[i + 2];
151 }
152 rgb.r = ~~(rgb.r / count);
153 rgb.g = ~~(rgb.g / count);
154 rgb.b = ~~(rgb.b / count);
155 return rgb;
156 }
157 static _drawDot(canvasContext, centerX, centerY, nSize, xyOffset = 0, dotScale = 1) {
158 canvasContext.fillRect((centerX + xyOffset) * nSize, (centerY + xyOffset) * nSize, dotScale * nSize, dotScale * nSize);
159 }
160 static _drawAlignProtector(canvasContext, centerX, centerY, nSize) {
161 canvasContext.clearRect((centerX - 2) * nSize, (centerY - 2) * nSize, 5 * nSize, 5 * nSize);
162 canvasContext.fillRect((centerX - 2) * nSize, (centerY - 2) * nSize, 5 * nSize, 5 * nSize);
163 }
164 static _drawAlign(canvasContext, centerX, centerY, nSize, xyOffset = 0, dotScale = 1, colorDark, hasProtector) {
165 const oldFillStyle = canvasContext.fillStyle;
166 canvasContext.fillStyle = colorDark;
167 new Array(4).fill(0).map((_, i) => {
168 AwesomeQR._drawDot(canvasContext, centerX - 2 + i, centerY - 2, nSize, xyOffset, dotScale);
169 AwesomeQR._drawDot(canvasContext, centerX + 2, centerY - 2 + i, nSize, xyOffset, dotScale);
170 AwesomeQR._drawDot(canvasContext, centerX + 2 - i, centerY + 2, nSize, xyOffset, dotScale);
171 AwesomeQR._drawDot(canvasContext, centerX - 2, centerY + 2 - i, nSize, xyOffset, dotScale);
172 });
173 AwesomeQR._drawDot(canvasContext, centerX, centerY, nSize, xyOffset, dotScale);
174 if (!hasProtector) {
175 canvasContext.fillStyle = "rgba(255, 255, 255, 0.6)";
176 new Array(2).fill(0).map((_, i) => {
177 AwesomeQR._drawDot(canvasContext, centerX - 1 + i, centerY - 1, nSize, xyOffset, dotScale);
178 AwesomeQR._drawDot(canvasContext, centerX + 1, centerY - 1 + i, nSize, xyOffset, dotScale);
179 AwesomeQR._drawDot(canvasContext, centerX + 1 - i, centerY + 1, nSize, xyOffset, dotScale);
180 AwesomeQR._drawDot(canvasContext, centerX - 1, centerY + 1 - i, nSize, xyOffset, dotScale);
181 });
182 }
183 canvasContext.fillStyle = oldFillStyle;
184 }
185 _draw() {
186 var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
187 return __awaiter(this, void 0, void 0, function* () {
188 const nCount = (_a = this.qrCode) === null || _a === void 0 ? void 0 : _a.moduleCount;
189 const rawSize = this.options.size;
190 let rawMargin = this.options.margin;
191 if (rawMargin < 0 || rawMargin * 2 >= rawSize) {
192 rawMargin = 0;
193 }
194 const margin = Math.ceil(rawMargin);
195 const rawViewportSize = rawSize - 2 * rawMargin;
196 const whiteMargin = this.options.whiteMargin;
197 const backgroundDimming = this.options.backgroundDimming;
198 const nSize = Math.ceil(rawViewportSize / nCount);
199 const viewportSize = nSize * nCount;
200 const size = viewportSize + 2 * margin;
201 const mainCanvas = new Canvas(size, size);
202 const mainCanvasContext = mainCanvas.getContext("2d");
203 this._clear();
204 // Translate to make the top and left margins off the viewport
205 mainCanvasContext.save();
206 mainCanvasContext.translate(margin, margin);
207 const backgroundCanvas = new Canvas(size, size);
208 const backgroundCanvasContext = backgroundCanvas.getContext("2d");
209 let parsedGIFBackground = null;
210 let gifFrames = [];
211 if (!!this.options.gifBackground) {
212 const gif = parseGIF(this.options.gifBackground);
213 parsedGIFBackground = gif;
214 gifFrames = decompressFrames(gif, true);
215 if (this.options.autoColor) {
216 let r = 0, g = 0, b = 0;
217 let count = 0;
218 for (let i = 0; i < gifFrames[0].colorTable.length; i++) {
219 const c = gifFrames[0].colorTable[i];
220 if (c[0] > 200 || c[1] > 200 || c[2] > 200)
221 continue;
222 if (c[0] === 0 && c[1] === 0 && c[2] === 0)
223 continue;
224 count++;
225 r += c[0];
226 g += c[1];
227 b += c[2];
228 }
229 r = ~~(r / count);
230 g = ~~(g / count);
231 b = ~~(b / count);
232 this.options.colorDark = `rgb(${r},${g},${b})`;
233 }
234 }
235 else if (!!this.options.backgroundImage) {
236 const backgroundImage = yield loadImage(this.options.backgroundImage);
237 if (this.options.autoColor) {
238 const avgRGB = AwesomeQR._getAverageRGB(backgroundImage);
239 this.options.colorDark = `rgb(${avgRGB.r},${avgRGB.g},${avgRGB.b})`;
240 }
241 backgroundCanvasContext.drawImage(backgroundImage, 0, 0, backgroundImage.width, backgroundImage.height, 0, 0, size, size);
242 backgroundCanvasContext.rect(0, 0, size, size);
243 backgroundCanvasContext.fillStyle = backgroundDimming;
244 backgroundCanvasContext.fill();
245 }
246 else {
247 backgroundCanvasContext.rect(0, 0, size, size);
248 backgroundCanvasContext.fillStyle = this.options.colorLight;
249 backgroundCanvasContext.fill();
250 }
251 const alignmentPatternCenters = QRUtil.getPatternPosition(this.qrCode.typeNumber);
252 const dataScale = ((_c = (_b = this.options.components) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.scale) || defaultScale;
253 const dataXyOffset = (1 - dataScale) * 0.5;
254 for (let row = 0; row < nCount; row++) {
255 for (let col = 0; col < nCount; col++) {
256 const bIsDark = this.qrCode.isDark(row, col);
257 const isBlkPosCtr = (col < 8 && (row < 8 || row >= nCount - 8)) || (col >= nCount - 8 && row < 8);
258 const isTiming = (row == 6 && col >= 8 && col <= nCount - 8) || (col == 6 && row >= 8 && row <= nCount - 8);
259 let isProtected = isBlkPosCtr || isTiming;
260 for (let i = 1; i < alignmentPatternCenters.length - 1; i++) {
261 isProtected =
262 isProtected ||
263 (row >= alignmentPatternCenters[i] - 2 &&
264 row <= alignmentPatternCenters[i] + 2 &&
265 col >= alignmentPatternCenters[i] - 2 &&
266 col <= alignmentPatternCenters[i] + 2);
267 }
268 const nLeft = col * nSize + (isProtected ? 0 : dataXyOffset * nSize);
269 const nTop = row * nSize + (isProtected ? 0 : dataXyOffset * nSize);
270 mainCanvasContext.strokeStyle = bIsDark ? this.options.colorDark : this.options.colorLight;
271 mainCanvasContext.lineWidth = 0.5;
272 mainCanvasContext.fillStyle = bIsDark ? this.options.colorDark : this.options.colorLight;
273 if (alignmentPatternCenters.length === 0) {
274 if (!isProtected) {
275 mainCanvasContext.fillRect(nLeft, nTop, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize);
276 }
277 }
278 else {
279 const inAgnRange = col < nCount - 4 && col >= nCount - 4 - 5 && row < nCount - 4 && row >= nCount - 4 - 5;
280 if (!isProtected && !inAgnRange) {
281 // if align pattern list is empty, then it means that we don't need to leave room for the align patterns
282 mainCanvasContext.fillRect(nLeft, nTop, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize);
283 }
284 }
285 }
286 }
287 const cornerAlignmentCenter = alignmentPatternCenters[alignmentPatternCenters.length - 1];
288 // - PROTECTORS
289 const protectorStyle = this.options.colorLight;
290 // - FINDER PROTECTORS
291 mainCanvasContext.fillStyle = protectorStyle;
292 mainCanvasContext.fillRect(0, 0, 8 * nSize, 8 * nSize);
293 mainCanvasContext.fillRect(0, (nCount - 8) * nSize, 8 * nSize, 8 * nSize);
294 mainCanvasContext.fillRect((nCount - 8) * nSize, 0, 8 * nSize, 8 * nSize);
295 // - TIMING PROTECTORS
296 if ((_e = (_d = this.options.components) === null || _d === void 0 ? void 0 : _d.timing) === null || _e === void 0 ? void 0 : _e.protectors) {
297 mainCanvasContext.fillRect(8 * nSize, 6 * nSize, (nCount - 8 - 8) * nSize, nSize);
298 mainCanvasContext.fillRect(6 * nSize, 8 * nSize, nSize, (nCount - 8 - 8) * nSize);
299 }
300 // - CORNER ALIGNMENT PROTECTORS
301 if ((_g = (_f = this.options.components) === null || _f === void 0 ? void 0 : _f.cornerAlignment) === null || _g === void 0 ? void 0 : _g.protectors) {
302 AwesomeQR._drawAlignProtector(mainCanvasContext, cornerAlignmentCenter, cornerAlignmentCenter, nSize);
303 }
304 // - ALIGNMENT PROTECTORS
305 if ((_j = (_h = this.options.components) === null || _h === void 0 ? void 0 : _h.alignment) === null || _j === void 0 ? void 0 : _j.protectors) {
306 for (let i = 0; i < alignmentPatternCenters.length; i++) {
307 for (let j = 0; j < alignmentPatternCenters.length; j++) {
308 const agnX = alignmentPatternCenters[j];
309 const agnY = alignmentPatternCenters[i];
310 if (agnX === 6 && (agnY === 6 || agnY === cornerAlignmentCenter)) {
311 continue;
312 }
313 else if (agnY === 6 && (agnX === 6 || agnX === cornerAlignmentCenter)) {
314 continue;
315 }
316 else if (agnX === cornerAlignmentCenter && agnY === cornerAlignmentCenter) {
317 continue;
318 }
319 else {
320 AwesomeQR._drawAlignProtector(mainCanvasContext, agnX, agnY, nSize);
321 }
322 }
323 }
324 }
325 // - FINDER
326 mainCanvasContext.fillStyle = this.options.colorDark;
327 mainCanvasContext.fillRect(0, 0, 7 * nSize, nSize);
328 mainCanvasContext.fillRect((nCount - 7) * nSize, 0, 7 * nSize, nSize);
329 mainCanvasContext.fillRect(0, 6 * nSize, 7 * nSize, nSize);
330 mainCanvasContext.fillRect((nCount - 7) * nSize, 6 * nSize, 7 * nSize, nSize);
331 mainCanvasContext.fillRect(0, (nCount - 7) * nSize, 7 * nSize, nSize);
332 mainCanvasContext.fillRect(0, (nCount - 7 + 6) * nSize, 7 * nSize, nSize);
333 mainCanvasContext.fillRect(0, 0, nSize, 7 * nSize);
334 mainCanvasContext.fillRect(6 * nSize, 0, nSize, 7 * nSize);
335 mainCanvasContext.fillRect((nCount - 7) * nSize, 0, nSize, 7 * nSize);
336 mainCanvasContext.fillRect((nCount - 7 + 6) * nSize, 0, nSize, 7 * nSize);
337 mainCanvasContext.fillRect(0, (nCount - 7) * nSize, nSize, 7 * nSize);
338 mainCanvasContext.fillRect(6 * nSize, (nCount - 7) * nSize, nSize, 7 * nSize);
339 mainCanvasContext.fillRect(2 * nSize, 2 * nSize, 3 * nSize, 3 * nSize);
340 mainCanvasContext.fillRect((nCount - 7 + 2) * nSize, 2 * nSize, 3 * nSize, 3 * nSize);
341 mainCanvasContext.fillRect(2 * nSize, (nCount - 7 + 2) * nSize, 3 * nSize, 3 * nSize);
342 // - TIMING
343 const timingScale = ((_l = (_k = this.options.components) === null || _k === void 0 ? void 0 : _k.timing) === null || _l === void 0 ? void 0 : _l.scale) || defaultScale;
344 const timingXyOffset = (1 - timingScale) * 0.5;
345 for (let i = 0; i < nCount - 8; i += 2) {
346 AwesomeQR._drawDot(mainCanvasContext, 8 + i, 6, nSize, timingXyOffset, timingScale);
347 AwesomeQR._drawDot(mainCanvasContext, 6, 8 + i, nSize, timingXyOffset, timingScale);
348 }
349 // - CORNER ALIGNMENT PROTECTORS
350 const cornerAlignmentScale = ((_o = (_m = this.options.components) === null || _m === void 0 ? void 0 : _m.cornerAlignment) === null || _o === void 0 ? void 0 : _o.scale) || defaultScale;
351 const cornerAlignmentXyOffset = (1 - cornerAlignmentScale) * 0.5;
352 AwesomeQR._drawAlign(mainCanvasContext, cornerAlignmentCenter, cornerAlignmentCenter, nSize, cornerAlignmentXyOffset, cornerAlignmentScale, this.options.colorDark, ((_q = (_p = this.options.components) === null || _p === void 0 ? void 0 : _p.cornerAlignment) === null || _q === void 0 ? void 0 : _q.protectors) || false);
353 // - ALIGNEMNT
354 const alignmentScale = ((_s = (_r = this.options.components) === null || _r === void 0 ? void 0 : _r.alignment) === null || _s === void 0 ? void 0 : _s.scale) || defaultScale;
355 const alignmentXyOffset = (1 - alignmentScale) * 0.5;
356 for (let i = 0; i < alignmentPatternCenters.length; i++) {
357 for (let j = 0; j < alignmentPatternCenters.length; j++) {
358 const agnX = alignmentPatternCenters[j];
359 const agnY = alignmentPatternCenters[i];
360 if (agnX === 6 && (agnY === 6 || agnY === cornerAlignmentCenter)) {
361 continue;
362 }
363 else if (agnY === 6 && (agnX === 6 || agnX === cornerAlignmentCenter)) {
364 continue;
365 }
366 else if (agnX === cornerAlignmentCenter && agnY === cornerAlignmentCenter) {
367 continue;
368 }
369 else {
370 AwesomeQR._drawAlign(mainCanvasContext, agnX, agnY, nSize, alignmentXyOffset, alignmentScale, this.options.colorDark, ((_u = (_t = this.options.components) === null || _t === void 0 ? void 0 : _t.alignment) === null || _u === void 0 ? void 0 : _u.protectors) || false);
371 }
372 }
373 }
374 // Fill the margin
375 if (whiteMargin) {
376 mainCanvasContext.fillStyle = this.options.backgroundColor;
377 mainCanvasContext.fillRect(-margin, -margin, size, margin);
378 mainCanvasContext.fillRect(-margin, viewportSize, size, margin);
379 mainCanvasContext.fillRect(viewportSize, -margin, margin, size);
380 mainCanvasContext.fillRect(-margin, -margin, margin, size);
381 }
382 if (!!this.options.logoImage) {
383 const logoImage = yield loadImage(this.options.logoImage);
384 let logoScale = this.options.logoScale;
385 let logoMargin = this.options.logoMargin;
386 let logoCornerRadius = this.options.logoCornerRadius;
387 if (logoScale <= 0 || logoScale >= 1.0) {
388 logoScale = 0.2;
389 }
390 if (logoMargin < 0) {
391 logoMargin = 0;
392 }
393 if (logoCornerRadius < 0) {
394 logoCornerRadius = 0;
395 }
396 const logoSize = viewportSize * logoScale;
397 const x = 0.5 * (size - logoSize);
398 const y = x;
399 // Restore the canvas
400 // After restoring, the top and left margins should be taken into account
401 mainCanvasContext.restore();
402 // Clean the area that the logo covers (including margins)
403 mainCanvasContext.fillStyle = this.options.logoBackgroundColor;
404 mainCanvasContext.save();
405 AwesomeQR._prepareRoundedCornerClip(mainCanvasContext, x - logoMargin, y - logoMargin, logoSize + 2 * logoMargin, logoSize + 2 * logoMargin, logoCornerRadius + logoMargin);
406 mainCanvasContext.clip();
407 const oldGlobalCompositeOperation = mainCanvasContext.globalCompositeOperation;
408 mainCanvasContext.globalCompositeOperation = "destination-out";
409 mainCanvasContext.fill();
410 mainCanvasContext.globalCompositeOperation = oldGlobalCompositeOperation;
411 mainCanvasContext.restore();
412 // Draw logo image
413 mainCanvasContext.save();
414 AwesomeQR._prepareRoundedCornerClip(mainCanvasContext, x, y, logoSize, logoSize, logoCornerRadius);
415 mainCanvasContext.clip();
416 mainCanvasContext.drawImage(logoImage, x, y, logoSize, logoSize);
417 mainCanvasContext.restore();
418 // Re-translate the canvas to translate the top and left margins into invisible area
419 mainCanvasContext.save();
420 mainCanvasContext.translate(margin, margin);
421 }
422 if (!!parsedGIFBackground) {
423 let gifOutput;
424 // Reuse in order to apply the patch
425 let backgroundCanvas;
426 let backgroundCanvasContext;
427 let patchCanvas;
428 let patchCanvasContext;
429 let patchData;
430 gifFrames.forEach(function (frame) {
431 if (!gifOutput) {
432 gifOutput = new GIFEncoder(rawSize, rawSize);
433 gifOutput.setDelay(frame.delay);
434 gifOutput.setRepeat(0);
435 }
436 const { width, height } = frame.dims;
437 if (!backgroundCanvas) {
438 backgroundCanvas = new Canvas(width, height);
439 backgroundCanvasContext = backgroundCanvas.getContext("2d");
440 backgroundCanvasContext.rect(0, 0, backgroundCanvas.width, backgroundCanvas.height);
441 backgroundCanvasContext.fillStyle = "#ffffff";
442 backgroundCanvasContext.fill();
443 }
444 if (!patchCanvas || !patchData || width !== patchCanvas.width || height !== patchCanvas.height) {
445 patchCanvas = new Canvas(width, height);
446 patchCanvasContext = patchCanvas.getContext("2d");
447 patchData = patchCanvasContext.createImageData(width, height);
448 }
449 patchData.data.set(frame.patch);
450 patchCanvasContext.putImageData(patchData, 0, 0);
451 backgroundCanvasContext.drawImage(patchCanvas.getContext('2d').canvas, frame.dims.left, frame.dims.top);
452 const unscaledCanvas = new Canvas(size, size);
453 const unscaledCanvasContext = unscaledCanvas.getContext("2d");
454 unscaledCanvasContext.drawImage(backgroundCanvas.getContext('2d').canvas, 0, 0, size, size);
455 unscaledCanvasContext.rect(0, 0, size, size);
456 unscaledCanvasContext.fillStyle = backgroundDimming;
457 unscaledCanvasContext.fill();
458 unscaledCanvasContext.drawImage(mainCanvas.getContext('2d').canvas, 0, 0, size, size);
459 // Scale the final image
460 const outCanvas = new Canvas(rawSize, rawSize);
461 const outCanvasContext = outCanvas.getContext("2d");
462 outCanvasContext.drawImage(unscaledCanvas.getContext('2d').canvas, 0, 0, rawSize, rawSize);
463 gifOutput.addFrame(outCanvasContext.getImageData(0, 0, outCanvas.width, outCanvas.height).data);
464 });
465 if (!gifOutput) {
466 throw new Error("No frames.");
467 }
468 gifOutput.finish();
469 if (isElement(this.canvas)) {
470 const u8array = gifOutput.stream().toFlattenUint8Array();
471 const binary = u8array.reduce((bin, u8) => bin + String.fromCharCode(u8), "");
472 return Promise.resolve(`data:image/gif;base64,${window.btoa(binary)}`);
473 }
474 return Promise.resolve(Buffer.from(gifOutput.stream().toFlattenUint8Array()));
475 }
476 else {
477 // Swap and merge the foreground and the background
478 backgroundCanvasContext.drawImage(mainCanvas.getContext('2d').canvas, 0, 0, size, size);
479 mainCanvasContext.drawImage(backgroundCanvas.getContext('2d').canvas, -margin, -margin, size, size);
480 // Scale the final image
481 const outCanvas = new Canvas(rawSize, rawSize); //document.createElement("canvas");
482 const outCanvasContext = outCanvas.getContext("2d");
483 outCanvasContext.drawImage(mainCanvas.getContext('2d').canvas, 0, 0, rawSize, rawSize);
484 this.canvas = outCanvas;
485 const format = this.options.gifBackground ? "gif" : "png";
486 if (isElement(this.canvas)) {
487 return Promise.resolve(this.canvas.toDataURL(format));
488 }
489 return Promise.resolve(this.canvas.toBuffer(format));
490 }
491 });
492 }
493 }
494 AwesomeQR.CorrectLevel = QRErrorCorrectLevel;
495 AwesomeQR.defaultComponentOptions = {
496 data: {
497 scale: 0.4,
498 },
499 timing: {
500 scale: 0.5,
501 protectors: false,
502 },
503 alignment: {
504 scale: 0.5,
505 protectors: false,
506 },
507 cornerAlignment: {
508 scale: 0.5,
509 protectors: true,
510 },
511 };
512 AwesomeQR.defaultOptions = {
513 text: "",
514 size: 400,
515 margin: 20,
516 colorDark: "#000000",
517 colorLight: "rgba(255, 255, 255, 0.6)",
518 correctLevel: QRErrorCorrectLevel.M,
519 backgroundImage: undefined,
520 backgroundDimming: "rgba(0,0,0,0)",
521 logoImage: undefined,
522 logoScale: 0.2,
523 logoMargin: 4,
524 logoCornerRadius: 8,
525 whiteMargin: true,
526 components: AwesomeQR.defaultComponentOptions,
527 autoColor: true,
528 logoBackgroundColor: '#ffffff',
529 backgroundColor: '#ffffff',
530 };
531 function isElement(obj) {
532 try {
533 //Using W3 DOM2 (works for FF, Opera and Chrome)
534 return obj instanceof HTMLElement;
535 }
536 catch (e) {
537 //Browsers not supporting W3 DOM2 don't have HTMLElement and
538 //an exception is thrown and we end up here. Testing some
539 //properties that all elements have (works on IE7)
540 return (typeof obj === "object" &&
541 obj.nodeType === 1 &&
542 typeof obj.style === "object" &&
543 typeof obj.ownerDocument === "object");
544 }
545 }
1 export default GIFEncoder;
2 declare function GIFEncoder(width: any, height: any): void;
3 declare class GIFEncoder {
4 constructor(width: any, height: any);
5 width: number;
6 height: number;
7 transparent: any;
8 transIndex: number;
9 repeat: number;
10 delay: number;
11 image: any;
12 pixels: Uint8Array | null;
13 indexedPixels: Uint8Array | null;
14 colorDepth: number | null;
15 colorTab: any;
16 neuQuant: NeuQuant | null;
17 usedEntry: any[];
18 palSize: number;
19 dispose: number;
20 firstFrame: boolean;
21 sample: number;
22 dither: boolean;
23 globalPalette: any;
24 out: ByteArray;
25 setDelay(milliseconds: any): void;
26 setFrameRate(fps: any): void;
27 setDispose(disposalCode: any): void;
28 setRepeat(repeat: any): void;
29 setTransparent(color: any): void;
30 addFrame(imageData: any): void;
31 finish(): void;
32 setQuality(quality: any): void;
33 setDither(dither: any): void;
34 setGlobalPalette(palette: any): void;
35 getGlobalPalette(): any;
36 writeHeader(): void;
37 analyzePixels(): void;
38 indexPixels(imgq: any): void;
39 ditherPixels(kernel: any, serpentine: any): void;
40 findClosest(c: any, used: any): number;
41 findClosestRGB(r: any, g: any, b: any, used: any): number;
42 getImagePixels(): void;
43 writeGraphicCtrlExt(): void;
44 writeImageDesc(): void;
45 writeLSD(): void;
46 writeNetscapeExt(): void;
47 writePalette(): void;
48 writeShort(pValue: any): void;
49 writePixels(): void;
50 stream(): ByteArray;
51 }
52 import NeuQuant from "./TypedNeuQuant.js";
53 declare function ByteArray(): void;
54 declare class ByteArray {
55 page: number;
56 pages: any[];
57 newPage(): void;
58 cursor: number | undefined;
59 getData(): string;
60 toFlattenUint8Array(): Uint8Array;
61 writeByte(val: any): void;
62 writeUTFBytes(string: any): void;
63 writeBytes(array: any, offset: any, length: any): void;
64 }
65 declare namespace ByteArray {
66 export const pageSize: number;
67 export const charMap: {};
68 }
1 /*
2 GIFEncoder.js
3
4 Authors
5 Kevin Weiner (original Java version - kweiner@fmsware.com)
6 Thibault Imbert (AS3 version - bytearray.org)
7 Johan Nordberg (JS version - code@johan-nordberg.com)
8 Makito (Optimized for AwesomeQR - sumimakito@hotmail,com)
9 */
10 // var NeuQuant = require("./TypedNeuQuant.js");
11 import NeuQuant from "./TypedNeuQuant.js";
12 // var LZWEncoder = require("./LZWEncoder.js");
13 import LZWEncoder from "./LZWEncoder.js";
14 function ByteArray() {
15 this.page = -1;
16 this.pages = [];
17 this.newPage();
18 }
19 ByteArray.pageSize = 4096;
20 ByteArray.charMap = {};
21 for (var i = 0; i < 256; i++)
22 ByteArray.charMap[i] = String.fromCharCode(i);
23 ByteArray.prototype.newPage = function () {
24 this.pages[++this.page] = new Uint8Array(ByteArray.pageSize);
25 this.cursor = 0;
26 };
27 ByteArray.prototype.getData = function () {
28 var rv = "";
29 for (var p = 0; p < this.pages.length; p++) {
30 for (var i = 0; i < ByteArray.pageSize; i++) {
31 rv += ByteArray.charMap[this.pages[p][i]];
32 }
33 }
34 return rv;
35 };
36 ByteArray.prototype.toFlattenUint8Array = function () {
37 const chunks = [];
38 for (var p = 0; p < this.pages.length; p++) {
39 if (p === this.pages.length - 1) {
40 const chunk = Uint8Array.from(this.pages[p].slice(0, this.cursor));
41 chunks.push(chunk);
42 }
43 else {
44 chunks.push(this.pages[p]);
45 }
46 }
47 const flatten = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
48 chunks.reduce((lastLength, chunk) => {
49 flatten.set(chunk, lastLength);
50 return lastLength + chunk.length;
51 }, 0);
52 return flatten;
53 };
54 ByteArray.prototype.writeByte = function (val) {
55 if (this.cursor >= ByteArray.pageSize)
56 this.newPage();
57 this.pages[this.page][this.cursor++] = val;
58 };
59 ByteArray.prototype.writeUTFBytes = function (string) {
60 for (var l = string.length, i = 0; i < l; i++)
61 this.writeByte(string.charCodeAt(i));
62 };
63 ByteArray.prototype.writeBytes = function (array, offset, length) {
64 for (var l = length || array.length, i = offset || 0; i < l; i++)
65 this.writeByte(array[i]);
66 };
67 function GIFEncoder(width, height) {
68 // image size
69 this.width = ~~width;
70 this.height = ~~height;
71 // transparent color if given
72 this.transparent = null;
73 // transparent index in color table
74 this.transIndex = 0;
75 // -1 = no repeat, 0 = forever. anything else is repeat count
76 this.repeat = -1;
77 // frame delay (hundredths)
78 this.delay = 0;
79 this.image = null; // current frame
80 this.pixels = null; // BGR byte array from frame
81 this.indexedPixels = null; // converted frame indexed to palette
82 this.colorDepth = null; // number of bit planes
83 this.colorTab = null; // RGB palette
84 this.neuQuant = null; // NeuQuant instance that was used to generate this.colorTab.
85 this.usedEntry = new Array(); // active palette entries
86 this.palSize = 7; // color table size (bits-1)
87 this.dispose = -1; // disposal code (-1 = use default)
88 this.firstFrame = true;
89 this.sample = 10; // default sample interval for quantizer
90 this.dither = false; // default dithering
91 this.globalPalette = false;
92 this.out = new ByteArray();
93 }
94 /*
95 Sets the delay time between each frame, or changes it for subsequent frames
96 (applies to last frame added)
97 */
98 GIFEncoder.prototype.setDelay = function (milliseconds) {
99 this.delay = Math.round(milliseconds / 10);
100 };
101 /*
102 Sets frame rate in frames per second.
103 */
104 GIFEncoder.prototype.setFrameRate = function (fps) {
105 this.delay = Math.round(100 / fps);
106 };
107 /*
108 Sets the GIF frame disposal code for the last added frame and any
109 subsequent frames.
110
111 Default is 0 if no transparent color has been set, otherwise 2.
112 */
113 GIFEncoder.prototype.setDispose = function (disposalCode) {
114 if (disposalCode >= 0)
115 this.dispose = disposalCode;
116 };
117 /*
118 Sets the number of times the set of GIF frames should be played.
119
120 -1 = play once
121 0 = repeat indefinitely
122
123 Default is -1
124
125 Must be invoked before the first image is added
126 */
127 GIFEncoder.prototype.setRepeat = function (repeat) {
128 this.repeat = repeat;
129 };
130 /*
131 Sets the transparent color for the last added frame and any subsequent
132 frames. Since all colors are subject to modification in the quantization
133 process, the color in the final palette for each frame closest to the given
134 color becomes the transparent color for that frame. May be set to null to
135 indicate no transparent color.
136 */
137 GIFEncoder.prototype.setTransparent = function (color) {
138 this.transparent = color;
139 };
140 /*
141 Adds next GIF frame. The frame is not written immediately, but is
142 actually deferred until the next frame is received so that timing
143 data can be inserted. Invoking finish() flushes all frames.
144 */
145 GIFEncoder.prototype.addFrame = function (imageData) {
146 this.image = imageData;
147 this.colorTab = this.globalPalette && this.globalPalette.slice ? this.globalPalette : null;
148 this.getImagePixels(); // convert to correct format if necessary
149 this.analyzePixels(); // build color table & map pixels
150 if (this.globalPalette === true)
151 this.globalPalette = this.colorTab;
152 if (this.firstFrame) {
153 this.writeHeader();
154 this.writeLSD(); // logical screen descriptior
155 this.writePalette(); // global color table
156 if (this.repeat >= 0) {
157 // use NS app extension to indicate reps
158 this.writeNetscapeExt();
159 }
160 }
161 this.writeGraphicCtrlExt(); // write graphic control extension
162 this.writeImageDesc(); // image descriptor
163 if (!this.firstFrame && !this.globalPalette)
164 this.writePalette(); // local color table
165 this.writePixels(); // encode and write pixel data
166 this.firstFrame = false;
167 };
168 /*
169 Adds final trailer to the GIF stream, if you don't call the finish method
170 the GIF stream will not be valid.
171 */
172 GIFEncoder.prototype.finish = function () {
173 this.out.writeByte(0x3b); // gif trailer
174 };
175 /*
176 Sets quality of color quantization (conversion of images to the maximum 256
177 colors allowed by the GIF specification). Lower values (minimum = 1)
178 produce better colors, but slow processing significantly. 10 is the
179 default, and produces good color mapping at reasonable speeds. Values
180 greater than 20 do not yield significant improvements in speed.
181 */
182 GIFEncoder.prototype.setQuality = function (quality) {
183 if (quality < 1)
184 quality = 1;
185 this.sample = quality;
186 };
187 /*
188 Sets dithering method. Available are:
189 - FALSE no dithering
190 - TRUE or FloydSteinberg
191 - FalseFloydSteinberg
192 - Stucki
193 - Atkinson
194 You can add '-serpentine' to use serpentine scanning
195 */
196 GIFEncoder.prototype.setDither = function (dither) {
197 if (dither === true)
198 dither = "FloydSteinberg";
199 this.dither = dither;
200 };
201 /*
202 Sets global palette for all frames.
203 You can provide TRUE to create global palette from first picture.
204 Or an array of r,g,b,r,g,b,...
205 */
206 GIFEncoder.prototype.setGlobalPalette = function (palette) {
207 this.globalPalette = palette;
208 };
209 /*
210 Returns global palette used for all frames.
211 If setGlobalPalette(true) was used, then this function will return
212 calculated palette after the first frame is added.
213 */
214 GIFEncoder.prototype.getGlobalPalette = function () {
215 return (this.globalPalette && this.globalPalette.slice && this.globalPalette.slice(0)) || this.globalPalette;
216 };
217 /*
218 Writes GIF file header
219 */
220 GIFEncoder.prototype.writeHeader = function () {
221 this.out.writeUTFBytes("GIF89a");
222 };
223 /*
224 Analyzes current frame colors and creates color map.
225 */
226 GIFEncoder.prototype.analyzePixels = function () {
227 if (!this.colorTab) {
228 this.neuQuant = new NeuQuant(this.pixels, this.sample);
229 this.neuQuant.buildColormap(); // create reduced palette
230 this.colorTab = this.neuQuant.getColormap();
231 }
232 // map image pixels to new palette
233 if (this.dither) {
234 this.ditherPixels(this.dither.replace("-serpentine", ""), this.dither.match(/-serpentine/) !== null);
235 }
236 else {
237 this.indexPixels();
238 }
239 this.pixels = null;
240 this.colorDepth = 8;
241 this.palSize = 7;
242 // get closest match to transparent color if specified
243 if (this.transparent !== null) {
244 this.transIndex = this.findClosest(this.transparent, true);
245 }
246 };
247 /*
248 Index pixels, without dithering
249 */
250 GIFEncoder.prototype.indexPixels = function (imgq) {
251 var nPix = this.pixels.length / 3;
252 this.indexedPixels = new Uint8Array(nPix);
253 var k = 0;
254 for (var j = 0; j < nPix; j++) {
255 var index = this.findClosestRGB(this.pixels[k++] & 0xff, this.pixels[k++] & 0xff, this.pixels[k++] & 0xff);
256 this.usedEntry[index] = true;
257 this.indexedPixels[j] = index;
258 }
259 };
260 /*
261 Taken from http://jsbin.com/iXofIji/2/edit by PAEz
262 */
263 GIFEncoder.prototype.ditherPixels = function (kernel, serpentine) {
264 var kernels = {
265 FalseFloydSteinberg: [
266 [3 / 8, 1, 0],
267 [3 / 8, 0, 1],
268 [2 / 8, 1, 1],
269 ],
270 FloydSteinberg: [
271 [7 / 16, 1, 0],
272 [3 / 16, -1, 1],
273 [5 / 16, 0, 1],
274 [1 / 16, 1, 1],
275 ],
276 Stucki: [
277 [8 / 42, 1, 0],
278 [4 / 42, 2, 0],
279 [2 / 42, -2, 1],
280 [4 / 42, -1, 1],
281 [8 / 42, 0, 1],
282 [4 / 42, 1, 1],
283 [2 / 42, 2, 1],
284 [1 / 42, -2, 2],
285 [2 / 42, -1, 2],
286 [4 / 42, 0, 2],
287 [2 / 42, 1, 2],
288 [1 / 42, 2, 2],
289 ],
290 Atkinson: [
291 [1 / 8, 1, 0],
292 [1 / 8, 2, 0],
293 [1 / 8, -1, 1],
294 [1 / 8, 0, 1],
295 [1 / 8, 1, 1],
296 [1 / 8, 0, 2],
297 ],
298 };
299 if (!kernel || !kernels[kernel]) {
300 throw "Unknown dithering kernel: " + kernel;
301 }
302 var ds = kernels[kernel];
303 var index = 0, height = this.height, width = this.width, data = this.pixels;
304 var direction = serpentine ? -1 : 1;
305 this.indexedPixels = new Uint8Array(this.pixels.length / 3);
306 for (var y = 0; y < height; y++) {
307 if (serpentine)
308 direction = direction * -1;
309 for (var x = direction == 1 ? 0 : width - 1, xend = direction == 1 ? width : 0; x !== xend; x += direction) {
310 index = y * width + x;
311 // Get original colour
312 var idx = index * 3;
313 var r1 = data[idx];
314 var g1 = data[idx + 1];
315 var b1 = data[idx + 2];
316 // Get converted colour
317 idx = this.findClosestRGB(r1, g1, b1);
318 this.usedEntry[idx] = true;
319 this.indexedPixels[index] = idx;
320 idx *= 3;
321 var r2 = this.colorTab[idx];
322 var g2 = this.colorTab[idx + 1];
323 var b2 = this.colorTab[idx + 2];
324 var er = r1 - r2;
325 var eg = g1 - g2;
326 var eb = b1 - b2;
327 for (var i = direction == 1 ? 0 : ds.length - 1, end = direction == 1 ? ds.length : 0; i !== end; i += direction) {
328 var x1 = ds[i][1]; // *direction; // Should this by timesd by direction?..to make the kernel go in the opposite direction....got no idea....
329 var y1 = ds[i][2];
330 if (x1 + x >= 0 && x1 + x < width && y1 + y >= 0 && y1 + y < height) {
331 var d = ds[i][0];
332 idx = index + x1 + y1 * width;
333 idx *= 3;
334 data[idx] = Math.max(0, Math.min(255, data[idx] + er * d));
335 data[idx + 1] = Math.max(0, Math.min(255, data[idx + 1] + eg * d));
336 data[idx + 2] = Math.max(0, Math.min(255, data[idx + 2] + eb * d));
337 }
338 }
339 }
340 }
341 };
342 /*
343 Returns index of palette color closest to c
344 */
345 GIFEncoder.prototype.findClosest = function (c, used) {
346 return this.findClosestRGB((c & 0xff0000) >> 16, (c & 0x00ff00) >> 8, c & 0x0000ff, used);
347 };
348 GIFEncoder.prototype.findClosestRGB = function (r, g, b, used) {
349 if (this.colorTab === null)
350 return -1;
351 if (this.neuQuant && !used) {
352 return this.neuQuant.lookupRGB(r, g, b);
353 }
354 var c = b | (g << 8) | (r << 16);
355 var minpos = 0;
356 var dmin = 256 * 256 * 256;
357 var len = this.colorTab.length;
358 for (var i = 0, index = 0; i < len; index++) {
359 var dr = r - (this.colorTab[i++] & 0xff);
360 var dg = g - (this.colorTab[i++] & 0xff);
361 var db = b - (this.colorTab[i++] & 0xff);
362 var d = dr * dr + dg * dg + db * db;
363 if ((!used || this.usedEntry[index]) && d < dmin) {
364 dmin = d;
365 minpos = index;
366 }
367 }
368 return minpos;
369 };
370 /*
371 Extracts image pixels into byte array pixels
372 (removes alphachannel from canvas imagedata)
373 */
374 GIFEncoder.prototype.getImagePixels = function () {
375 var w = this.width;
376 var h = this.height;
377 this.pixels = new Uint8Array(w * h * 3);
378 var data = this.image;
379 var srcPos = 0;
380 var count = 0;
381 for (var i = 0; i < h; i++) {
382 for (var j = 0; j < w; j++) {
383 this.pixels[count++] = data[srcPos++];
384 this.pixels[count++] = data[srcPos++];
385 this.pixels[count++] = data[srcPos++];
386 srcPos++;
387 }
388 }
389 };
390 /*
391 Writes Graphic Control Extension
392 */
393 GIFEncoder.prototype.writeGraphicCtrlExt = function () {
394 this.out.writeByte(0x21); // extension introducer
395 this.out.writeByte(0xf9); // GCE label
396 this.out.writeByte(4); // data block size
397 var transp, disp;
398 if (this.transparent === null) {
399 transp = 0;
400 disp = 0; // dispose = no action
401 }
402 else {
403 transp = 1;
404 disp = 2; // force clear if using transparent color
405 }
406 if (this.dispose >= 0) {
407 disp = this.dispose & 7; // user override
408 }
409 disp <<= 2;
410 // packed fields
411 this.out.writeByte(0 | // 1:3 reserved
412 disp | // 4:6 disposal
413 0 | // 7 user input - 0 = none
414 transp // 8 transparency flag
415 );
416 this.writeShort(this.delay); // delay x 1/100 sec
417 this.out.writeByte(this.transIndex); // transparent color index
418 this.out.writeByte(0); // block terminator
419 };
420 /*
421 Writes Image Descriptor
422 */
423 GIFEncoder.prototype.writeImageDesc = function () {
424 this.out.writeByte(0x2c); // image separator
425 this.writeShort(0); // image position x,y = 0,0
426 this.writeShort(0);
427 this.writeShort(this.width); // image size
428 this.writeShort(this.height);
429 // packed fields
430 if (this.firstFrame || this.globalPalette) {
431 // no LCT - GCT is used for first (or only) frame
432 this.out.writeByte(0);
433 }
434 else {
435 // specify normal LCT
436 this.out.writeByte(0x80 | // 1 local color table 1=yes
437 0 | // 2 interlace - 0=no
438 0 | // 3 sorted - 0=no
439 0 | // 4-5 reserved
440 this.palSize // 6-8 size of color table
441 );
442 }
443 };
444 /*
445 Writes Logical Screen Descriptor
446 */
447 GIFEncoder.prototype.writeLSD = function () {
448 // logical screen size
449 this.writeShort(this.width);
450 this.writeShort(this.height);
451 // packed fields
452 this.out.writeByte(0x80 | // 1 : global color table flag = 1 (gct used)
453 0x70 | // 2-4 : color resolution = 7
454 0x00 | // 5 : gct sort flag = 0
455 this.palSize // 6-8 : gct size
456 );
457 this.out.writeByte(0); // background color index
458 this.out.writeByte(0); // pixel aspect ratio - assume 1:1
459 };
460 /*
461 Writes Netscape application extension to define repeat count.
462 */
463 GIFEncoder.prototype.writeNetscapeExt = function () {
464 this.out.writeByte(0x21); // extension introducer
465 this.out.writeByte(0xff); // app extension label
466 this.out.writeByte(11); // block size
467 this.out.writeUTFBytes("NETSCAPE2.0"); // app id + auth code
468 this.out.writeByte(3); // sub-block size
469 this.out.writeByte(1); // loop sub-block id
470 this.writeShort(this.repeat); // loop count (extra iterations, 0=repeat forever)
471 this.out.writeByte(0); // block terminator
472 };
473 /*
474 Writes color table
475 */
476 GIFEncoder.prototype.writePalette = function () {
477 this.out.writeBytes(this.colorTab);
478 var n = 3 * 256 - this.colorTab.length;
479 for (var i = 0; i < n; i++)
480 this.out.writeByte(0);
481 };
482 GIFEncoder.prototype.writeShort = function (pValue) {
483 this.out.writeByte(pValue & 0xff);
484 this.out.writeByte((pValue >> 8) & 0xff);
485 };
486 /*
487 Encodes and writes pixel data
488 */
489 GIFEncoder.prototype.writePixels = function () {
490 var enc = new LZWEncoder(this.width, this.height, this.indexedPixels, this.colorDepth);
491 enc.encode(this.out);
492 };
493 /*
494 Retrieves the GIF stream
495 */
496 GIFEncoder.prototype.stream = function () {
497 return this.out;
498 };
499 // module.exports = GIFEncoder;
500 export default GIFEncoder;
1 export default LZWEncoder;
2 declare function LZWEncoder(width: any, height: any, pixels: any, colorDepth: any): void;
3 declare class LZWEncoder {
4 constructor(width: any, height: any, pixels: any, colorDepth: any);
5 encode: (outs: any) => void;
6 }
1 /*
2 LZWEncoder.js
3
4 Authors
5 Kevin Weiner (original Java version - kweiner@fmsware.com)
6 Thibault Imbert (AS3 version - bytearray.org)
7 Johan Nordberg (JS version - code@johan-nordberg.com)
8
9 Acknowledgements
10 GIFCOMPR.C - GIF Image compression routines
11 Lempel-Ziv compression based on 'compress'. GIF modifications by
12 David Rowley (mgardi@watdcsu.waterloo.edu)
13 GIF Image compression - modified 'compress'
14 Based on: compress.c - File compression ala IEEE Computer, June 1984.
15 By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
16 Jim McKie (decvax!mcvax!jim)
17 Steve Davies (decvax!vax135!petsd!peora!srd)
18 Ken Turkowski (decvax!decwrl!turtlevax!ken)
19 James A. Woods (decvax!ihnp4!ames!jaw)
20 Joe Orost (decvax!vax135!petsd!joe)
21 */
22 var EOF = -1;
23 var BITS = 12;
24 var HSIZE = 5003; // 80% occupancy
25 var masks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
26 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
27 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF];
28 function LZWEncoder(width, height, pixels, colorDepth) {
29 var initCodeSize = Math.max(2, colorDepth);
30 var accum = new Uint8Array(256);
31 var htab = new Int32Array(HSIZE);
32 var codetab = new Int32Array(HSIZE);
33 var cur_accum, cur_bits = 0;
34 var a_count;
35 var free_ent = 0; // first unused entry
36 var maxcode;
37 // block compression parameters -- after all codes are used up,
38 // and compression rate changes, start over.
39 var clear_flg = false;
40 // Algorithm: use open addressing double hashing (no chaining) on the
41 // prefix code / next character combination. We do a variant of Knuth's
42 // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
43 // secondary probe. Here, the modular division first probe is gives way
44 // to a faster exclusive-or manipulation. Also do block compression with
45 // an adaptive reset, whereby the code table is cleared when the compression
46 // ratio decreases, but after the table fills. The variable-length output
47 // codes are re-sized at this point, and a special CLEAR code is generated
48 // for the decompressor. Late addition: construct the table according to
49 // file size for noticeable speed improvement on small files. Please direct
50 // questions about this implementation to ames!jaw.
51 var g_init_bits, ClearCode, EOFCode;
52 var remaining, curPixel, n_bits;
53 // Add a character to the end of the current packet, and if it is 254
54 // characters, flush the packet to disk.
55 function char_out(c, outs) {
56 accum[a_count++] = c;
57 if (a_count >= 254)
58 flush_char(outs);
59 }
60 // Clear out the hash table
61 // table clear for block compress
62 function cl_block(outs) {
63 cl_hash(HSIZE);
64 free_ent = ClearCode + 2;
65 clear_flg = true;
66 output(ClearCode, outs);
67 }
68 // Reset code table
69 function cl_hash(hsize) {
70 for (var i = 0; i < hsize; ++i)
71 htab[i] = -1;
72 }
73 function compress(init_bits, outs) {
74 var fcode, c, i, ent, disp, hsize_reg, hshift;
75 // Set up the globals: g_init_bits - initial number of bits
76 g_init_bits = init_bits;
77 // Set up the necessary values
78 clear_flg = false;
79 n_bits = g_init_bits;
80 maxcode = MAXCODE(n_bits);
81 ClearCode = 1 << (init_bits - 1);
82 EOFCode = ClearCode + 1;
83 free_ent = ClearCode + 2;
84 a_count = 0; // clear packet
85 ent = nextPixel();
86 hshift = 0;
87 for (fcode = HSIZE; fcode < 65536; fcode *= 2)
88 ++hshift;
89 hshift = 8 - hshift; // set hash code range bound
90 hsize_reg = HSIZE;
91 cl_hash(hsize_reg); // clear hash table
92 output(ClearCode, outs);
93 outer_loop: while ((c = nextPixel()) != EOF) {
94 fcode = (c << BITS) + ent;
95 i = (c << hshift) ^ ent; // xor hashing
96 if (htab[i] === fcode) {
97 ent = codetab[i];
98 continue;
99 }
100 else if (htab[i] >= 0) { // non-empty slot
101 disp = hsize_reg - i; // secondary hash (after G. Knott)
102 if (i === 0)
103 disp = 1;
104 do {
105 if ((i -= disp) < 0)
106 i += hsize_reg;
107 if (htab[i] === fcode) {
108 ent = codetab[i];
109 continue outer_loop;
110 }
111 } while (htab[i] >= 0);
112 }
113 output(ent, outs);
114 ent = c;
115 if (free_ent < 1 << BITS) {
116 codetab[i] = free_ent++; // code -> hashtable
117 htab[i] = fcode;
118 }
119 else {
120 cl_block(outs);
121 }
122 }
123 // Put out the final code.
124 output(ent, outs);
125 output(EOFCode, outs);
126 }
127 function encode(outs) {
128 outs.writeByte(initCodeSize); // write "initial code size" byte
129 remaining = width * height; // reset navigation variables
130 curPixel = 0;
131 compress(initCodeSize + 1, outs); // compress and write the pixel data
132 outs.writeByte(0); // write block terminator
133 }
134 // Flush the packet to disk, and reset the accumulator
135 function flush_char(outs) {
136 if (a_count > 0) {
137 outs.writeByte(a_count);
138 outs.writeBytes(accum, 0, a_count);
139 a_count = 0;
140 }
141 }
142 function MAXCODE(n_bits) {
143 return (1 << n_bits) - 1;
144 }
145 // Return the next pixel from the image
146 function nextPixel() {
147 if (remaining === 0)
148 return EOF;
149 --remaining;
150 var pix = pixels[curPixel++];
151 return pix & 0xff;
152 }
153 function output(code, outs) {
154 cur_accum &= masks[cur_bits];
155 if (cur_bits > 0)
156 cur_accum |= (code << cur_bits);
157 else
158 cur_accum = code;
159 cur_bits += n_bits;
160 while (cur_bits >= 8) {
161 char_out((cur_accum & 0xff), outs);
162 cur_accum >>= 8;
163 cur_bits -= 8;
164 }
165 // If the next entry is going to be too big for the code size,
166 // then increase it, if possible.
167 if (free_ent > maxcode || clear_flg) {
168 if (clear_flg) {
169 maxcode = MAXCODE(n_bits = g_init_bits);
170 clear_flg = false;
171 }
172 else {
173 ++n_bits;
174 if (n_bits == BITS)
175 maxcode = 1 << BITS;
176 else
177 maxcode = MAXCODE(n_bits);
178 }
179 }
180 if (code == EOFCode) {
181 // At EOF, write the rest of the buffer.
182 while (cur_bits > 0) {
183 char_out((cur_accum & 0xff), outs);
184 cur_accum >>= 8;
185 cur_bits -= 8;
186 }
187 flush_char(outs);
188 }
189 }
190 this.encode = encode;
191 }
192 // module.exports = LZWEncoder;
193 export default LZWEncoder;
1 export default NeuQuant;
2 declare function NeuQuant(pixels: any, samplefac: any): void;
3 declare class NeuQuant {
4 constructor(pixels: any, samplefac: any);
5 buildColormap: () => void;
6 getColormap: () => any[];
7 lookupRGB: (b: any, g: any, r: any) => number;
8 }
1 /* NeuQuant Neural-Net Quantization Algorithm
2 * ------------------------------------------
3 *
4 * Copyright (c) 1994 Anthony Dekker
5 *
6 * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
7 * See "Kohonen neural networks for optimal colour quantization"
8 * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
9 * for a discussion of the algorithm.
10 * See also http://members.ozemail.com.au/~dekker/NEUQUANT.HTML
11 *
12 * Any party obtaining a copy of these files from the author, directly or
13 * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
14 * world-wide, paid up, royalty-free, nonexclusive right and license to deal
15 * in this software and documentation files (the "Software"), including without
16 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons who receive
18 * copies from any such party to do so, with the only requirement being
19 * that this copyright notice remain intact.
20 *
21 * (JavaScript port 2012 by Johan Nordberg)
22 */
23 function toInt(v) {
24 return ~~v;
25 }
26 var ncycles = 100; // number of learning cycles
27 var netsize = 256; // number of colors used
28 var maxnetpos = netsize - 1;
29 // defs for freq and bias
30 var netbiasshift = 4; // bias for colour values
31 var intbiasshift = 16; // bias for fractions
32 var intbias = (1 << intbiasshift);
33 var gammashift = 10;
34 var gamma = (1 << gammashift);
35 var betashift = 10;
36 var beta = (intbias >> betashift); /* beta = 1/1024 */
37 var betagamma = (intbias << (gammashift - betashift));
38 // defs for decreasing radius factor
39 var initrad = (netsize >> 3); // for 256 cols, radius starts
40 var radiusbiasshift = 6; // at 32.0 biased by 6 bits
41 var radiusbias = (1 << radiusbiasshift);
42 var initradius = (initrad * radiusbias); //and decreases by a
43 var radiusdec = 30; // factor of 1/30 each cycle
44 // defs for decreasing alpha factor
45 var alphabiasshift = 10; // alpha starts at 1.0
46 var initalpha = (1 << alphabiasshift);
47 var alphadec; // biased by 10 bits
48 /* radbias and alpharadbias used for radpower calculation */
49 var radbiasshift = 8;
50 var radbias = (1 << radbiasshift);
51 var alpharadbshift = (alphabiasshift + radbiasshift);
52 var alpharadbias = (1 << alpharadbshift);
53 // four primes near 500 - assume no image has a length so large that it is
54 // divisible by all four primes
55 var prime1 = 499;
56 var prime2 = 491;
57 var prime3 = 487;
58 var prime4 = 503;
59 var minpicturebytes = (3 * prime4);
60 /*
61 Constructor: NeuQuant
62
63 Arguments:
64
65 pixels - array of pixels in RGB format
66 samplefac - sampling factor 1 to 30 where lower is better quality
67
68 >
69 > pixels = [r, g, b, r, g, b, r, g, b, ..]
70 >
71 */
72 function NeuQuant(pixels, samplefac) {
73 var network; // int[netsize][4]
74 var netindex; // for network lookup - really 256
75 // bias and freq arrays for learning
76 var bias;
77 var freq;
78 var radpower;
79 /*
80 Private Method: init
81
82 sets up arrays
83 */
84 function init() {
85 network = [];
86 netindex = [];
87 bias = [];
88 freq = [];
89 radpower = [];
90 var i, v;
91 for (i = 0; i < netsize; i++) {
92 v = (i << (netbiasshift + 8)) / netsize;
93 network[i] = [v, v, v];
94 freq[i] = intbias / netsize;
95 bias[i] = 0;
96 }
97 }
98 /*
99 Private Method: unbiasnet
100
101 unbiases network to give byte values 0..255 and record position i to prepare for sort
102 */
103 function unbiasnet() {
104 for (var i = 0; i < netsize; i++) {
105 network[i][0] >>= netbiasshift;
106 network[i][1] >>= netbiasshift;
107 network[i][2] >>= netbiasshift;
108 network[i][3] = i; // record color number
109 }
110 }
111 /*
112 Private Method: altersingle
113
114 moves neuron *i* towards biased (b,g,r) by factor *alpha*
115 */
116 function altersingle(alpha, i, b, g, r) {
117 network[i][0] -= (alpha * (network[i][0] - b)) / initalpha;
118 network[i][1] -= (alpha * (network[i][1] - g)) / initalpha;
119 network[i][2] -= (alpha * (network[i][2] - r)) / initalpha;
120 }
121 /*
122 Private Method: alterneigh
123
124 moves neurons in *radius* around index *i* towards biased (b,g,r) by factor *alpha*
125 */
126 function alterneigh(radius, i, b, g, r) {
127 var lo = Math.abs(i - radius);
128 var hi = Math.min(i + radius, netsize);
129 var j = i + 1;
130 var k = i - 1;
131 var m = 1;
132 var p, a;
133 while ((j < hi) || (k > lo)) {
134 a = radpower[m++];
135 if (j < hi) {
136 p = network[j++];
137 p[0] -= (a * (p[0] - b)) / alpharadbias;
138 p[1] -= (a * (p[1] - g)) / alpharadbias;
139 p[2] -= (a * (p[2] - r)) / alpharadbias;
140 }
141 if (k > lo) {
142 p = network[k--];
143 p[0] -= (a * (p[0] - b)) / alpharadbias;
144 p[1] -= (a * (p[1] - g)) / alpharadbias;
145 p[2] -= (a * (p[2] - r)) / alpharadbias;
146 }
147 }
148 }
149 /*
150 Private Method: contest
151
152 searches for biased BGR values
153 */
154 function contest(b, g, r) {
155 /*
156 finds closest neuron (min dist) and updates freq
157 finds best neuron (min dist-bias) and returns position
158 for frequently chosen neurons, freq[i] is high and bias[i] is negative
159 bias[i] = gamma * ((1 / netsize) - freq[i])
160 */
161 var bestd = ~(1 << 31);
162 var bestbiasd = bestd;
163 var bestpos = -1;
164 var bestbiaspos = bestpos;
165 var i, n, dist, biasdist, betafreq;
166 for (i = 0; i < netsize; i++) {
167 n = network[i];
168 dist = Math.abs(n[0] - b) + Math.abs(n[1] - g) + Math.abs(n[2] - r);
169 if (dist < bestd) {
170 bestd = dist;
171 bestpos = i;
172 }
173 biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));
174 if (biasdist < bestbiasd) {
175 bestbiasd = biasdist;
176 bestbiaspos = i;
177 }
178 betafreq = (freq[i] >> betashift);
179 freq[i] -= betafreq;
180 bias[i] += (betafreq << gammashift);
181 }
182 freq[bestpos] += beta;
183 bias[bestpos] -= betagamma;
184 return bestbiaspos;
185 }
186 /*
187 Private Method: inxbuild
188
189 sorts network and builds netindex[0..255]
190 */
191 function inxbuild() {
192 var i, j, p, q, smallpos, smallval, previouscol = 0, startpos = 0;
193 for (i = 0; i < netsize; i++) {
194 p = network[i];
195 smallpos = i;
196 smallval = p[1]; // index on g
197 // find smallest in i..netsize-1
198 for (j = i + 1; j < netsize; j++) {
199 q = network[j];
200 if (q[1] < smallval) { // index on g
201 smallpos = j;
202 smallval = q[1]; // index on g
203 }
204 }
205 q = network[smallpos];
206 // swap p (i) and q (smallpos) entries
207 if (i != smallpos) {
208 j = q[0];
209 q[0] = p[0];
210 p[0] = j;
211 j = q[1];
212 q[1] = p[1];
213 p[1] = j;
214 j = q[2];
215 q[2] = p[2];
216 p[2] = j;
217 j = q[3];
218 q[3] = p[3];
219 p[3] = j;
220 }
221 // smallval entry is now in position i
222 if (smallval != previouscol) {
223 netindex[previouscol] = (startpos + i) >> 1;
224 for (j = previouscol + 1; j < smallval; j++)
225 netindex[j] = i;
226 previouscol = smallval;
227 startpos = i;
228 }
229 }
230 netindex[previouscol] = (startpos + maxnetpos) >> 1;
231 for (j = previouscol + 1; j < 256; j++)
232 netindex[j] = maxnetpos; // really 256
233 }
234 /*
235 Private Method: inxsearch
236
237 searches for BGR values 0..255 and returns a color index
238 */
239 function inxsearch(b, g, r) {
240 var a, p, dist;
241 var bestd = 1000; // biggest possible dist is 256*3
242 var best = -1;
243 var i = netindex[g]; // index on g
244 var j = i - 1; // start at netindex[g] and work outwards
245 while ((i < netsize) || (j >= 0)) {
246 if (i < netsize) {
247 p = network[i];
248 dist = p[1] - g; // inx key
249 if (dist >= bestd)
250 i = netsize; // stop iter
251 else {
252 i++;
253 if (dist < 0)
254 dist = -dist;
255 a = p[0] - b;
256 if (a < 0)
257 a = -a;
258 dist += a;
259 if (dist < bestd) {
260 a = p[2] - r;
261 if (a < 0)
262 a = -a;
263 dist += a;
264 if (dist < bestd) {
265 bestd = dist;
266 best = p[3];
267 }
268 }
269 }
270 }
271 if (j >= 0) {
272 p = network[j];
273 dist = g - p[1]; // inx key - reverse dif
274 if (dist >= bestd)
275 j = -1; // stop iter
276 else {
277 j--;
278 if (dist < 0)
279 dist = -dist;
280 a = p[0] - b;
281 if (a < 0)
282 a = -a;
283 dist += a;
284 if (dist < bestd) {
285 a = p[2] - r;
286 if (a < 0)
287 a = -a;
288 dist += a;
289 if (dist < bestd) {
290 bestd = dist;
291 best = p[3];
292 }
293 }
294 }
295 }
296 }
297 return best;
298 }
299 /*
300 Private Method: learn
301
302 "Main Learning Loop"
303 */
304 function learn() {
305 var i;
306 var lengthcount = pixels.length;
307 var alphadec = toInt(30 + ((samplefac - 1) / 3));
308 var samplepixels = toInt(lengthcount / (3 * samplefac));
309 var delta = toInt(samplepixels / ncycles);
310 var alpha = initalpha;
311 var radius = initradius;
312 var rad = radius >> radiusbiasshift;
313 if (rad <= 1)
314 rad = 0;
315 for (i = 0; i < rad; i++)
316 radpower[i] = toInt(alpha * (((rad * rad - i * i) * radbias) / (rad * rad)));
317 var step;
318 if (lengthcount < minpicturebytes) {
319 samplefac = 1;
320 step = 3;
321 }
322 else if ((lengthcount % prime1) !== 0) {
323 step = 3 * prime1;
324 }
325 else if ((lengthcount % prime2) !== 0) {
326 step = 3 * prime2;
327 }
328 else if ((lengthcount % prime3) !== 0) {
329 step = 3 * prime3;
330 }
331 else {
332 step = 3 * prime4;
333 }
334 var b, g, r, j;
335 var pix = 0; // current pixel
336 i = 0;
337 while (i < samplepixels) {
338 b = (pixels[pix] & 0xff) << netbiasshift;
339 g = (pixels[pix + 1] & 0xff) << netbiasshift;
340 r = (pixels[pix + 2] & 0xff) << netbiasshift;
341 j = contest(b, g, r);
342 altersingle(alpha, j, b, g, r);
343 if (rad !== 0)
344 alterneigh(rad, j, b, g, r); // alter neighbours
345 pix += step;
346 if (pix >= lengthcount)
347 pix -= lengthcount;
348 i++;
349 if (delta === 0)
350 delta = 1;
351 if (i % delta === 0) {
352 alpha -= alpha / alphadec;
353 radius -= radius / radiusdec;
354 rad = radius >> radiusbiasshift;
355 if (rad <= 1)
356 rad = 0;
357 for (j = 0; j < rad; j++)
358 radpower[j] = toInt(alpha * (((rad * rad - j * j) * radbias) / (rad * rad)));
359 }
360 }
361 }
362 /*
363 Method: buildColormap
364
365 1. initializes network
366 2. trains it
367 3. removes misconceptions
368 4. builds colorindex
369 */
370 function buildColormap() {
371 init();
372 learn();
373 unbiasnet();
374 inxbuild();
375 }
376 this.buildColormap = buildColormap;
377 /*
378 Method: getColormap
379
380 builds colormap from the index
381
382 returns array in the format:
383
384 >
385 > [r, g, b, r, g, b, r, g, b, ..]
386 >
387 */
388 function getColormap() {
389 var map = [];
390 var index = [];
391 for (var i = 0; i < netsize; i++)
392 index[network[i][3]] = i;
393 var k = 0;
394 for (var l = 0; l < netsize; l++) {
395 var j = index[l];
396 map[k++] = (network[j][0]);
397 map[k++] = (network[j][1]);
398 map[k++] = (network[j][2]);
399 }
400 return map;
401 }
402 this.getColormap = getColormap;
403 /*
404 Method: lookupRGB
405
406 looks for the closest *r*, *g*, *b* color in the map and
407 returns its index
408 */
409 this.lookupRGB = inxsearch;
410 }
411 // module.exports = NeuQuant;
412 export default NeuQuant;
1 export default NeuQuant;
2 declare function NeuQuant(pixels: any, samplefac: any): void;
3 declare class NeuQuant {
4 constructor(pixels: any, samplefac: any);
5 buildColormap: () => void;
6 getColormap: () => any[];
7 lookupRGB: (b: any, g: any, r: any) => number;
8 }
1 /* NeuQuant Neural-Net Quantization Algorithm
2 * ------------------------------------------
3 *
4 * Copyright (c) 1994 Anthony Dekker
5 *
6 * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
7 * See "Kohonen neural networks for optimal colour quantization"
8 * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
9 * for a discussion of the algorithm.
10 * See also http://members.ozemail.com.au/~dekker/NEUQUANT.HTML
11 *
12 * Any party obtaining a copy of these files from the author, directly or
13 * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
14 * world-wide, paid up, royalty-free, nonexclusive right and license to deal
15 * in this software and documentation files (the "Software"), including without
16 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons who receive
18 * copies from any such party to do so, with the only requirement being
19 * that this copyright notice remain intact.
20 *
21 * (JavaScript port 2012 by Johan Nordberg)
22 */
23 var ncycles = 100; // number of learning cycles
24 var netsize = 256; // number of colors used
25 var maxnetpos = netsize - 1;
26 // defs for freq and bias
27 var netbiasshift = 4; // bias for colour values
28 var intbiasshift = 16; // bias for fractions
29 var intbias = (1 << intbiasshift);
30 var gammashift = 10;
31 var gamma = (1 << gammashift);
32 var betashift = 10;
33 var beta = (intbias >> betashift); /* beta = 1/1024 */
34 var betagamma = (intbias << (gammashift - betashift));
35 // defs for decreasing radius factor
36 var initrad = (netsize >> 3); // for 256 cols, radius starts
37 var radiusbiasshift = 6; // at 32.0 biased by 6 bits
38 var radiusbias = (1 << radiusbiasshift);
39 var initradius = (initrad * radiusbias); //and decreases by a
40 var radiusdec = 30; // factor of 1/30 each cycle
41 // defs for decreasing alpha factor
42 var alphabiasshift = 10; // alpha starts at 1.0
43 var initalpha = (1 << alphabiasshift);
44 var alphadec; // biased by 10 bits
45 /* radbias and alpharadbias used for radpower calculation */
46 var radbiasshift = 8;
47 var radbias = (1 << radbiasshift);
48 var alpharadbshift = (alphabiasshift + radbiasshift);
49 var alpharadbias = (1 << alpharadbshift);
50 // four primes near 500 - assume no image has a length so large that it is
51 // divisible by all four primes
52 var prime1 = 499;
53 var prime2 = 491;
54 var prime3 = 487;
55 var prime4 = 503;
56 var minpicturebytes = (3 * prime4);
57 /*
58 Constructor: NeuQuant
59
60 Arguments:
61
62 pixels - array of pixels in RGB format
63 samplefac - sampling factor 1 to 30 where lower is better quality
64
65 >
66 > pixels = [r, g, b, r, g, b, r, g, b, ..]
67 >
68 */
69 function NeuQuant(pixels, samplefac) {
70 var network; // int[netsize][4]
71 var netindex; // for network lookup - really 256
72 // bias and freq arrays for learning
73 var bias;
74 var freq;
75 var radpower;
76 /*
77 Private Method: init
78
79 sets up arrays
80 */
81 function init() {
82 network = [];
83 netindex = new Int32Array(256);
84 bias = new Int32Array(netsize);
85 freq = new Int32Array(netsize);
86 radpower = new Int32Array(netsize >> 3);
87 var i, v;
88 for (i = 0; i < netsize; i++) {
89 v = (i << (netbiasshift + 8)) / netsize;
90 network[i] = new Float64Array([v, v, v, 0]);
91 //network[i] = [v, v, v, 0]
92 freq[i] = intbias / netsize;
93 bias[i] = 0;
94 }
95 }
96 /*
97 Private Method: unbiasnet
98
99 unbiases network to give byte values 0..255 and record position i to prepare for sort
100 */
101 function unbiasnet() {
102 for (var i = 0; i < netsize; i++) {
103 network[i][0] >>= netbiasshift;
104 network[i][1] >>= netbiasshift;
105 network[i][2] >>= netbiasshift;
106 network[i][3] = i; // record color number
107 }
108 }
109 /*
110 Private Method: altersingle
111
112 moves neuron *i* towards biased (b,g,r) by factor *alpha*
113 */
114 function altersingle(alpha, i, b, g, r) {
115 network[i][0] -= (alpha * (network[i][0] - b)) / initalpha;
116 network[i][1] -= (alpha * (network[i][1] - g)) / initalpha;
117 network[i][2] -= (alpha * (network[i][2] - r)) / initalpha;
118 }
119 /*
120 Private Method: alterneigh
121
122 moves neurons in *radius* around index *i* towards biased (b,g,r) by factor *alpha*
123 */
124 function alterneigh(radius, i, b, g, r) {
125 var lo = Math.abs(i - radius);
126 var hi = Math.min(i + radius, netsize);
127 var j = i + 1;
128 var k = i - 1;
129 var m = 1;
130 var p, a;
131 while ((j < hi) || (k > lo)) {
132 a = radpower[m++];
133 if (j < hi) {
134 p = network[j++];
135 p[0] -= (a * (p[0] - b)) / alpharadbias;
136 p[1] -= (a * (p[1] - g)) / alpharadbias;
137 p[2] -= (a * (p[2] - r)) / alpharadbias;
138 }
139 if (k > lo) {
140 p = network[k--];
141 p[0] -= (a * (p[0] - b)) / alpharadbias;
142 p[1] -= (a * (p[1] - g)) / alpharadbias;
143 p[2] -= (a * (p[2] - r)) / alpharadbias;
144 }
145 }
146 }
147 /*
148 Private Method: contest
149
150 searches for biased BGR values
151 */
152 function contest(b, g, r) {
153 /*
154 finds closest neuron (min dist) and updates freq
155 finds best neuron (min dist-bias) and returns position
156 for frequently chosen neurons, freq[i] is high and bias[i] is negative
157 bias[i] = gamma * ((1 / netsize) - freq[i])
158 */
159 var bestd = ~(1 << 31);
160 var bestbiasd = bestd;
161 var bestpos = -1;
162 var bestbiaspos = bestpos;
163 var i, n, dist, biasdist, betafreq;
164 for (i = 0; i < netsize; i++) {
165 n = network[i];
166 dist = Math.abs(n[0] - b) + Math.abs(n[1] - g) + Math.abs(n[2] - r);
167 if (dist < bestd) {
168 bestd = dist;
169 bestpos = i;
170 }
171 biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));
172 if (biasdist < bestbiasd) {
173 bestbiasd = biasdist;
174 bestbiaspos = i;
175 }
176 betafreq = (freq[i] >> betashift);
177 freq[i] -= betafreq;
178 bias[i] += (betafreq << gammashift);
179 }
180 freq[bestpos] += beta;
181 bias[bestpos] -= betagamma;
182 return bestbiaspos;
183 }
184 /*
185 Private Method: inxbuild
186
187 sorts network and builds netindex[0..255]
188 */
189 function inxbuild() {
190 var i, j, p, q, smallpos, smallval, previouscol = 0, startpos = 0;
191 for (i = 0; i < netsize; i++) {
192 p = network[i];
193 smallpos = i;
194 smallval = p[1]; // index on g
195 // find smallest in i..netsize-1
196 for (j = i + 1; j < netsize; j++) {
197 q = network[j];
198 if (q[1] < smallval) { // index on g
199 smallpos = j;
200 smallval = q[1]; // index on g
201 }
202 }
203 q = network[smallpos];
204 // swap p (i) and q (smallpos) entries
205 if (i != smallpos) {
206 j = q[0];
207 q[0] = p[0];
208 p[0] = j;
209 j = q[1];
210 q[1] = p[1];
211 p[1] = j;
212 j = q[2];
213 q[2] = p[2];
214 p[2] = j;
215 j = q[3];
216 q[3] = p[3];
217 p[3] = j;
218 }
219 // smallval entry is now in position i
220 if (smallval != previouscol) {
221 netindex[previouscol] = (startpos + i) >> 1;
222 for (j = previouscol + 1; j < smallval; j++)
223 netindex[j] = i;
224 previouscol = smallval;
225 startpos = i;
226 }
227 }
228 netindex[previouscol] = (startpos + maxnetpos) >> 1;
229 for (j = previouscol + 1; j < 256; j++)
230 netindex[j] = maxnetpos; // really 256
231 }
232 /*
233 Private Method: inxsearch
234
235 searches for BGR values 0..255 and returns a color index
236 */
237 function inxsearch(b, g, r) {
238 var a, p, dist;
239 var bestd = 1000; // biggest possible dist is 256*3
240 var best = -1;
241 var i = netindex[g]; // index on g
242 var j = i - 1; // start at netindex[g] and work outwards
243 while ((i < netsize) || (j >= 0)) {
244 if (i < netsize) {
245 p = network[i];
246 dist = p[1] - g; // inx key
247 if (dist >= bestd)
248 i = netsize; // stop iter
249 else {
250 i++;
251 if (dist < 0)
252 dist = -dist;
253 a = p[0] - b;
254 if (a < 0)
255 a = -a;
256 dist += a;
257 if (dist < bestd) {
258 a = p[2] - r;
259 if (a < 0)
260 a = -a;
261 dist += a;
262 if (dist < bestd) {
263 bestd = dist;
264 best = p[3];
265 }
266 }
267 }
268 }
269 if (j >= 0) {
270 p = network[j];
271 dist = g - p[1]; // inx key - reverse dif
272 if (dist >= bestd)
273 j = -1; // stop iter
274 else {
275 j--;
276 if (dist < 0)
277 dist = -dist;
278 a = p[0] - b;
279 if (a < 0)
280 a = -a;
281 dist += a;
282 if (dist < bestd) {
283 a = p[2] - r;
284 if (a < 0)
285 a = -a;
286 dist += a;
287 if (dist < bestd) {
288 bestd = dist;
289 best = p[3];
290 }
291 }
292 }
293 }
294 }
295 return best;
296 }
297 /*
298 Private Method: learn
299
300 "Main Learning Loop"
301 */
302 function learn() {
303 var i;
304 var lengthcount = pixels.length;
305 var alphadec = 30 + ((samplefac - 1) / 3);
306 var samplepixels = lengthcount / (3 * samplefac);
307 var delta = ~~(samplepixels / ncycles);
308 var alpha = initalpha;
309 var radius = initradius;
310 var rad = radius >> radiusbiasshift;
311 if (rad <= 1)
312 rad = 0;
313 for (i = 0; i < rad; i++)
314 radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad));
315 var step;
316 if (lengthcount < minpicturebytes) {
317 samplefac = 1;
318 step = 3;
319 }
320 else if ((lengthcount % prime1) !== 0) {
321 step = 3 * prime1;
322 }
323 else if ((lengthcount % prime2) !== 0) {
324 step = 3 * prime2;
325 }
326 else if ((lengthcount % prime3) !== 0) {
327 step = 3 * prime3;
328 }
329 else {
330 step = 3 * prime4;
331 }
332 var b, g, r, j;
333 var pix = 0; // current pixel
334 i = 0;
335 while (i < samplepixels) {
336 b = (pixels[pix] & 0xff) << netbiasshift;
337 g = (pixels[pix + 1] & 0xff) << netbiasshift;
338 r = (pixels[pix + 2] & 0xff) << netbiasshift;
339 j = contest(b, g, r);
340 altersingle(alpha, j, b, g, r);
341 if (rad !== 0)
342 alterneigh(rad, j, b, g, r); // alter neighbours
343 pix += step;
344 if (pix >= lengthcount)
345 pix -= lengthcount;
346 i++;
347 if (delta === 0)
348 delta = 1;
349 if (i % delta === 0) {
350 alpha -= alpha / alphadec;
351 radius -= radius / radiusdec;
352 rad = radius >> radiusbiasshift;
353 if (rad <= 1)
354 rad = 0;
355 for (j = 0; j < rad; j++)
356 radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad));
357 }
358 }
359 }
360 /*
361 Method: buildColormap
362
363 1. initializes network
364 2. trains it
365 3. removes misconceptions
366 4. builds colorindex
367 */
368 function buildColormap() {
369 init();
370 learn();
371 unbiasnet();
372 inxbuild();
373 }
374 this.buildColormap = buildColormap;
375 /*
376 Method: getColormap
377
378 builds colormap from the index
379
380 returns array in the format:
381
382 >
383 > [r, g, b, r, g, b, r, g, b, ..]
384 >
385 */
386 function getColormap() {
387 var map = [];
388 var index = [];
389 for (var i = 0; i < netsize; i++)
390 index[network[i][3]] = i;
391 var k = 0;
392 for (var l = 0; l < netsize; l++) {
393 var j = index[l];
394 map[k++] = (network[j][0]);
395 map[k++] = (network[j][1]);
396 map[k++] = (network[j][2]);
397 }
398 return map;
399 }
400 this.getColormap = getColormap;
401 /*
402 Method: lookupRGB
403
404 looks for the closest *r*, *g*, *b* color in the map and
405 returns its index
406 */
407 this.lookupRGB = inxsearch;
408 }
409 // module.exports = NeuQuant;
410 export default NeuQuant;
1 export function deinterlace(pixels: any, width: any): any[];
1 /**
2 * Deinterlace function from https://github.com/shachaf/jsgif
3 */
4 export const deinterlace = (pixels, width) => {
5 const newPixels = new Array(pixels.length);
6 const rows = pixels.length / width;
7 const cpRow = function (toRow, fromRow) {
8 const fromPixels = pixels.slice(fromRow * width, (fromRow + 1) * width);
9 newPixels.splice.apply(newPixels, [toRow * width, width].concat(fromPixels));
10 };
11 // See appendix E.
12 const offsets = [0, 4, 2, 1];
13 const steps = [8, 8, 4, 2];
14 var fromRow = 0;
15 for (var pass = 0; pass < 4; pass++) {
16 for (var toRow = offsets[pass]; toRow < rows; toRow += steps[pass]) {
17 cpRow(toRow, fromRow);
18 fromRow++;
19 }
20 }
21 return newPixels;
22 };
1 export function parseGIF(arrayBuffer: any): any;
2 export function decompressFrame(frame: any, gct: any, buildImagePatch: any): {
3 pixels: any[];
4 dims: {
5 top: any;
6 left: any;
7 width: any;
8 height: any;
9 };
10 } | undefined;
11 export function decompressFrames(parsedGif: any, buildImagePatches: any): any;
1 import GIF from 'js-binary-schema-parser/src/schemas/gif';
2 import { parse } from 'js-binary-schema-parser/src/index';
3 import { buildStream } from 'js-binary-schema-parser/src/parsers/uint8';
4 import { deinterlace } from './deinterlace';
5 import { lzw } from './lzw';
6 export const parseGIF = arrayBuffer => {
7 const byteData = new Uint8Array(arrayBuffer);
8 return parse(buildStream(byteData), GIF);
9 };
10 const generatePatch = image => {
11 const totalPixels = image.pixels.length;
12 const patchData = new Uint8ClampedArray(totalPixels * 4);
13 for (var i = 0; i < totalPixels; i++) {
14 const pos = i * 4;
15 const colorIndex = image.pixels[i];
16 const color = image.colorTable[colorIndex];
17 patchData[pos] = color[0];
18 patchData[pos + 1] = color[1];
19 patchData[pos + 2] = color[2];
20 patchData[pos + 3] = colorIndex !== image.transparentIndex ? 255 : 0;
21 }
22 return patchData;
23 };
24 export const decompressFrame = (frame, gct, buildImagePatch) => {
25 if (!frame.image) {
26 console.warn('gif frame does not have associated image.');
27 return;
28 }
29 const { image } = frame;
30 // get the number of pixels
31 const totalPixels = image.descriptor.width * image.descriptor.height;
32 // do lzw decompression
33 var pixels = lzw(image.data.minCodeSize, image.data.blocks, totalPixels);
34 // deal with interlacing if necessary
35 if (image.descriptor.lct.interlaced) {
36 pixels = deinterlace(pixels, image.descriptor.width);
37 }
38 const resultImage = {
39 pixels: pixels,
40 dims: {
41 top: frame.image.descriptor.top,
42 left: frame.image.descriptor.left,
43 width: frame.image.descriptor.width,
44 height: frame.image.descriptor.height
45 }
46 };
47 // color table
48 if (image.descriptor.lct && image.descriptor.lct.exists) {
49 resultImage.colorTable = image.lct;
50 }
51 else {
52 resultImage.colorTable = gct;
53 }
54 // add per frame relevant gce information
55 if (frame.gce) {
56 resultImage.delay = (frame.gce.delay || 10) * 10; // convert to ms
57 resultImage.disposalType = frame.gce.extras.disposal;
58 // transparency
59 if (frame.gce.extras.transparentColorGiven) {
60 resultImage.transparentIndex = frame.gce.transparentColorIndex;
61 }
62 }
63 // create canvas usable imagedata if desired
64 if (buildImagePatch) {
65 resultImage.patch = generatePatch(resultImage);
66 }
67 return resultImage;
68 };
69 export const decompressFrames = (parsedGif, buildImagePatches) => {
70 return parsedGif.frames
71 .filter(f => f.image)
72 .map(f => decompressFrame(f, parsedGif.gct, buildImagePatches));
73 };
1 export function lzw(minCodeSize: any, data: any, pixelCount: any): any[];
1 /**
2 * javascript port of java LZW decompression
3 * Original java author url: https://gist.github.com/devunwired/4479231
4 */
5 export const lzw = (minCodeSize, data, pixelCount) => {
6 const MAX_STACK_SIZE = 4096;
7 const nullCode = -1;
8 const npix = pixelCount;
9 var available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, i, datum, data_size, first, top, bi, pi;
10 const dstPixels = new Array(pixelCount);
11 const prefix = new Array(MAX_STACK_SIZE);
12 const suffix = new Array(MAX_STACK_SIZE);
13 const pixelStack = new Array(MAX_STACK_SIZE + 1);
14 // Initialize GIF data stream decoder.
15 data_size = minCodeSize;
16 clear = 1 << data_size;
17 end_of_information = clear + 1;
18 available = clear + 2;
19 old_code = nullCode;
20 code_size = data_size + 1;
21 code_mask = (1 << code_size) - 1;
22 for (code = 0; code < clear; code++) {
23 prefix[code] = 0;
24 suffix[code] = code;
25 }
26 // Decode GIF pixel stream.
27 var datum, bits, count, first, top, pi, bi;
28 datum = bits = count = first = top = pi = bi = 0;
29 for (i = 0; i < npix;) {
30 if (top === 0) {
31 if (bits < code_size) {
32 // get the next byte
33 datum += data[bi] << bits;
34 bits += 8;
35 bi++;
36 continue;
37 }
38 // Get the next code.
39 code = datum & code_mask;
40 datum >>= code_size;
41 bits -= code_size;
42 // Interpret the code
43 if (code > available || code == end_of_information) {
44 break;
45 }
46 if (code == clear) {
47 // Reset decoder.
48 code_size = data_size + 1;
49 code_mask = (1 << code_size) - 1;
50 available = clear + 2;
51 old_code = nullCode;
52 continue;
53 }
54 if (old_code == nullCode) {
55 pixelStack[top++] = suffix[code];
56 old_code = code;
57 first = code;
58 continue;
59 }
60 in_code = code;
61 if (code == available) {
62 pixelStack[top++] = first;
63 code = old_code;
64 }
65 while (code > clear) {
66 pixelStack[top++] = suffix[code];
67 code = prefix[code];
68 }
69 first = suffix[code] & 0xff;
70 pixelStack[top++] = first;
71 // add a new string to the table, but only if space is available
72 // if not, just continue with current table until a clear code is found
73 // (deferred clear code implementation as per GIF spec)
74 if (available < MAX_STACK_SIZE) {
75 prefix[available] = old_code;
76 suffix[available] = first;
77 available++;
78 if ((available & code_mask) === 0 && available < MAX_STACK_SIZE) {
79 code_size++;
80 code_mask += available;
81 }
82 }
83 old_code = in_code;
84 }
85 // Pop a pixel off the pixel stack.
86 top--;
87 dstPixels[pi++] = pixelStack[top];
88 i++;
89 }
90 for (i = pi; i < npix; i++) {
91 dstPixels[i] = 0; // clear missing pixels
92 }
93 return dstPixels;
94 };
1 export * from "./qrcode";
2 export { AwesomeQR, Options } from "./awesome-qr";
1 export * from "./qrcode";
2 export { AwesomeQR } from "./awesome-qr";
1 declare class QR8bitByte {
2 mode: number;
3 data: string;
4 parsedData: number[];
5 constructor(data: string);
6 getLength(): number;
7 write(buffer: QRBitBuffer): void;
8 }
9 export declare class QRCodeModel {
10 typeNumber: number;
11 errorCorrectLevel: number;
12 modules?: (boolean | null)[][];
13 moduleCount: number;
14 dataCache?: number[];
15 dataList: QR8bitByte[];
16 maskPattern?: number;
17 constructor(typeNumber?: number, errorCorrectLevel?: number);
18 addData(data: string): void;
19 isDark(row: number, col: number): boolean | null;
20 getModuleCount(): number;
21 make(): void;
22 makeImpl(test: boolean, maskPattern: number): void;
23 setupPositionProbePattern(row: number, col: number): void;
24 getBestMaskPattern(): number;
25 setupTimingPattern(): void;
26 setupPositionAdjustPattern(): void;
27 setupTypeNumber(test: boolean): void;
28 setupTypeInfo(test: boolean, maskPattern: number): void;
29 mapData(data: number[], maskPattern: number): void;
30 static PAD0: number;
31 static PAD1: number;
32 static createData(typeNumber: number, errorCorrectLevel: number, dataList: QR8bitByte[]): number[];
33 static createBytes(buffer: QRBitBuffer, rsBlocks: QRRSBlock[]): number[];
34 }
35 export declare const QRErrorCorrectLevel: {
36 L: number;
37 M: number;
38 Q: number;
39 H: number;
40 };
41 export declare const QRMaskPattern: {
42 PATTERN000: number;
43 PATTERN001: number;
44 PATTERN010: number;
45 PATTERN011: number;
46 PATTERN100: number;
47 PATTERN101: number;
48 PATTERN110: number;
49 PATTERN111: number;
50 };
51 export declare class QRUtil {
52 static PATTERN_POSITION_TABLE: number[][];
53 static G15: number;
54 static G18: number;
55 static G15_MASK: number;
56 static getBCHTypeInfo(data: number): number;
57 static getBCHTypeNumber(data: number): number;
58 static getBCHDigit(data: number): number;
59 static getPatternPosition(typeNumber: number): number[];
60 static getMask(maskPattern: number, i: number, j: number): boolean;
61 static getErrorCorrectPolynomial(errorCorrectLength: number): QRPolynomial;
62 static getLengthInBits(mode: number, type: number): 14 | 11 | 12 | 8 | 10 | 9 | 16 | 13;
63 static getLostPoint(qrCode: QRCodeModel): number;
64 }
65 export declare class QRMath {
66 static glog(n: number): any;
67 static gexp(n: number): any;
68 static EXP_TABLE: any[];
69 static LOG_TABLE: any[];
70 static _constructor: void;
71 }
72 declare class QRPolynomial {
73 num: number[];
74 constructor(num: number[], shift: number);
75 get(index: number): number;
76 getLength(): number;
77 multiply(e: QRPolynomial): QRPolynomial;
78 mod(e: QRPolynomial): QRPolynomial;
79 }
80 declare class QRRSBlock {
81 totalCount: number;
82 dataCount: number;
83 constructor(totalCount: number, dataCount: number);
84 static RS_BLOCK_TABLE: number[][];
85 static getRSBlocks(typeNumber: number, errorCorrectLevel: number): QRRSBlock[];
86 static getRsBlockTable(typeNumber: number, errorCorrectLevel: number): number[] | undefined;
87 }
88 declare class QRBitBuffer {
89 buffer: number[];
90 length: number;
91 constructor();
92 get(index: number): boolean;
93 put(num: number, length: number): void;
94 getLengthInBits(): number;
95 putBit(bit: boolean): void;
96 }
97 export {};
1 //---------------------------------------------------------------------
2 // QRCode for JavaScript
3 //
4 // Copyright (c) 2009 Kazuhiko Arase
5 // Re-written in TypeScript by Makito <sumimakito@hotmail.com>
6 //
7 // URL: http://www.d-project.com/
8 //
9 // Licensed under the MIT license:
10 // http://www.opensource.org/licenses/mit-license.php
11 //
12 // The word "QR Code" is registered trademark of
13 // DENSO WAVE INCORPORATED
14 // http://www.denso-wave.com/qrcode/faqpatent-e.html
15 //
16 //---------------------------------------------------------------------
17 function checkQRVersion(version, sText, nCorrectLevel) {
18 const length = _getUTF8Length(sText);
19 const i = version - 1;
20 let nLimit = 0;
21 switch (nCorrectLevel) {
22 case QRErrorCorrectLevel.L:
23 nLimit = QRCodeLimitLength[i][0];
24 break;
25 case QRErrorCorrectLevel.M:
26 nLimit = QRCodeLimitLength[i][1];
27 break;
28 case QRErrorCorrectLevel.Q:
29 nLimit = QRCodeLimitLength[i][2];
30 break;
31 case QRErrorCorrectLevel.H:
32 nLimit = QRCodeLimitLength[i][3];
33 break;
34 }
35 return length <= nLimit;
36 }
37 function _getTypeNumber(sText, nCorrectLevel) {
38 var nType = 1;
39 var length = _getUTF8Length(sText);
40 for (var i = 0, len = QRCodeLimitLength.length; i < len; i++) {
41 var nLimit = 0;
42 switch (nCorrectLevel) {
43 case QRErrorCorrectLevel.L:
44 nLimit = QRCodeLimitLength[i][0];
45 break;
46 case QRErrorCorrectLevel.M:
47 nLimit = QRCodeLimitLength[i][1];
48 break;
49 case QRErrorCorrectLevel.Q:
50 nLimit = QRCodeLimitLength[i][2];
51 break;
52 case QRErrorCorrectLevel.H:
53 nLimit = QRCodeLimitLength[i][3];
54 break;
55 }
56 if (length <= nLimit) {
57 break;
58 }
59 else {
60 nType++;
61 }
62 }
63 if (nType > QRCodeLimitLength.length) {
64 throw new Error("Too long data");
65 }
66 return nType;
67 }
68 function _getUTF8Length(sText) {
69 var replacedText = encodeURI(sText)
70 .toString()
71 .replace(/\%[0-9a-fA-F]{2}/g, "a");
72 return replacedText.length + (replacedText.length != Number(sText) ? 3 : 0);
73 }
74 class QR8bitByte {
75 constructor(data) {
76 this.mode = QRMode.MODE_8BIT_BYTE;
77 this.parsedData = [];
78 this.data = data;
79 const byteArrays = [];
80 // Added to support UTF-8 Characters
81 for (let i = 0, l = this.data.length; i < l; i++) {
82 const byteArray = [];
83 const code = this.data.charCodeAt(i);
84 if (code > 0x10000) {
85 byteArray[0] = 0xf0 | ((code & 0x1c0000) >>> 18);
86 byteArray[1] = 0x80 | ((code & 0x3f000) >>> 12);
87 byteArray[2] = 0x80 | ((code & 0xfc0) >>> 6);
88 byteArray[3] = 0x80 | (code & 0x3f);
89 }
90 else if (code > 0x800) {
91 byteArray[0] = 0xe0 | ((code & 0xf000) >>> 12);
92 byteArray[1] = 0x80 | ((code & 0xfc0) >>> 6);
93 byteArray[2] = 0x80 | (code & 0x3f);
94 }
95 else if (code > 0x80) {
96 byteArray[0] = 0xc0 | ((code & 0x7c0) >>> 6);
97 byteArray[1] = 0x80 | (code & 0x3f);
98 }
99 else {
100 byteArray[0] = code;
101 }
102 byteArrays.push(byteArray);
103 }
104 this.parsedData = Array.prototype.concat.apply([], byteArrays);
105 if (this.parsedData.length != this.data.length) {
106 this.parsedData.unshift(191);
107 this.parsedData.unshift(187);
108 this.parsedData.unshift(239);
109 }
110 }
111 getLength() {
112 return this.parsedData.length;
113 }
114 write(buffer) {
115 for (let i = 0, l = this.parsedData.length; i < l; i++) {
116 buffer.put(this.parsedData[i], 8);
117 }
118 }
119 }
120 export class QRCodeModel {
121 constructor(typeNumber = -1, errorCorrectLevel = QRErrorCorrectLevel.L) {
122 this.moduleCount = 0;
123 this.dataList = [];
124 this.typeNumber = typeNumber;
125 this.errorCorrectLevel = errorCorrectLevel;
126 this.moduleCount = 0;
127 this.dataList = [];
128 }
129 addData(data) {
130 if (this.typeNumber <= 0) {
131 this.typeNumber = _getTypeNumber(data, this.errorCorrectLevel);
132 }
133 else if (this.typeNumber > 40) {
134 throw new Error(`Invalid QR version: ${this.typeNumber}`);
135 }
136 else {
137 if (!checkQRVersion(this.typeNumber, data, this.errorCorrectLevel)) {
138 throw new Error(`Data is too long for QR version: ${this.typeNumber}`);
139 }
140 }
141 const newData = new QR8bitByte(data);
142 this.dataList.push(newData);
143 this.dataCache = undefined;
144 }
145 isDark(row, col) {
146 if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
147 throw new Error(`${row},${col}`);
148 }
149 return this.modules[row][col];
150 }
151 getModuleCount() {
152 return this.moduleCount;
153 }
154 make() {
155 this.makeImpl(false, this.getBestMaskPattern());
156 }
157 makeImpl(test, maskPattern) {
158 this.moduleCount = this.typeNumber * 4 + 17;
159 this.modules = new Array(this.moduleCount);
160 for (let row = 0; row < this.moduleCount; row++) {
161 this.modules[row] = new Array(this.moduleCount);
162 for (let col = 0; col < this.moduleCount; col++) {
163 this.modules[row][col] = null;
164 }
165 }
166 this.setupPositionProbePattern(0, 0);
167 this.setupPositionProbePattern(this.moduleCount - 7, 0);
168 this.setupPositionProbePattern(0, this.moduleCount - 7);
169 this.setupPositionAdjustPattern();
170 this.setupTimingPattern();
171 this.setupTypeInfo(test, maskPattern);
172 if (this.typeNumber >= 7) {
173 this.setupTypeNumber(test);
174 }
175 if (this.dataCache == null) {
176 this.dataCache = QRCodeModel.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
177 }
178 this.mapData(this.dataCache, maskPattern);
179 }
180 setupPositionProbePattern(row, col) {
181 for (let r = -1; r <= 7; r++) {
182 if (row + r <= -1 || this.moduleCount <= row + r)
183 continue;
184 for (let c = -1; c <= 7; c++) {
185 if (col + c <= -1 || this.moduleCount <= col + c)
186 continue;
187 if ((0 <= r && r <= 6 && (c == 0 || c == 6)) ||
188 (0 <= c && c <= 6 && (r == 0 || r == 6)) ||
189 (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
190 this.modules[row + r][col + c] = true;
191 }
192 else {
193 this.modules[row + r][col + c] = false;
194 }
195 }
196 }
197 }
198 getBestMaskPattern() {
199 if (Number.isInteger(this.maskPattern) && Object.values(QRMaskPattern).includes(this.maskPattern)) {
200 return this.maskPattern;
201 }
202 let minLostPoint = 0;
203 let pattern = 0;
204 for (let i = 0; i < 8; i++) {
205 this.makeImpl(true, i);
206 const lostPoint = QRUtil.getLostPoint(this);
207 if (i == 0 || minLostPoint > lostPoint) {
208 minLostPoint = lostPoint;
209 pattern = i;
210 }
211 }
212 return pattern;
213 }
214 setupTimingPattern() {
215 for (let r = 8; r < this.moduleCount - 8; r++) {
216 if (this.modules[r][6] != null) {
217 continue;
218 }
219 this.modules[r][6] = r % 2 == 0;
220 }
221 for (let c = 8; c < this.moduleCount - 8; c++) {
222 if (this.modules[6][c] != null) {
223 continue;
224 }
225 this.modules[6][c] = c % 2 == 0;
226 }
227 }
228 setupPositionAdjustPattern() {
229 const pos = QRUtil.getPatternPosition(this.typeNumber);
230 for (let i = 0; i < pos.length; i++) {
231 for (let j = 0; j < pos.length; j++) {
232 const row = pos[i];
233 const col = pos[j];
234 if (this.modules[row][col] != null) {
235 continue;
236 }
237 for (let r = -2; r <= 2; r++) {
238 for (let c = -2; c <= 2; c++) {
239 if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
240 this.modules[row + r][col + c] = true;
241 }
242 else {
243 this.modules[row + r][col + c] = false;
244 }
245 }
246 }
247 }
248 }
249 }
250 setupTypeNumber(test) {
251 const bits = QRUtil.getBCHTypeNumber(this.typeNumber);
252 for (var i = 0; i < 18; i++) {
253 var mod = !test && ((bits >> i) & 1) == 1;
254 this.modules[Math.floor(i / 3)][(i % 3) + this.moduleCount - 8 - 3] = mod;
255 }
256 for (var i = 0; i < 18; i++) {
257 var mod = !test && ((bits >> i) & 1) == 1;
258 this.modules[(i % 3) + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
259 }
260 }
261 setupTypeInfo(test, maskPattern) {
262 const data = (this.errorCorrectLevel << 3) | maskPattern;
263 const bits = QRUtil.getBCHTypeInfo(data);
264 for (var i = 0; i < 15; i++) {
265 var mod = !test && ((bits >> i) & 1) == 1;
266 if (i < 6) {
267 this.modules[i][8] = mod;
268 }
269 else if (i < 8) {
270 this.modules[i + 1][8] = mod;
271 }
272 else {
273 this.modules[this.moduleCount - 15 + i][8] = mod;
274 }
275 }
276 for (var i = 0; i < 15; i++) {
277 var mod = !test && ((bits >> i) & 1) == 1;
278 if (i < 8) {
279 this.modules[8][this.moduleCount - i - 1] = mod;
280 }
281 else if (i < 9) {
282 this.modules[8][15 - i - 1 + 1] = mod;
283 }
284 else {
285 this.modules[8][15 - i - 1] = mod;
286 }
287 }
288 this.modules[this.moduleCount - 8][8] = !test;
289 }
290 mapData(data, maskPattern) {
291 let inc = -1;
292 let row = this.moduleCount - 1;
293 let bitIndex = 7;
294 let byteIndex = 0;
295 for (let col = this.moduleCount - 1; col > 0; col -= 2) {
296 if (col == 6)
297 col--;
298 while (true) {
299 for (let c = 0; c < 2; c++) {
300 if (this.modules[row][col - c] == null) {
301 let dark = false;
302 if (byteIndex < data.length) {
303 dark = ((data[byteIndex] >>> bitIndex) & 1) == 1;
304 }
305 const mask = QRUtil.getMask(maskPattern, row, col - c);
306 if (mask) {
307 dark = !dark;
308 }
309 this.modules[row][col - c] = dark;
310 bitIndex--;
311 if (bitIndex == -1) {
312 byteIndex++;
313 bitIndex = 7;
314 }
315 }
316 }
317 row += inc;
318 if (row < 0 || this.moduleCount <= row) {
319 row -= inc;
320 inc = -inc;
321 break;
322 }
323 }
324 }
325 }
326 static createData(typeNumber, errorCorrectLevel, dataList) {
327 const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
328 const buffer = new QRBitBuffer();
329 for (var i = 0; i < dataList.length; i++) {
330 const data = dataList[i];
331 buffer.put(data.mode, 4);
332 buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
333 data.write(buffer);
334 }
335 let totalDataCount = 0;
336 for (var i = 0; i < rsBlocks.length; i++) {
337 totalDataCount += rsBlocks[i].dataCount;
338 }
339 if (buffer.getLengthInBits() > totalDataCount * 8) {
340 throw new Error(`code length overflow. (${buffer.getLengthInBits()}>${totalDataCount * 8})`);
341 }
342 if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
343 buffer.put(0, 4);
344 }
345 while (buffer.getLengthInBits() % 8 != 0) {
346 buffer.putBit(false);
347 }
348 while (true) {
349 if (buffer.getLengthInBits() >= totalDataCount * 8) {
350 break;
351 }
352 buffer.put(QRCodeModel.PAD0, 8);
353 if (buffer.getLengthInBits() >= totalDataCount * 8) {
354 break;
355 }
356 buffer.put(QRCodeModel.PAD1, 8);
357 }
358 return QRCodeModel.createBytes(buffer, rsBlocks);
359 }
360 static createBytes(buffer, rsBlocks) {
361 let offset = 0;
362 let maxDcCount = 0;
363 let maxEcCount = 0;
364 const dcdata = new Array(rsBlocks.length);
365 const ecdata = new Array(rsBlocks.length);
366 for (var r = 0; r < rsBlocks.length; r++) {
367 const dcCount = rsBlocks[r].dataCount;
368 const ecCount = rsBlocks[r].totalCount - dcCount;
369 maxDcCount = Math.max(maxDcCount, dcCount);
370 maxEcCount = Math.max(maxEcCount, ecCount);
371 dcdata[r] = new Array(dcCount);
372 for (var i = 0; i < dcdata[r].length; i++) {
373 dcdata[r][i] = 0xff & buffer.buffer[i + offset];
374 }
375 offset += dcCount;
376 const rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
377 const rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
378 const modPoly = rawPoly.mod(rsPoly);
379 ecdata[r] = new Array(rsPoly.getLength() - 1);
380 for (var i = 0; i < ecdata[r].length; i++) {
381 const modIndex = i + modPoly.getLength() - ecdata[r].length;
382 ecdata[r][i] = modIndex >= 0 ? modPoly.get(modIndex) : 0;
383 }
384 }
385 let totalCodeCount = 0;
386 for (var i = 0; i < rsBlocks.length; i++) {
387 totalCodeCount += rsBlocks[i].totalCount;
388 }
389 const data = new Array(totalCodeCount);
390 let index = 0;
391 for (var i = 0; i < maxDcCount; i++) {
392 for (var r = 0; r < rsBlocks.length; r++) {
393 if (i < dcdata[r].length) {
394 data[index++] = dcdata[r][i];
395 }
396 }
397 }
398 for (var i = 0; i < maxEcCount; i++) {
399 for (var r = 0; r < rsBlocks.length; r++) {
400 if (i < ecdata[r].length) {
401 data[index++] = ecdata[r][i];
402 }
403 }
404 }
405 return data;
406 }
407 }
408 QRCodeModel.PAD0 = 0xec;
409 QRCodeModel.PAD1 = 0x11;
410 export const QRErrorCorrectLevel = { L: 1, M: 0, Q: 3, H: 2 };
411 const QRMode = { MODE_NUMBER: 1 << 0, MODE_ALPHA_NUM: 1 << 1, MODE_8BIT_BYTE: 1 << 2, MODE_KANJI: 1 << 3 };
412 export const QRMaskPattern = {
413 PATTERN000: 0,
414 PATTERN001: 1,
415 PATTERN010: 2,
416 PATTERN011: 3,
417 PATTERN100: 4,
418 PATTERN101: 5,
419 PATTERN110: 6,
420 PATTERN111: 7,
421 };
422 export class QRUtil {
423 static getBCHTypeInfo(data) {
424 let d = data << 10;
425 while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
426 d ^= QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15));
427 }
428 return ((data << 10) | d) ^ QRUtil.G15_MASK;
429 }
430 static getBCHTypeNumber(data) {
431 let d = data << 12;
432 while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
433 d ^= QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18));
434 }
435 return (data << 12) | d;
436 }
437 static getBCHDigit(data) {
438 let digit = 0;
439 while (data != 0) {
440 digit++;
441 data >>>= 1;
442 }
443 return digit;
444 }
445 static getPatternPosition(typeNumber) {
446 return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
447 }
448 static getMask(maskPattern, i, j) {
449 switch (maskPattern) {
450 case QRMaskPattern.PATTERN000:
451 return (i + j) % 2 == 0;
452 case QRMaskPattern.PATTERN001:
453 return i % 2 == 0;
454 case QRMaskPattern.PATTERN010:
455 return j % 3 == 0;
456 case QRMaskPattern.PATTERN011:
457 return (i + j) % 3 == 0;
458 case QRMaskPattern.PATTERN100:
459 return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
460 case QRMaskPattern.PATTERN101:
461 return ((i * j) % 2) + ((i * j) % 3) == 0;
462 case QRMaskPattern.PATTERN110:
463 return (((i * j) % 2) + ((i * j) % 3)) % 2 == 0;
464 case QRMaskPattern.PATTERN111:
465 return (((i * j) % 3) + ((i + j) % 2)) % 2 == 0;
466 default:
467 throw new Error(`bad maskPattern:${maskPattern}`);
468 }
469 }
470 static getErrorCorrectPolynomial(errorCorrectLength) {
471 let a = new QRPolynomial([1], 0);
472 for (let i = 0; i < errorCorrectLength; i++) {
473 a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
474 }
475 return a;
476 }
477 static getLengthInBits(mode, type) {
478 if (1 <= type && type < 10) {
479 switch (mode) {
480 case QRMode.MODE_NUMBER:
481 return 10;
482 case QRMode.MODE_ALPHA_NUM:
483 return 9;
484 case QRMode.MODE_8BIT_BYTE:
485 return 8;
486 case QRMode.MODE_KANJI:
487 return 8;
488 default:
489 throw new Error(`mode:${mode}`);
490 }
491 }
492 else if (type < 27) {
493 switch (mode) {
494 case QRMode.MODE_NUMBER:
495 return 12;
496 case QRMode.MODE_ALPHA_NUM:
497 return 11;
498 case QRMode.MODE_8BIT_BYTE:
499 return 16;
500 case QRMode.MODE_KANJI:
501 return 10;
502 default:
503 throw new Error(`mode:${mode}`);
504 }
505 }
506 else if (type < 41) {
507 switch (mode) {
508 case QRMode.MODE_NUMBER:
509 return 14;
510 case QRMode.MODE_ALPHA_NUM:
511 return 13;
512 case QRMode.MODE_8BIT_BYTE:
513 return 16;
514 case QRMode.MODE_KANJI:
515 return 12;
516 default:
517 throw new Error(`mode:${mode}`);
518 }
519 }
520 else {
521 throw new Error(`type:${type}`);
522 }
523 }
524 static getLostPoint(qrCode) {
525 const moduleCount = qrCode.getModuleCount();
526 let lostPoint = 0;
527 for (var row = 0; row < moduleCount; row++) {
528 for (var col = 0; col < moduleCount; col++) {
529 let sameCount = 0;
530 const dark = qrCode.isDark(row, col);
531 for (let r = -1; r <= 1; r++) {
532 if (row + r < 0 || moduleCount <= row + r) {
533 continue;
534 }
535 for (let c = -1; c <= 1; c++) {
536 if (col + c < 0 || moduleCount <= col + c) {
537 continue;
538 }
539 if (r == 0 && c == 0) {
540 continue;
541 }
542 if (dark == qrCode.isDark(row + r, col + c)) {
543 sameCount++;
544 }
545 }
546 }
547 if (sameCount > 5) {
548 lostPoint += 3 + sameCount - 5;
549 }
550 }
551 }
552 for (var row = 0; row < moduleCount - 1; row++) {
553 for (var col = 0; col < moduleCount - 1; col++) {
554 let count = 0;
555 if (qrCode.isDark(row, col))
556 count++;
557 if (qrCode.isDark(row + 1, col))
558 count++;
559 if (qrCode.isDark(row, col + 1))
560 count++;
561 if (qrCode.isDark(row + 1, col + 1))
562 count++;
563 if (count == 0 || count == 4) {
564 lostPoint += 3;
565 }
566 }
567 }
568 for (var row = 0; row < moduleCount; row++) {
569 for (var col = 0; col < moduleCount - 6; col++) {
570 if (qrCode.isDark(row, col) &&
571 !qrCode.isDark(row, col + 1) &&
572 qrCode.isDark(row, col + 2) &&
573 qrCode.isDark(row, col + 3) &&
574 qrCode.isDark(row, col + 4) &&
575 !qrCode.isDark(row, col + 5) &&
576 qrCode.isDark(row, col + 6)) {
577 lostPoint += 40;
578 }
579 }
580 }
581 for (var col = 0; col < moduleCount; col++) {
582 for (var row = 0; row < moduleCount - 6; row++) {
583 if (qrCode.isDark(row, col) &&
584 !qrCode.isDark(row + 1, col) &&
585 qrCode.isDark(row + 2, col) &&
586 qrCode.isDark(row + 3, col) &&
587 qrCode.isDark(row + 4, col) &&
588 !qrCode.isDark(row + 5, col) &&
589 qrCode.isDark(row + 6, col)) {
590 lostPoint += 40;
591 }
592 }
593 }
594 let darkCount = 0;
595 for (var col = 0; col < moduleCount; col++) {
596 for (var row = 0; row < moduleCount; row++) {
597 if (qrCode.isDark(row, col)) {
598 darkCount++;
599 }
600 }
601 }
602 const ratio = Math.abs((100 * darkCount) / moduleCount / moduleCount - 50) / 5;
603 lostPoint += ratio * 10;
604 return lostPoint;
605 }
606 }
607 QRUtil.PATTERN_POSITION_TABLE = [
608 [],
609 [6, 18],
610 [6, 22],
611 [6, 26],
612 [6, 30],
613 [6, 34],
614 [6, 22, 38],
615 [6, 24, 42],
616 [6, 26, 46],
617 [6, 28, 50],
618 [6, 30, 54],
619 [6, 32, 58],
620 [6, 34, 62],
621 [6, 26, 46, 66],
622 [6, 26, 48, 70],
623 [6, 26, 50, 74],
624 [6, 30, 54, 78],
625 [6, 30, 56, 82],
626 [6, 30, 58, 86],
627 [6, 34, 62, 90],
628 [6, 28, 50, 72, 94],
629 [6, 26, 50, 74, 98],
630 [6, 30, 54, 78, 102],
631 [6, 28, 54, 80, 106],
632 [6, 32, 58, 84, 110],
633 [6, 30, 58, 86, 114],
634 [6, 34, 62, 90, 118],
635 [6, 26, 50, 74, 98, 122],
636 [6, 30, 54, 78, 102, 126],
637 [6, 26, 52, 78, 104, 130],
638 [6, 30, 56, 82, 108, 134],
639 [6, 34, 60, 86, 112, 138],
640 [6, 30, 58, 86, 114, 142],
641 [6, 34, 62, 90, 118, 146],
642 [6, 30, 54, 78, 102, 126, 150],
643 [6, 24, 50, 76, 102, 128, 154],
644 [6, 28, 54, 80, 106, 132, 158],
645 [6, 32, 58, 84, 110, 136, 162],
646 [6, 26, 54, 82, 110, 138, 166],
647 [6, 30, 58, 86, 114, 142, 170],
648 ];
649 QRUtil.G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
650 QRUtil.G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
651 QRUtil.G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
652 export class QRMath {
653 static glog(n) {
654 if (n < 1) {
655 throw new Error(`glog(${n})`);
656 }
657 return QRMath.LOG_TABLE[n];
658 }
659 static gexp(n) {
660 while (n < 0) {
661 n += 255;
662 }
663 while (n >= 256) {
664 n -= 255;
665 }
666 return QRMath.EXP_TABLE[n];
667 }
668 }
669 QRMath.EXP_TABLE = new Array(256);
670 QRMath.LOG_TABLE = new Array(256);
671 QRMath._constructor = (function () {
672 for (var i = 0; i < 8; i++) {
673 QRMath.EXP_TABLE[i] = 1 << i;
674 }
675 for (var i = 8; i < 256; i++) {
676 QRMath.EXP_TABLE[i] =
677 QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
678 }
679 for (var i = 0; i < 255; i++) {
680 QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
681 }
682 })();
683 class QRPolynomial {
684 constructor(num, shift) {
685 if (num.length == undefined) {
686 throw new Error(`${num.length}/${shift}`);
687 }
688 let offset = 0;
689 while (offset < num.length && num[offset] == 0) {
690 offset++;
691 }
692 this.num = new Array(num.length - offset + shift);
693 for (let i = 0; i < num.length - offset; i++) {
694 this.num[i] = num[i + offset];
695 }
696 }
697 get(index) {
698 return this.num[index];
699 }
700 getLength() {
701 return this.num.length;
702 }
703 multiply(e) {
704 const num = new Array(this.getLength() + e.getLength() - 1);
705 for (let i = 0; i < this.getLength(); i++) {
706 for (let j = 0; j < e.getLength(); j++) {
707 num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
708 }
709 }
710 return new QRPolynomial(num, 0);
711 }
712 mod(e) {
713 if (this.getLength() - e.getLength() < 0) {
714 return this;
715 }
716 const ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
717 const num = new Array(this.getLength());
718 for (var i = 0; i < this.getLength(); i++) {
719 num[i] = this.get(i);
720 }
721 for (var i = 0; i < e.getLength(); i++) {
722 num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
723 }
724 return new QRPolynomial(num, 0).mod(e);
725 }
726 }
727 class QRRSBlock {
728 constructor(totalCount, dataCount) {
729 this.totalCount = totalCount;
730 this.dataCount = dataCount;
731 }
732 static getRSBlocks(typeNumber, errorCorrectLevel) {
733 const rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
734 if (rsBlock == undefined) {
735 throw new Error(`bad rs block @ typeNumber:${typeNumber}/errorCorrectLevel:${errorCorrectLevel}`);
736 }
737 const length = rsBlock.length / 3;
738 const list = [];
739 for (let i = 0; i < length; i++) {
740 const count = rsBlock[i * 3 + 0];
741 const totalCount = rsBlock[i * 3 + 1];
742 const dataCount = rsBlock[i * 3 + 2];
743 for (let j = 0; j < count; j++) {
744 list.push(new QRRSBlock(totalCount, dataCount));
745 }
746 }
747 return list;
748 }
749 static getRsBlockTable(typeNumber, errorCorrectLevel) {
750 switch (errorCorrectLevel) {
751 case QRErrorCorrectLevel.L:
752 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
753 case QRErrorCorrectLevel.M:
754 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
755 case QRErrorCorrectLevel.Q:
756 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
757 case QRErrorCorrectLevel.H:
758 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
759 default:
760 return undefined;
761 }
762 }
763 }
764 QRRSBlock.RS_BLOCK_TABLE = [
765 [1, 26, 19],
766 [1, 26, 16],
767 [1, 26, 13],
768 [1, 26, 9],
769 [1, 44, 34],
770 [1, 44, 28],
771 [1, 44, 22],
772 [1, 44, 16],
773 [1, 70, 55],
774 [1, 70, 44],
775 [2, 35, 17],
776 [2, 35, 13],
777 [1, 100, 80],
778 [2, 50, 32],
779 [2, 50, 24],
780 [4, 25, 9],
781 [1, 134, 108],
782 [2, 67, 43],
783 [2, 33, 15, 2, 34, 16],
784 [2, 33, 11, 2, 34, 12],
785 [2, 86, 68],
786 [4, 43, 27],
787 [4, 43, 19],
788 [4, 43, 15],
789 [2, 98, 78],
790 [4, 49, 31],
791 [2, 32, 14, 4, 33, 15],
792 [4, 39, 13, 1, 40, 14],
793 [2, 121, 97],
794 [2, 60, 38, 2, 61, 39],
795 [4, 40, 18, 2, 41, 19],
796 [4, 40, 14, 2, 41, 15],
797 [2, 146, 116],
798 [3, 58, 36, 2, 59, 37],
799 [4, 36, 16, 4, 37, 17],
800 [4, 36, 12, 4, 37, 13],
801 [2, 86, 68, 2, 87, 69],
802 [4, 69, 43, 1, 70, 44],
803 [6, 43, 19, 2, 44, 20],
804 [6, 43, 15, 2, 44, 16],
805 [4, 101, 81],
806 [1, 80, 50, 4, 81, 51],
807 [4, 50, 22, 4, 51, 23],
808 [3, 36, 12, 8, 37, 13],
809 [2, 116, 92, 2, 117, 93],
810 [6, 58, 36, 2, 59, 37],
811 [4, 46, 20, 6, 47, 21],
812 [7, 42, 14, 4, 43, 15],
813 [4, 133, 107],
814 [8, 59, 37, 1, 60, 38],
815 [8, 44, 20, 4, 45, 21],
816 [12, 33, 11, 4, 34, 12],
817 [3, 145, 115, 1, 146, 116],
818 [4, 64, 40, 5, 65, 41],
819 [11, 36, 16, 5, 37, 17],
820 [11, 36, 12, 5, 37, 13],
821 [5, 109, 87, 1, 110, 88],
822 [5, 65, 41, 5, 66, 42],
823 [5, 54, 24, 7, 55, 25],
824 [11, 36, 12],
825 [5, 122, 98, 1, 123, 99],
826 [7, 73, 45, 3, 74, 46],
827 [15, 43, 19, 2, 44, 20],
828 [3, 45, 15, 13, 46, 16],
829 [1, 135, 107, 5, 136, 108],
830 [10, 74, 46, 1, 75, 47],
831 [1, 50, 22, 15, 51, 23],
832 [2, 42, 14, 17, 43, 15],
833 [5, 150, 120, 1, 151, 121],
834 [9, 69, 43, 4, 70, 44],
835 [17, 50, 22, 1, 51, 23],
836 [2, 42, 14, 19, 43, 15],
837 [3, 141, 113, 4, 142, 114],
838 [3, 70, 44, 11, 71, 45],
839 [17, 47, 21, 4, 48, 22],
840 [9, 39, 13, 16, 40, 14],
841 [3, 135, 107, 5, 136, 108],
842 [3, 67, 41, 13, 68, 42],
843 [15, 54, 24, 5, 55, 25],
844 [15, 43, 15, 10, 44, 16],
845 [4, 144, 116, 4, 145, 117],
846 [17, 68, 42],
847 [17, 50, 22, 6, 51, 23],
848 [19, 46, 16, 6, 47, 17],
849 [2, 139, 111, 7, 140, 112],
850 [17, 74, 46],
851 [7, 54, 24, 16, 55, 25],
852 [34, 37, 13],
853 [4, 151, 121, 5, 152, 122],
854 [4, 75, 47, 14, 76, 48],
855 [11, 54, 24, 14, 55, 25],
856 [16, 45, 15, 14, 46, 16],
857 [6, 147, 117, 4, 148, 118],
858 [6, 73, 45, 14, 74, 46],
859 [11, 54, 24, 16, 55, 25],
860 [30, 46, 16, 2, 47, 17],
861 [8, 132, 106, 4, 133, 107],
862 [8, 75, 47, 13, 76, 48],
863 [7, 54, 24, 22, 55, 25],
864 [22, 45, 15, 13, 46, 16],
865 [10, 142, 114, 2, 143, 115],
866 [19, 74, 46, 4, 75, 47],
867 [28, 50, 22, 6, 51, 23],
868 [33, 46, 16, 4, 47, 17],
869 [8, 152, 122, 4, 153, 123],
870 [22, 73, 45, 3, 74, 46],
871 [8, 53, 23, 26, 54, 24],
872 [12, 45, 15, 28, 46, 16],
873 [3, 147, 117, 10, 148, 118],
874 [3, 73, 45, 23, 74, 46],
875 [4, 54, 24, 31, 55, 25],
876 [11, 45, 15, 31, 46, 16],
877 [7, 146, 116, 7, 147, 117],
878 [21, 73, 45, 7, 74, 46],
879 [1, 53, 23, 37, 54, 24],
880 [19, 45, 15, 26, 46, 16],
881 [5, 145, 115, 10, 146, 116],
882 [19, 75, 47, 10, 76, 48],
883 [15, 54, 24, 25, 55, 25],
884 [23, 45, 15, 25, 46, 16],
885 [13, 145, 115, 3, 146, 116],
886 [2, 74, 46, 29, 75, 47],
887 [42, 54, 24, 1, 55, 25],
888 [23, 45, 15, 28, 46, 16],
889 [17, 145, 115],
890 [10, 74, 46, 23, 75, 47],
891 [10, 54, 24, 35, 55, 25],
892 [19, 45, 15, 35, 46, 16],
893 [17, 145, 115, 1, 146, 116],
894 [14, 74, 46, 21, 75, 47],
895 [29, 54, 24, 19, 55, 25],
896 [11, 45, 15, 46, 46, 16],
897 [13, 145, 115, 6, 146, 116],
898 [14, 74, 46, 23, 75, 47],
899 [44, 54, 24, 7, 55, 25],
900 [59, 46, 16, 1, 47, 17],
901 [12, 151, 121, 7, 152, 122],
902 [12, 75, 47, 26, 76, 48],
903 [39, 54, 24, 14, 55, 25],
904 [22, 45, 15, 41, 46, 16],
905 [6, 151, 121, 14, 152, 122],
906 [6, 75, 47, 34, 76, 48],
907 [46, 54, 24, 10, 55, 25],
908 [2, 45, 15, 64, 46, 16],
909 [17, 152, 122, 4, 153, 123],
910 [29, 74, 46, 14, 75, 47],
911 [49, 54, 24, 10, 55, 25],
912 [24, 45, 15, 46, 46, 16],
913 [4, 152, 122, 18, 153, 123],
914 [13, 74, 46, 32, 75, 47],
915 [48, 54, 24, 14, 55, 25],
916 [42, 45, 15, 32, 46, 16],
917 [20, 147, 117, 4, 148, 118],
918 [40, 75, 47, 7, 76, 48],
919 [43, 54, 24, 22, 55, 25],
920 [10, 45, 15, 67, 46, 16],
921 [19, 148, 118, 6, 149, 119],
922 [18, 75, 47, 31, 76, 48],
923 [34, 54, 24, 34, 55, 25],
924 [20, 45, 15, 61, 46, 16],
925 ];
926 class QRBitBuffer {
927 constructor() {
928 this.buffer = [];
929 this.length = 0;
930 }
931 get(index) {
932 const bufIndex = Math.floor(index / 8);
933 return ((this.buffer[bufIndex] >>> (7 - (index % 8))) & 1) == 1;
934 }
935 put(num, length) {
936 for (let i = 0; i < length; i++) {
937 this.putBit(((num >>> (length - i - 1)) & 1) == 1);
938 }
939 }
940 getLengthInBits() {
941 return this.length;
942 }
943 putBit(bit) {
944 const bufIndex = Math.floor(this.length / 8);
945 if (this.buffer.length <= bufIndex) {
946 this.buffer.push(0);
947 }
948 if (bit) {
949 this.buffer[bufIndex] |= 0x80 >>> this.length % 8;
950 }
951 this.length++;
952 }
953 }
954 const QRCodeLimitLength = [
955 [17, 14, 11, 7],
956 [32, 26, 20, 14],
957 [53, 42, 32, 24],
958 [78, 62, 46, 34],
959 [106, 84, 60, 44],
960 [134, 106, 74, 58],
961 [154, 122, 86, 64],
962 [192, 152, 108, 84],
963 [230, 180, 130, 98],
964 [271, 213, 151, 119],
965 [321, 251, 177, 137],
966 [367, 287, 203, 155],
967 [425, 331, 241, 177],
968 [458, 362, 258, 194],
969 [520, 412, 292, 220],
970 [586, 450, 322, 250],
971 [644, 504, 364, 280],
972 [718, 560, 394, 310],
973 [792, 624, 442, 338],
974 [858, 666, 482, 382],
975 [929, 711, 509, 403],
976 [1003, 779, 565, 439],
977 [1091, 857, 611, 461],
978 [1171, 911, 661, 511],
979 [1273, 997, 715, 535],
980 [1367, 1059, 751, 593],
981 [1465, 1125, 805, 625],
982 [1528, 1190, 868, 658],
983 [1628, 1264, 908, 698],
984 [1732, 1370, 982, 742],
985 [1840, 1452, 1030, 790],
986 [1952, 1538, 1112, 842],
987 [2068, 1628, 1168, 898],
988 [2188, 1722, 1228, 958],
989 [2303, 1809, 1283, 983],
990 [2431, 1911, 1351, 1051],
991 [2563, 1989, 1423, 1093],
992 [2699, 2099, 1499, 1139],
993 [2809, 2213, 1579, 1219],
994 [2953, 2331, 1663, 1273],
995 ];
1 import Vue from 'vue'
2 import App from './App.vue'
3
4 new Vue({
5 el: '#app',
6 render: h => h(App)
7 })
1 import vueQr from './vue-qr.vue';
2
3 vueQr.install = Vue => Vue.component(vueQr.name, vueQr);
4
5 export default vueQr;
1 function readAsArrayBuffer(url, callback) {
2 return new Promise((resolve, reject) => {
3 var xhr = new XMLHttpRequest();
4 xhr.responseType = "blob"; //设定返回数据类型为Blob
5 xhr.onload = function() {
6 var reader = new FileReader();
7 reader.onloadend = function() {
8 resolve(reader.result)
9 };
10 reader.readAsArrayBuffer(xhr.response); //xhr.response就是一个Blob,用FileReader读取
11 };
12 xhr.open("GET", url);
13 xhr.send();
14 });
15 }
16 export default readAsArrayBuffer
...\ No newline at end of file ...\ No newline at end of file
1 export function toBoolean(val) {
2 if (val === '') return val
3 return val === 'true' || val == '1'
4 }
1 <template>
2 <img style="display: inline-block" :src="imgUrl" v-if="bindElement" />
3 </template>
4
5 <script>
6 import { toBoolean } from "./util.js";
7 import readAsArrayBuffer from "./readAsArrayBuffer";
8 import { AwesomeQR } from "../lib/awesome-qr";
9 export default {
10 props: {
11 text: {
12 type: String,
13 required: true
14 },
15 qid: {
16 type: String
17 },
18 correctLevel: {
19 type: Number,
20 default: 1
21 },
22 size: {
23 type: Number,
24 default: 200
25 },
26 margin: {
27 type: Number,
28 default: 20
29 },
30 colorDark: {
31 type: String,
32 default: "#000000"
33 },
34 colorLight: {
35 type: String,
36 default: "#FFFFFF"
37 },
38 bgSrc: {
39 type: String,
40 default: undefined
41 },
42 background: {
43 type: String,
44 default: "rgba(0,0,0,0)"
45 },
46 backgroundDimming: {
47 type: String,
48 default: "rgba(0,0,0,0)"
49 },
50 logoSrc: {
51 type: String,
52 default: undefined
53 },
54 logoBackgroundColor: {
55 type: String,
56 default: "rgba(255,255,255,1)"
57 },
58 gifBgSrc: {
59 type: String,
60 default: undefined
61 },
62 logoScale: {
63 type: Number,
64 default: 0.2
65 },
66 logoMargin: {
67 type: Number,
68 default: 0
69 },
70 logoCornerRadius: {
71 type: Number,
72 default: 8
73 },
74 whiteMargin: {
75 type: [Boolean, String],
76 default: true
77 },
78 dotScale: {
79 type: Number,
80 default: 1
81 },
82 autoColor: {
83 type: [Boolean, String],
84 default: true
85 },
86 binarize: {
87 type: [Boolean, String],
88 default: false
89 },
90 binarizeThreshold: {
91 type: Number,
92 default: 128
93 },
94 callback: {
95 type: Function,
96 default: function() {
97 return undefined;
98 }
99 },
100 bindElement: {
101 type: Boolean,
102 default: true
103 },
104 backgroundColor: {
105 type: String,
106 default: "#FFFFFF"
107 },
108 components: {
109 default: function(){
110 return {
111 data: {
112 scale: 1
113 },
114 timing: {
115 scale: 1,
116 protectors: false
117 },
118 alignment: {
119 scale: 1,
120 protectors: false
121 },
122 cornerAlignment: {
123 scale: 1,
124 protectors: true
125 }
126 }
127 }
128 }
129 },
130 name: "vue-qr",
131 data() {
132 return {
133 imgUrl: ""
134 };
135 },
136 watch: {
137 $props: {
138 deep: true,
139 handler() {
140 this.main();
141 }
142 }
143 },
144 mounted() {
145 this.main();
146 },
147 methods: {
148 async main() {
149 // const that = this;
150 if (this.gifBgSrc) {
151 const gifImg = await readAsArrayBuffer(this.gifBgSrc);
152 const logoImg = this.logoSrc;
153
154 this.render(undefined, logoImg, gifImg);
155 return;
156 }
157 const bgImg = this.bgSrc;
158 const logoImg = this.logoSrc;
159 this.render(bgImg, logoImg);
160 },
161 async render(img, logoImg, gifBgSrc) {
162 const that = this;
163 // if (this.$isServer) {
164 // return;
165 // }
166 // if (!this.AwesomeQR) {
167 // this.AwesomeQR = AwesomeQR;
168 // }
169 new AwesomeQR({
170 gifBackground: gifBgSrc,
171 text: that.text,
172 size: that.size,
173 margin: that.margin,
174 colorDark: that.colorDark,
175 colorLight: that.colorLight,
176 backgroundColor: that.backgroundColor,
177 backgroundImage: img,
178 backgroundDimming: that.backgroundDimming,
179 logoImage: logoImg,
180 logoScale: that.logoScale,
181 logoBackgroundColor: that.logoBackgroundColor,
182 correctLevel: that.correctLevel,
183 logoMargin: that.logoMargin,
184 logoCornerRadius: that.logoCornerRadius,
185 whiteMargin: toBoolean(that.whiteMargin),
186 dotScale: that.dotScale,
187 autoColor: toBoolean(that.autoColor),
188 binarize: toBoolean(that.binarize),
189 binarizeThreshold: that.binarizeThreshold,
190 components: that.components
191 })
192 .draw()
193 .then(dataUri => {
194 this.imgUrl = dataUri;
195 that.callback && that.callback(dataUri, that.qid);
196 });
197 }
198 }
199 };
200 </script>
1 var path = require('path')
2 var webpack = require('webpack')
3 const VueLoaderPlugin = require('vue-loader/lib/plugin');
4
5 const NODE_ENV = process.env.NODE_ENV
6
7 module.exports = {
8 entry: NODE_ENV == 'development' ? ['./src/main.js'] : ['./src/index.js'],
9 output: {
10 path: path.resolve(__dirname, './dist'),
11 publicPath: '/dist/',
12 filename: 'vue-qr.js',
13 library: 'vue-qr',
14 libraryTarget: 'umd',
15 umdNamedDefine: true,
16 globalObject: 'this',
17
18 },
19 module: {
20 rules: [
21 {
22 test: /\.css$/,
23 use: [
24 'vue-style-loader',
25 'css-loader'
26 ],
27 }, {
28 test: /\.vue$/,
29 loader: 'vue-loader',
30 options: {
31 loaders: {
32 }
33 // other vue-loader options go here
34 }
35 },
36 {
37 test: /\.worker\.js$/,
38 loader: 'worker-loader',
39 options: { inline: 'no-fallback' }
40 },
41 {
42 test: /\.js$/,
43 loader: 'babel-loader',
44 exclude: /node_modules/
45 },
46 {
47 test: /\.(png|jpg|gif|svg)$/,
48 loader: 'file-loader',
49 options: {
50 name: '[name].[ext]?[hash]'
51 }
52 }
53 ]
54 },
55 plugins: [
56 // make sure to include the plugin for the magic
57 new VueLoaderPlugin()
58 ],
59 resolve: {
60 alias: {
61 'vue$': 'vue/dist/vue.esm.js'
62 },
63 extensions: ['*', '.js', '.vue', '.json']
64 },
65 devServer: {
66 historyApiFallback: true,
67 noInfo: true,
68 overlay: true,
69 port: 5555
70 },
71 performance: {
72 hints: false
73 },
74 devtool: '#eval-source-map'
75 }
76
77 if (process.env.NODE_ENV === 'production') {
78 module.exports.devtool = '#source-map'
79 module.exports.optimization = {
80 minimize: true
81 }
82 // http://vue-loader.vuejs.org/en/workflow/production.html
83 module.exports.plugins = (module.exports.plugins || []).concat([
84 new webpack.DefinePlugin({
85 'process.env': {
86 NODE_ENV: '"production"'
87 }
88 }),
89 new webpack.LoaderOptionsPlugin({
90 minimize: true
91 })
92 ])
93 }
...@@ -1131,8 +1131,7 @@ ...@@ -1131,8 +1131,7 @@
1131 "balanced-match": { 1131 "balanced-match": {
1132 "version": "1.0.0", 1132 "version": "1.0.0",
1133 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 1133 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
1134 "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 1134 "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
1135 "dev": true
1136 }, 1135 },
1137 "base": { 1136 "base": {
1138 "version": "0.11.2", 1137 "version": "0.11.2",
...@@ -3143,6 +3142,14 @@ ...@@ -3143,6 +3142,14 @@
3143 "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", 3142 "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
3144 "dev": true 3143 "dev": true
3145 }, 3144 },
3145 "decompress-response": {
3146 "version": "6.0.0",
3147 "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz",
3148 "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
3149 "requires": {
3150 "mimic-response": "^3.1.0"
3151 }
3152 },
3146 "deep-equal": { 3153 "deep-equal": {
3147 "version": "1.1.1", 3154 "version": "1.1.1",
3148 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", 3155 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
...@@ -4260,8 +4267,7 @@ ...@@ -4260,8 +4267,7 @@
4260 "fs.realpath": { 4267 "fs.realpath": {
4261 "version": "1.0.0", 4268 "version": "1.0.0",
4262 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 4269 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
4263 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 4270 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
4264 "dev": true
4265 }, 4271 },
4266 "fsevents": { 4272 "fsevents": {
4267 "version": "2.1.3", 4273 "version": "2.1.3",
...@@ -4838,7 +4844,6 @@ ...@@ -4838,7 +4844,6 @@
4838 "version": "1.0.6", 4844 "version": "1.0.6",
4839 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 4845 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
4840 "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 4846 "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
4841 "dev": true,
4842 "requires": { 4847 "requires": {
4843 "once": "^1.3.0", 4848 "once": "^1.3.0",
4844 "wrappy": "1" 4849 "wrappy": "1"
...@@ -4847,8 +4852,7 @@ ...@@ -4847,8 +4852,7 @@
4847 "inherits": { 4852 "inherits": {
4848 "version": "2.0.4", 4853 "version": "2.0.4",
4849 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 4854 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
4850 "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 4855 "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
4851 "dev": true
4852 }, 4856 },
4853 "internal-ip": { 4857 "internal-ip": {
4854 "version": "1.2.0", 4858 "version": "1.2.0",
...@@ -5167,6 +5171,11 @@ ...@@ -5167,6 +5171,11 @@
5167 "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", 5171 "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==",
5168 "dev": true 5172 "dev": true
5169 }, 5173 },
5174 "js-binary-schema-parser": {
5175 "version": "2.0.3",
5176 "resolved": "https://registry.npmmirror.com/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz",
5177 "integrity": "sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg=="
5178 },
5170 "js-tokens": { 5179 "js-tokens": {
5171 "version": "3.0.2", 5180 "version": "3.0.2",
5172 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 5181 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
...@@ -5760,6 +5769,11 @@ ...@@ -5760,6 +5769,11 @@
5760 "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 5769 "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
5761 "dev": true 5770 "dev": true
5762 }, 5771 },
5772 "mimic-response": {
5773 "version": "3.1.0",
5774 "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz",
5775 "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="
5776 },
5763 "minimalistic-assert": { 5777 "minimalistic-assert": {
5764 "version": "1.0.1", 5778 "version": "1.0.1",
5765 "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 5779 "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
...@@ -6199,7 +6213,6 @@ ...@@ -6199,7 +6213,6 @@
6199 "version": "1.4.0", 6213 "version": "1.4.0",
6200 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 6214 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
6201 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 6215 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
6202 "dev": true,
6203 "requires": { 6216 "requires": {
6204 "wrappy": "1" 6217 "wrappy": "1"
6205 } 6218 }
...@@ -6384,6 +6397,11 @@ ...@@ -6384,6 +6397,11 @@
6384 "no-case": "^2.2.0" 6397 "no-case": "^2.2.0"
6385 } 6398 }
6386 }, 6399 },
6400 "parenthesis": {
6401 "version": "3.1.8",
6402 "resolved": "https://registry.npmmirror.com/parenthesis/-/parenthesis-3.1.8.tgz",
6403 "integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw=="
6404 },
6387 "parse-asn1": { 6405 "parse-asn1": {
6388 "version": "5.1.6", 6406 "version": "5.1.6",
6389 "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", 6407 "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
...@@ -9657,6 +9675,21 @@ ...@@ -9657,6 +9675,21 @@
9657 "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", 9675 "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
9658 "dev": true 9676 "dev": true
9659 }, 9677 },
9678 "simple-concat": {
9679 "version": "1.0.1",
9680 "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz",
9681 "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
9682 },
9683 "simple-get": {
9684 "version": "4.0.1",
9685 "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-4.0.1.tgz",
9686 "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
9687 "requires": {
9688 "decompress-response": "^6.0.0",
9689 "once": "^1.3.1",
9690 "simple-concat": "^1.0.0"
9691 }
9692 },
9660 "simple-swizzle": { 9693 "simple-swizzle": {
9661 "version": "0.2.2", 9694 "version": "0.2.2",
9662 "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 9695 "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
...@@ -10092,6 +10125,14 @@ ...@@ -10092,6 +10125,14 @@
10092 "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", 10125 "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
10093 "dev": true 10126 "dev": true
10094 }, 10127 },
10128 "string-split-by": {
10129 "version": "1.0.0",
10130 "resolved": "https://registry.npmmirror.com/string-split-by/-/string-split-by-1.0.0.tgz",
10131 "integrity": "sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==",
10132 "requires": {
10133 "parenthesis": "^3.1.5"
10134 }
10135 },
10095 "string-width": { 10136 "string-width": {
10096 "version": "2.1.1", 10137 "version": "2.1.1",
10097 "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 10138 "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
...@@ -10863,6 +10904,47 @@ ...@@ -10863,6 +10904,47 @@
10863 } 10904 }
10864 } 10905 }
10865 }, 10906 },
10907 "vue-qr": {
10908 "version": "4.0.9",
10909 "resolved": "https://registry.npmmirror.com/vue-qr/-/vue-qr-4.0.9.tgz",
10910 "integrity": "sha512-pAISV94T0MNEYA3NGjykUpsXRE2QfaNxlu9ZhEL6CERgqNc21hJYuP3hRVzAWfBQlgO18DPmZTbrFerJC3+Ikw==",
10911 "requires": {
10912 "glob": "^8.0.1",
10913 "js-binary-schema-parser": "^2.0.2",
10914 "simple-get": "^4.0.1",
10915 "string-split-by": "^1.0.0"
10916 },
10917 "dependencies": {
10918 "brace-expansion": {
10919 "version": "2.0.1",
10920 "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
10921 "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
10922 "requires": {
10923 "balanced-match": "^1.0.0"
10924 }
10925 },
10926 "glob": {
10927 "version": "8.0.3",
10928 "resolved": "https://registry.npmmirror.com/glob/-/glob-8.0.3.tgz",
10929 "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
10930 "requires": {
10931 "fs.realpath": "^1.0.0",
10932 "inflight": "^1.0.4",
10933 "inherits": "2",
10934 "minimatch": "^5.0.1",
10935 "once": "^1.3.0"
10936 }
10937 },
10938 "minimatch": {
10939 "version": "5.1.0",
10940 "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.0.tgz",
10941 "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
10942 "requires": {
10943 "brace-expansion": "^2.0.1"
10944 }
10945 }
10946 }
10947 },
10866 "vue-router": { 10948 "vue-router": {
10867 "version": "3.4.3", 10949 "version": "3.4.3",
10868 "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.3.tgz", 10950 "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.3.tgz",
...@@ -11741,8 +11823,7 @@ ...@@ -11741,8 +11823,7 @@
11741 "wrappy": { 11823 "wrappy": {
11742 "version": "1.0.2", 11824 "version": "1.0.2",
11743 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 11825 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
11744 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 11826 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
11745 "dev": true
11746 }, 11827 },
11747 "ws": { 11828 "ws": {
11748 "version": "4.1.0", 11829 "version": "4.1.0",
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
18 "vue": "^2.5.2", 18 "vue": "^2.5.2",
19 "vue-clipboard2": "^0.3.1", 19 "vue-clipboard2": "^0.3.1",
20 "vue-json-viewer": "^2.2.15", 20 "vue-json-viewer": "^2.2.15",
21 "vue-qr": "^4.0.9",
21 "vue-router": "^3.0.1" 22 "vue-router": "^3.0.1"
22 }, 23 },
23 "devDependencies": { 24 "devDependencies": {
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
28 min-width="1"> 28 min-width="1">
29 </el-table-column> 29 </el-table-column>
30 </el-table> 30 </el-table>
31 <vue-qr :text="vueQrText" :size="180"></vue-qr>
31 <br/> 32 <br/>
32 <br/> 33 <br/>
33 <span>激活此用户的代理人(tbl_agent_properties)</span> 34 <span>激活此用户的代理人(tbl_agent_properties)</span>
...@@ -213,7 +214,11 @@ ...@@ -213,7 +214,11 @@
213 </template> 214 </template>
214 215
215 <script> 216 <script>
217 import vueQr from 'vue-qr'
216 export default { 218 export default {
219 components: {
220 vueQr
221 },
217 data() { 222 data() {
218 return { 223 return {
219 phone: this.$route.query.phone, 224 phone: this.$route.query.phone,
...@@ -222,7 +227,8 @@ ...@@ -222,7 +227,8 @@
222 tblAgentProperties: [], 227 tblAgentProperties: [],
223 tblAgentCustomers: [], 228 tblAgentCustomers: [],
224 tblAgentCustomersAll: [], 229 tblAgentCustomersAll: [],
225 tblJiHuoAgentProperties: [] 230 tblJiHuoAgentProperties: [],
231 vueQrText: 'Zn2YEd1Xq/qHH8B3j0KxsMSfsA55IsYY+lbrIdIZS62EHl45vYrVcfYejpjPwpEoFtO+yU66GxBGrU8lwJ3WmMzMzziUWIVeg75IYjzBIompmi/uFOHKxCTgC/rjtWW6/o4SFl0tWbU8M2RjLB1bYWJdf7PONFQeGOQ8gttIeTHPeOIROOWbLDcoPqzLWcnDaYkAM8g+fPvF9xMex32Rxg=='
226 } 232 }
227 }, 233 },
228 mounted() { 234 mounted() {
......