File Coverage

blib/lib/Unicode/Diacritic/Strip.pm
Criterion Covered Total %
statement 63 66 95.4
branch 15 18 83.3
condition 1 3 33.3
subroutine 9 9 100.0
pod 3 4 75.0
total 91 100 91.0


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