@@ -2745,20 +2745,28 @@ export function nportIdentifier(position: NportPosition): string {
27452745}
27462746
27472747/**
2748- * A company name as a lookup key: upper case, punctuation and legal suffixes dropped, `CLASS A` -> `CL A`. Dotted
2749- * abbreviations collapse like the undotted forms (`N.V.` = `NV`, `S.p.A.` = `SPA`, `A/S` = `A S` = `AS`, `S.A.B. de C.V.` = `SAB DE CV`)
2750- * and `PUBLIC LIMITED COMPANY` is `plc`, so both spellings of one issuer give one key.
2748+ * A company name as a lookup key: upper case, punctuation and legal suffixes dropped, `CLASS A` -> `CL A`. Initials are one
2749+ * word whether written with dots, spaces or a slash (`N.V.` = `N V` = `NV`, `C.H. ROBINSON` = `C H ROBINSON`, `A/S` = `A S`,
2750+ * `S.A.B. de C.V.` = `SAB DE CV`), `PUBLIC LIMITED COMPANY` is `plc`, and a leading `US` stays (`U.S. BANCORP` is not
2751+ * `BANCORP, INC.`), so both spellings of one issuer give one key.
27512752 */
27522753export function nportNameKey ( value : unknown ) : string {
2753- // EDGAR adds a state or qualifier suffix to company titles ("COSTCO WHOLESALE CORP /NEW", "BANK OF AMERICA CORP /DE/"): drop a trailing one
2754- const raw = String ( value === null || value === undefined ? '' : value ) . replace ( / (?: \s * \/ \s * [ A - Z a - z ] { 2 , 3 } \s * \/ ? ) + \s * $ / , '' )
2755- . replace ( / \b [ A - Z a - z ] (?: \. [ A - Z a - z ] ) + \. ? (? ! [ A - Z a - z ] ) / g, ( dotted ) => dotted . replace ( / \. / g, '' ) )
2756- . replace ( / \b A \/ S \b / gi, 'AS' ) ;
2757- let text = nportText ( raw ) . toUpperCase ( ) . replace ( / [ ' ’ ] / g, '' ) . replace ( / & / g, ' AND ' ) . replace ( / [ ^ A - Z 0 - 9 ] + / g, ' ' ) ;
2758- text = text . replace ( / A S ? $ / , ' AS' ) . replace ( / \b P U B L I C (?: (?: L I M I T E D | L T D ) (?: (?: C O M P [ A - Z ] * | C O ) ) ? | (?: C O M P A N Y | C O ) (?: L I M I T E D | L T D ) ) \b / g, 'PLC' ) . replace ( / \b (?: S D E R L ) ? D E C V \b / g, ' ' ) ;
2754+ // EDGAR adds a state or qualifier suffix to company titles ("COSTCO WHOLESALE CORP /NEW", "BANK OF AMERICA CORP /DE/", "US BANCORP \DE\"): drop a trailing one
2755+ const raw = String ( value === null || value === undefined ? '' : value ) . replace ( / (?: \s * [ \/ \\ ] \s * [ A - Z a - z ] { 2 , 3 } \s * [ \/ \\ ] ? ) + \s * $ / , '' ) ;
2756+ let text = nportText ( raw ) . toUpperCase ( ) . replace ( / [ ' ’ ] / g, '' ) . replace ( / & / g, ' AND ' ) . replace ( / [ ^ A - Z 0 - 9 ] + / g, ' ' ) . trim ( ) ;
27592757 text = text . replace ( / \b C L A S S \s + ( [ A - Z ] ) \b / g, 'CL $1' ) . replace ( / \b C L \s + ( [ A - Z ] ) \b / g, 'CL $1' ) ;
2758+ // a run of single letters is one word, never the class letter after CL
2759+ const words : string [ ] = [ ] ;
2760+ let joining = false ;
2761+ text . split ( ' ' ) . forEach ( ( word ) => {
2762+ const letter = / ^ [ A - Z ] $ / . test ( word ) ;
2763+ if ( letter && joining ) words [ words . length - 1 ] += word ;
2764+ else words . push ( word ) ;
2765+ joining = letter && ( joining || words [ words . length - 2 ] !== 'CL' ) ;
2766+ } ) ;
2767+ text = words . join ( ' ' ) . replace ( / \b P U B L I C (?: (?: L I M I T E D | L T D ) (?: (?: C O M P [ A - Z ] * | C O ) ) ? | (?: C O M P A N Y | C O ) (?: L I M I T E D | L T D ) ) \b / g, 'PLC' ) . replace ( / \b (?: S D E R L ) ? D E C V \b / g, ' ' ) ;
27602768 const share = / \b C L [ A - Z ] \b / . exec ( text ) ;
2761- text = text . replace ( / \b ( T H E | I N C | I N C O R P O R A T E D | C O R P | C O R P O R A T I O N | C O | C O M P A N Y | L T D | L I M I T E D | P L C | S A | S A B | N V | A G | S E | S P A | A S | A S A | O R D I N A R Y | C O M M O N | S T O C K | S H S | S H A R E S | A D R | D E P O S I T A R Y | R E C E I P T | U S D | U S | R E G | R E G I S T E R E D ) \b / g, ' ' ) . replace ( / \s + / g, ' ' ) . trim ( ) ;
2769+ text = text . replace ( / \b ( T H E | I N C | I N C O R P O R A T E D | C O R P | C O R P O R A T I O N | C O | C O M P A N Y | L T D | L I M I T E D | P L C | S A | S A B | N V | A G | S E | S P A | A S | A S A | O R D I N A R Y | C O M M O N | S T O C K | S H S | S H A R E S | A D R | D E P O S I T A R Y | R E C E I P T | U S D | U S | R E G | R E G I S T E R E D ) \b / g, ( word : string , _name : string , at : number ) => ( word === 'US' && at === 0 ? word : ' ' ) ) . replace ( / \s + / g, ' ' ) . trim ( ) ;
27622770 if ( share && ! / \b C L [ A - Z ] \b / . test ( text ) ) text = `${ text } ${ share [ 0 ] } ` ;
27632771 return text ;
27642772}
0 commit comments