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