mirror of https://github.com/jkjoy/sunpeiwen.git
增加AI摘要
This commit is contained in:
parent
44a4e79515
commit
48fea5d844
11
_config.yml
11
_config.yml
|
@ -145,3 +145,14 @@ abbrlink:
|
||||||
auto_title: false #enable auto title, it can auto fill the title by path
|
auto_title: false #enable auto title, it can auto fill the title by path
|
||||||
auto_date: false #enable auto date, it can auto fill the date by time today
|
auto_date: false #enable auto date, it can auto fill the date by time today
|
||||||
force: false #enable force mode,in this mode, the plugin will ignore the cache, and calc the abbrlink for every post even it already had abbrlink. This only updates abbrlink rather than other front variables.
|
force: false #enable force mode,in this mode, the plugin will ignore the cache, and calc the abbrlink for every post even it already had abbrlink. This only updates abbrlink rather than other front variables.
|
||||||
|
aiexcerpt:
|
||||||
|
default_enable: true
|
||||||
|
custom: true
|
||||||
|
api: https://burn.hair/v1
|
||||||
|
token: sk-7aHIS1dvoDbiWpJU4e9eAe2c16B1413f8920BaA87bA56325
|
||||||
|
model:
|
||||||
|
prompt: '你是一个摘要生成工具,你需要解释我发送给你的内容,不要换行,不要超过200字,只需要介绍文章的内容,不需要提出建议和缺少的东西。请用中文回答,输出的内容开头为“这篇文章介绍了”'
|
||||||
|
ignoreEl: [
|
||||||
|
'table', 'pre', 'figure'
|
||||||
|
]
|
||||||
|
max_token: 2000,
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/sh
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||||
|
|
||||||
|
case `uname` in
|
||||||
|
*CYGWIN*|*MINGW*|*MSYS*)
|
||||||
|
if command -v cygpath > /dev/null 2>&1; then
|
||||||
|
basedir=`cygpath -w "$basedir"`
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/node" ]; then
|
||||||
|
exec "$basedir/node" "$basedir/../chatgpt/bin/cli.js" "$@"
|
||||||
|
else
|
||||||
|
exec node "$basedir/../chatgpt/bin/cli.js" "$@"
|
||||||
|
fi
|
|
@ -0,0 +1,17 @@
|
||||||
|
@ECHO off
|
||||||
|
GOTO start
|
||||||
|
:find_dp0
|
||||||
|
SET dp0=%~dp0
|
||||||
|
EXIT /b
|
||||||
|
:start
|
||||||
|
SETLOCAL
|
||||||
|
CALL :find_dp0
|
||||||
|
|
||||||
|
IF EXIST "%dp0%\node.exe" (
|
||||||
|
SET "_prog=%dp0%\node.exe"
|
||||||
|
) ELSE (
|
||||||
|
SET "_prog=node"
|
||||||
|
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||||
|
)
|
||||||
|
|
||||||
|
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\chatgpt\bin\cli.js" %*
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/env pwsh
|
||||||
|
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||||
|
|
||||||
|
$exe=""
|
||||||
|
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||||
|
# Fix case when both the Windows and Linux builds of Node
|
||||||
|
# are installed in the same directory
|
||||||
|
$exe=".exe"
|
||||||
|
}
|
||||||
|
$ret=0
|
||||||
|
if (Test-Path "$basedir/node$exe") {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "$basedir/node$exe" "$basedir/../chatgpt/bin/cli.js" $args
|
||||||
|
} else {
|
||||||
|
& "$basedir/node$exe" "$basedir/../chatgpt/bin/cli.js" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
} else {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "node$exe" "$basedir/../chatgpt/bin/cli.js" $args
|
||||||
|
} else {
|
||||||
|
& "node$exe" "$basedir/../chatgpt/bin/cli.js" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
}
|
||||||
|
exit $ret
|
File diff suppressed because it is too large
Load Diff
|
@ -1,117 +0,0 @@
|
||||||
4.3.1 / 2023-03-14
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fix redos vulnerability with specific crafted css string - CVE-2023-26364
|
|
||||||
|
|
||||||
4.3.0 / 2023-03-07
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Update build tools
|
|
||||||
* Update exports path and files
|
|
||||||
|
|
||||||
4.2.0 / 2023-02-21
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Add @container support
|
|
||||||
* Add @layer support
|
|
||||||
|
|
||||||
4.1.0 / 2023-01-25
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Support ESM Modules
|
|
||||||
|
|
||||||
4.0.2 / 2023-01-12
|
|
||||||
==================
|
|
||||||
|
|
||||||
* #71 : @import does not work if url contains ';'
|
|
||||||
* #77 : Regression in selector parsing: Attribute selectors not parsed correctly
|
|
||||||
|
|
||||||
4.0.1 / 2022-08-03
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Change globalThis configuration for webpack so UMD module could be used in nodejs (jest-dom)
|
|
||||||
|
|
||||||
4.0.0 / 2022-06-09
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Adobe fork of css into @adobe/css
|
|
||||||
* Convert the project into typescript
|
|
||||||
* Optimization of performance (+25% in some cases)
|
|
||||||
* Update all deps
|
|
||||||
* Remove sourcemap support
|
|
||||||
|
|
||||||
2.2.1 / 2015-06-17
|
|
||||||
==================
|
|
||||||
|
|
||||||
* fix parsing escaped quotes in quoted strings
|
|
||||||
|
|
||||||
2.2.0 / 2015-02-18
|
|
||||||
==================
|
|
||||||
|
|
||||||
* add `parsingErrors` to list errors when parsing with `silent: true`
|
|
||||||
* accept EOL characters and all other whitespace characters in `@` rules such
|
|
||||||
as `@media`
|
|
||||||
|
|
||||||
2.1.0 / 2014-08-05
|
|
||||||
==================
|
|
||||||
|
|
||||||
* change error message format and add `.reason` property to errors
|
|
||||||
* add `inputSourcemaps` option to disable input source map processing
|
|
||||||
* use `inherits` for inheritance (fixes some browsers)
|
|
||||||
* add `sourcemap: 'generator'` option to return the `SourceMapGenerator`
|
|
||||||
object
|
|
||||||
|
|
||||||
2.0.0 / 2014-06-18
|
|
||||||
==================
|
|
||||||
|
|
||||||
* add non-enumerable parent reference to each node
|
|
||||||
* drop Component(1) support
|
|
||||||
* add support for @custom-media, @host, and @font-face
|
|
||||||
* allow commas inside selector functions
|
|
||||||
* allow empty property values
|
|
||||||
* changed default options.position value to true
|
|
||||||
* remove comments from properties and values
|
|
||||||
* asserts when selectors are missing
|
|
||||||
* added node.position.content property
|
|
||||||
* absorb css-parse and css-stringify libraries
|
|
||||||
* apply original source maps from source files
|
|
||||||
|
|
||||||
1.6.1 / 2014-01-02
|
|
||||||
==================
|
|
||||||
|
|
||||||
* fix component.json
|
|
||||||
|
|
||||||
1.6.0 / 2013-12-21
|
|
||||||
==================
|
|
||||||
|
|
||||||
* update deps
|
|
||||||
|
|
||||||
1.5.0 / 2013-12-03
|
|
||||||
==================
|
|
||||||
|
|
||||||
* update deps
|
|
||||||
|
|
||||||
1.1.0 / 2013-04-04
|
|
||||||
==================
|
|
||||||
|
|
||||||
* update deps
|
|
||||||
|
|
||||||
1.0.7 / 2012-11-21
|
|
||||||
==================
|
|
||||||
|
|
||||||
* fix component.json
|
|
||||||
|
|
||||||
1.0.4 / 2012-11-15
|
|
||||||
==================
|
|
||||||
|
|
||||||
* update css-stringify
|
|
||||||
|
|
||||||
1.0.3 / 2012-09-01
|
|
||||||
==================
|
|
||||||
|
|
||||||
* add component support
|
|
||||||
|
|
||||||
0.0.1 / 2010-01-03
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Initial release
|
|
|
@ -1,320 +0,0 @@
|
||||||
# @adobe/css-tools
|
|
||||||
|
|
||||||
> This is a fork of the npm css package due to low maintenance
|
|
||||||
|
|
||||||
CSS parser / stringifier.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
$ npm install @adobe/css-tools
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { parse, stringify } from '@adobe/css-tools'
|
|
||||||
let obj = parse('body { font-size: 12px; }', options);
|
|
||||||
let css = stringify(obj, options);
|
|
||||||
```
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### parse(code, [options])
|
|
||||||
|
|
||||||
Accepts a CSS string and returns an AST `object`.
|
|
||||||
|
|
||||||
`options`:
|
|
||||||
|
|
||||||
- silent: silently fail on parse errors.
|
|
||||||
- source: the path to the file containing `css`. Makes errors and source
|
|
||||||
maps more helpful, by letting them know where code comes from.
|
|
||||||
|
|
||||||
### stringify(object, [options])
|
|
||||||
|
|
||||||
Accepts an AST `object` (as `css.parse` produces) and returns a CSS string.
|
|
||||||
|
|
||||||
`options`:
|
|
||||||
|
|
||||||
- indent: the string used to indent the output. Defaults to two spaces.
|
|
||||||
- compress: omit comments and extraneous whitespace.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
var ast = parse('body { font-size: 12px; }', { source: 'source.css' });
|
|
||||||
|
|
||||||
var css = stringify(ast);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Errors
|
|
||||||
|
|
||||||
Errors thrown during parsing have the following properties:
|
|
||||||
|
|
||||||
- message: `String`. The full error message with the source position.
|
|
||||||
- reason: `String`. The error message without position.
|
|
||||||
- filename: `String` or `undefined`. The value of `options.source` if
|
|
||||||
passed to `css.parse`. Otherwise `undefined`.
|
|
||||||
- line: `Integer`.
|
|
||||||
- column: `Integer`.
|
|
||||||
- source: `String`. The portion of code that couldn't be parsed.
|
|
||||||
|
|
||||||
When parsing with the `silent` option, errors are listed in the
|
|
||||||
`parsingErrors` property of the [`stylesheet`](#stylesheet) node instead
|
|
||||||
of being thrown.
|
|
||||||
|
|
||||||
If you create any errors in plugins such as in
|
|
||||||
[rework](https://github.com/reworkcss/rework), you __must__ set the same
|
|
||||||
properties for consistency.
|
|
||||||
|
|
||||||
## AST
|
|
||||||
|
|
||||||
Interactively explore the AST with <http://iamdustan.com/reworkcss_ast_explorer/>.
|
|
||||||
|
|
||||||
### Common properties
|
|
||||||
|
|
||||||
All nodes have the following properties.
|
|
||||||
|
|
||||||
#### position
|
|
||||||
|
|
||||||
Information about the position in the source string that corresponds to
|
|
||||||
the node.
|
|
||||||
|
|
||||||
`Object`:
|
|
||||||
|
|
||||||
- start: `Object`:
|
|
||||||
- line: `Number`.
|
|
||||||
- column: `Number`.
|
|
||||||
- end: `Object`:
|
|
||||||
- line: `Number`.
|
|
||||||
- column: `Number`.
|
|
||||||
- source: `String` or `undefined`. The value of `options.source` if passed to
|
|
||||||
`css.parse`. Otherwise `undefined`.
|
|
||||||
- content: `String`. The full source string passed to `css.parse`.
|
|
||||||
|
|
||||||
The line and column numbers are 1-based: The first line is 1 and the first
|
|
||||||
column of a line is 1 (not 0).
|
|
||||||
|
|
||||||
The `position` property lets you know from which source file the node comes
|
|
||||||
from (if available), what that file contains, and what part of that file was
|
|
||||||
parsed into the node.
|
|
||||||
|
|
||||||
#### type
|
|
||||||
|
|
||||||
`String`. The possible values are the ones listed in the Types section below.
|
|
||||||
|
|
||||||
#### parent
|
|
||||||
|
|
||||||
A reference to the parent node, or `null` if the node has no parent.
|
|
||||||
|
|
||||||
### Types
|
|
||||||
|
|
||||||
The available values of `node.type` are listed below, as well as the available
|
|
||||||
properties of each node (other than the common properties listed above.)
|
|
||||||
|
|
||||||
#### stylesheet
|
|
||||||
|
|
||||||
The root node returned by `css.parse`.
|
|
||||||
|
|
||||||
- stylesheet: `Object`:
|
|
||||||
- rules: `Array` of nodes with the types `rule`, `comment` and any of the
|
|
||||||
at-rule types.
|
|
||||||
- parsingErrors: `Array` of `Error`s. Errors collected during parsing when
|
|
||||||
option `silent` is true.
|
|
||||||
|
|
||||||
#### rule
|
|
||||||
|
|
||||||
- selectors: `Array` of `String`s. The list of selectors of the rule, split
|
|
||||||
on commas. Each selector is trimmed from whitespace and comments.
|
|
||||||
- declarations: `Array` of nodes with the types `declaration` and `comment`.
|
|
||||||
|
|
||||||
#### declaration
|
|
||||||
|
|
||||||
- property: `String`. The property name, trimmed from whitespace and
|
|
||||||
comments. May not be empty.
|
|
||||||
- value: `String`. The value of the property, trimmed from whitespace and
|
|
||||||
comments. Empty values are allowed.
|
|
||||||
|
|
||||||
#### comment
|
|
||||||
|
|
||||||
A rule-level or declaration-level comment. Comments inside selectors,
|
|
||||||
properties and values etc. are lost.
|
|
||||||
|
|
||||||
- comment: `String`. The part between the starting `/*` and the ending `*/`
|
|
||||||
of the comment, including whitespace.
|
|
||||||
|
|
||||||
#### charset
|
|
||||||
|
|
||||||
The `@charset` at-rule.
|
|
||||||
|
|
||||||
- charset: `String`. The part following `@charset `.
|
|
||||||
|
|
||||||
#### custom-media
|
|
||||||
|
|
||||||
The `@custom-media` at-rule.
|
|
||||||
|
|
||||||
- name: `String`. The `--`-prefixed name.
|
|
||||||
- media: `String`. The part following the name.
|
|
||||||
|
|
||||||
#### document
|
|
||||||
|
|
||||||
The `@document` at-rule.
|
|
||||||
|
|
||||||
- document: `String`. The part following `@document `.
|
|
||||||
- vendor: `String` or `undefined`. The vendor prefix in `@document`, or
|
|
||||||
`undefined` if there is none.
|
|
||||||
- rules: `Array` of nodes with the types `rule`, `comment` and any of the
|
|
||||||
at-rule types.
|
|
||||||
|
|
||||||
#### font-face
|
|
||||||
|
|
||||||
The `@font-face` at-rule.
|
|
||||||
|
|
||||||
- declarations: `Array` of nodes with the types `declaration` and `comment`.
|
|
||||||
|
|
||||||
#### host
|
|
||||||
|
|
||||||
The `@host` at-rule.
|
|
||||||
|
|
||||||
- rules: `Array` of nodes with the types `rule`, `comment` and any of the
|
|
||||||
at-rule types.
|
|
||||||
|
|
||||||
#### import
|
|
||||||
|
|
||||||
The `@import` at-rule.
|
|
||||||
|
|
||||||
- import: `String`. The part following `@import `.
|
|
||||||
|
|
||||||
#### keyframes
|
|
||||||
|
|
||||||
The `@keyframes` at-rule.
|
|
||||||
|
|
||||||
- name: `String`. The name of the keyframes rule.
|
|
||||||
- vendor: `String` or `undefined`. The vendor prefix in `@keyframes`, or
|
|
||||||
`undefined` if there is none.
|
|
||||||
- keyframes: `Array` of nodes with the types `keyframe` and `comment`.
|
|
||||||
|
|
||||||
#### keyframe
|
|
||||||
|
|
||||||
- values: `Array` of `String`s. The list of “selectors” of the keyframe rule,
|
|
||||||
split on commas. Each “selector” is trimmed from whitespace.
|
|
||||||
- declarations: `Array` of nodes with the types `declaration` and `comment`.
|
|
||||||
|
|
||||||
#### media
|
|
||||||
|
|
||||||
The `@media` at-rule.
|
|
||||||
|
|
||||||
- media: `String`. The part following `@media `.
|
|
||||||
- rules: `Array` of nodes with the types `rule`, `comment` and any of the
|
|
||||||
at-rule types.
|
|
||||||
|
|
||||||
#### namespace
|
|
||||||
|
|
||||||
The `@namespace` at-rule.
|
|
||||||
|
|
||||||
- namespace: `String`. The part following `@namespace `.
|
|
||||||
|
|
||||||
#### page
|
|
||||||
|
|
||||||
The `@page` at-rule.
|
|
||||||
|
|
||||||
- selectors: `Array` of `String`s. The list of selectors of the rule, split
|
|
||||||
on commas. Each selector is trimmed from whitespace and comments.
|
|
||||||
- declarations: `Array` of nodes with the types `declaration` and `comment`.
|
|
||||||
|
|
||||||
#### supports
|
|
||||||
|
|
||||||
The `@supports` at-rule.
|
|
||||||
|
|
||||||
- supports: `String`. The part following `@supports `.
|
|
||||||
- rules: `Array` of nodes with the types `rule`, `comment` and any of the
|
|
||||||
at-rule types.
|
|
||||||
|
|
||||||
### container
|
|
||||||
|
|
||||||
The `@container` at-rule.
|
|
||||||
|
|
||||||
- conatiner: `String`. The part following `@container `.
|
|
||||||
- rules: `Array` of nodes with the types `rule`, `comment` and any of the
|
|
||||||
at-rule types.
|
|
||||||
|
|
||||||
### layer
|
|
||||||
|
|
||||||
The `@layer` at-rule.
|
|
||||||
|
|
||||||
- layer: `String`. The part following `@layer `.
|
|
||||||
- rules: `Array` of nodes with the types `rule`, `comment` and any of the
|
|
||||||
at-rule types. This may be null, if the rule did not contain any.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
CSS:
|
|
||||||
|
|
||||||
```css
|
|
||||||
body {
|
|
||||||
background: #eee;
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Parse tree:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "stylesheet",
|
|
||||||
"stylesheet": {
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"type": "rule",
|
|
||||||
"selectors": [
|
|
||||||
"body"
|
|
||||||
],
|
|
||||||
"declarations": [
|
|
||||||
{
|
|
||||||
"type": "declaration",
|
|
||||||
"property": "background",
|
|
||||||
"value": "#eee",
|
|
||||||
"position": {
|
|
||||||
"start": {
|
|
||||||
"line": 2,
|
|
||||||
"column": 3
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 2,
|
|
||||||
"column": 19
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "declaration",
|
|
||||||
"property": "color",
|
|
||||||
"value": "#888",
|
|
||||||
"position": {
|
|
||||||
"start": {
|
|
||||||
"line": 3,
|
|
||||||
"column": 3
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 3,
|
|
||||||
"column": 14
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"position": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 1
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 4,
|
|
||||||
"column": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
|
@ -1,762 +0,0 @@
|
||||||
function $parcel$defineInteropFlag(a) {
|
|
||||||
Object.defineProperty(a, '__esModule', {value: true, configurable: true});
|
|
||||||
}
|
|
||||||
function $parcel$exportWildcard(dest, source) {
|
|
||||||
Object.keys(source).forEach(function(key) {
|
|
||||||
if (key === 'default' || key === '__esModule' || dest.hasOwnProperty(key)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(dest, key, {
|
|
||||||
enumerable: true,
|
|
||||||
get: function get() {
|
|
||||||
return source[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
function $parcel$export(e, n, v, s) {
|
|
||||||
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
|
|
||||||
}
|
|
||||||
|
|
||||||
$parcel$defineInteropFlag(module.exports);
|
|
||||||
|
|
||||||
$parcel$export(module.exports, "parse", () => $882b6d93070905b3$export$98e6a39c04603d36);
|
|
||||||
$parcel$export(module.exports, "stringify", () => $882b6d93070905b3$export$fac44ee5b035f737);
|
|
||||||
$parcel$export(module.exports, "default", () => $882b6d93070905b3$export$2e2bcd8739ae039);
|
|
||||||
var $cb508b9219b02820$exports = {};
|
|
||||||
|
|
||||||
$parcel$defineInteropFlag($cb508b9219b02820$exports);
|
|
||||||
|
|
||||||
$parcel$export($cb508b9219b02820$exports, "default", () => $cb508b9219b02820$export$2e2bcd8739ae039);
|
|
||||||
class $cb508b9219b02820$export$2e2bcd8739ae039 extends Error {
|
|
||||||
constructor(filename, msg, lineno, column, css){
|
|
||||||
super(filename + ":" + lineno + ":" + column + ": " + msg);
|
|
||||||
this.reason = msg;
|
|
||||||
this.filename = filename;
|
|
||||||
this.line = lineno;
|
|
||||||
this.column = column;
|
|
||||||
this.source = css;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var $4bafb28828007b46$exports = {};
|
|
||||||
|
|
||||||
$parcel$defineInteropFlag($4bafb28828007b46$exports);
|
|
||||||
|
|
||||||
$parcel$export($4bafb28828007b46$exports, "default", () => $4bafb28828007b46$export$2e2bcd8739ae039);
|
|
||||||
/**
|
|
||||||
* Store position information for a node
|
|
||||||
*/ class $4bafb28828007b46$export$2e2bcd8739ae039 {
|
|
||||||
constructor(start, end, source){
|
|
||||||
this.start = start;
|
|
||||||
this.end = end;
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var $d103407e81c97042$exports = {};
|
|
||||||
|
|
||||||
$parcel$export($d103407e81c97042$exports, "CssTypes", () => $d103407e81c97042$export$9be5dd6e61d5d73a);
|
|
||||||
var $d103407e81c97042$export$9be5dd6e61d5d73a;
|
|
||||||
(function(CssTypes) {
|
|
||||||
CssTypes["stylesheet"] = "stylesheet";
|
|
||||||
CssTypes["rule"] = "rule";
|
|
||||||
CssTypes["declaration"] = "declaration";
|
|
||||||
CssTypes["comment"] = "comment";
|
|
||||||
CssTypes["container"] = "container";
|
|
||||||
CssTypes["charset"] = "charset";
|
|
||||||
CssTypes["document"] = "document";
|
|
||||||
CssTypes["customMedia"] = "custom-media";
|
|
||||||
CssTypes["fontFace"] = "font-face";
|
|
||||||
CssTypes["host"] = "host";
|
|
||||||
CssTypes["import"] = "import";
|
|
||||||
CssTypes["keyframes"] = "keyframes";
|
|
||||||
CssTypes["keyframe"] = "keyframe";
|
|
||||||
CssTypes["layer"] = "layer";
|
|
||||||
CssTypes["media"] = "media";
|
|
||||||
CssTypes["namespace"] = "namespace";
|
|
||||||
CssTypes["page"] = "page";
|
|
||||||
CssTypes["supports"] = "supports";
|
|
||||||
})($d103407e81c97042$export$9be5dd6e61d5d73a || ($d103407e81c97042$export$9be5dd6e61d5d73a = {}));
|
|
||||||
|
|
||||||
|
|
||||||
// http://www.w3.org/TR/CSS21/grammar.html
|
|
||||||
// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027
|
|
||||||
// New rule => https://www.w3.org/TR/CSS22/syndata.html#comments
|
|
||||||
// [^] is equivalent to [.\n\r]
|
|
||||||
const $b499486c7f02abe7$var$commentre = /\/\*[^]*?(?:\*\/|$)/g;
|
|
||||||
const $b499486c7f02abe7$export$98e6a39c04603d36 = (css, options)=>{
|
|
||||||
options = options || {};
|
|
||||||
/**
|
|
||||||
* Positional.
|
|
||||||
*/ let lineno = 1;
|
|
||||||
let column = 1;
|
|
||||||
/**
|
|
||||||
* Update lineno and column based on `str`.
|
|
||||||
*/ function updatePosition(str) {
|
|
||||||
const lines = str.match(/\n/g);
|
|
||||||
if (lines) lineno += lines.length;
|
|
||||||
const i = str.lastIndexOf("\n");
|
|
||||||
column = ~i ? str.length - i : column + str.length;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Mark position and patch `node.position`.
|
|
||||||
*/ function position() {
|
|
||||||
const start = {
|
|
||||||
line: lineno,
|
|
||||||
column: column
|
|
||||||
};
|
|
||||||
return function(node) {
|
|
||||||
node.position = new (0, $4bafb28828007b46$export$2e2bcd8739ae039)(start, {
|
|
||||||
line: lineno,
|
|
||||||
column: column
|
|
||||||
}, options?.source || "");
|
|
||||||
whitespace();
|
|
||||||
return node;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Error `msg`.
|
|
||||||
*/ const errorsList = [];
|
|
||||||
function error(msg) {
|
|
||||||
const err = new (0, $cb508b9219b02820$export$2e2bcd8739ae039)(options?.source || "", msg, lineno, column, css);
|
|
||||||
if (options?.silent) errorsList.push(err);
|
|
||||||
else throw err;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse stylesheet.
|
|
||||||
*/ function stylesheet() {
|
|
||||||
const rulesList = rules();
|
|
||||||
const result = {
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).stylesheet,
|
|
||||||
stylesheet: {
|
|
||||||
source: options?.source,
|
|
||||||
rules: rulesList,
|
|
||||||
parsingErrors: errorsList
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Opening brace.
|
|
||||||
*/ function open() {
|
|
||||||
return match(/^{\s*/);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Closing brace.
|
|
||||||
*/ function close() {
|
|
||||||
return match(/^}/);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse ruleset.
|
|
||||||
*/ function rules() {
|
|
||||||
let node;
|
|
||||||
const rules = [];
|
|
||||||
whitespace();
|
|
||||||
comments(rules);
|
|
||||||
while(css.length && css.charAt(0) !== "}" && (node = atrule() || rule()))if (node) {
|
|
||||||
rules.push(node);
|
|
||||||
comments(rules);
|
|
||||||
}
|
|
||||||
return rules;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Match `re` and return captures.
|
|
||||||
*/ function match(re) {
|
|
||||||
const m = re.exec(css);
|
|
||||||
if (!m) return;
|
|
||||||
const str = m[0];
|
|
||||||
updatePosition(str);
|
|
||||||
css = css.slice(str.length);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse whitespace.
|
|
||||||
*/ function whitespace() {
|
|
||||||
match(/^\s*/);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse comments;
|
|
||||||
*/ function comments(rules) {
|
|
||||||
let c;
|
|
||||||
rules = rules || [];
|
|
||||||
while(c = comment())if (c) rules.push(c);
|
|
||||||
return rules;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse comment.
|
|
||||||
*/ function comment() {
|
|
||||||
const pos = position();
|
|
||||||
if ("/" !== css.charAt(0) || "*" !== css.charAt(1)) return;
|
|
||||||
const m = match(/^\/\*[^]*?\*\//);
|
|
||||||
if (!m) return error("End of comment missing");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).comment,
|
|
||||||
comment: m[0].slice(2, -2)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse selector.
|
|
||||||
*/ function selector() {
|
|
||||||
const m = match(/^([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
// remove comment in selector;
|
|
||||||
const res = $b499486c7f02abe7$var$trim(m[0]).replace($b499486c7f02abe7$var$commentre, "");
|
|
||||||
// Optimisation: If there is no ',' no need to split or post-process (this is less costly)
|
|
||||||
if (res.indexOf(",") === -1) return [
|
|
||||||
res
|
|
||||||
];
|
|
||||||
return res/**
|
|
||||||
* replace ',' by \u200C for data selector (div[data-lang="fr,de,us"])
|
|
||||||
* replace ',' by \u200C for nthChild and other selector (div:nth-child(2,3,4))
|
|
||||||
*
|
|
||||||
* Examples:
|
|
||||||
* div[data-lang="fr,\"de,us"]
|
|
||||||
* div[data-lang='fr,\'de,us']
|
|
||||||
* div:matches(.toto, .titi:matches(.toto, .titi))
|
|
||||||
*
|
|
||||||
* Regex logic:
|
|
||||||
* ("|')(?:\\\1|.)*?\1 => Handle the " and '
|
|
||||||
* \(.*?\) => Handle the ()
|
|
||||||
*
|
|
||||||
* Optimization 1:
|
|
||||||
* No greedy capture (see docs about the difference between .* and .*?)
|
|
||||||
*
|
|
||||||
* Optimization 2:
|
|
||||||
* ("|')(?:\\\1|.)*?\1 this use reference to capture group, it work faster.
|
|
||||||
*/ .replace(/("|')(?:\\\1|.)*?\1|\(.*?\)/g, (m)=>m.replace(/,/g, ""))// Split the selector by ','
|
|
||||||
.split(",")// Replace back \u200C by ','
|
|
||||||
.map((s)=>{
|
|
||||||
return $b499486c7f02abe7$var$trim(s.replace(/\u200C/g, ","));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse declaration.
|
|
||||||
*/ function declaration() {
|
|
||||||
const pos = position();
|
|
||||||
// prop
|
|
||||||
const propMatch = match(/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/);
|
|
||||||
if (!propMatch) return;
|
|
||||||
const propValue = $b499486c7f02abe7$var$trim(propMatch[0]);
|
|
||||||
// :
|
|
||||||
if (!match(/^:\s*/)) return error("property missing ':'");
|
|
||||||
// val
|
|
||||||
const val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/);
|
|
||||||
const ret = pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).declaration,
|
|
||||||
property: propValue.replace($b499486c7f02abe7$var$commentre, ""),
|
|
||||||
value: val ? $b499486c7f02abe7$var$trim(val[0]).replace($b499486c7f02abe7$var$commentre, "") : ""
|
|
||||||
});
|
|
||||||
// ;
|
|
||||||
match(/^[;\s]*/);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse declarations.
|
|
||||||
*/ function declarations() {
|
|
||||||
const decls = [];
|
|
||||||
if (!open()) return error("missing '{'");
|
|
||||||
comments(decls);
|
|
||||||
// declarations
|
|
||||||
let decl;
|
|
||||||
while(decl = declaration())if (decl) {
|
|
||||||
decls.push(decl);
|
|
||||||
comments(decls);
|
|
||||||
}
|
|
||||||
if (!close()) return error("missing '}'");
|
|
||||||
return decls;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse keyframe.
|
|
||||||
*/ function keyframe() {
|
|
||||||
let m;
|
|
||||||
const vals = [];
|
|
||||||
const pos = position();
|
|
||||||
while(m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)){
|
|
||||||
vals.push(m[1]);
|
|
||||||
match(/^,\s*/);
|
|
||||||
}
|
|
||||||
if (!vals.length) return;
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).keyframe,
|
|
||||||
values: vals,
|
|
||||||
declarations: declarations() || []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse keyframes.
|
|
||||||
*/ function atkeyframes() {
|
|
||||||
const pos = position();
|
|
||||||
const m1 = match(/^@([-\w]+)?keyframes\s*/);
|
|
||||||
if (!m1) return;
|
|
||||||
const vendor = m1[1];
|
|
||||||
// identifier
|
|
||||||
const m2 = match(/^([-\w]+)\s*/);
|
|
||||||
if (!m2) return error("@keyframes missing name");
|
|
||||||
const name = m2[1];
|
|
||||||
if (!open()) return error("@keyframes missing '{'");
|
|
||||||
let frame;
|
|
||||||
let frames = comments();
|
|
||||||
while(frame = keyframe()){
|
|
||||||
frames.push(frame);
|
|
||||||
frames = frames.concat(comments());
|
|
||||||
}
|
|
||||||
if (!close()) return error("@keyframes missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).keyframes,
|
|
||||||
name: name,
|
|
||||||
vendor: vendor,
|
|
||||||
keyframes: frames
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse supports.
|
|
||||||
*/ function atsupports() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@supports *([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const supports = $b499486c7f02abe7$var$trim(m[1]);
|
|
||||||
if (!open()) return error("@supports missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@supports missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).supports,
|
|
||||||
supports: supports,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse host.
|
|
||||||
*/ function athost() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@host\s*/);
|
|
||||||
if (!m) return;
|
|
||||||
if (!open()) return error("@host missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@host missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).host,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse container.
|
|
||||||
*/ function atcontainer() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@container *([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const container = $b499486c7f02abe7$var$trim(m[1]);
|
|
||||||
if (!open()) return error("@container missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@container missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).container,
|
|
||||||
container: container,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse container.
|
|
||||||
*/ function atlayer() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@layer *([^{;@]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const layer = $b499486c7f02abe7$var$trim(m[1]);
|
|
||||||
if (!open()) {
|
|
||||||
match(/^[;\s]*/);
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).layer,
|
|
||||||
layer: layer
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@layer missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).layer,
|
|
||||||
layer: layer,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse media.
|
|
||||||
*/ function atmedia() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@media *([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const media = $b499486c7f02abe7$var$trim(m[1]);
|
|
||||||
if (!open()) return error("@media missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@media missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).media,
|
|
||||||
media: media,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse custom-media.
|
|
||||||
*/ function atcustommedia() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/);
|
|
||||||
if (!m) return;
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).customMedia,
|
|
||||||
name: $b499486c7f02abe7$var$trim(m[1]),
|
|
||||||
media: $b499486c7f02abe7$var$trim(m[2])
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse paged media.
|
|
||||||
*/ function atpage() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@page */);
|
|
||||||
if (!m) return;
|
|
||||||
const sel = selector() || [];
|
|
||||||
if (!open()) return error("@page missing '{'");
|
|
||||||
let decls = comments();
|
|
||||||
// declarations
|
|
||||||
let decl;
|
|
||||||
while(decl = declaration()){
|
|
||||||
decls.push(decl);
|
|
||||||
decls = decls.concat(comments());
|
|
||||||
}
|
|
||||||
if (!close()) return error("@page missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).page,
|
|
||||||
selectors: sel,
|
|
||||||
declarations: decls
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse document.
|
|
||||||
*/ function atdocument() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@([-\w]+)?document *([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const vendor = $b499486c7f02abe7$var$trim(m[1]);
|
|
||||||
const doc = $b499486c7f02abe7$var$trim(m[2]);
|
|
||||||
if (!open()) return error("@document missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@document missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).document,
|
|
||||||
document: doc,
|
|
||||||
vendor: vendor,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse font-face.
|
|
||||||
*/ function atfontface() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@font-face\s*/);
|
|
||||||
if (!m) return;
|
|
||||||
if (!open()) return error("@font-face missing '{'");
|
|
||||||
let decls = comments();
|
|
||||||
// declarations
|
|
||||||
let decl;
|
|
||||||
while(decl = declaration()){
|
|
||||||
decls.push(decl);
|
|
||||||
decls = decls.concat(comments());
|
|
||||||
}
|
|
||||||
if (!close()) return error("@font-face missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).fontFace,
|
|
||||||
declarations: decls
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse import
|
|
||||||
*/ const atimport = _compileAtrule("import");
|
|
||||||
/**
|
|
||||||
* Parse charset
|
|
||||||
*/ const atcharset = _compileAtrule("charset");
|
|
||||||
/**
|
|
||||||
* Parse namespace
|
|
||||||
*/ const atnamespace = _compileAtrule("namespace");
|
|
||||||
/**
|
|
||||||
* Parse non-block at-rules
|
|
||||||
*/ function _compileAtrule(name) {
|
|
||||||
const re = new RegExp("^@" + name + "\\s*((?::?[^;'\"]|\"(?:\\\\\"|[^\"])*?\"|'(?:\\\\'|[^'])*?')+)(?:;|$)");
|
|
||||||
// ^@import\s*([^;"']|("|')(?:\\\2|.)*?\2)+(;|$)
|
|
||||||
return function() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(re);
|
|
||||||
if (!m) return;
|
|
||||||
const ret = {
|
|
||||||
type: name
|
|
||||||
};
|
|
||||||
ret[name] = m[1].trim();
|
|
||||||
return pos(ret);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse at rule.
|
|
||||||
*/ function atrule() {
|
|
||||||
if (css[0] !== "@") return;
|
|
||||||
return atkeyframes() || atmedia() || atcustommedia() || atsupports() || atimport() || atcharset() || atnamespace() || atdocument() || atpage() || athost() || atfontface() || atcontainer() || atlayer();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse rule.
|
|
||||||
*/ function rule() {
|
|
||||||
const pos = position();
|
|
||||||
const sel = selector();
|
|
||||||
if (!sel) return error("selector missing");
|
|
||||||
comments();
|
|
||||||
return pos({
|
|
||||||
type: (0, $d103407e81c97042$export$9be5dd6e61d5d73a).rule,
|
|
||||||
selectors: sel,
|
|
||||||
declarations: declarations() || []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return $b499486c7f02abe7$var$addParent(stylesheet());
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Trim `str`.
|
|
||||||
*/ function $b499486c7f02abe7$var$trim(str) {
|
|
||||||
return str ? str.trim() : "";
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Adds non-enumerable parent node reference to each node.
|
|
||||||
*/ function $b499486c7f02abe7$var$addParent(obj, parent) {
|
|
||||||
const isNode = obj && typeof obj.type === "string";
|
|
||||||
const childParent = isNode ? obj : parent;
|
|
||||||
for(const k in obj){
|
|
||||||
const value = obj[k];
|
|
||||||
if (Array.isArray(value)) value.forEach((v)=>{
|
|
||||||
$b499486c7f02abe7$var$addParent(v, childParent);
|
|
||||||
});
|
|
||||||
else if (value && typeof value === "object") $b499486c7f02abe7$var$addParent(value, childParent);
|
|
||||||
}
|
|
||||||
if (isNode) Object.defineProperty(obj, "parent", {
|
|
||||||
configurable: true,
|
|
||||||
writable: true,
|
|
||||||
enumerable: false,
|
|
||||||
value: parent || null
|
|
||||||
});
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
var $b499486c7f02abe7$export$2e2bcd8739ae039 = $b499486c7f02abe7$export$98e6a39c04603d36;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class $24dc7e49cb76910e$var$Compiler {
|
|
||||||
constructor(options){
|
|
||||||
this.level = 0;
|
|
||||||
this.indentation = " ";
|
|
||||||
this.compress = false;
|
|
||||||
if (typeof options?.indent === "string") this.indentation = options?.indent;
|
|
||||||
if (options?.compress) this.compress = true;
|
|
||||||
}
|
|
||||||
// We disable no-unused-vars for _position. We keep position for potential reintroduction of source-map
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
emit(str, _position) {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Increase, decrease or return current indentation.
|
|
||||||
*/ indent(level) {
|
|
||||||
this.level = this.level || 1;
|
|
||||||
if (level) {
|
|
||||||
this.level += level;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return Array(this.level).join(this.indentation);
|
|
||||||
}
|
|
||||||
visit(node) {
|
|
||||||
switch(node.type){
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).stylesheet:
|
|
||||||
return this.stylesheet(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).rule:
|
|
||||||
return this.rule(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).declaration:
|
|
||||||
return this.declaration(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).comment:
|
|
||||||
return this.comment(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).container:
|
|
||||||
return this.container(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).charset:
|
|
||||||
return this.charset(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).document:
|
|
||||||
return this.document(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).customMedia:
|
|
||||||
return this.customMedia(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).fontFace:
|
|
||||||
return this.fontFace(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).host:
|
|
||||||
return this.host(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).import:
|
|
||||||
return this.import(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).keyframes:
|
|
||||||
return this.keyframes(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).keyframe:
|
|
||||||
return this.keyframe(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).layer:
|
|
||||||
return this.layer(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).media:
|
|
||||||
return this.media(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).namespace:
|
|
||||||
return this.namespace(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).page:
|
|
||||||
return this.page(node);
|
|
||||||
case (0, $d103407e81c97042$export$9be5dd6e61d5d73a).supports:
|
|
||||||
return this.supports(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mapVisit(nodes, delim) {
|
|
||||||
let buf = "";
|
|
||||||
delim = delim || "";
|
|
||||||
for(let i = 0, length = nodes.length; i < length; i++){
|
|
||||||
buf += this.visit(nodes[i]);
|
|
||||||
if (delim && i < length - 1) buf += this.emit(delim);
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
compile(node) {
|
|
||||||
if (this.compress) return node.stylesheet.rules.map(this.visit, this).join("");
|
|
||||||
return this.stylesheet(node);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit stylesheet node.
|
|
||||||
*/ stylesheet(node) {
|
|
||||||
return this.mapVisit(node.stylesheet.rules, "\n\n");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit comment node.
|
|
||||||
*/ comment(node) {
|
|
||||||
if (this.compress) return this.emit("", node.position);
|
|
||||||
return this.emit(this.indent() + "/*" + node.comment + "*/", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit container node.
|
|
||||||
*/ container(node) {
|
|
||||||
if (this.compress) return this.emit("@container " + node.container, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit(this.indent() + "@container " + node.container, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit container node.
|
|
||||||
*/ layer(node) {
|
|
||||||
if (this.compress) return this.emit("@layer " + node.layer, node.position) + (node.rules ? this.emit("{") + this.mapVisit(node.rules) + this.emit("}") : ";");
|
|
||||||
return this.emit(this.indent() + "@layer " + node.layer, node.position) + (node.rules ? this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}") : ";");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit import node.
|
|
||||||
*/ import(node) {
|
|
||||||
return this.emit("@import " + node.import + ";", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit media node.
|
|
||||||
*/ media(node) {
|
|
||||||
if (this.compress) return this.emit("@media " + node.media, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit(this.indent() + "@media " + node.media, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit document node.
|
|
||||||
*/ document(node) {
|
|
||||||
const doc = "@" + (node.vendor || "") + "document " + node.document;
|
|
||||||
if (this.compress) return this.emit(doc, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit(doc, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit(this.indent(-1) + "\n}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit charset node.
|
|
||||||
*/ charset(node) {
|
|
||||||
return this.emit("@charset " + node.charset + ";", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit namespace node.
|
|
||||||
*/ namespace(node) {
|
|
||||||
return this.emit("@namespace " + node.namespace + ";", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit supports node.
|
|
||||||
*/ supports(node) {
|
|
||||||
if (this.compress) return this.emit("@supports " + node.supports, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit(this.indent() + "@supports " + node.supports, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit keyframes node.
|
|
||||||
*/ keyframes(node) {
|
|
||||||
if (this.compress) return this.emit("@" + (node.vendor || "") + "keyframes " + node.name, node.position) + this.emit("{") + this.mapVisit(node.keyframes) + this.emit("}");
|
|
||||||
return this.emit("@" + (node.vendor || "") + "keyframes " + node.name, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.keyframes, "\n") + this.emit(this.indent(-1) + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit keyframe node.
|
|
||||||
*/ keyframe(node) {
|
|
||||||
const decls = node.declarations;
|
|
||||||
if (this.compress) return this.emit(node.values.join(","), node.position) + this.emit("{") + this.mapVisit(decls) + this.emit("}");
|
|
||||||
return this.emit(this.indent()) + this.emit(node.values.join(", "), node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(decls, "\n") + this.emit(this.indent(-1) + "\n" + this.indent() + "}\n");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit page node.
|
|
||||||
*/ page(node) {
|
|
||||||
if (this.compress) {
|
|
||||||
const sel = node.selectors.length ? node.selectors.join(", ") : "";
|
|
||||||
return this.emit("@page " + sel, node.position) + this.emit("{") + this.mapVisit(node.declarations) + this.emit("}");
|
|
||||||
}
|
|
||||||
const sel = node.selectors.length ? node.selectors.join(", ") + " " : "";
|
|
||||||
return this.emit("@page " + sel, node.position) + this.emit("{\n") + this.emit(this.indent(1)) + this.mapVisit(node.declarations, "\n") + this.emit(this.indent(-1)) + this.emit("\n}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit font-face node.
|
|
||||||
*/ fontFace(node) {
|
|
||||||
if (this.compress) return this.emit("@font-face", node.position) + this.emit("{") + this.mapVisit(node.declarations) + this.emit("}");
|
|
||||||
return this.emit("@font-face ", node.position) + this.emit("{\n") + this.emit(this.indent(1)) + this.mapVisit(node.declarations, "\n") + this.emit(this.indent(-1)) + this.emit("\n}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit host node.
|
|
||||||
*/ host(node) {
|
|
||||||
if (this.compress) return this.emit("@host", node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit("@host", node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit(this.indent(-1) + "\n}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit custom-media node.
|
|
||||||
*/ customMedia(node) {
|
|
||||||
return this.emit("@custom-media " + node.name + " " + node.media + ";", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit rule node.
|
|
||||||
*/ rule(node) {
|
|
||||||
const decls = node.declarations;
|
|
||||||
if (!decls.length) return "";
|
|
||||||
if (this.compress) return this.emit(node.selectors.join(","), node.position) + this.emit("{") + this.mapVisit(decls) + this.emit("}");
|
|
||||||
const indent = this.indent();
|
|
||||||
return this.emit(node.selectors.map((s)=>{
|
|
||||||
return indent + s;
|
|
||||||
}).join(",\n"), node.position) + this.emit(" {\n") + this.emit(this.indent(1)) + this.mapVisit(decls, "\n") + this.emit(this.indent(-1)) + this.emit("\n" + this.indent() + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit declaration node.
|
|
||||||
*/ declaration(node) {
|
|
||||||
if (this.compress) return this.emit(node.property + ":" + node.value, node.position) + this.emit(";");
|
|
||||||
return this.emit(this.indent()) + this.emit(node.property + ": " + node.value, node.position) + this.emit(";");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var $24dc7e49cb76910e$export$2e2bcd8739ae039 = $24dc7e49cb76910e$var$Compiler;
|
|
||||||
|
|
||||||
|
|
||||||
var $fd680ce0c35731f5$export$2e2bcd8739ae039 = (node, options)=>{
|
|
||||||
const compiler = new (0, $24dc7e49cb76910e$export$2e2bcd8739ae039)(options || {});
|
|
||||||
return compiler.compile(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const $882b6d93070905b3$export$98e6a39c04603d36 = (0, $b499486c7f02abe7$export$2e2bcd8739ae039);
|
|
||||||
const $882b6d93070905b3$export$fac44ee5b035f737 = (0, $fd680ce0c35731f5$export$2e2bcd8739ae039);
|
|
||||||
var $882b6d93070905b3$export$2e2bcd8739ae039 = {
|
|
||||||
parse: $882b6d93070905b3$export$98e6a39c04603d36,
|
|
||||||
stringify: $882b6d93070905b3$export$fac44ee5b035f737
|
|
||||||
};
|
|
||||||
$parcel$exportWildcard(module.exports, $d103407e81c97042$exports);
|
|
||||||
$parcel$exportWildcard(module.exports, $cb508b9219b02820$exports);
|
|
||||||
$parcel$exportWildcard(module.exports, $4bafb28828007b46$exports);
|
|
||||||
|
|
||||||
|
|
||||||
//# sourceMappingURL=index.cjs.map
|
|
File diff suppressed because one or more lines are too long
|
@ -1,738 +0,0 @@
|
||||||
function $parcel$defineInteropFlag(a) {
|
|
||||||
Object.defineProperty(a, '__esModule', {value: true, configurable: true});
|
|
||||||
}
|
|
||||||
function $parcel$export(e, n, v, s) {
|
|
||||||
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
|
|
||||||
}
|
|
||||||
var $009ddb00d3ec72b8$exports = {};
|
|
||||||
|
|
||||||
$parcel$defineInteropFlag($009ddb00d3ec72b8$exports);
|
|
||||||
|
|
||||||
$parcel$export($009ddb00d3ec72b8$exports, "default", () => $009ddb00d3ec72b8$export$2e2bcd8739ae039);
|
|
||||||
class $009ddb00d3ec72b8$export$2e2bcd8739ae039 extends Error {
|
|
||||||
constructor(filename, msg, lineno, column, css){
|
|
||||||
super(filename + ":" + lineno + ":" + column + ": " + msg);
|
|
||||||
this.reason = msg;
|
|
||||||
this.filename = filename;
|
|
||||||
this.line = lineno;
|
|
||||||
this.column = column;
|
|
||||||
this.source = css;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var $0865a9fb4cc365fe$exports = {};
|
|
||||||
|
|
||||||
$parcel$defineInteropFlag($0865a9fb4cc365fe$exports);
|
|
||||||
|
|
||||||
$parcel$export($0865a9fb4cc365fe$exports, "default", () => $0865a9fb4cc365fe$export$2e2bcd8739ae039);
|
|
||||||
/**
|
|
||||||
* Store position information for a node
|
|
||||||
*/ class $0865a9fb4cc365fe$export$2e2bcd8739ae039 {
|
|
||||||
constructor(start, end, source){
|
|
||||||
this.start = start;
|
|
||||||
this.end = end;
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var $b2e137848b48cf4f$exports = {};
|
|
||||||
|
|
||||||
$parcel$export($b2e137848b48cf4f$exports, "CssTypes", () => $b2e137848b48cf4f$export$9be5dd6e61d5d73a);
|
|
||||||
var $b2e137848b48cf4f$export$9be5dd6e61d5d73a;
|
|
||||||
(function(CssTypes) {
|
|
||||||
CssTypes["stylesheet"] = "stylesheet";
|
|
||||||
CssTypes["rule"] = "rule";
|
|
||||||
CssTypes["declaration"] = "declaration";
|
|
||||||
CssTypes["comment"] = "comment";
|
|
||||||
CssTypes["container"] = "container";
|
|
||||||
CssTypes["charset"] = "charset";
|
|
||||||
CssTypes["document"] = "document";
|
|
||||||
CssTypes["customMedia"] = "custom-media";
|
|
||||||
CssTypes["fontFace"] = "font-face";
|
|
||||||
CssTypes["host"] = "host";
|
|
||||||
CssTypes["import"] = "import";
|
|
||||||
CssTypes["keyframes"] = "keyframes";
|
|
||||||
CssTypes["keyframe"] = "keyframe";
|
|
||||||
CssTypes["layer"] = "layer";
|
|
||||||
CssTypes["media"] = "media";
|
|
||||||
CssTypes["namespace"] = "namespace";
|
|
||||||
CssTypes["page"] = "page";
|
|
||||||
CssTypes["supports"] = "supports";
|
|
||||||
})($b2e137848b48cf4f$export$9be5dd6e61d5d73a || ($b2e137848b48cf4f$export$9be5dd6e61d5d73a = {}));
|
|
||||||
|
|
||||||
|
|
||||||
// http://www.w3.org/TR/CSS21/grammar.html
|
|
||||||
// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027
|
|
||||||
// New rule => https://www.w3.org/TR/CSS22/syndata.html#comments
|
|
||||||
// [^] is equivalent to [.\n\r]
|
|
||||||
const $d708735ed1303b43$var$commentre = /\/\*[^]*?(?:\*\/|$)/g;
|
|
||||||
const $d708735ed1303b43$export$98e6a39c04603d36 = (css, options)=>{
|
|
||||||
options = options || {};
|
|
||||||
/**
|
|
||||||
* Positional.
|
|
||||||
*/ let lineno = 1;
|
|
||||||
let column = 1;
|
|
||||||
/**
|
|
||||||
* Update lineno and column based on `str`.
|
|
||||||
*/ function updatePosition(str) {
|
|
||||||
const lines = str.match(/\n/g);
|
|
||||||
if (lines) lineno += lines.length;
|
|
||||||
const i = str.lastIndexOf("\n");
|
|
||||||
column = ~i ? str.length - i : column + str.length;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Mark position and patch `node.position`.
|
|
||||||
*/ function position() {
|
|
||||||
const start = {
|
|
||||||
line: lineno,
|
|
||||||
column: column
|
|
||||||
};
|
|
||||||
return function(node) {
|
|
||||||
node.position = new (0, $0865a9fb4cc365fe$export$2e2bcd8739ae039)(start, {
|
|
||||||
line: lineno,
|
|
||||||
column: column
|
|
||||||
}, options?.source || "");
|
|
||||||
whitespace();
|
|
||||||
return node;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Error `msg`.
|
|
||||||
*/ const errorsList = [];
|
|
||||||
function error(msg) {
|
|
||||||
const err = new (0, $009ddb00d3ec72b8$export$2e2bcd8739ae039)(options?.source || "", msg, lineno, column, css);
|
|
||||||
if (options?.silent) errorsList.push(err);
|
|
||||||
else throw err;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse stylesheet.
|
|
||||||
*/ function stylesheet() {
|
|
||||||
const rulesList = rules();
|
|
||||||
const result = {
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).stylesheet,
|
|
||||||
stylesheet: {
|
|
||||||
source: options?.source,
|
|
||||||
rules: rulesList,
|
|
||||||
parsingErrors: errorsList
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Opening brace.
|
|
||||||
*/ function open() {
|
|
||||||
return match(/^{\s*/);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Closing brace.
|
|
||||||
*/ function close() {
|
|
||||||
return match(/^}/);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse ruleset.
|
|
||||||
*/ function rules() {
|
|
||||||
let node;
|
|
||||||
const rules = [];
|
|
||||||
whitespace();
|
|
||||||
comments(rules);
|
|
||||||
while(css.length && css.charAt(0) !== "}" && (node = atrule() || rule()))if (node) {
|
|
||||||
rules.push(node);
|
|
||||||
comments(rules);
|
|
||||||
}
|
|
||||||
return rules;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Match `re` and return captures.
|
|
||||||
*/ function match(re) {
|
|
||||||
const m = re.exec(css);
|
|
||||||
if (!m) return;
|
|
||||||
const str = m[0];
|
|
||||||
updatePosition(str);
|
|
||||||
css = css.slice(str.length);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse whitespace.
|
|
||||||
*/ function whitespace() {
|
|
||||||
match(/^\s*/);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse comments;
|
|
||||||
*/ function comments(rules) {
|
|
||||||
let c;
|
|
||||||
rules = rules || [];
|
|
||||||
while(c = comment())if (c) rules.push(c);
|
|
||||||
return rules;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse comment.
|
|
||||||
*/ function comment() {
|
|
||||||
const pos = position();
|
|
||||||
if ("/" !== css.charAt(0) || "*" !== css.charAt(1)) return;
|
|
||||||
const m = match(/^\/\*[^]*?\*\//);
|
|
||||||
if (!m) return error("End of comment missing");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).comment,
|
|
||||||
comment: m[0].slice(2, -2)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse selector.
|
|
||||||
*/ function selector() {
|
|
||||||
const m = match(/^([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
// remove comment in selector;
|
|
||||||
const res = $d708735ed1303b43$var$trim(m[0]).replace($d708735ed1303b43$var$commentre, "");
|
|
||||||
// Optimisation: If there is no ',' no need to split or post-process (this is less costly)
|
|
||||||
if (res.indexOf(",") === -1) return [
|
|
||||||
res
|
|
||||||
];
|
|
||||||
return res/**
|
|
||||||
* replace ',' by \u200C for data selector (div[data-lang="fr,de,us"])
|
|
||||||
* replace ',' by \u200C for nthChild and other selector (div:nth-child(2,3,4))
|
|
||||||
*
|
|
||||||
* Examples:
|
|
||||||
* div[data-lang="fr,\"de,us"]
|
|
||||||
* div[data-lang='fr,\'de,us']
|
|
||||||
* div:matches(.toto, .titi:matches(.toto, .titi))
|
|
||||||
*
|
|
||||||
* Regex logic:
|
|
||||||
* ("|')(?:\\\1|.)*?\1 => Handle the " and '
|
|
||||||
* \(.*?\) => Handle the ()
|
|
||||||
*
|
|
||||||
* Optimization 1:
|
|
||||||
* No greedy capture (see docs about the difference between .* and .*?)
|
|
||||||
*
|
|
||||||
* Optimization 2:
|
|
||||||
* ("|')(?:\\\1|.)*?\1 this use reference to capture group, it work faster.
|
|
||||||
*/ .replace(/("|')(?:\\\1|.)*?\1|\(.*?\)/g, (m)=>m.replace(/,/g, ""))// Split the selector by ','
|
|
||||||
.split(",")// Replace back \u200C by ','
|
|
||||||
.map((s)=>{
|
|
||||||
return $d708735ed1303b43$var$trim(s.replace(/\u200C/g, ","));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse declaration.
|
|
||||||
*/ function declaration() {
|
|
||||||
const pos = position();
|
|
||||||
// prop
|
|
||||||
const propMatch = match(/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/);
|
|
||||||
if (!propMatch) return;
|
|
||||||
const propValue = $d708735ed1303b43$var$trim(propMatch[0]);
|
|
||||||
// :
|
|
||||||
if (!match(/^:\s*/)) return error("property missing ':'");
|
|
||||||
// val
|
|
||||||
const val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/);
|
|
||||||
const ret = pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).declaration,
|
|
||||||
property: propValue.replace($d708735ed1303b43$var$commentre, ""),
|
|
||||||
value: val ? $d708735ed1303b43$var$trim(val[0]).replace($d708735ed1303b43$var$commentre, "") : ""
|
|
||||||
});
|
|
||||||
// ;
|
|
||||||
match(/^[;\s]*/);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse declarations.
|
|
||||||
*/ function declarations() {
|
|
||||||
const decls = [];
|
|
||||||
if (!open()) return error("missing '{'");
|
|
||||||
comments(decls);
|
|
||||||
// declarations
|
|
||||||
let decl;
|
|
||||||
while(decl = declaration())if (decl) {
|
|
||||||
decls.push(decl);
|
|
||||||
comments(decls);
|
|
||||||
}
|
|
||||||
if (!close()) return error("missing '}'");
|
|
||||||
return decls;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse keyframe.
|
|
||||||
*/ function keyframe() {
|
|
||||||
let m;
|
|
||||||
const vals = [];
|
|
||||||
const pos = position();
|
|
||||||
while(m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)){
|
|
||||||
vals.push(m[1]);
|
|
||||||
match(/^,\s*/);
|
|
||||||
}
|
|
||||||
if (!vals.length) return;
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframe,
|
|
||||||
values: vals,
|
|
||||||
declarations: declarations() || []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse keyframes.
|
|
||||||
*/ function atkeyframes() {
|
|
||||||
const pos = position();
|
|
||||||
const m1 = match(/^@([-\w]+)?keyframes\s*/);
|
|
||||||
if (!m1) return;
|
|
||||||
const vendor = m1[1];
|
|
||||||
// identifier
|
|
||||||
const m2 = match(/^([-\w]+)\s*/);
|
|
||||||
if (!m2) return error("@keyframes missing name");
|
|
||||||
const name = m2[1];
|
|
||||||
if (!open()) return error("@keyframes missing '{'");
|
|
||||||
let frame;
|
|
||||||
let frames = comments();
|
|
||||||
while(frame = keyframe()){
|
|
||||||
frames.push(frame);
|
|
||||||
frames = frames.concat(comments());
|
|
||||||
}
|
|
||||||
if (!close()) return error("@keyframes missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframes,
|
|
||||||
name: name,
|
|
||||||
vendor: vendor,
|
|
||||||
keyframes: frames
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse supports.
|
|
||||||
*/ function atsupports() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@supports *([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const supports = $d708735ed1303b43$var$trim(m[1]);
|
|
||||||
if (!open()) return error("@supports missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@supports missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).supports,
|
|
||||||
supports: supports,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse host.
|
|
||||||
*/ function athost() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@host\s*/);
|
|
||||||
if (!m) return;
|
|
||||||
if (!open()) return error("@host missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@host missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).host,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse container.
|
|
||||||
*/ function atcontainer() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@container *([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const container = $d708735ed1303b43$var$trim(m[1]);
|
|
||||||
if (!open()) return error("@container missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@container missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).container,
|
|
||||||
container: container,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse container.
|
|
||||||
*/ function atlayer() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@layer *([^{;@]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const layer = $d708735ed1303b43$var$trim(m[1]);
|
|
||||||
if (!open()) {
|
|
||||||
match(/^[;\s]*/);
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer,
|
|
||||||
layer: layer
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@layer missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer,
|
|
||||||
layer: layer,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse media.
|
|
||||||
*/ function atmedia() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@media *([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const media = $d708735ed1303b43$var$trim(m[1]);
|
|
||||||
if (!open()) return error("@media missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@media missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).media,
|
|
||||||
media: media,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse custom-media.
|
|
||||||
*/ function atcustommedia() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/);
|
|
||||||
if (!m) return;
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).customMedia,
|
|
||||||
name: $d708735ed1303b43$var$trim(m[1]),
|
|
||||||
media: $d708735ed1303b43$var$trim(m[2])
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse paged media.
|
|
||||||
*/ function atpage() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@page */);
|
|
||||||
if (!m) return;
|
|
||||||
const sel = selector() || [];
|
|
||||||
if (!open()) return error("@page missing '{'");
|
|
||||||
let decls = comments();
|
|
||||||
// declarations
|
|
||||||
let decl;
|
|
||||||
while(decl = declaration()){
|
|
||||||
decls.push(decl);
|
|
||||||
decls = decls.concat(comments());
|
|
||||||
}
|
|
||||||
if (!close()) return error("@page missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).page,
|
|
||||||
selectors: sel,
|
|
||||||
declarations: decls
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse document.
|
|
||||||
*/ function atdocument() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@([-\w]+)?document *([^{]+)/);
|
|
||||||
if (!m) return;
|
|
||||||
const vendor = $d708735ed1303b43$var$trim(m[1]);
|
|
||||||
const doc = $d708735ed1303b43$var$trim(m[2]);
|
|
||||||
if (!open()) return error("@document missing '{'");
|
|
||||||
const style = comments().concat(rules());
|
|
||||||
if (!close()) return error("@document missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).document,
|
|
||||||
document: doc,
|
|
||||||
vendor: vendor,
|
|
||||||
rules: style
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse font-face.
|
|
||||||
*/ function atfontface() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(/^@font-face\s*/);
|
|
||||||
if (!m) return;
|
|
||||||
if (!open()) return error("@font-face missing '{'");
|
|
||||||
let decls = comments();
|
|
||||||
// declarations
|
|
||||||
let decl;
|
|
||||||
while(decl = declaration()){
|
|
||||||
decls.push(decl);
|
|
||||||
decls = decls.concat(comments());
|
|
||||||
}
|
|
||||||
if (!close()) return error("@font-face missing '}'");
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).fontFace,
|
|
||||||
declarations: decls
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse import
|
|
||||||
*/ const atimport = _compileAtrule("import");
|
|
||||||
/**
|
|
||||||
* Parse charset
|
|
||||||
*/ const atcharset = _compileAtrule("charset");
|
|
||||||
/**
|
|
||||||
* Parse namespace
|
|
||||||
*/ const atnamespace = _compileAtrule("namespace");
|
|
||||||
/**
|
|
||||||
* Parse non-block at-rules
|
|
||||||
*/ function _compileAtrule(name) {
|
|
||||||
const re = new RegExp("^@" + name + "\\s*((?::?[^;'\"]|\"(?:\\\\\"|[^\"])*?\"|'(?:\\\\'|[^'])*?')+)(?:;|$)");
|
|
||||||
// ^@import\s*([^;"']|("|')(?:\\\2|.)*?\2)+(;|$)
|
|
||||||
return function() {
|
|
||||||
const pos = position();
|
|
||||||
const m = match(re);
|
|
||||||
if (!m) return;
|
|
||||||
const ret = {
|
|
||||||
type: name
|
|
||||||
};
|
|
||||||
ret[name] = m[1].trim();
|
|
||||||
return pos(ret);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse at rule.
|
|
||||||
*/ function atrule() {
|
|
||||||
if (css[0] !== "@") return;
|
|
||||||
return atkeyframes() || atmedia() || atcustommedia() || atsupports() || atimport() || atcharset() || atnamespace() || atdocument() || atpage() || athost() || atfontface() || atcontainer() || atlayer();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Parse rule.
|
|
||||||
*/ function rule() {
|
|
||||||
const pos = position();
|
|
||||||
const sel = selector();
|
|
||||||
if (!sel) return error("selector missing");
|
|
||||||
comments();
|
|
||||||
return pos({
|
|
||||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).rule,
|
|
||||||
selectors: sel,
|
|
||||||
declarations: declarations() || []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return $d708735ed1303b43$var$addParent(stylesheet());
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Trim `str`.
|
|
||||||
*/ function $d708735ed1303b43$var$trim(str) {
|
|
||||||
return str ? str.trim() : "";
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Adds non-enumerable parent node reference to each node.
|
|
||||||
*/ function $d708735ed1303b43$var$addParent(obj, parent) {
|
|
||||||
const isNode = obj && typeof obj.type === "string";
|
|
||||||
const childParent = isNode ? obj : parent;
|
|
||||||
for(const k in obj){
|
|
||||||
const value = obj[k];
|
|
||||||
if (Array.isArray(value)) value.forEach((v)=>{
|
|
||||||
$d708735ed1303b43$var$addParent(v, childParent);
|
|
||||||
});
|
|
||||||
else if (value && typeof value === "object") $d708735ed1303b43$var$addParent(value, childParent);
|
|
||||||
}
|
|
||||||
if (isNode) Object.defineProperty(obj, "parent", {
|
|
||||||
configurable: true,
|
|
||||||
writable: true,
|
|
||||||
enumerable: false,
|
|
||||||
value: parent || null
|
|
||||||
});
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
var $d708735ed1303b43$export$2e2bcd8739ae039 = $d708735ed1303b43$export$98e6a39c04603d36;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class $de9540138ed1fd01$var$Compiler {
|
|
||||||
constructor(options){
|
|
||||||
this.level = 0;
|
|
||||||
this.indentation = " ";
|
|
||||||
this.compress = false;
|
|
||||||
if (typeof options?.indent === "string") this.indentation = options?.indent;
|
|
||||||
if (options?.compress) this.compress = true;
|
|
||||||
}
|
|
||||||
// We disable no-unused-vars for _position. We keep position for potential reintroduction of source-map
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
emit(str, _position) {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Increase, decrease or return current indentation.
|
|
||||||
*/ indent(level) {
|
|
||||||
this.level = this.level || 1;
|
|
||||||
if (level) {
|
|
||||||
this.level += level;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return Array(this.level).join(this.indentation);
|
|
||||||
}
|
|
||||||
visit(node) {
|
|
||||||
switch(node.type){
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).stylesheet:
|
|
||||||
return this.stylesheet(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).rule:
|
|
||||||
return this.rule(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).declaration:
|
|
||||||
return this.declaration(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).comment:
|
|
||||||
return this.comment(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).container:
|
|
||||||
return this.container(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).charset:
|
|
||||||
return this.charset(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).document:
|
|
||||||
return this.document(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).customMedia:
|
|
||||||
return this.customMedia(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).fontFace:
|
|
||||||
return this.fontFace(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).host:
|
|
||||||
return this.host(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).import:
|
|
||||||
return this.import(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframes:
|
|
||||||
return this.keyframes(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframe:
|
|
||||||
return this.keyframe(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer:
|
|
||||||
return this.layer(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).media:
|
|
||||||
return this.media(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).namespace:
|
|
||||||
return this.namespace(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).page:
|
|
||||||
return this.page(node);
|
|
||||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).supports:
|
|
||||||
return this.supports(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mapVisit(nodes, delim) {
|
|
||||||
let buf = "";
|
|
||||||
delim = delim || "";
|
|
||||||
for(let i = 0, length = nodes.length; i < length; i++){
|
|
||||||
buf += this.visit(nodes[i]);
|
|
||||||
if (delim && i < length - 1) buf += this.emit(delim);
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
compile(node) {
|
|
||||||
if (this.compress) return node.stylesheet.rules.map(this.visit, this).join("");
|
|
||||||
return this.stylesheet(node);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit stylesheet node.
|
|
||||||
*/ stylesheet(node) {
|
|
||||||
return this.mapVisit(node.stylesheet.rules, "\n\n");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit comment node.
|
|
||||||
*/ comment(node) {
|
|
||||||
if (this.compress) return this.emit("", node.position);
|
|
||||||
return this.emit(this.indent() + "/*" + node.comment + "*/", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit container node.
|
|
||||||
*/ container(node) {
|
|
||||||
if (this.compress) return this.emit("@container " + node.container, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit(this.indent() + "@container " + node.container, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit container node.
|
|
||||||
*/ layer(node) {
|
|
||||||
if (this.compress) return this.emit("@layer " + node.layer, node.position) + (node.rules ? this.emit("{") + this.mapVisit(node.rules) + this.emit("}") : ";");
|
|
||||||
return this.emit(this.indent() + "@layer " + node.layer, node.position) + (node.rules ? this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}") : ";");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit import node.
|
|
||||||
*/ import(node) {
|
|
||||||
return this.emit("@import " + node.import + ";", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit media node.
|
|
||||||
*/ media(node) {
|
|
||||||
if (this.compress) return this.emit("@media " + node.media, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit(this.indent() + "@media " + node.media, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit document node.
|
|
||||||
*/ document(node) {
|
|
||||||
const doc = "@" + (node.vendor || "") + "document " + node.document;
|
|
||||||
if (this.compress) return this.emit(doc, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit(doc, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit(this.indent(-1) + "\n}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit charset node.
|
|
||||||
*/ charset(node) {
|
|
||||||
return this.emit("@charset " + node.charset + ";", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit namespace node.
|
|
||||||
*/ namespace(node) {
|
|
||||||
return this.emit("@namespace " + node.namespace + ";", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit supports node.
|
|
||||||
*/ supports(node) {
|
|
||||||
if (this.compress) return this.emit("@supports " + node.supports, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit(this.indent() + "@supports " + node.supports, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit keyframes node.
|
|
||||||
*/ keyframes(node) {
|
|
||||||
if (this.compress) return this.emit("@" + (node.vendor || "") + "keyframes " + node.name, node.position) + this.emit("{") + this.mapVisit(node.keyframes) + this.emit("}");
|
|
||||||
return this.emit("@" + (node.vendor || "") + "keyframes " + node.name, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.keyframes, "\n") + this.emit(this.indent(-1) + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit keyframe node.
|
|
||||||
*/ keyframe(node) {
|
|
||||||
const decls = node.declarations;
|
|
||||||
if (this.compress) return this.emit(node.values.join(","), node.position) + this.emit("{") + this.mapVisit(decls) + this.emit("}");
|
|
||||||
return this.emit(this.indent()) + this.emit(node.values.join(", "), node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(decls, "\n") + this.emit(this.indent(-1) + "\n" + this.indent() + "}\n");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit page node.
|
|
||||||
*/ page(node) {
|
|
||||||
if (this.compress) {
|
|
||||||
const sel = node.selectors.length ? node.selectors.join(", ") : "";
|
|
||||||
return this.emit("@page " + sel, node.position) + this.emit("{") + this.mapVisit(node.declarations) + this.emit("}");
|
|
||||||
}
|
|
||||||
const sel = node.selectors.length ? node.selectors.join(", ") + " " : "";
|
|
||||||
return this.emit("@page " + sel, node.position) + this.emit("{\n") + this.emit(this.indent(1)) + this.mapVisit(node.declarations, "\n") + this.emit(this.indent(-1)) + this.emit("\n}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit font-face node.
|
|
||||||
*/ fontFace(node) {
|
|
||||||
if (this.compress) return this.emit("@font-face", node.position) + this.emit("{") + this.mapVisit(node.declarations) + this.emit("}");
|
|
||||||
return this.emit("@font-face ", node.position) + this.emit("{\n") + this.emit(this.indent(1)) + this.mapVisit(node.declarations, "\n") + this.emit(this.indent(-1)) + this.emit("\n}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit host node.
|
|
||||||
*/ host(node) {
|
|
||||||
if (this.compress) return this.emit("@host", node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
|
||||||
return this.emit("@host", node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit(this.indent(-1) + "\n}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit custom-media node.
|
|
||||||
*/ customMedia(node) {
|
|
||||||
return this.emit("@custom-media " + node.name + " " + node.media + ";", node.position);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit rule node.
|
|
||||||
*/ rule(node) {
|
|
||||||
const decls = node.declarations;
|
|
||||||
if (!decls.length) return "";
|
|
||||||
if (this.compress) return this.emit(node.selectors.join(","), node.position) + this.emit("{") + this.mapVisit(decls) + this.emit("}");
|
|
||||||
const indent = this.indent();
|
|
||||||
return this.emit(node.selectors.map((s)=>{
|
|
||||||
return indent + s;
|
|
||||||
}).join(",\n"), node.position) + this.emit(" {\n") + this.emit(this.indent(1)) + this.mapVisit(decls, "\n") + this.emit(this.indent(-1)) + this.emit("\n" + this.indent() + "}");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Visit declaration node.
|
|
||||||
*/ declaration(node) {
|
|
||||||
if (this.compress) return this.emit(node.property + ":" + node.value, node.position) + this.emit(";");
|
|
||||||
return this.emit(this.indent()) + this.emit(node.property + ": " + node.value, node.position) + this.emit(";");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var $de9540138ed1fd01$export$2e2bcd8739ae039 = $de9540138ed1fd01$var$Compiler;
|
|
||||||
|
|
||||||
|
|
||||||
var $fdf773ab87e20450$export$2e2bcd8739ae039 = (node, options)=>{
|
|
||||||
const compiler = new (0, $de9540138ed1fd01$export$2e2bcd8739ae039)(options || {});
|
|
||||||
return compiler.compile(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const $149c1bd638913645$export$98e6a39c04603d36 = (0, $d708735ed1303b43$export$2e2bcd8739ae039);
|
|
||||||
const $149c1bd638913645$export$fac44ee5b035f737 = (0, $fdf773ab87e20450$export$2e2bcd8739ae039);
|
|
||||||
var $149c1bd638913645$export$2e2bcd8739ae039 = {
|
|
||||||
parse: $149c1bd638913645$export$98e6a39c04603d36,
|
|
||||||
stringify: $149c1bd638913645$export$fac44ee5b035f737
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export {$149c1bd638913645$export$98e6a39c04603d36 as parse, $149c1bd638913645$export$fac44ee5b035f737 as stringify, $149c1bd638913645$export$2e2bcd8739ae039 as default, $b2e137848b48cf4f$export$9be5dd6e61d5d73a as CssTypes};
|
|
||||||
//# sourceMappingURL=index.mjs.map
|
|
File diff suppressed because one or more lines are too long
|
@ -1,168 +0,0 @@
|
||||||
declare class CssParseError extends Error {
|
|
||||||
readonly reason: string;
|
|
||||||
readonly filename?: string;
|
|
||||||
readonly line: number;
|
|
||||||
readonly column: number;
|
|
||||||
readonly source: string;
|
|
||||||
constructor(filename: string, msg: string, lineno: number, column: number, css: string);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Store position information for a node
|
|
||||||
*/
|
|
||||||
declare class Position {
|
|
||||||
start: {
|
|
||||||
line: number;
|
|
||||||
column: number;
|
|
||||||
};
|
|
||||||
end: {
|
|
||||||
line: number;
|
|
||||||
column: number;
|
|
||||||
};
|
|
||||||
source?: string;
|
|
||||||
constructor(start: {
|
|
||||||
line: number;
|
|
||||||
column: number;
|
|
||||||
}, end: {
|
|
||||||
line: number;
|
|
||||||
column: number;
|
|
||||||
}, source: string);
|
|
||||||
}
|
|
||||||
export enum CssTypes {
|
|
||||||
stylesheet = "stylesheet",
|
|
||||||
rule = "rule",
|
|
||||||
declaration = "declaration",
|
|
||||||
comment = "comment",
|
|
||||||
container = "container",
|
|
||||||
charset = "charset",
|
|
||||||
document = "document",
|
|
||||||
customMedia = "custom-media",
|
|
||||||
fontFace = "font-face",
|
|
||||||
host = "host",
|
|
||||||
import = "import",
|
|
||||||
keyframes = "keyframes",
|
|
||||||
keyframe = "keyframe",
|
|
||||||
layer = "layer",
|
|
||||||
media = "media",
|
|
||||||
namespace = "namespace",
|
|
||||||
page = "page",
|
|
||||||
supports = "supports"
|
|
||||||
}
|
|
||||||
export type CssCommonAST = {
|
|
||||||
type: CssTypes;
|
|
||||||
};
|
|
||||||
export type CssCommonPositionAST = CssCommonAST & {
|
|
||||||
position?: Position;
|
|
||||||
parent?: unknown;
|
|
||||||
};
|
|
||||||
export type CssStylesheetAST = CssCommonAST & {
|
|
||||||
type: CssTypes.stylesheet;
|
|
||||||
stylesheet: {
|
|
||||||
source?: string;
|
|
||||||
rules: Array<CssAtRuleAST>;
|
|
||||||
parsingErrors?: Array<CssParseError>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export type CssRuleAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.rule;
|
|
||||||
selectors: Array<string>;
|
|
||||||
declarations: Array<CssDeclarationAST | CssCommentAST>;
|
|
||||||
};
|
|
||||||
export type CssDeclarationAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.declaration;
|
|
||||||
property: string;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
export type CssCommentAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.comment;
|
|
||||||
comment: string;
|
|
||||||
};
|
|
||||||
export type CssContainerAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.container;
|
|
||||||
container: string;
|
|
||||||
rules: Array<CssAtRuleAST>;
|
|
||||||
};
|
|
||||||
export type CssCharsetAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.charset;
|
|
||||||
charset: string;
|
|
||||||
};
|
|
||||||
export type CssCustomMediaAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.customMedia;
|
|
||||||
name: string;
|
|
||||||
media: string;
|
|
||||||
};
|
|
||||||
export type CssDocumentAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.document;
|
|
||||||
document: string;
|
|
||||||
vendor?: string;
|
|
||||||
rules: Array<CssAtRuleAST>;
|
|
||||||
};
|
|
||||||
export type CssFontFaceAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.fontFace;
|
|
||||||
declarations: Array<CssDeclarationAST | CssCommentAST>;
|
|
||||||
};
|
|
||||||
export type CssHostAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.host;
|
|
||||||
rules: Array<CssAtRuleAST>;
|
|
||||||
};
|
|
||||||
export type CssImportAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.import;
|
|
||||||
import: string;
|
|
||||||
};
|
|
||||||
export type CssKeyframesAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.keyframes;
|
|
||||||
name: string;
|
|
||||||
vendor?: string;
|
|
||||||
keyframes: Array<CssKeyframeAST | CssCommentAST>;
|
|
||||||
};
|
|
||||||
export type CssKeyframeAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.keyframe;
|
|
||||||
values: Array<string>;
|
|
||||||
declarations: Array<CssDeclarationAST | CssCommentAST>;
|
|
||||||
};
|
|
||||||
export type CssLayerAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.layer;
|
|
||||||
layer: string;
|
|
||||||
rules?: Array<CssAtRuleAST>;
|
|
||||||
};
|
|
||||||
export type CssMediaAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.media;
|
|
||||||
media: string;
|
|
||||||
rules: Array<CssAtRuleAST>;
|
|
||||||
};
|
|
||||||
export type CssNamespaceAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.namespace;
|
|
||||||
namespace: string;
|
|
||||||
};
|
|
||||||
export type CssPageAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.page;
|
|
||||||
selectors: Array<string>;
|
|
||||||
declarations: Array<CssDeclarationAST | CssCommentAST>;
|
|
||||||
};
|
|
||||||
export type CssSupportsAST = CssCommonPositionAST & {
|
|
||||||
type: CssTypes.supports;
|
|
||||||
supports: string;
|
|
||||||
rules: Array<CssAtRuleAST>;
|
|
||||||
};
|
|
||||||
export type CssAtRuleAST = CssRuleAST | CssCommentAST | CssContainerAST | CssCharsetAST | CssCustomMediaAST | CssDocumentAST | CssFontFaceAST | CssHostAST | CssImportAST | CssKeyframesAST | CssLayerAST | CssMediaAST | CssNamespaceAST | CssPageAST | CssSupportsAST;
|
|
||||||
export type CssAllNodesAST = CssAtRuleAST | CssStylesheetAST | CssDeclarationAST | CssKeyframeAST;
|
|
||||||
export const parse: (css: string, options?: {
|
|
||||||
source?: string | undefined;
|
|
||||||
silent?: boolean | undefined;
|
|
||||||
} | undefined) => CssStylesheetAST;
|
|
||||||
export const stringify: (node: CssStylesheetAST, options?: {
|
|
||||||
indent?: string | undefined;
|
|
||||||
compress?: boolean | undefined;
|
|
||||||
} | undefined) => string;
|
|
||||||
declare const _default: {
|
|
||||||
parse: (css: string, options?: {
|
|
||||||
source?: string | undefined;
|
|
||||||
silent?: boolean | undefined;
|
|
||||||
} | undefined) => CssStylesheetAST;
|
|
||||||
stringify: (node: CssStylesheetAST, options?: {
|
|
||||||
indent?: string | undefined;
|
|
||||||
compress?: boolean | undefined;
|
|
||||||
} | undefined) => string;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
|
|
||||||
//# sourceMappingURL=types.d.ts.map
|
|
|
@ -1 +0,0 @@
|
||||||
{"mappings":"AAAA,2BAAmC,SAAQ,KAAK;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGtB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM;CASd;ACrBD;;GAEG;AACH;IACE,KAAK,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC;IACtC,GAAG,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAGd,KAAK,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,EACrC,GAAG,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,EACnC,MAAM,EAAE,MAAM;CAMjB;ACdD;IACE,UAAU,eAAe;IACzB,IAAI,SAAS;IACb,WAAW,gBAAgB;IAC3B,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,WAAW,iBAAiB;IAC5B,QAAQ,cAAc;IACtB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,SAAS,cAAc;IACvB,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,2BAA2B;IACzB,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC;AAEF,mCAAmC,YAAY,GAAG;IAChD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,+BAA+B,YAAY,GAAG;IAC5C,IAAI,EAAE,SAAS,UAAU,CAAC;IAC1B,UAAU,EAAE;QACV,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;QAC3B,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;KACtC,CAAC;CACH,CAAC;AAEF,yBAAyB,oBAAoB,GAAG;IAC9C,IAAI,EAAE,SAAS,IAAI,CAAC;IACpB,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,YAAY,EAAE,KAAK,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAAC;CACxD,CAAC;AAEF,gCAAgC,oBAAoB,GAAG;IACrD,IAAI,EAAE,SAAS,WAAW,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,4BAA4B,oBAAoB,GAAG;IACjD,IAAI,EAAE,SAAS,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AACF,8BAA8B,oBAAoB,GAAG;IACnD,IAAI,EAAE,SAAS,SAAS,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC5B,CAAC;AAEF,4BAA4B,oBAAoB,GAAG;IACjD,IAAI,EAAE,SAAS,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AACF,gCAAgC,oBAAoB,GAAG;IACrD,IAAI,EAAE,SAAS,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AACF,6BAA6B,oBAAoB,GAAG;IAClD,IAAI,EAAE,SAAS,QAAQ,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC5B,CAAC;AACF,6BAA6B,oBAAoB,GAAG;IAClD,IAAI,EAAE,SAAS,QAAQ,CAAC;IACxB,YAAY,EAAE,KAAK,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAAC;CACxD,CAAC;AACF,yBAAyB,oBAAoB,GAAG;IAC9C,IAAI,EAAE,SAAS,IAAI,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC5B,CAAC;AACF,2BAA2B,oBAAoB,GAAG;IAChD,IAAI,EAAE,SAAS,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AACF,8BAA8B,oBAAoB,GAAG;IACnD,IAAI,EAAE,SAAS,SAAS,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,KAAK,CAAC,cAAc,GAAG,aAAa,CAAC,CAAC;CAClD,CAAC;AACF,6BAA6B,oBAAoB,GAAG;IAClD,IAAI,EAAE,SAAS,QAAQ,CAAC;IACxB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,YAAY,EAAE,KAAK,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAAC;CACxD,CAAC;AACF,0BAA0B,oBAAoB,GAAG;IAC/C,IAAI,EAAE,SAAS,KAAK,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC7B,CAAC;AACF,0BAA0B,oBAAoB,GAAG;IAC/C,IAAI,EAAE,SAAS,KAAK,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC5B,CAAC;AACF,8BAA8B,oBAAoB,GAAG;IACnD,IAAI,EAAE,SAAS,SAAS,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,yBAAyB,oBAAoB,GAAG;IAC9C,IAAI,EAAE,SAAS,IAAI,CAAC;IACpB,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,YAAY,EAAE,KAAK,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAAC;CACxD,CAAC;AACF,6BAA6B,oBAAoB,GAAG;IAClD,IAAI,EAAE,SAAS,QAAQ,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CAC5B,CAAC;AAEF,2BACI,UAAU,GACV,aAAa,GACb,eAAe,GACf,aAAa,GACb,iBAAiB,GACjB,cAAc,GACd,cAAc,GACd,UAAU,GACV,YAAY,GACZ,eAAe,GACf,WAAW,GACX,WAAW,GACX,eAAe,GACf,UAAU,GACV,cAAc,CAAC;AAEnB,6BACI,YAAY,GACZ,gBAAgB,GAChB,iBAAiB,GACjB,cAAc,CAAC;AIlJnB,OAAO,MAAM;;;qDAAe,CAAC;AAC7B,OAAO,MAAM;;;wBAAuB,CAAC;;;;;;;;;;;AAIrC,wBAAkC","sources":["src/src/CssParseError.ts","src/src/CssPosition.ts","src/src/type.ts","src/src/parse/index.ts","src/src/stringify/compiler.ts","src/src/stringify/index.ts","src/src/index.ts","src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,"import {default as parseFn} from './parse';\nimport {default as stringifyFn} from './stringify';\nexport const parse = parseFn;\nexport const stringify = stringifyFn;\nexport * from './type';\nexport * from './CssParseError';\nexport * from './CssPosition';\nexport default {parse, stringify};\n"],"names":[],"version":3,"file":"types.d.ts.map"}
|
|
|
@ -1,60 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@adobe/css-tools",
|
|
||||||
"version": "4.3.1",
|
|
||||||
"description": "CSS parser / stringifier",
|
|
||||||
"source": "src/index.ts",
|
|
||||||
"main": "./dist/index.cjs",
|
|
||||||
"module": "./dist/index.mjs",
|
|
||||||
"exports": {
|
|
||||||
"import": "./dist/index.mjs",
|
|
||||||
"require": "./dist/index.cjs"
|
|
||||||
},
|
|
||||||
"types": "./dist/types.d.ts",
|
|
||||||
"type": "module",
|
|
||||||
"files": [
|
|
||||||
"dist",
|
|
||||||
"Readme.md"
|
|
||||||
],
|
|
||||||
"devDependencies": {
|
|
||||||
"@parcel/packager-ts": "2.9.3",
|
|
||||||
"@parcel/transformer-typescript-types": "2.9.3",
|
|
||||||
"@types/benchmark": "^2.1.1",
|
|
||||||
"@types/bytes": "^3.1.1",
|
|
||||||
"@types/jest": "^29.5.3",
|
|
||||||
"@types/node": "^20.4.5",
|
|
||||||
"benchmark": "^2.1.4",
|
|
||||||
"bytes": "^3.1.0",
|
|
||||||
"gts": "^5.0.0",
|
|
||||||
"jest": "^29.6.2",
|
|
||||||
"parcel": "^2.9.3",
|
|
||||||
"ts-jest": "^29.1.1",
|
|
||||||
"typescript": "^5.0.2"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"benchmark": "node benchmark/index.mjs",
|
|
||||||
"test": "jest",
|
|
||||||
"clean": "gts clean && rm -rf ./dist",
|
|
||||||
"build": "parcel build && node ./utils/fix-type-generation.cjs",
|
|
||||||
"fix": "gts fix",
|
|
||||||
"lint": "gts lint",
|
|
||||||
"prepack": "npm run build",
|
|
||||||
"prepare": "npm run build",
|
|
||||||
"pretest": "npm run build",
|
|
||||||
"posttest": "npm run lint"
|
|
||||||
},
|
|
||||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
|
||||||
"contributors": [
|
|
||||||
"Jean-Philippe Zolesio <holblin@gmail.com>"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/adobe/css-tools.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"css",
|
|
||||||
"parser",
|
|
||||||
"stringifier",
|
|
||||||
"stylesheet"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,197 +0,0 @@
|
||||||
Description
|
|
||||||
===========
|
|
||||||
|
|
||||||
node-ftp is an FTP client module for [node.js](http://nodejs.org/) that provides an asynchronous interface for communicating with an FTP server.
|
|
||||||
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
============
|
|
||||||
|
|
||||||
* [node.js](http://nodejs.org/) -- v0.8.0 or newer
|
|
||||||
|
|
||||||
|
|
||||||
Install
|
|
||||||
=======
|
|
||||||
|
|
||||||
npm install ftp
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
|
||||||
========
|
|
||||||
|
|
||||||
* Get a directory listing of the current (remote) working directory:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var Client = require('ftp');
|
|
||||||
|
|
||||||
var c = new Client();
|
|
||||||
c.on('ready', function() {
|
|
||||||
c.list(function(err, list) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.dir(list);
|
|
||||||
c.end();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// connect to localhost:21 as anonymous
|
|
||||||
c.connect();
|
|
||||||
```
|
|
||||||
|
|
||||||
* Download remote file 'foo.txt' and save it to the local file system:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var Client = require('ftp');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var c = new Client();
|
|
||||||
c.on('ready', function() {
|
|
||||||
c.get('foo.txt', function(err, stream) {
|
|
||||||
if (err) throw err;
|
|
||||||
stream.once('close', function() { c.end(); });
|
|
||||||
stream.pipe(fs.createWriteStream('foo.local-copy.txt'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// connect to localhost:21 as anonymous
|
|
||||||
c.connect();
|
|
||||||
```
|
|
||||||
|
|
||||||
* Upload local file 'foo.txt' to the server:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var Client = require('ftp');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var c = new Client();
|
|
||||||
c.on('ready', function() {
|
|
||||||
c.put('foo.txt', 'foo.remote-copy.txt', function(err) {
|
|
||||||
if (err) throw err;
|
|
||||||
c.end();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// connect to localhost:21 as anonymous
|
|
||||||
c.connect();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
API
|
|
||||||
===
|
|
||||||
|
|
||||||
Events
|
|
||||||
------
|
|
||||||
|
|
||||||
* **greeting**(< _string_ >msg) - Emitted after connection. `msg` is the text the server sent upon connection.
|
|
||||||
|
|
||||||
* **ready**() - Emitted when connection and authentication were sucessful.
|
|
||||||
|
|
||||||
* **close**(< _boolean_ >hadErr) - Emitted when the connection has fully closed.
|
|
||||||
|
|
||||||
* **end**() - Emitted when the connection has ended.
|
|
||||||
|
|
||||||
* **error**(< _Error_ >err) - Emitted when an error occurs. In case of protocol-level errors, `err` contains a 'code' property that references the related 3-digit FTP response code.
|
|
||||||
|
|
||||||
|
|
||||||
Methods
|
|
||||||
-------
|
|
||||||
|
|
||||||
**\* Note: As with the 'error' event, any error objects passed to callbacks will have a 'code' property for protocol-level errors.**
|
|
||||||
|
|
||||||
* **(constructor)**() - Creates and returns a new FTP client instance.
|
|
||||||
|
|
||||||
* **connect**(< _object_ >config) - _(void)_ - Connects to an FTP server. Valid config properties:
|
|
||||||
|
|
||||||
* host - _string_ - The hostname or IP address of the FTP server. **Default:** 'localhost'
|
|
||||||
|
|
||||||
* port - _integer_ - The port of the FTP server. **Default:** 21
|
|
||||||
|
|
||||||
* secure - _mixed_ - Set to true for both control and data connection encryption, 'control' for control connection encryption only, or 'implicit' for implicitly encrypted control connection (this mode is deprecated in modern times, but usually uses port 990) **Default:** false
|
|
||||||
|
|
||||||
* secureOptions - _object_ - Additional options to be passed to `tls.connect()`. **Default:** (none)
|
|
||||||
|
|
||||||
* user - _string_ - Username for authentication. **Default:** 'anonymous'
|
|
||||||
|
|
||||||
* password - _string_ - Password for authentication. **Default:** 'anonymous@'
|
|
||||||
|
|
||||||
* connTimeout - _integer_ - How long (in milliseconds) to wait for the control connection to be established. **Default:** 10000
|
|
||||||
|
|
||||||
* pasvTimeout - _integer_ - How long (in milliseconds) to wait for a PASV data connection to be established. **Default:** 10000
|
|
||||||
|
|
||||||
* keepalive - _integer_ - How often (in milliseconds) to send a 'dummy' (NOOP) command to keep the connection alive. **Default:** 10000
|
|
||||||
|
|
||||||
* **end**() - _(void)_ - Closes the connection to the server after any/all enqueued commands have been executed.
|
|
||||||
|
|
||||||
* **destroy**() - _(void)_ - Closes the connection to the server immediately.
|
|
||||||
|
|
||||||
### Required "standard" commands (RFC 959)
|
|
||||||
|
|
||||||
* **list**([< _string_ >path, ][< _boolean_ >useCompression, ]< _function_ >callback) - _(void)_ - Retrieves the directory listing of `path`. `path` defaults to the current working directory. `useCompression` defaults to false. `callback` has 2 parameters: < _Error_ >err, < _array_ >list. `list` is an array of objects with these properties:
|
|
||||||
|
|
||||||
* type - _string_ - A single character denoting the entry type: 'd' for directory, '-' for file (or 'l' for symlink on **\*NIX only**).
|
|
||||||
|
|
||||||
* name - _string_ - The name of the entry.
|
|
||||||
|
|
||||||
* size - _string_ - The size of the entry in bytes.
|
|
||||||
|
|
||||||
* date - _Date_ - The last modified date of the entry.
|
|
||||||
|
|
||||||
* rights - _object_ - The various permissions for this entry **(*NIX only)**.
|
|
||||||
|
|
||||||
* user - _string_ - An empty string or any combination of 'r', 'w', 'x'.
|
|
||||||
|
|
||||||
* group - _string_ - An empty string or any combination of 'r', 'w', 'x'.
|
|
||||||
|
|
||||||
* other - _string_ - An empty string or any combination of 'r', 'w', 'x'.
|
|
||||||
|
|
||||||
* owner - _string_ - The user name or ID that this entry belongs to **(*NIX only)**.
|
|
||||||
|
|
||||||
* group - _string_ - The group name or ID that this entry belongs to **(*NIX only)**.
|
|
||||||
|
|
||||||
* target - _string_ - For symlink entries, this is the symlink's target **(*NIX only)**.
|
|
||||||
|
|
||||||
* sticky - _boolean_ - True if the sticky bit is set for this entry **(*NIX only)**.
|
|
||||||
|
|
||||||
* **get**(< _string_ >path, [< _boolean_ >useCompression, ]< _function_ >callback) - _(void)_ - Retrieves a file at `path` from the server. `useCompression` defaults to false. `callback` has 2 parameters: < _Error_ >err, < _ReadableStream_ >fileStream.
|
|
||||||
|
|
||||||
* **put**(< _mixed_ >input, < _string_ >destPath, [< _boolean_ >useCompression, ]< _function_ >callback) - _(void)_ - Sends data to the server to be stored as `destPath`. `input` can be a ReadableStream, a Buffer, or a path to a local file. `useCompression` defaults to false. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **append**(< _mixed_ >input, < _string_ >destPath, [< _boolean_ >useCompression, ]< _function_ >callback) - _(void)_ - Same as **put()**, except if `destPath` already exists, it will be appended to instead of overwritten.
|
|
||||||
|
|
||||||
* **rename**(< _string_ >oldPath, < _string_ >newPath, < _function_ >callback) - _(void)_ - Renames `oldPath` to `newPath` on the server. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **logout**(< _function_ >callback) - _(void)_ - Logout the user from the server. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **delete**(< _string_ >path, < _function_ >callback) - _(void)_ - Deletes a file, `path`, on the server. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **cwd**(< _string_ >path, < _function_ >callback) - _(void)_ - Changes the current working directory to `path`. `callback` has 2 parameters: < _Error_ >err, < _string_ >currentDir. Note: `currentDir` is only given if the server replies with the path in the response text.
|
|
||||||
|
|
||||||
* **abort**(< _function_ >callback) - _(void)_ - Aborts the current data transfer (e.g. from get(), put(), or list()). `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **site**(< _string_ >command, < _function_ >callback) - _(void)_ - Sends `command` (e.g. 'CHMOD 755 foo', 'QUOTA') using SITE. `callback` has 3 parameters: < _Error_ >err, < _string >responseText, < _integer_ >responseCode.
|
|
||||||
|
|
||||||
* **status**(< _function_ >callback) - _(void)_ - Retrieves human-readable information about the server's status. `callback` has 2 parameters: < _Error_ >err, < _string_ >status.
|
|
||||||
|
|
||||||
* **ascii**(< _function_ >callback) - _(void)_ - Sets the transfer data type to ASCII. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **binary**(< _function_ >callback) - _(void)_ - Sets the transfer data type to binary (default at time of connection). `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
### Optional "standard" commands (RFC 959)
|
|
||||||
|
|
||||||
* **mkdir**(< _string_ >path, [< _boolean_ >recursive, ]< _function_ >callback) - _(void)_ - Creates a new directory, `path`, on the server. `recursive` is for enabling a 'mkdir -p' algorithm and defaults to false. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **rmdir**(< _string_ >path, [< _boolean_ >recursive, ]< _function_ >callback) - _(void)_ - Removes a directory, `path`, on the server. If `recursive`, this call will delete the contents of the directory if it is not empty. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **cdup**(< _function_ >callback) - _(void)_ - Changes the working directory to the parent of the current directory. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **pwd**(< _function_ >callback) - _(void)_ - Retrieves the current working directory. `callback` has 2 parameters: < _Error_ >err, < _string_ >cwd.
|
|
||||||
|
|
||||||
* **system**(< _function_ >callback) - _(void)_ - Retrieves the server's operating system. `callback` has 2 parameters: < _Error_ >err, < _string_ >OS.
|
|
||||||
|
|
||||||
* **listSafe**([< _string_ >path, ][< _boolean_ >useCompression, ]< _function_ >callback) - _(void)_ - Similar to list(), except the directory is temporarily changed to `path` to retrieve the directory listing. This is useful for servers that do not handle characters like spaces and quotes in directory names well for the LIST command. This function is "optional" because it relies on pwd() being available.
|
|
||||||
|
|
||||||
### Extended commands (RFC 3659)
|
|
||||||
|
|
||||||
* **size**(< _string_ >path, < _function_ >callback) - _(void)_ - Retrieves the size of `path`. `callback` has 2 parameters: < _Error_ >err, < _integer_ >numBytes.
|
|
||||||
|
|
||||||
* **lastMod**(< _string_ >path, < _function_ >callback) - _(void)_ - Retrieves the last modified date and time for `path`. `callback` has 2 parameters: < _Error_ >err, < _Date_ >lastModified.
|
|
||||||
|
|
||||||
* **restart**(< _integer_ >byteOffset, < _function_ >callback) - _(void)_ - Sets the file byte offset for the next file transfer action (get/put) to `byteOffset`. `callback` has 1 parameter: < _Error_ >err.
|
|
||||||
|
|
||||||
* **mlsd**([< _string_ >path, ][< _boolean_ >useCompression, ]< _function_ >callback) - _(void)_ - Retrieves the directory listing of `path`. `path` defaults to the current working directory. `useCompression` defaults to false. `callback` has 2 parameters: < _Error_ >err, < _array_ >list. See the `list` command for a list of properties. Also see https://tools.ietf.org/html/rfc3659 7.2.
|
|
|
@ -1,3 +0,0 @@
|
||||||
- Add support for some SITE commands such as CHMOD, CHGRP, and QUOTA
|
|
||||||
- Active (non-passive) data connections
|
|
||||||
- IPv6 support
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,244 +0,0 @@
|
||||||
var WritableStream = require('stream').Writable
|
|
||||||
|| require('readable-stream').Writable,
|
|
||||||
inherits = require('util').inherits,
|
|
||||||
inspect = require('util').inspect;
|
|
||||||
|
|
||||||
var XRegExp = require('xregexp').XRegExp;
|
|
||||||
|
|
||||||
var REX_LISTUNIX = XRegExp.cache('^(?<type>[\\-ld])(?<permission>([\\-r][\\-w][\\-xstT]){3})(?<acl>(\\+))?\\s+(?<inodes>\\d+)\\s+(?<owner>\\S+)\\s+(?<group>\\S+)\\s+(?<size>\\d+)\\s+(?<timestamp>((?<month1>\\w{3})\\s+(?<date1>\\d{1,2})\\s+(?<hour>\\d{1,2}):(?<minute>\\d{2}))|((?<month2>\\w{3})\\s+(?<date2>\\d{1,2})\\s+(?<year>\\d{4})))\\s+(?<name>.+)$'),
|
|
||||||
REX_LISTMSDOS = XRegExp.cache('^(?<month>\\d{2})(?:\\-|\\/)(?<date>\\d{2})(?:\\-|\\/)(?<year>\\d{2,4})\\s+(?<hour>\\d{2}):(?<minute>\\d{2})\\s{0,1}(?<ampm>[AaMmPp]{1,2})\\s+(?:(?<size>\\d+)|(?<isdir>\\<DIR\\>))\\s+(?<name>.+)$'),
|
|
||||||
RE_ENTRY_TOTAL = /^total/,
|
|
||||||
RE_RES_END = /(?:^|\r?\n)(\d{3}) [^\r\n]*\r?\n/,
|
|
||||||
RE_EOL = /\r?\n/g,
|
|
||||||
RE_DASH = /\-/g,
|
|
||||||
RE_SEP = /;/g,
|
|
||||||
RE_EQ = /=/;
|
|
||||||
|
|
||||||
var MONTHS = {
|
|
||||||
jan: 1, feb: 2, mar: 3, apr: 4, may: 5, jun: 6,
|
|
||||||
jul: 7, aug: 8, sep: 9, oct: 10, nov: 11, dec: 12
|
|
||||||
};
|
|
||||||
|
|
||||||
function Parser(options) {
|
|
||||||
if (!(this instanceof Parser))
|
|
||||||
return new Parser(options);
|
|
||||||
WritableStream.call(this);
|
|
||||||
|
|
||||||
this._buffer = '';
|
|
||||||
this._debug = options.debug;
|
|
||||||
}
|
|
||||||
inherits(Parser, WritableStream);
|
|
||||||
|
|
||||||
Parser.prototype._write = function(chunk, encoding, cb) {
|
|
||||||
var m, code, reRmLeadCode, rest = '', debug = this._debug;
|
|
||||||
|
|
||||||
this._buffer += chunk.toString('binary');
|
|
||||||
|
|
||||||
while (m = RE_RES_END.exec(this._buffer)) {
|
|
||||||
// support multiple terminating responses in the buffer
|
|
||||||
rest = this._buffer.substring(m.index + m[0].length);
|
|
||||||
if (rest.length)
|
|
||||||
this._buffer = this._buffer.substring(0, m.index + m[0].length);
|
|
||||||
|
|
||||||
debug&&debug('[parser] < ' + inspect(this._buffer));
|
|
||||||
|
|
||||||
// we have a terminating response line
|
|
||||||
code = parseInt(m[1], 10);
|
|
||||||
|
|
||||||
// RFC 959 does not require each line in a multi-line response to begin
|
|
||||||
// with '<code>-', but many servers will do this.
|
|
||||||
//
|
|
||||||
// remove this leading '<code>-' (or '<code> ' from last line) from each
|
|
||||||
// line in the response ...
|
|
||||||
reRmLeadCode = '(^|\\r?\\n)';
|
|
||||||
reRmLeadCode += m[1];
|
|
||||||
reRmLeadCode += '(?: |\\-)';
|
|
||||||
reRmLeadCode = new RegExp(reRmLeadCode, 'g');
|
|
||||||
var text = this._buffer.replace(reRmLeadCode, '$1').trim();
|
|
||||||
this._buffer = rest;
|
|
||||||
|
|
||||||
debug&&debug('[parser] Response: code=' + code + ', buffer=' + inspect(text));
|
|
||||||
this.emit('response', code, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
|
|
||||||
Parser.parseFeat = function(text) {
|
|
||||||
var lines = text.split(RE_EOL);
|
|
||||||
lines.shift(); // initial response line
|
|
||||||
lines.pop(); // final response line
|
|
||||||
|
|
||||||
for (var i = 0, len = lines.length; i < len; ++i)
|
|
||||||
lines[i] = lines[i].trim();
|
|
||||||
|
|
||||||
// just return the raw lines for now
|
|
||||||
return lines;
|
|
||||||
};
|
|
||||||
|
|
||||||
Parser.parseListEntry = function(line) {
|
|
||||||
var ret,
|
|
||||||
info,
|
|
||||||
month, day, year,
|
|
||||||
hour, mins;
|
|
||||||
|
|
||||||
if (ret = XRegExp.exec(line, REX_LISTUNIX)) {
|
|
||||||
info = {
|
|
||||||
type: ret.type,
|
|
||||||
name: undefined,
|
|
||||||
target: undefined,
|
|
||||||
sticky: false,
|
|
||||||
rights: {
|
|
||||||
user: ret.permission.substr(0, 3).replace(RE_DASH, ''),
|
|
||||||
group: ret.permission.substr(3, 3).replace(RE_DASH, ''),
|
|
||||||
other: ret.permission.substr(6, 3).replace(RE_DASH, '')
|
|
||||||
},
|
|
||||||
acl: (ret.acl === '+'),
|
|
||||||
owner: ret.owner,
|
|
||||||
group: ret.group,
|
|
||||||
size: parseInt(ret.size, 10),
|
|
||||||
date: undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
// check for sticky bit
|
|
||||||
var lastbit = info.rights.other.slice(-1);
|
|
||||||
if (lastbit === 't') {
|
|
||||||
info.rights.other = info.rights.other.slice(0, -1) + 'x';
|
|
||||||
info.sticky = true;
|
|
||||||
} else if (lastbit === 'T') {
|
|
||||||
info.rights.other = info.rights.other.slice(0, -1);
|
|
||||||
info.sticky = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret.month1 !== undefined) {
|
|
||||||
month = parseInt(MONTHS[ret.month1.toLowerCase()], 10);
|
|
||||||
day = parseInt(ret.date1, 10);
|
|
||||||
year = (new Date()).getFullYear();
|
|
||||||
hour = parseInt(ret.hour, 10);
|
|
||||||
mins = parseInt(ret.minute, 10);
|
|
||||||
if (month < 10)
|
|
||||||
month = '0' + month;
|
|
||||||
if (day < 10)
|
|
||||||
day = '0' + day;
|
|
||||||
if (hour < 10)
|
|
||||||
hour = '0' + hour;
|
|
||||||
if (mins < 10)
|
|
||||||
mins = '0' + mins;
|
|
||||||
info.date = new Date(year + '-'
|
|
||||||
+ month + '-'
|
|
||||||
+ day + 'T'
|
|
||||||
+ hour + ':'
|
|
||||||
+ mins);
|
|
||||||
// If the date is in the past but no more than 6 months old, year
|
|
||||||
// isn't displayed and doesn't have to be the current year.
|
|
||||||
//
|
|
||||||
// If the date is in the future (less than an hour from now), year
|
|
||||||
// isn't displayed and doesn't have to be the current year.
|
|
||||||
// That second case is much more rare than the first and less annoying.
|
|
||||||
// It's impossible to fix without knowing about the server's timezone,
|
|
||||||
// so we just don't do anything about it.
|
|
||||||
//
|
|
||||||
// If we're here with a time that is more than 28 hours into the
|
|
||||||
// future (1 hour + maximum timezone offset which is 27 hours),
|
|
||||||
// there is a problem -- we should be in the second conditional block
|
|
||||||
if (info.date.getTime() - Date.now() > 100800000) {
|
|
||||||
info.date = new Date((year - 1) + '-'
|
|
||||||
+ month + '-'
|
|
||||||
+ day + 'T'
|
|
||||||
+ hour + ':'
|
|
||||||
+ mins);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're here with a time that is more than 6 months old, there's
|
|
||||||
// a problem as well.
|
|
||||||
// Maybe local & remote servers aren't on the same timezone (with remote
|
|
||||||
// ahead of local)
|
|
||||||
// For instance, remote is in 2014 while local is still in 2013. In
|
|
||||||
// this case, a date like 01/01/13 02:23 could be detected instead of
|
|
||||||
// 01/01/14 02:23
|
|
||||||
// Our trigger point will be 3600*24*31*6 (since we already use 31
|
|
||||||
// as an upper bound, no need to add the 27 hours timezone offset)
|
|
||||||
if (Date.now() - info.date.getTime() > 16070400000) {
|
|
||||||
info.date = new Date((year + 1) + '-'
|
|
||||||
+ month + '-'
|
|
||||||
+ day + 'T'
|
|
||||||
+ hour + ':'
|
|
||||||
+ mins);
|
|
||||||
}
|
|
||||||
} else if (ret.month2 !== undefined) {
|
|
||||||
month = parseInt(MONTHS[ret.month2.toLowerCase()], 10);
|
|
||||||
day = parseInt(ret.date2, 10);
|
|
||||||
year = parseInt(ret.year, 10);
|
|
||||||
if (month < 10)
|
|
||||||
month = '0' + month;
|
|
||||||
if (day < 10)
|
|
||||||
day = '0' + day;
|
|
||||||
info.date = new Date(year + '-' + month + '-' + day);
|
|
||||||
}
|
|
||||||
if (ret.type === 'l') {
|
|
||||||
var pos = ret.name.indexOf(' -> ');
|
|
||||||
info.name = ret.name.substring(0, pos);
|
|
||||||
info.target = ret.name.substring(pos+4);
|
|
||||||
} else
|
|
||||||
info.name = ret.name;
|
|
||||||
ret = info;
|
|
||||||
} else if (ret = XRegExp.exec(line, REX_LISTMSDOS)) {
|
|
||||||
info = {
|
|
||||||
name: ret.name,
|
|
||||||
type: (ret.isdir ? 'd' : '-'),
|
|
||||||
size: (ret.isdir ? 0 : parseInt(ret.size, 10)),
|
|
||||||
date: undefined,
|
|
||||||
};
|
|
||||||
month = parseInt(ret.month, 10),
|
|
||||||
day = parseInt(ret.date, 10),
|
|
||||||
year = parseInt(ret.year, 10),
|
|
||||||
hour = parseInt(ret.hour, 10),
|
|
||||||
mins = parseInt(ret.minute, 10);
|
|
||||||
|
|
||||||
if (year < 70)
|
|
||||||
year += 2000;
|
|
||||||
else
|
|
||||||
year += 1900;
|
|
||||||
|
|
||||||
if (ret.ampm[0].toLowerCase() === 'p' && hour < 12)
|
|
||||||
hour += 12;
|
|
||||||
else if (ret.ampm[0].toLowerCase() === 'a' && hour === 12)
|
|
||||||
hour = 0;
|
|
||||||
|
|
||||||
info.date = new Date(year, month - 1, day, hour, mins);
|
|
||||||
|
|
||||||
ret = info;
|
|
||||||
} else if (!RE_ENTRY_TOTAL.test(line))
|
|
||||||
ret = line; // could not parse, so at least give the end user a chance to
|
|
||||||
// look at the raw listing themselves
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
Parser.parseMlsdEntry = function(entry) {
|
|
||||||
var kvs = entry.split(RE_SEP);
|
|
||||||
var obj = { name: kvs.pop().substring(1) };
|
|
||||||
kvs.forEach(function(kv) {
|
|
||||||
kv = kv.split( RE_EQ );
|
|
||||||
obj[kv[0].toLowerCase()] = kv[1];
|
|
||||||
});
|
|
||||||
|
|
||||||
obj.size = parseInt(obj.size, 10);
|
|
||||||
|
|
||||||
var modify = obj.modify;
|
|
||||||
if (modify) {
|
|
||||||
var year = modify.substr(0, 4);
|
|
||||||
var month = modify.substr(4, 2);
|
|
||||||
var date = modify.substr(6, 2);
|
|
||||||
var hour = modify.substr(8, 2);
|
|
||||||
var minute = modify.substr(10, 2);
|
|
||||||
var second = modify.substr(12, 2);
|
|
||||||
obj.date = new Date(
|
|
||||||
year + '-' + month + '-' + date + 'T' + hour + ':' +minute + ':' + second
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Parser;
|
|
|
@ -1,5 +0,0 @@
|
||||||
build/
|
|
||||||
test/
|
|
||||||
examples/
|
|
||||||
fs.js
|
|
||||||
zlib.js
|
|
|
@ -1,18 +0,0 @@
|
||||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
||||||
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.
|
|
|
@ -1,15 +0,0 @@
|
||||||
# readable-stream
|
|
||||||
|
|
||||||
***Node-core streams for userland***
|
|
||||||
|
|
||||||
[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/)
|
|
||||||
[![NPM](https://nodei.co/npm-dl/readable-stream.png&months=6&height=3)](https://nodei.co/npm/readable-stream/)
|
|
||||||
|
|
||||||
This package is a mirror of the Streams2 and Streams3 implementations in Node-core.
|
|
||||||
|
|
||||||
If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core.
|
|
||||||
|
|
||||||
**readable-stream** comes in two major versions, v1.0.x and v1.1.x. The former tracks the Streams2 implementation in Node 0.10, including bug-fixes and minor improvements as they are added. The latter tracks Streams3 as it develops in Node 0.11; we will likely see a v1.2.x branch for Node 0.12.
|
|
||||||
|
|
||||||
**readable-stream** uses proper patch-level versioning so if you pin to `"~1.0.0"` you’ll get the latest Node 0.10 Streams2 implementation, including any fixes and minor non-breaking improvements. The patch-level versions of 1.0.x and 1.1.x should mirror the patch-level versions of Node-core releases. You should prefer the **1.0.x** releases for now and when you’re ready to start using Streams3, pin to `"~1.1.0"`
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
module.exports = require("./lib/_stream_duplex.js")
|
|
|
@ -1,923 +0,0 @@
|
||||||
diff --git a/lib/_stream_duplex.js b/lib/_stream_duplex.js
|
|
||||||
index c5a741c..a2e0d8e 100644
|
|
||||||
--- a/lib/_stream_duplex.js
|
|
||||||
+++ b/lib/_stream_duplex.js
|
|
||||||
@@ -26,8 +26,8 @@
|
|
||||||
|
|
||||||
module.exports = Duplex;
|
|
||||||
var util = require('util');
|
|
||||||
-var Readable = require('_stream_readable');
|
|
||||||
-var Writable = require('_stream_writable');
|
|
||||||
+var Readable = require('./_stream_readable');
|
|
||||||
+var Writable = require('./_stream_writable');
|
|
||||||
|
|
||||||
util.inherits(Duplex, Readable);
|
|
||||||
|
|
||||||
diff --git a/lib/_stream_passthrough.js b/lib/_stream_passthrough.js
|
|
||||||
index a5e9864..330c247 100644
|
|
||||||
--- a/lib/_stream_passthrough.js
|
|
||||||
+++ b/lib/_stream_passthrough.js
|
|
||||||
@@ -25,7 +25,7 @@
|
|
||||||
|
|
||||||
module.exports = PassThrough;
|
|
||||||
|
|
||||||
-var Transform = require('_stream_transform');
|
|
||||||
+var Transform = require('./_stream_transform');
|
|
||||||
var util = require('util');
|
|
||||||
util.inherits(PassThrough, Transform);
|
|
||||||
|
|
||||||
diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js
|
|
||||||
index 0c3fe3e..90a8298 100644
|
|
||||||
--- a/lib/_stream_readable.js
|
|
||||||
+++ b/lib/_stream_readable.js
|
|
||||||
@@ -23,10 +23,34 @@ module.exports = Readable;
|
|
||||||
Readable.ReadableState = ReadableState;
|
|
||||||
|
|
||||||
var EE = require('events').EventEmitter;
|
|
||||||
+if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
|
|
||||||
+ return emitter.listeners(type).length;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+if (!global.setImmediate) global.setImmediate = function setImmediate(fn) {
|
|
||||||
+ return setTimeout(fn, 0);
|
|
||||||
+};
|
|
||||||
+if (!global.clearImmediate) global.clearImmediate = function clearImmediate(i) {
|
|
||||||
+ return clearTimeout(i);
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
var Stream = require('stream');
|
|
||||||
var util = require('util');
|
|
||||||
+if (!util.isUndefined) {
|
|
||||||
+ var utilIs = require('core-util-is');
|
|
||||||
+ for (var f in utilIs) {
|
|
||||||
+ util[f] = utilIs[f];
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
var StringDecoder;
|
|
||||||
-var debug = util.debuglog('stream');
|
|
||||||
+var debug;
|
|
||||||
+if (util.debuglog)
|
|
||||||
+ debug = util.debuglog('stream');
|
|
||||||
+else try {
|
|
||||||
+ debug = require('debuglog')('stream');
|
|
||||||
+} catch (er) {
|
|
||||||
+ debug = function() {};
|
|
||||||
+}
|
|
||||||
|
|
||||||
util.inherits(Readable, Stream);
|
|
||||||
|
|
||||||
@@ -380,7 +404,7 @@ function chunkInvalid(state, chunk) {
|
|
||||||
|
|
||||||
|
|
||||||
function onEofChunk(stream, state) {
|
|
||||||
- if (state.decoder && !state.ended) {
|
|
||||||
+ if (state.decoder && !state.ended && state.decoder.end) {
|
|
||||||
var chunk = state.decoder.end();
|
|
||||||
if (chunk && chunk.length) {
|
|
||||||
state.buffer.push(chunk);
|
|
||||||
diff --git a/lib/_stream_transform.js b/lib/_stream_transform.js
|
|
||||||
index b1f9fcc..b0caf57 100644
|
|
||||||
--- a/lib/_stream_transform.js
|
|
||||||
+++ b/lib/_stream_transform.js
|
|
||||||
@@ -64,8 +64,14 @@
|
|
||||||
|
|
||||||
module.exports = Transform;
|
|
||||||
|
|
||||||
-var Duplex = require('_stream_duplex');
|
|
||||||
+var Duplex = require('./_stream_duplex');
|
|
||||||
var util = require('util');
|
|
||||||
+if (!util.isUndefined) {
|
|
||||||
+ var utilIs = require('core-util-is');
|
|
||||||
+ for (var f in utilIs) {
|
|
||||||
+ util[f] = utilIs[f];
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
util.inherits(Transform, Duplex);
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js
|
|
||||||
index ba2e920..f49288b 100644
|
|
||||||
--- a/lib/_stream_writable.js
|
|
||||||
+++ b/lib/_stream_writable.js
|
|
||||||
@@ -27,6 +27,12 @@ module.exports = Writable;
|
|
||||||
Writable.WritableState = WritableState;
|
|
||||||
|
|
||||||
var util = require('util');
|
|
||||||
+if (!util.isUndefined) {
|
|
||||||
+ var utilIs = require('core-util-is');
|
|
||||||
+ for (var f in utilIs) {
|
|
||||||
+ util[f] = utilIs[f];
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
var Stream = require('stream');
|
|
||||||
|
|
||||||
util.inherits(Writable, Stream);
|
|
||||||
@@ -119,7 +125,7 @@ function WritableState(options, stream) {
|
|
||||||
function Writable(options) {
|
|
||||||
// Writable ctor is applied to Duplexes, though they're not
|
|
||||||
// instanceof Writable, they're instanceof Readable.
|
|
||||||
- if (!(this instanceof Writable) && !(this instanceof Stream.Duplex))
|
|
||||||
+ if (!(this instanceof Writable) && !(this instanceof require('./_stream_duplex')))
|
|
||||||
return new Writable(options);
|
|
||||||
|
|
||||||
this._writableState = new WritableState(options, this);
|
|
||||||
diff --git a/test/simple/test-stream-big-push.js b/test/simple/test-stream-big-push.js
|
|
||||||
index e3787e4..8cd2127 100644
|
|
||||||
--- a/test/simple/test-stream-big-push.js
|
|
||||||
+++ b/test/simple/test-stream-big-push.js
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
var str = 'asdfasdfasdfasdfasdf';
|
|
||||||
|
|
||||||
var r = new stream.Readable({
|
|
||||||
diff --git a/test/simple/test-stream-end-paused.js b/test/simple/test-stream-end-paused.js
|
|
||||||
index bb73777..d40efc7 100644
|
|
||||||
--- a/test/simple/test-stream-end-paused.js
|
|
||||||
+++ b/test/simple/test-stream-end-paused.js
|
|
||||||
@@ -25,7 +25,7 @@ var gotEnd = false;
|
|
||||||
|
|
||||||
// Make sure we don't miss the end event for paused 0-length streams
|
|
||||||
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
var stream = new Readable();
|
|
||||||
var calledRead = false;
|
|
||||||
stream._read = function() {
|
|
||||||
diff --git a/test/simple/test-stream-pipe-after-end.js b/test/simple/test-stream-pipe-after-end.js
|
|
||||||
index b46ee90..0be8366 100644
|
|
||||||
--- a/test/simple/test-stream-pipe-after-end.js
|
|
||||||
+++ b/test/simple/test-stream-pipe-after-end.js
|
|
||||||
@@ -22,8 +22,8 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var Readable = require('_stream_readable');
|
|
||||||
-var Writable = require('_stream_writable');
|
|
||||||
+var Readable = require('../../lib/_stream_readable');
|
|
||||||
+var Writable = require('../../lib/_stream_writable');
|
|
||||||
var util = require('util');
|
|
||||||
|
|
||||||
util.inherits(TestReadable, Readable);
|
|
||||||
diff --git a/test/simple/test-stream-pipe-cleanup.js b/test/simple/test-stream-pipe-cleanup.js
|
|
||||||
deleted file mode 100644
|
|
||||||
index f689358..0000000
|
|
||||||
--- a/test/simple/test-stream-pipe-cleanup.js
|
|
||||||
+++ /dev/null
|
|
||||||
@@ -1,122 +0,0 @@
|
|
||||||
-// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
-//
|
|
||||||
-// 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.
|
|
||||||
-
|
|
||||||
-// This test asserts that Stream.prototype.pipe does not leave listeners
|
|
||||||
-// hanging on the source or dest.
|
|
||||||
-
|
|
||||||
-var common = require('../common');
|
|
||||||
-var stream = require('stream');
|
|
||||||
-var assert = require('assert');
|
|
||||||
-var util = require('util');
|
|
||||||
-
|
|
||||||
-function Writable() {
|
|
||||||
- this.writable = true;
|
|
||||||
- this.endCalls = 0;
|
|
||||||
- stream.Stream.call(this);
|
|
||||||
-}
|
|
||||||
-util.inherits(Writable, stream.Stream);
|
|
||||||
-Writable.prototype.end = function() {
|
|
||||||
- this.endCalls++;
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-Writable.prototype.destroy = function() {
|
|
||||||
- this.endCalls++;
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-function Readable() {
|
|
||||||
- this.readable = true;
|
|
||||||
- stream.Stream.call(this);
|
|
||||||
-}
|
|
||||||
-util.inherits(Readable, stream.Stream);
|
|
||||||
-
|
|
||||||
-function Duplex() {
|
|
||||||
- this.readable = true;
|
|
||||||
- Writable.call(this);
|
|
||||||
-}
|
|
||||||
-util.inherits(Duplex, Writable);
|
|
||||||
-
|
|
||||||
-var i = 0;
|
|
||||||
-var limit = 100;
|
|
||||||
-
|
|
||||||
-var w = new Writable();
|
|
||||||
-
|
|
||||||
-var r;
|
|
||||||
-
|
|
||||||
-for (i = 0; i < limit; i++) {
|
|
||||||
- r = new Readable();
|
|
||||||
- r.pipe(w);
|
|
||||||
- r.emit('end');
|
|
||||||
-}
|
|
||||||
-assert.equal(0, r.listeners('end').length);
|
|
||||||
-assert.equal(limit, w.endCalls);
|
|
||||||
-
|
|
||||||
-w.endCalls = 0;
|
|
||||||
-
|
|
||||||
-for (i = 0; i < limit; i++) {
|
|
||||||
- r = new Readable();
|
|
||||||
- r.pipe(w);
|
|
||||||
- r.emit('close');
|
|
||||||
-}
|
|
||||||
-assert.equal(0, r.listeners('close').length);
|
|
||||||
-assert.equal(limit, w.endCalls);
|
|
||||||
-
|
|
||||||
-w.endCalls = 0;
|
|
||||||
-
|
|
||||||
-r = new Readable();
|
|
||||||
-
|
|
||||||
-for (i = 0; i < limit; i++) {
|
|
||||||
- w = new Writable();
|
|
||||||
- r.pipe(w);
|
|
||||||
- w.emit('close');
|
|
||||||
-}
|
|
||||||
-assert.equal(0, w.listeners('close').length);
|
|
||||||
-
|
|
||||||
-r = new Readable();
|
|
||||||
-w = new Writable();
|
|
||||||
-var d = new Duplex();
|
|
||||||
-r.pipe(d); // pipeline A
|
|
||||||
-d.pipe(w); // pipeline B
|
|
||||||
-assert.equal(r.listeners('end').length, 2); // A.onend, A.cleanup
|
|
||||||
-assert.equal(r.listeners('close').length, 2); // A.onclose, A.cleanup
|
|
||||||
-assert.equal(d.listeners('end').length, 2); // B.onend, B.cleanup
|
|
||||||
-assert.equal(d.listeners('close').length, 3); // A.cleanup, B.onclose, B.cleanup
|
|
||||||
-assert.equal(w.listeners('end').length, 0);
|
|
||||||
-assert.equal(w.listeners('close').length, 1); // B.cleanup
|
|
||||||
-
|
|
||||||
-r.emit('end');
|
|
||||||
-assert.equal(d.endCalls, 1);
|
|
||||||
-assert.equal(w.endCalls, 0);
|
|
||||||
-assert.equal(r.listeners('end').length, 0);
|
|
||||||
-assert.equal(r.listeners('close').length, 0);
|
|
||||||
-assert.equal(d.listeners('end').length, 2); // B.onend, B.cleanup
|
|
||||||
-assert.equal(d.listeners('close').length, 2); // B.onclose, B.cleanup
|
|
||||||
-assert.equal(w.listeners('end').length, 0);
|
|
||||||
-assert.equal(w.listeners('close').length, 1); // B.cleanup
|
|
||||||
-
|
|
||||||
-d.emit('end');
|
|
||||||
-assert.equal(d.endCalls, 1);
|
|
||||||
-assert.equal(w.endCalls, 1);
|
|
||||||
-assert.equal(r.listeners('end').length, 0);
|
|
||||||
-assert.equal(r.listeners('close').length, 0);
|
|
||||||
-assert.equal(d.listeners('end').length, 0);
|
|
||||||
-assert.equal(d.listeners('close').length, 0);
|
|
||||||
-assert.equal(w.listeners('end').length, 0);
|
|
||||||
-assert.equal(w.listeners('close').length, 0);
|
|
||||||
diff --git a/test/simple/test-stream-pipe-error-handling.js b/test/simple/test-stream-pipe-error-handling.js
|
|
||||||
index c5d724b..c7d6b7d 100644
|
|
||||||
--- a/test/simple/test-stream-pipe-error-handling.js
|
|
||||||
+++ b/test/simple/test-stream-pipe-error-handling.js
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
-var Stream = require('stream').Stream;
|
|
||||||
+var Stream = require('../../').Stream;
|
|
||||||
|
|
||||||
(function testErrorListenerCatches() {
|
|
||||||
var source = new Stream();
|
|
||||||
diff --git a/test/simple/test-stream-pipe-event.js b/test/simple/test-stream-pipe-event.js
|
|
||||||
index cb9d5fe..56f8d61 100644
|
|
||||||
--- a/test/simple/test-stream-pipe-event.js
|
|
||||||
+++ b/test/simple/test-stream-pipe-event.js
|
|
||||||
@@ -20,7 +20,7 @@
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
var assert = require('assert');
|
|
||||||
var util = require('util');
|
|
||||||
|
|
||||||
diff --git a/test/simple/test-stream-push-order.js b/test/simple/test-stream-push-order.js
|
|
||||||
index f2e6ec2..a5c9bf9 100644
|
|
||||||
--- a/test/simple/test-stream-push-order.js
|
|
||||||
+++ b/test/simple/test-stream-push-order.js
|
|
||||||
@@ -20,7 +20,7 @@
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
var s = new Readable({
|
|
||||||
diff --git a/test/simple/test-stream-push-strings.js b/test/simple/test-stream-push-strings.js
|
|
||||||
index 06f43dc..1701a9a 100644
|
|
||||||
--- a/test/simple/test-stream-push-strings.js
|
|
||||||
+++ b/test/simple/test-stream-push-strings.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
var util = require('util');
|
|
||||||
|
|
||||||
util.inherits(MyStream, Readable);
|
|
||||||
diff --git a/test/simple/test-stream-readable-event.js b/test/simple/test-stream-readable-event.js
|
|
||||||
index ba6a577..a8e6f7b 100644
|
|
||||||
--- a/test/simple/test-stream-readable-event.js
|
|
||||||
+++ b/test/simple/test-stream-readable-event.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
|
|
||||||
(function first() {
|
|
||||||
// First test, not reading when the readable is added.
|
|
||||||
diff --git a/test/simple/test-stream-readable-flow-recursion.js b/test/simple/test-stream-readable-flow-recursion.js
|
|
||||||
index 2891ad6..11689ba 100644
|
|
||||||
--- a/test/simple/test-stream-readable-flow-recursion.js
|
|
||||||
+++ b/test/simple/test-stream-readable-flow-recursion.js
|
|
||||||
@@ -27,7 +27,7 @@ var assert = require('assert');
|
|
||||||
// more data continuously, but without triggering a nextTick
|
|
||||||
// warning or RangeError.
|
|
||||||
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
|
|
||||||
// throw an error if we trigger a nextTick warning.
|
|
||||||
process.throwDeprecation = true;
|
|
||||||
diff --git a/test/simple/test-stream-unshift-empty-chunk.js b/test/simple/test-stream-unshift-empty-chunk.js
|
|
||||||
index 0c96476..7827538 100644
|
|
||||||
--- a/test/simple/test-stream-unshift-empty-chunk.js
|
|
||||||
+++ b/test/simple/test-stream-unshift-empty-chunk.js
|
|
||||||
@@ -24,7 +24,7 @@ var assert = require('assert');
|
|
||||||
|
|
||||||
// This test verifies that stream.unshift(Buffer(0)) or
|
|
||||||
// stream.unshift('') does not set state.reading=false.
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
|
|
||||||
var r = new Readable();
|
|
||||||
var nChunks = 10;
|
|
||||||
diff --git a/test/simple/test-stream-unshift-read-race.js b/test/simple/test-stream-unshift-read-race.js
|
|
||||||
index 83fd9fa..17c18aa 100644
|
|
||||||
--- a/test/simple/test-stream-unshift-read-race.js
|
|
||||||
+++ b/test/simple/test-stream-unshift-read-race.js
|
|
||||||
@@ -29,7 +29,7 @@ var assert = require('assert');
|
|
||||||
// 3. push() after the EOF signaling null is an error.
|
|
||||||
// 4. _read() is not called after pushing the EOF null chunk.
|
|
||||||
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
var hwm = 10;
|
|
||||||
var r = stream.Readable({ highWaterMark: hwm });
|
|
||||||
var chunks = 10;
|
|
||||||
@@ -51,7 +51,14 @@ r._read = function(n) {
|
|
||||||
|
|
||||||
function push(fast) {
|
|
||||||
assert(!pushedNull, 'push() after null push');
|
|
||||||
- var c = pos >= data.length ? null : data.slice(pos, pos + n);
|
|
||||||
+ var c;
|
|
||||||
+ if (pos >= data.length)
|
|
||||||
+ c = null;
|
|
||||||
+ else {
|
|
||||||
+ if (n + pos > data.length)
|
|
||||||
+ n = data.length - pos;
|
|
||||||
+ c = data.slice(pos, pos + n);
|
|
||||||
+ }
|
|
||||||
pushedNull = c === null;
|
|
||||||
if (fast) {
|
|
||||||
pos += n;
|
|
||||||
diff --git a/test/simple/test-stream-writev.js b/test/simple/test-stream-writev.js
|
|
||||||
index 5b49e6e..b5321f3 100644
|
|
||||||
--- a/test/simple/test-stream-writev.js
|
|
||||||
+++ b/test/simple/test-stream-writev.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
|
|
||||||
var queue = [];
|
|
||||||
for (var decode = 0; decode < 2; decode++) {
|
|
||||||
diff --git a/test/simple/test-stream2-basic.js b/test/simple/test-stream2-basic.js
|
|
||||||
index 3814bf0..248c1be 100644
|
|
||||||
--- a/test/simple/test-stream2-basic.js
|
|
||||||
+++ b/test/simple/test-stream2-basic.js
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var R = require('_stream_readable');
|
|
||||||
+var R = require('../../lib/_stream_readable');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
var util = require('util');
|
|
||||||
diff --git a/test/simple/test-stream2-compatibility.js b/test/simple/test-stream2-compatibility.js
|
|
||||||
index 6cdd4e9..f0fa84b 100644
|
|
||||||
--- a/test/simple/test-stream2-compatibility.js
|
|
||||||
+++ b/test/simple/test-stream2-compatibility.js
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var R = require('_stream_readable');
|
|
||||||
+var R = require('../../lib/_stream_readable');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
var util = require('util');
|
|
||||||
diff --git a/test/simple/test-stream2-finish-pipe.js b/test/simple/test-stream2-finish-pipe.js
|
|
||||||
index 39b274f..006a19b 100644
|
|
||||||
--- a/test/simple/test-stream2-finish-pipe.js
|
|
||||||
+++ b/test/simple/test-stream2-finish-pipe.js
|
|
||||||
@@ -20,7 +20,7 @@
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
var Buffer = require('buffer').Buffer;
|
|
||||||
|
|
||||||
var r = new stream.Readable();
|
|
||||||
diff --git a/test/simple/test-stream2-fs.js b/test/simple/test-stream2-fs.js
|
|
||||||
deleted file mode 100644
|
|
||||||
index e162406..0000000
|
|
||||||
--- a/test/simple/test-stream2-fs.js
|
|
||||||
+++ /dev/null
|
|
||||||
@@ -1,72 +0,0 @@
|
|
||||||
-// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
-//
|
|
||||||
-// 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 common = require('../common.js');
|
|
||||||
-var R = require('_stream_readable');
|
|
||||||
-var assert = require('assert');
|
|
||||||
-
|
|
||||||
-var fs = require('fs');
|
|
||||||
-var FSReadable = fs.ReadStream;
|
|
||||||
-
|
|
||||||
-var path = require('path');
|
|
||||||
-var file = path.resolve(common.fixturesDir, 'x1024.txt');
|
|
||||||
-
|
|
||||||
-var size = fs.statSync(file).size;
|
|
||||||
-
|
|
||||||
-var expectLengths = [1024];
|
|
||||||
-
|
|
||||||
-var util = require('util');
|
|
||||||
-var Stream = require('stream');
|
|
||||||
-
|
|
||||||
-util.inherits(TestWriter, Stream);
|
|
||||||
-
|
|
||||||
-function TestWriter() {
|
|
||||||
- Stream.apply(this);
|
|
||||||
- this.buffer = [];
|
|
||||||
- this.length = 0;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-TestWriter.prototype.write = function(c) {
|
|
||||||
- this.buffer.push(c.toString());
|
|
||||||
- this.length += c.length;
|
|
||||||
- return true;
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-TestWriter.prototype.end = function(c) {
|
|
||||||
- if (c) this.buffer.push(c.toString());
|
|
||||||
- this.emit('results', this.buffer);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-var r = new FSReadable(file);
|
|
||||||
-var w = new TestWriter();
|
|
||||||
-
|
|
||||||
-w.on('results', function(res) {
|
|
||||||
- console.error(res, w.length);
|
|
||||||
- assert.equal(w.length, size);
|
|
||||||
- var l = 0;
|
|
||||||
- assert.deepEqual(res.map(function (c) {
|
|
||||||
- return c.length;
|
|
||||||
- }), expectLengths);
|
|
||||||
- console.log('ok');
|
|
||||||
-});
|
|
||||||
-
|
|
||||||
-r.pipe(w);
|
|
||||||
diff --git a/test/simple/test-stream2-httpclient-response-end.js b/test/simple/test-stream2-httpclient-response-end.js
|
|
||||||
deleted file mode 100644
|
|
||||||
index 15cffc2..0000000
|
|
||||||
--- a/test/simple/test-stream2-httpclient-response-end.js
|
|
||||||
+++ /dev/null
|
|
||||||
@@ -1,52 +0,0 @@
|
|
||||||
-// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
-//
|
|
||||||
-// 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 common = require('../common.js');
|
|
||||||
-var assert = require('assert');
|
|
||||||
-var http = require('http');
|
|
||||||
-var msg = 'Hello';
|
|
||||||
-var readable_event = false;
|
|
||||||
-var end_event = false;
|
|
||||||
-var server = http.createServer(function(req, res) {
|
|
||||||
- res.writeHead(200, {'Content-Type': 'text/plain'});
|
|
||||||
- res.end(msg);
|
|
||||||
-}).listen(common.PORT, function() {
|
|
||||||
- http.get({port: common.PORT}, function(res) {
|
|
||||||
- var data = '';
|
|
||||||
- res.on('readable', function() {
|
|
||||||
- console.log('readable event');
|
|
||||||
- readable_event = true;
|
|
||||||
- data += res.read();
|
|
||||||
- });
|
|
||||||
- res.on('end', function() {
|
|
||||||
- console.log('end event');
|
|
||||||
- end_event = true;
|
|
||||||
- assert.strictEqual(msg, data);
|
|
||||||
- server.close();
|
|
||||||
- });
|
|
||||||
- });
|
|
||||||
-});
|
|
||||||
-
|
|
||||||
-process.on('exit', function() {
|
|
||||||
- assert(readable_event);
|
|
||||||
- assert(end_event);
|
|
||||||
-});
|
|
||||||
-
|
|
||||||
diff --git a/test/simple/test-stream2-large-read-stall.js b/test/simple/test-stream2-large-read-stall.js
|
|
||||||
index 2fbfbca..667985b 100644
|
|
||||||
--- a/test/simple/test-stream2-large-read-stall.js
|
|
||||||
+++ b/test/simple/test-stream2-large-read-stall.js
|
|
||||||
@@ -30,7 +30,7 @@ var PUSHSIZE = 20;
|
|
||||||
var PUSHCOUNT = 1000;
|
|
||||||
var HWM = 50;
|
|
||||||
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
var r = new Readable({
|
|
||||||
highWaterMark: HWM
|
|
||||||
});
|
|
||||||
@@ -39,23 +39,23 @@ var rs = r._readableState;
|
|
||||||
r._read = push;
|
|
||||||
|
|
||||||
r.on('readable', function() {
|
|
||||||
- console.error('>> readable');
|
|
||||||
+ //console.error('>> readable');
|
|
||||||
do {
|
|
||||||
- console.error(' > read(%d)', READSIZE);
|
|
||||||
+ //console.error(' > read(%d)', READSIZE);
|
|
||||||
var ret = r.read(READSIZE);
|
|
||||||
- console.error(' < %j (%d remain)', ret && ret.length, rs.length);
|
|
||||||
+ //console.error(' < %j (%d remain)', ret && ret.length, rs.length);
|
|
||||||
} while (ret && ret.length === READSIZE);
|
|
||||||
|
|
||||||
- console.error('<< after read()',
|
|
||||||
- ret && ret.length,
|
|
||||||
- rs.needReadable,
|
|
||||||
- rs.length);
|
|
||||||
+ //console.error('<< after read()',
|
|
||||||
+ // ret && ret.length,
|
|
||||||
+ // rs.needReadable,
|
|
||||||
+ // rs.length);
|
|
||||||
});
|
|
||||||
|
|
||||||
var endEmitted = false;
|
|
||||||
r.on('end', function() {
|
|
||||||
endEmitted = true;
|
|
||||||
- console.error('end');
|
|
||||||
+ //console.error('end');
|
|
||||||
});
|
|
||||||
|
|
||||||
var pushes = 0;
|
|
||||||
@@ -64,11 +64,11 @@ function push() {
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (pushes++ === PUSHCOUNT) {
|
|
||||||
- console.error(' push(EOF)');
|
|
||||||
+ //console.error(' push(EOF)');
|
|
||||||
return r.push(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
- console.error(' push #%d', pushes);
|
|
||||||
+ //console.error(' push #%d', pushes);
|
|
||||||
if (r.push(new Buffer(PUSHSIZE)))
|
|
||||||
setTimeout(push);
|
|
||||||
}
|
|
||||||
diff --git a/test/simple/test-stream2-objects.js b/test/simple/test-stream2-objects.js
|
|
||||||
index 3e6931d..ff47d89 100644
|
|
||||||
--- a/test/simple/test-stream2-objects.js
|
|
||||||
+++ b/test/simple/test-stream2-objects.js
|
|
||||||
@@ -21,8 +21,8 @@
|
|
||||||
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var Readable = require('_stream_readable');
|
|
||||||
-var Writable = require('_stream_writable');
|
|
||||||
+var Readable = require('../../lib/_stream_readable');
|
|
||||||
+var Writable = require('../../lib/_stream_writable');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
// tiny node-tap lookalike.
|
|
||||||
diff --git a/test/simple/test-stream2-pipe-error-handling.js b/test/simple/test-stream2-pipe-error-handling.js
|
|
||||||
index cf7531c..e3f3e4e 100644
|
|
||||||
--- a/test/simple/test-stream2-pipe-error-handling.js
|
|
||||||
+++ b/test/simple/test-stream2-pipe-error-handling.js
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
|
|
||||||
(function testErrorListenerCatches() {
|
|
||||||
var count = 1000;
|
|
||||||
diff --git a/test/simple/test-stream2-pipe-error-once-listener.js b/test/simple/test-stream2-pipe-error-once-listener.js
|
|
||||||
index 5e8e3cb..53b2616 100755
|
|
||||||
--- a/test/simple/test-stream2-pipe-error-once-listener.js
|
|
||||||
+++ b/test/simple/test-stream2-pipe-error-once-listener.js
|
|
||||||
@@ -24,7 +24,7 @@ var common = require('../common.js');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
var util = require('util');
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
|
|
||||||
|
|
||||||
var Read = function() {
|
|
||||||
diff --git a/test/simple/test-stream2-push.js b/test/simple/test-stream2-push.js
|
|
||||||
index b63edc3..eb2b0e9 100644
|
|
||||||
--- a/test/simple/test-stream2-push.js
|
|
||||||
+++ b/test/simple/test-stream2-push.js
|
|
||||||
@@ -20,7 +20,7 @@
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
var Readable = stream.Readable;
|
|
||||||
var Writable = stream.Writable;
|
|
||||||
var assert = require('assert');
|
|
||||||
diff --git a/test/simple/test-stream2-read-sync-stack.js b/test/simple/test-stream2-read-sync-stack.js
|
|
||||||
index e8a7305..9740a47 100644
|
|
||||||
--- a/test/simple/test-stream2-read-sync-stack.js
|
|
||||||
+++ b/test/simple/test-stream2-read-sync-stack.js
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
var r = new Readable();
|
|
||||||
var N = 256 * 1024;
|
|
||||||
|
|
||||||
diff --git a/test/simple/test-stream2-readable-empty-buffer-no-eof.js b/test/simple/test-stream2-readable-empty-buffer-no-eof.js
|
|
||||||
index cd30178..4b1659d 100644
|
|
||||||
--- a/test/simple/test-stream2-readable-empty-buffer-no-eof.js
|
|
||||||
+++ b/test/simple/test-stream2-readable-empty-buffer-no-eof.js
|
|
||||||
@@ -22,10 +22,9 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var Readable = require('stream').Readable;
|
|
||||||
+var Readable = require('../../').Readable;
|
|
||||||
|
|
||||||
test1();
|
|
||||||
-test2();
|
|
||||||
|
|
||||||
function test1() {
|
|
||||||
var r = new Readable();
|
|
||||||
@@ -88,31 +87,3 @@ function test1() {
|
|
||||||
console.log('ok');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
-
|
|
||||||
-function test2() {
|
|
||||||
- var r = new Readable({ encoding: 'base64' });
|
|
||||||
- var reads = 5;
|
|
||||||
- r._read = function(n) {
|
|
||||||
- if (!reads--)
|
|
||||||
- return r.push(null); // EOF
|
|
||||||
- else
|
|
||||||
- return r.push(new Buffer('x'));
|
|
||||||
- };
|
|
||||||
-
|
|
||||||
- var results = [];
|
|
||||||
- function flow() {
|
|
||||||
- var chunk;
|
|
||||||
- while (null !== (chunk = r.read()))
|
|
||||||
- results.push(chunk + '');
|
|
||||||
- }
|
|
||||||
- r.on('readable', flow);
|
|
||||||
- r.on('end', function() {
|
|
||||||
- results.push('EOF');
|
|
||||||
- });
|
|
||||||
- flow();
|
|
||||||
-
|
|
||||||
- process.on('exit', function() {
|
|
||||||
- assert.deepEqual(results, [ 'eHh4', 'eHg=', 'EOF' ]);
|
|
||||||
- console.log('ok');
|
|
||||||
- });
|
|
||||||
-}
|
|
||||||
diff --git a/test/simple/test-stream2-readable-from-list.js b/test/simple/test-stream2-readable-from-list.js
|
|
||||||
index 7c96ffe..04a96f5 100644
|
|
||||||
--- a/test/simple/test-stream2-readable-from-list.js
|
|
||||||
+++ b/test/simple/test-stream2-readable-from-list.js
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
|
|
||||||
var assert = require('assert');
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var fromList = require('_stream_readable')._fromList;
|
|
||||||
+var fromList = require('../../lib/_stream_readable')._fromList;
|
|
||||||
|
|
||||||
// tiny node-tap lookalike.
|
|
||||||
var tests = [];
|
|
||||||
diff --git a/test/simple/test-stream2-readable-legacy-drain.js b/test/simple/test-stream2-readable-legacy-drain.js
|
|
||||||
index 675da8e..51fd3d5 100644
|
|
||||||
--- a/test/simple/test-stream2-readable-legacy-drain.js
|
|
||||||
+++ b/test/simple/test-stream2-readable-legacy-drain.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var Stream = require('stream');
|
|
||||||
+var Stream = require('../../');
|
|
||||||
var Readable = Stream.Readable;
|
|
||||||
|
|
||||||
var r = new Readable();
|
|
||||||
diff --git a/test/simple/test-stream2-readable-non-empty-end.js b/test/simple/test-stream2-readable-non-empty-end.js
|
|
||||||
index 7314ae7..c971898 100644
|
|
||||||
--- a/test/simple/test-stream2-readable-non-empty-end.js
|
|
||||||
+++ b/test/simple/test-stream2-readable-non-empty-end.js
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
|
|
||||||
var assert = require('assert');
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var Readable = require('_stream_readable');
|
|
||||||
+var Readable = require('../../lib/_stream_readable');
|
|
||||||
|
|
||||||
var len = 0;
|
|
||||||
var chunks = new Array(10);
|
|
||||||
diff --git a/test/simple/test-stream2-readable-wrap-empty.js b/test/simple/test-stream2-readable-wrap-empty.js
|
|
||||||
index 2e5cf25..fd8a3dc 100644
|
|
||||||
--- a/test/simple/test-stream2-readable-wrap-empty.js
|
|
||||||
+++ b/test/simple/test-stream2-readable-wrap-empty.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var Readable = require('_stream_readable');
|
|
||||||
+var Readable = require('../../lib/_stream_readable');
|
|
||||||
var EE = require('events').EventEmitter;
|
|
||||||
|
|
||||||
var oldStream = new EE();
|
|
||||||
diff --git a/test/simple/test-stream2-readable-wrap.js b/test/simple/test-stream2-readable-wrap.js
|
|
||||||
index 90eea01..6b177f7 100644
|
|
||||||
--- a/test/simple/test-stream2-readable-wrap.js
|
|
||||||
+++ b/test/simple/test-stream2-readable-wrap.js
|
|
||||||
@@ -22,8 +22,8 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var Readable = require('_stream_readable');
|
|
||||||
-var Writable = require('_stream_writable');
|
|
||||||
+var Readable = require('../../lib/_stream_readable');
|
|
||||||
+var Writable = require('../../lib/_stream_writable');
|
|
||||||
var EE = require('events').EventEmitter;
|
|
||||||
|
|
||||||
var testRuns = 0, completedRuns = 0;
|
|
||||||
diff --git a/test/simple/test-stream2-set-encoding.js b/test/simple/test-stream2-set-encoding.js
|
|
||||||
index 5d2c32a..685531b 100644
|
|
||||||
--- a/test/simple/test-stream2-set-encoding.js
|
|
||||||
+++ b/test/simple/test-stream2-set-encoding.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
var assert = require('assert');
|
|
||||||
-var R = require('_stream_readable');
|
|
||||||
+var R = require('../../lib/_stream_readable');
|
|
||||||
var util = require('util');
|
|
||||||
|
|
||||||
// tiny node-tap lookalike.
|
|
||||||
diff --git a/test/simple/test-stream2-transform.js b/test/simple/test-stream2-transform.js
|
|
||||||
index 9c9ddd8..a0cacc6 100644
|
|
||||||
--- a/test/simple/test-stream2-transform.js
|
|
||||||
+++ b/test/simple/test-stream2-transform.js
|
|
||||||
@@ -21,8 +21,8 @@
|
|
||||||
|
|
||||||
var assert = require('assert');
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var PassThrough = require('_stream_passthrough');
|
|
||||||
-var Transform = require('_stream_transform');
|
|
||||||
+var PassThrough = require('../../').PassThrough;
|
|
||||||
+var Transform = require('../../').Transform;
|
|
||||||
|
|
||||||
// tiny node-tap lookalike.
|
|
||||||
var tests = [];
|
|
||||||
diff --git a/test/simple/test-stream2-unpipe-drain.js b/test/simple/test-stream2-unpipe-drain.js
|
|
||||||
index d66dc3c..365b327 100644
|
|
||||||
--- a/test/simple/test-stream2-unpipe-drain.js
|
|
||||||
+++ b/test/simple/test-stream2-unpipe-drain.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
var assert = require('assert');
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
var crypto = require('crypto');
|
|
||||||
|
|
||||||
var util = require('util');
|
|
||||||
diff --git a/test/simple/test-stream2-unpipe-leak.js b/test/simple/test-stream2-unpipe-leak.js
|
|
||||||
index 99f8746..17c92ae 100644
|
|
||||||
--- a/test/simple/test-stream2-unpipe-leak.js
|
|
||||||
+++ b/test/simple/test-stream2-unpipe-leak.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
var assert = require('assert');
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
|
|
||||||
var chunk = new Buffer('hallo');
|
|
||||||
|
|
||||||
diff --git a/test/simple/test-stream2-writable.js b/test/simple/test-stream2-writable.js
|
|
||||||
index 704100c..209c3a6 100644
|
|
||||||
--- a/test/simple/test-stream2-writable.js
|
|
||||||
+++ b/test/simple/test-stream2-writable.js
|
|
||||||
@@ -20,8 +20,8 @@
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common.js');
|
|
||||||
-var W = require('_stream_writable');
|
|
||||||
-var D = require('_stream_duplex');
|
|
||||||
+var W = require('../../').Writable;
|
|
||||||
+var D = require('../../').Duplex;
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
var util = require('util');
|
|
||||||
diff --git a/test/simple/test-stream3-pause-then-read.js b/test/simple/test-stream3-pause-then-read.js
|
|
||||||
index b91bde3..2f72c15 100644
|
|
||||||
--- a/test/simple/test-stream3-pause-then-read.js
|
|
||||||
+++ b/test/simple/test-stream3-pause-then-read.js
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
-var stream = require('stream');
|
|
||||||
+var stream = require('../../');
|
|
||||||
var Readable = stream.Readable;
|
|
||||||
var Writable = stream.Writable;
|
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// a duplex stream is just a stream that is both readable and writable.
|
|
||||||
// Since JS doesn't have multiple prototypal inheritance, this class
|
|
||||||
// prototypally inherits from Readable, and then parasitically from
|
|
||||||
// Writable.
|
|
||||||
|
|
||||||
module.exports = Duplex;
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var objectKeys = Object.keys || function (obj) {
|
|
||||||
var keys = [];
|
|
||||||
for (var key in obj) keys.push(key);
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var util = require('core-util-is');
|
|
||||||
util.inherits = require('inherits');
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
var Readable = require('./_stream_readable');
|
|
||||||
var Writable = require('./_stream_writable');
|
|
||||||
|
|
||||||
util.inherits(Duplex, Readable);
|
|
||||||
|
|
||||||
forEach(objectKeys(Writable.prototype), function(method) {
|
|
||||||
if (!Duplex.prototype[method])
|
|
||||||
Duplex.prototype[method] = Writable.prototype[method];
|
|
||||||
});
|
|
||||||
|
|
||||||
function Duplex(options) {
|
|
||||||
if (!(this instanceof Duplex))
|
|
||||||
return new Duplex(options);
|
|
||||||
|
|
||||||
Readable.call(this, options);
|
|
||||||
Writable.call(this, options);
|
|
||||||
|
|
||||||
if (options && options.readable === false)
|
|
||||||
this.readable = false;
|
|
||||||
|
|
||||||
if (options && options.writable === false)
|
|
||||||
this.writable = false;
|
|
||||||
|
|
||||||
this.allowHalfOpen = true;
|
|
||||||
if (options && options.allowHalfOpen === false)
|
|
||||||
this.allowHalfOpen = false;
|
|
||||||
|
|
||||||
this.once('end', onend);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the no-half-open enforcer
|
|
||||||
function onend() {
|
|
||||||
// if we allow half-open state, or if the writable side ended,
|
|
||||||
// then we're ok.
|
|
||||||
if (this.allowHalfOpen || this._writableState.ended)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// no more data can be written.
|
|
||||||
// But allow more writes to happen in this tick.
|
|
||||||
process.nextTick(this.end.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
function forEach (xs, f) {
|
|
||||||
for (var i = 0, l = xs.length; i < l; i++) {
|
|
||||||
f(xs[i], i);
|
|
||||||
}
|
|
||||||
}
|
|
46
node_modules/@icetee/ftp/node_modules/readable-stream/lib/_stream_passthrough.js
generated
vendored
46
node_modules/@icetee/ftp/node_modules/readable-stream/lib/_stream_passthrough.js
generated
vendored
|
@ -1,46 +0,0 @@
|
||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// a passthrough stream.
|
|
||||||
// basically just the most minimal sort of Transform stream.
|
|
||||||
// Every written chunk gets output as-is.
|
|
||||||
|
|
||||||
module.exports = PassThrough;
|
|
||||||
|
|
||||||
var Transform = require('./_stream_transform');
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var util = require('core-util-is');
|
|
||||||
util.inherits = require('inherits');
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
util.inherits(PassThrough, Transform);
|
|
||||||
|
|
||||||
function PassThrough(options) {
|
|
||||||
if (!(this instanceof PassThrough))
|
|
||||||
return new PassThrough(options);
|
|
||||||
|
|
||||||
Transform.call(this, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
PassThrough.prototype._transform = function(chunk, encoding, cb) {
|
|
||||||
cb(null, chunk);
|
|
||||||
};
|
|
951
node_modules/@icetee/ftp/node_modules/readable-stream/lib/_stream_readable.js
generated
vendored
951
node_modules/@icetee/ftp/node_modules/readable-stream/lib/_stream_readable.js
generated
vendored
|
@ -1,951 +0,0 @@
|
||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
module.exports = Readable;
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var isArray = require('isarray');
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var Buffer = require('buffer').Buffer;
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
Readable.ReadableState = ReadableState;
|
|
||||||
|
|
||||||
var EE = require('events').EventEmitter;
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
|
|
||||||
return emitter.listeners(type).length;
|
|
||||||
};
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
var Stream = require('stream');
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var util = require('core-util-is');
|
|
||||||
util.inherits = require('inherits');
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
var StringDecoder;
|
|
||||||
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var debug = require('util');
|
|
||||||
if (debug && debug.debuglog) {
|
|
||||||
debug = debug.debuglog('stream');
|
|
||||||
} else {
|
|
||||||
debug = function () {};
|
|
||||||
}
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
|
|
||||||
util.inherits(Readable, Stream);
|
|
||||||
|
|
||||||
function ReadableState(options, stream) {
|
|
||||||
var Duplex = require('./_stream_duplex');
|
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
// the point at which it stops calling _read() to fill the buffer
|
|
||||||
// Note: 0 is a valid value, means "don't call _read preemptively ever"
|
|
||||||
var hwm = options.highWaterMark;
|
|
||||||
var defaultHwm = options.objectMode ? 16 : 16 * 1024;
|
|
||||||
this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
|
|
||||||
|
|
||||||
// cast to ints.
|
|
||||||
this.highWaterMark = ~~this.highWaterMark;
|
|
||||||
|
|
||||||
this.buffer = [];
|
|
||||||
this.length = 0;
|
|
||||||
this.pipes = null;
|
|
||||||
this.pipesCount = 0;
|
|
||||||
this.flowing = null;
|
|
||||||
this.ended = false;
|
|
||||||
this.endEmitted = false;
|
|
||||||
this.reading = false;
|
|
||||||
|
|
||||||
// a flag to be able to tell if the onwrite cb is called immediately,
|
|
||||||
// or on a later tick. We set this to true at first, because any
|
|
||||||
// actions that shouldn't happen until "later" should generally also
|
|
||||||
// not happen before the first write call.
|
|
||||||
this.sync = true;
|
|
||||||
|
|
||||||
// whenever we return null, then we set a flag to say
|
|
||||||
// that we're awaiting a 'readable' event emission.
|
|
||||||
this.needReadable = false;
|
|
||||||
this.emittedReadable = false;
|
|
||||||
this.readableListening = false;
|
|
||||||
|
|
||||||
|
|
||||||
// object stream flag. Used to make read(n) ignore n and to
|
|
||||||
// make all the buffer merging and length checks go away
|
|
||||||
this.objectMode = !!options.objectMode;
|
|
||||||
|
|
||||||
if (stream instanceof Duplex)
|
|
||||||
this.objectMode = this.objectMode || !!options.readableObjectMode;
|
|
||||||
|
|
||||||
// Crypto is kind of old and crusty. Historically, its default string
|
|
||||||
// encoding is 'binary' so we have to make this configurable.
|
|
||||||
// Everything else in the universe uses 'utf8', though.
|
|
||||||
this.defaultEncoding = options.defaultEncoding || 'utf8';
|
|
||||||
|
|
||||||
// when piping, we only care about 'readable' events that happen
|
|
||||||
// after read()ing all the bytes and not getting any pushback.
|
|
||||||
this.ranOut = false;
|
|
||||||
|
|
||||||
// the number of writers that are awaiting a drain event in .pipe()s
|
|
||||||
this.awaitDrain = 0;
|
|
||||||
|
|
||||||
// if true, a maybeReadMore has been scheduled
|
|
||||||
this.readingMore = false;
|
|
||||||
|
|
||||||
this.decoder = null;
|
|
||||||
this.encoding = null;
|
|
||||||
if (options.encoding) {
|
|
||||||
if (!StringDecoder)
|
|
||||||
StringDecoder = require('string_decoder/').StringDecoder;
|
|
||||||
this.decoder = new StringDecoder(options.encoding);
|
|
||||||
this.encoding = options.encoding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Readable(options) {
|
|
||||||
var Duplex = require('./_stream_duplex');
|
|
||||||
|
|
||||||
if (!(this instanceof Readable))
|
|
||||||
return new Readable(options);
|
|
||||||
|
|
||||||
this._readableState = new ReadableState(options, this);
|
|
||||||
|
|
||||||
// legacy
|
|
||||||
this.readable = true;
|
|
||||||
|
|
||||||
Stream.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manually shove something into the read() buffer.
|
|
||||||
// This returns true if the highWaterMark has not been hit yet,
|
|
||||||
// similar to how Writable.write() returns true if you should
|
|
||||||
// write() some more.
|
|
||||||
Readable.prototype.push = function(chunk, encoding) {
|
|
||||||
var state = this._readableState;
|
|
||||||
|
|
||||||
if (util.isString(chunk) && !state.objectMode) {
|
|
||||||
encoding = encoding || state.defaultEncoding;
|
|
||||||
if (encoding !== state.encoding) {
|
|
||||||
chunk = new Buffer(chunk, encoding);
|
|
||||||
encoding = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return readableAddChunk(this, state, chunk, encoding, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Unshift should *always* be something directly out of read()
|
|
||||||
Readable.prototype.unshift = function(chunk) {
|
|
||||||
var state = this._readableState;
|
|
||||||
return readableAddChunk(this, state, chunk, '', true);
|
|
||||||
};
|
|
||||||
|
|
||||||
function readableAddChunk(stream, state, chunk, encoding, addToFront) {
|
|
||||||
var er = chunkInvalid(state, chunk);
|
|
||||||
if (er) {
|
|
||||||
stream.emit('error', er);
|
|
||||||
} else if (util.isNullOrUndefined(chunk)) {
|
|
||||||
state.reading = false;
|
|
||||||
if (!state.ended)
|
|
||||||
onEofChunk(stream, state);
|
|
||||||
} else if (state.objectMode || chunk && chunk.length > 0) {
|
|
||||||
if (state.ended && !addToFront) {
|
|
||||||
var e = new Error('stream.push() after EOF');
|
|
||||||
stream.emit('error', e);
|
|
||||||
} else if (state.endEmitted && addToFront) {
|
|
||||||
var e = new Error('stream.unshift() after end event');
|
|
||||||
stream.emit('error', e);
|
|
||||||
} else {
|
|
||||||
if (state.decoder && !addToFront && !encoding)
|
|
||||||
chunk = state.decoder.write(chunk);
|
|
||||||
|
|
||||||
if (!addToFront)
|
|
||||||
state.reading = false;
|
|
||||||
|
|
||||||
// if we want the data now, just emit it.
|
|
||||||
if (state.flowing && state.length === 0 && !state.sync) {
|
|
||||||
stream.emit('data', chunk);
|
|
||||||
stream.read(0);
|
|
||||||
} else {
|
|
||||||
// update the buffer info.
|
|
||||||
state.length += state.objectMode ? 1 : chunk.length;
|
|
||||||
if (addToFront)
|
|
||||||
state.buffer.unshift(chunk);
|
|
||||||
else
|
|
||||||
state.buffer.push(chunk);
|
|
||||||
|
|
||||||
if (state.needReadable)
|
|
||||||
emitReadable(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
maybeReadMore(stream, state);
|
|
||||||
}
|
|
||||||
} else if (!addToFront) {
|
|
||||||
state.reading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return needMoreData(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if it's past the high water mark, we can push in some more.
|
|
||||||
// Also, if we have no data yet, we can stand some
|
|
||||||
// more bytes. This is to work around cases where hwm=0,
|
|
||||||
// such as the repl. Also, if the push() triggered a
|
|
||||||
// readable event, and the user called read(largeNumber) such that
|
|
||||||
// needReadable was set, then we ought to push more, so that another
|
|
||||||
// 'readable' event will be triggered.
|
|
||||||
function needMoreData(state) {
|
|
||||||
return !state.ended &&
|
|
||||||
(state.needReadable ||
|
|
||||||
state.length < state.highWaterMark ||
|
|
||||||
state.length === 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// backwards compatibility.
|
|
||||||
Readable.prototype.setEncoding = function(enc) {
|
|
||||||
if (!StringDecoder)
|
|
||||||
StringDecoder = require('string_decoder/').StringDecoder;
|
|
||||||
this._readableState.decoder = new StringDecoder(enc);
|
|
||||||
this._readableState.encoding = enc;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Don't raise the hwm > 128MB
|
|
||||||
var MAX_HWM = 0x800000;
|
|
||||||
function roundUpToNextPowerOf2(n) {
|
|
||||||
if (n >= MAX_HWM) {
|
|
||||||
n = MAX_HWM;
|
|
||||||
} else {
|
|
||||||
// Get the next highest power of 2
|
|
||||||
n--;
|
|
||||||
for (var p = 1; p < 32; p <<= 1) n |= n >> p;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
function howMuchToRead(n, state) {
|
|
||||||
if (state.length === 0 && state.ended)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (state.objectMode)
|
|
||||||
return n === 0 ? 0 : 1;
|
|
||||||
|
|
||||||
if (isNaN(n) || util.isNull(n)) {
|
|
||||||
// only flow one buffer at a time
|
|
||||||
if (state.flowing && state.buffer.length)
|
|
||||||
return state.buffer[0].length;
|
|
||||||
else
|
|
||||||
return state.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// If we're asking for more than the target buffer level,
|
|
||||||
// then raise the water mark. Bump up to the next highest
|
|
||||||
// power of 2, to prevent increasing it excessively in tiny
|
|
||||||
// amounts.
|
|
||||||
if (n > state.highWaterMark)
|
|
||||||
state.highWaterMark = roundUpToNextPowerOf2(n);
|
|
||||||
|
|
||||||
// don't have that much. return null, unless we've ended.
|
|
||||||
if (n > state.length) {
|
|
||||||
if (!state.ended) {
|
|
||||||
state.needReadable = true;
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
return state.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// you can override either this method, or the async _read(n) below.
|
|
||||||
Readable.prototype.read = function(n) {
|
|
||||||
debug('read', n);
|
|
||||||
var state = this._readableState;
|
|
||||||
var nOrig = n;
|
|
||||||
|
|
||||||
if (!util.isNumber(n) || n > 0)
|
|
||||||
state.emittedReadable = false;
|
|
||||||
|
|
||||||
// if we're doing read(0) to trigger a readable event, but we
|
|
||||||
// already have a bunch of data in the buffer, then just trigger
|
|
||||||
// the 'readable' event and move on.
|
|
||||||
if (n === 0 &&
|
|
||||||
state.needReadable &&
|
|
||||||
(state.length >= state.highWaterMark || state.ended)) {
|
|
||||||
debug('read: emitReadable', state.length, state.ended);
|
|
||||||
if (state.length === 0 && state.ended)
|
|
||||||
endReadable(this);
|
|
||||||
else
|
|
||||||
emitReadable(this);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = howMuchToRead(n, state);
|
|
||||||
|
|
||||||
// if we've ended, and we're now clear, then finish it up.
|
|
||||||
if (n === 0 && state.ended) {
|
|
||||||
if (state.length === 0)
|
|
||||||
endReadable(this);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All the actual chunk generation logic needs to be
|
|
||||||
// *below* the call to _read. The reason is that in certain
|
|
||||||
// synthetic stream cases, such as passthrough streams, _read
|
|
||||||
// may be a completely synchronous operation which may change
|
|
||||||
// the state of the read buffer, providing enough data when
|
|
||||||
// before there was *not* enough.
|
|
||||||
//
|
|
||||||
// So, the steps are:
|
|
||||||
// 1. Figure out what the state of things will be after we do
|
|
||||||
// a read from the buffer.
|
|
||||||
//
|
|
||||||
// 2. If that resulting state will trigger a _read, then call _read.
|
|
||||||
// Note that this may be asynchronous, or synchronous. Yes, it is
|
|
||||||
// deeply ugly to write APIs this way, but that still doesn't mean
|
|
||||||
// that the Readable class should behave improperly, as streams are
|
|
||||||
// designed to be sync/async agnostic.
|
|
||||||
// Take note if the _read call is sync or async (ie, if the read call
|
|
||||||
// has returned yet), so that we know whether or not it's safe to emit
|
|
||||||
// 'readable' etc.
|
|
||||||
//
|
|
||||||
// 3. Actually pull the requested chunks out of the buffer and return.
|
|
||||||
|
|
||||||
// if we need a readable event, then we need to do some reading.
|
|
||||||
var doRead = state.needReadable;
|
|
||||||
debug('need readable', doRead);
|
|
||||||
|
|
||||||
// if we currently have less than the highWaterMark, then also read some
|
|
||||||
if (state.length === 0 || state.length - n < state.highWaterMark) {
|
|
||||||
doRead = true;
|
|
||||||
debug('length less than watermark', doRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
// however, if we've ended, then there's no point, and if we're already
|
|
||||||
// reading, then it's unnecessary.
|
|
||||||
if (state.ended || state.reading) {
|
|
||||||
doRead = false;
|
|
||||||
debug('reading or ended', doRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doRead) {
|
|
||||||
debug('do read');
|
|
||||||
state.reading = true;
|
|
||||||
state.sync = true;
|
|
||||||
// if the length is currently zero, then we *need* a readable event.
|
|
||||||
if (state.length === 0)
|
|
||||||
state.needReadable = true;
|
|
||||||
// call internal read method
|
|
||||||
this._read(state.highWaterMark);
|
|
||||||
state.sync = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If _read pushed data synchronously, then `reading` will be false,
|
|
||||||
// and we need to re-evaluate how much data we can return to the user.
|
|
||||||
if (doRead && !state.reading)
|
|
||||||
n = howMuchToRead(nOrig, state);
|
|
||||||
|
|
||||||
var ret;
|
|
||||||
if (n > 0)
|
|
||||||
ret = fromList(n, state);
|
|
||||||
else
|
|
||||||
ret = null;
|
|
||||||
|
|
||||||
if (util.isNull(ret)) {
|
|
||||||
state.needReadable = true;
|
|
||||||
n = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.length -= n;
|
|
||||||
|
|
||||||
// If we have nothing in the buffer, then we want to know
|
|
||||||
// as soon as we *do* get something into the buffer.
|
|
||||||
if (state.length === 0 && !state.ended)
|
|
||||||
state.needReadable = true;
|
|
||||||
|
|
||||||
// If we tried to read() past the EOF, then emit end on the next tick.
|
|
||||||
if (nOrig !== n && state.ended && state.length === 0)
|
|
||||||
endReadable(this);
|
|
||||||
|
|
||||||
if (!util.isNull(ret))
|
|
||||||
this.emit('data', ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
function chunkInvalid(state, chunk) {
|
|
||||||
var er = null;
|
|
||||||
if (!util.isBuffer(chunk) &&
|
|
||||||
!util.isString(chunk) &&
|
|
||||||
!util.isNullOrUndefined(chunk) &&
|
|
||||||
!state.objectMode) {
|
|
||||||
er = new TypeError('Invalid non-string/buffer chunk');
|
|
||||||
}
|
|
||||||
return er;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function onEofChunk(stream, state) {
|
|
||||||
if (state.decoder && !state.ended) {
|
|
||||||
var chunk = state.decoder.end();
|
|
||||||
if (chunk && chunk.length) {
|
|
||||||
state.buffer.push(chunk);
|
|
||||||
state.length += state.objectMode ? 1 : chunk.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.ended = true;
|
|
||||||
|
|
||||||
// emit 'readable' now to make sure it gets picked up.
|
|
||||||
emitReadable(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't emit readable right away in sync mode, because this can trigger
|
|
||||||
// another read() call => stack overflow. This way, it might trigger
|
|
||||||
// a nextTick recursion warning, but that's not so bad.
|
|
||||||
function emitReadable(stream) {
|
|
||||||
var state = stream._readableState;
|
|
||||||
state.needReadable = false;
|
|
||||||
if (!state.emittedReadable) {
|
|
||||||
debug('emitReadable', state.flowing);
|
|
||||||
state.emittedReadable = true;
|
|
||||||
if (state.sync)
|
|
||||||
process.nextTick(function() {
|
|
||||||
emitReadable_(stream);
|
|
||||||
});
|
|
||||||
else
|
|
||||||
emitReadable_(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function emitReadable_(stream) {
|
|
||||||
debug('emit readable');
|
|
||||||
stream.emit('readable');
|
|
||||||
flow(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// at this point, the user has presumably seen the 'readable' event,
|
|
||||||
// and called read() to consume some data. that may have triggered
|
|
||||||
// in turn another _read(n) call, in which case reading = true if
|
|
||||||
// it's in progress.
|
|
||||||
// However, if we're not ended, or reading, and the length < hwm,
|
|
||||||
// then go ahead and try to read some more preemptively.
|
|
||||||
function maybeReadMore(stream, state) {
|
|
||||||
if (!state.readingMore) {
|
|
||||||
state.readingMore = true;
|
|
||||||
process.nextTick(function() {
|
|
||||||
maybeReadMore_(stream, state);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function maybeReadMore_(stream, state) {
|
|
||||||
var len = state.length;
|
|
||||||
while (!state.reading && !state.flowing && !state.ended &&
|
|
||||||
state.length < state.highWaterMark) {
|
|
||||||
debug('maybeReadMore read 0');
|
|
||||||
stream.read(0);
|
|
||||||
if (len === state.length)
|
|
||||||
// didn't get any data, stop spinning.
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
len = state.length;
|
|
||||||
}
|
|
||||||
state.readingMore = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// abstract method. to be overridden in specific implementation classes.
|
|
||||||
// call cb(er, data) where data is <= n in length.
|
|
||||||
// for virtual (non-string, non-buffer) streams, "length" is somewhat
|
|
||||||
// arbitrary, and perhaps not very meaningful.
|
|
||||||
Readable.prototype._read = function(n) {
|
|
||||||
this.emit('error', new Error('not implemented'));
|
|
||||||
};
|
|
||||||
|
|
||||||
Readable.prototype.pipe = function(dest, pipeOpts) {
|
|
||||||
var src = this;
|
|
||||||
var state = this._readableState;
|
|
||||||
|
|
||||||
switch (state.pipesCount) {
|
|
||||||
case 0:
|
|
||||||
state.pipes = dest;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
state.pipes = [state.pipes, dest];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
state.pipes.push(dest);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
state.pipesCount += 1;
|
|
||||||
debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
|
|
||||||
|
|
||||||
var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
|
|
||||||
dest !== process.stdout &&
|
|
||||||
dest !== process.stderr;
|
|
||||||
|
|
||||||
var endFn = doEnd ? onend : cleanup;
|
|
||||||
if (state.endEmitted)
|
|
||||||
process.nextTick(endFn);
|
|
||||||
else
|
|
||||||
src.once('end', endFn);
|
|
||||||
|
|
||||||
dest.on('unpipe', onunpipe);
|
|
||||||
function onunpipe(readable) {
|
|
||||||
debug('onunpipe');
|
|
||||||
if (readable === src) {
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onend() {
|
|
||||||
debug('onend');
|
|
||||||
dest.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// when the dest drains, it reduces the awaitDrain counter
|
|
||||||
// on the source. This would be more elegant with a .once()
|
|
||||||
// handler in flow(), but adding and removing repeatedly is
|
|
||||||
// too slow.
|
|
||||||
var ondrain = pipeOnDrain(src);
|
|
||||||
dest.on('drain', ondrain);
|
|
||||||
|
|
||||||
function cleanup() {
|
|
||||||
debug('cleanup');
|
|
||||||
// cleanup event handlers once the pipe is broken
|
|
||||||
dest.removeListener('close', onclose);
|
|
||||||
dest.removeListener('finish', onfinish);
|
|
||||||
dest.removeListener('drain', ondrain);
|
|
||||||
dest.removeListener('error', onerror);
|
|
||||||
dest.removeListener('unpipe', onunpipe);
|
|
||||||
src.removeListener('end', onend);
|
|
||||||
src.removeListener('end', cleanup);
|
|
||||||
src.removeListener('data', ondata);
|
|
||||||
|
|
||||||
// if the reader is waiting for a drain event from this
|
|
||||||
// specific writer, then it would cause it to never start
|
|
||||||
// flowing again.
|
|
||||||
// So, if this is awaiting a drain, then we just call it now.
|
|
||||||
// If we don't know, then assume that we are waiting for one.
|
|
||||||
if (state.awaitDrain &&
|
|
||||||
(!dest._writableState || dest._writableState.needDrain))
|
|
||||||
ondrain();
|
|
||||||
}
|
|
||||||
|
|
||||||
src.on('data', ondata);
|
|
||||||
function ondata(chunk) {
|
|
||||||
debug('ondata');
|
|
||||||
var ret = dest.write(chunk);
|
|
||||||
if (false === ret) {
|
|
||||||
debug('false write response, pause',
|
|
||||||
src._readableState.awaitDrain);
|
|
||||||
src._readableState.awaitDrain++;
|
|
||||||
src.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the dest has an error, then stop piping into it.
|
|
||||||
// however, don't suppress the throwing behavior for this.
|
|
||||||
function onerror(er) {
|
|
||||||
debug('onerror', er);
|
|
||||||
unpipe();
|
|
||||||
dest.removeListener('error', onerror);
|
|
||||||
if (EE.listenerCount(dest, 'error') === 0)
|
|
||||||
dest.emit('error', er);
|
|
||||||
}
|
|
||||||
// This is a brutally ugly hack to make sure that our error handler
|
|
||||||
// is attached before any userland ones. NEVER DO THIS.
|
|
||||||
if (!dest._events || !dest._events.error)
|
|
||||||
dest.on('error', onerror);
|
|
||||||
else if (isArray(dest._events.error))
|
|
||||||
dest._events.error.unshift(onerror);
|
|
||||||
else
|
|
||||||
dest._events.error = [onerror, dest._events.error];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Both close and finish should trigger unpipe, but only once.
|
|
||||||
function onclose() {
|
|
||||||
dest.removeListener('finish', onfinish);
|
|
||||||
unpipe();
|
|
||||||
}
|
|
||||||
dest.once('close', onclose);
|
|
||||||
function onfinish() {
|
|
||||||
debug('onfinish');
|
|
||||||
dest.removeListener('close', onclose);
|
|
||||||
unpipe();
|
|
||||||
}
|
|
||||||
dest.once('finish', onfinish);
|
|
||||||
|
|
||||||
function unpipe() {
|
|
||||||
debug('unpipe');
|
|
||||||
src.unpipe(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tell the dest that it's being piped to
|
|
||||||
dest.emit('pipe', src);
|
|
||||||
|
|
||||||
// start the flow if it hasn't been started already.
|
|
||||||
if (!state.flowing) {
|
|
||||||
debug('pipe resume');
|
|
||||||
src.resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
};
|
|
||||||
|
|
||||||
function pipeOnDrain(src) {
|
|
||||||
return function() {
|
|
||||||
var state = src._readableState;
|
|
||||||
debug('pipeOnDrain', state.awaitDrain);
|
|
||||||
if (state.awaitDrain)
|
|
||||||
state.awaitDrain--;
|
|
||||||
if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) {
|
|
||||||
state.flowing = true;
|
|
||||||
flow(src);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Readable.prototype.unpipe = function(dest) {
|
|
||||||
var state = this._readableState;
|
|
||||||
|
|
||||||
// if we're not piping anywhere, then do nothing.
|
|
||||||
if (state.pipesCount === 0)
|
|
||||||
return this;
|
|
||||||
|
|
||||||
// just one destination. most common case.
|
|
||||||
if (state.pipesCount === 1) {
|
|
||||||
// passed in one, but it's not the right one.
|
|
||||||
if (dest && dest !== state.pipes)
|
|
||||||
return this;
|
|
||||||
|
|
||||||
if (!dest)
|
|
||||||
dest = state.pipes;
|
|
||||||
|
|
||||||
// got a match.
|
|
||||||
state.pipes = null;
|
|
||||||
state.pipesCount = 0;
|
|
||||||
state.flowing = false;
|
|
||||||
if (dest)
|
|
||||||
dest.emit('unpipe', this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// slow case. multiple pipe destinations.
|
|
||||||
|
|
||||||
if (!dest) {
|
|
||||||
// remove all.
|
|
||||||
var dests = state.pipes;
|
|
||||||
var len = state.pipesCount;
|
|
||||||
state.pipes = null;
|
|
||||||
state.pipesCount = 0;
|
|
||||||
state.flowing = false;
|
|
||||||
|
|
||||||
for (var i = 0; i < len; i++)
|
|
||||||
dests[i].emit('unpipe', this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to find the right one.
|
|
||||||
var i = indexOf(state.pipes, dest);
|
|
||||||
if (i === -1)
|
|
||||||
return this;
|
|
||||||
|
|
||||||
state.pipes.splice(i, 1);
|
|
||||||
state.pipesCount -= 1;
|
|
||||||
if (state.pipesCount === 1)
|
|
||||||
state.pipes = state.pipes[0];
|
|
||||||
|
|
||||||
dest.emit('unpipe', this);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
// set up data events if they are asked for
|
|
||||||
// Ensure readable listeners eventually get something
|
|
||||||
Readable.prototype.on = function(ev, fn) {
|
|
||||||
var res = Stream.prototype.on.call(this, ev, fn);
|
|
||||||
|
|
||||||
// If listening to data, and it has not explicitly been paused,
|
|
||||||
// then call resume to start the flow of data on the next tick.
|
|
||||||
if (ev === 'data' && false !== this._readableState.flowing) {
|
|
||||||
this.resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev === 'readable' && this.readable) {
|
|
||||||
var state = this._readableState;
|
|
||||||
if (!state.readableListening) {
|
|
||||||
state.readableListening = true;
|
|
||||||
state.emittedReadable = false;
|
|
||||||
state.needReadable = true;
|
|
||||||
if (!state.reading) {
|
|
||||||
var self = this;
|
|
||||||
process.nextTick(function() {
|
|
||||||
debug('readable nexttick read 0');
|
|
||||||
self.read(0);
|
|
||||||
});
|
|
||||||
} else if (state.length) {
|
|
||||||
emitReadable(this, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
Readable.prototype.addListener = Readable.prototype.on;
|
|
||||||
|
|
||||||
// pause() and resume() are remnants of the legacy readable stream API
|
|
||||||
// If the user uses them, then switch into old mode.
|
|
||||||
Readable.prototype.resume = function() {
|
|
||||||
var state = this._readableState;
|
|
||||||
if (!state.flowing) {
|
|
||||||
debug('resume');
|
|
||||||
state.flowing = true;
|
|
||||||
if (!state.reading) {
|
|
||||||
debug('resume read 0');
|
|
||||||
this.read(0);
|
|
||||||
}
|
|
||||||
resume(this, state);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
function resume(stream, state) {
|
|
||||||
if (!state.resumeScheduled) {
|
|
||||||
state.resumeScheduled = true;
|
|
||||||
process.nextTick(function() {
|
|
||||||
resume_(stream, state);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function resume_(stream, state) {
|
|
||||||
state.resumeScheduled = false;
|
|
||||||
stream.emit('resume');
|
|
||||||
flow(stream);
|
|
||||||
if (state.flowing && !state.reading)
|
|
||||||
stream.read(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Readable.prototype.pause = function() {
|
|
||||||
debug('call pause flowing=%j', this._readableState.flowing);
|
|
||||||
if (false !== this._readableState.flowing) {
|
|
||||||
debug('pause');
|
|
||||||
this._readableState.flowing = false;
|
|
||||||
this.emit('pause');
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
function flow(stream) {
|
|
||||||
var state = stream._readableState;
|
|
||||||
debug('flow', state.flowing);
|
|
||||||
if (state.flowing) {
|
|
||||||
do {
|
|
||||||
var chunk = stream.read();
|
|
||||||
} while (null !== chunk && state.flowing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrap an old-style stream as the async data source.
|
|
||||||
// This is *not* part of the readable stream interface.
|
|
||||||
// It is an ugly unfortunate mess of history.
|
|
||||||
Readable.prototype.wrap = function(stream) {
|
|
||||||
var state = this._readableState;
|
|
||||||
var paused = false;
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
stream.on('end', function() {
|
|
||||||
debug('wrapped end');
|
|
||||||
if (state.decoder && !state.ended) {
|
|
||||||
var chunk = state.decoder.end();
|
|
||||||
if (chunk && chunk.length)
|
|
||||||
self.push(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.push(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
stream.on('data', function(chunk) {
|
|
||||||
debug('wrapped data');
|
|
||||||
if (state.decoder)
|
|
||||||
chunk = state.decoder.write(chunk);
|
|
||||||
if (!chunk || !state.objectMode && !chunk.length)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var ret = self.push(chunk);
|
|
||||||
if (!ret) {
|
|
||||||
paused = true;
|
|
||||||
stream.pause();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// proxy all the other methods.
|
|
||||||
// important when wrapping filters and duplexes.
|
|
||||||
for (var i in stream) {
|
|
||||||
if (util.isFunction(stream[i]) && util.isUndefined(this[i])) {
|
|
||||||
this[i] = function(method) { return function() {
|
|
||||||
return stream[method].apply(stream, arguments);
|
|
||||||
}}(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// proxy certain important events.
|
|
||||||
var events = ['error', 'close', 'destroy', 'pause', 'resume'];
|
|
||||||
forEach(events, function(ev) {
|
|
||||||
stream.on(ev, self.emit.bind(self, ev));
|
|
||||||
});
|
|
||||||
|
|
||||||
// when we try to consume some more bytes, simply unpause the
|
|
||||||
// underlying stream.
|
|
||||||
self._read = function(n) {
|
|
||||||
debug('wrapped _read', n);
|
|
||||||
if (paused) {
|
|
||||||
paused = false;
|
|
||||||
stream.resume();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return self;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// exposed for testing purposes only.
|
|
||||||
Readable._fromList = fromList;
|
|
||||||
|
|
||||||
// Pluck off n bytes from an array of buffers.
|
|
||||||
// Length is the combined lengths of all the buffers in the list.
|
|
||||||
function fromList(n, state) {
|
|
||||||
var list = state.buffer;
|
|
||||||
var length = state.length;
|
|
||||||
var stringMode = !!state.decoder;
|
|
||||||
var objectMode = !!state.objectMode;
|
|
||||||
var ret;
|
|
||||||
|
|
||||||
// nothing in the list, definitely empty.
|
|
||||||
if (list.length === 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (length === 0)
|
|
||||||
ret = null;
|
|
||||||
else if (objectMode)
|
|
||||||
ret = list.shift();
|
|
||||||
else if (!n || n >= length) {
|
|
||||||
// read it all, truncate the array.
|
|
||||||
if (stringMode)
|
|
||||||
ret = list.join('');
|
|
||||||
else
|
|
||||||
ret = Buffer.concat(list, length);
|
|
||||||
list.length = 0;
|
|
||||||
} else {
|
|
||||||
// read just some of it.
|
|
||||||
if (n < list[0].length) {
|
|
||||||
// just take a part of the first list item.
|
|
||||||
// slice is the same for buffers and strings.
|
|
||||||
var buf = list[0];
|
|
||||||
ret = buf.slice(0, n);
|
|
||||||
list[0] = buf.slice(n);
|
|
||||||
} else if (n === list[0].length) {
|
|
||||||
// first list is a perfect match
|
|
||||||
ret = list.shift();
|
|
||||||
} else {
|
|
||||||
// complex case.
|
|
||||||
// we have enough to cover it, but it spans past the first buffer.
|
|
||||||
if (stringMode)
|
|
||||||
ret = '';
|
|
||||||
else
|
|
||||||
ret = new Buffer(n);
|
|
||||||
|
|
||||||
var c = 0;
|
|
||||||
for (var i = 0, l = list.length; i < l && c < n; i++) {
|
|
||||||
var buf = list[0];
|
|
||||||
var cpy = Math.min(n - c, buf.length);
|
|
||||||
|
|
||||||
if (stringMode)
|
|
||||||
ret += buf.slice(0, cpy);
|
|
||||||
else
|
|
||||||
buf.copy(ret, c, 0, cpy);
|
|
||||||
|
|
||||||
if (cpy < buf.length)
|
|
||||||
list[0] = buf.slice(cpy);
|
|
||||||
else
|
|
||||||
list.shift();
|
|
||||||
|
|
||||||
c += cpy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function endReadable(stream) {
|
|
||||||
var state = stream._readableState;
|
|
||||||
|
|
||||||
// If we get here before consuming all the bytes, then that is a
|
|
||||||
// bug in node. Should never happen.
|
|
||||||
if (state.length > 0)
|
|
||||||
throw new Error('endReadable called on non-empty stream');
|
|
||||||
|
|
||||||
if (!state.endEmitted) {
|
|
||||||
state.ended = true;
|
|
||||||
process.nextTick(function() {
|
|
||||||
// Check that we didn't get one last unshift.
|
|
||||||
if (!state.endEmitted && state.length === 0) {
|
|
||||||
state.endEmitted = true;
|
|
||||||
stream.readable = false;
|
|
||||||
stream.emit('end');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function forEach (xs, f) {
|
|
||||||
for (var i = 0, l = xs.length; i < l; i++) {
|
|
||||||
f(xs[i], i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function indexOf (xs, x) {
|
|
||||||
for (var i = 0, l = xs.length; i < l; i++) {
|
|
||||||
if (xs[i] === x) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
209
node_modules/@icetee/ftp/node_modules/readable-stream/lib/_stream_transform.js
generated
vendored
209
node_modules/@icetee/ftp/node_modules/readable-stream/lib/_stream_transform.js
generated
vendored
|
@ -1,209 +0,0 @@
|
||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
|
|
||||||
// a transform stream is a readable/writable stream where you do
|
|
||||||
// something with the data. Sometimes it's called a "filter",
|
|
||||||
// but that's not a great name for it, since that implies a thing where
|
|
||||||
// some bits pass through, and others are simply ignored. (That would
|
|
||||||
// be a valid example of a transform, of course.)
|
|
||||||
//
|
|
||||||
// While the output is causally related to the input, it's not a
|
|
||||||
// necessarily symmetric or synchronous transformation. For example,
|
|
||||||
// a zlib stream might take multiple plain-text writes(), and then
|
|
||||||
// emit a single compressed chunk some time in the future.
|
|
||||||
//
|
|
||||||
// Here's how this works:
|
|
||||||
//
|
|
||||||
// The Transform stream has all the aspects of the readable and writable
|
|
||||||
// stream classes. When you write(chunk), that calls _write(chunk,cb)
|
|
||||||
// internally, and returns false if there's a lot of pending writes
|
|
||||||
// buffered up. When you call read(), that calls _read(n) until
|
|
||||||
// there's enough pending readable data buffered up.
|
|
||||||
//
|
|
||||||
// In a transform stream, the written data is placed in a buffer. When
|
|
||||||
// _read(n) is called, it transforms the queued up data, calling the
|
|
||||||
// buffered _write cb's as it consumes chunks. If consuming a single
|
|
||||||
// written chunk would result in multiple output chunks, then the first
|
|
||||||
// outputted bit calls the readcb, and subsequent chunks just go into
|
|
||||||
// the read buffer, and will cause it to emit 'readable' if necessary.
|
|
||||||
//
|
|
||||||
// This way, back-pressure is actually determined by the reading side,
|
|
||||||
// since _read has to be called to start processing a new chunk. However,
|
|
||||||
// a pathological inflate type of transform can cause excessive buffering
|
|
||||||
// here. For example, imagine a stream where every byte of input is
|
|
||||||
// interpreted as an integer from 0-255, and then results in that many
|
|
||||||
// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
|
|
||||||
// 1kb of data being output. In this case, you could write a very small
|
|
||||||
// amount of input, and end up with a very large amount of output. In
|
|
||||||
// such a pathological inflating mechanism, there'd be no way to tell
|
|
||||||
// the system to stop doing the transform. A single 4MB write could
|
|
||||||
// cause the system to run out of memory.
|
|
||||||
//
|
|
||||||
// However, even in such a pathological case, only a single written chunk
|
|
||||||
// would be consumed, and then the rest would wait (un-transformed) until
|
|
||||||
// the results of the previous transformed chunk were consumed.
|
|
||||||
|
|
||||||
module.exports = Transform;
|
|
||||||
|
|
||||||
var Duplex = require('./_stream_duplex');
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var util = require('core-util-is');
|
|
||||||
util.inherits = require('inherits');
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
util.inherits(Transform, Duplex);
|
|
||||||
|
|
||||||
|
|
||||||
function TransformState(options, stream) {
|
|
||||||
this.afterTransform = function(er, data) {
|
|
||||||
return afterTransform(stream, er, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.needTransform = false;
|
|
||||||
this.transforming = false;
|
|
||||||
this.writecb = null;
|
|
||||||
this.writechunk = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function afterTransform(stream, er, data) {
|
|
||||||
var ts = stream._transformState;
|
|
||||||
ts.transforming = false;
|
|
||||||
|
|
||||||
var cb = ts.writecb;
|
|
||||||
|
|
||||||
if (!cb)
|
|
||||||
return stream.emit('error', new Error('no writecb in Transform class'));
|
|
||||||
|
|
||||||
ts.writechunk = null;
|
|
||||||
ts.writecb = null;
|
|
||||||
|
|
||||||
if (!util.isNullOrUndefined(data))
|
|
||||||
stream.push(data);
|
|
||||||
|
|
||||||
if (cb)
|
|
||||||
cb(er);
|
|
||||||
|
|
||||||
var rs = stream._readableState;
|
|
||||||
rs.reading = false;
|
|
||||||
if (rs.needReadable || rs.length < rs.highWaterMark) {
|
|
||||||
stream._read(rs.highWaterMark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function Transform(options) {
|
|
||||||
if (!(this instanceof Transform))
|
|
||||||
return new Transform(options);
|
|
||||||
|
|
||||||
Duplex.call(this, options);
|
|
||||||
|
|
||||||
this._transformState = new TransformState(options, this);
|
|
||||||
|
|
||||||
// when the writable side finishes, then flush out anything remaining.
|
|
||||||
var stream = this;
|
|
||||||
|
|
||||||
// start out asking for a readable event once data is transformed.
|
|
||||||
this._readableState.needReadable = true;
|
|
||||||
|
|
||||||
// we have implemented the _read method, and done the other things
|
|
||||||
// that Readable wants before the first _read call, so unset the
|
|
||||||
// sync guard flag.
|
|
||||||
this._readableState.sync = false;
|
|
||||||
|
|
||||||
this.once('prefinish', function() {
|
|
||||||
if (util.isFunction(this._flush))
|
|
||||||
this._flush(function(er) {
|
|
||||||
done(stream, er);
|
|
||||||
});
|
|
||||||
else
|
|
||||||
done(stream);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform.prototype.push = function(chunk, encoding) {
|
|
||||||
this._transformState.needTransform = false;
|
|
||||||
return Duplex.prototype.push.call(this, chunk, encoding);
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is the part where you do stuff!
|
|
||||||
// override this function in implementation classes.
|
|
||||||
// 'chunk' is an input chunk.
|
|
||||||
//
|
|
||||||
// Call `push(newChunk)` to pass along transformed output
|
|
||||||
// to the readable side. You may call 'push' zero or more times.
|
|
||||||
//
|
|
||||||
// Call `cb(err)` when you are done with this chunk. If you pass
|
|
||||||
// an error, then that'll put the hurt on the whole operation. If you
|
|
||||||
// never call cb(), then you'll never get another chunk.
|
|
||||||
Transform.prototype._transform = function(chunk, encoding, cb) {
|
|
||||||
throw new Error('not implemented');
|
|
||||||
};
|
|
||||||
|
|
||||||
Transform.prototype._write = function(chunk, encoding, cb) {
|
|
||||||
var ts = this._transformState;
|
|
||||||
ts.writecb = cb;
|
|
||||||
ts.writechunk = chunk;
|
|
||||||
ts.writeencoding = encoding;
|
|
||||||
if (!ts.transforming) {
|
|
||||||
var rs = this._readableState;
|
|
||||||
if (ts.needTransform ||
|
|
||||||
rs.needReadable ||
|
|
||||||
rs.length < rs.highWaterMark)
|
|
||||||
this._read(rs.highWaterMark);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Doesn't matter what the args are here.
|
|
||||||
// _transform does all the work.
|
|
||||||
// That we got here means that the readable side wants more data.
|
|
||||||
Transform.prototype._read = function(n) {
|
|
||||||
var ts = this._transformState;
|
|
||||||
|
|
||||||
if (!util.isNull(ts.writechunk) && ts.writecb && !ts.transforming) {
|
|
||||||
ts.transforming = true;
|
|
||||||
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
|
|
||||||
} else {
|
|
||||||
// mark that we need a transform, so that any data that comes in
|
|
||||||
// will get processed, now that we've asked for it.
|
|
||||||
ts.needTransform = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function done(stream, er) {
|
|
||||||
if (er)
|
|
||||||
return stream.emit('error', er);
|
|
||||||
|
|
||||||
// if there's nothing in the write buffer, then that means
|
|
||||||
// that nothing more will ever be provided
|
|
||||||
var ws = stream._writableState;
|
|
||||||
var ts = stream._transformState;
|
|
||||||
|
|
||||||
if (ws.length)
|
|
||||||
throw new Error('calling transform done when ws.length != 0');
|
|
||||||
|
|
||||||
if (ts.transforming)
|
|
||||||
throw new Error('calling transform done when still transforming');
|
|
||||||
|
|
||||||
return stream.push(null);
|
|
||||||
}
|
|
477
node_modules/@icetee/ftp/node_modules/readable-stream/lib/_stream_writable.js
generated
vendored
477
node_modules/@icetee/ftp/node_modules/readable-stream/lib/_stream_writable.js
generated
vendored
|
@ -1,477 +0,0 @@
|
||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// A bit simpler than readable streams.
|
|
||||||
// Implement an async ._write(chunk, cb), and it'll handle all
|
|
||||||
// the drain event emission and buffering.
|
|
||||||
|
|
||||||
module.exports = Writable;
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var Buffer = require('buffer').Buffer;
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
Writable.WritableState = WritableState;
|
|
||||||
|
|
||||||
|
|
||||||
/*<replacement>*/
|
|
||||||
var util = require('core-util-is');
|
|
||||||
util.inherits = require('inherits');
|
|
||||||
/*</replacement>*/
|
|
||||||
|
|
||||||
var Stream = require('stream');
|
|
||||||
|
|
||||||
util.inherits(Writable, Stream);
|
|
||||||
|
|
||||||
function WriteReq(chunk, encoding, cb) {
|
|
||||||
this.chunk = chunk;
|
|
||||||
this.encoding = encoding;
|
|
||||||
this.callback = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
function WritableState(options, stream) {
|
|
||||||
var Duplex = require('./_stream_duplex');
|
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
// the point at which write() starts returning false
|
|
||||||
// Note: 0 is a valid value, means that we always return false if
|
|
||||||
// the entire buffer is not flushed immediately on write()
|
|
||||||
var hwm = options.highWaterMark;
|
|
||||||
var defaultHwm = options.objectMode ? 16 : 16 * 1024;
|
|
||||||
this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
|
|
||||||
|
|
||||||
// object stream flag to indicate whether or not this stream
|
|
||||||
// contains buffers or objects.
|
|
||||||
this.objectMode = !!options.objectMode;
|
|
||||||
|
|
||||||
if (stream instanceof Duplex)
|
|
||||||
this.objectMode = this.objectMode || !!options.writableObjectMode;
|
|
||||||
|
|
||||||
// cast to ints.
|
|
||||||
this.highWaterMark = ~~this.highWaterMark;
|
|
||||||
|
|
||||||
this.needDrain = false;
|
|
||||||
// at the start of calling end()
|
|
||||||
this.ending = false;
|
|
||||||
// when end() has been called, and returned
|
|
||||||
this.ended = false;
|
|
||||||
// when 'finish' is emitted
|
|
||||||
this.finished = false;
|
|
||||||
|
|
||||||
// should we decode strings into buffers before passing to _write?
|
|
||||||
// this is here so that some node-core streams can optimize string
|
|
||||||
// handling at a lower level.
|
|
||||||
var noDecode = options.decodeStrings === false;
|
|
||||||
this.decodeStrings = !noDecode;
|
|
||||||
|
|
||||||
// Crypto is kind of old and crusty. Historically, its default string
|
|
||||||
// encoding is 'binary' so we have to make this configurable.
|
|
||||||
// Everything else in the universe uses 'utf8', though.
|
|
||||||
this.defaultEncoding = options.defaultEncoding || 'utf8';
|
|
||||||
|
|
||||||
// not an actual buffer we keep track of, but a measurement
|
|
||||||
// of how much we're waiting to get pushed to some underlying
|
|
||||||
// socket or file.
|
|
||||||
this.length = 0;
|
|
||||||
|
|
||||||
// a flag to see when we're in the middle of a write.
|
|
||||||
this.writing = false;
|
|
||||||
|
|
||||||
// when true all writes will be buffered until .uncork() call
|
|
||||||
this.corked = 0;
|
|
||||||
|
|
||||||
// a flag to be able to tell if the onwrite cb is called immediately,
|
|
||||||
// or on a later tick. We set this to true at first, because any
|
|
||||||
// actions that shouldn't happen until "later" should generally also
|
|
||||||
// not happen before the first write call.
|
|
||||||
this.sync = true;
|
|
||||||
|
|
||||||
// a flag to know if we're processing previously buffered items, which
|
|
||||||
// may call the _write() callback in the same tick, so that we don't
|
|
||||||
// end up in an overlapped onwrite situation.
|
|
||||||
this.bufferProcessing = false;
|
|
||||||
|
|
||||||
// the callback that's passed to _write(chunk,cb)
|
|
||||||
this.onwrite = function(er) {
|
|
||||||
onwrite(stream, er);
|
|
||||||
};
|
|
||||||
|
|
||||||
// the callback that the user supplies to write(chunk,encoding,cb)
|
|
||||||
this.writecb = null;
|
|
||||||
|
|
||||||
// the amount that is being written when _write is called.
|
|
||||||
this.writelen = 0;
|
|
||||||
|
|
||||||
this.buffer = [];
|
|
||||||
|
|
||||||
// number of pending user-supplied write callbacks
|
|
||||||
// this must be 0 before 'finish' can be emitted
|
|
||||||
this.pendingcb = 0;
|
|
||||||
|
|
||||||
// emit prefinish if the only thing we're waiting for is _write cbs
|
|
||||||
// This is relevant for synchronous Transform streams
|
|
||||||
this.prefinished = false;
|
|
||||||
|
|
||||||
// True if the error was already emitted and should not be thrown again
|
|
||||||
this.errorEmitted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Writable(options) {
|
|
||||||
var Duplex = require('./_stream_duplex');
|
|
||||||
|
|
||||||
// Writable ctor is applied to Duplexes, though they're not
|
|
||||||
// instanceof Writable, they're instanceof Readable.
|
|
||||||
if (!(this instanceof Writable) && !(this instanceof Duplex))
|
|
||||||
return new Writable(options);
|
|
||||||
|
|
||||||
this._writableState = new WritableState(options, this);
|
|
||||||
|
|
||||||
// legacy.
|
|
||||||
this.writable = true;
|
|
||||||
|
|
||||||
Stream.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise people can pipe Writable streams, which is just wrong.
|
|
||||||
Writable.prototype.pipe = function() {
|
|
||||||
this.emit('error', new Error('Cannot pipe. Not readable.'));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function writeAfterEnd(stream, state, cb) {
|
|
||||||
var er = new Error('write after end');
|
|
||||||
// TODO: defer error events consistently everywhere, not just the cb
|
|
||||||
stream.emit('error', er);
|
|
||||||
process.nextTick(function() {
|
|
||||||
cb(er);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get something that is not a buffer, string, null, or undefined,
|
|
||||||
// and we're not in objectMode, then that's an error.
|
|
||||||
// Otherwise stream chunks are all considered to be of length=1, and the
|
|
||||||
// watermarks determine how many objects to keep in the buffer, rather than
|
|
||||||
// how many bytes or characters.
|
|
||||||
function validChunk(stream, state, chunk, cb) {
|
|
||||||
var valid = true;
|
|
||||||
if (!util.isBuffer(chunk) &&
|
|
||||||
!util.isString(chunk) &&
|
|
||||||
!util.isNullOrUndefined(chunk) &&
|
|
||||||
!state.objectMode) {
|
|
||||||
var er = new TypeError('Invalid non-string/buffer chunk');
|
|
||||||
stream.emit('error', er);
|
|
||||||
process.nextTick(function() {
|
|
||||||
cb(er);
|
|
||||||
});
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
Writable.prototype.write = function(chunk, encoding, cb) {
|
|
||||||
var state = this._writableState;
|
|
||||||
var ret = false;
|
|
||||||
|
|
||||||
if (util.isFunction(encoding)) {
|
|
||||||
cb = encoding;
|
|
||||||
encoding = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (util.isBuffer(chunk))
|
|
||||||
encoding = 'buffer';
|
|
||||||
else if (!encoding)
|
|
||||||
encoding = state.defaultEncoding;
|
|
||||||
|
|
||||||
if (!util.isFunction(cb))
|
|
||||||
cb = function() {};
|
|
||||||
|
|
||||||
if (state.ended)
|
|
||||||
writeAfterEnd(this, state, cb);
|
|
||||||
else if (validChunk(this, state, chunk, cb)) {
|
|
||||||
state.pendingcb++;
|
|
||||||
ret = writeOrBuffer(this, state, chunk, encoding, cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
Writable.prototype.cork = function() {
|
|
||||||
var state = this._writableState;
|
|
||||||
|
|
||||||
state.corked++;
|
|
||||||
};
|
|
||||||
|
|
||||||
Writable.prototype.uncork = function() {
|
|
||||||
var state = this._writableState;
|
|
||||||
|
|
||||||
if (state.corked) {
|
|
||||||
state.corked--;
|
|
||||||
|
|
||||||
if (!state.writing &&
|
|
||||||
!state.corked &&
|
|
||||||
!state.finished &&
|
|
||||||
!state.bufferProcessing &&
|
|
||||||
state.buffer.length)
|
|
||||||
clearBuffer(this, state);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function decodeChunk(state, chunk, encoding) {
|
|
||||||
if (!state.objectMode &&
|
|
||||||
state.decodeStrings !== false &&
|
|
||||||
util.isString(chunk)) {
|
|
||||||
chunk = new Buffer(chunk, encoding);
|
|
||||||
}
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we're already writing something, then just put this
|
|
||||||
// in the queue, and wait our turn. Otherwise, call _write
|
|
||||||
// If we return false, then we need a drain event, so set that flag.
|
|
||||||
function writeOrBuffer(stream, state, chunk, encoding, cb) {
|
|
||||||
chunk = decodeChunk(state, chunk, encoding);
|
|
||||||
if (util.isBuffer(chunk))
|
|
||||||
encoding = 'buffer';
|
|
||||||
var len = state.objectMode ? 1 : chunk.length;
|
|
||||||
|
|
||||||
state.length += len;
|
|
||||||
|
|
||||||
var ret = state.length < state.highWaterMark;
|
|
||||||
// we must ensure that previous needDrain will not be reset to false.
|
|
||||||
if (!ret)
|
|
||||||
state.needDrain = true;
|
|
||||||
|
|
||||||
if (state.writing || state.corked)
|
|
||||||
state.buffer.push(new WriteReq(chunk, encoding, cb));
|
|
||||||
else
|
|
||||||
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
|
|
||||||
state.writelen = len;
|
|
||||||
state.writecb = cb;
|
|
||||||
state.writing = true;
|
|
||||||
state.sync = true;
|
|
||||||
if (writev)
|
|
||||||
stream._writev(chunk, state.onwrite);
|
|
||||||
else
|
|
||||||
stream._write(chunk, encoding, state.onwrite);
|
|
||||||
state.sync = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onwriteError(stream, state, sync, er, cb) {
|
|
||||||
if (sync)
|
|
||||||
process.nextTick(function() {
|
|
||||||
state.pendingcb--;
|
|
||||||
cb(er);
|
|
||||||
});
|
|
||||||
else {
|
|
||||||
state.pendingcb--;
|
|
||||||
cb(er);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream._writableState.errorEmitted = true;
|
|
||||||
stream.emit('error', er);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onwriteStateUpdate(state) {
|
|
||||||
state.writing = false;
|
|
||||||
state.writecb = null;
|
|
||||||
state.length -= state.writelen;
|
|
||||||
state.writelen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onwrite(stream, er) {
|
|
||||||
var state = stream._writableState;
|
|
||||||
var sync = state.sync;
|
|
||||||
var cb = state.writecb;
|
|
||||||
|
|
||||||
onwriteStateUpdate(state);
|
|
||||||
|
|
||||||
if (er)
|
|
||||||
onwriteError(stream, state, sync, er, cb);
|
|
||||||
else {
|
|
||||||
// Check if we're actually ready to finish, but don't emit yet
|
|
||||||
var finished = needFinish(stream, state);
|
|
||||||
|
|
||||||
if (!finished &&
|
|
||||||
!state.corked &&
|
|
||||||
!state.bufferProcessing &&
|
|
||||||
state.buffer.length) {
|
|
||||||
clearBuffer(stream, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sync) {
|
|
||||||
process.nextTick(function() {
|
|
||||||
afterWrite(stream, state, finished, cb);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
afterWrite(stream, state, finished, cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function afterWrite(stream, state, finished, cb) {
|
|
||||||
if (!finished)
|
|
||||||
onwriteDrain(stream, state);
|
|
||||||
state.pendingcb--;
|
|
||||||
cb();
|
|
||||||
finishMaybe(stream, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must force callback to be called on nextTick, so that we don't
|
|
||||||
// emit 'drain' before the write() consumer gets the 'false' return
|
|
||||||
// value, and has a chance to attach a 'drain' listener.
|
|
||||||
function onwriteDrain(stream, state) {
|
|
||||||
if (state.length === 0 && state.needDrain) {
|
|
||||||
state.needDrain = false;
|
|
||||||
stream.emit('drain');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// if there's something in the buffer waiting, then process it
|
|
||||||
function clearBuffer(stream, state) {
|
|
||||||
state.bufferProcessing = true;
|
|
||||||
|
|
||||||
if (stream._writev && state.buffer.length > 1) {
|
|
||||||
// Fast case, write everything using _writev()
|
|
||||||
var cbs = [];
|
|
||||||
for (var c = 0; c < state.buffer.length; c++)
|
|
||||||
cbs.push(state.buffer[c].callback);
|
|
||||||
|
|
||||||
// count the one we are adding, as well.
|
|
||||||
// TODO(isaacs) clean this up
|
|
||||||
state.pendingcb++;
|
|
||||||
doWrite(stream, state, true, state.length, state.buffer, '', function(err) {
|
|
||||||
for (var i = 0; i < cbs.length; i++) {
|
|
||||||
state.pendingcb--;
|
|
||||||
cbs[i](err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear buffer
|
|
||||||
state.buffer = [];
|
|
||||||
} else {
|
|
||||||
// Slow case, write chunks one-by-one
|
|
||||||
for (var c = 0; c < state.buffer.length; c++) {
|
|
||||||
var entry = state.buffer[c];
|
|
||||||
var chunk = entry.chunk;
|
|
||||||
var encoding = entry.encoding;
|
|
||||||
var cb = entry.callback;
|
|
||||||
var len = state.objectMode ? 1 : chunk.length;
|
|
||||||
|
|
||||||
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
||||||
|
|
||||||
// if we didn't call the onwrite immediately, then
|
|
||||||
// it means that we need to wait until it does.
|
|
||||||
// also, that means that the chunk and cb are currently
|
|
||||||
// being processed, so move the buffer counter past them.
|
|
||||||
if (state.writing) {
|
|
||||||
c++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c < state.buffer.length)
|
|
||||||
state.buffer = state.buffer.slice(c);
|
|
||||||
else
|
|
||||||
state.buffer.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.bufferProcessing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Writable.prototype._write = function(chunk, encoding, cb) {
|
|
||||||
cb(new Error('not implemented'));
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Writable.prototype._writev = null;
|
|
||||||
|
|
||||||
Writable.prototype.end = function(chunk, encoding, cb) {
|
|
||||||
var state = this._writableState;
|
|
||||||
|
|
||||||
if (util.isFunction(chunk)) {
|
|
||||||
cb = chunk;
|
|
||||||
chunk = null;
|
|
||||||
encoding = null;
|
|
||||||
} else if (util.isFunction(encoding)) {
|
|
||||||
cb = encoding;
|
|
||||||
encoding = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!util.isNullOrUndefined(chunk))
|
|
||||||
this.write(chunk, encoding);
|
|
||||||
|
|
||||||
// .end() fully uncorks
|
|
||||||
if (state.corked) {
|
|
||||||
state.corked = 1;
|
|
||||||
this.uncork();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore unnecessary end() calls.
|
|
||||||
if (!state.ending && !state.finished)
|
|
||||||
endWritable(this, state, cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function needFinish(stream, state) {
|
|
||||||
return (state.ending &&
|
|
||||||
state.length === 0 &&
|
|
||||||
!state.finished &&
|
|
||||||
!state.writing);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prefinish(stream, state) {
|
|
||||||
if (!state.prefinished) {
|
|
||||||
state.prefinished = true;
|
|
||||||
stream.emit('prefinish');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function finishMaybe(stream, state) {
|
|
||||||
var need = needFinish(stream, state);
|
|
||||||
if (need) {
|
|
||||||
if (state.pendingcb === 0) {
|
|
||||||
prefinish(stream, state);
|
|
||||||
state.finished = true;
|
|
||||||
stream.emit('finish');
|
|
||||||
} else
|
|
||||||
prefinish(stream, state);
|
|
||||||
}
|
|
||||||
return need;
|
|
||||||
}
|
|
||||||
|
|
||||||
function endWritable(stream, state, cb) {
|
|
||||||
state.ending = true;
|
|
||||||
finishMaybe(stream, state);
|
|
||||||
if (cb) {
|
|
||||||
if (state.finished)
|
|
||||||
process.nextTick(cb);
|
|
||||||
else
|
|
||||||
stream.once('finish', cb);
|
|
||||||
}
|
|
||||||
state.ended = true;
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"name": "readable-stream",
|
|
||||||
"version": "1.1.14",
|
|
||||||
"description": "Streams3, a user-land copy of the stream library from Node.js v0.11.x",
|
|
||||||
"main": "readable.js",
|
|
||||||
"dependencies": {
|
|
||||||
"core-util-is": "~1.0.0",
|
|
||||||
"isarray": "0.0.1",
|
|
||||||
"string_decoder": "~0.10.x",
|
|
||||||
"inherits": "~2.0.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "~0.2.6"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test/simple/*.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/isaacs/readable-stream"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"readable",
|
|
||||||
"stream",
|
|
||||||
"pipe"
|
|
||||||
],
|
|
||||||
"browser": {
|
|
||||||
"util": false
|
|
||||||
},
|
|
||||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
|
||||||
"license": "MIT"
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
module.exports = require("./lib/_stream_passthrough.js")
|
|
|
@ -1,10 +0,0 @@
|
||||||
exports = module.exports = require('./lib/_stream_readable.js');
|
|
||||||
exports.Stream = require('stream');
|
|
||||||
exports.Readable = exports;
|
|
||||||
exports.Writable = require('./lib/_stream_writable.js');
|
|
||||||
exports.Duplex = require('./lib/_stream_duplex.js');
|
|
||||||
exports.Transform = require('./lib/_stream_transform.js');
|
|
||||||
exports.PassThrough = require('./lib/_stream_passthrough.js');
|
|
||||||
if (!process.browser && process.env.READABLE_STREAM === 'disable') {
|
|
||||||
module.exports = require('stream');
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
module.exports = require("./lib/_stream_transform.js")
|
|
|
@ -1 +0,0 @@
|
||||||
module.exports = require("./lib/_stream_writable.js")
|
|
|
@ -1,2 +0,0 @@
|
||||||
build
|
|
||||||
test
|
|
|
@ -1,20 +0,0 @@
|
||||||
Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,7 +0,0 @@
|
||||||
**string_decoder.js** (`require('string_decoder')`) from Node.js core
|
|
||||||
|
|
||||||
Copyright Joyent, Inc. and other Node contributors. See LICENCE file for details.
|
|
||||||
|
|
||||||
Version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. **Prefer the stable version over the unstable.**
|
|
||||||
|
|
||||||
The *build/* directory contains a build script that will scrape the source from the [joyent/node](https://github.com/joyent/node) repo given a specific Node version.
|
|
|
@ -1,221 +0,0 @@
|
||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// 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 Buffer = require('buffer').Buffer;
|
|
||||||
|
|
||||||
var isBufferEncoding = Buffer.isEncoding
|
|
||||||
|| function(encoding) {
|
|
||||||
switch (encoding && encoding.toLowerCase()) {
|
|
||||||
case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function assertEncoding(encoding) {
|
|
||||||
if (encoding && !isBufferEncoding(encoding)) {
|
|
||||||
throw new Error('Unknown encoding: ' + encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringDecoder provides an interface for efficiently splitting a series of
|
|
||||||
// buffers into a series of JS strings without breaking apart multi-byte
|
|
||||||
// characters. CESU-8 is handled as part of the UTF-8 encoding.
|
|
||||||
//
|
|
||||||
// @TODO Handling all encodings inside a single object makes it very difficult
|
|
||||||
// to reason about this code, so it should be split up in the future.
|
|
||||||
// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
|
|
||||||
// points as used by CESU-8.
|
|
||||||
var StringDecoder = exports.StringDecoder = function(encoding) {
|
|
||||||
this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
|
|
||||||
assertEncoding(encoding);
|
|
||||||
switch (this.encoding) {
|
|
||||||
case 'utf8':
|
|
||||||
// CESU-8 represents each of Surrogate Pair by 3-bytes
|
|
||||||
this.surrogateSize = 3;
|
|
||||||
break;
|
|
||||||
case 'ucs2':
|
|
||||||
case 'utf16le':
|
|
||||||
// UTF-16 represents each of Surrogate Pair by 2-bytes
|
|
||||||
this.surrogateSize = 2;
|
|
||||||
this.detectIncompleteChar = utf16DetectIncompleteChar;
|
|
||||||
break;
|
|
||||||
case 'base64':
|
|
||||||
// Base-64 stores 3 bytes in 4 chars, and pads the remainder.
|
|
||||||
this.surrogateSize = 3;
|
|
||||||
this.detectIncompleteChar = base64DetectIncompleteChar;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.write = passThroughWrite;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enough space to store all bytes of a single character. UTF-8 needs 4
|
|
||||||
// bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
|
|
||||||
this.charBuffer = new Buffer(6);
|
|
||||||
// Number of bytes received for the current incomplete multi-byte character.
|
|
||||||
this.charReceived = 0;
|
|
||||||
// Number of bytes expected for the current incomplete multi-byte character.
|
|
||||||
this.charLength = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// write decodes the given buffer and returns it as JS string that is
|
|
||||||
// guaranteed to not contain any partial multi-byte characters. Any partial
|
|
||||||
// character found at the end of the buffer is buffered up, and will be
|
|
||||||
// returned when calling write again with the remaining bytes.
|
|
||||||
//
|
|
||||||
// Note: Converting a Buffer containing an orphan surrogate to a String
|
|
||||||
// currently works, but converting a String to a Buffer (via `new Buffer`, or
|
|
||||||
// Buffer#write) will replace incomplete surrogates with the unicode
|
|
||||||
// replacement character. See https://codereview.chromium.org/121173009/ .
|
|
||||||
StringDecoder.prototype.write = function(buffer) {
|
|
||||||
var charStr = '';
|
|
||||||
// if our last write ended with an incomplete multibyte character
|
|
||||||
while (this.charLength) {
|
|
||||||
// determine how many remaining bytes this buffer has to offer for this char
|
|
||||||
var available = (buffer.length >= this.charLength - this.charReceived) ?
|
|
||||||
this.charLength - this.charReceived :
|
|
||||||
buffer.length;
|
|
||||||
|
|
||||||
// add the new bytes to the char buffer
|
|
||||||
buffer.copy(this.charBuffer, this.charReceived, 0, available);
|
|
||||||
this.charReceived += available;
|
|
||||||
|
|
||||||
if (this.charReceived < this.charLength) {
|
|
||||||
// still not enough chars in this buffer? wait for more ...
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove bytes belonging to the current character from the buffer
|
|
||||||
buffer = buffer.slice(available, buffer.length);
|
|
||||||
|
|
||||||
// get the character that was split
|
|
||||||
charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
|
|
||||||
|
|
||||||
// CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
|
|
||||||
var charCode = charStr.charCodeAt(charStr.length - 1);
|
|
||||||
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
|
|
||||||
this.charLength += this.surrogateSize;
|
|
||||||
charStr = '';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
this.charReceived = this.charLength = 0;
|
|
||||||
|
|
||||||
// if there are no more bytes in this buffer, just emit our char
|
|
||||||
if (buffer.length === 0) {
|
|
||||||
return charStr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine and set charLength / charReceived
|
|
||||||
this.detectIncompleteChar(buffer);
|
|
||||||
|
|
||||||
var end = buffer.length;
|
|
||||||
if (this.charLength) {
|
|
||||||
// buffer the incomplete character bytes we got
|
|
||||||
buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
|
|
||||||
end -= this.charReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
charStr += buffer.toString(this.encoding, 0, end);
|
|
||||||
|
|
||||||
var end = charStr.length - 1;
|
|
||||||
var charCode = charStr.charCodeAt(end);
|
|
||||||
// CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
|
|
||||||
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
|
|
||||||
var size = this.surrogateSize;
|
|
||||||
this.charLength += size;
|
|
||||||
this.charReceived += size;
|
|
||||||
this.charBuffer.copy(this.charBuffer, size, 0, size);
|
|
||||||
buffer.copy(this.charBuffer, 0, 0, size);
|
|
||||||
return charStr.substring(0, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
// or just emit the charStr
|
|
||||||
return charStr;
|
|
||||||
};
|
|
||||||
|
|
||||||
// detectIncompleteChar determines if there is an incomplete UTF-8 character at
|
|
||||||
// the end of the given buffer. If so, it sets this.charLength to the byte
|
|
||||||
// length that character, and sets this.charReceived to the number of bytes
|
|
||||||
// that are available for this character.
|
|
||||||
StringDecoder.prototype.detectIncompleteChar = function(buffer) {
|
|
||||||
// determine how many bytes we have to check at the end of this buffer
|
|
||||||
var i = (buffer.length >= 3) ? 3 : buffer.length;
|
|
||||||
|
|
||||||
// Figure out if one of the last i bytes of our buffer announces an
|
|
||||||
// incomplete char.
|
|
||||||
for (; i > 0; i--) {
|
|
||||||
var c = buffer[buffer.length - i];
|
|
||||||
|
|
||||||
// See http://en.wikipedia.org/wiki/UTF-8#Description
|
|
||||||
|
|
||||||
// 110XXXXX
|
|
||||||
if (i == 1 && c >> 5 == 0x06) {
|
|
||||||
this.charLength = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1110XXXX
|
|
||||||
if (i <= 2 && c >> 4 == 0x0E) {
|
|
||||||
this.charLength = 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 11110XXX
|
|
||||||
if (i <= 3 && c >> 3 == 0x1E) {
|
|
||||||
this.charLength = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.charReceived = i;
|
|
||||||
};
|
|
||||||
|
|
||||||
StringDecoder.prototype.end = function(buffer) {
|
|
||||||
var res = '';
|
|
||||||
if (buffer && buffer.length)
|
|
||||||
res = this.write(buffer);
|
|
||||||
|
|
||||||
if (this.charReceived) {
|
|
||||||
var cr = this.charReceived;
|
|
||||||
var buf = this.charBuffer;
|
|
||||||
var enc = this.encoding;
|
|
||||||
res += buf.slice(0, cr).toString(enc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
function passThroughWrite(buffer) {
|
|
||||||
return buffer.toString(this.encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
function utf16DetectIncompleteChar(buffer) {
|
|
||||||
this.charReceived = buffer.length % 2;
|
|
||||||
this.charLength = this.charReceived ? 2 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function base64DetectIncompleteChar(buffer) {
|
|
||||||
this.charReceived = buffer.length % 3;
|
|
||||||
this.charLength = this.charReceived ? 3 : 0;
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"name": "string_decoder",
|
|
||||||
"version": "0.10.31",
|
|
||||||
"description": "The string_decoder module from Node core",
|
|
||||||
"main": "index.js",
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "~0.4.8"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test/simple/*.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/rvagg/string_decoder.git"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/rvagg/string_decoder",
|
|
||||||
"keywords": [
|
|
||||||
"string",
|
|
||||||
"decoder",
|
|
||||||
"browser",
|
|
||||||
"browserify"
|
|
||||||
],
|
|
||||||
"license": "MIT"
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@icetee/ftp",
|
|
||||||
"version": "0.3.15",
|
|
||||||
"author": "Tamás András Horváth <htomy92@gmail.com>",
|
|
||||||
"contributors": [
|
|
||||||
"Brian White <mscdex@mscdex.net>"
|
|
||||||
],
|
|
||||||
"description": "An FTP client module for node.js",
|
|
||||||
"main": "./lib/connection",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.8.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"xregexp": "2.0.0",
|
|
||||||
"readable-stream": "1.1.x"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "node test/test.js"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"ftp",
|
|
||||||
"client",
|
|
||||||
"transfer"
|
|
||||||
],
|
|
||||||
"licenses": [
|
|
||||||
{
|
|
||||||
"type": "MIT",
|
|
||||||
"url": "http://github.com/icetee/node-ftp/raw/master/LICENSE"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "http://github.com/icetee/node-ftp.git"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
# FTP deployer
|
|
||||||
|
|
||||||
[![NPM version](https://badge.fury.io/js/hexo-deployer-ftp-sync.svg)](https://www.npmjs.com/package/hexo-deployer-ftp-sync)
|
|
||||||
|
|
||||||
Deploy your site via FTP.
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
```
|
|
||||||
$ npm install hexo-deployer-ftp-sync --save
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
$ yarn add hexo-deployer-ftp-sync
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Edit settings.
|
|
||||||
````yaml
|
|
||||||
deploy:
|
|
||||||
type: ftpsync
|
|
||||||
host: <host>
|
|
||||||
user: <user>
|
|
||||||
password: <password>
|
|
||||||
remote: [remote]
|
|
||||||
port: [port]
|
|
||||||
ignore: [ignore]
|
|
||||||
verbose: [verbose]
|
|
||||||
````
|
|
||||||
|
|
||||||
| Option | Description | Default |
|
|
||||||
|---------|-------------------------------------------|-----------------------------------|
|
|
||||||
| host | Address of remote host | |
|
|
||||||
| user | Username | Environment variable FTP_USER |
|
|
||||||
| pass | Password | Environment variable FTP_PASSWORD |
|
|
||||||
| remote | Root directory of remote host | / |
|
|
||||||
| port | Port | 21 |
|
|
||||||
| ignore | Ignore the files on either host or remote | false |
|
|
||||||
| verbose | Enable a verbose mode for debug | false |
|
|
||||||
|
|
||||||
## Warning
|
|
||||||
|
|
||||||
This application will delete files and directories on the remote server to match the local machine. Use this application in production at your own risk.
|
|
|
@ -1,65 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const FtpDeploy = require("ftp-deploy");
|
|
||||||
const ftpDeploy = new FtpDeploy();
|
|
||||||
|
|
||||||
hexo.extend.deployer.register('ftpsync', (args, callback) => {
|
|
||||||
|
|
||||||
const { FTP_USER, FTP_PASSWORD } = process.env;
|
|
||||||
|
|
||||||
if (!args.host || (!args.user && !FTP_USER) || (args.password == null && FTP_PASSWORD == null)) {
|
|
||||||
const help = [
|
|
||||||
'You should configure deployment settings in _config.yml first!',
|
|
||||||
'',
|
|
||||||
'Example:',
|
|
||||||
' deploy:',
|
|
||||||
' type: ftpsync',
|
|
||||||
' host: <host>',
|
|
||||||
' port: [port] # Default is 21',
|
|
||||||
' remote: [remote] # Default is `/`',
|
|
||||||
' user: <user>',
|
|
||||||
' password: <password>',
|
|
||||||
' ignore: false # Default is false',
|
|
||||||
' passive: true # Default is true',
|
|
||||||
'',
|
|
||||||
'For more help, you can check the docs: ' + 'https://github.com/m-maillot/hexo-deployer-ftp-sync#usage'.underline
|
|
||||||
];
|
|
||||||
|
|
||||||
console.log(help.join('\n'));
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
user: args.user || FTP_USER,
|
|
||||||
password: args.password || FTP_PASSWORD,
|
|
||||||
host: args.host,
|
|
||||||
port: args.port || 21,
|
|
||||||
localRoot: hexo.public_dir,
|
|
||||||
remoteRoot: args.remote || '/',
|
|
||||||
include: ["*", "**/*"],
|
|
||||||
deleteRemote: !args.ignore,
|
|
||||||
// Passive mode is forced (EPSV command is not sent)
|
|
||||||
forcePasv: args.passive === undefined ? true : args.passive,
|
|
||||||
// use sftp or ftp
|
|
||||||
sftp: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (args.verbose) {
|
|
||||||
console.log("Config:");
|
|
||||||
console.log(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
ftpDeploy
|
|
||||||
.deploy(config)
|
|
||||||
.then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
callback();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
if (args.verbose) {
|
|
||||||
console.error("Upload failed");
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@m-maillot/hexo-deployer-ftp-sync",
|
|
||||||
"version": "1.0.3",
|
|
||||||
"description": "FTP deployer for Hexo",
|
|
||||||
"main": "index.js",
|
|
||||||
"files": [
|
|
||||||
"index.js"
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"run": "node ./index.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/m-maillot/hexo-deployer-ftp-sync.git"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/m-maillot/hexo-deployer-ftp-sync/issues"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"hexo",
|
|
||||||
"ftp",
|
|
||||||
"sync",
|
|
||||||
"deploy",
|
|
||||||
"deployer"
|
|
||||||
],
|
|
||||||
"author": "Martial Maillot",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ftp-deploy": "^2.4.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/m-maillot/hexo-deployer-ftp-sync#readme",
|
|
||||||
"devDependencies": {}
|
|
||||||
}
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Version 0.11.0
|
||||||
|
|
||||||
|
* (`selderee`) Escape sequences in selectors.
|
||||||
|
|
||||||
|
## Version 0.10.0
|
||||||
|
|
||||||
|
* Targeting Node.js version 14 and ES2020;
|
||||||
|
* Bump dependencies.
|
||||||
|
|
||||||
|
## Version 0.9.0
|
||||||
|
|
||||||
|
* Bump dependencies - fix "./core module cannot be found" issue.
|
||||||
|
|
||||||
|
## Version 0.8.1
|
||||||
|
|
||||||
|
* Sync with `selderee` package version. Now all dependencies are TypeScript, dual CommonJS/ES module packages;
|
||||||
|
* Use `rollup-plugin-cleanup` to condition published files.
|
||||||
|
|
||||||
|
## Version 0.7.0
|
||||||
|
|
||||||
|
* Drop Node.js version 10 support. At least 12.22.x is required.
|
||||||
|
|
||||||
|
## Version 0.6.0
|
||||||
|
|
||||||
|
* `selderee` 0.6.0 - [changelog](https://github.com/mxxii/selderee/blob/main/packages/selderee/CHANGELOG.md).
|
||||||
|
|
||||||
|
## Version 0.5.0
|
||||||
|
|
||||||
|
Initial release.
|
||||||
|
|
||||||
|
Aiming at Node.js version 10 and up.
|
43
node_modules/promise-ftp/LICENSE → node_modules/@selderee/plugin-htmlparser2/LICENSE
generated
vendored
43
node_modules/promise-ftp/LICENSE → node_modules/@selderee/plugin-htmlparser2/LICENSE
generated
vendored
|
@ -1,22 +1,21 @@
|
||||||
The MIT License (MIT)
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2015
|
Copyright (c) 2021-2022 KillyMXI <killy@mxii.eu.org>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# selderee
|
||||||
|
|
||||||
|
![lint status badge](https://github.com/mxxii/selderee/workflows/lint/badge.svg)
|
||||||
|
![test status badge](https://github.com/mxxii/selderee/workflows/test/badge.svg)
|
||||||
|
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/mxxii/selderee/blob/main/LICENSE)
|
||||||
|
|
||||||
|
[selderee](https://github.com/mxxii/selderee) plugin - selectors decision tree builder for [htmlparser2](https://github.com/fb55/htmlparser2) DOM AST.
|
||||||
|
|
||||||
|
(Technically, the package depends not on `htmlparser2` but on [domhandler](https://github.com/fb55/domhandler), underlying package of `htmlparser2`.)
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
[Changelog](https://github.com/mxxii/selderee/blob/main/packages/plugin-htmlparser2/CHANGELOG.md).
|
||||||
|
|
||||||
|
See [main README file](https://github.com/mxxii/selderee/blob/main/README.md) for more info.
|
|
@ -0,0 +1,94 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
|
||||||
|
var domhandler = require('domhandler');
|
||||||
|
var selderee = require('selderee');
|
||||||
|
|
||||||
|
function hp2Builder(nodes) {
|
||||||
|
return new selderee.Picker(handleArray(nodes));
|
||||||
|
}
|
||||||
|
function handleArray(nodes) {
|
||||||
|
const matchers = nodes.map(handleNode);
|
||||||
|
return (el, ...tail) => matchers.flatMap(m => m(el, ...tail));
|
||||||
|
}
|
||||||
|
function handleNode(node) {
|
||||||
|
switch (node.type) {
|
||||||
|
case 'terminal': {
|
||||||
|
const result = [node.valueContainer];
|
||||||
|
return (el, ...tail) => result;
|
||||||
|
}
|
||||||
|
case 'tagName':
|
||||||
|
return handleTagName(node);
|
||||||
|
case 'attrValue':
|
||||||
|
return handleAttrValueName(node);
|
||||||
|
case 'attrPresence':
|
||||||
|
return handleAttrPresenceName(node);
|
||||||
|
case 'pushElement':
|
||||||
|
return handlePushElementNode(node);
|
||||||
|
case 'popElement':
|
||||||
|
return handlePopElementNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleTagName(node) {
|
||||||
|
const variants = {};
|
||||||
|
for (const variant of node.variants) {
|
||||||
|
variants[variant.value] = handleArray(variant.cont);
|
||||||
|
}
|
||||||
|
return (el, ...tail) => {
|
||||||
|
const continuation = variants[el.name];
|
||||||
|
return (continuation) ? continuation(el, ...tail) : [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function handleAttrPresenceName(node) {
|
||||||
|
const attrName = node.name;
|
||||||
|
const continuation = handleArray(node.cont);
|
||||||
|
return (el, ...tail) => (Object.prototype.hasOwnProperty.call(el.attribs, attrName))
|
||||||
|
? continuation(el, ...tail)
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
function handleAttrValueName(node) {
|
||||||
|
const callbacks = [];
|
||||||
|
for (const matcher of node.matchers) {
|
||||||
|
const predicate = matcher.predicate;
|
||||||
|
const continuation = handleArray(matcher.cont);
|
||||||
|
callbacks.push((attr, el, ...tail) => (predicate(attr) ? continuation(el, ...tail) : []));
|
||||||
|
}
|
||||||
|
const attrName = node.name;
|
||||||
|
return (el, ...tail) => {
|
||||||
|
const attr = el.attribs[attrName];
|
||||||
|
return (attr || attr === '')
|
||||||
|
? callbacks.flatMap(cb => cb(attr, el, ...tail))
|
||||||
|
: [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function handlePushElementNode(node) {
|
||||||
|
const continuation = handleArray(node.cont);
|
||||||
|
const leftElementGetter = (node.combinator === '+')
|
||||||
|
? getPrecedingElement
|
||||||
|
: getParentElement;
|
||||||
|
return (el, ...tail) => {
|
||||||
|
const next = leftElementGetter(el);
|
||||||
|
if (next === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return continuation(next, el, ...tail);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const getPrecedingElement = (el) => {
|
||||||
|
const prev = el.prev;
|
||||||
|
if (prev === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (domhandler.isTag(prev)) ? prev : getPrecedingElement(prev);
|
||||||
|
};
|
||||||
|
const getParentElement = (el) => {
|
||||||
|
const parent = el.parent;
|
||||||
|
return (parent && domhandler.isTag(parent)) ? parent : null;
|
||||||
|
};
|
||||||
|
function handlePopElementNode(node) {
|
||||||
|
const continuation = handleArray(node.cont);
|
||||||
|
return (el, next, ...tail) => continuation(next, ...tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.hp2Builder = hp2Builder;
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Element } from 'domhandler';
|
||||||
|
import { Picker, Ast } from 'selderee';
|
||||||
|
/**
|
||||||
|
* A {@link BuilderFunction} implementation.
|
||||||
|
*
|
||||||
|
* Creates a function (in a {@link Picker} wrapper) that can run
|
||||||
|
* the decision tree against `htmlparser2` `Element` nodes.
|
||||||
|
*
|
||||||
|
* @typeParam V - the type of values associated with selectors.
|
||||||
|
*
|
||||||
|
* @param nodes - nodes ({@link DecisionTreeNode})
|
||||||
|
* from the root level of the decision tree.
|
||||||
|
*
|
||||||
|
* @returns a {@link Picker} object.
|
||||||
|
*/
|
||||||
|
export declare function hp2Builder<V>(nodes: Ast.DecisionTreeNode<V>[]): Picker<Element, V>;
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { isTag } from 'domhandler';
|
||||||
|
import { Picker } from 'selderee';
|
||||||
|
|
||||||
|
function hp2Builder(nodes) {
|
||||||
|
return new Picker(handleArray(nodes));
|
||||||
|
}
|
||||||
|
function handleArray(nodes) {
|
||||||
|
const matchers = nodes.map(handleNode);
|
||||||
|
return (el, ...tail) => matchers.flatMap(m => m(el, ...tail));
|
||||||
|
}
|
||||||
|
function handleNode(node) {
|
||||||
|
switch (node.type) {
|
||||||
|
case 'terminal': {
|
||||||
|
const result = [node.valueContainer];
|
||||||
|
return (el, ...tail) => result;
|
||||||
|
}
|
||||||
|
case 'tagName':
|
||||||
|
return handleTagName(node);
|
||||||
|
case 'attrValue':
|
||||||
|
return handleAttrValueName(node);
|
||||||
|
case 'attrPresence':
|
||||||
|
return handleAttrPresenceName(node);
|
||||||
|
case 'pushElement':
|
||||||
|
return handlePushElementNode(node);
|
||||||
|
case 'popElement':
|
||||||
|
return handlePopElementNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleTagName(node) {
|
||||||
|
const variants = {};
|
||||||
|
for (const variant of node.variants) {
|
||||||
|
variants[variant.value] = handleArray(variant.cont);
|
||||||
|
}
|
||||||
|
return (el, ...tail) => {
|
||||||
|
const continuation = variants[el.name];
|
||||||
|
return (continuation) ? continuation(el, ...tail) : [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function handleAttrPresenceName(node) {
|
||||||
|
const attrName = node.name;
|
||||||
|
const continuation = handleArray(node.cont);
|
||||||
|
return (el, ...tail) => (Object.prototype.hasOwnProperty.call(el.attribs, attrName))
|
||||||
|
? continuation(el, ...tail)
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
function handleAttrValueName(node) {
|
||||||
|
const callbacks = [];
|
||||||
|
for (const matcher of node.matchers) {
|
||||||
|
const predicate = matcher.predicate;
|
||||||
|
const continuation = handleArray(matcher.cont);
|
||||||
|
callbacks.push((attr, el, ...tail) => (predicate(attr) ? continuation(el, ...tail) : []));
|
||||||
|
}
|
||||||
|
const attrName = node.name;
|
||||||
|
return (el, ...tail) => {
|
||||||
|
const attr = el.attribs[attrName];
|
||||||
|
return (attr || attr === '')
|
||||||
|
? callbacks.flatMap(cb => cb(attr, el, ...tail))
|
||||||
|
: [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function handlePushElementNode(node) {
|
||||||
|
const continuation = handleArray(node.cont);
|
||||||
|
const leftElementGetter = (node.combinator === '+')
|
||||||
|
? getPrecedingElement
|
||||||
|
: getParentElement;
|
||||||
|
return (el, ...tail) => {
|
||||||
|
const next = leftElementGetter(el);
|
||||||
|
if (next === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return continuation(next, el, ...tail);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const getPrecedingElement = (el) => {
|
||||||
|
const prev = el.prev;
|
||||||
|
if (prev === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (isTag(prev)) ? prev : getPrecedingElement(prev);
|
||||||
|
};
|
||||||
|
const getParentElement = (el) => {
|
||||||
|
const parent = el.parent;
|
||||||
|
return (parent && isTag(parent)) ? parent : null;
|
||||||
|
};
|
||||||
|
function handlePopElementNode(node) {
|
||||||
|
const continuation = handleArray(node.cont);
|
||||||
|
return (el, next, ...tail) => continuation(next, ...tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { hp2Builder };
|
11
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/LICENSE
generated
vendored
Normal file
11
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
Copyright (c) Felix Böhm
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
|
||||||
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
76
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/index.d.ts
generated
vendored
Normal file
76
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/index.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import { ChildNode, Element, DataNode, Document, ParentNode } from "./node.js";
|
||||||
|
export * from "./node.js";
|
||||||
|
export interface DomHandlerOptions {
|
||||||
|
/**
|
||||||
|
* Add a `startIndex` property to nodes.
|
||||||
|
* When the parser is used in a non-streaming fashion, `startIndex` is an integer
|
||||||
|
* indicating the position of the start of the node in the document.
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
withStartIndices?: boolean;
|
||||||
|
/**
|
||||||
|
* Add an `endIndex` property to nodes.
|
||||||
|
* When the parser is used in a non-streaming fashion, `endIndex` is an integer
|
||||||
|
* indicating the position of the end of the node in the document.
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
withEndIndices?: boolean;
|
||||||
|
/**
|
||||||
|
* Treat the markup as XML.
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
xmlMode?: boolean;
|
||||||
|
}
|
||||||
|
interface ParserInterface {
|
||||||
|
startIndex: number | null;
|
||||||
|
endIndex: number | null;
|
||||||
|
}
|
||||||
|
declare type Callback = (error: Error | null, dom: ChildNode[]) => void;
|
||||||
|
declare type ElementCallback = (element: Element) => void;
|
||||||
|
export declare class DomHandler {
|
||||||
|
/** The elements of the DOM */
|
||||||
|
dom: ChildNode[];
|
||||||
|
/** The root element for the DOM */
|
||||||
|
root: Document;
|
||||||
|
/** Called once parsing has completed. */
|
||||||
|
private readonly callback;
|
||||||
|
/** Settings for the handler. */
|
||||||
|
private readonly options;
|
||||||
|
/** Callback whenever a tag is closed. */
|
||||||
|
private readonly elementCB;
|
||||||
|
/** Indicated whether parsing has been completed. */
|
||||||
|
private done;
|
||||||
|
/** Stack of open tags. */
|
||||||
|
protected tagStack: ParentNode[];
|
||||||
|
/** A data node that is still being written to. */
|
||||||
|
protected lastNode: DataNode | null;
|
||||||
|
/** Reference to the parser instance. Used for location information. */
|
||||||
|
private parser;
|
||||||
|
/**
|
||||||
|
* @param callback Called once parsing has completed.
|
||||||
|
* @param options Settings for the handler.
|
||||||
|
* @param elementCB Callback whenever a tag is closed.
|
||||||
|
*/
|
||||||
|
constructor(callback?: Callback | null, options?: DomHandlerOptions | null, elementCB?: ElementCallback);
|
||||||
|
onparserinit(parser: ParserInterface): void;
|
||||||
|
onreset(): void;
|
||||||
|
onend(): void;
|
||||||
|
onerror(error: Error): void;
|
||||||
|
onclosetag(): void;
|
||||||
|
onopentag(name: string, attribs: {
|
||||||
|
[key: string]: string;
|
||||||
|
}): void;
|
||||||
|
ontext(data: string): void;
|
||||||
|
oncomment(data: string): void;
|
||||||
|
oncommentend(): void;
|
||||||
|
oncdatastart(): void;
|
||||||
|
oncdataend(): void;
|
||||||
|
onprocessinginstruction(name: string, data: string): void;
|
||||||
|
protected handleCallback(error: Error | null): void;
|
||||||
|
protected addNode(node: ChildNode): void;
|
||||||
|
}
|
||||||
|
export default DomHandler;
|
||||||
|
//# sourceMappingURL=index.d.ts.map
|
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/index.d.ts.map
generated
vendored
Normal file
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/index.d.ts.map
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,SAAS,EACT,OAAO,EACP,QAAQ,EAIR,QAAQ,EAER,UAAU,EACb,MAAM,WAAW,CAAC;AAEnB,cAAc,WAAW,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IAC9B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AASD,UAAU,eAAe;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,aAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;AAChE,aAAK,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAElD,qBAAa,UAAU;IACnB,8BAA8B;IACvB,GAAG,EAAE,SAAS,EAAE,CAAM;IAE7B,mCAAmC;IAC5B,IAAI,WAA0B;IAErC,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAE3C,gCAAgC;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAE5C,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAEnD,oDAAoD;IACpD,OAAO,CAAC,IAAI,CAAS;IAErB,0BAA0B;IAC1B,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAe;IAE/C,kDAAkD;IAClD,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAE3C,uEAAuE;IACvE,OAAO,CAAC,MAAM,CAAgC;IAE9C;;;;OAIG;gBAEC,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,EAClC,SAAS,CAAC,EAAE,eAAe;IAiBxB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAK3C,OAAO,IAAI,IAAI;IAUf,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAI3B,UAAU,IAAI,IAAI;IAYlB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI;IAOjE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAe1B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAW7B,YAAY,IAAI,IAAI;IAIpB,YAAY,IAAI,IAAI;IAUpB,UAAU,IAAI,IAAI;IAIlB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKhE,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI;IAQnD,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;CAwB3C;AAED,eAAe,UAAU,CAAC"}
|
146
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/index.js
generated
vendored
Normal file
146
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/index.js
generated
vendored
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import { ElementType } from "domelementtype";
|
||||||
|
import { Element, Text, Comment, CDATA, Document, ProcessingInstruction, } from "./node.js";
|
||||||
|
export * from "./node.js";
|
||||||
|
// Default options
|
||||||
|
const defaultOpts = {
|
||||||
|
withStartIndices: false,
|
||||||
|
withEndIndices: false,
|
||||||
|
xmlMode: false,
|
||||||
|
};
|
||||||
|
export class DomHandler {
|
||||||
|
/**
|
||||||
|
* @param callback Called once parsing has completed.
|
||||||
|
* @param options Settings for the handler.
|
||||||
|
* @param elementCB Callback whenever a tag is closed.
|
||||||
|
*/
|
||||||
|
constructor(callback, options, elementCB) {
|
||||||
|
/** The elements of the DOM */
|
||||||
|
this.dom = [];
|
||||||
|
/** The root element for the DOM */
|
||||||
|
this.root = new Document(this.dom);
|
||||||
|
/** Indicated whether parsing has been completed. */
|
||||||
|
this.done = false;
|
||||||
|
/** Stack of open tags. */
|
||||||
|
this.tagStack = [this.root];
|
||||||
|
/** A data node that is still being written to. */
|
||||||
|
this.lastNode = null;
|
||||||
|
/** Reference to the parser instance. Used for location information. */
|
||||||
|
this.parser = null;
|
||||||
|
// Make it possible to skip arguments, for backwards-compatibility
|
||||||
|
if (typeof options === "function") {
|
||||||
|
elementCB = options;
|
||||||
|
options = defaultOpts;
|
||||||
|
}
|
||||||
|
if (typeof callback === "object") {
|
||||||
|
options = callback;
|
||||||
|
callback = undefined;
|
||||||
|
}
|
||||||
|
this.callback = callback !== null && callback !== void 0 ? callback : null;
|
||||||
|
this.options = options !== null && options !== void 0 ? options : defaultOpts;
|
||||||
|
this.elementCB = elementCB !== null && elementCB !== void 0 ? elementCB : null;
|
||||||
|
}
|
||||||
|
onparserinit(parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
// Resets the handler back to starting state
|
||||||
|
onreset() {
|
||||||
|
this.dom = [];
|
||||||
|
this.root = new Document(this.dom);
|
||||||
|
this.done = false;
|
||||||
|
this.tagStack = [this.root];
|
||||||
|
this.lastNode = null;
|
||||||
|
this.parser = null;
|
||||||
|
}
|
||||||
|
// Signals the handler that parsing is done
|
||||||
|
onend() {
|
||||||
|
if (this.done)
|
||||||
|
return;
|
||||||
|
this.done = true;
|
||||||
|
this.parser = null;
|
||||||
|
this.handleCallback(null);
|
||||||
|
}
|
||||||
|
onerror(error) {
|
||||||
|
this.handleCallback(error);
|
||||||
|
}
|
||||||
|
onclosetag() {
|
||||||
|
this.lastNode = null;
|
||||||
|
const elem = this.tagStack.pop();
|
||||||
|
if (this.options.withEndIndices) {
|
||||||
|
elem.endIndex = this.parser.endIndex;
|
||||||
|
}
|
||||||
|
if (this.elementCB)
|
||||||
|
this.elementCB(elem);
|
||||||
|
}
|
||||||
|
onopentag(name, attribs) {
|
||||||
|
const type = this.options.xmlMode ? ElementType.Tag : undefined;
|
||||||
|
const element = new Element(name, attribs, undefined, type);
|
||||||
|
this.addNode(element);
|
||||||
|
this.tagStack.push(element);
|
||||||
|
}
|
||||||
|
ontext(data) {
|
||||||
|
const { lastNode } = this;
|
||||||
|
if (lastNode && lastNode.type === ElementType.Text) {
|
||||||
|
lastNode.data += data;
|
||||||
|
if (this.options.withEndIndices) {
|
||||||
|
lastNode.endIndex = this.parser.endIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const node = new Text(data);
|
||||||
|
this.addNode(node);
|
||||||
|
this.lastNode = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oncomment(data) {
|
||||||
|
if (this.lastNode && this.lastNode.type === ElementType.Comment) {
|
||||||
|
this.lastNode.data += data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const node = new Comment(data);
|
||||||
|
this.addNode(node);
|
||||||
|
this.lastNode = node;
|
||||||
|
}
|
||||||
|
oncommentend() {
|
||||||
|
this.lastNode = null;
|
||||||
|
}
|
||||||
|
oncdatastart() {
|
||||||
|
const text = new Text("");
|
||||||
|
const node = new CDATA([text]);
|
||||||
|
this.addNode(node);
|
||||||
|
text.parent = node;
|
||||||
|
this.lastNode = text;
|
||||||
|
}
|
||||||
|
oncdataend() {
|
||||||
|
this.lastNode = null;
|
||||||
|
}
|
||||||
|
onprocessinginstruction(name, data) {
|
||||||
|
const node = new ProcessingInstruction(name, data);
|
||||||
|
this.addNode(node);
|
||||||
|
}
|
||||||
|
handleCallback(error) {
|
||||||
|
if (typeof this.callback === "function") {
|
||||||
|
this.callback(error, this.dom);
|
||||||
|
}
|
||||||
|
else if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addNode(node) {
|
||||||
|
const parent = this.tagStack[this.tagStack.length - 1];
|
||||||
|
const previousSibling = parent.children[parent.children.length - 1];
|
||||||
|
if (this.options.withStartIndices) {
|
||||||
|
node.startIndex = this.parser.startIndex;
|
||||||
|
}
|
||||||
|
if (this.options.withEndIndices) {
|
||||||
|
node.endIndex = this.parser.endIndex;
|
||||||
|
}
|
||||||
|
parent.children.push(node);
|
||||||
|
if (previousSibling) {
|
||||||
|
node.prev = previousSibling;
|
||||||
|
previousSibling.next = node;
|
||||||
|
}
|
||||||
|
node.parent = parent;
|
||||||
|
this.lastNode = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default DomHandler;
|
245
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/node.d.ts
generated
vendored
Normal file
245
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/node.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
import { ElementType } from "domelementtype";
|
||||||
|
interface SourceCodeLocation {
|
||||||
|
/** One-based line index of the first character. */
|
||||||
|
startLine: number;
|
||||||
|
/** One-based column index of the first character. */
|
||||||
|
startCol: number;
|
||||||
|
/** Zero-based first character index. */
|
||||||
|
startOffset: number;
|
||||||
|
/** One-based line index of the last character. */
|
||||||
|
endLine: number;
|
||||||
|
/** One-based column index of the last character. Points directly *after* the last character. */
|
||||||
|
endCol: number;
|
||||||
|
/** Zero-based last character index. Points directly *after* the last character. */
|
||||||
|
endOffset: number;
|
||||||
|
}
|
||||||
|
interface TagSourceCodeLocation extends SourceCodeLocation {
|
||||||
|
startTag?: SourceCodeLocation;
|
||||||
|
endTag?: SourceCodeLocation;
|
||||||
|
}
|
||||||
|
export declare type ParentNode = Document | Element | CDATA;
|
||||||
|
export declare type ChildNode = Text | Comment | ProcessingInstruction | Element | CDATA | Document;
|
||||||
|
export declare type AnyNode = ParentNode | ChildNode;
|
||||||
|
/**
|
||||||
|
* This object will be used as the prototype for Nodes when creating a
|
||||||
|
* DOM-Level-1-compliant structure.
|
||||||
|
*/
|
||||||
|
export declare abstract class Node {
|
||||||
|
/** The type of the node. */
|
||||||
|
abstract readonly type: ElementType;
|
||||||
|
/** Parent of the node */
|
||||||
|
parent: ParentNode | null;
|
||||||
|
/** Previous sibling */
|
||||||
|
prev: ChildNode | null;
|
||||||
|
/** Next sibling */
|
||||||
|
next: ChildNode | null;
|
||||||
|
/** The start index of the node. Requires `withStartIndices` on the handler to be `true. */
|
||||||
|
startIndex: number | null;
|
||||||
|
/** The end index of the node. Requires `withEndIndices` on the handler to be `true. */
|
||||||
|
endIndex: number | null;
|
||||||
|
/**
|
||||||
|
* `parse5` source code location info.
|
||||||
|
*
|
||||||
|
* Available if parsing with parse5 and location info is enabled.
|
||||||
|
*/
|
||||||
|
sourceCodeLocation?: SourceCodeLocation | null;
|
||||||
|
/**
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org/#dom-node-nodetype)-compatible
|
||||||
|
* node {@link type}.
|
||||||
|
*/
|
||||||
|
abstract readonly nodeType: number;
|
||||||
|
/**
|
||||||
|
* Same as {@link parent}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get parentNode(): ParentNode | null;
|
||||||
|
set parentNode(parent: ParentNode | null);
|
||||||
|
/**
|
||||||
|
* Same as {@link prev}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get previousSibling(): ChildNode | null;
|
||||||
|
set previousSibling(prev: ChildNode | null);
|
||||||
|
/**
|
||||||
|
* Same as {@link next}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get nextSibling(): ChildNode | null;
|
||||||
|
set nextSibling(next: ChildNode | null);
|
||||||
|
/**
|
||||||
|
* Clone this node, and optionally its children.
|
||||||
|
*
|
||||||
|
* @param recursive Clone child nodes as well.
|
||||||
|
* @returns A clone of the node.
|
||||||
|
*/
|
||||||
|
cloneNode<T extends Node>(this: T, recursive?: boolean): T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A node that contains some data.
|
||||||
|
*/
|
||||||
|
export declare abstract class DataNode extends Node {
|
||||||
|
data: string;
|
||||||
|
/**
|
||||||
|
* @param data The content of the data node
|
||||||
|
*/
|
||||||
|
constructor(data: string);
|
||||||
|
/**
|
||||||
|
* Same as {@link data}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get nodeValue(): string;
|
||||||
|
set nodeValue(data: string);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Text within the document.
|
||||||
|
*/
|
||||||
|
export declare class Text extends DataNode {
|
||||||
|
type: ElementType.Text;
|
||||||
|
get nodeType(): 3;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Comments within the document.
|
||||||
|
*/
|
||||||
|
export declare class Comment extends DataNode {
|
||||||
|
type: ElementType.Comment;
|
||||||
|
get nodeType(): 8;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Processing instructions, including doc types.
|
||||||
|
*/
|
||||||
|
export declare class ProcessingInstruction extends DataNode {
|
||||||
|
name: string;
|
||||||
|
type: ElementType.Directive;
|
||||||
|
constructor(name: string, data: string);
|
||||||
|
get nodeType(): 1;
|
||||||
|
/** If this is a doctype, the document type name (parse5 only). */
|
||||||
|
"x-name"?: string;
|
||||||
|
/** If this is a doctype, the document type public identifier (parse5 only). */
|
||||||
|
"x-publicId"?: string;
|
||||||
|
/** If this is a doctype, the document type system identifier (parse5 only). */
|
||||||
|
"x-systemId"?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A `Node` that can have children.
|
||||||
|
*/
|
||||||
|
export declare abstract class NodeWithChildren extends Node {
|
||||||
|
children: ChildNode[];
|
||||||
|
/**
|
||||||
|
* @param children Children of the node. Only certain node types can have children.
|
||||||
|
*/
|
||||||
|
constructor(children: ChildNode[]);
|
||||||
|
/** First child of the node. */
|
||||||
|
get firstChild(): ChildNode | null;
|
||||||
|
/** Last child of the node. */
|
||||||
|
get lastChild(): ChildNode | null;
|
||||||
|
/**
|
||||||
|
* Same as {@link children}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get childNodes(): ChildNode[];
|
||||||
|
set childNodes(children: ChildNode[]);
|
||||||
|
}
|
||||||
|
export declare class CDATA extends NodeWithChildren {
|
||||||
|
type: ElementType.CDATA;
|
||||||
|
get nodeType(): 4;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The root node of the document.
|
||||||
|
*/
|
||||||
|
export declare class Document extends NodeWithChildren {
|
||||||
|
type: ElementType.Root;
|
||||||
|
get nodeType(): 9;
|
||||||
|
/** [Document mode](https://dom.spec.whatwg.org/#concept-document-limited-quirks) (parse5 only). */
|
||||||
|
"x-mode"?: "no-quirks" | "quirks" | "limited-quirks";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The description of an individual attribute.
|
||||||
|
*/
|
||||||
|
interface Attribute {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
namespace?: string;
|
||||||
|
prefix?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An element within the DOM.
|
||||||
|
*/
|
||||||
|
export declare class Element extends NodeWithChildren {
|
||||||
|
name: string;
|
||||||
|
attribs: {
|
||||||
|
[name: string]: string;
|
||||||
|
};
|
||||||
|
type: ElementType.Tag | ElementType.Script | ElementType.Style;
|
||||||
|
/**
|
||||||
|
* @param name Name of the tag, eg. `div`, `span`.
|
||||||
|
* @param attribs Object mapping attribute names to attribute values.
|
||||||
|
* @param children Children of the node.
|
||||||
|
*/
|
||||||
|
constructor(name: string, attribs: {
|
||||||
|
[name: string]: string;
|
||||||
|
}, children?: ChildNode[], type?: ElementType.Tag | ElementType.Script | ElementType.Style);
|
||||||
|
get nodeType(): 1;
|
||||||
|
/**
|
||||||
|
* `parse5` source code location info, with start & end tags.
|
||||||
|
*
|
||||||
|
* Available if parsing with parse5 and location info is enabled.
|
||||||
|
*/
|
||||||
|
sourceCodeLocation?: TagSourceCodeLocation | null;
|
||||||
|
/**
|
||||||
|
* Same as {@link name}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get tagName(): string;
|
||||||
|
set tagName(name: string);
|
||||||
|
get attributes(): Attribute[];
|
||||||
|
/** Element namespace (parse5 only). */
|
||||||
|
namespace?: string;
|
||||||
|
/** Element attribute namespaces (parse5 only). */
|
||||||
|
"x-attribsNamespace"?: Record<string, string>;
|
||||||
|
/** Element attribute namespace-related prefixes (parse5 only). */
|
||||||
|
"x-attribsPrefix"?: Record<string, string>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node is a `Element`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isTag(node: Node): node is Element;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `CDATA`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isCDATA(node: Node): node is CDATA;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `Text`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isText(node: Node): node is Text;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `Comment`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isComment(node: Node): node is Comment;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isDirective(node: Node): node is ProcessingInstruction;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isDocument(node: Node): node is Document;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has children, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function hasChildren(node: Node): node is ParentNode;
|
||||||
|
/**
|
||||||
|
* Clone a node, and optionally its children.
|
||||||
|
*
|
||||||
|
* @param recursive Clone child nodes as well.
|
||||||
|
* @returns A clone of the node.
|
||||||
|
*/
|
||||||
|
export declare function cloneNode<T extends Node>(node: T, recursive?: boolean): T;
|
||||||
|
export {};
|
||||||
|
//# sourceMappingURL=node.d.ts.map
|
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/node.d.ts.map
generated
vendored
Normal file
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/node.d.ts.map
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAqB,MAAM,gBAAgB,CAAC;AAEhE,UAAU,kBAAkB;IACxB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,MAAM,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,qBAAsB,SAAQ,kBAAkB;IACtD,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED,oBAAY,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;AACpD,oBAAY,SAAS,GACf,IAAI,GACJ,OAAO,GACP,qBAAqB,GACrB,OAAO,GACP,KAAK,GAEL,QAAQ,CAAC;AACf,oBAAY,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAE7C;;;GAGG;AACH,8BAAsB,IAAI;IACtB,4BAA4B;IAC5B,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAEpC,yBAAyB;IACzB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAQ;IAEjC,uBAAuB;IACvB,IAAI,EAAE,SAAS,GAAG,IAAI,CAAQ;IAE9B,mBAAmB;IACnB,IAAI,EAAE,SAAS,GAAG,IAAI,CAAQ;IAE9B,2FAA2F;IAC3F,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC,uFAAuF;IACvF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAI/C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAInC;;;OAGG;IACH,IAAI,UAAU,IAAI,UAAU,GAAG,IAAI,CAElC;IAED,IAAI,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAEvC;IAED;;;OAGG;IACH,IAAI,eAAe,IAAI,SAAS,GAAG,IAAI,CAEtC;IAED,IAAI,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,EAEzC;IAED;;;OAGG;IACH,IAAI,WAAW,IAAI,SAAS,GAAG,IAAI,CAElC;IAED,IAAI,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,EAErC;IAED;;;;;OAKG;IACH,SAAS,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,UAAQ,GAAG,CAAC;CAG3D;AAED;;GAEG;AACH,8BAAsB,QAAS,SAAQ,IAAI;IAIpB,IAAI,EAAE,MAAM;IAH/B;;OAEG;gBACgB,IAAI,EAAE,MAAM;IAI/B;;;OAGG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,SAAS,CAAC,IAAI,EAAE,MAAM,EAEzB;CACJ;AAED;;GAEG;AACH,qBAAa,IAAK,SAAQ,QAAQ;IAC9B,IAAI,EAAE,WAAW,CAAC,IAAI,CAAoB;IAE1C,IAAI,QAAQ,IAAI,CAAC,CAEhB;CACJ;AAED;;GAEG;AACH,qBAAa,OAAQ,SAAQ,QAAQ;IACjC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAuB;IAEhD,IAAI,QAAQ,IAAI,CAAC,CAEhB;CACJ;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,QAAQ;IAG5B,IAAI,EAAE,MAAM;IAF/B,IAAI,EAAE,WAAW,CAAC,SAAS,CAAyB;gBAEjC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAI7C,IAAa,QAAQ,IAAI,CAAC,CAEzB;IAED,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,8BAAsB,gBAAiB,SAAQ,IAAI;IAI5B,QAAQ,EAAE,SAAS,EAAE;IAHxC;;OAEG;gBACgB,QAAQ,EAAE,SAAS,EAAE;IAKxC,+BAA+B;IAC/B,IAAI,UAAU,IAAI,SAAS,GAAG,IAAI,CAEjC;IAED,8BAA8B;IAC9B,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,CAIhC;IAED;;;OAGG;IACH,IAAI,UAAU,IAAI,SAAS,EAAE,CAE5B;IAED,IAAI,UAAU,CAAC,QAAQ,EAAE,SAAS,EAAE,EAEnC;CACJ;AAED,qBAAa,KAAM,SAAQ,gBAAgB;IACvC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAqB;IAE5C,IAAI,QAAQ,IAAI,CAAC,CAEhB;CACJ;AAED;;GAEG;AACH,qBAAa,QAAS,SAAQ,gBAAgB;IAC1C,IAAI,EAAE,WAAW,CAAC,IAAI,CAAoB;IAE1C,IAAI,QAAQ,IAAI,CAAC,CAEhB;IAED,mGAAmG;IACnG,QAAQ,CAAC,EAAE,WAAW,GAAG,QAAQ,GAAG,gBAAgB,CAAC;CACxD;AAED;;GAEG;AACH,UAAU,SAAS;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,OAAQ,SAAQ,gBAAgB;IAO9B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE;IAEnC,IAAI,EACL,WAAW,CAAC,GAAG,GACf,WAAW,CAAC,MAAM,GAClB,WAAW,CAAC,KAAK;IAZ3B;;;;OAIG;gBAEQ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,EAC1C,QAAQ,GAAE,SAAS,EAAO,EACnB,IAAI,GACL,WAAW,CAAC,GAAG,GACf,WAAW,CAAC,MAAM,GAClB,WAAW,CAAC,KAIG;IAKzB,IAAI,QAAQ,IAAI,CAAC,CAEhB;IAED;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAIlD;;;OAGG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,MAAM,EAEvB;IAED,IAAI,UAAU,IAAI,SAAS,EAAE,CAO5B;IAED,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,OAAO,CAEjD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,KAAK,CAEjD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,IAAI,CAE/C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,OAAO,CAErD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,qBAAqB,CAErE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,QAAQ,CAEvD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,UAAU,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,UAAQ,GAAG,CAAC,CA4DvE"}
|
338
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/node.js
generated
vendored
Normal file
338
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/node.js
generated
vendored
Normal file
|
@ -0,0 +1,338 @@
|
||||||
|
import { ElementType, isTag as isTagRaw } from "domelementtype";
|
||||||
|
/**
|
||||||
|
* This object will be used as the prototype for Nodes when creating a
|
||||||
|
* DOM-Level-1-compliant structure.
|
||||||
|
*/
|
||||||
|
export class Node {
|
||||||
|
constructor() {
|
||||||
|
/** Parent of the node */
|
||||||
|
this.parent = null;
|
||||||
|
/** Previous sibling */
|
||||||
|
this.prev = null;
|
||||||
|
/** Next sibling */
|
||||||
|
this.next = null;
|
||||||
|
/** The start index of the node. Requires `withStartIndices` on the handler to be `true. */
|
||||||
|
this.startIndex = null;
|
||||||
|
/** The end index of the node. Requires `withEndIndices` on the handler to be `true. */
|
||||||
|
this.endIndex = null;
|
||||||
|
}
|
||||||
|
// Read-write aliases for properties
|
||||||
|
/**
|
||||||
|
* Same as {@link parent}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get parentNode() {
|
||||||
|
return this.parent;
|
||||||
|
}
|
||||||
|
set parentNode(parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Same as {@link prev}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get previousSibling() {
|
||||||
|
return this.prev;
|
||||||
|
}
|
||||||
|
set previousSibling(prev) {
|
||||||
|
this.prev = prev;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Same as {@link next}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get nextSibling() {
|
||||||
|
return this.next;
|
||||||
|
}
|
||||||
|
set nextSibling(next) {
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Clone this node, and optionally its children.
|
||||||
|
*
|
||||||
|
* @param recursive Clone child nodes as well.
|
||||||
|
* @returns A clone of the node.
|
||||||
|
*/
|
||||||
|
cloneNode(recursive = false) {
|
||||||
|
return cloneNode(this, recursive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A node that contains some data.
|
||||||
|
*/
|
||||||
|
export class DataNode extends Node {
|
||||||
|
/**
|
||||||
|
* @param data The content of the data node
|
||||||
|
*/
|
||||||
|
constructor(data) {
|
||||||
|
super();
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Same as {@link data}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get nodeValue() {
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
set nodeValue(data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Text within the document.
|
||||||
|
*/
|
||||||
|
export class Text extends DataNode {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.type = ElementType.Text;
|
||||||
|
}
|
||||||
|
get nodeType() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Comments within the document.
|
||||||
|
*/
|
||||||
|
export class Comment extends DataNode {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.type = ElementType.Comment;
|
||||||
|
}
|
||||||
|
get nodeType() {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Processing instructions, including doc types.
|
||||||
|
*/
|
||||||
|
export class ProcessingInstruction extends DataNode {
|
||||||
|
constructor(name, data) {
|
||||||
|
super(data);
|
||||||
|
this.name = name;
|
||||||
|
this.type = ElementType.Directive;
|
||||||
|
}
|
||||||
|
get nodeType() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A `Node` that can have children.
|
||||||
|
*/
|
||||||
|
export class NodeWithChildren extends Node {
|
||||||
|
/**
|
||||||
|
* @param children Children of the node. Only certain node types can have children.
|
||||||
|
*/
|
||||||
|
constructor(children) {
|
||||||
|
super();
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
// Aliases
|
||||||
|
/** First child of the node. */
|
||||||
|
get firstChild() {
|
||||||
|
var _a;
|
||||||
|
return (_a = this.children[0]) !== null && _a !== void 0 ? _a : null;
|
||||||
|
}
|
||||||
|
/** Last child of the node. */
|
||||||
|
get lastChild() {
|
||||||
|
return this.children.length > 0
|
||||||
|
? this.children[this.children.length - 1]
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Same as {@link children}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get childNodes() {
|
||||||
|
return this.children;
|
||||||
|
}
|
||||||
|
set childNodes(children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class CDATA extends NodeWithChildren {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.type = ElementType.CDATA;
|
||||||
|
}
|
||||||
|
get nodeType() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The root node of the document.
|
||||||
|
*/
|
||||||
|
export class Document extends NodeWithChildren {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.type = ElementType.Root;
|
||||||
|
}
|
||||||
|
get nodeType() {
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An element within the DOM.
|
||||||
|
*/
|
||||||
|
export class Element extends NodeWithChildren {
|
||||||
|
/**
|
||||||
|
* @param name Name of the tag, eg. `div`, `span`.
|
||||||
|
* @param attribs Object mapping attribute names to attribute values.
|
||||||
|
* @param children Children of the node.
|
||||||
|
*/
|
||||||
|
constructor(name, attribs, children = [], type = name === "script"
|
||||||
|
? ElementType.Script
|
||||||
|
: name === "style"
|
||||||
|
? ElementType.Style
|
||||||
|
: ElementType.Tag) {
|
||||||
|
super(children);
|
||||||
|
this.name = name;
|
||||||
|
this.attribs = attribs;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
get nodeType() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// DOM Level 1 aliases
|
||||||
|
/**
|
||||||
|
* Same as {@link name}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get tagName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
set tagName(name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
get attributes() {
|
||||||
|
return Object.keys(this.attribs).map((name) => {
|
||||||
|
var _a, _b;
|
||||||
|
return ({
|
||||||
|
name,
|
||||||
|
value: this.attribs[name],
|
||||||
|
namespace: (_a = this["x-attribsNamespace"]) === null || _a === void 0 ? void 0 : _a[name],
|
||||||
|
prefix: (_b = this["x-attribsPrefix"]) === null || _b === void 0 ? void 0 : _b[name],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node is a `Element`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export function isTag(node) {
|
||||||
|
return isTagRaw(node);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `CDATA`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export function isCDATA(node) {
|
||||||
|
return node.type === ElementType.CDATA;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `Text`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export function isText(node) {
|
||||||
|
return node.type === ElementType.Text;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `Comment`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export function isComment(node) {
|
||||||
|
return node.type === ElementType.Comment;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export function isDirective(node) {
|
||||||
|
return node.type === ElementType.Directive;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export function isDocument(node) {
|
||||||
|
return node.type === ElementType.Root;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has children, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export function hasChildren(node) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(node, "children");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Clone a node, and optionally its children.
|
||||||
|
*
|
||||||
|
* @param recursive Clone child nodes as well.
|
||||||
|
* @returns A clone of the node.
|
||||||
|
*/
|
||||||
|
export function cloneNode(node, recursive = false) {
|
||||||
|
let result;
|
||||||
|
if (isText(node)) {
|
||||||
|
result = new Text(node.data);
|
||||||
|
}
|
||||||
|
else if (isComment(node)) {
|
||||||
|
result = new Comment(node.data);
|
||||||
|
}
|
||||||
|
else if (isTag(node)) {
|
||||||
|
const children = recursive ? cloneChildren(node.children) : [];
|
||||||
|
const clone = new Element(node.name, { ...node.attribs }, children);
|
||||||
|
children.forEach((child) => (child.parent = clone));
|
||||||
|
if (node.namespace != null) {
|
||||||
|
clone.namespace = node.namespace;
|
||||||
|
}
|
||||||
|
if (node["x-attribsNamespace"]) {
|
||||||
|
clone["x-attribsNamespace"] = { ...node["x-attribsNamespace"] };
|
||||||
|
}
|
||||||
|
if (node["x-attribsPrefix"]) {
|
||||||
|
clone["x-attribsPrefix"] = { ...node["x-attribsPrefix"] };
|
||||||
|
}
|
||||||
|
result = clone;
|
||||||
|
}
|
||||||
|
else if (isCDATA(node)) {
|
||||||
|
const children = recursive ? cloneChildren(node.children) : [];
|
||||||
|
const clone = new CDATA(children);
|
||||||
|
children.forEach((child) => (child.parent = clone));
|
||||||
|
result = clone;
|
||||||
|
}
|
||||||
|
else if (isDocument(node)) {
|
||||||
|
const children = recursive ? cloneChildren(node.children) : [];
|
||||||
|
const clone = new Document(children);
|
||||||
|
children.forEach((child) => (child.parent = clone));
|
||||||
|
if (node["x-mode"]) {
|
||||||
|
clone["x-mode"] = node["x-mode"];
|
||||||
|
}
|
||||||
|
result = clone;
|
||||||
|
}
|
||||||
|
else if (isDirective(node)) {
|
||||||
|
const instruction = new ProcessingInstruction(node.name, node.data);
|
||||||
|
if (node["x-name"] != null) {
|
||||||
|
instruction["x-name"] = node["x-name"];
|
||||||
|
instruction["x-publicId"] = node["x-publicId"];
|
||||||
|
instruction["x-systemId"] = node["x-systemId"];
|
||||||
|
}
|
||||||
|
result = instruction;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error(`Not implemented yet: ${node.type}`);
|
||||||
|
}
|
||||||
|
result.startIndex = node.startIndex;
|
||||||
|
result.endIndex = node.endIndex;
|
||||||
|
if (node.sourceCodeLocation != null) {
|
||||||
|
result.sourceCodeLocation = node.sourceCodeLocation;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function cloneChildren(childs) {
|
||||||
|
const children = childs.map((child) => cloneNode(child, true));
|
||||||
|
for (let i = 1; i < children.length; i++) {
|
||||||
|
children[i].prev = children[i - 1];
|
||||||
|
children[i - 1].next = children[i];
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/package.json
generated
vendored
Normal file
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/esm/package.json
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"type":"module"}
|
76
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/index.d.ts
generated
vendored
Normal file
76
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/index.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import { ChildNode, Element, DataNode, Document, ParentNode } from "./node.js";
|
||||||
|
export * from "./node.js";
|
||||||
|
export interface DomHandlerOptions {
|
||||||
|
/**
|
||||||
|
* Add a `startIndex` property to nodes.
|
||||||
|
* When the parser is used in a non-streaming fashion, `startIndex` is an integer
|
||||||
|
* indicating the position of the start of the node in the document.
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
withStartIndices?: boolean;
|
||||||
|
/**
|
||||||
|
* Add an `endIndex` property to nodes.
|
||||||
|
* When the parser is used in a non-streaming fashion, `endIndex` is an integer
|
||||||
|
* indicating the position of the end of the node in the document.
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
withEndIndices?: boolean;
|
||||||
|
/**
|
||||||
|
* Treat the markup as XML.
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
xmlMode?: boolean;
|
||||||
|
}
|
||||||
|
interface ParserInterface {
|
||||||
|
startIndex: number | null;
|
||||||
|
endIndex: number | null;
|
||||||
|
}
|
||||||
|
declare type Callback = (error: Error | null, dom: ChildNode[]) => void;
|
||||||
|
declare type ElementCallback = (element: Element) => void;
|
||||||
|
export declare class DomHandler {
|
||||||
|
/** The elements of the DOM */
|
||||||
|
dom: ChildNode[];
|
||||||
|
/** The root element for the DOM */
|
||||||
|
root: Document;
|
||||||
|
/** Called once parsing has completed. */
|
||||||
|
private readonly callback;
|
||||||
|
/** Settings for the handler. */
|
||||||
|
private readonly options;
|
||||||
|
/** Callback whenever a tag is closed. */
|
||||||
|
private readonly elementCB;
|
||||||
|
/** Indicated whether parsing has been completed. */
|
||||||
|
private done;
|
||||||
|
/** Stack of open tags. */
|
||||||
|
protected tagStack: ParentNode[];
|
||||||
|
/** A data node that is still being written to. */
|
||||||
|
protected lastNode: DataNode | null;
|
||||||
|
/** Reference to the parser instance. Used for location information. */
|
||||||
|
private parser;
|
||||||
|
/**
|
||||||
|
* @param callback Called once parsing has completed.
|
||||||
|
* @param options Settings for the handler.
|
||||||
|
* @param elementCB Callback whenever a tag is closed.
|
||||||
|
*/
|
||||||
|
constructor(callback?: Callback | null, options?: DomHandlerOptions | null, elementCB?: ElementCallback);
|
||||||
|
onparserinit(parser: ParserInterface): void;
|
||||||
|
onreset(): void;
|
||||||
|
onend(): void;
|
||||||
|
onerror(error: Error): void;
|
||||||
|
onclosetag(): void;
|
||||||
|
onopentag(name: string, attribs: {
|
||||||
|
[key: string]: string;
|
||||||
|
}): void;
|
||||||
|
ontext(data: string): void;
|
||||||
|
oncomment(data: string): void;
|
||||||
|
oncommentend(): void;
|
||||||
|
oncdatastart(): void;
|
||||||
|
oncdataend(): void;
|
||||||
|
onprocessinginstruction(name: string, data: string): void;
|
||||||
|
protected handleCallback(error: Error | null): void;
|
||||||
|
protected addNode(node: ChildNode): void;
|
||||||
|
}
|
||||||
|
export default DomHandler;
|
||||||
|
//# sourceMappingURL=index.d.ts.map
|
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/index.d.ts.map
generated
vendored
Normal file
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/index.d.ts.map
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,SAAS,EACT,OAAO,EACP,QAAQ,EAIR,QAAQ,EAER,UAAU,EACb,MAAM,WAAW,CAAC;AAEnB,cAAc,WAAW,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IAC9B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AASD,UAAU,eAAe;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,aAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;AAChE,aAAK,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAElD,qBAAa,UAAU;IACnB,8BAA8B;IACvB,GAAG,EAAE,SAAS,EAAE,CAAM;IAE7B,mCAAmC;IAC5B,IAAI,WAA0B;IAErC,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAE3C,gCAAgC;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAE5C,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAEnD,oDAAoD;IACpD,OAAO,CAAC,IAAI,CAAS;IAErB,0BAA0B;IAC1B,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAe;IAE/C,kDAAkD;IAClD,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAE3C,uEAAuE;IACvE,OAAO,CAAC,MAAM,CAAgC;IAE9C;;;;OAIG;gBAEC,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,EAClC,SAAS,CAAC,EAAE,eAAe;IAiBxB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAK3C,OAAO,IAAI,IAAI;IAUf,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAI3B,UAAU,IAAI,IAAI;IAYlB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI;IAOjE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAe1B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAW7B,YAAY,IAAI,IAAI;IAIpB,YAAY,IAAI,IAAI;IAUpB,UAAU,IAAI,IAAI;IAIlB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKhE,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI;IAQnD,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;CAwB3C;AAED,eAAe,UAAU,CAAC"}
|
165
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/index.js
generated
vendored
Normal file
165
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/index.js
generated
vendored
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||||
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.DomHandler = void 0;
|
||||||
|
var domelementtype_1 = require("domelementtype");
|
||||||
|
var node_js_1 = require("./node.js");
|
||||||
|
__exportStar(require("./node.js"), exports);
|
||||||
|
// Default options
|
||||||
|
var defaultOpts = {
|
||||||
|
withStartIndices: false,
|
||||||
|
withEndIndices: false,
|
||||||
|
xmlMode: false,
|
||||||
|
};
|
||||||
|
var DomHandler = /** @class */ (function () {
|
||||||
|
/**
|
||||||
|
* @param callback Called once parsing has completed.
|
||||||
|
* @param options Settings for the handler.
|
||||||
|
* @param elementCB Callback whenever a tag is closed.
|
||||||
|
*/
|
||||||
|
function DomHandler(callback, options, elementCB) {
|
||||||
|
/** The elements of the DOM */
|
||||||
|
this.dom = [];
|
||||||
|
/** The root element for the DOM */
|
||||||
|
this.root = new node_js_1.Document(this.dom);
|
||||||
|
/** Indicated whether parsing has been completed. */
|
||||||
|
this.done = false;
|
||||||
|
/** Stack of open tags. */
|
||||||
|
this.tagStack = [this.root];
|
||||||
|
/** A data node that is still being written to. */
|
||||||
|
this.lastNode = null;
|
||||||
|
/** Reference to the parser instance. Used for location information. */
|
||||||
|
this.parser = null;
|
||||||
|
// Make it possible to skip arguments, for backwards-compatibility
|
||||||
|
if (typeof options === "function") {
|
||||||
|
elementCB = options;
|
||||||
|
options = defaultOpts;
|
||||||
|
}
|
||||||
|
if (typeof callback === "object") {
|
||||||
|
options = callback;
|
||||||
|
callback = undefined;
|
||||||
|
}
|
||||||
|
this.callback = callback !== null && callback !== void 0 ? callback : null;
|
||||||
|
this.options = options !== null && options !== void 0 ? options : defaultOpts;
|
||||||
|
this.elementCB = elementCB !== null && elementCB !== void 0 ? elementCB : null;
|
||||||
|
}
|
||||||
|
DomHandler.prototype.onparserinit = function (parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
};
|
||||||
|
// Resets the handler back to starting state
|
||||||
|
DomHandler.prototype.onreset = function () {
|
||||||
|
this.dom = [];
|
||||||
|
this.root = new node_js_1.Document(this.dom);
|
||||||
|
this.done = false;
|
||||||
|
this.tagStack = [this.root];
|
||||||
|
this.lastNode = null;
|
||||||
|
this.parser = null;
|
||||||
|
};
|
||||||
|
// Signals the handler that parsing is done
|
||||||
|
DomHandler.prototype.onend = function () {
|
||||||
|
if (this.done)
|
||||||
|
return;
|
||||||
|
this.done = true;
|
||||||
|
this.parser = null;
|
||||||
|
this.handleCallback(null);
|
||||||
|
};
|
||||||
|
DomHandler.prototype.onerror = function (error) {
|
||||||
|
this.handleCallback(error);
|
||||||
|
};
|
||||||
|
DomHandler.prototype.onclosetag = function () {
|
||||||
|
this.lastNode = null;
|
||||||
|
var elem = this.tagStack.pop();
|
||||||
|
if (this.options.withEndIndices) {
|
||||||
|
elem.endIndex = this.parser.endIndex;
|
||||||
|
}
|
||||||
|
if (this.elementCB)
|
||||||
|
this.elementCB(elem);
|
||||||
|
};
|
||||||
|
DomHandler.prototype.onopentag = function (name, attribs) {
|
||||||
|
var type = this.options.xmlMode ? domelementtype_1.ElementType.Tag : undefined;
|
||||||
|
var element = new node_js_1.Element(name, attribs, undefined, type);
|
||||||
|
this.addNode(element);
|
||||||
|
this.tagStack.push(element);
|
||||||
|
};
|
||||||
|
DomHandler.prototype.ontext = function (data) {
|
||||||
|
var lastNode = this.lastNode;
|
||||||
|
if (lastNode && lastNode.type === domelementtype_1.ElementType.Text) {
|
||||||
|
lastNode.data += data;
|
||||||
|
if (this.options.withEndIndices) {
|
||||||
|
lastNode.endIndex = this.parser.endIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var node = new node_js_1.Text(data);
|
||||||
|
this.addNode(node);
|
||||||
|
this.lastNode = node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DomHandler.prototype.oncomment = function (data) {
|
||||||
|
if (this.lastNode && this.lastNode.type === domelementtype_1.ElementType.Comment) {
|
||||||
|
this.lastNode.data += data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var node = new node_js_1.Comment(data);
|
||||||
|
this.addNode(node);
|
||||||
|
this.lastNode = node;
|
||||||
|
};
|
||||||
|
DomHandler.prototype.oncommentend = function () {
|
||||||
|
this.lastNode = null;
|
||||||
|
};
|
||||||
|
DomHandler.prototype.oncdatastart = function () {
|
||||||
|
var text = new node_js_1.Text("");
|
||||||
|
var node = new node_js_1.CDATA([text]);
|
||||||
|
this.addNode(node);
|
||||||
|
text.parent = node;
|
||||||
|
this.lastNode = text;
|
||||||
|
};
|
||||||
|
DomHandler.prototype.oncdataend = function () {
|
||||||
|
this.lastNode = null;
|
||||||
|
};
|
||||||
|
DomHandler.prototype.onprocessinginstruction = function (name, data) {
|
||||||
|
var node = new node_js_1.ProcessingInstruction(name, data);
|
||||||
|
this.addNode(node);
|
||||||
|
};
|
||||||
|
DomHandler.prototype.handleCallback = function (error) {
|
||||||
|
if (typeof this.callback === "function") {
|
||||||
|
this.callback(error, this.dom);
|
||||||
|
}
|
||||||
|
else if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DomHandler.prototype.addNode = function (node) {
|
||||||
|
var parent = this.tagStack[this.tagStack.length - 1];
|
||||||
|
var previousSibling = parent.children[parent.children.length - 1];
|
||||||
|
if (this.options.withStartIndices) {
|
||||||
|
node.startIndex = this.parser.startIndex;
|
||||||
|
}
|
||||||
|
if (this.options.withEndIndices) {
|
||||||
|
node.endIndex = this.parser.endIndex;
|
||||||
|
}
|
||||||
|
parent.children.push(node);
|
||||||
|
if (previousSibling) {
|
||||||
|
node.prev = previousSibling;
|
||||||
|
previousSibling.next = node;
|
||||||
|
}
|
||||||
|
node.parent = parent;
|
||||||
|
this.lastNode = null;
|
||||||
|
};
|
||||||
|
return DomHandler;
|
||||||
|
}());
|
||||||
|
exports.DomHandler = DomHandler;
|
||||||
|
exports.default = DomHandler;
|
245
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/node.d.ts
generated
vendored
Normal file
245
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/node.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
import { ElementType } from "domelementtype";
|
||||||
|
interface SourceCodeLocation {
|
||||||
|
/** One-based line index of the first character. */
|
||||||
|
startLine: number;
|
||||||
|
/** One-based column index of the first character. */
|
||||||
|
startCol: number;
|
||||||
|
/** Zero-based first character index. */
|
||||||
|
startOffset: number;
|
||||||
|
/** One-based line index of the last character. */
|
||||||
|
endLine: number;
|
||||||
|
/** One-based column index of the last character. Points directly *after* the last character. */
|
||||||
|
endCol: number;
|
||||||
|
/** Zero-based last character index. Points directly *after* the last character. */
|
||||||
|
endOffset: number;
|
||||||
|
}
|
||||||
|
interface TagSourceCodeLocation extends SourceCodeLocation {
|
||||||
|
startTag?: SourceCodeLocation;
|
||||||
|
endTag?: SourceCodeLocation;
|
||||||
|
}
|
||||||
|
export declare type ParentNode = Document | Element | CDATA;
|
||||||
|
export declare type ChildNode = Text | Comment | ProcessingInstruction | Element | CDATA | Document;
|
||||||
|
export declare type AnyNode = ParentNode | ChildNode;
|
||||||
|
/**
|
||||||
|
* This object will be used as the prototype for Nodes when creating a
|
||||||
|
* DOM-Level-1-compliant structure.
|
||||||
|
*/
|
||||||
|
export declare abstract class Node {
|
||||||
|
/** The type of the node. */
|
||||||
|
abstract readonly type: ElementType;
|
||||||
|
/** Parent of the node */
|
||||||
|
parent: ParentNode | null;
|
||||||
|
/** Previous sibling */
|
||||||
|
prev: ChildNode | null;
|
||||||
|
/** Next sibling */
|
||||||
|
next: ChildNode | null;
|
||||||
|
/** The start index of the node. Requires `withStartIndices` on the handler to be `true. */
|
||||||
|
startIndex: number | null;
|
||||||
|
/** The end index of the node. Requires `withEndIndices` on the handler to be `true. */
|
||||||
|
endIndex: number | null;
|
||||||
|
/**
|
||||||
|
* `parse5` source code location info.
|
||||||
|
*
|
||||||
|
* Available if parsing with parse5 and location info is enabled.
|
||||||
|
*/
|
||||||
|
sourceCodeLocation?: SourceCodeLocation | null;
|
||||||
|
/**
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org/#dom-node-nodetype)-compatible
|
||||||
|
* node {@link type}.
|
||||||
|
*/
|
||||||
|
abstract readonly nodeType: number;
|
||||||
|
/**
|
||||||
|
* Same as {@link parent}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get parentNode(): ParentNode | null;
|
||||||
|
set parentNode(parent: ParentNode | null);
|
||||||
|
/**
|
||||||
|
* Same as {@link prev}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get previousSibling(): ChildNode | null;
|
||||||
|
set previousSibling(prev: ChildNode | null);
|
||||||
|
/**
|
||||||
|
* Same as {@link next}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get nextSibling(): ChildNode | null;
|
||||||
|
set nextSibling(next: ChildNode | null);
|
||||||
|
/**
|
||||||
|
* Clone this node, and optionally its children.
|
||||||
|
*
|
||||||
|
* @param recursive Clone child nodes as well.
|
||||||
|
* @returns A clone of the node.
|
||||||
|
*/
|
||||||
|
cloneNode<T extends Node>(this: T, recursive?: boolean): T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A node that contains some data.
|
||||||
|
*/
|
||||||
|
export declare abstract class DataNode extends Node {
|
||||||
|
data: string;
|
||||||
|
/**
|
||||||
|
* @param data The content of the data node
|
||||||
|
*/
|
||||||
|
constructor(data: string);
|
||||||
|
/**
|
||||||
|
* Same as {@link data}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get nodeValue(): string;
|
||||||
|
set nodeValue(data: string);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Text within the document.
|
||||||
|
*/
|
||||||
|
export declare class Text extends DataNode {
|
||||||
|
type: ElementType.Text;
|
||||||
|
get nodeType(): 3;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Comments within the document.
|
||||||
|
*/
|
||||||
|
export declare class Comment extends DataNode {
|
||||||
|
type: ElementType.Comment;
|
||||||
|
get nodeType(): 8;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Processing instructions, including doc types.
|
||||||
|
*/
|
||||||
|
export declare class ProcessingInstruction extends DataNode {
|
||||||
|
name: string;
|
||||||
|
type: ElementType.Directive;
|
||||||
|
constructor(name: string, data: string);
|
||||||
|
get nodeType(): 1;
|
||||||
|
/** If this is a doctype, the document type name (parse5 only). */
|
||||||
|
"x-name"?: string;
|
||||||
|
/** If this is a doctype, the document type public identifier (parse5 only). */
|
||||||
|
"x-publicId"?: string;
|
||||||
|
/** If this is a doctype, the document type system identifier (parse5 only). */
|
||||||
|
"x-systemId"?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A `Node` that can have children.
|
||||||
|
*/
|
||||||
|
export declare abstract class NodeWithChildren extends Node {
|
||||||
|
children: ChildNode[];
|
||||||
|
/**
|
||||||
|
* @param children Children of the node. Only certain node types can have children.
|
||||||
|
*/
|
||||||
|
constructor(children: ChildNode[]);
|
||||||
|
/** First child of the node. */
|
||||||
|
get firstChild(): ChildNode | null;
|
||||||
|
/** Last child of the node. */
|
||||||
|
get lastChild(): ChildNode | null;
|
||||||
|
/**
|
||||||
|
* Same as {@link children}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get childNodes(): ChildNode[];
|
||||||
|
set childNodes(children: ChildNode[]);
|
||||||
|
}
|
||||||
|
export declare class CDATA extends NodeWithChildren {
|
||||||
|
type: ElementType.CDATA;
|
||||||
|
get nodeType(): 4;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The root node of the document.
|
||||||
|
*/
|
||||||
|
export declare class Document extends NodeWithChildren {
|
||||||
|
type: ElementType.Root;
|
||||||
|
get nodeType(): 9;
|
||||||
|
/** [Document mode](https://dom.spec.whatwg.org/#concept-document-limited-quirks) (parse5 only). */
|
||||||
|
"x-mode"?: "no-quirks" | "quirks" | "limited-quirks";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The description of an individual attribute.
|
||||||
|
*/
|
||||||
|
interface Attribute {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
namespace?: string;
|
||||||
|
prefix?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An element within the DOM.
|
||||||
|
*/
|
||||||
|
export declare class Element extends NodeWithChildren {
|
||||||
|
name: string;
|
||||||
|
attribs: {
|
||||||
|
[name: string]: string;
|
||||||
|
};
|
||||||
|
type: ElementType.Tag | ElementType.Script | ElementType.Style;
|
||||||
|
/**
|
||||||
|
* @param name Name of the tag, eg. `div`, `span`.
|
||||||
|
* @param attribs Object mapping attribute names to attribute values.
|
||||||
|
* @param children Children of the node.
|
||||||
|
*/
|
||||||
|
constructor(name: string, attribs: {
|
||||||
|
[name: string]: string;
|
||||||
|
}, children?: ChildNode[], type?: ElementType.Tag | ElementType.Script | ElementType.Style);
|
||||||
|
get nodeType(): 1;
|
||||||
|
/**
|
||||||
|
* `parse5` source code location info, with start & end tags.
|
||||||
|
*
|
||||||
|
* Available if parsing with parse5 and location info is enabled.
|
||||||
|
*/
|
||||||
|
sourceCodeLocation?: TagSourceCodeLocation | null;
|
||||||
|
/**
|
||||||
|
* Same as {@link name}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get tagName(): string;
|
||||||
|
set tagName(name: string);
|
||||||
|
get attributes(): Attribute[];
|
||||||
|
/** Element namespace (parse5 only). */
|
||||||
|
namespace?: string;
|
||||||
|
/** Element attribute namespaces (parse5 only). */
|
||||||
|
"x-attribsNamespace"?: Record<string, string>;
|
||||||
|
/** Element attribute namespace-related prefixes (parse5 only). */
|
||||||
|
"x-attribsPrefix"?: Record<string, string>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node is a `Element`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isTag(node: Node): node is Element;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `CDATA`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isCDATA(node: Node): node is CDATA;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `Text`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isText(node: Node): node is Text;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `Comment`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isComment(node: Node): node is Comment;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isDirective(node: Node): node is ProcessingInstruction;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function isDocument(node: Node): node is Document;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has children, `false` otherwise.
|
||||||
|
*/
|
||||||
|
export declare function hasChildren(node: Node): node is ParentNode;
|
||||||
|
/**
|
||||||
|
* Clone a node, and optionally its children.
|
||||||
|
*
|
||||||
|
* @param recursive Clone child nodes as well.
|
||||||
|
* @returns A clone of the node.
|
||||||
|
*/
|
||||||
|
export declare function cloneNode<T extends Node>(node: T, recursive?: boolean): T;
|
||||||
|
export {};
|
||||||
|
//# sourceMappingURL=node.d.ts.map
|
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/node.d.ts.map
generated
vendored
Normal file
1
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/node.d.ts.map
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAqB,MAAM,gBAAgB,CAAC;AAEhE,UAAU,kBAAkB;IACxB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,MAAM,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,qBAAsB,SAAQ,kBAAkB;IACtD,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED,oBAAY,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;AACpD,oBAAY,SAAS,GACf,IAAI,GACJ,OAAO,GACP,qBAAqB,GACrB,OAAO,GACP,KAAK,GAEL,QAAQ,CAAC;AACf,oBAAY,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAE7C;;;GAGG;AACH,8BAAsB,IAAI;IACtB,4BAA4B;IAC5B,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAEpC,yBAAyB;IACzB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAQ;IAEjC,uBAAuB;IACvB,IAAI,EAAE,SAAS,GAAG,IAAI,CAAQ;IAE9B,mBAAmB;IACnB,IAAI,EAAE,SAAS,GAAG,IAAI,CAAQ;IAE9B,2FAA2F;IAC3F,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC,uFAAuF;IACvF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAI/C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAInC;;;OAGG;IACH,IAAI,UAAU,IAAI,UAAU,GAAG,IAAI,CAElC;IAED,IAAI,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAEvC;IAED;;;OAGG;IACH,IAAI,eAAe,IAAI,SAAS,GAAG,IAAI,CAEtC;IAED,IAAI,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,EAEzC;IAED;;;OAGG;IACH,IAAI,WAAW,IAAI,SAAS,GAAG,IAAI,CAElC;IAED,IAAI,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,EAErC;IAED;;;;;OAKG;IACH,SAAS,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,UAAQ,GAAG,CAAC;CAG3D;AAED;;GAEG;AACH,8BAAsB,QAAS,SAAQ,IAAI;IAIpB,IAAI,EAAE,MAAM;IAH/B;;OAEG;gBACgB,IAAI,EAAE,MAAM;IAI/B;;;OAGG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,SAAS,CAAC,IAAI,EAAE,MAAM,EAEzB;CACJ;AAED;;GAEG;AACH,qBAAa,IAAK,SAAQ,QAAQ;IAC9B,IAAI,EAAE,WAAW,CAAC,IAAI,CAAoB;IAE1C,IAAI,QAAQ,IAAI,CAAC,CAEhB;CACJ;AAED;;GAEG;AACH,qBAAa,OAAQ,SAAQ,QAAQ;IACjC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAuB;IAEhD,IAAI,QAAQ,IAAI,CAAC,CAEhB;CACJ;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,QAAQ;IAG5B,IAAI,EAAE,MAAM;IAF/B,IAAI,EAAE,WAAW,CAAC,SAAS,CAAyB;gBAEjC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAI7C,IAAa,QAAQ,IAAI,CAAC,CAEzB;IAED,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,8BAAsB,gBAAiB,SAAQ,IAAI;IAI5B,QAAQ,EAAE,SAAS,EAAE;IAHxC;;OAEG;gBACgB,QAAQ,EAAE,SAAS,EAAE;IAKxC,+BAA+B;IAC/B,IAAI,UAAU,IAAI,SAAS,GAAG,IAAI,CAEjC;IAED,8BAA8B;IAC9B,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,CAIhC;IAED;;;OAGG;IACH,IAAI,UAAU,IAAI,SAAS,EAAE,CAE5B;IAED,IAAI,UAAU,CAAC,QAAQ,EAAE,SAAS,EAAE,EAEnC;CACJ;AAED,qBAAa,KAAM,SAAQ,gBAAgB;IACvC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAqB;IAE5C,IAAI,QAAQ,IAAI,CAAC,CAEhB;CACJ;AAED;;GAEG;AACH,qBAAa,QAAS,SAAQ,gBAAgB;IAC1C,IAAI,EAAE,WAAW,CAAC,IAAI,CAAoB;IAE1C,IAAI,QAAQ,IAAI,CAAC,CAEhB;IAED,mGAAmG;IACnG,QAAQ,CAAC,EAAE,WAAW,GAAG,QAAQ,GAAG,gBAAgB,CAAC;CACxD;AAED;;GAEG;AACH,UAAU,SAAS;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,OAAQ,SAAQ,gBAAgB;IAO9B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE;IAEnC,IAAI,EACL,WAAW,CAAC,GAAG,GACf,WAAW,CAAC,MAAM,GAClB,WAAW,CAAC,KAAK;IAZ3B;;;;OAIG;gBAEQ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,EAC1C,QAAQ,GAAE,SAAS,EAAO,EACnB,IAAI,GACL,WAAW,CAAC,GAAG,GACf,WAAW,CAAC,MAAM,GAClB,WAAW,CAAC,KAIG;IAKzB,IAAI,QAAQ,IAAI,CAAC,CAEhB;IAED;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAIlD;;;OAGG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,MAAM,EAEvB;IAED,IAAI,UAAU,IAAI,SAAS,EAAE,CAO5B;IAED,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,OAAO,CAEjD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,KAAK,CAEjD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,IAAI,CAE/C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,OAAO,CAErD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,qBAAqB,CAErE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,QAAQ,CAEvD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,UAAU,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,UAAQ,GAAG,CAAC,CA4DvE"}
|
474
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/node.js
generated
vendored
Normal file
474
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/lib/node.js
generated
vendored
Normal file
|
@ -0,0 +1,474 @@
|
||||||
|
"use strict";
|
||||||
|
var __extends = (this && this.__extends) || (function () {
|
||||||
|
var extendStatics = function (d, b) {
|
||||||
|
extendStatics = Object.setPrototypeOf ||
|
||||||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||||
|
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||||||
|
return extendStatics(d, b);
|
||||||
|
};
|
||||||
|
return function (d, b) {
|
||||||
|
if (typeof b !== "function" && b !== null)
|
||||||
|
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
||||||
|
extendStatics(d, b);
|
||||||
|
function __() { this.constructor = d; }
|
||||||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
var __assign = (this && this.__assign) || function () {
|
||||||
|
__assign = Object.assign || function(t) {
|
||||||
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||||
|
s = arguments[i];
|
||||||
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||||
|
t[p] = s[p];
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
};
|
||||||
|
return __assign.apply(this, arguments);
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.cloneNode = exports.hasChildren = exports.isDocument = exports.isDirective = exports.isComment = exports.isText = exports.isCDATA = exports.isTag = exports.Element = exports.Document = exports.CDATA = exports.NodeWithChildren = exports.ProcessingInstruction = exports.Comment = exports.Text = exports.DataNode = exports.Node = void 0;
|
||||||
|
var domelementtype_1 = require("domelementtype");
|
||||||
|
/**
|
||||||
|
* This object will be used as the prototype for Nodes when creating a
|
||||||
|
* DOM-Level-1-compliant structure.
|
||||||
|
*/
|
||||||
|
var Node = /** @class */ (function () {
|
||||||
|
function Node() {
|
||||||
|
/** Parent of the node */
|
||||||
|
this.parent = null;
|
||||||
|
/** Previous sibling */
|
||||||
|
this.prev = null;
|
||||||
|
/** Next sibling */
|
||||||
|
this.next = null;
|
||||||
|
/** The start index of the node. Requires `withStartIndices` on the handler to be `true. */
|
||||||
|
this.startIndex = null;
|
||||||
|
/** The end index of the node. Requires `withEndIndices` on the handler to be `true. */
|
||||||
|
this.endIndex = null;
|
||||||
|
}
|
||||||
|
Object.defineProperty(Node.prototype, "parentNode", {
|
||||||
|
// Read-write aliases for properties
|
||||||
|
/**
|
||||||
|
* Same as {@link parent}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get: function () {
|
||||||
|
return this.parent;
|
||||||
|
},
|
||||||
|
set: function (parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(Node.prototype, "previousSibling", {
|
||||||
|
/**
|
||||||
|
* Same as {@link prev}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get: function () {
|
||||||
|
return this.prev;
|
||||||
|
},
|
||||||
|
set: function (prev) {
|
||||||
|
this.prev = prev;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(Node.prototype, "nextSibling", {
|
||||||
|
/**
|
||||||
|
* Same as {@link next}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get: function () {
|
||||||
|
return this.next;
|
||||||
|
},
|
||||||
|
set: function (next) {
|
||||||
|
this.next = next;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* Clone this node, and optionally its children.
|
||||||
|
*
|
||||||
|
* @param recursive Clone child nodes as well.
|
||||||
|
* @returns A clone of the node.
|
||||||
|
*/
|
||||||
|
Node.prototype.cloneNode = function (recursive) {
|
||||||
|
if (recursive === void 0) { recursive = false; }
|
||||||
|
return cloneNode(this, recursive);
|
||||||
|
};
|
||||||
|
return Node;
|
||||||
|
}());
|
||||||
|
exports.Node = Node;
|
||||||
|
/**
|
||||||
|
* A node that contains some data.
|
||||||
|
*/
|
||||||
|
var DataNode = /** @class */ (function (_super) {
|
||||||
|
__extends(DataNode, _super);
|
||||||
|
/**
|
||||||
|
* @param data The content of the data node
|
||||||
|
*/
|
||||||
|
function DataNode(data) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
_this.data = data;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(DataNode.prototype, "nodeValue", {
|
||||||
|
/**
|
||||||
|
* Same as {@link data}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get: function () {
|
||||||
|
return this.data;
|
||||||
|
},
|
||||||
|
set: function (data) {
|
||||||
|
this.data = data;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return DataNode;
|
||||||
|
}(Node));
|
||||||
|
exports.DataNode = DataNode;
|
||||||
|
/**
|
||||||
|
* Text within the document.
|
||||||
|
*/
|
||||||
|
var Text = /** @class */ (function (_super) {
|
||||||
|
__extends(Text, _super);
|
||||||
|
function Text() {
|
||||||
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
_this.type = domelementtype_1.ElementType.Text;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(Text.prototype, "nodeType", {
|
||||||
|
get: function () {
|
||||||
|
return 3;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return Text;
|
||||||
|
}(DataNode));
|
||||||
|
exports.Text = Text;
|
||||||
|
/**
|
||||||
|
* Comments within the document.
|
||||||
|
*/
|
||||||
|
var Comment = /** @class */ (function (_super) {
|
||||||
|
__extends(Comment, _super);
|
||||||
|
function Comment() {
|
||||||
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
_this.type = domelementtype_1.ElementType.Comment;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(Comment.prototype, "nodeType", {
|
||||||
|
get: function () {
|
||||||
|
return 8;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return Comment;
|
||||||
|
}(DataNode));
|
||||||
|
exports.Comment = Comment;
|
||||||
|
/**
|
||||||
|
* Processing instructions, including doc types.
|
||||||
|
*/
|
||||||
|
var ProcessingInstruction = /** @class */ (function (_super) {
|
||||||
|
__extends(ProcessingInstruction, _super);
|
||||||
|
function ProcessingInstruction(name, data) {
|
||||||
|
var _this = _super.call(this, data) || this;
|
||||||
|
_this.name = name;
|
||||||
|
_this.type = domelementtype_1.ElementType.Directive;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(ProcessingInstruction.prototype, "nodeType", {
|
||||||
|
get: function () {
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return ProcessingInstruction;
|
||||||
|
}(DataNode));
|
||||||
|
exports.ProcessingInstruction = ProcessingInstruction;
|
||||||
|
/**
|
||||||
|
* A `Node` that can have children.
|
||||||
|
*/
|
||||||
|
var NodeWithChildren = /** @class */ (function (_super) {
|
||||||
|
__extends(NodeWithChildren, _super);
|
||||||
|
/**
|
||||||
|
* @param children Children of the node. Only certain node types can have children.
|
||||||
|
*/
|
||||||
|
function NodeWithChildren(children) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
_this.children = children;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(NodeWithChildren.prototype, "firstChild", {
|
||||||
|
// Aliases
|
||||||
|
/** First child of the node. */
|
||||||
|
get: function () {
|
||||||
|
var _a;
|
||||||
|
return (_a = this.children[0]) !== null && _a !== void 0 ? _a : null;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(NodeWithChildren.prototype, "lastChild", {
|
||||||
|
/** Last child of the node. */
|
||||||
|
get: function () {
|
||||||
|
return this.children.length > 0
|
||||||
|
? this.children[this.children.length - 1]
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(NodeWithChildren.prototype, "childNodes", {
|
||||||
|
/**
|
||||||
|
* Same as {@link children}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get: function () {
|
||||||
|
return this.children;
|
||||||
|
},
|
||||||
|
set: function (children) {
|
||||||
|
this.children = children;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return NodeWithChildren;
|
||||||
|
}(Node));
|
||||||
|
exports.NodeWithChildren = NodeWithChildren;
|
||||||
|
var CDATA = /** @class */ (function (_super) {
|
||||||
|
__extends(CDATA, _super);
|
||||||
|
function CDATA() {
|
||||||
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
_this.type = domelementtype_1.ElementType.CDATA;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(CDATA.prototype, "nodeType", {
|
||||||
|
get: function () {
|
||||||
|
return 4;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return CDATA;
|
||||||
|
}(NodeWithChildren));
|
||||||
|
exports.CDATA = CDATA;
|
||||||
|
/**
|
||||||
|
* The root node of the document.
|
||||||
|
*/
|
||||||
|
var Document = /** @class */ (function (_super) {
|
||||||
|
__extends(Document, _super);
|
||||||
|
function Document() {
|
||||||
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
_this.type = domelementtype_1.ElementType.Root;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(Document.prototype, "nodeType", {
|
||||||
|
get: function () {
|
||||||
|
return 9;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return Document;
|
||||||
|
}(NodeWithChildren));
|
||||||
|
exports.Document = Document;
|
||||||
|
/**
|
||||||
|
* An element within the DOM.
|
||||||
|
*/
|
||||||
|
var Element = /** @class */ (function (_super) {
|
||||||
|
__extends(Element, _super);
|
||||||
|
/**
|
||||||
|
* @param name Name of the tag, eg. `div`, `span`.
|
||||||
|
* @param attribs Object mapping attribute names to attribute values.
|
||||||
|
* @param children Children of the node.
|
||||||
|
*/
|
||||||
|
function Element(name, attribs, children, type) {
|
||||||
|
if (children === void 0) { children = []; }
|
||||||
|
if (type === void 0) { type = name === "script"
|
||||||
|
? domelementtype_1.ElementType.Script
|
||||||
|
: name === "style"
|
||||||
|
? domelementtype_1.ElementType.Style
|
||||||
|
: domelementtype_1.ElementType.Tag; }
|
||||||
|
var _this = _super.call(this, children) || this;
|
||||||
|
_this.name = name;
|
||||||
|
_this.attribs = attribs;
|
||||||
|
_this.type = type;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(Element.prototype, "nodeType", {
|
||||||
|
get: function () {
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(Element.prototype, "tagName", {
|
||||||
|
// DOM Level 1 aliases
|
||||||
|
/**
|
||||||
|
* Same as {@link name}.
|
||||||
|
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
|
||||||
|
*/
|
||||||
|
get: function () {
|
||||||
|
return this.name;
|
||||||
|
},
|
||||||
|
set: function (name) {
|
||||||
|
this.name = name;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(Element.prototype, "attributes", {
|
||||||
|
get: function () {
|
||||||
|
var _this = this;
|
||||||
|
return Object.keys(this.attribs).map(function (name) {
|
||||||
|
var _a, _b;
|
||||||
|
return ({
|
||||||
|
name: name,
|
||||||
|
value: _this.attribs[name],
|
||||||
|
namespace: (_a = _this["x-attribsNamespace"]) === null || _a === void 0 ? void 0 : _a[name],
|
||||||
|
prefix: (_b = _this["x-attribsPrefix"]) === null || _b === void 0 ? void 0 : _b[name],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return Element;
|
||||||
|
}(NodeWithChildren));
|
||||||
|
exports.Element = Element;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node is a `Element`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function isTag(node) {
|
||||||
|
return (0, domelementtype_1.isTag)(node);
|
||||||
|
}
|
||||||
|
exports.isTag = isTag;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `CDATA`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function isCDATA(node) {
|
||||||
|
return node.type === domelementtype_1.ElementType.CDATA;
|
||||||
|
}
|
||||||
|
exports.isCDATA = isCDATA;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `Text`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function isText(node) {
|
||||||
|
return node.type === domelementtype_1.ElementType.Text;
|
||||||
|
}
|
||||||
|
exports.isText = isText;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `Comment`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function isComment(node) {
|
||||||
|
return node.type === domelementtype_1.ElementType.Comment;
|
||||||
|
}
|
||||||
|
exports.isComment = isComment;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function isDirective(node) {
|
||||||
|
return node.type === domelementtype_1.ElementType.Directive;
|
||||||
|
}
|
||||||
|
exports.isDirective = isDirective;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function isDocument(node) {
|
||||||
|
return node.type === domelementtype_1.ElementType.Root;
|
||||||
|
}
|
||||||
|
exports.isDocument = isDocument;
|
||||||
|
/**
|
||||||
|
* @param node Node to check.
|
||||||
|
* @returns `true` if the node has children, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function hasChildren(node) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(node, "children");
|
||||||
|
}
|
||||||
|
exports.hasChildren = hasChildren;
|
||||||
|
/**
|
||||||
|
* Clone a node, and optionally its children.
|
||||||
|
*
|
||||||
|
* @param recursive Clone child nodes as well.
|
||||||
|
* @returns A clone of the node.
|
||||||
|
*/
|
||||||
|
function cloneNode(node, recursive) {
|
||||||
|
if (recursive === void 0) { recursive = false; }
|
||||||
|
var result;
|
||||||
|
if (isText(node)) {
|
||||||
|
result = new Text(node.data);
|
||||||
|
}
|
||||||
|
else if (isComment(node)) {
|
||||||
|
result = new Comment(node.data);
|
||||||
|
}
|
||||||
|
else if (isTag(node)) {
|
||||||
|
var children = recursive ? cloneChildren(node.children) : [];
|
||||||
|
var clone_1 = new Element(node.name, __assign({}, node.attribs), children);
|
||||||
|
children.forEach(function (child) { return (child.parent = clone_1); });
|
||||||
|
if (node.namespace != null) {
|
||||||
|
clone_1.namespace = node.namespace;
|
||||||
|
}
|
||||||
|
if (node["x-attribsNamespace"]) {
|
||||||
|
clone_1["x-attribsNamespace"] = __assign({}, node["x-attribsNamespace"]);
|
||||||
|
}
|
||||||
|
if (node["x-attribsPrefix"]) {
|
||||||
|
clone_1["x-attribsPrefix"] = __assign({}, node["x-attribsPrefix"]);
|
||||||
|
}
|
||||||
|
result = clone_1;
|
||||||
|
}
|
||||||
|
else if (isCDATA(node)) {
|
||||||
|
var children = recursive ? cloneChildren(node.children) : [];
|
||||||
|
var clone_2 = new CDATA(children);
|
||||||
|
children.forEach(function (child) { return (child.parent = clone_2); });
|
||||||
|
result = clone_2;
|
||||||
|
}
|
||||||
|
else if (isDocument(node)) {
|
||||||
|
var children = recursive ? cloneChildren(node.children) : [];
|
||||||
|
var clone_3 = new Document(children);
|
||||||
|
children.forEach(function (child) { return (child.parent = clone_3); });
|
||||||
|
if (node["x-mode"]) {
|
||||||
|
clone_3["x-mode"] = node["x-mode"];
|
||||||
|
}
|
||||||
|
result = clone_3;
|
||||||
|
}
|
||||||
|
else if (isDirective(node)) {
|
||||||
|
var instruction = new ProcessingInstruction(node.name, node.data);
|
||||||
|
if (node["x-name"] != null) {
|
||||||
|
instruction["x-name"] = node["x-name"];
|
||||||
|
instruction["x-publicId"] = node["x-publicId"];
|
||||||
|
instruction["x-systemId"] = node["x-systemId"];
|
||||||
|
}
|
||||||
|
result = instruction;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("Not implemented yet: ".concat(node.type));
|
||||||
|
}
|
||||||
|
result.startIndex = node.startIndex;
|
||||||
|
result.endIndex = node.endIndex;
|
||||||
|
if (node.sourceCodeLocation != null) {
|
||||||
|
result.sourceCodeLocation = node.sourceCodeLocation;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
exports.cloneNode = cloneNode;
|
||||||
|
function cloneChildren(childs) {
|
||||||
|
var children = childs.map(function (child) { return cloneNode(child, true); });
|
||||||
|
for (var i = 1; i < children.length; i++) {
|
||||||
|
children[i].prev = children[i - 1];
|
||||||
|
children[i - 1].next = children[i];
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
73
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/package.json
generated
vendored
Normal file
73
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/package.json
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"name": "domhandler",
|
||||||
|
"version": "5.0.3",
|
||||||
|
"description": "Handler for htmlparser2 that turns pages into a dom",
|
||||||
|
"author": "Felix Boehm <me@feedic.com>",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
|
},
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"types": "lib/index.d.ts",
|
||||||
|
"module": "lib/esm/index.js",
|
||||||
|
"exports": {
|
||||||
|
"require": "./lib/index.js",
|
||||||
|
"import": "./lib/esm/index.js"
|
||||||
|
},
|
||||||
|
"sideEffects": false,
|
||||||
|
"files": [
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "npm run test:jest && npm run lint",
|
||||||
|
"test:jest": "jest",
|
||||||
|
"lint": "npm run lint:es && npm run lint:prettier",
|
||||||
|
"lint:es": "eslint --ignore-path .gitignore .",
|
||||||
|
"lint:prettier": "npm run prettier -- --check",
|
||||||
|
"format": "npm run format:es && npm run format:prettier",
|
||||||
|
"format:es": "npm run lint:es -- --fix",
|
||||||
|
"format:prettier": "npm run prettier -- --write",
|
||||||
|
"prettier": "prettier \"**/*.{ts,md,json,yml}\" --ignore-path .gitignore",
|
||||||
|
"build": "npm run build:cjs && npm run build:esm",
|
||||||
|
"build:cjs": "tsc",
|
||||||
|
"build:esm": "tsc --module esnext --target es2019 --outDir lib/esm && echo '{\"type\":\"module\"}' > lib/esm/package.json",
|
||||||
|
"prepare": "npm run build"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/fb55/domhandler.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"dom",
|
||||||
|
"htmlparser2"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^27.4.1",
|
||||||
|
"@types/node": "^17.0.30",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.21.0",
|
||||||
|
"@typescript-eslint/parser": "^5.21.0",
|
||||||
|
"eslint": "^8.14.0",
|
||||||
|
"eslint-config-prettier": "^8.5.0",
|
||||||
|
"htmlparser2": "^8.0.0",
|
||||||
|
"jest": "^27.5.1",
|
||||||
|
"prettier": "^2.6.2",
|
||||||
|
"ts-jest": "^27.1.4",
|
||||||
|
"typescript": "^4.6.4"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"preset": "ts-jest",
|
||||||
|
"testEnvironment": "node",
|
||||||
|
"moduleNameMapper": {
|
||||||
|
"^(.*)\\.js$": "$1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"tabWidth": 4
|
||||||
|
}
|
||||||
|
}
|
92
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/readme.md
generated
vendored
Normal file
92
node_modules/@selderee/plugin-htmlparser2/node_modules/domhandler/readme.md
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
# domhandler [![Build Status](https://travis-ci.com/fb55/domhandler.svg?branch=master)](https://travis-ci.com/fb55/domhandler)
|
||||||
|
|
||||||
|
The DOM handler creates a tree containing all nodes of a page.
|
||||||
|
The tree can be manipulated using the [domutils](https://github.com/fb55/domutils)
|
||||||
|
or [cheerio](https://github.com/cheeriojs/cheerio) libraries and
|
||||||
|
rendered using [dom-serializer](https://github.com/cheeriojs/dom-serializer) .
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const handler = new DomHandler([ <func> callback(err, dom), ] [ <obj> options ]);
|
||||||
|
// const parser = new Parser(handler[, options]);
|
||||||
|
```
|
||||||
|
|
||||||
|
Available options are described below.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const { Parser } = require("htmlparser2");
|
||||||
|
const { DomHandler } = require("domhandler");
|
||||||
|
const rawHtml =
|
||||||
|
"Xyz <script language= javascript>var foo = '<<bar>>';</script><!--<!-- Waah! -- -->";
|
||||||
|
const handler = new DomHandler((error, dom) => {
|
||||||
|
if (error) {
|
||||||
|
// Handle error
|
||||||
|
} else {
|
||||||
|
// Parsing completed, do something
|
||||||
|
console.log(dom);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const parser = new Parser(handler);
|
||||||
|
parser.write(rawHtml);
|
||||||
|
parser.end();
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
[
|
||||||
|
{
|
||||||
|
data: "Xyz ",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "script",
|
||||||
|
name: "script",
|
||||||
|
attribs: {
|
||||||
|
language: "javascript",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
data: "var foo = '<bar>';<",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: "<!-- Waah! -- ",
|
||||||
|
type: "comment",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
## Option: `withStartIndices`
|
||||||
|
|
||||||
|
Add a `startIndex` property to nodes.
|
||||||
|
When the parser is used in a non-streaming fashion, `startIndex` is an integer
|
||||||
|
indicating the position of the start of the node in the document.
|
||||||
|
The default value is `false`.
|
||||||
|
|
||||||
|
## Option: `withEndIndices`
|
||||||
|
|
||||||
|
Add an `endIndex` property to nodes.
|
||||||
|
When the parser is used in a non-streaming fashion, `endIndex` is an integer
|
||||||
|
indicating the position of the end of the node in the document.
|
||||||
|
The default value is `false`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
License: BSD-2-Clause
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## `domhandler` for enterprise
|
||||||
|
|
||||||
|
Available as part of the Tidelift Subscription
|
||||||
|
|
||||||
|
The maintainers of `domhandler` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-domhandler?utm_source=npm-domhandler&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"name": "@selderee/plugin-htmlparser2",
|
||||||
|
"version": "0.11.0",
|
||||||
|
"description": "selderee plugin - selectors decision tree builder for htmlparser2 DOM.",
|
||||||
|
"keywords": [
|
||||||
|
"htmlparser2",
|
||||||
|
"selderee",
|
||||||
|
"plugin",
|
||||||
|
"selderee plugin"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/mxxii/selderee.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/mxxii/selderee/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/mxxii/selderee",
|
||||||
|
"author": "KillyMXI",
|
||||||
|
"funding": "https://ko-fi.com/killymxi",
|
||||||
|
"license": "MIT",
|
||||||
|
"exports": {
|
||||||
|
"import": "./lib/hp2-builder.mjs",
|
||||||
|
"require": "./lib/hp2-builder.cjs"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "./lib/hp2-builder.cjs",
|
||||||
|
"module": "./lib/hp2-builder.mjs",
|
||||||
|
"types": "./lib/hp2-builder.d.ts",
|
||||||
|
"typedocMain": "./src/hp2-builder.ts",
|
||||||
|
"files": [
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build:rollup": "rollup -c",
|
||||||
|
"build:types": "tsc -d --emitDeclarationOnly --declarationDir ./lib",
|
||||||
|
"build": "npm run clean && npm run build:rollup && npm run build:types",
|
||||||
|
"clean": "rimraf lib"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"selderee": "^0.11.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"htmlparser2": "^8.0.1"
|
||||||
|
}
|
||||||
|
}
|
42
node_modules/promise-ftp/node_modules/bluebird/LICENSE → node_modules/base64-js/LICENSE
generated
vendored
42
node_modules/promise-ftp/node_modules/bluebird/LICENSE → node_modules/base64-js/LICENSE
generated
vendored
|
@ -1,21 +1,21 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2013-2015 Petka Antonov
|
Copyright (c) 2014 Jameson Little
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
|
@ -0,0 +1,34 @@
|
||||||
|
base64-js
|
||||||
|
=========
|
||||||
|
|
||||||
|
`base64-js` does basic base64 encoding/decoding in pure JS.
|
||||||
|
|
||||||
|
[![build status](https://secure.travis-ci.org/beatgammit/base64-js.png)](http://travis-ci.org/beatgammit/base64-js)
|
||||||
|
|
||||||
|
Many browsers already have base64 encoding/decoding functionality, but it is for text data, not all-purpose binary data.
|
||||||
|
|
||||||
|
Sometimes encoding/decoding binary data in the browser is useful, and that is what this module does.
|
||||||
|
|
||||||
|
## install
|
||||||
|
|
||||||
|
With [npm](https://npmjs.org) do:
|
||||||
|
|
||||||
|
`npm install base64-js` and `var base64js = require('base64-js')`
|
||||||
|
|
||||||
|
For use in web browsers do:
|
||||||
|
|
||||||
|
`<script src="base64js.min.js"></script>`
|
||||||
|
|
||||||
|
[Get supported base64-js with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-base64-js?utm_source=npm-base64-js&utm_medium=referral&utm_campaign=readme)
|
||||||
|
|
||||||
|
## methods
|
||||||
|
|
||||||
|
`base64js` has three exposed functions, `byteLength`, `toByteArray` and `fromByteArray`, which both take a single argument.
|
||||||
|
|
||||||
|
* `byteLength` - Takes a base64 string and returns length of byte array
|
||||||
|
* `toByteArray` - Takes a base64 string and returns a byte array
|
||||||
|
* `fromByteArray` - Takes a byte array and returns a base64 string
|
||||||
|
|
||||||
|
## license
|
||||||
|
|
||||||
|
MIT
|
|
@ -0,0 +1 @@
|
||||||
|
(function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,b.base64js=a()}})(function(){return function(){function b(d,e,g){function a(j,i){if(!e[j]){if(!d[j]){var f="function"==typeof require&&require;if(!i&&f)return f(j,!0);if(h)return h(j,!0);var c=new Error("Cannot find module '"+j+"'");throw c.code="MODULE_NOT_FOUND",c}var k=e[j]={exports:{}};d[j][0].call(k.exports,function(b){var c=d[j][1][b];return a(c||b)},k,k.exports,b,d,e,g)}return e[j].exports}for(var h="function"==typeof require&&require,c=0;c<g.length;c++)a(g[c]);return a}return b}()({"/":[function(a,b,c){'use strict';function d(a){var b=a.length;if(0<b%4)throw new Error("Invalid string. Length must be a multiple of 4");var c=a.indexOf("=");-1===c&&(c=b);var d=c===b?0:4-c%4;return[c,d]}function e(a,b,c){return 3*(b+c)/4-c}function f(a){var b,c,f=d(a),g=f[0],h=f[1],j=new m(e(a,g,h)),k=0,n=0<h?g-4:g;for(c=0;c<n;c+=4)b=l[a.charCodeAt(c)]<<18|l[a.charCodeAt(c+1)]<<12|l[a.charCodeAt(c+2)]<<6|l[a.charCodeAt(c+3)],j[k++]=255&b>>16,j[k++]=255&b>>8,j[k++]=255&b;return 2===h&&(b=l[a.charCodeAt(c)]<<2|l[a.charCodeAt(c+1)]>>4,j[k++]=255&b),1===h&&(b=l[a.charCodeAt(c)]<<10|l[a.charCodeAt(c+1)]<<4|l[a.charCodeAt(c+2)]>>2,j[k++]=255&b>>8,j[k++]=255&b),j}function g(a){return k[63&a>>18]+k[63&a>>12]+k[63&a>>6]+k[63&a]}function h(a,b,c){for(var d,e=[],f=b;f<c;f+=3)d=(16711680&a[f]<<16)+(65280&a[f+1]<<8)+(255&a[f+2]),e.push(g(d));return e.join("")}function j(a){for(var b,c=a.length,d=c%3,e=[],f=16383,g=0,j=c-d;g<j;g+=f)e.push(h(a,g,g+f>j?j:g+f));return 1===d?(b=a[c-1],e.push(k[b>>2]+k[63&b<<4]+"==")):2===d&&(b=(a[c-2]<<8)+a[c-1],e.push(k[b>>10]+k[63&b>>4]+k[63&b<<2]+"=")),e.join("")}c.byteLength=function(a){var b=d(a),c=b[0],e=b[1];return 3*(c+e)/4-e},c.toByteArray=f,c.fromByteArray=j;for(var k=[],l=[],m="undefined"==typeof Uint8Array?Array:Uint8Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,p=n.length;o<p;++o)k[o]=n[o],l[n.charCodeAt(o)]=o;l[45]=62,l[95]=63},{}]},{},[])("/")});
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function byteLength(b64: string): number;
|
||||||
|
export function toByteArray(b64: string): Uint8Array;
|
||||||
|
export function fromByteArray(uint8: Uint8Array): string;
|
|
@ -0,0 +1,150 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
exports.byteLength = byteLength
|
||||||
|
exports.toByteArray = toByteArray
|
||||||
|
exports.fromByteArray = fromByteArray
|
||||||
|
|
||||||
|
var lookup = []
|
||||||
|
var revLookup = []
|
||||||
|
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
|
||||||
|
|
||||||
|
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
|
for (var i = 0, len = code.length; i < len; ++i) {
|
||||||
|
lookup[i] = code[i]
|
||||||
|
revLookup[code.charCodeAt(i)] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support decoding URL-safe base64 strings, as Node.js does.
|
||||||
|
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
|
||||||
|
revLookup['-'.charCodeAt(0)] = 62
|
||||||
|
revLookup['_'.charCodeAt(0)] = 63
|
||||||
|
|
||||||
|
function getLens (b64) {
|
||||||
|
var len = b64.length
|
||||||
|
|
||||||
|
if (len % 4 > 0) {
|
||||||
|
throw new Error('Invalid string. Length must be a multiple of 4')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim off extra bytes after placeholder bytes are found
|
||||||
|
// See: https://github.com/beatgammit/base64-js/issues/42
|
||||||
|
var validLen = b64.indexOf('=')
|
||||||
|
if (validLen === -1) validLen = len
|
||||||
|
|
||||||
|
var placeHoldersLen = validLen === len
|
||||||
|
? 0
|
||||||
|
: 4 - (validLen % 4)
|
||||||
|
|
||||||
|
return [validLen, placeHoldersLen]
|
||||||
|
}
|
||||||
|
|
||||||
|
// base64 is 4/3 + up to two characters of the original data
|
||||||
|
function byteLength (b64) {
|
||||||
|
var lens = getLens(b64)
|
||||||
|
var validLen = lens[0]
|
||||||
|
var placeHoldersLen = lens[1]
|
||||||
|
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
|
||||||
|
}
|
||||||
|
|
||||||
|
function _byteLength (b64, validLen, placeHoldersLen) {
|
||||||
|
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
|
||||||
|
}
|
||||||
|
|
||||||
|
function toByteArray (b64) {
|
||||||
|
var tmp
|
||||||
|
var lens = getLens(b64)
|
||||||
|
var validLen = lens[0]
|
||||||
|
var placeHoldersLen = lens[1]
|
||||||
|
|
||||||
|
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
|
||||||
|
|
||||||
|
var curByte = 0
|
||||||
|
|
||||||
|
// if there are placeholders, only get up to the last complete 4 chars
|
||||||
|
var len = placeHoldersLen > 0
|
||||||
|
? validLen - 4
|
||||||
|
: validLen
|
||||||
|
|
||||||
|
var i
|
||||||
|
for (i = 0; i < len; i += 4) {
|
||||||
|
tmp =
|
||||||
|
(revLookup[b64.charCodeAt(i)] << 18) |
|
||||||
|
(revLookup[b64.charCodeAt(i + 1)] << 12) |
|
||||||
|
(revLookup[b64.charCodeAt(i + 2)] << 6) |
|
||||||
|
revLookup[b64.charCodeAt(i + 3)]
|
||||||
|
arr[curByte++] = (tmp >> 16) & 0xFF
|
||||||
|
arr[curByte++] = (tmp >> 8) & 0xFF
|
||||||
|
arr[curByte++] = tmp & 0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placeHoldersLen === 2) {
|
||||||
|
tmp =
|
||||||
|
(revLookup[b64.charCodeAt(i)] << 2) |
|
||||||
|
(revLookup[b64.charCodeAt(i + 1)] >> 4)
|
||||||
|
arr[curByte++] = tmp & 0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placeHoldersLen === 1) {
|
||||||
|
tmp =
|
||||||
|
(revLookup[b64.charCodeAt(i)] << 10) |
|
||||||
|
(revLookup[b64.charCodeAt(i + 1)] << 4) |
|
||||||
|
(revLookup[b64.charCodeAt(i + 2)] >> 2)
|
||||||
|
arr[curByte++] = (tmp >> 8) & 0xFF
|
||||||
|
arr[curByte++] = tmp & 0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
function tripletToBase64 (num) {
|
||||||
|
return lookup[num >> 18 & 0x3F] +
|
||||||
|
lookup[num >> 12 & 0x3F] +
|
||||||
|
lookup[num >> 6 & 0x3F] +
|
||||||
|
lookup[num & 0x3F]
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeChunk (uint8, start, end) {
|
||||||
|
var tmp
|
||||||
|
var output = []
|
||||||
|
for (var i = start; i < end; i += 3) {
|
||||||
|
tmp =
|
||||||
|
((uint8[i] << 16) & 0xFF0000) +
|
||||||
|
((uint8[i + 1] << 8) & 0xFF00) +
|
||||||
|
(uint8[i + 2] & 0xFF)
|
||||||
|
output.push(tripletToBase64(tmp))
|
||||||
|
}
|
||||||
|
return output.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromByteArray (uint8) {
|
||||||
|
var tmp
|
||||||
|
var len = uint8.length
|
||||||
|
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
|
||||||
|
var parts = []
|
||||||
|
var maxChunkLength = 16383 // must be multiple of 3
|
||||||
|
|
||||||
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
||||||
|
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
||||||
|
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
||||||
|
if (extraBytes === 1) {
|
||||||
|
tmp = uint8[len - 1]
|
||||||
|
parts.push(
|
||||||
|
lookup[tmp >> 2] +
|
||||||
|
lookup[(tmp << 4) & 0x3F] +
|
||||||
|
'=='
|
||||||
|
)
|
||||||
|
} else if (extraBytes === 2) {
|
||||||
|
tmp = (uint8[len - 2] << 8) + uint8[len - 1]
|
||||||
|
parts.push(
|
||||||
|
lookup[tmp >> 10] +
|
||||||
|
lookup[(tmp >> 4) & 0x3F] +
|
||||||
|
lookup[(tmp << 2) & 0x3F] +
|
||||||
|
'='
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.join('')
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"name": "base64-js",
|
||||||
|
"description": "Base64 encoding/decoding in pure JS",
|
||||||
|
"version": "1.5.1",
|
||||||
|
"author": "T. Jameson Little <t.jameson.little@gmail.com>",
|
||||||
|
"typings": "index.d.ts",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/beatgammit/base64-js/issues"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-minify": "^0.5.1",
|
||||||
|
"benchmark": "^2.1.4",
|
||||||
|
"browserify": "^16.3.0",
|
||||||
|
"standard": "*",
|
||||||
|
"tape": "4.x"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/beatgammit/base64-js",
|
||||||
|
"keywords": [
|
||||||
|
"base64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/beatgammit/base64-js.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "browserify -s base64js -r ./ | minify > base64js.min.js",
|
||||||
|
"lint": "standard",
|
||||||
|
"test": "npm run lint && npm run unit",
|
||||||
|
"unit": "tape test/*.js"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
extends: '@mscdex/eslint-config',
|
|
||||||
};
|
|
|
@ -1,72 +0,0 @@
|
||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests-linux:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
node-version: [10.x, 12.x, 14.x, 16.x, 18.x]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
- name: Install module
|
|
||||||
run: npm install
|
|
||||||
- name: Run tests
|
|
||||||
run: npm test
|
|
||||||
tests-macos:
|
|
||||||
runs-on: macos-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
node-version: [10.x, 12.x, 14.x, 16.x, 18.x]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
- name: Install module
|
|
||||||
run: npm install
|
|
||||||
- name: Run tests
|
|
||||||
run: npm test
|
|
||||||
tests-windows-2019:
|
|
||||||
runs-on: windows-2019
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
node-version: [10.x, 12.x, 14.x, 16.x, 18.x]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
- name: Install module
|
|
||||||
run: npm install
|
|
||||||
- name: Run tests
|
|
||||||
run: npm test
|
|
||||||
tests-windows-2022:
|
|
||||||
runs-on: windows-2022
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
node-version: [18.x]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
- name: Install module
|
|
||||||
run: npm install
|
|
||||||
- name: Run tests
|
|
||||||
run: npm test
|
|
|
@ -1,23 +0,0 @@
|
||||||
name: lint
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
NODE_VERSION: 14.x
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint-js:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Use Node.js ${{ env.NODE_VERSION }}
|
|
||||||
uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
|
||||||
- name: Install ESLint + ESLint configs/plugins
|
|
||||||
run: npm install --only=dev
|
|
||||||
- name: Lint files
|
|
||||||
run: npm run lint
|
|
|
@ -1,3 +0,0 @@
|
||||||
.eslintcache
|
|
||||||
**/node_modules/**
|
|
||||||
/package-lock.json
|
|
|
@ -1,106 +0,0 @@
|
||||||
# Description
|
|
||||||
|
|
||||||
Build environment checking for [node.js](http://nodejs.org/).
|
|
||||||
|
|
||||||
This allows for autoconf-like functionality for node addons/build scripts.
|
|
||||||
|
|
||||||
**Note:** Obsolete and/or exotic build environments or platforms not supported
|
|
||||||
by node.js are not supported.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
* [node.js](http://nodejs.org/) -- v10.0.0 or newer
|
|
||||||
* Supported compilers:
|
|
||||||
* gcc
|
|
||||||
* clang
|
|
||||||
* MSVC 2013+ and Windows SDK 8.1+
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
npm install buildcheck
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Check if a C function exists
|
|
||||||
|
|
||||||
```js
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const BuildEnvironment = require('buildcheck');
|
|
||||||
|
|
||||||
const buildEnv = new BuildEnvironment();
|
|
||||||
|
|
||||||
console.log(buildEnv.checkFunction('c', 'preadv2'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check if a C header is usable
|
|
||||||
|
|
||||||
```js
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const BuildEnvironment = require('buildcheck');
|
|
||||||
|
|
||||||
const buildEnv = new BuildEnvironment();
|
|
||||||
|
|
||||||
console.log(buildEnv.checkHeader('c', 'linux/io_uring.h'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Try to compile some C code
|
|
||||||
|
|
||||||
```js
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const BuildEnvironment = require('buildcheck');
|
|
||||||
|
|
||||||
const buildEnv = new BuildEnvironment();
|
|
||||||
|
|
||||||
// Should be a successful compile
|
|
||||||
console.log(buildEnv.tryCompile('c', 'int main() { return 0; }'));
|
|
||||||
|
|
||||||
// Should be a failed compile
|
|
||||||
console.log(buildEnv.tryCompile('c', 'int main() { return z; }'));
|
|
||||||
```
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### Exports
|
|
||||||
|
|
||||||
The exported value is `BuildEnvironment`, the main class for dealing with a build environment.
|
|
||||||
|
|
||||||
### BuildEnvironment
|
|
||||||
|
|
||||||
#### Methods
|
|
||||||
|
|
||||||
* **(constructor)**([< _object_ >config]) - Creates and returns a new BuildEnvironment instance. `config` may contain:
|
|
||||||
|
|
||||||
* **compilerC** - _string_ - C compiler command to use. *Note: this is ignored on Windows.* **Default:** `process.env.CC` or `'cc'`
|
|
||||||
|
|
||||||
* **compilerCXX** - _string_ - C++ compiler command to use. *Note: this is ignored on Windows.* **Default:** `process.env.CXX` or `'c++'`
|
|
||||||
|
|
||||||
* **msvs_version** - _mixed_ - A string or number containing the year of the Visual Studio compiler to use. *Note: this is for Windows only.* **Default:** newest version installed
|
|
||||||
|
|
||||||
* **checkDeclared**(< _string_ >lang, < _string_ >symbolName[, < _object_ >options]) - _boolean_ - Checks if a symbol `symbolName` is declared where `lang` is either `'c'` or `'c++'`. Returns `true` if symbol exists, `false` otherwise. `options` may contain:
|
|
||||||
|
|
||||||
* **headers** - _array_ - A list of headers to try when checking if the symbol is declared. `checkFunction()` will always first try without a library. If not supplied, a default list of common (platform-specific) headers will be used.
|
|
||||||
|
|
||||||
* **searchLibs** - _array_ - A list of library names (without the `'-l'` prefix) to try when checking if the symbol is declared. `checkDeclared()` will always first try without a library.
|
|
||||||
|
|
||||||
* **checkFunction**(< _string_ >lang, < _string_ >functionName[, < _object_ >options]) - _boolean_ - Checks if a function `functionName` exists and is linkable where `lang` is either `'c'` or `'c++'`. Returns `true` if function exists, `false` otherwise. `options` may contain:
|
|
||||||
|
|
||||||
* **searchLibs** - _array_ - A list of library names (without the `'-l'` prefix) to try when checking for this function. `checkFunction()` will always first try without a library.
|
|
||||||
|
|
||||||
* **checkFeature**(< _string_ >featureName) - _mixed_ - Executes a special test for a "feature" and returns the result. Supported values for `featureName`:
|
|
||||||
|
|
||||||
* `'strerror_r'` - Returns an object containing:
|
|
||||||
|
|
||||||
* `declared` - _boolean_ - Whether `strerror_r()` is declared
|
|
||||||
|
|
||||||
* `returnsCharPtr` - _boolean_ - If `strerror_r()` is declared, whether it returns `char*` (a GNU extension) or not.
|
|
||||||
|
|
||||||
* **checkHeader**(< _string_ >lang, < _string_ >headerName) - _boolean_ - Checks if the header `headerName` exists and is usable where `lang` is either `'c'` or `'c++'`. Returns `true` if the header exists and is usable, `false` otherwise.
|
|
||||||
|
|
||||||
* **defines**([< _string_ >lang[, < _boolean_ >rendered]]) - _array_ - Returns a list of features, functions, headers, and symbols known to be defined by this build environment instance. `lang` is either `'c'` or `'c++'` If `lang` is not set, defines for both `'c'` and `'c++'` will be returned. If `rendered` is `true` (defaults to `false`), autoconf-style defines (e.g. "HAVE_FOO=1") will be returned instead. Defines coming from features utilize base strings/names from autoconf for better compatibility.
|
|
||||||
|
|
||||||
* **libs**([< _string_ >lang]) - _array_ - Returns a list of (`'-l'`-prefixed) libraries known to be required for features and functions defined by this build environment instance. `lang` is either `'c'` or `'c++'` If `lang` is not set, defines for both `'c'` and `'c++'` will be returned.
|
|
||||||
|
|
||||||
* **tryCompile**(< _string_ >lang, < _string_ >code[, < _array_ >compilerParams]) - _mixed_ - Attempts to compile `code` where `lang` is either `'c'` or `'c++'`. `compilerParams` is an optional array of compiler/linker flags to include. Returns `true` on successful compilation, or an _Error_ instance with an `output` property containing the compiler error output.
|
|
|
@ -1,250 +0,0 @@
|
||||||
// Copyright 2017 - Refael Ackermann
|
|
||||||
// Distributed under MIT style license
|
|
||||||
// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf
|
|
||||||
|
|
||||||
// Usage:
|
|
||||||
// powershell -ExecutionPolicy Unrestricted -Command "Add-Type -Path Find-VisualStudio.cs; [VisualStudioConfiguration.Main]::PrintJson()"
|
|
||||||
// This script needs to be compatible with PowerShell v2 to run on Windows 2008R2 and Windows 7.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace VisualStudioConfiguration
|
|
||||||
{
|
|
||||||
[Flags]
|
|
||||||
public enum InstanceState : uint
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Local = 1,
|
|
||||||
Registered = 2,
|
|
||||||
NoRebootRequired = 4,
|
|
||||||
NoErrors = 8,
|
|
||||||
Complete = 4294967295,
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[ComImport]
|
|
||||||
public interface IEnumSetupInstances
|
|
||||||
{
|
|
||||||
|
|
||||||
void Next([MarshalAs(UnmanagedType.U4), In] int celt,
|
|
||||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt,
|
|
||||||
[MarshalAs(UnmanagedType.U4)] out int pceltFetched);
|
|
||||||
|
|
||||||
void Skip([MarshalAs(UnmanagedType.U4), In] int celt);
|
|
||||||
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.Interface)]
|
|
||||||
IEnumSetupInstances Clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[ComImport]
|
|
||||||
public interface ISetupConfiguration
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[ComImport]
|
|
||||||
public interface ISetupConfiguration2 : ISetupConfiguration
|
|
||||||
{
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.Interface)]
|
|
||||||
IEnumSetupInstances EnumInstances();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.Interface)]
|
|
||||||
ISetupInstance GetInstanceForCurrentProcess();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.Interface)]
|
|
||||||
ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path);
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.Interface)]
|
|
||||||
IEnumSetupInstances EnumAllInstances();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[ComImport]
|
|
||||||
public interface ISetupInstance
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[ComImport]
|
|
||||||
public interface ISetupInstance2 : ISetupInstance
|
|
||||||
{
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetInstanceId();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.Struct)]
|
|
||||||
System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetInstallationName();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetInstallationPath();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetInstallationVersion();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid);
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid);
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath);
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.U4)]
|
|
||||||
InstanceState GetState();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
|
|
||||||
ISetupPackageReference[] GetPackages();
|
|
||||||
|
|
||||||
ISetupPackageReference GetProduct();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetProductPath();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.VariantBool)]
|
|
||||||
bool IsLaunchable();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.VariantBool)]
|
|
||||||
bool IsComplete();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
|
|
||||||
ISetupPropertyStore GetProperties();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetEnginePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[ComImport]
|
|
||||||
public interface ISetupPackageReference
|
|
||||||
{
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetId();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetVersion();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetChip();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetLanguage();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetBranch();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetType();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.BStr)]
|
|
||||||
string GetUniqueId();
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.VariantBool)]
|
|
||||||
bool GetIsExtension();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[ComImport]
|
|
||||||
public interface ISetupPropertyStore
|
|
||||||
{
|
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
|
|
||||||
string[] GetNames();
|
|
||||||
|
|
||||||
object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
|
|
||||||
[CoClass(typeof(SetupConfigurationClass))]
|
|
||||||
[ComImport]
|
|
||||||
public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
|
|
||||||
[ClassInterface(ClassInterfaceType.None)]
|
|
||||||
[ComImport]
|
|
||||||
public class SetupConfigurationClass
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Main
|
|
||||||
{
|
|
||||||
public static void PrintJson()
|
|
||||||
{
|
|
||||||
ISetupConfiguration query = new SetupConfiguration();
|
|
||||||
ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
|
|
||||||
IEnumSetupInstances e = query2.EnumAllInstances();
|
|
||||||
|
|
||||||
int pceltFetched;
|
|
||||||
ISetupInstance2[] rgelt = new ISetupInstance2[1];
|
|
||||||
List<string> instances = new List<string>();
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
e.Next(1, rgelt, out pceltFetched);
|
|
||||||
if (pceltFetched <= 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine(String.Format("[{0}]", string.Join(",", instances.ToArray())));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
instances.Add(InstanceJson(rgelt[0]));
|
|
||||||
}
|
|
||||||
catch (COMException)
|
|
||||||
{
|
|
||||||
// Ignore instances that can't be queried.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string JsonString(string s)
|
|
||||||
{
|
|
||||||
return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string InstanceJson(ISetupInstance2 setupInstance2)
|
|
||||||
{
|
|
||||||
// Visual Studio component directory:
|
|
||||||
// https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids
|
|
||||||
|
|
||||||
StringBuilder json = new StringBuilder();
|
|
||||||
json.Append("{");
|
|
||||||
|
|
||||||
string path = JsonString(setupInstance2.GetInstallationPath());
|
|
||||||
json.Append(String.Format("\"path\":{0},", path));
|
|
||||||
|
|
||||||
string version = JsonString(setupInstance2.GetInstallationVersion());
|
|
||||||
json.Append(String.Format("\"version\":{0},", version));
|
|
||||||
|
|
||||||
List<string> packages = new List<string>();
|
|
||||||
foreach (ISetupPackageReference package in setupInstance2.GetPackages())
|
|
||||||
{
|
|
||||||
string id = JsonString(package.GetId());
|
|
||||||
packages.Add(id);
|
|
||||||
}
|
|
||||||
json.Append(String.Format("\"packages\":[{0}]", string.Join(",", packages.ToArray())));
|
|
||||||
|
|
||||||
json.Append("}");
|
|
||||||
return json.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,345 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const { execFileSync } = require('child_process');
|
|
||||||
const { readFileSync, statSync } = require('fs');
|
|
||||||
const { win32: path } = require('path');
|
|
||||||
|
|
||||||
const VS_VERSIONS_MODERN = new Map([
|
|
||||||
[15, {
|
|
||||||
year: 2017,
|
|
||||||
msbuild: path.join('MSBuild', '15.0', 'Bin', 'MSBuild.exe'),
|
|
||||||
toolset: 'v141',
|
|
||||||
}],
|
|
||||||
[16, {
|
|
||||||
year: 2019,
|
|
||||||
msbuild: path.join('MSBuild', 'Current', 'Bin', 'MSBuild.exe'),
|
|
||||||
toolset: 'v142',
|
|
||||||
}],
|
|
||||||
[17, {
|
|
||||||
year: 2022,
|
|
||||||
msbuild:
|
|
||||||
(process.arch === 'x64'
|
|
||||||
? path.join('MSBuild', 'Current', 'Bin', 'amd64', 'MSBuild.exe')
|
|
||||||
: path.join('MSBuild', 'Current', 'Bin', 'MSBuild.exe')),
|
|
||||||
toolset: 'v143',
|
|
||||||
}],
|
|
||||||
]);
|
|
||||||
const PACKAGES = {
|
|
||||||
msbuild: /^Microsoft[.]VisualStudio[.]VC[.]MSBuild[.](?:v\d+[.])?Base$/i,
|
|
||||||
vctools: /^Microsoft[.]VisualStudio[.]Component[.]VC[.]Tools[.]x86[.]x64$/i,
|
|
||||||
express: /^Microsoft[.]VisualStudio[.]WDExpress$/i,
|
|
||||||
winsdk:
|
|
||||||
/^Microsoft[.]VisualStudio[.]Component[.]Windows(81|10|11)SDK(?:[.](\d+)(?:[.]Desktop.*)?)?$/,
|
|
||||||
};
|
|
||||||
const SDK_REG = 'HKLM\\Software\\Microsoft\\Microsoft SDKs\\Windows';
|
|
||||||
const SDK32_REG =
|
|
||||||
'HKLM\\Software\\Wow6432Node\\Microsoft\\Microsoft SDKs\\Windows';
|
|
||||||
|
|
||||||
function checkRequiredPackages(packages) {
|
|
||||||
if (!Array.isArray(packages))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let foundMSBuild = false;
|
|
||||||
let foundVCTools = false;
|
|
||||||
let foundExpress = false;
|
|
||||||
for (const pkg of packages) {
|
|
||||||
if (!foundMSBuild && PACKAGES.msbuild.test(pkg))
|
|
||||||
foundMSBuild = true;
|
|
||||||
else if (!foundVCTools && PACKAGES.vctools.test(pkg))
|
|
||||||
foundVCTools = true;
|
|
||||||
else if (!foundExpress && PACKAGES.express.test(pkg))
|
|
||||||
foundExpress = true;
|
|
||||||
|
|
||||||
if (foundMSBuild && (foundVCTools || foundExpress))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sorts newest to oldest
|
|
||||||
function versionStringCompare(a, b) {
|
|
||||||
const splitA = a.split('.');
|
|
||||||
const splitB = b.split('.');
|
|
||||||
const len = Math.min(splitA.length, splitB.length);
|
|
||||||
for (let i = 0; i < len; ++i) {
|
|
||||||
const nA = parseInt(splitA[i], 10);
|
|
||||||
const nB = parseInt(splitB[i], 10);
|
|
||||||
if (nA > nB)
|
|
||||||
return -1;
|
|
||||||
if (nA < nB)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (splitA.length > splitB.length)
|
|
||||||
return -1;
|
|
||||||
else if (splitA.length < splitB.length)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sdkVersionCompare(a, b) {
|
|
||||||
return versionStringCompare(a.fullVersion, b.fullVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSDKPaths(fullVer) {
|
|
||||||
if (typeof fullVer !== 'string' || !fullVer)
|
|
||||||
return;
|
|
||||||
try {
|
|
||||||
const arch = (process.arch === 'ia32' ? 'x86' : 'x64');
|
|
||||||
const shortVer = `v${/^\d+[.]\d+/.exec(fullVer)[0]}`;
|
|
||||||
let verPath = getRegValue(`${SDK_REG}\\${shortVer}`, 'InstallationFolder');
|
|
||||||
if (!verPath)
|
|
||||||
verPath = getRegValue(`${SDK32_REG}\\${shortVer}`, 'InstallationFolder');
|
|
||||||
if (!verPath)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Includes
|
|
||||||
const includePaths = [];
|
|
||||||
for (const type of ['shared', 'um', 'ucrt']) {
|
|
||||||
const testPath = path.resolve(verPath, 'Include', fullVer, type);
|
|
||||||
statSync(testPath);
|
|
||||||
includePaths.push(testPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Libraries
|
|
||||||
const libPaths = [];
|
|
||||||
for (const type of ['um', 'ucrt']) {
|
|
||||||
const testPath = path.resolve(verPath, 'Lib', fullVer, type, arch);
|
|
||||||
statSync(testPath);
|
|
||||||
libPaths.push(testPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { includePaths, libPaths };
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
const execOpts = {
|
|
||||||
encoding: 'utf8',
|
|
||||||
stdio: ['ignore', 'pipe', 'pipe'],
|
|
||||||
windowsHide: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
function findModernVS() {
|
|
||||||
const versions = [];
|
|
||||||
const ps = path.join(
|
|
||||||
process.env.SystemRoot,
|
|
||||||
'System32',
|
|
||||||
'WindowsPowerShell',
|
|
||||||
'v1.0',
|
|
||||||
'powershell.exe'
|
|
||||||
);
|
|
||||||
const cs = path.resolve(__dirname, '..', 'deps', 'Find-VisualStudio.cs');
|
|
||||||
const args = [
|
|
||||||
'-ExecutionPolicy',
|
|
||||||
'Unrestricted',
|
|
||||||
'-NoProfile',
|
|
||||||
'-Command',
|
|
||||||
`&{Add-Type -Path '${cs}';[VisualStudioConfiguration.Main]::PrintJson()}`
|
|
||||||
];
|
|
||||||
try {
|
|
||||||
const out = execFileSync(ps, args, execOpts);
|
|
||||||
const info = JSON.parse(out);
|
|
||||||
if (Array.isArray(info)) {
|
|
||||||
for (const vs of info) {
|
|
||||||
const vsPath = path.resolve(vs.path);
|
|
||||||
let vsVer = /^(?<major>\d+)[.](?<minor>\d+)[.]/.exec(vs.version);
|
|
||||||
if (!vsVer)
|
|
||||||
continue;
|
|
||||||
vsVer = {
|
|
||||||
full: vs.version,
|
|
||||||
major: +vsVer.groups.major,
|
|
||||||
minor: +vsVer.groups.minor,
|
|
||||||
};
|
|
||||||
const verInfo = VS_VERSIONS_MODERN.get(vsVer.major);
|
|
||||||
if (verInfo === undefined)
|
|
||||||
continue;
|
|
||||||
if (!checkRequiredPackages(vs.packages))
|
|
||||||
continue;
|
|
||||||
const vsSDKs = [];
|
|
||||||
for (const pkg of vs.packages) {
|
|
||||||
let fullVersion;
|
|
||||||
let version;
|
|
||||||
const m = PACKAGES.winsdk.exec(pkg);
|
|
||||||
if (!m)
|
|
||||||
continue;
|
|
||||||
const sdk = m[1];
|
|
||||||
switch (sdk) {
|
|
||||||
case '81':
|
|
||||||
fullVersion = version = '8.1';
|
|
||||||
break;
|
|
||||||
case '10':
|
|
||||||
case '11': {
|
|
||||||
if (m[2] === undefined)
|
|
||||||
continue;
|
|
||||||
const sdkVer = parseInt(m[2], 10);
|
|
||||||
if (!isFinite(sdkVer) || sdkVer < 0)
|
|
||||||
continue;
|
|
||||||
fullVersion = `10.0.${sdkVer}.0`;
|
|
||||||
version = '10.0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const paths = getSDKPaths(fullVersion);
|
|
||||||
if (!paths)
|
|
||||||
continue;
|
|
||||||
vsSDKs.push({
|
|
||||||
version,
|
|
||||||
fullVersion,
|
|
||||||
...paths,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (vsSDKs.length === 0)
|
|
||||||
continue;
|
|
||||||
let clPath;
|
|
||||||
const includePaths = [];
|
|
||||||
const libPaths = [];
|
|
||||||
try {
|
|
||||||
let vcVerFile;
|
|
||||||
let clVer;
|
|
||||||
try {
|
|
||||||
vcVerFile = path.join(
|
|
||||||
vsPath,
|
|
||||||
'VC',
|
|
||||||
'Auxiliary',
|
|
||||||
'Build',
|
|
||||||
`Microsoft.VCToolsVersion.${verInfo.toolset}.default.txt`
|
|
||||||
);
|
|
||||||
clVer = readFileSync(vcVerFile, { encoding: 'utf8' }).trim();
|
|
||||||
} catch {}
|
|
||||||
if (!clVer) {
|
|
||||||
vcVerFile = path.join(
|
|
||||||
vsPath,
|
|
||||||
'VC',
|
|
||||||
'Auxiliary',
|
|
||||||
'Build',
|
|
||||||
'Microsoft.VCToolsVersion.default.txt'
|
|
||||||
);
|
|
||||||
clVer = readFileSync(vcVerFile, { encoding: 'utf8' }).trim();
|
|
||||||
}
|
|
||||||
const arch = (process.arch === 'ia32' ? 'x86' : 'x64');
|
|
||||||
let testPath = path.join(
|
|
||||||
vsPath,
|
|
||||||
'VC',
|
|
||||||
'Tools',
|
|
||||||
'MSVC',
|
|
||||||
clVer,
|
|
||||||
'bin',
|
|
||||||
`Host${arch}`,
|
|
||||||
arch,
|
|
||||||
'cl.exe'
|
|
||||||
);
|
|
||||||
statSync(testPath);
|
|
||||||
clPath = testPath;
|
|
||||||
|
|
||||||
testPath = path.join(
|
|
||||||
vsPath,
|
|
||||||
'VC',
|
|
||||||
'Tools',
|
|
||||||
'MSVC',
|
|
||||||
clVer,
|
|
||||||
'include'
|
|
||||||
);
|
|
||||||
statSync(testPath);
|
|
||||||
includePaths.push(testPath);
|
|
||||||
|
|
||||||
testPath = path.join(
|
|
||||||
vsPath,
|
|
||||||
'VC',
|
|
||||||
'Tools',
|
|
||||||
'MSVC',
|
|
||||||
clVer,
|
|
||||||
'lib',
|
|
||||||
arch
|
|
||||||
);
|
|
||||||
statSync(testPath);
|
|
||||||
libPaths.push(testPath);
|
|
||||||
} catch {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
vsSDKs.sort(sdkVersionCompare);
|
|
||||||
versions.push({
|
|
||||||
path: vsPath,
|
|
||||||
version: vsVer,
|
|
||||||
sdks: vsSDKs,
|
|
||||||
...verInfo,
|
|
||||||
msbuild: path.join(vsPath, verInfo.msbuild),
|
|
||||||
cl: clPath,
|
|
||||||
includePaths,
|
|
||||||
libPaths,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
return versions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const VS_VERSIONS_OLDER = [
|
|
||||||
{
|
|
||||||
version: { full: '12.0', major: 12, minor: 0 },
|
|
||||||
year: 2013,
|
|
||||||
toolset: 'v120',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
version: { full: '14.0', major: 14, minor: 0 },
|
|
||||||
year: 2015,
|
|
||||||
toolset: 'v140',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const VC_REG = 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7';
|
|
||||||
const VC32_REG =
|
|
||||||
'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7';
|
|
||||||
const MSBUILD_REG = 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions';
|
|
||||||
|
|
||||||
function getRegValue(key, value, use32) {
|
|
||||||
const extraArgs = (use32 ? [ '/reg:32' ] : []);
|
|
||||||
const regexp = new RegExp(`^\\s+${value}\\s+REG_\\w+\\s+(\\S.*)$`, 'im');
|
|
||||||
const reg = path.join(process.env.SystemRoot, 'System32', 'reg.exe');
|
|
||||||
const args = [ 'query', key, '/v', value, ...extraArgs ];
|
|
||||||
|
|
||||||
try {
|
|
||||||
const out = execFileSync(reg, args, execOpts);
|
|
||||||
const m = regexp.exec(out);
|
|
||||||
if (m)
|
|
||||||
return m[1];
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findOlderVS() {
|
|
||||||
const versions = [];
|
|
||||||
try {
|
|
||||||
for (const vs of VS_VERSIONS_OLDER) {
|
|
||||||
let vsPath = getRegValue(VC_REG, vs.version.full);
|
|
||||||
if (!vsPath)
|
|
||||||
vsPath = getRegValue(VC32_REG, vs.version.full);
|
|
||||||
if (!vsPath)
|
|
||||||
continue;
|
|
||||||
vsPath = path.resolve(vsPath, '..');
|
|
||||||
|
|
||||||
const msbuildPath = getRegValue(
|
|
||||||
`${MSBUILD_REG}\\${vs.version.full}`,
|
|
||||||
'MSBuildToolsPath',
|
|
||||||
(process.arch === 'ia32')
|
|
||||||
);
|
|
||||||
if (!msbuildPath)
|
|
||||||
continue;
|
|
||||||
versions.push({
|
|
||||||
path: vsPath,
|
|
||||||
...vs,
|
|
||||||
msbuild: path.join(msbuildPath, 'MSBuild.exe'),
|
|
||||||
cl: path.join(vsPath, 'VC', 'bin', 'cl.exe'),
|
|
||||||
includePaths: [path.join(vsPath, 'VC', 'include')],
|
|
||||||
libPaths: [path.join(vsPath, 'VC', 'lib')],
|
|
||||||
sdks: [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
return versions;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = () => {
|
|
||||||
const versions = findModernVS().concat(findOlderVS());
|
|
||||||
// Sorts newest to oldest
|
|
||||||
versions.sort((a, b) => {
|
|
||||||
return versionStringCompare(a.version.full, b.version.full);
|
|
||||||
});
|
|
||||||
return versions;
|
|
||||||
};
|
|
|
@ -1,738 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// TODO: take `compilerParams`, headers into account in cache for all cached
|
|
||||||
// results
|
|
||||||
// TODO: debug output
|
|
||||||
|
|
||||||
const { spawnSync } = require('child_process');
|
|
||||||
const { unlinkSync, writeFileSync } = require('fs');
|
|
||||||
const { tmpdir } = require('os');
|
|
||||||
const { win32: path } = require('path');
|
|
||||||
const { inspect } = require('util');
|
|
||||||
|
|
||||||
const isWindows = (process.platform === 'win32');
|
|
||||||
const findVS = require('./findvs.js');
|
|
||||||
|
|
||||||
const RE_HEADER_DECORATED = /^(?:"(.+)")|(?:<(.+)>)$/;
|
|
||||||
|
|
||||||
const genWinTmpFilenames = (() => {
|
|
||||||
let instance = 1;
|
|
||||||
return () => {
|
|
||||||
const base =
|
|
||||||
path.resolve(tmpdir(), `_buildcheck-${process.pid}-${instance++}`);
|
|
||||||
return {
|
|
||||||
input: `${base}.in.tmp`,
|
|
||||||
object: `${base}.out.obj`,
|
|
||||||
output: `${base}.out.tmp`,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
function getKind(prop) {
|
|
||||||
const spawnOpts = {
|
|
||||||
encoding: 'utf8',
|
|
||||||
stdio: 'pipe',
|
|
||||||
windowsHide: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const lang = (prop === '_cc' ? 'c' : 'c++');
|
|
||||||
|
|
||||||
if (isWindows) {
|
|
||||||
spawnOpts.stdio = [ 'ignore', 'pipe', 'pipe' ];
|
|
||||||
writeFileSync(this._tmpInFile, [
|
|
||||||
'_MSC_VER',
|
|
||||||
].join(' '));
|
|
||||||
const result = spawnSync(
|
|
||||||
this[prop],
|
|
||||||
[ '-EP', `-T${lang === 'c' ? 'c' : 'p'}`, this._tmpInFile],
|
|
||||||
spawnOpts
|
|
||||||
);
|
|
||||||
unlinkSync(this._tmpInFile);
|
|
||||||
|
|
||||||
if (result.status === 0) {
|
|
||||||
const values = result.stdout.trim().split(' ');
|
|
||||||
if (values.length === 1 && /^\d+$/.test(values[0])) {
|
|
||||||
this[`${prop}Kind`] = 'msvc';
|
|
||||||
this[`${prop}Version`] = values[0];
|
|
||||||
this[`${prop}SpawnOpts`] = spawnOpts;
|
|
||||||
this._debug(
|
|
||||||
`>>> Detected MSVC ${values[0]} for ${lang.toUpperCase()} language`
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const result = spawnSync(
|
|
||||||
this[prop],
|
|
||||||
[ '-E', '-P', '-x', lang, '-' ],
|
|
||||||
{
|
|
||||||
...spawnOpts,
|
|
||||||
input: [
|
|
||||||
'__clang__',
|
|
||||||
'__GNUC__',
|
|
||||||
'__GNUC_MINOR__',
|
|
||||||
'__GNUC_PATCHLEVEL__',
|
|
||||||
'__clang_major__',
|
|
||||||
'__clang_minor__',
|
|
||||||
'__clang_patchlevel__',
|
|
||||||
].join(' '),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.status === 0) {
|
|
||||||
const values = result.stdout.trim().split(' ');
|
|
||||||
if (values.length === 7) {
|
|
||||||
let kind;
|
|
||||||
let version;
|
|
||||||
if (values[0] === '1') {
|
|
||||||
kind = 'clang';
|
|
||||||
version = values.slice(4).map((v) => +v);
|
|
||||||
} else {
|
|
||||||
kind = 'gnu';
|
|
||||||
version = values.slice(1, 4).map((v) => +v);
|
|
||||||
}
|
|
||||||
let good = true;
|
|
||||||
for (const part of version) {
|
|
||||||
if (!isFinite(part) || part < 0) {
|
|
||||||
good = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (good) {
|
|
||||||
this[`${prop}Kind`] = kind;
|
|
||||||
this[`${prop}Version`] = version;
|
|
||||||
this[`${prop}SpawnOpts`] = spawnOpts;
|
|
||||||
const verStr = version.join('.');
|
|
||||||
this._debug(
|
|
||||||
`>>> Detected ${kind} ${verStr} for ${lang.toUpperCase()} language`
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('Unable to detect compiler type');
|
|
||||||
}
|
|
||||||
|
|
||||||
class BuildEnvironment {
|
|
||||||
constructor(cfg) {
|
|
||||||
if (typeof cfg !== 'object' || cfg === null)
|
|
||||||
cfg = {};
|
|
||||||
|
|
||||||
this._debug = (typeof cfg.debug === 'function' ? cfg.debug : () => {});
|
|
||||||
|
|
||||||
let cc;
|
|
||||||
let cxx;
|
|
||||||
if (isWindows) {
|
|
||||||
const versions = findVS();
|
|
||||||
this._debug(
|
|
||||||
`>>> Detected MSVS installations: ${inspect(versions, false, 10)}`
|
|
||||||
);
|
|
||||||
if (versions.length === 0)
|
|
||||||
throw new Error('Unable to detect compiler type');
|
|
||||||
let selected_msvs;
|
|
||||||
if (cfg.msvs_version
|
|
||||||
&& (typeof cfg.msvs_version === 'string'
|
|
||||||
|| typeof cfg.msvs_version === 'number')) {
|
|
||||||
this._debug(`>>> Explicit MSVS requested: ${cfg.msvs_version}`);
|
|
||||||
// Try to select compiler by year
|
|
||||||
const msvs_version = cfg.msvs_version.toString();
|
|
||||||
for (const vs of versions) {
|
|
||||||
if (vs.year.toString() === msvs_version) {
|
|
||||||
selected_msvs = vs;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selected_msvs === undefined)
|
|
||||||
throw new Error(`Unable to find MSVS with year '${msvs_version}'`);
|
|
||||||
} else {
|
|
||||||
selected_msvs = versions[0]; // Use newest
|
|
||||||
}
|
|
||||||
this._debug(`>>> Using MSVS: ${selected_msvs.year}`);
|
|
||||||
cc = selected_msvs.cl;
|
|
||||||
cxx = cc;
|
|
||||||
this._includePaths = selected_msvs.includePaths;
|
|
||||||
this._libPaths = selected_msvs.libPaths;
|
|
||||||
// Add (newest) SDK paths if we have them
|
|
||||||
for (const sdk of selected_msvs.sdks) {
|
|
||||||
this._debug(`>>> Using Windows SDK: ${sdk.fullVersion}`);
|
|
||||||
this._includePaths = this._includePaths.concat(sdk.includePaths);
|
|
||||||
this._libPaths = this._libPaths.concat(sdk.libPaths);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { input, object, output } = genWinTmpFilenames();
|
|
||||||
this._tmpInFile = input;
|
|
||||||
this._tmpObjFile = object;
|
|
||||||
this._tmpOutFile = output;
|
|
||||||
} else {
|
|
||||||
cc = ((typeof cfg.compilerC === 'string' && cfg.compilerC)
|
|
||||||
|| process.env.CC
|
|
||||||
|| 'cc');
|
|
||||||
cxx = ((typeof cfg.compilerCXX === 'string' && cfg.compilerCXX)
|
|
||||||
|| process.env.CXX
|
|
||||||
|| 'c++');
|
|
||||||
this._debug(`>>> Using C compiler: ${cc}`);
|
|
||||||
this._debug(`>>> Using C++ compiler: ${cxx}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._cc = cc;
|
|
||||||
this._ccKind = undefined;
|
|
||||||
this._ccVersion = undefined;
|
|
||||||
this._ccSpawnOpts = undefined;
|
|
||||||
|
|
||||||
this._cxx = cxx;
|
|
||||||
this._cxxKind = undefined;
|
|
||||||
this._cxxVersion = undefined;
|
|
||||||
this._cxxSpawnOpts = undefined;
|
|
||||||
|
|
||||||
if (cfg.cache !== false) {
|
|
||||||
this._cache = new Map(Object.entries({
|
|
||||||
c: new Map(),
|
|
||||||
cxx: new Map(),
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
this._cache = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkDeclared(type, symbolName, opts) {
|
|
||||||
validateType(type);
|
|
||||||
if (typeof symbolName !== 'string' || !symbolName)
|
|
||||||
throw new Error(`Invalid symbol name: ${inspect(symbolName)}`);
|
|
||||||
|
|
||||||
const cached = getCachedValue(type, this._cache, 'declared', symbolName);
|
|
||||||
if (cached !== undefined) {
|
|
||||||
this._debug(
|
|
||||||
`>>> Checking if '${symbolName}' is declared... ${cached} (cached)`
|
|
||||||
);
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof opts !== 'object' || opts === null)
|
|
||||||
opts = {};
|
|
||||||
|
|
||||||
const { headers, searchLibs } = opts;
|
|
||||||
const headersList = renderHeaders(Array.isArray(headers)
|
|
||||||
? headers
|
|
||||||
: getDefaultHeaders(this, type));
|
|
||||||
|
|
||||||
const declName = symbolName.replace(/ *\(.*/, '');
|
|
||||||
const declUse = symbolName.replace(/\(/, '((')
|
|
||||||
.replace(/\)/, ') 0)')
|
|
||||||
.replace(/,/g, ') 0, (');
|
|
||||||
|
|
||||||
const libs = [
|
|
||||||
'',
|
|
||||||
...(Array.isArray(searchLibs) ? searchLibs : [])
|
|
||||||
];
|
|
||||||
|
|
||||||
for (let lib of libs) {
|
|
||||||
if (typeof lib !== 'string')
|
|
||||||
continue;
|
|
||||||
lib = lib.trim();
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
${headersList}
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
#ifndef ${declName}
|
|
||||||
#ifdef __cplusplus
|
|
||||||
(void) ${declUse};
|
|
||||||
#else
|
|
||||||
(void) ${declName};
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}`;
|
|
||||||
const compilerParams = (lib ? [`-l${lib}`] : []);
|
|
||||||
const result = this.tryCompile(type, code, compilerParams);
|
|
||||||
|
|
||||||
this._debug(
|
|
||||||
`>>> Checking if '${symbolName}' is declared `
|
|
||||||
+ `(using ${lib ? `'${lib}'` : 'no'} library)... ${result === true}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result !== true) {
|
|
||||||
this._debug('... check failed with compiler output:');
|
|
||||||
this._debug(result.output);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result === true) {
|
|
||||||
setCachedValue(
|
|
||||||
type,
|
|
||||||
this._cache,
|
|
||||||
'declared',
|
|
||||||
symbolName,
|
|
||||||
(result === true)
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkFeature(name) {
|
|
||||||
const cached = getCachedValue('features', this._cache, null, name);
|
|
||||||
if (cached !== undefined) {
|
|
||||||
if (typeof cached === 'object'
|
|
||||||
&& cached !== null
|
|
||||||
&& typeof cached.val !== undefined) {
|
|
||||||
return cached.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
const feature = features.get(name);
|
|
||||||
if (feature === undefined)
|
|
||||||
throw new Error(`Invalid feature: ${name}`);
|
|
||||||
|
|
||||||
let result = feature(this);
|
|
||||||
if (result === undefined)
|
|
||||||
result = null;
|
|
||||||
|
|
||||||
setCachedValue('features', this._cache, null, name, result);
|
|
||||||
|
|
||||||
if (typeof result === 'object'
|
|
||||||
&& result !== null
|
|
||||||
&& typeof result.val !== undefined) {
|
|
||||||
return result.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkFunction(type, funcName, opts) {
|
|
||||||
validateType(type);
|
|
||||||
if (typeof funcName !== 'string' || !funcName)
|
|
||||||
throw new Error(`Invalid function name: ${inspect(funcName)}`);
|
|
||||||
|
|
||||||
const cached = getCachedValue(type, this._cache, 'functions', funcName);
|
|
||||||
if (cached !== undefined) {
|
|
||||||
this._debug(
|
|
||||||
`>>> Checking if function '${funcName}' exists... true (cached)`
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof opts !== 'object' || opts === null)
|
|
||||||
opts = {};
|
|
||||||
|
|
||||||
const { searchLibs } = opts;
|
|
||||||
const libs = [
|
|
||||||
'',
|
|
||||||
...(Array.isArray(searchLibs) ? searchLibs : [])
|
|
||||||
];
|
|
||||||
|
|
||||||
for (let lib of libs) {
|
|
||||||
if (typeof lib !== 'string')
|
|
||||||
continue;
|
|
||||||
lib = lib.trim();
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
/* Define ${funcName} to an innocuous variant, in case <limits.h> declares
|
|
||||||
${funcName}.
|
|
||||||
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
|
||||||
#define ${funcName} innocuous_${funcName}
|
|
||||||
/* System header to define __stub macros and hopefully few prototypes,
|
|
||||||
which can conflict with char ${funcName} (); below. */
|
|
||||||
#include <limits.h>
|
|
||||||
#undef ${funcName}
|
|
||||||
/* Override any GCC internal prototype to avoid an error.
|
|
||||||
Use char because int might match the return type of a GCC
|
|
||||||
builtin and then its argument prototype would still apply. */
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
#endif
|
|
||||||
char ${funcName} ();
|
|
||||||
/* The GNU C library defines this for functions which it implements
|
|
||||||
to always fail with ENOSYS. Some functions are actually named
|
|
||||||
something starting with __ and the normal name is an alias. */
|
|
||||||
#if defined __stub_${funcName} || defined __stub___${funcName}
|
|
||||||
choke me
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
return ${funcName} ();
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}`;
|
|
||||||
|
|
||||||
const compilerParams = (lib ? [`-l${lib}`] : []);
|
|
||||||
const result = this.tryCompile(type, code, compilerParams);
|
|
||||||
|
|
||||||
this._debug(
|
|
||||||
`>>> Checking if function '${funcName}' exists `
|
|
||||||
+ `(using ${lib ? `'${lib}'` : 'no'} library)... ${result === true}`
|
|
||||||
);
|
|
||||||
if (result !== true) {
|
|
||||||
this._debug('... check failed with compiler output:');
|
|
||||||
this._debug(result.output);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result === true) {
|
|
||||||
setCachedValue(
|
|
||||||
type,
|
|
||||||
this._cache,
|
|
||||||
'functions',
|
|
||||||
funcName,
|
|
||||||
compilerParams
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkHeader(type, header) {
|
|
||||||
validateType(type);
|
|
||||||
const cached = getCachedValue(
|
|
||||||
type,
|
|
||||||
this._cache,
|
|
||||||
'headers',
|
|
||||||
normalizeHeader(header)
|
|
||||||
);
|
|
||||||
if (cached !== undefined) {
|
|
||||||
this._debug(
|
|
||||||
`>>> Checking if header '${header}' exists... ${cached} (cached)`
|
|
||||||
);
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
const headersList = renderHeaders([header]);
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
${headersList}
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}`;
|
|
||||||
|
|
||||||
const result = this.tryCompile(type, code);
|
|
||||||
setCachedValue(
|
|
||||||
type,
|
|
||||||
this._cache,
|
|
||||||
'headers',
|
|
||||||
normalizeHeader(header),
|
|
||||||
(result === true)
|
|
||||||
);
|
|
||||||
this._debug(
|
|
||||||
`>>> Checking if header '${header}' exists... ${result === true}`
|
|
||||||
);
|
|
||||||
if (result !== true) {
|
|
||||||
this._debug('... check failed with compiler output:');
|
|
||||||
this._debug(result.output);
|
|
||||||
}
|
|
||||||
return (result === true);
|
|
||||||
}
|
|
||||||
|
|
||||||
defines(type, rendered) {
|
|
||||||
if (this._cache === null)
|
|
||||||
return [];
|
|
||||||
|
|
||||||
const defines = new Map();
|
|
||||||
|
|
||||||
let types;
|
|
||||||
if (!['c', 'c++'].includes(type))
|
|
||||||
types = ['c', 'c++'];
|
|
||||||
else
|
|
||||||
types = [type];
|
|
||||||
|
|
||||||
for (const t of types) {
|
|
||||||
const typeCache = this._cache.get(t);
|
|
||||||
if (!typeCache)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (const [subtype, entries] of typeCache) {
|
|
||||||
for (let name of entries.keys()) {
|
|
||||||
if (subtype === 'headers')
|
|
||||||
name = name.replace(RE_HEADER_DECORATED, '$1$2');
|
|
||||||
defines.set(makeDefine(name, rendered), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const featuresCache = this._cache.get('features');
|
|
||||||
if (featuresCache) {
|
|
||||||
for (const result of featuresCache.values()) {
|
|
||||||
if (typeof result === 'object'
|
|
||||||
&& result !== null
|
|
||||||
&& Array.isArray(result.defines)) {
|
|
||||||
for (const define of result.defines)
|
|
||||||
defines.set(makeDefine(define, rendered), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(defines.keys());
|
|
||||||
}
|
|
||||||
|
|
||||||
libs(type) {
|
|
||||||
if (this._cache === null)
|
|
||||||
return [];
|
|
||||||
|
|
||||||
const libs = new Map();
|
|
||||||
|
|
||||||
let types;
|
|
||||||
if (!['c', 'c++'].includes(type))
|
|
||||||
types = ['c', 'c++'];
|
|
||||||
else
|
|
||||||
types = [type];
|
|
||||||
|
|
||||||
for (const t of types) {
|
|
||||||
const typeCache = this._cache.get(t);
|
|
||||||
if (!typeCache)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const functionsCache = typeCache.get('functions');
|
|
||||||
if (!functionsCache)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (const compilerParams of functionsCache.values()) {
|
|
||||||
for (const param of compilerParams)
|
|
||||||
libs.set(param, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const featuresCache = this._cache.get('features');
|
|
||||||
if (featuresCache) {
|
|
||||||
for (const result of featuresCache.values()) {
|
|
||||||
if (typeof result === 'object'
|
|
||||||
&& result !== null
|
|
||||||
&& Array.isArray(result.libs)) {
|
|
||||||
for (const lib of result.libs)
|
|
||||||
libs.set(lib, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(libs.keys());
|
|
||||||
}
|
|
||||||
|
|
||||||
tryCompile(type, code, compilerParams) {
|
|
||||||
validateType(type);
|
|
||||||
if (typeof code !== 'string')
|
|
||||||
throw new TypeError('Invalid code argument');
|
|
||||||
|
|
||||||
type = (type === 'c' ? 'c' : 'c++');
|
|
||||||
const prop = (type === 'c' ? '_cc' : '_cxx');
|
|
||||||
|
|
||||||
if (this[`${prop}Kind`] === undefined)
|
|
||||||
getKind.call(this, prop);
|
|
||||||
|
|
||||||
if (!Array.isArray(compilerParams))
|
|
||||||
compilerParams = [];
|
|
||||||
|
|
||||||
let result;
|
|
||||||
if (this[`${prop}Kind`] === 'msvc') {
|
|
||||||
const cmpOpts = [`-Fo${this._tmpObjFile}`];
|
|
||||||
for (const includePath of this._includePaths)
|
|
||||||
cmpOpts.push('-I', includePath);
|
|
||||||
const lnkOpts = [];
|
|
||||||
for (const libPath of this._libPaths)
|
|
||||||
lnkOpts.push(`-LIBPATH:${libPath}`);
|
|
||||||
for (const opt of compilerParams) {
|
|
||||||
let m;
|
|
||||||
if (m = /^[-/]l(.+)$/.exec(opt))
|
|
||||||
lnkOpts.push(m[1]);
|
|
||||||
else
|
|
||||||
cmpOpts.push(opt);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writeFileSync(this._tmpInFile, code);
|
|
||||||
const args = [
|
|
||||||
...cmpOpts,
|
|
||||||
`-T${prop === '_cc' ? 'c' : 'p'}`,
|
|
||||||
this._tmpInFile,
|
|
||||||
'-link',
|
|
||||||
`-out:${this._tmpOutFile}`,
|
|
||||||
...lnkOpts,
|
|
||||||
];
|
|
||||||
result = spawnSync(
|
|
||||||
this[prop],
|
|
||||||
args,
|
|
||||||
this[`${prop}SpawnOpts`]
|
|
||||||
);
|
|
||||||
unlinkSync(this._tmpInFile);
|
|
||||||
// Overwrite stderr with stdout because MSVC seems to print
|
|
||||||
// errors to stdout instead for some reason
|
|
||||||
result.stderr = result.stdout;
|
|
||||||
} catch (ex) {
|
|
||||||
// We had trouble writing or deleting a temp file, fake
|
|
||||||
// the result
|
|
||||||
result = { status: Infinity, stderr: ex.stack };
|
|
||||||
}
|
|
||||||
try { unlinkSync(this._tmpObjFile); } catch {}
|
|
||||||
try { unlinkSync(this._tmpOutFile); } catch {}
|
|
||||||
} else {
|
|
||||||
result = spawnSync(
|
|
||||||
this[prop],
|
|
||||||
[
|
|
||||||
'-x', type,
|
|
||||||
'-o', '/dev/null',
|
|
||||||
'-',
|
|
||||||
...compilerParams,
|
|
||||||
],
|
|
||||||
{
|
|
||||||
...this[`${prop}SpawnOpts`],
|
|
||||||
input: code,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.status === 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
const err = new Error('Compilation failed');
|
|
||||||
err.output = result.stderr;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateType(type) {
|
|
||||||
if (!['c', 'c++'].includes(type))
|
|
||||||
throw new Error('Invalid type argument');
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCachedValue(type, cache, subtype, key) {
|
|
||||||
if (cache === null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const typeCache = cache.get(type);
|
|
||||||
if (!typeCache)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const subtypeCache = (typeof subtype !== 'string'
|
|
||||||
? typeCache
|
|
||||||
: typeCache.get(subtype));
|
|
||||||
if (!subtypeCache)
|
|
||||||
return;
|
|
||||||
|
|
||||||
return subtypeCache.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCachedValue(type, cache, subtype, key, value) {
|
|
||||||
if (cache === null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let typeCache = cache.get(type);
|
|
||||||
if (!typeCache)
|
|
||||||
cache.set(type, typeCache = new Map());
|
|
||||||
|
|
||||||
let subtypeCache = (typeof subtype !== 'string'
|
|
||||||
? typeCache
|
|
||||||
: typeCache.get(subtype));
|
|
||||||
if (!subtypeCache)
|
|
||||||
typeCache.set(subtype, subtypeCache = new Map());
|
|
||||||
|
|
||||||
subtypeCache.set(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderHeaders(headers) {
|
|
||||||
let ret = '';
|
|
||||||
|
|
||||||
if (Array.isArray(headers)) {
|
|
||||||
for (const header of headers) {
|
|
||||||
if (typeof header !== 'string' || !header)
|
|
||||||
throw new Error(`Invalid header: ${inspect(header)}`);
|
|
||||||
ret += `#include ${normalizeHeader(header)}\n`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeHeader(header) {
|
|
||||||
if (!RE_HEADER_DECORATED.test(header))
|
|
||||||
header = `<${header}>`;
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_HEADERS_POSIX = [
|
|
||||||
'stdio.h',
|
|
||||||
'sys/types.h',
|
|
||||||
'sys/stat.h',
|
|
||||||
'stdlib.h',
|
|
||||||
'stddef.h',
|
|
||||||
'memory.h',
|
|
||||||
'string.h',
|
|
||||||
'strings.h',
|
|
||||||
'inttypes.h',
|
|
||||||
'stdint.h',
|
|
||||||
'unistd.h'
|
|
||||||
];
|
|
||||||
const DEFAULT_HEADERS_MSVC = [
|
|
||||||
'windows.h',
|
|
||||||
];
|
|
||||||
function getDefaultHeaders(be, type) {
|
|
||||||
const prop = (type === 'c' ? '_cc' : '_cxx');
|
|
||||||
if (be[`${prop}Kind`] === undefined)
|
|
||||||
getKind.call(be, prop);
|
|
||||||
|
|
||||||
let headers;
|
|
||||||
if (be[`${prop}Kind`] === 'msvc')
|
|
||||||
headers = DEFAULT_HEADERS_MSVC;
|
|
||||||
else
|
|
||||||
headers = DEFAULT_HEADERS_POSIX;
|
|
||||||
|
|
||||||
return headers.filter((hdr) => be.checkHeader(type, hdr));
|
|
||||||
}
|
|
||||||
|
|
||||||
const features = new Map(Object.entries({
|
|
||||||
'strerror_r': (be) => {
|
|
||||||
const defines = [];
|
|
||||||
let returnsCharPtr = false;
|
|
||||||
|
|
||||||
const declared = be.checkDeclared('c', 'strerror_r');
|
|
||||||
if (declared) {
|
|
||||||
const code = `
|
|
||||||
${renderHeaders(getDefaultHeaders(be, 'c'))}
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
|
|
||||||
char buf[100];
|
|
||||||
char x = *strerror_r (0, buf, sizeof buf);
|
|
||||||
char *p = strerror_r (0, buf, sizeof buf);
|
|
||||||
return !p || x;
|
|
||||||
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}`;
|
|
||||||
returnsCharPtr = (be.tryCompile('c', code) === true);
|
|
||||||
if (returnsCharPtr)
|
|
||||||
defines.push('STRERROR_R_CHAR_P');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
defines,
|
|
||||||
val: { declared, returnsCharPtr }
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
function makeDefine(name, rendered) {
|
|
||||||
name = name.replace(/[*]/g, 'P')
|
|
||||||
.replace(/[^_A-Za-z0-9]/g, '_')
|
|
||||||
.toUpperCase();
|
|
||||||
return (rendered ? `HAVE_${name}=1` : name);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = BuildEnvironment;
|
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
"name": "buildcheck",
|
|
||||||
"version": "0.0.6",
|
|
||||||
"author": "Brian White <mscdex@mscdex.net>",
|
|
||||||
"description": "Build environment checking (a la autoconf) for node.js",
|
|
||||||
"main": "./lib/index.js",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@mscdex/eslint-config": "^1.1.0",
|
|
||||||
"eslint": "^7.0.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "node test/test.js",
|
|
||||||
"lint": "eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib",
|
|
||||||
"lint:fix": "npm run lint -- --fix"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"build",
|
|
||||||
"autoconf",
|
|
||||||
"addons",
|
|
||||||
"compiler",
|
|
||||||
"environment"
|
|
||||||
],
|
|
||||||
"licenses": [
|
|
||||||
{
|
|
||||||
"type": "MIT",
|
|
||||||
"url": "http://github.com/mscdex/buildcheck/raw/master/LICENSE"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "http://github.com/mscdex/buildcheck.git"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const BE = require('..');
|
|
||||||
|
|
||||||
{
|
|
||||||
// Test compiler detection
|
|
||||||
new BE({ debug: console.log });
|
|
||||||
}
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) EGOIST <0x142857@gmail.com> (https://github.com/egoist)
|
||||||
|
|
||||||
|
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.
|
|
@ -0,0 +1,536 @@
|
||||||
|
<img width="945" alt="2017-07-26 9 27 05" src="https://user-images.githubusercontent.com/8784712/28623641-373450f4-7249-11e7-854d-1b076dab274d.png">
|
||||||
|
|
||||||
|
[![NPM version](https://img.shields.io/npm/v/cac.svg?style=flat)](https://npmjs.com/package/cac) [![NPM downloads](https://img.shields.io/npm/dm/cac.svg?style=flat)](https://npmjs.com/package/cac) [![CircleCI](https://circleci.com/gh/cacjs/cac/tree/master.svg?style=shield)](https://circleci.com/gh/cacjs/cac/tree/master) [![Codecov](https://badgen.net/codecov/c/github/cacjs/cac/master)](https://codecov.io/gh/cacjs/cac) [![donate](https://img.shields.io/badge/$-donate-ff69b4.svg?maxAge=2592000&style=flat)](https://github.com/egoist/donate) [![chat](https://img.shields.io/badge/chat-on%20discord-7289DA.svg?style=flat)](https://chat.egoist.moe) [![install size](https://badgen.net/packagephobia/install/cac)](https://packagephobia.now.sh/result?p=cac)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
**C**ommand **A**nd **C**onquer is a JavaScript library for building CLI apps.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Super light-weight**: No dependency, just a single file.
|
||||||
|
- **Easy to learn**. There're only 4 APIs you need to learn for building simple CLIs: `cli.option` `cli.version` `cli.help` `cli.parse`.
|
||||||
|
- **Yet so powerful**. Enable features like default command, git-like subcommands, validation for required arguments and options, variadic arguments, dot-nested options, automated help message generation and so on.
|
||||||
|
- **Developer friendly**. Written in TypeScript.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
<!-- toc -->
|
||||||
|
|
||||||
|
- [Install](#install)
|
||||||
|
- [Usage](#usage)
|
||||||
|
- [Simple Parsing](#simple-parsing)
|
||||||
|
- [Display Help Message and Version](#display-help-message-and-version)
|
||||||
|
- [Command-specific Options](#command-specific-options)
|
||||||
|
- [Dash in option names](#dash-in-option-names)
|
||||||
|
- [Brackets](#brackets)
|
||||||
|
- [Negated Options](#negated-options)
|
||||||
|
- [Variadic Arguments](#variadic-arguments)
|
||||||
|
- [Dot-nested Options](#dot-nested-options)
|
||||||
|
- [Default Command](#default-command)
|
||||||
|
- [Supply an array as option value](#supply-an-array-as-option-value)
|
||||||
|
- [Error Handling](#error-handling)
|
||||||
|
- [With TypeScript](#with-typescript)
|
||||||
|
- [With Deno](#with-deno)
|
||||||
|
- [Projects Using CAC](#projects-using-cac)
|
||||||
|
- [References](#references)
|
||||||
|
- [CLI Instance](#cli-instance)
|
||||||
|
- [cac(name?)](#cacname)
|
||||||
|
- [cli.command(name, description, config?)](#clicommandname-description-config)
|
||||||
|
- [cli.option(name, description, config?)](#clioptionname-description-config)
|
||||||
|
- [cli.parse(argv?)](#cliparseargv)
|
||||||
|
- [cli.version(version, customFlags?)](#cliversionversion-customflags)
|
||||||
|
- [cli.help(callback?)](#clihelpcallback)
|
||||||
|
- [cli.outputHelp()](#clioutputhelp)
|
||||||
|
- [cli.usage(text)](#cliusagetext)
|
||||||
|
- [Command Instance](#command-instance)
|
||||||
|
- [command.option()](#commandoption)
|
||||||
|
- [command.action(callback)](#commandactioncallback)
|
||||||
|
- [command.alias(name)](#commandaliasname)
|
||||||
|
- [command.allowUnknownOptions()](#commandallowunknownoptions)
|
||||||
|
- [command.example(example)](#commandexampleexample)
|
||||||
|
- [command.usage(text)](#commandusagetext)
|
||||||
|
- [Events](#events)
|
||||||
|
- [FAQ](#faq)
|
||||||
|
- [How is the name written and pronounced?](#how-is-the-name-written-and-pronounced)
|
||||||
|
- [Why not use Commander.js?](#why-not-use-commanderjs)
|
||||||
|
- [Project Stats](#project-stats)
|
||||||
|
- [Contributing](#contributing)
|
||||||
|
- [Author](#author)
|
||||||
|
|
||||||
|
<!-- tocstop -->
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn add cac
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Simple Parsing
|
||||||
|
|
||||||
|
Use CAC as simple argument parser:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// examples/basic-usage.js
|
||||||
|
const cli = require('cac')()
|
||||||
|
|
||||||
|
cli.option('--type <type>', 'Choose a project type', {
|
||||||
|
default: 'node',
|
||||||
|
})
|
||||||
|
|
||||||
|
const parsed = cli.parse()
|
||||||
|
|
||||||
|
console.log(JSON.stringify(parsed, null, 2))
|
||||||
|
```
|
||||||
|
|
||||||
|
<img width="500" alt="2018-11-26 12 28 03" src="https://user-images.githubusercontent.com/8784712/48981576-2a871000-f112-11e8-8151-80f61e9b9908.png">
|
||||||
|
|
||||||
|
### Display Help Message and Version
|
||||||
|
|
||||||
|
```js
|
||||||
|
// examples/help.js
|
||||||
|
const cli = require('cac')()
|
||||||
|
|
||||||
|
cli.option('--type [type]', 'Choose a project type', {
|
||||||
|
default: 'node',
|
||||||
|
})
|
||||||
|
cli.option('--name <name>', 'Provide your name')
|
||||||
|
|
||||||
|
cli.command('lint [...files]', 'Lint files').action((files, options) => {
|
||||||
|
console.log(files, options)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Display help message when `-h` or `--help` appears
|
||||||
|
cli.help()
|
||||||
|
// Display version number when `-v` or `--version` appears
|
||||||
|
// It's also used in help message
|
||||||
|
cli.version('0.0.0')
|
||||||
|
|
||||||
|
cli.parse()
|
||||||
|
```
|
||||||
|
|
||||||
|
<img width="500" alt="2018-11-25 8 21 14" src="https://user-images.githubusercontent.com/8784712/48979012-acb20d00-f0ef-11e8-9cc6-8ffca00ab78a.png">
|
||||||
|
|
||||||
|
### Command-specific Options
|
||||||
|
|
||||||
|
You can attach options to a command.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cli = require('cac')()
|
||||||
|
|
||||||
|
cli
|
||||||
|
.command('rm <dir>', 'Remove a dir')
|
||||||
|
.option('-r, --recursive', 'Remove recursively')
|
||||||
|
.action((dir, options) => {
|
||||||
|
console.log('remove ' + dir + (options.recursive ? ' recursively' : ''))
|
||||||
|
})
|
||||||
|
|
||||||
|
cli.help()
|
||||||
|
|
||||||
|
cli.parse()
|
||||||
|
```
|
||||||
|
|
||||||
|
A command's options are validated when the command is used. Any unknown options will be reported as an error. However, if an action-based command does not define an action, then the options are not validated. If you really want to use unknown options, use [`command.allowUnknownOptions`](#commandallowunknownoptions).
|
||||||
|
|
||||||
|
<img alt="command options" width="500" src="https://user-images.githubusercontent.com/8784712/49065552-49dc8500-f259-11e8-9c7b-a7c32d70920e.png">
|
||||||
|
|
||||||
|
### Dash in option names
|
||||||
|
|
||||||
|
Options in kebab-case should be referenced in camelCase in your code:
|
||||||
|
|
||||||
|
```js
|
||||||
|
cli
|
||||||
|
.command('dev', 'Start dev server')
|
||||||
|
.option('--clear-screen', 'Clear screen')
|
||||||
|
.action((options) => {
|
||||||
|
console.log(options.clearScreen)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
In fact `--clear-screen` and `--clearScreen` are both mapped to `options.clearScreen`.
|
||||||
|
|
||||||
|
### Brackets
|
||||||
|
|
||||||
|
When using brackets in command name, angled brackets indicate required command arguments, while square bracket indicate optional arguments.
|
||||||
|
|
||||||
|
When using brackets in option name, angled brackets indicate that a string / number value is required, while square bracket indicate that the value can also be `true`.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cli = require('cac')()
|
||||||
|
|
||||||
|
cli
|
||||||
|
.command('deploy <folder>', 'Deploy a folder to AWS')
|
||||||
|
.option('--scale [level]', 'Scaling level')
|
||||||
|
.action((folder, options) => {
|
||||||
|
// ...
|
||||||
|
})
|
||||||
|
|
||||||
|
cli
|
||||||
|
.command('build [project]', 'Build a project')
|
||||||
|
.option('--out <dir>', 'Output directory')
|
||||||
|
.action((folder, options) => {
|
||||||
|
// ...
|
||||||
|
})
|
||||||
|
|
||||||
|
cli.parse()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Negated Options
|
||||||
|
|
||||||
|
To allow an option whose value is `false`, you need to manually specify a negated option:
|
||||||
|
|
||||||
|
```js
|
||||||
|
cli
|
||||||
|
.command('build [project]', 'Build a project')
|
||||||
|
.option('--no-config', 'Disable config file')
|
||||||
|
.option('--config <path>', 'Use a custom config file')
|
||||||
|
```
|
||||||
|
|
||||||
|
This will let CAC set the default value of `config` to true, and you can use `--no-config` flag to set it to `false`.
|
||||||
|
|
||||||
|
### Variadic Arguments
|
||||||
|
|
||||||
|
The last argument of a command can be variadic, and only the last argument. To make an argument variadic you have to add `...` to the start of argument name, just like the rest operator in JavaScript. Here is an example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cli = require('cac')()
|
||||||
|
|
||||||
|
cli
|
||||||
|
.command('build <entry> [...otherFiles]', 'Build your app')
|
||||||
|
.option('--foo', 'Foo option')
|
||||||
|
.action((entry, otherFiles, options) => {
|
||||||
|
console.log(entry)
|
||||||
|
console.log(otherFiles)
|
||||||
|
console.log(options)
|
||||||
|
})
|
||||||
|
|
||||||
|
cli.help()
|
||||||
|
|
||||||
|
cli.parse()
|
||||||
|
```
|
||||||
|
|
||||||
|
<img width="500" alt="2018-11-25 8 25 30" src="https://user-images.githubusercontent.com/8784712/48979056-47125080-f0f0-11e8-9d8f-3219e0beb0ed.png">
|
||||||
|
|
||||||
|
### Dot-nested Options
|
||||||
|
|
||||||
|
Dot-nested options will be merged into a single option.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cli = require('cac')()
|
||||||
|
|
||||||
|
cli
|
||||||
|
.command('build', 'desc')
|
||||||
|
.option('--env <env>', 'Set envs')
|
||||||
|
.example('--env.API_SECRET xxx')
|
||||||
|
.action((options) => {
|
||||||
|
console.log(options)
|
||||||
|
})
|
||||||
|
|
||||||
|
cli.help()
|
||||||
|
|
||||||
|
cli.parse()
|
||||||
|
```
|
||||||
|
|
||||||
|
<img width="500" alt="2018-11-25 9 37 53" src="https://user-images.githubusercontent.com/8784712/48979771-6ada9400-f0fa-11e8-8192-e541b2cfd9da.png">
|
||||||
|
|
||||||
|
### Default Command
|
||||||
|
|
||||||
|
Register a command that will be used when no other command is matched.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cli = require('cac')()
|
||||||
|
|
||||||
|
cli
|
||||||
|
// Simply omit the command name, just brackets
|
||||||
|
.command('[...files]', 'Build files')
|
||||||
|
.option('--minimize', 'Minimize output')
|
||||||
|
.action((files, options) => {
|
||||||
|
console.log(files)
|
||||||
|
console.log(options.minimize)
|
||||||
|
})
|
||||||
|
|
||||||
|
cli.parse()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supply an array as option value
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node cli.js --include project-a
|
||||||
|
# The parsed options will be:
|
||||||
|
# { include: 'project-a' }
|
||||||
|
|
||||||
|
node cli.js --include project-a --include project-b
|
||||||
|
# The parsed options will be:
|
||||||
|
# { include: ['project-a', 'project-b'] }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
To handle command errors globally:
|
||||||
|
|
||||||
|
```js
|
||||||
|
try {
|
||||||
|
// Parse CLI args without running the command
|
||||||
|
cli.parse(process.argv, { run: false })
|
||||||
|
// Run the command yourself
|
||||||
|
// You only need `await` when your command action returns a Promise
|
||||||
|
await cli.runMatchedCommand()
|
||||||
|
} catch (error) {
|
||||||
|
// Handle error here..
|
||||||
|
// e.g.
|
||||||
|
// console.error(error.stack)
|
||||||
|
// process.exit(1)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### With TypeScript
|
||||||
|
|
||||||
|
First you need `@types/node` to be installed as a dev dependency in your project:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn add @types/node --dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Then everything just works out of the box:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { cac } = require('cac')
|
||||||
|
// OR ES modules
|
||||||
|
import { cac } from 'cac'
|
||||||
|
```
|
||||||
|
|
||||||
|
### With Deno
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { cac } from 'https://unpkg.com/cac/mod.ts'
|
||||||
|
|
||||||
|
const cli = cac('my-program')
|
||||||
|
```
|
||||||
|
|
||||||
|
## Projects Using CAC
|
||||||
|
|
||||||
|
Projects that use **CAC**:
|
||||||
|
|
||||||
|
- [VuePress](https://github.com/vuejs/vuepress): :memo: Minimalistic Vue-powered static site generator.
|
||||||
|
- [SAO](https://github.com/egoist/sao): ⚔️ Futuristic scaffolding tool.
|
||||||
|
- [DocPad](https://github.com/docpad/docpad): 🏹 Powerful Static Site Generator.
|
||||||
|
- [Poi](https://github.com/egoist/poi): ⚡️ Delightful web development.
|
||||||
|
- [bili](https://github.com/egoist/bili): 🥂 Schweizer Armeemesser for bundling JavaScript libraries.
|
||||||
|
- [Lad](https://github.com/ladjs/lad): 👦 Lad scaffolds a Koa webapp and API framework for Node.js.
|
||||||
|
- [Lass](https://github.com/lassjs/lass): 💁🏻 Scaffold a modern package boilerplate for Node.js.
|
||||||
|
- [Foy](https://github.com/zaaack/foy): 🏗 A lightweight and modern task runner and build tool for general purpose.
|
||||||
|
- [Vuese](https://github.com/vuese/vuese): 🤗 One-stop solution for vue component documentation.
|
||||||
|
- [NUT](https://github.com/nut-project/nut): 🌰 A framework born for microfrontends
|
||||||
|
- Feel free to add yours here...
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
**💁 Check out [the generated docs](https://cac-api-doc.egoist.sh/classes/_cac_.cac.html) from source code if you want a more in-depth API references.**
|
||||||
|
|
||||||
|
Below is a brief overview.
|
||||||
|
|
||||||
|
### CLI Instance
|
||||||
|
|
||||||
|
CLI instance is created by invoking the `cac` function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cac = require('cac')
|
||||||
|
const cli = cac()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### cac(name?)
|
||||||
|
|
||||||
|
Create a CLI instance, optionally specify the program name which will be used to display in help and version message. When not set we use the basename of `argv[1]`.
|
||||||
|
|
||||||
|
#### cli.command(name, description, config?)
|
||||||
|
|
||||||
|
- Type: `(name: string, description: string) => Command`
|
||||||
|
|
||||||
|
Create a command instance.
|
||||||
|
|
||||||
|
The option also accepts a third argument `config` for additional command config:
|
||||||
|
|
||||||
|
- `config.allowUnknownOptions`: `boolean` Allow unknown options in this command.
|
||||||
|
- `config.ignoreOptionDefaultValue`: `boolean` Don't use the options's default value in parsed options, only display them in help message.
|
||||||
|
|
||||||
|
#### cli.option(name, description, config?)
|
||||||
|
|
||||||
|
- Type: `(name: string, description: string, config?: OptionConfig) => CLI`
|
||||||
|
|
||||||
|
Add a global option.
|
||||||
|
|
||||||
|
The option also accepts a third argument `config` for additional option config:
|
||||||
|
|
||||||
|
- `config.default`: Default value for the option.
|
||||||
|
- `config.type`: `any[]` When set to `[]`, the option value returns an array type. You can also use a conversion function such as `[String]`, which will invoke the option value with `String`.
|
||||||
|
|
||||||
|
#### cli.parse(argv?)
|
||||||
|
|
||||||
|
- Type: `(argv = process.argv) => ParsedArgv`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface ParsedArgv {
|
||||||
|
args: string[]
|
||||||
|
options: {
|
||||||
|
[k: string]: any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When this method is called, `cli.rawArgs` `cli.args` `cli.options` `cli.matchedCommand` will also be available.
|
||||||
|
|
||||||
|
#### cli.version(version, customFlags?)
|
||||||
|
|
||||||
|
- Type: `(version: string, customFlags = '-v, --version') => CLI`
|
||||||
|
|
||||||
|
Output version number when `-v, --version` flag appears.
|
||||||
|
|
||||||
|
#### cli.help(callback?)
|
||||||
|
|
||||||
|
- Type: `(callback?: HelpCallback) => CLI`
|
||||||
|
|
||||||
|
Output help message when `-h, --help` flag appears.
|
||||||
|
|
||||||
|
Optional `callback` allows post-processing of help text before it is displayed:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type HelpCallback = (sections: HelpSection[]) => void
|
||||||
|
|
||||||
|
interface HelpSection {
|
||||||
|
title?: string
|
||||||
|
body: string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### cli.outputHelp()
|
||||||
|
|
||||||
|
- Type: `() => CLI`
|
||||||
|
|
||||||
|
Output help message.
|
||||||
|
|
||||||
|
#### cli.usage(text)
|
||||||
|
|
||||||
|
- Type: `(text: string) => CLI`
|
||||||
|
|
||||||
|
Add a global usage text. This is not used by sub-commands.
|
||||||
|
|
||||||
|
### Command Instance
|
||||||
|
|
||||||
|
Command instance is created by invoking the `cli.command` method:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const command = cli.command('build [...files]', 'Build given files')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### command.option()
|
||||||
|
|
||||||
|
Basically the same as `cli.option` but this adds the option to specific command.
|
||||||
|
|
||||||
|
#### command.action(callback)
|
||||||
|
|
||||||
|
- Type: `(callback: ActionCallback) => Command`
|
||||||
|
|
||||||
|
Use a callback function as the command action when the command matches user inputs.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type ActionCallback = (
|
||||||
|
// Parsed CLI args
|
||||||
|
// The last arg will be an array if it's a variadic argument
|
||||||
|
...args: string | string[] | number | number[]
|
||||||
|
// Parsed CLI options
|
||||||
|
options: Options
|
||||||
|
) => any
|
||||||
|
|
||||||
|
interface Options {
|
||||||
|
[k: string]: any
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### command.alias(name)
|
||||||
|
|
||||||
|
- Type: `(name: string) => Command`
|
||||||
|
|
||||||
|
Add an alias name to this command, the `name` here can't contain brackets.
|
||||||
|
|
||||||
|
#### command.allowUnknownOptions()
|
||||||
|
|
||||||
|
- Type: `() => Command`
|
||||||
|
|
||||||
|
Allow unknown options in this command, by default CAC will log an error when unknown options are used.
|
||||||
|
|
||||||
|
#### command.example(example)
|
||||||
|
|
||||||
|
- Type: `(example: CommandExample) => Command`
|
||||||
|
|
||||||
|
Add an example which will be displayed at the end of help message.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type CommandExample = ((name: string) => string) | string
|
||||||
|
```
|
||||||
|
|
||||||
|
#### command.usage(text)
|
||||||
|
|
||||||
|
- Type: `(text: string) => Command`
|
||||||
|
|
||||||
|
Add a usage text for this command.
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
Listen to commands:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Listen to the `foo` command
|
||||||
|
cli.on('command:foo', () => {
|
||||||
|
// Do something
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen to the default command
|
||||||
|
cli.on('command:!', () => {
|
||||||
|
// Do something
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen to unknown commands
|
||||||
|
cli.on('command:*', () => {
|
||||||
|
console.error('Invalid command: %s', cli.args.join(' '))
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### How is the name written and pronounced?
|
||||||
|
|
||||||
|
CAC, or cac, pronounced `C-A-C`.
|
||||||
|
|
||||||
|
This project is dedicated to our lovely C.C. sama. Maybe CAC stands for C&C as well :P
|
||||||
|
|
||||||
|
<img src="http://i.giphy.com/v3FeH4swox9mg.gif" width="400"/>
|
||||||
|
|
||||||
|
### Why not use Commander.js?
|
||||||
|
|
||||||
|
CAC is very similar to Commander.js, while the latter does not support dot nested options, i.e. something like `--env.API_SECRET foo`. Besides, you can't use unknown options in Commander.js either.
|
||||||
|
|
||||||
|
_And maybe more..._
|
||||||
|
|
||||||
|
Basically I made CAC to fulfill my own needs for building CLI apps like [Poi](https://poi.js.org), [SAO](https://sao.vercel.app) and all my CLI apps. It's small, simple but powerful :P
|
||||||
|
|
||||||
|
## Project Stats
|
||||||
|
|
||||||
|
![Alt](https://repobeats.axiom.co/api/embed/58caf6203631bcdb9bbe22f0728a0af1683dc0bb.svg 'Repobeats analytics image')
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork it!
|
||||||
|
2. Create your feature branch: `git checkout -b my-new-feature`
|
||||||
|
3. Commit your changes: `git commit -am 'Add some feature'`
|
||||||
|
4. Push to the branch: `git push origin my-new-feature`
|
||||||
|
5. Submit a pull request :D
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
**CAC** © [EGOIST](https://github.com/egoist), Released under the [MIT](./LICENSE) License.<br>
|
||||||
|
Authored and maintained by egoist with help from contributors ([list](https://github.com/cacjs/cac/contributors)).
|
||||||
|
|
||||||
|
> [Website](https://egoist.sh) · GitHub [@egoist](https://github.com/egoist) · Twitter [@\_egoistlily](https://twitter.com/_egoistlily)
|
|
@ -0,0 +1,331 @@
|
||||||
|
import { EventEmitter } from "https://deno.land/std@0.114.0/node/events.ts";
|
||||||
|
import mri from "https://cdn.skypack.dev/mri";
|
||||||
|
import Command, { GlobalCommand, CommandConfig, HelpCallback, CommandExample } from "./Command.ts";
|
||||||
|
import { OptionConfig } from "./Option.ts";
|
||||||
|
import { getMriOptions, setDotProp, setByType, getFileName, camelcaseOptionName } from "./utils.ts";
|
||||||
|
import { processArgs } from "./deno.ts";
|
||||||
|
interface ParsedArgv {
|
||||||
|
args: ReadonlyArray<string>;
|
||||||
|
options: {
|
||||||
|
[k: string]: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class CAC extends EventEmitter {
|
||||||
|
/** The program name to display in help and version message */
|
||||||
|
name: string;
|
||||||
|
commands: Command[];
|
||||||
|
globalCommand: GlobalCommand;
|
||||||
|
matchedCommand?: Command;
|
||||||
|
matchedCommandName?: string;
|
||||||
|
/**
|
||||||
|
* Raw CLI arguments
|
||||||
|
*/
|
||||||
|
|
||||||
|
rawArgs: string[];
|
||||||
|
/**
|
||||||
|
* Parsed CLI arguments
|
||||||
|
*/
|
||||||
|
|
||||||
|
args: ParsedArgv['args'];
|
||||||
|
/**
|
||||||
|
* Parsed CLI options, camelCased
|
||||||
|
*/
|
||||||
|
|
||||||
|
options: ParsedArgv['options'];
|
||||||
|
showHelpOnExit?: boolean;
|
||||||
|
showVersionOnExit?: boolean;
|
||||||
|
/**
|
||||||
|
* @param name The program name to display in help and version message
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(name = '') {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
this.commands = [];
|
||||||
|
this.rawArgs = [];
|
||||||
|
this.args = [];
|
||||||
|
this.options = {};
|
||||||
|
this.globalCommand = new GlobalCommand(this);
|
||||||
|
this.globalCommand.usage('<command> [options]');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a global usage text.
|
||||||
|
*
|
||||||
|
* This is not used by sub-commands.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
usage(text: string) {
|
||||||
|
this.globalCommand.usage(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a sub-command
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
command(rawName: string, description?: string, config?: CommandConfig) {
|
||||||
|
const command = new Command(rawName, description || '', config, this);
|
||||||
|
command.globalCommand = this.globalCommand;
|
||||||
|
this.commands.push(command);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a global CLI option.
|
||||||
|
*
|
||||||
|
* Which is also applied to sub-commands.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
option(rawName: string, description: string, config?: OptionConfig) {
|
||||||
|
this.globalCommand.option(rawName, description, config);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Show help message when `-h, --help` flags appear.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
help(callback?: HelpCallback) {
|
||||||
|
this.globalCommand.option('-h, --help', 'Display this message');
|
||||||
|
this.globalCommand.helpCallback = callback;
|
||||||
|
this.showHelpOnExit = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Show version number when `-v, --version` flags appear.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
version(version: string, customFlags = '-v, --version') {
|
||||||
|
this.globalCommand.version(version, customFlags);
|
||||||
|
this.showVersionOnExit = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a global example.
|
||||||
|
*
|
||||||
|
* This example added here will not be used by sub-commands.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
example(example: CommandExample) {
|
||||||
|
this.globalCommand.example(example);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Output the corresponding help message
|
||||||
|
* When a sub-command is matched, output the help message for the command
|
||||||
|
* Otherwise output the global one.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
outputHelp() {
|
||||||
|
if (this.matchedCommand) {
|
||||||
|
this.matchedCommand.outputHelp();
|
||||||
|
} else {
|
||||||
|
this.globalCommand.outputHelp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Output the version number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
outputVersion() {
|
||||||
|
this.globalCommand.outputVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setParsedInfo({
|
||||||
|
args,
|
||||||
|
options
|
||||||
|
}: ParsedArgv, matchedCommand?: Command, matchedCommandName?: string) {
|
||||||
|
this.args = args;
|
||||||
|
this.options = options;
|
||||||
|
|
||||||
|
if (matchedCommand) {
|
||||||
|
this.matchedCommand = matchedCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchedCommandName) {
|
||||||
|
this.matchedCommandName = matchedCommandName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsetMatchedCommand() {
|
||||||
|
this.matchedCommand = undefined;
|
||||||
|
this.matchedCommandName = undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse argv
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
parse(argv = processArgs, {
|
||||||
|
/** Whether to run the action for matched command */
|
||||||
|
run = true
|
||||||
|
} = {}): ParsedArgv {
|
||||||
|
this.rawArgs = argv;
|
||||||
|
|
||||||
|
if (!this.name) {
|
||||||
|
this.name = argv[1] ? getFileName(argv[1]) : 'cli';
|
||||||
|
}
|
||||||
|
|
||||||
|
let shouldParse = true; // Search sub-commands
|
||||||
|
|
||||||
|
for (const command of this.commands) {
|
||||||
|
const parsed = this.mri(argv.slice(2), command);
|
||||||
|
const commandName = parsed.args[0];
|
||||||
|
|
||||||
|
if (command.isMatched(commandName)) {
|
||||||
|
shouldParse = false;
|
||||||
|
const parsedInfo = { ...parsed,
|
||||||
|
args: parsed.args.slice(1)
|
||||||
|
};
|
||||||
|
this.setParsedInfo(parsedInfo, command, commandName);
|
||||||
|
this.emit(`command:${commandName}`, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldParse) {
|
||||||
|
// Search the default command
|
||||||
|
for (const command of this.commands) {
|
||||||
|
if (command.name === '') {
|
||||||
|
shouldParse = false;
|
||||||
|
const parsed = this.mri(argv.slice(2), command);
|
||||||
|
this.setParsedInfo(parsed, command);
|
||||||
|
this.emit(`command:!`, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldParse) {
|
||||||
|
const parsed = this.mri(argv.slice(2));
|
||||||
|
this.setParsedInfo(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.help && this.showHelpOnExit) {
|
||||||
|
this.outputHelp();
|
||||||
|
run = false;
|
||||||
|
this.unsetMatchedCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) {
|
||||||
|
this.outputVersion();
|
||||||
|
run = false;
|
||||||
|
this.unsetMatchedCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedArgv = {
|
||||||
|
args: this.args,
|
||||||
|
options: this.options
|
||||||
|
};
|
||||||
|
|
||||||
|
if (run) {
|
||||||
|
this.runMatchedCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.matchedCommand && this.args[0]) {
|
||||||
|
this.emit('command:*');
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedArgv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private mri(argv: string[],
|
||||||
|
/** Matched command */
|
||||||
|
command?: Command): ParsedArgv {
|
||||||
|
// All added options
|
||||||
|
const cliOptions = [...this.globalCommand.options, ...(command ? command.options : [])];
|
||||||
|
const mriOptions = getMriOptions(cliOptions); // Extract everything after `--` since mri doesn't support it
|
||||||
|
|
||||||
|
let argsAfterDoubleDashes: string[] = [];
|
||||||
|
const doubleDashesIndex = argv.indexOf('--');
|
||||||
|
|
||||||
|
if (doubleDashesIndex > -1) {
|
||||||
|
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
|
||||||
|
argv = argv.slice(0, doubleDashesIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parsed = mri(argv, mriOptions);
|
||||||
|
parsed = Object.keys(parsed).reduce((res, name) => {
|
||||||
|
return { ...res,
|
||||||
|
[camelcaseOptionName(name)]: parsed[name]
|
||||||
|
};
|
||||||
|
}, {
|
||||||
|
_: []
|
||||||
|
});
|
||||||
|
const args = parsed._;
|
||||||
|
const options: {
|
||||||
|
[k: string]: any;
|
||||||
|
} = {
|
||||||
|
'--': argsAfterDoubleDashes
|
||||||
|
}; // Set option default value
|
||||||
|
|
||||||
|
const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
|
||||||
|
let transforms = Object.create(null);
|
||||||
|
|
||||||
|
for (const cliOption of cliOptions) {
|
||||||
|
if (!ignoreDefault && cliOption.config.default !== undefined) {
|
||||||
|
for (const name of cliOption.names) {
|
||||||
|
options[name] = cliOption.config.default;
|
||||||
|
}
|
||||||
|
} // If options type is defined
|
||||||
|
|
||||||
|
|
||||||
|
if (Array.isArray(cliOption.config.type)) {
|
||||||
|
if (transforms[cliOption.name] === undefined) {
|
||||||
|
transforms[cliOption.name] = Object.create(null);
|
||||||
|
transforms[cliOption.name]['shouldTransform'] = true;
|
||||||
|
transforms[cliOption.name]['transformFunction'] = cliOption.config.type[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // Set option values (support dot-nested property name)
|
||||||
|
|
||||||
|
|
||||||
|
for (const key of Object.keys(parsed)) {
|
||||||
|
if (key !== '_') {
|
||||||
|
const keys = key.split('.');
|
||||||
|
setDotProp(options, keys, parsed[key]);
|
||||||
|
setByType(options, transforms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
args,
|
||||||
|
options
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
runMatchedCommand() {
|
||||||
|
const {
|
||||||
|
args,
|
||||||
|
options,
|
||||||
|
matchedCommand: command
|
||||||
|
} = this;
|
||||||
|
if (!command || !command.commandAction) return;
|
||||||
|
command.checkUnknownOptions();
|
||||||
|
command.checkOptionValue();
|
||||||
|
command.checkRequiredArgs();
|
||||||
|
const actionArgs: any[] = [];
|
||||||
|
command.args.forEach((arg, index) => {
|
||||||
|
if (arg.variadic) {
|
||||||
|
actionArgs.push(args.slice(index));
|
||||||
|
} else {
|
||||||
|
actionArgs.push(args[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
actionArgs.push(options);
|
||||||
|
return command.commandAction.apply(this, actionArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CAC;
|
|
@ -0,0 +1,269 @@
|
||||||
|
import CAC from "./CAC.ts";
|
||||||
|
import Option, { OptionConfig } from "./Option.ts";
|
||||||
|
import { removeBrackets, findAllBrackets, findLongest, padRight, CACError } from "./utils.ts";
|
||||||
|
import { platformInfo } from "./deno.ts";
|
||||||
|
interface CommandArg {
|
||||||
|
required: boolean;
|
||||||
|
value: string;
|
||||||
|
variadic: boolean;
|
||||||
|
}
|
||||||
|
interface HelpSection {
|
||||||
|
title?: string;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
|
interface CommandConfig {
|
||||||
|
allowUnknownOptions?: boolean;
|
||||||
|
ignoreOptionDefaultValue?: boolean;
|
||||||
|
}
|
||||||
|
type HelpCallback = (sections: HelpSection[]) => void | HelpSection[];
|
||||||
|
type CommandExample = ((bin: string) => string) | string;
|
||||||
|
|
||||||
|
class Command {
|
||||||
|
options: Option[];
|
||||||
|
aliasNames: string[];
|
||||||
|
/* Parsed command name */
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
args: CommandArg[];
|
||||||
|
commandAction?: (...args: any[]) => any;
|
||||||
|
usageText?: string;
|
||||||
|
versionNumber?: string;
|
||||||
|
examples: CommandExample[];
|
||||||
|
helpCallback?: HelpCallback;
|
||||||
|
globalCommand?: GlobalCommand;
|
||||||
|
|
||||||
|
constructor(public rawName: string, public description: string, public config: CommandConfig = {}, public cli: CAC) {
|
||||||
|
this.options = [];
|
||||||
|
this.aliasNames = [];
|
||||||
|
this.name = removeBrackets(rawName);
|
||||||
|
this.args = findAllBrackets(rawName);
|
||||||
|
this.examples = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
usage(text: string) {
|
||||||
|
this.usageText = text;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
allowUnknownOptions() {
|
||||||
|
this.config.allowUnknownOptions = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignoreOptionDefaultValue() {
|
||||||
|
this.config.ignoreOptionDefaultValue = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
version(version: string, customFlags = '-v, --version') {
|
||||||
|
this.versionNumber = version;
|
||||||
|
this.option(customFlags, 'Display version number');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
example(example: CommandExample) {
|
||||||
|
this.examples.push(example);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a option for this command
|
||||||
|
* @param rawName Raw option name(s)
|
||||||
|
* @param description Option description
|
||||||
|
* @param config Option config
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
option(rawName: string, description: string, config?: OptionConfig) {
|
||||||
|
const option = new Option(rawName, description, config);
|
||||||
|
this.options.push(option);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
alias(name: string) {
|
||||||
|
this.aliasNames.push(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
action(callback: (...args: any[]) => any) {
|
||||||
|
this.commandAction = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check if a command name is matched by this command
|
||||||
|
* @param name Command name
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
isMatched(name: string) {
|
||||||
|
return this.name === name || this.aliasNames.includes(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
get isDefaultCommand() {
|
||||||
|
return this.name === '' || this.aliasNames.includes('!');
|
||||||
|
}
|
||||||
|
|
||||||
|
get isGlobalCommand(): boolean {
|
||||||
|
return this instanceof GlobalCommand;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check if an option is registered in this command
|
||||||
|
* @param name Option name
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
hasOption(name: string) {
|
||||||
|
name = name.split('.')[0];
|
||||||
|
return this.options.find(option => {
|
||||||
|
return option.names.includes(name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
outputHelp() {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
commands
|
||||||
|
} = this.cli;
|
||||||
|
const {
|
||||||
|
versionNumber,
|
||||||
|
options: globalOptions,
|
||||||
|
helpCallback
|
||||||
|
} = this.cli.globalCommand;
|
||||||
|
let sections: HelpSection[] = [{
|
||||||
|
body: `${name}${versionNumber ? `/${versionNumber}` : ''}`
|
||||||
|
}];
|
||||||
|
sections.push({
|
||||||
|
title: 'Usage',
|
||||||
|
body: ` $ ${name} ${this.usageText || this.rawName}`
|
||||||
|
});
|
||||||
|
const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
|
||||||
|
|
||||||
|
if (showCommands) {
|
||||||
|
const longestCommandName = findLongest(commands.map(command => command.rawName));
|
||||||
|
sections.push({
|
||||||
|
title: 'Commands',
|
||||||
|
body: commands.map(command => {
|
||||||
|
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
|
||||||
|
}).join('\n')
|
||||||
|
});
|
||||||
|
sections.push({
|
||||||
|
title: `For more info, run any command with the \`--help\` flag`,
|
||||||
|
body: commands.map(command => ` $ ${name}${command.name === '' ? '' : ` ${command.name}`} --help`).join('\n')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let options = this.isGlobalCommand ? globalOptions : [...this.options, ...(globalOptions || [])];
|
||||||
|
|
||||||
|
if (!this.isGlobalCommand && !this.isDefaultCommand) {
|
||||||
|
options = options.filter(option => option.name !== 'version');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.length > 0) {
|
||||||
|
const longestOptionName = findLongest(options.map(option => option.rawName));
|
||||||
|
sections.push({
|
||||||
|
title: 'Options',
|
||||||
|
body: options.map(option => {
|
||||||
|
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === undefined ? '' : `(default: ${option.config.default})`}`;
|
||||||
|
}).join('\n')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.examples.length > 0) {
|
||||||
|
sections.push({
|
||||||
|
title: 'Examples',
|
||||||
|
body: this.examples.map(example => {
|
||||||
|
if (typeof example === 'function') {
|
||||||
|
return example(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return example;
|
||||||
|
}).join('\n')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helpCallback) {
|
||||||
|
sections = helpCallback(sections) || sections;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(sections.map(section => {
|
||||||
|
return section.title ? `${section.title}:\n${section.body}` : section.body;
|
||||||
|
}).join('\n\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
outputVersion() {
|
||||||
|
const {
|
||||||
|
name
|
||||||
|
} = this.cli;
|
||||||
|
const {
|
||||||
|
versionNumber
|
||||||
|
} = this.cli.globalCommand;
|
||||||
|
|
||||||
|
if (versionNumber) {
|
||||||
|
console.log(`${name}/${versionNumber} ${platformInfo}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkRequiredArgs() {
|
||||||
|
const minimalArgsCount = this.args.filter(arg => arg.required).length;
|
||||||
|
|
||||||
|
if (this.cli.args.length < minimalArgsCount) {
|
||||||
|
throw new CACError(`missing required args for command \`${this.rawName}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check if the parsed options contain any unknown options
|
||||||
|
*
|
||||||
|
* Exit and output error when true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
checkUnknownOptions() {
|
||||||
|
const {
|
||||||
|
options,
|
||||||
|
globalCommand
|
||||||
|
} = this.cli;
|
||||||
|
|
||||||
|
if (!this.config.allowUnknownOptions) {
|
||||||
|
for (const name of Object.keys(options)) {
|
||||||
|
if (name !== '--' && !this.hasOption(name) && !globalCommand.hasOption(name)) {
|
||||||
|
throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Check if the required string-type options exist
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
checkOptionValue() {
|
||||||
|
const {
|
||||||
|
options: parsedOptions,
|
||||||
|
globalCommand
|
||||||
|
} = this.cli;
|
||||||
|
const options = [...globalCommand.options, ...this.options];
|
||||||
|
|
||||||
|
for (const option of options) {
|
||||||
|
const value = parsedOptions[option.name.split('.')[0]]; // Check required option value
|
||||||
|
|
||||||
|
if (option.required) {
|
||||||
|
const hasNegated = options.some(o => o.negated && o.names.includes(option.name));
|
||||||
|
|
||||||
|
if (value === true || value === false && !hasNegated) {
|
||||||
|
throw new CACError(`option \`${option.rawName}\` value is missing`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class GlobalCommand extends Command {
|
||||||
|
constructor(cli: CAC) {
|
||||||
|
super('@@global@@', '', {}, cli);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { HelpCallback, CommandExample, CommandConfig };
|
||||||
|
export { GlobalCommand };
|
||||||
|
export default Command;
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { removeBrackets, camelcaseOptionName } from "./utils.ts";
|
||||||
|
interface OptionConfig {
|
||||||
|
default?: any;
|
||||||
|
type?: any[];
|
||||||
|
}
|
||||||
|
export default class Option {
|
||||||
|
/** Option name */
|
||||||
|
name: string;
|
||||||
|
/** Option name and aliases */
|
||||||
|
|
||||||
|
names: string[];
|
||||||
|
isBoolean?: boolean; // `required` will be a boolean for options with brackets
|
||||||
|
|
||||||
|
required?: boolean;
|
||||||
|
config: OptionConfig;
|
||||||
|
negated: boolean;
|
||||||
|
|
||||||
|
constructor(public rawName: string, public description: string, config?: OptionConfig) {
|
||||||
|
this.config = Object.assign({}, config); // You may use cli.option('--env.* [value]', 'desc') to denote a dot-nested option
|
||||||
|
|
||||||
|
rawName = rawName.replace(/\.\*/g, '');
|
||||||
|
this.negated = false;
|
||||||
|
this.names = removeBrackets(rawName).split(',').map((v: string) => {
|
||||||
|
let name = v.trim().replace(/^-{1,2}/, '');
|
||||||
|
|
||||||
|
if (name.startsWith('no-')) {
|
||||||
|
this.negated = true;
|
||||||
|
name = name.replace(/^no-/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return camelcaseOptionName(name);
|
||||||
|
}).sort((a, b) => a.length > b.length ? 1 : -1); // Sort names
|
||||||
|
// Use the longest name (last one) as actual option name
|
||||||
|
|
||||||
|
this.name = this.names[this.names.length - 1];
|
||||||
|
|
||||||
|
if (this.negated && this.config.default == null) {
|
||||||
|
this.config.default = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawName.includes('<')) {
|
||||||
|
this.required = true;
|
||||||
|
} else if (rawName.includes('[')) {
|
||||||
|
this.required = false;
|
||||||
|
} else {
|
||||||
|
// No arg needed, it's boolean flag
|
||||||
|
this.isBoolean = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export type { OptionConfig };
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Ignore the TypeScript errors
|
||||||
|
// Since this file will only be used in Deno runtime
|
||||||
|
export const processArgs = ['deno', 'cli'].concat(Deno.args);
|
||||||
|
export const platformInfo = `${Deno.build.os}-${Deno.build.arch} deno-${Deno.version.deno}`;
|
|
@ -0,0 +1,10 @@
|
||||||
|
import CAC from "./CAC.ts";
|
||||||
|
import Command from "./Command.ts";
|
||||||
|
/**
|
||||||
|
* @param name The program name to display in help and version message
|
||||||
|
*/
|
||||||
|
|
||||||
|
const cac = (name = '') => new CAC(name);
|
||||||
|
|
||||||
|
export default cac;
|
||||||
|
export { cac, CAC, Command };
|
|
@ -0,0 +1,145 @@
|
||||||
|
import Option from "./Option.ts";
|
||||||
|
export const removeBrackets = (v: string) => v.replace(/[<[].+/, '').trim();
|
||||||
|
export const findAllBrackets = (v: string) => {
|
||||||
|
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
|
||||||
|
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
|
||||||
|
const res = [];
|
||||||
|
|
||||||
|
const parse = (match: string[]) => {
|
||||||
|
let variadic = false;
|
||||||
|
let value = match[1];
|
||||||
|
|
||||||
|
if (value.startsWith('...')) {
|
||||||
|
value = value.slice(3);
|
||||||
|
variadic = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
required: match[0].startsWith('<'),
|
||||||
|
value,
|
||||||
|
variadic
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let angledMatch;
|
||||||
|
|
||||||
|
while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) {
|
||||||
|
res.push(parse(angledMatch));
|
||||||
|
}
|
||||||
|
|
||||||
|
let squareMatch;
|
||||||
|
|
||||||
|
while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) {
|
||||||
|
res.push(parse(squareMatch));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
interface MriOptions {
|
||||||
|
alias: {
|
||||||
|
[k: string]: string[];
|
||||||
|
};
|
||||||
|
boolean: string[];
|
||||||
|
}
|
||||||
|
export const getMriOptions = (options: Option[]) => {
|
||||||
|
const result: MriOptions = {
|
||||||
|
alias: {},
|
||||||
|
boolean: []
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [index, option] of options.entries()) {
|
||||||
|
// We do not set default values in mri options
|
||||||
|
// Since its type (typeof) will be used to cast parsed arguments.
|
||||||
|
// Which mean `--foo foo` will be parsed as `{foo: true}` if we have `{default:{foo: true}}`
|
||||||
|
// Set alias
|
||||||
|
if (option.names.length > 1) {
|
||||||
|
result.alias[option.names[0]] = option.names.slice(1);
|
||||||
|
} // Set boolean
|
||||||
|
|
||||||
|
|
||||||
|
if (option.isBoolean) {
|
||||||
|
if (option.negated) {
|
||||||
|
// For negated option
|
||||||
|
// We only set it to `boolean` type when there's no string-type option with the same name
|
||||||
|
const hasStringTypeOption = options.some((o, i) => {
|
||||||
|
return i !== index && o.names.some(name => option.names.includes(name)) && typeof o.required === 'boolean';
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasStringTypeOption) {
|
||||||
|
result.boolean.push(option.names[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.boolean.push(option.names[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
export const findLongest = (arr: string[]) => {
|
||||||
|
return arr.sort((a, b) => {
|
||||||
|
return a.length > b.length ? -1 : 1;
|
||||||
|
})[0];
|
||||||
|
};
|
||||||
|
export const padRight = (str: string, length: number) => {
|
||||||
|
return str.length >= length ? str : `${str}${' '.repeat(length - str.length)}`;
|
||||||
|
};
|
||||||
|
export const camelcase = (input: string) => {
|
||||||
|
return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
|
||||||
|
return p1 + p2.toUpperCase();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export const setDotProp = (obj: {
|
||||||
|
[k: string]: any;
|
||||||
|
}, keys: string[], val: any) => {
|
||||||
|
let i = 0;
|
||||||
|
let length = keys.length;
|
||||||
|
let t = obj;
|
||||||
|
let x;
|
||||||
|
|
||||||
|
for (; i < length; ++i) {
|
||||||
|
x = t[keys[i]];
|
||||||
|
t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf('.') || !(+keys[i + 1] > -1) ? {} : [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const setByType = (obj: {
|
||||||
|
[k: string]: any;
|
||||||
|
}, transforms: {
|
||||||
|
[k: string]: any;
|
||||||
|
}) => {
|
||||||
|
for (const key of Object.keys(transforms)) {
|
||||||
|
const transform = transforms[key];
|
||||||
|
|
||||||
|
if (transform.shouldTransform) {
|
||||||
|
obj[key] = Array.prototype.concat.call([], obj[key]);
|
||||||
|
|
||||||
|
if (typeof transform.transformFunction === 'function') {
|
||||||
|
obj[key] = obj[key].map(transform.transformFunction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const getFileName = (input: string) => {
|
||||||
|
const m = /([^\\\/]+)$/.exec(input);
|
||||||
|
return m ? m[1] : '';
|
||||||
|
};
|
||||||
|
export const camelcaseOptionName = (name: string) => {
|
||||||
|
// Camelcase the option name
|
||||||
|
// Don't camelcase anything after the dot `.`
|
||||||
|
return name.split('.').map((v, i) => {
|
||||||
|
return i === 0 ? camelcase(v) : v;
|
||||||
|
}).join('.');
|
||||||
|
};
|
||||||
|
export class CACError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
|
||||||
|
if (typeof Error.captureStackTrace === 'function') {
|
||||||
|
Error.captureStackTrace(this, this.constructor);
|
||||||
|
} else {
|
||||||
|
this.stack = new Error(message).stack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,191 @@
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
interface OptionConfig {
|
||||||
|
default?: any;
|
||||||
|
type?: any[];
|
||||||
|
}
|
||||||
|
declare class Option {
|
||||||
|
rawName: string;
|
||||||
|
description: string;
|
||||||
|
/** Option name */
|
||||||
|
name: string;
|
||||||
|
/** Option name and aliases */
|
||||||
|
names: string[];
|
||||||
|
isBoolean?: boolean;
|
||||||
|
required?: boolean;
|
||||||
|
config: OptionConfig;
|
||||||
|
negated: boolean;
|
||||||
|
constructor(rawName: string, description: string, config?: OptionConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CommandArg {
|
||||||
|
required: boolean;
|
||||||
|
value: string;
|
||||||
|
variadic: boolean;
|
||||||
|
}
|
||||||
|
interface HelpSection {
|
||||||
|
title?: string;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
|
interface CommandConfig {
|
||||||
|
allowUnknownOptions?: boolean;
|
||||||
|
ignoreOptionDefaultValue?: boolean;
|
||||||
|
}
|
||||||
|
declare type HelpCallback = (sections: HelpSection[]) => void | HelpSection[];
|
||||||
|
declare type CommandExample = ((bin: string) => string) | string;
|
||||||
|
declare class Command {
|
||||||
|
rawName: string;
|
||||||
|
description: string;
|
||||||
|
config: CommandConfig;
|
||||||
|
cli: CAC;
|
||||||
|
options: Option[];
|
||||||
|
aliasNames: string[];
|
||||||
|
name: string;
|
||||||
|
args: CommandArg[];
|
||||||
|
commandAction?: (...args: any[]) => any;
|
||||||
|
usageText?: string;
|
||||||
|
versionNumber?: string;
|
||||||
|
examples: CommandExample[];
|
||||||
|
helpCallback?: HelpCallback;
|
||||||
|
globalCommand?: GlobalCommand;
|
||||||
|
constructor(rawName: string, description: string, config: CommandConfig, cli: CAC);
|
||||||
|
usage(text: string): this;
|
||||||
|
allowUnknownOptions(): this;
|
||||||
|
ignoreOptionDefaultValue(): this;
|
||||||
|
version(version: string, customFlags?: string): this;
|
||||||
|
example(example: CommandExample): this;
|
||||||
|
/**
|
||||||
|
* Add a option for this command
|
||||||
|
* @param rawName Raw option name(s)
|
||||||
|
* @param description Option description
|
||||||
|
* @param config Option config
|
||||||
|
*/
|
||||||
|
option(rawName: string, description: string, config?: OptionConfig): this;
|
||||||
|
alias(name: string): this;
|
||||||
|
action(callback: (...args: any[]) => any): this;
|
||||||
|
/**
|
||||||
|
* Check if a command name is matched by this command
|
||||||
|
* @param name Command name
|
||||||
|
*/
|
||||||
|
isMatched(name: string): boolean;
|
||||||
|
get isDefaultCommand(): boolean;
|
||||||
|
get isGlobalCommand(): boolean;
|
||||||
|
/**
|
||||||
|
* Check if an option is registered in this command
|
||||||
|
* @param name Option name
|
||||||
|
*/
|
||||||
|
hasOption(name: string): Option | undefined;
|
||||||
|
outputHelp(): void;
|
||||||
|
outputVersion(): void;
|
||||||
|
checkRequiredArgs(): void;
|
||||||
|
/**
|
||||||
|
* Check if the parsed options contain any unknown options
|
||||||
|
*
|
||||||
|
* Exit and output error when true
|
||||||
|
*/
|
||||||
|
checkUnknownOptions(): void;
|
||||||
|
/**
|
||||||
|
* Check if the required string-type options exist
|
||||||
|
*/
|
||||||
|
checkOptionValue(): void;
|
||||||
|
}
|
||||||
|
declare class GlobalCommand extends Command {
|
||||||
|
constructor(cli: CAC);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ParsedArgv {
|
||||||
|
args: ReadonlyArray<string>;
|
||||||
|
options: {
|
||||||
|
[k: string]: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
declare class CAC extends EventEmitter {
|
||||||
|
/** The program name to display in help and version message */
|
||||||
|
name: string;
|
||||||
|
commands: Command[];
|
||||||
|
globalCommand: GlobalCommand;
|
||||||
|
matchedCommand?: Command;
|
||||||
|
matchedCommandName?: string;
|
||||||
|
/**
|
||||||
|
* Raw CLI arguments
|
||||||
|
*/
|
||||||
|
rawArgs: string[];
|
||||||
|
/**
|
||||||
|
* Parsed CLI arguments
|
||||||
|
*/
|
||||||
|
args: ParsedArgv['args'];
|
||||||
|
/**
|
||||||
|
* Parsed CLI options, camelCased
|
||||||
|
*/
|
||||||
|
options: ParsedArgv['options'];
|
||||||
|
showHelpOnExit?: boolean;
|
||||||
|
showVersionOnExit?: boolean;
|
||||||
|
/**
|
||||||
|
* @param name The program name to display in help and version message
|
||||||
|
*/
|
||||||
|
constructor(name?: string);
|
||||||
|
/**
|
||||||
|
* Add a global usage text.
|
||||||
|
*
|
||||||
|
* This is not used by sub-commands.
|
||||||
|
*/
|
||||||
|
usage(text: string): this;
|
||||||
|
/**
|
||||||
|
* Add a sub-command
|
||||||
|
*/
|
||||||
|
command(rawName: string, description?: string, config?: CommandConfig): Command;
|
||||||
|
/**
|
||||||
|
* Add a global CLI option.
|
||||||
|
*
|
||||||
|
* Which is also applied to sub-commands.
|
||||||
|
*/
|
||||||
|
option(rawName: string, description: string, config?: OptionConfig): this;
|
||||||
|
/**
|
||||||
|
* Show help message when `-h, --help` flags appear.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
help(callback?: HelpCallback): this;
|
||||||
|
/**
|
||||||
|
* Show version number when `-v, --version` flags appear.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
version(version: string, customFlags?: string): this;
|
||||||
|
/**
|
||||||
|
* Add a global example.
|
||||||
|
*
|
||||||
|
* This example added here will not be used by sub-commands.
|
||||||
|
*/
|
||||||
|
example(example: CommandExample): this;
|
||||||
|
/**
|
||||||
|
* Output the corresponding help message
|
||||||
|
* When a sub-command is matched, output the help message for the command
|
||||||
|
* Otherwise output the global one.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
outputHelp(): void;
|
||||||
|
/**
|
||||||
|
* Output the version number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
outputVersion(): void;
|
||||||
|
private setParsedInfo;
|
||||||
|
unsetMatchedCommand(): void;
|
||||||
|
/**
|
||||||
|
* Parse argv
|
||||||
|
*/
|
||||||
|
parse(argv?: string[], {
|
||||||
|
/** Whether to run the action for matched command */
|
||||||
|
run, }?: {
|
||||||
|
run?: boolean | undefined;
|
||||||
|
}): ParsedArgv;
|
||||||
|
private mri;
|
||||||
|
runMatchedCommand(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name The program name to display in help and version message
|
||||||
|
*/
|
||||||
|
declare const cac: (name?: string) => CAC;
|
||||||
|
|
||||||
|
export default cac;
|
||||||
|
export { CAC, Command, cac };
|
|
@ -0,0 +1,623 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
|
||||||
|
var events = require('events');
|
||||||
|
|
||||||
|
function toArr(any) {
|
||||||
|
return any == null ? [] : Array.isArray(any) ? any : [any];
|
||||||
|
}
|
||||||
|
|
||||||
|
function toVal(out, key, val, opts) {
|
||||||
|
var x, old=out[key], nxt=(
|
||||||
|
!!~opts.string.indexOf(key) ? (val == null || val === true ? '' : String(val))
|
||||||
|
: typeof val === 'boolean' ? val
|
||||||
|
: !!~opts.boolean.indexOf(key) ? (val === 'false' ? false : val === 'true' || (out._.push((x = +val,x * 0 === 0) ? x : val),!!val))
|
||||||
|
: (x = +val,x * 0 === 0) ? x : val
|
||||||
|
);
|
||||||
|
out[key] = old == null ? nxt : (Array.isArray(old) ? old.concat(nxt) : [old, nxt]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mri2 (args, opts) {
|
||||||
|
args = args || [];
|
||||||
|
opts = opts || {};
|
||||||
|
|
||||||
|
var k, arr, arg, name, val, out={ _:[] };
|
||||||
|
var i=0, j=0, idx=0, len=args.length;
|
||||||
|
|
||||||
|
const alibi = opts.alias !== void 0;
|
||||||
|
const strict = opts.unknown !== void 0;
|
||||||
|
const defaults = opts.default !== void 0;
|
||||||
|
|
||||||
|
opts.alias = opts.alias || {};
|
||||||
|
opts.string = toArr(opts.string);
|
||||||
|
opts.boolean = toArr(opts.boolean);
|
||||||
|
|
||||||
|
if (alibi) {
|
||||||
|
for (k in opts.alias) {
|
||||||
|
arr = opts.alias[k] = toArr(opts.alias[k]);
|
||||||
|
for (i=0; i < arr.length; i++) {
|
||||||
|
(opts.alias[arr[i]] = arr.concat(k)).splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=opts.boolean.length; i-- > 0;) {
|
||||||
|
arr = opts.alias[opts.boolean[i]] || [];
|
||||||
|
for (j=arr.length; j-- > 0;) opts.boolean.push(arr[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=opts.string.length; i-- > 0;) {
|
||||||
|
arr = opts.alias[opts.string[i]] || [];
|
||||||
|
for (j=arr.length; j-- > 0;) opts.string.push(arr[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaults) {
|
||||||
|
for (k in opts.default) {
|
||||||
|
name = typeof opts.default[k];
|
||||||
|
arr = opts.alias[k] = opts.alias[k] || [];
|
||||||
|
if (opts[name] !== void 0) {
|
||||||
|
opts[name].push(k);
|
||||||
|
for (i=0; i < arr.length; i++) {
|
||||||
|
opts[name].push(arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys = strict ? Object.keys(opts.alias) : [];
|
||||||
|
|
||||||
|
for (i=0; i < len; i++) {
|
||||||
|
arg = args[i];
|
||||||
|
|
||||||
|
if (arg === '--') {
|
||||||
|
out._ = out._.concat(args.slice(++i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j=0; j < arg.length; j++) {
|
||||||
|
if (arg.charCodeAt(j) !== 45) break; // "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j === 0) {
|
||||||
|
out._.push(arg);
|
||||||
|
} else if (arg.substring(j, j + 3) === 'no-') {
|
||||||
|
name = arg.substring(j + 3);
|
||||||
|
if (strict && !~keys.indexOf(name)) {
|
||||||
|
return opts.unknown(arg);
|
||||||
|
}
|
||||||
|
out[name] = false;
|
||||||
|
} else {
|
||||||
|
for (idx=j+1; idx < arg.length; idx++) {
|
||||||
|
if (arg.charCodeAt(idx) === 61) break; // "="
|
||||||
|
}
|
||||||
|
|
||||||
|
name = arg.substring(j, idx);
|
||||||
|
val = arg.substring(++idx) || (i+1 === len || (''+args[i+1]).charCodeAt(0) === 45 || args[++i]);
|
||||||
|
arr = (j === 2 ? [name] : name);
|
||||||
|
|
||||||
|
for (idx=0; idx < arr.length; idx++) {
|
||||||
|
name = arr[idx];
|
||||||
|
if (strict && !~keys.indexOf(name)) return opts.unknown('-'.repeat(j) + name);
|
||||||
|
toVal(out, name, (idx + 1 < arr.length) || val, opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaults) {
|
||||||
|
for (k in opts.default) {
|
||||||
|
if (out[k] === void 0) {
|
||||||
|
out[k] = opts.default[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alibi) {
|
||||||
|
for (k in out) {
|
||||||
|
arr = opts.alias[k] || [];
|
||||||
|
while (arr.length > 0) {
|
||||||
|
out[arr.shift()] = out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeBrackets = (v) => v.replace(/[<[].+/, "").trim();
|
||||||
|
const findAllBrackets = (v) => {
|
||||||
|
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
|
||||||
|
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
|
||||||
|
const res = [];
|
||||||
|
const parse = (match) => {
|
||||||
|
let variadic = false;
|
||||||
|
let value = match[1];
|
||||||
|
if (value.startsWith("...")) {
|
||||||
|
value = value.slice(3);
|
||||||
|
variadic = true;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
required: match[0].startsWith("<"),
|
||||||
|
value,
|
||||||
|
variadic
|
||||||
|
};
|
||||||
|
};
|
||||||
|
let angledMatch;
|
||||||
|
while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) {
|
||||||
|
res.push(parse(angledMatch));
|
||||||
|
}
|
||||||
|
let squareMatch;
|
||||||
|
while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) {
|
||||||
|
res.push(parse(squareMatch));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
const getMriOptions = (options) => {
|
||||||
|
const result = {alias: {}, boolean: []};
|
||||||
|
for (const [index, option] of options.entries()) {
|
||||||
|
if (option.names.length > 1) {
|
||||||
|
result.alias[option.names[0]] = option.names.slice(1);
|
||||||
|
}
|
||||||
|
if (option.isBoolean) {
|
||||||
|
if (option.negated) {
|
||||||
|
const hasStringTypeOption = options.some((o, i) => {
|
||||||
|
return i !== index && o.names.some((name) => option.names.includes(name)) && typeof o.required === "boolean";
|
||||||
|
});
|
||||||
|
if (!hasStringTypeOption) {
|
||||||
|
result.boolean.push(option.names[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.boolean.push(option.names[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
const findLongest = (arr) => {
|
||||||
|
return arr.sort((a, b) => {
|
||||||
|
return a.length > b.length ? -1 : 1;
|
||||||
|
})[0];
|
||||||
|
};
|
||||||
|
const padRight = (str, length) => {
|
||||||
|
return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`;
|
||||||
|
};
|
||||||
|
const camelcase = (input) => {
|
||||||
|
return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
|
||||||
|
return p1 + p2.toUpperCase();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const setDotProp = (obj, keys, val) => {
|
||||||
|
let i = 0;
|
||||||
|
let length = keys.length;
|
||||||
|
let t = obj;
|
||||||
|
let x;
|
||||||
|
for (; i < length; ++i) {
|
||||||
|
x = t[keys[i]];
|
||||||
|
t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf(".") || !(+keys[i + 1] > -1) ? {} : [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const setByType = (obj, transforms) => {
|
||||||
|
for (const key of Object.keys(transforms)) {
|
||||||
|
const transform = transforms[key];
|
||||||
|
if (transform.shouldTransform) {
|
||||||
|
obj[key] = Array.prototype.concat.call([], obj[key]);
|
||||||
|
if (typeof transform.transformFunction === "function") {
|
||||||
|
obj[key] = obj[key].map(transform.transformFunction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getFileName = (input) => {
|
||||||
|
const m = /([^\\\/]+)$/.exec(input);
|
||||||
|
return m ? m[1] : "";
|
||||||
|
};
|
||||||
|
const camelcaseOptionName = (name) => {
|
||||||
|
return name.split(".").map((v, i) => {
|
||||||
|
return i === 0 ? camelcase(v) : v;
|
||||||
|
}).join(".");
|
||||||
|
};
|
||||||
|
class CACError extends Error {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
if (typeof Error.captureStackTrace === "function") {
|
||||||
|
Error.captureStackTrace(this, this.constructor);
|
||||||
|
} else {
|
||||||
|
this.stack = new Error(message).stack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Option {
|
||||||
|
constructor(rawName, description, config) {
|
||||||
|
this.rawName = rawName;
|
||||||
|
this.description = description;
|
||||||
|
this.config = Object.assign({}, config);
|
||||||
|
rawName = rawName.replace(/\.\*/g, "");
|
||||||
|
this.negated = false;
|
||||||
|
this.names = removeBrackets(rawName).split(",").map((v) => {
|
||||||
|
let name = v.trim().replace(/^-{1,2}/, "");
|
||||||
|
if (name.startsWith("no-")) {
|
||||||
|
this.negated = true;
|
||||||
|
name = name.replace(/^no-/, "");
|
||||||
|
}
|
||||||
|
return camelcaseOptionName(name);
|
||||||
|
}).sort((a, b) => a.length > b.length ? 1 : -1);
|
||||||
|
this.name = this.names[this.names.length - 1];
|
||||||
|
if (this.negated && this.config.default == null) {
|
||||||
|
this.config.default = true;
|
||||||
|
}
|
||||||
|
if (rawName.includes("<")) {
|
||||||
|
this.required = true;
|
||||||
|
} else if (rawName.includes("[")) {
|
||||||
|
this.required = false;
|
||||||
|
} else {
|
||||||
|
this.isBoolean = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const processArgs = process.argv;
|
||||||
|
const platformInfo = `${process.platform}-${process.arch} node-${process.version}`;
|
||||||
|
|
||||||
|
class Command {
|
||||||
|
constructor(rawName, description, config = {}, cli) {
|
||||||
|
this.rawName = rawName;
|
||||||
|
this.description = description;
|
||||||
|
this.config = config;
|
||||||
|
this.cli = cli;
|
||||||
|
this.options = [];
|
||||||
|
this.aliasNames = [];
|
||||||
|
this.name = removeBrackets(rawName);
|
||||||
|
this.args = findAllBrackets(rawName);
|
||||||
|
this.examples = [];
|
||||||
|
}
|
||||||
|
usage(text) {
|
||||||
|
this.usageText = text;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
allowUnknownOptions() {
|
||||||
|
this.config.allowUnknownOptions = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
ignoreOptionDefaultValue() {
|
||||||
|
this.config.ignoreOptionDefaultValue = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
version(version, customFlags = "-v, --version") {
|
||||||
|
this.versionNumber = version;
|
||||||
|
this.option(customFlags, "Display version number");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
example(example) {
|
||||||
|
this.examples.push(example);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
option(rawName, description, config) {
|
||||||
|
const option = new Option(rawName, description, config);
|
||||||
|
this.options.push(option);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
alias(name) {
|
||||||
|
this.aliasNames.push(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
action(callback) {
|
||||||
|
this.commandAction = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
isMatched(name) {
|
||||||
|
return this.name === name || this.aliasNames.includes(name);
|
||||||
|
}
|
||||||
|
get isDefaultCommand() {
|
||||||
|
return this.name === "" || this.aliasNames.includes("!");
|
||||||
|
}
|
||||||
|
get isGlobalCommand() {
|
||||||
|
return this instanceof GlobalCommand;
|
||||||
|
}
|
||||||
|
hasOption(name) {
|
||||||
|
name = name.split(".")[0];
|
||||||
|
return this.options.find((option) => {
|
||||||
|
return option.names.includes(name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
outputHelp() {
|
||||||
|
const {name, commands} = this.cli;
|
||||||
|
const {
|
||||||
|
versionNumber,
|
||||||
|
options: globalOptions,
|
||||||
|
helpCallback
|
||||||
|
} = this.cli.globalCommand;
|
||||||
|
let sections = [
|
||||||
|
{
|
||||||
|
body: `${name}${versionNumber ? `/${versionNumber}` : ""}`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
sections.push({
|
||||||
|
title: "Usage",
|
||||||
|
body: ` $ ${name} ${this.usageText || this.rawName}`
|
||||||
|
});
|
||||||
|
const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
|
||||||
|
if (showCommands) {
|
||||||
|
const longestCommandName = findLongest(commands.map((command) => command.rawName));
|
||||||
|
sections.push({
|
||||||
|
title: "Commands",
|
||||||
|
body: commands.map((command) => {
|
||||||
|
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
|
||||||
|
}).join("\n")
|
||||||
|
});
|
||||||
|
sections.push({
|
||||||
|
title: `For more info, run any command with the \`--help\` flag`,
|
||||||
|
body: commands.map((command) => ` $ ${name}${command.name === "" ? "" : ` ${command.name}`} --help`).join("\n")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
|
||||||
|
if (!this.isGlobalCommand && !this.isDefaultCommand) {
|
||||||
|
options = options.filter((option) => option.name !== "version");
|
||||||
|
}
|
||||||
|
if (options.length > 0) {
|
||||||
|
const longestOptionName = findLongest(options.map((option) => option.rawName));
|
||||||
|
sections.push({
|
||||||
|
title: "Options",
|
||||||
|
body: options.map((option) => {
|
||||||
|
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === void 0 ? "" : `(default: ${option.config.default})`}`;
|
||||||
|
}).join("\n")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.examples.length > 0) {
|
||||||
|
sections.push({
|
||||||
|
title: "Examples",
|
||||||
|
body: this.examples.map((example) => {
|
||||||
|
if (typeof example === "function") {
|
||||||
|
return example(name);
|
||||||
|
}
|
||||||
|
return example;
|
||||||
|
}).join("\n")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (helpCallback) {
|
||||||
|
sections = helpCallback(sections) || sections;
|
||||||
|
}
|
||||||
|
console.log(sections.map((section) => {
|
||||||
|
return section.title ? `${section.title}:
|
||||||
|
${section.body}` : section.body;
|
||||||
|
}).join("\n\n"));
|
||||||
|
}
|
||||||
|
outputVersion() {
|
||||||
|
const {name} = this.cli;
|
||||||
|
const {versionNumber} = this.cli.globalCommand;
|
||||||
|
if (versionNumber) {
|
||||||
|
console.log(`${name}/${versionNumber} ${platformInfo}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkRequiredArgs() {
|
||||||
|
const minimalArgsCount = this.args.filter((arg) => arg.required).length;
|
||||||
|
if (this.cli.args.length < minimalArgsCount) {
|
||||||
|
throw new CACError(`missing required args for command \`${this.rawName}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkUnknownOptions() {
|
||||||
|
const {options, globalCommand} = this.cli;
|
||||||
|
if (!this.config.allowUnknownOptions) {
|
||||||
|
for (const name of Object.keys(options)) {
|
||||||
|
if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) {
|
||||||
|
throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkOptionValue() {
|
||||||
|
const {options: parsedOptions, globalCommand} = this.cli;
|
||||||
|
const options = [...globalCommand.options, ...this.options];
|
||||||
|
for (const option of options) {
|
||||||
|
const value = parsedOptions[option.name.split(".")[0]];
|
||||||
|
if (option.required) {
|
||||||
|
const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));
|
||||||
|
if (value === true || value === false && !hasNegated) {
|
||||||
|
throw new CACError(`option \`${option.rawName}\` value is missing`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class GlobalCommand extends Command {
|
||||||
|
constructor(cli) {
|
||||||
|
super("@@global@@", "", {}, cli);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var __assign = Object.assign;
|
||||||
|
class CAC extends events.EventEmitter {
|
||||||
|
constructor(name = "") {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
this.commands = [];
|
||||||
|
this.rawArgs = [];
|
||||||
|
this.args = [];
|
||||||
|
this.options = {};
|
||||||
|
this.globalCommand = new GlobalCommand(this);
|
||||||
|
this.globalCommand.usage("<command> [options]");
|
||||||
|
}
|
||||||
|
usage(text) {
|
||||||
|
this.globalCommand.usage(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
command(rawName, description, config) {
|
||||||
|
const command = new Command(rawName, description || "", config, this);
|
||||||
|
command.globalCommand = this.globalCommand;
|
||||||
|
this.commands.push(command);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
option(rawName, description, config) {
|
||||||
|
this.globalCommand.option(rawName, description, config);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
help(callback) {
|
||||||
|
this.globalCommand.option("-h, --help", "Display this message");
|
||||||
|
this.globalCommand.helpCallback = callback;
|
||||||
|
this.showHelpOnExit = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
version(version, customFlags = "-v, --version") {
|
||||||
|
this.globalCommand.version(version, customFlags);
|
||||||
|
this.showVersionOnExit = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
example(example) {
|
||||||
|
this.globalCommand.example(example);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
outputHelp() {
|
||||||
|
if (this.matchedCommand) {
|
||||||
|
this.matchedCommand.outputHelp();
|
||||||
|
} else {
|
||||||
|
this.globalCommand.outputHelp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputVersion() {
|
||||||
|
this.globalCommand.outputVersion();
|
||||||
|
}
|
||||||
|
setParsedInfo({args, options}, matchedCommand, matchedCommandName) {
|
||||||
|
this.args = args;
|
||||||
|
this.options = options;
|
||||||
|
if (matchedCommand) {
|
||||||
|
this.matchedCommand = matchedCommand;
|
||||||
|
}
|
||||||
|
if (matchedCommandName) {
|
||||||
|
this.matchedCommandName = matchedCommandName;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
unsetMatchedCommand() {
|
||||||
|
this.matchedCommand = void 0;
|
||||||
|
this.matchedCommandName = void 0;
|
||||||
|
}
|
||||||
|
parse(argv = processArgs, {
|
||||||
|
run = true
|
||||||
|
} = {}) {
|
||||||
|
this.rawArgs = argv;
|
||||||
|
if (!this.name) {
|
||||||
|
this.name = argv[1] ? getFileName(argv[1]) : "cli";
|
||||||
|
}
|
||||||
|
let shouldParse = true;
|
||||||
|
for (const command of this.commands) {
|
||||||
|
const parsed = this.mri(argv.slice(2), command);
|
||||||
|
const commandName = parsed.args[0];
|
||||||
|
if (command.isMatched(commandName)) {
|
||||||
|
shouldParse = false;
|
||||||
|
const parsedInfo = __assign(__assign({}, parsed), {
|
||||||
|
args: parsed.args.slice(1)
|
||||||
|
});
|
||||||
|
this.setParsedInfo(parsedInfo, command, commandName);
|
||||||
|
this.emit(`command:${commandName}`, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldParse) {
|
||||||
|
for (const command of this.commands) {
|
||||||
|
if (command.name === "") {
|
||||||
|
shouldParse = false;
|
||||||
|
const parsed = this.mri(argv.slice(2), command);
|
||||||
|
this.setParsedInfo(parsed, command);
|
||||||
|
this.emit(`command:!`, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldParse) {
|
||||||
|
const parsed = this.mri(argv.slice(2));
|
||||||
|
this.setParsedInfo(parsed);
|
||||||
|
}
|
||||||
|
if (this.options.help && this.showHelpOnExit) {
|
||||||
|
this.outputHelp();
|
||||||
|
run = false;
|
||||||
|
this.unsetMatchedCommand();
|
||||||
|
}
|
||||||
|
if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) {
|
||||||
|
this.outputVersion();
|
||||||
|
run = false;
|
||||||
|
this.unsetMatchedCommand();
|
||||||
|
}
|
||||||
|
const parsedArgv = {args: this.args, options: this.options};
|
||||||
|
if (run) {
|
||||||
|
this.runMatchedCommand();
|
||||||
|
}
|
||||||
|
if (!this.matchedCommand && this.args[0]) {
|
||||||
|
this.emit("command:*");
|
||||||
|
}
|
||||||
|
return parsedArgv;
|
||||||
|
}
|
||||||
|
mri(argv, command) {
|
||||||
|
const cliOptions = [
|
||||||
|
...this.globalCommand.options,
|
||||||
|
...command ? command.options : []
|
||||||
|
];
|
||||||
|
const mriOptions = getMriOptions(cliOptions);
|
||||||
|
let argsAfterDoubleDashes = [];
|
||||||
|
const doubleDashesIndex = argv.indexOf("--");
|
||||||
|
if (doubleDashesIndex > -1) {
|
||||||
|
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
|
||||||
|
argv = argv.slice(0, doubleDashesIndex);
|
||||||
|
}
|
||||||
|
let parsed = mri2(argv, mriOptions);
|
||||||
|
parsed = Object.keys(parsed).reduce((res, name) => {
|
||||||
|
return __assign(__assign({}, res), {
|
||||||
|
[camelcaseOptionName(name)]: parsed[name]
|
||||||
|
});
|
||||||
|
}, {_: []});
|
||||||
|
const args = parsed._;
|
||||||
|
const options = {
|
||||||
|
"--": argsAfterDoubleDashes
|
||||||
|
};
|
||||||
|
const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
|
||||||
|
let transforms = Object.create(null);
|
||||||
|
for (const cliOption of cliOptions) {
|
||||||
|
if (!ignoreDefault && cliOption.config.default !== void 0) {
|
||||||
|
for (const name of cliOption.names) {
|
||||||
|
options[name] = cliOption.config.default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Array.isArray(cliOption.config.type)) {
|
||||||
|
if (transforms[cliOption.name] === void 0) {
|
||||||
|
transforms[cliOption.name] = Object.create(null);
|
||||||
|
transforms[cliOption.name]["shouldTransform"] = true;
|
||||||
|
transforms[cliOption.name]["transformFunction"] = cliOption.config.type[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const key of Object.keys(parsed)) {
|
||||||
|
if (key !== "_") {
|
||||||
|
const keys = key.split(".");
|
||||||
|
setDotProp(options, keys, parsed[key]);
|
||||||
|
setByType(options, transforms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
args,
|
||||||
|
options
|
||||||
|
};
|
||||||
|
}
|
||||||
|
runMatchedCommand() {
|
||||||
|
const {args, options, matchedCommand: command} = this;
|
||||||
|
if (!command || !command.commandAction)
|
||||||
|
return;
|
||||||
|
command.checkUnknownOptions();
|
||||||
|
command.checkOptionValue();
|
||||||
|
command.checkRequiredArgs();
|
||||||
|
const actionArgs = [];
|
||||||
|
command.args.forEach((arg, index) => {
|
||||||
|
if (arg.variadic) {
|
||||||
|
actionArgs.push(args.slice(index));
|
||||||
|
} else {
|
||||||
|
actionArgs.push(args[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
actionArgs.push(options);
|
||||||
|
return command.commandAction.apply(this, actionArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cac = (name = "") => new CAC(name);
|
||||||
|
|
||||||
|
exports.CAC = CAC;
|
||||||
|
exports.Command = Command;
|
||||||
|
exports.cac = cac;
|
||||||
|
exports.default = cac;
|
|
@ -0,0 +1,617 @@
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
function toArr(any) {
|
||||||
|
return any == null ? [] : Array.isArray(any) ? any : [any];
|
||||||
|
}
|
||||||
|
|
||||||
|
function toVal(out, key, val, opts) {
|
||||||
|
var x, old=out[key], nxt=(
|
||||||
|
!!~opts.string.indexOf(key) ? (val == null || val === true ? '' : String(val))
|
||||||
|
: typeof val === 'boolean' ? val
|
||||||
|
: !!~opts.boolean.indexOf(key) ? (val === 'false' ? false : val === 'true' || (out._.push((x = +val,x * 0 === 0) ? x : val),!!val))
|
||||||
|
: (x = +val,x * 0 === 0) ? x : val
|
||||||
|
);
|
||||||
|
out[key] = old == null ? nxt : (Array.isArray(old) ? old.concat(nxt) : [old, nxt]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mri2 (args, opts) {
|
||||||
|
args = args || [];
|
||||||
|
opts = opts || {};
|
||||||
|
|
||||||
|
var k, arr, arg, name, val, out={ _:[] };
|
||||||
|
var i=0, j=0, idx=0, len=args.length;
|
||||||
|
|
||||||
|
const alibi = opts.alias !== void 0;
|
||||||
|
const strict = opts.unknown !== void 0;
|
||||||
|
const defaults = opts.default !== void 0;
|
||||||
|
|
||||||
|
opts.alias = opts.alias || {};
|
||||||
|
opts.string = toArr(opts.string);
|
||||||
|
opts.boolean = toArr(opts.boolean);
|
||||||
|
|
||||||
|
if (alibi) {
|
||||||
|
for (k in opts.alias) {
|
||||||
|
arr = opts.alias[k] = toArr(opts.alias[k]);
|
||||||
|
for (i=0; i < arr.length; i++) {
|
||||||
|
(opts.alias[arr[i]] = arr.concat(k)).splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=opts.boolean.length; i-- > 0;) {
|
||||||
|
arr = opts.alias[opts.boolean[i]] || [];
|
||||||
|
for (j=arr.length; j-- > 0;) opts.boolean.push(arr[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=opts.string.length; i-- > 0;) {
|
||||||
|
arr = opts.alias[opts.string[i]] || [];
|
||||||
|
for (j=arr.length; j-- > 0;) opts.string.push(arr[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaults) {
|
||||||
|
for (k in opts.default) {
|
||||||
|
name = typeof opts.default[k];
|
||||||
|
arr = opts.alias[k] = opts.alias[k] || [];
|
||||||
|
if (opts[name] !== void 0) {
|
||||||
|
opts[name].push(k);
|
||||||
|
for (i=0; i < arr.length; i++) {
|
||||||
|
opts[name].push(arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys = strict ? Object.keys(opts.alias) : [];
|
||||||
|
|
||||||
|
for (i=0; i < len; i++) {
|
||||||
|
arg = args[i];
|
||||||
|
|
||||||
|
if (arg === '--') {
|
||||||
|
out._ = out._.concat(args.slice(++i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j=0; j < arg.length; j++) {
|
||||||
|
if (arg.charCodeAt(j) !== 45) break; // "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j === 0) {
|
||||||
|
out._.push(arg);
|
||||||
|
} else if (arg.substring(j, j + 3) === 'no-') {
|
||||||
|
name = arg.substring(j + 3);
|
||||||
|
if (strict && !~keys.indexOf(name)) {
|
||||||
|
return opts.unknown(arg);
|
||||||
|
}
|
||||||
|
out[name] = false;
|
||||||
|
} else {
|
||||||
|
for (idx=j+1; idx < arg.length; idx++) {
|
||||||
|
if (arg.charCodeAt(idx) === 61) break; // "="
|
||||||
|
}
|
||||||
|
|
||||||
|
name = arg.substring(j, idx);
|
||||||
|
val = arg.substring(++idx) || (i+1 === len || (''+args[i+1]).charCodeAt(0) === 45 || args[++i]);
|
||||||
|
arr = (j === 2 ? [name] : name);
|
||||||
|
|
||||||
|
for (idx=0; idx < arr.length; idx++) {
|
||||||
|
name = arr[idx];
|
||||||
|
if (strict && !~keys.indexOf(name)) return opts.unknown('-'.repeat(j) + name);
|
||||||
|
toVal(out, name, (idx + 1 < arr.length) || val, opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaults) {
|
||||||
|
for (k in opts.default) {
|
||||||
|
if (out[k] === void 0) {
|
||||||
|
out[k] = opts.default[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alibi) {
|
||||||
|
for (k in out) {
|
||||||
|
arr = opts.alias[k] || [];
|
||||||
|
while (arr.length > 0) {
|
||||||
|
out[arr.shift()] = out[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeBrackets = (v) => v.replace(/[<[].+/, "").trim();
|
||||||
|
const findAllBrackets = (v) => {
|
||||||
|
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
|
||||||
|
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
|
||||||
|
const res = [];
|
||||||
|
const parse = (match) => {
|
||||||
|
let variadic = false;
|
||||||
|
let value = match[1];
|
||||||
|
if (value.startsWith("...")) {
|
||||||
|
value = value.slice(3);
|
||||||
|
variadic = true;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
required: match[0].startsWith("<"),
|
||||||
|
value,
|
||||||
|
variadic
|
||||||
|
};
|
||||||
|
};
|
||||||
|
let angledMatch;
|
||||||
|
while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) {
|
||||||
|
res.push(parse(angledMatch));
|
||||||
|
}
|
||||||
|
let squareMatch;
|
||||||
|
while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) {
|
||||||
|
res.push(parse(squareMatch));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
const getMriOptions = (options) => {
|
||||||
|
const result = {alias: {}, boolean: []};
|
||||||
|
for (const [index, option] of options.entries()) {
|
||||||
|
if (option.names.length > 1) {
|
||||||
|
result.alias[option.names[0]] = option.names.slice(1);
|
||||||
|
}
|
||||||
|
if (option.isBoolean) {
|
||||||
|
if (option.negated) {
|
||||||
|
const hasStringTypeOption = options.some((o, i) => {
|
||||||
|
return i !== index && o.names.some((name) => option.names.includes(name)) && typeof o.required === "boolean";
|
||||||
|
});
|
||||||
|
if (!hasStringTypeOption) {
|
||||||
|
result.boolean.push(option.names[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.boolean.push(option.names[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
const findLongest = (arr) => {
|
||||||
|
return arr.sort((a, b) => {
|
||||||
|
return a.length > b.length ? -1 : 1;
|
||||||
|
})[0];
|
||||||
|
};
|
||||||
|
const padRight = (str, length) => {
|
||||||
|
return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`;
|
||||||
|
};
|
||||||
|
const camelcase = (input) => {
|
||||||
|
return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
|
||||||
|
return p1 + p2.toUpperCase();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const setDotProp = (obj, keys, val) => {
|
||||||
|
let i = 0;
|
||||||
|
let length = keys.length;
|
||||||
|
let t = obj;
|
||||||
|
let x;
|
||||||
|
for (; i < length; ++i) {
|
||||||
|
x = t[keys[i]];
|
||||||
|
t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf(".") || !(+keys[i + 1] > -1) ? {} : [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const setByType = (obj, transforms) => {
|
||||||
|
for (const key of Object.keys(transforms)) {
|
||||||
|
const transform = transforms[key];
|
||||||
|
if (transform.shouldTransform) {
|
||||||
|
obj[key] = Array.prototype.concat.call([], obj[key]);
|
||||||
|
if (typeof transform.transformFunction === "function") {
|
||||||
|
obj[key] = obj[key].map(transform.transformFunction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getFileName = (input) => {
|
||||||
|
const m = /([^\\\/]+)$/.exec(input);
|
||||||
|
return m ? m[1] : "";
|
||||||
|
};
|
||||||
|
const camelcaseOptionName = (name) => {
|
||||||
|
return name.split(".").map((v, i) => {
|
||||||
|
return i === 0 ? camelcase(v) : v;
|
||||||
|
}).join(".");
|
||||||
|
};
|
||||||
|
class CACError extends Error {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
if (typeof Error.captureStackTrace === "function") {
|
||||||
|
Error.captureStackTrace(this, this.constructor);
|
||||||
|
} else {
|
||||||
|
this.stack = new Error(message).stack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Option {
|
||||||
|
constructor(rawName, description, config) {
|
||||||
|
this.rawName = rawName;
|
||||||
|
this.description = description;
|
||||||
|
this.config = Object.assign({}, config);
|
||||||
|
rawName = rawName.replace(/\.\*/g, "");
|
||||||
|
this.negated = false;
|
||||||
|
this.names = removeBrackets(rawName).split(",").map((v) => {
|
||||||
|
let name = v.trim().replace(/^-{1,2}/, "");
|
||||||
|
if (name.startsWith("no-")) {
|
||||||
|
this.negated = true;
|
||||||
|
name = name.replace(/^no-/, "");
|
||||||
|
}
|
||||||
|
return camelcaseOptionName(name);
|
||||||
|
}).sort((a, b) => a.length > b.length ? 1 : -1);
|
||||||
|
this.name = this.names[this.names.length - 1];
|
||||||
|
if (this.negated && this.config.default == null) {
|
||||||
|
this.config.default = true;
|
||||||
|
}
|
||||||
|
if (rawName.includes("<")) {
|
||||||
|
this.required = true;
|
||||||
|
} else if (rawName.includes("[")) {
|
||||||
|
this.required = false;
|
||||||
|
} else {
|
||||||
|
this.isBoolean = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const processArgs = process.argv;
|
||||||
|
const platformInfo = `${process.platform}-${process.arch} node-${process.version}`;
|
||||||
|
|
||||||
|
class Command {
|
||||||
|
constructor(rawName, description, config = {}, cli) {
|
||||||
|
this.rawName = rawName;
|
||||||
|
this.description = description;
|
||||||
|
this.config = config;
|
||||||
|
this.cli = cli;
|
||||||
|
this.options = [];
|
||||||
|
this.aliasNames = [];
|
||||||
|
this.name = removeBrackets(rawName);
|
||||||
|
this.args = findAllBrackets(rawName);
|
||||||
|
this.examples = [];
|
||||||
|
}
|
||||||
|
usage(text) {
|
||||||
|
this.usageText = text;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
allowUnknownOptions() {
|
||||||
|
this.config.allowUnknownOptions = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
ignoreOptionDefaultValue() {
|
||||||
|
this.config.ignoreOptionDefaultValue = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
version(version, customFlags = "-v, --version") {
|
||||||
|
this.versionNumber = version;
|
||||||
|
this.option(customFlags, "Display version number");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
example(example) {
|
||||||
|
this.examples.push(example);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
option(rawName, description, config) {
|
||||||
|
const option = new Option(rawName, description, config);
|
||||||
|
this.options.push(option);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
alias(name) {
|
||||||
|
this.aliasNames.push(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
action(callback) {
|
||||||
|
this.commandAction = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
isMatched(name) {
|
||||||
|
return this.name === name || this.aliasNames.includes(name);
|
||||||
|
}
|
||||||
|
get isDefaultCommand() {
|
||||||
|
return this.name === "" || this.aliasNames.includes("!");
|
||||||
|
}
|
||||||
|
get isGlobalCommand() {
|
||||||
|
return this instanceof GlobalCommand;
|
||||||
|
}
|
||||||
|
hasOption(name) {
|
||||||
|
name = name.split(".")[0];
|
||||||
|
return this.options.find((option) => {
|
||||||
|
return option.names.includes(name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
outputHelp() {
|
||||||
|
const {name, commands} = this.cli;
|
||||||
|
const {
|
||||||
|
versionNumber,
|
||||||
|
options: globalOptions,
|
||||||
|
helpCallback
|
||||||
|
} = this.cli.globalCommand;
|
||||||
|
let sections = [
|
||||||
|
{
|
||||||
|
body: `${name}${versionNumber ? `/${versionNumber}` : ""}`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
sections.push({
|
||||||
|
title: "Usage",
|
||||||
|
body: ` $ ${name} ${this.usageText || this.rawName}`
|
||||||
|
});
|
||||||
|
const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
|
||||||
|
if (showCommands) {
|
||||||
|
const longestCommandName = findLongest(commands.map((command) => command.rawName));
|
||||||
|
sections.push({
|
||||||
|
title: "Commands",
|
||||||
|
body: commands.map((command) => {
|
||||||
|
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
|
||||||
|
}).join("\n")
|
||||||
|
});
|
||||||
|
sections.push({
|
||||||
|
title: `For more info, run any command with the \`--help\` flag`,
|
||||||
|
body: commands.map((command) => ` $ ${name}${command.name === "" ? "" : ` ${command.name}`} --help`).join("\n")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
|
||||||
|
if (!this.isGlobalCommand && !this.isDefaultCommand) {
|
||||||
|
options = options.filter((option) => option.name !== "version");
|
||||||
|
}
|
||||||
|
if (options.length > 0) {
|
||||||
|
const longestOptionName = findLongest(options.map((option) => option.rawName));
|
||||||
|
sections.push({
|
||||||
|
title: "Options",
|
||||||
|
body: options.map((option) => {
|
||||||
|
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === void 0 ? "" : `(default: ${option.config.default})`}`;
|
||||||
|
}).join("\n")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.examples.length > 0) {
|
||||||
|
sections.push({
|
||||||
|
title: "Examples",
|
||||||
|
body: this.examples.map((example) => {
|
||||||
|
if (typeof example === "function") {
|
||||||
|
return example(name);
|
||||||
|
}
|
||||||
|
return example;
|
||||||
|
}).join("\n")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (helpCallback) {
|
||||||
|
sections = helpCallback(sections) || sections;
|
||||||
|
}
|
||||||
|
console.log(sections.map((section) => {
|
||||||
|
return section.title ? `${section.title}:
|
||||||
|
${section.body}` : section.body;
|
||||||
|
}).join("\n\n"));
|
||||||
|
}
|
||||||
|
outputVersion() {
|
||||||
|
const {name} = this.cli;
|
||||||
|
const {versionNumber} = this.cli.globalCommand;
|
||||||
|
if (versionNumber) {
|
||||||
|
console.log(`${name}/${versionNumber} ${platformInfo}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkRequiredArgs() {
|
||||||
|
const minimalArgsCount = this.args.filter((arg) => arg.required).length;
|
||||||
|
if (this.cli.args.length < minimalArgsCount) {
|
||||||
|
throw new CACError(`missing required args for command \`${this.rawName}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkUnknownOptions() {
|
||||||
|
const {options, globalCommand} = this.cli;
|
||||||
|
if (!this.config.allowUnknownOptions) {
|
||||||
|
for (const name of Object.keys(options)) {
|
||||||
|
if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) {
|
||||||
|
throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkOptionValue() {
|
||||||
|
const {options: parsedOptions, globalCommand} = this.cli;
|
||||||
|
const options = [...globalCommand.options, ...this.options];
|
||||||
|
for (const option of options) {
|
||||||
|
const value = parsedOptions[option.name.split(".")[0]];
|
||||||
|
if (option.required) {
|
||||||
|
const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));
|
||||||
|
if (value === true || value === false && !hasNegated) {
|
||||||
|
throw new CACError(`option \`${option.rawName}\` value is missing`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class GlobalCommand extends Command {
|
||||||
|
constructor(cli) {
|
||||||
|
super("@@global@@", "", {}, cli);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var __assign = Object.assign;
|
||||||
|
class CAC extends EventEmitter {
|
||||||
|
constructor(name = "") {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
this.commands = [];
|
||||||
|
this.rawArgs = [];
|
||||||
|
this.args = [];
|
||||||
|
this.options = {};
|
||||||
|
this.globalCommand = new GlobalCommand(this);
|
||||||
|
this.globalCommand.usage("<command> [options]");
|
||||||
|
}
|
||||||
|
usage(text) {
|
||||||
|
this.globalCommand.usage(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
command(rawName, description, config) {
|
||||||
|
const command = new Command(rawName, description || "", config, this);
|
||||||
|
command.globalCommand = this.globalCommand;
|
||||||
|
this.commands.push(command);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
option(rawName, description, config) {
|
||||||
|
this.globalCommand.option(rawName, description, config);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
help(callback) {
|
||||||
|
this.globalCommand.option("-h, --help", "Display this message");
|
||||||
|
this.globalCommand.helpCallback = callback;
|
||||||
|
this.showHelpOnExit = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
version(version, customFlags = "-v, --version") {
|
||||||
|
this.globalCommand.version(version, customFlags);
|
||||||
|
this.showVersionOnExit = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
example(example) {
|
||||||
|
this.globalCommand.example(example);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
outputHelp() {
|
||||||
|
if (this.matchedCommand) {
|
||||||
|
this.matchedCommand.outputHelp();
|
||||||
|
} else {
|
||||||
|
this.globalCommand.outputHelp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputVersion() {
|
||||||
|
this.globalCommand.outputVersion();
|
||||||
|
}
|
||||||
|
setParsedInfo({args, options}, matchedCommand, matchedCommandName) {
|
||||||
|
this.args = args;
|
||||||
|
this.options = options;
|
||||||
|
if (matchedCommand) {
|
||||||
|
this.matchedCommand = matchedCommand;
|
||||||
|
}
|
||||||
|
if (matchedCommandName) {
|
||||||
|
this.matchedCommandName = matchedCommandName;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
unsetMatchedCommand() {
|
||||||
|
this.matchedCommand = void 0;
|
||||||
|
this.matchedCommandName = void 0;
|
||||||
|
}
|
||||||
|
parse(argv = processArgs, {
|
||||||
|
run = true
|
||||||
|
} = {}) {
|
||||||
|
this.rawArgs = argv;
|
||||||
|
if (!this.name) {
|
||||||
|
this.name = argv[1] ? getFileName(argv[1]) : "cli";
|
||||||
|
}
|
||||||
|
let shouldParse = true;
|
||||||
|
for (const command of this.commands) {
|
||||||
|
const parsed = this.mri(argv.slice(2), command);
|
||||||
|
const commandName = parsed.args[0];
|
||||||
|
if (command.isMatched(commandName)) {
|
||||||
|
shouldParse = false;
|
||||||
|
const parsedInfo = __assign(__assign({}, parsed), {
|
||||||
|
args: parsed.args.slice(1)
|
||||||
|
});
|
||||||
|
this.setParsedInfo(parsedInfo, command, commandName);
|
||||||
|
this.emit(`command:${commandName}`, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldParse) {
|
||||||
|
for (const command of this.commands) {
|
||||||
|
if (command.name === "") {
|
||||||
|
shouldParse = false;
|
||||||
|
const parsed = this.mri(argv.slice(2), command);
|
||||||
|
this.setParsedInfo(parsed, command);
|
||||||
|
this.emit(`command:!`, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldParse) {
|
||||||
|
const parsed = this.mri(argv.slice(2));
|
||||||
|
this.setParsedInfo(parsed);
|
||||||
|
}
|
||||||
|
if (this.options.help && this.showHelpOnExit) {
|
||||||
|
this.outputHelp();
|
||||||
|
run = false;
|
||||||
|
this.unsetMatchedCommand();
|
||||||
|
}
|
||||||
|
if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) {
|
||||||
|
this.outputVersion();
|
||||||
|
run = false;
|
||||||
|
this.unsetMatchedCommand();
|
||||||
|
}
|
||||||
|
const parsedArgv = {args: this.args, options: this.options};
|
||||||
|
if (run) {
|
||||||
|
this.runMatchedCommand();
|
||||||
|
}
|
||||||
|
if (!this.matchedCommand && this.args[0]) {
|
||||||
|
this.emit("command:*");
|
||||||
|
}
|
||||||
|
return parsedArgv;
|
||||||
|
}
|
||||||
|
mri(argv, command) {
|
||||||
|
const cliOptions = [
|
||||||
|
...this.globalCommand.options,
|
||||||
|
...command ? command.options : []
|
||||||
|
];
|
||||||
|
const mriOptions = getMriOptions(cliOptions);
|
||||||
|
let argsAfterDoubleDashes = [];
|
||||||
|
const doubleDashesIndex = argv.indexOf("--");
|
||||||
|
if (doubleDashesIndex > -1) {
|
||||||
|
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
|
||||||
|
argv = argv.slice(0, doubleDashesIndex);
|
||||||
|
}
|
||||||
|
let parsed = mri2(argv, mriOptions);
|
||||||
|
parsed = Object.keys(parsed).reduce((res, name) => {
|
||||||
|
return __assign(__assign({}, res), {
|
||||||
|
[camelcaseOptionName(name)]: parsed[name]
|
||||||
|
});
|
||||||
|
}, {_: []});
|
||||||
|
const args = parsed._;
|
||||||
|
const options = {
|
||||||
|
"--": argsAfterDoubleDashes
|
||||||
|
};
|
||||||
|
const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
|
||||||
|
let transforms = Object.create(null);
|
||||||
|
for (const cliOption of cliOptions) {
|
||||||
|
if (!ignoreDefault && cliOption.config.default !== void 0) {
|
||||||
|
for (const name of cliOption.names) {
|
||||||
|
options[name] = cliOption.config.default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Array.isArray(cliOption.config.type)) {
|
||||||
|
if (transforms[cliOption.name] === void 0) {
|
||||||
|
transforms[cliOption.name] = Object.create(null);
|
||||||
|
transforms[cliOption.name]["shouldTransform"] = true;
|
||||||
|
transforms[cliOption.name]["transformFunction"] = cliOption.config.type[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const key of Object.keys(parsed)) {
|
||||||
|
if (key !== "_") {
|
||||||
|
const keys = key.split(".");
|
||||||
|
setDotProp(options, keys, parsed[key]);
|
||||||
|
setByType(options, transforms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
args,
|
||||||
|
options
|
||||||
|
};
|
||||||
|
}
|
||||||
|
runMatchedCommand() {
|
||||||
|
const {args, options, matchedCommand: command} = this;
|
||||||
|
if (!command || !command.commandAction)
|
||||||
|
return;
|
||||||
|
command.checkUnknownOptions();
|
||||||
|
command.checkOptionValue();
|
||||||
|
command.checkRequiredArgs();
|
||||||
|
const actionArgs = [];
|
||||||
|
command.args.forEach((arg, index) => {
|
||||||
|
if (arg.variadic) {
|
||||||
|
actionArgs.push(args.slice(index));
|
||||||
|
} else {
|
||||||
|
actionArgs.push(args[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
actionArgs.push(options);
|
||||||
|
return command.commandAction.apply(this, actionArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cac = (name = "") => new CAC(name);
|
||||||
|
|
||||||
|
export default cac;
|
||||||
|
export { CAC, Command, cac };
|
|
@ -0,0 +1,11 @@
|
||||||
|
const { cac, CAC, Command } = require('./dist/index')
|
||||||
|
|
||||||
|
// For backwards compatibility
|
||||||
|
module.exports = cac
|
||||||
|
|
||||||
|
Object.assign(module.exports, {
|
||||||
|
default: cac,
|
||||||
|
cac,
|
||||||
|
CAC,
|
||||||
|
Command,
|
||||||
|
})
|
|
@ -0,0 +1,2 @@
|
||||||
|
// Deno users should use mod.ts instead
|
||||||
|
export * from './deno/index.ts'
|
|
@ -0,0 +1,2 @@
|
||||||
|
// For Deno
|
||||||
|
export * from './deno/index.ts'
|
|
@ -0,0 +1,104 @@
|
||||||
|
{
|
||||||
|
"name": "cac",
|
||||||
|
"version": "6.7.14",
|
||||||
|
"description": "Simple yet powerful framework for building command-line apps.",
|
||||||
|
"repository": {
|
||||||
|
"url": "egoist/cac",
|
||||||
|
"type": "git"
|
||||||
|
},
|
||||||
|
"main": "index-compat.js",
|
||||||
|
"module": "dist/index.mjs",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"import": "./dist/index.mjs",
|
||||||
|
"require": "./index-compat.js"
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json",
|
||||||
|
"./*": "./*"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"!**/__test__/**",
|
||||||
|
"/mod.js",
|
||||||
|
"/mod.ts",
|
||||||
|
"/deno",
|
||||||
|
"/index-compat.js"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest",
|
||||||
|
"test:cov": "jest --coverage",
|
||||||
|
"build:deno": "node -r sucrase/register scripts/build-deno.ts",
|
||||||
|
"build:node": "rollup -c",
|
||||||
|
"build": "yarn build:deno && yarn build:node",
|
||||||
|
"toc": "markdown-toc -i README.md",
|
||||||
|
"prepublishOnly": "npm run build && cp mod.js mod.mjs",
|
||||||
|
"docs:api": "typedoc --out api-doc --readme none --exclude \"**/__test__/**\" --theme minimal"
|
||||||
|
},
|
||||||
|
"author": "egoist <0x142857@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.12.10",
|
||||||
|
"@babel/plugin-syntax-typescript": "^7.12.1",
|
||||||
|
"@rollup/plugin-commonjs": "^17.0.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^11.0.0",
|
||||||
|
"@types/fs-extra": "^9.0.5",
|
||||||
|
"@types/jest": "^26.0.19",
|
||||||
|
"@types/mri": "^1.1.0",
|
||||||
|
"cz-conventional-changelog": "^2.1.0",
|
||||||
|
"esbuild": "^0.8.21",
|
||||||
|
"eslint-config-rem": "^3.0.0",
|
||||||
|
"execa": "^5.0.0",
|
||||||
|
"fs-extra": "^9.0.1",
|
||||||
|
"globby": "^11.0.1",
|
||||||
|
"husky": "^1.2.0",
|
||||||
|
"jest": "^24.9.0",
|
||||||
|
"lint-staged": "^8.1.0",
|
||||||
|
"markdown-toc": "^1.2.0",
|
||||||
|
"mri": "^1.1.6",
|
||||||
|
"prettier": "^2.2.1",
|
||||||
|
"rollup": "^2.34.2",
|
||||||
|
"rollup-plugin-dts": "^2.0.1",
|
||||||
|
"rollup-plugin-esbuild": "^2.6.1",
|
||||||
|
"semantic-release": "^17.3.0",
|
||||||
|
"sucrase": "^3.16.0",
|
||||||
|
"ts-jest": "^26.4.4",
|
||||||
|
"ts-node": "^9.1.1",
|
||||||
|
"typedoc": "^0.19.2",
|
||||||
|
"typescript": "^4.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"branch": "master"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"commitizen": {
|
||||||
|
"path": "./node_modules/cz-conventional-changelog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"linters": {
|
||||||
|
"*.{js,json,ts}": [
|
||||||
|
"prettier --write",
|
||||||
|
"git add"
|
||||||
|
],
|
||||||
|
"*.md": [
|
||||||
|
"markdown-toc -i",
|
||||||
|
"prettier --write",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ignore": [
|
||||||
|
"dist/**",
|
||||||
|
"mod.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "npm t && lint-staged"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,395 +1,395 @@
|
||||||
Attribution 4.0 International
|
Attribution 4.0 International
|
||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
|
||||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||||
does not provide legal services or legal advice. Distribution of
|
does not provide legal services or legal advice. Distribution of
|
||||||
Creative Commons public licenses does not create a lawyer-client or
|
Creative Commons public licenses does not create a lawyer-client or
|
||||||
other relationship. Creative Commons makes its licenses and related
|
other relationship. Creative Commons makes its licenses and related
|
||||||
information available on an "as-is" basis. Creative Commons gives no
|
information available on an "as-is" basis. Creative Commons gives no
|
||||||
warranties regarding its licenses, any material licensed under their
|
warranties regarding its licenses, any material licensed under their
|
||||||
terms and conditions, or any related information. Creative Commons
|
terms and conditions, or any related information. Creative Commons
|
||||||
disclaims all liability for damages resulting from their use to the
|
disclaims all liability for damages resulting from their use to the
|
||||||
fullest extent possible.
|
fullest extent possible.
|
||||||
|
|
||||||
Using Creative Commons Public Licenses
|
Using Creative Commons Public Licenses
|
||||||
|
|
||||||
Creative Commons public licenses provide a standard set of terms and
|
Creative Commons public licenses provide a standard set of terms and
|
||||||
conditions that creators and other rights holders may use to share
|
conditions that creators and other rights holders may use to share
|
||||||
original works of authorship and other material subject to copyright
|
original works of authorship and other material subject to copyright
|
||||||
and certain other rights specified in the public license below. The
|
and certain other rights specified in the public license below. The
|
||||||
following considerations are for informational purposes only, are not
|
following considerations are for informational purposes only, are not
|
||||||
exhaustive, and do not form part of our licenses.
|
exhaustive, and do not form part of our licenses.
|
||||||
|
|
||||||
Considerations for licensors: Our public licenses are
|
Considerations for licensors: Our public licenses are
|
||||||
intended for use by those authorized to give the public
|
intended for use by those authorized to give the public
|
||||||
permission to use material in ways otherwise restricted by
|
permission to use material in ways otherwise restricted by
|
||||||
copyright and certain other rights. Our licenses are
|
copyright and certain other rights. Our licenses are
|
||||||
irrevocable. Licensors should read and understand the terms
|
irrevocable. Licensors should read and understand the terms
|
||||||
and conditions of the license they choose before applying it.
|
and conditions of the license they choose before applying it.
|
||||||
Licensors should also secure all rights necessary before
|
Licensors should also secure all rights necessary before
|
||||||
applying our licenses so that the public can reuse the
|
applying our licenses so that the public can reuse the
|
||||||
material as expected. Licensors should clearly mark any
|
material as expected. Licensors should clearly mark any
|
||||||
material not subject to the license. This includes other CC-
|
material not subject to the license. This includes other CC-
|
||||||
licensed material, or material used under an exception or
|
licensed material, or material used under an exception or
|
||||||
limitation to copyright. More considerations for licensors:
|
limitation to copyright. More considerations for licensors:
|
||||||
wiki.creativecommons.org/Considerations_for_licensors
|
wiki.creativecommons.org/Considerations_for_licensors
|
||||||
|
|
||||||
Considerations for the public: By using one of our public
|
Considerations for the public: By using one of our public
|
||||||
licenses, a licensor grants the public permission to use the
|
licenses, a licensor grants the public permission to use the
|
||||||
licensed material under specified terms and conditions. If
|
licensed material under specified terms and conditions. If
|
||||||
the licensor's permission is not necessary for any reason--for
|
the licensor's permission is not necessary for any reason--for
|
||||||
example, because of any applicable exception or limitation to
|
example, because of any applicable exception or limitation to
|
||||||
copyright--then that use is not regulated by the license. Our
|
copyright--then that use is not regulated by the license. Our
|
||||||
licenses grant only permissions under copyright and certain
|
licenses grant only permissions under copyright and certain
|
||||||
other rights that a licensor has authority to grant. Use of
|
other rights that a licensor has authority to grant. Use of
|
||||||
the licensed material may still be restricted for other
|
the licensed material may still be restricted for other
|
||||||
reasons, including because others have copyright or other
|
reasons, including because others have copyright or other
|
||||||
rights in the material. A licensor may make special requests,
|
rights in the material. A licensor may make special requests,
|
||||||
such as asking that all changes be marked or described.
|
such as asking that all changes be marked or described.
|
||||||
Although not required by our licenses, you are encouraged to
|
Although not required by our licenses, you are encouraged to
|
||||||
respect those requests where reasonable. More_considerations
|
respect those requests where reasonable. More_considerations
|
||||||
for the public:
|
for the public:
|
||||||
wiki.creativecommons.org/Considerations_for_licensees
|
wiki.creativecommons.org/Considerations_for_licensees
|
||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
|
||||||
Creative Commons Attribution 4.0 International Public License
|
Creative Commons Attribution 4.0 International Public License
|
||||||
|
|
||||||
By exercising the Licensed Rights (defined below), You accept and agree
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
to be bound by the terms and conditions of this Creative Commons
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
Attribution 4.0 International Public License ("Public License"). To the
|
Attribution 4.0 International Public License ("Public License"). To the
|
||||||
extent this Public License may be interpreted as a contract, You are
|
extent this Public License may be interpreted as a contract, You are
|
||||||
granted the Licensed Rights in consideration of Your acceptance of
|
granted the Licensed Rights in consideration of Your acceptance of
|
||||||
these terms and conditions, and the Licensor grants You such rights in
|
these terms and conditions, and the Licensor grants You such rights in
|
||||||
consideration of benefits the Licensor receives from making the
|
consideration of benefits the Licensor receives from making the
|
||||||
Licensed Material available under these terms and conditions.
|
Licensed Material available under these terms and conditions.
|
||||||
|
|
||||||
|
|
||||||
Section 1 -- Definitions.
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
a. Adapted Material means material subject to Copyright and Similar
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
Rights that is derived from or based upon the Licensed Material
|
Rights that is derived from or based upon the Licensed Material
|
||||||
and in which the Licensed Material is translated, altered,
|
and in which the Licensed Material is translated, altered,
|
||||||
arranged, transformed, or otherwise modified in a manner requiring
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
permission under the Copyright and Similar Rights held by the
|
permission under the Copyright and Similar Rights held by the
|
||||||
Licensor. For purposes of this Public License, where the Licensed
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
Material is a musical work, performance, or sound recording,
|
Material is a musical work, performance, or sound recording,
|
||||||
Adapted Material is always produced where the Licensed Material is
|
Adapted Material is always produced where the Licensed Material is
|
||||||
synched in timed relation with a moving image.
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
b. Adapter's License means the license You apply to Your Copyright
|
b. Adapter's License means the license You apply to Your Copyright
|
||||||
and Similar Rights in Your contributions to Adapted Material in
|
and Similar Rights in Your contributions to Adapted Material in
|
||||||
accordance with the terms and conditions of this Public License.
|
accordance with the terms and conditions of this Public License.
|
||||||
|
|
||||||
c. Copyright and Similar Rights means copyright and/or similar rights
|
c. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
closely related to copyright including, without limitation,
|
closely related to copyright including, without limitation,
|
||||||
performance, broadcast, sound recording, and Sui Generis Database
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
Rights, without regard to how the rights are labeled or
|
Rights, without regard to how the rights are labeled or
|
||||||
categorized. For purposes of this Public License, the rights
|
categorized. For purposes of this Public License, the rights
|
||||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
Rights.
|
Rights.
|
||||||
|
|
||||||
d. Effective Technological Measures means those measures that, in the
|
d. Effective Technological Measures means those measures that, in the
|
||||||
absence of proper authority, may not be circumvented under laws
|
absence of proper authority, may not be circumvented under laws
|
||||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
Treaty adopted on December 20, 1996, and/or similar international
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
agreements.
|
agreements.
|
||||||
|
|
||||||
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
any other exception or limitation to Copyright and Similar Rights
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
that applies to Your use of the Licensed Material.
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
f. Licensed Material means the artistic or literary work, database,
|
f. Licensed Material means the artistic or literary work, database,
|
||||||
or other material to which the Licensor applied this Public
|
or other material to which the Licensor applied this Public
|
||||||
License.
|
License.
|
||||||
|
|
||||||
g. Licensed Rights means the rights granted to You subject to the
|
g. Licensed Rights means the rights granted to You subject to the
|
||||||
terms and conditions of this Public License, which are limited to
|
terms and conditions of this Public License, which are limited to
|
||||||
all Copyright and Similar Rights that apply to Your use of the
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
Licensed Material and that the Licensor has authority to license.
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
h. Licensor means the individual(s) or entity(ies) granting rights
|
h. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
under this Public License.
|
under this Public License.
|
||||||
|
|
||||||
i. Share means to provide material to the public by any means or
|
i. Share means to provide material to the public by any means or
|
||||||
process that requires permission under the Licensed Rights, such
|
process that requires permission under the Licensed Rights, such
|
||||||
as reproduction, public display, public performance, distribution,
|
as reproduction, public display, public performance, distribution,
|
||||||
dissemination, communication, or importation, and to make material
|
dissemination, communication, or importation, and to make material
|
||||||
available to the public including in ways that members of the
|
available to the public including in ways that members of the
|
||||||
public may access the material from a place and at a time
|
public may access the material from a place and at a time
|
||||||
individually chosen by them.
|
individually chosen by them.
|
||||||
|
|
||||||
j. Sui Generis Database Rights means rights other than copyright
|
j. Sui Generis Database Rights means rights other than copyright
|
||||||
resulting from Directive 96/9/EC of the European Parliament and of
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
the Council of 11 March 1996 on the legal protection of databases,
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
as amended and/or succeeded, as well as other essentially
|
as amended and/or succeeded, as well as other essentially
|
||||||
equivalent rights anywhere in the world.
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
k. You means the individual or entity exercising the Licensed Rights
|
k. You means the individual or entity exercising the Licensed Rights
|
||||||
under this Public License. Your has a corresponding meaning.
|
under this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
|
||||||
Section 2 -- Scope.
|
Section 2 -- Scope.
|
||||||
|
|
||||||
a. License grant.
|
a. License grant.
|
||||||
|
|
||||||
1. Subject to the terms and conditions of this Public License,
|
1. Subject to the terms and conditions of this Public License,
|
||||||
the Licensor hereby grants You a worldwide, royalty-free,
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
non-sublicensable, non-exclusive, irrevocable license to
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
exercise the Licensed Rights in the Licensed Material to:
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
a. reproduce and Share the Licensed Material, in whole or
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
in part; and
|
in part; and
|
||||||
|
|
||||||
b. produce, reproduce, and Share Adapted Material.
|
b. produce, reproduce, and Share Adapted Material.
|
||||||
|
|
||||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
Exceptions and Limitations apply to Your use, this Public
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
License does not apply, and You do not need to comply with
|
License does not apply, and You do not need to comply with
|
||||||
its terms and conditions.
|
its terms and conditions.
|
||||||
|
|
||||||
3. Term. The term of this Public License is specified in Section
|
3. Term. The term of this Public License is specified in Section
|
||||||
6(a).
|
6(a).
|
||||||
|
|
||||||
4. Media and formats; technical modifications allowed. The
|
4. Media and formats; technical modifications allowed. The
|
||||||
Licensor authorizes You to exercise the Licensed Rights in
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
all media and formats whether now known or hereafter created,
|
all media and formats whether now known or hereafter created,
|
||||||
and to make technical modifications necessary to do so. The
|
and to make technical modifications necessary to do so. The
|
||||||
Licensor waives and/or agrees not to assert any right or
|
Licensor waives and/or agrees not to assert any right or
|
||||||
authority to forbid You from making technical modifications
|
authority to forbid You from making technical modifications
|
||||||
necessary to exercise the Licensed Rights, including
|
necessary to exercise the Licensed Rights, including
|
||||||
technical modifications necessary to circumvent Effective
|
technical modifications necessary to circumvent Effective
|
||||||
Technological Measures. For purposes of this Public License,
|
Technological Measures. For purposes of this Public License,
|
||||||
simply making modifications authorized by this Section 2(a)
|
simply making modifications authorized by this Section 2(a)
|
||||||
(4) never produces Adapted Material.
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
5. Downstream recipients.
|
5. Downstream recipients.
|
||||||
|
|
||||||
a. Offer from the Licensor -- Licensed Material. Every
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
recipient of the Licensed Material automatically
|
recipient of the Licensed Material automatically
|
||||||
receives an offer from the Licensor to exercise the
|
receives an offer from the Licensor to exercise the
|
||||||
Licensed Rights under the terms and conditions of this
|
Licensed Rights under the terms and conditions of this
|
||||||
Public License.
|
Public License.
|
||||||
|
|
||||||
b. No downstream restrictions. You may not offer or impose
|
b. No downstream restrictions. You may not offer or impose
|
||||||
any additional or different terms or conditions on, or
|
any additional or different terms or conditions on, or
|
||||||
apply any Effective Technological Measures to, the
|
apply any Effective Technological Measures to, the
|
||||||
Licensed Material if doing so restricts exercise of the
|
Licensed Material if doing so restricts exercise of the
|
||||||
Licensed Rights by any recipient of the Licensed
|
Licensed Rights by any recipient of the Licensed
|
||||||
Material.
|
Material.
|
||||||
|
|
||||||
6. No endorsement. Nothing in this Public License constitutes or
|
6. No endorsement. Nothing in this Public License constitutes or
|
||||||
may be construed as permission to assert or imply that You
|
may be construed as permission to assert or imply that You
|
||||||
are, or that Your use of the Licensed Material is, connected
|
are, or that Your use of the Licensed Material is, connected
|
||||||
with, or sponsored, endorsed, or granted official status by,
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
the Licensor or others designated to receive attribution as
|
the Licensor or others designated to receive attribution as
|
||||||
provided in Section 3(a)(1)(A)(i).
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
b. Other rights.
|
b. Other rights.
|
||||||
|
|
||||||
1. Moral rights, such as the right of integrity, are not
|
1. Moral rights, such as the right of integrity, are not
|
||||||
licensed under this Public License, nor are publicity,
|
licensed under this Public License, nor are publicity,
|
||||||
privacy, and/or other similar personality rights; however, to
|
privacy, and/or other similar personality rights; however, to
|
||||||
the extent possible, the Licensor waives and/or agrees not to
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
assert any such rights held by the Licensor to the limited
|
assert any such rights held by the Licensor to the limited
|
||||||
extent necessary to allow You to exercise the Licensed
|
extent necessary to allow You to exercise the Licensed
|
||||||
Rights, but not otherwise.
|
Rights, but not otherwise.
|
||||||
|
|
||||||
2. Patent and trademark rights are not licensed under this
|
2. Patent and trademark rights are not licensed under this
|
||||||
Public License.
|
Public License.
|
||||||
|
|
||||||
3. To the extent possible, the Licensor waives any right to
|
3. To the extent possible, the Licensor waives any right to
|
||||||
collect royalties from You for the exercise of the Licensed
|
collect royalties from You for the exercise of the Licensed
|
||||||
Rights, whether directly or through a collecting society
|
Rights, whether directly or through a collecting society
|
||||||
under any voluntary or waivable statutory or compulsory
|
under any voluntary or waivable statutory or compulsory
|
||||||
licensing scheme. In all other cases the Licensor expressly
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
reserves any right to collect such royalties.
|
reserves any right to collect such royalties.
|
||||||
|
|
||||||
|
|
||||||
Section 3 -- License Conditions.
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
Your exercise of the Licensed Rights is expressly made subject to the
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
following conditions.
|
following conditions.
|
||||||
|
|
||||||
a. Attribution.
|
a. Attribution.
|
||||||
|
|
||||||
1. If You Share the Licensed Material (including in modified
|
1. If You Share the Licensed Material (including in modified
|
||||||
form), You must:
|
form), You must:
|
||||||
|
|
||||||
a. retain the following if it is supplied by the Licensor
|
a. retain the following if it is supplied by the Licensor
|
||||||
with the Licensed Material:
|
with the Licensed Material:
|
||||||
|
|
||||||
i. identification of the creator(s) of the Licensed
|
i. identification of the creator(s) of the Licensed
|
||||||
Material and any others designated to receive
|
Material and any others designated to receive
|
||||||
attribution, in any reasonable manner requested by
|
attribution, in any reasonable manner requested by
|
||||||
the Licensor (including by pseudonym if
|
the Licensor (including by pseudonym if
|
||||||
designated);
|
designated);
|
||||||
|
|
||||||
ii. a copyright notice;
|
ii. a copyright notice;
|
||||||
|
|
||||||
iii. a notice that refers to this Public License;
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
iv. a notice that refers to the disclaimer of
|
iv. a notice that refers to the disclaimer of
|
||||||
warranties;
|
warranties;
|
||||||
|
|
||||||
v. a URI or hyperlink to the Licensed Material to the
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
extent reasonably practicable;
|
extent reasonably practicable;
|
||||||
|
|
||||||
b. indicate if You modified the Licensed Material and
|
b. indicate if You modified the Licensed Material and
|
||||||
retain an indication of any previous modifications; and
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
c. indicate the Licensed Material is licensed under this
|
c. indicate the Licensed Material is licensed under this
|
||||||
Public License, and include the text of, or the URI or
|
Public License, and include the text of, or the URI or
|
||||||
hyperlink to, this Public License.
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
reasonable manner based on the medium, means, and context in
|
reasonable manner based on the medium, means, and context in
|
||||||
which You Share the Licensed Material. For example, it may be
|
which You Share the Licensed Material. For example, it may be
|
||||||
reasonable to satisfy the conditions by providing a URI or
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
hyperlink to a resource that includes the required
|
hyperlink to a resource that includes the required
|
||||||
information.
|
information.
|
||||||
|
|
||||||
3. If requested by the Licensor, You must remove any of the
|
3. If requested by the Licensor, You must remove any of the
|
||||||
information required by Section 3(a)(1)(A) to the extent
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
reasonably practicable.
|
reasonably practicable.
|
||||||
|
|
||||||
4. If You Share Adapted Material You produce, the Adapter's
|
4. If You Share Adapted Material You produce, the Adapter's
|
||||||
License You apply must not prevent recipients of the Adapted
|
License You apply must not prevent recipients of the Adapted
|
||||||
Material from complying with this Public License.
|
Material from complying with this Public License.
|
||||||
|
|
||||||
|
|
||||||
Section 4 -- Sui Generis Database Rights.
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
Where the Licensed Rights include Sui Generis Database Rights that
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
apply to Your use of the Licensed Material:
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
to extract, reuse, reproduce, and Share all or a substantial
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
portion of the contents of the database;
|
portion of the contents of the database;
|
||||||
|
|
||||||
b. if You include all or a substantial portion of the database
|
b. if You include all or a substantial portion of the database
|
||||||
contents in a database in which You have Sui Generis Database
|
contents in a database in which You have Sui Generis Database
|
||||||
Rights, then the database in which You have Sui Generis Database
|
Rights, then the database in which You have Sui Generis Database
|
||||||
Rights (but not its individual contents) is Adapted Material; and
|
Rights (but not its individual contents) is Adapted Material; and
|
||||||
|
|
||||||
c. You must comply with the conditions in Section 3(a) if You Share
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
all or a substantial portion of the contents of the database.
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
For the avoidance of doubt, this Section 4 supplements and does not
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
replace Your obligations under this Public License where the Licensed
|
replace Your obligations under this Public License where the Licensed
|
||||||
Rights include other Copyright and Similar Rights.
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
|
||||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
c. The disclaimer of warranties and limitation of liability provided
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
above shall be interpreted in a manner that, to the extent
|
above shall be interpreted in a manner that, to the extent
|
||||||
possible, most closely approximates an absolute disclaimer and
|
possible, most closely approximates an absolute disclaimer and
|
||||||
waiver of all liability.
|
waiver of all liability.
|
||||||
|
|
||||||
|
|
||||||
Section 6 -- Term and Termination.
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
a. This Public License applies for the term of the Copyright and
|
a. This Public License applies for the term of the Copyright and
|
||||||
Similar Rights licensed here. However, if You fail to comply with
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
this Public License, then Your rights under this Public License
|
this Public License, then Your rights under this Public License
|
||||||
terminate automatically.
|
terminate automatically.
|
||||||
|
|
||||||
b. Where Your right to use the Licensed Material has terminated under
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
Section 6(a), it reinstates:
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
1. automatically as of the date the violation is cured, provided
|
1. automatically as of the date the violation is cured, provided
|
||||||
it is cured within 30 days of Your discovery of the
|
it is cured within 30 days of Your discovery of the
|
||||||
violation; or
|
violation; or
|
||||||
|
|
||||||
2. upon express reinstatement by the Licensor.
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
right the Licensor may have to seek remedies for Your violations
|
right the Licensor may have to seek remedies for Your violations
|
||||||
of this Public License.
|
of this Public License.
|
||||||
|
|
||||||
c. For the avoidance of doubt, the Licensor may also offer the
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
Licensed Material under separate terms or conditions or stop
|
Licensed Material under separate terms or conditions or stop
|
||||||
distributing the Licensed Material at any time; however, doing so
|
distributing the Licensed Material at any time; however, doing so
|
||||||
will not terminate this Public License.
|
will not terminate this Public License.
|
||||||
|
|
||||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
License.
|
License.
|
||||||
|
|
||||||
|
|
||||||
Section 7 -- Other Terms and Conditions.
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
a. The Licensor shall not be bound by any additional or different
|
a. The Licensor shall not be bound by any additional or different
|
||||||
terms or conditions communicated by You unless expressly agreed.
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
b. Any arrangements, understandings, or agreements regarding the
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
Licensed Material not stated herein are separate from and
|
Licensed Material not stated herein are separate from and
|
||||||
independent of the terms and conditions of this Public License.
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
|
||||||
Section 8 -- Interpretation.
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
a. For the avoidance of doubt, this Public License does not, and
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
conditions on any use of the Licensed Material that could lawfully
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
be made without permission under this Public License.
|
be made without permission under this Public License.
|
||||||
|
|
||||||
b. To the extent possible, if any provision of this Public License is
|
b. To the extent possible, if any provision of this Public License is
|
||||||
deemed unenforceable, it shall be automatically reformed to the
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
minimum extent necessary to make it enforceable. If the provision
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
cannot be reformed, it shall be severed from this Public License
|
cannot be reformed, it shall be severed from this Public License
|
||||||
without affecting the enforceability of the remaining terms and
|
without affecting the enforceability of the remaining terms and
|
||||||
conditions.
|
conditions.
|
||||||
|
|
||||||
c. No term or condition of this Public License will be waived and no
|
c. No term or condition of this Public License will be waived and no
|
||||||
failure to comply consented to unless expressly agreed to by the
|
failure to comply consented to unless expressly agreed to by the
|
||||||
Licensor.
|
Licensor.
|
||||||
|
|
||||||
d. Nothing in this Public License constitutes or may be interpreted
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
as a limitation upon, or waiver of, any privileges and immunities
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
that apply to the Licensor or You, including from the legal
|
that apply to the Licensor or You, including from the legal
|
||||||
processes of any jurisdiction or authority.
|
processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
|
||||||
Creative Commons is not a party to its public
|
Creative Commons is not a party to its public
|
||||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||||
its public licenses to material it publishes and in those instances
|
its public licenses to material it publishes and in those instances
|
||||||
will be considered the “Licensor.” The text of the Creative Commons
|
will be considered the “Licensor.” The text of the Creative Commons
|
||||||
public licenses is dedicated to the public domain under the CC0 Public
|
public licenses is dedicated to the public domain under the CC0 Public
|
||||||
Domain Dedication. Except for the limited purpose of indicating that
|
Domain Dedication. Except for the limited purpose of indicating that
|
||||||
material is shared under a Creative Commons public license or as
|
material is shared under a Creative Commons public license or as
|
||||||
otherwise permitted by the Creative Commons policies published at
|
otherwise permitted by the Creative Commons policies published at
|
||||||
creativecommons.org/policies, Creative Commons does not authorize the
|
creativecommons.org/policies, Creative Commons does not authorize the
|
||||||
use of the trademark "Creative Commons" or any other trademark or logo
|
use of the trademark "Creative Commons" or any other trademark or logo
|
||||||
of Creative Commons without its prior written consent including,
|
of Creative Commons without its prior written consent including,
|
||||||
without limitation, in connection with any unauthorized modifications
|
without limitation, in connection with any unauthorized modifications
|
||||||
to any of its public licenses or any other arrangements,
|
to any of its public licenses or any other arrangements,
|
||||||
understandings, or agreements concerning use of licensed material. For
|
understandings, or agreements concerning use of licensed material. For
|
||||||
the avoidance of doubt, this paragraph does not form part of the
|
the avoidance of doubt, this paragraph does not form part of the
|
||||||
public licenses.
|
public licenses.
|
||||||
|
|
||||||
Creative Commons may be contacted at creativecommons.org.
|
Creative Commons may be contacted at creativecommons.org.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# caniuse-lite
|
# caniuse-lite
|
||||||
|
|
||||||
A smaller version of caniuse-db, with only the essentials!
|
A smaller version of caniuse-db, with only the essentials!
|
||||||
|
|
||||||
## Docs
|
## Docs
|
||||||
Read full docs **[here](https://github.com/browserslist/caniuse-lite#readme)**.
|
Read full docs **[here](https://github.com/browserslist/caniuse-lite#readme)**.
|
||||||
|
|
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue