Commit 71285982 71285982c4c894750e2b7b1c0b7927ca01735f69 by zhanghao

commit

1 parent cc1d2bfe
Showing 125 changed files with 4865 additions and 0 deletions
/// <reference types="node"/>
import {IncomingMessage} from 'http';
/**
Decompress a HTTP response if needed.
@param response - The HTTP incoming stream with compressed data.
@returns The decompressed HTTP response stream.
@example
```
import {http} from 'http';
import decompressResponse = require('decompress-response');
http.get('https://sindresorhus.com', response => {
response = decompressResponse(response);
});
```
*/
declare function decompressResponse(response: IncomingMessage): IncomingMessage;
export = decompressResponse;
'use strict';
const {Transform, PassThrough} = require('stream');
const zlib = require('zlib');
const mimicResponse = require('mimic-response');
module.exports = response => {
const contentEncoding = (response.headers['content-encoding'] || '').toLowerCase();
if (!['gzip', 'deflate', 'br'].includes(contentEncoding)) {
return response;
}
// TODO: Remove this when targeting Node.js 12.
const isBrotli = contentEncoding === 'br';
if (isBrotli && typeof zlib.createBrotliDecompress !== 'function') {
response.destroy(new Error('Brotli is not supported on Node.js < 12'));
return response;
}
let isEmpty = true;
const checker = new Transform({
transform(data, _encoding, callback) {
isEmpty = false;
callback(null, data);
},
flush(callback) {
callback();
}
});
const finalStream = new PassThrough({
autoDestroy: false,
destroy(error, callback) {
response.destroy();
callback(error);
}
});
const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip();
decompressStream.once('error', error => {
if (isEmpty && !response.readable) {
finalStream.end();
return;
}
finalStream.destroy(error);
});
mimicResponse(response, finalStream);
response.pipe(checker).pipe(decompressStream).pipe(finalStream);
return finalStream;
};
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
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:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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.
{
"_from": "decompress-response@^6.0.0",
"_id": "decompress-response@6.0.0",
"_inBundle": false,
"_integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"_location": "/decompress-response",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "decompress-response@^6.0.0",
"name": "decompress-response",
"escapedName": "decompress-response",
"rawSpec": "^6.0.0",
"saveSpec": null,
"fetchSpec": "^6.0.0"
},
"_requiredBy": [
"/simple-get"
],
"_resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz",
"_shasum": "ca387612ddb7e104bd16d85aab00d5ecf09c66fc",
"_spec": "decompress-response@^6.0.0",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/simple-get",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/decompress-response/issues"
},
"bundleDependencies": false,
"dependencies": {
"mimic-response": "^3.1.0"
},
"deprecated": false,
"description": "Decompress a HTTP response if needed",
"devDependencies": {
"@types/node": "^14.0.1",
"ava": "^2.2.0",
"get-stream": "^5.0.0",
"pify": "^5.0.0",
"tsd": "^0.11.0",
"xo": "^0.30.0"
},
"engines": {
"node": ">=10"
},
"files": [
"index.js",
"index.d.ts"
],
"funding": "https://github.com/sponsors/sindresorhus",
"homepage": "https://github.com/sindresorhus/decompress-response#readme",
"keywords": [
"decompress",
"response",
"http",
"https",
"zlib",
"gzip",
"zip",
"deflate",
"unzip",
"ungzip",
"incoming",
"message",
"stream",
"compressed",
"brotli"
],
"license": "MIT",
"name": "decompress-response",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/decompress-response.git"
},
"scripts": {
"test": "xo && ava && tsd"
},
"version": "6.0.0",
"xo": {
"rules": {
"@typescript-eslint/prefer-readonly-parameter-types": "off"
}
}
}
# decompress-response [![Build Status](https://travis-ci.com/sindresorhus/decompress-response.svg?branch=master)](https://travis-ci.com/sindresorhus/decompress-response)
> Decompress a HTTP response if needed
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.
Used by [`got`](https://github.com/sindresorhus/got).
## Install
```
$ npm install decompress-response
```
## Usage
```js
const http = require('http');
const decompressResponse = require('decompress-response');
http.get('https://sindresorhus.com', response => {
response = decompressResponse(response);
});
```
## API
### decompressResponse(response)
Returns the decompressed HTTP response stream.
#### response
Type: [`http.IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
The HTTP incoming stream with compressed data.
---
<div align="center">
<b>
<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>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>
{
"presets": ["@babel/preset-env"]
}
{
"singleQuote": true,
"write": true,
"semi": false,
"tabWidth": 2,
"printWidth": 80
}
The MIT License (MIT)
Copyright (c) 2015 Matt Way
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
# js Binary Schema Parser
Parse binary files in javascript using a schema to convert to plain objects.
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.
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.
### How to Use
_Installation:_
npm install js-binary-schema-parser
_Create a schema and parse a file:_
import { parse, conditional } from 'js-binary-schema-parser'
import { buildStream, readByte } from 'js-binary-schema-parser/lib/parsers/uint8'
const schema = [
// part definitions...
{ someKey: readByte() }
];
// get the input file data
const data = new Uint8Array(fileArrayBuffer);
// create a stream object and parse it
const parsedObject = parse(buildStream(data), schema)
### Schemas
So far in this library there is only one built in schema, which is for the GIF format. You can import included schemas like:
import GIF from 'js-binary-schema-parser/lib/schemas/gif'
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.
### Example
var gifSchema = [
{
label: 'header', // gif header
parts: [
{ label: 'signature', parser: Parsers.readString(3) },
{ label: 'version', parser: Parsers.readString(3) }
]
},{
label: 'lsd', // local screen descriptor
parts: [
{ label: 'width', parser: Parsers.readUnsigned(true) },
{ label: 'height', parser: Parsers.readUnsigned(true) },
{ label: 'gct', bits: {
exists: { index: 0 },
resolution: { index: 1, length: 3 },
sort: { index: 4 },
size: { index: 5, length: 3 }
}},
{ label: 'backgroundColorIndex', parser: Parsers.readByte() },
{ label: 'pixelAspectRatio', parser: Parsers.readByte() }
]
}
];
### Why this parser?
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.
### Demo
You can see a full demo **[here][2]** which uses this lib to parse GIF files for manipulation.
### Who are we?
[Matt Way][3] & [Nick Drewe][5]
[Wethrift.com][6]
[1]: https://www.producthunt.com/posts/ruffle
[2]: https://github.com/matt-way/gifuct-js
[3]: https://twitter.com/_MattWay
[4]: https://github.com/jDataView/jBinary
[5]: https://twitter.com/nickdrewe
[6]: https://wethrift.com
import fs from 'fs'
import { parse } from '../src'
import { buildStream } from '../src/parsers/uint8'
import { GIF } from '../src/schemas'
debugger
const data = fs.readFileSync('./example/dog.gif')
const result = parse(buildStream(new Uint8Array(data)), GIF)
console.log(result)
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loop = exports.conditional = exports.parse = void 0;
var parse = function parse(stream, schema) {
var result = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var parent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : result;
if (Array.isArray(schema)) {
schema.forEach(function (partSchema) {
return parse(stream, partSchema, result, parent);
});
} else if (typeof schema === 'function') {
schema(stream, result, parent, parse);
} else {
var key = Object.keys(schema)[0];
if (Array.isArray(schema[key])) {
parent[key] = {};
parse(stream, schema[key], result, parent[key]);
} else {
parent[key] = schema[key](stream, result, parent, parse);
}
}
return result;
};
exports.parse = parse;
var conditional = function conditional(schema, conditionFunc) {
return function (stream, result, parent, parse) {
if (conditionFunc(stream, result, parent)) {
parse(stream, schema, result, parent);
}
};
};
exports.conditional = conditional;
var loop = function loop(schema, continueFunc) {
return function (stream, result, parent, parse) {
var arr = [];
var lastStreamPos = stream.pos;
while (continueFunc(stream, result, parent)) {
var newParent = {};
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
// it falls into infinite recursion, null check to avoid the same
if (stream.pos === lastStreamPos) {
break;
}
lastStreamPos = stream.pos;
arr.push(newParent);
}
return arr;
};
};
exports.loop = loop;
\ No newline at end of file
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.readBits = exports.readArray = exports.readUnsigned = exports.readString = exports.peekBytes = exports.readBytes = exports.peekByte = exports.readByte = exports.buildStream = void 0;
// Default stream and parsers for Uint8TypedArray data type
var buildStream = function buildStream(uint8Data) {
return {
data: uint8Data,
pos: 0
};
};
exports.buildStream = buildStream;
var readByte = function readByte() {
return function (stream) {
return stream.data[stream.pos++];
};
};
exports.readByte = readByte;
var peekByte = function peekByte() {
var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return function (stream) {
return stream.data[stream.pos + offset];
};
};
exports.peekByte = peekByte;
var readBytes = function readBytes(length) {
return function (stream) {
return stream.data.subarray(stream.pos, stream.pos += length);
};
};
exports.readBytes = readBytes;
var peekBytes = function peekBytes(length) {
return function (stream) {
return stream.data.subarray(stream.pos, stream.pos + length);
};
};
exports.peekBytes = peekBytes;
var readString = function readString(length) {
return function (stream) {
return Array.from(readBytes(length)(stream)).map(function (value) {
return String.fromCharCode(value);
}).join('');
};
};
exports.readString = readString;
var readUnsigned = function readUnsigned(littleEndian) {
return function (stream) {
var bytes = readBytes(2)(stream);
return littleEndian ? (bytes[1] << 8) + bytes[0] : (bytes[0] << 8) + bytes[1];
};
};
exports.readUnsigned = readUnsigned;
var readArray = function readArray(byteSize, totalOrFunc) {
return function (stream, result, parent) {
var total = typeof totalOrFunc === 'function' ? totalOrFunc(stream, result, parent) : totalOrFunc;
var parser = readBytes(byteSize);
var arr = new Array(total);
for (var i = 0; i < total; i++) {
arr[i] = parser(stream);
}
return arr;
};
};
exports.readArray = readArray;
var subBitsTotal = function subBitsTotal(bits, startIndex, length) {
var result = 0;
for (var i = 0; i < length; i++) {
result += bits[startIndex + i] && Math.pow(2, length - i - 1);
}
return result;
};
var readBits = function readBits(schema) {
return function (stream) {
var _byte = readByte()(stream); // convert the byte to bit array
var bits = new Array(8);
for (var i = 0; i < 8; i++) {
bits[7 - i] = !!(_byte & 1 << i);
} // convert the bit array to values based on the schema
return Object.keys(schema).reduce(function (res, key) {
var def = schema[key];
if (def.length) {
res[key] = subBitsTotal(bits, def.index, def.length);
} else {
res[key] = bits[def.index];
}
return res;
}, {});
};
};
exports.readBits = readBits;
\ No newline at end of file
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _ = require("../");
var _uint = require("../parsers/uint8");
// a set of 0x00 terminated subblocks
var subBlocksSchema = {
blocks: function blocks(stream) {
var terminator = 0x00;
var chunks = [];
var streamSize = stream.data.length;
var total = 0;
for (var size = (0, _uint.readByte)()(stream); size !== terminator; size = (0, _uint.readByte)()(stream)) {
// size becomes undefined for some case when file is corrupted and terminator is not proper
// null check to avoid recursion
if (!size) break; // catch corrupted files with no terminator
if (stream.pos + size >= streamSize) {
var availableSize = streamSize - stream.pos;
chunks.push((0, _uint.readBytes)(availableSize)(stream));
total += availableSize;
break;
}
chunks.push((0, _uint.readBytes)(size)(stream));
total += size;
}
var result = new Uint8Array(total);
var offset = 0;
for (var i = 0; i < chunks.length; i++) {
result.set(chunks[i], offset);
offset += chunks[i].length;
}
return result;
}
}; // global control extension
var gceSchema = (0, _.conditional)({
gce: [{
codes: (0, _uint.readBytes)(2)
}, {
byteSize: (0, _uint.readByte)()
}, {
extras: (0, _uint.readBits)({
future: {
index: 0,
length: 3
},
disposal: {
index: 3,
length: 3
},
userInput: {
index: 6
},
transparentColorGiven: {
index: 7
}
})
}, {
delay: (0, _uint.readUnsigned)(true)
}, {
transparentColorIndex: (0, _uint.readByte)()
}, {
terminator: (0, _uint.readByte)()
}]
}, function (stream) {
var codes = (0, _uint.peekBytes)(2)(stream);
return codes[0] === 0x21 && codes[1] === 0xf9;
}); // image pipeline block
var imageSchema = (0, _.conditional)({
image: [{
code: (0, _uint.readByte)()
}, {
descriptor: [{
left: (0, _uint.readUnsigned)(true)
}, {
top: (0, _uint.readUnsigned)(true)
}, {
width: (0, _uint.readUnsigned)(true)
}, {
height: (0, _uint.readUnsigned)(true)
}, {
lct: (0, _uint.readBits)({
exists: {
index: 0
},
interlaced: {
index: 1
},
sort: {
index: 2
},
future: {
index: 3,
length: 2
},
size: {
index: 5,
length: 3
}
})
}]
}, (0, _.conditional)({
lct: (0, _uint.readArray)(3, function (stream, result, parent) {
return Math.pow(2, parent.descriptor.lct.size + 1);
})
}, function (stream, result, parent) {
return parent.descriptor.lct.exists;
}), {
data: [{
minCodeSize: (0, _uint.readByte)()
}, subBlocksSchema]
}]
}, function (stream) {
return (0, _uint.peekByte)()(stream) === 0x2c;
}); // plain text block
var textSchema = (0, _.conditional)({
text: [{
codes: (0, _uint.readBytes)(2)
}, {
blockSize: (0, _uint.readByte)()
}, {
preData: function preData(stream, result, parent) {
return (0, _uint.readBytes)(parent.text.blockSize)(stream);
}
}, subBlocksSchema]
}, function (stream) {
var codes = (0, _uint.peekBytes)(2)(stream);
return codes[0] === 0x21 && codes[1] === 0x01;
}); // application block
var applicationSchema = (0, _.conditional)({
application: [{
codes: (0, _uint.readBytes)(2)
}, {
blockSize: (0, _uint.readByte)()
}, {
id: function id(stream, result, parent) {
return (0, _uint.readString)(parent.blockSize)(stream);
}
}, subBlocksSchema]
}, function (stream) {
var codes = (0, _uint.peekBytes)(2)(stream);
return codes[0] === 0x21 && codes[1] === 0xff;
}); // comment block
var commentSchema = (0, _.conditional)({
comment: [{
codes: (0, _uint.readBytes)(2)
}, subBlocksSchema]
}, function (stream) {
var codes = (0, _uint.peekBytes)(2)(stream);
return codes[0] === 0x21 && codes[1] === 0xfe;
});
var schema = [{
header: [{
signature: (0, _uint.readString)(3)
}, {
version: (0, _uint.readString)(3)
}]
}, {
lsd: [{
width: (0, _uint.readUnsigned)(true)
}, {
height: (0, _uint.readUnsigned)(true)
}, {
gct: (0, _uint.readBits)({
exists: {
index: 0
},
resolution: {
index: 1,
length: 3
},
sort: {
index: 4
},
size: {
index: 5,
length: 3
}
})
}, {
backgroundColorIndex: (0, _uint.readByte)()
}, {
pixelAspectRatio: (0, _uint.readByte)()
}]
}, (0, _.conditional)({
gct: (0, _uint.readArray)(3, function (stream, result) {
return Math.pow(2, result.lsd.gct.size + 1);
})
}, function (stream, result) {
return result.lsd.gct.exists;
}), // content frames
{
frames: (0, _.loop)([gceSchema, applicationSchema, commentSchema, imageSchema, textSchema], function (stream) {
var nextCode = (0, _uint.peekByte)()(stream); // rather than check for a terminator, we should check for the existence
// of an ext or image block to avoid infinite loops
//var terminator = 0x3B;
//return nextCode !== terminator;
return nextCode === 0x21 || nextCode === 0x2c;
})
}];
var _default = schema;
exports["default"] = _default;
\ No newline at end of file
{
"_from": "js-binary-schema-parser@^2.0.2",
"_id": "js-binary-schema-parser@2.0.3",
"_inBundle": false,
"_integrity": "sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==",
"_location": "/js-binary-schema-parser",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "js-binary-schema-parser@^2.0.2",
"name": "js-binary-schema-parser",
"escapedName": "js-binary-schema-parser",
"rawSpec": "^2.0.2",
"saveSpec": null,
"fetchSpec": "^2.0.2"
},
"_requiredBy": [
"/vue-qr"
],
"_resolved": "https://registry.npmmirror.com/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz",
"_shasum": "3d7848748e8586e63b34e8911b643f59cfb6396e",
"_spec": "js-binary-schema-parser@^2.0.2",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr",
"author": {
"name": "Matt Way"
},
"bugs": {
"url": "https://github.com/matt-way/jsBinarySchemaParser/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Parse binary files with a schema into nicely readable objects",
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.4",
"@babel/node": "^7.8.4",
"@babel/preset-env": "^7.8.4"
},
"homepage": "https://github.com/matt-way/jsBinarySchemaParser",
"keywords": [
"javascript",
"binary",
"file",
"parser",
"schema"
],
"license": "MIT",
"main": "lib/index.js",
"name": "js-binary-schema-parser",
"repository": {
"type": "git",
"url": "git+https://github.com/matt-way/jsBinarySchemaParser.git"
},
"scripts": {
"build": "babel src --out-dir lib",
"example": "babel-node ./example/index.js",
"example-debug": "babel-node --inspect-brk ./example/index.js"
},
"version": "2.0.3"
}
export const parse = (stream, schema, result = {}, parent = result) => {
if (Array.isArray(schema)) {
schema.forEach(partSchema => parse(stream, partSchema, result, parent))
} else if (typeof schema === 'function') {
schema(stream, result, parent, parse)
} else {
const key = Object.keys(schema)[0]
if (Array.isArray(schema[key])) {
parent[key] = {}
parse(stream, schema[key], result, parent[key])
} else {
parent[key] = schema[key](stream, result, parent, parse)
}
}
return result
}
export const conditional = (schema, conditionFunc) => (
stream,
result,
parent,
parse
) => {
if (conditionFunc(stream, result, parent)) {
parse(stream, schema, result, parent)
}
}
export const loop = (schema, continueFunc) => (
stream,
result,
parent,
parse
) => {
const arr = []
let lastStreamPos = stream.pos;
while (continueFunc(stream, result, parent)) {
const newParent = {}
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
// it falls into infinite recursion, null check to avoid the same
if(stream.pos === lastStreamPos) {
break
}
lastStreamPos = stream.pos
arr.push(newParent)
}
return arr
}
// Default stream and parsers for Uint8TypedArray data type
export const buildStream = uint8Data => ({
data: uint8Data,
pos: 0
})
export const readByte = () => stream => {
return stream.data[stream.pos++]
}
export const peekByte = (offset = 0) => stream => {
return stream.data[stream.pos + offset]
}
export const readBytes = length => stream => {
return stream.data.subarray(stream.pos, (stream.pos += length))
}
export const peekBytes = length => stream => {
return stream.data.subarray(stream.pos, stream.pos + length)
}
export const readString = length => stream => {
return Array.from(readBytes(length)(stream))
.map(value => String.fromCharCode(value))
.join('')
}
export const readUnsigned = littleEndian => stream => {
const bytes = readBytes(2)(stream)
return littleEndian ? (bytes[1] << 8) + bytes[0] : (bytes[0] << 8) + bytes[1]
}
export const readArray = (byteSize, totalOrFunc) => (
stream,
result,
parent
) => {
const total =
typeof totalOrFunc === 'function'
? totalOrFunc(stream, result, parent)
: totalOrFunc
const parser = readBytes(byteSize)
const arr = new Array(total)
for (var i = 0; i < total; i++) {
arr[i] = parser(stream)
}
return arr
}
const subBitsTotal = (bits, startIndex, length) => {
var result = 0
for (var i = 0; i < length; i++) {
result += bits[startIndex + i] && 2 ** (length - i - 1)
}
return result
}
export const readBits = schema => stream => {
const byte = readByte()(stream)
// convert the byte to bit array
const bits = new Array(8)
for (var i = 0; i < 8; i++) {
bits[7 - i] = !!(byte & (1 << i))
}
// convert the bit array to values based on the schema
return Object.keys(schema).reduce((res, key) => {
const def = schema[key]
if (def.length) {
res[key] = subBitsTotal(bits, def.index, def.length)
} else {
res[key] = bits[def.index]
}
return res
}, {})
}
import { conditional, loop } from '../'
import {
readByte,
peekByte,
readBytes,
peekBytes,
readString,
readUnsigned,
readArray,
readBits,
} from '../parsers/uint8'
// a set of 0x00 terminated subblocks
var subBlocksSchema = {
blocks: (stream) => {
const terminator = 0x00
const chunks = []
const streamSize = stream.data.length
var total = 0
for (
var size = readByte()(stream);
size !== terminator;
size = readByte()(stream)
) {
// size becomes undefined for some case when file is corrupted and terminator is not proper
// null check to avoid recursion
if(!size) break;
// catch corrupted files with no terminator
if (stream.pos + size >= streamSize) {
const availableSize = streamSize - stream.pos
chunks.push(readBytes(availableSize)(stream))
total += availableSize
break
}
chunks.push(readBytes(size)(stream))
total += size
}
const result = new Uint8Array(total)
var offset = 0
for (var i = 0; i < chunks.length; i++) {
result.set(chunks[i], offset)
offset += chunks[i].length
}
return result
},
}
// global control extension
const gceSchema = conditional(
{
gce: [
{ codes: readBytes(2) },
{ byteSize: readByte() },
{
extras: readBits({
future: { index: 0, length: 3 },
disposal: { index: 3, length: 3 },
userInput: { index: 6 },
transparentColorGiven: { index: 7 },
}),
},
{ delay: readUnsigned(true) },
{ transparentColorIndex: readByte() },
{ terminator: readByte() },
],
},
(stream) => {
var codes = peekBytes(2)(stream)
return codes[0] === 0x21 && codes[1] === 0xf9
}
)
// image pipeline block
const imageSchema = conditional(
{
image: [
{ code: readByte() },
{
descriptor: [
{ left: readUnsigned(true) },
{ top: readUnsigned(true) },
{ width: readUnsigned(true) },
{ height: readUnsigned(true) },
{
lct: readBits({
exists: { index: 0 },
interlaced: { index: 1 },
sort: { index: 2 },
future: { index: 3, length: 2 },
size: { index: 5, length: 3 },
}),
},
],
},
conditional(
{
lct: readArray(3, (stream, result, parent) => {
return Math.pow(2, parent.descriptor.lct.size + 1)
}),
},
(stream, result, parent) => {
return parent.descriptor.lct.exists
}
),
{ data: [{ minCodeSize: readByte() }, subBlocksSchema] },
],
},
(stream) => {
return peekByte()(stream) === 0x2c
}
)
// plain text block
const textSchema = conditional(
{
text: [
{ codes: readBytes(2) },
{ blockSize: readByte() },
{
preData: (stream, result, parent) =>
readBytes(parent.text.blockSize)(stream),
},
subBlocksSchema,
],
},
(stream) => {
var codes = peekBytes(2)(stream)
return codes[0] === 0x21 && codes[1] === 0x01
}
)
// application block
const applicationSchema = conditional(
{
application: [
{ codes: readBytes(2) },
{ blockSize: readByte() },
{ id: (stream, result, parent) => readString(parent.blockSize)(stream) },
subBlocksSchema,
],
},
(stream) => {
var codes = peekBytes(2)(stream)
return codes[0] === 0x21 && codes[1] === 0xff
}
)
// comment block
const commentSchema = conditional(
{
comment: [{ codes: readBytes(2) }, subBlocksSchema],
},
(stream) => {
var codes = peekBytes(2)(stream)
return codes[0] === 0x21 && codes[1] === 0xfe
}
)
const schema = [
{ header: [{ signature: readString(3) }, { version: readString(3) }] },
{
lsd: [
{ width: readUnsigned(true) },
{ height: readUnsigned(true) },
{
gct: readBits({
exists: { index: 0 },
resolution: { index: 1, length: 3 },
sort: { index: 4 },
size: { index: 5, length: 3 },
}),
},
{ backgroundColorIndex: readByte() },
{ pixelAspectRatio: readByte() },
],
},
conditional(
{
gct: readArray(3, (stream, result) =>
Math.pow(2, result.lsd.gct.size + 1)
),
},
(stream, result) => result.lsd.gct.exists
),
// content frames
{
frames: loop(
[gceSchema, applicationSchema, commentSchema, imageSchema, textSchema],
(stream) => {
var nextCode = peekByte()(stream)
// rather than check for a terminator, we should check for the existence
// of an ext or image block to avoid infinite loops
//var terminator = 0x3B;
//return nextCode !== terminator;
return nextCode === 0x21 || nextCode === 0x2c
}
),
},
]
export default schema
import {IncomingMessage} from 'http';
/**
Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
Makes `toStream` include the properties from `fromStream`.
@param fromStream - The stream to copy the properties from.
@param toStream - The stream to copy the properties to.
@return The same object as `toStream`.
*/
declare function mimicResponse<T extends NodeJS.ReadableStream>(
fromStream: IncomingMessage, // eslint-disable-line @typescript-eslint/prefer-readonly-parameter-types
toStream: T,
): T & IncomingMessage;
export = mimicResponse;
'use strict';
// We define these manually to ensure they're always copied
// even if they would move up the prototype chain
// https://nodejs.org/api/http.html#http_class_http_incomingmessage
const knownProperties = [
'aborted',
'complete',
'headers',
'httpVersion',
'httpVersionMinor',
'httpVersionMajor',
'method',
'rawHeaders',
'rawTrailers',
'setTimeout',
'socket',
'statusCode',
'statusMessage',
'trailers',
'url'
];
module.exports = (fromStream, toStream) => {
if (toStream._readableState.autoDestroy) {
throw new Error('The second stream must have the `autoDestroy` option set to `false`');
}
const fromProperties = new Set(Object.keys(fromStream).concat(knownProperties));
const properties = {};
for (const property of fromProperties) {
// Don't overwrite existing properties.
if (property in toStream) {
continue;
}
properties[property] = {
get() {
const value = fromStream[property];
const isFunction = typeof value === 'function';
return isFunction ? value.bind(fromStream) : value;
},
set(value) {
fromStream[property] = value;
},
enumerable: true,
configurable: false
};
}
Object.defineProperties(toStream, properties);
fromStream.once('aborted', () => {
toStream.destroy();
toStream.emit('aborted');
});
fromStream.once('close', () => {
if (fromStream.complete) {
if (toStream.readable) {
toStream.once('end', () => {
toStream.emit('close');
});
} else {
toStream.emit('close');
}
} else {
toStream.emit('close');
}
});
return toStream;
};
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
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:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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.
{
"_from": "mimic-response@^3.1.0",
"_id": "mimic-response@3.1.0",
"_inBundle": false,
"_integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"_location": "/mimic-response",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "mimic-response@^3.1.0",
"name": "mimic-response",
"escapedName": "mimic-response",
"rawSpec": "^3.1.0",
"saveSpec": null,
"fetchSpec": "^3.1.0"
},
"_requiredBy": [
"/decompress-response"
],
"_resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz",
"_shasum": "2d1d59af9c1b129815accc2c46a022a5ce1fa3c9",
"_spec": "mimic-response@^3.1.0",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/decompress-response",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/mimic-response/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Mimic a Node.js HTTP response stream",
"devDependencies": {
"@types/node": "^14.0.1",
"ava": "^2.4.0",
"create-test-server": "^2.4.0",
"p-event": "^4.1.0",
"pify": "^5.0.0",
"tsd": "^0.11.0",
"xo": "^0.30.0"
},
"engines": {
"node": ">=10"
},
"files": [
"index.d.ts",
"index.js"
],
"funding": "https://github.com/sponsors/sindresorhus",
"homepage": "https://github.com/sindresorhus/mimic-response#readme",
"keywords": [
"mimic",
"response",
"stream",
"http",
"https",
"request",
"get",
"core"
],
"license": "MIT",
"name": "mimic-response",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/mimic-response.git"
},
"scripts": {
"test": "xo && ava && tsd"
},
"version": "3.1.0"
}
# mimic-response [![Build Status](https://travis-ci.com/sindresorhus/mimic-response.svg?branch=master)](https://travis-ci.com/sindresorhus/mimic-response)
> Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
## Install
```
$ npm install mimic-response
```
## Usage
```js
const stream = require('stream');
const mimicResponse = require('mimic-response');
const responseStream = getHttpResponseStream();
const myStream = new stream.PassThrough();
mimicResponse(responseStream, myStream);
console.log(myStream.statusCode);
//=> 200
```
## API
### mimicResponse(from, to)
**Note #1:** The `from.destroy(error)` function is not proxied. You have to call it manually:
```js
const stream = require('stream');
const mimicResponse = require('mimic-response');
const responseStream = getHttpResponseStream();
const myStream = new stream.PassThrough({
destroy(error, callback) {
responseStream.destroy();
callback(error);
}
});
myStream.destroy();
```
Please note that `myStream` and `responseStream` never throws. The error is passed to the request instead.
#### from
Type: `Stream`
[Node.js HTTP response stream.](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
#### to
Type: `Stream`
Any stream.
## Related
- [mimic-fn](https://github.com/sindresorhus/mimic-fn) - Make a function mimic another one
- [clone-response](https://github.com/lukechilds/clone-response) - Clone a Node.js response stream
---
<div align="center">
<b>
<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>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>
The MIT License (MIT)
Copyright © 2016 Dmitry Ivanov
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:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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
# parenthesis [![Build Status](https://travis-ci.org/dy/parenthesis.svg?branch=master)](https://travis-ci.org/dy/parenthesis)
Parse parentheses from a string, return folded arrays.
[![npm install parenthesis](https://nodei.co/npm/parenthesis.png?mini=true)](https://npmjs.org/package/parenthesis/)
```js
var parse = require('parenthesis')
// Parse into nested format
parse('a(b[c{d}])')
// ['a(', ['b[', ['c{', ['d'], '}'], ']'], ')']
// Parse into flat format with cross-references
parse('a(b[c{d}])', {
brackets: ['()'],
escape: '\\',
flat: true
})
// ['a(\\1)', 'b[c{d}]']
// Stringify nested format
parse.stringify(['a(', ['b[', ['c{', ['d'], '}'], ']'], ')'])
// 'a(b[c{d}])'
// Stringify flat format with cross-references
parse.stringify(['a(\\1)', 'b[c{d}]'], {flat: true, escape: '\\'})
// 'a(b[c{d}])'
```
## API
### tokens = paren.parse(string, brackets|opts?)
Return array with tokens.
Option | Default | Meaning
---|---|---
`brackets` | `['{}', '[]', '()']` | Single brackets string or list of strings to detect brackets. Can be repeating brackets eg. `"" or ''`.
`escape` | `'___'` | Escape prefix for flat references.
`flat` | `false` | Return flat array instead of nested arrays.
### str = paren.stringify(tokens, {flat}?)
Stringify tokens back. Pass `{flat: true}` flag for flat tokens array.
## Related
* [balanced-match](http://npmjs.org/package/balanced-match)
## License
© 2018 Dmitry Yv. MIT License
declare module "parenthesis" {
namespace parens {
// One entry in the returned nested array
type Node = string | ArrayTree;
// A nested array of strings
interface ArrayTree extends Array<Node> {}
// Second-argument options used by the function
interface Opts {
// Single brackets string or list of strings to detect brackets. Can be repeating brackets eg. "" or ''.
brackets?: string | string[],
// Escape prefix for flat references.
escape?: string,
// `flat` is a boolean but since it affects return type, it's explicitly specified below
}
// Parse parentheses from a string, return folded arrays
function parse(
str: string,
opts?: string | string[] | (parens.Opts & { flat?: false })
): parens.ArrayTree;
// Parse parentheses from a string, return flat array
function parse(
str: string,
opts: (parens.Opts & { flat: true })
): string[];
// Stringify tokens back. Pass {flat: true} flag for flat tokens array.
function stringify(tokens: ArrayTree, opts?: {flat: boolean}): string;
}
// Parse parentheses from a string, return folded arrays
function parens(
str: string,
opts?: string | string[] | (parens.Opts & { flat?: false })
): parens.ArrayTree;
// Parse parentheses from a string, return flat array
function parens(
str: string,
opts: (parens.Opts & { flat: true })
): string[];
function parens(tokens: parens.ArrayTree, opts?: {flat: boolean}): string;
// imports via `import paren from "parenthesis", can call the export
// directly or use `paren.parse` / `paren.stringify`.
export = parens;
}
'use strict'
/**
* @module parenthesis
*/
function parse (str, opts) {
// pretend non-string parsed per-se
if (typeof str !== 'string') return [str]
var res = [str]
if (typeof opts === 'string' || Array.isArray(opts)) {
opts = {brackets: opts}
}
else if (!opts) opts = {}
var brackets = opts.brackets ? (Array.isArray(opts.brackets) ? opts.brackets : [opts.brackets]) : ['{}', '[]', '()']
var escape = opts.escape || '___'
var flat = !!opts.flat
brackets.forEach(function (bracket) {
// create parenthesis regex
var pRE = new RegExp(['\\', bracket[0], '[^\\', bracket[0], '\\', bracket[1], ']*\\', bracket[1]].join(''))
var ids = []
function replaceToken(token, idx, str){
// save token to res
var refId = res.push(token.slice(bracket[0].length, -bracket[1].length)) - 1
ids.push(refId)
return escape + refId + escape
}
res.forEach(function (str, i) {
var prevStr
// replace paren tokens till there’s none
var a = 0
while (str != prevStr) {
prevStr = str
str = str.replace(pRE, replaceToken)
if (a++ > 10e3) throw Error('References have circular dependency. Please, check them.')
}
res[i] = str
})
// wrap found refs to brackets
ids = ids.reverse()
res = res.map(function (str) {
ids.forEach(function (id) {
str = str.replace(new RegExp('(\\' + escape + id + '\\' + escape + ')', 'g'), bracket[0] + '$1' + bracket[1])
})
return str
})
})
var re = new RegExp('\\' + escape + '([0-9]+)' + '\\' + escape)
// transform references to tree
function nest (str, refs, escape) {
var res = [], match
var a = 0
while (match = re.exec(str)) {
if (a++ > 10e3) throw Error('Circular references in parenthesis')
res.push(str.slice(0, match.index))
res.push(nest(refs[match[1]], refs))
str = str.slice(match.index + match[0].length)
}
res.push(str)
return res
}
return flat ? res : nest(res[0], res)
}
function stringify (arg, opts) {
if (opts && opts.flat) {
var escape = opts && opts.escape || '___'
var str = arg[0], prevStr
// pretend bad string stringified with no parentheses
if (!str) return ''
var re = new RegExp('\\' + escape + '([0-9]+)' + '\\' + escape)
var a = 0
while (str != prevStr) {
if (a++ > 10e3) throw Error('Circular references in ' + arg)
prevStr = str
str = str.replace(re, replaceRef)
}
return str
}
return arg.reduce(function f (prev, curr) {
if (Array.isArray(curr)) {
curr = curr.reduce(f, '')
}
return prev + curr
}, '')
function replaceRef(match, idx){
if (arg[idx] == null) throw Error('Reference ' + idx + 'is undefined')
return arg[idx]
}
}
function parenthesis (arg, opts) {
if (Array.isArray(arg)) {
return stringify(arg, opts)
}
else {
return parse(arg, opts)
}
}
parenthesis.parse = parse
parenthesis.stringify = stringify
module.exports = parenthesis
{
"_from": "parenthesis@^3.1.5",
"_id": "parenthesis@3.1.8",
"_inBundle": false,
"_integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==",
"_location": "/parenthesis",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "parenthesis@^3.1.5",
"name": "parenthesis",
"escapedName": "parenthesis",
"rawSpec": "^3.1.5",
"saveSpec": null,
"fetchSpec": "^3.1.5"
},
"_requiredBy": [
"/string-split-by"
],
"_resolved": "https://registry.npmmirror.com/parenthesis/-/parenthesis-3.1.8.tgz",
"_shasum": "3457fccb8f05db27572b841dad9d2630b912f125",
"_spec": "parenthesis@^3.1.5",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/string-split-by",
"author": {
"name": "Dmitry Yv",
"email": "df.creative@gmail.com",
"url": "http://github.com/dy"
},
"bugs": {
"url": "https://github.com/dy/parenthesis/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Parse parentheses from a string",
"devDependencies": {
"tape": "^4.9.0"
},
"files": [
"index.js",
"index.d.ts"
],
"homepage": "https://github.com/dy/parenthesis",
"keywords": [
"paren",
"parenthesis",
"parse",
"brackets",
"parser",
"regexp",
"stringify",
"tokenizer",
"replace",
"csv",
"string"
],
"license": "MIT",
"main": "index.js",
"name": "parenthesis",
"repository": {
"type": "git",
"url": "git://github.com/dy/parenthesis.git"
},
"scripts": {
"test": "node test.js",
"test:browser": "budo test.js"
},
"types": "index.d.ts",
"version": "3.1.8"
}
language: node_js
node_js:
- lts/*
The MIT License (MIT)
Copyright (c) Feross Aboukhadijeh
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
# simple-concat [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
[travis-image]: https://img.shields.io/travis/feross/simple-concat/master.svg
[travis-url]: https://travis-ci.org/feross/simple-concat
[npm-image]: https://img.shields.io/npm/v/simple-concat.svg
[npm-url]: https://npmjs.org/package/simple-concat
[downloads-image]: https://img.shields.io/npm/dm/simple-concat.svg
[downloads-url]: https://npmjs.org/package/simple-concat
[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
[standard-url]: https://standardjs.com
### Super-minimalist version of [`concat-stream`](https://github.com/maxogden/concat-stream). Less than 15 lines!
## install
```
npm install simple-concat
```
## usage
This example is longer than the implementation.
```js
var s = new stream.PassThrough()
concat(s, function (err, buf) {
if (err) throw err
console.error(buf)
})
s.write('abc')
setTimeout(function () {
s.write('123')
}, 10)
setTimeout(function () {
s.write('456')
}, 20)
setTimeout(function () {
s.end('789')
}, 30)
```
## license
MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org).
/*! simple-concat. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
module.exports = function (stream, cb) {
var chunks = []
stream.on('data', function (chunk) {
chunks.push(chunk)
})
stream.once('end', function () {
if (cb) cb(null, Buffer.concat(chunks))
cb = null
})
stream.once('error', function (err) {
if (cb) cb(err)
cb = null
})
}
{
"_from": "simple-concat@^1.0.0",
"_id": "simple-concat@1.0.1",
"_inBundle": false,
"_integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
"_location": "/simple-concat",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "simple-concat@^1.0.0",
"name": "simple-concat",
"escapedName": "simple-concat",
"rawSpec": "^1.0.0",
"saveSpec": null,
"fetchSpec": "^1.0.0"
},
"_requiredBy": [
"/simple-get"
],
"_resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz",
"_shasum": "f46976082ba35c2263f1c8ab5edfe26c41c9552f",
"_spec": "simple-concat@^1.0.0",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/simple-get",
"author": {
"name": "Feross Aboukhadijeh",
"email": "feross@feross.org",
"url": "https://feross.org"
},
"bugs": {
"url": "https://github.com/feross/simple-concat/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Super-minimalist version of `concat-stream`. Less than 15 lines!",
"devDependencies": {
"standard": "*",
"tape": "^5.0.1"
},
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"homepage": "https://github.com/feross/simple-concat",
"keywords": [
"concat",
"concat-stream",
"concat stream"
],
"license": "MIT",
"main": "index.js",
"name": "simple-concat",
"repository": {
"type": "git",
"url": "git://github.com/feross/simple-concat.git"
},
"scripts": {
"test": "standard && tape test/*.js"
},
"version": "1.0.1"
}
var concat = require('../')
var stream = require('stream')
var test = require('tape')
test('basic', function (t) {
t.plan(2)
var s = new stream.PassThrough()
concat(s, function (err, buf) {
t.error(err)
t.deepEqual(buf, Buffer.from('abc123456789'))
})
s.write('abc')
setTimeout(function () {
s.write('123')
}, 10)
setTimeout(function () {
s.write('456')
}, 20)
setTimeout(function () {
s.end('789')
}, 30)
})
test('error', function (t) {
t.plan(2)
var s = new stream.PassThrough()
concat(s, function (err, buf) {
t.ok(err, 'got expected error')
t.ok(!buf)
})
s.write('abc')
setTimeout(function () {
s.write('123')
}, 10)
setTimeout(function () {
s.write('456')
}, 20)
setTimeout(function () {
s.emit('error', new Error('error'))
}, 30)
})
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: daily
labels:
- dependency
versioning-strategy: increase-if-necessary
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
labels:
- dependency
name: ci
'on':
- push
- pull_request
jobs:
test:
name: Node ${{ matrix.node }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
node:
- '14'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
- run: npm install
- run: npm run build --if-present
- run: npm test
The MIT License (MIT)
Copyright (c) Feross Aboukhadijeh
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
# simple-get [![ci][ci-image]][ci-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
[ci-image]: https://img.shields.io/github/workflow/status/feross/simple-get/ci/master
[ci-url]: https://github.com/feross/simple-get/actions
[npm-image]: https://img.shields.io/npm/v/simple-get.svg
[npm-url]: https://npmjs.org/package/simple-get
[downloads-image]: https://img.shields.io/npm/dm/simple-get.svg
[downloads-url]: https://npmjs.org/package/simple-get
[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
[standard-url]: https://standardjs.com
### Simplest way to make http get requests
## features
This module is the lightest possible wrapper on top of node.js `http`, but supporting these essential features:
- follows redirects
- automatically handles gzip/deflate responses
- supports HTTPS
- supports specifying a timeout
- supports convenience `url` key so there's no need to use `url.parse` on the url when specifying options
- composes well with npm packages for features like cookies, proxies, form data, & OAuth
All this in < 100 lines of code.
## install
```
npm install simple-get
```
## usage
Note, all these examples also work in the browser with [browserify](http://browserify.org/).
### simple GET request
Doesn't get easier than this:
```js
const get = require('simple-get')
get('http://example.com', function (err, res) {
if (err) throw err
console.log(res.statusCode) // 200
res.pipe(process.stdout) // `res` is a stream
})
```
### even simpler GET request
If you just want the data, and don't want to deal with streams:
```js
const get = require('simple-get')
get.concat('http://example.com', function (err, res, data) {
if (err) throw err
console.log(res.statusCode) // 200
console.log(data) // Buffer('this is the server response')
})
```
### POST, PUT, PATCH, HEAD, DELETE support
For `POST`, call `get.post` or use option `{ method: 'POST' }`.
```js
const get = require('simple-get')
const opts = {
url: 'http://example.com',
body: 'this is the POST body'
}
get.post(opts, function (err, res) {
if (err) throw err
res.pipe(process.stdout) // `res` is a stream
})
```
#### A more complex example:
```js
const get = require('simple-get')
get({
url: 'http://example.com',
method: 'POST',
body: 'this is the POST body',
// simple-get accepts all options that node.js `http` accepts
// See: http://nodejs.org/api/http.html#http_http_request_options_callback
headers: {
'user-agent': 'my cool app'
}
}, function (err, res) {
if (err) throw err
// All properties/methods from http.IncomingResponse are available,
// even if a gunzip/inflate transform stream was returned.
// See: http://nodejs.org/api/http.html#http_http_incomingmessage
res.setTimeout(10000)
console.log(res.headers)
res.on('data', function (chunk) {
// `chunk` is the decoded response, after it's been gunzipped or inflated
// (if applicable)
console.log('got a chunk of the response: ' + chunk)
}))
})
```
### JSON
You can serialize/deserialize request and response with JSON:
```js
const get = require('simple-get')
const opts = {
method: 'POST',
url: 'http://example.com',
body: {
key: 'value'
},
json: true
}
get.concat(opts, function (err, res, data) {
if (err) throw err
console.log(data.key) // `data` is an object
})
```
### Timeout
You can set a timeout (in milliseconds) on the request with the `timeout` option.
If the request takes longer than `timeout` to complete, then the entire request
will fail with an `Error`.
```js
const get = require('simple-get')
const opts = {
url: 'http://example.com',
timeout: 2000 // 2 second timeout
}
get(opts, function (err, res) {})
```
### One Quick Tip
It's a good idea to set the `'user-agent'` header so the provider can more easily
see how their resource is used.
```js
const get = require('simple-get')
const pkg = require('./package.json')
get('http://example.com', {
headers: {
'user-agent': `my-module/${pkg.version} (https://github.com/username/my-module)`
}
})
```
### Proxies
You can use the [`tunnel`](https://github.com/koichik/node-tunnel) module with the
`agent` option to work with proxies:
```js
const get = require('simple-get')
const tunnel = require('tunnel')
const opts = {
url: 'http://example.com',
agent: tunnel.httpOverHttp({
proxy: {
host: 'localhost'
}
})
}
get(opts, function (err, res) {})
```
### Cookies
You can use the [`cookie`](https://github.com/jshttp/cookie) module to include
cookies in a request:
```js
const get = require('simple-get')
const cookie = require('cookie')
const opts = {
url: 'http://example.com',
headers: {
cookie: cookie.serialize('foo', 'bar')
}
}
get(opts, function (err, res) {})
```
### Form data
You can use the [`form-data`](https://github.com/form-data/form-data) module to
create POST request with form data:
```js
const fs = require('fs')
const get = require('simple-get')
const FormData = require('form-data')
const form = new FormData()
form.append('my_file', fs.createReadStream('/foo/bar.jpg'))
const opts = {
url: 'http://example.com',
body: form
}
get.post(opts, function (err, res) {})
```
#### Or, include `application/x-www-form-urlencoded` form data manually:
```js
const get = require('simple-get')
const opts = {
url: 'http://example.com',
form: {
key: 'value'
}
}
get.post(opts, function (err, res) {})
```
### Specifically disallowing redirects
```js
const get = require('simple-get')
const opts = {
url: 'http://example.com/will-redirect-elsewhere',
followRedirects: false
}
// res.statusCode will be 301, no error thrown
get(opts, function (err, res) {})
```
### Basic Auth
```js
const user = 'someuser'
const pass = 'pa$$word'
const encodedAuth = Buffer.from(`${user}:${pass}`).toString('base64')
get('http://example.com', {
headers: {
authorization: `Basic ${encodedAuth}`
}
})
```
### OAuth
You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) module to create
a signed OAuth request:
```js
const get = require('simple-get')
const crypto = require('crypto')
const OAuth = require('oauth-1.0a')
const oauth = OAuth({
consumer: {
key: process.env.CONSUMER_KEY,
secret: process.env.CONSUMER_SECRET
},
signature_method: 'HMAC-SHA1',
hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
})
const token = {
key: process.env.ACCESS_TOKEN,
secret: process.env.ACCESS_TOKEN_SECRET
}
const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json'
const opts = {
url: url,
headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
json: true
}
get(opts, function (err, res) {})
```
### Throttle requests
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.
```js
const simpleGet = require('simple-get')
const RateLimiter = require('limiter').RateLimiter
const limiter = new RateLimiter(1, 'second')
const get = (opts, cb) => limiter.removeTokens(1, () => simpleGet(opts, cb))
get.concat = (opts, cb) => limiter.removeTokens(1, () => simpleGet.concat(opts, cb))
var opts = {
url: 'http://example.com'
}
get.concat(opts, processResult)
get.concat(opts, processResult)
function processResult (err, res, data) {
if (err) throw err
console.log(data.toString())
}
```
## license
MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org).
/*! simple-get. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
module.exports = simpleGet
const concat = require('simple-concat')
const decompressResponse = require('decompress-response') // excluded from browser build
const http = require('http')
const https = require('https')
const once = require('once')
const querystring = require('querystring')
const url = require('url')
const isStream = o => o !== null && typeof o === 'object' && typeof o.pipe === 'function'
function simpleGet (opts, cb) {
opts = Object.assign({ maxRedirects: 10 }, typeof opts === 'string' ? { url: opts } : opts)
cb = once(cb)
if (opts.url) {
const { hostname, port, protocol, auth, path } = url.parse(opts.url) // eslint-disable-line node/no-deprecated-api
delete opts.url
if (!hostname && !port && !protocol && !auth) opts.path = path // Relative redirect
else Object.assign(opts, { hostname, port, protocol, auth, path }) // Absolute redirect
}
const headers = { 'accept-encoding': 'gzip, deflate' }
if (opts.headers) Object.keys(opts.headers).forEach(k => (headers[k.toLowerCase()] = opts.headers[k]))
opts.headers = headers
let body
if (opts.body) {
body = opts.json && !isStream(opts.body) ? JSON.stringify(opts.body) : opts.body
} else if (opts.form) {
body = typeof opts.form === 'string' ? opts.form : querystring.stringify(opts.form)
opts.headers['content-type'] = 'application/x-www-form-urlencoded'
}
if (body) {
if (!opts.method) opts.method = 'POST'
if (!isStream(body)) opts.headers['content-length'] = Buffer.byteLength(body)
if (opts.json && !opts.form) opts.headers['content-type'] = 'application/json'
}
delete opts.body; delete opts.form
if (opts.json) opts.headers.accept = 'application/json'
if (opts.method) opts.method = opts.method.toUpperCase()
const originalHost = opts.hostname // hostname before potential redirect
const protocol = opts.protocol === 'https:' ? https : http // Support http/https urls
const req = protocol.request(opts, res => {
if (opts.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
opts.url = res.headers.location // Follow 3xx redirects
delete opts.headers.host // Discard `host` header on redirect (see #32)
res.resume() // Discard response
const redirectHost = url.parse(opts.url).hostname // eslint-disable-line node/no-deprecated-api
// If redirected host is different than original host, drop headers to prevent cookie leak (#73)
if (redirectHost !== null && redirectHost !== originalHost) {
delete opts.headers.cookie
delete opts.headers.authorization
}
if (opts.method === 'POST' && [301, 302].includes(res.statusCode)) {
opts.method = 'GET' // On 301/302 redirect, change POST to GET (see #35)
delete opts.headers['content-length']; delete opts.headers['content-type']
}
if (opts.maxRedirects-- === 0) return cb(new Error('too many redirects'))
else return simpleGet(opts, cb)
}
const tryUnzip = typeof decompressResponse === 'function' && opts.method !== 'HEAD'
cb(null, tryUnzip ? decompressResponse(res) : res)
})
req.on('timeout', () => {
req.abort()
cb(new Error('Request timed out'))
})
req.on('error', cb)
if (isStream(body)) body.on('error', cb).pipe(req)
else req.end(body)
return req
}
simpleGet.concat = (opts, cb) => {
return simpleGet(opts, (err, res) => {
if (err) return cb(err)
concat(res, (err, data) => {
if (err) return cb(err)
if (opts.json) {
try {
data = JSON.parse(data.toString())
} catch (err) {
return cb(err, res, data)
}
}
cb(null, res, data)
})
})
}
;['get', 'post', 'put', 'patch', 'head', 'delete'].forEach(method => {
simpleGet[method] = (opts, cb) => {
if (typeof opts === 'string') opts = { url: opts }
return simpleGet(Object.assign({ method: method.toUpperCase() }, opts), cb)
}
})
{
"_from": "simple-get@^4.0.1",
"_id": "simple-get@4.0.1",
"_inBundle": false,
"_integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
"_location": "/simple-get",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "simple-get@^4.0.1",
"name": "simple-get",
"escapedName": "simple-get",
"rawSpec": "^4.0.1",
"saveSpec": null,
"fetchSpec": "^4.0.1"
},
"_requiredBy": [
"/vue-qr"
],
"_resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-4.0.1.tgz",
"_shasum": "4a39db549287c979d352112fa03fd99fd6bc3543",
"_spec": "simple-get@^4.0.1",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr",
"author": {
"name": "Feross Aboukhadijeh",
"email": "feross@feross.org",
"url": "https://feross.org"
},
"browser": {
"decompress-response": false
},
"bugs": {
"url": "https://github.com/feross/simple-get/issues"
},
"bundleDependencies": false,
"dependencies": {
"decompress-response": "^6.0.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
},
"deprecated": false,
"description": "Simplest way to make http get requests. Supports HTTPS, redirects, gzip/deflate, streams in < 100 lines.",
"devDependencies": {
"self-signed-https": "^1.0.5",
"standard": "*",
"string-to-stream": "^3.0.0",
"tape": "^5.0.0"
},
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"homepage": "https://github.com/feross/simple-get",
"keywords": [
"request",
"http",
"GET",
"get request",
"http.get",
"redirects",
"follow redirects",
"gzip",
"deflate",
"https",
"http-https",
"stream",
"simple request",
"simple get"
],
"license": "MIT",
"main": "index.js",
"name": "simple-get",
"repository": {
"type": "git",
"url": "git://github.com/feross/simple-get.git"
},
"scripts": {
"test": "standard && tape test/*.js"
},
"version": "4.0.1"
}
{
"env": {
"browser": true,
"node": true,
"commonjs": true,
"es6": true
},
"extends": "eslint:recommended",
"rules": {
"strict": 2,
"indent": 0,
"linebreak-style": 0,
"quotes": 0,
"semi": 0,
"no-cond-assign": 1,
"no-constant-condition": 1,
"no-duplicate-case": 1,
"no-empty": 1,
"no-ex-assign": 1,
"no-extra-boolean-cast": 1,
"no-extra-semi": 1,
"no-fallthrough": 1,
"no-func-assign": 1,
"no-global-assign": 1,
"no-implicit-globals": 2,
"no-inner-declarations": ["error", "functions"],
"no-irregular-whitespace": 2,
"no-loop-func": 1,
"no-magic-numbers": ["warn", { "ignore": [1, 0, -1], "ignoreArrayIndexes": true}],
"no-multi-str": 1,
"no-mixed-spaces-and-tabs": 1,
"no-proto": 1,
"no-sequences": 1,
"no-throw-literal": 1,
"no-unmodified-loop-condition": 1,
"no-useless-call": 1,
"no-void": 1,
"no-with": 2,
"wrap-iife": 1,
"no-redeclare": 1,
"no-unused-vars": ["error", { "vars": "all", "args": "none" }],
"no-sparse-arrays": 1
}
}
language: node_js
node_js:
- '6'
- '5'
- '4'
'use strict'
var paren = require('parenthesis')
module.exports = function splitBy (string, separator, o) {
if (string == null) throw Error('First argument should be a string')
if (separator == null) throw Error('Separator should be a string or a RegExp')
if (!o) o = {}
else if (typeof o === 'string' || Array.isArray(o)) {
o = {ignore: o}
}
if (o.escape == null) o.escape = true
if (o.ignore == null) o.ignore = ['[]', '()', '{}', '<>', '""', "''", '``', '“”', '«»']
else {
if (typeof o.ignore === 'string') {o.ignore = [o.ignore]}
o.ignore = o.ignore.map(function (pair) {
// '"' → '""'
if (pair.length === 1) pair = pair + pair
return pair
})
}
var tokens = paren.parse(string, {flat: true, brackets: o.ignore})
var str = tokens[0]
var parts = str.split(separator)
// join parts separated by escape
if (o.escape) {
var cleanParts = []
for (var i = 0; i < parts.length; i++) {
var prev = parts[i]
var part = parts[i + 1]
if (prev[prev.length - 1] === '\\' && prev[prev.length - 2] !== '\\') {
cleanParts.push(prev + separator + part)
i++
}
else {
cleanParts.push(prev)
}
}
parts = cleanParts
}
// open parens pack & apply unquotes, if any
for (var i = 0; i < parts.length; i++) {
tokens[0] = parts[i]
parts[i] = paren.stringify(tokens, {flat: true})
}
return parts
}
{
"_from": "string-split-by@^1.0.0",
"_id": "string-split-by@1.0.0",
"_inBundle": false,
"_integrity": "sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==",
"_location": "/string-split-by",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "string-split-by@^1.0.0",
"name": "string-split-by",
"escapedName": "string-split-by",
"rawSpec": "^1.0.0",
"saveSpec": null,
"fetchSpec": "^1.0.0"
},
"_requiredBy": [
"/vue-qr"
],
"_resolved": "https://registry.npmmirror.com/string-split-by/-/string-split-by-1.0.0.tgz",
"_shasum": "53895fb3397ebc60adab1f1e3a131f5372586812",
"_spec": "string-split-by@^1.0.0",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr",
"author": {
"name": "Dmitry Yv",
"email": "dfcreative@gmail.com"
},
"bugs": {
"url": "https://github.com/dy/string-split-by/issues"
},
"bundleDependencies": false,
"dependencies": {
"parenthesis": "^3.1.5"
},
"deprecated": false,
"description": "Split string by any separator excluding brackets, quotes and escaped characters",
"devDependencies": {
"tape": "^4.9.0"
},
"homepage": "https://github.com/dy/string-split-by#readme",
"keywords": [
"split-string",
"string-split",
"split-stirng-words",
"space",
"string",
"split"
],
"license": "MIT",
"main": "index.js",
"name": "string-split-by",
"repository": {
"type": "git",
"url": "git+https://github.com/dy/string-split-by.git"
},
"scripts": {
"test": "node test.js"
},
"version": "1.0.0"
}
# string-split-by [![unstable](https://img.shields.io/badge/stability-unstable-orange.svg)](http://github.com/badges/stability-badges) [![Build Status](https://img.shields.io/travis/dy/string-split-by.svg)](https://travis-ci.org/dy/string-split-by)
Split string by a separator with respect to brackets, quotes and escape markers. Optimized version of [string-split](https://github.com/jonschlinkert/split-string).
## Usage
[![npm install string-split-by](https://nodei.co/npm/string-split-by.png?mini=true)](https://npmjs.org/package/string-split-by/)
```js
var split = require('string-split-by')
split('a."b.c".d.{.e.f.g.}.h', '.')
// ['a', '"b.c"', 'd', '{.e.f.g.}', 'h']
split('a."b.c".d.{.e.f.g.}.h', '.', {ignore: '""'})
// ['a', '"b.c"', 'd', '{', 'e', 'f', 'g', '}', 'h']
```
## API
### parts = splitBy(string, separator, options?)
Return array with parts split from string by a separator, which can be whether _String_ or _RegExp_. Options can define:
Option | Default | Meaning
---|---|---
`ignore` | ``['"', "'", '`', '“”', '«»', '[]', '()', '{}']`` | Avoid splitting content enclosed in the character pairs. Can be a string or a list of strings.
`escape` | `true` | Avoid splitting at the escaped separator, eg. `\.` won't be separated by `'.'` separator.
## Related
* [parenthesis](http://npmjs.org/package/parenthesis)
## License
© 2018 Dmitry Yv. MIT License
'use strict';
var t = require('tape')
var split = require('.');
t('should throw an error when arguments are invalid', t => {
t.throws(() => split());
t.end()
});
t('readme', t => {
t.deepEqual(
split('a."b.c".d.{.e.f.g.}.h', '.'),
['a', '"b.c"', 'd', '{.e.f.g.}', 'h']
)
t.deepEqual(
split('a."b.c".d.{.e.f.g.}.h', '.', {ignore: '""'}),
['a', '"b.c"', 'd', '{', 'e', 'f', 'g', '}', 'h']
)
t.end()
})
t('should not split on escaped dots:', t => {
t.deepEqual(split('a.b.c\\.d', '.'), ['a', 'b', 'c\\.d']);
t.deepEqual(split('a.b.c\\.d.e', '.'), ['a', 'b', 'c\\.d', 'e']);
t.end()
});
t('should keep escaping when followed by a backslash:', t => {
t.deepEqual(split('a.b.c\\\\.d', '.'), ['a', 'b', 'c\\\\', 'd']);
t.deepEqual(split('a.b.c\\\\d', '.'), ['a', 'b', 'c\\\\d']);
t.end()
});
t('should split a string on dots by default:', t => {
t.deepEqual(split('a.b.c', '.'), ['a', 'b', 'c']);
t.end()
});
t('should respect double-quoted strings', t => {
t.deepEqual(split('"b.c"', '.'), ['"b.c"']);
t.deepEqual(split('a."b.c"', '.'), ['a', '"b.c"']);
t.deepEqual(split('a".b.c"', '.'), ['a".b.c"']);
t.deepEqual(split('a."b.c".d', '.'), ['a', '"b.c"', 'd']);
t.deepEqual(split('a."b.c".d.".e.f.g.".h', '.'), ['a', '"b.c"', 'd', '".e.f.g."', 'h']);
t.end()
});
t('should respect singlequoted strings', t => {
t.deepEqual(split('\'b.c\'', '.'), ['\'b.c\'']);
t.deepEqual(split('a.\'b.c\'', '.'), ['a', '\'b.c\'']);
t.deepEqual(split('a.\'b.c\'.d', '.'), ['a', '\'b.c\'', 'd']);
t.deepEqual(split('a.\'b.c\'.d.\'.e.f.g.\'.h', '.'), ['a', '\'b.c\'', 'd', '\'.e.f.g.\'', 'h']);
t.end()
});
t('should respect strings in backticks', t => {
t.deepEqual(split('`b.c`', '.'), ['`b.c`']);
t.deepEqual(split('a.`b.c`', '.'), ['a', '`b.c`']);
t.deepEqual(split('a.`b.c`.d', '.'), ['a', '`b.c`', 'd']);
t.deepEqual(split('a.`b.c`.d.`.e.f.g.`.h', '.'), ['a', '`b.c`', 'd', '`.e.f.g.`', 'h']);
t.end()
});
t('should respect strings in double smart-quotes: “”', t => {
t.deepEqual(split('“b.c”', '.'), ['“b.c”']);
t.deepEqual(split('a.“b.c”', '.'), ['a', '“b.c”']);
t.deepEqual(split('a.“b.c”.d', '.'), ['a', '“b.c”', 'd']);
t.deepEqual(split('a.“b.c”.d.“.e.f.g.”.h', '.'), ['a', '“b.c”', 'd', '“.e.f.g.”', 'h']);
t.end()
});
t('should retain unclosed double quotes in the results', t => {
t.deepEqual(split('a."b.c', '.'), ['a', '"b', 'c']);
t.end()
});
t('should retain unclosed single quotes in the results', t => {
t.deepEqual(split('brian\'s', '.'), ['brian\'s']);
t.deepEqual(split('a.\'b.c', '.'), ['a', '\'b', 'c']);
t.end()
});
t('should split on a custom separator', t => {
t.deepEqual(split('a/b/c', '/'), ['a', 'b', 'c']);
t.deepEqual(split('a,b,c', ','), ['a', 'b', 'c']);
t.end()
});
t('should not split on an escaped custom separator:', t => {
t.deepEqual(split('a/b/c\\/d', '/'), ['a', 'b', 'c\\/d']);
t.end()
});
t('should disable quotes support', t => {
t.deepEqual(split('a.\'b.c\'."d"', '.', {ignore: '"'}), ['a', '\'b', 'c\'', '"d"']);
t.end()
});
t('should keep single quotes', t => {
t.deepEqual(split('a.\'b.c\'."d"', '.', {ignore: '\''}), ['a', '\'b.c\'', '"d"']);
t.end()
});
t('should keep double quotes', t => {
t.deepEqual(split('a."b.c".d', '.', '"'), ['a', '"b.c"', 'd']);
t.end()
});
t('should keep “” double quotes', t => {
t.deepEqual(split('a.“b.c”.d', '.', '“”'), ['a', '“b.c”', 'd']);
t.end()
});
t('should keep backticks', t => {
t.deepEqual(split('a.`b.c`.d', '.', {ignore: '`'}), ['a', '`b.c`', 'd']);
t.end()
});
t('should allow custom quotes object', t => {
t.deepEqual(split('a.^b.c$', '.', {ignore: '^$'}), ['a', '^b.c$']);
t.deepEqual(split('a.^b.c^', '.', {ignore: '^^'}), ['a', '^b.c^']);
t.deepEqual(split('a.~b.c~', '.', {ignore: '~~'}), ['a', '~b.c~']);
t.end()
});
t('should keep escape characters', t => {
t.deepEqual(split('a.b\\.c', '.', {escape: true}), ['a', 'b\\.c']);
t.end()
});
t.skip('should throw when brackets are unclosed', t => {
t.throws(function() {
}, /unclosed/);
t.end()
});
t('should not split inside brackets', t => {
t.deepEqual(split('a.(b.c).d', '.'), ['a', '(b.c)', 'd']);
t.deepEqual(split('a.[(b.c)].d', '.'), ['a', '[(b.c)]', 'd']);
t.deepEqual(split('a.[b.c].d', '.'), ['a', '[b.c]', 'd']);
t.deepEqual(split('a.{b.c}.d', '.'), ['a', '{b.c}', 'd']);
t.deepEqual(split('a.<b.c>.d', '.'), ['a', '<b.c>', 'd']);
t.end()
});
t('should support nested brackets', t => {
t.deepEqual(split('a.{b.{c}.d}.e', '.'), ['a', '{b.{c}.d}', 'e']);
t.deepEqual(split('a.{b.{c.d}.e}.f', '.'), ['a', '{b.{c.d}.e}', 'f']);
t.deepEqual(split('a.{[b.{{c.d}}.e]}.f', '.'), ['a', '{[b.{{c.d}}.e]}', 'f']);
t.end()
});
t.skip('should support escaped brackets', t => {
t.deepEqual(split('a.\\{b.{c.c}.d}.e', '.'), ['a', '{b', '{c.c}', 'd}', 'e']);
t.deepEqual(split('a.{b.c}.\\{d.e}.f', '.'), ['a', '{b.c}', '{d', 'e}', 'f']);
t.end()
});
t('should support quoted brackets', t => {
t.deepEqual(split('a.{b.c}."{d.e}".f', '.'), ['a', '{b.c}', '"{d.e}"', 'f']);
t.deepEqual(split('a.{b.c}.{"d.e"}.f', '.'), ['a', '{b.c}', '{"d.e"}', 'f']);
t.end()
});
t('should ignore imbalanced brackets', t => {
t.deepEqual(split('a.{b.c', '.'), ['a', '{b', 'c']);
t.deepEqual(split('a.{a.{b.c}.d', '.'), ['a', '{a', '{b.c}', 'd']);
t.end()
});
{
"presets": [
[
"@babel/preset-env",
{
"modules": false
}
]
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{}
],
"@babel/plugin-proposal-class-properties"
]
}
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
module.exports = {
plugins: {
autoprefixer: {}
}
}
\ No newline at end of file
# Changelog
## 4.0.9 | 2022.05.24
- Fix `path-browserify` export error
## 4.0.6 | 2022.04.14
- Fix dependency error position
## 4.0.5 | 2022.04.13
- Remove `canvas` dependency
## 3.2.4 | 2022.01.19
- Update `canvas` version
## 3.2.2 | 2021.10.13
- Bugfix: components default value [#100](https://github.com/Binaryify/vue-qr/pull/100)
- Update `components` default value
## 3.2.0 | 2021.10.12
- Add `components` params [#98](https://github.com/Binaryify/vue-qr/issues/98)
## 3.1.0 | 2021.10.05
- Support Vite [#90](https://github.com/Binaryify/vue-qr/issues/90) [#96](https://github.com/Binaryify/vue-qr/issues/96)
## 3.0.0 | 2021.10.02
- Using Awesome-qr.js v2.0
- Support Vue v3.0(not support Vite yet) [#82](https://github.com/Binaryify/vue-qr/issues/82)
## 2.3.1 | 2021.05.03
- Fixed [#86](https://github.com/Binaryify/vue-qr/issues/86)
## 2.3.0 | 2020.10.05
- Support SSR
## 2.2.0
- Fixed [#65](https://github.com/Binaryify/vue-qr/issues/65) [#68](https://github.com/Binaryify/vue-qr/issues/68)
- Set `dotScale` default value to 1
## 2.1.0
- 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))
## 2.0.7
- Improve image load function
## 2.0.6
- Remove babel-polyfill [#53](https://github.com/Binaryify/vue-qr/issues/53)
- add .npmignore
## 2.0.4
- Fix dotScale defalut value bug
## 2.0.2
- Fix bug
## 2.0.2
- Update README.MD
## 2.0.1
- Fix colorLight can't set bug
- Support background color and logo background
## 2.0.0
- Refactoring
- Support gif background
The MIT License (MIT)
Copyright (c) 2013-2022 Binaryify
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:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
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.
# vue-qr
<a href="https://www.npmjs.com/package/vue-qr"><img src="https://img.shields.io/npm/v/vue-qr.svg" alt="Version"></a>
<a href="https://www.npmjs.com/package/vue-qr"><img src="https://img.shields.io/npm/l/vue-qr.svg" alt="License"></a>
The Vue Component for [SumiMakito's Awesome-qr.js](https://github.com/SumiMakito/Awesome-qr.js). Support Vue2/Vue3/Vite
The only one qr code component for Vue.js you need !
### Notice
Not support IE 不支持IE浏览器
### Examples, 样例
> Try to scan these QR codes below with your smart phone.
Example 1|Example 2|Example 3|Example 4
------------ | ------------- | -------------| -------------
<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">
### Demo
Run `npm run dev` or `yarn dev`
运行 `npm run dev` or `yarn dev`
## Installation
**install with NPM**
```bash
npm install vue-qr --save
```
**Import**
```js
// vue2.0
import VueQr from 'vue-qr'
// vue3.0 (support vite)
import vueQr from 'vue-qr/src/packages/vue-qr.vue'
...
{
components: {VueQr}
}
```
## Usage
**In template**
```html
<vue-qr :bgSrc='src' :logoSrc="src2" text="Hello world!" :size="200"></vue-qr>
<vue-qr text="Hello world!" :callback="test" qid="testid"></vue-qr>
```
```js
export default {
methods:{
test(dataUrl,id){
console.log(url, id)
}
}
}
```
Parameter | Explanation
----|----
text | Contents to encode. 欲编码的内容
correctLevel| Correct Level 0-3 容错级别 0-3
size | Width as well as the height of the output QR code, includes margin. 尺寸, 长宽一致, 包含外边距
margin | Margin to add around the QR code, default 20px. 二维码图像的外边距, 默认 20px
colorDark | Color of "true" blocks. Works only when both colorDark and colorLight are set. (BYTE_DTA, BYTE_POS, BYTE_AGN, BYTE_TMG) 实点的颜色
colorLight | Color of empty space, or "false" blocks. Works only when both colorDark and colorLight are set. (BYTE_EPT) 空白区的颜色
components | Controls the appearances of parts in the QR code. Read section [ComponentOptions](#componentoptions) to learn more. 阅读 [ComponentOptions](#componentoptions) 了解更多信息。
bgSrc | Background url to embed in the QR code. 欲嵌入的背景图地址
gifBgSrc | Gif background url to embed in the QR code, If gifBackground is set, backgroundImage will be ignored. This option will affects performance. 欲嵌入的背景图 gif 地址,设置后普通的背景图将失效。设置此选项会影响性能
backgroundColor | Background color 背景色
backgroundDimming | Color mask to add above the background image. Helpful when having problems with decoding. 叠加在背景图上的颜色, 在解码有难度的时有一定帮助
logoSrc | Logo url to embed at the center of generated QR code 嵌入至二维码中心的 LOGO 地址
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
logoMargin | White margin that appears around the logo image. Default is 0. LOGO 标识周围的空白边框, 默认为0
logoBackgroundColor | Logo background color, need set logo margin. Logo 背景色,需要设置 logo margin
logoCornerRadius | Radius of the logo's corners.Default is 0 LOGO 标识及其边框的圆角半径, 默认为0
whiteMargin | If set to true, a white border will appear around the background image. Default is true. 若设为 true, 背景图外将绘制白色边框
dotScale | Value used to scale down the data dots' size. (0 < scale < 1.0) default 1 数据区域点缩小比例,默认为1
autoColor | If set to true, the dominant color of backgroundImage will be used as colorDark. Default is true. 若为 true, 背景图的主要颜色将作为实点的颜色, 即 colorDark,默认 true
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, 图像将被二值化处理, 未指定阈值则使用默认值
binarizeThreshold | Threshold used to binarize the whole image. Default is 128. (0 < threshold < 255) 二值化处理的阈值
callback | Data URI of the generated QR code will be available here. 生成的二维码 Data URI 可以在回调中取得,第一个参数为二维码 data URL, 第二个参数为 props 传过来的 qid(因为二维码生成是异步的,所以加个 id 用于排序)
bindElement | If set to true, the generated QR will bind to a HTML element automatically. Default is true. 指定是否需要自动将生成的二维码绑定到HTML上, 默认是true
## ComponentOptions
> _ComponentOptions_ controls the appearances of parts in the QR code.组件选项控制二维码中零件的外观。
```ts
type ComponentOptions = {
data?: {
scale?: number;
};
timing?: {
scale?: number;
protectors?: boolean;
};
alignment?: {
scale?: number;
protectors?: boolean;
};
cornerAlignment?: {
scale?: number;
protectors?: boolean;
};
};
```
```ts
// default ComponentOptions
{
data: {
scale: 1,
},
timing: {
scale: 1,
protectors: false,
},
alignment: {
scale: 1,
protectors: false,
},
cornerAlignment: {
scale: 1,
protectors: true,
},
}
```
### scale 比例尺
Type number?
Scale factor for blocks in the specified area of the QR code.
在 QR 码指定区域的块的比例。
### protectors
**Type** `boolean?`
Controls whether or not to draw the translucent protectors under the specified area in the QR code.控制是否在 QR 码的指定区域下绘制半透明保护器。
For more details you should definitely check out [Awesome-qr.js ](https://github.com/SumiMakito/Awesome-qr.js)
This diff could not be displayed because it is too large.
<div id="app">
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script src="/dist/vue-qr.js"></script>
tidelift: "npm/brace-expansion"
patreon: juliangruber
MIT License
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
# brace-expansion
[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
as known from sh/bash, in JavaScript.
[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion)
[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion)
[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/)
[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion)
## Example
```js
var expand = require('brace-expansion');
expand('file-{a,b,c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('-v{,,}')
// => ['-v', '-v', '-v']
expand('file{0..2}.jpg')
// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
expand('file-{a..c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('file{2..0}.jpg')
// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
expand('file{0..4..2}.jpg')
// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
expand('file-{a..e..2}.jpg')
// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
expand('file{00..10..5}.jpg')
// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
expand('{{A..C},{a..c}}')
// => ['A', 'B', 'C', 'a', 'b', 'c']
expand('ppp{,config,oe{,conf}}')
// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
```
## API
```js
var expand = require('brace-expansion');
```
### var expanded = expand(str)
Return an array of all possible and valid expansions of `str`. If none are
found, `[str]` is returned.
Valid expansions are:
```js
/^(.*,)+(.+)?$/
// {a,b,...}
```
A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
A numeric sequence from `x` to `y` inclusive, with optional increment.
If `x` or `y` start with a leading `0`, all the numbers will be padded
to have equal length. Negative numbers and backwards iteration work too.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
An alphabetic sequence from `x` to `y` inclusive, with optional increment.
`x` and `y` must be exactly one character, and if given, `incr` must be a
number.
For compatibility reasons, the string `${` is not eligible for brace expansion.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install brace-expansion
```
## Contributors
- [Julian Gruber](https://github.com/juliangruber)
- [Isaac Z. Schlueter](https://github.com/isaacs)
## Sponsors
This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
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)!
## Security contact information
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
var balanced = require('balanced-match');
module.exports = expandTop;
var escSlash = '\0SLASH'+Math.random()+'\0';
var escOpen = '\0OPEN'+Math.random()+'\0';
var escClose = '\0CLOSE'+Math.random()+'\0';
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
: str.charCodeAt(0);
}
function escapeBraces(str) {
return str.split('\\\\').join(escSlash)
.split('\\{').join(escOpen)
.split('\\}').join(escClose)
.split('\\,').join(escComma)
.split('\\.').join(escPeriod);
}
function unescapeBraces(str) {
return str.split(escSlash).join('\\')
.split(escOpen).join('{')
.split(escClose).join('}')
.split(escComma).join(',')
.split(escPeriod).join('.');
}
// Basically just str.split(","), but handling cases
// where we have nested braced sections, which should be
// treated as individual members, like {a,{b,c},d}
function parseCommaParts(str) {
if (!str)
return [''];
var parts = [];
var m = balanced('{', '}', str);
if (!m)
return str.split(',');
var pre = m.pre;
var body = m.body;
var post = m.post;
var p = pre.split(',');
p[p.length-1] += '{' + body + '}';
var postParts = parseCommaParts(post);
if (post.length) {
p[p.length-1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expandTop(str) {
if (!str)
return [];
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.substr(0, 2) === '{}') {
str = '\\{\\}' + str.substr(2);
}
return expand(escapeBraces(str), true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand(str, isTop) {
var expansions = [];
var m = balanced('{', '}', str);
if (!m) return [str];
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
? expand(m.post, false)
: [''];
if (/\$$/.test(m.pre)) {
for (var k = 0; k < post.length; k++) {
var expansion = pre+ '{' + m.body + '}' + post[k];
expansions.push(expansion);
}
} else {
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
var isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,.*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand(str);
}
return [str];
}
var n;
if (isSequence) {
n = m.body.split(/\.\./);
} else {
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand(n[0], false).map(embrace);
if (n.length === 1) {
return post.map(function(p) {
return m.pre + n[0] + p;
});
}
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
var N;
if (isSequence) {
var x = numeric(n[0]);
var y = numeric(n[1]);
var width = Math.max(n[0].length, n[1].length)
var incr = n.length == 3
? Math.abs(numeric(n[2]))
: 1;
var test = lte;
var reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
var pad = n.some(isPadded);
N = [];
for (var i = x; test(i, y); i += incr) {
var c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\')
c = '';
} else {
c = String(i);
if (pad) {
var need = width - c.length;
if (need > 0) {
var z = new Array(need + 1).join('0');
if (i < 0)
c = '-' + z + c.slice(1);
else
c = z + c;
}
}
}
N.push(c);
}
} else {
N = [];
for (var j = 0; j < n.length; j++) {
N.push.apply(N, expand(n[j], false));
}
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);
}
}
}
return expansions;
}
{
"_from": "brace-expansion@^2.0.1",
"_id": "brace-expansion@2.0.1",
"_inBundle": false,
"_integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"_location": "/vue-qr/brace-expansion",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "brace-expansion@^2.0.1",
"name": "brace-expansion",
"escapedName": "brace-expansion",
"rawSpec": "^2.0.1",
"saveSpec": null,
"fetchSpec": "^2.0.1"
},
"_requiredBy": [
"/vue-qr/minimatch"
],
"_resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
"_shasum": "1edc459e0f0c548486ecf9fc99f2221364b9a0ae",
"_spec": "brace-expansion@^2.0.1",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr/node_modules/minimatch",
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"bugs": {
"url": "https://github.com/juliangruber/brace-expansion/issues"
},
"bundleDependencies": false,
"dependencies": {
"balanced-match": "^1.0.0"
},
"deprecated": false,
"description": "Brace expansion as known from sh/bash",
"devDependencies": {
"@c4312/matcha": "^1.3.1",
"tape": "^4.6.0"
},
"homepage": "https://github.com/juliangruber/brace-expansion",
"keywords": [],
"license": "MIT",
"main": "index.js",
"name": "brace-expansion",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/brace-expansion.git"
},
"scripts": {
"bench": "matcha test/perf/bench.js",
"gentest": "bash test/generate.sh",
"test": "tape test/*.js"
},
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"version": "2.0.1"
}
The ISC License
Copyright (c) 2009-2022 Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
exports.setopts = setopts
exports.ownProp = ownProp
exports.makeAbs = makeAbs
exports.finish = finish
exports.mark = mark
exports.isIgnored = isIgnored
exports.childrenIgnored = childrenIgnored
function ownProp (obj, field) {
return Object.prototype.hasOwnProperty.call(obj, field)
}
var fs = require("fs")
var path = require("path")
var minimatch = require("minimatch")
var isAbsolute = require("path").isAbsolute
var Minimatch = minimatch.Minimatch
function alphasort (a, b) {
return a.localeCompare(b, 'en')
}
function setupIgnores (self, options) {
self.ignore = options.ignore || []
if (!Array.isArray(self.ignore))
self.ignore = [self.ignore]
if (self.ignore.length) {
self.ignore = self.ignore.map(ignoreMap)
}
}
// ignore patterns are always in dot:true mode.
function ignoreMap (pattern) {
var gmatcher = null
if (pattern.slice(-3) === '/**') {
var gpattern = pattern.replace(/(\/\*\*)+$/, '')
gmatcher = new Minimatch(gpattern, { dot: true })
}
return {
matcher: new Minimatch(pattern, { dot: true }),
gmatcher: gmatcher
}
}
function setopts (self, pattern, options) {
if (!options)
options = {}
// base-matching: just use globstar for that.
if (options.matchBase && -1 === pattern.indexOf("/")) {
if (options.noglobstar) {
throw new Error("base matching requires globstar")
}
pattern = "**/" + pattern
}
self.silent = !!options.silent
self.pattern = pattern
self.strict = options.strict !== false
self.realpath = !!options.realpath
self.realpathCache = options.realpathCache || Object.create(null)
self.follow = !!options.follow
self.dot = !!options.dot
self.mark = !!options.mark
self.nodir = !!options.nodir
if (self.nodir)
self.mark = true
self.sync = !!options.sync
self.nounique = !!options.nounique
self.nonull = !!options.nonull
self.nosort = !!options.nosort
self.nocase = !!options.nocase
self.stat = !!options.stat
self.noprocess = !!options.noprocess
self.absolute = !!options.absolute
self.fs = options.fs || fs
self.maxLength = options.maxLength || Infinity
self.cache = options.cache || Object.create(null)
self.statCache = options.statCache || Object.create(null)
self.symlinks = options.symlinks || Object.create(null)
setupIgnores(self, options)
self.changedCwd = false
var cwd = process.cwd()
if (!ownProp(options, "cwd"))
self.cwd = path.resolve(cwd)
else {
self.cwd = path.resolve(options.cwd)
self.changedCwd = self.cwd !== cwd
}
self.root = options.root || path.resolve(self.cwd, "/")
self.root = path.resolve(self.root)
// TODO: is an absolute `cwd` supposed to be resolved against `root`?
// e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd)
self.nomount = !!options.nomount
if (process.platform === "win32") {
self.root = self.root.replace(/\\/g, "/")
self.cwd = self.cwd.replace(/\\/g, "/")
self.cwdAbs = self.cwdAbs.replace(/\\/g, "/")
}
// disable comments and negation in Minimatch.
// Note that they are not supported in Glob itself anyway.
options.nonegate = true
options.nocomment = true
// always treat \ in patterns as escapes, not path separators
options.allowWindowsEscape = true
self.minimatch = new Minimatch(pattern, options)
self.options = self.minimatch.options
}
function finish (self) {
var nou = self.nounique
var all = nou ? [] : Object.create(null)
for (var i = 0, l = self.matches.length; i < l; i ++) {
var matches = self.matches[i]
if (!matches || Object.keys(matches).length === 0) {
if (self.nonull) {
// do like the shell, and spit out the literal glob
var literal = self.minimatch.globSet[i]
if (nou)
all.push(literal)
else
all[literal] = true
}
} else {
// had matches
var m = Object.keys(matches)
if (nou)
all.push.apply(all, m)
else
m.forEach(function (m) {
all[m] = true
})
}
}
if (!nou)
all = Object.keys(all)
if (!self.nosort)
all = all.sort(alphasort)
// at *some* point we statted all of these
if (self.mark) {
for (var i = 0; i < all.length; i++) {
all[i] = self._mark(all[i])
}
if (self.nodir) {
all = all.filter(function (e) {
var notDir = !(/\/$/.test(e))
var c = self.cache[e] || self.cache[makeAbs(self, e)]
if (notDir && c)
notDir = c !== 'DIR' && !Array.isArray(c)
return notDir
})
}
}
if (self.ignore.length)
all = all.filter(function(m) {
return !isIgnored(self, m)
})
self.found = all
}
function mark (self, p) {
var abs = makeAbs(self, p)
var c = self.cache[abs]
var m = p
if (c) {
var isDir = c === 'DIR' || Array.isArray(c)
var slash = p.slice(-1) === '/'
if (isDir && !slash)
m += '/'
else if (!isDir && slash)
m = m.slice(0, -1)
if (m !== p) {
var mabs = makeAbs(self, m)
self.statCache[mabs] = self.statCache[abs]
self.cache[mabs] = self.cache[abs]
}
}
return m
}
// lotta situps...
function makeAbs (self, f) {
var abs = f
if (f.charAt(0) === '/') {
abs = path.join(self.root, f)
} else if (isAbsolute(f) || f === '') {
abs = f
} else if (self.changedCwd) {
abs = path.resolve(self.cwd, f)
} else {
abs = path.resolve(f)
}
if (process.platform === 'win32')
abs = abs.replace(/\\/g, '/')
return abs
}
// Return true, if pattern ends with globstar '**', for the accompanying parent directory.
// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
function isIgnored (self, path) {
if (!self.ignore.length)
return false
return self.ignore.some(function(item) {
return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
})
}
function childrenIgnored (self, path) {
if (!self.ignore.length)
return false
return self.ignore.some(function(item) {
return !!(item.gmatcher && item.gmatcher.match(path))
})
}
{
"_from": "glob@^8.0.1",
"_id": "glob@8.0.3",
"_inBundle": false,
"_integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
"_location": "/vue-qr/glob",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "glob@^8.0.1",
"name": "glob",
"escapedName": "glob",
"rawSpec": "^8.0.1",
"saveSpec": null,
"fetchSpec": "^8.0.1"
},
"_requiredBy": [
"/vue-qr"
],
"_resolved": "https://registry.npmmirror.com/glob/-/glob-8.0.3.tgz",
"_shasum": "415c6eb2deed9e502c68fa44a272e6da6eeca42e",
"_spec": "glob@^8.0.1",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"bugs": {
"url": "https://github.com/isaacs/node-glob/issues"
},
"bundleDependencies": false,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
},
"deprecated": false,
"description": "a little globber",
"devDependencies": {
"memfs": "^3.2.0",
"mkdirp": "0",
"rimraf": "^2.2.8",
"tap": "^16.0.1",
"tick": "0.0.6"
},
"engines": {
"node": ">=12"
},
"files": [
"glob.js",
"sync.js",
"common.js"
],
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"homepage": "https://github.com/isaacs/node-glob#readme",
"license": "ISC",
"main": "glob.js",
"name": "glob",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-glob.git"
},
"scripts": {
"bench": "bash benchmark.sh",
"benchclean": "node benchclean.js",
"prepublish": "npm run benchclean",
"prof": "bash prof.sh && cat profile.txt",
"profclean": "rm -f v8.log profile.txt",
"test": "tap",
"test-regen": "npm run profclean && TEST_REGEN=1 node test/00-setup.js"
},
"tap": {
"before": "test/00-setup.js",
"after": "test/zz-cleanup.js",
"statements": 90,
"branches": 90,
"functions": 90,
"lines": 90,
"jobs": 1
},
"version": "8.0.3"
}
The ISC License
Copyright (c) 2011-2022 Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# minimatch
A minimal matching utility.
[![Build Status](https://travis-ci.org/isaacs/minimatch.svg?branch=master)](http://travis-ci.org/isaacs/minimatch)
This is the matching library used internally by npm.
It works by converting glob expressions into JavaScript `RegExp`
objects.
## Usage
```javascript
var minimatch = require("minimatch")
minimatch("bar.foo", "*.foo") // true!
minimatch("bar.foo", "*.bar") // false!
minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
```
## Features
Supports these glob features:
* Brace Expansion
* Extended glob matching
* "Globstar" `**` matching
See:
* `man sh`
* `man bash`
* `man 3 fnmatch`
* `man 5 gitignore`
## Windows
**Please only use forward-slashes in glob expressions.**
Though windows uses either `/` or `\` as its path separator, only `/`
characters are used by this glob implementation. You must use
forward-slashes **only** in glob expressions. Back-slashes in patterns
will always be interpreted as escape characters, not path separators.
Note that `\` or `/` _will_ be interpreted as path separators in paths on
Windows, and will match against `/` in glob expressions.
So just always use `/` in patterns.
## Minimatch Class
Create a minimatch object by instantiating the `minimatch.Minimatch` class.
```javascript
var Minimatch = require("minimatch").Minimatch
var mm = new Minimatch(pattern, options)
```
### Properties
* `pattern` The original pattern the minimatch object represents.
* `options` The options supplied to the constructor.
* `set` A 2-dimensional array of regexp or string expressions.
Each row in the
array corresponds to a brace-expanded pattern. Each item in the row
corresponds to a single path-part. For example, the pattern
`{a,b/c}/d` would expand to a set of patterns like:
[ [ a, d ]
, [ b, c, d ] ]
If a portion of the pattern doesn't have any "magic" in it
(that is, it's something like `"foo"` rather than `fo*o?`), then it
will be left as a string rather than converted to a regular
expression.
* `regexp` Created by the `makeRe` method. A single regular expression
expressing the entire pattern. This is useful in cases where you wish
to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
* `negate` True if the pattern is negated.
* `comment` True if the pattern is a comment.
* `empty` True if the pattern is `""`.
### Methods
* `makeRe` Generate the `regexp` member if necessary, and return it.
Will return `false` if the pattern is invalid.
* `match(fname)` Return true if the filename matches the pattern, or
false otherwise.
* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
filename, and match it against a single row in the `regExpSet`. This
method is mainly for internal use, but is exposed so that it can be
used by a glob-walker that needs to avoid excessive filesystem calls.
All other methods are internal, and will be called as necessary.
### minimatch(path, pattern, options)
Main export. Tests a path against the pattern using the options.
```javascript
var isJS = minimatch(file, "*.js", { matchBase: true })
```
### minimatch.filter(pattern, options)
Returns a function that tests its
supplied argument, suitable for use with `Array.filter`. Example:
```javascript
var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
```
### minimatch.match(list, pattern, options)
Match against the list of
files, in the style of fnmatch or glob. If nothing is matched, and
options.nonull is set, then return a list containing the pattern itself.
```javascript
var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})
```
### minimatch.makeRe(pattern, options)
Make a regular expression object from the pattern.
## Options
All options are `false` by default.
### debug
Dump a ton of stuff to stderr.
### nobrace
Do not expand `{a,b}` and `{1..3}` brace sets.
### noglobstar
Disable `**` matching against multiple folder names.
### dot
Allow patterns to match filenames starting with a period, even if
the pattern does not explicitly have a period in that spot.
Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
is set.
### noext
Disable "extglob" style patterns like `+(a|b)`.
### nocase
Perform a case-insensitive match.
### nonull
When a match is not found by `minimatch.match`, return a list containing
the pattern itself if this option is set. When not set, an empty list
is returned if there are no matches.
### matchBase
If set, then patterns without slashes will be matched
against the basename of the path if it contains slashes. For example,
`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
### nocomment
Suppress the behavior of treating `#` at the start of a pattern as a
comment.
### nonegate
Suppress the behavior of treating a leading `!` character as negation.
### flipNegate
Returns from negate expressions the same as if they were not negated.
(Ie, true on a hit, false on a miss.)
### partial
Compare a partial path to a pattern. As long as the parts of the path that
are present are not contradicted by the pattern, it will be treated as a
match. This is useful in applications where you're walking through a
folder structure, and don't yet have the full path, but want to ensure that
you do not walk down paths that can never be a match.
For example,
```js
minimatch('/a/b', '/a/*/c/d', { partial: true }) // true, might be /a/b/c/d
minimatch('/a/b', '/**/d', { partial: true }) // true, might be /a/b/.../d
minimatch('/x/y/z', '/a/**/z', { partial: true }) // false, because x !== a
```
### windowsPathsNoEscape
Use `\\` as a path separator _only_, and _never_ as an escape
character. If set, all `\\` characters are replaced with `/` in
the pattern. Note that this makes it **impossible** to match
against paths containing literal glob pattern characters, but
allows matching with patterns constructed using `path.join()` and
`path.resolve()` on Windows platforms, mimicking the (buggy!)
behavior of earlier versions on Windows. Please use with
caution, and be mindful of [the caveat about Windows
paths](#windows).
For legacy reasons, this is also set if
`options.allowWindowsEscape` is set to the exact value `false`.
## Comparisons to other fnmatch/glob implementations
While strict compliance with the existing standards is a worthwhile
goal, some discrepancies exist between minimatch and other
implementations, and are intentional.
If the pattern starts with a `!` character, then it is negated. Set the
`nonegate` flag to suppress this behavior, and treat leading `!`
characters normally. This is perhaps relevant if you wish to start the
pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
characters at the start of a pattern will negate the pattern multiple
times.
If a pattern starts with `#`, then it is treated as a comment, and
will not match anything. Use `\#` to match a literal `#` at the
start of a line, or set the `nocomment` flag to suppress this behavior.
The double-star character `**` is supported by default, unless the
`noglobstar` flag is set. This is supported in the manner of bsdglob
and bash 4.1, where `**` only has special significance if it is the only
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
`a/**b` will not.
If an escaped pattern has no matches, and the `nonull` flag is set,
then minimatch.match returns the pattern as-provided, rather than
interpreting the character escapes. For example,
`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
`"*a?"`. This is akin to setting the `nullglob` option in bash, except
that it does not resolve escaped pattern characters.
If brace expansion is not disabled, then it is performed before any
other interpretation of the glob pattern. Thus, a pattern like
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
checked for validity. Since those two are valid, matching proceeds.
Note that `fnmatch(3)` in libc is an extremely naive string comparison
matcher, which does not do anything special for slashes. This library is
designed to be used in glob searching and file walkers, and so it does do
special things with `/`. Thus, `foo*` will not match `foo/bar` in this
library, even though it would in `fnmatch(3)`.
const isWindows = typeof process === 'object' &&
process &&
process.platform === 'win32'
module.exports = isWindows ? { sep: '\\' } : { sep: '/' }
{
"_from": "minimatch@^5.0.1",
"_id": "minimatch@5.1.0",
"_inBundle": false,
"_integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
"_location": "/vue-qr/minimatch",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "minimatch@^5.0.1",
"name": "minimatch",
"escapedName": "minimatch",
"rawSpec": "^5.0.1",
"saveSpec": null,
"fetchSpec": "^5.0.1"
},
"_requiredBy": [
"/vue-qr/glob"
],
"_resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.0.tgz",
"_shasum": "1717b464f4971b144f6aabe8f2d0b8e4511e09c7",
"_spec": "minimatch@^5.0.1",
"_where": "/Users/zhanghao/brcode/br-client/node_modules/vue-qr/node_modules/glob",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me"
},
"bugs": {
"url": "https://github.com/isaacs/minimatch/issues"
},
"bundleDependencies": false,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"deprecated": false,
"description": "a glob matcher in javascript",
"devDependencies": {
"tap": "^15.1.6"
},
"engines": {
"node": ">=10"
},
"files": [
"minimatch.js",
"lib"
],
"homepage": "https://github.com/isaacs/minimatch#readme",
"license": "ISC",
"main": "minimatch.js",
"name": "minimatch",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/minimatch.git"
},
"scripts": {
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"preversion": "npm test",
"snap": "tap",
"test": "tap"
},
"version": "5.1.0"
}
{
"_from": "vue-qr",
"_id": "vue-qr@4.0.9",
"_inBundle": false,
"_integrity": "sha512-pAISV94T0MNEYA3NGjykUpsXRE2QfaNxlu9ZhEL6CERgqNc21hJYuP3hRVzAWfBQlgO18DPmZTbrFerJC3+Ikw==",
"_location": "/vue-qr",
"_phantomChildren": {
"balanced-match": "1.0.0",
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.4",
"once": "1.4.0"
},
"_requested": {
"type": "tag",
"registry": true,
"raw": "vue-qr",
"name": "vue-qr",
"escapedName": "vue-qr",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmmirror.com/vue-qr/-/vue-qr-4.0.9.tgz",
"_shasum": "6cb965dd0c5a0dff947e6ef582ef149b0780b986",
"_spec": "vue-qr",
"_where": "/Users/zhanghao/brcode/br-client",
"author": {
"name": "Binaryify"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"bugs": {
"url": "https://github.com/Binaryify/vue-qr/issues"
},
"bundleDependencies": false,
"dependencies": {
"glob": "^8.0.1",
"js-binary-schema-parser": "^2.0.2",
"simple-get": "^4.0.1",
"string-split-by": "^1.0.0"
},
"deprecated": false,
"description": "The Vue 2.x component of Awesome-qr.js",
"devDependencies": {
"@babel/cli": "^7.11.6",
"@babel/core": "^7.11.6",
"@babel/plugin-proposal-class-properties": "^7.16.7",
"@babel/plugin-transform-runtime": "^7.11.5",
"@babel/preset-env": "^7.11.5",
"@babel/preset-stage-0": "^7.8.3",
"babel-loader": "^8.1.0",
"babel-plugin-lodash": "^3.3.4",
"cross-env": "^7.0.2",
"css-loader": "^4.3.0",
"file-loader": "^6.1.0",
"uuid": "^8.3.1",
"vue": "^2.6.12",
"vue-loader": "^15.9.3",
"vue-template-compiler": "^2.6.12",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
},
"homepage": "https://github.com/Binaryify/vue-qr#readme",
"keywords": [
"vue-qr",
"vue qr",
"vue qrcode",
"qr",
"vue"
],
"license": "MIT",
"main": "dist/vue-qr.js",
"name": "vue-qr",
"repository": {
"type": "git",
"url": "git+https://github.com/Binaryify/vue-qr.git"
},
"scripts": {
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot --host 0.0.0.0"
},
"version": "4.0.9"
}
"use strict";
// const {asBuffer, asDownload, asZipDownload, atScale, options} = require('./io')
import io from "./io";
const { asBuffer, asDownload, asZipDownload, atScale, options } = io;
//
// Browser equivalents of the skia-canvas convenience initializers and polyfills for
// the Canvas object’s newPage & export methods
//
const _toURL_ = Symbol.for("toDataURL");
const loadImage = src =>
new Promise((onload, onerror) =>
Object.assign(new Image(), {
crossOrigin: "Anonymous",
onload,
onerror,
src
})
);
class Canvas {
constructor(width, height) {
// alert(1)
let elt = document.createElement("canvas"),
pages = [];
Object.defineProperty(elt, "async", {
value: true,
writable: false,
enumerable: true
});
for (var [prop, get] of Object.entries({
png: () => asBuffer(elt, "image/png"),
jpg: () => asBuffer(elt, "image/jpeg"),
pages: () => pages.concat(elt).map(c => c.getContext("2d"))
}))
Object.defineProperty(elt, prop, { get });
return Object.assign(elt, {
width,
height,
newPage(...size) {
var { width, height } = elt,
page = Object.assign(document.createElement("canvas"), {
width,
height
});
page.getContext("2d").drawImage(elt, 0, 0);
pages.push(page);
var [width, height] = size.length ? size : [width, height];
return Object.assign(elt, { width, height }).getContext("2d");
},
saveAs(filename, args) {
args = typeof args == "number" ? { quality: args } : args;
let opts = options(this.pages, { filename, ...args }),
{ pattern, padding, mime, quality, matte, density, archive } = opts,
pages = atScale(opts.pages, density);
return padding == undefined
? asDownload(pages[0], mime, quality, matte, filename)
: asZipDownload(
pages,
mime,
quality,
matte,
archive,
pattern,
padding
);
},
toBuffer(extension = "png", args = {}) {
args = typeof args == "number" ? { quality: args } : args;
let opts = options(this.pages, { extension, ...args }),
{ mime, quality, matte, pages, density } = opts,
canvas = atScale(pages, density, matte)[0];
return asBuffer(canvas, mime, quality, matte);
},
[_toURL_]: elt.toDataURL.bind(elt),
toDataURL(extension = "png", args = {}) {
args = typeof args == "number" ? { quality: args } : args;
let opts = options(this.pages, { extension, ...args }),
{ mime, quality, matte, pages, density } = opts,
canvas = atScale(pages, density, matte)[0],
url = canvas[canvas === elt ? _toURL_ : "toDataURL"](mime, quality);
return Promise.resolve(url);
}
});
}
}
const {
CanvasRenderingContext2D,
CanvasGradient,
CanvasPattern,
Image,
ImageData,
Path2D,
DOMMatrix,
DOMRect,
DOMPoint
} = window;
// module.exports = {
// Canvas,
// loadImage,
// CanvasRenderingContext2D,
// CanvasGradient,
// CanvasPattern,
// Image,
// ImageData,
// Path2D,
// DOMMatrix,
// DOMRect,
// DOMPoint
// };
const obj = {
Canvas,
loadImage,
CanvasRenderingContext2D,
CanvasGradient,
CanvasPattern,
Image,
ImageData,
Path2D,
DOMMatrix,
DOMRect,
DOMPoint
};
export default obj;
"use strict";
//
// Parsers for properties that take CSS-style strings as values
//
// -- Font & Variant --------------------------------------------------------------------
// https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant
// https://www.w3.org/TR/css-fonts-3/#font-size-prop
import splitBy from "string-split-by";
var m,
cache = { font: {}, variant: {} };
const styleRE = /^(normal|italic|oblique)$/,
smallcapsRE = /^(normal|small-caps)$/,
stretchRE = /^(normal|(semi-|extra-|ultra-)?(condensed|expanded))$/,
namedSizeRE = /(?:xx?-)?small|smaller|medium|larger|(?:xx?-)?large|normal/,
numSizeRE = /^([\d\.]+)(px|pt|pc|in|cm|mm|%|em|ex|ch|rem|q)/,
namedWeightRE = /^(normal|bold(er)?|lighter)$/,
numWeightRE = /^(1000|\d{1,3})$/,
parameterizedRE = /([\w\-]+)\((.*?)\)/,
unquote = s => s.replace(/^(['"])(.*?)\1$/, "$2"),
isSize = s => namedSizeRE.test(s) || numSizeRE.test(s),
isWeight = s => namedWeightRE.test(s) || numWeightRE.test(s);
function parseFont(str) {
if (cache.font[str] === undefined) {
try {
if (typeof str !== "string")
throw new Error("Font specification must be a string");
if (!str) throw new Error("Font specification cannot be an empty string");
let font = {
style: "normal",
variant: "normal",
weight: "normal",
stretch: "normal"
},
value = str.replace(/\s*\/\*s/, "/"),
tokens = splitBy(value, /\s+/),
token;
while ((token = tokens.shift())) {
let match = styleRE.test(token)
? "style"
: smallcapsRE.test(token)
? "variant"
: stretchRE.test(token)
? "stretch"
: isWeight(token)
? "weight"
: isSize(token)
? "size"
: null;
switch (match) {
case "style":
case "variant":
case "stretch":
case "weight":
font[match] = token;
break;
case "size":
// size is the pivot point between the style fields and the family name stack,
// so start processing what's been collected
let [emSize, leading] = splitBy(token, "/"),
size = parseSize(emSize),
lineHeight = parseSize(
(leading || "1.2").replace(/(\d)$/, "$1em"),
size
),
weight = parseWeight(font.weight),
family = splitBy(tokens.join(" "), /\s*,\s*/).map(unquote),
features =
font.variant == "small-caps" ? { on: ["smcp", "onum"] } : {},
{ style, stretch, variant } = font;
// make sure all the numeric fields have legitimate values
let invalid = !isFinite(size)
? `font size "${emSize}"`
: !isFinite(lineHeight)
? `line height "${leading}"`
: !isFinite(weight)
? `font weight "${font.weight}"`
: family.length == 0
? `font family "${tokens.join(", ")}"`
: false;
if (!invalid) {
// include a re-stringified version of the decoded/absified values
return (cache.font[str] = Object.assign(font, {
size,
lineHeight,
weight,
family,
features,
canonical: [
style,
variant !== style && variant,
[variant, style].indexOf(weight) == -1 && weight,
[variant, style, weight].indexOf(stretch) == -1 && stretch,
`${size}px/${lineHeight}px`,
family.map(nm => (nm.match(/\s/) ? `"${nm}"` : nm)).join(", ")
]
.filter(Boolean)
.join(" ")
}));
}
throw new Error(`Invalid ${invalid}`);
default:
throw new Error(`Unrecognized font attribute "${token}"`);
}
}
throw new Error("Could not find a font size value");
} catch (e) {
// console.warn(Object.assign(e, {name:"Warning"}))
cache.font[str] = null;
}
}
return cache.font[str];
}
function parseSize(str, emSize = 16) {
if ((m = numSizeRE.exec(str))) {
let [size, unit] = [parseFloat(m[1]), m[2]];
return (
size *
(unit == "px"
? 1
: unit == "pt"
? 1 / 0.75
: unit == "%"
? emSize / 100
: unit == "pc"
? 16
: unit == "in"
? 96
: unit == "cm"
? 96.0 / 2.54
: unit == "mm"
? 96.0 / 25.4
: unit == "q"
? 96 / 25.4 / 4
: unit.match("r?em")
? emSize
: NaN)
);
}
if ((m = namedSizeRE.exec(str))) {
return emSize * (sizeMap[m[0]] || 1.0);
}
return NaN;
}
function parseWeight(str) {
return (m = numWeightRE.exec(str))
? parseInt(m[0]) || NaN
: (m = namedWeightRE.exec(str))
? weightMap[m[0]]
: NaN;
}
function parseVariant(str) {
if (cache.variant[str] === undefined) {
let variants = [],
features = { on: [], off: [] };
for (let token of splitBy(str, /\s+/)) {
if (token == "normal") {
return { variants: [token], features: { on: [], off: [] } };
} else if (token in featureMap) {
featureMap[token].forEach(feat => {
if (feat[0] == "-") features.off.push(feat.slice(1));
else features.on.push(feat);
});
variants.push(token);
} else if ((m = parameterizedRE.exec(token))) {
let subPattern = alternatesMap[m[1]],
subValue = Math.max(0, Math.min(99, parseInt(m[2], 10))),
[feat, val] = subPattern
.replace(/##/, subValue < 10 ? "0" + subValue : subValue)
.replace(/#/, Math.min(9, subValue))
.split(" ");
if (typeof val == "undefined") features.on.push(feat);
else features[feat] = parseInt(val, 10);
variants.push(`${m[1]}(${subValue})`);
} else {
throw new Error(`Invalid font variant "${token}"`);
}
}
cache.variant[str] = { variant: variants.join(" "), features: features };
}
return cache.variant[str];
}
// -- Image Filters -----------------------------------------------------------------------
// https://developer.mozilla.org/en-US/docs/Web/CSS/filter
var plainFilterRE = /(blur|hue-rotate|brightness|contrast|grayscale|invert|opacity|saturate|sepia)\((.*?)\)/,
shadowFilterRE = /drop-shadow\((.*)\)/,
percentValueRE = /^(\+|-)?\d+%$/,
angleValueRE = /([\d\.]+)(deg|g?rad|turn)/;
function parseFilter(str) {
let filters = {};
let canonical = [];
for (var spec of splitBy(str, /\s+/) || []) {
if ((m = shadowFilterRE.exec(spec))) {
let kind = "drop-shadow",
args = m[1].trim().split(/\s+/),
lengths = args.slice(0, 3),
color = args.slice(3).join(" "),
dims = lengths.map(s => parseSize(s)).filter(isFinite);
if (dims.length == 3 && !!color) {
filters[kind] = [...dims, color];
canonical.push(
`${kind}(${lengths.join(" ")} ${color.replace(/ /g, "")})`
);
}
} else if ((m = plainFilterRE.exec(spec))) {
let [kind, arg] = m.slice(1);
let val =
kind == "blur"
? parseSize(arg)
: kind == "hue-rotate"
? parseAngle(arg)
: parsePercentage(arg);
if (isFinite(val)) {
filters[kind] = val;
canonical.push(`${kind}(${arg.trim()})`);
}
}
}
return str.trim() == "none"
? { canonical: "none", filters }
: canonical.length
? { canonical: canonical.join(" "), filters }
: null;
}
function parsePercentage(str) {
return percentValueRE.test(str.trim()) ? parseInt(str, 10) / 100 : NaN;
}
function parseAngle(str) {
if ((m = angleValueRE.exec(str.trim()))) {
let [amt, unit] = [parseFloat(m[1]), m[2]];
return unit == "deg"
? amt
: unit == "rad"
? (360 * amt) / (2 * Math.PI)
: unit == "grad"
? (360 * amt) / 400
: unit == "turn"
? 360 * amt
: NaN;
}
}
//
// Font attribute keywords & corresponding values
//
const weightMap = {
lighter: 300,
normal: 400,
bold: 700,
bolder: 800
};
const sizeMap = {
"xx-small": 3 / 5,
"x-small": 3 / 4,
small: 8 / 9,
smaller: 8 / 9,
large: 6 / 5,
larger: 6 / 5,
"x-large": 3 / 2,
"xx-large": 2 / 1,
normal: 1.2 // special case for lineHeight
};
const featureMap = {
normal: [],
// font-variant-ligatures
"common-ligatures": ["liga", "clig"],
"no-common-ligatures": ["-liga", "-clig"],
"discretionary-ligatures": ["dlig"],
"no-discretionary-ligatures": ["-dlig"],
"historical-ligatures": ["hlig"],
"no-historical-ligatures": ["-hlig"],
contextual: ["calt"],
"no-contextual": ["-calt"],
// font-variant-position
super: ["sups"],
sub: ["subs"],
// font-variant-caps
"small-caps": ["smcp"],
"all-small-caps": ["c2sc", "smcp"],
"petite-caps": ["pcap"],
"all-petite-caps": ["c2pc", "pcap"],
unicase: ["unic"],
"titling-caps": ["titl"],
// font-variant-numeric
"lining-nums": ["lnum"],
"oldstyle-nums": ["onum"],
"proportional-nums": ["pnum"],
"tabular-nums": ["tnum"],
"diagonal-fractions": ["frac"],
"stacked-fractions": ["afrc"],
ordinal: ["ordn"],
"slashed-zero": ["zero"],
// font-variant-east-asian
jis78: ["jp78"],
jis83: ["jp83"],
jis90: ["jp90"],
jis04: ["jp04"],
simplified: ["smpl"],
traditional: ["trad"],
"full-width": ["fwid"],
"proportional-width": ["pwid"],
ruby: ["ruby"],
// font-variant-alternates (non-parameterized)
"historical-forms": ["hist"]
};
const alternatesMap = {
stylistic: "salt #",
styleset: "ss##",
"character-variant": "cv##",
swash: "swsh #",
ornaments: "ornm #",
annotation: "nalt #"
};
// module.exports = {
// font: parseFont,
// variant: parseVariant,
// size: parseSize,
// filter: parseFilter
// };
export default {
font: parseFont,
variant: parseVariant,
size: parseSize,
filter: parseFilter
};