-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
125 lines (100 loc) · 3.11 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
const betaCodeToUnicode = require('./vendor/beta-code-json/beta_code_to_unicode.json');
const unicodeToBetaCode = require('./vendor/beta-code-json/unicode_to_beta_code.json');
function longestKeyLength(obj) {
const keys = Object.keys(obj);
let ii;
let key;
let length = 0;
for (ii = 0; ii < keys.length; ii += 1) {
key = keys[ii];
if (Object.prototype.hasOwnProperty.call(obj, key)) {
if (key.length > length) {
length = key.length;
}
}
}
return length;
}
// this function replaces σ with ς when:
// - at the end of a line
// - followed by whitespace
// - followed by a punctuation character
// REGEX NOTE: word boundary \b doesn't work well with Unicode
function sigmaToEndOfWordSigma(string) {
return string.replace(/σ(?=[,.:;·\s]|$)/g, 'ς');
}
function min(a, b) {
return a < b ? a : b;
}
function normalize(string) {
if (string.normalize) {
return string.normalize();
}
return string;
}
function mergeObjects(obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
const retObj = {};
let key;
let ii;
for (ii = 0; ii < keys1.length; ii += 1) {
key = keys1[ii];
retObj[key] = obj1[key];
}
for (ii = 0; ii < keys2.length; ii += 1) {
key = keys2[ii];
retObj[key] = obj2[key];
}
return retObj;
}
function greekToBetaCode(greek, customMap) {
const greekCharacters = normalize(greek).split('');
const betaCodeCharacters = [];
const map = mergeObjects(unicodeToBetaCode, customMap || {});
let currentCharacter;
let ii;
for (ii = 0; ii < greekCharacters.length; ii += 1) {
currentCharacter = greekCharacters[ii];
if (Object.prototype.hasOwnProperty.call(map, currentCharacter)) {
betaCodeCharacters.push(map[currentCharacter]);
} else {
betaCodeCharacters.push(currentCharacter);
}
}
return betaCodeCharacters.join('');
}
function betaCodeToGreek(betaCode, customMap) {
const betaCodeCharacters = normalize(betaCode).split('');
const greekCharacters = [];
const map = mergeObjects(betaCodeToUnicode, customMap || {});
const maxBetaCodeCharacterLength = longestKeyLength(map);
let start = 0;
let end;
let slice;
let newStart;
let currentCharacter;
let maxLength;
while (start <= betaCodeCharacters.length) {
currentCharacter = betaCodeCharacters[start];
newStart = start + 1;
maxLength = min(betaCodeCharacters.length, start + maxBetaCodeCharacterLength);
// match the longest possible substring that's valid Beta Code, from left to right
// for example 'e)' is valid Beta Code (ἐ) but 'e)/' is also valid Beta Code (ἕ)
// the string 'e)/' should be interpreted as 'e)/' and not as 'e)' + '/'
for (end = newStart; end <= maxLength; end += 1) {
slice = betaCodeCharacters.slice(start, end).join('');
if (Object.prototype.hasOwnProperty.call(map, slice)) {
currentCharacter = map[slice];
newStart = end;
}
}
greekCharacters.push(currentCharacter);
start = newStart;
}
return sigmaToEndOfWordSigma(greekCharacters.join(''));
}
module.exports = {
greekToBetaCode,
betaCodeToGreek,
};