[
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "Is this a bug? If not consider asking on [StackOverflow][StackOverflow].\n\nDoes the documentation require improvement? Consider posting a [Feature][Feature] with the the recommended changes.\n\n# Subject of the issue\n\nProvide a brief description of your issue.\n\n## Environment\n\n- Platform: Node | Browser \n- Version: Chrome 50\n- Usage: Load from file | Load from Ajax | Hooks\n\n## Steps to reproduce\n\n- step1\n- step2\n- step3\n\n## Expected behaviour\n\nTell us what should happen\n\n## Actual behaviour\n\nTell us what happens instead\n\n## References\n\n - [name](href)\n\n[Feature]: https://github.com/evanplaice/jquery-csv/issues/new?template=FEAT_TEMPLATE.md&labels=feature\n[StackOverflow]: https://stackoverflow.com/questions/tagged/jquery-csv?mixed=1\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATES/DISC_TEMPLATE.md",
    "content": "# Topic\n\n## What Does this Impact?\n\nWrite a brief description of how this discussion applies to jquery-csv.\n\n## Notes\n\nOptionally, compile notes from the discussion here.\n\n## References\n\n- [link](href)\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATES/FEAT_TEMPLATE.md",
    "content": "# the name of the feature\n\nA brief description of what the feature aims to accomplish\n\n## Goals\n\n- goal\n- goal\n\n## Checklist\n\n- [ ] Is this tested?\n- [ ] Is documentation up-to-date?\n\n## Details\n\n<!-- Add a loose outline. Don't worry about implementation specifics yet. Feature requests are intended to start a dialog. If this is good to move forward, a specification will be created to outline the implementation details. -->\n\n## References\n\n - [name](href)\n\n<!-- When this feature is ready to move on to implementation, create a [Specification][Specification]. -->\n\n[Specification]: https://github.com/evanplaice/jquery-csv/issues/new?template=SPEC_TEMPLATE.md&labels=specification\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATES/SPEC_TEMPLATE.md",
    "content": "# the name of the specification\n\nA brief description of the specification\n\n## Goals\n\n- goal\n- goal\n\n## Milestones\n\n- [ ] milestone\n- [ ] milestone\n\n## Details\n\nAdd code snippets and/or a more in-depth description of the implementation details\n\n## References\n\n - [name](href)\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "If this PR applies to an existing spec, link to it and delete the rest.\n\n## Checklist\n\n- [ ] Is this API breaking?\n- [ ] Is this tested?\n- [ ] Is Documentation required?\n\n*Note: Don't worry about leaving these unchecked. These exist to quickly identify common requirements.*\n\n## Description\n\nPost a brief description of the changes.\n\n## References\n\n- [name](href)\n"
  },
  {
    "path": ".github/workflows/latest.yml",
    "content": "name: Latest\n\non:\n  push:\n    branches:\n      - main\n    paths-ignore:\n      - package.json\n      - package-lock.json\n\njobs:\n  ci:\n    uses: evanplaice/jquery-csv/.github/workflows/verify.yml@main \n"
  },
  {
    "path": ".github/workflows/npm.yml",
    "content": "name: NPM Release\n\non:\n  workflow_call:\n\njobs:\n  npm:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      id-token: write\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v4\n    - name: Setup\n      uses: actions/setup-node@v4\n      with:\n        registry-url: \"https://registry.npmjs.org\"\n        cache: npm\n    - run: npm ci\n    - name: Publish\n      run: npm publish --provenance --access public\n      env:\n        NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/pr.yml",
    "content": "name: Pull Request\n\non: [pull_request]\n  \njobs:\n  ci:\n    uses: evanplaice/jquery-csv/.github/workflows/verify.yml@main\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    tags:\n    - v*\n\njobs:\n  ci:\n    uses: evanplaice/jquery-csv/.github/workflows/verify.yml@main\n\n  cd:\n    needs: ci\n    uses: evanplaice/jquery-csv/.github/workflows/npm.yml@main\n    secrets: inherit\n\n"
  },
  {
    "path": ".github/workflows/verify.yml",
    "content": "name: Verify\n\non:\n  workflow_call:\n\njobs:\n  verify:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Setup\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'npm'\n      - name: Install\n        run: npm ci\n      - name: Lint\n        run: npm run lint\n      - name: Test\n        run: npm t\n\n      # - name: Types\n      #   run: npm run types\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\npackage/\n.DS_Store\n*.tgz\n"
  },
  {
    "path": ".npmignore",
    "content": ".github/\ndocs/\nexamples/\npackage/\ntest/\n.git/\n*.tgz\n.travis.yml\nCONTRIBUTING.md\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How You Can Help\n\n## Non-code contributions\n\n- If you'd like to edit/update the documentation, submit a Pull Request\n- If you'd like to start a dialog, post a new [Discussion][Discussion]\n- If you'd like to assist other users of jquery-csv, answer qustions on [StackOverflow][StackOverflow]\n- If you'd like to promote this project, write articles or blog posts and link back to the project\n\n## Code Contributions\n\n- If you'd like to add a new example or test, submit a [Specification][Specification]\n- If you'd like to propose a new feature, submit a [Feature][Feature] request\n\n**DO**\n\n- Follow the [Forking Workflow][Forking Workflow]\n   1. Fork the project\n   2. Clone your fork\n   3. Add a remote pointing to the origin repo\n   3. Create a new `feature` branch\n   4. Checkout the `feature` branch\n   5. Commit your changes\n   6. Rebase your changes onto the latest w/ `git pull --rebase`\n   7. Post a PR comparing `origin/master` to the `fork/feature`\n- Provide tests where applicable\n- Provide documentation updates that apply to the changes\n- Follow the current style of the project\n\n**Don't**\n\n- Group multiple features into a single PR\n- Co-mingle whitespace changes with code changes\n- Make superficial changes (ie style/structure) to existing code\n- Make API breaking changes unless they're clearly documented in a Specification\n\n[Discussion]: https://github.com/evanplaice/jquery-csv/issues/new?template=DISC_TEMPLATE.md&labels=discussion\n[StackOverflow]: https://stackoverflow.com/questions/tagged/jquery-csv?mixed=1\n[Feature]: https://github.com/evanplaice/jquery-csv/issues/new?template=FEAT_TEMPLATE.md&labels=feature\n[Specification]: https://github.com/evanplaice/jquery-csv/issues/new?template=SPEC_TEMPLATE.md&labels=specification\n[Forking Workflow]: https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2012 Evan Plaice <evanplaice@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\"><strong>✓ NOTICE: For a more modern CSV parser, check out the <a href=\"https://github.com/vanillaes/csv\">@VanillaES/CSV</a> project ✓</strong></p>\n\n<div align=\"center\">\n  <a href=\"https://github.com/evanplaice/jquery-csv/releases\"><img src=\"https://img.shields.io/github/release/evanplaice/jquery-csv.svg\" alt=\"GitHub Releases\"></a>\n  <a href=\"https://www.npmjs.com/package/jquery-csv\"><img src=\"https://img.shields.io/npm/v/jquery-csv.svg\" alt=\"NPM Release\"></a>\n  <a href=\"https://bundlephobia.com/result?p=jquery-csv\"><img src=\"https://badgen.net/bundlephobia/minzip/jquery-csv\" alt=\"Bundlephobia\"></a>\n  <a href=\"https://github.com/evanplaice/jquery-csv/actions\"><img src=\"https://github.com/evanplaice/jquery-csv/workflows/Latest/badge.svg\" alt=\"Latest Status\"></a>\n  <a href=\"https://github.com/evanplaice/jquery-csv/actions\"><img src=\"https://github.com/evanplaice/jquery-csv/workflows/Release/badge.svg\" alt=\"Release Status\"></a>\n</div>\n\n# Introduction\n\njQuery-csv is an artifact of a simpler time (ie 2012) when the JS library ecosystem was still very underdeveloped. This was the first and still is one of the fastest spec compliant CSV parsers available. \n\nThis is a complete, customizable, battle tested, performance optimized CSV parser that follows the traditional jQuery-style of syntax. Featuring a slim Chomsky - Type III parser implementation. Full (that means 100%) [IETF RFC 4180](http://tools.ietf.org/html/rfc4180) compliance. Including coverage for a few edge cases that even the spec fails to cover.\n\nEnough with the wind-up...\n\n\n# Features\n\n* Convert a CSV String to an array\n* Convert a multi-line CSV string to a 2D array\n* Convert a multi-line CSV string to an array of objects (ie header:value pairs)\n* Convert an array of values to CSV (under development)\n* Convert an array of objects to CSV (under development)\n* Hooks/Callbacks to extend the default parsing process\n* Customizable delimiter (default: \") and separator (default: ,) characters\n* Node.js support (ie CommonJS importing and async callback support)\n\n# Syntax\n\n## Importing\n\n**Client-Side** (ie browser) - import via the script element.\n```javascript\n<script src=\"jquery-csv.js\"></script>\n```\n\n**Server-Side** (ie Node.js) - Import via the standard CommonJS approach.\n\nInstall the package via NPM\n\n```bash\nnpm i jquery-csv\n```\nThen import it as a CommonJS module.\n\n```javascript\nvar csv = require('jquery-csv');\n```\n\n## Usage\n\nEach one of the methods can be called with the following form:\n```javascript\n$.csv.function(csv, {options}, callback);\n```\n\n| Name\t\t  |           | Description |\n|-----------|-----------|:------------|\n| csv\t\t    | required\t| The csv data to be transformed. |\n| options\t  | optional\t| An object containing user-defined overrides for the default options. |\n| callback\t| optional\t| Used for Node.js-style async callbacks. Uses the form function(err, data). |\n\n## Methods\n\n**toArray**\n\nParse a single entry string to an array\n```javascript\n$.csv.toArray(csv);\n```\n*Documented under API#$.csv.toArray().*\n\n**toArrays**\n\nParse a multi-line CSV string to a 2D array\n```javascript\n$.csv.toArrays(csv);\n```\n*Documented under API#$.csv.toArrays().*\n\n**toObjects**\n\nParse a multi-line CSV string to an array of objects\n```javascript\n$.csv.toObjects(csv);\n```\n*Documented under API#$.csv.toObjects().*\n\n**fromArrays**\n\nConvert array data to a CSV string\n```javascript\n$.csv.fromArrays(arrays);\n```\n\n**fromObjects**\n\nConvert an array of objects to a CSV string\n```javascript\n$.csv.fromObjects(objects);\n```\n\n# Documentation\n\n- [API](./docs/api.md)\n- [Hooks & Callbacks](./docs/hooks-callbacks.md)\n- [Algorithm](./docs/algorithm.md)\n\n# Use Cases\n\nInstead of the typical useless contrived example code, I have provided a handful of simple yet powerful demos. Not only are they fun to play with but a quick peak at the source will show you how simple and easy they were to implement. Feel free to copy and reuse these in your own projects.\n\n## Basic Usage\n\nWant to play with the parser and maybe validate your CSV data without all the frills? No need to download the source first, there's a demo for that...\n\n[jQuery-CSV - toArray()](http://evanplaice.github.io/jquery-csv/examples/to-array.html)\n\n[jQuery-CSV - toArrays()](http://evanplaice.github.io/jquery-csv/examples/to-arrays.html)\n\n[jQuery-CSV - fromArrays()](http://evanplaice.github.io/jquery-csv/examples/from-arrays.html)\n\n[jQuery-CSV - toObjects()](http://evanplaice.github.io/jquery-csv/examples/to-objects.html)\n\n[jQuery-CSV - fromObjects()](http://evanplaice.github.io/jquery-csv/examples/from-objects.html)\n\n## Node.js ESM (EcmaScript Module) Import\n\nHere's how to import jQuery-CSV as am ECMAScript module Node.js:\n\n[jQuery-CSV - ESM Import Demonstration](http://evanplaice.github.io/jquery-csv/examples/snippets/esm-usage.js)\n\n## Node.js CJS (CommonJS Module) Import\n\nHere's how to import jQuery-CSV as CommonJS module Node.js:\n\n[jQuery-CSV - CJS Import Demonstration](http://evanplaice.github.io/jquery-csv/examples/snippets/node-usage.js)\n\n## Client-Side File Handling\n\nYes, you read that right. It's now possible to open local files in the browser without firing a single request to the server.\n\nThe functionality is still pretty new so not all browsers support it (I'm looking @ you IE). If that's not an issue I highly suggest you try it. It's much easier than the traditional client/server approach.\n\n[jQuery-CSV - File Handling Demonstration](http://evanplaice.github.io/jquery-csv/examples/file-handling.html)\n\n## jQuery-CSV + Flot\n\nHands down, the most exciting addition to the demo collection so far...\n\nYou can input the data set using either the text area provided or via uploading CSV data files.\n\nWant to plot 5 data sets on the same grid, no problem; Just upload 5 files containing one dataset each. The jQuery-CSV will handle the plumbing while Flot will make it all look pretty.\n\n[jQuery-CSV - Flot Demonstration](http://evanplaice.github.io/jquery-csv/examples/flot.html)\n\n## jQuery-CSV + Google Visualization API\n\nOK, I lied. This one is even cooler than Flot. Hike up your fancy pants because these things look slick.\n\nDon't want to draw a line graph, no problem you can tap into the massive collection of different graph types available. Embedded is a fully configurable dashboard.\n\nWarning: You may experience multiple spontaneous 'oh my got that's soo awesome' fits of excitement. Maybe even get stoked. Happens to the best us...\n\n[jQuery-CSV - Google Visualization API Demonstration](http://evanplaice.github.io/jquery-csv/examples/google-visualization.html)\n\n**jQuery-CSV** coding style is inherited from the [JQuery Core Style Guidelines](https://contribute.jquery.org/style-guide/)\n"
  },
  {
    "path": "docs/algorithm.md",
    "content": "## Algorithm\n\nBelow is the algorithm used to parse a single-line of raw CSV.\n\n![jquery-csv state diagram](algorithms_csv-parser.png)\n\n*States:*\n\n- (a) initial\n- (b) delimited\n- (c) capture delimited\n- (d) capture undelimited\n\n*Transitions:*\n\n- (0) return value\n- (1) opening delimiter\n- (2) closing delimiter\n- (3) undelimited data\n\n*Source:*\n\n```javascript\nsplitLines: function(csv, delimiter) {\n  var state = 0;\n  var value = \"\";\n  var line = \"\";\n  var lines = [];\n  function endOfRow() {\n    lines.push(value);\n    value = \"\";\n    state = 0;\n  };\n  csv.replace(/(\\\"|,|\\n|\\r|[^\\\",\\r\\n]+)/gm, function (m0){\n    switch (state) {\n      // the start of a value/entry\n      case 0:\n        if (m0 === \"\\\"\") {\n          state = 1;\n        } else if (m0 === \"\\n\") {\n          endOfRow();\n        } else if (/^\\r$/.test(m0)) {\n          // carriage returns are ignored\n        } else {\n          value += m0;\n          state = 3;\n        }\n        break;\n      // delimited input  \n      case 1:\n        if (m0 === \"\\\"\") {\n          state = 2;\n        } else {\n          value += m0;\n          state = 1;\n        }\n        break;\n      // delimiter found in delimited input\n      case 2:\n        // is the delimiter escaped?\n        if (m0 === \"\\\"\" && value.substr(value.length - 1) === \"\\\"\") {\n          value += m0;\n          state = 1;\n        } else if (m0 === \",\") {\n          value += m0;\n          state = 0;\n        } else if (m0 === \"\\n\") {\n          endOfRow();\n        } else if (m0 === \"\\r\") {\n          // Ignore\n        } else {\n          throw new Error(\"Illegal state\");\n        }\n        break;\n      // un-delimited input\n      case 3:\n        if (m0 === \",\") {\n          value += m0;\n          state = 0;\n        } else if (m0 === \"\\\"\") {\n          throw new Error(\"Unquoted delimiter found\");\n        } else if (m0 === \"\\n\") {\n          endOfRow();\n        } else if (m0 === \"\\r\") {\n          // Ignore\n        } else {\n          throw new Error(\"Illegal data\");\n        }\n          break;\n      default:\n        throw new Error(\"Unknown state\");\n    }\n    return \"\";\n  });\n  if (state != 0) {\n    endOfRow();\n  }\n  return lines;\n}\n```"
  },
  {
    "path": "docs/api.md",
    "content": "## Introduction\n\nThe following will cover the core utilities provided by `jquery-csv`.\n\nThe project's home page outlines the most general use cases but this library is capable of much more. If you're interested in learning some of the more advanced capabilities of this library, then you're in the right place.\n\nNote: To avoid confusion, assume that the terms row/entry and column/value as both will be used interchangeably.\n\n## Namespaces\n\nTo keep the library out of the global namespace, everything contained in this library has been organized into a hierarchy of namespaces.\n\n### $.csv\n\nThe top-level namespace where you will find the primary parser methods and the utility functions needed by them.\n\n### $.options\n\nA namespace containing the default option values for the library. If you're looking to change the defaults (as opposed to overriding them) this is where you may do so.\n\n### $.config\n\nCreated after parser initialization. This is where the settings can be read/modified for an active parser instance.\n\n### $.state\n\nCreated after parser initialization. This is where the current state of the parser can be read/modified.\n\n### $.hooks\n\nA namespace containing helpful user-defined hook callbacks. For more information on what's available refer to the Hooks? page.\n\n### $.parsers\n\nWhere the parser methods live. They're useful if you just need access to a CSV-specific split-lines function, or a single-entry parser. You can also override the default parser by changing these values inline.\n\n## Core Methods\n\nThe following methods make up the core of the jquery-csv library.\n\n### $.csv.toArray()\nUseful for parsing a single entry of CSV data into an array of `[values]`.\n\n*Structure:*\n\n```javascript\n$.csv.toArray(csv, options, callback)\n```\n\n*Parameters:*\n\n- csv (required)\n  - a string of CSV data\n- options (optional)\n  - contains a list of user-configurable options\n- callback (optional)\n  - used for node.js and/or asynchronous processing of data\n  - used to define the callback that is executed when parsing is complete\n  - the callbacks take the standard form [function(err, data){}]\n\n*Options:*\n\n- separator\n  - an override for the separator character\n  - defaults to a comma(,)\n- delimiter\n  - an override for the delimiter character\n  - defaults to a double-quote(\")\n\n### $.csv.toArrays()\n\nUseful for parsing multi-line CSV data into a two-dimensional array of `[record][values].`\n\n*Structure:*\n\n```javascript\n$.csv.toArrays(csv, options, callback)\n```\n\n*Parameters:*\n\n- csv (required)\n  - a string of CSV data\n- options (optional)\n  - contains a list of user-configurable options\n- callback (optional)\n  - used for node.js and/or asynchronous processing of data\n  - used to define the callback that is executed when parsing is complete\n  - the callbacks take the standard form [function(err, data){}]\n\n*Options:*\n\n- separator\n  - an override for the separator character\n  - defaults to a comma(,)\n- delimiter\n  - an override for the delimiter character\n  - defaults to a double-quote(\")\n- startIndex (not implemented)\n  - the line where the parser should start processing\n  - defaults to 1 (non-zero based counting)\n- endIndex (not implemented)\n  - the line the parser should stop after\n  - defaults to EOF\n\n### $.csv.toObjects()\n\nUseful for parsing multi-line CSV data into an array of objects representing data in the form `[record][{header:value}]`.\n\nUnless overridden, the first line of data is assumed to contain the headers.\n\n*Structure:*\n\n```javascript\n$.csv.toObjects(csv, options, callback)\n```\n\n*Parameters:*\n\n- csv (required)\n  - a string of CSV data\n- options (optional)\n  - contains a list of user-configurable options\n- callback (optional)\n  - used for node.js and/or asynchronous processing of data\n  - used to define the callback that is executed when parsing is complete\n  - the callbacks take the standard form [function(err, data){}]\n\n*Options:*\n\n- separator\n  - an override for the separator character\n  - defaults to a comma(,)\n- delimiter\n  - an override for the delimiter character\n  - defaults to a double-quote(\")\n- headerIndex (not implemented)\n  - the line containing the headers\n  - defaults to 1 (non-zero based counting)\n- startIndex (not implemented)\n  - the line where the parser should start processing\n  - defaults to 2 (non-zero based counting)\n- endIndex (not implemented)\n  - the line the parser should stop after\n  - defaults to EOF\n\n## Helper Method(s)\n\nThe following methods may or may not be useful unless you're trying to tackle a specific use case. These methods make up some of the magic that makes the library work.\n\nWarning: Replace and/or modify these at your own risk. Their purpose is to override the internal behavior of the parser. Don't expect support if your custom implementation introduces bugs.\n\n```javascript\n$.csv.splitLines(csv)\n```\n\nAn advanced line splitter that converts a CSV data string into an array of CSV entries represented in string form.\n\nAs opposed to the commonly used string.split() function, this is a more advanced line splitting implementation capable of ignoring new-lines contained in the value data.\n\nSplitting data by lines may sound trivial (no split('\\n) does not work) but under the covers it required the development a special lexer tailored specifically to handle CSV data.\n\n*Structure:*\n\n```javascript```\n$.csv.parsers.splitLines(csv, options)\n```\n\n*Parameters:*\n\n- csv (required)\n  - a string of CSV data\n- options (optional)\n  - contains a list of user-configurable options\n\n*Options:*\n\n- separator\n  - an override for the separator character\n  - defaults to a comma(,)\n- delimiter\n  - an override for the delimiter character\n  - defaults to a double-quote(\")"
  },
  {
    "path": "docs/hooks-callbacks.md",
    "content": "\n## Why hook?\n\nCSV as a data format is very loosely implemented. Part of what makes it so versatile is the lack of specific rules to enforce how it should be used. Unfortunately, without such rules it becomes a lot more difficult to define how the data should be interpreted.\n\nTo keep the library size small and avoid baking in a ton of domain-specific 'magic', an extensible architecture is provided whereby users can define their own 'magic'.\n\n## How it works\n\nHooks work by defining a user-defined function that will be used inline during the parsing process. The point where it's called during parsing depends on the hook used.\n\nTo use a hook, simply attach a function callback (ie anonymous function) of your design to the hook in the parser options object.\n\nNo really... it's that easy.\n\n## Available Hooks\n\n### onPreParse()\n\nThis hook is called before the parser starts processing the dataset. Useful if you need to make a pass to 'clean' the data first.\n\n*Usage:*\n\n```javascript\n// strips empty (illegal) lines from the data before parsing \nvar removeEmptyLines = function(csv, state) {\n  var lines = $.csv.splitLines(csv);\n  var output = [];\n  for(var i=0, len=lines.length; i<len; i++) {\n    if(lines[i] !== '') {\n      output.push(lines[i]);\n    }\n  }\n  return output.join('\\n');\n}; \n$.csv.toArrays(csv, { onPreParse: removeEmptyLines });\n```\n\n### onParseEntry()\n\nThis hook is called each time an entry is parsed and before the entry is broken down further into values. Useful if you need to modify specific entries, or process-by-row.\n\n*Usage:*\n\n```javascript\n// signals to only parse rows 3 and 4\nvar rowRange = function(entry, state) {\n  var start = 3;\n  var end = 4;\n  if(state.rowNum >= start && state.rowNum <= end) {\n    return entry;\n  }\n  return false;\n}  \n$.csv.toArrays(testHook3, { onParseEntry: rowRange });\n```\n\n### onParseValue()\n\nThis hook is called each time a value is parsed. Useful if you want to modify the output values inline, or process-by-column.\n\n*Usage:*\n\n```javascript\n// signals to only parse columns 4 and 5\nvar columnRange = function(value, state) {\n  var start = 4;\n  var end = 5;\n  if(state.colNum >= start && state.colNum <= end) {\n    return value;\n  }\n  return false;\n}\n$.csv.toArrays(testHook2, { onParseValue: columnRange });\n```\n\n### onPostParse()\n\nThis hook is called after the parser is complete. Useful if you want to modify the output data.\n\n*Usage:*\n\n```javascript\n// sort the 2D array by the value of the second column\nvar sortByCol2 = function(data) {\n  data.sort(function(a,b){\n    return a[1] - b[1];\n  });\n  return data;\n}\n$.csv.toArrays(csv, { onPostParse: sortByCol2 });\n```\n\n## Available User-Defined Callbacks\n\nSo... I lied when I said that the library won't provide any user-defined hook callbacks. Some are just too common and valuable to leave out.\n\nThe following will outline the user-defined callbacks that will be provided with the library by defaults.\n\n### $.csv.hooks.castToScalar(value)\n\nThis is a onParseValue callback that detects and casts all output values to the correct type.\n\n*Usage:*\n\n```javascript\nvar csv = '734,4.5,sda,\"555\",\"4523.35\",\"af323\"';\n\nvar data = $.csv2Array(csv, {\n      onParseValue: $.csv.hooks.castToScalar\n    });\nconsole.log(data);\nOutput:\n\n[\n  734,\n  4.5,\n  \"sda\",\n  555,\n  4523.35,\n  \"af323\"]\n]\n```\n\n### Custom User Defined Date Parser\n\nThis is an example of using a custom function passed to the onParseValue callback that will parse dates\n\n*Usage:*\n\n```javascript\nconst csv = '10-11-1995,10/23/1993,12.30.1962,10,hello,5.47';\n\nconst parseDates = function(value, state) {\n  // Only try to parse values that include a '.' or '/' or '-'\n  if (value.match(/(\\.|\\/|\\-)/g)) {\n    const date = new Date(value);\n\n    if (date != 'Invalid Date')\n      return date;\n  }\n\n  return value;\n};\n\nconst data = $.csv2Array(csv, { onParseValue: parseDates });\n\nOutput:\n[\n  Wed Oct 11 1995 00:00:00 GMT-0500 (Central Daylight Time),\n  Sat Oct 23 1993 00:00:00 GMT-0500 (Central Daylight Time),\n  Sun Dec 30 1962 00:00:00 GMT-0600 (Central Standard Time),\n  10,\n  hello,\n  5.47\n]\n```\n\nAside: There are plenty more use-cases to be discovered for the plethora of hooks. If you feel like you have one that is common enough to justify adding it to the library we'd like to see it. Just create a new 'feature request' in the 'issues' section outlining the details.\n"
  },
  {
    "path": "examples/_template.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Template</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">[operator]</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>[description]</p>\n        <hr>\n        <h2>Usage</h2>\n        <pre><code class=\"javascript\">[code]</code></pre>\n        <hr />\n        <h2>Input</h2>\n        <textarea id=\"input\" style=\"height: 25px;\">[input]</textarea>\n        <input id=\"run\" type=\"button\" value=\"Run\" />\n        <hr />\n        <h2>Result</h2>\n        <textarea id=\"result\" style=\"height: 82px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"http://code.jquery.com/jquery-3.3.1.slim.js\" integrity=\"sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $(document).ready(() => {\n        // set initial state\n      });\n\n      $('#run').bind('click', function () {\n        // this executes when the run 'Run' button is clicked\n      });\n\n      // add additional functionality here\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "examples/custom-date-parsing.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Custom Date Parsing</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">User Defined Date Parsing Callback</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>Using a custom defined hook to parse dates</p>\n        <hr>\n        <h2>Usage</h2>\n        <pre><code class=\"javascript\">const parseDates = function(value, state) {\n  if (value.match(/(\\.|\\/|\\-)/g)) {\n    const date = new Date(value);\n  \n    if (date != 'Invalid Date')\n      return date;\n  }\n  \n    return value;\n};\n  \nconst data = $.csv2Array(csv, { onParseValue: parseDates });</code></pre>\n        <hr />\n        <h2>Input</h2>\n        <textarea id=\"input\" style=\"height: 200px;\">\n10-11-1995,10/23/1993,12.30.1962,10,hello,5.47\n        </textarea>\n        <input id=\"run\" type=\"button\" value=\"Run\" />\n        <hr />\n        <h2>Result</h2>\n        <textarea id=\"result\" style=\"height: 170px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"http://code.jquery.com/jquery-3.3.1.slim.js\" integrity=\"sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $(document).ready(() => {\n        format();\n      });\n\n      $('#run').bind('click', function () {\n        format();\n      });\n\n      function format() {\n        const csv = $('#input').val();\n        \n        const parseDates = function(value, state) {\n          if (value.match(/(\\.|\\/|\\-)/g)) {\n            const date = new Date(value);\n\n            if (date != 'Invalid Date')\n              return date;\n          }\n\n          return value;\n        };\n\n        const data = $.csv2Array(csv, { onParseValue: parseDates });\n\n        $('#result').empty();\n        $('#result').html(data);\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/data/analytics1.csv",
    "content": "1,30\n2,44\n3,30\n4,12\n5,14\n6,42\n7,43\n8,25\n9,48\n10,35\n11,12\n12,8\n13,57\n14,48\n15,49\n16,41\n17,24\n18,14\n19,22\n20,46\n21,54\n22,83\n23,68\n24,63\n25,26\n26,34\n27,60\n28,55\n29,77\n30,73\n31,42\n"
  },
  {
    "path": "examples/data/analytics2.csv",
    "content": "1,21\n2,26\n3,61\n4,70\n5,50\n6,66\n7,43\n8,29\n9,30\n10,71\n11,74\n12,77\n13,74\n14,63\n15,25\n16,18\n17,64\n18,77\n19,84\n20,85\n21,71\n22,36\n23,22\n24,82\n25,99\n26,97\n27,92\n28,67\n29,37\n30,59\n31,111\n"
  },
  {
    "path": "examples/data/sample.csv",
    "content": "ID,iManufacturer,iMPartNumber,iSerialNumber,iSimCategory,iPartType,iDescription,iGroup,iLocation,iSold\n1,\"Evans & Sutherland\",\"230-132-111AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n2,\"Evans & Sutherland\",\"230-132-111AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n3,\"Evans & Sutherland\",\"230-120-112AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n4,\"Evans & Sutherland\",\"230-120-112AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n5,\"Evans & Sutherland\",\"230-120-112AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n6,\"Evans & Sutherland\",\"230-120-112AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n7,\"Evans & Sutherland\",\"230-120-112AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n8,\"Evans & Sutherland\",\"230-120-112AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n9,\"Evans & Sutherland\",\"230-120-112AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n10,\"Evans & Sutherland\",\"230-121-150AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n11,\"Evans & Sutherland\",\"230-121-150AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n12,\"Evans & Sutherland\",\"230-121-150AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n13,\"Evans & Sutherland\",\"230-121-150AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n14,\"Evans & Sutherland\",\"230-121-150AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n15,\"Evans & Sutherland\",\"230-140-110DA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n16,\"Evans & Sutherland\",\"230-140-110DA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n17,\"Evans & Sutherland\",\"230-140-110DA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n18,\"Evans & Sutherland\",\"230-140-110DA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n19,\"Evans & Sutherland\",\"230-140-110DA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n20,\"Evans & Sutherland\",\"230-140-110DA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n21,\"Evans & Sutherland\",\"230-140-110DA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n22,\"Evans & Sutherland\",\"230-140-110DA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n23,\"Evans & Sutherland\",\"230-120-112AB\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n24,\"Evans & Sutherland\",\"230-120-112AB\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n25,\"Evans & Sutherland\",\"230-120-112AB\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n26,\"Evans & Sutherland\",\"230-113-130CF\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n27,\"Evans & Sutherland\",\"230-114-111AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n28,\"Evans & Sutherland\",\"230-114-111AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n29,\"Evans & Sutherland\",\"230-110-130AC\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n30,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n31,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n32,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n33,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n34,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n35,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n36,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n37,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n38,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n39,\"Evans & Sutherland\",\"230-116-121AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n40,\"Evans & Sutherland\",\"230-132-111AB\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n41,\"Evans & Sutherland\",\"230-121-150AB\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n42,\"Evans & Sutherland\",\"230-121-150AB\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n43,\"Evans & Sutherland\",\"230-121-150AB\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n44,\"Evans & Sutherland\",\"230-113-130CD\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n45,\"Evans & Sutherland\",\"230-113-130CD\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n46,\"Evans & Sutherland\",\"230-111-207AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n47,\"Evans & Sutherland\",\"230-111-207AA\",,\"Visual\",\"PCB\",,1,\"Offsite\",\n48,\"Evans & Sutherland\",\"230040-146AD\",,\"Visual\",\"Backplane Chassis\",,1,\"Offsite\",\n49,\"Evans & Sutherland\",\"230040-146AD\",,\"Visual\",\"Backplane Chassis\",,1,\"Offsite\",\n50,\"Evans & Sutherland\",\"230040-146AD\",,\"Visual\",\"Backplane Chassis\",,1,\"Offsite\",\n51,\"Pioneer Magnetics\",\"801966-105XA\",,\"Visual\",\"Power Supply\",\"5v 300A  208/230  50/60  Model # 250LB-2-3P\",1,\"Offsite\",\n52,\"Pioneer Magnetics\",\"801966-105XA\",,\"Visual\",\"Power Supply\",\"5v 300A  208/230  50/60  Model # 250LB-2-3P\",1,\"Offsite\",\n53,\"Pioneer Magnetics\",\"801966-105XA\",,\"Visual\",\"Power Supply\",\"5v 300A  208/230  50/60  Model # 250LB-2-3P\",1,\"Offsite\",\n54,\"Evans & Sutherland\",,,\"Visual\",\"Misc\",\"Cabinet Fan Assembly\",1,\"Offsite\",\n55,\"Evans & Sutherland\",,,\"Visual\",\"Misc\",\"Power Controller\",1,\"Offsite\",\n56,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - Upper Memory Board\",2,\"Offsite\",0\n57,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - Lower Memory Board\",2,\"Offsite\",0\n58,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - Processor Board\",2,\"Offsite\",0\n59,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - Memory Map Board\",2,\"Offsite\",0\n60,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - Option Board\",2,\"Offsite\",0\n61,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - I/O Port Board\",2,\"Offsite\",0\n62,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - I/O Extension Power Supply\",2,\"Offsite\",0\n63,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - Disk Unit w/ HDD and 8” FDD\",2,\"Offsite\",0\n64,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - CPU Power Supply\",2,\"Offsite\",0\n65,\"Varia Datamachines\",,,\"Visual\",,\"Sperry Univac V77 - Memory Power Supply\",2,\"Offsite\",0\n66,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - Peddle\",2,\"Offsite\",0\n67,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - Terminator Shoe\",2,\"Offsite\",0\n68,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - I/O Expander\",2,\"Offsite\",0\n69,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - I/O Expander Paddele\",2,\"Offsite\",0\n70,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - S-Bus Controller\",2,\"Offsite\",0\n71,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - PIM #1\",2,\"Offsite\",0\n72,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - PIM #2\",2,\"Offsite\",0\n73,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - BIC #1\",2,\"Offsite\",0\n74,\"VITAL\",,,\"Visual\",,\"Vital IV Interface – PMAC\",2,\"Offsite\",0\n75,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - DIOC\",2,\"Offsite\",0\n76,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - BIC #3\",2,\"Offsite\",0\n77,\"VITAL\",,,\"Visual\",,\"Vital IV Interface - Matrix Multiplier\",2,\"Offsite\",0\n78,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A1 FOV\",2,\"Offsite\",0\n79,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A2 MM\",2,\"Offsite\",0\n80,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A3 ACC\",2,\"Offsite\",0\n81,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A4 IS\",2,\"Offsite\",0\n82,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A5 PD\",2,\"Offsite\",0\n83,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A6 Int/Def\",2,\"Offsite\",0\n84,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A7 OB\",2,\"Offsite\",0\n85,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A9 SB\",2,\"Offsite\",0\n86,\"VITAL\",,,\"Visual\",,\"Vital IV TASK - A1A10 SF\",2,\"Offsite\",0\n87,\"VITAL\",,,\"Visual\",,\"Vital IV RBOS - A2A1-A5 OL\",2,\"Offsite\",0\n88,\"VITAL\",,,\"Visual\",,\"Vital IV RBOS - A2A6 OC/DEF\",2,\"Offsite\",0\n89,\"VITAL\",,,\"Visual\",,\"Vital IV RBOS - A2A8 D/A\",2,\"Offsite\",0\n90,\"VITAL\",,,\"Visual\",,\"Vital IV RBOS - A2A9 XC\",2,\"Offsite\",0\n91,\"VITAL\",,,\"Visual\",,\"Vital IV RBOS - A2A10 CL\",2,\"Offsite\",0\n92,\"VITAL\",,,\"Visual\",,\"Vital IV RBOS - A2A11 YC\",2,\"Offsite\",0\n93,\"VITAL\",,,\"Visual\",,\"Vital IV RBOS - A2A12 LLS\",2,\"Offsite\",0\n94,\"VITAL\",,,\"Visual\",,\"Vital IV RBOS - A2A13 ZC\",2,\"Offsite\",0\n95,\"CITRONIX\",\"H06G2072-4\",,\"Visual\",,\"VITAL Monitor Power Supply\",2,\"Offsite\",0\n96,,,,\"Visual\",,\"VT220 Terminal\",2,\"Offsite\",0\n97,,,,\"Visual\",,\"VT220 Terminal\",2,\"Offsite\",0\n98,\"Mannisman\",\"MT88\",,\"Visual\",,\"Tally Matrix Printer\",2,\"Offsite\",0\n99,,,,\"Visual\",,\"DIGITAL Laserwriter Printer\",2,\"Offsite\",0\n100,,,,\"Visual\",,\"DIGITAL Laserwriter Printer\",2,\"Offsite\",0\n101,,,,\"Visual\",,\"Signal Cable - IG <-> Monitor\",2,\"Offsite\",0\n102,,,,\"Visual\",,\"Signal Cable - IG <-> Monitor\",2,\"Offsite\",0\n103,,,,\"Visual\",,\"Signal Cable - IG <-> Monitor\",2,\"Offsite\",0\n104,,,,\"Visual\",,\"One Short Signal Cable\",2,\"Offsite\",0\n105,\"VITAL\",\"H06G2033-1\",,\"Visual\",,\"Interface Unit\",2,\"Offsite\",0\n106,,,,\"Visual\",,\"Two Channel Main Power Cable\",2,\"Offsite\",0\n107,,,,\"Visual\",,\"One Monitor Main Power Cable\",2,\"Offsite\",0\n108,,,,\"Visual\",,\"One Interface Power Cable\",2,\"Offsite\",0\n109,\"Gould-Encore\",\"160-103025-001\",79292031,\"Host Computer\",\"PCB\",\"ADS MOD 9122\",3,\"1A1\",0\n110,\"Gould-Encore\",\"160-103109-001K\",\"TNP 20985\",\"Host Computer\",\"PCB\",\"Real Time Option Module MOD 2345\",3,\"1A1\",0\n111,\"Gould-Encore\",\"160-103175-001K\",\"SMP 24421\",\"Host Computer\",\"PCB\",\"Terminal, Line Printer, Console Controller MOD 9005\",3,\"1A1\",0\n112,\"Gould-Encore\",\"160-103478-005D\",\"PB 191078\",\"Host Computer\",\"PCB\",\"IMM\",3,\"1A2\",0\n113,\"Gould-Encore\",\"160-103196-001F\",\"LFP 6830\",\"Host Computer\",\"PCB\",\"Control Panel, Serial\",3,\"1A2\",0\n114,\"Gould-Encore\",\"160-103210-001C\",\"SMP 18186\",\"Host Computer\",\"PCB\",\"MTC\",3,\"1A2\",0\n115,\"Gould-Encore\",\"160-103249-005A\",\"NHP 16162\",\"Host Computer\",\"PCB\",\"MMB Set A 1-2 For Dynamic Test\",3,\"1A3\",0\n116,\"Gould-Encore\",\"160-103249-005A\",\"NHP 16305\",\"Host Computer\",\"PCB\",\"MMB Set A 2-2\",3,\"1A3\",0\n117,\"Gould-Encore\",\"160-103249-005A\",\"HE 411146\",\"Host Computer\",\"PCB\",\"MMB Set B 1-2\",3,\"1A3\",0\n118,\"Gould-Encore\",\"160-103249-005A\",\"NHP 16194\",\"Host Computer\",\"PCB\",\"MMB Set B 2-2\",3,\"1A3\",0\n119,\"Gould-Encore\",\"160-103249-005A\",\"NHP 16163\",\"Host Computer\",\"PCB\",\"MMB Set C 1-2\",3,\"1A3\",0\n120,\"Gould-Encore\",\"160-103249-005A\",49053,\"Host Computer\",\"PCB\",\"MMB Set C 2-2\",3,\"1A3\",0\n121,\"Gould-Encore\",\"160-103249-005A\",\"ES 391119\",\"Host Computer\",\"PCB\",\"MMB Set D 1-2\",3,\"1A4\",0\n122,\"Gould-Encore\",\"160-103249-005A\",\"WA 241207\",\"Host Computer\",\"PCB\",\"MMB Set D 2-2 For Dynamic Test\",3,\"1A4\",0\n123,\"Gould-Encore\",\"160-103265-002H\",\"HE 421214\",\"Host Computer\",\"PCB\",\"MBC Set 1-3\",3,\"1A4\",0\n124,\"Gould-Encore\",\"160-103265-002H\",\"NR 121278\",\"Host Computer\",\"PCB\",\"MBC Set 2-3\",3,\"1A4\",0\n125,\"Gould-Encore\",\"160-103265-002H\",\"BR 451344\",\"Host Computer\",\"PCB\",\"MBC Set 3-3 For Dynamic Test\",3,\"1A4\",0\n126,\"Gould-Encore\",\"EPOCH90  Rev K\",1083,\"Host Computer\",\"PCB\",\"Epoch Processor \",3,\"1A4\",0\n127,\"Gould-Encore\",\"160-103308-001N\",\"WA 261194\",\"Host Computer\",\"PCB\",\"Floating Point Processor MOD 2341 Set A 1-2\",3,\"1B1\",0\n128,\"Gould-Encore\",\"160-103309-001R\",\"NHP 15821\",\"Host Computer\",\"PCB\",\"Floating Point Processor MOD 2341 Set A 2-2\",3,\"1B1\",0\n129,\"Gould-Encore\",\"160-103308-001L\",\"KA 141748\",\"Host Computer\",\"PCB\",\"Floating Point Processor MOD 2341 Set B 1-2\",3,\"1B1\",0\n130,\"Gould-Encore\",\"160-103309-001M\",\"CW 071508\",\"Host Computer\",\"PCB\",\"Floating Point Processor MOD 2341 Set B 2-2\",3,\"1B1\",0\n131,\"Gould-Encore\",\"160-103308-001N\",\"BR 461072\",\"Host Computer\",\"PCB\",\"Floating Point Processor MOD 2341 Set A 1-2\",3,\"1B1\",0\n132,\"Gould-Encore\",\"160-103309-001P\",\"BR 471385\",\"Host Computer\",\"PCB\",\"Floating Point Processor MOD 2341 Set A 2-2\",3,\"1B1\",0\n133,\"Gould-Encore\",\"160-103308-001N\",\"FAP 3297\",\"Host Computer\",\"PCB\",\"Floating Point Processor Set B 1-2\",3,\"1B2\",0\n134,\"Gould-Encore\",\"160-103309-001R\",\"FAP 3247\",\"Host Computer\",\"PCB\",\"Floating Point Processor Set B 2-2\",3,\"1B2\",0\n135,\"Gould-Encore\",\"160-103436-001F\",\"SMP 19282\",\"Host Computer\",\"PCB\",\"CPU Processor Set A 1-3 \",3,\"1B2\",0\n136,\"Gould-Encore\",\"160-103437-001E\",\"SMP 19289\",\"Host Computer\",\"PCB\",\"CPU Processor Set A 2-3\",3,\"1B2\",0\n137,\"Gould-Encore\",\"160-103438-001D\",\"SMP 19305\",\"Host Computer\",\"PCB\",\"CPU Processor Set A 3-3\",3,\"1B2\",0\n138,\"Gould-Encore\",\"160-103436-001F\",\"SMP 16517\",\"Host Computer\",\"PCB\",\"CPU Processor Set B 1-3\",3,\"1B2\",0\n139,\"Gould-Encore\",\"160-103437-001E\",\"SMP 16552\",\"Host Computer\",\"PCB\",\"CPU Processor Set B 2-3\",3,\"1B2\",0\n140,\"Gould-Encore\",\"160-103438-001A\",\"AS 361101\",\"Host Computer\",\"PCB\",\"CPU Processor Set B 3-3\",3,\"1B2\",0\n141,\"Gould-Encore\",\"160-103436-001F\",\"PM 331697\",\"Host Computer\",\"PCB\",\"CPU Processor Set C 1-3\",3,\"1B3\",0\n142,\"Gould-Encore\",\"160-103437-001E\",\"PM 331638\",\"Host Computer\",\"PCB\",\"CPU Processor Set C 2-3\",3,\"1B3\",0\n143,\"Gould-Encore\",\"160-103438-001D\",\"PM 331611\",\"Host Computer\",\"PCB\",\"CPU Processor Set C 3-3\",3,\"1B3\",0\n144,\"Gould-Encore\",\"160-103436-001B\",\"ATZ 90063\",\"Host Computer\",\"PCB\",\"CPU Processor MOD 2005 Set 1-3\",3,\"1B4\",0\n145,\"Gould-Encore\",\"160-103437-001B\",\"TC 470118\",\"Host Computer\",\"PCB\",\"CPU Processor MOD 2005 Set 2-3\",3,\"1B4\",0\n146,\"Gould-Encore\",\"160-103438-001D\",\"SMP 19319\",\"Host Computer\",\"PCB\",\"CPU Processor MOD 2005 Set 3-3\",3,\"1B4\",0\n147,\"Gould-Encore\",\"160-103509-001H\",501,\"Host Computer\",\"PCB\",\"PCB Set 1-3 - IOP/DI\",3,\"1B4\",0\n148,\"Gould-Encore\",\"160-103519-001H\",\"A642\",\"Host Computer\",\"PCB\",\"PCB Set 2-3 - IOP\",3,\"1B4\",0\n149,\"Gould-Encore\",\"160-103998-001\",2192880,\"Host Computer\",\"PCB\",\"PCB Set 3-3 - Module DE, Interface PC\",3,\"1B4\",0\n150,\"Gould-Encore\",\"160-103554-001C\",\"PWP 01208\",\"Host Computer\",\"PCB\",\"HSD\",3,\"1B4\",0\n151,\"LH Research\",\"845293-051\",\"8331441AC\",\"Host Computer\",\"Power Supply\",\"5v 40a, 15v 11a, 15v 5a, 5v 1a   115vac\",3,\"1C1\",0\n152,\"LH Research\",\"845293-051\",\"8353670AD\",\"Host Computer\",\"Power Supply\",\"5v 40a, 15v 11a, 15v 5a, 5v 1a   115vac\",3,\"1C1\",0\n153,\"LH Research\",\"845293-051\",\"8353660AD\",\"Host Computer\",\"Power Supply\",\"5v 40a, 15v 11a, 15v 5a, 5v 1a   115vac\",3,\"1C1\",0\n154,\"LH Research\",\"845293-051\",\"8372000AF\",\"Host Computer\",\"Power Supply\",\"5v 40a, 15v 11a, 15v 5a, 5v 1a   115vac\",3,\"1C1\",0\n155,\"LH Research\",\"845293-051\",\"8235235Y\",\"Host Computer\",\"Power Supply\",\"5v 40a, 15v 11a, 15v 5a, 5v 1a   115vac\",3,\"1C2\",0\n156,\"LH Research\",\"846764-002\",\"P8303164U\",\"Host Computer\",\"Power Supply\",\"5v 200a\",3,\"1C2\",0\n157,\"Powertec\",\"9K5-200-17\",11118,\"Host Computer\",\"Power Supply\",\"5v 200a  115/230 vac\",3,\"1C2\",0\n158,\"Powertec\",\"9K5-200-17\",12264,\"Host Computer\",\"Power Supply\",\"5v 200a  115/230 vac\",3,\"1C2\",0\n159,\"Powertec\",\"9K5-200-17\",9703,\"Host Computer\",\"Power Supply\",\"5v 200a  115/230 vac\",3,\"1C3\",0\n160,\"Powertec\",\"9N5-150-17\",2296,\"Host Computer\",\"Power Supply\",\"5v 150a  115/230 vac\",3,\"1C3\",0\n161,\"Powertec\",\"9N5-150-17\",7274,\"Host Computer\",\"Power Supply\",\"5v 150a  115/230 vac\",3,\"1C3\",0\n162,\"Powertec\",\"9K5-200-17\",3476,\"Host Computer\",\"Power Supply\",\"5v 200a  115/230 vac\",3,\"1C3\",0\n163,\"Powertec\",\"9K5-200-17\",1132,\"Host Computer\",\"Power Supply\",\"5v 200a  115/230 vac\",3,\"1C4\",0\n164,\"Powertec\",\"9N5-150-17\",27356,\"Host Computer\",\"Power Supply\",\"26v 6a  115vac\",3,\"1C4\",0\n165,\"Powertec\",\"9N5-150-17\",22174,\"Host Computer\",\"Power Supply\",\"26v 6a  115vac\",3,\"1C4\",0\n166,\"Secur-A-Stor\",400976,17746,\"Host Computer\",\"Disc Drive\",\"SCSI Host Disc Drive\",3,\"1C5\",0\n167,\"Crown\",\"Model D75\",22208,\"Linkage\",\"Amplifier\",\"240 Watts  120 vac\",3,\"Offshelf\",0\n168,\"Crown\",\"Model D75\",22210,\"Linkage\",\"Amplifier\",\"240 Watts  120 vac\",3,\"Offshelf\",0\n169,\"Singer Link\",\"2010839-04\",\"C005\",\"Linkage\",\"PCB\",\"Fail Safe Force Amp. Card\",4,\"Prepacked\",0\n170,\"Singer Link\",\"2010846-03\",22,\"Linkage\",\"PCB\",\"Logic 1 Card (Serviceable)\",4,\"Prepacked\",0\n171,\"Singer Link\",\"2010859-02\",\"0264P\",\"Linkage\",\"PCB\",\"I/O Card\",4,\"Prepacked\",0\n172,\"Singer Link\",\"2010861-02\",1203,\"Linkage\",\"PCB\",\"Lamp Driver Card\",4,\"Prepacked\",0\n173,\"Singer Link\",\"2010862-02\",\"0191P\",\"Linkage\",\"PCB\",\"Sequence 2 Card\",4,\"Prepacked\",0\n174,\"Singer Link\",\"2010863-09\",36378,\"Linkage\",\"PCB\",\"DC Power Fault Dect\",4,\"Prepacked\",0\n175,\"Singer Link\",2010864,\"C0012\",\"Linkage\",\"PCB\",\"Hybrid Card. Condition - Repairable\",4,\"Prepacked\",0\n176,\"Singer Link\",\"2010864-02\",2,\"Linkage\",\"PCB\",\"Hybrid Card\",4,\"Prepacked\",0\n177,\"Singer Link\",\"2010864-02\",10,\"Linkage\",\"PCB\",\"Hybrid Card\",4,\"Prepacked\",0\n178,\"Singer Link\",\"2010881-02\",\"R10976\",\"Linkage\",\"PCB\",\"AO/AI Card\",4,\"Prepacked\",0\n179,\"Singer Link\",\"2010919-01\",\"C0002\",\"Linkage\",\"PCB\",\"Power Sequence Card\",4,\"Prepacked\",0\n180,\"Singer Link\",\"2010928-01\",\"C0059\",\"Linkage\",\"PCB\",\"Terminator Card Subcontroller\",4,\"Prepacked\",0\n181,\"Singer Link\",\"2010959-01\",\"0029P\",\"Linkage\",\"PCB\",\"Pump Logic Hyd\",4,\"Prepacked\",0\n182,\"Singer Link\",\"2010975-03\",910,\"Linkage\",\"PCB\",\"Subcontroller Card\",4,\"Prepacked\",0\n183,\"Singer Link\",\"2010975-03\",422,\"Linkage\",\"PCB\",\"Subcontroller Card\",4,\"Prepacked\",0\n184,\"Singer Link\",\"2010975-03\",425,\"Linkage\",\"PCB\",\"Subcontroller Card\",4,\"Prepacked\",0\n185,\"Singer Link\",\"2010975-03\",399,\"Linkage\",\"PCB\",\"Subcontroller Card. Condition - Repairable\",4,\"Prepacked\",0\n186,\"Singer Link\",\"2010975-03\",430,\"Linkage\",\"PCB\",\"Subcontroller Card\",4,\"Prepacked\",0\n187,\"Singer Link\",\"2010983-01\",24,\"Linkage\",\"PCB\",\"Logic II Card\",4,\"Prepacked\",0\n188,\"Singer Link\",\"2010983-01\",31,\"Linkage\",\"PCB\",\"Logic II Card\",4,\"Prepacked\",0\n189,\"Singer Link\",\"2014047-001\",89,\"Linkage\",\"PCB\",\"Memory Card\",4,\"Prepacked\",0\n190,\"Singer Link\",\"2018509-01\",19,\"Linkage\",\"PCB\",\"Master Controller Panel\",4,\"Prepacked\",0\n191,\"Singer Link\",\"2058402-001\",\"0013P\",\"Linkage\",\"PCB\",\"Sel DMA No. 2\",4,\"Prepacked\",0\n192,\"Singer Link\",\"2058404-001\",\"C0012\",\"Linkage\",\"PCB\",\"Sel DMA No. 1\",4,\"Prepacked\",0\n193,\"Singer Link\",\"2062361-02\",\"C0003\",\"Linkage\",\"PCB\",\"Isolator Aural Cue Card\",4,\"Prepacked\",0\n194,\"Singer Link\",\"2062442-01\",\"C0728\",\"Linkage\",\"PCB\",\"I/O Card (Solid State Relay)\",4,\"Prepacked\",0\n195,\"Singer Link\",\"2070213-01\",\"C0108\",\"Linkage\",\"PCB\",\"I/O Card (Circuit Breaker)\",4,\"Prepacked\",0\n196,\"Singer Link\",\"2070215-02\",\"R0010\",\"Linkage\",\"PCB\",\"Syncro Output Card\",4,\"Prepacked\",0\n197,\"Singer Link\",\"2070216-01\",107,\"Linkage\",\"PCB\",\"I/O Card (System Card 2)\",4,\"Prepacked\",0\n198,\"Singer Link\",\"2070217-01\",192,\"Linkage\",\"PCB\",\"I/O Card (System Card 3)\",4,\"Prepacked\",0\n199,\"Singer Link\",\"2070218-01\",533,\"Linkage\",\"PCB\",\"I/O Card (Relay Card). Condition - Repairable\",4,\"Prepacked\",0\n200,\"Singer Link\",\"2070230-02\",\"0013P\",\"Linkage\",\"PCB\",\"Lamp Dimmer Card\",4,\"Prepacked\",0\n201,\"Singer Link\",\"2070881-01\",\"C0007\",\"Linkage\",\"PCB\",\"Relay Floor Air Conditioning\",4,\"Prepacked\",0\n202,\"Singer Link\",\"2071073-002\",62,\"Linkage\",\"PCB\",\"Servo Control Card\",4,\"Prepacked\",0\n203,\"Singer Link\",\"2071078-002\",\"C0005\",\"Linkage\",\"PCB\",\"Power Control Card\",4,\"Prepacked\",0\n204,\"Singer Link\",\"2080723-001\",2,\"Linkage\",\"PCB\",\"Circuit Board\",4,\"Prepacked\",0\n205,\"Singer Link\",\"2080723-001\",1,\"Linkage\",\"PCB\",\"Circuit Board\",4,\"Prepacked\",0\n206,\"Singer Link\",\"2090599-01\",34,\"Linkage\",\"PCB\",\"RA Drive & Compass Amp. Card. Condition Unserviceable\",4,\"Prepacked\",0\n207,\"Singer Link\",\"2092708-01\",\"C0004\",\"Linkage\",\"PCB\",\"IRCU Lamp Due Card\",4,\"Prepacked\",0\n208,\"Singer Link\",\"2092713-01\",\"0004C\",\"Linkage\",\"PCB\",\"Digital Test Card\",4,\"Prepacked\",0\n209,\"Singer Link\",\"2114719-006\",\"C1009D\",\"Linkage\",\"PCB\",\"Force / Servo Amp. Card\",4,\"Prepacked\",0\n210,\"Singer Link\",\"2114719-006\",\"C0001\",\"Linkage\",\"PCB\",\"Force / Servo Amp. Card\",4,\"Prepacked\",0\n211,\"Singer Link\",\"2114719-006\",\"1008P\",\"Linkage\",\"PCB\",\"Force / Servo Amp. Card\",4,\"Prepacked\",0\n212,\"Singer Link\",\"2114719-006\",\"0005P\",\"Linkage\",\"PCB\",\"Force / Servo Amp. Card\",4,\"Prepacked\",0\n213,\"Singer Link\",\"2114726-001\",\"C0014\",\"Linkage\",\"PCB\",\"Latency Test Filter & Buffer Card\",4,\"Prepacked\",0\n214,\"Singer Link\",\"2123081-001\",391,\"Linkage\",\"PCB\",\"I/O Card\",4,\"Prepacked\",0\n215,\"Singer Link\",\"2123081-001\",392,\"Linkage\",\"PCB\",\"I/O Card\",4,\"Prepacked\",0\n216,\"Singer Link\",\"2123081-001\",\"0784P\",\"Linkage\",\"PCB\",\"I/O Card\",4,\"Prepacked\",0\n217,\"Singer Link\",\"2123081-001\",399,\"Linkage\",\"PCB\",\"I/O Card\",4,\"Prepacked\",0\n218,\"Singer Link\",\"2128702-004\",1,\"Linkage\",\"PCB\",\"Aileron Control Loading Card\",4,\"Prepacked\",0\n219,\"Singer Link\",\"2128702-005\",35378,\"Linkage\",\"PCB\",\"Elevator Control Loading Card\",4,\"Prepacked\",0\n220,\"Singer Link\",\"2128702-006\",\"C0001\",\"Linkage\",\"PCB\",\"Rudder Control Loading Card\",4,\"Prepacked\",0\n221,\"Singer Link\",\"2128704-001\",\"C0003\",\"Linkage\",\"PCB\",\"Input Message Assembler Card\",4,\"Prepacked\",0\n222,\"Singer Link\",\"2128706-001\",\"C0002\",\"Linkage\",\"PCB\",\"Input Message Control Card\",4,\"Prepacked\",0\n223,\"Singer Link\",\"2128707-001\",36378,\"Linkage\",\"PCB\",\"Output Message Assembler Card. Condition - Repairable\",4,\"Prepacked\",0\n224,\"Singer Link\",\"2128708-001\",\"C0004\",\"Linkage\",\"PCB\",\"Memory Control Card\",4,\"Prepacked\",0\n225,\"Singer Link\",\"2128709-001\",\"C0003\",\"Linkage\",\"PCB\",\"Pointer Data Control Card\",4,\"Prepacked\",0\n226,\"Singer Link\",\"2128710-001\",\"C0005\",\"Linkage\",\"PCB\",\"Test Message Control 1 Card\",4,\"Prepacked\",0\n227,\"Singer Link\",\"2128711-001\",\"C0002\",\"Linkage\",\"PCB\",\"Output Port Card\",4,\"Prepacked\",0\n228,\"Singer Link\",\"2128712-001\",\"C0003\",\"Linkage\",\"PCB\",\"Test Message Control 2 Card\",4,\"Prepacked\",0\n229,\"Singer Link\",\"2131555-003\",\"C0003\",\"Linkage\",\"PCB\",\"Component Misc. Flt. Director Card\",4,\"Prepacked\",0\n230,\"Singer Link\",\"2131556-001\",\"C0001\",\"Linkage\",\"PCB\",\"GPWS Misc. Card\",4,\"Prepacked\",0\n231,\"Singer Link\",\"2131559-001\",\"A2584\",\"Linkage\",\"PCB\",\"Circuit Card. Condition - ??\",4,\"Prepacked\",0\n232,\"Singer Link\",\"2131563-001\",\"C0004\",\"Linkage\",\"PCB\",\"Control Loading Misc. Card\",4,\"Prepacked\",0\n233,\"Singer Link\",\"3015626-001\",4,\"Linkage\",\"PCB\",\"Serial Data IRCU Interface\",4,\"Prepacked\",0\n234,\"Singer Link\",\"3099328-001\",24,\"Linkage\",\"PCB\",\"D/S ESRD Card\",4,\"Prepacked\",0\n235,\"Singer Link\",\"3099328-001\",25,\"Linkage\",\"PCB\",\"D/S ESRD Card. Condition - Unserviceable\",4,\"Prepacked\",0\n236,\"Singer Link\",\"3099328-001\",57,\"Linkage\",\"PCB\",\"D/S ESRD Card\",4,\"Prepacked\",0\n237,\"Singer Link\",\"7464814-30\",\"C0195\",\"Linkage\",\"PCB\",\"I/O Card\",4,\"Prepacked\",0\n238,\"Singer Link\",\"7464848-10\",\"C0142\",\"Linkage\",\"PCB\",\"Monitor and Briefing Audio Card\",4,\"Prepacked\",0\n239,\"Singer Link\",\"2010975-03\",429,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n240,\"Singer Link\",\"2010859-02\",1130,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n241,\"Singer Link\",\"2010859-02\",1121,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n242,\"Singer Link\",\"2010213-01\",220,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n243,\"Singer Link\",\"2010213-01\",224,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n244,\"Singer Link\",\"2010859-02\",1123,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n245,\"Singer Link\",\"2010859-02\",1122,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n246,\"Singer Link\",\"2010859-02\",1126,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n247,\"Singer Link\",\"2070213-01\",222,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n248,\"Singer Link\",\"2070218-01\",530,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n249,\"Singer Link\",\"2010859-02\",1128,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n250,\"Singer Link\",\"2062444-03\",\"No SN\",\"Linkage\",\"PCB\",,4,\"Box 8\",0\n251,\"Singer Link\",\"2062444-02\",56,\"Linkage\",\"PCB\",,4,\"Box9\",0\n252,\"Singer Link\",\"3015628-001\",17,\"Linkage\",\"PCB\",,4,\"Box9\",0\n253,\"Singer Link\",\"2010975-03\",421,\"Linkage\",\"PCB\",,4,\"Box9\",0\n254,\"Singer Link\",\"2062436-01\",470,\"Linkage\",\"PCB\",,4,\"Box9\",0\n255,\"Singer Link\",\"2062436-01\",465,\"Linkage\",\"PCB\",,4,\"Box9\",0\n256,\"Singer Link\",\"2090598-01\",9,\"Linkage\",\"PCB\",,4,\"Box9\",0\n257,\"Singer Link\",\"2062436-01\",469,\"Linkage\",\"PCB\",,4,\"Box9\",0\n258,\"Singer Link\",\"2062436-01\",468,\"Linkage\",\"PCB\",,4,\"Box9\",0\n259,\"Singer Link\",\"2062436-01\",466,\"Linkage\",\"PCB\",,4,\"Box9\",0\n260,\"Singer Link\",\"2123081-001\",408,\"Linkage\",\"PCB\",,4,\"Box9\",0\n261,\"Singer Link\",\"2062422-01\",49,\"Linkage\",\"PCB\",,4,\"Box9\",0\n262,\"Singer Link\",\"2092706-02\",1,\"Linkage\",\"PCB\",,4,\"Box9\",0\n263,\"Singer Link\",\"7464848-10\",125,\"Linkage\",\"PCB\",,4,\"BFB\",0\n264,\"Singer Link\",\"2090607-01\",1,\"Linkage\",\"PCB\",,4,\"BFB\",0\n265,\"Singer Link\",\"2010975-03\",426,\"Linkage\",\"PCB\",,4,\"BFB\",0\n266,\"Singer Link\",\"2010837-02\",435,\"Linkage\",\"PCB\",,4,\"BFB\",0\n267,\"Singer Link\",\"2010834-02\",103,\"Linkage\",\"PCB\",,4,\"BFB\",0\n268,\"Singer Link\",\"2010837-02\",434,\"Linkage\",\"PCB\",,4,\"BFB\",0\n269,\"Singer Link\",\"2010833-02\",63,\"Linkage\",\"PCB\",,4,\"BFB\",0\n270,\"Singer Link\",\"2090603-02\",128,\"Linkage\",\"PCB\",,4,\"BFB\",0\n271,\"Singer Link\",\"2090603-01\",127,\"Linkage\",\"PCB\",,4,\"BFB\",0\n272,\"Singer Link\",\"2010837-02\",433,\"Linkage\",\"PCB\",,4,\"BFB\",0\n273,\"Singer Link\",\"2010834-03\",132,\"Linkage\",\"PCB\",,4,\"BFB\",0\n274,\"Singer Link\",\"2010836-02\",145,\"Linkage\",\"PCB\",,4,\"BFB\",0\n275,\"Singer Link\",\"2010949-01\",158,\"Linkage\",\"PCB\",,4,\"BFB\",0\n276,\"Singer Link\",\"2090601-01\",116,\"Linkage\",\"PCB\",,4,\"BFB\",0\n277,\"Singer Link\",\"2082590-01\",4,\"Linkage\",\"PCB\",,4,\"BFB\",0\n278,\"Singer Link\",\"2124345-001\",910,\"Linkage\",\"PCB\",,4,\"BFB\",0\n279,\"Singer Link\",\"2070218-01\",528,\"Linkage\",\"PCB\",,4,\"BFB\",0\n280,\"Singer Link\",\"2062436-01\",467,\"Linkage\",\"PCB\",,4,\"BFB\",0\n281,\"Singer Link\",\"2010975-03\",427,\"Linkage\",\"PCB\",,4,\"BFB\",0\n282,\"Singer Link\",\"2010861-02\",209,\"Linkage\",\"PCB\",,4,\"BFB\",0\n283,\"Singer Link\",\"2123081-001\",332,\"Linkage\",\"PCB\",,4,\"BFB\",0\n284,\"Singer Link\",\"2123081-001\",414,\"Linkage\",\"PCB\",,4,\"BFB\",0\n285,\"Singer Link\",\"2123081-001\",400,\"Linkage\",\"PCB\",,4,\"BFB\",0\n286,\"Singer Link\",\"2070213-01\",218,\"Linkage\",\"PCB\",,4,\"BFB\",0\n287,\"Singer Link\",\"2070218-01\",\"No SN\",\"Linkage\",\"PCB\",,4,\"BFB\",0\n288,\"Singer Link\",\"2070218-01\",529,\"Linkage\",\"PCB\",,4,\"BFB\",0\n289,\"Singer Link\",\"3099328-001\",44,\"Linkage\",\"PCB\",,4,\"BFB\",0\n290,\"Singer Link\",\"3099328-001\",33,\"Linkage\",\"PCB\",,4,\"BFB\",0\n291,\"Singer Link\",\"3099328-001\",23,\"Linkage\",\"PCB\",,4,\"BFB\",0\n292,\"Singer Link\",\"2070219-01\",174,\"Linkage\",\"PCB\",,4,\"BFB\",0\n293,\"Singer Link\",\"3015626-001\",9,\"Linkage\",\"PCB\",,4,\"BFB\",0\n294,\"Singer Link\",\"3015626-001\",8,\"Linkage\",\"PCB\",,4,\"BFB\",0\n295,\"Singer Link\",\"2070218-01\",526,\"Linkage\",\"PCB\",,4,\"BFB\",0\n296,\"Singer Link\",\"2010975-03\",417,\"Linkage\",\"PCB\",,4,\"Box1\",0\n297,\"Singer Link\",\"2010861-02\",1110,\"Linkage\",\"PCB\",,4,\"Box1\",0\n298,\"Singer Link\",\"2010861-02\",1204,\"Linkage\",\"PCB\",,4,\"Box1\",0\n299,\"Singer Link\",\"2062442-01\",604,\"Linkage\",\"PCB\",,4,\"Box1\",0\n300,\"Singer Link\",\"2062442-01\",603,\"Linkage\",\"PCB\",,4,\"Box1\",0\n301,\"Singer Link\",\"2062442-01\",602,\"Linkage\",\"PCB\",,4,\"Box1\",0\n302,\"Singer Link\",\"2070213-01\",\"No SN\",\"Linkage\",\"PCB\",,4,\"Box1\",0\n303,\"Singer Link\",\"2010859-02\",1125,\"Linkage\",\"PCB\",,4,\"Box1\",0\n304,\"Singer Link\",\"2010859-02\",1129,\"Linkage\",\"PCB\",,4,\"Box1\",0\n305,\"Singer Link\",\"2123081-001\",404,\"Linkage\",\"PCB\",,4,\"Box1\",0\n306,\"Singer Link\",\"2123081-001\",396,\"Linkage\",\"PCB\",,4,\"Box1\",0\n307,\"Singer Link\",\"2123081-001\",397,\"Linkage\",\"PCB\",,4,\"Box1\",0\n308,\"Singer Link\",\"2070218-01\",539,\"Linkage\",\"PCB\",,4,\"Box1\",0\n309,\"Singer Link\",\"2070218-01\",531,\"Linkage\",\"PCB\",,4,\"Box1\",0\n310,\"Singer Link\",\"2070218-01\",510,\"Linkage\",\"PCB\",,4,\"Box1\",0\n311,\"Singer Link\",\"2123081-001\",412,\"Linkage\",\"PCB\",,4,\"Box2\",0\n312,\"Singer Link\",\"2087685-02\",1000,\"Linkage\",\"PCB\",,4,\"Box2\",0\n313,\"Singer Link\",\"2010975-03\",\"No SN\",\"Linkage\",\"PCB\",,4,\"Box2\",0\n314,\"Singer Link\",\"3099328-001\",30,\"Linkage\",\"PCB\",,4,\"Box2\",0\n315,\"Singer Link\",\"3099328-001\",10,\"Linkage\",\"PCB\",,4,\"Box2\",0\n316,\"Singer Link\",\"3099328-001\",43,\"Linkage\",\"PCB\",,4,\"Box2\",0\n317,\"Singer Link\",\"2070218-01\",527,\"Linkage\",\"PCB\",,4,\"Box2\",0\n318,\"Singer Link\",\"2070216-01\",252,\"Linkage\",\"PCB\",,4,\"Box2\",0\n319,\"Singer Link\",\"2070218-01\",536,\"Linkage\",\"PCB\",,4,\"Box2\",0\n320,\"Singer Link\",\"2070219-01\",175,\"Linkage\",\"PCB\",,4,\"Box2\",0\n321,\"Singer Link\",\"2123081-001\",407,\"Linkage\",\"PCB\",,4,\"Box2\",0\n322,\"Singer Link\",\"2123081-001\",402,\"Linkage\",\"PCB\",,4,\"Box3\",0\n323,\"Singer Link\",\"2090599-01\",\"No SN\",\"Linkage\",\"PCB\",,4,\"Box3\",0\n324,\"Singer Link\",\"2131563-001\",3,\"Linkage\",\"PCB\",,4,\"Box3\",0\n325,\"Singer Link\",\"2080723-01\",,\"Linkage\",\"PCB\",,4,\"Box3\",0\n326,\"Singer Link\",\"2123081-001\",393,\"Linkage\",\"PCB\",,4,\"Box3\",0\n327,\"Singer Link\",\"2123081-001\",403,\"Linkage\",\"PCB\",,4,\"Box3\",0\n328,\"Singer Link\",\"2128702-006\",1000,\"Linkage\",\"PCB\",,4,\"Box3\",0\n329,\"Singer Link\",\"2128702-005\",\"0003P\",\"Linkage\",\"PCB\",,4,\"Box3\",0\n330,\"Singer Link\",\"2128702-004\",\"C0003\",\"Linkage\",\"PCB\",,4,\"Box3\",0\n331,\"Singer Link\",\"2123081-001\",394,\"Linkage\",\"PCB\",,4,\"Box3\",0\n332,\"Singer Link\",\"2123081-001\",398,\"Linkage\",\"PCB\",,4,\"Box3\",0\n333,\"Singer Link\",\"2070213-01\",\"No SN\",\"Linkage\",\"PCB\",,4,\"Box3\",0\n334,\"Singer Link\",\"2010975-03\",448,\"Linkage\",\"PCB\",,4,\"Box3\",0\n335,\"Singer Link\",\"2123081-001\",415,\"Linkage\",\"PCB\",,4,\"Box4\",0\n336,\"Singer Link\",\"2123081-001\",416,\"Linkage\",\"PCB\",,4,\"Box4\",0\n337,\"Singer Link\",\"2123081-001\",405,\"Linkage\",\"PCB\",,4,\"Box4\",0\n338,\"Singer Link\",\"2123081-001\",395,\"Linkage\",\"PCB\",,4,\"Box4\",0\n339,\"Singer Link\",\"2123081-001\",401,\"Linkage\",\"PCB\",,4,\"Box4\",0\n340,\"Singer Link\",\"2010860-02\",204,\"Linkage\",\"PCB\",,4,\"Box4\",0\n341,\"Singer Link\",\"2010861-02\",1113,\"Linkage\",\"PCB\",,4,\"Box4\",0\n342,\"Singer Link\",\"2010975-03\",423,\"Linkage\",\"PCB\",,4,\"Box4\",0\n343,\"Singer Link\",\"3099328-001\",41,\"Linkage\",\"PCB\",,4,\"Box4\",0\n344,\"Singer Link\",\"3099328-001\",40,\"Linkage\",\"PCB\",,4,\"Box4\",0\n345,\"Singer Link\",\"3099328-001\",34,\"Linkage\",\"PCB\",,4,\"Box4\",0\n346,\"Singer Link\",\"3099328-001\",6,\"Linkage\",\"PCB\",,4,\"Box4\",0\n347,\"Singer Link\",\"3099328-001\",42,\"Linkage\",\"PCB\",,4,\"Box5\",0\n348,\"Singer Link\",\"3099328-001\",66,\"Linkage\",\"PCB\",,4,\"Box5\",0\n349,\"Singer Link\",\"3099328-001\",26,\"Linkage\",\"PCB\",,4,\"Box5\",0\n350,\"Singer Link\",\"2070216-01\",253,\"Linkage\",\"PCB\",,4,\"Box5\",0\n351,\"Singer Link\",\"2070218-01\",525,\"Linkage\",\"PCB\",,4,\"Box5\",0\n352,\"Singer Link\",\"2123081-01\",413,\"Linkage\",\"PCB\",,4,\"Box5\",0\n353,\"Singer Link\",\"2070219-01\",171,\"Linkage\",\"PCB\",,4,\"Box5\",0\n354,\"Singer Link\",\"2070219-01\",176,\"Linkage\",\"PCB\",,4,\"Box5\",0\n355,\"Singer Link\",\"2123081-001\",409,\"Linkage\",\"PCB\",,4,\"Box5\",0\n356,\"Singer Link\",\"2090599-01\",\"0042P\",\"Linkage\",\"PCB\",,4,\"Box5\",0\n357,\"Singer Link\",\"2010975-03\",420,\"Linkage\",\"PCB\",,4,\"Box5\",0\n358,\"Singer Link\",\"2010975-03\",419,\"Linkage\",\"PCB\",,4,\"Box5\",0\n359,\"Singer Link\",\"7464834-10\",36,\"Linkage\",\"PCB\",,4,\"Box6\",0\n360,\"Singer Link\",\"7464834-10\",35,\"Linkage\",\"PCB\",,4,\"Box6\",0\n361,\"Singer Link\",\"7464834-10\",32,\"Linkage\",\"PCB\",,4,\"Box6\",0\n362,\"Singer Link\",\"7464834-10\",\"No SN\",\"Linkage\",\"PCB\",,4,\"Box6\",0\n363,\"Singer Link\",\"2070218-01\",566,\"Linkage\",\"PCB\",,4,\"Box6\",0\n364,\"Singer Link\",\"2070216-01\",106,\"Linkage\",\"PCB\",,4,\"Box6\",0\n365,\"Singer Link\",\"2070219-01\",177,\"Linkage\",\"PCB\",,4,\"Box6\",0\n366,\"Singer Link\",\"2070218-01\",534,\"Linkage\",\"PCB\",,4,\"Box6\",0\n367,\"Singer Link\",\"2062442-01\",601,\"Linkage\",\"PCB\",,4,\"Box6\",0\n368,\"Singer Link\",\"2010861-02\",1064,\"Linkage\",\"PCB\",,4,\"Box6\",0\n369,\"Singer Link\",\"2010861-02\",1107,\"Linkage\",\"PCB\",,4,\"Box6\",0\n370,\"Singer Link\",\"7464814-30\",180,\"Linkage\",\"PCB\",,4,\"Box6\",0\n371,\"Singer Link\",\"2070217-01\",\"No SN\",\"Linkage\",\"PCB\",,4,\"Box6\",0\n372,\"Singer Link\",\"2010861-02\",1108,\"Linkage\",\"PCB\",,4,\"Box7\",0\n373,\"Singer Link\",\"2010861-02\",1109,\"Linkage\",\"PCB\",,4,\"Box7\",0\n374,\"Singer Link\",\"2010975-03\",424,\"Linkage\",\"PCB\",,4,\"Box7\",0\n375,\"Singer Link\",\"2010859-02\",1120,\"Linkage\",\"PCB\",,4,\"Box7\",0\n376,\"Singer Link\",\"2010859-02\",1127,\"Linkage\",\"PCB\",,4,\"Box7\",0\n377,\"Singer Link\",\"2070219-01\",172,\"Linkage\",\"PCB\",,4,\"Box7\",0\n378,\"Singer Link\",\"2070218-01\",538,\"Linkage\",\"PCB\",,4,\"Box7\",0\n379,\"Singer Link\",\"2123081-001\",411,\"Linkage\",\"PCB\",,4,\"Box7\",0\n380,\"Singer Link\",\"2123081-001\",410,\"Linkage\",\"PCB\",,4,\"Box7\",0\n381,\"Singer Link\",\"2070215-01\",126,\"Linkage\",\"PCB\",,4,\"Box7\",0\n382,\"Singer Link\",\"2070219-01\",182,\"Linkage\",\"PCB\",,4,\"Box7\",0\n383,\"Singer Link\",\"2070215-01\",168,\"Linkage\",\"PCB\",,4,\"Box7\",0\n384,\"Singer Link\",\"2010859-02\",1124,\"Linkage\",\"PCB\",,4,\"Box7\",0\n385,\"Singer Link\",\"2010218-01\",537,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n386,\"Singer Link\",\"2010975-03\",161,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n387,\"Singer Link\",\"2070213-01\",219,\"Linkage\",\"PCB\",,4,\"Box 8\",0\n388,\"Singer Link\",\"2070245-01/2145549-001\",11,\"Linkage\",\"PCB\",\"Lighting/Power Distribution Cards\",4,\"Box 9\",0\n389,\"Singer Link\",\"2070245-01/2145549-001\",22,\"Linkage\",\"PCB\",\"Lighting/Power Distribution Cards\",4,\"Box 9\","
  },
  {
    "path": "examples/data/sample2.csv",
    "content": "\"TimeStamp (ms)\",\"MID 128|PID 91|Accelerator pedal position (%)\",\"MID 128|PID 92|Engine load(%)\",\"MID 128|PID 100|Engine oil pressure (bar)\",\"MID 128|PID 105|Intake manifold temperature (N0C)\",\"MID 128|PID 110|Engine coolant temperature (N0C)\",\"MID 128|PID 190|Engine speed (r/min)\"\n115,10.4,0,0,0,0,0\n175,,40,,,,\n309,,,4.55,,,\n529,,,,17,,\n630,,,,,46,\n682,,,,,,1011.25\n751,10.4,,,,,\n803,,40,,,,\n856,,,4.55,,,\n921,,,,17,,\n1013,,,,,46,\n1521,,,,,,1016.5\n1593,10.4,,,,,\n1641,,39,,,,\n1704,,,4.58,,,\n1761,,,,17,,\n1832,,,,,46,\n1897,,,,,,1023\n1961,10.4,,,,,\n2025,,37,,,,\n2088,,,4.58,,,\n2145,,,,17,,\n2217,,,,,46,\n2283,,,,,,1022.25\n2344,10.4,,,,,\n2408,,36,,,,\n2464,,,4.58,,,\n2576,,,,17,,\n2633,,,,,46,\n2698,,,,,,1001\n2767,10.4,,,,,"
  },
  {
    "path": "examples/data/sine.csv",
    "content": "0,0.5\n0.01,0.5313952597646567\n0.02,0.5626666167821521\n0.03,0.5936906572928623\n0.04,0.6243449435824274\n0.05,0.6545084971874737\n0.060000000000000005,0.684062276342339\n0.07,0.7128896457825363\n0.08,0.7408768370508576\n0.09,0.7679133974894983\n0.09999999999999999,0.7938926261462365\n0.10999999999999999,0.8187119948743449\n0.11999999999999998,0.8422735529643443\n0.12999999999999998,0.8644843137107057\n0.13999999999999999,0.8852566213878945\n0.15,0.9045084971874736\n0.16,0.9221639627510074\n0.17,0.9381533400219317\n0.18000000000000002,0.9524135262330098\n0.19000000000000003,0.9648882429441257\n0.20000000000000004,0.9755282581475768\n0.21000000000000005,0.9842915805643155\n0.22000000000000006,0.9911436253643444\n0.23000000000000007,0.996057350657239\n0.24000000000000007,0.9990133642141358\n0.25000000000000006,1\n0.26000000000000006,0.9990133642141358\n0.2700000000000001,0.9960573506572389\n0.2800000000000001,0.9911436253643442\n0.2900000000000001,0.9842915805643154\n0.3000000000000001,0.9755282581475766\n0.3100000000000001,0.9648882429441255\n0.3200000000000001,0.9524135262330096\n0.3300000000000001,0.9381533400219315\n0.34000000000000014,0.9221639627510072\n0.35000000000000014,0.9045084971874733\n0.36000000000000015,0.8852566213878942\n0.37000000000000016,0.8644843137107052\n0.38000000000000017,0.8422735529643438\n0.3900000000000002,0.8187119948743442\n0.4000000000000002,0.7938926261462359\n0.4100000000000002,0.7679133974894976\n0.4200000000000002,0.7408768370508568\n0.4300000000000002,0.7128896457825354\n0.4400000000000002,0.6840622763423381\n0.45000000000000023,0.6545084971874727\n0.46000000000000024,0.6243449435824263\n0.47000000000000025,0.5936906572928612\n0.48000000000000026,0.5626666167821509\n0.49000000000000027,0.5313952597646555\n0.5000000000000002,0.4999999999999987\n0.5100000000000002,0.468604740235342\n0.5200000000000002,0.43733338321784654\n0.5300000000000002,0.4063093427071363\n0.5400000000000003,0.3756550564175712\n0.5500000000000003,0.3454915028125249\n0.5600000000000003,0.3159377236576596\n0.5700000000000003,0.2871103542174622\n0.5800000000000003,0.25912316294914095\n0.5900000000000003,0.23208660251050028\n0.6000000000000003,0.20610737385376204\n0.6100000000000003,0.1812880051256538\n0.6200000000000003,0.15772644703565436\n0.6300000000000003,0.135515686289293\n0.6400000000000003,0.11474337861210421\n0.6500000000000004,0.09549150281252528\n0.6600000000000004,0.07783603724899163\n0.6700000000000004,0.06184665997806754\n0.6800000000000004,0.04758647376698977\n0.6900000000000004,0.03511175705587394\n0.7000000000000004,0.024471741852422957\n0.7100000000000004,0.015708419435684295\n0.7200000000000004,0.008856374635655584\n0.7300000000000004,0.003942649342761062\n0.7400000000000004,0.0009866357858642205\n0.7500000000000004,0\n0.7600000000000005,0.0009866357858642205\n0.7700000000000005,0.0039426493427610065\n0.7800000000000005,0.008856374635655528\n0.7900000000000005,0.01570841943568424\n0.8000000000000005,0.0244717418524229\n0.8100000000000005,0.03511175705587388\n0.8200000000000005,0.047586473766989656\n0.8300000000000005,0.061846659978067486\n0.8400000000000005,0.07783603724899157\n0.8500000000000005,0.09549150281252516\n0.8600000000000005,0.1147433786121041\n0.8700000000000006,0.13551568628929272\n0.8800000000000006,0.15772644703565392\n0.8900000000000006,0.18128800512565313\n0.9000000000000006,0.2061073738537612\n0.9100000000000006,0.23208660251049917\n0.9200000000000006,0.2591231629491396\n0.9300000000000006,0.2871103542174607\n0.9400000000000006,0.31593772365765777\n0.9500000000000006,0.34549150281252283\n0.9600000000000006,0.3756550564175689\n0.9700000000000006,0.4063093427071337\n0.9800000000000006,0.4373333832178437\n0.9900000000000007,0.46860474023533893 \n"
  },
  {
    "path": "examples/demo.css",
    "content": "body {\n  font-family: 'Lato', san-serif;\n}\n\nh1, h2, h3, h4, h5 {\n  font-family: 'Roboto', sans-serif;\n  font-weight: 900;\n  margin: 0;\n}\n\nh2 {\n  margin-bottom: 10px;\n}\n\nhr {\n  margin: 20px;\n}\n\ntextarea {\n  width:100%;\n  white-space: nowrap;\n}\n\ncode {\n  font-family: 'Source Code Pro', monospace;\n}\n\n#header {\n  position: fixed;\n  top: 0px;\n  left: 0px;\n  width: 100%;\n  height: 50px;\n  background: #333333;\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n  z-index: 999;\n}\n\n#title {\n  float: left;\n  padding-top: 10px;\n  padding-left: 10%;\n  color: white;\n  font-size: 1.25rem;\n}\n\n#link {\n  float: right;\n  padding-top: 10px;\n  padding-right: 10%;\n  font-size: 1.25rem;\n  font-weight: 600;\n  text-decoration: none;\n}\n\n#link a, #link a:hover {\n  color: mediumorchid;\n  text-decoration: none;\n}\n\n#container {\n  width: 80%;\n  max-width: 960px;\n  padding: 0 50px 0 50px;\n  margin: 0 auto;\n  display: block;\n  overflow-x: hidden;\n  background: #F0F0F0;\n}\n\n#content {\n  background: #F0F0F0;\n  margin: 50px auto 0 auto;\n  padding: 20px 0 20px 0;\n}\n\n#run {\n  margin-top: 10px;\n  border-radius: 15%;\n}\n\n#result {\n  width: 100%;\n  height: 200px;\n  overflow: auto;\n}\n"
  },
  {
    "path": "examples/file-handling.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>File Handling</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">Load from File</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>The following demonstrates how to use the HTML5 File API to load a file from the client.</p>\n        <hr>\n        <h2>Input</h2>\n        <input type=\"file\" id=\"files\" name=\"files[]\" multiple />\n        <hr />\n        <h2>FileInfo</h2>\n        <div id=\"file-info\"></div>\n        <hr />\n        <h2>Result</h2>\n        <textarea id=\"result\" style=\"height: 250px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"http://code.jquery.com/jquery-3.3.1.slim.js\" integrity=\"sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"helpers.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $(document).ready(function() {\n        if(isFileAPIAvailable()) {\n          $('#files').bind('change', handleDialog);\n        }\n      });\n\n      function handleDialog(event) {\n        var files = event.target.files;\n        var file = files[0];\n\n        var fileInfo = `\n          <span style=\"font-weight:bold;\">${escape(file.name)}</span><br>\n          - FileType: ${file.type || 'n/a'}<br>\n          - FileSize: ${file.size} bytes<br>\n          - LastModified: ${file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() : 'n/a'}\n        `;\n        $('#file-info').append(fileInfo);\n\n        var reader = new FileReader();\n        reader.readAsText(file);\n        reader.onload = function(event){\n          var csv = event.target.result;\n          var data = $.csv.toArrays(csv);\n          $('#result').empty();\n          $('#result').html(JSON.stringify(data, null, 2));\n        }\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/flot.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Flot</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">jQuery-CSV + Flot</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>Flot is a popular library used to generate graphs in Javascript.</p>\n        <p>This Demo generates a basic Flot line graph using CSV as the input data.</p>\n        <hr>\n        <h2>Load File</h2>\n          <select id=\"file\" name=\"file\">\n            <option value=\"data/analytics1.csv\">analytics1.csv</option>\n            <option value=\"data/analytics2.csv\">analytics2.csv</option>\n            <option value=\"data/sine.csv\">sine.csv</option>\n            <option value=\"data/sample2.csv\">sample2.csv</option>\n          </select>\n          <input id=\"load-file\" type=\"button\" value=\"Load\" />\n        <hr />\n        <h2>Load Data</h2>\n        <textarea id=\"input\" style=\"height: 250px;\">0,0.5\n0.01,0.5313952597646567\n0.02,0.5626666167821521\n0.03,0.5936906572928623\n0.04,0.6243449435824274\n0.05,0.6545084971874737\n0.060000000000000005,0.684062276342339\n0.07,0.7128896457825363\n0.08,0.7408768370508576\n0.09,0.7679133974894983\n0.09999999999999999,0.7938926261462365\n0.10999999999999999,0.8187119948743449\n0.11999999999999998,0.8422735529643443\n0.12999999999999998,0.8644843137107057\n0.13999999999999999,0.8852566213878945\n0.15,0.9045084971874736\n0.16,0.9221639627510074\n0.17,0.9381533400219317\n0.18000000000000002,0.9524135262330098\n0.19000000000000003,0.9648882429441257\n0.20000000000000004,0.9755282581475768\n0.21000000000000005,0.9842915805643155\n0.22000000000000006,0.9911436253643444\n0.23000000000000007,0.996057350657239\n0.24000000000000007,0.9990133642141358\n0.25000000000000006,1\n0.26000000000000006,0.9990133642141358\n0.2700000000000001,0.9960573506572389\n0.2800000000000001,0.9911436253643442\n0.2900000000000001,0.9842915805643154\n0.3000000000000001,0.9755282581475766\n0.3100000000000001,0.9648882429441255\n0.3200000000000001,0.9524135262330096\n0.3300000000000001,0.9381533400219315\n0.34000000000000014,0.9221639627510072\n0.35000000000000014,0.9045084971874733\n0.36000000000000015,0.8852566213878942\n0.37000000000000016,0.8644843137107052\n0.38000000000000017,0.8422735529643438\n0.3900000000000002,0.8187119948743442\n0.4000000000000002,0.7938926261462359\n0.4100000000000002,0.7679133974894976\n0.4200000000000002,0.7408768370508568\n0.4300000000000002,0.7128896457825354\n0.4400000000000002,0.6840622763423381\n0.45000000000000023,0.6545084971874727\n0.46000000000000024,0.6243449435824263\n0.47000000000000025,0.5936906572928612\n0.48000000000000026,0.5626666167821509\n0.49000000000000027,0.5313952597646555\n0.5000000000000002,0.4999999999999987\n0.5100000000000002,0.468604740235342\n0.5200000000000002,0.43733338321784654\n0.5300000000000002,0.4063093427071363\n0.5400000000000003,0.3756550564175712\n0.5500000000000003,0.3454915028125249\n0.5600000000000003,0.3159377236576596\n0.5700000000000003,0.2871103542174622\n0.5800000000000003,0.25912316294914095\n0.5900000000000003,0.23208660251050028\n0.6000000000000003,0.20610737385376204\n0.6100000000000003,0.1812880051256538\n0.6200000000000003,0.15772644703565436\n0.6300000000000003,0.135515686289293\n0.6400000000000003,0.11474337861210421\n0.6500000000000004,0.09549150281252528\n0.6600000000000004,0.07783603724899163\n0.6700000000000004,0.06184665997806754\n0.6800000000000004,0.04758647376698977\n0.6900000000000004,0.03511175705587394\n0.7000000000000004,0.024471741852422957\n0.7100000000000004,0.015708419435684295\n0.7200000000000004,0.008856374635655584\n0.7300000000000004,0.003942649342761062\n0.7400000000000004,0.0009866357858642205\n0.7500000000000004,0\n0.7600000000000005,0.0009866357858642205\n0.7700000000000005,0.0039426493427610065\n0.7800000000000005,0.008856374635655528\n0.7900000000000005,0.01570841943568424\n0.8000000000000005,0.0244717418524229\n0.8100000000000005,0.03511175705587388\n0.8200000000000005,0.047586473766989656\n0.8300000000000005,0.061846659978067486\n0.8400000000000005,0.07783603724899157\n0.8500000000000005,0.09549150281252516\n0.8600000000000005,0.1147433786121041\n0.8700000000000006,0.13551568628929272\n0.8800000000000006,0.15772644703565392\n0.8900000000000006,0.18128800512565313\n0.9000000000000006,0.2061073738537612\n0.9100000000000006,0.23208660251049917\n0.9200000000000006,0.2591231629491396\n0.9300000000000006,0.2871103542174607\n0.9400000000000006,0.31593772365765777\n0.9500000000000006,0.34549150281252283\n0.9600000000000006,0.3756550564175689\n0.9700000000000006,0.4063093427071337\n0.9800000000000006,0.4373333832178437\n0.9900000000000007,0.46860474023533893</textarea>\n        <input id=\"load-data\" type=\"button\" value=\"Load\" />\n        <hr />\n        <h2>Plot</h2>\n        <div id=\"flot\" style=\"width:600px;height:300px;margin:0 auto;\"></div>\n        <h2>Data</h2>\n        <textarea id=\"result\" style=\"height: 250px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"https://code.jquery.com/jquery-3.3.1.min.js\" integrity=\"sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=\" crossorigin=\"anonymous\"></script>    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.min.js\"></script>\n    <script src=\"helpers.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $('#load-file').bind('click', function () {\n        loadFile();\n      });\n\n      $('#load-data').bind('click', function() {\n        loadData();\n      });\n\n      function loadFile() {\n        var file = $('#file').val();\n        $.get(file, function(csv) {\n            var data = $.csv.toArrays(csv, {\n              onParseValue: $.csv.hooks.castToScalar\n            });\n            plot(data);\n            $('#result').empty();\n            $('#result').html(JSON.stringify(data, null, 2));\n        });\n      }\n\n      function loadData() {\n        var csv = $('#input').val();\n        var data = $.csv.toArrays(csv, {\n          onParseValue: $.csv.hooks.castToScalar\n        });\n        plot(data);\n        $('#result').empty();\n        $('#result').html(JSON.stringify(data, null, 2));\n      }\n\n      function plot(data) {\n        $.plot($('#flot'), [data], {\n          series: {\n            lines: { show: true },\n            points: { show: true }\n          }\n        });\n      }\n    </script>\n\n  </body>\n</html>"
  },
  {
    "path": "examples/from-arrays.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>From Arrays</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">$.csv.fromArrays()</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>Used to format a fixed 2D array of data as CSV.</p>\n        <hr>\n        <h2>Usage</h2>\n        <pre><code class=\"javascript\">var result = $.csv.fromArrays(input);</code></pre>\n        <hr />\n        <h2>Input</h2>\n        <textarea id=\"input\" style=\"height: 200px;\">\n[\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n  [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"]\n]\n        </textarea>\n        <input id=\"run\" type=\"button\" value=\"Run\" />\n        <hr />\n        <h2>Result</h2>\n        <textarea id=\"result\" style=\"height: 170px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"http://code.jquery.com/jquery-3.3.1.slim.js\" integrity=\"sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $(document).ready(() => {\n        format();\n      });\n\n      $('#run').bind('click', function () {\n        format();\n      });\n\n      function format() {\n        const input = JSON.parse($('#input').val());\n        const csv = $.csv.fromArrays(input);\n        $('#result').empty();\n        $('#result').html(csv);\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/from-objects.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>From Objects</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">$.csv.fromObjects()</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>Used to format an array of structured objects as CSV.</p>\n        <hr>\n        <h2>Usage</h2>\n        <pre><code class=\"javascript\">var result = $.csv.fromObjects(input);</code></pre>\n        <hr />\n        <h2>Input</h2>\n        <textarea id=\"input\" style=\"height: 320px;\">\n[\n  {\n    \"ID\":\"1\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-132-111AA\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\"\n  },\n  {\n    \"ID\":\"2\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-132-111AA\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\"\n  }\n]\n        </textarea>\n        <input id=\"run\" type=\"button\" value=\"Run\" />\n        <hr />\n        <h2>Result</h2>\n        <textarea id=\"result\" style=\"height: 65px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"http://code.jquery.com/jquery-3.3.1.slim.js\" integrity=\"sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $(document).ready(() => {\n        format();\n      });\n\n      $('#run').bind('click', function () {\n        format();\n      });\n\n      function format() {\n        const input = JSON.parse($('#input').val());\n        const csv = $.csv.fromObjects(input);\n        $('#result').empty();\n        $('#result').html(csv);\n      }\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "examples/google-visualization.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Google Visualization</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">jQuery-CSV + Google Visualization API</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>Google Visualization API is a powerful too used to generate graphs in Javascript.</p>\n        <p>This Demo generates a basic scatter plot CSV as the input data.</p>\n        <hr>\n        <h2>Load File</h2>\n        <span>sample.csv</span>\n        <input id=\"load-file\" type=\"button\" value=\"Load File\" />\n        <hr />\n        <h2>Load Data</h2>\n        <textarea id=\"input\" style=\"height: 250px;\">\"TimeStamp (ms)\",\"MID 128|PID 91|Accelerator pedal position (%)\",\"MID 128|PID 92|Engine load(%)\",\"MID 128|PID 100|Engine oil pressure (bar)\",\"MID 128|PID 105|Intake manifold temperature (N0C)\",\"MID 128|PID 110|Engine coolant temperature (N0C)\",\"MID 128|PID 190|Engine speed (r/min)\"\n115,10.4,0,0,0,0,0\n175,,40,,,,\n309,,,4.55,,,\n529,,,,17,,\n630,,,,,46,\n682,,,,,,1011.25\n751,10.4,,,,,\n803,,40,,,,\n856,,,4.55,,,\n921,,,,17,,\n1013,,,,,46,\n1521,,,,,,1016.5\n1593,10.4,,,,,\n1641,,39,,,,\n1704,,,4.58,,,\n1761,,,,17,,\n1832,,,,,46,\n1897,,,,,,1023\n1961,10.4,,,,,\n2025,,37,,,,\n2088,,,4.58,,,\n2145,,,,17,,\n2217,,,,,46,\n2283,,,,,,1022.25\n2344,10.4,,,,,\n2408,,36,,,,\n2464,,,4.58,,,\n2576,,,,17,,\n2633,,,,,46,\n2698,,,,,,1001\n2767,10.4,,,,,</textarea>\n        <input id=\"load-data\" type=\"button\" value=\"Load\" />\n        <hr />\n        <h2>Plot</h2>\n        <div id=\"dashboard\">\n          <div id=\"chart\"></div>\n          <div id=\"control\"></div>\n          <input id=\"edit\" type=\"button\" value=\"Edit Chart\" />\n        </div>\n        <hr />\n        <h2>Data</h2>\n        <textarea id=\"result\" style=\"height: 250px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"https://code.jquery.com/jquery-3.3.1.min.js\" integrity=\"sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"http://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['controls', 'charteditor']}]}\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $('#load-file').bind('click', function () {\n        loadFile();\n      });\n\n      $('#load-data').bind('click', function() {\n        loadData();\n      });\n\n      function loadFile() {\n        var file = 'data/sample2.csv';\n        $.get(file, function(csv) {\n            var data = $.csv.toArrays(csv, {\n              onParseValue: $.csv.hooks.castToScalar\n            });\n            plot(data);\n            $('#result').empty();\n            $('#result').html(JSON.stringify(data, null, 2));\n        });\n      }\n\n      function loadData() {\n        var csv = $('#input').val();\n        var data = $.csv.toArrays(csv, {\n          onParseValue: $.csv.hooks.castToScalar\n        });\n        plot(data);\n        $('#result').empty();\n        $('#result').html(JSON.stringify(data, null, 2));\n      }\n\n      function plot(data) {\n        var data = new google.visualization.arrayToDataTable(data);\n        var dash = new google.visualization.Dashboard(document.getElementById('dashboard'));\n        var control = new google.visualization.ControlWrapper({\n          controlType: 'ChartRangeFilter',\n          containerId: 'control',\n          options: {\n            filterColumnIndex: 0,\n            ui: {\n              chartOptions: {\n                height: 50,\n                width: 800,\n                chartArea: {\n                  width: '50%'\n                },\n              },\n              chartView: {\n                columns: [0, 1]\n              }\n            }\n          }\n        });\n\n        var chart = new google.visualization.ChartWrapper({\n          chartType: 'LineChart',\n          containerId: 'chart',\n        });\n\n        function fixOptions(wrapper) {\n          // sets the options on the chart wrapper so that it draws correctly\n          wrapper.setOption('height', 300);\n          wrapper.setOption('width', 800);\n          wrapper.setOption('chartArea.width', '60%');\n          // the chart editor automatically enables animations, which doesn't look right with the ChartRangeFilter\n          wrapper.setOption('animation', null);\n          // the chart editor sets hAxis.viewWindowMode to 'pretty', which doesn't work well with continuous axes\n          wrapper.setOption('hAxis.viewWindowMode', 'maximized');\n          wrapper.setOption('curveType', 'function');\n        }\n\n        fixOptions(chart);\n\n        document.getElementById('edit').onclick = function() {\n          var editor = new google.visualization.ChartEditor();\n          google.visualization.events.addListener(editor, 'ok', function() {\n            chart = editor.getChartWrapper();\n            fixOptions(chart);\n            dash.bind([control], [chart]);\n            dash.draw(data);\n          });\n          editor.openDialog(chart);\n        };\n        \n        dash.bind([control], [chart]);\n        dash.draw(data);\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/helpers.js",
    "content": "const global = window\n\nglobal.isFileAPIAvailable = function () {\n  // Check for the various File API support.\n  if (window.File && window.FileReader && window.FileList && window.Blob) {\n    // Great success! All the File APIs are supported.\n    return true\n  } else {\n    // source: File API availability - http://caniuse.com/#feat=fileapi\n    // source: <output> availability - http://html5doctor.com/the-output-element/\n    document.writeln('The HTML5 APIs used in this form are only available in the following browsers:<br />')\n    // 6.0 File API & 13.0 <output>\n    document.writeln(' - Google Chrome: 13.0 or later<br />')\n    // 3.6 File API & 6.0 <output>\n    document.writeln(' - Mozilla Firefox: 6.0 or later<br />')\n    // 10.0 File API & 10.0 <output>\n    document.writeln(' - Internet Explorer: Not supported (partial support expected in 10.0)<br />')\n    // ? File API & 5.1 <output>\n    document.writeln(' - Safari: Not supported<br />')\n    // ? File API & 9.2 <output>\n    document.writeln(' - Opera: Not supported')\n    return false\n  }\n}\n\n// Used to generate the data for the sine wave demo\n// source: http://coding.smashingmagazine.com/2011/10/04/quick-look-math-animations-javascript/\nglobal.drawSine = function () {\n  let counter = 0\n  // 100 iterations\n  const increase = Math.PI * 2 / 100\n  for (let i = 0; i <= 1; i += 0.01) {\n    const x = i\n    const y = Math.sin(counter) / 2 + 0.5\n    counter += increase\n    console.log(x + ',' + y)\n  }\n}\n"
  },
  {
    "path": "examples/snippets/esm-usage.js",
    "content": "import * as csv from 'jquery-csv'\nimport * as fs from 'fs'\n\nconst sample = './data/sample.csv'\nfs.readFile(sample, 'UTF-8', (err, fileContent) => {\n  if (err) { console.log(err) }\n  csv.toArrays(fileContent, {}, (err, data) => {\n    if (err) { console.log(err) }\n    for (let i = 0, len = data.length; i < len; i++) {\n      console.log(data[i])\n    }\n  })\n})\n"
  },
  {
    "path": "examples/snippets/node-usage.js",
    "content": "/* eslint-disable no-unused-vars */\nconst fs = require('fs')\nconst csv = require('jquery-csv')\nconst sample = './data/sample.csv'\n\nfs.readFile(sample, 'UTF-8', function (err, csv) {\n  if (err) { console.log(err) }\n  csv.toArrays(csv, {}, function (err, data) {\n    if (err) { console.log(err) }\n    for (let i = 0, len = data.length; i < len; i++) {\n      console.log(data[i])\n    }\n  })\n})\n"
  },
  {
    "path": "examples/to-array.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>To Array</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">$.csv.toArray()</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>Used to parse a single line of CSV data into an array of values.</p>\n        <hr>\n        <h2>Usage</h2>\n        <pre><code class=\"javascript\">var result = $.csv.toArray(input);</code></pre>\n        <hr />\n        <h2>Input</h2>\n        <textarea id=\"input\" style=\"height: 25px;\">\"You will come back stronger then ever\",\"like Lance Armstrong\",\"but with two balls\"</textarea>\n        <input id=\"run\" type=\"button\" value=\"Run\" />\n        <hr />\n        <h2>Result</h2>\n        <textarea id=\"result\" style=\"height: 82px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"http://code.jquery.com/jquery-3.3.1.slim.js\" integrity=\"sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $(document).ready(() => {\n        parse();\n      });\n\n      $('#run').bind('click', function () {\n        parse();\n      });\n\n      function parse() {\n        const input = $('#input').val();\n        const data = $.csv.toArray(input);\n        $('#result').empty();\n        $('#result').html(JSON.stringify(data, null, 2));\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/to-arrays.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>To Arrays</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">$.csv.toArrays()</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>Used to parse multi-line CSV data into a JavaScript 2D (two-dimensional) array.</p>\n        <hr>\n        <h2>Usage</h2>\n        <pre><code class=\"javascript\">var result = $.csv.toArrays(input);</code></pre>\n        <hr />\n        <h2>Input</h2>\n        <textarea id=\"input\" style=\"height: 155px;\">\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"\n\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"</textarea>\n        <input id=\"run\" type=\"button\" value=\"Run\" />\n        <hr />\n        <h2>Result</h2>\n        <textarea id=\"result\" style=\"height: 940px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"http://code.jquery.com/jquery-3.3.1.slim.js\" integrity=\"sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $(document).ready(() => {\n        parse();\n      });\n\n      $('#run').bind('click', function () {\n        parse();\n      });\n\n      function parse() {\n        const input = $('#input').val();\n        const data = $.csv.toArrays(input);\n        $('#result').empty();\n        $('#result').html(JSON.stringify(data, null, 2));\n      }\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "examples/to-objects.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>To Objects</title>\n    <link href=\"https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro\" rel=\"stylesheet\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n\n  <body>\n\n    <div id=\"header\">\n      <h1 id=\"title\">$.csv.toObjects()</h1>\n      <div id=\"link\"><a href=\"https://github.com/evanplaice/jquery-csv\">GitHub</a></div>\n    </div>\n    <div id=\"container\">\n      <section id=\"content\">\n        <h2>Description</h2>\n        <p>Used to convert multi-line CSV data into an array objects containing the data as key-value (ie header:value) pairs.</p>\n        <hr>\n        <h2>Usage</h2>\n        <pre><code class=\"javascript\">var result = $.csv.toObjects(input);</code></pre>\n        <hr />\n        <h2>Input</h2>\n        <textarea id=\"input\" style=\"height: 190px;\">\"ID\",\"iManufacturer\",\"iMPartNumber\",\"iSimCategory\",\"iPartType\",\"iGroup\",\"iLocation\"\n\"1\",\"Evans & Sutherland\",\"230-132-111AA\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"2\",\"Evans & Sutherland\",\"230-132-111AA\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"3\",\"Evans & Sutherland\",\"230-120-112AC\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"4\",\"Evans & Sutherland\",\"230-120-112AC\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"5\",\"Evans & Sutherland\",\"230-120-112AC\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"6\",\"Evans & Sutherland\",\"230-120-112AC\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"7\",\"Evans & Sutherland\",\"230-120-112AC\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"8\",\"Evans & Sutherland\",\"230-120-112AC\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"9\",\"Evans & Sutherland\",\"230-120-112AC\",\"Visual\",\"PCB\",\"1\",\"Offsite\"\n\"10\",\"Evans & Sutherland\",\"230-121-150AC\",\"Visual\",\"PCB\",\"1\",\"Offsite\"</textarea>\n        <input id=\"run\" type=\"button\" value=\"Run\" />\n        <hr />\n        <h2>Result</h2>\n        <textarea id=\"result\" style=\"height: 1400px;\"></textarea>\n      </section>\n    </div>\n\n    <script src=\"http://code.jquery.com/jquery-3.3.1.slim.js\" integrity=\"sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=\" crossorigin=\"anonymous\"></script>\n    <script src=\"../src/jquery.csv.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js\"></script>\n    <script>\n      // enable syntax highlighting\n      hljs.initHighlightingOnLoad();\n\n      $(document).ready(() => {\n        parse();\n      });\n\n      $('#run').bind('click', function () {\n        parse();\n      });\n\n      function parse() {\n        const input = $('#input').val();\n        const data = $.csv.toObjects(input);\n        $('#result').empty();\n        $('#result').html(JSON.stringify(data, null, 2));\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"jquery-csv\",\n  \"version\": \"1.0.40\",\n  \"description\": \"A jQuery CSV parser plugin. Battle Tested | Optimized | 100% IETF RFC 4180 Complete\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+ssh://git@github.com/evanplaice/jquery-csv.git\"\n  },\n  \"author\": {\n    \"name\": \"Evan Plaice\",\n    \"email\": \"evan.plaice@gmail.com\",\n    \"url\": \"http://evanplaice.com\"\n  },\n  \"contributors\": [\n    {\n      \"name\": \"Colton Ehrman\",\n      \"email\": \"coltonje95@gmail.com\",\n      \"url\": \"http://coltonehrman.com\"\n    }\n  ],\n  \"main\": \"src/jquery.csv.js\",\n  \"scripts\": {\n    \"start\": \"npx live-server\",\n    \"test\": \"tape ./test/*.js\",\n    \"lint\": \"standard\",\n    \"minify\": \"npx uglify-js src/jquery.csv.js -o src/jquery.csv.min.js --compress --mangle\",\n    \"package\": \"npx rimraf package && npm pack | tail -n 1 | xargs tar -xf\",\n    \"preversion\": \"npm run lint && npm run test\",\n    \"postversion\": \"git push --follow-tags\"\n  },\n  \"devDependencies\": {\n    \"standard\": \"^17.1.0\",\n    \"tape\": \"^5.8.1\"\n  },\n  \"standard\": {\n    \"globals\": [\n      \"$\",\n      \"jQuery\"\n    ]\n  }\n}\n"
  },
  {
    "path": "src/jquery.csv.js",
    "content": "/* eslint no-prototype-builtins: 0 */\n/**\n * jQuery-csv (jQuery Plugin)\n *\n * This document is licensed as free software under the terms of the\n * MIT License: http://www.opensource.org/licenses/mit-license.php\n *\n * Acknowledgements:\n * The original design and influence to implement this library as a jquery\n * plugin is influenced by jquery-json (http://code.google.com/p/jquery-json/).\n * If you're looking to use native JSON.Stringify but want additional backwards\n * compatibility for browsers that don't support it, I highly recommend you\n * check it out.\n *\n * A special thanks goes out to rwk@acm.org for providing a lot of valuable\n * feedback to the project including the core for the new FSM\n * (Finite State Machine) parsers. If you're looking for a stable TSV parser\n * be sure to take a look at jquery-tsv (http://code.google.com/p/jquery-tsv/).\n\n * For legal purposes I'll include the \"NO WARRANTY EXPRESSED OR IMPLIED.\n * USE AT YOUR OWN RISK.\". Which, in 'layman's terms' means, by using this\n * library you are accepting responsibility if it breaks your code.\n *\n * Legal jargon aside, I will do my best to provide a useful and stable core\n * that can effectively be built on.\n *\n * Copyrighted 2012 by Evan Plaice.\n */\n\nRegExp.escape = function (s) {\n  return s.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')\n};\n\n(function () {\n  'use strict'\n\n  let $\n\n  // to keep backwards compatibility\n  if (typeof jQuery !== 'undefined' && jQuery) {\n    $ = jQuery\n  } else {\n    $ = {}\n  }\n\n  /**\n   * jQuery.csv.defaults\n   * Encapsulates the method paramater defaults for the CSV plugin module.\n   */\n\n  $.csv = {\n    defaults: {\n      separator: ',',\n      delimiter: '\"',\n      headers: true\n    },\n\n    hooks: {\n      castToScalar: function (value, state) {\n        const hasDot = /\\./\n        if (isNaN(value)) {\n          return value\n        } else {\n          if (hasDot.test(value)) {\n            return parseFloat(value)\n          } else {\n            const integer = parseInt(value)\n            if (isNaN(integer)) {\n              return null\n            } else {\n              return integer\n            }\n          }\n        }\n      }\n    },\n\n    parsers: {\n      parse: function (csv, options) {\n        // cache settings\n        const separator = options.separator\n        const delimiter = options.delimiter\n\n        // set initial state if it's missing\n        if (!options.state.rowNum) {\n          options.state.rowNum = 1\n        }\n        if (!options.state.colNum) {\n          options.state.colNum = 1\n        }\n\n        // clear initial state\n        const data = []\n        let entry = []\n        let state = 0\n        let value = ''\n        let exit = false\n\n        function endOfEntry () {\n          // reset the state\n          state = 0\n          value = ''\n\n          // if 'start' hasn't been met, don't output\n          if (options.start && options.state.rowNum < options.start) {\n            // update global state\n            entry = []\n            options.state.rowNum++\n            options.state.colNum = 1\n            return\n          }\n\n          if (options.onParseEntry === undefined) {\n            // onParseEntry hook not set\n            data.push(entry)\n          } else {\n            const hookVal = options.onParseEntry(entry, options.state) // onParseEntry Hook\n            // false skips the row, configurable through a hook\n            if (hookVal !== false) {\n              data.push(hookVal)\n            }\n          }\n          // console.log('entry:' + entry);\n\n          // cleanup\n          entry = []\n\n          // if 'end' is met, stop parsing\n          if (options.end && options.state.rowNum >= options.end) {\n            exit = true\n          }\n\n          // update global state\n          options.state.rowNum++\n          options.state.colNum = 1\n        }\n\n        function endOfValue () {\n          if (options.onParseValue === undefined) {\n            // onParseValue hook not set\n            entry.push(value)\n          } else if (options.headers && options.state.rowNum === 1) {\n            // don't onParseValue object headers\n            entry.push(value)\n          } else {\n            const hook = options.onParseValue(value, options.state) // onParseValue Hook\n            // false skips the row, configurable through a hook\n            if (hook !== false) {\n              entry.push(hook)\n            }\n          }\n          // console.log('value:' + value);\n          // reset the state\n          value = ''\n          state = 0\n          // update global state\n          options.state.colNum++\n        }\n\n        // escape regex-specific control chars\n        const escSeparator = RegExp.escape(separator)\n        const escDelimiter = RegExp.escape(delimiter)\n\n        // compile the regEx str using the custom delimiter/separator\n        let match = /(D|S|\\r\\n|\\n|\\r|[^DS\\r\\n]+)/\n        let matchSrc = match.source\n        matchSrc = matchSrc.replace(/S/g, escSeparator)\n        matchSrc = matchSrc.replace(/D/g, escDelimiter)\n        match = new RegExp(matchSrc, 'gm')\n\n        // put on your fancy pants...\n        // process control chars individually, use look-ahead on non-control chars\n        csv.replace(match, function (m0) {\n          if (exit) {\n            return\n          }\n          switch (state) {\n            // the start of a value\n            case 0:\n              // null last value\n              if (m0 === separator) {\n                value += ''\n                endOfValue()\n                break\n              }\n              // opening delimiter\n              if (m0 === delimiter) {\n                state = 1\n                break\n              }\n              // null last value\n              if (/^(\\r\\n|\\n|\\r)$/.test(m0)) {\n                endOfValue()\n                endOfEntry()\n                break\n              }\n              // un-delimited value\n              value += m0\n              state = 3\n              break\n\n            // delimited input\n            case 1:\n              // second delimiter? check further\n              if (m0 === delimiter) {\n                state = 2\n                break\n              }\n              // delimited data\n              value += m0\n              state = 1\n              break\n\n            // delimiter found in delimited input\n            case 2:\n              // escaped delimiter?\n              if (m0 === delimiter) {\n                value += m0\n                state = 1\n                break\n              }\n              // null value\n              if (m0 === separator) {\n                endOfValue()\n                break\n              }\n              // end of entry\n              if (/^(\\r\\n|\\n|\\r)$/.test(m0)) {\n                endOfValue()\n                endOfEntry()\n                break\n              }\n              // broken paser?\n              throw Error('CSVDataError: Illegal State [Row:' + options.state.rowNum + '][Col:' + options.state.colNum + ']')\n\n            // un-delimited input\n            case 3:\n              // null last value\n              if (m0 === separator) {\n                endOfValue()\n                break\n              }\n              // end of entry\n              if (/^(\\r\\n|\\n|\\r)$/.test(m0)) {\n                endOfValue()\n                endOfEntry()\n                break\n              }\n              if (m0 === delimiter) {\n              // non-compliant data\n                throw Error('CSVDataError: Illegal Quote [Row:' + options.state.rowNum + '][Col:' + options.state.colNum + ']')\n              }\n              // broken parser?\n              throw Error('CSVDataError: Illegal Data [Row:' + options.state.rowNum + '][Col:' + options.state.colNum + ']')\n            default:\n              // shenanigans\n              throw Error('CSVDataError: Unknown State [Row:' + options.state.rowNum + '][Col:' + options.state.colNum + ']')\n          }\n          // console.log('val:' + m0 + ' state:' + state);\n        })\n\n        // submit the last entry\n        // ignore null last line\n        if (entry.length !== 0) {\n          endOfValue()\n          endOfEntry()\n        }\n\n        return data\n      },\n\n      // a csv-specific line splitter\n      splitLines: function (csv, options) {\n        if (!csv) {\n          return undefined\n        }\n\n        options = options || {}\n\n        // cache settings\n        const separator = options.separator || $.csv.defaults.separator\n        const delimiter = options.delimiter || $.csv.defaults.delimiter\n\n        // set initial state if it's missing\n        options.state = options.state || {}\n        if (!options.state.rowNum) {\n          options.state.rowNum = 1\n        }\n\n        // clear initial state\n        const entries = []\n        let state = 0\n        let entry = ''\n        let exit = false\n\n        function endOfLine () {\n          // reset the state\n          state = 0\n\n          // if 'start' hasn't been met, don't output\n          if (options.start && options.state.rowNum < options.start) {\n            // update global state\n            entry = ''\n            options.state.rowNum++\n            return\n          }\n\n          if (options.onParseEntry === undefined) {\n            // onParseEntry hook not set\n            entries.push(entry)\n          } else {\n            const hookVal = options.onParseEntry(entry, options.state) // onParseEntry Hook\n            // false skips the row, configurable through a hook\n            if (hookVal !== false) {\n              entries.push(hookVal)\n            }\n          }\n\n          // cleanup\n          entry = ''\n\n          // if 'end' is met, stop parsing\n          if (options.end && options.state.rowNum >= options.end) {\n            exit = true\n          }\n\n          // update global state\n          options.state.rowNum++\n        }\n\n        // escape regex-specific control chars\n        const escSeparator = RegExp.escape(separator)\n        const escDelimiter = RegExp.escape(delimiter)\n\n        // compile the regEx str using the custom delimiter/separator\n        let match = /(D|S|\\n|\\r|[^DS\\r\\n]+)/\n        let matchSrc = match.source\n        matchSrc = matchSrc.replace(/S/g, escSeparator)\n        matchSrc = matchSrc.replace(/D/g, escDelimiter)\n        match = new RegExp(matchSrc, 'gm')\n\n        // put on your fancy pants...\n        // process control chars individually, use look-ahead on non-control chars\n        csv.replace(match, function (m0) {\n          if (exit) {\n            return\n          }\n          switch (state) {\n            // the start of a value/entry\n            case 0:\n              // null value\n              if (m0 === separator) {\n                entry += m0\n                state = 0\n                break\n              }\n              // opening delimiter\n              if (m0 === delimiter) {\n                entry += m0\n                state = 1\n                break\n              }\n              // end of line\n              if (m0 === '\\n') {\n                endOfLine()\n                break\n              }\n              // phantom carriage return\n              if (/^\\r$/.test(m0)) {\n                break\n              }\n              // un-delimit value\n              entry += m0\n              state = 3\n              break\n\n            // delimited input\n            case 1:\n              // second delimiter? check further\n              if (m0 === delimiter) {\n                entry += m0\n                state = 2\n                break\n              }\n              // delimited data\n              entry += m0\n              state = 1\n              break\n\n            // delimiter found in delimited input\n            case 2: {\n              // escaped delimiter?\n              const prevChar = entry.substr(entry.length - 1)\n              if (m0 === delimiter && prevChar === delimiter) {\n                entry += m0\n                state = 1\n                break\n              }\n              // end of value\n              if (m0 === separator) {\n                entry += m0\n                state = 0\n                break\n              }\n              // end of line\n              if (m0 === '\\n') {\n                endOfLine()\n                break\n              }\n              // phantom carriage return\n              if (m0 === '\\r') {\n                break\n              }\n              // broken paser?\n              throw Error('CSVDataError: Illegal state [Row:' + options.state.rowNum + ']')\n            }\n            // un-delimited input\n            case 3:\n              // null value\n              if (m0 === separator) {\n                entry += m0\n                state = 0\n                break\n              }\n              // end of line\n              if (m0 === '\\n') {\n                endOfLine()\n                break\n              }\n              // phantom carriage return\n              if (m0 === '\\r') {\n                break\n              }\n              // non-compliant data\n              if (m0 === delimiter) {\n                throw Error('CSVDataError: Illegal quote [Row:' + options.state.rowNum + ']')\n              }\n              // broken parser?\n              throw Error('CSVDataError: Illegal state [Row:' + options.state.rowNum + ']')\n            default:\n              // shenanigans\n              throw Error('CSVDataError: Unknown state [Row:' + options.state.rowNum + ']')\n          }\n          // console.log('val:' + m0 + ' state:' + state);\n        })\n\n        // submit the last entry\n        // ignore null last line\n        if (entry !== '') {\n          endOfLine()\n        }\n\n        return entries\n      },\n\n      // a csv entry parser\n      parseEntry: function (csv, options) {\n        // cache settings\n        const separator = options.separator\n        const delimiter = options.delimiter\n\n        // set initial state if it's missing\n        if (!options.state.rowNum) {\n          options.state.rowNum = 1\n        }\n        if (!options.state.colNum) {\n          options.state.colNum = 1\n        }\n\n        // clear initial state\n        const entry = []\n        let state = 0\n        let value = ''\n\n        function endOfValue () {\n          if (options.onParseValue === undefined) {\n            // onParseValue hook not set\n            entry.push(value)\n          } else {\n            const hook = options.onParseValue(value, options.state) // onParseValue Hook\n            // false skips the value, configurable through a hook\n            if (hook !== false) {\n              entry.push(hook)\n            }\n          }\n          // reset the state\n          value = ''\n          state = 0\n          // update global state\n          options.state.colNum++\n        }\n\n        // checked for a cached regEx first\n        if (!options.match) {\n          // escape regex-specific control chars\n          const escSeparator = RegExp.escape(separator)\n          const escDelimiter = RegExp.escape(delimiter)\n\n          // compile the regEx str using the custom delimiter/separator\n          const match = /(D|S|\\n|\\r|[^DS\\r\\n]+)/\n          let matchSrc = match.source\n          matchSrc = matchSrc.replace(/S/g, escSeparator)\n          matchSrc = matchSrc.replace(/D/g, escDelimiter)\n          options.match = new RegExp(matchSrc, 'gm')\n        }\n\n        // put on your fancy pants...\n        // process control chars individually, use look-ahead on non-control chars\n        csv.replace(options.match, function (m0) {\n          switch (state) {\n            // the start of a value\n            case 0:\n              // null last value\n              if (m0 === separator) {\n                value += ''\n                endOfValue()\n                break\n              }\n              // opening delimiter\n              if (m0 === delimiter) {\n                state = 1\n                break\n              }\n              // skip un-delimited new-lines\n              if (m0 === '\\n' || m0 === '\\r') {\n                break\n              }\n              // un-delimited value\n              value += m0\n              state = 3\n              break\n\n            // delimited input\n            case 1:\n              // second delimiter? check further\n              if (m0 === delimiter) {\n                state = 2\n                break\n              }\n              // delimited data\n              value += m0\n              state = 1\n              break\n\n            // delimiter found in delimited input\n            case 2:\n              // escaped delimiter?\n              if (m0 === delimiter) {\n                value += m0\n                state = 1\n                break\n              }\n              // null value\n              if (m0 === separator) {\n                endOfValue()\n                break\n              }\n              // skip un-delimited new-lines\n              if (m0 === '\\n' || m0 === '\\r') {\n                break\n              }\n              // broken paser?\n              throw Error('CSVDataError: Illegal State [Row:' + options.state.rowNum + '][Col:' + options.state.colNum + ']')\n\n            // un-delimited input\n            case 3:\n              // null last value\n              if (m0 === separator) {\n                endOfValue()\n                break\n              }\n              // skip un-delimited new-lines\n              if (m0 === '\\n' || m0 === '\\r') {\n                break\n              }\n              // non-compliant data\n              if (m0 === delimiter) {\n                throw Error('CSVDataError: Illegal Quote [Row:' + options.state.rowNum + '][Col:' + options.state.colNum + ']')\n              }\n              // broken parser?\n              throw Error('CSVDataError: Illegal Data [Row:' + options.state.rowNum + '][Col:' + options.state.colNum + ']')\n            default:\n              // shenanigans\n              throw Error('CSVDataError: Unknown State [Row:' + options.state.rowNum + '][Col:' + options.state.colNum + ']')\n          }\n          // console.log('val:' + m0 + ' state:' + state);\n        })\n\n        // submit the last value\n        endOfValue()\n\n        return entry\n      }\n    },\n\n    helpers: {\n\n      /**\n       * $.csv.helpers.collectPropertyNames(objectsArray)\n       * Collects all unique property names from all passed objects.\n       *\n       * @param {Array} objects Objects to collect properties from.\n       *\n       * Returns an array of property names (array will be empty,\n       * if objects have no own properties).\n       */\n      collectPropertyNames: function (objects) {\n        let o = []\n        let propName = []\n        const props = []\n        for (o in objects) {\n          for (propName in objects[o]) {\n            if ((objects[o].hasOwnProperty(propName)) &&\n                (props.indexOf(propName) < 0) &&\n                (typeof objects[o][propName] !== 'function')) {\n              props.push(propName)\n            }\n          }\n        }\n        return props\n      }\n    },\n\n    /**\n     * $.csv.toArray(csv)\n     * Converts a CSV entry string to a javascript array.\n     *\n     * @param {Array} csv The string containing the CSV data.\n     * @param {Object} [options] An object containing user-defined options.\n     * @param {Character} [separator] An override for the separator character. Defaults to a comma(,).\n     * @param {Character} [delimiter] An override for the delimiter character. Defaults to a double-quote(\").\n     *\n     * This method deals with simple CSV strings only. It's useful if you only\n     * need to parse a single entry. If you need to parse more than one line,\n     * use $.csv2Array instead.\n     */\n    toArray: function (csv, options, callback) {\n      // if callback was passed to options swap callback with options\n      if (options !== undefined && typeof (options) === 'function') {\n        if (callback !== undefined) {\n          return console.error('You cannot 3 arguments with the 2nd argument being a function')\n        }\n        callback = options\n        options = {}\n      }\n\n      options = (options !== undefined ? options : {})\n      const config = {}\n      config.callback = ((callback !== undefined && typeof (callback) === 'function') ? callback : false)\n      config.separator = 'separator' in options ? options.separator : $.csv.defaults.separator\n      config.delimiter = 'delimiter' in options ? options.delimiter : $.csv.defaults.delimiter\n      const state = (options.state !== undefined ? options.state : {})\n\n      // setup\n      options = {\n        delimiter: config.delimiter,\n        separator: config.separator,\n        onParseEntry: options.onParseEntry,\n        onParseValue: options.onParseValue,\n        state\n      }\n\n      const entry = $.csv.parsers.parseEntry(csv, options)\n\n      // push the value to a callback if one is defined\n      if (!config.callback) {\n        return entry\n      } else {\n        config.callback('', entry)\n      }\n    },\n\n    /**\n     * $.csv.toArrays(csv)\n     * Converts a CSV string to a javascript array.\n     *\n     * @param {String} csv The string containing the raw CSV data.\n     * @param {Object} [options] An object containing user-defined options.\n     * @param {Character} [separator] An override for the separator character. Defaults to a comma(,).\n     * @param {Character} [delimiter] An override for the delimiter character. Defaults to a double-quote(\").\n     *\n     * This method deals with multi-line CSV. The breakdown is simple. The first\n     * dimension of the array represents the line (or entry/row) while the second\n     * dimension contains the values (or values/columns).\n     */\n    toArrays: function (csv, options, callback) {\n      // if callback was passed to options swap callback with options\n      if (options !== undefined && typeof (options) === 'function') {\n        if (callback !== undefined) {\n          return console.error('You cannot 3 arguments with the 2nd argument being a function')\n        }\n        callback = options\n        options = {}\n      }\n\n      options = (options !== undefined ? options : {})\n      const config = {}\n      config.callback = ((callback !== undefined && typeof (callback) === 'function') ? callback : false)\n      config.separator = 'separator' in options ? options.separator : $.csv.defaults.separator\n      config.delimiter = 'delimiter' in options ? options.delimiter : $.csv.defaults.delimiter\n\n      // setup\n      let data = []\n      options = {\n        delimiter: config.delimiter,\n        separator: config.separator,\n        onPreParse: options.onPreParse,\n        onParseEntry: options.onParseEntry,\n        onParseValue: options.onParseValue,\n        onPostParse: options.onPostParse,\n        start: options.start,\n        end: options.end,\n        state: {\n          rowNum: 1,\n          colNum: 1\n        }\n      }\n\n      // onPreParse hook\n      if (options.onPreParse !== undefined) {\n        csv = options.onPreParse(csv, options.state)\n      }\n\n      // parse the data\n      data = $.csv.parsers.parse(csv, options)\n\n      // onPostParse hook\n      if (options.onPostParse !== undefined) {\n        data = options.onPostParse(data, options.state)\n      }\n\n      // push the value to a callback if one is defined\n      if (!config.callback) {\n        return data\n      } else {\n        config.callback('', data)\n      }\n    },\n\n    /**\n     * $.csv.toObjects(csv)\n     * Converts a CSV string to a javascript object.\n     * @param {String} csv The string containing the raw CSV data.\n     * @param {Object} [options] An object containing user-defined options.\n     * @param {Character} [separator] An override for the separator character. Defaults to a comma(,).\n     * @param {Character} [delimiter] An override for the delimiter character. Defaults to a double-quote(\").\n     * @param {Boolean} [headers] Indicates whether the data contains a header line. Defaults to true.\n     *\n     * This method deals with multi-line CSV strings. Where the headers line is\n     * used as the key for each value per entry.\n     */\n    toObjects: function (csv, options, callback) {\n      // if callback was passed to options swap callback with options\n      if (options !== undefined && typeof (options) === 'function') {\n        if (callback !== undefined) {\n          return console.error('You cannot 3 arguments with the 2nd argument being a function')\n        }\n        callback = options\n        options = {}\n      }\n\n      options = (options !== undefined ? options : {})\n      const config = {}\n      config.callback = ((callback !== undefined && typeof (callback) === 'function') ? callback : false)\n      config.separator = 'separator' in options ? options.separator : $.csv.defaults.separator\n      config.delimiter = 'delimiter' in options ? options.delimiter : $.csv.defaults.delimiter\n      config.headers = 'headers' in options ? options.headers : $.csv.defaults.headers\n      options.start = 'start' in options ? options.start : 1\n\n      // account for headers\n      if (config.headers) {\n        options.start++\n      }\n      if (options.end && config.headers) {\n        options.end++\n      }\n\n      // setup\n      let lines = []\n      let data = []\n\n      options = {\n        delimiter: config.delimiter,\n        separator: config.separator,\n        onPreParse: options.onPreParse,\n        onParseEntry: options.onParseEntry,\n        onParseValue: options.onParseValue,\n        onPostParse: options.onPostParse,\n        start: options.start,\n        end: options.end,\n        state: {\n          rowNum: 1,\n          colNum: 1\n        },\n        match: false,\n        transform: options.transform\n      }\n\n      // fetch the headers\n      const headerOptions = {\n        delimiter: config.delimiter,\n        separator: config.separator,\n        start: 1,\n        end: 1,\n        state: {\n          rowNum: 1,\n          colNum: 1\n        },\n        headers: true\n      }\n\n      // onPreParse hook\n      if (options.onPreParse !== undefined) {\n        csv = options.onPreParse(csv, options.state)\n      }\n\n      // parse the csv\n      const headerLine = $.csv.parsers.splitLines(csv, headerOptions)\n      const headers = $.csv.toArray(headerLine[0], headerOptions)\n\n      // fetch the data\n      lines = $.csv.parsers.splitLines(csv, options)\n\n      // reset the state for re-use\n      options.state.colNum = 1\n      if (headers) {\n        options.state.rowNum = 2\n      } else {\n        options.state.rowNum = 1\n      }\n\n      // convert data to objects\n      for (let i = 0, len = lines.length; i < len; i++) {\n        const entry = $.csv.toArray(lines[i], options)\n        const object = {}\n        for (let j = 0; j < headers.length; j++) {\n          object[headers[j]] = entry[j]\n        }\n        if (options.transform !== undefined) {\n          data.push(options.transform.call(undefined, object))\n        } else {\n          data.push(object)\n        }\n\n        // update row state\n        options.state.rowNum++\n      }\n\n      // onPostParse hook\n      if (options.onPostParse !== undefined) {\n        data = options.onPostParse(data, options.state)\n      }\n\n      // push the value to a callback if one is defined\n      if (!config.callback) {\n        return data\n      } else {\n        config.callback('', data)\n      }\n    },\n\n    /**\n    * $.csv.fromArrays(arrays)\n    * Converts a javascript array to a CSV String.\n    *\n    * @param {Array} arrays An array containing an array of CSV entries.\n    * @param {Object} [options] An object containing user-defined options.\n    * @param {Character} [separator] An override for the separator character. Defaults to a comma(,).\n    * @param {Character} [delimiter] An override for the delimiter character. Defaults to a double-quote(\").\n    *\n    * This method generates a CSV file from an array of arrays (representing entries).\n    */\n    fromArrays: function (arrays, options, callback) {\n      // if callback was passed to options swap callback with options\n      if (options !== undefined && typeof (options) === 'function') {\n        if (callback !== undefined) {\n          return console.error('You cannot 3 arguments with the 2nd argument being a function')\n        }\n        callback = options\n        options = {}\n      }\n\n      options = (options !== undefined ? options : {})\n      const config = {}\n      config.callback = ((callback !== undefined && typeof (callback) === 'function') ? callback : false)\n      config.separator = 'separator' in options ? options.separator : $.csv.defaults.separator\n      config.delimiter = 'delimiter' in options ? options.delimiter : $.csv.defaults.delimiter\n\n      let output = ''\n\n      for (let i = 0; i < arrays.length; i++) {\n        const line = arrays[i]\n        const lineValues = []\n        for (let j = 0; j < line.length; j++) {\n          let strValue = (line[j] === undefined || line[j] === null) ? '' : line[j].toString()\n          if (strValue.indexOf(config.delimiter) > -1) {\n            strValue = strValue.replace(new RegExp(config.delimiter, 'g'), config.delimiter + config.delimiter)\n          }\n\n          let escMatcher = '\\n|\\r|S|D'\n          escMatcher = escMatcher.replace('S', config.separator)\n          escMatcher = escMatcher.replace('D', config.delimiter)\n\n          if (strValue.search(escMatcher) > -1) {\n            strValue = config.delimiter + strValue + config.delimiter\n          }\n          lineValues.push(strValue)\n        }\n        output += lineValues.join(config.separator) + '\\n'\n      }\n\n      // push the value to a callback if one is defined\n      if (!config.callback) {\n        return output\n      } else {\n        config.callback('', output)\n      }\n    },\n\n    /**\n     * $.csv.fromObjects(objects)\n     * Converts a javascript dictionary to a CSV string.\n     *\n     * @param {Object} objects An array of objects containing the data.\n     * @param {Object} [options] An object containing user-defined options.\n     * @param {Character} [separator] An override for the separator character. Defaults to a comma(,).\n     * @param {Character} [delimiter] An override for the delimiter character. Defaults to a double-quote(\").\n     * @param {Character} [sortOrder] Sort order of columns (named after\n     *   object properties). Use 'alpha' for alphabetic. Default is 'declare',\n     *   which means, that properties will _probably_ appear in order they were\n     *   declared for the object. But without any guarantee.\n     * @param {Character or Array} [manualOrder] Manually order columns. May be\n     * a strin in a same csv format as an output or an array of header names\n     * (array items won't be parsed). All the properties, not present in\n     * `manualOrder` will be appended to the end in accordance with `sortOrder`\n     * option. So the `manualOrder` always takes preference, if present.\n     *\n     * This method generates a CSV file from an array of objects (name:value pairs).\n     * It starts by detecting the headers and adding them as the first line of\n     * the CSV file, followed by a structured dump of the data.\n     */\n    fromObjects: function (objects, options, callback) {\n      // if callback was passed to options swap callback with options\n      if (options !== undefined && typeof (options) === 'function') {\n        if (callback !== undefined) {\n          return console.error('You cannot 3 arguments with the 2nd argument being a function')\n        }\n        callback = options\n        options = {}\n      }\n\n      options = (options !== undefined ? options : {})\n      const config = {}\n      config.callback = ((callback !== undefined && typeof (callback) === 'function') ? callback : false)\n      config.separator = 'separator' in options ? options.separator : $.csv.defaults.separator\n      config.delimiter = 'delimiter' in options ? options.delimiter : $.csv.defaults.delimiter\n      config.headers = 'headers' in options ? options.headers : $.csv.defaults.headers\n      config.sortOrder = 'sortOrder' in options ? options.sortOrder : 'declare'\n      config.manualOrder = 'manualOrder' in options ? options.manualOrder : []\n      config.transform = options.transform\n\n      if (typeof config.manualOrder === 'string') {\n        config.manualOrder = $.csv.toArray(config.manualOrder, config)\n      }\n\n      if (config.transform !== undefined) {\n        const origObjects = objects\n        objects = []\n\n        for (let i = 0; i < origObjects.length; i++) {\n          objects.push(config.transform.call(undefined, origObjects[i]))\n        }\n      }\n\n      let props = $.csv.helpers.collectPropertyNames(objects)\n\n      if (config.sortOrder === 'alpha') {\n        props.sort()\n      }\n\n      if (config.manualOrder.length > 0) {\n        const propsManual = [].concat(config.manualOrder)\n\n        for (let p = 0; p < props.length; p++) {\n          if (propsManual.indexOf(props[p]) < 0) {\n            propsManual.push(props[p])\n          }\n        }\n        props = propsManual\n      }\n\n      let line\n      const output = []\n      let propName\n      if (config.headers) {\n        output.push(props)\n      }\n\n      for (let o = 0; o < objects.length; o++) {\n        line = []\n        for (let p = 0; p < props.length; p++) {\n          propName = props[p]\n          if (propName in objects[o] && typeof objects[o][propName] !== 'function') {\n            line.push(objects[o][propName])\n          } else {\n            line.push('')\n          }\n        }\n        output.push(line)\n      }\n\n      // push the value to a callback if one is defined\n      return $.csv.fromArrays(output, options, config.callback)\n    }\n  }\n\n  // Maintenance code to maintain backward-compatibility\n  // Will be removed in release 1.0\n  $.csvEntry2Array = $.csv.toArray\n  $.csv2Array = $.csv.toArrays\n  $.csv2Dictionary = $.csv.toObjects\n\n  // CommonJS module is defined\n  if (typeof module !== 'undefined' && module.exports) {\n    module.exports = $.csv\n  }\n}).call(this)\n"
  },
  {
    "path": "test/csv.from_array.js",
    "content": "/* eslint-disable no-unused-vars */\nconst test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.fromArray()', (t) => { t.end() })\n\n// TODO: Implement csv.fromArray()\n// test('should be able to format a multi-cell entry', (t) => {\n//   let result = csv.fromArray(fixtures.array_obj)\n//   let expect = fixtures.array_csv\n//   t.deepEqual(result, expect)\n//   t.end()\n// })\n"
  },
  {
    "path": "test/csv.from_arrays.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.fromArrays() - should be able to format multi-entry/multi-cell data set', (t) => {\n  const result = csv.fromArrays(fixtures.arrays1_obj)\n  const expect = fixtures.arrays1_csv\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('$.csv.fromArrays() - should be able to format multi-entry/multi-cell data set with escaped delimiters', (t) => {\n  const result = csv.fromArrays(fixtures.arrays2_obj)\n  console.dir(result)\n  const expect = fixtures.arrays2_csv\n  t.deepEqual(result, expect)\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.from_objects.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.fromObjects() - should parse javascript object to a csv', (t) => {\n  const result = csv.fromObjects(fixtures.objects_obj)\n  t.deepEquals(result, fixtures.objects2_csv)\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.on_parse_entry_hook.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.toObjects onParseEntry hook callback - should be passed the data and state', (t) => {\n  let passedData, passedState\n\n  csv.toObjects(fixtures.objects_csv, {\n    onParseEntry: (data, state) => {\n      passedData = data\n      passedState = state\n      return data\n    }\n  })\n\n  t.isNot(passedData, null, 'data argument should not be null')\n  t.isNot(passedState, null, 'state argument should not be null')\n  t.end()\n})\n\ntest('$.csv.toArrays onParseEntry hook callback - should be passed the data and state', (t) => {\n  let passedData, passedState\n\n  csv.toArrays(fixtures.arrays1_csv, {\n    onParseEntry: (data, state) => {\n      passedData = data\n      passedState = state\n      return data\n    }\n  })\n\n  t.isNot(passedData, null, 'data argument should not be null')\n  t.isNot(passedState, null, 'state argument should not be null')\n  t.end()\n})\n\ntest('$.csv.toObjects onParseEntry hook callback - should affect return value', (t) => {\n  const returnMutatedEntry = (entry, state) => (state.rowNum === 2) ? false : entry\n  const result = csv.toObjects(fixtures.entry_objects_csv, { onParseEntry: returnMutatedEntry })\n  t.deepEqual(result, fixtures.entry_objects_obj, 'return value should reflect what was returned from callback')\n  t.end()\n})\n\ntest('$.csv.toArrays onParseEntry hook callback - should affect return value', (t) => {\n  const returnMutatedEntry = (entry, state) => (state.rowNum === 2) ? false : entry\n  const result = csv.toArrays(fixtures.entry_arrays_csv, { onParseEntry: returnMutatedEntry })\n  t.deepEqual(result, fixtures.entry_arrays_obj, 'return value should reflect what was returned from callback')\n  t.end()\n})\n\ntest('$.csv.toObjects onParseEntry hook callback - should have correct state', (t) => {\n  const checkEntryState = (entry, state) => {\n    if (state.rowNum === 3) {\n      t.equal(entry, 'keep3')\n    }\n    return entry\n  }\n  csv.toObjects(fixtures.entry_objects_csv, { onParseEntry: checkEntryState })\n  t.end()\n})\n\ntest('$.csv.toArrays onParseEntry hook callback - should have correct state', (t) => {\n  const checkEntryState = (entry, state) => {\n    if (state.rowNum === 3) {\n      t.deepEqual(entry, ['keep3'])\n    }\n    return entry\n  }\n  csv.toArrays(fixtures.entry_arrays_csv, { onParseEntry: checkEntryState })\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.on_parse_value_hook.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.toObjects onParseValue hook callback - should be passed the data and state', (t) => {\n  let passedData, passedState\n\n  csv.toObjects(fixtures.objects_csv, {\n    onParseValue: (data, state) => {\n      passedData = data\n      passedState = state\n      return data\n    }\n  })\n\n  t.isNot(passedData, null, 'data argument should not be null')\n  t.isNot(passedState, null, 'state argument should not be null')\n  t.end()\n})\n\ntest('$.csv.toArrays onParseValue hook callback - should be passed the data and state', (t) => {\n  let passedData, passedState\n\n  csv.toArrays(fixtures.arrays1_csv, {\n    onParseValue: (data, state) => {\n      passedData = data\n      passedState = state\n      return data\n    }\n  })\n\n  t.isNot(passedData, null, 'data argument should not be null')\n  t.isNot(passedState, null, 'state argument should not be null')\n  t.end()\n})\n\ntest('$.csv.toObjects onParseValue hook callback - should affect return value', (t) => {\n  const returnMutatedValues = (value) => value + 'a'\n  const result = csv.toObjects(fixtures.value_objects_csv, { onParseValue: returnMutatedValues })\n  t.deepEqual(result, fixtures.value_objects_obj, 'return value should reflect what was returned from callback')\n  t.end()\n})\n\ntest('$.csv.toObjects onParseValue hook callback - should have correct state', (t) => {\n  const checkValueState = (value, state) => {\n    if (state.rowNum === 2 && state.colNum === 3) {\n      t.equal(value, 'some')\n    }\n    return value\n  }\n  csv.toObjects(fixtures.value_objects_csv, { onParseValue: checkValueState })\n  t.end()\n})\n\ntest('$.csv.toArrays onParseValue hook callback - should have correct state', (t) => {\n  const checkValueState = (value, state) => {\n    if (state.rowNum === 1 && state.colNum === 3) {\n      t.equal(value, 'some')\n    }\n    return value\n  }\n  csv.toArrays(fixtures.value_arrays_csv, { onParseValue: checkValueState })\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.on_post_parse_hook.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.toObjects onPostParse hook callback - should be passed the data and state', (t) => {\n  let passedData, passedState\n\n  csv.toObjects(fixtures.objects_csv, {\n    onPostParse: (data, state) => {\n      passedData = data\n      passedState = state\n    }\n  })\n\n  t.isNot(passedData, null, 'data argument should not be null')\n  t.isNot(passedState, null, 'state argument should not be null')\n  t.end()\n})\n\ntest('$.csv.toArrays onPostParse hook callback - should be passed the data and state', (t) => {\n  let passedData, passedState\n\n  csv.toArrays(fixtures.arrays1_csv, {\n    onPostParse: (data, state) => {\n      passedData = data\n      passedState = state\n    }\n  })\n\n  t.isNot(passedData, null, 'data argument should not be null')\n  t.isNot(passedState, null, 'state argument should not be null')\n  t.end()\n})\n\ntest('$.csv.toObjects onPostParse hook callback - should affect return value', (t) => {\n  const returnEmptyArray = () => []\n  const result = csv.toObjects(fixtures.objects_csv, { onPostParse: returnEmptyArray })\n  t.deepEqual(result, [], 'return value should reflect what was returned from callback')\n  t.end()\n})\n\ntest('$.csv.toArrays onPostParse hook callback - should affect return value', (t) => {\n  const returnEmptyArray = () => []\n  const result = csv.toArrays(fixtures.arrays1_csv, { onPostParse: returnEmptyArray })\n  t.deepEqual(result, [], 'return value should reflect what was returned from callback')\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.on_pre_parse_hook.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.toObjects onPreParse hook callback - should be passed the raw csv and state', (t) => {\n  let passedCSV, passedState\n\n  csv.toObjects(fixtures.objects_csv, {\n    onPreParse: (csv, state) => {\n      passedCSV = csv\n      passedState = state\n      return csv\n    }\n  })\n\n  t.isNot(passedCSV, null, 'data argument should not be null')\n  t.isNot(passedState, null, 'state argument should not be null')\n  t.end()\n})\n\ntest('$.csv.toArrays onPreParse hook callback - should be passed the raw csv and state', (t) => {\n  let passedCSV, passedState\n\n  csv.toArrays(fixtures.arrays1_csv, {\n    onPreParse: (csv, state) => {\n      passedCSV = csv\n      passedState = state\n      return csv\n    }\n  })\n\n  t.isNot(passedCSV, null, 'data argument should not be null')\n  t.isNot(passedState, null, 'state argument should not be null')\n  t.end()\n})\n\ntest('$.csv.toObjects onPreParse hook callback - should affect return value', (t) => {\n  const returnEmptyCSV = () => 'header\\n\"\"'\n  const result = csv.toObjects(fixtures.objects_csv, { onPreParse: returnEmptyCSV })\n  t.deepEqual(result, [{ header: '' }], 'return value should reflect what was returned from callback')\n  t.end()\n})\n\ntest('$.csv.toArrays onPreParse hook callback - should affect return value', (t) => {\n  const returnEmptyCSV = () => ''\n  const result = csv.toArrays(fixtures.arrays1_csv, { onPreParse: returnEmptyCSV })\n  t.deepEqual(result, [], 'return value should reflect what was returned from callback')\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.parsers.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.parsers.splitLines() - should correctly split lines with default options', (t) => {\n  const result = csv.parsers.splitLines(fixtures.defaults_fivelines_csv)\n  t.equal(typeof (result), 'object', 'the returned object should be an array')\n  t.true(Array.isArray(result), 'the returned object should be an array')\n  t.equal(result.length, 5, 'the returned array should contain 5 lines')\n  t.end()\n})\n\ntest('$.csv.parsers.splitLines() - should correctly split lines with custom separator', (t) => {\n  const options = {\n    separator: ';'\n  }\n\n  const result = csv.parsers.splitLines(fixtures.separator_fivelines_csv, options)\n  t.equal(typeof (result), 'object', 'the returned object should be an array')\n  t.true(Array.isArray(result), 'the returned object should be an array')\n  t.equal(result.length, 5, 'the returned array should contain 5 lines')\n  t.end()\n})\n\ntest('$.csv.parsers.splitLines() - should throw an error for using the wrong separator', (t) => {\n  const options = {\n    separator: ';'\n  }\n\n  function splitLines () {\n    csv.parsers.splitLines(fixtures.defaults_fivelines_csv, options)\n  }\n\n  t.throws(splitLines)\n  t.end()\n})\n\ntest('$.csv.parsers.splitLines() - should correctly split lines with custom delimiter', (t) => {\n  const options = {\n    delimiter: \"'\"\n  }\n\n  const result = csv.parsers.splitLines(fixtures.delimiter_fivelines_csv, options)\n  t.equal(typeof (result), 'object', 'the returned object should be an array')\n  t.true(Array.isArray(result), 'the returned object should be an array')\n  t.equal(result.length, 5, 'the returned array should contain 5 lines')\n  t.end()\n})\n\ntest('$.csv.parsers.splitLines() - should return undefined when csv is undefined', (t) => {\n  const result = csv.parsers.splitLines()\n  t.equal(typeof (result), 'undefined')\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.to_array.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.toArray() - should be able to parse an entry containing multiple cells', (t) => {\n  const result = csv.toArray(fixtures.array_csv)\n  const expect = fixtures.array_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('$.csv.toArray() - should return [\"\"] when input is empty', (t) => {\n  const result = csv.toArray('')\n  t.equal(result.length, 1)\n  t.end()\n})\n\ntest('$.csv.toArray() - should return [\"a1\"] when input is \"a1\"', (t) => {\n  const result = csv.toArray('a1')\n  t.equal(result.length, 1)\n  t.equal(result[0], 'a1')\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.to_arrays.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.toArrays() - should be able to parse multi-entry/multi-cell input', (t) => {\n  const result = csv.toArrays(fixtures.arrays1_csv)\n  const expect = fixtures.arrays1_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('$.csv.toArrays() - should be able to parse multi-entry/multi-cell input with escaped delimiters', (t) => {\n  const result = csv.toArrays(fixtures.arrays2_csv)\n  const expect = fixtures.arrays2_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n"
  },
  {
    "path": "test/csv.to_objects.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('$.csv.toObjects() - should parse csv to a javascript object', (t) => {\n  const result = csv.toObjects(fixtures.objects_csv)\n  t.deepEquals(result, fixtures.objects_obj)\n  t.end()\n})\n"
  },
  {
    "path": "test/edge_cases.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('Edge Case - should properly escape backslashes', (t) => {\n  const result = csv.toObjects(fixtures.backslash_csv)\n  const expect = fixtures.backslash_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('Edge Case - should support \\\\n (unix) line endings', (t) => {\n  const result = csv.toArrays(fixtures.newline_unix)\n  t.equal(result.length, 2)\n  t.end()\n})\n\ntest('Edge Case - should support \\\\r (mac) line endings', (t) => {\n  const result = csv.toArrays(fixtures.newline_mac)\n  t.equal(result.length, 2)\n  t.end()\n})\n\ntest('Edge Case - should support \\\\r\\\\n (dos) line endings', (t) => {\n  const result = csv.toArrays(fixtures.newline_dos)\n  t.equal(result.length, 2)\n  t.end()\n})\n"
  },
  {
    "path": "test/fixtures/array.csv",
    "content": "\"You will come back stronger then ever\",\"like Lance Armstrong\",\"but with two balls\"\n"
  },
  {
    "path": "test/fixtures/array.json",
    "content": "[\n\t\"You will come back stronger then ever\",\n\t\"like Lance Armstrong\",\n\t\"but with two balls\"\n]\n"
  },
  {
    "path": "test/fixtures/arrays1.csv",
    "content": "All work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\n"
  },
  {
    "path": "test/fixtures/arrays1.json",
    "content": "[\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"]\n]\n"
  },
  {
    "path": "test/fixtures/arrays2.csv",
    "content": "All work,and no play,makes Jack,a dull boy...\nAll work,and no play,\"makes \"\"Jack\",a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,\"a \"\"dull\"\" boy...\"\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\n\"All \"\"work\",and no play,makes Jack,a dull boy...\nAll work,and no play,makes Jack,a dull boy...\n"
  },
  {
    "path": "test/fixtures/arrays2.json",
    "content": "[\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes \\\"Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a \\\"dull\\\" boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All \\\"work\",\"and no play\",\"makes Jack\",\"a dull boy...\"],\n    [\"All work\",\"and no play\",\"makes Jack\",\"a dull boy...\"]\n]\n"
  },
  {
    "path": "test/fixtures/backslash.csv",
    "content": "test1,test2\ndata1,data2\\3"
  },
  {
    "path": "test/fixtures/backslash.json",
    "content": "[\n {\n  \"test1\":\"data1\",\n  \"test2\":\"data2\\\\3\"\n }\n]"
  },
  {
    "path": "test/fixtures/defaults.csv",
    "content": "\"1\",\"he said \"\"you are crazy\"\"\",\"one \"\", two \"\", three \"\"\"\r\n"
  },
  {
    "path": "test/fixtures/defaults.json",
    "content": "[\r\n\t\"1\",\r\n\t\"he said \\\"you are crazy\\\"\",\r\n\t\"one \\\", two \\\", three \\\"\"\r\n]\r\n"
  },
  {
    "path": "test/fixtures/defaults_fivelines.csv",
    "content": "\"1\",\"he said \"\"you are crazy\"\"\",\"one \"\", two \"\", three \"\"\"\n\"2\",\"he said \"\"you are crazy\"\"\",\"one \"\", two \"\", three \"\"\"\n\"3\",\"he said \"\"you are crazy\"\"\",\"one \"\", two \"\", three \"\"\"\n\"4\",\"he said \"\"you are crazy\"\"\",\"one \"\", two \"\", three \"\"\"\n\"5\",\"he said \"\"you are crazy\"\"\",\"one \"\", two \"\", three \"\"\"\n"
  },
  {
    "path": "test/fixtures/delimiter.csv",
    "content": "'2','he said ''you are crazy''','one '', two '', three '''"
  },
  {
    "path": "test/fixtures/delimiter.json",
    "content": "[\n\t\"2\",\n\t\"he said 'you are crazy'\",\n\t\"one ', two ', three '\"\n]"
  },
  {
    "path": "test/fixtures/delimiter_fivelines.csv",
    "content": "'2','he said ''you are crazy''','one '', two '', three '''\n'2','he said ''you are crazy''','one '', two '', three '''\n'2','he said ''you are crazy''','one '', two '', three '''\n'2','he said ''you are crazy''','one '', two '', three '''\n'2','he said ''you are crazy''','one '', two '', three '''\n"
  },
  {
    "path": "test/fixtures/entry_arrays.csv",
    "content": "keep1\nremove2\nkeep3\nkeep4\n"
  },
  {
    "path": "test/fixtures/entry_arrays.json",
    "content": "[\n  [\"keep1\"],\n  [\"keep3\"],\n  [\"keep4\"]\n]"
  },
  {
    "path": "test/fixtures/entry_objects.csv",
    "content": "header\nremove2\nkeep3\nkeep4\n"
  },
  {
    "path": "test/fixtures/entry_objects.json",
    "content": "[\n  { \"header\": \"keep3\" },\n  { \"header\": \"keep4\" }\n]"
  },
  {
    "path": "test/fixtures/fixtures.js",
    "content": "const fs = require('fs')\n\nfunction csvFixture (fixtureName) {\n  return fs.readFileSync('./test/fixtures/' + fixtureName + '.csv', 'utf8')\n}\n\nfunction jsonFixture (fixtureName) {\n  return JSON.parse(fs.readFileSync('./test/fixtures/' + fixtureName + '.json'))\n}\n\nmodule.exports = {\n  array_csv: csvFixture('array'),\n  array_obj: jsonFixture('array'),\n  arrays1_csv: csvFixture('arrays1'),\n  arrays1_obj: jsonFixture('arrays1'),\n  arrays2_csv: csvFixture('arrays2'),\n  arrays2_obj: jsonFixture('arrays2'),\n  rfc1_csv: csvFixture('rfc1'),\n  rfc1_obj: jsonFixture('rfc1'),\n  rfc2_csv: csvFixture('rfc2'),\n  rfc2_obj: jsonFixture('rfc2'),\n  rfc3_csv: csvFixture('rfc3'),\n  rfc3_obj: jsonFixture('rfc3'),\n  rfc4_csv: csvFixture('rfc4'),\n  rfc4_obj: jsonFixture('rfc4'),\n  rfc5_csv: csvFixture('rfc5'),\n  rfc5_obj: jsonFixture('rfc5'),\n  rfc6_csv: csvFixture('rfc6'),\n  rfc6_obj: jsonFixture('rfc6'),\n  rfc7_csv: csvFixture('rfc7'),\n  rfc7_obj: jsonFixture('rfc7'),\n  rfcA1_csv: csvFixture('rfcA1'),\n  rfcA1_obj: jsonFixture('rfcA1'),\n  rfcA2_csv: csvFixture('rfcA2'),\n  rfcA2_obj: jsonFixture('rfcA2'),\n  rfcA3_csv: csvFixture('rfcA3'),\n  rfcA3_obj: jsonFixture('rfcA3'),\n  newline_unix: csvFixture('newline_unix'),\n  newline_dos: csvFixture('newline_dos'),\n  newline_mac: csvFixture('newline_mac'),\n  defaults_csv: csvFixture('defaults'),\n  defaults_obj: jsonFixture('defaults'),\n  defaults_fivelines_csv: csvFixture('defaults_fivelines'),\n  delimiter_csv: csvFixture('delimiter'),\n  delimiter_obj: jsonFixture('delimiter'),\n  delimiter_fivelines_csv: csvFixture('delimiter_fivelines'),\n  separator_csv: csvFixture('separator'),\n  separator_obj: jsonFixture('separator'),\n  separator_fivelines_csv: csvFixture('separator_fivelines'),\n  regex_csv: csvFixture('regex'),\n  regex_obj: jsonFixture('regex'),\n  regex2_csv: csvFixture('regex2'),\n  regex2_obj: jsonFixture('regex2'),\n  regex3_csv: csvFixture('regex3'),\n  regex3_obj: jsonFixture('regex3'),\n  term_arrays_csv: csvFixture('term_arrays'),\n  term_arrays_obj: jsonFixture('term_arrays'),\n  term_objects_csv: csvFixture('term_objects'),\n  term_objects_obj: jsonFixture('term_objects'),\n  backslash_csv: csvFixture('backslash'),\n  backslash_obj: jsonFixture('backslash'),\n  objects_csv: csvFixture('objects'),\n  objects_obj: jsonFixture('objects'),\n  objects2_csv: csvFixture('objects2'),\n  value_arrays_csv: csvFixture('value_arrays'),\n  value_arrays_obj: jsonFixture('value_arrays'),\n  value_objects_csv: csvFixture('value_objects'),\n  value_objects_obj: jsonFixture('value_objects'),\n  entry_arrays_csv: csvFixture('entry_arrays'),\n  entry_arrays_obj: jsonFixture('entry_arrays'),\n  entry_objects_csv: csvFixture('entry_objects'),\n  entry_objects_obj: jsonFixture('entry_objects')\n}\n"
  },
  {
    "path": "test/fixtures/newline_dos.csv",
    "content": "a1\r\na2\r\n"
  },
  {
    "path": "test/fixtures/newline_mac.csv",
    "content": "a1\ra2\r"
  },
  {
    "path": "test/fixtures/newline_unix.csv",
    "content": "a1\na2\n"
  },
  {
    "path": "test/fixtures/objects.csv",
    "content": "\"ID\",\"iManufacturer\",\"iMPartNumber\",\"iSerialNumber\",\"iSimCategory\",\"iPartType\",\"iDescription\",\"iGroup\",\"iLocation\",\"iSold\"\n\"1\",\"Evans & Sutherland\",\"230-132-111AA\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"2\",\"Evans & Sutherland\",\"230-132-111AA\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"3\",\"Evans & Sutherland\",\"230-120-112AC\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"4\",\"Evans & Sutherland\",\"230-120-112AC\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"5\",\"Evans & Sutherland\",\"230-120-112AC\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"6\",\"Evans & Sutherland\",\"230-120-112AC\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"7\",\"Evans & Sutherland\",\"230-120-112AC\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"8\",\"Evans & Sutherland\",\"230-120-112AC\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"9\",\"Evans & Sutherland\",\"230-120-112AC\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n\"10\",\"Evans & Sutherland\",\"230-121-150AC\",\"\",\"Visual\",\"PCB\",\"\",\"1\",\"Offsite\",\"\"\n"
  },
  {
    "path": "test/fixtures/objects.json",
    "content": "[\n  {\n    \"ID\":\"1\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-132-111AA\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"2\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-132-111AA\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"3\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-120-112AC\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"4\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-120-112AC\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"5\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-120-112AC\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"6\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-120-112AC\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"7\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-120-112AC\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"8\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-120-112AC\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"9\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-120-112AC\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  },\n  {\n    \"ID\":\"10\",\n    \"iManufacturer\":\"Evans & Sutherland\",\n    \"iMPartNumber\":\"230-121-150AC\",\n    \"iSerialNumber\":\"\",\n    \"iSimCategory\":\"Visual\",\n    \"iPartType\":\"PCB\",\n    \"iDescription\":\"\",\n    \"iGroup\":\"1\",\n    \"iLocation\":\"Offsite\",\n    \"iSold\":\"\"\n  }\n]\n"
  },
  {
    "path": "test/fixtures/objects2.csv",
    "content": "ID,iManufacturer,iMPartNumber,iSerialNumber,iSimCategory,iPartType,iDescription,iGroup,iLocation,iSold\n1,Evans & Sutherland,230-132-111AA,,Visual,PCB,,1,Offsite,\n2,Evans & Sutherland,230-132-111AA,,Visual,PCB,,1,Offsite,\n3,Evans & Sutherland,230-120-112AC,,Visual,PCB,,1,Offsite,\n4,Evans & Sutherland,230-120-112AC,,Visual,PCB,,1,Offsite,\n5,Evans & Sutherland,230-120-112AC,,Visual,PCB,,1,Offsite,\n6,Evans & Sutherland,230-120-112AC,,Visual,PCB,,1,Offsite,\n7,Evans & Sutherland,230-120-112AC,,Visual,PCB,,1,Offsite,\n8,Evans & Sutherland,230-120-112AC,,Visual,PCB,,1,Offsite,\n9,Evans & Sutherland,230-120-112AC,,Visual,PCB,,1,Offsite,\n10,Evans & Sutherland,230-121-150AC,,Visual,PCB,,1,Offsite,\n"
  },
  {
    "path": "test/fixtures/regex.csv",
    "content": "\"4\"|\"he said \"\"you are crazy\"\"\"|\"one \"\", two \"\", three \"\"\""
  },
  {
    "path": "test/fixtures/regex.json",
    "content": "[\n\t\"4\",\n\t\"he said \\\"you are crazy\\\"\",\n\t\"one \\\", two \\\", three \\\"\"\n]"
  },
  {
    "path": "test/fixtures/regex2.csv",
    "content": "\"3\"(\"he said \"\"you are crazy\"\"\"(\"one \"\", two \"\", three \"\"\""
  },
  {
    "path": "test/fixtures/regex2.json",
    "content": "[\n\t\"3\",\n\t\"he said \\\"you are crazy\\\"\",\n\t\"one \\\", two \\\", three \\\"\"\n]"
  },
  {
    "path": "test/fixtures/regex3.csv",
    "content": "*3*,*he said **you are crazy***,*one **, two **, three ***"
  },
  {
    "path": "test/fixtures/regex3.json",
    "content": "[\n\t\"3\",\n\t\"he said *you are crazy*\",\n\t\"one *, two *, three *\"\n]"
  },
  {
    "path": "test/fixtures/rfc1.csv",
    "content": "aaa,bbb,ccc\nzzz,yyy,xxx\n"
  },
  {
    "path": "test/fixtures/rfc1.json",
    "content": "[\n  [\n    \"aaa\",\n    \"bbb\",\n    \"ccc\"\n  ],\n  [\n    \"zzz\",\n    \"yyy\",\n    \"xxx\"\n  ]\n]\n"
  },
  {
    "path": "test/fixtures/rfc2.csv",
    "content": "aaa,bbb,ccc\nzzz,yyy,xxx"
  },
  {
    "path": "test/fixtures/rfc2.json",
    "content": "[\n  [\n    \"aaa\",\n    \"bbb\",\n    \"ccc\"\n  ],\n  [\n    \"zzz\",\n    \"yyy\",\n    \"xxx\"\n  ]\n]\n"
  },
  {
    "path": "test/fixtures/rfc3.csv",
    "content": "field1,field2,field3\naaa,bbb,ccc\nzzz,yyy,xxx\n"
  },
  {
    "path": "test/fixtures/rfc3.json",
    "content": "[\n  {\n    \"field1\":\"aaa\",\n    \"field2\":\"bbb\",\n    \"field3\":\"ccc\"\n  },\n  {\n    \"field1\":\"zzz\",\n    \"field2\":\"yyy\",\n    \"field3\":\"xxx\"\n  }\n]"
  },
  {
    "path": "test/fixtures/rfc4.csv",
    "content": "aaa , bbb, c  cc\n"
  },
  {
    "path": "test/fixtures/rfc4.json",
    "content": "[\n  \"aaa \",\n  \" bbb\",\n  \" c  cc\"\n]\n"
  },
  {
    "path": "test/fixtures/rfc5.csv",
    "content": "\"aaa\",\"bbb\",\"ccc\"\nzzz,yyy,xxx\n"
  },
  {
    "path": "test/fixtures/rfc5.json",
    "content": "[\n  [\n    \"aaa\",\n    \"bbb\",\n    \"ccc\"\n  ],\n  [\n    \"zzz\",\n    \"yyy\",\n    \"xxx\"\n  ]\n]\n"
  },
  {
    "path": "test/fixtures/rfc6.csv",
    "content": "\"aaa\",\"b\\r\\nbb\",\"cc,c\"\nzzz,yyy,xxx\n"
  },
  {
    "path": "test/fixtures/rfc6.json",
    "content": "[\n  [\n    \"aaa\",\n    \"b\\\\r\\\\nbb\",\n    \"cc,c\"\n  ],\n  [\n    \"zzz\",\n    \"yyy\",\n    \"xxx\"\n  ]\n]\n"
  },
  {
    "path": "test/fixtures/rfc7.csv",
    "content": "\"aaa\",\"b\"\"bb\",\"ccc\"\n"
  },
  {
    "path": "test/fixtures/rfc7.json",
    "content": "[\n  \"aaa\",\n  \"b\\\"bb\",\n  \"ccc\"\n]\n"
  },
  {
    "path": "test/fixtures/rfcA1.csv",
    "content": "aaa,,ccc\n"
  },
  {
    "path": "test/fixtures/rfcA1.json",
    "content": "[\n  \"aaa\",\n  \"\",\n  \"ccc\"\n]\n"
  },
  {
    "path": "test/fixtures/rfcA2.csv",
    "content": "\"aaa\",\"\",\"ccc\"\n"
  },
  {
    "path": "test/fixtures/rfcA2.json",
    "content": "[\n  \"aaa\",\n  \"\",\n  \"ccc\"\n]\n"
  },
  {
    "path": "test/fixtures/rfcA3.csv",
    "content": "\"aaa\",\"bbb\",\n"
  },
  {
    "path": "test/fixtures/rfcA3.json",
    "content": "[\n  \"aaa\",\n  \"bbb\",\n  \"\"\n]\n"
  },
  {
    "path": "test/fixtures/separator.csv",
    "content": "\"3\";\"he said \"\"you are crazy\"\"\";\"one \"\", two \"\", three \"\"\""
  },
  {
    "path": "test/fixtures/separator.json",
    "content": "[\n\t\"3\",\n\t\"he said \\\"you are crazy\\\"\",\n\t\"one \\\", two \\\", three \\\"\"\n]"
  },
  {
    "path": "test/fixtures/separator_fivelines.csv",
    "content": "\"3\";\"he said \"\"you are crazy\"\"\";\"one \"\", two \"\", three \"\"\"\n\"3\";\"he said \"\"you are crazy\"\"\";\"one \"\", two \"\", three \"\"\"\n\"3\";\"he said \"\"you are crazy\"\"\";\"one \"\", two \"\", three \"\"\"\n\"3\";\"he said \"\"you are crazy\"\"\";\"one \"\", two \"\", three \"\"\"\n\"3\";\"he said \"\"you are crazy\"\"\";\"one \"\", two \"\", three \"\"\"\n"
  },
  {
    "path": "test/fixtures/term_arrays.csv",
    "content": "*Look*:*there's two women*:*fucking a polar bear!*\n*Don't*:*tell me these things*:*not now man.*\n"
  },
  {
    "path": "test/fixtures/term_arrays.json",
    "content": "[\n\t[\n\t\t\"Look\",\n\t\t\"there's two women\",\n\t\t\"fucking a polar bear!\"\n\t],\n\t[\n\t\t\"Don't\",\n\t\t\"tell me these things\",\n\t\t\"not now man.\"\n\t]\n]"
  },
  {
    "path": "test/fixtures/term_objects.csv",
    "content": "^preposition^&^evaluation^&^response^\n^One toke?^&^you poor fool!^&^wait till you see those goddamn bats.^\n^Wait!^&^we can't stop here^&^this is bat country.^"
  },
  {
    "path": "test/fixtures/term_objects.json",
    "content": "[\n\t{\n\t\t\"preposition\":\"One toke?\",\n\t\t\"evaluation\":\"you poor fool!\",\n\t\t\"response\":\"wait till you see those goddamn bats.\"\n\t},\n \t{\n \t\t\"preposition\":\"Wait!\",\n \t\t\"evaluation\":\"we can't stop here\",\n \t\t\"response\":\"this is bat country.\"\n \t}\n]"
  },
  {
    "path": "test/fixtures/value_arrays.csv",
    "content": "this,is,some,data"
  },
  {
    "path": "test/fixtures/value_arrays.json",
    "content": "[\n  [ \"thisa\", \"isa\", \"somea\", \"dataa\" ]\n]"
  },
  {
    "path": "test/fixtures/value_objects.csv",
    "content": "h1,h2,h3,h4\nthis,is,some,data"
  },
  {
    "path": "test/fixtures/value_objects.json",
    "content": "[\n  { \"h1\": \"thisa\", \"h2\": \"isa\", \"h3\": \"somea\", \"h4\": \"dataa\" }\n]"
  },
  {
    "path": "test/options.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('Options - should parse using the default terminals', (t) => {\n  const result = csv.toArray(fixtures.defaults_csv)\n  const expect = fixtures.defaults_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('Options - should parse using a custom delimiter', (t) => {\n  const options = {\n    delimiter: '\\''\n  }\n\n  const result = csv.toArray(fixtures.delimiter_csv, options)\n  const expect = fixtures.delimiter_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('Options - should parse using a custom separator', (t) => {\n  const options = {\n    separator: ';'\n  }\n\n  const result = csv.toArray(fixtures.separator_csv, options)\n  const expect = fixtures.separator_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('Options - should properly escape regex special chars', (t) => {\n  const options = {\n    separator: '|'\n  }\n\n  const result = csv.toArray(fixtures.regex_csv, options)\n  const expect = fixtures.regex_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('Options - should properly escape regex ( chars', (t) => {\n  const options = {\n    separator: '('\n  }\n\n  const result = csv.toArray(fixtures.regex2_csv, options)\n  const expect = fixtures.regex2_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('Options - should properly escape regex * chars', (t) => {\n  const options = {\n    delimiter: '*'\n  }\n\n  const result = csv.toArray(fixtures.regex3_csv, options)\n  const expect = fixtures.regex3_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('Options - should support custom terminals via toArrays()', (t) => {\n  const options = {\n    delimiter: '*',\n    separator: ':'\n  }\n\n  const result = csv.toArrays(fixtures.term_arrays_csv, options)\n  const expect = fixtures.term_arrays_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('Options - should support custom terminals via toObjects()', (t) => {\n  const options = {\n    delimiter: '^',\n    separator: '&'\n  }\n\n  const result = csv.toObjects(fixtures.term_objects_csv, options)\n  const expect = fixtures.term_objects_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n"
  },
  {
    "path": "test/rfc_amendments.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('RFC Amendment #1 - An unquoted field may contain a null (ie empty) value', (t) => {\n  const result = csv.toArray(fixtures.rfcA1_csv)\n  const expect = fixtures.rfcA1_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('RFC Amendment #2 - A quoted field may contain a null (ie empty) value', (t) => {\n  const result = csv.toArray(fixtures.rfcA2_csv)\n  const expect = fixtures.rfcA2_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('RFC Amendment #3 - The last field in an entry may contain a null (ie empty) value', (t) => {\n  const result = csv.toArray(fixtures.rfcA3_csv)\n  const expect = fixtures.rfcA3_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n"
  },
  {
    "path": "test/rfc_compliance.js",
    "content": "const test = require('tape')\nconst csv = require('../src/jquery.csv.js')\nconst fixtures = require('./fixtures/fixtures.js')\n\ntest('RFC Rule #1 - One entry per line, each line ends with a newline', (t) => {\n  const result = csv.toArrays(fixtures.rfc1_csv)\n  const expect = fixtures.rfc1_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('RFC Rule #2 - Trailing newline at the end of the file ommitted', (t) => {\n  const result = csv.toArrays(fixtures.rfc2_csv)\n  const expect = fixtures.rfc2_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('RFC Rule #3 - First row contains header data', (t) => {\n  const result = csv.toObjects(fixtures.rfc3_csv)\n  const expect = fixtures.rfc3_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('RFC Rule #4 - Spaces are considered data and entries should not contain a trailing comma', (t) => {\n  const result = csv.toArray(fixtures.rfc4_csv)\n  const expect = fixtures.rfc4_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('RFC Rule #5 - Lines may or may not be delimited by double-quotes', (t) => {\n  const result = csv.toArrays(fixtures.rfc5_csv)\n  const expect = fixtures.rfc5_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('RFC Rule #6 - Fields containing line breaks, double-quotes, and commas should be enclosed in double-quotes', (t) => {\n  const result = csv.toArrays(fixtures.rfc6_csv)\n  const expect = fixtures.rfc6_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n\ntest('RFC Rule #7 - If double-quotes are used to enclose fields, then a double-quote appering inside a field must be escaped by a preceding it with another double-quote', (t) => {\n  const result = csv.toArray(fixtures.rfc7_csv)\n  const expect = fixtures.rfc7_obj\n  t.deepEqual(result, expect)\n  t.end()\n})\n"
  }
]