├── .gitignore ├── LICENSE ├── README.md ├── bin └── pfdparser ├── index.js ├── lib ├── domparsermock.js ├── filing.js ├── parser.js └── spec.js ├── package.json ├── swagger.yaml ├── test ├── data │ ├── Donnelly, Sally.pdf │ ├── Kushner, Jared.pdf │ └── Mashburn, Lori K.pdf └── test.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | test/data/**/*.csv -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 The Center for Public Integrity 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Parses public financial disclosure data from OGE form 278e. 2 | 3 | ## Installation 4 | 5 | ```sh 6 | npm i -g github:publici/pfd-parser 7 | ``` 8 | 9 | ## Usage 10 | 11 | ```sh 12 | pfdparser /path/to/filings/ /path/to/data/folder/ 13 | ``` 14 | 15 | ## Input 16 | 17 | Takes a single or a folder full of OGE 278e disclosure PDFs as input. You can find [many here](https://extapps2.oge.gov/201/Presiden.nsf/PAS%20Filings%20by%20Date?OpenView). Also handles 278s from FDM or FDonline. Does not handle scanned paper or non-standard PDFs. 18 | 19 | ## Output 20 | 21 | Outputs up to 10 CSVs with data from the disclosure files. The format is (briefly) documented here. 22 | 23 | Entries should be read with the employee's separate ethics agreement and the endnotes included in the final table, which often indicate whether the employee intends to divest the asset upon entering government. 24 | 25 | ### 1. Filer's Positions Held Outside United States Government 26 | filer-s-positions-held-outside-united-states-government.csv 27 | 28 | | Column | 29 | | ---- | 30 | | # | 31 | | organization-name | 32 | | city-state | 33 | | organization-type | 34 | | position-held | 35 | | from | 36 | | to | 37 | 38 | ### 2. Filer's Employment Assets & Income and Retirement Accounts 39 | filer-s-employment-assets-&-income-and-retirement-accounts.csv 40 | 41 | | Column | 42 | | ---- | 43 | | # | 44 | | description | 45 | | eif | 46 | | value | 47 | | income-type | 48 | | income-amount | 49 | 50 | ### 3. Filer's Employment Agreements and Arrangements 51 | filer-s-employment-agreements-and-arrangements.csv 52 | 53 | | Column | 54 | | ---- | 55 | | # | 56 | | employer-or-party | 57 | | city-state | 58 | | status-and-terms | 59 | | date | 60 | 61 | ### 4. Filers Sources of Compensation Exceeding $5,000 in a Year 62 | filer-s-sources-of-compensation-exceeding-$5-000-in-a-year.csv 63 | 64 | | Column | 65 | | ---- | 66 | | # | 67 | | source-name | 68 | | city-state | 69 | | brief-description-of-duties | 70 | 71 | ### 5. Spouse's Employment Assets & Income and Retirement accounts 72 | spouse-s-employment-assets-&-income-and-retirement-accounts.csv 73 | 74 | | Column | 75 | | ---- | 76 | | # | 77 | | description | 78 | | eif | 79 | | value | 80 | | income-type | 81 | | income-amount | 82 | 83 | ### 6. Other Assets and Income 84 | other-assets-and-income.csv 85 | 86 | | Column | 87 | | ---- | 88 | | # | 89 | | description | 90 | | eif | 91 | | value | 92 | | income-type | 93 | | income-amount | 94 | 95 | ### 7. Transactions 96 | transactions.csv 97 | 98 | | Column | 99 | | ---- | 100 | | # | 101 | | description | 102 | | type | 103 | | date | 104 | | amount | 105 | 106 | ### 8. Liabilities 107 | liabilities.csv 108 | 109 | | Column | 110 | | ---- | 111 | | # | 112 | | creditor-name | 113 | | type | 114 | | amount | 115 | | year-incurred | 116 | | rate | 117 | | term | 118 | 119 | ### 9. Gifts and Travel Reimbursements 120 | gifts-and-travel-reimbursements.csv 121 | 122 | | Column | 123 | | ---- | 124 | | # | 125 | | source-name | 126 | | city-state | 127 | | brief-description | 128 | | value | 129 | 130 | ### Endnotes 131 | endnotes.csv 132 | 133 | | Column | 134 | | ---- | 135 | | part | 136 | | # | 137 | | endnote | -------------------------------------------------------------------------------- /bin/pfdparser: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var _ = require('highland'), 4 | program = require('commander'), 5 | pkg = require('../package.json'), 6 | parser = require('../'), 7 | fs = require('fs'); 8 | 9 | program 10 | .version(pkg.version); 11 | 12 | program 13 | .usage(' ') 14 | .action((filingsPath, dataPath, options) => { 15 | console.log('file,lines'); 16 | 17 | _(parser(filingsPath)) 18 | .flatten() 19 | .flatMap(filing => _(filing.save(dataPath)) ) 20 | .each(filing => console.log('"' + filing.file + '",' + filing.count)) 21 | .done(() => {}); 22 | }); 23 | 24 | program.parse(process.argv); 25 | 26 | if (!process.argv.slice(2).length) { 27 | program.outputHelp(); 28 | } 29 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = require('./lib/parser'); 3 | -------------------------------------------------------------------------------- /lib/domparsermock.js: -------------------------------------------------------------------------------- 1 | /* Any copyright is dedicated to the Public Domain. 2 | * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 | 4 | // Dummy XML Parser 5 | 6 | function DOMNodeMock(nodeName, nodeValue) { 7 | this.nodeName = nodeName; 8 | this.nodeValue = nodeValue; 9 | Object.defineProperty(this, 'parentNode', {value: null, writable: true}); 10 | } 11 | DOMNodeMock.prototype = { 12 | get firstChild() { 13 | return this.childNodes[0]; 14 | }, 15 | get nextSibling() { 16 | var index = this.parentNode.childNodes.indexOf(this); 17 | return this.parentNode.childNodes[index + 1]; 18 | }, 19 | get textContent() { 20 | if (!this.childNodes) { 21 | return this.nodeValue || ''; 22 | } 23 | return this.childNodes.map(function (child) { 24 | return child.textContent; 25 | }).join(''); 26 | }, 27 | hasChildNodes: function () { 28 | return this.childNodes && this.childNodes.length > 0; 29 | } 30 | }; 31 | 32 | function decodeXML(text) { 33 | if (text.indexOf('&') < 0) { 34 | return text; 35 | } 36 | return text.replace(/&(#(x[0-9a-f]+|\d+)|\w+);/gi, function (all, entityName, number) { 37 | if (number) { 38 | return String.fromCharCode(number[0] === 'x' ? parseInt(number.substring(1), 16) : +number); 39 | } 40 | switch (entityName) { 41 | case 'amp': 42 | return '&'; 43 | case 'lt': 44 | return '<'; 45 | case 'gt': 46 | return '>'; 47 | case 'quot': 48 | return '\"'; 49 | case 'apos': 50 | return '\''; 51 | } 52 | return '&' + entityName + ';'; 53 | }); 54 | } 55 | 56 | function DOMParserMock() {}; 57 | DOMParserMock.prototype = { 58 | parseFromString: function (content) { 59 | content = content.replace(/<\?[\s\S]*?\?>|/g, '').trim(); 60 | var nodes = []; 61 | content = content.replace(/>([\s\S]+?)<'; // ignoring whitespaces 67 | } 68 | return '>' + i + ',<'; 69 | }); 70 | content = content.replace(//g, function (all, text) { 71 | var i = nodes.length; 72 | var node = new DOMNodeMock('#text', text); 73 | nodes.push(node); 74 | return i + ','; 75 | }); 76 | var lastLength; 77 | do { 78 | lastLength = nodes.length; 79 | content = content.replace(/<([\w\:]+)((?:[\s\w:=]|'[^']*'|"[^"]*")*)(?:\/>|>([\d,]*)<\/[^>]+>)/g, 80 | function (all, name, attrs, content) { 81 | var i = nodes.length; 82 | var node = new DOMNodeMock(name); 83 | var children = []; 84 | if (content) { 85 | content = content.split(','); 86 | content.pop(); 87 | content.forEach(function (child) { 88 | var childNode = nodes[+child]; 89 | childNode.parentNode = node; 90 | children.push(childNode); 91 | }) 92 | } 93 | node.childNodes = children; 94 | nodes.push(node); 95 | return i + ','; 96 | 97 | }); 98 | } while(lastLength < nodes.length); 99 | return { 100 | documentElement: nodes.pop() 101 | }; 102 | } 103 | }; 104 | 105 | exports.DOMParserMock = DOMParserMock; 106 | -------------------------------------------------------------------------------- /lib/filing.js: -------------------------------------------------------------------------------- 1 | const dsv = require('d3-dsv'), 2 | fs = require('fs'), 3 | clone = require('lodash.clonedeep'); 4 | 5 | class Filing { 6 | constructor(file) { 7 | this.file = null; 8 | this.tables = []; 9 | this.count = 0; 10 | } 11 | 12 | // does save belong in Filing or somewhere else? 13 | save(dataPath) { 14 | let filing = this; 15 | 16 | return new Promise((resolve, reject) => { 17 | clone(this.tables).forEach(table => { 18 | const csvFile = `${dataPath + table.name.toLowerCase().replace(/[ ,']+/g, '-')}.csv`; 19 | 20 | table.rows.forEach((row) => { 21 | row.file = filing.file; 22 | }); 23 | 24 | const columns = ['file'].concat(Object.keys(table.cols)); 25 | let csvString = dsv.csvFormat(table.rows, columns); 26 | 27 | let exists = fs.existsSync(csvFile); 28 | 29 | if (exists) { 30 | csvString = csvString.substring(csvString.indexOf('\n') + 1); 31 | } 32 | 33 | fs.appendFileSync(csvFile, `${csvString}\n`); 34 | 35 | this.count += table.rows.length; 36 | }); 37 | 38 | resolve(filing); 39 | }); 40 | } 41 | } 42 | 43 | module.exports = Filing; 44 | -------------------------------------------------------------------------------- /lib/parser.js: -------------------------------------------------------------------------------- 1 | const _ = require('highland'), 2 | Filing = require('./filing'), 3 | spec = require('./spec'), 4 | vfs = require('vinyl-fs'), 5 | Vinyl = require('vinyl'), 6 | clone = require('lodash.clonedeep'); 7 | 8 | global.DOMParser = require('./domparsermock.js').DOMParserMock; 9 | 10 | var pdfjs = require('pdfjs-dist'); 11 | 12 | function parser(files) { 13 | let file = null, 14 | filing = null, 15 | curTable = null, 16 | viewport = null, 17 | fdOnline = false, 18 | rowY = 0; 19 | 20 | function getSlug (str) { 21 | return str.toLowerCase().replace(/[ ,/]+/g, '-'); 22 | } 23 | 24 | function getDefinition(str) { 25 | return new Promise((resolve, reject) => { 26 | _.values(spec.definitions) 27 | .find((def) => 28 | def.title.toLowerCase() == str.toLowerCase() || 29 | (def.aliases && def.aliases.indexOf(str) !== -1)) 30 | .stopOnError(reject) 31 | .apply((def) => { 32 | resolve(def) 33 | }); 34 | }); 35 | } 36 | 37 | function getHeaderParts(name) { 38 | const headerParts = name.split('. '); 39 | 40 | let part = null; 41 | 42 | if (headerParts.length > 1) { 43 | part = parseInt(headerParts[0]); 44 | name = headerParts.slice(1).join('. '); 45 | } 46 | 47 | return { 48 | name, 49 | part 50 | }; 51 | } 52 | 53 | function getFirstColumn(table) { 54 | return Object.keys(table.cols)[0]; 55 | } 56 | 57 | function within(a,b,distance) { 58 | return a+distance > b && a-distance < b; 59 | } 60 | 61 | function processItem(item) { 62 | if (item.fontName == 'Helvetica') { 63 | fdOnline = true; 64 | } 65 | 66 | return getDefinition(item.str) 67 | .then((def) => { 68 | return new Promise((resolve, reject) => { 69 | let firstCol = null; 70 | if (curTable) { 71 | firstCol = getFirstColumn(curTable); 72 | } 73 | 74 | // table header 75 | if (typeof def !== 'undefined' && def) { 76 | let table = getHeaderParts(def.title); 77 | 78 | table.cols = clone(def.properties); 79 | table.rows = []; 80 | table.items = []; 81 | 82 | curTable = table; 83 | 84 | filing.tables.push(table); 85 | } 86 | // table column headers 87 | else if ((firstCol && firstCol.toUpperCase() == item.str && 88 | item.x < 100) || 89 | (curTable && curTable.cols[firstCol].y && 90 | within(curTable.cols[firstCol].y,item.y,2))) { 91 | if (firstCol && firstCol.toUpperCase() == item.str) { 92 | Object.keys(curTable.cols) 93 | .forEach((key) => { 94 | delete curTable.cols[key].x; 95 | delete curTable.cols[key].y; 96 | }); 97 | } 98 | 99 | let slug = getSlug(item.str); 100 | 101 | if (!(slug in curTable.cols)) { 102 | Object.keys(curTable.cols) 103 | .forEach((key) => { 104 | if (key.indexOf(slug) !== -1 && 105 | !curTable.cols[key].x) { 106 | slug = key; 107 | } 108 | else if (curTable.cols[key].aliases) { 109 | curTable.cols[key] 110 | .aliases 111 | .forEach((alias) => { 112 | if (alias.indexOf(slug) !== -1 && 113 | !curTable.cols[key].x) { 114 | slug = key; 115 | } 116 | }) 117 | } 118 | }); 119 | } 120 | 121 | if (slug in curTable.cols) { 122 | curTable.cols[slug].x = item.x; 123 | curTable.cols[slug].y = item.y; 124 | } 125 | } 126 | // table rows 127 | else if (curTable) { 128 | Object.keys(curTable.cols).forEach((key,i) => { 129 | let col = curTable.cols[key]; 130 | 131 | 132 | if (col.x && within(col.x,item.x,2)) { 133 | if ((fdOnline && item.y - rowY > 15) || (!fdOnline && i === 0 && item.y - rowY > 10)) { 134 | curTable.rows.push({}); 135 | rowY = item.y; 136 | } 137 | 138 | if (curTable.rows.length > 0) { // && item.y - rowY < 60 139 | if (fdOnline) { 140 | rowY = item.y; 141 | } 142 | 143 | let curRow = curTable.rows[curTable.rows.length - 1]; 144 | 145 | if (key in curRow) { 146 | if (key !== '#' && key !== 'date') { 147 | curRow[key] += ' '; 148 | } 149 | curRow[key] += item.str; 150 | } 151 | else { 152 | curRow[key] = item.str; 153 | } 154 | } 155 | else { 156 | // console.log(item.str,item.y - rowY) 157 | } 158 | } 159 | }); 160 | } 161 | 162 | resolve(item); 163 | }); 164 | }); 165 | } 166 | 167 | function itemCompare(a,b) { 168 | if (a.y - b.y !== 0) { 169 | return a.y - b.y; 170 | } 171 | else { 172 | return a.x - b.x; 173 | } 174 | } 175 | 176 | function transformItem (item) { 177 | let transform = pdfjs.PDFJS.Util.transform( 178 | pdfjs.PDFJS.Util.transform(viewport.transform, item.transform), 179 | [1, 0, 0, -1, 0, 0]); 180 | 181 | item.x = transform[4]; 182 | item.y = transform[5]; 183 | 184 | return item; 185 | } 186 | 187 | function processPage(page) { 188 | rowY = 0; 189 | 190 | viewport = page.getViewport(1.0); 191 | 192 | return _(page.getTextContent()) 193 | .flatten() 194 | .pluck('items') 195 | .flatten() 196 | .map(transformItem) 197 | .sortBy(itemCompare) 198 | .map(item => _(processItem(item))) 199 | .flatten(); 200 | } 201 | 202 | function process() { 203 | filing = new Filing(); 204 | 205 | filing.file = file.relative 206 | .replace('.pdf', '') 207 | .replace('.PDF', ''); // consider extracting the name out of the filing instead 208 | 209 | const data = new Uint8Array(file.contents); 210 | 211 | // parse PDF document 212 | return new Promise((resolve,reject) => { 213 | _(pdfjs.getDocument(data)) 214 | // get each page in the document 215 | .flatMap(doc => { 216 | let pages = []; 217 | 218 | for (let i = 1; i <= doc.numPages; i++) { 219 | pages.push(i); 220 | } 221 | 222 | return _(pages) 223 | .map(page => _(doc.getPage(page))); 224 | }) 225 | .flatten() 226 | .flatMap(processPage) 227 | .stopOnError(() => reject()) 228 | .done(() => { 229 | filing.tables = filing.tables.filter((table) => { 230 | return table.rows.length > 0; 231 | }); 232 | 233 | resolve(filing); 234 | }); 235 | }); 236 | } 237 | 238 | function processList(fileList) { 239 | return new Promise((resolve,reject) => { 240 | _(fileList) 241 | .flatMap((file) => { 242 | return _(parser(file)); 243 | }) 244 | .stopOnError(reject) 245 | .toArray(resolve); 246 | }); 247 | } 248 | 249 | if (Vinyl.isVinyl(files)) { 250 | // is files just a vinyl file? process it 251 | file = files; 252 | 253 | return process(); 254 | } 255 | else if (Array.isArray(files)) { 256 | // is files an array? parse each entry 257 | return processList(files); 258 | } 259 | else if (typeof files === 'string' || files instanceof String) { 260 | // is files a string? check if it seems to be a single file or use glob syntax 261 | if (files.toLowerCase().indexOf('.pdf') !== -1 || 262 | files.toLowerCase().indexOf('*') !== -1) { 263 | // if so, src it directly 264 | return processList(vfs.src(files)); 265 | } 266 | else { 267 | // otherwise, assume it's a directory and parse PDFs under the directory 268 | return processList(vfs.src(files + '**/*.@(pdf|PDF)')); 269 | } 270 | } 271 | } 272 | 273 | module.exports = parser; 274 | -------------------------------------------------------------------------------- /lib/spec.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'), 2 | yaml = require('js-yaml'); 3 | 4 | const spec = yaml.safeLoad(fs.readFileSync(__dirname + '/../swagger.yaml', 'utf8')); 5 | 6 | module.exports = spec; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pfd-parser", 3 | "version": "1.0.0-alpha", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node ./bin/pfdparser", 8 | "test": "./node_modules/mocha/bin/mocha" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "commander": "^2.9.0", 14 | "d3-dsv": "^1.0.3", 15 | "highland": "^2.10.5", 16 | "js-yaml": "^3.8.4", 17 | "lodash.clonedeep": "^4.5.0", 18 | "pdfjs-dist": "^1.6.483", 19 | "vinyl-fs": "^2.4.4" 20 | }, 21 | "devDependencies": { 22 | "chai": "^4.0.0", 23 | "mocha": "^3.4.2" 24 | }, 25 | "bin": { 26 | "pfdparser": "./bin/pfdparser" 27 | }, 28 | "pkg": { 29 | "assets": "swagger.yaml" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /swagger.yaml: -------------------------------------------------------------------------------- 1 | # swagger: '2.0' 2 | info: 3 | description: >- 4 | Public financial disclosure data from OGE form 278e. Entries should be read 5 | with the employee's separate ethics agreement and the endnotes included in 6 | the final table, which often indicate whether the employee intends to divest 7 | the asset upon entering government. 8 | version: 0.1.0 9 | title: PFD Filing 10 | paths: {} 11 | definitions: 12 | filer-s-positions-held-outside-united-states-government: 13 | title: 1. Filer's Positions Held Outside United States Government 14 | aliases: 15 | - 1. Filer Positions Held outside United States Government 16 | - 1. Filer's Positions Held Outside the United States Government 17 | description: >- 18 | Part 1 discloses positions that the filer held at any time during the 19 | reporting period (excluding positions with the United States Government). 20 | Positions are reportable even if the filer did not receive compensation. 21 | This section does not include the following: (1) positions with religious, 22 | social, fraternal, or political organizations; (2) positions solely of an 23 | honorary nature; (3) positions held as part of the filer's official duties 24 | with the United States Government; (4) mere membership in an organization; 25 | and (5) passive investment interests as a limited partner or non-managing 26 | member of a limited liability company. 27 | type: object 28 | properties: 29 | # file: 30 | # type: string 31 | '#': 32 | type: string 33 | organization-name: 34 | type: string 35 | aliases: 36 | - name 37 | city-state: 38 | type: string 39 | organization-type: 40 | type: string 41 | aliases: 42 | - oge-type 43 | - org-type 44 | position-held: 45 | type: string 46 | aliases: 47 | - position 48 | from: 49 | type: string 50 | to: 51 | type: string 52 | filer-s-employment-assets-&-income-and-retirement-accounts: 53 | title: 2. Filer's Employment Assets & Income and Retirement Accounts 54 | aliases: 55 | - 2. Filer's Employment Assets and Income 56 | description: >- 57 | Part 2 discloses the following: Sources of earned and other non-investment 58 | income of the filer totaling more than $200 during the reporting period 59 | (e.g., salary, fees, partnership share, honoraria, scholarships, and 60 | prizes); Assets related to the filer's business, employment, or other 61 | income-generating activities that (1) ended the reporting period with a 62 | value greater than $1,000 or (2) produced more than $200 in income during 63 | the reporting period (e.g., equity in business or partnership, stock 64 | options, retirement plans/accounts and their underlying holdings as 65 | appropriate, deferred compensation, and intellectual property, such as 66 | book deals and patents). This section does not include assets or income 67 | from United States Government employment or assets that were acquired 68 | separately from the filer's business, employment, or other 69 | income-generating activities (e.g., assets purchased through a brokerage 70 | account). Note: The type of income is not required if the amount of income 71 | is $0 - $200 or if the asset qualifies as an excepted investment fund 72 | (EIF). 73 | type: object 74 | properties: 75 | # file: 76 | # type: string 77 | '#': 78 | type: string 79 | description: 80 | type: string 81 | eif: 82 | type: string 83 | value: 84 | type: string 85 | income-type: 86 | type: string 87 | income-amount: 88 | type: string 89 | filer-s-employment-agreements-and-arrangements: 90 | title: 3. Filer's Employment Agreements and Arrangements 91 | aliases: 92 | - 3. Filer Employment Agreements and Arrangements 93 | description: >- 94 | Part 3 discloses agreements or arrangements that the filer had during the 95 | reporting period with an employer or former employer (except the United 96 | States Government), such as the following: Future employment; Leave of 97 | absence; Continuing payments from an employer, including severance and 98 | payments not yet received for previous work (excluding ordinary salary 99 | from a current employer); Continuing participation in an employee welfare, 100 | retirement, or other benefit plan, such as pensions or a deferred 101 | compensation plan; Retention or disposition of employer-awarded equity, 102 | sharing in profits or carried interests (e.g., vested and unvested stock 103 | options, restricted stock, future share of a company's profits, etc.). 104 | type: object 105 | properties: 106 | # file: 107 | # type: string 108 | '#': 109 | type: string 110 | employer-or-party: 111 | type: string 112 | aliases: 113 | - employer-or-other-party-to-agreement-arrangement 114 | city-state: 115 | type: string 116 | status-and-terms: 117 | type: string 118 | date: 119 | type: string 120 | filer-s-sources-of-compensation-exceeding-$5-000-in-a-year: 121 | title: '4. Filer''s Sources of Compensation Exceeding $5,000 in a Year' 122 | description: >- 123 | Part 4 discloses sources (except the United States Government) that paid 124 | more than $5,000 in a calendar year for the filer's services during any 125 | year of the reporting period. The filer discloses payments both from 126 | employers and from any clients to whom the filer personally provided 127 | services. The filer discloses a source even if the source made its payment 128 | to the filer's employer and not to the filer. The filer does not disclose 129 | a client's payment to the filer's employer if the filer did not provide 130 | the services for which the client is paying. 131 | type: object 132 | properties: 133 | # file: 134 | # type: string 135 | '#': 136 | type: string 137 | source-name: 138 | type: string 139 | aliases: 140 | - name 141 | city-state: 142 | type: string 143 | brief-description-of-duties: 144 | type: string 145 | aliases: 146 | - description 147 | spouse-s-employment-assets-&-income-and-retirement-accounts: 148 | title: 5. Spouse's Employment Assets & Income and Retirement Accounts 149 | aliases: 150 | - 5. Spouse's Employment Assets and Income 151 | description: >- 152 | Part 5 discloses the following: Sources of earned income (excluding 153 | honoraria) for the filer's spouse totaling more than $1,000 during the 154 | reporting period (e.g., salary, consulting fees, and partnership share); 155 | Sources of honoraria for the filer's spouse greater than $200 during the 156 | reporting period; Assets related to the filer's spouse's employment, 157 | business activities, other income-generating activities that (1) ended the 158 | reporting period with a value greater than $1,000 or (2) produced more 159 | than $200 in income during the reporting period (e.g., equity in business 160 | or partnership, stock options, retirement plans/accounts; and their 161 | underlying holdings as appropriate, deferred compensation, and 162 | intellectual property, such as book deals and patents); This section does 163 | not include assets or income from United States Government employment or 164 | assets that were acquired separately from the filer's spouse's business, 165 | employment, or other income-generating activities (e.g., assets purchased 166 | through a brokerage account). Note: The type of income is not required if 167 | the amount of income is $0 - $200 or if the asset qualifies as an excepted 168 | investment fund (EIF). Amounts of income are not required for a spouse's 169 | earned income (excluding honoraria). 170 | type: object 171 | properties: 172 | # file: 173 | # type: string 174 | '#': 175 | type: string 176 | description: 177 | type: string 178 | eif: 179 | type: string 180 | value: 181 | type: string 182 | income-type: 183 | type: string 184 | income-amount: 185 | type: string 186 | other-assets-and-income: 187 | title: 6. Other Assets and Income 188 | description: >- 189 | Part 6 discloses each asset, not already reported, that (1) ended the 190 | reporting period with a value greater than $1,000 or (2) produced more 191 | than $200 in investment income during the reporting period. For purposes 192 | of the value and income thresholds, the filer aggregates the filer's 193 | interests with those of the filer's spouse and dependent children. This 194 | section does not include the following types of assets: (1) a personal 195 | residence (unless it was rented out during the reporting period); (2) 196 | income or retirement benefits associated with United States Government 197 | employment (e.g., Thrift Savings Plan); and (3) cash accounts (e.g., 198 | checking, savings, money market accounts) at a single financial 199 | institution with a value of $5,000 or less (unless more than $200 of 200 | income was produced). Additional exceptions apply. Note: The type of 201 | income is not required if the amount of income is $0 - $200 or if the 202 | asset qualifies as an excepted investment fund (EIF). 203 | type: object 204 | properties: 205 | # file: 206 | # type: string 207 | '#': 208 | type: string 209 | description: 210 | type: string 211 | eif: 212 | type: string 213 | value: 214 | type: string 215 | income-type: 216 | type: string 217 | income-amount: 218 | type: string 219 | transactions: 220 | title: 7. Transactions 221 | description: >- 222 | Part 7 discloses purchases, sales, or exchanges of real property or 223 | securities in excess of $1,000 made on behalf of the filer, the filer's 224 | spouse or dependent child during reporting period. This section does not 225 | include transactions that concern the following: (1) a personal residence, 226 | unless rented out; (2) cash accounts (e.g., checking, savings, CDs, money 227 | market accounts) and money market mutual funds; (3) Treasury bills, bonds, 228 | and notes; and (4) holdings within a federal Thrift Savings Plan account. 229 | Additional exceptions apply. 230 | type: object 231 | properties: 232 | # file: 233 | # type: string 234 | '#': 235 | type: string 236 | description: 237 | type: string 238 | type: 239 | type: string 240 | date: 241 | type: string 242 | amount: 243 | type: string 244 | liabilities: 245 | title: 8. Liabilities 246 | description: >- 247 | Part 8 discloses liabilities over $10,000 that the filer, the filer's 248 | spouse or dependent child owed at any time during the reporting period. 249 | This section does not include the following types of liabilities: (1) 250 | mortgages on a personal residence, unless rented out (limitations apply 251 | for PAS filers); (2) loans secured by a personal motor vehicle, household 252 | furniture, or appliances, unless the loan exceeds the item's purchase 253 | price; and (3) revolving charge accounts, such as credit card balances, if 254 | the outstanding liability did not exceed $10,000 at the end of the 255 | reporting period. Additional exceptions apply. 256 | type: object 257 | properties: 258 | # file: 259 | # type: string 260 | '#': 261 | type: string 262 | creditor-name: 263 | type: string 264 | type: 265 | type: string 266 | aliases: 267 | - type-of-liability 268 | amount: 269 | type: string 270 | year-incurred: 271 | type: string 272 | rate: 273 | type: string 274 | aliases: 275 | - interest-rate 276 | term: 277 | type: string 278 | gifts-and-travel-reimbursements: 279 | title: 9. Gifts and Travel Reimbursements 280 | aliases: 281 | - 9. Gifts and Reimbursements 282 | description: >- 283 | This section discloses: Gifts totaling more than $375 that the filer, the 284 | filer's spouse, and dependent children received from any one source during 285 | the reporting period; Travel reimbursements totaling more than $375 that 286 | the filer, the filer's spouse, and dependent children received from any 287 | one source during the reporting period. For purposes of this section, the 288 | filer need not aggregate any gift or travel reimbursement with a value of 289 | $150 or less. Regardless of the value, this section does not include the 290 | following items: (1) anything received from relatives; (2) anything 291 | received from the United States Government or from the District of 292 | Columbia, state, or local governments; (3) bequests and other forms of 293 | inheritance; (4) gifts and travel reimbursements given to the filer's 294 | agency in connection with the filer's official travel; (5) gifts of 295 | hospitality (food, lodging, entertainment) at the donor's residence or 296 | personal premises; and (6) anything received by the filer's spouse or 297 | dependent children totally independent of their relationship to the filer. 298 | Additional exceptions apply. 299 | type: object 300 | properties: 301 | # file: 302 | # type: string 303 | '#': 304 | type: string 305 | source-name: 306 | type: string 307 | city-state: 308 | type: string 309 | brief-description: 310 | type: string 311 | value: 312 | type: string 313 | endnotes: 314 | title: Endnotes 315 | type: object 316 | properties: 317 | # file: 318 | # type: string 319 | part: 320 | type: string 321 | '#': 322 | type: string 323 | endnote: 324 | type: string 325 | -------------------------------------------------------------------------------- /test/data/Donnelly, Sally.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PublicI/pfd-parser/c2c6f9ace1aa5c47dda4a7b1432a46c3e33693f2/test/data/Donnelly, Sally.pdf -------------------------------------------------------------------------------- /test/data/Kushner, Jared.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PublicI/pfd-parser/c2c6f9ace1aa5c47dda4a7b1432a46c3e33693f2/test/data/Kushner, Jared.pdf -------------------------------------------------------------------------------- /test/data/Mashburn, Lori K.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PublicI/pfd-parser/c2c6f9ace1aa5c47dda4a7b1432a46c3e33693f2/test/data/Mashburn, Lori K.pdf -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const _ = require('highland'), 2 | chai = require('chai'), 3 | parser = require('../lib/parser'), 4 | vfs = require('vinyl-fs'); 5 | 6 | let should = chai.should(); 7 | 8 | const filingPath = __dirname + '/data/'; 9 | 10 | const integrityFiling = filingPath + 'Kushner, Jared.pdf', 11 | fdmFiling = filingPath + 'Donnelly, Sally.pdf', 12 | fdOnlineFiling = filingPath + 'Mashburn, Lori K.pdf'; 13 | 14 | describe('lib/parser.js', () => { 15 | it('should find seven tables in Integrity filing', (done) => { 16 | parser(integrityFiling) 17 | .then((filings) => { 18 | filings[0].tables.length.should.equal(7); 19 | 20 | done(); 21 | }); 22 | }).timeout(4000); 23 | 24 | it('should find seven tables in example FDM filing', (done) => { 25 | parser(fdmFiling) 26 | .then((filings) => { 27 | filings[0].tables.length.should.equal(7); 28 | 29 | done(); 30 | }); 31 | }); 32 | 33 | it('should find seven tables in example FDonline filing', (done) => { 34 | parser(fdOnlineFiling) 35 | .then((filings) => { 36 | filings[0].tables.length.should.equal(7); 37 | 38 | done(); 39 | }); 40 | }); 41 | }); 42 | 43 | 44 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | argparse@^1.0.7: 4 | version "1.0.9" 5 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" 6 | dependencies: 7 | sprintf-js "~1.0.2" 8 | 9 | arr-diff@^2.0.0: 10 | version "2.0.0" 11 | resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" 12 | dependencies: 13 | arr-flatten "^1.0.1" 14 | 15 | arr-flatten@^1.0.1: 16 | version "1.0.3" 17 | resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.3.tgz#a274ed85ac08849b6bd7847c4580745dc51adfb1" 18 | 19 | array-unique@^0.2.1: 20 | version "0.2.1" 21 | resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" 22 | 23 | assertion-error@^1.0.1: 24 | version "1.0.2" 25 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" 26 | 27 | balanced-match@^0.4.1: 28 | version "0.4.2" 29 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" 30 | 31 | brace-expansion@^1.1.7: 32 | version "1.1.7" 33 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" 34 | dependencies: 35 | balanced-match "^0.4.1" 36 | concat-map "0.0.1" 37 | 38 | braces@^1.8.2: 39 | version "1.8.5" 40 | resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" 41 | dependencies: 42 | expand-range "^1.8.1" 43 | preserve "^0.2.0" 44 | repeat-element "^1.1.2" 45 | 46 | browser-stdout@1.3.0: 47 | version "1.3.0" 48 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" 49 | 50 | buffer-shims@~1.0.0: 51 | version "1.0.0" 52 | resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" 53 | 54 | chai: 55 | version "4.0.0" 56 | resolved "https://registry.yarnpkg.com/chai/-/chai-4.0.0.tgz#f6c989e45a5707d40c54d97ddd7ca89b30a6a06a" 57 | dependencies: 58 | assertion-error "^1.0.1" 59 | check-error "^1.0.1" 60 | deep-eql "^2.0.1" 61 | get-func-name "^2.0.0" 62 | pathval "^1.0.0" 63 | type-detect "^4.0.0" 64 | 65 | check-error@^1.0.1: 66 | version "1.0.2" 67 | resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" 68 | 69 | clone-stats@^0.0.1: 70 | version "0.0.1" 71 | resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" 72 | 73 | clone@^1.0.0: 74 | version "1.0.2" 75 | resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" 76 | 77 | commander, commander@2, commander@2.9.0: 78 | version "2.9.0" 79 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 80 | dependencies: 81 | graceful-readlink ">= 1.0.0" 82 | 83 | concat-map@0.0.1: 84 | version "0.0.1" 85 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 86 | 87 | convert-source-map@^1.1.1: 88 | version "1.5.0" 89 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" 90 | 91 | core-util-is@~1.0.0: 92 | version "1.0.2" 93 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 94 | 95 | d3-dsv: 96 | version "1.0.3" 97 | resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.0.3.tgz#049fe43c0f5f60c7ff7d376616bc76d6fc9d378f" 98 | dependencies: 99 | commander "2" 100 | iconv-lite "0.4" 101 | rw "1" 102 | 103 | debug@2.6.0: 104 | version "2.6.0" 105 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" 106 | dependencies: 107 | ms "0.7.2" 108 | 109 | deep-eql@^2.0.1: 110 | version "2.0.2" 111 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-2.0.2.tgz#b1bac06e56f0a76777686d50c9feb75c2ed7679a" 112 | dependencies: 113 | type-detect "^3.0.0" 114 | 115 | diff@3.2.0: 116 | version "3.2.0" 117 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" 118 | 119 | duplexify@^3.2.0: 120 | version "3.5.0" 121 | resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.0.tgz#1aa773002e1578457e9d9d4a50b0ccaaebcbd604" 122 | dependencies: 123 | end-of-stream "1.0.0" 124 | inherits "^2.0.1" 125 | readable-stream "^2.0.0" 126 | stream-shift "^1.0.0" 127 | 128 | end-of-stream@1.0.0: 129 | version "1.0.0" 130 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e" 131 | dependencies: 132 | once "~1.3.0" 133 | 134 | escape-string-regexp@1.0.5: 135 | version "1.0.5" 136 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 137 | 138 | esprima@^3.1.1: 139 | version "3.1.3" 140 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" 141 | 142 | expand-brackets@^0.1.4: 143 | version "0.1.5" 144 | resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" 145 | dependencies: 146 | is-posix-bracket "^0.1.0" 147 | 148 | expand-range@^1.8.1: 149 | version "1.8.2" 150 | resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" 151 | dependencies: 152 | fill-range "^2.1.0" 153 | 154 | extend-shallow@^2.0.1: 155 | version "2.0.1" 156 | resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" 157 | dependencies: 158 | is-extendable "^0.1.0" 159 | 160 | extend@^3.0.0: 161 | version "3.0.1" 162 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" 163 | 164 | extglob@^0.3.1: 165 | version "0.3.2" 166 | resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" 167 | dependencies: 168 | is-extglob "^1.0.0" 169 | 170 | filename-regex@^2.0.0: 171 | version "2.0.1" 172 | resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" 173 | 174 | fill-range@^2.1.0: 175 | version "2.2.3" 176 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" 177 | dependencies: 178 | is-number "^2.1.0" 179 | isobject "^2.0.0" 180 | randomatic "^1.1.3" 181 | repeat-element "^1.1.2" 182 | repeat-string "^1.5.2" 183 | 184 | first-chunk-stream@^1.0.0: 185 | version "1.0.0" 186 | resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" 187 | 188 | for-in@^1.0.1: 189 | version "1.0.2" 190 | resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" 191 | 192 | for-own@^0.1.4: 193 | version "0.1.5" 194 | resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" 195 | dependencies: 196 | for-in "^1.0.1" 197 | 198 | fs.realpath@^1.0.0: 199 | version "1.0.0" 200 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 201 | 202 | get-func-name@^2.0.0: 203 | version "2.0.0" 204 | resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" 205 | 206 | glob-base@^0.3.0: 207 | version "0.3.0" 208 | resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" 209 | dependencies: 210 | glob-parent "^2.0.0" 211 | is-glob "^2.0.0" 212 | 213 | glob-parent@^2.0.0: 214 | version "2.0.0" 215 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" 216 | dependencies: 217 | is-glob "^2.0.0" 218 | 219 | glob-parent@^3.0.0: 220 | version "3.1.0" 221 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" 222 | dependencies: 223 | is-glob "^3.1.0" 224 | path-dirname "^1.0.0" 225 | 226 | glob-stream@^5.3.2: 227 | version "5.3.5" 228 | resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" 229 | dependencies: 230 | extend "^3.0.0" 231 | glob "^5.0.3" 232 | glob-parent "^3.0.0" 233 | micromatch "^2.3.7" 234 | ordered-read-streams "^0.3.0" 235 | through2 "^0.6.0" 236 | to-absolute-glob "^0.1.1" 237 | unique-stream "^2.0.2" 238 | 239 | glob@^5.0.3: 240 | version "5.0.15" 241 | resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" 242 | dependencies: 243 | inflight "^1.0.4" 244 | inherits "2" 245 | minimatch "2 || 3" 246 | once "^1.3.0" 247 | path-is-absolute "^1.0.0" 248 | 249 | glob@7.1.1: 250 | version "7.1.1" 251 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" 252 | dependencies: 253 | fs.realpath "^1.0.0" 254 | inflight "^1.0.4" 255 | inherits "2" 256 | minimatch "^3.0.2" 257 | once "^1.3.0" 258 | path-is-absolute "^1.0.0" 259 | 260 | graceful-fs@^4.0.0, graceful-fs@^4.1.2: 261 | version "4.1.11" 262 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 263 | 264 | "graceful-readlink@>= 1.0.0": 265 | version "1.0.1" 266 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 267 | 268 | growl@1.9.2: 269 | version "1.9.2" 270 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" 271 | 272 | gulp-sourcemaps@1.6.0: 273 | version "1.6.0" 274 | resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" 275 | dependencies: 276 | convert-source-map "^1.1.1" 277 | graceful-fs "^4.1.2" 278 | strip-bom "^2.0.0" 279 | through2 "^2.0.0" 280 | vinyl "^1.0.0" 281 | 282 | has-flag@^1.0.0: 283 | version "1.0.0" 284 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 285 | 286 | highland: 287 | version "2.10.5" 288 | resolved "https://registry.yarnpkg.com/highland/-/highland-2.10.5.tgz#6007fd24f4838d9117ba41bdcc98ec3b54bfde18" 289 | dependencies: 290 | util-deprecate "^1.0.2" 291 | 292 | iconv-lite@0.4: 293 | version "0.4.15" 294 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" 295 | 296 | inflight@^1.0.4: 297 | version "1.0.6" 298 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 299 | dependencies: 300 | once "^1.3.0" 301 | wrappy "1" 302 | 303 | inherits@^2.0.1, inherits@~2.0.1, inherits@2: 304 | version "2.0.3" 305 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 306 | 307 | is-buffer@^1.1.5: 308 | version "1.1.5" 309 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" 310 | 311 | is-dotfile@^1.0.0: 312 | version "1.0.2" 313 | resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" 314 | 315 | is-equal-shallow@^0.1.3: 316 | version "0.1.3" 317 | resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" 318 | dependencies: 319 | is-primitive "^2.0.0" 320 | 321 | is-extendable@^0.1.0, is-extendable@^0.1.1: 322 | version "0.1.1" 323 | resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" 324 | 325 | is-extglob@^1.0.0: 326 | version "1.0.0" 327 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" 328 | 329 | is-extglob@^2.1.0: 330 | version "2.1.1" 331 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 332 | 333 | is-glob@^2.0.0, is-glob@^2.0.1: 334 | version "2.0.1" 335 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" 336 | dependencies: 337 | is-extglob "^1.0.0" 338 | 339 | is-glob@^3.1.0: 340 | version "3.1.0" 341 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" 342 | dependencies: 343 | is-extglob "^2.1.0" 344 | 345 | is-number@^2.0.2, is-number@^2.1.0: 346 | version "2.1.0" 347 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" 348 | dependencies: 349 | kind-of "^3.0.2" 350 | 351 | is-posix-bracket@^0.1.0: 352 | version "0.1.1" 353 | resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" 354 | 355 | is-primitive@^2.0.0: 356 | version "2.0.0" 357 | resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" 358 | 359 | is-stream@^1.0.1: 360 | version "1.1.0" 361 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 362 | 363 | is-utf8@^0.2.0: 364 | version "0.2.1" 365 | resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" 366 | 367 | is-valid-glob@^0.3.0: 368 | version "0.3.0" 369 | resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" 370 | 371 | isarray@~1.0.0, isarray@1.0.0: 372 | version "1.0.0" 373 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 374 | 375 | isarray@0.0.1: 376 | version "0.0.1" 377 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 378 | 379 | isobject@^2.0.0: 380 | version "2.1.0" 381 | resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" 382 | dependencies: 383 | isarray "1.0.0" 384 | 385 | js-yaml: 386 | version "3.8.4" 387 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" 388 | dependencies: 389 | argparse "^1.0.7" 390 | esprima "^3.1.1" 391 | 392 | json-stable-stringify@^1.0.0: 393 | version "1.0.1" 394 | resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" 395 | dependencies: 396 | jsonify "~0.0.0" 397 | 398 | json3@3.3.2: 399 | version "3.3.2" 400 | resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" 401 | 402 | jsonify@~0.0.0: 403 | version "0.0.0" 404 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" 405 | 406 | kind-of@^3.0.2: 407 | version "3.2.2" 408 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" 409 | dependencies: 410 | is-buffer "^1.1.5" 411 | 412 | lazystream@^1.0.0: 413 | version "1.0.0" 414 | resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" 415 | dependencies: 416 | readable-stream "^2.0.5" 417 | 418 | lodash._baseassign@^3.0.0: 419 | version "3.2.0" 420 | resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" 421 | dependencies: 422 | lodash._basecopy "^3.0.0" 423 | lodash.keys "^3.0.0" 424 | 425 | lodash._basecopy@^3.0.0: 426 | version "3.0.1" 427 | resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" 428 | 429 | lodash._basecreate@^3.0.0: 430 | version "3.0.3" 431 | resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" 432 | 433 | lodash._getnative@^3.0.0: 434 | version "3.9.1" 435 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" 436 | 437 | lodash._isiterateecall@^3.0.0: 438 | version "3.0.9" 439 | resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" 440 | 441 | lodash.clonedeep: 442 | version "4.5.0" 443 | resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" 444 | 445 | lodash.create@3.1.1: 446 | version "3.1.1" 447 | resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" 448 | dependencies: 449 | lodash._baseassign "^3.0.0" 450 | lodash._basecreate "^3.0.0" 451 | lodash._isiterateecall "^3.0.0" 452 | 453 | lodash.isarguments@^3.0.0: 454 | version "3.1.0" 455 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 456 | 457 | lodash.isarray@^3.0.0: 458 | version "3.0.4" 459 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" 460 | 461 | lodash.isequal@^4.0.0: 462 | version "4.5.0" 463 | resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" 464 | 465 | lodash.keys@^3.0.0: 466 | version "3.1.2" 467 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" 468 | dependencies: 469 | lodash._getnative "^3.0.0" 470 | lodash.isarguments "^3.0.0" 471 | lodash.isarray "^3.0.0" 472 | 473 | merge-stream@^1.0.0: 474 | version "1.0.1" 475 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" 476 | dependencies: 477 | readable-stream "^2.0.1" 478 | 479 | micromatch@^2.3.7: 480 | version "2.3.11" 481 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" 482 | dependencies: 483 | arr-diff "^2.0.0" 484 | array-unique "^0.2.1" 485 | braces "^1.8.2" 486 | expand-brackets "^0.1.4" 487 | extglob "^0.3.1" 488 | filename-regex "^2.0.0" 489 | is-extglob "^1.0.0" 490 | is-glob "^2.0.1" 491 | kind-of "^3.0.2" 492 | normalize-path "^2.0.1" 493 | object.omit "^2.0.0" 494 | parse-glob "^3.0.4" 495 | regex-cache "^0.4.2" 496 | 497 | minimatch@^3.0.2, "minimatch@2 || 3": 498 | version "3.0.4" 499 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 500 | dependencies: 501 | brace-expansion "^1.1.7" 502 | 503 | minimist@0.0.8: 504 | version "0.0.8" 505 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 506 | 507 | mkdirp@^0.5.0, mkdirp@0.5.1: 508 | version "0.5.1" 509 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 510 | dependencies: 511 | minimist "0.0.8" 512 | 513 | mocha: 514 | version "3.4.2" 515 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.4.2.tgz#d0ef4d332126dbf18d0d640c9b382dd48be97594" 516 | dependencies: 517 | browser-stdout "1.3.0" 518 | commander "2.9.0" 519 | debug "2.6.0" 520 | diff "3.2.0" 521 | escape-string-regexp "1.0.5" 522 | glob "7.1.1" 523 | growl "1.9.2" 524 | json3 "3.3.2" 525 | lodash.create "3.1.1" 526 | mkdirp "0.5.1" 527 | supports-color "3.1.2" 528 | 529 | ms@0.7.2: 530 | version "0.7.2" 531 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" 532 | 533 | node-ensure@^0.0.0: 534 | version "0.0.0" 535 | resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7" 536 | 537 | normalize-path@^2.0.1: 538 | version "2.1.1" 539 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" 540 | dependencies: 541 | remove-trailing-separator "^1.0.1" 542 | 543 | object-assign@^4.0.0: 544 | version "4.1.1" 545 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 546 | 547 | object.omit@^2.0.0: 548 | version "2.0.1" 549 | resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" 550 | dependencies: 551 | for-own "^0.1.4" 552 | is-extendable "^0.1.1" 553 | 554 | once@^1.3.0: 555 | version "1.4.0" 556 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 557 | dependencies: 558 | wrappy "1" 559 | 560 | once@~1.3.0: 561 | version "1.3.3" 562 | resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" 563 | dependencies: 564 | wrappy "1" 565 | 566 | ordered-read-streams@^0.3.0: 567 | version "0.3.0" 568 | resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" 569 | dependencies: 570 | is-stream "^1.0.1" 571 | readable-stream "^2.0.1" 572 | 573 | parse-glob@^3.0.4: 574 | version "3.0.4" 575 | resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" 576 | dependencies: 577 | glob-base "^0.3.0" 578 | is-dotfile "^1.0.0" 579 | is-extglob "^1.0.0" 580 | is-glob "^2.0.0" 581 | 582 | path-dirname@^1.0.0: 583 | version "1.0.2" 584 | resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" 585 | 586 | path-is-absolute@^1.0.0: 587 | version "1.0.1" 588 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 589 | 590 | pathval@^1.0.0: 591 | version "1.1.0" 592 | resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" 593 | 594 | pdfjs-dist: 595 | version "1.6.483" 596 | resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-1.6.483.tgz#f97a36be98ee5b956a3053dba889190b6b9a4bf2" 597 | dependencies: 598 | node-ensure "^0.0.0" 599 | 600 | preserve@^0.2.0: 601 | version "0.2.0" 602 | resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" 603 | 604 | process-nextick-args@~1.0.6: 605 | version "1.0.7" 606 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 607 | 608 | randomatic@^1.1.3: 609 | version "1.1.6" 610 | resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" 611 | dependencies: 612 | is-number "^2.0.2" 613 | kind-of "^3.0.2" 614 | 615 | readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5: 616 | version "2.2.9" 617 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" 618 | dependencies: 619 | buffer-shims "~1.0.0" 620 | core-util-is "~1.0.0" 621 | inherits "~2.0.1" 622 | isarray "~1.0.0" 623 | process-nextick-args "~1.0.6" 624 | string_decoder "~1.0.0" 625 | util-deprecate "~1.0.1" 626 | 627 | "readable-stream@>=1.0.33-1 <1.1.0-0": 628 | version "1.0.34" 629 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" 630 | dependencies: 631 | core-util-is "~1.0.0" 632 | inherits "~2.0.1" 633 | isarray "0.0.1" 634 | string_decoder "~0.10.x" 635 | 636 | regex-cache@^0.4.2: 637 | version "0.4.3" 638 | resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" 639 | dependencies: 640 | is-equal-shallow "^0.1.3" 641 | is-primitive "^2.0.0" 642 | 643 | remove-trailing-separator@^1.0.1: 644 | version "1.0.1" 645 | resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4" 646 | 647 | repeat-element@^1.1.2: 648 | version "1.1.2" 649 | resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" 650 | 651 | repeat-string@^1.5.2: 652 | version "1.6.1" 653 | resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" 654 | 655 | replace-ext@0.0.1: 656 | version "0.0.1" 657 | resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" 658 | 659 | rw@1: 660 | version "1.3.3" 661 | resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" 662 | 663 | safe-buffer@^5.0.1: 664 | version "5.0.1" 665 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" 666 | 667 | sprintf-js@~1.0.2: 668 | version "1.0.3" 669 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 670 | 671 | stream-shift@^1.0.0: 672 | version "1.0.0" 673 | resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" 674 | 675 | string_decoder@~0.10.x: 676 | version "0.10.31" 677 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 678 | 679 | string_decoder@~1.0.0: 680 | version "1.0.1" 681 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.1.tgz#62e200f039955a6810d8df0a33ffc0f013662d98" 682 | dependencies: 683 | safe-buffer "^5.0.1" 684 | 685 | strip-bom-stream@^1.0.0: 686 | version "1.0.0" 687 | resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" 688 | dependencies: 689 | first-chunk-stream "^1.0.0" 690 | strip-bom "^2.0.0" 691 | 692 | strip-bom@^2.0.0: 693 | version "2.0.0" 694 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" 695 | dependencies: 696 | is-utf8 "^0.2.0" 697 | 698 | supports-color@3.1.2: 699 | version "3.1.2" 700 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" 701 | dependencies: 702 | has-flag "^1.0.0" 703 | 704 | through2-filter@^2.0.0: 705 | version "2.0.0" 706 | resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" 707 | dependencies: 708 | through2 "~2.0.0" 709 | xtend "~4.0.0" 710 | 711 | through2@^0.6.0: 712 | version "0.6.5" 713 | resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" 714 | dependencies: 715 | readable-stream ">=1.0.33-1 <1.1.0-0" 716 | xtend ">=4.0.0 <4.1.0-0" 717 | 718 | through2@^2.0.0, through2@~2.0.0: 719 | version "2.0.3" 720 | resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" 721 | dependencies: 722 | readable-stream "^2.1.5" 723 | xtend "~4.0.1" 724 | 725 | to-absolute-glob@^0.1.1: 726 | version "0.1.1" 727 | resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" 728 | dependencies: 729 | extend-shallow "^2.0.1" 730 | 731 | type-detect@^3.0.0: 732 | version "3.0.0" 733 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-3.0.0.tgz#46d0cc8553abb7b13a352b0d6dea2fd58f2d9b55" 734 | 735 | type-detect@^4.0.0: 736 | version "4.0.3" 737 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea" 738 | 739 | unique-stream@^2.0.2: 740 | version "2.2.1" 741 | resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" 742 | dependencies: 743 | json-stable-stringify "^1.0.0" 744 | through2-filter "^2.0.0" 745 | 746 | util-deprecate@^1.0.2, util-deprecate@~1.0.1: 747 | version "1.0.2" 748 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 749 | 750 | vali-date@^1.0.0: 751 | version "1.0.0" 752 | resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" 753 | 754 | vinyl-fs: 755 | version "2.4.4" 756 | resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" 757 | dependencies: 758 | duplexify "^3.2.0" 759 | glob-stream "^5.3.2" 760 | graceful-fs "^4.0.0" 761 | gulp-sourcemaps "1.6.0" 762 | is-valid-glob "^0.3.0" 763 | lazystream "^1.0.0" 764 | lodash.isequal "^4.0.0" 765 | merge-stream "^1.0.0" 766 | mkdirp "^0.5.0" 767 | object-assign "^4.0.0" 768 | readable-stream "^2.0.4" 769 | strip-bom "^2.0.0" 770 | strip-bom-stream "^1.0.0" 771 | through2 "^2.0.0" 772 | through2-filter "^2.0.0" 773 | vali-date "^1.0.0" 774 | vinyl "^1.0.0" 775 | 776 | vinyl@^1.0.0: 777 | version "1.2.0" 778 | resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" 779 | dependencies: 780 | clone "^1.0.0" 781 | clone-stats "^0.0.1" 782 | replace-ext "0.0.1" 783 | 784 | wrappy@1: 785 | version "1.0.2" 786 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 787 | 788 | "xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: 789 | version "4.0.1" 790 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 791 | 792 | --------------------------------------------------------------------------------