commit
Showing
125 changed files
with
15187 additions
and
11 deletions
node_modules/decompress-response/index.d.ts
0 → 100644
| 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; |
node_modules/decompress-response/index.js
0 → 100644
| 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 | }; |
node_modules/decompress-response/license
0 → 100644
| 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 | } |
node_modules/decompress-response/readme.md
0 → 100644
| 1 | # decompress-response [](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> |
node_modules/js-binary-schema-parser/LICENSE
0 → 100644
| 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 |
69 Bytes
75.8 KB
2.91 MB
| 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 |
node_modules/mimic-response/index.d.ts
0 → 100644
| 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; |
node_modules/mimic-response/index.js
0 → 100644
| 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 | }; |
node_modules/mimic-response/license
0 → 100644
| 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. |
node_modules/mimic-response/package.json
0 → 100644
| 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 | } |
node_modules/mimic-response/readme.md
0 → 100644
| 1 | # mimic-response [](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> |
node_modules/parenthesis/LICENSE
0 → 100644
| 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 |
node_modules/parenthesis/README.md
0 → 100644
| 1 | # parenthesis [](https://travis-ci.org/dy/parenthesis) | ||
| 2 | |||
| 3 | Parse parentheses from a string, return folded arrays. | ||
| 4 | |||
| 5 | [](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 |
node_modules/parenthesis/index.d.ts
0 → 100644
| 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 | } |
node_modules/parenthesis/index.js
0 → 100644
| 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 |
node_modules/parenthesis/package.json
0 → 100644
| 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 | } |
node_modules/simple-concat/.travis.yml
0 → 100644
node_modules/simple-concat/LICENSE
0 → 100644
| 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. |
node_modules/simple-concat/README.md
0 → 100644
| 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). |
node_modules/simple-concat/index.js
0 → 100644
| 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 | } |
node_modules/simple-concat/package.json
0 → 100644
| 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 | } |
node_modules/simple-concat/test/basic.js
0 → 100644
| 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 | 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 |
node_modules/simple-get/LICENSE
0 → 100644
| 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. |
node_modules/simple-get/README.md
0 → 100644
| 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). |
node_modules/simple-get/index.js
0 → 100644
| 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 | }) |
node_modules/simple-get/package.json
0 → 100644
| 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 | } |
node_modules/string-split-by/.eslintrc.json
0 → 100644
| 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 | } |
node_modules/string-split-by/.travis.yml
0 → 100644
node_modules/string-split-by/index.js
0 → 100644
| 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 | } |
node_modules/string-split-by/package.json
0 → 100644
| 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 | } |
node_modules/string-split-by/readme.md
0 → 100644
| 1 | # string-split-by [](http://github.com/badges/stability-badges) [](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 | [](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 |
node_modules/string-split-by/test.js
0 → 100644
| 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 |
node_modules/vue-qr/.babelrc
0 → 100644
node_modules/vue-qr/.editorconfig
0 → 100644
node_modules/vue-qr/.postcssrc.js
0 → 100644
node_modules/vue-qr/CHANGELOG.MD
0 → 100644
| 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 |
node_modules/vue-qr/LICENSE.txt
0 → 100644
| 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. |
node_modules/vue-qr/README.md
0 → 100644
| 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) |
node_modules/vue-qr/dist/vue-qr.js
0 → 100644
| 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 |
node_modules/vue-qr/dist/vue-qr.js.map
0 → 100644
This diff could not be displayed because it is too large.
node_modules/vue-qr/index.html
0 → 100644
| 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 | [](http://travis-ci.org/juliangruber/brace-expansion) | ||
| 7 | [](https://www.npmjs.org/package/brace-expansion) | ||
| 8 | [](https://greenkeeper.io/) | ||
| 9 | |||
| 10 | [](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 <julian@juliangruber.com> | ||
| 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 | [](https://travis-ci.org/isaacs/node-glob/) [](https://ci.appveyor.com/project/isaacs/node-glob) [](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 |  | ||
| 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 |  |
| 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 | [](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 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 | } |
node_modules/vue-qr/package.json
0 → 100644
| 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 }; |
No preview for this file type
| 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 | } |
node_modules/vue-qr/src/App.vue
0 → 100644
| 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> |
node_modules/vue-qr/src/assets/avatar.png
0 → 100644
13.3 KB
node_modules/vue-qr/src/assets/bg1.png
0 → 100644
54.1 KB
node_modules/vue-qr/src/assets/bg2.jpg
0 → 100644
37.2 KB
node_modules/vue-qr/src/assets/bg3.jpg
0 → 100644
752 KB
node_modules/vue-qr/src/assets/dog.gif
0 → 100644
493 KB
node_modules/vue-qr/src/assets/logo.png
0 → 100644
6.69 KB
node_modules/vue-qr/src/assets/result1.png
0 → 100644
188 KB
node_modules/vue-qr/src/assets/result2.png
0 → 100644
36.5 KB
node_modules/vue-qr/src/assets/result3.png
0 → 100644
94.8 KB
node_modules/vue-qr/src/assets/result4.gif
0 → 100644
1.46 MB
node_modules/vue-qr/src/assets/scare.gif
0 → 100644
858 KB
node_modules/vue-qr/src/index.js
0 → 100644
| 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 |
node_modules/vue-qr/src/lib/awesome-qr.d.ts
0 → 100644
| 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 <color>. | ||
| 118 | * | ||
| 119 | * For more information about CSS <color>, 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 <color>. | ||
| 128 | * | ||
| 129 | * For more information about CSS <color>, 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 <color>. | ||
| 152 | * | ||
| 153 | * For more information about CSS <color>, 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 | } |
node_modules/vue-qr/src/lib/awesome-qr.js
0 → 100644
| 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 | /* | ||
| 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 | /* 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 | /* 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[]; |
node_modules/vue-qr/src/lib/gifuct-js/lzw.js
0 → 100644
| 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 | }; |
node_modules/vue-qr/src/lib/index.d.ts
0 → 100644
node_modules/vue-qr/src/lib/index.js
0 → 100644
node_modules/vue-qr/src/lib/qrcode.d.ts
0 → 100644
| 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 {}; |
node_modules/vue-qr/src/lib/qrcode.js
0 → 100644
| 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 | ]; |
node_modules/vue-qr/src/main.js
0 → 100644
node_modules/vue-qr/src/packages/index.js
0 → 100644
| 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 |
node_modules/vue-qr/src/packages/util.js
0 → 100644
node_modules/vue-qr/src/packages/vue-qr.vue
0 → 100644
| 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> |
node_modules/vue-qr/webpack.config.js
0 → 100644
| 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() { | ... | ... |
-
Please register or sign in to post a comment