hh-shipments 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/extract.js +28 -2
- package/src/extract.js +28 -2
package/package.json
CHANGED
package/public/extract.js
CHANGED
|
@@ -111,6 +111,9 @@
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function extractOcrTolerant(text, found, seen) {
|
|
114
|
+
// Strict UPS structure: 1Z + 6-char shipper number + 2-digit service + 8-digit serial.
|
|
115
|
+
// Used to validate "1Z"-as-"12" OCR repairs so we don't invent false positives.
|
|
116
|
+
var UPS_STRICT = /^1Z[0-9A-Z]{6}[0-9]{2}[0-9]{8}$/;
|
|
114
117
|
function push(num, carrier, confidence, extra) {
|
|
115
118
|
num = normalize(num);
|
|
116
119
|
if (!num || seen[num]) return;
|
|
@@ -119,11 +122,27 @@
|
|
|
119
122
|
if (extra) for (var k in extra) c[k] = extra[k];
|
|
120
123
|
found.push(c);
|
|
121
124
|
}
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
function repairUpsZ(ups) {
|
|
126
|
+
// Tesseract often reads the "1Z" anchor as "12" (or "IZ"). Repair it
|
|
127
|
+
// only when the rest has strict UPS structure AND the shipper segment
|
|
128
|
+
// contains a letter — real UPS shipper numbers do, random digit runs
|
|
129
|
+
// don't. Never invent numbers from thin air.
|
|
130
|
+
var cand = null;
|
|
131
|
+
if (/^12[0-9A-Z]{16}$/.test(ups)) cand = '1Z' + ups.slice(2);
|
|
132
|
+
else if (/^IZ[0-9A-Z]{16}$/i.test(ups)) cand = '1Z' + ups.slice(2);
|
|
133
|
+
if (!cand || !UPS_STRICT.test(cand)) return null;
|
|
134
|
+
if (!/[A-Z]/.test(cand.slice(2, 8))) return null;
|
|
135
|
+
return cand;
|
|
136
|
+
}
|
|
137
|
+
// a) UPS number split by spaces/dashes: "1Z 9999 99 ..." (or "12 ..."/"IZ ..." misreads)
|
|
138
|
+
var m, spacedUps = /\b(?:1Z|12|IZ)[\s-]?(?:[0-9A-Z][\s-]?){16}\b/gi;
|
|
124
139
|
while ((m = spacedUps.exec(text)) !== null) {
|
|
125
140
|
var ups = normalize(m[0]);
|
|
126
141
|
if (/^1Z[0-9A-Z]{16}$/.test(ups)) push(ups, 'ups', 'medium');
|
|
142
|
+
else {
|
|
143
|
+
var fixed = repairUpsZ(ups);
|
|
144
|
+
if (fixed) push(fixed, 'ups', 'medium');
|
|
145
|
+
}
|
|
127
146
|
}
|
|
128
147
|
// b) long digit-like runs with OCR confusions -> fix -> re-match digit formats
|
|
129
148
|
var runRe = /[0-9OILSBoilszb]{10,24}/g, run;
|
|
@@ -145,6 +164,13 @@
|
|
|
145
164
|
});
|
|
146
165
|
tokens.sort(function (a, b) { return b.length - a.length; });
|
|
147
166
|
tokens.slice(0, 3).forEach(function (t) {
|
|
167
|
+
// UPS "1Z" misread as "12"/"IZ" in a joined (space-free) token
|
|
168
|
+
var fixed = repairUpsZ(t);
|
|
169
|
+
if (fixed) { push(fixed, 'ups', 'medium'); return; }
|
|
170
|
+
// OCR-fixed variant may match a carrier format (e.g. I->1 at the start)
|
|
171
|
+
var digitFixed = ocrDigitFix(t);
|
|
172
|
+
var gc = guessCarrier(digitFixed);
|
|
173
|
+
if (gc !== 'unknown') { push(digitFixed, gc, 'low', { possible: true }); return; }
|
|
148
174
|
push(t, guessCarrier(t), 'low', { possible: true });
|
|
149
175
|
});
|
|
150
176
|
}
|
package/src/extract.js
CHANGED
|
@@ -111,6 +111,9 @@
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function extractOcrTolerant(text, found, seen) {
|
|
114
|
+
// Strict UPS structure: 1Z + 6-char shipper number + 2-digit service + 8-digit serial.
|
|
115
|
+
// Used to validate "1Z"-as-"12" OCR repairs so we don't invent false positives.
|
|
116
|
+
var UPS_STRICT = /^1Z[0-9A-Z]{6}[0-9]{2}[0-9]{8}$/;
|
|
114
117
|
function push(num, carrier, confidence, extra) {
|
|
115
118
|
num = normalize(num);
|
|
116
119
|
if (!num || seen[num]) return;
|
|
@@ -119,11 +122,27 @@
|
|
|
119
122
|
if (extra) for (var k in extra) c[k] = extra[k];
|
|
120
123
|
found.push(c);
|
|
121
124
|
}
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
function repairUpsZ(ups) {
|
|
126
|
+
// Tesseract often reads the "1Z" anchor as "12" (or "IZ"). Repair it
|
|
127
|
+
// only when the rest has strict UPS structure AND the shipper segment
|
|
128
|
+
// contains a letter — real UPS shipper numbers do, random digit runs
|
|
129
|
+
// don't. Never invent numbers from thin air.
|
|
130
|
+
var cand = null;
|
|
131
|
+
if (/^12[0-9A-Z]{16}$/.test(ups)) cand = '1Z' + ups.slice(2);
|
|
132
|
+
else if (/^IZ[0-9A-Z]{16}$/i.test(ups)) cand = '1Z' + ups.slice(2);
|
|
133
|
+
if (!cand || !UPS_STRICT.test(cand)) return null;
|
|
134
|
+
if (!/[A-Z]/.test(cand.slice(2, 8))) return null;
|
|
135
|
+
return cand;
|
|
136
|
+
}
|
|
137
|
+
// a) UPS number split by spaces/dashes: "1Z 9999 99 ..." (or "12 ..."/"IZ ..." misreads)
|
|
138
|
+
var m, spacedUps = /\b(?:1Z|12|IZ)[\s-]?(?:[0-9A-Z][\s-]?){16}\b/gi;
|
|
124
139
|
while ((m = spacedUps.exec(text)) !== null) {
|
|
125
140
|
var ups = normalize(m[0]);
|
|
126
141
|
if (/^1Z[0-9A-Z]{16}$/.test(ups)) push(ups, 'ups', 'medium');
|
|
142
|
+
else {
|
|
143
|
+
var fixed = repairUpsZ(ups);
|
|
144
|
+
if (fixed) push(fixed, 'ups', 'medium');
|
|
145
|
+
}
|
|
127
146
|
}
|
|
128
147
|
// b) long digit-like runs with OCR confusions -> fix -> re-match digit formats
|
|
129
148
|
var runRe = /[0-9OILSBoilszb]{10,24}/g, run;
|
|
@@ -145,6 +164,13 @@
|
|
|
145
164
|
});
|
|
146
165
|
tokens.sort(function (a, b) { return b.length - a.length; });
|
|
147
166
|
tokens.slice(0, 3).forEach(function (t) {
|
|
167
|
+
// UPS "1Z" misread as "12"/"IZ" in a joined (space-free) token
|
|
168
|
+
var fixed = repairUpsZ(t);
|
|
169
|
+
if (fixed) { push(fixed, 'ups', 'medium'); return; }
|
|
170
|
+
// OCR-fixed variant may match a carrier format (e.g. I->1 at the start)
|
|
171
|
+
var digitFixed = ocrDigitFix(t);
|
|
172
|
+
var gc = guessCarrier(digitFixed);
|
|
173
|
+
if (gc !== 'unknown') { push(digitFixed, gc, 'low', { possible: true }); return; }
|
|
148
174
|
push(t, guessCarrier(t), 'low', { possible: true });
|
|
149
175
|
});
|
|
150
176
|
}
|