Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add field to get the visual document number #58

Merged
merged 3 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
extends: cheminfo-typescript
env:
node: true
parserOptions:
sourceType: script
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ Object mapping field names to their respective value. The value is set to `null`
if it is invalid. The value may be different from the raw value. For example,
`result.fields.sex` will be "male" when the raw value was "M".

##### result.documentNumber

The document number, as can be found in the visual elements of the document, outside the MRZ. For some documents, it may
be composed of multiple parsed fields. It may also not include the MRZ field named `documentNumber`. If any of the used
fields is invalid, this field will be set to `null`.

##### result.details

Array of objects describing all parsed fields. Its structure is:
Expand Down Expand Up @@ -113,11 +119,11 @@ https://www.icao.int/publications/pages/publication.aspx?docnum=9303

### Swiss driving license

http://www.astra2.admin.ch/media/pdfpub/2003-10-15_2262_f.pdf
https://www.astra.admin.ch/dam/astra/fr/dokumente/dokumente-strassenverkehr/kreisschreiben/ch-fak.pdf.download.pdf/Le%20permis%20de%20conduire%20suisse%20format%20carte%20de%20cr%C3%A9dit%20(PCC).pdf

### French national id

https://fr.wikipedia.org/wiki/Carte_nationale_d%27identit%C3%A9_en_France#Codage_Bande_MRZ_(lecture_optique)
https://fr.wikipedia.org/wiki/Carte_nationale_d%27identit%C3%A9_en_France#Codage_bande_%C3%A0_lecture_optique

## License

Expand Down
2 changes: 2 additions & 0 deletions builder/.eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parserOptions:
sourceType: script
1 change: 0 additions & 1 deletion builder/createStatesJs.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const statesObject = {
};

const result = [];
result.push("'use strict';");
result.push(`const states = ${JSON.stringify(statesObject, null, 2)};`);
result.push('Object.freeze(states);');
result.push('export default states;');
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@
},
"homepage": "https://github.com/cheminfo/mrz#readme",
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.23.0",
"@babel/preset-typescript": "^7.23.2",
"@types/jest": "^29.5.6",
"@babel/plugin-transform-modules-commonjs": "^7.24.6",
"@babel/preset-typescript": "^7.24.6",
"@types/jest": "^29.5.12",
"cheminfo-build": "^1.2.0",
"eslint": "^8.52.0",
"eslint-config-cheminfo-typescript": "^12.0.4",
"eslint-config-cheminfo-typescript": "^12.4.0",
"jest": "^29.7.0",
"prettier": "^3.0.3",
"rimraf": "^5.0.5",
"typescript": "^5.2.2"
"prettier": "^3.2.5",
"rimraf": "^5.0.7",
"typescript": "^5.4.5"
}
}
2 changes: 0 additions & 2 deletions src/formats.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

export type FormatType = keyof typeof formats;

