윤혜원

다음 오늘의 웹툰 크로링 성공!

Showing 504 changed files with 4930 additions and 0 deletions
This diff is collapsed. Click to expand it.
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../he/bin/he" "$@"
ret=$?
else
node "$basedir/../he/bin/he" "$@"
ret=$?
fi
exit $ret
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\..\he\bin\he" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\..\he\bin\he" %*
)
\ No newline at end of file
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../prettyjson/bin/prettyjson" "$@"
ret=$?
else
node "$basedir/../prettyjson/bin/prettyjson" "$@"
ret=$?
fi
exit $ret
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\..\prettyjson\bin\prettyjson" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\..\prettyjson\bin\prettyjson" %*
)
\ No newline at end of file
MIT License
Copyright (c) Microsoft Corporation. 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
# Installation
> `npm install --save @types/cheerio`
# Summary
This package contains type definitions for Cheerio (https://github.com/cheeriojs/cheerio).
# Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/cheerio
Additional Details
* Last updated: Mon, 26 Nov 2018 15:56:46 GMT
* Dependencies: none
* Global values: cheerio
# Credits
These definitions were written by Bret Little <https://github.com/blittle>, VILIC VANE <http://vilic.info>, Wayne Maurer <https://github.com/wmaurer>, Umar Nizamani <https://github.com/umarniz>, LiJinyao <https://github.com/LiJinyao>, Chennakrishna <https://github.com/chennakrishna8>, AzSiAz <https://github.com/AzSiAz>.
// Type definitions for Cheerio v0.22.0
// Project: https://github.com/cheeriojs/cheerio
// Definitions by: Bret Little <https://github.com/blittle>, VILIC VANE <http://vilic.info>, Wayne Maurer <https://github.com/wmaurer>, Umar Nizamani <https://github.com/umarniz>, LiJinyao <https://github.com/LiJinyao>, Chennakrishna <https://github.com/chennakrishna8>, AzSiAz <https://github.com/AzSiAz>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
interface Cheerio {
// Document References
// Cheerio https://github.com/cheeriojs/cheerio
// JQuery http://api.jquery.com
[index: number]: CheerioElement;
length: number;
// Attributes
attr(): {[attr: string]: string};
attr(name: string): string;
attr(name: string, value: any): Cheerio;
data(): any;
data(name: string): any;
data(name: string, value: any): any;
val(): string;
val(value: string): Cheerio;
removeAttr(name: string): Cheerio;
has(selector: string): Cheerio;
has(element: CheerioElement): Cheerio;
hasClass(className: string): boolean;
addClass(classNames: string): Cheerio;
removeClass(): Cheerio;
removeClass(className: string): Cheerio;
removeClass(func: (index: number, className: string) => string): Cheerio;
toggleClass(className: string): Cheerio;
toggleClass(className: string, toggleSwitch: boolean): Cheerio;
toggleClass(toggleSwitch?: boolean): Cheerio;
toggleClass(func: (index: number, className: string, toggleSwitch: boolean) => string, toggleSwitch?: boolean): Cheerio;
is(selector: string): boolean;
is(element: CheerioElement): boolean;
is(element: CheerioElement[]): boolean;
is(selection: Cheerio): boolean;
is(func: (index: number, element: CheerioElement) => boolean): boolean;
// Form
serialize(): string;
serializeArray(): {name: string, value: string}[];
// Traversing
find(selector: string): Cheerio;
find(element: Cheerio): Cheerio;
parent(selector?: string): Cheerio;
parents(selector?: string): Cheerio;
parentsUntil(selector?: string, filter?: string): Cheerio;
parentsUntil(element: CheerioElement, filter?: string): Cheerio;
parentsUntil(element: Cheerio, filter?: string): Cheerio;
prop(name: string): any;
prop(name: string, value: any): Cheerio;
closest(): Cheerio;
closest(selector: string): Cheerio;
next(selector?: string): Cheerio;
nextAll(): Cheerio;
nextAll(selector: string): Cheerio;
nextUntil(selector?: string, filter?: string): Cheerio;
nextUntil(element: CheerioElement, filter?: string): Cheerio;
nextUntil(element: Cheerio, filter?: string): Cheerio;
prev(selector?: string): Cheerio;
prevAll(): Cheerio;
prevAll(selector: string): Cheerio;
prevUntil(selector?: string, filter?: string): Cheerio;
prevUntil(element: CheerioElement, filter?: string): Cheerio;
prevUntil(element: Cheerio, filter?: string): Cheerio;
slice(start: number, end?: number): Cheerio;
siblings(selector?: string): Cheerio;
children(selector?: string): Cheerio;
contents(): Cheerio;
each(func: (index: number, element: CheerioElement) => any): Cheerio;
map(func: (index: number, element: CheerioElement) => any): Cheerio;
filter(selector: string): Cheerio;
filter(selection: Cheerio): Cheerio;
filter(element: CheerioElement): Cheerio;
filter(elements: CheerioElement[]): Cheerio;
filter(func: (index: number, element: CheerioElement) => boolean): Cheerio;
not(selector: string): Cheerio;
not(selection: Cheerio): Cheerio;
not(element: CheerioElement): Cheerio;
not(func: (index: number, element: CheerioElement) => boolean): Cheerio;
first(): Cheerio;
last(): Cheerio;
eq(index: number): Cheerio;
get(): any[];
get(index: number): any;
index(): number;
index(selector: string): number;
index(selection: Cheerio): number;
end(): Cheerio;
add(selectorOrHtml: string): Cheerio;
add(selector: string, context: Document): Cheerio;
add(element: CheerioElement): Cheerio;
add(elements: CheerioElement[]): Cheerio;
add(selection: Cheerio): Cheerio;
addBack():Cheerio;
addBack(filter: string):Cheerio;
// Manipulation
appendTo(target: Cheerio) : Cheerio
prependTo(target: Cheerio) : Cheerio
append(content: string, ...contents: any[]): Cheerio;
append(content: Document, ...contents: any[]): Cheerio;
append(content: Document[], ...contents: any[]): Cheerio;
append(content: Cheerio, ...contents: any[]): Cheerio;
prepend(content: string, ...contents: any[]): Cheerio;
prepend(content: Document, ...contents: any[]): Cheerio;
prepend(content: Document[], ...contents: any[]): Cheerio;
prepend(content: Cheerio, ...contents: any[]): Cheerio;
after(content: string, ...contents: any[]): Cheerio;
after(content: Document, ...contents: any[]): Cheerio;
after(content: Document[], ...contents: any[]): Cheerio;
after(content: Cheerio, ...contents: any[]): Cheerio;
insertAfter(content: string): Cheerio;
insertAfter(content: Document): Cheerio;
insertAfter(content: Cheerio): Cheerio;
before(content: string, ...contents: any[]): Cheerio;
before(content: Document, ...contents: any[]): Cheerio;
before(content: Document[], ...contents: any[]): Cheerio;
before(content: Cheerio, ...contents: any[]): Cheerio;
insertBefore(content: string): Cheerio;
insertBefore(content: Document): Cheerio;
insertBefore(content: Cheerio): Cheerio;
remove(selector?: string): Cheerio;
replaceWith(content: string): Cheerio;
replaceWith(content: CheerioElement): Cheerio;
replaceWith(content: CheerioElement[]): Cheerio;
replaceWith(content: Cheerio): Cheerio;
replaceWith(content: () => Cheerio): Cheerio;
empty(): Cheerio;
html(): string | null;
html(html: string): Cheerio;
text(): string;
text(text: string): Cheerio;
wrap(content: string): Cheerio;
wrap(content: Document): Cheerio;
wrap(content: Cheerio): Cheerio;
css(propertyName: string): string;
css(propertyNames: string[]): string[];
css(propertyName: string, value: string): Cheerio;
css(propertyName: string, value: number): Cheerio;
css(propertyName: string, func: (index: number, value: string) => string): Cheerio;
css(propertyName: string, func: (index: number, value: string) => number): Cheerio;
css(properties: Object): Cheerio;
// Rendering
// Miscellaneous
clone(): Cheerio;
// Not Documented
toArray(): CheerioElement[];
}
interface CheerioOptionsInterface {
// Document References
// Cheerio https://github.com/cheeriojs/cheerio
// HTMLParser2 https://github.com/fb55/htmlparser2/wiki/Parser-options
// DomHandler https://github.com/fb55/DomHandler
xmlMode?: boolean;
decodeEntities?: boolean;
lowerCaseTags?: boolean;
lowerCaseAttributeNames?: boolean;
recognizeCDATA?: boolean;
recognizeSelfClosing?: boolean;
normalizeWhitespace?: boolean;
ignoreWhitespace?: boolean;
}
interface CheerioSelector {
(selector: string): Cheerio;
(selector: string, context: string): Cheerio;
(selector: string, context: CheerioElement): Cheerio;
(selector: string, context: CheerioElement[]): Cheerio;
(selector: string, context: Cheerio): Cheerio;
(selector: string, context: string, root: string): Cheerio;
(selector: string, context: CheerioElement, root: string): Cheerio;
(selector: string, context: CheerioElement[], root: string): Cheerio;
(selector: string, context: Cheerio, root: string): Cheerio;
(selector: any): Cheerio;
}
interface CheerioStatic extends CheerioSelector {
// Document References
// Cheerio https://github.com/cheeriojs/cheerio
// JQuery http://api.jquery.com
xml(): string;
root(): Cheerio;
contains(container: CheerioElement, contained: CheerioElement): boolean;
parseHTML(data: string, context?: Document, keepScripts?: boolean): Document[];
html(options?: CheerioOptionsInterface): string;
html(selector: string, options?: CheerioOptionsInterface): string;
html(element: Cheerio, options?: CheerioOptionsInterface): string;
html(element: CheerioElement, options?: CheerioOptionsInterface): string;
}
interface CheerioElement {
// Document References
// Node Console
tagName: string;
type: string;
name: string;
attribs: {[attr: string]: string};
children: CheerioElement[];
childNodes: CheerioElement[];
lastChild: CheerioElement;
firstChild: CheerioElement;
next: CheerioElement;
nextSibling: CheerioElement;
prev: CheerioElement;
previousSibling: CheerioElement;
parent: CheerioElement;
parentNode: CheerioElement;
nodeValue: string;
data?: string;
}
interface CheerioAPI extends CheerioSelector, CheerioStatic {
load(html: string, options?: CheerioOptionsInterface): CheerioStatic;
load(element: CheerioElement, options?: CheerioOptionsInterface): CheerioStatic;
}
interface Document { }
declare var cheerio:CheerioAPI;
declare module "cheerio" {
export = cheerio;
}
{
"_from": "@types/cheerio@^0.22.7",
"_id": "@types/cheerio@0.22.10",
"_inBundle": false,
"_integrity": "sha512-fOM/Jhv51iyugY7KOBZz2ThfT1gwvsGCfWxpLpZDgkGjpEO4Le9cld07OdskikLjDUQJ43dzDaVRSFwQlpdqVg==",
"_location": "/@types/cheerio",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "@types/cheerio@^0.22.7",
"name": "@types/cheerio",
"escapedName": "@types%2fcheerio",
"scope": "@types",
"rawSpec": "^0.22.7",
"saveSpec": null,
"fetchSpec": "^0.22.7"
},
"_requiredBy": [
"/cheerio-httpcli"
],
"_resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.10.tgz",
"_shasum": "780d552467824be4a241b29510a7873a7432c4a6",
"_spec": "@types/cheerio@^0.22.7",
"_where": "D:\\OSS project\\YTMT\\node_modules\\cheerio-httpcli",
"bugs": {
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Bret Little",
"url": "https://github.com/blittle"
},
{
"name": "VILIC VANE",
"url": "http://vilic.info"
},
{
"name": "Wayne Maurer",
"url": "https://github.com/wmaurer"
},
{
"name": "Umar Nizamani",
"url": "https://github.com/umarniz"
},
{
"name": "LiJinyao",
"url": "https://github.com/LiJinyao"
},
{
"name": "Chennakrishna",
"url": "https://github.com/chennakrishna8"
},
{
"name": "AzSiAz",
"url": "https://github.com/AzSiAz"
}
],
"dependencies": {},
"deprecated": false,
"description": "TypeScript definitions for Cheerio",
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped#readme",
"license": "MIT",
"main": "",
"name": "@types/cheerio",
"repository": {
"type": "git",
"url": "git+https://github.com/DefinitelyTyped/DefinitelyTyped.git"
},
"scripts": {},
"typeScriptVersion": "2.0",
"types": "index",
"typesPublisherContentHash": "2e27eac8c695bdef169dcf5482e7a17f84ae485381d5de916cdddaedbd3787be",
"version": "0.22.10"
}
'use strict';
var callsites = require('callsites');
module.exports = function () {
return callsites()[2].getFileName();
};
{
"_from": "caller-path@^0.1.0",
"_id": "caller-path@0.1.0",
"_inBundle": false,
"_integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
"_location": "/caller-path",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "caller-path@^0.1.0",
"name": "caller-path",
"escapedName": "caller-path",
"rawSpec": "^0.1.0",
"saveSpec": null,
"fetchSpec": "^0.1.0"
},
"_requiredBy": [
"/require-uncached"
],
"_resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
"_shasum": "94085ef63581ecd3daa92444a8fe94e82577751f",
"_spec": "caller-path@^0.1.0",
"_where": "D:\\OSS project\\YTMT\\node_modules\\require-uncached",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/caller-path/issues"
},
"bundleDependencies": false,
"dependencies": {
"callsites": "^0.2.0"
},
"deprecated": false,
"description": "Get the path of the caller module",
"devDependencies": {
"mocha": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/caller-path#readme",
"keywords": [
"caller",
"calling",
"module",
"path",
"parent",
"callsites",
"callsite",
"stacktrace",
"stack",
"trace",
"function",
"file"
],
"license": "MIT",
"name": "caller-path",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/caller-path.git"
},
"scripts": {
"test": "mocha"
},
"version": "0.1.0"
}
# caller-path [![Build Status](https://travis-ci.org/sindresorhus/caller-path.svg?branch=master)](https://travis-ci.org/sindresorhus/caller-path)
> Get the path of the caller module
You can't use [`module.parent`](http://nodejs.org/api/modules.html#modules_module_parent) as modules are cached and it will return the first caller module, not necessarily the current one.
## Install
```
$ npm install --save caller-path
```
## Usage
```js
// foo.js
var callerPath = require('caller-path');
module.exports = function () {
console.log(callerPath());
//=> /Users/sindresorhus/dev/unicorn/bar.js
}
```
```js
// bar.js
var foo = require('./foo');
foo();
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
'use strict';
module.exports = function () {
var _ = Error.prepareStackTrace;
Error.prepareStackTrace = function (_, stack) { return stack };
var stack = new Error().stack.slice(1);
Error.prepareStackTrace = _;
return stack;
};
{
"_from": "callsites@^0.2.0",
"_id": "callsites@0.2.0",
"_inBundle": false,
"_integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
"_location": "/callsites",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "callsites@^0.2.0",
"name": "callsites",
"escapedName": "callsites",
"rawSpec": "^0.2.0",
"saveSpec": null,
"fetchSpec": "^0.2.0"
},
"_requiredBy": [
"/caller-path"
],
"_resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
"_shasum": "afab96262910a7f33c19a5775825c69f34e350ca",
"_spec": "callsites@^0.2.0",
"_where": "D:\\OSS project\\YTMT\\node_modules\\caller-path",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/callsites/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Get callsites from the V8 stack trace API",
"devDependencies": {
"mocha": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/callsites#readme",
"keywords": [
"callsites",
"callsite",
"v8",
"stacktrace",
"stack",
"trace",
"function",
"file",
"line",
"debug"
],
"license": "MIT",
"name": "callsites",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/callsites.git"
},
"scripts": {
"test": "mocha"
},
"version": "0.2.0"
}
# callsites [![Build Status](https://travis-ci.org/sindresorhus/callsites.svg?branch=master)](https://travis-ci.org/sindresorhus/callsites)
> Get callsites from the [V8 stack trace API](https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi)
## Install
```sh
$ npm install --save callsites
```
## Usage
```js
var callsites = require('callsites');
function unicorn() {
console.log(callsites()[0].getFileName());
//=> /Users/sindresorhus/dev/callsites/test.js
}
unicorn();
```
## API
Returns an array of callsite objects with the following methods:
- `getThis`: returns the value of this
- `getTypeName`: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object's [[Class]] internal property.
- `getFunction`: returns the current function
- `getFunctionName`: returns the name of the current function, typically its name property. If a name property is not available an attempt will be made to try to infer a name from the function's context.
- `getMethodName`: returns the name of the property of this or one of its prototypes that holds the current function
- `getFileName`: if this function was defined in a script returns the name of the script
- `getLineNumber`: if this function was defined in a script returns the current line number
- `getColumnNumber`: if this function was defined in a script returns the current column number
- `getEvalOrigin`: if this function was created using a call to eval returns a CallSite object representing the location where eval was called
- `isToplevel`: is this a toplevel invocation, that is, is this the global object?
- `isEval`: does this call take place in code defined by a call to eval?
- `isNative`: is this call in native V8 code?
- `isConstructor`: is this a constructor call?
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
{
"extends": "eslint:recommended",
"env": {
"node": true,
"es6": false,
"browser": false
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"modules": true
}
},
"plugins": [
],
"rules": {
"curly": [2, "multi-line"],
"camelcase": [1, {
"properties": "never"
}],
"require-jsdoc": 0,
"valid-jsdoc": 0,
"valid-typeof": 2,
"no-array-constructor": 2,
"no-bitwise": 2,
"no-buffer-constructor": 0,
"no-caller": 1,
"no-catch-shadow": 2,
"no-class-assign": 2,
"no-compare-neg-zero": 2,
"no-cond-assign": 2,
"no-confusing-arrow": 2,
"no-console": [1, {
"allow": ["info", "warn", "error"]
}],
"no-const-assign": 2,
"no-constant-condition": 2,
"no-control-regex": 2,
"no-debugger": 2,
"no-delete-var": 2,
"no-dupe-args": 2,
"no-dupe-class-members": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-duplicate-imports": 2,
"no-else-return": [2, {
"allowElseIf": false
}],
"no-empty": [1, {
"allowEmptyCatch": true
}],
"no-empty-character-class": 2,
"no-eq-null": 2,
"no-eval": 2,
"no-ex-assign": 2,
"no-extend-native": 2,
"no-extra-bind": 1,
"no-extra-boolean-cast": 2,
"no-extra-parens": [0, "all", {
"returnAssign": false,
"nestedBinaryExpressions": false
}],
"no-extra-semi": 2,
"no-fallthrough": 2,
"no-floating-decimal": 2,
"no-func-assign": 2,
"no-global-assign": 2,
"no-implicit-coercion": 2,
"no-implied-eval": 2,
"no-inner-declarations": 1,
"no-invalid-regexp": 2,
"no-invalid-this": 2,
"no-irregular-whitespace": 2,
"no-labels": 2,
"no-lonely-if": 1,
"no-loop-func": 0,
"no-multi-assign": 1,
"no-multi-str": 1,
"no-multiple-empty-lines": [1, {"max": 2}],
"no-nested-ternary": 2,
"no-new": 1,
"no-new-func": 2,
"no-new-require": 2,
"no-new-wrappers": 1,
"no-obj-calls": 2,
"no-octal": 2,
"no-octal-escape": 2,
"no-param-reassign": 0,
"no-path-concat": 2,
"no-process-env": 0,
"no-proto": 2,
"no-redeclare": 2,
"no-regex-spaces": 1,
"no-return-assign": 2,
"no-self-compare": 1,
"no-self-assign": [2, {
"props": true
}],
"no-sequences": 2,
"no-shadow-restricted-names": 2,
"no-sparse-arrays": 2,
"no-this-before-super": 2,
"no-tabs": 2,
"no-throw-literal": 2,
"prefer-promise-reject-errors": 2,
"no-template-curly-in-string": 1,
"no-undef": 2,
"no-undef-init": 2,
"no-undefined": 2,
"no-unexpected-multiline": 2,
"no-unneeded-ternary": 2,
"no-unreachable": 1,
"no-unsafe-negation": 2,
"no-unused-expressions": 1,
"no-unused-vars": [2, {
"vars": "all",
"args": "none",
"caughtErrors": "none",
"ignoreRestSiblings": true
}],
"no-use-before-define": 2,
"no-useless-call": 2,
"no-useless-concat": 1,
"no-useless-escape": 0,
"no-void": 2,
"no-with": 2,
"no-return-await": 1,
"no-await-in-loop": 2,
"nonblock-statement-body-position": [2, "beside"],
"use-isnan": 2,
"accessor-pairs": 2,
"block-scoped-var": 2,
"func-name-matching": [2, {
"includeCommonJSModuleExports": true
}],
"func-call-spacing": [2, "never"],
"consistent-return": [2, {
"treatUndefinedAsUnspecified": true
}],
"linebreak-style": [0, "unix"],
"new-cap": 2,
"new-parens": 2,
"newline-after-var": [0, "always"],
"generator-star-spacing": [2, {
"before": true,
"after": false
}],
"complexity": [2, 20],
"lines-around-directive": 1,
"dot-notation": 1,
"guard-for-in": 1,
"for-direction": 2,
"require-await": 2,
"require-yield": 2,
"arrow-parens": [2, "always", {
"requireForBlockBody": true
}],
"arrow-spacing": 2,
"callback-return": [1, [
"callback", "cb", "next", "done"
]],
"getter-return": 2,
"operator-linebreak": [1, "before", {
"overrides": {
"&&": "after",
"||": "after"
}
}],
"wrap-iife": [2, "inside", {
"functionPrototypeMethods": true
}],
"function-paren-newline": 0,
"yoda": 2,
"prefer-arrow-callback": 0,
"prefer-template": 0,
"prefer-const": 0,
"prefer-destructuring": 0,
"prefer-spread": 0,
"prefer-numeric-literals": 1,
"rest-spread-spacing": 0,
"constructor-super": 2,
"template-tag-spacing": 2,
"default-case": 1,
"sort-keys": 0,
"vars-on-top": 0,
"eqeqeq": [2, "always", {
"null": "always"
}],
"radix": 2,
"consistent-this": [2, "_this"],
"eol-last": 2,
"func-style": 0,
"jsx-quotes": [2, "prefer-double"],
"semi": [2, "always"],
"semi-spacing": [2, {
"before": false,
"after": true
}],
"one-var": [2, "never"],
"quote-props": [2, "as-needed"],
"init-declarations": [2, "always"],
"computed-property-spacing": [2, "never"],
"no-underscore-dangle": [2, {
"allowAfterThis": true,
"allowAfterSuper": true,
"allow": [
"_this",
"_root", "_documentInfo", "_html", "_text",
"_originalRoot", "_traceRoute", "_$"
]
}],
"comma-dangle": [2, "never"],
"comma-style": [2, "last"],
"brace-style": [1, "1tbs", {
"allowSingleLine": true
}],
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
"no-mixed-operators": [2, {
"groups": [
["+", "-", "*", "/", "%", "**"],
["&", "|", "^", "~", "<<", ">>", ">>>"],
["==", "!=", "===", "!==", ">", ">=", "<", "<="],
["&&", "||"],
["in", "instanceof"]
],
"allowSamePrecedence": true
}],
"indent": [2, 2, {
"SwitchCase": 1,
"ImportDeclaration": "first",
"MemberExpression": 0,
"CallExpression": {
"arguments": "first"
},
"FunctionDeclaration": {
"parameters": "first",
"body": 1
}
}
],
"keyword-spacing": [2, {
"before": true,
"after": true,
"overrides": {}
}],
"lines-between-class-members": [2, "always"],
"lines-around-comment": [2, {
"beforeBlockComment": true,
"afterBlockComment": false,
"beforeLineComment": false,
"afterLineComment": false,
"allowBlockStart": true,
"allowBlockEnd": true,
"allowObjectStart": true,
"allowObjectEnd": true,
"allowArrayStart": true,
"allowArrayEnd": true
}],
"space-before-blocks": [2, "always"],
"space-before-function-paren": [2, {
"named": "never",
"asyncArrow": "always"
}],
"space-in-parens": [2, "never"],
"space-infix-ops": 2,
"space-unary-ops": [2, {
"words": true,
"nonwords": false,
"overrides": {
"!": true,
"!!": true
}
}],
"semi-style": [2, "last"],
"switch-colon-spacing": 2,
"multiline-ternary": [2, "always-multiline"],
"object-curly-spacing": [2, "always", {
"objectsInObjects": false,
"arraysInObjects": false
}],
"object-curly-newline": [0, {
"ObjectExpression": "always",
"ObjectPattern": {"multiline": true}
}],
"object-property-newline": 0,
"no-trailing-spaces": [2, {
"skipBlankLines": false
}],
"object-shorthand": [1, "consistent"],
"key-spacing": [2, {
"beforeColon": false,
"afterColon": true
}],
"comma-spacing": [2, {
"before": false,
"after": true
}],
"no-multi-spaces": [2, {
"ignoreEOLComments": true,
"exceptions": {
"ImportDeclaration": true,
"VariableDeclarator": true,
"Property": true
}
}],
"array-bracket-spacing": [2, "always", {
"singleValue": true,
"objectsInArrays": false,
"arraysInArrays": true
}],
"array-bracket-newline": [2, "consistent"],
"quotes": [1,
"single", "avoid-escape"
],
"max-statements-per-line": [1, { "max": 1 }],
"max-len": [1, {
"code": 100,
"tabWidth": 2,
"ignoreComments": true,
"ignoreTrailingComments": true,
"ignoreUrls": true,
"ignoreStrings": true,
"ignoreTemplateLiterals": true,
"ignoreRegExpLiterals": true
}],
"max-lines": [1, 2000],
"max-params": [1, 5],
"max-depth": [1, 4],
"max-nested-callbacks": [1, 5],
"max-statements": [1, 30]
}
}
{
"excludeFiles": [],
"fileExtensions": [
".js"
],
"requireCurlyBraces": [
"if",
"else",
"for",
"while",
"do",
"try",
"catch",
"case",
"default"
],
"requireSpaceAfterKeywords": [
"do",
"for",
"if",
"else",
"switch",
"case",
"try",
"catch",
"void",
"while",
"with",
"return",
"typeof",
"function"
],
"requireSpaceBeforeBlockStatements": true,
"requireParenthesesAroundIIFE": true,
"requireSpacesInConditionalExpression": {
"afterTest": true,
"beforeConsequent": true,
"afterConsequent": true,
"beforeAlternate": true
},
"requireSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": true,
"beforeOpeningCurlyBrace": true
},
"requireSpacesInNamedFunctionExpression": {
"beforeOpeningCurlyBrace": true
},
"disallowMultipleVarDecl": true,
"requireBlocksOnNewline": true,
"disallowEmptyBlocks": true,
"disallowSpacesInsideParentheses": true,
"requireSpacesInsideObjectBrackets": "all",
"requireSpacesInsideArrayBrackets": {
"allExcept": [ "[", "]", "{", "}" ]
},
"disallowQuotedKeysInObjects": "allButReserved",
"disallowSpaceAfterObjectKeys": false,
"requireSpaceBeforeObjectValues": true,
"requireCommaBeforeLineBreak": true,
"disallowSpaceAfterPrefixUnaryOperators": [
"++",
"--"
],
"requireSpaceAfterPrefixUnaryOperators": [
"+",
"~",
"!"
],
"disallowSpaceBeforePostfixUnaryOperators": [
"++",
"--"
],
"requireSpaceBeforeBinaryOperators": [
"=",
"+",
"-",
"/",
"*",
"==",
"===",
"!=",
"!=="
],
"requireSpaceAfterBinaryOperators": [
"=",
",",
"+",
"-",
"/",
"*",
"==",
"===",
"!=",
"!=="
],
"disallowImplicitTypeConversion": [
"string"
],
"requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties",
"disallowKeywords": [
"with"
],
"disallowMultipleLineStrings": true,
"disallowMultipleLineBreaks": false,
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"disallowTrailingComma": true,
"requireLineFeedAtFileEnd": true,
"requireCapitalizedConstructors": true,
"requireDotNotation": true,
"maximumLineLength": 120,
"disallowYodaConditions": true,
"requireSpaceAfterLineComment": true,
"requireAnonymousFunctions": {
"allExcept": [
"declarations"
]
},
"disallowNewlineBeforeBlockStatements": true,
"validateQuoteMarks": {
"mark": "'",
"escape": true
},
"validateIndentation": 2,
"safeContextKeyword": [
"_this"
]
}
This diff is collapsed. Click to expand it.
Copyright (c) 2013-2015 ktty1220
The MIT License
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 diff is collapsed. Click to expand it.
// このtsファイルをtscでコンパイルしてエラーにならなければOK的なゆるいチェック
import * as cli from '../../cheerio-httpcli';
import * as fs from 'fs';
cli.set('debug', true);
cli.set('browser', 'edge');
cli.set('timeout', 3000);
cli.set('agentOptions', {
secureProtocol: 'TLSv1_2_method'
}, true);
console.info(cli.headers);
cli.download
.on('ready', (stream) => {
stream.pipe(fs.createWriteStream('/path/to/image.png'));
console.info(`${stream.url.href}をダウンロードしました`);
})
.on('error', (err) => {
console.error(`${err.url}をダウンロードできませんでした: ${err.message}`);
})
.on('end', () => {
console.info('ダウンロードが完了しました');
})
.parallel = 4;
const url = 'http://foo.bar.baz.co.ne.jp/';
cli.fetch(url, (_err, $, _res, _body) => {
const docInfo = $.documentInfo();
console.info(docInfo.url);
console.info(docInfo.encoding);
console.info($.xml());
$('a').css('color', 'black').tick().url({
absolute: false
});
$('img.thumbnail').download();
$('button').eq(3).click()
.then((result) => {
const key = 'hoge';
console.info(
result.response.cookies[key],
result.$('#content').entityHtml(),
result.$('form').field()
);
})
.catch(console.error)
.finally(() => console.info('done'));
});
cli.fetch(url, 'euc-jp')
.then((result2) => {
console.info(result2.response.headers);
});
{
const { error, $, response, body } = cli.fetchSync(url, { q: 'hoge' });
console.info(error, $, response, body);
}
// #18
{
const wrapper = async (u: string): Promise<cli.CheerioStaticEx> => {
const result = await cli.fetch(u);
const type: string = result.response.headers['content-type'] as string;
/* rejects */
if (result.error !== undefined && result.error !== null) {
throw new Error('happend-error');
}
if (! /text\/html/.test(type)) {
throw new Error('not-html');
}
/* resolve result */
return result.$;
};
wrapper(url).then((result) => {
console.dir(result);
});
}
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"dom",
"es2015"
],
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"alwaysStrict": true,
"suppressImplicitAnyIndexErrors": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"suppressImplicitAnyIndexErrors": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"pretty": true,
"importHelpers": false,
"noEmitOnError": true,
"noEmit": true
}
}
#!/usr/bin/env node
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
/**
* 5ちゃんねる検索サンプル
*
* 以下のword変数の内容で検索します
*/
var word = 'ぬるぽ';
var client = require('../index');
client.fetch('http://www.5ch.net/')
.then(function (result) {
return result.$('form').eq(0).submit({
q: word
});
})
.then(function (result) {
var $ = result.$;
var results = [];
$('.list_line').each(function () {
var $a = $(this).find('a').eq(0);
results.push({
title: $a.text().trim(),
url: $a.attr('href'),
info: $(this).find('.list_line_info_container').text().trim()
});
});
console.info(results);
})
.catch(function (err) {
console.error('エラーが発生しました', err);
})
.finally(function () {
console.info('終了します');
});
#!/usr/bin/env node
/*jshint -W100*/
'use strict';
/**
* excite翻訳サンプル
*
* 以下のstr変数の内容を翻訳します(言語自動判定)
*/
var str = 'お前はもう死んでいる';
var client = require('../index');
console.info('デバッグオプションを有効にします');
client.set('debug', true);
console.info('excite翻訳ページにアクセスします');
client.fetch('http://www.excite.co.jp/world/')
.then(function (result) {
return result.$('#formTrans').submit({
auto_detect: 'on',
before: str
});
})
.then(function (result) {
console.info('「' + str + '」=>「' + result.$('#after').val() + '」');
})
.catch(function (err) {
console.error('エラーが発生しました', err);
})
.finally(function () {
console.info('終了します');
});
#!/usr/bin/env node
/*jshint -W100*/
'use strict';
/**
*****************************************************************
* !!! このサンプルは2015-08-30現在のfacebookでは動作しません !!!
*****************************************************************
* facebookログインサンプル
*
* 以下のusernameとpasswordを書き換えてから実行してください
*/
var username = 'hogehoge';
var password = 'fugafuga';
var client = require('../index');
console.info('facebookTOPページにアクセスします');
client.fetch('http://www.facebook.com/')
.then(function (result) {
console.info('ログインフォームを送信します');
return result.$('#login_form').submit({
email: username,
pass: password
});
})
.then(function (result) {
console.info('クッキー', result.response.cookies);
console.info('ユーザー名を取得します');
console.info(result.$('._2dpb').text());
})
.catch(function (err) {
console.error('エラーが発生しました', err);
})
.finally(function () {
console.info('終了します');
});
#!/usr/bin/env node
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
/**
* Google検索サンプル
*
* 以下のword変数の内容で検索します
*/
var word = 'ドラえもん';
var client = require('../index');
// [重要] google検索の場合はfollowMetaRefreshをfalseにする(README.md参照)
client.set('followMetaRefresh', false);
client.fetch('http://www.google.co.jp/search', { q: word }, function (err, $, res, body) {
if (err) {
console.error(err);
return;
}
var results = [];
// 検索結果が個別に格納されている要素をループ
$('#rso .g').each(function () {
// 各検索結果のタイトル部分とURL、概要を取得
var $h3 = $(this).find('h3');
var url = $h3.find('a').attr('href');
if (url) {
results.push({
title: $h3.text(),
url: url,
description: $(this).find('.st').text()
});
}
});
console.info(results);
});
#!/usr/bin/env node
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
/**
* はてなキーワード検索サンプル
*
* 以下のword変数の内容で検索します
*/
var word = 'ネッシー';
var client = require('../index');
console.info('はてなキーワードTOPページにアクセスします');
client.fetch('http://d.hatena.ne.jp/keyword/')
.then(function (result) {
console.info('最近更新されたキーワード一覧');
var $ = result.$;
$('#updatekeywords ul li .name').each(function () {
// NEW!は邪魔なので削除
$('.new', $(this)).remove();
console.info('* ' + $(this).text());
});
console.info('「' + word + '」を検索します');
return $('#index-search').submit({
word: word
});
})
.then(function (result) {
console.info(result.$('.keyword-body').text().trim().replace(/[\t\u3000]/g, ''));
})
.catch(function (err) {
console.error('エラーが発生しました', err);
})
.finally(function () {
console.info('終了します');
});
#!/usr/bin/env node
/*jshint -W100*/
'use strict';
/**
* ニコニコ動画ログインサンプル
*
* 以下のusernameとpasswordを書き換えてから実行してください
*/
var username = 'hogehoge';
var password = 'fugafuga';
var client = require('../index');
console.info('ニコニコTOPページにアクセスします');
client.fetch('http://nicovideo.jp/')
.then(function (result) {
console.info('ログインリンクをクリックします');
return result.$('#sideNav .loginBtn').click();
})
.then(function (result) {
console.info('ログインフォームを送信します');
return result.$('#login_form').submit({
mail_tel: username,
password: password
});
})
.then(function (result) {
console.info('ログイン可否をチェックします');
if (! result.response.headers['x-niconico-id']) {
throw new Error('login failed');
}
console.info('クッキー', result.response.cookies);
console.info('マイページに移動します');
return client.fetch('http://www.nicovideo.jp/my/top');
})
.then(function (result) {
console.info('マイページに表示されるアカウント名を取得します');
console.info(result.$('#siteHeaderUserNickNameContainer').text());
})
.catch(function (err) {
console.error('エラーが発生しました', err.message);
})
.finally(function () {
console.info('終了します');
});
#!/usr/bin/env node
/*jshint -W100*/
'use strict';
/**
* Promise形式での利用サンプル
*/
var client = require('../index');
// なんとなくgooglebotのUser-Agentをセット
client.set('browser', 'googlebot');
// Yahooのトップページを取得
client.fetch('http://www.yahoo.co.jp/')
.then(function (result) {
console.info('<then>', result.$('title').text());
// Googleのトップページを取得
return client.fetch('http://www.google.co.jp/');
}).then(function (result) {
console.info('<then>', result.$('title').text());
// 例外を発生させる
throw new Error('!!! error !!!');
}).catch(function (err) {
// 例外発生時の処理
console.error('<catch>', err.message);
}).finally(function () {
// 最終的に必ず実行される処理
console.info('<finally>');
});
#!/usr/bin/env node
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
/**
* 同期リクエストによるGoogle検索サンプル
*
* 以下のword変数の内容で検索します
*/
var word = 'チュパカブラ';
var client = require('../index');
// [重要] google検索の場合はfollowMetaRefreshをfalseにする(README.md参照)
client.set('followMetaRefresh', false);
console.info('--- Bingで検索 ---');
var result1 = client.fetchSync('http://www.bing.com/search', { q: word });
if (result1.error) {
console.error(result1.error);
} else {
var results1 = [];
// 検索結果が個別に格納されている要素をループ
var $ = result1.$;
$('.b_algo').each(function () {
// 各検索結果のタイトル部分とURL、概要を取得
var $h2 = $(this).find('h2');
var url = $h2.find('a').attr('href');
if (url) {
results1.push({
title: $h2.text(),
url: url,
description: $(this).find('.b_caption p').text()
});
}
});
console.info(results1);
}
console.info('\n--- Googleで検索 ---');
var result2 = client.fetchSync('http://www.google.co.jp/search', { q: word });
if (result2.error) {
console.error(result2.error);
} else {
var results2 = [];
// 検索結果が個別に格納されている要素をループ
var _$ = result2.$;
_$('#rso .g').each(function () {
// 各検索結果のタイトル部分とURL、概要を取得
var $h3 = _$(this).find('h3');
var url = $h3.find('a').attr('href');
if (url) {
results2.push({
title: $h3.text(),
url: url,
description: _$(this).find('.st').text()
});
}
});
console.info(results2);
}
#!/usr/bin/env node
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
var C = require('colors/safe');
/**
* tiqav画像取得サンプル
*/
var fs = require('fs');
var path = require('path');
var client = require('../index');
// 画像保存フォルダ作成
var imgdir = path.join(__dirname, 'img');
if (! fs.existsSync(imgdir)) {
fs.mkdirSync(imgdir);
}
// ダウンロードマネージャー設定
client.download
.on('ready', function (stream) {
// ダウンロード完了時の処理(各ファイルごとに呼ばれる)
var file = stream.url.pathname.match(/([^\/]+)$/)[1];
var savepath = path.join(imgdir, file);
stream.pipe(fs.createWriteStream(savepath));
console.info(C.green('SUCCESS'), C.blue(stream.url.href) + ' => ' + C.yellow(savepath));
console.info(C.magenta('STATE'), this.state);
})
.on('error', function (err) {
// ダウンロード失敗時の処理(各ファイルごとに呼ばれる)
console.error(C.red('ERROR'), err);
console.info(C.magenta('STATE'), this.state);
})
.on('end', function (err) {
// ダウンロードキューが空になった時の処理
console.info(C.green.bold('COMPLETE'), this.state);
});
// fetch start
console.info(C.cyan('INFO'), 'tiqavにアクセスします');
client.fetch('http://tiqav.com/')
.then(function (result) {
// 画像を根こそぎダウンロード
var $imgs = result.$('.box img');
console.info(C.cyan('INFO'), $imgs.length + '個の画像があります');
$imgs.download();
})
.catch(function (err) {
console.error(C.red('ERROR'), err);
})
.finally(function () {
console.info(C.cyan('INFO'), 'スクレイピングが終了しました');
});
#!/usr/bin/env node
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
/**
*****************************************************************
* !!! 2017-02-06現在サイトが消えているので動作しません !!!
*****************************************************************
* 2chスレタイ検索サンプル
*
* 以下のword変数の内容で検索します
*/
var word = '話題';
var client = require('../index');
client.fetch('http://ttsearch.net/')
.then(function (result) {
return result.$('form').eq(0).submit({
k: word
});
})
.then(function (result) {
var $ = result.$;
var results = [];
$('a.title').each(function () {
results.push({
title: $(this).text().trim(),
url: $(this).attr('href')
});
});
console.info(results);
})
.catch(function (err) {
console.error('エラーが発生しました', err);
})
.finally(function () {
console.info('終了します');
});
#!/usr/bin/env node
/*jshint -W100*/
'use strict';
/**
* ブラウザ設定確認
*/
var client = require('../index');
client.set('debug', true);
client.set('browser', 'firefox');
client.fetch('http://www.useragentstring.com/')
.then(function (result) {
console.info(result.$('#dieTabelle th').text());
})
.catch(function (err) {
console.error(err);
});
import * as http from 'http';
import * as url from 'url';
import * as stream from 'stream';
//tslint:disable:next-line: no-import-side-effect
import 'cheerio';
// cheerio-httpcli本体
declare namespace CheerioHttpcli {
interface FetchResponse extends http.IncomingMessage {
cookies: {[ name: string ]: string};
}
// CheerioStatic拡張
interface CheerioStaticEx extends CheerioStatic {
documentInfo(): { url: string, encoding: string | null, isXml: boolean };
entityHtml(options?: CheerioOptionsInterface): string;
entityHtml(selector: string, options?: CheerioOptionsInterface): string;
entityHtml(element: Cheerio, options?: CheerioOptionsInterface): string;
entityHtml(element: CheerioElement, options?: CheerioOptionsInterface): string;
}
interface FetchResult {
error: Error;
$: CheerioStaticEx;
response: FetchResponse;
body: string;
}
type FetchCallback = (error: Error, $: CheerioStaticEx, response: FetchResponse, body: string) => void;
// やっつけPromise
interface Promise {
then(callback: (result: FetchResult) => void): Promise;
catch(callbck: (error: Error) => void): Promise;
finally(callback: () => void): Promise;
}
namespace Download {
interface Stream extends stream.Stream {
url: url.Url;
type: string;
length: number;
toBuffer(callback: (error: Error, buffer: Buffer) => void): void;
end(): void;
}
interface ErrorEx extends Error {
url: string;
}
export interface Manager {
parallel: number;
state: { queue: number, complete: number, error: number };
clearCache(): void;
on(event: 'ready', handler: ((stream: Stream) => void)): Manager;
on(event: 'error', handler: ((error: ErrorEx) => void)): Manager;
on(event: 'end', handler: (() => void)): Manager;
}
}
type FreeObject = {[ name: string ]: string};
const headers: FreeObject;
const agentOptions: FreeObject;
const timeout: number;
const maxDataSize: number;
const gzip: boolean;
const referer: boolean;
const followMetaRefresh: boolean;
const forceHtml: boolean;
const debug: boolean;
const browser: string;
const iconv: string;
const version: string;
const download: Download.Manager;
function reset(): void;
function set(name: 'browser' | 'iconv', value: string): void;
function set(name: 'timeout' | 'maxDataSize', value: number): void;
function set(name: 'gzip' | 'referer' | 'followMetaRefresh' | 'forceHtml' | 'debug', value: boolean): void;
function set(name: 'headers' | 'agentOptions', value: FreeObject, nomerge?: boolean): void;
function setIconvEngine(icmod: 'iconv' | 'iconv-jp' | 'iconv-lite'): void;
function setBrowser(type:
'ie' | 'edge' | 'chrome' | 'firefox' |
'opera' | 'vivaldi' | 'safari' |
'ipad' | 'iphone' | 'ipod' | 'android' |
'googlebot'): boolean;
function fetch(url: string, param: {[ name: string ]: any}, encode: string, callback: FetchCallback): void;
function fetch(url: string, param: {[ name: string ]: any}, callback: FetchCallback): void;
function fetch(url: string, encode: string, callback: FetchCallback): void;
function fetch(url: string, callback: FetchCallback): void;
function fetch(url: string, param: {[ name: string ]: any}, encode: string): Promise;
function fetch(url: string, param: {[ name: string ]: any}): Promise;
function fetch(url: string, encode: string): Promise;
function fetch(url: string): Promise;
function fetchSync(url: string, param: {[ name: string ]: any}, encode: string): FetchResult;
function fetchSync(url: string, param: {[ name: string ]: any}): FetchResult;
function fetchSync(url: string, encode: string): FetchResult;
function fetchSync(url: string): FetchResult;
}
// cheerio拡張メソッド(オリジナルのinterfaceにマージ)
declare global {
interface Cheerio {
click(callback: CheerioHttpcli.FetchCallback): void;
click(): CheerioHttpcli.Promise;
clickSync(): CheerioHttpcli.FetchResult;
download(srcAttr?: string | string[]): void;
field(): {[ name: string ]: string | number};
field(name: string): string | number;
field(name: string, value: string | (() => string), onNotFound?: 'append' | 'throw'): Cheerio;
field(name: {[ name: string ]: string | number}, onNotFound?: 'append' | 'throw'): Cheerio;
entityHtml(): string;
entityHtml(html: string): Cheerio;
submit(param: {[ name: string ]: string | number}, callback: CheerioHttpcli.FetchCallback): void;
submit(callback: CheerioHttpcli.FetchCallback): void;
submit(param?: {[ name: string ]: string | number}): CheerioHttpcli.Promise;
submitSync(param?: {[ name: string ]: string | number}): CheerioHttpcli.FetchResult;
tick(): Cheerio;
untick(): Cheerio;
url(optFilter: { absolute?: boolean, relative?: boolean, invalid?: boolean }, srcAttrs?: string | string[]): string | string[];
url(srcAttrs?: string | string[]): string | string[];
}
}
export = CheerioHttpcli;
module.exports = require('./lib/core');
{
"ie": "Mozilla/5.0 (Windows NT 10.0; Trident/7.0; rv:11.0) like Gecko",
"edge": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063",
"chrome": "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
"firefox": "Mozilla/5.0 (Windows NT 10.0; rv:54.0) Gecko/20100101 Firefox/59.0",
"opera": "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; ja) Presto/2.10.289 Version/12.00",
"vivaldi": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.143 Safari/537.36 Vivaldi/1.95.1077.45",
"safari": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8",
"ipad": "Mozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1",
"iphone": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1",
"ipod": "Mozilla/5.0 (iPod; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3",
"android": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Safari/537.36",
"ps4": "Mozilla/5.0 (PlayStation 4 5.00) AppleWebKit/601.2 (KHTML, like Gecko)",
"3ds": "Mozilla/5.0 (Nintendo 3DS; U; ; ja) Version/1.7567.JP",
"googlebot": "Googlebot/2.1 (+http://www.google.com/bot.html)"
}
/*jshint -W100*/
'use strict';
var cheerio = require('cheerio');
var each = require('foreach');
/**
* cheerioオブジェクト拡張モジュール(プロトタイプにメソッド追加)
*/
module.exports = function (encoding, client) {
each([
'html',
'click',
'submit',
'tick-untick',
'field',
'url',
'download'
], function (m) {
require('./cheerio/' + m)(encoding, client, cheerio);
});
return cheerio;
};
/*jshint -W100*/
'use strict';
var cutil = require('./util');
module.exports = function (encoding, client, cheerio) {
/**
* a要素のリンク/submit系ボタンのクリックをエミュレート
*
* a要素: リンク先のページを取得
* submit系ボタン: 所属フォームのsubmit
*
* @param callback リクエスト完了時のコールバック関数(err, response, body(buffer))
*/
var emulateClick = function (elem, callback) {
var doc = cutil.documentInfo(elem);
var $link = null;
// a要素でなければエラー
try {
if (elem.length === 0) {
throw new Error('no elements');
}
// 複数ある場合は先頭の要素のみ
$link = elem.eq(0);
// submit系要素の場合はsubmit()に飛ばす
var type = $link.attr('type');
var is = {
a: $link.is('a'),
input: $link.is('input'),
button: $link.is('button')
};
if ((is.input || is.button) && cutil.inArray([ 'submit', 'image' ], type)) {
var $form = $link.closest('form');
var param = {};
var name = cutil.paramFilter($link.attr('name'));
if (name.length > 0) {
if (type === 'submit') {
// submit: 押したボタンのnameとvalueを送信する
param[name] = $link.val() || $link.attr('value');
} else {
// image: 押したボタンのname.xとname.y座標を送信する(ダミーなので0)
param[name + '.x'] = 0;
param[name + '.y'] = 0;
}
}
return $form.submit(param, callback);
}
// submit系要素でもa要素でもなければエラー
if (! is.a) {
throw new Error('element is not clickable');
}
} catch (e) {
return client.error(e.message, {
param: { uri: doc.url },
callback: callback
});
}
return client.run('GET', $link.url(), {}, null, callback);
};
/**
* 非同期クリック
*/
cheerio.prototype.click = function (callback) {
return emulateClick(this, callback);
};
/**
* 同期クリック
*/
cheerio.prototype.clickSync = function (callback) {
return emulateClick(this, 'sync');
};
};
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
var util = require('util');
var events = require('events');
var stream = require('stream');
var async = require('async');
var assign = require('object-assign');
var cutil = require('./util');
module.exports = function (encoding, client, cheerio) {
var urlCache = [];
/**
* ダウンロードイベント管理用クラス
*
* すべてのダウンロード結果はこのクラスにemit()される
* - success: ダウンロード完了時(url, buffer)
* - error: ダウンロード失敗時(error)
*/
var DownloadEvent = (function () {
function DownloadEvent() {
events.EventEmitter.call(this);
this.parallel = 3;
this.state = Object.freeze({
queue: 0, // ダウンロードキューに残っている順番待ち画像の数
complete: 0, // ダウンロードが完了した画像の数
error: 0 // ダウンロードが失敗した画像の数
});
}
util.inherits(DownloadEvent, events.EventEmitter);
/**
* URLキャッシュクリア
*/
DownloadEvent.prototype.clearCache = function () {
urlCache.length = 0;
};
return DownloadEvent;
})();
var downloadEvent = new DownloadEvent();
Object.defineProperty(client.core, 'download', {
enumerable: true,
get: function () {
return downloadEvent;
}
});
/**
* ダウンロードストリームクラス
*/
var DownloadStream = (function () {
function DownloadStream(res) {
stream.PassThrough.call(this);
this.url = (res.request) ? res.request.uri : 'base64';
this.type = res.headers['content-type'];
this.length = Number(res.headers['content-length'] || -1);
// タイムアウト時間を過ぎてもStreamの読み出しが行われていない場合は放置されているとみなす
this.__timer = setTimeout((function () {
if (! this.isUsed()) {
clearTimeout(this.__timer);
this.__timer = null;
this.emit('error', new Error('stream timeout (maybe stream is not used)'));
}
}).bind(this), client.core.timeout);
}
util.inherits(DownloadStream, stream.PassThrough);
/**
* Stream => Buffer
*
* @param cb 変換後のBufferを受け取るコールバック関数(err, buffer)
*/
DownloadStream.prototype.toBuffer = function (cb) {
if (! (cb instanceof Function)) {
throw new Error('callback is not function');
}
if (this.isUsed()) {
throw new Error('stream has already been read');
}
var buffer = [];
this.on('data', function (chunk) {
buffer.push(chunk);
});
this.on('error', function (err) {
cb.call(this, err);
});
this.on('end', function () {
cb.call(this, null, Buffer.concat(buffer));
});
};
/**
* Streamの読み出しが開始されたかどうか(on('data')/pipe()が使用された形跡でチェック)
*
* @return true: 開始された
*/
DownloadStream.prototype.isUsed = function () {
return (this._readableState.pipesCount > 0 || this.listeners('data').length > 0);
};
/**
* 手動でend()が呼ばれた場合はスキップ扱いにする
*/
DownloadStream.prototype.end = function () {
if (! this.__timer) {
return;
}
clearTimeout(this.__timer);
this.__timer = null;
this.emit('end');
};
return DownloadStream;
})();
/**
* イベント管理用クラスカウントを更新
*/
function updateState(counts) {
client.core.download.state = Object.freeze(
assign({}, client.core.download.state, counts)
);
}
/**
* ダウンロード統括管理用クラス
*/
var DownloadManager = (function () {
var jobRunning = false;
/**
* ダウンロードループ実行
*/
function downloadJob(manager) {
// 実行フラグON
jobRunning = true;
// 現在キューに入っている分を全部切り出して一時キューに移動
var qLen = manager.queue.length;
var tmp = {
queue: manager.queue.splice(0, qLen),
complete: 0,
error: 0,
applyState: function (complete, error) {
// 一時キューの処理状況をダウンロードマネージャーに反映させる
this.complete += complete;
this.error += error;
updateState({
complete: client.core.download.state.complete + complete,
error: client.core.download.state.error + error,
queue: manager.queue.length + this.queue.length - this.complete - this.error
});
}
};
// 一時キュー内のURLを順番にダウンロード(同時処理数: parallel)
async.eachLimit(tmp.queue, manager.parallel, function (url, next) {
var req = null; // リクエストオブジェクト
var strm = null; // ダウンロードストリームオブジェクト
// 失敗時の処理
var onError = function (err) {
tmp.applyState(0, 1);
err.url = url;
client.core.download.emit('error', err);
req.abort();
next();
return;
};
// ストリームで取得する場合はgzipにしない
var options = client.prepare('GET', url, {}, null);
options.param.gzip = false;
try {
req = client.request(options.param);
} catch (e) {
e.type = 'Request Exception';
onError(e);
return;
}
req
.on('response', function (res) {
if (String(res.statusCode).substr(0, 2) !== '20') {
var err = new Error('server status');
err.statusCode = res.statusCode;
err.type = 'Invalid Response';
onError(err);
return;
}
// ダウンロードストリームオブジェクトを作成してレスポンスを流し込む
strm = new DownloadStream(res);
// ダウンロード完了時
strm
.on('end', function () {
tmp.applyState(1, 0);
req.abort();
next();
})
.on('error', function (err) {
err.type = 'Stream Error';
onError(err);
});
client.core.download.emit('ready', strm);
req.pipe(strm);
})
// 複数回発生するようなのでonce
.once('error', function (err) {
err.type = 'Request Error';
return onError(err);
});
}, function (err) {
// 現在のダウンロード中にキューに追加されているURLがあるかもしれないので
// 再度loopイベントを飛ばしておく
jobRunning = false;
manager.emit('loop');
});
}
function DownloadManager() {
this.queue = []; // ダウンロード待ちURL配列
this.on('loop', (function () {
if (jobRunning) {
// 二重処理防止
return;
}
if (this.queue.length > 0) {
downloadJob(this);
} else {
client.core.download.emit('end');
}
}).bind(this));
}
util.inherits(DownloadManager, events.EventEmitter);
/**
* ダウンロードキューにURLを追加
*
* @param url ダウンロードするURL
* @return true: キューに登録された
*/
DownloadManager.prototype.addQueue = function (url) {
if (! url) {
return false;
}
if (cutil.inArray(urlCache, url)) {
// 登録/ダウンロード済み
return false;
}
urlCache.push(url);
process.nextTick((function () {
this.queue.push(url);
this.emit('loop');
}).bind(this));
return true;
};
return DownloadManager;
})();
var manager = new DownloadManager();
/**
* img要素の画像をダウンロード
*
* @param srcAttrs (imgのみ)srcよりも優先して取得する属性名(文字列 or 配列)
* @return キューに登録した数
*/
cheerio.prototype.download = function (srcAttrs) {
// ダウンロードマネージャーの設定がされていない
if (client.core.download.listeners('ready').length === 0) {
throw new Error('download manager configured no event');
}
var doc = cutil.documentInfo(this);
var $ = cheerio;
// 最初に全要素がimg要素かどうかチェック
this.each(function () {
if (! $(this).is('img')) {
throw new Error('element is not img');
}
});
// 同時実行数チェック
var parallel = parseInt(client.core.download.parallel, 10);
if (parallel < 1 || parallel > 5) {
throw new Error('valid download parallel range is 1 and 5');
}
manager.parallel = parallel;
var queued = 0;
this.each(function () {
var $elem = $(this);
// ここの$はfetch()を経由していないので_documentInfoがない
if (! $elem._root) {
$elem._root = {
0: { _documentInfo: doc }
};
}
// Base64埋め込み画像の場合はBuffer化して即返す
var b64chk = ($elem.attr('src') || '').match(/^data:(image\/\w+);base64,([\s\S]+)$/i);
if (b64chk) {
updateState({
complete: client.core.download.state.complete + 1
});
var b64buf = cutil.newBuffer(b64chk[2], 'base64');
var strm = new DownloadStream({
headers: {
'content-type': b64chk[1],
'content-length': b64buf.length
}
});
client.core.download.emit('ready', strm);
strm.write(b64buf);
strm.end();
queued++;
return;
}
var url = $elem.url({ invalid: false }, srcAttrs);
if (manager.addQueue(url)) {
queued++;
}
});
return queued;
};
};
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
var typeOf = require('type-of');
var each = require('foreach');
var cutil = require('./util');
module.exports = function (encoding, client, cheerio) {
/**
* フォーム内部品の値取得/設定
*
* jQueryの$().attrや$().cssと同じ使用感
* 1. nameのみ指定した場合はそのname部品の値を取得
* 2. name, valueを指定した場合はそのname部品の値をvalueに設定
* 3. valueに関数を指定した場合はその関数の戻り値をname部品の値に設定
* 4. nameに文字列でなくname:valueの連想配列を指定した場合は複数要素をまとめて設定
*
* @param name 対象のフォーム部品のname or name: valueの連想配列
* @param value 設定する値 or 値を返す関数 or undefined
* @param onNotFound 指定したnameの要素が見つからない場合の挙動('throw', 'append')
* @return 1: name部品の値 or 2-4: this(メソッドチェーン用)
*/
cheerio.prototype.field = function (name, value, onNotFound) {
var $ = cheerio;
var $form = null;
// form要素でなければエラー
if (this.length === 0) {
throw new Error('no elements');
}
// 複数ある場合は先頭のフォームのみ
$form = this.eq(0);
if (! $form.is('form')) {
throw new Error('element is not form');
}
// *** 値取得モード ***
var argLen = arguments.length;
var isGet = ((argLen === 0) || (typeOf(name) === 'string' && argLen === 1));
if (isGet) {
// cheerio.serializeArray()だと値のない部品を拾ってくれないようなので自力でやる
var fieldInfo = {};
$form.find('input,textarea,select').each(function (idx) {
var $e = $(this);
var name = $e.attr('name');
var type = ($e.attr('type') || '').toLowerCase();
var val = $e.val() || $e.attr('value');
if (! name) {
return;
}
// submit系要素はjavascriptでform.submit()した時にはパラメータとして付加しない
// (ブラウザと同じ挙動)
if (cutil.inArray([ 'submit', 'image' ], type)) {
return;
}
fieldInfo[name] = fieldInfo[name] || {};
fieldInfo[name].count = (fieldInfo[name].count || 0) + 1;
fieldInfo[name].params = fieldInfo[name].params || [];
// radioは複数同nameがあるのが普通なので設定値を配列にしない
if (type === 'radio' && ! fieldInfo[name].force) {
fieldInfo[name].force = 'single';
}
// selectでmultipleの場合は強制的に設定値を配列にする
if ($e.is('select') && $e.attr('multiple') && ! fieldInfo[name].force) {
fieldInfo[name].force = 'multi';
}
if (cutil.inArray([ 'checkbox', 'radio' ], type) && ! $e.attr('checked')) {
return;
}
if (typeOf(val) === 'array') {
fieldInfo[name].params = fieldInfo[name].params.concat(val);
} else {
fieldInfo[name].params.push(val);
}
});
// 複数同nameのcheckboxやmultipleのselect以外は値の配列化を解除
var fieldParams = {};
each(fieldInfo, function (info, name) {
fieldParams[name] = info.params;
if (info.force !== 'multi' && (info.force === 'single' || info.count === 1)) {
fieldParams[name] = fieldParams[name].shift();
}
});
// 引数未指定の場合はそのフォーム内の全要素のname:valueを連想配列で返す
return (argLen === 0) ? fieldParams : fieldParams[name];
}
// *** 値設定モード ***
var values = {};
switch (typeOf(name)) {
case 'string': {
// name: valueの連想配列化してvaluesにセット
values[name] = value;
break;
}
case 'object': {
values = name;
// 連想配列で指定した場合はvalueの位置にonNotFoundが入っているのでずらす
onNotFound = value;
break;
}
default: {
// それ以外の型は受け付けない
throw new Error('name is not string or object');
}
}
each(values, function (v, k, o) {
// valueが関数で指定されている場合は実行して値ベースにそろえる
var realValue = (typeOf(v) === 'function') ? v() : v;
// 同じnameで別部品とかあってもさすがにそれはフォーム側の問題な気がするので無視
var selector = [ 'input', 'textarea', 'select' ].map(function (s) {
return s + '[name="' + k + '"]';
}).join(',');
var $parts = $form.find(selector);
var pType = $parts.attr('type');
if ($parts.length === 0) {
// nameに該当する部品が見つからない場合はonNotFoundに従う
if (onNotFound === 'append') {
// append: 新規に要素を作成してフォームに付加
var iType = 'hidden';
if (typeOf(realValue) === 'array') {
// 値が配列: checkbox
iType = 'checkbox';
} else {
// 値が文字列: hidden
realValue = [ realValue ];
}
each(realValue, function (val) {
var $input = $('<input/>').attr({ type: iType, name: k, value: val });
if (iType === 'checkbox') {
$input.attr('checked', 'checked');
}
$form.append($input);
});
return;
}
if (onNotFound === 'throw') {
// throw: エラー
throw new Error('Element named "' + k + '" could not be found in this form');
}
}
if (cutil.inArray([ 'checkbox', 'radio' ], pType)) {
// radioの場合は指定したvalueが該当しなければ何もしない
if (pType === 'radio') {
realValue = String(realValue);
var partsValues = $parts.map(function (idx) {
return $(this).val();
}).get();
if (! cutil.inArray(partsValues, realValue)) {
return;
}
}
// tick/untickで値を操作
if (typeOf(realValue) !== 'array') {
realValue = [ realValue ];
}
$parts.untick().each(function (idx) {
if (cutil.inArray(realValue, $(this).val())) {
$(this).tick();
}
});
return;
}
$parts.val(realValue);
});
return this;
};
};
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
var util = require('util');
var cutil = require('./util');
module.exports = function (encoding, client, cheerio) {
/**
* cheerio.load()の際にdecodeEntitiesをtrueにするとhtml()メソッドで文字列が
* すべてエンティティ表記になってしまうのでエンティティをデコードするように拡張する
*
* @param str 指定した場合はその文字列を要素のHTMLとして設定
* 指定しない場合は要素に設定されているHTMLを返す
*/
// cheerioデフォルトのhtmlメソッドをentityHtmlとして退避
cheerio.prototype.entityHtml = cheerio.prototype.html;
cheerio.prototype.html = function (str) {
// cheerioデフォルトのhtml()結果をデコード(エンティティ可読文字化)したものを返す
return cutil.decodeEntities(this.entityHtml(str));
};
/***
* [DEPRECATED] 将来削除予定
*/
var deprecatedMessage = '%s() will be removed in the future)';
cheerio.prototype._text = function (str) {
cutil.colorMessage('DEPRECATED', util.format(deprecatedMessage, '_text'));
return this.text(str);
};
cheerio.prototype._html = function (str) {
cutil.colorMessage('DEPRECATED', util.format(deprecatedMessage, '_html'));
return this.html(str);
};
};
/*jshint -W100*/
'use strict';
var urlParser = require('url');
var typeOf = require('type-of');
var each = require('foreach');
var cutil = require('./util');
module.exports = function (encoding, client, cheerio) {
/**
* form要素からの送信をエミュレート
*
* @param param 疑似設定するフォーム送信パラメータ
* @param callback リクエスト完了時のコールバック関数(err, response, body(buffer))
*/
var emulateSubmit = function (elem, param, callback) {
if (param === 'sync' || typeOf(param) === 'function') {
callback = param;
param = {};
}
param = param || {};
var doc = cutil.documentInfo(elem);
var $form = null;
// form要素でなければエラー
try {
if (elem.length === 0) {
throw new Error('no elements');
}
// 複数ある場合は先頭のフォームのみ
$form = elem.eq(0);
if (! $form.is('form')) {
throw new Error('element is not form');
}
} catch (e) {
return client.error(e.message, {
param: { uri: doc.url },
callback: callback
});
}
// methodとURL確定
var method = ($form.attr('method') || 'GET').toUpperCase();
var url = urlParser.resolve(doc.url, $form.attr('action') || '');
// フォーム送信パラメータ作成
// 1. デフォルトパラメータ($form.field())を取得した後に
// 2. 引数で指定したパラメータ(param)で上書き
var formParam = {};
each([ $form.field(), param ], function (fp) {
each(fp, function (val, name) {
var fparam = cutil.paramFilter(val);
var fvalue = (typeOf(fparam) === 'array') ? fparam : [ fparam ];
// 空パラメータでもname=のみで送信するための仕込み
if (fvalue.length === 0) {
fvalue.push('');
}
formParam[name] = fvalue;
});
});
// 各種エンコーディングに対応したURLエンコードをする必要があるのでパラメータ文字列を自力で作成
var formParamArray = [];
// accept-charsetは先頭で指定されているものを使用
var enc = ($form.attr('accept-charset') || doc.encoding).split(/[\s,]+/)[0];
each(formParam, function (val, name) {
formParamArray.push(val.map(function (vv) {
var escName = encoding.escape(enc, name);
var escVal = encoding.escape(enc, vv);
if (method === 'POST') {
// application/x-www-form-urlencodedでは半角スペースは%20ではなく+にする
escName = escName.replace(/%20/g, '+');
escVal = escVal.replace(/%20/g, '+');
}
return escName + '=' + escVal;
}).join('&'));
});
var formParamStr = formParamArray.join('&');
// GETの場合はURLに繋げてパラメータを空にする(そうしないと上手く動かないケースがたまにあった)
if (method === 'GET') {
var join = (url.indexOf('?') === -1) ? '?' : '&';
if (formParamStr.length > 0) {
url += join + formParamStr;
}
formParamStr = {};
}
return client.run(method, url, formParamStr, null, callback);
};
/**
* 非同期フォーム送信
*/
cheerio.prototype.submit = function (param, callback) {
return emulateSubmit(this, param, callback);
};
/**
* 同期フォーム送信
*/
cheerio.prototype.submitSync = function (param) {
return emulateSubmit(this, param, 'sync');
};
};
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
var each = require('foreach');
var cutil = require('./util');
module.exports = function (encoding, client, cheerio) {
/**
* チェックボックス/ラジオボタンの選択クリックをエミュレート
*
* @param elem checked状態を変更するcheerio要素
* @param checked 設定する値('checked' or undefined)
*/
var emulateTick = function (elem, checked) {
var $ = cheerio;
if ($(elem).length === 0) {
throw new Error('no elements');
}
// checkboxとradioの振り分け
var $targets = {
checkbox: [],
radio: []
};
var radioGroups = [];
$(elem).each(function (i) {
var $e = $(this);
var type = $e.attr('type');
if (! $e.is('input') || ! cutil.inArray([ 'checkbox', 'radio' ], type)) {
// input[type=checkbox/radio]以外が混じっていたらエラー
throw new Error('element is not checkbox or radio');
}
// radio: 同グループで複数要素がtick対象となっている場合は先頭以外の要素は無視
if (type === 'radio' && checked) {
var name = $e.attr('name').toLowerCase();
if (cutil.inArray(radioGroups, name)) {
return;
}
radioGroups.push(name);
}
$targets[type].push($e);
});
// 振り分けたcheckboxとradioに対してそれぞれ選択状態の変更を行う
each($targets, function ($elem, type) {
if (type === 'radio' && checked) {
// radioかつtickの場合はまず同グループの選択済みradioを全部未選択にする
each($elem, function ($e) {
var name = $e.attr('name');
$e
.closest('form') // 所属するフォーム
.find('input[type=radio][name="' + name + '"]') // 同グループのradio
.removeAttr('checked'); // 選択状態
});
}
each($elem, function ($e) {
if (checked) {
$e.attr('checked', checked);
} else {
$e.removeAttr('checked');
}
});
});
return elem;
};
/**
* チェックボックス/ラジオボタンを選択状態にする
*/
cheerio.prototype.tick = function () {
return emulateTick(this, 'checked');
};
/**
* チェックボックス/ラジオボタンの選択状態を解除する
*/
cheerio.prototype.untick = function () {
return emulateTick(this);
};
};
/*eslint no-invalid-this:0*/
/*jshint -W100*/
'use strict';
var urlParser = require('url');
var valUrl = require('valid-url');
var typeOf = require('type-of');
var cutil = require('./util');
var assign = require('object-assign');
module.exports = function (encoding, client, cheerio) {
/**
* a要素/img要素/script要素/link要素の絶対URLを取得
*
* @param optFilter 取得するURLのフィルタリングオプション
* @param srcAttrs (imgのみ)srcよりも優先して取得する属性名(文字列 or 配列)
* @return 絶対URLもしくはその配列
*/
cheerio.prototype.url = function (optFilter, srcAttrs) {
var doc = cutil.documentInfo(this);
var $ = cheerio;
var result = [];
if (cutil.inArray([ 'string', 'array' ], typeOf(optFilter))) {
srcAttrs = optFilter;
optFilter = {};
} else {
optFilter = optFilter || {};
}
var filter = assign({
relative: true, // 相対リンク
absolute: true, // 絶対リンク
invalid: true // URL以外
}, optFilter);
srcAttrs = srcAttrs || [ 'data-original', 'data-lazy-src', 'data-src' ];
if (typeOf(srcAttrs) !== 'array') {
srcAttrs = [ srcAttrs ];
}
srcAttrs.push('src');
// a要素/img要素/script要素でなければエラー
this.each(function () {
var $elem = $(this);
var is = {
a: $elem.is('a'),
img: $elem.is('img'),
script: $elem.is('script'),
link: $elem.is('link')
};
if (! is.a && ! is.img && ! is.script && ! is.link) {
throw new Error('element is not link, img, script or link');
}
// URLを取り出して絶対化
var srcUrl = null;
if (is.a || is.link) {
srcUrl = $elem.attr('href');
} else if (is.script) {
srcUrl = $elem.attr('src');
} else {
// imgの場合はsrcAttrsの優先順に従って属性を見ていく
for (var i = 0; i < srcAttrs.length; i++) {
srcUrl = $elem.attr(srcAttrs[i]);
if (srcUrl) {
break;
}
}
}
var absUrl = (srcUrl) ? urlParser.resolve(doc.url, srcUrl) : srcUrl;
// 除外判定
if (valUrl.isWebUri(absUrl)) {
var isAbsoluteLink = /^[a-z]+:\/\//i.test(srcUrl);
if (isAbsoluteLink && ! filter.absolute) {
return;
}
if (! isAbsoluteLink && ! filter.relative) {
return;
}
} else if (! filter.invalid) {
return;
}
result.push(absUrl);
});
// 要素数が1の場合は配列でなく文字列で返す
return (this.length === 1) ? result[0] : result;
};
};
/*jshint -W100*/
'use strict';
var he = require('he');
var typeOf = require('type-of');
var colors = require('colors/safe');
/**
* 汎用関数 - エンティティのデコード
*
* @param str エンティティ化された文字列
*/
module.exports.decodeEntities = function (str) {
// 文字列でない場合(cheerioオブジェクトなど)はそのまま返す
if (typeOf(str) !== 'string') {
return str;
}
return he.decode(str);
};
/**
* 汎用関数 - パラメータの正規化
*
* @param val GET/POSTパラメータ
*/
module.exports.paramFilter = function (val) {
// 0はパラメータとして有効なので残す
// null/undefinedは空文字にして返す
if (typeOf(val) !== 'number' && ! val) {
val = '';
}
return val;
};
/**
* 汎用関数 - cheerio拡張情報_documentInfo取得
*
* @param $ 拡張cheerioオブジェクト
* @return client.jsでWEBページ情報取得時にセットされた_documentInfo
*/
module.exports.documentInfo = function ($) {
if ($.cheerio !== '[cheerio object]') {
throw new Error('argument is not cheerio object');
}
// 大元の_rootは_originalRootという名称で保持されているらしい by cheerio/lib/static.js
return $._root[0]._documentInfo || $._originalRoot._documentInfo;
};
/**
* 汎用関数 - PHPでいうin_array()
* cheerioとは無関係
*
* @param array 調べる配列
* @param val 調べる値
* @return true or false
*/
module.exports.inArray = function (array, val) {
if (typeOf(array) !== 'array') {
throw new Error(array + ' is not Array');
}
return (array.indexOf(val) !== -1);
};
/**
* 汎用関数 - Buffer初期化
* Buffer.fromが実装されているバージョンならそちらを優先して使用
* cheerioとは無関係
*
* @param val 初期化内容
* @param type 初期化型
* @return Buffer
*/
module.exports.newBuffer = function (val, type) {
return (Buffer.from) ? Buffer.from(val, type) : new Buffer(val, type);
};
/**
* 汎用関数 - 色付きメッセージ表示
* cheerioとは無関係
*
* @param type メッセージの種類
* @param msg 表示するメッセージ
*/
module.exports.colorMessage = function (type, msg) {
/*eslint-disable key-spacing*/
var colorConf = {
DEPRECATED : 'yellow',
WARNING : 'magenta'
};
/*eslint-enable key-spacing*/
// スタックトレースを取得
var stackTrace = null;
try {
throw new Error('dummy');
} catch (e) {
stackTrace = e.stack.split(/[\r\n]+/).filter(function (v, v2, v3) {
return /^\s*at\s+.*:[\d]+:[\d]+/.test(v);
}).map(function (v) {
return v.trim();
});
}
// メッセージのトリガーとなった箇所を取得
var at = '';
for (var i = 0; i < stackTrace.length; i++) {
var trace = stackTrace[i];
if (! /^at/.test(trace)) continue;
if (/[\\\/]cheerio-httpcli[\\\/]lib[\\\/]/.test(trace)) continue;
at = trace;
break;
}
console.warn(colors[colorConf[type] || 'white'](
'[' + type + '] ' + msg + ' ' + at
));
};
This diff is collapsed. Click to expand it.
/*jshint -W100*/
'use strict';
var assign = require('object-assign');
var typeOf = require('type-of');
var each = require('foreach');
var cheerioExtend = require('./cheerio-extend');
var util = require('./cheerio/util.js');
var encoding = require('./encoding');
var client = require('./client');
var pkg = require('../package.json');
var browsers = require('./browsers.json');
/**
* cheerio-httpcli内部からプロパティを直接更新する際の黒魔術
*/
var propertyUpdater = {
// 内部的にプロパティを直接更新する際の照合キー
Key: Math.random().toString(36).substr(2),
// プロパティ更新時の値を黒魔術で包み込む
wrap: function (value) {
return [ this.key, value ];
},
// プロパティ更新時の値を黒魔術から取り出す
unwrap: function (value) {
if ((value instanceof Array) &&
value.length === 2 && value[0] === this.key) {
return value[1];
}
util.colorMessage('DEPRECATED', 'direct property update will be refused in the future. use set(key, value)');
//throw new Error(direct property update is not permitted. use set(key, value)');
return value;
}
};
// リクエストヘッダを作り直す
var rebuildHeaders = function (value) {
var tmp = {};
var nullKeys = [];
// リクエストヘッダは小文字に統一する & 値にnullが入っているキーは削除
each(value, function (val, key) {
if (value[key] === null) {
nullKeys.push(key.toLowerCase());
}
tmp[key.toLowerCase()] = val;
});
each(nullKeys, function (key) {
delete tmp[key];
});
return tmp;
};
// 通常プロパティ作成(property変数内で管理)
var defineNormalProperties = function (cli) {
/*eslint-disable key-spacing*/
var property = {
// リクエストヘッダ
headers : { types: [ 'object' ], value: null },
// タイムアウトまでの時間
timeout : { types: [ 'number' ], value: null },
// gzip転送する/しない
gzip : { types: [ 'boolean' ], value: null },
// Refererを自動設定する/しない
referer : { types: [ 'boolean' ], value: null },
// <meta[http-equiv=refresh]>を検知してリダイレクトする/しない
followMetaRefresh : { types: [ 'boolean' ], value: null },
// 受信を許可する最大のサイズ
maxDataSize : { types: [ 'number', 'null' ], value: null },
// XML自動判別を使用しない
forceHtml : { types: [ 'boolean' ], value: null },
// requestモジュールに渡すagentOptions
agentOptions : { types: [ 'object' ], value: null },
// デバッグオプション
debug : { types: [ 'boolean' ], value: null }
};
/*eslint-enable key-spacing*/
// プロパティ登録(直接更新時にはDEPRECATEDメッセージを表示)
Object.keys(property).forEach(function (prop) {
Object.defineProperty(cli, prop, {
enumerable: true,
get: function () {
// TODO 現在は直接更新も可としているのでコメントアウトしておく
//if (typeOf(property[prop].value) === 'object') {
// // オブジェクトの場合は複製を返す
// var copy = {};
// each(property[prop].value, function (val, key) {
// copy[key] = val;
// });
// return copy;
//}
return property[prop].value;
},
set: function (value) {
value = propertyUpdater.unwrap(value);
// 型チェック
var types = property[prop].types;
var vtype = typeOf(value);
if (types.indexOf(vtype) === -1 || (vtype === 'number' && value < 0)) {
util.colorMessage(
'WARNING',
'invalid value: ' + String(value) + '. '
+ 'property "' + prop + '" can accept only ' + types.join(' or ')
);
return;
}
// headersのキーを全部小文字に変換 & 値がnullのキーは削除
if (prop === 'headers') {
value = rebuildHeaders(value);
}
property[prop].value = value;
}
});
});
};
// 特殊プロパティ作成(動的に値を用意する)
var defineSpecialProperties = function (cli) {
// browserプロパティ
Object.defineProperty(cli, 'browser', {
enumerable: true,
get: function () {
// User-Agentとブラウザテンプレが一致するものを探す
var ua = this.headers['user-agent'];
if (! ua) {
return null;
}
var browser = Object.keys(browsers).filter(function (name) {
return (browsers[name] === ua);
});
if (browser.length > 0) {
return browser[0];
}
return 'custom';
},
set: function (type) {
type = propertyUpdater.unwrap(type);
if (type in browsers) {
this.set('headers', {
'User-Agent': browsers[type]
});
return;
}
util.colorMessage('WARNING', 'unknown browser: ' + type);
}
});
// iconvプロパティ
Object.defineProperty(cli, 'iconv', {
enumerable: true,
get: function () {
return encoding.getIconvType();
},
set: function (icmod) {
icmod = propertyUpdater.unwrap(icmod);
if (! encoding.iconvLoad(icmod)) {
throw new Error('Cannot find module "' + icmod + '"');
}
}
});
// バージョン情報プロパティ
Object.defineProperty(cli, 'version', {
enumerable: true,
get: function () {
return pkg.version;
}
});
};
// WIP マルチインスタンス化に向けて構造変更中
var CheerioHttpCli = (function () {
/**
* コンストラクタ
*/
function CheerioHttpCli() {
defineNormalProperties(this);
defineSpecialProperties(this);
}
/**
* プロパティや内部情報の初期化
*/
CheerioHttpCli.prototype.reset = function () {
// リクエストヘッダ
this.set('headers', {}, true);
// タイムアウトまでの時間(効いているかどうか不明)
this.set('timeout', 30000);
// gzip転送する/しない
this.set('gzip', true);
// Refererを自動設定する/しない
this.set('referer', true);
// <meta[http-equiv=refresh]>を検知してリダイレクトする/しない
this.set('followMetaRefresh', false);
// 受信を許可する最大のサイズ
this.set('maxDataSize', null);
// XML自動判別を使用しない
this.set('forceHtml', false);
// requestモジュールに渡すagentOptions
this.set('agentOptions', {}, true);
// デバッグオプション
this.set('debug', false);
client.reset();
return this;
};
/**
* プロパティを操作
*
* @param name 操作するプロパティ名
* @param value 挿入する値
* @param nomerge trueのときマージを行わない
*/
CheerioHttpCli.prototype.set = function (name, value, nomerge) {
// 特殊プロパティ
if ([ 'browser', 'iconv' ].indexOf(name) !== -1) {
this[name] = propertyUpdater.wrap(value);
return this;
}
// プロパティが存在するかチェック
if (! Object.keys(this).some((function (prop) {
return (prop === name && typeOf(this[prop]) !== 'function');
}).bind(this))) {
throw new Error('no such property "' + name + '"');
}
// オブジェクトへの代入ならマージする(黒魔術使用)
if (! nomerge && typeOf(this[name]) === 'object' && typeOf(value) === 'object') {
this[name] = propertyUpdater.wrap(assign(this[name], value));
} else {
this[name] = propertyUpdater.wrap(value);
}
return this;
};
/**
* [DEPRECATED] 使用するiconvモジュールを指定
*
* @param icmod iconvモジュール名(iconv|iconv-jp|iconv-lite)
*/
CheerioHttpCli.prototype.setIconvEngine = function (icmod) {
util.colorMessage('DEPRECATED', 'setIconvEngine() will be removed in the future. use set("iconv", value)');
this.set('iconv', icmod);
};
/**
* [DEPRECATED] ブラウザごとのUser-Agentをワンタッチ設定
*
* @param browser ブラウザ種類(see browsers.json)
* @return 設定できた/できなかった
*/
CheerioHttpCli.prototype.setBrowser = function (type) {
util.colorMessage('DEPRECATED', 'setBrowser() will be removed in the future. use set("browser", value)');
this.set('browser', type);
};
/**
* GETによる非同期httpリクエストを実行
*
* @param url リクエスト先のURL
* @param param リクエストパラメータ
* @param encode 取得先のHTMLのエンコーディング(default: 自動判定)
* @param callback リクエスト完了時のコールバック関数(err, cheerio, response, body)
*/
CheerioHttpCli.prototype.fetch = function (url, param, encode, callback) {
return client.run('GET', url, param, encode, callback);
};
/**
* GETによる同期httpリクエストを実行
*
* @param url リクエスト先のURL
* @param param リクエストパラメータ
* @param encode 取得先のHTMLのエンコーディング(default: 自動判定)
* @param callback リクエスト完了時のコールバック関数(err, cheerio, response, body)
*/
CheerioHttpCli.prototype.fetchSync = function (url, param, encode) {
return client.run('GET', url, param, encode, 'sync');
};
return CheerioHttpCli;
})();
var mainClient = new CheerioHttpCli();
// clientオブジェクト内で使用する外部オブジェクトを登録
mainClient.reset();
client.core = mainClient;
client.encoding = encoding;
client.cheerio = cheerioExtend(encoding, client);
module.exports = mainClient;
/*jshint -W100*/
'use strict';
var jschardet = require('jschardet');
var cutil = require('./cheerio/util');
/**
* <head>タグ内からエンコーディングを判定する正規表現
*/
/*eslint-disable key-spacing*/
var reEnc = {
head : /<head[\s>]([\s\S]*?)<\/head>/i,
charset : /<meta[^>]*[\s;]+charset\s*=\s*["']?([\w\-_]+)["']?/i
};
/**
* iconvモジュール情報
*/
var iconvMod = {
name : null,
engine : null,
func : null,
cache : {}
};
/*eslint-enable key-spacing*/
/**
* encodingモジュール本体
*/
var encoding = {
/**
* メソッド
*/
/**
* iconvモジュールをロード
*
* @param module iconvモジュール名(iconv|iconv-jp|iconv-lite)
* @return ロードできた/できなかった
*/
iconvLoad: function (module) {
// モジュール名チェック
if (! /^iconv(-(jp|lite))?$/.test(module)) {
return false;
}
// モジュールをロード
try {
iconvMod.engine = require(module);
} catch (/*eslint-disable no-unused-vars*/ e /*eslint-enable no-unused-vars*/) {
return false;
}
if (iconvMod.engine.Iconv) {
// iconv/iconv-jpはIconvというメソッドを持っている
iconvMod.func = function (enc, buffer, revert) {
enc = enc.toUpperCase();
var from = enc;
var to = 'UTF-8';
if (revert) {
from = 'UTF-8';
to = enc;
}
var cacheKey = from + ':' + to;
if (! (cacheKey in iconvMod.cache)) {
// Iconvオブジェクトをキャッシュする
iconvMod.cache[cacheKey] = new iconvMod.engine.Iconv(from, to + '//TRANSLIT//IGNORE');
}
return iconvMod.cache[cacheKey].convert(buffer);
};
} else {
// iconv-lite用
iconvMod.func = function (enc, buffer, revert) {
if (! iconvMod.engine.encodingExists(enc)) {
// iconv/iconv-jpとエラーオブジェクトの形を合わせる
var err = new Error('EINVAL, Conversion not supported.');
err.errno = 22;
err.code = 'EINVAL';
throw err;
}
return iconvMod.engine[(revert) ? 'encode' : 'decode'](buffer, enc);
};
}
iconvMod.name = module;
return true;
},
/**
* 使用中のiconvモジュールの種類を取得
*
* @return iconvモジュール名(iconv|iconv-jp|iconv-lite)
*/
getIconvType: function () {
return iconvMod.name;
},
/**
* エンコーディング名指定がUTF-8かどうか
*
* @param enc エンコーディング指定名('utf-8', 'shift_jis', ...)
* @return true or false
*/
isUTF8: function (enc) {
return /^utf\-?8$/i.test(enc);
},
/**
* HTML(Buffer)のエンコーディングをUTF-8に変換
*
* @param enc 変換元のエンコーディング
* @param buffer HTML(Buffer)
* @return UTF-8に変換後のHTML(Buffer)
*/
convert: function (enc, buffer) {
if (this.isUTF8(enc)) {
return buffer;
}
if (/(shift_jis|sjis)/i.test(enc)) {
// Shift_JISを指定してIconvで変換すると半角チルダが波ダッシュ(0x301C)に変換されてしまうのでCP932に変更
enc = 'CP932';
}
return iconvMod.func(enc, buffer);
},
/**
* パラメータのURL%エンコード(各種エンコーディング対応)
*
* @param enc 変換先のエンコーディング
* @param str URLエンコードする文字列
* @return encで指定したエンコーディングでURL%エンコードした文字列
*/
escape: function (enc, str) {
// var re = /^[\w\.\(\)\-!~*']+$/; // encodeURIComponent互換
var re = /^[\w~.-]+$/; // RFC-3986準拠
str = String(str);
if (re.test(str)) {
// エンコード不要
return str;
}
// UTF-8から指定したエンコーディングに変換したバッファを回してエスケープ文字列作成
var buffer = cutil.newBuffer(str);
if (! this.isUTF8(enc)) {
buffer = iconvMod.func(enc, buffer, true);
}
return Array.prototype.slice.call(buffer).map(function (b) {
if (b < 128) {
var c = String.fromCharCode(b);
if (re.test(c)) {
return c;
}
}
return '%' + ('0' + b.toString(16).toUpperCase()).substr(-2);
}).join('');
},
/**
* jschardetモジュールによるHTMLのエンコーディング判定
*
* @param buffer HTML(Buffer)
* @return 判定できた場合はエンコーディング名
*/
detectByBuffer: function (buffer) {
var enc = jschardet.detect(buffer);
// 高精度で判定できた場合のみ
if (enc && enc.encoding && (enc.confidence || 0) >= 0.99) {
return enc.encoding;
}
return null;
},
/**
* <head>タグ内から正規表現でエンコーディング判定
*
* @param buffer HTML(Buffer)
* @return 判定できた場合はエンコーディング名
*/
detectByHeader: function (buffer) {
var head = buffer.toString('ascii').match(reEnc.head);
if (head) {
var charset = head[1].match(reEnc.charset);
if (charset) {
return charset[1].trim();
}
}
return null;
},
/**
* HTMLエンコーディング判定(自動判定 -> <head>タグ判定の順)
*
* @param buffer HTML(Buffer)
* @return 判定できた場合はエンコーディング名
*/
detect: function (buffer) {
return this.detectByBuffer(buffer) || this.detectByHeader(buffer);
}
};
// 初期状態では iconv > iconv-lite の優先順でロードしておく
/*eslint-disable no-unused-expressions*/
encoding.iconvLoad('iconv') || encoding.iconvLoad('iconv-lite');
/*eslint-enable no-unused-expressions*/
module.exports = encoding;
/*jshint -W100*/
'use strict';
var client = require('./client');
process.stdin.resume();
process.stdin.setEncoding('utf8');
var input = '';
process.stdin.on('data', function (chunk) {
input += chunk;
});
process.stdin.on('end', function () {
var args = JSON.parse(input);
client.core = args.core;
// こちらでjarを作りなおす
args.param.jar = client.engine.jar();
Object.keys(args.cookies).forEach(function (key) {
var val = args.cookies[key];
var cookie = client.engine.cookie(key + '=' + val);
args.param.jar.setCookie(cookie, args.param.uri);
});
client.request(args.param, args.core.gzip, function (err, res, body) {
if (err) {
process.stderr.write(err.message);
}
process.stdout.write(JSON.stringify({
body: body,
response: (res) ? res.toJSON() : null,
cookies: args.param.jar.getCookies(args.param.uri) || []
}));
});
});
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
/**
* Export cheerio (with )
*/
exports = module.exports = require('./lib/cheerio');
/*
Export the version
*/
exports.version = require('./package.json').version;
var domEach = require('../utils').domEach,
_ = {
pick: require('lodash.pick'),
};
var toString = Object.prototype.toString;
/**
* Set / Get css.
*
* @param {String|Object} prop
* @param {String} val
* @return {self}
* @api public
*/
exports.css = function(prop, val) {
if (arguments.length === 2 ||
// When `prop` is a "plain" object
(toString.call(prop) === '[object Object]')) {
return domEach(this, function(idx, el) {
setCss(el, prop, val, idx);
});
} else {
return getCss(this[0], prop);
}
};
/**
* Set styles of all elements.
*
* @param {String|Object} prop
* @param {String} val
* @param {Number} idx - optional index within the selection
* @return {self}
* @api private
*/
function setCss(el, prop, val, idx) {
if ('string' == typeof prop) {
var styles = getCss(el);
if (typeof val === 'function') {
val = val.call(el, idx, styles[prop]);
}
if (val === '') {
delete styles[prop];
} else if (val != null) {
styles[prop] = val;
}
el.attribs.style = stringify(styles);
} else if ('object' == typeof prop) {
Object.keys(prop).forEach(function(k){
setCss(el, k, prop[k]);
});
}
}
/**
* Get parsed styles of the first element.
*
* @param {String} prop
* @return {Object}
* @api private
*/
function getCss(el, prop) {
var styles = parse(el.attribs.style);
if (typeof prop === 'string') {
return styles[prop];
} else if (Array.isArray(prop)) {
return _.pick(styles, prop);
} else {
return styles;
}
}
/**
* Stringify `obj` to styles.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function stringify(obj) {
return Object.keys(obj || {})
.reduce(function(str, prop){
return str += ''
+ (str ? ' ' : '')
+ prop
+ ': '
+ obj[prop]
+ ';';
}, '');
}
/**
* Parse `styles`.
*
* @param {String} styles
* @return {Object}
* @api private
*/
function parse(styles) {
styles = (styles || '').trim();
if (!styles) return {};
return styles
.split(';')
.reduce(function(obj, str){
var n = str.indexOf(':');
// skip if there is no :, or if it is the first/last character
if (n < 1 || n === str.length-1) return obj;
obj[str.slice(0,n).trim()] = str.slice(n+1).trim();
return obj;
}, {});
}
// https://github.com/jquery/jquery/blob/2.1.3/src/manipulation/var/rcheckableType.js
// https://github.com/jquery/jquery/blob/2.1.3/src/serialize.js
var submittableSelector = 'input,select,textarea,keygen',
r20 = /%20/g,
rCRLF = /\r?\n/g,
_ = {
map: require('lodash.map')
};
exports.serialize = function() {
// Convert form elements into name/value objects
var arr = this.serializeArray();
// Serialize each element into a key/value string
var retArr = _.map(arr, function(data) {
return encodeURIComponent(data.name) + '=' + encodeURIComponent(data.value);
});
// Return the resulting serialization
return retArr.join('&').replace(r20, '+');
};
exports.serializeArray = function() {
// Resolve all form elements from either forms or collections of form elements
var Cheerio = this.constructor;
return this.map(function() {
var elem = this;
var $elem = Cheerio(elem);
if (elem.name === 'form') {
return $elem.find(submittableSelector).toArray();
} else {
return $elem.filter(submittableSelector).toArray();
}
}).filter(
// Verify elements have a name (`attr.name`) and are not disabled (`:disabled`)
'[name!=""]:not(:disabled)'
// and cannot be clicked (`[type=submit]`) or are used in `x-www-form-urlencoded` (`[type=file]`)
+ ':not(:submit, :button, :image, :reset, :file)'
// and are either checked/don't have a checkable state
+ ':matches([checked], :not(:checkbox, :radio))'
// Convert each of the elements to its value(s)
).map(function(i, elem) {
var $elem = Cheerio(elem);
var name = $elem.attr('name');
var val = $elem.val();
// If there is no value set (e.g. `undefined`, `null`), then return nothing
if (val == null) {
return null;
} else {
// If we have an array of values (e.g. `<select multiple>`), return an array of key/value pairs
if (Array.isArray(val)) {
return _.map(val, function(val) {
// We trim replace any line endings (e.g. `\r` or `\r\n` with `\r\n`) to guarantee consistency across platforms
// These can occur inside of `<textarea>'s`
return {name: name, value: val.replace( rCRLF, '\r\n' )};
});
// Otherwise (e.g. `<input type="text">`, return only one key/value pair
} else {
return {name: name, value: val.replace( rCRLF, '\r\n' )};
}
}
// Convert our result to an array
}).get();
};
/*
Module dependencies
*/
var parse = require('./parse'),
isHtml = require('./utils').isHtml,
_ = {
extend: require('lodash.assignin'),
bind: require('lodash.bind'),
forEach: require('lodash.foreach'),
defaults: require('lodash.defaults')
};
/*
* The API
*/
var api = [
require('./api/attributes'),
require('./api/traversing'),
require('./api/manipulation'),
require('./api/css'),
require('./api/forms')
];
/*
* Instance of cheerio
*/
var Cheerio = module.exports = function(selector, context, root, options) {
if (!(this instanceof Cheerio)) return new Cheerio(selector, context, root, options);
this.options = _.defaults(options || {}, this.options);
// $(), $(null), $(undefined), $(false)
if (!selector) return this;
if (root) {
if (typeof root === 'string') root = parse(root, this.options);
this._root = Cheerio.call(this, root);
}
// $($)
if (selector.cheerio) return selector;
// $(dom)
if (isNode(selector))
selector = [selector];
// $([dom])
if (Array.isArray(selector)) {
_.forEach(selector, _.bind(function(elem, idx) {
this[idx] = elem;
}, this));
this.length = selector.length;
return this;
}
// $(<html>)
if (typeof selector === 'string' && isHtml(selector)) {
return Cheerio.call(this, parse(selector, this.options).children);
}
// If we don't have a context, maybe we have a root, from loading
if (!context) {
context = this._root;
} else if (typeof context === 'string') {
if (isHtml(context)) {
// $('li', '<ul>...</ul>')
context = parse(context, this.options);
context = Cheerio.call(this, context);
} else {
// $('li', 'ul')
selector = [context, selector].join(' ');
context = this._root;
}
// $('li', node), $('li', [nodes])
} else if (!context.cheerio) {
context = Cheerio.call(this, context);
}
// If we still don't have a context, return
if (!context) return this;
// #id, .class, tag
return context.find(selector);
};
/**
* Mix in `static`
*/
_.extend(Cheerio, require('./static'));
/*
* Set a signature of the object
*/
Cheerio.prototype.cheerio = '[cheerio object]';
/*
* Cheerio default options
*/
Cheerio.prototype.options = {
withDomLvl1: true,
normalizeWhitespace: false,
xmlMode: false,
decodeEntities: true
};
/*
* Make cheerio an array-like object
*/
Cheerio.prototype.length = 0;
Cheerio.prototype.splice = Array.prototype.splice;
/*
* Make a cheerio object
*
* @api private
*/
Cheerio.prototype._make = function(dom, context) {
var cheerio = new this.constructor(dom, context, this._root, this.options);
cheerio.prevObject = this;
return cheerio;
};
/**
* Turn a cheerio object into an array
*/
Cheerio.prototype.toArray = function() {
return this.get();
};
/**
* Plug in the API
*/
api.forEach(function(mod) {
_.extend(Cheerio.prototype, mod);
});
var isNode = function(obj) {
return obj.name || obj.type === 'text' || obj.type === 'comment';
};
/*
Module Dependencies
*/
var htmlparser = require('htmlparser2');
/*
Parser
*/
exports = module.exports = function(content, options) {
var dom = exports.evaluate(content, options),
// Generic root element
root = exports.evaluate('<root></root>', options)[0];
root.type = 'root';
// Update the dom using the root
exports.update(dom, root);
return root;
};
exports.evaluate = function(content, options) {
// options = options || $.fn.options;
var dom;
if (typeof content === 'string' || Buffer.isBuffer(content)) {
dom = htmlparser.parseDOM(content, options);
} else {
dom = content;
}
return dom;
};
/*
Update the dom structure, for one changed layer
*/
exports.update = function(arr, parent) {
// normalize
if (!Array.isArray(arr)) arr = [arr];
// Update parent
if (parent) {
parent.children = arr;
} else {
parent = null;
}
// Update neighbors
for (var i = 0; i < arr.length; i++) {
var node = arr[i];
// Cleanly remove existing nodes from their previous structures.
var oldParent = node.parent || node.root,
oldSiblings = oldParent && oldParent.children;
if (oldSiblings && oldSiblings !== arr) {
oldSiblings.splice(oldSiblings.indexOf(node), 1);
if (node.prev) {
node.prev.next = node.next;
}
if (node.next) {
node.next.prev = node.prev;
}
}
if (parent) {
node.prev = arr[i - 1] || null;
node.next = arr[i + 1] || null;
} else {
node.prev = node.next = null;
}
if (parent && parent.type === 'root') {
node.root = parent;
node.parent = null;
} else {
node.root = null;
node.parent = parent;
}
}
return parent;
};
// module.exports = $.extend(exports);
/**
* Module dependencies
*/
var serialize = require('dom-serializer'),
select = require('css-select'),
parse = require('./parse'),
_ = {
merge: require('lodash.merge'),
defaults: require('lodash.defaults')
};
/**
* $.load(str)
*/
exports.load = function(content, options) {
var Cheerio = require('./cheerio');
options = _.defaults(options || {}, Cheerio.prototype.options);
var root = parse(content, options);
var initialize = function(selector, context, r, opts) {
if (!(this instanceof initialize)) {
return new initialize(selector, context, r, opts);
}
opts = _.defaults(opts || {}, options);
return Cheerio.call(this, selector, context, r || root, opts);
};
// Ensure that selections created by the "loaded" `initialize` function are
// true Cheerio instances.
initialize.prototype = Object.create(Cheerio.prototype);
initialize.prototype.constructor = initialize;
// Mimic jQuery's prototype alias for plugin authors.
initialize.fn = initialize.prototype;
// Keep a reference to the top-level scope so we can chain methods that implicitly
// resolve selectors; e.g. $("<span>").(".bar"), which otherwise loses ._root
initialize.prototype._originalRoot = root;
// Add in the static methods
_.merge(initialize, exports);
// Add in the root
initialize._root = root;
// store options
initialize._options = options;
return initialize;
};
/*
* Helper function
*/
function render(that, dom, options) {
if (!dom) {
if (that._root && that._root.children) {
dom = that._root.children;
} else {
return '';
}
} else if (typeof dom === 'string') {
dom = select(dom, that._root, options);
}
return serialize(dom, options);
}
/**
* $.html([selector | dom], [options])
*/
exports.html = function(dom, options) {
var Cheerio = require('./cheerio');
// be flexible about parameters, sometimes we call html(),
// with options as only parameter
// check dom argument for dom element specific properties
// assume there is no 'length' or 'type' properties in the options object
if (Object.prototype.toString.call(dom) === '[object Object]' && !options && !('length' in dom) && !('type' in dom))
{
options = dom;
dom = undefined;
}
// sometimes $.html() used without preloading html
// so fallback non existing options to the default ones
options = _.defaults(options || {}, this._options, Cheerio.prototype.options);
return render(this, dom, options);
};
/**
* $.xml([selector | dom])
*/
exports.xml = function(dom) {
var options = _.defaults({xmlMode: true}, this._options);
return render(this, dom, options);
};
/**
* $.text(dom)
*/
exports.text = function(elems) {
if (!elems) {
elems = this.root();
}
var ret = '',
len = elems.length,
elem;
for (var i = 0; i < len; i++) {
elem = elems[i];
if (elem.type === 'text') ret += elem.data;
else if (elem.children && elem.type !== 'comment') {
ret += exports.text(elem.children);
}
}
return ret;
};
/**
* $.parseHTML(data [, context ] [, keepScripts ])
* Parses a string into an array of DOM nodes. The `context` argument has no
* meaning for Cheerio, but it is maintained for API compatibility with jQuery.
*/
exports.parseHTML = function(data, context, keepScripts) {
var parsed;
if (!data || typeof data !== 'string') {
return null;
}
if (typeof context === 'boolean') {
keepScripts = context;
}
parsed = this.load(data);
if (!keepScripts) {
parsed('script').remove();
}
// The `children` array is used by Cheerio internally to group elements that
// share the same parents. When nodes created through `parseHTML` are
// inserted into previously-existing DOM structures, they will be removed
// from the `children` array. The results of `parseHTML` should remain
// constant across these operations, so a shallow copy should be returned.
return parsed.root()[0].children.slice();
};
/**
* $.root()
*/
exports.root = function() {
return this(this._root);
};
/**
* $.contains()
*/
exports.contains = function(container, contained) {
// According to the jQuery API, an element does not "contain" itself
if (contained === container) {
return false;
}
// Step up the descendants, stopping when the root element is reached
// (signaled by `.parent` returning a reference to the same object)
while (contained && contained !== contained.parent) {
contained = contained.parent;
if (contained === container) {
return true;
}
}
return false;
};
var parse = require('./parse'),
render = require('dom-serializer');
/**
* HTML Tags
*/
var tags = { tag: true, script: true, style: true };
/**
* Check if the DOM element is a tag
*
* isTag(type) includes <script> and <style> tags
*/
exports.isTag = function(type) {
if (type.type) type = type.type;
return tags[type] || false;
};
/**
* Convert a string to camel case notation.
* @param {String} str String to be converted.
* @return {String} String in camel case notation.
*/
exports.camelCase = function(str) {
return str.replace(/[_.-](\w|$)/g, function(_, x) {
return x.toUpperCase();
});
};
/**
* Convert a string from camel case to "CSS case", where word boundaries are
* described by hyphens ("-") and all characters are lower-case.
* @param {String} str String to be converted.
* @return {string} String in "CSS case".
*/
exports.cssCase = function(str) {
return str.replace(/[A-Z]/g, '-$&').toLowerCase();
};
/**
* Iterate over each DOM element without creating intermediary Cheerio instances.
*
* This is indented for use internally to avoid otherwise unnecessary memory pressure introduced
* by _make.
*/
exports.domEach = function(cheerio, fn) {
var i = 0, len = cheerio.length;
while (i < len && fn.call(cheerio, i, cheerio[i]) !== false) ++i;
return cheerio;
};
/**
* Create a deep copy of the given DOM structure by first rendering it to a
* string and then parsing the resultant markup.
*
* @argument {Object} dom - The htmlparser2-compliant DOM structure
* @argument {Object} options - The parsing/rendering options
*/
exports.cloneDom = function(dom, options) {
return parse(render(dom, options), options).children;
};
/*
* A simple way to check for HTML strings or ID strings
*/
var quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;
/*
* Check if string is HTML
*/
exports.isHtml = function(str) {
// Faster than running regex, if str starts with `<` and ends with `>`, assume it's HTML
if (str.charAt(0) === '<' && str.charAt(str.length - 1) === '>' && str.length >= 3) return true;
// Run the regex
var match = quickExpr.exec(str);
return !!(match && match[1]);
};
{
"_from": "cheerio@^0.22.0",
"_id": "cheerio@0.22.0",
"_inBundle": false,
"_integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
"_location": "/cheerio-httpcli/cheerio",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "cheerio@^0.22.0",
"name": "cheerio",
"escapedName": "cheerio",
"rawSpec": "^0.22.0",
"saveSpec": null,
"fetchSpec": "^0.22.0"
},
"_requiredBy": [
"/cheerio-httpcli"
],
"_resolved": "http://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
"_shasum": "a9baa860a3f9b595a6b81b1a86873121ed3a269e",
"_spec": "cheerio@^0.22.0",
"_where": "D:\\OSS project\\YTMT\\node_modules\\cheerio-httpcli",
"author": {
"name": "Matt Mueller",
"email": "mattmuelle@gmail.com",
"url": "mat.io"
},
"bugs": {
"url": "https://github.com/cheeriojs/cheerio/issues"
},
"bundleDependencies": false,
"dependencies": {
"css-select": "~1.2.0",
"dom-serializer": "~0.1.0",
"entities": "~1.1.1",
"htmlparser2": "^3.9.1",
"lodash.assignin": "^4.0.9",
"lodash.bind": "^4.1.4",
"lodash.defaults": "^4.0.1",
"lodash.filter": "^4.4.0",
"lodash.flatten": "^4.2.0",
"lodash.foreach": "^4.3.0",
"lodash.map": "^4.4.0",
"lodash.merge": "^4.4.0",
"lodash.pick": "^4.2.1",
"lodash.reduce": "^4.4.0",
"lodash.reject": "^4.4.0",
"lodash.some": "^4.4.0"
},
"deprecated": false,
"description": "Tiny, fast, and elegant implementation of core jQuery designed specifically for the server",
"devDependencies": {
"benchmark": "^2.1.0",
"coveralls": "^2.11.9",
"expect.js": "~0.3.1",
"istanbul": "^0.4.3",
"jquery": "^3.0.0",
"jsdom": "^9.2.1",
"jshint": "^2.9.2",
"mocha": "^2.5.3",
"xyz": "~0.5.0"
},
"engines": {
"node": ">= 0.6"
},
"files": [
"index.js",
"lib"
],
"homepage": "https://github.com/cheeriojs/cheerio#readme",
"keywords": [
"htmlparser",
"jquery",
"selector",
"scraper",
"parser",
"html"
],
"license": "MIT",
"main": "./index.js",
"name": "cheerio",
"repository": {
"type": "git",
"url": "git://github.com/cheeriojs/cheerio.git"
},
"scripts": {
"test": "make test"
},
"version": "0.22.0"
}
Copyright (c) 2015, Salesforce.com, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This diff is collapsed. Click to expand it.
/*!
* Copyright (c) 2015, Salesforce.com, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. Neither the name of Salesforce.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE 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 SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
'use strict';
var Store = require('./store').Store;
var permuteDomain = require('./permuteDomain').permuteDomain;
var pathMatch = require('./pathMatch').pathMatch;
var util = require('util');
function MemoryCookieStore() {
Store.call(this);
this.idx = {};
}
util.inherits(MemoryCookieStore, Store);
exports.MemoryCookieStore = MemoryCookieStore;
MemoryCookieStore.prototype.idx = null;
// Since it's just a struct in RAM, this Store is synchronous
MemoryCookieStore.prototype.synchronous = true;
// force a default depth:
MemoryCookieStore.prototype.inspect = function() {
return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
};
// Use the new custom inspection symbol to add the custom inspect function if
// available.
if (util.inspect.custom) {
MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
}
MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
if (!this.idx[domain]) {
return cb(null,undefined);
}
if (!this.idx[domain][path]) {
return cb(null,undefined);
}
return cb(null,this.idx[domain][path][key]||null);
};
MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
var results = [];
if (!domain) {
return cb(null,[]);
}
var pathMatcher;
if (!path) {
// null means "all paths"
pathMatcher = function matchAll(domainIndex) {
for (var curPath in domainIndex) {
var pathIndex = domainIndex[curPath];
for (var key in pathIndex) {
results.push(pathIndex[key]);
}
}
};
} else {
pathMatcher = function matchRFC(domainIndex) {
//NOTE: we should use path-match algorithm from S5.1.4 here
//(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)
Object.keys(domainIndex).forEach(function (cookiePath) {
if (pathMatch(path, cookiePath)) {
var pathIndex = domainIndex[cookiePath];
for (var key in pathIndex) {
results.push(pathIndex[key]);
}
}
});
};
}
var domains = permuteDomain(domain) || [domain];
var idx = this.idx;
domains.forEach(function(curDomain) {
var domainIndex = idx[curDomain];
if (!domainIndex) {
return;
}
pathMatcher(domainIndex);
});
cb(null,results);
};
MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
if (!this.idx[cookie.domain]) {
this.idx[cookie.domain] = {};
}
if (!this.idx[cookie.domain][cookie.path]) {
this.idx[cookie.domain][cookie.path] = {};
}
this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
cb(null);
};
MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
// updateCookie() may avoid updating cookies that are identical. For example,
// lastAccessed may not be important to some stores and an equality
// comparison could exclude that field.
this.putCookie(newCookie,cb);
};
MemoryCookieStore.prototype.removeCookie = function(domain, path, key, cb) {
if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
delete this.idx[domain][path][key];
}
cb(null);
};
MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
if (this.idx[domain]) {
if (path) {
delete this.idx[domain][path];
} else {
delete this.idx[domain];
}
}
return cb(null);
};
MemoryCookieStore.prototype.removeAllCookies = function(cb) {
this.idx = {};
return cb(null);
}
MemoryCookieStore.prototype.getAllCookies = function(cb) {
var cookies = [];
var idx = this.idx;
var domains = Object.keys(idx);
domains.forEach(function(domain) {
var paths = Object.keys(idx[domain]);
paths.forEach(function(path) {
var keys = Object.keys(idx[domain][path]);
keys.forEach(function(key) {
if (key !== null) {
cookies.push(idx[domain][path][key]);
}
});
});
});
// Sort by creationIndex so deserializing retains the creation order.
// When implementing your own store, this SHOULD retain the order too
cookies.sort(function(a,b) {
return (a.creationIndex||0) - (b.creationIndex||0);
});
cb(null, cookies);
};
/*!
* Copyright (c) 2015, Salesforce.com, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. Neither the name of Salesforce.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE 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 SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
"use strict";
/*
* "A request-path path-matches a given cookie-path if at least one of the
* following conditions holds:"
*/
function pathMatch (reqPath, cookiePath) {
// "o The cookie-path and the request-path are identical."
if (cookiePath === reqPath) {
return true;
}
var idx = reqPath.indexOf(cookiePath);
if (idx === 0) {
// "o The cookie-path is a prefix of the request-path, and the last
// character of the cookie-path is %x2F ("/")."
if (cookiePath.substr(-1) === "/") {
return true;
}
// " o The cookie-path is a prefix of the request-path, and the first
// character of the request-path that is not included in the cookie- path
// is a %x2F ("/") character."
if (reqPath.substr(cookiePath.length, 1) === "/") {
return true;
}
}
return false;
}
exports.pathMatch = pathMatch;
/*!
* Copyright (c) 2015, Salesforce.com, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. Neither the name of Salesforce.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE 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 SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
"use strict";
var pubsuffix = require('./pubsuffix-psl');
// Gives the permutation of all possible domainMatch()es of a given domain. The
// array is in shortest-to-longest order. Handy for indexing.
function permuteDomain (domain) {
var pubSuf = pubsuffix.getPublicSuffix(domain);
if (!pubSuf) {
return null;
}
if (pubSuf == domain) {
return [domain];
}
var prefix = domain.slice(0, -(pubSuf.length + 1)); // ".example.com"
var parts = prefix.split('.').reverse();
var cur = pubSuf;
var permutations = [cur];
while (parts.length) {
cur = parts.shift() + '.' + cur;
permutations.push(cur);
}
return permutations;
}
exports.permuteDomain = permuteDomain;
/*!
* Copyright (c) 2018, Salesforce.com, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. Neither the name of Salesforce.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE 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 SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
'use strict';
var psl = require('psl');
function getPublicSuffix(domain) {
return psl.get(domain);
}
exports.getPublicSuffix = getPublicSuffix;
/*!
* Copyright (c) 2015, Salesforce.com, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. Neither the name of Salesforce.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE 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 SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
'use strict';
/*jshint unused:false */
function Store() {
}
exports.Store = Store;
// Stores may be synchronous, but are still required to use a
// Continuation-Passing Style API. The CookieJar itself will expose a "*Sync"
// API that converts from synchronous-callbacks to imperative style.
Store.prototype.synchronous = false;
Store.prototype.findCookie = function(domain, path, key, cb) {
throw new Error('findCookie is not implemented');
};
Store.prototype.findCookies = function(domain, path, cb) {
throw new Error('findCookies is not implemented');
};
Store.prototype.putCookie = function(cookie, cb) {
throw new Error('putCookie is not implemented');
};
Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
// recommended default implementation:
// return this.putCookie(newCookie, cb);
throw new Error('updateCookie is not implemented');
};
Store.prototype.removeCookie = function(domain, path, key, cb) {
throw new Error('removeCookie is not implemented');
};
Store.prototype.removeCookies = function(domain, path, cb) {
throw new Error('removeCookies is not implemented');
};
Store.prototype.removeAllCookies = function(cb) {
throw new Error('removeAllCookies is not implemented');
}
Store.prototype.getAllCookies = function(cb) {
throw new Error('getAllCookies is not implemented (therefore jar cannot be serialized)');
};
// generated by genversion
module.exports = '2.5.0'
{
"_from": "tough-cookie@^2.3.4",
"_id": "tough-cookie@2.5.0",
"_inBundle": false,
"_integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"_location": "/cheerio-httpcli/tough-cookie",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "tough-cookie@^2.3.4",
"name": "tough-cookie",
"escapedName": "tough-cookie",
"rawSpec": "^2.3.4",
"saveSpec": null,
"fetchSpec": "^2.3.4"
},
"_requiredBy": [
"/cheerio-httpcli"
],
"_resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"_shasum": "cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2",
"_spec": "tough-cookie@^2.3.4",
"_where": "D:\\OSS project\\YTMT\\node_modules\\cheerio-httpcli",
"author": {
"name": "Jeremy Stashewsky",
"email": "jstash@gmail.com"
},
"bugs": {
"url": "https://github.com/salesforce/tough-cookie/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Alexander Savin"
},
{
"name": "Ian Livingstone"
},
{
"name": "Ivan Nikulin"
},
{
"name": "Lalit Kapoor"
},
{
"name": "Sam Thompson"
},
{
"name": "Sebastian Mayr"
}
],
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
},
"deprecated": false,
"description": "RFC6265 Cookies and Cookie Jar for node.js",
"devDependencies": {
"async": "^1.4.2",
"genversion": "^2.1.0",
"nyc": "^11.6.0",
"string.prototype.repeat": "^0.2.0",
"vows": "^0.8.2"
},
"engines": {
"node": ">=0.8"
},
"files": [
"lib"
],
"homepage": "https://github.com/salesforce/tough-cookie",
"keywords": [
"HTTP",
"cookie",
"cookies",
"set-cookie",
"cookiejar",
"jar",
"RFC6265",
"RFC2965"
],
"license": "BSD-3-Clause",
"main": "./lib/cookie",
"name": "tough-cookie",
"repository": {
"type": "git",
"url": "git://github.com/salesforce/tough-cookie.git"
},
"scripts": {
"cover": "nyc --reporter=lcov --reporter=html vows test/*_test.js",
"test": "vows test/*_test.js",
"version": "genversion lib/version.js && git add lib/version.js"
},
"version": "2.5.0"
}
{
"_from": "cheerio-httpcli",
"_id": "cheerio-httpcli@0.7.3",
"_inBundle": false,
"_integrity": "sha512-6grjmuzSwjv/8gsDwZcNbrWL5Ce9trbrO4rkqSJC7ci3DmDkePFAmXfMZgokO8xiy9ZvRMT2jxvwTlt6e5cHTA==",
"_location": "/cheerio-httpcli",
"_phantomChildren": {
"css-select": "1.2.0",
"dom-serializer": "0.1.0",
"entities": "1.1.2",
"htmlparser2": "3.10.0",
"lodash.assignin": "4.2.0",
"lodash.bind": "4.2.1",
"lodash.defaults": "4.2.0",
"lodash.filter": "4.6.0",
"lodash.flatten": "4.4.0",
"lodash.foreach": "4.5.0",
"lodash.map": "4.6.0",
"lodash.merge": "4.6.1",
"lodash.pick": "4.4.0",
"lodash.reduce": "4.6.0",
"lodash.reject": "4.6.0",
"lodash.some": "4.6.0",
"psl": "1.1.29",
"punycode": "2.1.1"
},
"_requested": {
"type": "tag",
"registry": true,
"raw": "cheerio-httpcli",
"name": "cheerio-httpcli",
"escapedName": "cheerio-httpcli",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/cheerio-httpcli/-/cheerio-httpcli-0.7.3.tgz",
"_shasum": "a8a00032abeadda909849e5d28bdb500242f11a7",
"_spec": "cheerio-httpcli",
"_where": "D:\\OSS project\\YTMT\\routes",
"author": {
"name": "ktty1220",
"email": "ktty1220@gmail.com"
},
"bugs": {
"url": "https://github.com/ktty1220/cheerio-httpcli/issues"
},
"bundleDependencies": false,
"dependencies": {
"@types/cheerio": "^0.22.7",
"async": "^2.6.0",
"cheerio": "^0.22.0",
"colors": "^1.2.1",
"foreach": "^2.0.5",
"he": "^1.1.1",
"iconv-lite": "^0.4.21",
"jschardet": "^1.6.0",
"object-assign": "^4.1.1",
"os-locale": "^2.1.0",
"prettyjson": "^1.2.1",
"request": "^2.85.0",
"require-uncached": "^1.0.3",
"rsvp": "^4.8.2",
"spawn-sync": "^1.0.15",
"tough-cookie": "^2.3.4",
"type-of": "^2.0.1",
"valid-url": "^1.0.9"
},
"deprecated": false,
"description": "http client module with cheerio & iconv(-lite) & promise",
"devDependencies": {
"@types/node": "^8.0.47",
"constants": "^0.0.2",
"dev-null": "^0.1.1",
"eslint": "^4.19.1",
"espower-loader": "^1.2.2",
"intelli-espower-loader": "^1.0.1",
"isstream": "^0.1.2",
"istanbul": "^0.4.5",
"mocha": "^5.1.1",
"mocha-clean": "^1.0.0",
"node-static": "^0.7.10",
"pkg-ok": "^2.2.0",
"power-assert": "^1.5.0",
"pre-commit": "^1.2.2",
"random-string": "^0.2.0",
"strip-ansi": "^4.0.0",
"yargs": "^11.0.0"
},
"engines": {
"node": ">=4"
},
"homepage": "https://github.com/ktty1220/cheerio-httpcli#readme",
"keywords": [
"cheerio",
"http",
"dom",
"scrape"
],
"license": "MIT",
"main": "index.js",
"name": "cheerio-httpcli",
"pre-commit": [
"lint"
],
"repository": {
"type": "git",
"url": "git://github.com/ktty1220/cheerio-httpcli.git"
},
"scripts": {
"cov": "istanbul cover -x index.js -x testrunner.js testrunner.js -- -R nyan || true",
"cs": "jscs lib test example || true",
"dep": "depcheck --parsers=*.js:es6,*.json:json --ignores=iconv-lite,os-locale,constants,pre-commit,@types/*,espower-loader || true",
"dts": "tsc -p dts",
"lint": "eslint lib test example --ext .js",
"prepublish": "pkg-ok",
"test": "node testrunner.js || true",
"todo": "leasot -S lib/**/**/* test/** example/** || true"
},
"typings": "./index.d.ts",
"version": "0.7.3"
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
No preview for this file type
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.