From f45dc46a42543b53bd775782fc5e81a0af7a8c2f Mon Sep 17 00:00:00 2001 From: Ron S Date: Sun, 3 Oct 2021 15:44:18 -0400 Subject: [PATCH 1/9] test: Added test for prototype pollution (closes #129) --- test/129.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100755 test/129.js diff --git a/test/129.js b/test/129.js new file mode 100755 index 0000000..80790e9 --- /dev/null +++ b/test/129.js @@ -0,0 +1,10 @@ +const { parse } = require('../dist'); + +// see: https://github.com/taoqf/node-html-parser/issues/129 +describe('Prototype pollution', () => { + it('prevents prototype pollution', () => { + const root = parse(''); + should(root.firstChild.attributes.polluted).not.be.ok(); + should(root.firstChild.attributes.hasOwnProperty('proto__')).be.ok(); + }); +}); From 5a2dd0c0ea93b33be7726c54bbcabc807bd0d58d Mon Sep 17 00:00:00 2001 From: Ron S Date: Sun, 3 Oct 2021 16:03:49 -0400 Subject: [PATCH 2/9] fix: blockTextElements incorrectly matching partial tag (detail) (fixes #156 fixes #124) Tags 'premises' is matched as 'pre', 'pstyle' as 'style', etc. --- src/nodes/html.ts | 4 ++-- test/pre.js | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/nodes/html.ts b/src/nodes/html.ts index 07d5f99..1fd1573 100644 --- a/src/nodes/html.ts +++ b/src/nodes/html.ts @@ -974,8 +974,8 @@ export function base_parse(data: string, options = { lowerCaseTagName: false, co pre: true, }; const element_names = Object.keys(elements); - const kBlockTextElements = element_names.map((it) => new RegExp(it, 'i')); - const kIgnoreElements = element_names.filter((it) => elements[it]).map((it) => new RegExp(it, 'i')); + const kBlockTextElements = element_names.map((it) => new RegExp(`^${it}$`, 'i')); + const kIgnoreElements = element_names.filter((it) => elements[it]).map((it) => new RegExp(`^${it}$`, 'i')); function element_should_be_ignore(tag: string) { return kIgnoreElements.some((it) => it.test(tag)); diff --git a/test/pre.js b/test/pre.js index 8ea275d..34a6db1 100644 --- a/test/pre.js +++ b/test/pre.js @@ -1,4 +1,5 @@ const { parse } = require('../dist'); +const { HTMLElement } = require('../dist'); // https://github.com/taoqf/node-html-parser/issues/77 describe('pre tag', function () { @@ -51,4 +52,10 @@ describe('pre tag', function () { const code = pre.firstChild; code.childNodes.length.should.eql(11); }); + // see: https://github.com/taoqf/node-html-parser/issues/156 + it('does not treat pre* tag as pre (partial match)', () => { + const docRoot = parse("Red"); + Object.getPrototypeOf(docRoot.firstChild.firstChild).should.eql(HTMLElement.prototype); + docRoot.firstChild.firstChild.tagName.should.eql('COLOR'); + }) }); From a80c90780e01e705da880b3701aea37c0ec360bc Mon Sep 17 00:00:00 2001 From: Ron S Date: Sun, 3 Oct 2021 17:31:29 -0400 Subject: [PATCH 3/9] fix: Add null to return type for HTMLElement#querySelector (closes #157) --- src/nodes/html.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nodes/html.ts b/src/nodes/html.ts index 1fd1573..c1da816 100644 --- a/src/nodes/html.ts +++ b/src/nodes/html.ts @@ -521,9 +521,9 @@ export default class HTMLElement extends Node { /** * Query CSS Selector to find matching node. * @param {string} selector Simplified CSS selector - * @return {HTMLElement} matching node + * @return {(HTMLElement|null)} matching node */ - public querySelector(selector: string) { + public querySelector(selector: string): HTMLElement | null { return selectOne(selector, this as HTMLElement, { xmlMode: true, adapter: Matcher, From 5a2fc80a31a1e5b8d0bfddd5789e96086ccadad0 Mon Sep 17 00:00:00 2001 From: Ron S Date: Sun, 3 Oct 2021 17:36:03 -0400 Subject: [PATCH 4/9] feat!: Add esm named export support (closes #160 closes #139) Added wrapper for esm over CJS module and removed nonworking separate ESM build (per advice from url below). Note: Essentially a breaking change as `exports` package.json property prevents direct import from files in dist see: https://redfin.engineering/node-modules-at-war-why-commonjs-and-es-modules-cant-get-along-9617135eeca1 --- .eslintignore | 1 + esm/index.js | 11 +++++++++++ esm/package.json | 3 +++ package.json | 13 ++++++++----- test/assets/cjs/index.ts | 4 ++++ test/assets/cjs/package.json | 8 ++++++++ test/assets/cjs/tsconfig.json | 9 +++++++++ test/assets/esm/index.ts | 4 ++++ test/assets/esm/package.json | 8 ++++++++ test/assets/esm/tsconfig.json | 9 +++++++++ test/assets/package.json | 9 +++++++++ test/assets/tsconfig.base.json | 7 +++++++ test/import.js | 20 ++++++++++++++++++++ 13 files changed, 101 insertions(+), 5 deletions(-) create mode 100755 esm/index.js create mode 100755 esm/package.json create mode 100755 test/assets/cjs/index.ts create mode 100755 test/assets/cjs/package.json create mode 100755 test/assets/cjs/tsconfig.json create mode 100755 test/assets/esm/index.ts create mode 100755 test/assets/esm/package.json create mode 100755 test/assets/esm/tsconfig.json create mode 100755 test/assets/package.json create mode 100755 test/assets/tsconfig.base.json create mode 100755 test/import.js diff --git a/.eslintignore b/.eslintignore index 6372315..5dff5c2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ test/ dist/ node_modules/ +esm/ \ No newline at end of file diff --git a/esm/index.js b/esm/index.js new file mode 100755 index 0000000..46edf2a --- /dev/null +++ b/esm/index.js @@ -0,0 +1,11 @@ +import nhp from '../dist/index.js' + +export const CommentNode = nhp.CommentNode; +export const HTMLElement = nhp.HTMLElement; +export const parse = nhp.parse; +export const valid = nhp.valid; +export const Node = nhp.Node; +export const TextNode = nhp.TextNode; +export const NodeType = nhp.NodeType; + +export default nhp; \ No newline at end of file diff --git a/esm/package.json b/esm/package.json new file mode 100755 index 0000000..aead43d --- /dev/null +++ b/esm/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} \ No newline at end of file diff --git a/package.json b/package.json index 23e7e52..caee529 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "version": "4.1.5", "description": "A very fast HTML parser, generating a simplified DOM, with basic element query support.", "main": "dist/index.js", - "module": "dist/esm/index.js", "types": "dist/index.d.ts", "scripts": { "test": "mocha", @@ -11,10 +10,9 @@ "clean": "del-cli ./dist/", "ts:cjs": "tsc -m commonjs", "ts:amd": "tsc -t es5 -m amd -d false --outFile ./dist/main.js", - "ts:esm": "tsc -t es2019 -m esnext -d false --outDir ./dist/esm/", - "build": "npm run lint && npm run clean && npm run ts:cjs && npm run ts:amd && npm run ts:esm", + "build": "npm run lint && npm run clean && npm run ts:cjs && npm run ts:amd", "dev": "tsc -w & mocha -w ./test/*.js", - "pretest": "tsc -m commonjs", + "pretest": "tsc -m commonjs && cd test/assets && yarn install", "release": "yarn build && np", "prepare": "npm run build" }, @@ -60,6 +58,7 @@ "should": "latest", "spec": "latest", "travis-cov": "latest", + "ts-node": "^10.2.1", "typescript": "next" }, "config": { @@ -84,5 +83,9 @@ "url": "https://github.com/taoqf/node-fast-html-parser/issues" }, "homepage": "https://github.com/taoqf/node-fast-html-parser", - "sideEffects": false + "sideEffects": false, + "exports": { + "require": "./dist/index.js", + "import": "./esm/index.js" + } } diff --git a/test/assets/cjs/index.ts b/test/assets/cjs/index.ts new file mode 100755 index 0000000..eaca320 --- /dev/null +++ b/test/assets/cjs/index.ts @@ -0,0 +1,4 @@ +import { parse } from 'node-html-parser' + +const res = parse('parse succeeded'); +console.log(res.firstChild.text); \ No newline at end of file diff --git a/test/assets/cjs/package.json b/test/assets/cjs/package.json new file mode 100755 index 0000000..59937a6 --- /dev/null +++ b/test/assets/cjs/package.json @@ -0,0 +1,8 @@ +{ + "name": "cjs-test", + "private": true, + "type": "commonjs", + "peerDependencies": { + "node-html-parser": "*" + } +} diff --git a/test/assets/cjs/tsconfig.json b/test/assets/cjs/tsconfig.json new file mode 100755 index 0000000..4bfd375 --- /dev/null +++ b/test/assets/cjs/tsconfig.json @@ -0,0 +1,9 @@ +{ + "files": [ "index.ts" ], + "extends": "../tsconfig.base.json", + "compilerOptions": { + "noEmit": true, + "module": "CommonJS", + "moduleResolution": "node" + } +} \ No newline at end of file diff --git a/test/assets/esm/index.ts b/test/assets/esm/index.ts new file mode 100755 index 0000000..eaca320 --- /dev/null +++ b/test/assets/esm/index.ts @@ -0,0 +1,4 @@ +import { parse } from 'node-html-parser' + +const res = parse('parse succeeded'); +console.log(res.firstChild.text); \ No newline at end of file diff --git a/test/assets/esm/package.json b/test/assets/esm/package.json new file mode 100755 index 0000000..d1878b7 --- /dev/null +++ b/test/assets/esm/package.json @@ -0,0 +1,8 @@ +{ + "name": "esm-test", + "private": true, + "type": "module", + "peerDependencies": { + "node-html-parser": "*" + } +} diff --git a/test/assets/esm/tsconfig.json b/test/assets/esm/tsconfig.json new file mode 100755 index 0000000..a979782 --- /dev/null +++ b/test/assets/esm/tsconfig.json @@ -0,0 +1,9 @@ +{ + "files": [ "index.ts" ], + "extends": "../tsconfig.base.json", + "compilerOptions": { + "noEmit": true, + "module": "ESNext", + "moduleResolution": "node" + } +} \ No newline at end of file diff --git a/test/assets/package.json b/test/assets/package.json new file mode 100755 index 0000000..a421db9 --- /dev/null +++ b/test/assets/package.json @@ -0,0 +1,9 @@ +{ + "private": true, + "workspaces": [ + "assets/*" + ], + "dependencies": { + "node-html-parser": "link:../.." + } +} \ No newline at end of file diff --git a/test/assets/tsconfig.base.json b/test/assets/tsconfig.base.json new file mode 100755 index 0000000..c82fd8f --- /dev/null +++ b/test/assets/tsconfig.base.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "skipDefaultLibCheck": true, + "skipLibCheck": true, + "noLib": true + } +} \ No newline at end of file diff --git a/test/import.js b/test/import.js new file mode 100755 index 0000000..754bad4 --- /dev/null +++ b/test/import.js @@ -0,0 +1,20 @@ +const { execSync } = require('child_process'); +const path = require('path'); + +describe(`Module Import`, function () { + this.timeout(20000); + + it(`ESM project can import and use named exports`, () => { + execSync('node --loader ts-node/esm index.ts', { + cwd: path.resolve(__dirname, 'assets/esm'), + stdio: "pipe" + }).toString().should.eql('parse succeeded\n') + }); + + it(`CommonJS project can import and use named exports`, () => { + execSync('node -r ts-node/register index.ts', { + cwd: path.resolve(__dirname, 'assets/cjs'), + stdio: "pipe" + }).toString().should.eql('parse succeeded\n') + }); +}); \ No newline at end of file From f64fc4dff7f369f429880114ab21234829d80f95 Mon Sep 17 00:00:00 2001 From: Ron S Date: Sun, 3 Oct 2021 17:44:40 -0400 Subject: [PATCH 5/9] build(github): Added CI workflows --- .github/workflows/build.yml | 50 +++++++++++++++++++++++++++++++++++ .github/workflows/publish.yml | 47 ++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100755 .github/workflows/build.yml create mode 100755 .github/workflows/publish.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100755 index 0000000..efff59e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,50 @@ +name: Build (CI) + +on: + pull_request: + branches: [ master ] + types: [ opened, synchronize, closed ] + push: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [ 12.x, 14.x, 16.x ] + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Determine Yarn Cache Path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + + - uses: actions/cache@v1 + id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Install Packages + run: yarn install --frozen-lockfile + + - name: Build + run: yarn build + env: + CI: true + + - name: Test + run: yarn run test + env: + CI: true \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100755 index 0000000..51d9005 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,47 @@ +name: Publish + +on: + push: + tags: + - v*.*.* + +jobs: + publish: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Node.js 12.x to publish to npmjs.org + uses: actions/setup-node@v1 + with: + node-version: '12.x' + registry-url: 'https://registry.npmjs.org' + + - name: Install Packages + run: yarn install --frozen-lockfile + + - name: Build + run: yarn build + env: + CI: true + + - name: Test + run: yarn run test + env: + CI: true + + - name: Generate Release Body + run: npx extract-changelog-release > RELEASE_BODY.md + + - name: Publish to NPM + run: yarn publish --non-interactive + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Create GitHub Release + uses: ncipollo/release-action@v1 + with: + bodyFile: "RELEASE_BODY.md" + token: ${{ secrets.GITHUB_TOKEN }} From e6266864713d2a9eaa1b191e5906a64496084492 Mon Sep 17 00:00:00 2001 From: Ron S Date: Sun, 3 Oct 2021 17:57:48 -0400 Subject: [PATCH 6/9] build: Dropped travis config & replaced badge with GH actions --- .travis.yml | 3 --- README.md | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d6b8187..0000000 --- a/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: node_js -node_js: - - node diff --git a/README.md b/README.md index be4f385..9835c71 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Fast HTML Parser [![NPM version](https://badge.fury.io/js/node-html-parser.png)](http://badge.fury.io/js/node-html-parser) [![Build Status](https://travis-ci.org/taoqf/node-html-parser.svg?branch=master)](https://travis-ci.org/taoqf/node-html-parser) +# Fast HTML Parser [![NPM version](https://badge.fury.io/js/node-html-parser.png)](http://badge.fury.io/js/node-html-parser) [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Ftaoqf%2Fnode-html-parser%2Fbadge%3Fref%3Dmaster&style=flat)](https://actions-badge.atrox.dev/taoqf/node-html-parser/goto?ref=master) Fast HTML Parser is a _very fast_ HTML parser. Which will generate a simplified DOM tree, with element query support. @@ -78,7 +78,7 @@ Parse given data, and return root of the generated DOM. ```js { lowerCaseTagName: false, // convert tag name to lower case (hurt performance heavily) - comment: false // retrieve comments (hurt performance slightly) + comment: false, // retrieve comments (hurt performance slightly) blockTextElements: { script: true, // keep text content when parsing noscript: true, // keep text content when parsing From 75280a8d9640893a4b1b9c999a10feb73ed6b234 Mon Sep 17 00:00:00 2001 From: Ron S Date: Sun, 3 Oct 2021 18:42:15 -0400 Subject: [PATCH 7/9] build(deps): Added standard-version to devDeps --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index caee529..aae29a8 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "parse5": "^6.0.1", "should": "latest", "spec": "latest", + "standard-version": "^9.3.1", "travis-cov": "latest", "ts-node": "^10.2.1", "typescript": "next" From f41f77c22e0c8d433fde2e1ccc0e86c3ede5477b Mon Sep 17 00:00:00 2001 From: Ron S Date: Sat, 9 Oct 2021 22:35:38 -0400 Subject: [PATCH 8/9] feat: Improved parsing performance + matching (closes #164) --- src/nodes/html.ts | 186 ++++++++++++---------------------------------- 1 file changed, 48 insertions(+), 138 deletions(-) diff --git a/src/nodes/html.ts b/src/nodes/html.ts index c1da816..3596bf4 100644 --- a/src/nodes/html.ts +++ b/src/nodes/html.ts @@ -7,7 +7,7 @@ import Matcher from '../matcher'; import arr_back from '../back'; import CommentNode from './comment'; -// const { decode } = he; +const voidTags = new Set([ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr' ]); type IRawTagName = | 'LI' @@ -154,7 +154,7 @@ export default class HTMLElement extends Node { */ private quoteAttribute(attr: string) { - if (attr === null) { + if (attr == null) { return 'null'; } @@ -241,6 +241,11 @@ export default class HTMLElement extends Node { public get localName() { return this.rawTagName.toLowerCase(); } + + public get isVoidElement() { + return voidTags.has(this.localName); + } + /** * Get escpaed (as-it) text value of current node and its children. * @return {string} text content @@ -313,14 +318,8 @@ export default class HTMLElement extends Node { public toString() { const tag = this.rawTagName; if (tag) { - // const void_tags = new Set('area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr'.split('|')); - // const is_void = void_tags.has(tag); - const is_void = /^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/i.test(tag); const attrs = this.rawAttrs ? ` ${this.rawAttrs}` : ''; - if (is_void) { - return `<${tag}${attrs}>`; - } - return `<${tag}${attrs}>${this.innerHTML}`; + return this.isVoidElement ? `<${tag}${attrs}>` : `<${tag}${attrs}>${this.innerHTML}`; } return this.innerHTML; } @@ -458,64 +457,6 @@ export default class HTMLElement extends Node { xmlMode: true, adapter: Matcher, }); - - // let matcher: Matcher; - // if (selector instanceof Matcher) { - // matcher = selector; - // matcher.reset(); - // } else { - // if (selector.includes(',')) { - // const selectors = selector.split(','); - // return Array.from(selectors.reduce((pre, cur) => { - // const result = this.querySelectorAll(cur.trim()); - // return result.reduce((p, c) => { - // return p.add(c); - // }, pre); - // }, new Set())); - // } - // matcher = new Matcher(selector); - // } - // interface IStack { - // 0: Node; // node - // 1: number; // children - // 2: boolean; // found flag - // } - // const stack = [] as IStack[]; - // return this.childNodes.reduce((res, cur) => { - // stack.push([cur, 0, false]); - // while (stack.length) { - // const state = arr_back(stack); // get last element - // const el = state[0]; - // if (state[1] === 0) { - // // Seen for first time. - // if (el.nodeType !== NodeType.ELEMENT_NODE) { - // stack.pop(); - // continue; - // } - // const html_el = el as HTMLElement; - // state[2] = matcher.advance(html_el); - // if (state[2]) { - // if (matcher.matched) { - // res.push(html_el); - // res.push(...(html_el.querySelectorAll(selector))); - // // no need to go further. - // matcher.rewind(); - // stack.pop(); - // continue; - // } - // } - // } - // if (state[1] < el.childNodes.length) { - // stack.push([el.childNodes[state[1]++], 0, false]); - // } else { - // if (state[2]) { - // matcher.rewind(); - // } - // stack.pop(); - // } - // } - // return res; - // }, [] as HTMLElement[]); } /** @@ -528,43 +469,6 @@ export default class HTMLElement extends Node { xmlMode: true, adapter: Matcher, }); - // let matcher: Matcher; - // if (selector instanceof Matcher) { - // matcher = selector; - // matcher.reset(); - // } else { - // matcher = new Matcher(selector); - // } - // const stack = [] as { 0: Node; 1: 0 | 1; 2: boolean }[]; - // for (const node of this.childNodes) { - // stack.push([node, 0, false]); - // while (stack.length) { - // const state = arr_back(stack); - // const el = state[0]; - // if (state[1] === 0) { - // // Seen for first time. - // if (el.nodeType !== NodeType.ELEMENT_NODE) { - // stack.pop(); - // continue; - // } - // state[2] = matcher.advance(el as HTMLElement); - // if (state[2]) { - // if (matcher.matched) { - // return el as HTMLElement; - // } - // } - // } - // if (state[1] < el.childNodes.length) { - // stack.push([el.childNodes[state[1]++], 0, false]); - // } else { - // if (state[2]) { - // matcher.rewind(); - // } - // stack.pop(); - // } - // } - // } - // return null; } /** @@ -682,7 +586,7 @@ export default class HTMLElement extends Node { } /** - * Get escaped (as-it) attributes + * Get escaped (as-is) attributes * @return {Object} parsed attributes */ public get rawAttributes() { @@ -691,10 +595,13 @@ export default class HTMLElement extends Node { } const attrs = {} as RawAttributes; if (this.rawAttrs) { - const re = /([a-z()#][a-z0-9-_:()#]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+)))?/gi; + const re = /([a-zA-Z()#][a-zA-Z0-9-_:()#]*)(?:\s*=\s*((?:'[^']*')|(?:"[^"]*")|\S+))?/g; let match: RegExpExecArray; while ((match = re.exec(this.rawAttrs))) { - attrs[match[1]] = match[2] || match[3] || match[4] || null; + const key = match[1]; + let val = match[2] || null; + if (val && (val[0] === `'` || val[0] === `"`)) val = val.slice(1, val.length - 1); + attrs[key] = val; } } this._rawAttrs = attrs; @@ -873,12 +780,8 @@ export default class HTMLElement extends Node { } // https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name -const kMarkupPattern = /)-->|<(\/?)([a-z][-.:0-9_a-z]*)\s*((?=[/>]*?)|(?:.*?[\s\d/'"])|(?:.*?[\w]))(\/?)>/gi; -// <(?[^\s]*)(.*)>(.*)> -// <([a-z][-.:0-9_a-z]*)\s*\/> -// <(area|base|br|col|hr|img|input|link|meta|source)\s*(.*)\/?> -// <(area|base|br|col|hr|img|input|link|meta|source)\s*(.*)\/?>|<(?[^\s]*)(.*)>(.*)> -const kAttributePattern = /(^|\s)(id|class)\s*=\s*("([^"]*)"|'([^']*)'|(\S+))/gi; +const kMarkupPattern = /|<(\/?)([a-zA-Z][-.:0-9_a-zA-Z]*)((?:\s+[^>]*?(?:(?:'[^']*')|(?:"[^"]*"))?)*)\s*(\/?)>/g; +const kAttributePattern = /(?:^|\s)(id|class)\s*=\s*((?:'[^']*')|(?:"[^"]*")|\S+)/gi; const kSelfClosingElements = { area: true, AREA: true, @@ -995,17 +898,22 @@ export function base_parse(data: string, options = { lowerCaseTagName: false, co let match: RegExpExecArray; // https://github.com/taoqf/node-html-parser/issues/38 data = `<${frameflag}>${data}`; + const { lowerCaseTagName } = options; const dataEndPos = data.length - (frameflag.length + 2); const frameFlagOffset = frameflag.length + 2; while ((match = kMarkupPattern.exec(data))) { - const tagStartPos = kMarkupPattern.lastIndex - match[0].length; + // Note: Object destructuring here consistently tests as higher performance than array destructuring + // eslint-disable-next-line prefer-const + let { 0: matchText, 1: leadingSlash, 2: tagName, 3: attributes, 4: closingSlash } = match; + const matchLength = matchText.length; + const tagStartPos = kMarkupPattern.lastIndex - matchLength; const tagEndPos = kMarkupPattern.lastIndex; // Add TextNode if content if (lastTextPos > -1) { - if (lastTextPos + match[0].length < tagEndPos) { + if (lastTextPos + matchLength < tagEndPos) { const text = data.substring(lastTextPos, tagStartPos); currentParent.appendChild(new TextNode(text, currentParent, createRange(lastTextPos, tagStartPos))); } @@ -1015,10 +923,10 @@ export function base_parse(data: string, options = { lowerCaseTagName: false, co // https://github.com/taoqf/node-html-parser/issues/38 // Skip frameflag node - if (match[2] === frameflag) continue; + if (tagName === frameflag) continue; // Handle comments - if (match[0][1] === '!') { + if (matchText[1] === '!') { if (options.comment) { // Only keep what is in between const text = data.substring(tagStartPos + 4, tagEndPos - 3); @@ -1029,27 +937,29 @@ export function base_parse(data: string, options = { lowerCaseTagName: false, co /* -- Handle tag matching -- */ // Fix tag casing if necessary - if (options.lowerCaseTagName) match[2] = match[2].toLowerCase(); + if (lowerCaseTagName) tagName = tagName.toLowerCase(); // Handle opening tags (ie. not ) - if (!match[1]) { + if (!leadingSlash) { /* Populate attributes */ const attrs = {}; - for (let attMatch; (attMatch = kAttributePattern.exec(match[3])); ) { - attrs[attMatch[2].toLowerCase()] = attMatch[4] || attMatch[5] || attMatch[6]; + for (let attMatch; (attMatch = kAttributePattern.exec(attributes)); ) { + const { 1: key, 2: val } = attMatch; + const isQuoted = val[0] === `'` || val[0] === `"`; + attrs[key.toLowerCase()] = isQuoted ? val.slice(1, val.length - 1) : val; } - const tagName = currentParent.rawTagName as IRawTagName; + const parentTagName = currentParent.rawTagName as IRawTagName; - if (!match[4] && kElementsClosedByOpening[tagName]) { - if (kElementsClosedByOpening[tagName][match[2]]) { + if (!closingSlash && kElementsClosedByOpening[parentTagName]) { + if (kElementsClosedByOpening[parentTagName][tagName]) { stack.pop(); currentParent = arr_back(stack); } } // Prevent nested A tags by terminating the last A and starting a new one : see issue #144 - if (match[2] === 'a' || match[2] === 'A') { + if (tagName === 'a' || tagName === 'A') { if (noNestedTagIndex !== undefined) { stack.splice(noNestedTagIndex); currentParent = arr_back(stack); @@ -1058,23 +968,23 @@ export function base_parse(data: string, options = { lowerCaseTagName: false, co } const tagEndPos = kMarkupPattern.lastIndex; - const tagStartPos = tagEndPos - match[0].length; + const tagStartPos = tagEndPos - matchLength; currentParent = currentParent.appendChild( // Initialize range (end position updated later for closed tags) - new HTMLElement(match[2], attrs, match[3], null, createRange(tagStartPos, tagEndPos)) + new HTMLElement(tagName, attrs, attributes.slice(1), null, createRange(tagStartPos, tagEndPos)) ); stack.push(currentParent); - if (is_block_text_element(match[2])) { + if (is_block_text_element(tagName)) { // Find closing tag - const closeMarkup = ``; - const closeIndex = options.lowerCaseTagName + const closeMarkup = ``; + const closeIndex = lowerCaseTagName ? data.toLocaleLowerCase().indexOf(closeMarkup, kMarkupPattern.lastIndex) : data.indexOf(closeMarkup, kMarkupPattern.lastIndex); const textEndPos = closeIndex === -1 ? dataEndPos : closeIndex; - if (element_should_be_ignore(match[2])) { + if (element_should_be_ignore(tagName)) { const text = data.substring(tagEndPos, textEndPos); if (text.length > 0 && /\S/.test(text)) { currentParent.appendChild(new TextNode(text, currentParent, createRange(tagEndPos, textEndPos))); @@ -1086,26 +996,26 @@ export function base_parse(data: string, options = { lowerCaseTagName: false, co } else { lastTextPos = kMarkupPattern.lastIndex = closeIndex + closeMarkup.length; // Cause to be treated as self-closing, because no close found - match[1] = 'true'; + leadingSlash = '/'; } } } // Handle closing tags or self-closed elements (ie or
) - if (match[1] || match[4] || kSelfClosingElements[match[2]]) { + if (leadingSlash || closingSlash || kSelfClosingElements[tagName]) { while (true) { - if (match[2] === 'a' || match[2] === 'A') noNestedTagIndex = undefined; - if (currentParent.rawTagName === match[2]) { + if (tagName === 'a' || tagName === 'A') noNestedTagIndex = undefined; + if (currentParent.rawTagName === tagName) { // Update range end for closed tag (<[number, number]>currentParent.range)[1] = createRange(-1, Math.max(lastTextPos, tagEndPos))[1]; stack.pop(); currentParent = arr_back(stack); break; } else { - const tagName = currentParent.tagName as 'LI' | 'A' | 'B' | 'I' | 'P' | 'TD' | 'TH'; + const parentTagName = currentParent.tagName as 'LI' | 'A' | 'B' | 'I' | 'P' | 'TD' | 'TH'; // Trying to close current tag, and move on - if (kElementsClosedByClosing[tagName]) { - if (kElementsClosedByClosing[tagName][match[2]]) { + if (kElementsClosedByClosing[parentTagName]) { + if (kElementsClosedByClosing[parentTagName][tagName]) { stack.pop(); currentParent = arr_back(stack); continue; From 2c23eec2248149225c2223088e468c204abf9baf Mon Sep 17 00:00:00 2001 From: Ron S Date: Sat, 9 Oct 2021 22:53:16 -0400 Subject: [PATCH 9/9] refactor: Organized tests + added ability to test src or dist --- .mocharc.yaml | 2 +- package.json | 24 +- test/assets/cjs/index.ts | 4 - test/assets/esm/index.ts | 4 - test/{ => assets}/html/ffmpeg.html | 1436 ++++++++--------- test/{ => assets}/html/gmail.html | 788 ++++----- test/{ => assets}/html/google.html | 16 +- .../html/hillcrestpartyrentals.html | 1174 +++++++------- test/{ => assets}/html/incomplete-script | 0 test/{ => assets}/html/nice.html | 0 test/{ => assets}/html/tables.html | 0 ...picentrk.ua_shop_kirpich-ogneupornyy_.html | 8 +- test/assets/package.json | 9 - test/assets/packages/cjs/index.ts | 4 + test/assets/{ => packages}/cjs/package.json | 1 + test/assets/{ => packages}/cjs/tsconfig.json | 0 test/assets/packages/esm/index.ts | 4 + test/assets/{ => packages}/esm/package.json | 1 + test/assets/{ => packages}/esm/tsconfig.json | 0 test/assets/{ => packages}/tsconfig.base.json | 0 test/assets/packages/wrapper/index.d.ts | 1 + test/assets/packages/wrapper/index.js | 8 + test/assets/packages/wrapper/package.json | 8 + test/{ => benchmark}/compare-cheerio.mjs | 0 test/{ => benchmark}/compare-high5.mjs | 0 test/{ => benchmark}/compare-htmlparser.mjs | 0 test/{ => benchmark}/compare-htmlparser2.mjs | 0 test/benchmark/compare-nhp-last.mjs | 11 + .../compare-node-html-parser.mjs | 2 +- test/{ => benchmark}/compare-parse5.mjs | 0 test/{ => benchmark}/compare.mjs | 2 + test/package.json | 11 + test/{ => tests}/caseinsensitive.js | 2 +- test/{ => tests}/emptyattribute.js | 2 +- test/{ => tests}/html.js | 13 +- test/{ => tests}/import.js | 4 +- test/{ => tests/issues}/100.js | 2 +- test/{ => tests/issues}/106.js | 4 +- test/{ => tests/issues}/109.js | 2 +- test/{ => tests/issues}/112.js | 2 +- test/{ => tests/issues}/115.js | 2 +- test/{ => tests/issues}/119.js | 2 +- test/{ => tests/issues}/129.js | 2 +- test/{ => tests/issues}/135.js | 2 +- test/{ => tests/issues}/136.js | 2 +- test/{ => tests/issues}/144.js | 2 +- test/{ => tests/issues}/145.js | 2 +- test/{ => tests/issues}/152.js | 2 +- test/{ => tests/issues}/28,59,74.js | 2 +- test/{ => tests/issues}/41.js | 2 +- test/{ => tests/issues}/42.js | 2 +- test/{ => tests/issues}/48.js | 2 +- test/{ => tests/issues}/51.js | 2 +- test/{ => tests/issues}/69.js | 76 +- test/{ => tests/issues}/70.js | 2 +- test/{ => tests/issues}/84.js | 2 +- test/{ => tests/issues}/85.js | 2 +- test/{ => tests/issues}/95.js | 2 +- test/{ => tests/issues}/98.js | 2 +- test/{ => tests}/node-ranges.js | 2 +- test/{ => tests}/parse.js | 2 +- test/{ => tests}/pre.js | 4 +- test/{ => tests}/quoteattributes.js | 2 +- test/{ => tests}/replacewith.js | 2 +- test/{ => tests}/valid.js | 14 +- 65 files changed, 1861 insertions(+), 1826 deletions(-) delete mode 100755 test/assets/cjs/index.ts delete mode 100755 test/assets/esm/index.ts rename test/{ => assets}/html/ffmpeg.html (98%) rename test/{ => assets}/html/gmail.html (99%) rename test/{ => assets}/html/google.html (99%) rename test/{ => assets}/html/hillcrestpartyrentals.html (98%) rename test/{ => assets}/html/incomplete-script (100%) rename test/{ => assets}/html/nice.html (100%) rename test/{ => assets}/html/tables.html (100%) rename test/{ => assets}/html/view-source_https___epicentrk.ua_shop_kirpich-ogneupornyy_.html (99%) delete mode 100755 test/assets/package.json create mode 100755 test/assets/packages/cjs/index.ts rename test/assets/{ => packages}/cjs/package.json (84%) rename test/assets/{ => packages}/cjs/tsconfig.json (100%) create mode 100755 test/assets/packages/esm/index.ts rename test/assets/{ => packages}/esm/package.json (84%) rename test/assets/{ => packages}/esm/tsconfig.json (100%) rename test/assets/{ => packages}/tsconfig.base.json (100%) create mode 100755 test/assets/packages/wrapper/index.d.ts create mode 100755 test/assets/packages/wrapper/index.js create mode 100755 test/assets/packages/wrapper/package.json rename test/{ => benchmark}/compare-cheerio.mjs (100%) rename test/{ => benchmark}/compare-high5.mjs (100%) rename test/{ => benchmark}/compare-htmlparser.mjs (100%) rename test/{ => benchmark}/compare-htmlparser2.mjs (100%) create mode 100755 test/benchmark/compare-nhp-last.mjs rename test/{ => benchmark}/compare-node-html-parser.mjs (89%) rename test/{ => benchmark}/compare-parse5.mjs (100%) rename test/{ => benchmark}/compare.mjs (72%) create mode 100755 test/package.json rename test/{ => tests}/caseinsensitive.js (93%) rename test/{ => tests}/emptyattribute.js (95%) rename test/{ => tests}/html.js (97%) rename test/{ => tests}/import.js (80%) rename test/{ => tests/issues}/100.js (93%) rename test/{ => tests/issues}/106.js (83%) rename test/{ => tests/issues}/109.js (89%) rename test/{ => tests/issues}/112.js (95%) rename test/{ => tests/issues}/115.js (82%) rename test/{ => tests/issues}/119.js (97%) rename test/{ => tests/issues}/129.js (88%) rename test/{ => tests/issues}/135.js (96%) rename test/{ => tests/issues}/136.js (93%) rename test/{ => tests/issues}/144.js (95%) rename test/{ => tests/issues}/145.js (90%) rename test/{ => tests/issues}/152.js (91%) rename test/{ => tests/issues}/28,59,74.js (98%) rename test/{ => tests/issues}/41.js (94%) rename test/{ => tests/issues}/42.js (87%) rename test/{ => tests/issues}/48.js (90%) rename test/{ => tests/issues}/51.js (92%) rename test/{ => tests/issues}/69.js (97%) rename test/{ => tests/issues}/70.js (94%) rename test/{ => tests/issues}/84.js (98%) rename test/{ => tests/issues}/85.js (96%) rename test/{ => tests/issues}/95.js (97%) rename test/{ => tests/issues}/98.js (96%) rename test/{ => tests}/node-ranges.js (96%) rename test/{ => tests}/parse.js (96%) rename test/{ => tests}/pre.js (96%) rename test/{ => tests}/quoteattributes.js (95%) rename test/{ => tests}/replacewith.js (98%) rename test/{ => tests}/valid.js (75%) diff --git a/.mocharc.yaml b/.mocharc.yaml index efb9b14..9a6401d 100644 --- a/.mocharc.yaml +++ b/.mocharc.yaml @@ -1 +1 @@ -require: blanket,should,spec +require: blanket,should,spec,"ts-node/register" \ No newline at end of file diff --git a/package.json b/package.json index aae29a8..bc4f402 100644 --- a/package.json +++ b/package.json @@ -5,16 +5,21 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "test": "mocha", + "compile": "tsc", + "build": "npm run lint && npm run clean && npm run compile:cjs && npm run compile:amd", + "compile:cjs": "tsc -m commonjs", + "compile:amd": "tsc -t es5 -m amd -d false --outFile ./dist/main.js", + "---------------": "", + "test": "mocha ./test/tests/**/*.js", + "test:src": "cross-env TEST_TARGET=src mocha ./test/tests", + "test:dist": "cross-env TEST_TARGET=dist mocha ./test/tests", + "benchmark": "node ./test/benchmark/compare.mjs", + "--------------- ": "", "lint": "eslint ./src/*.ts ./src/**/*.ts", "clean": "del-cli ./dist/", - "ts:cjs": "tsc -m commonjs", - "ts:amd": "tsc -t es5 -m amd -d false --outFile ./dist/main.js", - "build": "npm run lint && npm run clean && npm run ts:cjs && npm run ts:amd", - "dev": "tsc -w & mocha -w ./test/*.js", - "pretest": "tsc -m commonjs && cd test/assets && yarn install", - "release": "yarn build && np", - "prepare": "npm run build" + "--------------- ": "", + "posttest": "yarn run benchmark", + "prepare": "cd test && yarn install" }, "keywords": [ "parser", @@ -60,7 +65,8 @@ "standard-version": "^9.3.1", "travis-cov": "latest", "ts-node": "^10.2.1", - "typescript": "next" + "typescript": "latest", + "cross-env": "^7.0.3" }, "config": { "blanket": { diff --git a/test/assets/cjs/index.ts b/test/assets/cjs/index.ts deleted file mode 100755 index eaca320..0000000 --- a/test/assets/cjs/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { parse } from 'node-html-parser' - -const res = parse('parse succeeded'); -console.log(res.firstChild.text); \ No newline at end of file diff --git a/test/assets/esm/index.ts b/test/assets/esm/index.ts deleted file mode 100755 index eaca320..0000000 --- a/test/assets/esm/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { parse } from 'node-html-parser' - -const res = parse('parse succeeded'); -console.log(res.firstChild.text); \ No newline at end of file diff --git a/test/html/ffmpeg.html b/test/assets/html/ffmpeg.html similarity index 98% rename from test/html/ffmpeg.html rename to test/assets/html/ffmpeg.html index 748a64b..8e789cd 100644 --- a/test/html/ffmpeg.html +++ b/test/assets/html/ffmpeg.html @@ -1,719 +1,719 @@ - - - - - StreamingGuide – FFmpeg - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
-
- -
-

Streaming

-

-

- -

-

-

- FFmpeg can basically stream through one of two ways: It either streams to a some "other server", which re-streams - for it to multiple clients, or it can stream via UDP/TCP directly to some single destination receiver, or - alternatively directly to a multicast destination. Theoretically you might be able to send to multiple receivers - via Creating Multiple Outputs? but there is no built-in full blown server. -

-

- Servers which can receive from FFmpeg (to restream to multiple clients) include ffserver - (linux only, though with cygwin it might work on windows), or Wowza Media Server, or Flash Media Server, Red5, or various others. Even VLC can pick up the stream from ffmpeg, then redistribute it, acting as a server. - Since FFmpeg is at times more efficient than VLC at doing the raw encoding, this can be a useful option compared - to doing both transcoding and streaming in VLC. Nginx also has an rtmp redistribution plugin, as does apache etc. and there is probably more out there for apache, etc.. You can also live - stream to online redistribution servers like own3d.tv or justin.tv (for instance streaming your desktop). Also - any rtmp - server will most likely work to receive streams from FFmpeg (these typically require you to setup a running - instance on a server). -

-

The -re flag

-

- The FFmpeg's "-re" flag means to "Read input at native frame rate. Mainly used to simulate a grab device." i.e. - if you wanted to stream a video file, then you would want to use this, otherwise it might stream it too fast (it - attempts to stream at line speed by default). My guess is you typically don't want to use this flag when - streaming from a live device, ever. -

-

Setting

-

- Here is what another person once did for broadcast: -

-
ffmpeg -f dshow -i video="Virtual-Camera" -preset ultrafast -vcodec libx264 -tune zerolatency -b 900k -f mpegts udp://10.1.0.102:1234
-
-

- And here is what another person did: -

-
ffmpeg -f dshow -i video="screen-capture-recorder":audio="Stereo Mix (IDT High Definition" \
--vcodec libx264 -preset ultrafast -tune zerolatency -r 10 -async 1 -acodec libmp3lame -ab 24k -ar 22050 -bsf:v h264_mp4toannexb \
--maxrate 750k -bufsize 3000k -f mpegts udp://192.168.5.215:48550
-
-

- NB that they also (for directshow devices) had to adjust the rtbufsize in that example. -

-

- You can see a description of what some of these means, (for example bufsize, bitrate settings) in the Encode/H.264. -

-

- Here's how one guy broadcast a live stream (in this instance a Capture/Desktop#Windows? - screen capture device): -

-
$ ffmpeg -y -loglevel warning -f dshow -i video="screen-capture-recorder" -vf crop=690:388:136:0 -r 30 -s 962x388 -threads 2 -vcodec libx264 -vpre baseline -vpre my_ffpreset -f flv rtmp:///live/myStream.sdp
-
-

- with a custom FFmpeg preset (libx264-my_ffpreset.ffpreset) in this case: -

-
coder=1
-flags2=+wpred+dct8x8
-level=31
-maxrate=1200000
-bufsize=200000
-wpredp=0
-g=60
-refs=1
-subq=3
-trellis=0
-bf=0
-rc_lookahead=0
-
-

- Here is how you stream to twitch.tv or similar services (rtmp protocol), using ffmpeg 1.0 or ffmpeg-git (tested - on 2012-11-12), this is also for pulseaudio users: - Example 1, no sound: -

-
ffmpeg -f x11grab -s 1920x1200 -framerate 15 -i :0.0 -c:v libx264 -preset fast -pix_fmt yuv420p -s 1280x800 -threads 0 -f flv "rtmp://live.twitch.tv/app/live_********_******************************"
-
-

- Example 2, first screen (on dual screen setup, or if on a single screen): -

-
ffmpeg -f x11grab -s 1920x1200 -framerate 15 -i :0.0 -f pulse -ac 2 -i default -c:v libx264 -preset fast -pix_fmt yuv420p -s 1280x800 -c:a aac -b:a 160k -ar 44100 -threads 0 -f flv "rtmp://live.twitch.tv/app/live_********_******************************"
-
-

- Example 3, second screen (on dual screen setup): -

-
ffmpeg -f x11grab -s 1920x1200 -framerate 15 -i :0.0+1920,0 -f pulse -ac 2 -i default -c:v libx264 -preset fast -pix_fmt yuv420p -s 1280x800 -c:a aac -b:a 160k -ar 44100 -threads 0 -f flv "rtmp://live.twitch.tv/app/live_********_******************************"
-
-

Latency

-

- You may be able to decrease initial "startup" latency by specifing that I-frames come "more frequently" (or - basically always, in the case of x264's zerolatency setting), - though this can increase frame size and decrease quality, see here for some more background. Basically for typical x264 streams, it inserts an - I-frame every 250 frames. This means that new clients that connect to the stream may have to wait up to 250 - frames before they can start receiving the stream (or start with old data). So increasing I-frame frequency - (makes the stream larger, but might decrease latency). For real time captures you can also decrease latency of - audio in windows dshow by using the dshow audio_buffer_size setting. You can also decrease latency by tuning any broadcast server you are using to - minimize latency, and finally by tuning the client that receives the stream to not "cache" any incoming data, - which, if it does, increases latency. -

-

- Sometimes audio codecs also introduce some latency of their own. You may be able to get less latency by using - speex, for example, or opus, in place of libmp3lame. -

-

- You will also want to try and decrease latency at the server side, for instance wowza hints. -

-

- Also setting -probesize and -analyzeduration to low values may help your stream start up more quickly (it uses - these to scan for "streams" in certain muxers, like ts, where some can appears "later", and also to estimate the - duration, which, for live streams, the latter you don't need anyway). This should be unneeded by dshow input. -

-

- Reducing cacheing at the client side can help, too, for instance mplayer has a "-nocache" option, other players - may similarly has some type of pre-playback buffering that is occurring. (The reality is mplayers -benchmark - option has much more effect). -

-

- Using an encoder that encodes more quickly (or possibly even raw format?) might reduce latency. -

-

- You might get less latency by using one of the "point to point" protocols described in this document, at well. - You'd lose the benefit of having a server, of course. -

-

- NB that a client when it initially starts up may have to wait until the next i-frame to be able to start - receiving the stream (ex: if receiving UDP), so the GOP setting (-g) i-frame interval will have an effect on how - quickly they can start streaming (i.e. they must receive an i-frame before they start). Setting it to a lower - number means it will use more bandwidth, but clients will be able to connect more quickly (the default for x264 - is 250--so for 30 fps that means an i-frame only once every 10 seconds or so). So it's a tradeoff if you adjust - it. This does not affect actual latency (just connection time) since the client can still display frames very - quickly after and once it has received its first i-frame. Also if you're using a lossy transport, like UDP, then - an i-frame represents "the next change it will have to repair the stream" if there are problems from packet loss. -

-

- You can also (if capturing from a live source) increase frame rate to decrease latency (which affects throughput - and also i-frame frequency, of course). This obvious sends packets more frequently, so (with 5 fps, you introduce - at least a 0.2s latency, with 10 fps 0.1s latency) but it also helps clients to fill their internal buffers, etc. - more quickly. -

-

- Note also that using dshow's "rtbufsize" has the unfortunate side effect of sometimes allowing frames to "buffer" - while it is waiting on encoding of previous frames, or waiting for them to be sent over the wire. This means that - if you use a higher value at all, it can cause/introduce added latency if it ever gets used (but if used, can be - helpful for other aspects, like transmitting more frames overall consistently etc. so YMMV). Almost certainly if - you set a very large value for this, and then see the "buffer XX% full! dropping!" message, you are introducing - latency. -

-

- There is also apparently an option -fflags nobuffer which might possibly help, usually for receiving streams reduce - latency. -

-
-

- mpv udp://236.0.0.1:2000 --no-cache --untimed --no-demuxer-thread --video-sync=audio --vd-lavc-threads=1 -

-

- may be useful. -

-

Testing latency

-

- By default, ffplay (as a receiver for testing latency) introduces significant latency of its own, so if you use - it for testing (see troubleshooting section) it may not reflect latency accurately. FFplay introduces some video - artifacts, also, see notes for it in "troubleshooting streaming" section Also some settings mentioned above like - "probesize" might help it start more quickly. Also useful: -

-
ffplay -probesize 32 -sync ext INPUT
-
-

- (the sync part tells it to try and stay realtime). -

-

- Useful is mplayer with its -benchmark for testing latency (-noaudio and/or -nocache *might* be useful, though I - haven't found -nocache to provide any latency benefit it might work for you). -

-

- Using the SDL out option while using FFmpeg to receive the stream might also help to view frames with less - client side latency: "ffmpeg ... -f sdl <input_here> "window title"" (this works especially well with - -fflags nobuffer, though in my tests is still barely more latency than using mplayer -benchmark always). This - doesn't have a "drop frames if you run out of cpu" option so it can get quite far behind at times (introduce - more latency variably). -

-

- Another possibly useful receiving client is "omxplayer -live" -

-

- See also "Point to point streaming" section esp. if you use UDP etc. -

-

See also

-

- Here is a - list of some other ideas to try (using VBR may help, etc.) -

-

CPU usage / File size - ¶

-

- In general, the more CPU you use to compress, the better the output image will be, or the smaller of a file the - output will be for the same quality. -

-

- Basically, the easiest way to save cpu is to decrease the input frame rate/size, or decrease the output frame - rate/size. -

-

- Also you could (if capturing from live source), instruct the live source to feed a "smaller stream" (ex: webcam - stream 640x480 instead of 1024x1280), or you could set a lower output "output quality" setting (q level), or - specify a lower output desired bitrate (see Encode/H.264 for a - background). Or try a different output codec, or specify new parameters to your codec (for instance, a different - profile or preset for libx264). Specifying $ -threads 0 instructs - the encoder to use all available cpu cores, which is the default. You could also resize the input first, before - transcoding it, so it's not as large. Applying a smoothing filter like hqdn3d before encoding might help it - compress better, yielding smaller files. -

-

- You can also set a lower output frame rate to of course decrease cpu usage. -

-

- If you're able to live capture in a pixel format that matches your output format (ex: yuv420p output from a - webcam, instead of mjpeg), that might help with cpu usage, since it avoids an extra conversion. Using 64-bit - instead of 32-bit executables (for those that have that choice) can result in a slight speedup. If you're able - to use -vcodec copy that, of course, uses the least cpu of all options since it just sends the frames verbatim - to the output. -

-

- Sometimes you can change the "pixel formats" somehow, like using rgb16 instead of rgb24, to save time/space (or - yuv420 instead of yuv444 or the like, since 420 stores less information it may compress better and use less - bandwidth). This may not affect latency. -

-

Streaming a simple RTP audio stream from FFmpeg

-

- FFmpeg can stream a single stream using the RTP protocol. In order to avoid buffering problems on the other hand, the streaming - should be done through the -re option, which means that the stream will be streamed in real-time (i.e. it slows - it down to simulate a live streaming source. -

-

- For example the following command will generate a signal, and will stream it to the port 1234 on localhost: -

-
ffmpeg -re -f lavfi -i aevalsrc="sin(400*2*PI*t)" -ar 8000 -f mulaw -f rtp rtp://127.0.0.1:1234
-
-

- To play the stream with ffplay (which has some caveats, see above), run the command: -

-
ffplay rtp://127.0.0.1:1234
-
-

- Note that rtp by default uses UDP, which, for large streams, can cause packet loss. See the "point to point" - section in this document for hints if this ever happens to you. -

-

Codecs

-

- The most popular streaming codec is probably libx264, though if you're streaming to a device which requires a "crippled" baseline - h264 implementation, you can use the x264 "baseline" profile. Some have have argued that the mp4 video codec is - better - than x264 baseline, because it encodes about as well with less cpu. You may be able to use other codecs, like - mpeg2video, or really any other video codec you want, typically, as long as your receiver can decode it, if it - suits your needs. -

-

- Also note that encoding it to the x264 "baseline" is basically a "compatibility mode" for older iOS devices or - the like, see here. -

-

- The mpeg4 video codec sometimes also comes "within a few percentage" of the compression of x264 "normal - settings", but uses much less cpu to do the encoding. See http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=7&t=631&hilit=mpeg4+libx264+cores&start=10#p2163 - for some graphs (which may be slightly outdated). Basically in that particular test it was 54 fps to 58 fps - (libx264 faster), and libx264 file was 5.1MB and mpeg4 was 6MB, but mpeg4 used only half as much cpu for its - computation, so take it with a grain of salt. -

-

HTTP Live Streaming and Streaming with multiple - bitrates - ¶

-

- FFmpeg supports splitting files (using "-f segment" for the output, see segment muxer) into time based chunks, useful for HTTP live streaming style file output. -

-

- How to stream with several different simultaneous bitrates is described here. -

-

- See also http://sonnati.wordpress.com/2012/07/02/ffmpeg-the-swiss-army-knife-of-internet-streaming-part-v -

-

Saving a file and Streaming at the same time

-

- See Creating multiple outputs. Basically, you may - only be able to accept from a webcam or some other source from at most one process, in this case you'll need to - "split" your output if you want to save it and stream it simultaneously. Streaming and saving simultaneously - (and only encoding once) can also save cpu. -

-

Transcoding / repeating - ¶

-

- FFmpeg can also receive from "a source" (for instance live or UDP) and then transcode and re-broadcast the - stream. -

-

- One mailing list user wrote this, quote: -

-
-

- In my application, I have a server running vlc sucking streams from some cameras, encoding them as MPEG2 - streams and sending them to ports 5000 through 5003 on my intermediary server (I'll have to let someone else - explain how to set that up, as that was someone else's part of the project). I have another server running - Wowza, with an instance named "live". And I've got an intermediate server that sucks in MPEG2 streams coming in - on ports 5000 to 5003, transcoding them into mp4 streams with H.264 and AAC codecs, and pushing the transcoded - streams on to Wowza. -

-
-
-

- The command line I use to pull the stream from port 5000, transcode it, and push it is: - ffmpeg -i 'udp://localhost:5000?fifo_size=1000000&overrun_nonfatal=1' -crf 30 -preset ultrafast -acodec aac - -strict experimental -ar 44100 -ac 2 -b:a 96k -vcodec libx264 -r 25 -b:v 500k -f flv 'rtmp://<wowza server - IP>/live/cam0' -

-
-
-

- -i 'udp://localhost:5000?fifo_size=1000000&overrun_nonfatal=1' tells ffmpeg where to pull the input stream - from. The parts after the ? are probably not needed most of the time, but I did need it after all. -

-
-
-

- -crf 30 sets the Content Rate Factor. That's an x264 argument that tries to keep reasonably consistent video - quality, while varying bitrate during more 'complicated' scenes, etc. A value of 30 allows somewhat lower - quality and bit rate. See Encode/H.264. -

-
-
-

- -preset ultrafast as the name implies provides for the fastest possible encoding. If some tradeoff between - quality and encode speed, go for the speed. This might be needed if you are going to be transcoding multiple - streams on one machine. -

-
-
-

- -acodec aac sets the audio codec (internal AAC encoder) -

-
-
-

- -strict experimental allows use of some experimental codecs (the internal AAC encoder is experimental) -

-
-
-

- -ar 44100 set the audio sample rate -

-
-
-

- -ac 2 specifies two channels of audio -

-
-
-

- -b:a 96k sets the audio bit rate -

-
-
-

- -vcodec libx264 sets the video codec -

-
-
-

- -r 25 set the frame rate -

-
-
-

- -b:v 500k set the video bit rate -

-
-
-

- -f flv says to deliver the output stream in an flv wrapper -

-
-
-

- 'rtmp://<wowza server IP>/live/cam0' is where the transcoded video stream gets pushed to -

-
-

Adjusting bitrate based on line conditions

-

- FFmpeg doesn't (today) support varying the encoding bitrate based on fluctuating network conditions. It does - support outputting in several "different" fixed bitrates, at the same time, however, see "Streaming with - multiple bitrates" on this page, which is vaguely related. Also if you are during direct capture from - directshow, the input device starts dropping frames when there is congestion, which somewhat simulates a - variable outgoing bitrate. -

-

Troubleshooting Streaming

-

- If you get a "black/blank" screen in the client, try sending it yuv422p or yuv420p type input. Some servers get - confused if you send them yuv444 input (which is the default for libx264). -

-

- NB that when you are testing your stream settings, you may want to test them with both VLC and FFplay, as FFplay sometimes introduces its - own artifacts when it is scaled (FFplay uses poor quality default scaling, which can be inaccurate). Don't use - ffplay as your baseline for determining quality. -

-

Point to point streaming - ¶

-

- If you want to stream "from one computer to another", you could start up a server on one, and then stream from - FFmpeg to that server, then have the client connect to that server (server could either be on client or server - side computers). Or you could do a point to point type stream, like: -

-
ffmpeg -i INPUT -acodec libmp3lame -ar 11025 --f rtp rtp://host:port
-
-

- where host is the receiving IP. Then receive the stream using VLC or ffmpeg from that port (since rtp uses UDP, - the receiver can start up any time). -

-

- or -

-
ffmpeg -i INPUT -f mpegts udp://host:port
-
-

- If you run into packet loss (green frames, tearing/shearing--since UDP is not guaranteed delivery, this can - occur) first make sure your FFmpeg is compiled with pthreads support enabled (if it is, then it uses a separate - thread to receive from the UDP port, which can cause less packet loss). You can tell that it is by specifying a - url like udp://host:post?fifo_size=10000 (if it accepts fifo_size, then you're good to go). Similarly, for - mplayer, you can use mplayer ffmpeg://udp://host:port?fifo_size=XXX for possibly better results on the receiving - end (mplayer needs a patch first, email rogerdpack@gmail.com - for it, once was https://gist.githubusercontent.com/rdp/9075572/raw/002dc1b745c895693fdb160cc9be77ef31f75531/possible_mplayer_udp_fix.diff - hackey work around patch, applied with ffmpeg subdir). -

-

- Alternatively, increase your buffer size, like mplayer ffmpeg://udp://host:port?buffer_size=10000000 (the - default is system dependent and typically far too low for any reasonable buffering. On linux though you can only - set it to like 200K max anyway, so this isn't good enough--make sure to use the circular buffer, and that the - following works: ffmpeg://udp://host:port?buffer_size=10000000?fifo_size=100000 (the fifo_size should not emit a - warning, and implies that you have a secondary thread that collects incoming packets for you if there is no - warning). -

-

- Another option is to use some transmission type that uses TCP for your transport. (The RTMP protocol, popular in - streaming to servers, uses TCP probably for this reason--you just can't use that for point to point streaming). -

-

- One option to use TCP is like this: -

-
ffmpeg -i INPUT -f mpegts tcp://host:port
-
-

- which I would guess will try and (as a client) establish a connection do that host on that port (assuming it has - a server waiting for the incoming connection). You could receive it like this: -

-
ffmpeg -i tcp://local_hostname:port?listen
-
-

- (basically, one side needs to specify "listen" and the other needs to not to). -

-

- To use with mplayer as a receiver it would be like -

-
ffmpeg -i ... -f mpegts "tcp://127.0.0.1:2000"
-
-

- and on the mplayer side -

-
mplayer ... ffmpeg://tcp://127.0.0.1:2000?listen
-
-

- (start mplayer first) -

-

- Another option is to use RTP (which by default uses UDP) but by specifying it use TCP: -

-
ffmpeg -i input -f rtsp -rtsp_transport tcp rtsp://localhost:8888/live.sdp
-
-

- (For meanings of options see official - documentation. -

-

- Then you may receive it like this (ffplay or ffmpeg): -

-
ffplay -rtsp_flags listen rtsp://localhost:8888/live.sdp?tcp
-# ending "?tcp" may not be needed -- you will need to start the server up first, before the sending client
-
-

- ffmpeg also has a "listen" option for rtmp so it may be able to receive a "straight" rtmp streams from a single - client that way. -

-

- With tcp based streams you can probably use any formatting/muxer, but with udp you need to be careful and use a - muxer that supports 'connecting anytime' like mpegts. -

-

- If you are forced to use udp (for instance you need to broadcast to a multicast port for whatever reason) then - you may be able to avoid the packet loss by (sending less data or sending the same frames over and over again so - they have a higher chance of being received). -

-

- See also the section on i-frames in #Latency. -

-

- Final working p2p client, with multicast: -

-

- server: -

-
ffmpeg -f dshow  -framerate 20 -i video=screen-capture-recorder -vf scale=1280:720 -vcodec libx264 -pix_fmt yuv420p -tune zerolatency -preset ultrafast -f mpegts udp://236.0.0.1:2000
-
-

- client: -

-
mplayer -demuxer +mpegts -framedrop -benchmark ffmpeg://udp://236.0.0.1:2000?fifo_size=100000&buffer_size=10000000
-# (see note above about linux needing fifo_size as well as buffer_size).
-
- - -
- -
- Last modified - 5 - months ago - Last modified on Aug 30, 2018, 1:49:59 AM -
- - -
- - -
- -
- - -
You have turned - off the paragraph player. You can turn it on again from the options page.
- - + + + + + StreamingGuide – FFmpeg + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ +
+

Streaming

+

+

+ +

+

+

+ FFmpeg can basically stream through one of two ways: It either streams to a some "other server", which re-streams + for it to multiple clients, or it can stream via UDP/TCP directly to some single destination receiver, or + alternatively directly to a multicast destination. Theoretically you might be able to send to multiple receivers + via Creating Multiple Outputs? but there is no built-in full blown server. +

+

+ Servers which can receive from FFmpeg (to restream to multiple clients) include ffserver + (linux only, though with cygwin it might work on windows), or Wowza Media Server, or Flash Media Server, Red5, or various others. Even VLC can pick up the stream from ffmpeg, then redistribute it, acting as a server. + Since FFmpeg is at times more efficient than VLC at doing the raw encoding, this can be a useful option compared + to doing both transcoding and streaming in VLC. Nginx also has an rtmp redistribution plugin, as does apache etc. and there is probably more out there for apache, etc.. You can also live + stream to online redistribution servers like own3d.tv or justin.tv (for instance streaming your desktop). Also + any rtmp + server will most likely work to receive streams from FFmpeg (these typically require you to setup a running + instance on a server). +

+

The -re flag

+

+ The FFmpeg's "-re" flag means to "Read input at native frame rate. Mainly used to simulate a grab device." i.e. + if you wanted to stream a video file, then you would want to use this, otherwise it might stream it too fast (it + attempts to stream at line speed by default). My guess is you typically don't want to use this flag when + streaming from a live device, ever. +

+

Setting

+

+ Here is what another person once did for broadcast: +

+
ffmpeg -f dshow -i video="Virtual-Camera" -preset ultrafast -vcodec libx264 -tune zerolatency -b 900k -f mpegts udp://10.1.0.102:1234
+
+

+ And here is what another person did: +

+
ffmpeg -f dshow -i video="screen-capture-recorder":audio="Stereo Mix (IDT High Definition" \
+-vcodec libx264 -preset ultrafast -tune zerolatency -r 10 -async 1 -acodec libmp3lame -ab 24k -ar 22050 -bsf:v h264_mp4toannexb \
+-maxrate 750k -bufsize 3000k -f mpegts udp://192.168.5.215:48550
+
+

+ NB that they also (for directshow devices) had to adjust the rtbufsize in that example. +

+

+ You can see a description of what some of these means, (for example bufsize, bitrate settings) in the Encode/H.264. +

+

+ Here's how one guy broadcast a live stream (in this instance a Capture/Desktop#Windows? + screen capture device): +

+
$ ffmpeg -y -loglevel warning -f dshow -i video="screen-capture-recorder" -vf crop=690:388:136:0 -r 30 -s 962x388 -threads 2 -vcodec libx264 -vpre baseline -vpre my_ffpreset -f flv rtmp:///live/myStream.sdp
+
+

+ with a custom FFmpeg preset (libx264-my_ffpreset.ffpreset) in this case: +

+
coder=1
+flags2=+wpred+dct8x8
+level=31
+maxrate=1200000
+bufsize=200000
+wpredp=0
+g=60
+refs=1
+subq=3
+trellis=0
+bf=0
+rc_lookahead=0
+
+

+ Here is how you stream to twitch.tv or similar services (rtmp protocol), using ffmpeg 1.0 or ffmpeg-git (tested + on 2012-11-12), this is also for pulseaudio users: + Example 1, no sound: +

+
ffmpeg -f x11grab -s 1920x1200 -framerate 15 -i :0.0 -c:v libx264 -preset fast -pix_fmt yuv420p -s 1280x800 -threads 0 -f flv "rtmp://live.twitch.tv/app/live_********_******************************"
+
+

+ Example 2, first screen (on dual screen setup, or if on a single screen): +

+
ffmpeg -f x11grab -s 1920x1200 -framerate 15 -i :0.0 -f pulse -ac 2 -i default -c:v libx264 -preset fast -pix_fmt yuv420p -s 1280x800 -c:a aac -b:a 160k -ar 44100 -threads 0 -f flv "rtmp://live.twitch.tv/app/live_********_******************************"
+
+

+ Example 3, second screen (on dual screen setup): +

+
ffmpeg -f x11grab -s 1920x1200 -framerate 15 -i :0.0+1920,0 -f pulse -ac 2 -i default -c:v libx264 -preset fast -pix_fmt yuv420p -s 1280x800 -c:a aac -b:a 160k -ar 44100 -threads 0 -f flv "rtmp://live.twitch.tv/app/live_********_******************************"
+
+

Latency

+

+ You may be able to decrease initial "startup" latency by specifing that I-frames come "more frequently" (or + basically always, in the case of x264's zerolatency setting), + though this can increase frame size and decrease quality, see here for some more background. Basically for typical x264 streams, it inserts an + I-frame every 250 frames. This means that new clients that connect to the stream may have to wait up to 250 + frames before they can start receiving the stream (or start with old data). So increasing I-frame frequency + (makes the stream larger, but might decrease latency). For real time captures you can also decrease latency of + audio in windows dshow by using the dshow audio_buffer_size setting. You can also decrease latency by tuning any broadcast server you are using to + minimize latency, and finally by tuning the client that receives the stream to not "cache" any incoming data, + which, if it does, increases latency. +

+

+ Sometimes audio codecs also introduce some latency of their own. You may be able to get less latency by using + speex, for example, or opus, in place of libmp3lame. +

+

+ You will also want to try and decrease latency at the server side, for instance wowza hints. +

+

+ Also setting -probesize and -analyzeduration to low values may help your stream start up more quickly (it uses + these to scan for "streams" in certain muxers, like ts, where some can appears "later", and also to estimate the + duration, which, for live streams, the latter you don't need anyway). This should be unneeded by dshow input. +

+

+ Reducing cacheing at the client side can help, too, for instance mplayer has a "-nocache" option, other players + may similarly has some type of pre-playback buffering that is occurring. (The reality is mplayers -benchmark + option has much more effect). +

+

+ Using an encoder that encodes more quickly (or possibly even raw format?) might reduce latency. +

+

+ You might get less latency by using one of the "point to point" protocols described in this document, at well. + You'd lose the benefit of having a server, of course. +

+

+ NB that a client when it initially starts up may have to wait until the next i-frame to be able to start + receiving the stream (ex: if receiving UDP), so the GOP setting (-g) i-frame interval will have an effect on how + quickly they can start streaming (i.e. they must receive an i-frame before they start). Setting it to a lower + number means it will use more bandwidth, but clients will be able to connect more quickly (the default for x264 + is 250--so for 30 fps that means an i-frame only once every 10 seconds or so). So it's a tradeoff if you adjust + it. This does not affect actual latency (just connection time) since the client can still display frames very + quickly after and once it has received its first i-frame. Also if you're using a lossy transport, like UDP, then + an i-frame represents "the next change it will have to repair the stream" if there are problems from packet loss. +

+

+ You can also (if capturing from a live source) increase frame rate to decrease latency (which affects throughput + and also i-frame frequency, of course). This obvious sends packets more frequently, so (with 5 fps, you introduce + at least a 0.2s latency, with 10 fps 0.1s latency) but it also helps clients to fill their internal buffers, etc. + more quickly. +

+

+ Note also that using dshow's "rtbufsize" has the unfortunate side effect of sometimes allowing frames to "buffer" + while it is waiting on encoding of previous frames, or waiting for them to be sent over the wire. This means that + if you use a higher value at all, it can cause/introduce added latency if it ever gets used (but if used, can be + helpful for other aspects, like transmitting more frames overall consistently etc. so YMMV). Almost certainly if + you set a very large value for this, and then see the "buffer XX% full! dropping!" message, you are introducing + latency. +

+

+ There is also apparently an option -fflags nobuffer which might possibly help, usually for receiving streams reduce + latency. +

+
+

+ mpv udp://236.0.0.1:2000 --no-cache --untimed --no-demuxer-thread --video-sync=audio --vd-lavc-threads=1 +

+

+ may be useful. +

+

Testing latency

+

+ By default, ffplay (as a receiver for testing latency) introduces significant latency of its own, so if you use + it for testing (see troubleshooting section) it may not reflect latency accurately. FFplay introduces some video + artifacts, also, see notes for it in "troubleshooting streaming" section Also some settings mentioned above like + "probesize" might help it start more quickly. Also useful: +

+
ffplay -probesize 32 -sync ext INPUT
+
+

+ (the sync part tells it to try and stay realtime). +

+

+ Useful is mplayer with its -benchmark for testing latency (-noaudio and/or -nocache *might* be useful, though I + haven't found -nocache to provide any latency benefit it might work for you). +

+

+ Using the SDL out option while using FFmpeg to receive the stream might also help to view frames with less + client side latency: "ffmpeg ... -f sdl <input_here> "window title"" (this works especially well with + -fflags nobuffer, though in my tests is still barely more latency than using mplayer -benchmark always). This + doesn't have a "drop frames if you run out of cpu" option so it can get quite far behind at times (introduce + more latency variably). +

+

+ Another possibly useful receiving client is "omxplayer -live" +

+

+ See also "Point to point streaming" section esp. if you use UDP etc. +

+

See also

+

+ Here is a + list of some other ideas to try (using VBR may help, etc.) +

+

CPU usage / File size + ¶

+

+ In general, the more CPU you use to compress, the better the output image will be, or the smaller of a file the + output will be for the same quality. +

+

+ Basically, the easiest way to save cpu is to decrease the input frame rate/size, or decrease the output frame + rate/size. +

+

+ Also you could (if capturing from live source), instruct the live source to feed a "smaller stream" (ex: webcam + stream 640x480 instead of 1024x1280), or you could set a lower output "output quality" setting (q level), or + specify a lower output desired bitrate (see Encode/H.264 for a + background). Or try a different output codec, or specify new parameters to your codec (for instance, a different + profile or preset for libx264). Specifying $ -threads 0 instructs + the encoder to use all available cpu cores, which is the default. You could also resize the input first, before + transcoding it, so it's not as large. Applying a smoothing filter like hqdn3d before encoding might help it + compress better, yielding smaller files. +

+

+ You can also set a lower output frame rate to of course decrease cpu usage. +

+

+ If you're able to live capture in a pixel format that matches your output format (ex: yuv420p output from a + webcam, instead of mjpeg), that might help with cpu usage, since it avoids an extra conversion. Using 64-bit + instead of 32-bit executables (for those that have that choice) can result in a slight speedup. If you're able + to use -vcodec copy that, of course, uses the least cpu of all options since it just sends the frames verbatim + to the output. +

+

+ Sometimes you can change the "pixel formats" somehow, like using rgb16 instead of rgb24, to save time/space (or + yuv420 instead of yuv444 or the like, since 420 stores less information it may compress better and use less + bandwidth). This may not affect latency. +

+

Streaming a simple RTP audio stream from FFmpeg

+

+ FFmpeg can stream a single stream using the RTP protocol. In order to avoid buffering problems on the other hand, the streaming + should be done through the -re option, which means that the stream will be streamed in real-time (i.e. it slows + it down to simulate a live streaming source. +

+

+ For example the following command will generate a signal, and will stream it to the port 1234 on localhost: +

+
ffmpeg -re -f lavfi -i aevalsrc="sin(400*2*PI*t)" -ar 8000 -f mulaw -f rtp rtp://127.0.0.1:1234
+
+

+ To play the stream with ffplay (which has some caveats, see above), run the command: +

+
ffplay rtp://127.0.0.1:1234
+
+

+ Note that rtp by default uses UDP, which, for large streams, can cause packet loss. See the "point to point" + section in this document for hints if this ever happens to you. +

+

Codecs

+

+ The most popular streaming codec is probably libx264, though if you're streaming to a device which requires a "crippled" baseline + h264 implementation, you can use the x264 "baseline" profile. Some have have argued that the mp4 video codec is + better + than x264 baseline, because it encodes about as well with less cpu. You may be able to use other codecs, like + mpeg2video, or really any other video codec you want, typically, as long as your receiver can decode it, if it + suits your needs. +

+

+ Also note that encoding it to the x264 "baseline" is basically a "compatibility mode" for older iOS devices or + the like, see here. +

+

+ The mpeg4 video codec sometimes also comes "within a few percentage" of the compression of x264 "normal + settings", but uses much less cpu to do the encoding. See http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=7&t=631&hilit=mpeg4+libx264+cores&start=10#p2163 + for some graphs (which may be slightly outdated). Basically in that particular test it was 54 fps to 58 fps + (libx264 faster), and libx264 file was 5.1MB and mpeg4 was 6MB, but mpeg4 used only half as much cpu for its + computation, so take it with a grain of salt. +

+

HTTP Live Streaming and Streaming with multiple + bitrates + ¶

+

+ FFmpeg supports splitting files (using "-f segment" for the output, see segment muxer) into time based chunks, useful for HTTP live streaming style file output. +

+

+ How to stream with several different simultaneous bitrates is described here. +

+

+ See also http://sonnati.wordpress.com/2012/07/02/ffmpeg-the-swiss-army-knife-of-internet-streaming-part-v +

+

Saving a file and Streaming at the same time

+

+ See Creating multiple outputs. Basically, you may + only be able to accept from a webcam or some other source from at most one process, in this case you'll need to + "split" your output if you want to save it and stream it simultaneously. Streaming and saving simultaneously + (and only encoding once) can also save cpu. +

+

Transcoding / repeating + ¶

+

+ FFmpeg can also receive from "a source" (for instance live or UDP) and then transcode and re-broadcast the + stream. +

+

+ One mailing list user wrote this, quote: +

+
+

+ In my application, I have a server running vlc sucking streams from some cameras, encoding them as MPEG2 + streams and sending them to ports 5000 through 5003 on my intermediary server (I'll have to let someone else + explain how to set that up, as that was someone else's part of the project). I have another server running + Wowza, with an instance named "live". And I've got an intermediate server that sucks in MPEG2 streams coming in + on ports 5000 to 5003, transcoding them into mp4 streams with H.264 and AAC codecs, and pushing the transcoded + streams on to Wowza. +

+
+
+

+ The command line I use to pull the stream from port 5000, transcode it, and push it is: + ffmpeg -i 'udp://localhost:5000?fifo_size=1000000&overrun_nonfatal=1' -crf 30 -preset ultrafast -acodec aac + -strict experimental -ar 44100 -ac 2 -b:a 96k -vcodec libx264 -r 25 -b:v 500k -f flv 'rtmp://<wowza server + IP>/live/cam0' +

+
+
+

+ -i 'udp://localhost:5000?fifo_size=1000000&overrun_nonfatal=1' tells ffmpeg where to pull the input stream + from. The parts after the ? are probably not needed most of the time, but I did need it after all. +

+
+
+

+ -crf 30 sets the Content Rate Factor. That's an x264 argument that tries to keep reasonably consistent video + quality, while varying bitrate during more 'complicated' scenes, etc. A value of 30 allows somewhat lower + quality and bit rate. See Encode/H.264. +

+
+
+

+ -preset ultrafast as the name implies provides for the fastest possible encoding. If some tradeoff between + quality and encode speed, go for the speed. This might be needed if you are going to be transcoding multiple + streams on one machine. +

+
+
+

+ -acodec aac sets the audio codec (internal AAC encoder) +

+
+
+

+ -strict experimental allows use of some experimental codecs (the internal AAC encoder is experimental) +

+
+
+

+ -ar 44100 set the audio sample rate +

+
+
+

+ -ac 2 specifies two channels of audio +

+
+
+

+ -b:a 96k sets the audio bit rate +

+
+
+

+ -vcodec libx264 sets the video codec +

+
+
+

+ -r 25 set the frame rate +

+
+
+

+ -b:v 500k set the video bit rate +

+
+
+

+ -f flv says to deliver the output stream in an flv wrapper +

+
+
+

+ 'rtmp://<wowza server IP>/live/cam0' is where the transcoded video stream gets pushed to +

+
+

Adjusting bitrate based on line conditions

+

+ FFmpeg doesn't (today) support varying the encoding bitrate based on fluctuating network conditions. It does + support outputting in several "different" fixed bitrates, at the same time, however, see "Streaming with + multiple bitrates" on this page, which is vaguely related. Also if you are during direct capture from + directshow, the input device starts dropping frames when there is congestion, which somewhat simulates a + variable outgoing bitrate. +

+

Troubleshooting Streaming

+

+ If you get a "black/blank" screen in the client, try sending it yuv422p or yuv420p type input. Some servers get + confused if you send them yuv444 input (which is the default for libx264). +

+

+ NB that when you are testing your stream settings, you may want to test them with both VLC and FFplay, as FFplay sometimes introduces its + own artifacts when it is scaled (FFplay uses poor quality default scaling, which can be inaccurate). Don't use + ffplay as your baseline for determining quality. +

+

Point to point streaming + ¶

+

+ If you want to stream "from one computer to another", you could start up a server on one, and then stream from + FFmpeg to that server, then have the client connect to that server (server could either be on client or server + side computers). Or you could do a point to point type stream, like: +

+
ffmpeg -i INPUT -acodec libmp3lame -ar 11025 --f rtp rtp://host:port
+
+

+ where host is the receiving IP. Then receive the stream using VLC or ffmpeg from that port (since rtp uses UDP, + the receiver can start up any time). +

+

+ or +

+
ffmpeg -i INPUT -f mpegts udp://host:port
+
+

+ If you run into packet loss (green frames, tearing/shearing--since UDP is not guaranteed delivery, this can + occur) first make sure your FFmpeg is compiled with pthreads support enabled (if it is, then it uses a separate + thread to receive from the UDP port, which can cause less packet loss). You can tell that it is by specifying a + url like udp://host:post?fifo_size=10000 (if it accepts fifo_size, then you're good to go). Similarly, for + mplayer, you can use mplayer ffmpeg://udp://host:port?fifo_size=XXX for possibly better results on the receiving + end (mplayer needs a patch first, email rogerdpack@gmail.com + for it, once was https://gist.githubusercontent.com/rdp/9075572/raw/002dc1b745c895693fdb160cc9be77ef31f75531/possible_mplayer_udp_fix.diff + hackey work around patch, applied with ffmpeg subdir). +

+

+ Alternatively, increase your buffer size, like mplayer ffmpeg://udp://host:port?buffer_size=10000000 (the + default is system dependent and typically far too low for any reasonable buffering. On linux though you can only + set it to like 200K max anyway, so this isn't good enough--make sure to use the circular buffer, and that the + following works: ffmpeg://udp://host:port?buffer_size=10000000?fifo_size=100000 (the fifo_size should not emit a + warning, and implies that you have a secondary thread that collects incoming packets for you if there is no + warning). +

+

+ Another option is to use some transmission type that uses TCP for your transport. (The RTMP protocol, popular in + streaming to servers, uses TCP probably for this reason--you just can't use that for point to point streaming). +

+

+ One option to use TCP is like this: +

+
ffmpeg -i INPUT -f mpegts tcp://host:port
+
+

+ which I would guess will try and (as a client) establish a connection do that host on that port (assuming it has + a server waiting for the incoming connection). You could receive it like this: +

+
ffmpeg -i tcp://local_hostname:port?listen
+
+

+ (basically, one side needs to specify "listen" and the other needs to not to). +

+

+ To use with mplayer as a receiver it would be like +

+
ffmpeg -i ... -f mpegts "tcp://127.0.0.1:2000"
+
+

+ and on the mplayer side +

+
mplayer ... ffmpeg://tcp://127.0.0.1:2000?listen
+
+

+ (start mplayer first) +

+

+ Another option is to use RTP (which by default uses UDP) but by specifying it use TCP: +

+
ffmpeg -i input -f rtsp -rtsp_transport tcp rtsp://localhost:8888/live.sdp
+
+

+ (For meanings of options see official + documentation. +

+

+ Then you may receive it like this (ffplay or ffmpeg): +

+
ffplay -rtsp_flags listen rtsp://localhost:8888/live.sdp?tcp
+# ending "?tcp" may not be needed -- you will need to start the server up first, before the sending client
+
+

+ ffmpeg also has a "listen" option for rtmp so it may be able to receive a "straight" rtmp streams from a single + client that way. +

+

+ With tcp based streams you can probably use any formatting/muxer, but with udp you need to be careful and use a + muxer that supports 'connecting anytime' like mpegts. +

+

+ If you are forced to use udp (for instance you need to broadcast to a multicast port for whatever reason) then + you may be able to avoid the packet loss by (sending less data or sending the same frames over and over again so + they have a higher chance of being received). +

+

+ See also the section on i-frames in #Latency. +

+

+ Final working p2p client, with multicast: +

+

+ server: +

+
ffmpeg -f dshow  -framerate 20 -i video=screen-capture-recorder -vf scale=1280:720 -vcodec libx264 -pix_fmt yuv420p -tune zerolatency -preset ultrafast -f mpegts udp://236.0.0.1:2000
+
+

+ client: +

+
mplayer -demuxer +mpegts -framedrop -benchmark ffmpeg://udp://236.0.0.1:2000?fifo_size=100000&buffer_size=10000000
+# (see note above about linux needing fifo_size as well as buffer_size).
+
+ + +
+ +
+ Last modified + 5 + months ago + Last modified on Aug 30, 2018, 1:49:59 AM +
+ + +
+ + +
+ +
+ + +
You have turned + off the paragraph player. You can turn it on again from the options page.
+ + \ No newline at end of file diff --git a/test/html/gmail.html b/test/assets/html/gmail.html similarity index 99% rename from test/html/gmail.html rename to test/assets/html/gmail.html index 89cf180..3858581 100644 --- a/test/html/gmail.html +++ b/test/assets/html/gmail.html @@ -1,395 +1,395 @@ -Inbox (157) - kd19850511@gmail.com - Gmail
You have turned off the paragraph player. You can turn it on again from the options page.
Conversation opened. 1 unread message.
Compose

Conversations

 
Not starredAd
Amazon Web Services
Ad
AWS for Web Hosting - Flexible, Low Cost Website Hosting. Learn the Benefits of AWS Today.
Not starredAd
GoToMeeting
Ad
Kick Some Business - GoToMeeting is a simple collaboration platform that makes it easier to get work done.

Primary

 
150 of 318
 
Not starred
donotreply,Verify your email address, 1:10 AM, Please verify your email address to complete registration Verify your email address to complete registration Hi Bill, Thanks for your interest in joining Upwork! To complete your registration, we need.
donotreply
Verify your email address
 - Please verify your email address to complete registration Verify your email address to complete registration Hi Bill, Thanks for your interest in joining Upwork! To complete your registration, we need
 1:10 AM
Not starred
Upwork Help Center 2,Upwork Help Center: Your Upwork Account, Jan 17, https://support.upwork.com/hc/requests/23953084 Kate (Upwork Help Center) Jan 17, 10:45 AM CST Hello Willer, Upwork Trust & Safety Team Sincerely, Upwork Trust .
Upwork Help Center 2
Upwork Help Center: Your Upwork Account
 - https://support.upwork.com/hc/requests/23953084 Kate (Upwork Help Center) Jan 17, 10:45 AM CST Hello Willer, Upwork Trust & Safety Team Sincerely, Upwork Trust
View ticket
 Jan 17
Not starred
Peter Hitchcock (Ji. 3,[JIRA] (OTFE-96) Vendor role drivers table action cable, Jan 16, Peter Hitchcock updated OTFE-96 OnTrack FE / OTFE-96 Vendor role drivers table action cable Change By: Peter Hitchcock Status: In Review Backlog Add Comment Get.
Peter Hitchcock (Ji. 3
[JIRA] (OTFE-96) Vendor role drivers table action cable
 - Peter Hitchcock updated OTFE-96 OnTrack FE / OTFE-96 Vendor role drivers table action cable Change By: Peter Hitchcock Status: In Review Backlog Add Comment Get
 Jan 16
Not starred
Peter Hitchcock (Ji. 9,[JIRA] (OTFE-137) Scheduling - Vendor removed from event should also remove all vendors drivers from event, Jan 16, Peter Hitchcock updated OTFE-137 OnTrack FE / OTFE-137 Scheduling - Vendor removed from event should also remove all vendors drivers from event Change By: Peter.
Peter Hitchcock (Ji. 9
[JIRA] (OTFE-137) Scheduling - Vendor removed from event should also remove all vendors drivers from event
 - Peter Hitchcock updated OTFE-137 OnTrack FE / OTFE-137 Scheduling - Vendor removed from event should also remove all vendors drivers from event Change By: Peter
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 7,[JIRA] (OTFE-136) Scheduling - Admin role should be able to schedule vendors on all routes, vendor role should only see routes they can schedule, Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-136 Scheduling - Admin role should be able to schedule vendors on all routes, vendor role should.
Peter Hitchcock (Ji. 7
[JIRA] (OTFE-136) Scheduling - Admin role should be able to schedule vendors on all routes, vendor role should only see routes they can schedule
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-136 Scheduling - Admin role should be able to schedule vendors on all routes, vendor role should
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 4,[JIRA] (OTFE-144) Service request modal add time to close (time open - time to close), Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-144 Service request modal add time to close (time open - time to close) Change By: Peter Hitchco.
Peter Hitchcock (Ji. 4
[JIRA] (OTFE-144) Service request modal add time to close (time open - time to close)
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-144 Service request modal add time to close (time open - time to close) Change By: Peter Hitchco
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-180) Service Request - Update search field text, Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-180 Service Request - Update search field text Change By: Peter Hitchcock Assignee: KING DEV Add.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-180) Service Request - Update search field text
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-180 Service Request - Update search field text Change By: Peter Hitchcock Assignee: KING DEV Add
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-179) Service Request - When toggling off service types it should update Total Requests and Total Value for remaining types, Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-179 Service Request - When toggling off service types it should update Total Requests and Total .
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-179) Service Request - When toggling off service types it should update Total Requests and Total Value for remaining types
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-179 Service Request - When toggling off service types it should update Total Requests and Total
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 3,[JIRA] (OTFE-177) Service Request - map pins should be same color as service type, Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-177 Service Request - map pins should be same color as service type Change By: Peter Hitchcock A.
Peter Hitchcock (Ji. 3
[JIRA] (OTFE-177) Service Request - map pins should be same color as service type
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-177 Service Request - map pins should be same color as service type Change By: Peter Hitchcock A
 Jan 16
Not starred
Peter Hitchcock (Ji. 2,[JIRA] (OTFE-178) Service Request - Edit service type, Jan 16, Peter Hitchcock updated OTFE-178 OnTrack FE / OTFE-178 Service Request - Edit service type Change By: Peter Hitchcock Status: Backlog Selected for Development A.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-178) Service Request - Edit service type
 - Peter Hitchcock updated OTFE-178 OnTrack FE / OTFE-178 Service Request - Edit service type Change By: Peter Hitchcock Status: Backlog Selected for Development A
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-176) Service Request - add count next to service type name ex Fix Tent (3), Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-176 Service Request - add count next to service type name ex Fix Tent (3) Change By: Peter Hitch.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-176) Service Request - add count next to service type name ex Fix Tent (3)
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-176 Service Request - add count next to service type name ex Fix Tent (3) Change By: Peter Hitch
 Jan 16
Not starred
Peter Hitchcock (Ji. 2,[JIRA] (OTFE-175) Service Request - not all types are showing in chart, Jan 16, Peter Hitchcock updated OTFE-175 OnTrack FE / OTFE-175 Service Request - not all types are showing in chart Change By: Peter Hitchcock Status: Backlog Selected .
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-175) Service Request - not all types are showing in chart
 - Peter Hitchcock updated OTFE-175 OnTrack FE / OTFE-175 Service Request - not all types are showing in chart Change By: Peter Hitchcock Status: Backlog Selected
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 9,[JIRA] (OTFE-76) Setup Ingress vs Egress on routes, Jan 16, Peter Hitchcock updated an issue OnTrack FE / OTFE-76 Setup Ingress vs Egress on routes Change By: Peter Hitchcock Fix Version/s: 1.1.2 Fix Version/s: 1.1.3 Add.
Peter Hitchcock (Ji. 9
[JIRA] (OTFE-76) Setup Ingress vs Egress on routes
 - Peter Hitchcock updated an issue OnTrack FE / OTFE-76 Setup Ingress vs Egress on routes Change By: Peter Hitchcock Fix Version/s: 1.1.2 Fix Version/s: 1.1.3 Add
 Jan 16
Not starred
philippe Mudaheranw. 2,You have unread messages about the job Webgl developer, Jan 14, You have unread messages about the job Webgl developer philippe Mudaheranwa 4:17 PM CST, 14 Jan 2019 hello sam, is threejs a licensed engine? I mean is there fe.
philippe Mudaheranw. 2
You have unread messages about the job Webgl developer
 - You have unread messages about the job Webgl developer philippe Mudaheranwa 4:17 PM CST, 14 Jan 2019 hello sam, is threejs a licensed engine? I mean is there fe
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 4,[JIRA] (OTFE-169) Service Request charts - action cable for both, Jan 14, Peter Hitchcock updated an issue OnTrack FE / OTFE-169 Service Request charts - action cable for both Change By: Peter Hitchcock Summary: Service Request charts.
Peter Hitchcock (Ji. 4
[JIRA] (OTFE-169) Service Request charts - action cable for both
 - Peter Hitchcock updated an issue OnTrack FE / OTFE-169 Service Request charts - action cable for both Change By: Peter Hitchcock Summary: Service Request charts
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 5,[JIRA] (OTFE-157) Messaging - messaging camper is sending reservation id not camper id, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-157 Messaging - messaging camper is sending reservation id not camper id Change By: Peter Hitchc.
Peter Hitchcock (Ji. 5
[JIRA] (OTFE-157) Messaging - messaging camper is sending reservation id not camper id
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-157 Messaging - messaging camper is sending reservation id not camper id Change By: Peter Hitchc
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 4,[JIRA] (OTFE-147) Service request - add value on create, this is an optional field see api /api/service_request_types, Jan 14, Peter Hitchcock updated an issue OnTrack FE / OTFE-147 Service request - add value on create, this is an optional field see api /api/service_request_types Chang.
Peter Hitchcock (Ji. 4
[JIRA] (OTFE-147) Service request - add value on create, this is an optional field see api /api/service_request_types
 - Peter Hitchcock updated an issue OnTrack FE / OTFE-147 Service request - add value on create, this is an optional field see api /api/service_request_types Chang
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-168) Service Request - Add Service Request, request type needs to be dynamic, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-168 Service Request - Add Service Request, request type needs to be dynamic Change By: Peter Hit.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-168) Service Request - Add Service Request, request type needs to be dynamic
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-168 Service Request - Add Service Request, request type needs to be dynamic Change By: Peter Hit
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-170) Service Request - Map view remove toggles add dropdown filter, map pins same color as service request color, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-170 Service Request - Map view remove toggles add dropdown filter, map pins same color as servic.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-170) Service Request - Map view remove toggles add dropdown filter, map pins same color as service request color
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-170 Service Request - Map view remove toggles add dropdown filter, map pins same color as servic
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-171) Service Request - add type color picker is loading higher than the model and we can't select a color, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-171 Service Request - add type color picker is loading higher than the model and we can't select.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-171) Service Request - add type color picker is loading higher than the model and we can't select a color
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-171 Service Request - add type color picker is loading higher than the model and we can't select
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 9,[JIRA] (OTFE-145) Service Requests - Update chart with counts of each service type, update Average time chart, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-145 Service Requests - Update chart with counts of each service type, update Average time chart .
Peter Hitchcock (Ji. 9
[JIRA] (OTFE-145) Service Requests - Update chart with counts of each service type, update Average time chart
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-145 Service Requests - Update chart with counts of each service type, update Average time chart
 Jan 14
Not starred
Upwork Help Center 5,Upwork Help Center: Your Upwork Account, Jan 13, https://support.upwork.com/hc/requests/23908737 Cris (Upwork Help Center) Jan 13, 10:19 PM CST Hello Chase, [V0V3D0-6RM8].
Upwork Help Center 5
Upwork Help Center: Your Upwork Account
 - https://support.upwork.com/hc/requests/23908737 Cris (Upwork Help Center) Jan 13, 10:19 PM CST Hello Chase, [V0V3D0-6RM8]
View ticket
 Jan 13
Not starred
Upwork Help Center 2,Upwork Help Center: Your Upwork account has been suspended, Jan 13, https://support.upwork.com/hc/requests/23903135 Jan 13, 10:03 AM CST Dear Ryan, [V0V383-R959].
Upwork Help Center 2
Upwork Help Center: Your Upwork account has been suspended
 - https://support.upwork.com/hc/requests/23903135 Jan 13, 10:03 AM CST Dear Ryan, [V0V383-R959]
View ticket
 Jan 13
Not starred
unread, Upwork Notification 5,Your request to join Upwork, Jan 11, Hi Chris, Thank you for your interest in joining Upwork. We have reviewed your application to join, and regret to inform you that we are unable to accept your U.
Upwork Notification 5
Your request to join Upwork
 - Hi Chris, Thank you for your interest in joining Upwork. We have reviewed your application to join, and regret to inform you that we are unable to accept your U
 Jan 11
Not starred
Upwork Help Center 5,Upwork Help Center: Your Upwork Account, Jan 11, https://support.upwork.com/hc/requests/23877035 Hello Tony, [XZ4RR6-482K].
Upwork Help Center 5
Upwork Help Center: Your Upwork Account
 - https://support.upwork.com/hc/requests/23877035 Hello Tony, [XZ4RR6-482K]
View ticket
 Jan 11
Not starred
donotreply 2,Verify your email address, Jan 11, Verify your email address to complete registration Hi Ryan, Thanks for your interest in joining Upwork! To complete your registration, we need you to verify you.
donotreply 2
Verify your email address
 - Verify your email address to complete registration Hi Ryan, Thanks for your interest in joining Upwork! To complete your registration, we need you to verify you
 Jan 11
Not starred
unread, support 4,Atlassian Bitbucket Incident - Bitbucket webhooks experiencing delays - 10 January 2019, Jan 10, Investigating - 2 components affected - Bitbucket Webhooks are experiencing delays.... ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌.
support 4
Atlassian Bitbucket Incident - Bitbucket webhooks experiencing delays - 10 January 2019
 - Investigating - 2 components affected - Bitbucket Webhooks are experiencing delays.... ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌
 Jan 10
Not starred
donotreply 2,Verify your email address, Jan 10, Please verify your email address to complete registration Verify your email address to complete registration Hi Kyle, Thanks for your interest in joining Upwork! To complete your registration, we need.
donotreply 2
Verify your email address
 - Please verify your email address to complete registration Verify your email address to complete registration Hi Kyle, Thanks for your interest in joining Upwork! To complete your registration, we need
 Jan 10
Not starred
Upwork Notification 5,Your request to join Upwork, Jan 9, Hi Jack, Thank you for your interest in joining Upwork. We have reviewed your application to join, and regret to inform you that we are unable to accept your Upwork freelancer registration at this time.
Upwork Notification 5
Your request to join Upwork
 - Hi Jack, Thank you for your interest in joining Upwork. We have reviewed your application to join, and regret to inform you that we are unable to accept your Upwork freelancer registration at this time
 Jan 9
Not starred
Google,Critical security alert for your linked Google Account, Jan 9, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account.
Google
Critical security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account
 Jan 9
Not starred
Google,Security alert for your linked Google Account, Jan 9, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here New sign-in to your linked account ideveloper003@gmail.com.
Google
Security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here New sign-in to your linked account ideveloper003@gmail.com
 Jan 9
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-147) Service request - add value on create, Jan 8, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-147 Service request - add value on create Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment Get Jira.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-147) Service request - add value on create
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-147 Service request - add value on create Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment Get Jira
 Jan 8
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-169) Service Request charts - action cable, Jan 8, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-169 Service Request charts - action cable Change By: Peter Hitchcock Assignee: Contact SFS KING DEV Add Comment Add Comment Get Jira.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-169) Service Request charts - action cable
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-169 Service Request charts - action cable Change By: Peter Hitchcock Assignee: Contact SFS KING DEV Add Comment Add Comment Get Jira
 Jan 8
Not starred
Chioma First,Fake USA Passport PSD Template, Jan 8, Please I got ur email from this website(http://leakforums.blogspot.com/2017/01/all-country-fake-psd-files-21-gb.html) Please I need USA USA Passport PSD editable. Reply to me pls.
Chioma First
Fake USA Passport PSD Template
 - Please I got ur email from this website(http://leakforums.blogspot.com/2017/01/all-country-fake-psd-files-21-gb.html) Please I need USA USA Passport PSD editable. Reply to me pls
 Jan 8
Not starred
unread, Peter Hitchcock (Ji. 8,[JIRA] (OTFE-133) Vendors - Add button like scheduling to associate vendor, Jan 7, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-133 Vendors - Add button like scheduling to associate vendor Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment.
Peter Hitchcock (Ji. 8
[JIRA] (OTFE-133) Vendors - Add button like scheduling to associate vendor
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-133 Vendors - Add button like scheduling to associate vendor Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment
 Jan 7
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-152) Scheduling error, Jan 7, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Bug OTFE-152 Scheduling error Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment Get Jira notifications on your phone!.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-152) Scheduling error
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Bug OTFE-152 Scheduling error Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment Get Jira notifications on your phone!
 Jan 7
Not starred
Google,KING, your new Lenovo A6600 Plus doesn't have the latest Google apps, Jan 6, Hi KING, Welcome to Google on your new Lenovo A6600 Plus Take the final steps to finish setting up your Lenovo A6600 Plus, and try these official Google apps. Google Maps Beat traffic with real-time.
Google
KING, your new Lenovo A6600 Plus doesn't have the latest Google apps
 - Hi KING, Welcome to Google on your new Lenovo A6600 Plus Take the final steps to finish setting up your Lenovo A6600 Plus, and try these official Google apps. Google Maps Beat traffic with real-time
 Jan 6
Not starred
Google,Security alert, Jan 6, New device signed in to kd19850511@gmail.com Your Google Account was just signed in to from a new Lenovo A6600 Plus device. You're getting this email to make sure it was you. Check activity You.
Google
Security alert
 - New device signed in to kd19850511@gmail.com Your Google Account was just signed in to from a new Lenovo A6600 Plus device. You're getting this email to make sure it was you. Check activity You
Review Activity
 Jan 6
Not starred
unread, Google,Critical security alert for your linked Google Account, 12/24/18, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account.
Google
Critical security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account
 12/24/18
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-134) Scheduling - Vendors add total allowed and total scheduled ex. 5 allowed 3 scheduled 5/3, 12/22/18, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-134 Scheduling - Vendors add total allowed and total scheduled ex. 5 allowed 3 scheduled 5/3 Change By: Peter Hitchcock Assignee:.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-134) Scheduling - Vendors add total allowed and total scheduled ex. 5 allowed 3 scheduled 5/3
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-134 Scheduling - Vendors add total allowed and total scheduled ex. 5 allowed 3 scheduled 5/3 Change By: Peter Hitchcock Assignee:
 12/22/18
Not starred
Peter Hitchcock (Ji. 6,[JIRA] (OTFE-135) Scheduling - Available drivers and Available Vendors should be fixed in place, routes should scroll by, 12/22/18, Peter Hitchcock updated Task OTFE-135 OnTrack FE / Task OTFE-135 Scheduling - Available drivers and Available Vendors should be fixed in place, routes should scroll by Change By: Peter Hitchcock.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-135) Scheduling - Available drivers and Available Vendors should be fixed in place, routes should scroll by
 - Peter Hitchcock updated Task OTFE-135 OnTrack FE / Task OTFE-135 Scheduling - Available drivers and Available Vendors should be fixed in place, routes should scroll by Change By: Peter Hitchcock
 12/22/18
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-138) Scheduling - If vendor number of drivers is decreased for event and drivers are already scheduled highlight vendor in Vendor Schedule red, 12/22/18, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-138 Scheduling - If vendor number of drivers is decreased for event and drivers are already scheduled highlight vendor in Vendor.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-138) Scheduling - If vendor number of drivers is decreased for event and drivers are already scheduled highlight vendor in Vendor Schedule red
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-138 Scheduling - If vendor number of drivers is decreased for event and drivers are already scheduled highlight vendor in Vendor
 12/22/18
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-110) Schedule - Available drivers stationary all routes scroll, 12/22/18, Peter Hitchcock updated an issue OnTrack FE / Task OTFE-110 Schedule - Available drivers stationary all routes scroll Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add Comment Add Comment Get Jira.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-110) Schedule - Available drivers stationary all routes scroll
 - Peter Hitchcock updated an issue OnTrack FE / Task OTFE-110 Schedule - Available drivers stationary all routes scroll Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add Comment Add Comment Get Jira
 12/22/18
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-113) Schedule - route modal show vendors with # of drivers allowed and # scheduled, 12/22/18, Peter Hitchcock updated an issue OnTrack FE / Task OTFE-113 Schedule - route modal show vendors with # of drivers allowed and # scheduled Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add Comment Add.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-113) Schedule - route modal show vendors with # of drivers allowed and # scheduled
 - Peter Hitchcock updated an issue OnTrack FE / Task OTFE-113 Schedule - route modal show vendors with # of drivers allowed and # scheduled Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add Comment Add
 12/22/18
Not starred
Microsoft account t. 2,Microsoft account security code, 12/21/18, Microsoft account Security code Please use the following security code for the Microsoft account kd*****@gmail.com. Security code: 0279161 If you don't recognize the Microsoft account kd*****@gmail.
Microsoft account t. 2
Microsoft account security code
 - Microsoft account Security code Please use the following security code for the Microsoft account kd*****@gmail.com. Security code: 0279161 If you don't recognize the Microsoft account kd*****@gmail
 12/21/18
Not starred
Google,Critical security alert for your linked Google Account, 12/20/18, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account.
Google
Critical security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account
 12/20/18
Not starred
FB Dollars,Your FB Dollars Account Is Pending Approval, 12/19/18, Hey King Dev, Thank you for signing up with FB Dollars. Here is your login info: Username: kd19850511@gmail.com Password: ****** To reset your password, please visit this page: https://fbdollars.com/.
FB Dollars
Your FB Dollars Account Is Pending Approval
 - Hey King Dev, Thank you for signing up with FB Dollars. Here is your login info: Username: kd19850511@gmail.com Password: ****** To reset your password, please visit this page: https://fbdollars.com/
 12/19/18
Not starred
unread, Google,Security alert for your linked Google Account, 12/19/18, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here New sign-in to your linked account ideveloper003@gmail.com.
Google
Security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here New sign-in to your linked account ideveloper003@gmail.com
Review Activity
 12/19/18
Not starred
Google,Security alert, 12/17/18, KING DEV New device signed in to kd19850511@gmail.com Your Google Account was just signed in to from a new Google Emulator device. You're getting this email to make sure it was you. Check activity.
Google
Security alert
 - KING DEV New device signed in to kd19850511@gmail.com Your Google Account was just signed in to from a new Google Emulator device. You're getting this email to make sure it was you. Check activity
Review Activity
 12/17/18
Not starred
unread, Peter Hitchcock (Ji. 5,[JIRA] (OTFE-109) Schedule - Add vendor (associate to event) and remove vendor from event (disassociate), 12/15/18, Peter Hitchcock updated an issue OnTrack FE / Task OTFE-109 Schedule - Add vendor (associate to event) and remove vendor from event (disassociate) Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add.
Peter Hitchcock (Ji. 5
[JIRA] (OTFE-109) Schedule - Add vendor (associate to event) and remove vendor from event (disassociate)
 - Peter Hitchcock updated an issue OnTrack FE / Task OTFE-109 Schedule - Add vendor (associate to event) and remove vendor from event (disassociate) Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add
 12/15/18
Inbox (157) - kd19850511@gmail.com - Gmail
You have turned off the paragraph player. You can turn it on again from the options page.
Conversation opened. 1 unread message.
Compose

Conversations

 
Not starredAd
Amazon Web Services
Ad
AWS for Web Hosting - Flexible, Low Cost Website Hosting. Learn the Benefits of AWS Today.
Not starredAd
GoToMeeting
Ad
Kick Some Business - GoToMeeting is a simple collaboration platform that makes it easier to get work done.

Primary

 
150 of 318
 
Not starred
donotreply,Verify your email address, 1:10 AM, Please verify your email address to complete registration Verify your email address to complete registration Hi Bill, Thanks for your interest in joining Upwork! To complete your registration, we need.
donotreply
Verify your email address
 - Please verify your email address to complete registration Verify your email address to complete registration Hi Bill, Thanks for your interest in joining Upwork! To complete your registration, we need
 1:10 AM
Not starred
Upwork Help Center 2,Upwork Help Center: Your Upwork Account, Jan 17, https://support.upwork.com/hc/requests/23953084 Kate (Upwork Help Center) Jan 17, 10:45 AM CST Hello Willer, Upwork Trust & Safety Team Sincerely, Upwork Trust .
Upwork Help Center 2
Upwork Help Center: Your Upwork Account
 - https://support.upwork.com/hc/requests/23953084 Kate (Upwork Help Center) Jan 17, 10:45 AM CST Hello Willer, Upwork Trust & Safety Team Sincerely, Upwork Trust
View ticket
 Jan 17
Not starred
Peter Hitchcock (Ji. 3,[JIRA] (OTFE-96) Vendor role drivers table action cable, Jan 16, Peter Hitchcock updated OTFE-96 OnTrack FE / OTFE-96 Vendor role drivers table action cable Change By: Peter Hitchcock Status: In Review Backlog Add Comment Get.
Peter Hitchcock (Ji. 3
[JIRA] (OTFE-96) Vendor role drivers table action cable
 - Peter Hitchcock updated OTFE-96 OnTrack FE / OTFE-96 Vendor role drivers table action cable Change By: Peter Hitchcock Status: In Review Backlog Add Comment Get
 Jan 16
Not starred
Peter Hitchcock (Ji. 9,[JIRA] (OTFE-137) Scheduling - Vendor removed from event should also remove all vendors drivers from event, Jan 16, Peter Hitchcock updated OTFE-137 OnTrack FE / OTFE-137 Scheduling - Vendor removed from event should also remove all vendors drivers from event Change By: Peter.
Peter Hitchcock (Ji. 9
[JIRA] (OTFE-137) Scheduling - Vendor removed from event should also remove all vendors drivers from event
 - Peter Hitchcock updated OTFE-137 OnTrack FE / OTFE-137 Scheduling - Vendor removed from event should also remove all vendors drivers from event Change By: Peter
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 7,[JIRA] (OTFE-136) Scheduling - Admin role should be able to schedule vendors on all routes, vendor role should only see routes they can schedule, Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-136 Scheduling - Admin role should be able to schedule vendors on all routes, vendor role should.
Peter Hitchcock (Ji. 7
[JIRA] (OTFE-136) Scheduling - Admin role should be able to schedule vendors on all routes, vendor role should only see routes they can schedule
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-136 Scheduling - Admin role should be able to schedule vendors on all routes, vendor role should
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 4,[JIRA] (OTFE-144) Service request modal add time to close (time open - time to close), Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-144 Service request modal add time to close (time open - time to close) Change By: Peter Hitchco.
Peter Hitchcock (Ji. 4
[JIRA] (OTFE-144) Service request modal add time to close (time open - time to close)
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-144 Service request modal add time to close (time open - time to close) Change By: Peter Hitchco
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-180) Service Request - Update search field text, Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-180 Service Request - Update search field text Change By: Peter Hitchcock Assignee: KING DEV Add.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-180) Service Request - Update search field text
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-180 Service Request - Update search field text Change By: Peter Hitchcock Assignee: KING DEV Add
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-179) Service Request - When toggling off service types it should update Total Requests and Total Value for remaining types, Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-179 Service Request - When toggling off service types it should update Total Requests and Total .
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-179) Service Request - When toggling off service types it should update Total Requests and Total Value for remaining types
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-179 Service Request - When toggling off service types it should update Total Requests and Total
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 3,[JIRA] (OTFE-177) Service Request - map pins should be same color as service type, Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-177 Service Request - map pins should be same color as service type Change By: Peter Hitchcock A.
Peter Hitchcock (Ji. 3
[JIRA] (OTFE-177) Service Request - map pins should be same color as service type
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-177 Service Request - map pins should be same color as service type Change By: Peter Hitchcock A
 Jan 16
Not starred
Peter Hitchcock (Ji. 2,[JIRA] (OTFE-178) Service Request - Edit service type, Jan 16, Peter Hitchcock updated OTFE-178 OnTrack FE / OTFE-178 Service Request - Edit service type Change By: Peter Hitchcock Status: Backlog Selected for Development A.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-178) Service Request - Edit service type
 - Peter Hitchcock updated OTFE-178 OnTrack FE / OTFE-178 Service Request - Edit service type Change By: Peter Hitchcock Status: Backlog Selected for Development A
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-176) Service Request - add count next to service type name ex Fix Tent (3), Jan 16, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-176 Service Request - add count next to service type name ex Fix Tent (3) Change By: Peter Hitch.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-176) Service Request - add count next to service type name ex Fix Tent (3)
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-176 Service Request - add count next to service type name ex Fix Tent (3) Change By: Peter Hitch
 Jan 16
Not starred
Peter Hitchcock (Ji. 2,[JIRA] (OTFE-175) Service Request - not all types are showing in chart, Jan 16, Peter Hitchcock updated OTFE-175 OnTrack FE / OTFE-175 Service Request - not all types are showing in chart Change By: Peter Hitchcock Status: Backlog Selected .
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-175) Service Request - not all types are showing in chart
 - Peter Hitchcock updated OTFE-175 OnTrack FE / OTFE-175 Service Request - not all types are showing in chart Change By: Peter Hitchcock Status: Backlog Selected
 Jan 16
Not starred
unread, Peter Hitchcock (Ji. 9,[JIRA] (OTFE-76) Setup Ingress vs Egress on routes, Jan 16, Peter Hitchcock updated an issue OnTrack FE / OTFE-76 Setup Ingress vs Egress on routes Change By: Peter Hitchcock Fix Version/s: 1.1.2 Fix Version/s: 1.1.3 Add.
Peter Hitchcock (Ji. 9
[JIRA] (OTFE-76) Setup Ingress vs Egress on routes
 - Peter Hitchcock updated an issue OnTrack FE / OTFE-76 Setup Ingress vs Egress on routes Change By: Peter Hitchcock Fix Version/s: 1.1.2 Fix Version/s: 1.1.3 Add
 Jan 16
Not starred
philippe Mudaheranw. 2,You have unread messages about the job Webgl developer, Jan 14, You have unread messages about the job Webgl developer philippe Mudaheranwa 4:17 PM CST, 14 Jan 2019 hello sam, is threejs a licensed engine? I mean is there fe.
philippe Mudaheranw. 2
You have unread messages about the job Webgl developer
 - You have unread messages about the job Webgl developer philippe Mudaheranwa 4:17 PM CST, 14 Jan 2019 hello sam, is threejs a licensed engine? I mean is there fe
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 4,[JIRA] (OTFE-169) Service Request charts - action cable for both, Jan 14, Peter Hitchcock updated an issue OnTrack FE / OTFE-169 Service Request charts - action cable for both Change By: Peter Hitchcock Summary: Service Request charts.
Peter Hitchcock (Ji. 4
[JIRA] (OTFE-169) Service Request charts - action cable for both
 - Peter Hitchcock updated an issue OnTrack FE / OTFE-169 Service Request charts - action cable for both Change By: Peter Hitchcock Summary: Service Request charts
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 5,[JIRA] (OTFE-157) Messaging - messaging camper is sending reservation id not camper id, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-157 Messaging - messaging camper is sending reservation id not camper id Change By: Peter Hitchc.
Peter Hitchcock (Ji. 5
[JIRA] (OTFE-157) Messaging - messaging camper is sending reservation id not camper id
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-157 Messaging - messaging camper is sending reservation id not camper id Change By: Peter Hitchc
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 4,[JIRA] (OTFE-147) Service request - add value on create, this is an optional field see api /api/service_request_types, Jan 14, Peter Hitchcock updated an issue OnTrack FE / OTFE-147 Service request - add value on create, this is an optional field see api /api/service_request_types Chang.
Peter Hitchcock (Ji. 4
[JIRA] (OTFE-147) Service request - add value on create, this is an optional field see api /api/service_request_types
 - Peter Hitchcock updated an issue OnTrack FE / OTFE-147 Service request - add value on create, this is an optional field see api /api/service_request_types Chang
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-168) Service Request - Add Service Request, request type needs to be dynamic, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-168 Service Request - Add Service Request, request type needs to be dynamic Change By: Peter Hit.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-168) Service Request - Add Service Request, request type needs to be dynamic
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-168 Service Request - Add Service Request, request type needs to be dynamic Change By: Peter Hit
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-170) Service Request - Map view remove toggles add dropdown filter, map pins same color as service request color, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-170 Service Request - Map view remove toggles add dropdown filter, map pins same color as servic.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-170) Service Request - Map view remove toggles add dropdown filter, map pins same color as service request color
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-170 Service Request - Map view remove toggles add dropdown filter, map pins same color as servic
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-171) Service Request - add type color picker is loading higher than the model and we can't select a color, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-171 Service Request - add type color picker is loading higher than the model and we can't select.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-171) Service Request - add type color picker is loading higher than the model and we can't select a color
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-171 Service Request - add type color picker is loading higher than the model and we can't select
 Jan 14
Not starred
unread, Peter Hitchcock (Ji. 9,[JIRA] (OTFE-145) Service Requests - Update chart with counts of each service type, update Average time chart, Jan 14, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-145 Service Requests - Update chart with counts of each service type, update Average time chart .
Peter Hitchcock (Ji. 9
[JIRA] (OTFE-145) Service Requests - Update chart with counts of each service type, update Average time chart
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / OTFE-145 Service Requests - Update chart with counts of each service type, update Average time chart
 Jan 14
Not starred
Upwork Help Center 5,Upwork Help Center: Your Upwork Account, Jan 13, https://support.upwork.com/hc/requests/23908737 Cris (Upwork Help Center) Jan 13, 10:19 PM CST Hello Chase, [V0V3D0-6RM8].
Upwork Help Center 5
Upwork Help Center: Your Upwork Account
 - https://support.upwork.com/hc/requests/23908737 Cris (Upwork Help Center) Jan 13, 10:19 PM CST Hello Chase, [V0V3D0-6RM8]
View ticket
 Jan 13
Not starred
Upwork Help Center 2,Upwork Help Center: Your Upwork account has been suspended, Jan 13, https://support.upwork.com/hc/requests/23903135 Jan 13, 10:03 AM CST Dear Ryan, [V0V383-R959].
Upwork Help Center 2
Upwork Help Center: Your Upwork account has been suspended
 - https://support.upwork.com/hc/requests/23903135 Jan 13, 10:03 AM CST Dear Ryan, [V0V383-R959]
View ticket
 Jan 13
Not starred
unread, Upwork Notification 5,Your request to join Upwork, Jan 11, Hi Chris, Thank you for your interest in joining Upwork. We have reviewed your application to join, and regret to inform you that we are unable to accept your U.
Upwork Notification 5
Your request to join Upwork
 - Hi Chris, Thank you for your interest in joining Upwork. We have reviewed your application to join, and regret to inform you that we are unable to accept your U
 Jan 11
Not starred
Upwork Help Center 5,Upwork Help Center: Your Upwork Account, Jan 11, https://support.upwork.com/hc/requests/23877035 Hello Tony, [XZ4RR6-482K].
Upwork Help Center 5
Upwork Help Center: Your Upwork Account
 - https://support.upwork.com/hc/requests/23877035 Hello Tony, [XZ4RR6-482K]
View ticket
 Jan 11
Not starred
donotreply 2,Verify your email address, Jan 11, Verify your email address to complete registration Hi Ryan, Thanks for your interest in joining Upwork! To complete your registration, we need you to verify you.
donotreply 2
Verify your email address
 - Verify your email address to complete registration Hi Ryan, Thanks for your interest in joining Upwork! To complete your registration, we need you to verify you
 Jan 11
Not starred
unread, support 4,Atlassian Bitbucket Incident - Bitbucket webhooks experiencing delays - 10 January 2019, Jan 10, Investigating - 2 components affected - Bitbucket Webhooks are experiencing delays.... ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌.
support 4
Atlassian Bitbucket Incident - Bitbucket webhooks experiencing delays - 10 January 2019
 - Investigating - 2 components affected - Bitbucket Webhooks are experiencing delays.... ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌
 Jan 10
Not starred
donotreply 2,Verify your email address, Jan 10, Please verify your email address to complete registration Verify your email address to complete registration Hi Kyle, Thanks for your interest in joining Upwork! To complete your registration, we need.
donotreply 2
Verify your email address
 - Please verify your email address to complete registration Verify your email address to complete registration Hi Kyle, Thanks for your interest in joining Upwork! To complete your registration, we need
 Jan 10
Not starred
Upwork Notification 5,Your request to join Upwork, Jan 9, Hi Jack, Thank you for your interest in joining Upwork. We have reviewed your application to join, and regret to inform you that we are unable to accept your Upwork freelancer registration at this time.
Upwork Notification 5
Your request to join Upwork
 - Hi Jack, Thank you for your interest in joining Upwork. We have reviewed your application to join, and regret to inform you that we are unable to accept your Upwork freelancer registration at this time
 Jan 9
Not starred
Google,Critical security alert for your linked Google Account, Jan 9, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account.
Google
Critical security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account
 Jan 9
Not starred
Google,Security alert for your linked Google Account, Jan 9, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here New sign-in to your linked account ideveloper003@gmail.com.
Google
Security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here New sign-in to your linked account ideveloper003@gmail.com
 Jan 9
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-147) Service request - add value on create, Jan 8, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-147 Service request - add value on create Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment Get Jira.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-147) Service request - add value on create
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-147 Service request - add value on create Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment Get Jira
 Jan 8
Not starred
unread, Peter Hitchcock (Ji. 2,[JIRA] (OTFE-169) Service Request charts - action cable, Jan 8, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-169 Service Request charts - action cable Change By: Peter Hitchcock Assignee: Contact SFS KING DEV Add Comment Add Comment Get Jira.
Peter Hitchcock (Ji. 2
[JIRA] (OTFE-169) Service Request charts - action cable
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-169 Service Request charts - action cable Change By: Peter Hitchcock Assignee: Contact SFS KING DEV Add Comment Add Comment Get Jira
 Jan 8
Not starred
Chioma First,Fake USA Passport PSD Template, Jan 8, Please I got ur email from this website(http://leakforums.blogspot.com/2017/01/all-country-fake-psd-files-21-gb.html) Please I need USA USA Passport PSD editable. Reply to me pls.
Chioma First
Fake USA Passport PSD Template
 - Please I got ur email from this website(http://leakforums.blogspot.com/2017/01/all-country-fake-psd-files-21-gb.html) Please I need USA USA Passport PSD editable. Reply to me pls
 Jan 8
Not starred
unread, Peter Hitchcock (Ji. 8,[JIRA] (OTFE-133) Vendors - Add button like scheduling to associate vendor, Jan 7, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-133 Vendors - Add button like scheduling to associate vendor Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment.
Peter Hitchcock (Ji. 8
[JIRA] (OTFE-133) Vendors - Add button like scheduling to associate vendor
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-133 Vendors - Add button like scheduling to associate vendor Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment
 Jan 7
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-152) Scheduling error, Jan 7, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Bug OTFE-152 Scheduling error Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment Get Jira notifications on your phone!.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-152) Scheduling error
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Bug OTFE-152 Scheduling error Change By: Peter Hitchcock Assignee: KING DEV Add Comment Add Comment Get Jira notifications on your phone!
 Jan 7
Not starred
Google,KING, your new Lenovo A6600 Plus doesn't have the latest Google apps, Jan 6, Hi KING, Welcome to Google on your new Lenovo A6600 Plus Take the final steps to finish setting up your Lenovo A6600 Plus, and try these official Google apps. Google Maps Beat traffic with real-time.
Google
KING, your new Lenovo A6600 Plus doesn't have the latest Google apps
 - Hi KING, Welcome to Google on your new Lenovo A6600 Plus Take the final steps to finish setting up your Lenovo A6600 Plus, and try these official Google apps. Google Maps Beat traffic with real-time
 Jan 6
Not starred
Google,Security alert, Jan 6, New device signed in to kd19850511@gmail.com Your Google Account was just signed in to from a new Lenovo A6600 Plus device. You're getting this email to make sure it was you. Check activity You.
Google
Security alert
 - New device signed in to kd19850511@gmail.com Your Google Account was just signed in to from a new Lenovo A6600 Plus device. You're getting this email to make sure it was you. Check activity You
Review Activity
 Jan 6
Not starred
unread, Google,Critical security alert for your linked Google Account, 12/24/18, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account.
Google
Critical security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account
 12/24/18
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-134) Scheduling - Vendors add total allowed and total scheduled ex. 5 allowed 3 scheduled 5/3, 12/22/18, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-134 Scheduling - Vendors add total allowed and total scheduled ex. 5 allowed 3 scheduled 5/3 Change By: Peter Hitchcock Assignee:.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-134) Scheduling - Vendors add total allowed and total scheduled ex. 5 allowed 3 scheduled 5/3
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-134 Scheduling - Vendors add total allowed and total scheduled ex. 5 allowed 3 scheduled 5/3 Change By: Peter Hitchcock Assignee:
 12/22/18
Not starred
Peter Hitchcock (Ji. 6,[JIRA] (OTFE-135) Scheduling - Available drivers and Available Vendors should be fixed in place, routes should scroll by, 12/22/18, Peter Hitchcock updated Task OTFE-135 OnTrack FE / Task OTFE-135 Scheduling - Available drivers and Available Vendors should be fixed in place, routes should scroll by Change By: Peter Hitchcock.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-135) Scheduling - Available drivers and Available Vendors should be fixed in place, routes should scroll by
 - Peter Hitchcock updated Task OTFE-135 OnTrack FE / Task OTFE-135 Scheduling - Available drivers and Available Vendors should be fixed in place, routes should scroll by Change By: Peter Hitchcock
 12/22/18
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-138) Scheduling - If vendor number of drivers is decreased for event and drivers are already scheduled highlight vendor in Vendor Schedule red, 12/22/18, Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-138 Scheduling - If vendor number of drivers is decreased for event and drivers are already scheduled highlight vendor in Vendor.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-138) Scheduling - If vendor number of drivers is decreased for event and drivers are already scheduled highlight vendor in Vendor Schedule red
 - Peter Hitchcock assigned an issue to KING DEV OnTrack FE / Task OTFE-138 Scheduling - If vendor number of drivers is decreased for event and drivers are already scheduled highlight vendor in Vendor
 12/22/18
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-110) Schedule - Available drivers stationary all routes scroll, 12/22/18, Peter Hitchcock updated an issue OnTrack FE / Task OTFE-110 Schedule - Available drivers stationary all routes scroll Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add Comment Add Comment Get Jira.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-110) Schedule - Available drivers stationary all routes scroll
 - Peter Hitchcock updated an issue OnTrack FE / Task OTFE-110 Schedule - Available drivers stationary all routes scroll Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add Comment Add Comment Get Jira
 12/22/18
Not starred
unread, Peter Hitchcock (Ji. 6,[JIRA] (OTFE-113) Schedule - route modal show vendors with # of drivers allowed and # scheduled, 12/22/18, Peter Hitchcock updated an issue OnTrack FE / Task OTFE-113 Schedule - route modal show vendors with # of drivers allowed and # scheduled Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add Comment Add.
Peter Hitchcock (Ji. 6
[JIRA] (OTFE-113) Schedule - route modal show vendors with # of drivers allowed and # scheduled
 - Peter Hitchcock updated an issue OnTrack FE / Task OTFE-113 Schedule - route modal show vendors with # of drivers allowed and # scheduled Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add Comment Add
 12/22/18
Not starred
Microsoft account t. 2,Microsoft account security code, 12/21/18, Microsoft account Security code Please use the following security code for the Microsoft account kd*****@gmail.com. Security code: 0279161 If you don't recognize the Microsoft account kd*****@gmail.
Microsoft account t. 2
Microsoft account security code
 - Microsoft account Security code Please use the following security code for the Microsoft account kd*****@gmail.com. Security code: 0279161 If you don't recognize the Microsoft account kd*****@gmail
 12/21/18
Not starred
Google,Critical security alert for your linked Google Account, 12/20/18, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account.
Google
Critical security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here Sign-in attempt was blocked for your linked Google Account
 12/20/18
Not starred
FB Dollars,Your FB Dollars Account Is Pending Approval, 12/19/18, Hey King Dev, Thank you for signing up with FB Dollars. Here is your login info: Username: kd19850511@gmail.com Password: ****** To reset your password, please visit this page: https://fbdollars.com/.
FB Dollars
Your FB Dollars Account Is Pending Approval
 - Hey King Dev, Thank you for signing up with FB Dollars. Here is your login info: Username: kd19850511@gmail.com Password: ****** To reset your password, please visit this page: https://fbdollars.com/
 12/19/18
Not starred
unread, Google,Security alert for your linked Google Account, 12/19/18, Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here New sign-in to your linked account ideveloper003@gmail.com.
Google
Security alert for your linked Google Account
 - Your account kd19850511@gmail.com is listed as the recovery email for ideveloper003@gmail.com. Don't recognize this account? Click here New sign-in to your linked account ideveloper003@gmail.com
Review Activity
 12/19/18
Not starred
Google,Security alert, 12/17/18, KING DEV New device signed in to kd19850511@gmail.com Your Google Account was just signed in to from a new Google Emulator device. You're getting this email to make sure it was you. Check activity.
Google
Security alert
 - KING DEV New device signed in to kd19850511@gmail.com Your Google Account was just signed in to from a new Google Emulator device. You're getting this email to make sure it was you. Check activity
Review Activity
 12/17/18
Not starred
unread, Peter Hitchcock (Ji. 5,[JIRA] (OTFE-109) Schedule - Add vendor (associate to event) and remove vendor from event (disassociate), 12/15/18, Peter Hitchcock updated an issue OnTrack FE / Task OTFE-109 Schedule - Add vendor (associate to event) and remove vendor from event (disassociate) Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add.
Peter Hitchcock (Ji. 5
[JIRA] (OTFE-109) Schedule - Add vendor (associate to event) and remove vendor from event (disassociate)
 - Peter Hitchcock updated an issue OnTrack FE / Task OTFE-109 Schedule - Add vendor (associate to event) and remove vendor from event (disassociate) Change By: Peter Hitchcock Fix Version/s: 1.1.2 Add
 12/15/18
Search
Clear search
Close search
Google apps
Notifications
Google Account
KING DEV
kd19850511@gmail.com
Main menu
\ No newline at end of file diff --git a/test/html/google.html b/test/assets/html/google.html similarity index 99% rename from test/html/google.html rename to test/assets/html/google.html index 095cc87..1218a0a 100644 --- a/test/html/google.html +++ b/test/assets/html/google.html @@ -1,9 +1,9 @@ -
Search Google or type a URL
Customise this page
Chrome backgrounds
Upload an image
Restore default background

Select a collection
Connection error
Connection error.
More info
Backgrounds are unavailable. Try again later.
Back
selected
Add shortcut
Edit shortcut
Name
URL
Remove
Cancel
Done
Type a valid URL
Shortcut removed
Shortcut edited
Shortcut added
Can’t create shortcut
Can’t edit shortcut
Can’t remove shortcut
\ No newline at end of file diff --git a/test/html/hillcrestpartyrentals.html b/test/assets/html/hillcrestpartyrentals.html similarity index 98% rename from test/html/hillcrestpartyrentals.html rename to test/assets/html/hillcrestpartyrentals.html index 96c19e7..f095f48 100644 --- a/test/html/hillcrestpartyrentals.html +++ b/test/assets/html/hillcrestpartyrentals.html @@ -1,588 +1,588 @@ - - - - - - - Hillcrest Party Rentals - Offering Tents, Chairs, Tables, Lighting, Linens, China, Glassware, Silverware, - Trays, Heaters and more for your Events, Weddings and Other Occasions - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - -
-
-
- - - - - - -
-

- -

-

- Your - #1 Party Rental source for all Outdoor Events, Tents & Canopies, - - Weddings - , Cateting Equipment, Lighting and more! -

-
-
-
-
-
-
- - - - - - - - - - - - - - - - -
  -
-
- - - - - -
-

- - HillCrest Party Rentals -

-
-
- - - - - - - - - - - - - - - - - - - - - - - -
 
-

Want - to plan an event or have questions? Call Now!       - -

-

- -

-

- 3507 Motor Avenue - Los Angeles, CA 90034     - -

-

  -

-

  -

-

- - -

-

- - -

-

- - -

 
-
-
-
-
-
-
-
-   
-
  
  -
-
- - - - - - - - - - - - - - -
- - -
- -
- -
- -
-
-
-
 
  -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
Our PRODUCT - CATALOG
-  
  - - - - Chairs - -
  - - - - Tables - -
  - - - - Linens & - Napkins - - -
  - - - - China & - Chargers - - -
  - - - - Glassware - -
  - - - - Flatware - -
  - - - - Buffett & - Serving - -
  - - - - Wedding & - Garden - -
    - - - - Full Catalog - -
-
-
-
-

- ...serving Los - Angeles area since 1984 from their facility located at Motor - Ave and Palms Ave. HillCrest Party Rentals is a family owned business originating - with Irving Sanshuck with business experience, Marilyn - Sanshuck owner of The Paper Rainbow and Dorothy Levinson had a - successful greeting card company and Bernie Sanshuck, manager - and customer service at D&B Card Company.
-
- - - more About US - -
-

 
-

- -

We have the PARTY RENTALS for all - Events & Occasions!
-

-           -           -           - -

 
  - Providing - Party Rental Supplies to the city of Los Angeles Including: -
-
-
- - - - - - - - - - - - -
-

- - Beverly Hills
- Malibu
- Bel Air
- Culver City
- West Los Angeles
-

-

- -

-

- - Santa Monica
- Manhattan Beach
- Redondo Beach
- South Bay
- Marina Del Rey
-

-

- -

-

- - Playa Del Rey
- Pacific Palisades
- Encino
- Tarzana
- Sherman Oaks
-

-

- -

-

- - Studio City Pasadena
- San Marino
- Cheviot Hills
- Westlake Village
-

-

- -

-

- - Valley Village
- Westchester
- Playa Vista
- Del Rey
- Venice
-

-
-
-
-
-
- - - - - -
-

- Follow us:   - -

- -
-
-
-
-
-
- - - - - - - - - - - - - - - - -
-

- - LA Party Rentals - -

- - Wedding Party - Rentals - Outdoor - Events Party Rentals
-

Tents & Canopies Rentals -

  
   
-
-
-
-
-
-
 
-
-
-
-
-
- - - - - - -
-

- -

-

- - - HOME -   - |  - ABOUT US -   |  - - PRODUCT CATALOG -   |  - - SERVICES -   |  - - EVENT GALLERY -   |  - - SERVICE REQUEST -   - |  - CONTACT US - -

-
-
-
-
-

- Copyright © - 2013 Hillcrest Party Rentals. All rights reserved. Designed by Kt - Designing Inc. -

-
-
- - - + + + + + + + Hillcrest Party Rentals - Offering Tents, Chairs, Tables, Lighting, Linens, China, Glassware, Silverware, + Trays, Heaters and more for your Events, Weddings and Other Occasions + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + +
+
+
+ + + + + + +
+

+ +

+

+ Your + #1 Party Rental source for all Outdoor Events, Tents & Canopies, + + Weddings + , Cateting Equipment, Lighting and more! +

+
+
+
+
+
+
+ + + + + + + + + + + + + + + + +
  +
+
+ + + + + +
+

+ + HillCrest Party Rentals +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
 
+

Want + to plan an event or have questions? Call Now!       + +

+

+ +

+

+ 3507 Motor Avenue + Los Angeles, CA 90034     + +

+

  +

+

  +

+

+ + +

+

+ + +

+

+ + +

 
+
+
+
+
+
+
+
+   
+
  
  +
+
+ + + + + + + + + + + + + + +
+ + +
+ +
+ +
+ +
+
+
+
 
  +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
Our PRODUCT + CATALOG
+  
  + + + + Chairs + +
  + + + + Tables + +
  + + + + Linens & + Napkins + + +
  + + + + China & + Chargers + + +
  + + + + Glassware + +
  + + + + Flatware + +
  + + + + Buffett & + Serving + +
  + + + + Wedding & + Garden + +
    + + + + Full Catalog + +
+
+
+
+

+ ...serving Los + Angeles area since 1984 from their facility located at Motor + Ave and Palms Ave. HillCrest Party Rentals is a family owned business originating + with Irving Sanshuck with business experience, Marilyn + Sanshuck owner of The Paper Rainbow and Dorothy Levinson had a + successful greeting card company and Bernie Sanshuck, manager + and customer service at D&B Card Company.
+
+ + + more About US + +
+

 
+

+ +

We have the PARTY RENTALS for all + Events & Occasions!
+

+           +           +           + +

 
  + Providing + Party Rental Supplies to the city of Los Angeles Including: +
+
+
+ + + + + + + + + + + + +
+

+ + Beverly Hills
+ Malibu
+ Bel Air
+ Culver City
+ West Los Angeles
+

+

+ +

+

+ + Santa Monica
+ Manhattan Beach
+ Redondo Beach
+ South Bay
+ Marina Del Rey
+

+

+ +

+

+ + Playa Del Rey
+ Pacific Palisades
+ Encino
+ Tarzana
+ Sherman Oaks
+

+

+ +

+

+ + Studio City Pasadena
+ San Marino
+ Cheviot Hills
+ Westlake Village
+

+

+ +

+

+ + Valley Village
+ Westchester
+ Playa Vista
+ Del Rey
+ Venice
+

+
+
+
+
+
+ + + + + +
+

+ Follow us:   + +

+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + +
+

+ + LA Party Rentals + +

+ + Wedding Party + Rentals + Outdoor + Events Party Rentals
+

Tents & Canopies Rentals +

  
   
+
+
+
+
+
+
 
+
+
+
+
+
+ + + + + + +
+

+ +

+

+ + + HOME +   + |  + ABOUT US +   |  + + PRODUCT CATALOG +   |  + + SERVICES +   |  + + EVENT GALLERY +   |  + + SERVICE REQUEST +   + |  + CONTACT US + +

+
+
+
+
+

+ Copyright © + 2013 Hillcrest Party Rentals. All rights reserved. Designed by Kt + Designing Inc. +

+
+
+ + + \ No newline at end of file diff --git a/test/html/incomplete-script b/test/assets/html/incomplete-script similarity index 100% rename from test/html/incomplete-script rename to test/assets/html/incomplete-script diff --git a/test/html/nice.html b/test/assets/html/nice.html similarity index 100% rename from test/html/nice.html rename to test/assets/html/nice.html diff --git a/test/html/tables.html b/test/assets/html/tables.html similarity index 100% rename from test/html/tables.html rename to test/assets/html/tables.html diff --git a/test/html/view-source_https___epicentrk.ua_shop_kirpich-ogneupornyy_.html b/test/assets/html/view-source_https___epicentrk.ua_shop_kirpich-ogneupornyy_.html similarity index 99% rename from test/html/view-source_https___epicentrk.ua_shop_kirpich-ogneupornyy_.html rename to test/assets/html/view-source_https___epicentrk.ua_shop_kirpich-ogneupornyy_.html index 83805ef..d690dc1 100644 --- a/test/html/view-source_https___epicentrk.ua_shop_kirpich-ogneupornyy_.html +++ b/test/assets/html/view-source_https___epicentrk.ua_shop_kirpich-ogneupornyy_.html @@ -4875,10 +4875,10 @@