export const formats = {
Expand Down
2 changes: 0 additions & 2 deletions src/generated/__tests__/states.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

import states from '../states';

describe('check countries', function () {
Expand Down
1 change: 0 additions & 1 deletion src/generated/states.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
'use strict';
const states = {
"AFG": "Afghanistan",
"ALB": "Albania",
Expand Down
2 changes: 0 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

import { formats } from './formats';
import states from './generated/states';
import parse from './parse/parse';
Expand Down
2 changes: 0 additions & 2 deletions src/parse/__tests__/errors.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

import parse from '../parse';

describe('Bad MRZ', () => {
Expand Down
13 changes: 8 additions & 5 deletions src/parse/__tests__/frenchDrivingLicense.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

import parse from '../parse';

describe('parse French Driving License', () => {
Expand All @@ -8,9 +6,12 @@ describe('parse French Driving License', () => {

const result = parse(MRZ);

expect(result.format).toBe('FRENCH_DRIVING_LICENSE');
expect(result.valid).toBe(true);
expect(result.details.filter((a) => !a.valid)).toHaveLength(0);
expect(result).toMatchObject({
format: 'FRENCH_DRIVING_LICENSE',
valid: true,
documentNumber: result.fields.documentNumber,
});

expect(result.fields).toStrictEqual({
documentCode: 'D1',
issuingState: 'FRA',
Expand All @@ -20,6 +21,8 @@ describe('parse French Driving License', () => {
lastName: 'MARTIN',
compositeCheckDigit: '9',
});

expect(result.details.filter((a) => !a.valid)).toHaveLength(0);
});

it('Use autocorrect', () => {
Expand Down
54 changes: 47 additions & 7 deletions src/parse/__tests__/frenchNationalId.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

import parse from '../parse';

describe('parse French National Id', () => {
Expand All @@ -10,9 +8,13 @@ describe('parse French National Id', () => {
];

const result = parse(MRZ);
expect(result.format).toBe('FRENCH_NATIONAL_ID');
// expect(result.valid).toStrictEqual(true);
expect(result.details.filter((a) => !a.valid)).toHaveLength(0);

expect(result).toMatchObject({
format: 'FRENCH_NATIONAL_ID',
valid: true,
documentNumber: '1710GVA12345',
});

expect(result.fields).toStrictEqual({
documentCode: 'ID',
issuingState: 'FRA',
Expand All @@ -28,21 +30,59 @@ describe('parse French National Id', () => {
sex: 'female',
compositeCheckDigit: '2',
});

expect(result.details.filter((a) => !a.valid)).toHaveLength(0);
});

it('invalid MRZ', () => {
const MRZ = [
'IDFRATEST<NAME<<<<<<<<<<<<<<<<0CHE02',
'1710GV?123451ROBERTA<<<<<<<9112311F2',
];

const result = parse(MRZ);

expect(result).toMatchObject({
format: 'FRENCH_NATIONAL_ID',
valid: false,
documentNumber: null,
});

expect(result.fields).toStrictEqual({
documentCode: 'ID',
issuingState: 'FRA',
lastName: 'TEST NAME',
administrativeCode: '0CHE02',
issueDate: '1710',
administrativeCode2: null,
documentNumber: '12345',
documentNumberCheckDigit: null,
firstName: 'ROBERTA',
birthDate: '911231',
birthDateCheckDigit: '1',
sex: 'female',
compositeCheckDigit: null,
});

expect(result.details.filter((a) => !a.valid)).toHaveLength(3);
});

it('Use autocorrect', () => {
const MRZ = [
'IDFRATEST<NAME<<<<<<<<<<<<<<<<0CHE02',
'1710GVA123451ROBERTA<<<<<<<9112311F2',
];

const reference = parse(MRZ);

const falseMRZ = [
'1DFRATE5T<NAME<<<<<<<<<<<<<<<<0CHE02',
'I7I0GVA123451RO8ERTA<<<<<<<9IIZ3IIF2',
];

const result = parse(MRZ);
const correctedResult = parse(falseMRZ, { autocorrect: true });
expect(correctedResult.fields).toStrictEqual(reference.fields);

expect(result.fields).toStrictEqual(correctedResult.fields);
expect(
correctedResult.details.map(({ autocorrect }) => autocorrect),
).toStrictEqual([
Expand Down
75 changes: 44 additions & 31 deletions src/parse/__tests__/swissDrivingLicense.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

import parse from '../parse';

describe('parse Swiss Driving License', () => {
Expand All @@ -11,8 +9,25 @@ describe('parse Swiss Driving License', () => {
];

const result = parse(MRZ);
expect(result.format).toBe('SWISS_DRIVING_LICENSE');
expect(result.valid).toBe(true);

expect(result).toMatchObject({
format: 'SWISS_DRIVING_LICENSE',
valid: true,
documentNumber: '305142128097',
});

expect(result.fields).toStrictEqual({
documentNumber: 'AAA001D',
languageCode: 'D',
documentCode: 'FA',
issuingState: 'CHE',
pinCode: '305142128',
versionNumber: '097',
birthDate: '800126',
firstName: 'FABIENNE',
lastName: 'MARCHAND',
});

expect(result.details.filter((a) => !a.valid)).toHaveLength(0);
expect(result.details[0]).toStrictEqual({
label: 'Document number',
Expand Down Expand Up @@ -43,29 +58,36 @@ describe('parse Swiss Driving License', () => {
end: 18,
autocorrect: [],
});
});

it('invalid text', () => {
const MRZ = [
'AAA001D<<',
'FACHE305142128?97<<800126<<<<<',
'M4RCHAND<<FABI3NNE<<<<<<<<<<<<',
];

const result = parse(MRZ);

expect(result).toMatchObject({
format: 'SWISS_DRIVING_LICENSE',
valid: false,
documentNumber: null,
});

expect(result.fields).toStrictEqual({
documentNumber: 'AAA001D',
languageCode: 'D',
documentCode: 'FA',
issuingState: 'CHE',
pinCode: '305142128',
versionNumber: '097',
versionNumber: null,
birthDate: '800126',
firstName: 'FABIENNE',
lastName: 'MARCHAND',
firstName: null,
lastName: null,
});
});
it('invalid text', () => {
const MRZ = [
'AAA001D<<',
'FACHE305142128097<<800126<<<<<',
'M4RCHAND<<FABI3NNE<<<<<<<<<<<<',
];

const result = parse(MRZ);
expect(result.format).toBe('SWISS_DRIVING_LICENSE');
expect(result.valid).toBe(false);
expect(result.details.filter((a) => !a.valid)).toHaveLength(2);
expect(result.details.filter((a) => !a.valid)).toHaveLength(3);
expect(result.details[0]).toStrictEqual({
label: 'Document number',
field: 'documentNumber',
Expand Down Expand Up @@ -105,34 +127,25 @@ describe('parse Swiss Driving License', () => {
start: 0,
end: 8,
});
expect(result.fields).toStrictEqual({
documentNumber: 'AAA001D',
languageCode: 'D',
documentCode: 'FA',
issuingState: 'CHE',
pinCode: '305142128',
versionNumber: '097',
birthDate: '800126',
firstName: null,
lastName: null,
});
});
it('Use autocorrect', () => {
const MRZ = [
'AAA001D<<',
'FACHE305142128097<<800126<<<<<',
'MARCHAND<<FABIENNE<<<<<<<<<<<<',
];

const reference = parse(MRZ);

const falseMRZ = [
'AAA001D<<',
'FACHE30S142IZBO97<<8OO12G<<<<<',
'MARCHAND<<FA81ENNE<<<<<<<<<<<<',
];

const result = parse(MRZ);
const correctedResult = parse(falseMRZ, { autocorrect: true });

expect(result.fields).toStrictEqual(correctedResult.fields);
expect(correctedResult.fields).toStrictEqual(reference.fields);
expect(
correctedResult.details.map(({ autocorrect }) => autocorrect),
).toStrictEqual([
Expand Down
Loading