rapydscript-ng 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +8 -0
- package/bin/build.ts +117 -0
- package/build_wheels.py +133 -0
- package/editor-plugins/README.md +80 -0
- package/editor-plugins/nvim.lua +321 -0
- package/package.json +1 -1
- package/publish.py +27 -17
- package/release/compiler.js +8125 -8093
- package/release/signatures.json +27 -27
- package/release/stdlib_modules.json +1 -0
- package/src/ast.pyj +379 -279
- package/src/baselib-builtins.pyj +47 -26
- package/src/baselib-containers.pyj +105 -92
- package/src/baselib-errors.pyj +8 -1
- package/src/baselib-internal.pyj +35 -20
- package/src/baselib-itertools.pyj +13 -7
- package/src/baselib-str.pyj +55 -80
- package/src/compiler.pyj +4 -4
- package/src/errors.pyj +3 -4
- package/src/lib/aes.pyj +46 -32
- package/src/lib/elementmaker.pyj +11 -9
- package/src/lib/encodings.pyj +15 -5
- package/src/lib/gettext.pyj +9 -4
- package/src/lib/math.pyj +106 -45
- package/src/lib/operator.pyj +10 -10
- package/src/lib/pythonize.pyj +2 -1
- package/src/lib/random.pyj +28 -21
- package/src/lib/re.pyj +490 -17
- package/src/lib/traceback.pyj +7 -2
- package/src/lib/uuid.pyj +2 -2
- package/src/output/classes.pyj +28 -27
- package/src/output/codegen.pyj +80 -83
- package/src/output/comments.pyj +8 -8
- package/src/output/exceptions.pyj +20 -21
- package/src/output/functions.pyj +37 -26
- package/src/output/literals.pyj +14 -10
- package/src/output/loops.pyj +63 -59
- package/src/output/modules.pyj +52 -23
- package/src/output/operators.pyj +40 -29
- package/src/output/statements.pyj +20 -14
- package/src/output/stream.pyj +33 -34
- package/src/output/utils.pyj +12 -8
- package/src/parse.pyj +234 -233
- package/src/string_interpolation.pyj +5 -3
- package/src/tokenizer.pyj +176 -148
- package/src/utils.pyj +31 -14
- package/test/fmt.pyj +94 -4
- package/test/generic.pyj +9 -0
- package/test/lsp.pyj +35 -0
- package/test/str.pyj +8 -0
- package/tools/cli.mjs +25 -4
- package/tools/compile.mjs +7 -3
- package/tools/compiler.mjs +34 -2
- package/tools/fmt.mjs +262 -22
- package/tools/ini.mjs +112 -1
- package/tools/lsp.mjs +56 -6
- package/tools/repl.mjs +5 -2
- package/tools/self.mjs +15 -0
- package/tools/test.mjs +100 -0
- package/tools/web_repl_export.mjs +4 -0
- package/tree-sitter/package.json +1 -1
- package/tree-sitter/tree-sitter.json +1 -1
- package/editor-plugins/nvim/rapydscript/README.md +0 -184
- package/editor-plugins/nvim/rapydscript/bin/rapydscript.so +0 -0
- package/editor-plugins/nvim/rapydscript/ftdetect/rapydscript.lua +0 -10
- package/editor-plugins/nvim/rapydscript/lua/rapydscript/health.lua +0 -88
- package/editor-plugins/nvim/rapydscript/lua/rapydscript/init.lua +0 -279
- /package/tree-sitter/queries/{rapydscript/highlights.scm → highlights.scm} +0 -0
- /package/tree-sitter/queries/{rapydscript/indents.scm → indents.scm} +0 -0
- /package/tree-sitter/queries/{rapydscript/injections.scm → injections.scm} +0 -0
- /package/tree-sitter/queries/{rapydscript/locals.scm → locals.scm} +0 -0
package/src/lib/aes.pyj
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
# Internal API {{{
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
def string_to_bytes_encoder(string):
|
|
9
10
|
return TextEncoder('utf-8').encode(string + '')
|
|
10
11
|
|
|
12
|
+
|
|
11
13
|
def string_to_bytes_slow(string):
|
|
12
14
|
escstr = encodeURIComponent(string)
|
|
13
|
-
binstr = escstr.replace(/%([0-9A-F]{2})/g, def(match, p1):
|
|
15
|
+
binstr = escstr.replace(/%([0-9A-F]{2})/g, def (match, p1):
|
|
14
16
|
return String.fromCharCode('0x' + p1)
|
|
15
17
|
)
|
|
16
18
|
ua = Uint8Array(binstr.length)
|
|
@@ -18,17 +20,20 @@ def string_to_bytes_slow(string):
|
|
|
18
20
|
ua[i] = ch.charCodeAt(0)
|
|
19
21
|
return ua
|
|
20
22
|
|
|
23
|
+
|
|
21
24
|
def as_hex(array, sep=''):
|
|
22
25
|
num = array.BYTES_PER_ELEMENT or 1
|
|
23
26
|
fmt = '{:0' + num * 2 + 'x}'
|
|
24
27
|
return [str.format(fmt, x) for x in array].join(sep)
|
|
25
28
|
|
|
29
|
+
|
|
26
30
|
def bytes_to_string_decoder(bytes, offset):
|
|
27
31
|
offset = offset or 0
|
|
28
32
|
if offset:
|
|
29
33
|
bytes = bytes.subarray(offset)
|
|
30
34
|
return TextDecoder('utf-8').decode(bytes)
|
|
31
35
|
|
|
36
|
+
|
|
32
37
|
def bytes_to_string_slow(bytes, offset):
|
|
33
38
|
ans = v'[]'
|
|
34
39
|
i = offset or 0
|
|
@@ -48,6 +53,7 @@ def bytes_to_string_slow(bytes, offset):
|
|
|
48
53
|
string_to_bytes = string_to_bytes_encoder if jstype(TextEncoder) is 'function' else string_to_bytes_slow
|
|
49
54
|
bytes_to_string = bytes_to_string_decoder if jstype(TextDecoder) is 'function' else bytes_to_string_slow
|
|
50
55
|
|
|
56
|
+
|
|
51
57
|
def increment_counter(c):
|
|
52
58
|
# c must be a Uint8Array of length 16
|
|
53
59
|
for v'var i = 15; i >= 12; i--':
|
|
@@ -57,11 +63,13 @@ def increment_counter(c):
|
|
|
57
63
|
c[i] += 1
|
|
58
64
|
break
|
|
59
65
|
|
|
66
|
+
|
|
60
67
|
def convert_to_int32(bytes, output, offset, length):
|
|
61
68
|
offset = offset or 0
|
|
62
69
|
length = length or bytes.length
|
|
63
70
|
for v'var i = offset, j = 0; i < offset + length; i += 4, j++':
|
|
64
|
-
output[j] = (bytes[i] << 24) | (bytes[i + 1] << 16) | (bytes[i + 2] <<
|
|
71
|
+
output[j] = (bytes[i] << 24) | (bytes[i + 1] << 16) | (bytes[i + 2] << 8) | bytes[i + 3]
|
|
72
|
+
|
|
65
73
|
|
|
66
74
|
def convert_to_int32_pad(bytes):
|
|
67
75
|
extra = bytes.length % 4
|
|
@@ -74,7 +82,7 @@ def convert_to_int32_pad(bytes):
|
|
|
74
82
|
return ans
|
|
75
83
|
|
|
76
84
|
if not Uint8Array.prototype.fill:
|
|
77
|
-
Uint8Array.prototype.fill = Uint32Array.prototype.fill = def(val, start, end):
|
|
85
|
+
Uint8Array.prototype.fill = Uint32Array.prototype.fill = def (val, start, end):
|
|
78
86
|
start = start or 0
|
|
79
87
|
if end is undefined:
|
|
80
88
|
end = this.length
|
|
@@ -85,12 +93,13 @@ if not Uint8Array.prototype.fill:
|
|
|
85
93
|
for v'var i = start; i < end; i++':
|
|
86
94
|
this[i] = val
|
|
87
95
|
|
|
96
|
+
|
|
88
97
|
def from_64_to_32(num):
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
# convert 64-bit number to two BE Int32s
|
|
99
|
+
ans = Uint32Array(2)
|
|
100
|
+
ans[0] = (num / 0x100000000) | 0
|
|
101
|
+
ans[1] = num & 0xFFFFFFFF
|
|
102
|
+
return ans
|
|
94
103
|
|
|
95
104
|
# Lookup tables for AES {{{
|
|
96
105
|
# Number of rounds by keysize
|
|
@@ -122,8 +131,8 @@ U4 = v'new Uint32Array([0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c
|
|
|
122
131
|
|
|
123
132
|
# }}}
|
|
124
133
|
|
|
125
|
-
class AES: # {{{
|
|
126
134
|
|
|
135
|
+
class AES: # {{{
|
|
127
136
|
def __init__(self, key):
|
|
128
137
|
self.working_mem = [Uint32Array(4), Uint32Array(4)]
|
|
129
138
|
rounds = number_of_rounds[key.length]
|
|
@@ -160,9 +169,9 @@ class AES: # {{{
|
|
|
160
169
|
while t < round_key_count:
|
|
161
170
|
tt = tk[KC - 1]
|
|
162
171
|
tk[0] ^= ((S[(tt >> 16) & 0xFF] << 24) ^
|
|
163
|
-
(S[(tt >>
|
|
164
|
-
(S[
|
|
165
|
-
S[(tt >> 24) & 0xFF]
|
|
172
|
+
(S[(tt >> 8) & 0xFF] << 16) ^
|
|
173
|
+
(S[tt & 0xFF] << 8) ^
|
|
174
|
+
S[(tt >> 24) & 0xFF] ^
|
|
166
175
|
(rcon[rconpointer] << 24))
|
|
167
176
|
rconpointer += 1
|
|
168
177
|
|
|
@@ -177,8 +186,8 @@ class AES: # {{{
|
|
|
177
186
|
tk[i] ^= tk[i - 1]
|
|
178
187
|
tt = tk[(KC / 2) - 1]
|
|
179
188
|
|
|
180
|
-
tk[KC / 2] ^= (S[
|
|
181
|
-
(S[(tt >>
|
|
189
|
+
tk[KC / 2] ^= (S[tt & 0xFF] ^
|
|
190
|
+
(S[(tt >> 8) & 0xFF] << 8) ^
|
|
182
191
|
(S[(tt >> 16) & 0xFF] << 16) ^
|
|
183
192
|
(S[(tt >> 24) & 0xFF] << 24))
|
|
184
193
|
|
|
@@ -200,8 +209,8 @@ class AES: # {{{
|
|
|
200
209
|
tt = self._Kd[r][c]
|
|
201
210
|
self._Kd[r][c] = (U1[(tt >> 24) & 0xFF] ^
|
|
202
211
|
U2[(tt >> 16) & 0xFF] ^
|
|
203
|
-
U3[(tt >>
|
|
204
|
-
U4[
|
|
212
|
+
U3[(tt >> 8) & 0xFF] ^
|
|
213
|
+
U4[tt & 0xFF])
|
|
205
214
|
|
|
206
215
|
def _crypt(self, ciphertext, offset, encrypt):
|
|
207
216
|
if encrypt:
|
|
@@ -227,8 +236,8 @@ class AES: # {{{
|
|
|
227
236
|
for v'var i = 0; i < 4; i++':
|
|
228
237
|
a[i] = (R1[(t[i] >> 24) & 0xff] ^
|
|
229
238
|
R2[(t[(i + o1) % 4] >> 16) & 0xff] ^
|
|
230
|
-
R3[(t[(i +
|
|
231
|
-
R4[
|
|
239
|
+
R3[(t[(i + 2) % 4] >> 8) & 0xff] ^
|
|
240
|
+
R4[t[(i + o3) % 4] & 0xff] ^
|
|
232
241
|
K[r][i])
|
|
233
242
|
t.set(a)
|
|
234
243
|
|
|
@@ -237,8 +246,8 @@ class AES: # {{{
|
|
|
237
246
|
tt = K[rounds][i]
|
|
238
247
|
ciphertext[offset + 4 * i] = (SB[(t[i] >> 24) & 0xff] ^ (tt >> 24)) & 0xff
|
|
239
248
|
ciphertext[offset + 4 * i + 1] = (SB[(t[(i + o1) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff
|
|
240
|
-
ciphertext[offset + 4 * i + 2] = (SB[(t[(i +
|
|
241
|
-
ciphertext[offset + 4 * i + 3] = (SB[
|
|
249
|
+
ciphertext[offset + 4 * i + 2] = (SB[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff
|
|
250
|
+
ciphertext[offset + 4 * i + 3] = (SB[t[(i + o3) % 4] & 0xff] ^ tt) & 0xff
|
|
242
251
|
|
|
243
252
|
def encrypt(self, plaintext, ciphertext, offset):
|
|
244
253
|
convert_to_int32(plaintext, self.working_mem[1], offset, 16)
|
|
@@ -257,12 +266,14 @@ class AES: # {{{
|
|
|
257
266
|
return self._crypt(plaintext, offset, False)
|
|
258
267
|
# }}}
|
|
259
268
|
|
|
269
|
+
|
|
260
270
|
def random_bytes_insecure(sz):
|
|
261
271
|
ans = Uint8Array(sz)
|
|
262
272
|
for v'var i = 0; i < sz; i++':
|
|
263
273
|
ans[i] = Math.floor(Math.random() * 256)
|
|
264
274
|
return ans
|
|
265
275
|
|
|
276
|
+
|
|
266
277
|
def random_bytes_secure(sz):
|
|
267
278
|
ans = Uint8Array(sz)
|
|
268
279
|
crypto.getRandomValues(ans)
|
|
@@ -272,13 +283,13 @@ random_bytes = random_bytes_secure if jstype(crypto) is not 'undefined' and jsty
|
|
|
272
283
|
if random_bytes is random_bytes_insecure:
|
|
273
284
|
try:
|
|
274
285
|
noderandom = require('crypto').randomBytes
|
|
275
|
-
random_bytes = def(sz):
|
|
286
|
+
random_bytes = def (sz):
|
|
276
287
|
return Uint8Array(noderandom(sz))
|
|
277
288
|
except:
|
|
278
289
|
print('WARNING: Using insecure RNG for AES')
|
|
279
290
|
|
|
280
|
-
class ModeOfOperation: # {{{
|
|
281
291
|
|
|
292
|
+
class ModeOfOperation: # {{{
|
|
282
293
|
def __init__(self, key):
|
|
283
294
|
self.key = key or generate_key(32)
|
|
284
295
|
self.aes = AES(self.key)
|
|
@@ -297,8 +308,8 @@ class ModeOfOperation: # {{{
|
|
|
297
308
|
raise TypeError('Invalid tag, must be a string or a Uint8Array')
|
|
298
309
|
# }}}
|
|
299
310
|
|
|
300
|
-
class GaloisField: # {{{
|
|
301
311
|
|
|
312
|
+
class GaloisField: # {{{
|
|
302
313
|
def __init__(self, sub_key):
|
|
303
314
|
k32 = Uint32Array(4)
|
|
304
315
|
convert_to_int32(sub_key, k32, 0)
|
|
@@ -362,7 +373,7 @@ class GaloisField: # {{{
|
|
|
362
373
|
ans = Array(size)
|
|
363
374
|
for v'var i =0; i < size; ++i':
|
|
364
375
|
tmp = Uint32Array(4)
|
|
365
|
-
idx = (i/ per_int) | 0
|
|
376
|
+
idx = (i / per_int) | 0
|
|
366
377
|
shft = ((per_int - 1 - (i % per_int)) * bits)
|
|
367
378
|
tmp[idx] = (1 << (bits - 1)) << shft
|
|
368
379
|
ans[i] = self.generate_sub_hash_table(self.multiply(tmp, key_as_int32_array))
|
|
@@ -393,20 +404,23 @@ class GaloisField: # {{{
|
|
|
393
404
|
|
|
394
405
|
# }}}
|
|
395
406
|
|
|
407
|
+
|
|
396
408
|
def generate_key(sz):
|
|
397
409
|
if not number_of_rounds[sz]:
|
|
398
410
|
raise ValueError('Invalid key size, must be: 16, 24 or 32')
|
|
399
411
|
return random_bytes(sz)
|
|
400
412
|
|
|
413
|
+
|
|
401
414
|
def generate_tag(sz):
|
|
402
415
|
return random_bytes(sz or 32)
|
|
403
416
|
|
|
417
|
+
|
|
404
418
|
def typed_array_as_js(x):
|
|
405
419
|
name = x.constructor.name or 'Uint8Array'
|
|
406
|
-
return '(new ' + name + '(' + JSON.stringify(Array.from(x)) + '))'
|
|
420
|
+
return '(new ' + name + '(' + JSON.stringify(Array.from (x)) + '))'
|
|
407
421
|
|
|
408
|
-
class CBC(ModeOfOperation): # {{{
|
|
409
422
|
|
|
423
|
+
class CBC(ModeOfOperation): # {{{
|
|
410
424
|
def encrypt_bytes(self, bytes, tag_bytes, iv):
|
|
411
425
|
iv = first_iv = iv or random_bytes(16)
|
|
412
426
|
mlen = bytes.length + tag_bytes.length
|
|
@@ -424,7 +438,7 @@ class CBC(ModeOfOperation): # {{{
|
|
|
424
438
|
for v'var i = 0; i < 16; i++':
|
|
425
439
|
inputbytes[block + i] ^= iv[offset + i]
|
|
426
440
|
self.aes.encrypt(inputbytes, outputbytes, block)
|
|
427
|
-
return {'iv':first_iv, 'cipherbytes':outputbytes}
|
|
441
|
+
return {'iv': first_iv, 'cipherbytes': outputbytes}
|
|
428
442
|
|
|
429
443
|
def encrypt(self, plaintext, tag):
|
|
430
444
|
return self.encrypt_bytes(string_to_bytes(plaintext), self.tag_as_bytes(tag))
|
|
@@ -449,8 +463,8 @@ class CBC(ModeOfOperation): # {{{
|
|
|
449
463
|
return str.rstrip(bytes_to_string(ans), '\0')
|
|
450
464
|
# }}}
|
|
451
465
|
|
|
452
|
-
class CTR(ModeOfOperation): # {{{
|
|
453
466
|
|
|
467
|
+
class CTR(ModeOfOperation): # {{{
|
|
454
468
|
# Note that this mode of operation requires the pair of (counterbytes,
|
|
455
469
|
# secret key) to always be unique, for every block. Therefore, if you are
|
|
456
470
|
# using it for bi-directional messaging it is best to use a different
|
|
@@ -483,7 +497,7 @@ class CTR(ModeOfOperation): # {{{
|
|
|
483
497
|
t.set(outbytes, tag_bytes.length)
|
|
484
498
|
outbytes = t
|
|
485
499
|
self._crypt(outbytes)
|
|
486
|
-
return {'cipherbytes':outbytes, 'counterbytes':counterbytes}
|
|
500
|
+
return {'cipherbytes': outbytes, 'counterbytes': counterbytes}
|
|
487
501
|
|
|
488
502
|
def __enter__(self):
|
|
489
503
|
self.before_index = self.counter_index
|
|
@@ -509,8 +523,8 @@ class CTR(ModeOfOperation): # {{{
|
|
|
509
523
|
return bytes_to_string(b, offset)
|
|
510
524
|
# }}}
|
|
511
525
|
|
|
512
|
-
class GCM(ModeOfOperation): # {{{
|
|
513
526
|
|
|
527
|
+
class GCM(ModeOfOperation): # {{{
|
|
514
528
|
# Note that this mode of operation requires the pair of (iv,
|
|
515
529
|
# secret key) to always be unique, for every message. Therefore, if you are
|
|
516
530
|
# using it for bi-directional messaging it is best to use a different
|
|
@@ -593,7 +607,7 @@ class GCM(ModeOfOperation): # {{{
|
|
|
593
607
|
tag = Uint32Array(4)
|
|
594
608
|
for v'var i = 0; i < S.length; i++':
|
|
595
609
|
tag[i] = S[i] ^ self.wmem[i]
|
|
596
|
-
return {'iv':iv, 'cipherbytes':outbytes, 'tag':tag}
|
|
610
|
+
return {'iv': iv, 'cipherbytes': outbytes, 'tag': tag}
|
|
597
611
|
|
|
598
612
|
def _crypt(self, iv, bytes, additional_data, decrypt):
|
|
599
613
|
ghash = self.galois.ghash.bind(self.galois)
|
|
@@ -643,4 +657,4 @@ class GCM(ModeOfOperation): # {{{
|
|
|
643
657
|
if ans.tag != output_from_encrypt.tag:
|
|
644
658
|
raise ValueError('Corrupted message')
|
|
645
659
|
return bytes_to_string(ans.cipherbytes)
|
|
646
|
-
# }}}
|
|
660
|
+
# }}}
|
package/src/lib/elementmaker.pyj
CHANGED
|
@@ -36,6 +36,7 @@ svg_elements = {
|
|
|
36
36
|
|
|
37
37
|
html5_tags = html_elements.union(mathml_elements).union(svg_elements)
|
|
38
38
|
|
|
39
|
+
|
|
39
40
|
def _makeelement(tag, *args, **kwargs):
|
|
40
41
|
ans = this.createElement(tag)
|
|
41
42
|
|
|
@@ -57,26 +58,27 @@ def _makeelement(tag, *args, **kwargs):
|
|
|
57
58
|
ans.appendChild(arg)
|
|
58
59
|
return ans
|
|
59
60
|
|
|
61
|
+
|
|
60
62
|
def maker_for_document(document):
|
|
61
63
|
# Create an elementmaker to be used with the specified document
|
|
62
64
|
E = _makeelement.bind(document)
|
|
63
65
|
Object.defineProperties(E, {
|
|
64
66
|
tag: {
|
|
65
|
-
'value':_makeelement.bind(document, tag)
|
|
67
|
+
'value': _makeelement.bind(document, tag)
|
|
66
68
|
} for tag in html5_tags
|
|
67
69
|
})
|
|
68
70
|
return E
|
|
69
71
|
|
|
70
72
|
if jstype(document) is 'undefined':
|
|
71
73
|
E = maker_for_document({
|
|
72
|
-
'createTextNode': def(value): return value;,
|
|
73
|
-
'createElement': def(name):
|
|
74
|
-
return
|
|
75
|
-
'name':name,
|
|
76
|
-
'children':[],
|
|
77
|
-
'attributes':{},
|
|
78
|
-
'setAttribute': def(name, val): this.attributes[name] = val;,
|
|
79
|
-
'appendChild': def(child): this.children.push(child);,
|
|
74
|
+
'createTextNode': def (value): return value;,
|
|
75
|
+
'createElement': def (name):
|
|
76
|
+
return {
|
|
77
|
+
'name': name,
|
|
78
|
+
'children': [],
|
|
79
|
+
'attributes': {},
|
|
80
|
+
'setAttribute': def (name, val): this.attributes[name] = val;,
|
|
81
|
+
'appendChild': def (child): this.children.push(child);,
|
|
80
82
|
}
|
|
81
83
|
})
|
|
82
84
|
else:
|
package/src/lib/encodings.pyj
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# vim:fileencoding=utf-8
|
|
2
2
|
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
def base64encode(bytes, altchars, pad_char):
|
|
5
6
|
# Convert an array of bytes into a base-64 encoded string
|
|
6
7
|
l = bytes.length
|
|
@@ -20,25 +21,29 @@ def base64encode(bytes, altchars, pad_char):
|
|
|
20
21
|
ans.push(encodings[(chunk & 64512) >> 10], encodings[(chunk & 1008) >> 4], encodings[(chunk & 15) << 2], pad_char)
|
|
21
22
|
return ans.join('')
|
|
22
23
|
|
|
24
|
+
|
|
23
25
|
def base64decode(string):
|
|
24
26
|
# convert the output of base64encode back into an array of bytes
|
|
25
27
|
# (Uint8Array) only works with the standard altchars and pad_char
|
|
26
28
|
if jstype(window) is not 'undefined':
|
|
27
29
|
chars = window.atob(string)
|
|
28
30
|
else:
|
|
29
|
-
chars = Buffer.from(string, 'base64').toString('binary') # noqa: undef
|
|
31
|
+
chars = Buffer.from (string, 'base64').toString('binary') # noqa: undef
|
|
30
32
|
ans = Uint8Array(chars.length)
|
|
31
33
|
for i in range(ans.length):
|
|
32
34
|
ans[i] = chars.charCodeAt(i)
|
|
33
35
|
return ans
|
|
34
36
|
|
|
37
|
+
|
|
35
38
|
def urlsafe_b64encode(bytes, pad_char):
|
|
36
39
|
return base64encode(bytes, '-_', pad_char)
|
|
37
40
|
|
|
41
|
+
|
|
38
42
|
def urlsafe_b64decode(string):
|
|
39
|
-
string = String.prototype.replace.call(string, /[_-]/g, def(m): return '+' if m is '-' else '/';)
|
|
43
|
+
string = String.prototype.replace.call(string, /[_-]/g, def (m): return '+' if m is '-' else '/';)
|
|
40
44
|
return base64decode(string)
|
|
41
45
|
|
|
46
|
+
|
|
42
47
|
def hexlify(bytes):
|
|
43
48
|
ans = v'[]'
|
|
44
49
|
for v'var i = 0; i < bytes.length; i++':
|
|
@@ -48,13 +53,14 @@ def hexlify(bytes):
|
|
|
48
53
|
ans.push(x)
|
|
49
54
|
return ans.join('')
|
|
50
55
|
|
|
56
|
+
|
|
51
57
|
def unhexlify(string):
|
|
52
58
|
num = string.length // 2
|
|
53
59
|
if num * 2 is not string.length:
|
|
54
60
|
raise ValueError('string length is not a multiple of two')
|
|
55
61
|
ans = Uint8Array(num)
|
|
56
62
|
for v'var i = 0; i < num; i++':
|
|
57
|
-
x = parseInt(string[i*2:i*2+2], 16)
|
|
63
|
+
x = parseInt(string[i * 2:i * 2 + 2], 16)
|
|
58
64
|
if isNaN(x):
|
|
59
65
|
raise ValueError('string is not hex-encoded')
|
|
60
66
|
ans[i] = x
|
|
@@ -77,12 +83,14 @@ utf8_decoder_table = v'''[
|
|
|
77
83
|
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
|
78
84
|
]'''
|
|
79
85
|
|
|
86
|
+
|
|
80
87
|
def _from_code_point(x):
|
|
81
88
|
if x <= 0xFFFF:
|
|
82
89
|
return String.fromCharCode(x)
|
|
83
90
|
x -= 0x10000
|
|
84
91
|
return String.fromCharCode((x >> 10) + 0xD800, (x % 0x400) + 0xDC00)
|
|
85
92
|
|
|
93
|
+
|
|
86
94
|
def utf8_decode(bytes, errors, replacement):
|
|
87
95
|
# Convert an array of UTF-8 encoded bytes into a string
|
|
88
96
|
state = 0
|
|
@@ -92,7 +100,7 @@ def utf8_decode(bytes, errors, replacement):
|
|
|
92
100
|
byte = bytes[i]
|
|
93
101
|
typ = utf8_decoder_table[byte]
|
|
94
102
|
codep = (byte & 0x3f) | (codep << 6) if state is not 0 else (0xff >> typ) & (byte)
|
|
95
|
-
state = utf8_decoder_table[256 + state*16 + typ]
|
|
103
|
+
state = utf8_decoder_table[256 + state * 16 + typ]
|
|
96
104
|
if state is 0:
|
|
97
105
|
ans.push(_from_code_point(codep))
|
|
98
106
|
elif state is 1:
|
|
@@ -102,6 +110,7 @@ def utf8_decode(bytes, errors, replacement):
|
|
|
102
110
|
ans.push(replacement or '?')
|
|
103
111
|
return ans.join('')
|
|
104
112
|
|
|
113
|
+
|
|
105
114
|
def utf8_encode_js(string):
|
|
106
115
|
# Encode a string as an array of UTF-8 bytes
|
|
107
116
|
escstr = encodeURIComponent(string)
|
|
@@ -109,7 +118,7 @@ def utf8_encode_js(string):
|
|
|
109
118
|
for v'var i = 0; i < escstr.length; i++':
|
|
110
119
|
ch = escstr[i]
|
|
111
120
|
if ch is '%':
|
|
112
|
-
ans.push(parseInt(escstr[i+1:i+3], 16))
|
|
121
|
+
ans.push(parseInt(escstr[i + 1:i + 3], 16))
|
|
113
122
|
i += 2
|
|
114
123
|
else:
|
|
115
124
|
ans.push(ch.charCodeAt(0))
|
|
@@ -122,5 +131,6 @@ if jstype(TextEncoder) is 'function':
|
|
|
122
131
|
else:
|
|
123
132
|
utf8_encode = utf8_encode_js
|
|
124
133
|
|
|
134
|
+
|
|
125
135
|
def utf8_encode_native(string):
|
|
126
136
|
return _u8enc.encode(string)
|
package/src/lib/gettext.pyj
CHANGED
|
@@ -500,19 +500,23 @@ return parser;
|
|
|
500
500
|
plural_forms_parser = Jed.PF
|
|
501
501
|
# }}}
|
|
502
502
|
|
|
503
|
+
|
|
503
504
|
def _get_plural_forms_function(plural_forms_string):
|
|
504
|
-
return plural_forms_parser.compile(plural_forms_string or
|
|
505
|
+
return plural_forms_parser.compile(plural_forms_string or 'nplurals=2; plural=(n != 1);')
|
|
506
|
+
|
|
507
|
+
_gettext = def (text): return text
|
|
505
508
|
|
|
506
|
-
|
|
509
|
+
_ngettext = def (text, plural, n): return text if n is 1 else plural
|
|
507
510
|
|
|
508
|
-
_ngettext = def(text, plural, n): return text if n is 1 else plural
|
|
509
511
|
|
|
510
512
|
def gettext(text):
|
|
511
513
|
return _gettext(text)
|
|
512
514
|
|
|
515
|
+
|
|
513
516
|
def ngettext(text, plural, n):
|
|
514
517
|
return _ngettext(text, plural, n)
|
|
515
518
|
|
|
519
|
+
|
|
516
520
|
def install(translation_data):
|
|
517
521
|
t = new Translations(translation_data)
|
|
518
522
|
t.install()
|
|
@@ -525,6 +529,7 @@ def install(translation_data):
|
|
|
525
529
|
|
|
526
530
|
has_prop = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty)
|
|
527
531
|
|
|
532
|
+
|
|
528
533
|
def register_callback(func):
|
|
529
534
|
# Register callbacks that will be called when new translation data is
|
|
530
535
|
# installed
|
|
@@ -533,8 +538,8 @@ register_callback.install_callbacks = v'[]'
|
|
|
533
538
|
|
|
534
539
|
empty_translation_data = {'entries': {}}
|
|
535
540
|
|
|
536
|
-
class Translations:
|
|
537
541
|
|
|
542
|
+
class Translations:
|
|
538
543
|
def __init__(self, translation_data):
|
|
539
544
|
translation_data = translation_data or empty_translation_data
|
|
540
545
|
func = _get_plural_forms_function(translation_data.plural_forms)
|