Skip to content

Commit

Permalink
fix(parse): Handle escaped escape properly #340
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-martin committed May 15, 2020
1 parent a71e712 commit 78d9b16
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 2 deletions.
12 changes: 12 additions & 0 deletions .run/Run Examples.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Examples" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="examples" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>
12 changes: 12 additions & 0 deletions .run/Serve Docs.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Serve Docs" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/documentation/package.json" />
<command value="run" />
<scripts>
<script value="start" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>
13 changes: 13 additions & 0 deletions .run/jest.config.js.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Tests" type="JavaScriptTestRunnerJest">
<config-file value="$PROJECT_DIR$/jest.config.js" />
<node-interpreter value="project" />
<node-options value="" />
<jest-package value="$PROJECT_DIR$/node_modules/jest" />
<working-dir value="$PROJECT_DIR$/packages/parse" />
<jest-options value="--runInBand --coverage" />
<envs />
<scope-kind value="ALL" />
<method v="2" />
</configuration>
</component>
22 changes: 22 additions & 0 deletions packages/parse/__tests__/issues/issue340.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { EOL } from 'os';
import { parseString, RowMap, RowArray } from '../../src';

describe('Issue #340 - https://github.com/C2FO/fast-csv/issues/340', () => {
const CSV_CONTENT = ['Col1', `"A '"Good'" row''"`, 'Row 2'].join(EOL);
const expectedRows = [{ Col1: `A "Good" row'` }, { Col1: 'Row 2' }];

it('handle a trailing escape', (done) => {
const invalid: RowArray[] = [];
const rows: RowMap[] = [];
parseString(CSV_CONTENT, { headers: true, escape: "'" })
.on('data-invalid', (row: RowArray) => invalid.push(row))
.on('data', (r: RowMap) => rows.push(r))
.on('error', done)
.on('end', (count: number) => {
expect(rows).toEqual(expectedRows);
expect(invalid).toHaveLength(0);
expect(count).toBe(expectedRows.length + invalid.length);
done();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,13 @@ describe('QuotedColumnParser', () => {
expect(scanner.lineFromCursor).toBe(',"world"');
});

it('should parse an escape followed by another escape', () => {
const line = '"hello$$","world"';
const { scanner, col } = parse(line, true, { escape: '$' });
expect(col).toBe('hello$');
expect(scanner.lineFromCursor).toBe(',"world"');
});

it('should parse a quoted col up to a LF', () => {
const line = '"hello"\n"world"';
const { scanner, col } = parse(line, true, { escape: '$' });
Expand Down
8 changes: 6 additions & 2 deletions packages/parse/src/parser/column/QuotedColumnParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class QuotedColumnParser {
throw new Error(
`Parse Error: missing closing: '${
this.parserOptions.quote
}' in line: at '${scanner.lineFromCursor.replace(/[r\n]/g, "\\n'")}'`,
}' in line: at '${scanner.lineFromCursor.replace(/[\r\n]/g, "\\n'")}'`,
);
}
return null;
Expand All @@ -62,7 +62,11 @@ export class QuotedColumnParser {
const tokenFollowingEscape = scanner.nextCharacterToken;
// if the character following the escape is a quote character then just add
// the quote and advance to that character
if (tokenFollowingEscape !== null && isTokenQuote(tokenFollowingEscape, parserOptions)) {
if (
tokenFollowingEscape !== null &&
(isTokenQuote(tokenFollowingEscape, parserOptions) ||
isTokenEscapeCharacter(tokenFollowingEscape, parserOptions))
) {
characters.push(tokenFollowingEscape.token);
nextToken = tokenFollowingEscape;
} else if (isQuote) {
Expand Down

0 comments on commit 78d9b16

Please sign in to comment.