1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | "use strict";
|
23 |
|
24 | Object.defineProperty(exports, "__esModule", {
|
25 | value: true
|
26 | });
|
27 | exports.bidi = bidi;
|
28 |
|
29 | var _util = require("../shared/util");
|
30 |
|
31 | var baseTypes = ['BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS', 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'ON', 'ES', 'CS', 'ES', 'CS', 'CS', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'CS', 'ON', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON', 'ON', 'BN', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON', 'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'];
|
32 | var arabicTypes = ['AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'ON', 'ON', 'AL', 'ET', 'ET', 'AL', 'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', '', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AN', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'NSM', 'NSM', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'];
|
33 |
|
34 | function isOdd(i) {
|
35 | return (i & 1) !== 0;
|
36 | }
|
37 |
|
38 | function isEven(i) {
|
39 | return (i & 1) === 0;
|
40 | }
|
41 |
|
42 | function findUnequal(arr, start, value) {
|
43 | for (var j = start, jj = arr.length; j < jj; ++j) {
|
44 | if (arr[j] !== value) {
|
45 | return j;
|
46 | }
|
47 | }
|
48 |
|
49 | return j;
|
50 | }
|
51 |
|
52 | function setValues(arr, start, end, value) {
|
53 | for (var j = start; j < end; ++j) {
|
54 | arr[j] = value;
|
55 | }
|
56 | }
|
57 |
|
58 | function reverseValues(arr, start, end) {
|
59 | for (var i = start, j = end - 1; i < j; ++i, --j) {
|
60 | var temp = arr[i];
|
61 | arr[i] = arr[j];
|
62 | arr[j] = temp;
|
63 | }
|
64 | }
|
65 |
|
66 | function createBidiText(str, isLTR, vertical) {
|
67 | return {
|
68 | str: str,
|
69 | dir: vertical ? 'ttb' : isLTR ? 'ltr' : 'rtl'
|
70 | };
|
71 | }
|
72 |
|
73 | var chars = [];
|
74 | var types = [];
|
75 |
|
76 | function bidi(str, startLevel, vertical) {
|
77 | var isLTR = true;
|
78 | var strLength = str.length;
|
79 |
|
80 | if (strLength === 0 || vertical) {
|
81 | return createBidiText(str, isLTR, vertical);
|
82 | }
|
83 |
|
84 | chars.length = strLength;
|
85 | types.length = strLength;
|
86 | var numBidi = 0;
|
87 | var i, ii;
|
88 |
|
89 | for (i = 0; i < strLength; ++i) {
|
90 | chars[i] = str.charAt(i);
|
91 | var charCode = str.charCodeAt(i);
|
92 | var charType = 'L';
|
93 |
|
94 | if (charCode <= 0x00ff) {
|
95 | charType = baseTypes[charCode];
|
96 | } else if (0x0590 <= charCode && charCode <= 0x05f4) {
|
97 | charType = 'R';
|
98 | } else if (0x0600 <= charCode && charCode <= 0x06ff) {
|
99 | charType = arabicTypes[charCode & 0xff];
|
100 |
|
101 | if (!charType) {
|
102 | (0, _util.warn)('Bidi: invalid Unicode character ' + charCode.toString(16));
|
103 | }
|
104 | } else if (0x0700 <= charCode && charCode <= 0x08AC) {
|
105 | charType = 'AL';
|
106 | }
|
107 |
|
108 | if (charType === 'R' || charType === 'AL' || charType === 'AN') {
|
109 | numBidi++;
|
110 | }
|
111 |
|
112 | types[i] = charType;
|
113 | }
|
114 |
|
115 | if (numBidi === 0) {
|
116 | isLTR = true;
|
117 | return createBidiText(str, isLTR);
|
118 | }
|
119 |
|
120 | if (startLevel === -1) {
|
121 | if (numBidi / strLength < 0.3) {
|
122 | isLTR = true;
|
123 | startLevel = 0;
|
124 | } else {
|
125 | isLTR = false;
|
126 | startLevel = 1;
|
127 | }
|
128 | }
|
129 |
|
130 | var levels = [];
|
131 |
|
132 | for (i = 0; i < strLength; ++i) {
|
133 | levels[i] = startLevel;
|
134 | }
|
135 |
|
136 | var e = isOdd(startLevel) ? 'R' : 'L';
|
137 | var sor = e;
|
138 | var eor = sor;
|
139 | var lastType = sor;
|
140 |
|
141 | for (i = 0; i < strLength; ++i) {
|
142 | if (types[i] === 'NSM') {
|
143 | types[i] = lastType;
|
144 | } else {
|
145 | lastType = types[i];
|
146 | }
|
147 | }
|
148 |
|
149 | lastType = sor;
|
150 | var t;
|
151 |
|
152 | for (i = 0; i < strLength; ++i) {
|
153 | t = types[i];
|
154 |
|
155 | if (t === 'EN') {
|
156 | types[i] = lastType === 'AL' ? 'AN' : 'EN';
|
157 | } else if (t === 'R' || t === 'L' || t === 'AL') {
|
158 | lastType = t;
|
159 | }
|
160 | }
|
161 |
|
162 | for (i = 0; i < strLength; ++i) {
|
163 | t = types[i];
|
164 |
|
165 | if (t === 'AL') {
|
166 | types[i] = 'R';
|
167 | }
|
168 | }
|
169 |
|
170 | for (i = 1; i < strLength - 1; ++i) {
|
171 | if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') {
|
172 | types[i] = 'EN';
|
173 | }
|
174 |
|
175 | if (types[i] === 'CS' && (types[i - 1] === 'EN' || types[i - 1] === 'AN') && types[i + 1] === types[i - 1]) {
|
176 | types[i] = types[i - 1];
|
177 | }
|
178 | }
|
179 |
|
180 | for (i = 0; i < strLength; ++i) {
|
181 | if (types[i] === 'EN') {
|
182 | var j;
|
183 |
|
184 | for (j = i - 1; j >= 0; --j) {
|
185 | if (types[j] !== 'ET') {
|
186 | break;
|
187 | }
|
188 |
|
189 | types[j] = 'EN';
|
190 | }
|
191 |
|
192 | for (j = i + 1; j < strLength; ++j) {
|
193 | if (types[j] !== 'ET') {
|
194 | break;
|
195 | }
|
196 |
|
197 | types[j] = 'EN';
|
198 | }
|
199 | }
|
200 | }
|
201 |
|
202 | for (i = 0; i < strLength; ++i) {
|
203 | t = types[i];
|
204 |
|
205 | if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') {
|
206 | types[i] = 'ON';
|
207 | }
|
208 | }
|
209 |
|
210 | lastType = sor;
|
211 |
|
212 | for (i = 0; i < strLength; ++i) {
|
213 | t = types[i];
|
214 |
|
215 | if (t === 'EN') {
|
216 | types[i] = lastType === 'L' ? 'L' : 'EN';
|
217 | } else if (t === 'R' || t === 'L') {
|
218 | lastType = t;
|
219 | }
|
220 | }
|
221 |
|
222 | for (i = 0; i < strLength; ++i) {
|
223 | if (types[i] === 'ON') {
|
224 | var end = findUnequal(types, i + 1, 'ON');
|
225 | var before = sor;
|
226 |
|
227 | if (i > 0) {
|
228 | before = types[i - 1];
|
229 | }
|
230 |
|
231 | var after = eor;
|
232 |
|
233 | if (end + 1 < strLength) {
|
234 | after = types[end + 1];
|
235 | }
|
236 |
|
237 | if (before !== 'L') {
|
238 | before = 'R';
|
239 | }
|
240 |
|
241 | if (after !== 'L') {
|
242 | after = 'R';
|
243 | }
|
244 |
|
245 | if (before === after) {
|
246 | setValues(types, i, end, before);
|
247 | }
|
248 |
|
249 | i = end - 1;
|
250 | }
|
251 | }
|
252 |
|
253 | for (i = 0; i < strLength; ++i) {
|
254 | if (types[i] === 'ON') {
|
255 | types[i] = e;
|
256 | }
|
257 | }
|
258 |
|
259 | for (i = 0; i < strLength; ++i) {
|
260 | t = types[i];
|
261 |
|
262 | if (isEven(levels[i])) {
|
263 | if (t === 'R') {
|
264 | levels[i] += 1;
|
265 | } else if (t === 'AN' || t === 'EN') {
|
266 | levels[i] += 2;
|
267 | }
|
268 | } else {
|
269 | if (t === 'L' || t === 'AN' || t === 'EN') {
|
270 | levels[i] += 1;
|
271 | }
|
272 | }
|
273 | }
|
274 |
|
275 | var highestLevel = -1;
|
276 | var lowestOddLevel = 99;
|
277 | var level;
|
278 |
|
279 | for (i = 0, ii = levels.length; i < ii; ++i) {
|
280 | level = levels[i];
|
281 |
|
282 | if (highestLevel < level) {
|
283 | highestLevel = level;
|
284 | }
|
285 |
|
286 | if (lowestOddLevel > level && isOdd(level)) {
|
287 | lowestOddLevel = level;
|
288 | }
|
289 | }
|
290 |
|
291 | for (level = highestLevel; level >= lowestOddLevel; --level) {
|
292 | var start = -1;
|
293 |
|
294 | for (i = 0, ii = levels.length; i < ii; ++i) {
|
295 | if (levels[i] < level) {
|
296 | if (start >= 0) {
|
297 | reverseValues(chars, start, i);
|
298 | start = -1;
|
299 | }
|
300 | } else if (start < 0) {
|
301 | start = i;
|
302 | }
|
303 | }
|
304 |
|
305 | if (start >= 0) {
|
306 | reverseValues(chars, start, levels.length);
|
307 | }
|
308 | }
|
309 |
|
310 | for (i = 0, ii = chars.length; i < ii; ++i) {
|
311 | var ch = chars[i];
|
312 |
|
313 | if (ch === '<' || ch === '>') {
|
314 | chars[i] = '';
|
315 | }
|
316 | }
|
317 |
|
318 | return createBidiText(chars.join(''), isLTR);
|
319 | } |
\ | No newline at end of file |