File Coverage

blib/lib/Unicode/Diacritic/Strip.pm
Criterion Covered Total %
statement 63 67 94.0
branch 16 20 80.0
condition 1 3 33.3
subroutine 9 9 100.0
pod 3 4 75.0
total 92 103 89.3


line stmt bran cond sub pod time code
1             package Unicode::Diacritic::Strip;
2 5     5   347707 use warnings;
  5         48  
  5         169  
3 5     5   28 use strict;
  5         10  
  5         126  
4 5     5   2105 use utf8;
  5         54  
  5         46  
5             require Exporter;
6 5     5   219 use base qw(Exporter);
  5         11  
  5         1104  
7             our @EXPORT_OK = qw/strip_diacritics strip_alphabet fast_strip/;
8             our %EXPORT_TAGS = (all => \@EXPORT_OK);
9             our $VERSION = '0.14';
10 5     5   5195 use Unicode::UCD 'charinfo';
  5         264248  
  5         8081  
11              
12             sub strip_diacritics
13             {
14 3     3 1 13061 my ($diacritics_text) = @_;
15 3 100       23 if ($diacritics_text !~ /[^\x{01}-\x{80}]/) {
16             # All the characters in this text are ASCII, and so there are
17             # no diacritics.
18 1         4 return $diacritics_text;
19             }
20 2         17 my @characters = split //, $diacritics_text;
21 2         8 for my $character (@characters) {
22             # Leave non-word characters unaltered.
23 34 100       147 if ($character =~ /\W/) {
24 1         2 next;
25             }
26 33         72 my $decomposed = decompose ($character);
27 33 100       101 if ($character ne $decomposed) {
28 28         63 $character = $decomposed;
29             }
30             }
31 2         21 my $stripped_text = join '', @characters;
32 2         16 return $stripped_text;
33             }
34              
35             sub decompose
36             {
37 109     109 0 211 my ($character) = @_;
38             # Get the Unicode::UCD decomposition.
39 109         282 my $charinfo = charinfo (ord $character);
40 109         844548 my $decomposition = $charinfo->{decomposition};
41             # Give up if there is no decomposition for $character
42 109 100       270 if (! $decomposition) {
43 71         402 return $character;
44             }
45             # Get the first character of the decomposition
46 38         186 my @dc = split /\s+/, $decomposition;
47             # Remove etc.
48 38 50       116 if ($dc[0] =~ /
49 0         0 print "$character $decomposition\n";
50             }
51 38         169 @dc = grep !/<.*?>/, @dc;
52 38         102 $character = chr hex $dc[0];
53             # A character may have multiple decompositions, so repeat this
54             # process until there are none left.
55 38         98 return decompose ($character);
56             }
57              
58             sub strip_alphabet
59             {
60 1     1 1 11873 my ($diacritics_text, %options) = @_;
61 1         3 my %swaps;
62 1 50 33     13 if (! defined $diacritics_text || length ($diacritics_text) == 0) {
63 0         0 return ($diacritics_text, {});
64             }
65 1         40 my @characters = split //, $diacritics_text;
66 1         4 my %alphabet;
67 1         3 for my $c (@characters) {
68 295         479 $alphabet{$c} = 1;
69             }
70 1         12 my @c = keys %alphabet;
71              
72 1         4 for my $character (@c) {
73             # Reject non-word characters
74 44 100       172 if ($character !~ /\w/) {
75 6 50       22 if ($options{verbose}) {
76 0         0 print "Not altering non-word character '$character'.\n";
77             }
78 6         16 next;
79             }
80 38         94 my $decomposed = decompose ($character, %options);
81 38 100       113 if ($character ne $decomposed) {
82 8         19 my $boo = "$decomposed baba";
83 8         26 $swaps{$character} = $boo;
84 8         44 $swaps{$character} =~ s/ baba$//;
85             }
86             }
87              
88             # Make the version of the text with all the diacritics removed.
89              
90 1         2 my $stripped_text = $diacritics_text;
91 1         7 for my $k (keys %swaps) {
92 8 50       22 if ($options{verbose}) {
93 0         0 printf "Swapping $k for $swaps{$k} (%X).\n", ord ($swaps{$k});
94             }
95 8         105 $stripped_text =~ s/$k/$swaps{$k}/g;
96             }
97 1         77 return ($stripped_text, \%swaps);
98             }
99              
100             my %strip = (
101             'À' => 'A',
102             'Á' => 'A',
103             'Â' => 'A',
104             'Ã' => 'A',
105             'Ä' => 'A',
106             'Å' => 'A',
107             'Ç' => 'C',
108             'È' => 'E',
109             'É' => 'E',
110             'Ê' => 'E',
111             'Ë' => 'E',
112             'Ì' => 'I',
113             'Í' => 'I',
114             'Î' => 'I',
115             'Ï' => 'I',
116             'Ñ' => 'N',
117             'Ò' => 'O',
118             'Ó' => 'O',
119             'Ô' => 'O',
120             'Õ' => 'O',
121             'Ö' => 'O',
122             'Ø' => 'O',
123             'Ù' => 'U',
124             'Ú' => 'U',
125             'Û' => 'U',
126             'Ü' => 'U',
127             'Ý' => 'Y',
128             'à' => 'a',
129             'á' => 'a',
130             'â' => 'a',
131             'ã' => 'a',
132             'ä' => 'a',
133             'å' => 'a',
134             'ç' => 'c',
135             'è' => 'e',
136             'é' => 'e',
137             'ê' => 'e',
138             'ë' => 'e',
139             'ì' => 'i',
140             'í' => 'i',
141             'î' => 'i',
142             'ï' => 'i',
143             'ñ' => 'n',
144             'ò' => 'o',
145             'ó' => 'o',
146             'ô' => 'o',
147             'õ' => 'o',
148             'ö' => 'o',
149             'ø' => 'o',
150             'ù' => 'u',
151             'ú' => 'u',
152             'û' => 'u',
153             'ü' => 'u',
154             'ý' => 'y',
155             'ÿ' => 'y',
156             'Ā' => 'A',
157             'ā' => 'a',
158             'Ă' => 'A',
159             'ă' => 'a',
160             'Ą' => 'A',
161             'ą' => 'a',
162             'Ć' => 'C',
163             'ć' => 'c',
164             'Ĉ' => 'C',
165             'ĉ' => 'c',
166             'Ċ' => 'C',
167             'ċ' => 'c',
168             'Č' => 'C',
169             'č' => 'c',
170             'Ď' => 'D',
171             'ď' => 'd',
172             'Ē' => 'E',
173             'ē' => 'e',
174             'Ĕ' => 'E',
175             'ĕ' => 'e',
176             'Ė' => 'E',
177             'ė' => 'e',
178             'Ę' => 'E',
179             'ę' => 'e',
180             'Ě' => 'E',
181             'ě' => 'e',
182             'Ĝ' => 'G',
183             'ĝ' => 'g',
184             'Ğ' => 'G',
185             'ğ' => 'g',
186             'Ġ' => 'G',
187             'ġ' => 'g',
188             'Ģ' => 'G',
189             'ģ' => 'g',
190             'Ĥ' => 'H',
191             'ĥ' => 'h',
192             'Ĩ' => 'I',
193             'ĩ' => 'i',
194             'Ī' => 'I',
195             'ī' => 'i',
196             'Ĭ' => 'I',
197             'ĭ' => 'i',
198             'Į' => 'I',
199             'į' => 'i',
200             'İ' => 'I',
201             'Ĵ' => 'J',
202             'ĵ' => 'j',
203             'Ķ' => 'K',
204             'ķ' => 'k',
205             'Ĺ' => 'L',
206             'ĺ' => 'l',
207             'Ļ' => 'L',
208             'ļ' => 'l',
209             'Ľ' => 'L',
210             'ľ' => 'l',
211             'Ł' => 'L',
212             'ł' => 'l',
213             'Ń' => 'N',
214             'ń' => 'n',
215             'Ņ' => 'N',
216             'ņ' => 'n',
217             'Ň' => 'N',
218             'ň' => 'n',
219             'Ō' => 'O',
220             'ō' => 'o',
221             'Ŏ' => 'O',
222             'ŏ' => 'o',
223             'Ő' => 'O',
224             'ő' => 'o',
225             'Ŕ' => 'R',
226             'ŕ' => 'r',
227             'Ŗ' => 'R',
228             'ŗ' => 'r',
229             'Ř' => 'R',
230             'ř' => 'r',
231             'Ś' => 'S',
232             'ś' => 's',
233             'Ŝ' => 'S',
234             'ŝ' => 's',
235             'Ş' => 'S',
236             'ş' => 's',
237             'Š' => 'S',
238             'š' => 's',
239             'Ţ' => 'T',
240             'ţ' => 't',
241             'Ť' => 'T',
242             'ť' => 't',
243             'Ũ' => 'U',
244             'ũ' => 'u',
245             'Ū' => 'U',
246             'ū' => 'u',
247             'Ŭ' => 'U',
248             'ŭ' => 'u',
249             'Ů' => 'U',
250             'ů' => 'u',
251             'Ű' => 'U',
252             'ű' => 'u',
253             'Ų' => 'U',
254             'ų' => 'u',
255             'Ŵ' => 'W',
256             'ŵ' => 'w',
257             'Ŷ' => 'Y',
258             'ŷ' => 'y',
259             'Ÿ' => 'Y',
260             'Ź' => 'Z',
261             'ź' => 'z',
262             'Ż' => 'Z',
263             'ż' => 'z',
264             'Ž' => 'Z',
265             'ž' => 'z',
266             'Ơ' => 'O',
267             'ơ' => 'o',
268             'Ư' => 'U',
269             'ư' => 'u',
270             'Ǎ' => 'A',
271             'ǎ' => 'a',
272             'Ǐ' => 'I',
273             'ǐ' => 'i',
274             'Ǒ' => 'O',
275             'ǒ' => 'o',
276             'Ǔ' => 'U',
277             'ǔ' => 'u',
278             'Ǖ' => 'U',
279             'ǖ' => 'u',
280             'Ǘ' => 'U',
281             'ǘ' => 'u',
282             'Ǚ' => 'U',
283             'ǚ' => 'u',
284             'Ǜ' => 'U',
285             'ǜ' => 'u',
286             'Ǟ' => 'A',
287             'ǟ' => 'a',
288             'Ǡ' => 'A',
289             'ǡ' => 'a',
290             'Ǧ' => 'G',
291             'ǧ' => 'g',
292             'Ǩ' => 'K',
293             'ǩ' => 'k',
294             'Ǫ' => 'O',
295             'ǫ' => 'o',
296             'Ǭ' => 'O',
297             'ǭ' => 'o',
298             'ǰ' => 'j',
299             'Ǵ' => 'G',
300             'ǵ' => 'g',
301             'Ǹ' => 'N',
302             'ǹ' => 'n',
303             'Ǻ' => 'A',
304             'ǻ' => 'a',
305             'Ȁ' => 'A',
306             'ȁ' => 'a',
307             'Ȃ' => 'A',
308             'ȃ' => 'a',
309             'Ȅ' => 'E',
310             'ȅ' => 'e',
311             'Ȇ' => 'E',
312             'ȇ' => 'e',
313             'Ȉ' => 'I',
314             'ȉ' => 'i',
315             'Ȋ' => 'I',
316             'ȋ' => 'i',
317             'Ȍ' => 'O',
318             'ȍ' => 'o',
319             'Ȏ' => 'O',
320             'ȏ' => 'o',
321             'Ȑ' => 'R',
322             'ȑ' => 'r',
323             'Ȓ' => 'R',
324             'ȓ' => 'r',
325             'Ȕ' => 'U',
326             'ȕ' => 'u',
327             'Ȗ' => 'U',
328             'ȗ' => 'u',
329             'Ș' => 'S',
330             'ș' => 's',
331             'Ț' => 'T',
332             'ț' => 't',
333             'Ȟ' => 'H',
334             'ȟ' => 'h',
335             'Ȧ' => 'A',
336             'ȧ' => 'a',
337             'Ȩ' => 'E',
338             'ȩ' => 'e',
339             'Ȫ' => 'O',
340             'ȫ' => 'o',
341             'Ȭ' => 'O',
342             'ȭ' => 'o',
343             'Ȯ' => 'O',
344             'ȯ' => 'o',
345             'Ȱ' => 'O',
346             'ȱ' => 'o',
347             'Ȳ' => 'Y',
348             'ȳ' => 'y',
349             'Ḁ' => 'A',
350             'ḁ' => 'a',
351             'Ḃ' => 'B',
352             'ḃ' => 'b',
353             'Ḅ' => 'B',
354             'ḅ' => 'b',
355             'Ḇ' => 'B',
356             'ḇ' => 'b',
357             'Ḉ' => 'C',
358             'ḉ' => 'c',
359             'Ḋ' => 'D',
360             'ḋ' => 'd',
361             'Ḍ' => 'D',
362             'ḍ' => 'd',
363             'Ḏ' => 'D',
364             'ḏ' => 'd',
365             'Ḑ' => 'D',
366             'ḑ' => 'd',
367             'Ḓ' => 'D',
368             'ḓ' => 'd',
369             'Ḕ' => 'E',
370             'ḕ' => 'e',
371             'Ḗ' => 'E',
372             'ḗ' => 'e',
373             'Ḙ' => 'E',
374             'ḙ' => 'e',
375             'Ḛ' => 'E',
376             'ḛ' => 'e',
377             'Ḝ' => 'E',
378             'ḝ' => 'e',
379             'Ḟ' => 'F',
380             'ḟ' => 'f',
381             'Ḡ' => 'G',
382             'ḡ' => 'g',
383             'Ḣ' => 'H',
384             'ḣ' => 'h',
385             'Ḥ' => 'H',
386             'ḥ' => 'h',
387             'Ḧ' => 'H',
388             'ḧ' => 'h',
389             'Ḩ' => 'H',
390             'ḩ' => 'h',
391             'Ḫ' => 'H',
392             'ḫ' => 'h',
393             'Ḭ' => 'I',
394             'ḭ' => 'i',
395             'Ḯ' => 'I',
396             'ḯ' => 'i',
397             'Ḱ' => 'K',
398             'ḱ' => 'k',
399             'Ḳ' => 'K',
400             'ḳ' => 'k',
401             'Ḵ' => 'K',
402             'ḵ' => 'k',
403             'Ḷ' => 'L',
404             'ḷ' => 'l',
405             'Ḹ' => 'L',
406             'ḹ' => 'l',
407             'Ḻ' => 'L',
408             'ḻ' => 'l',
409             'Ḽ' => 'L',
410             'ḽ' => 'l',
411             'Ḿ' => 'M',
412             'ḿ' => 'm',
413             'Ṁ' => 'M',
414             'ṁ' => 'm',
415             'Ṃ' => 'M',
416             'ṃ' => 'm',
417             'Ṅ' => 'N',
418             'ṅ' => 'n',
419             'Ṇ' => 'N',
420             'ṇ' => 'n',
421             'Ṉ' => 'N',
422             'ṉ' => 'n',
423             'Ṋ' => 'N',
424             'ṋ' => 'n',
425             'Ṍ' => 'O',
426             'ṍ' => 'o',
427             'Ṏ' => 'O',
428             'ṏ' => 'o',
429             'Ṑ' => 'O',
430             'ṑ' => 'o',
431             'Ṓ' => 'O',
432             'ṓ' => 'o',
433             'Ṕ' => 'P',
434             'ṕ' => 'p',
435             'Ṗ' => 'P',
436             'ṗ' => 'p',
437             'Ṙ' => 'R',
438             'ṙ' => 'r',
439             'Ṛ' => 'R',
440             'ṛ' => 'r',
441             'Ṝ' => 'R',
442             'ṝ' => 'r',
443             'Ṟ' => 'R',
444             'ṟ' => 'r',
445             'Ṡ' => 'S',
446             'ṡ' => 's',
447             'Ṣ' => 'S',
448             'ṣ' => 's',
449             'Ṥ' => 'S',
450             'ṥ' => 's',
451             'Ṧ' => 'S',
452             'ṧ' => 's',
453             'Ṩ' => 'S',
454             'ṩ' => 's',
455             'Ṫ' => 'T',
456             'ṫ' => 't',
457             'Ṭ' => 'T',
458             'ṭ' => 't',
459             'Ṯ' => 'T',
460             'ṯ' => 't',
461             'Ṱ' => 'T',
462             'ṱ' => 't',
463             'Ṳ' => 'U',
464             'ṳ' => 'u',
465             'Ṵ' => 'U',
466             'ṵ' => 'u',
467             'Ṷ' => 'U',
468             'ṷ' => 'u',
469             'Ṹ' => 'U',
470             'ṹ' => 'u',
471             'Ṻ' => 'U',
472             'ṻ' => 'u',
473             'Ṽ' => 'V',
474             'ṽ' => 'v',
475             'Ṿ' => 'V',
476             'ṿ' => 'v',
477             'Ẁ' => 'W',
478             'ẁ' => 'w',
479             'Ẃ' => 'W',
480             'ẃ' => 'w',
481             'Ẅ' => 'W',
482             'ẅ' => 'w',
483             'Ẇ' => 'W',
484             'ẇ' => 'w',
485             'Ẉ' => 'W',
486             'ẉ' => 'w',
487             'Ẋ' => 'X',
488             'ẋ' => 'x',
489             'Ẍ' => 'X',
490             'ẍ' => 'x',
491             'Ẏ' => 'Y',
492             'ẏ' => 'y',
493             'Ẑ' => 'Z',
494             'ẑ' => 'z',
495             'Ẓ' => 'Z',
496             'ẓ' => 'z',
497             'Ẕ' => 'Z',
498             'ẕ' => 'z',
499             'ẖ' => 'h',
500             'ẗ' => 't',
501             'ẘ' => 'w',
502             'ẙ' => 'y',
503             'ẚ' => 'a',
504             'ẛ' => 'f',
505             'ẜ' => 'f',
506             'ẝ' => 'f',
507             'Ạ' => 'A',
508             'ạ' => 'a',
509             'Ả' => 'A',
510             'ả' => 'a',
511             'Ấ' => 'A',
512             'ấ' => 'a',
513             'Ầ' => 'A',
514             'ầ' => 'a',
515             'Ẩ' => 'A',
516             'ẩ' => 'a',
517             'Ẫ' => 'A',
518             'ẫ' => 'a',
519             'Ậ' => 'A',
520             'ậ' => 'a',
521             'Ắ' => 'A',
522             'ắ' => 'a',
523             'Ằ' => 'A',
524             'ằ' => 'a',
525             'Ẳ' => 'A',
526             'ẳ' => 'a',
527             'Ẵ' => 'A',
528             'ẵ' => 'a',
529             'Ặ' => 'A',
530             'ặ' => 'a',
531             'Ẹ' => 'E',
532             'ẹ' => 'e',
533             'Ẻ' => 'E',
534             'ẻ' => 'e',
535             'Ẽ' => 'E',
536             'ẽ' => 'e',
537             'Ế' => 'E',
538             'ế' => 'e',
539             'Ề' => 'E',
540             'ề' => 'e',
541             'Ể' => 'E',
542             'ể' => 'e',
543             'Ễ' => 'E',
544             'ễ' => 'e',
545             'Ệ' => 'E',
546             'ệ' => 'e',
547             'Ỉ' => 'I',
548             'ỉ' => 'i',
549             'Ị' => 'I',
550             'ị' => 'i',
551             'Ọ' => 'O',
552             'ọ' => 'o',
553             'Ỏ' => 'O',
554             'ỏ' => 'o',
555             'Ố' => 'O',
556             'ố' => 'o',
557             'Ồ' => 'O',
558             'ồ' => 'o',
559             'Ổ' => 'O',
560             'ổ' => 'o',
561             'Ỗ' => 'O',
562             'ỗ' => 'o',
563             'Ộ' => 'O',
564             'ộ' => 'o',
565             'Ớ' => 'O',
566             'ớ' => 'o',
567             'Ờ' => 'O',
568             'ờ' => 'o',
569             'Ở' => 'O',
570             'ở' => 'o',
571             'Ỡ' => 'O',
572             'ỡ' => 'o',
573             'Ợ' => 'O',
574             'ợ' => 'o',
575             'Ụ' => 'O',
576             'ụ' => 'o',
577             'Ủ' => 'U',
578             'ủ' => 'u',
579             'Ứ' => 'U',
580             'ứ' => 'u',
581             'Ừ' => 'U',
582             'ừ' => 'u',
583             'Ử' => 'U',
584             'ử' => 'u',
585             'Ữ' => 'U',
586             'ữ' => 'u',
587             'Ự' => 'U',
588             'ự' => 'u',
589             'Ỳ' => 'Y',
590             'ỳ' => 'y',
591             'Ỵ' => 'Y',
592             'ỵ' => 'y',
593             'Ỷ' => 'Y',
594             'ỷ' => 'y',
595             'Ỹ' => 'Y',
596             'ỹ' => 'y',
597             # Various ligatures
598             'Œ' => 'OE',
599             'œ' => 'oe',
600             'ƕ' => 'hv',
601             'DŽ' => 'DZ',
602             'Dž' => 'Dz',
603             'dž' => 'dz',
604             'LJ' => 'LJ',
605             'Lj' => 'Lj',
606             'lj' => 'lj',
607             'NJ' => 'NJ',
608             'Nj' => 'Nj',
609             'nj' => 'nj',
610             'Ǣ' => 'AE',
611             'ǣ' => 'ae',
612             'DZ' => 'DZ',
613             'Dz' => 'Dz',
614             'dz' => 'dz',
615             'Ǽ' => 'AE',
616             'ǽ' => 'ae',
617             # Thorn
618             'Þ' => 'Th',
619             'þ' => 'th',
620             );
621              
622             my $strip_keys = join '', keys %strip;
623              
624             sub fast_strip
625             {
626 250     250 1 162668 my ($word) = @_;
627             # Remove all diacritics
628 250         3897 $word =~ s/([$strip_keys])/$strip{$1}/g;
629 250         718 $word =~ s/\p{InCombiningDiacriticalMarks}//g;
630 250         848 return $word;
631             }
632              
633             1;