@@ -32,8 +32,106 @@ type SearchData = {
3232
3333const dataUrl = "/ucd.json" ;
3434
35+ const categoryMap : { [ key : string ] : string } = {
36+ "Cc" : "Other, Control" ,
37+ "Cf" : "Other, Format" ,
38+ "Cn" : "Other, Not Assigned (no characters in the file have this property)" ,
39+ "Co" : "Other, Private Use" ,
40+ "Cs" : "Other, Surrogate" ,
41+ "LC" : "Letter, Cased" ,
42+ "Ll" : "Letter, Lowercase" ,
43+ "Lm" : "Letter, Modifier" ,
44+ "Lo" : "Letter, Other" ,
45+ "Lt" : "Letter, Titlecase" ,
46+ "Lu" : "Letter, Uppercase" ,
47+ "Mc" : "Mark, Spacing Combining" ,
48+ "Me" : "Mark, Enclosing" ,
49+ "Mn" : "Mark, Nonspacing" ,
50+ "Nd" : "Number, Decimal Digit" ,
51+ "Nl" : "Number, Letter" ,
52+ "No" : "Number, Other" ,
53+ "Pc" : "Punctuation, Connector" ,
54+ "Pd" : "Punctuation, Dash" ,
55+ "Pe" : "Punctuation, Close" ,
56+ "Pf" : "Punctuation, Final quote (may behave like Ps or Pe depending on usage)" ,
57+ "Pi" : "Punctuation, Initial quote (may behave like Ps or Pe depending on usage)" ,
58+ "Po" : "Punctuation, Other" ,
59+ "Ps" : "Punctuation, Open" ,
60+ "Sc" : "Symbol, Currency" ,
61+ "Sk" : "Symbol, Modifier" ,
62+ "Sm" : "Symbol, Math" ,
63+ "So" : "Symbol, Other" ,
64+ "Zl" : "Separator, Line" ,
65+ "Zp" : "Separator, Paragraph" ,
66+ "Zs" : "Separator, Space"
67+ }
68+
69+ function filterCategory (
70+ headerValue : string ,
71+ rowValue : string ,
72+ rowData : any ,
73+ filterParams : any
74+ ) {
75+ if ( ! headerValue ) return true ;
76+
77+ const headerUpper = headerValue . toUpperCase ( ) ;
78+ if ( headerValue . length == 2 ) {
79+ return rowValue . toUpperCase ( ) == headerUpper ;
80+ }
81+
82+ const description = categoryMap [ rowValue ] . toUpperCase ( ) ;
83+
84+ return description . startsWith ( headerUpper ) ;
85+ }
86+
87+ function filterName (
88+ headerValue : string ,
89+ sortValue : string ,
90+ rowData : any ,
91+ filterParams : any
92+ ) {
93+ if ( ! headerValue ) return true ;
94+
95+ const rowValue = rowData . name ;
96+
97+ if ( headerValue . length == 1 && headerValue != "^" && headerValue != "/" ) {
98+ // single character, do starts with
99+ const search = headerValue . toLowerCase ( ) ;
100+ return rowValue . toLowerCase ( ) . startsWith ( search ) ;
101+ }
102+
103+ if ( headerValue . startsWith ( "^" ) ) {
104+ // starts with
105+ if ( headerValue . length == 1 ) {
106+ return true ;
107+ }
108+ const search = headerValue . substring ( 1 ) . toLowerCase ( ) ;
109+ return rowValue . toLowerCase ( ) . startsWith ( search ) ;
110+ }
111+
112+ if ( headerValue . startsWith ( "/" ) && headerValue . endsWith ( "/" ) ) {
113+ // regex
114+ const pattern = headerValue . substring ( 1 , headerValue . length - 1 ) ;
115+ try {
116+ const re = new RegExp ( pattern , "i" ) ;
117+ return re . test ( rowValue ) ;
118+ } catch ( e ) {
119+ // bad regex
120+ return false ;
121+ }
122+ }
123+
124+ // contains
125+ const search = headerValue . toLowerCase ( ) ;
126+ return rowValue . toLowerCase ( ) . includes ( search ) ;
127+ }
128+
35129function fmtCategory ( cell : CellComponent ) {
36130 const val = cell . getValue ( ) as string ;
131+ if ( ! val ) {
132+ return "(missing)" ;
133+ }
134+ return categoryMap [ val ] || val ;
37135}
38136
39137function fmtCodepoint ( cell : CellComponent ) {
@@ -156,47 +254,7 @@ function makeTagMap(row: any, socialmedia: SocialMedia[]): Map<string, string> {
156254 return tagMap ;
157255}
158256
159- function nameFilter (
160- headerValue : string ,
161- sortValue : string ,
162- rowData : any ,
163- filterParams : any
164- ) {
165- if ( ! headerValue ) return true ;
166-
167- const rowValue = rowData . name ;
168-
169- if ( headerValue . length == 1 && headerValue != "^" && headerValue != "/" ) {
170- // single character, do starts with
171- const search = headerValue . toLowerCase ( ) ;
172- return rowValue . toLowerCase ( ) . startsWith ( search ) ;
173- }
174-
175- if ( headerValue . startsWith ( "^" ) ) {
176- // starts with
177- if ( headerValue . length == 1 ) {
178- return true ;
179- }
180- const search = headerValue . substring ( 1 ) . toLowerCase ( ) ;
181- return rowValue . toLowerCase ( ) . startsWith ( search ) ;
182- }
183-
184- if ( headerValue . startsWith ( "/" ) && headerValue . endsWith ( "/" ) ) {
185- // regex
186- const pattern = headerValue . substring ( 1 , headerValue . length - 1 ) ;
187- try {
188- const re = new RegExp ( pattern , "i" ) ;
189- return re . test ( rowValue ) ;
190- } catch ( e ) {
191- // bad regex
192- return false ;
193- }
194- }
195257
196- // contains
197- const search = headerValue . toLowerCase ( ) ;
198- return rowValue . toLowerCase ( ) . includes ( search ) ;
199- }
200258
201259async function main ( ) {
202260 let data : SearchEntry [ ] ;
@@ -282,12 +340,14 @@ async function main() {
282340 } ,
283341 {
284342 field : "category" ,
343+ formatter : fmtCategory ,
285344 headerFilter : "input" ,
345+ headerFilterFunc : filterCategory ,
286346 headerHozAlign : "center" ,
287347 hozAlign : "center" ,
288348 responsive : 2 ,
289349 title : "Category" ,
290- width : 175 ,
350+ width : 200 ,
291351 } ,
292352 {
293353 field : "age" ,
@@ -312,7 +372,7 @@ async function main() {
312372 target : "_blank" ,
313373 } ,
314374 headerFilter : "input" ,
315- headerFilterFunc : nameFilter ,
375+ headerFilterFunc : filterName ,
316376 responsive : 0 ,
317377 //sorter: "string",
318378 width : 375 ,
0 commit comments