rapydscript-ns 0.8.2 → 0.8.4
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/.agignore +1 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +39 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/PYTHON_DIFFERENCES_REPORT.md +291 -0
- package/PYTHON_FEATURE_COVERAGE.md +106 -15
- package/README.md +831 -52
- package/TODO.md +4 -286
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +70 -70
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +4623 -0
- package/language-service/language-service.d.ts +40 -0
- package/package.json +9 -7
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +2006 -229
- package/release/baselib-plain-ugly.js +70 -3
- package/release/compiler.js +11554 -3870
- package/release/signatures.json +31 -29
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +93 -1
- package/src/baselib-builtins.pyj +99 -2
- package/src/baselib-containers.pyj +107 -4
- package/src/baselib-errors.pyj +44 -0
- package/src/baselib-internal.pyj +124 -5
- package/src/baselib-itertools.pyj +97 -97
- package/src/baselib-str.pyj +32 -1
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/collections.pyj +1 -1
- package/src/lib/copy.pyj +120 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/gettext.pyj +569 -569
- package/src/lib/itertools.pyj +580 -580
- package/src/lib/math.pyj +193 -193
- package/src/lib/numpy.pyj +10 -10
- package/src/lib/operator.pyj +11 -11
- package/src/lib/pythonize.pyj +20 -20
- package/src/lib/random.pyj +118 -118
- package/src/lib/re.pyj +470 -470
- package/src/lib/react.pyj +74 -0
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/analyzer.js +131 -9
- package/src/monaco-language-service/builtins.js +17 -2
- package/src/monaco-language-service/completions.js +170 -1
- package/src/monaco-language-service/diagnostics.js +25 -3
- package/src/monaco-language-service/dts.js +550 -550
- package/src/monaco-language-service/index.js +17 -0
- package/src/monaco-language-service/scope.js +3 -0
- package/src/output/classes.pyj +128 -11
- package/src/output/codegen.pyj +17 -3
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -105
- package/src/output/functions.pyj +13 -16
- package/src/output/jsx.pyj +164 -0
- package/src/output/literals.pyj +28 -2
- package/src/output/loops.pyj +0 -9
- package/src/output/modules.pyj +2 -5
- package/src/output/operators.pyj +22 -2
- package/src/output/statements.pyj +2 -2
- package/src/output/stream.pyj +1 -13
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +434 -114
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +29 -0
- package/src/unicode_aliases.pyj +576 -576
- package/src/utils.pyj +192 -192
- package/test/_import_one.pyj +37 -37
- package/test/_import_two/__init__.pyj +11 -11
- package/test/_import_two/level2/deep.pyj +4 -4
- package/test/_import_two/other.pyj +6 -6
- package/test/_import_two/sub.pyj +13 -13
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/baselib.pyj +4 -4
- package/test/classes.pyj +56 -17
- package/test/collections.pyj +5 -5
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/imports.pyj +72 -72
- package/test/internationalization.pyj +73 -73
- package/test/lint.pyj +164 -164
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/omit_function_metadata.pyj +20 -20
- package/test/python_compat.pyj +326 -0
- package/test/python_features.pyj +129 -29
- package/test/regexp.pyj +55 -55
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/slice.pyj +105 -0
- package/test/str.pyj +25 -0
- package/test/unit/fixtures/fibonacci_expected.js +1 -1
- package/test/unit/index.js +2296 -71
- package/test/unit/language-service-builtins.js +70 -0
- package/test/unit/language-service-bundle.js +5 -5
- package/test/unit/language-service-completions.js +180 -0
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service-index.js +350 -0
- package/test/unit/language-service-scope.js +255 -0
- package/test/unit/language-service.js +625 -4
- package/test/unit/run-language-service.js +1 -0
- package/test/unit/web-repl.js +437 -0
- package/tools/build-language-service.js +2 -2
- package/tools/cli.js +547 -547
- package/tools/compile.js +219 -219
- package/tools/compiler.js +0 -24
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +251 -251
- package/tools/export.js +3 -37
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/msgfmt.js +187 -187
- package/tools/repl.js +223 -223
- package/tools/test.js +118 -118
- package/tools/utils.js +128 -128
- package/tools/web_repl.js +95 -95
- package/try +41 -41
- package/web-repl/env.js +196 -74
- package/web-repl/index.html +163 -163
- package/web-repl/main.js +252 -254
- package/web-repl/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +227 -139
- package/web-repl/sha1.js +25 -25
- package/hack_demo.pyj +0 -112
- package/web-repl/language-service.js +0 -4187
|
@@ -1,105 +1,201 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
from __python__ import hash_literals
|
|
4
|
-
|
|
5
|
-
from output.statements import print_bracketed
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def print_try(self, output):
|
|
9
|
-
else_var_name = None
|
|
10
|
-
def update_output_var(output):
|
|
11
|
-
output.indent(), output.assign(else_var_name), output.print('true'), output.end_statement()
|
|
12
|
-
if self.belse:
|
|
13
|
-
else_var_name = output.new_try_else_counter()
|
|
14
|
-
output.assign('var ' + else_var_name), output.print('false'), output.end_statement(), output.indent()
|
|
15
|
-
output.print("try")
|
|
16
|
-
output.space()
|
|
17
|
-
print_bracketed(self, output, False, None, None, update_output_var if else_var_name else None)
|
|
18
|
-
if self.bcatch:
|
|
19
|
-
output.space()
|
|
20
|
-
print_catch(self.bcatch, output)
|
|
21
|
-
|
|
22
|
-
if self.bfinally:
|
|
23
|
-
output.space()
|
|
24
|
-
print_finally(self.bfinally, output, self.belse, else_var_name)
|
|
25
|
-
elif self.belse:
|
|
26
|
-
output.newline()
|
|
27
|
-
print_else(self.belse, else_var_name, output)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def print_catch(self, output):
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
)
|
|
36
|
-
output.space()
|
|
37
|
-
output.
|
|
38
|
-
output.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
output.
|
|
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
|
-
output
|
|
74
|
-
output.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
output.
|
|
80
|
-
output.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
output.
|
|
104
|
-
output.
|
|
105
|
-
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
from __python__ import hash_literals
|
|
4
|
+
|
|
5
|
+
from output.statements import print_bracketed, display_body
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def print_try(self, output):
|
|
9
|
+
else_var_name = None
|
|
10
|
+
def update_output_var(output):
|
|
11
|
+
output.indent(), output.assign(else_var_name), output.print('true'), output.end_statement()
|
|
12
|
+
if self.belse:
|
|
13
|
+
else_var_name = output.new_try_else_counter()
|
|
14
|
+
output.assign('var ' + else_var_name), output.print('false'), output.end_statement(), output.indent()
|
|
15
|
+
output.print("try")
|
|
16
|
+
output.space()
|
|
17
|
+
print_bracketed(self, output, False, None, None, update_output_var if else_var_name else None)
|
|
18
|
+
if self.bcatch:
|
|
19
|
+
output.space()
|
|
20
|
+
print_catch(self.bcatch, output)
|
|
21
|
+
|
|
22
|
+
if self.bfinally:
|
|
23
|
+
output.space()
|
|
24
|
+
print_finally(self.bfinally, output, self.belse, else_var_name)
|
|
25
|
+
elif self.belse:
|
|
26
|
+
output.newline()
|
|
27
|
+
print_else(self.belse, else_var_name, output)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def print_catch(self, output):
|
|
31
|
+
# Dispatch to except* handler when any clause is an exception group handler
|
|
32
|
+
if self.body.length and self.body[0].is_star:
|
|
33
|
+
print_catch_star(self, output)
|
|
34
|
+
return
|
|
35
|
+
output.print("catch")
|
|
36
|
+
output.space()
|
|
37
|
+
output.with_parens(def():
|
|
38
|
+
output.print("ρσ_Exception")
|
|
39
|
+
)
|
|
40
|
+
output.space()
|
|
41
|
+
output.with_block(def():
|
|
42
|
+
output.indent()
|
|
43
|
+
output.spaced('ρσ_last_exception', '=', 'ρσ_Exception'), output.end_statement()
|
|
44
|
+
output.indent()
|
|
45
|
+
no_default = True
|
|
46
|
+
for i, exception in enumerate(self.body):
|
|
47
|
+
if i:
|
|
48
|
+
output.print("else ")
|
|
49
|
+
|
|
50
|
+
if exception.errors.length:
|
|
51
|
+
output.print("if")
|
|
52
|
+
output.space()
|
|
53
|
+
output.with_parens(def():
|
|
54
|
+
for i, err in enumerate(exception.errors):
|
|
55
|
+
if i:
|
|
56
|
+
output.newline()
|
|
57
|
+
output.indent()
|
|
58
|
+
output.print("||")
|
|
59
|
+
output.space()
|
|
60
|
+
|
|
61
|
+
output.print("ρσ_Exception")
|
|
62
|
+
output.space()
|
|
63
|
+
output.print("instanceof")
|
|
64
|
+
output.space()
|
|
65
|
+
if err.name is 'Exception':
|
|
66
|
+
output.print('Error')
|
|
67
|
+
else:
|
|
68
|
+
err.print(output)
|
|
69
|
+
)
|
|
70
|
+
output.space()
|
|
71
|
+
else:
|
|
72
|
+
no_default = False
|
|
73
|
+
print_bracketed(exception, output, True)
|
|
74
|
+
output.space()
|
|
75
|
+
if no_default:
|
|
76
|
+
output.print("else")
|
|
77
|
+
output.space()
|
|
78
|
+
output.with_block(def():
|
|
79
|
+
output.indent()
|
|
80
|
+
output.print("throw")
|
|
81
|
+
output.space()
|
|
82
|
+
output.print("ρσ_Exception")
|
|
83
|
+
output.semicolon()
|
|
84
|
+
output.newline()
|
|
85
|
+
)
|
|
86
|
+
output.newline()
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _eg_type_cond(errors, varname):
|
|
91
|
+
# Build a JS condition string testing varname against each error type
|
|
92
|
+
parts = []
|
|
93
|
+
for err in errors:
|
|
94
|
+
if err.name is 'Exception':
|
|
95
|
+
parts.push(varname + " instanceof Error")
|
|
96
|
+
else:
|
|
97
|
+
parts.push(varname + " instanceof " + err.name)
|
|
98
|
+
return parts.join(" || ")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def print_catch_star(self, output):
|
|
102
|
+
output.print("catch")
|
|
103
|
+
output.space()
|
|
104
|
+
output.with_parens(def():
|
|
105
|
+
output.print("ρσ_Exception")
|
|
106
|
+
)
|
|
107
|
+
output.space()
|
|
108
|
+
output.with_block(def():
|
|
109
|
+
output.indent()
|
|
110
|
+
output.spaced('ρσ_last_exception', '=', 'ρσ_Exception'), output.end_statement()
|
|
111
|
+
|
|
112
|
+
# Normalise: wrap non-ExceptionGroup exception into a one-element array
|
|
113
|
+
output.indent()
|
|
114
|
+
output.print("var ρσ_eg_exceptions = (ρσ_Exception instanceof ExceptionGroup) ? ρσ_Exception.exceptions.slice() : [ρσ_Exception]")
|
|
115
|
+
output.semicolon(), output.newline()
|
|
116
|
+
output.indent()
|
|
117
|
+
output.print("var ρσ_eg_raised = []")
|
|
118
|
+
output.semicolon(), output.newline()
|
|
119
|
+
|
|
120
|
+
for ei, exception in enumerate(self.body):
|
|
121
|
+
idx = str(ei)
|
|
122
|
+
if exception.errors.length:
|
|
123
|
+
cond = _eg_type_cond(exception.errors, "ρσ_et")
|
|
124
|
+
output.indent()
|
|
125
|
+
output.print("var ρσ_eg_matched_" + idx + " = ρσ_eg_exceptions.filter(function(ρσ_et) { return " + cond + "; })")
|
|
126
|
+
output.semicolon(), output.newline()
|
|
127
|
+
output.indent()
|
|
128
|
+
output.print("ρσ_eg_exceptions = ρσ_eg_exceptions.filter(function(ρσ_et) { return !(" + cond + "); })")
|
|
129
|
+
output.semicolon(), output.newline()
|
|
130
|
+
else:
|
|
131
|
+
# Bare except*: take all remaining
|
|
132
|
+
output.indent()
|
|
133
|
+
output.print("var ρσ_eg_matched_" + idx + " = ρσ_eg_exceptions.slice()")
|
|
134
|
+
output.semicolon(), output.newline()
|
|
135
|
+
output.indent()
|
|
136
|
+
output.print("ρσ_eg_exceptions = []")
|
|
137
|
+
output.semicolon(), output.newline()
|
|
138
|
+
|
|
139
|
+
output.indent()
|
|
140
|
+
output.print("if (ρσ_eg_matched_" + idx + ".length > 0)")
|
|
141
|
+
output.space()
|
|
142
|
+
output.with_block(def():
|
|
143
|
+
if exception.argname:
|
|
144
|
+
output.indent()
|
|
145
|
+
output.print("var ")
|
|
146
|
+
output.assign(exception.argname)
|
|
147
|
+
output.print("(ρσ_Exception instanceof ExceptionGroup) ? new ExceptionGroup(ρσ_Exception.message, ρσ_eg_matched_" + idx + ") : ρσ_eg_matched_" + idx + "[0]")
|
|
148
|
+
output.semicolon(), output.newline()
|
|
149
|
+
output.indent()
|
|
150
|
+
output.print("try")
|
|
151
|
+
output.space()
|
|
152
|
+
output.with_block(def():
|
|
153
|
+
display_body(exception.body, False, output)
|
|
154
|
+
)
|
|
155
|
+
output.print(" catch (ρσ_eg_exc_" + idx + ")")
|
|
156
|
+
output.space()
|
|
157
|
+
output.with_block(def():
|
|
158
|
+
output.indent()
|
|
159
|
+
output.print("ρσ_eg_raised.push(ρσ_eg_exc_" + idx + ")")
|
|
160
|
+
output.semicolon(), output.newline()
|
|
161
|
+
)
|
|
162
|
+
output.newline()
|
|
163
|
+
)
|
|
164
|
+
output.newline()
|
|
165
|
+
|
|
166
|
+
# Re-raise unmatched exceptions and any raised by handlers
|
|
167
|
+
output.indent()
|
|
168
|
+
output.print("var ρσ_eg_unhandled = ρσ_eg_exceptions.concat(ρσ_eg_raised)")
|
|
169
|
+
output.semicolon(), output.newline()
|
|
170
|
+
output.indent()
|
|
171
|
+
output.print("if (ρσ_eg_unhandled.length > 0)")
|
|
172
|
+
output.space()
|
|
173
|
+
output.with_block(def():
|
|
174
|
+
output.indent()
|
|
175
|
+
output.print("throw (ρσ_eg_unhandled.length === 1 && !(ρσ_Exception instanceof ExceptionGroup)) ? ρσ_eg_unhandled[0] : new ExceptionGroup((ρσ_Exception instanceof ExceptionGroup) ? ρσ_Exception.message : \"unhandled exceptions\", ρσ_eg_unhandled)")
|
|
176
|
+
output.semicolon(), output.newline()
|
|
177
|
+
)
|
|
178
|
+
output.newline()
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def print_finally(self, output, belse, else_var_name):
|
|
183
|
+
output.print("finally")
|
|
184
|
+
output.space()
|
|
185
|
+
if else_var_name:
|
|
186
|
+
output.with_block(def():
|
|
187
|
+
output.indent(), output.print("try")
|
|
188
|
+
output.space()
|
|
189
|
+
output.with_block(def():
|
|
190
|
+
print_else(belse, else_var_name, output)
|
|
191
|
+
)
|
|
192
|
+
print_finally(self, output)
|
|
193
|
+
)
|
|
194
|
+
else:
|
|
195
|
+
print_bracketed(self, output)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def print_else(self, else_var_name, output):
|
|
199
|
+
output.indent(), output.spaced('if', '(' + else_var_name + ')')
|
|
200
|
+
output.space()
|
|
201
|
+
print_bracketed(self, output)
|
package/src/output/functions.pyj
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# vim:fileencoding=utf-8
|
|
2
2
|
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
# globals:regenerate
|
|
4
3
|
from __python__ import hash_literals
|
|
5
4
|
|
|
6
5
|
from ast import AST_ClassCall, AST_New, has_calls, AST_Dot, AST_SymbolRef, is_node_type
|
|
@@ -151,6 +150,15 @@ def function_preamble(node, output, offset):
|
|
|
151
150
|
output.print('.pop()')
|
|
152
151
|
output.end_statement()
|
|
153
152
|
|
|
153
|
+
# Convert the plain JS kwargs object to a proper Python dict so that
|
|
154
|
+
# kw.items(), kw.keys(), etc. work in the function body.
|
|
155
|
+
# This must happen AFTER defaults/kwonly/starargs processing which rely on
|
|
156
|
+
# plain property access (kw.name) and ρσ_kwargs_symbol checks.
|
|
157
|
+
if a.kwargs:
|
|
158
|
+
output.indent()
|
|
159
|
+
output.spaced(kw, '=', 'ρσ_kwargs_to_dict(' + kw + ')')
|
|
160
|
+
output.end_statement()
|
|
161
|
+
|
|
154
162
|
def has_annotations(self):
|
|
155
163
|
if self.return_annotation:
|
|
156
164
|
return True
|
|
@@ -263,21 +271,10 @@ def function_definition(self, output, strip_first, as_expression):
|
|
|
263
271
|
if self.is_generator:
|
|
264
272
|
output.print('()'), output.space()
|
|
265
273
|
output.with_block(def():
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
print_bracketed(self, output, True, function_preamble)
|
|
271
|
-
else:
|
|
272
|
-
temp = OutputStream({'beautify':True})
|
|
273
|
-
temp.print('function* js_generator')
|
|
274
|
-
function_args(self.argnames, temp, strip_first)
|
|
275
|
-
print_bracketed(self, temp, True, function_preamble)
|
|
276
|
-
transpiled = regenerate(temp.get(), output.options.beautify).replace(/regeneratorRuntime.(wrap|mark)/g, 'ρσ_regenerator.regeneratorRuntime.$1')
|
|
277
|
-
if output.options.beautify:
|
|
278
|
-
ci = output.make_indent(0)
|
|
279
|
-
transpiled = [ci + x for x in transpiled.split('\n')].join('\n')
|
|
280
|
-
output.print(transpiled)
|
|
274
|
+
output.indent()
|
|
275
|
+
output.print('function* js_generator')
|
|
276
|
+
function_args(self.argnames, output, strip_first)
|
|
277
|
+
print_bracketed(self, output, True, function_preamble)
|
|
281
278
|
output.newline()
|
|
282
279
|
output.indent()
|
|
283
280
|
output.spaced('var', 'result', '=', 'js_generator.apply(this,', 'arguments)')
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
from __python__ import hash_literals
|
|
4
|
+
|
|
5
|
+
from ast import AST_String, AST_JSXText, AST_JSXSpread, AST_JSXExprContainer, is_node_type
|
|
6
|
+
|
|
7
|
+
def _is_component_tag(tag):
|
|
8
|
+
# Components start with uppercase or use dot notation (e.g. Router.Route)
|
|
9
|
+
first = tag[0]
|
|
10
|
+
return (first >= 'A' and first <= 'Z') or '.' in tag
|
|
11
|
+
|
|
12
|
+
def _needs_quoting(name):
|
|
13
|
+
# Attribute names containing non-identifier chars (e.g. aria-label) need quoting
|
|
14
|
+
return not v'/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)'
|
|
15
|
+
|
|
16
|
+
def _decode_html_entities(text):
|
|
17
|
+
# Decode HTML entities in a single pass to avoid double-decoding (e.g. &lt; -> <)
|
|
18
|
+
return text.replace(/&(?:#x([0-9a-fA-F]+)|#(\d+)|([a-zA-Z]+));/g, def(match, hex, dec, name):
|
|
19
|
+
if hex:
|
|
20
|
+
return String.fromCharCode(parseInt(hex, 16))
|
|
21
|
+
if dec:
|
|
22
|
+
return String.fromCharCode(parseInt(dec, 10))
|
|
23
|
+
if name is 'amp':
|
|
24
|
+
return '&'
|
|
25
|
+
if name is 'lt':
|
|
26
|
+
return '<'
|
|
27
|
+
if name is 'gt':
|
|
28
|
+
return '>'
|
|
29
|
+
if name is 'quot':
|
|
30
|
+
return '"'
|
|
31
|
+
if name is 'apos':
|
|
32
|
+
return "'"
|
|
33
|
+
if name is 'nbsp':
|
|
34
|
+
return '\u00a0'
|
|
35
|
+
return match
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def _normalize_jsx_whitespace(text):
|
|
39
|
+
# Implements the Babel JSX whitespace algorithm:
|
|
40
|
+
# - Split by newlines; trim leading whitespace from all lines except the first,
|
|
41
|
+
# trailing whitespace from all lines except the last.
|
|
42
|
+
# - Lines that are empty after trimming are dropped.
|
|
43
|
+
# - Remaining non-empty lines are joined; each line except the last non-empty
|
|
44
|
+
# gets a trailing space to separate it from the next.
|
|
45
|
+
lines = text.split('\n')
|
|
46
|
+
last_non_empty = -1
|
|
47
|
+
for i in range(lines.length):
|
|
48
|
+
if /[^ \t]/.test(lines[i]):
|
|
49
|
+
last_non_empty = i
|
|
50
|
+
result = ''
|
|
51
|
+
for i in range(lines.length):
|
|
52
|
+
line = lines[i].replace(/\t/g, ' ')
|
|
53
|
+
is_first = (i is 0)
|
|
54
|
+
is_last = (i is lines.length - 1)
|
|
55
|
+
if not is_first:
|
|
56
|
+
line = line.replace(/^[ ]+/, '')
|
|
57
|
+
if not is_last:
|
|
58
|
+
line = line.replace(/[ ]+$/, '')
|
|
59
|
+
if line:
|
|
60
|
+
if i is not last_non_empty:
|
|
61
|
+
line += ' '
|
|
62
|
+
result += line
|
|
63
|
+
return result
|
|
64
|
+
|
|
65
|
+
def _process_jsx_text(text):
|
|
66
|
+
text = _normalize_jsx_whitespace(text)
|
|
67
|
+
if text:
|
|
68
|
+
text = _decode_html_entities(text)
|
|
69
|
+
return text
|
|
70
|
+
|
|
71
|
+
def _print_tag(tag, output):
|
|
72
|
+
if _is_component_tag(tag):
|
|
73
|
+
output.print(tag)
|
|
74
|
+
else:
|
|
75
|
+
output.print('"')
|
|
76
|
+
output.print(tag)
|
|
77
|
+
output.print('"')
|
|
78
|
+
|
|
79
|
+
def _print_props(props, output):
|
|
80
|
+
if not props or not props.length:
|
|
81
|
+
output.print('null')
|
|
82
|
+
return
|
|
83
|
+
output.print('{')
|
|
84
|
+
first = True
|
|
85
|
+
for prop in props:
|
|
86
|
+
if not first:
|
|
87
|
+
output.print(', ')
|
|
88
|
+
first = False
|
|
89
|
+
if is_node_type(prop, AST_JSXSpread):
|
|
90
|
+
output.print('...')
|
|
91
|
+
prop.expression.print(output)
|
|
92
|
+
else:
|
|
93
|
+
if _needs_quoting(prop.name):
|
|
94
|
+
output.print('"')
|
|
95
|
+
output.print(prop.name)
|
|
96
|
+
output.print('"')
|
|
97
|
+
else:
|
|
98
|
+
output.print(prop.name)
|
|
99
|
+
output.print(': ')
|
|
100
|
+
if prop.value is None:
|
|
101
|
+
output.print('true')
|
|
102
|
+
elif is_node_type(prop.value, AST_String):
|
|
103
|
+
output.print_string(prop.value.value)
|
|
104
|
+
else:
|
|
105
|
+
prop.value.print(output)
|
|
106
|
+
output.print('}')
|
|
107
|
+
|
|
108
|
+
def _print_children(children, output):
|
|
109
|
+
for child in children:
|
|
110
|
+
if is_node_type(child, AST_JSXText):
|
|
111
|
+
text = _process_jsx_text(child.value)
|
|
112
|
+
if text:
|
|
113
|
+
output.print(', ')
|
|
114
|
+
output.print_string(text)
|
|
115
|
+
elif is_node_type(child, AST_JSXExprContainer):
|
|
116
|
+
output.print(', ')
|
|
117
|
+
child.expression.print(output)
|
|
118
|
+
else:
|
|
119
|
+
output.print(', ')
|
|
120
|
+
child.print(output)
|
|
121
|
+
|
|
122
|
+
def print_jsx_element(self, output):
|
|
123
|
+
output.print('React.createElement(')
|
|
124
|
+
_print_tag(self.tag, output)
|
|
125
|
+
output.print(', ')
|
|
126
|
+
_print_props(self.props, output)
|
|
127
|
+
if not self.self_closing:
|
|
128
|
+
_print_children(self.children, output)
|
|
129
|
+
output.print(')')
|
|
130
|
+
|
|
131
|
+
def print_jsx_fragment(self, output):
|
|
132
|
+
output.print('React.createElement(React.Fragment, null')
|
|
133
|
+
_print_children(self.children, output)
|
|
134
|
+
output.print(')')
|
|
135
|
+
|
|
136
|
+
def print_jsx_attribute(self, output):
|
|
137
|
+
# Handled directly by _print_props; kept for completeness
|
|
138
|
+
if _needs_quoting(self.name):
|
|
139
|
+
output.print('"')
|
|
140
|
+
output.print(self.name)
|
|
141
|
+
output.print('"')
|
|
142
|
+
else:
|
|
143
|
+
output.print(self.name)
|
|
144
|
+
if self.value is not None:
|
|
145
|
+
output.print(': ')
|
|
146
|
+
if is_node_type(self.value, AST_String):
|
|
147
|
+
output.print_string(self.value.value)
|
|
148
|
+
else:
|
|
149
|
+
self.value.print(output)
|
|
150
|
+
|
|
151
|
+
def print_jsx_spread(self, output):
|
|
152
|
+
# Handled directly by _print_props; kept for completeness
|
|
153
|
+
output.print('...')
|
|
154
|
+
self.expression.print(output)
|
|
155
|
+
|
|
156
|
+
def print_jsx_text(self, output):
|
|
157
|
+
# Handled directly by _print_children; kept for completeness
|
|
158
|
+
text = _process_jsx_text(self.value)
|
|
159
|
+
if text:
|
|
160
|
+
output.print_string(text)
|
|
161
|
+
|
|
162
|
+
def print_jsx_expr_container(self, output):
|
|
163
|
+
# Handled directly by _print_children; kept for completeness
|
|
164
|
+
self.expression.print(output)
|
package/src/output/literals.pyj
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
3
|
from __python__ import hash_literals
|
|
4
4
|
|
|
5
|
-
from ast import AST_Binary, AST_ObjectSpread, is_node_type
|
|
5
|
+
from ast import AST_Binary, AST_ObjectSpread, AST_Spread, AST_SetItem, is_node_type
|
|
6
6
|
|
|
7
7
|
def print_array(self, output):
|
|
8
8
|
output.print('ρσ_list_decorate')
|
|
@@ -15,7 +15,11 @@ def print_array(self, output):
|
|
|
15
15
|
for i, exp in enumerate(a):
|
|
16
16
|
if i:
|
|
17
17
|
output.comma()
|
|
18
|
-
exp
|
|
18
|
+
if is_node_type(exp, AST_Spread):
|
|
19
|
+
output.print('...')
|
|
20
|
+
exp.expression.print(output)
|
|
21
|
+
else:
|
|
22
|
+
exp.print(output)
|
|
19
23
|
if len_ > 0:
|
|
20
24
|
output.space()
|
|
21
25
|
)
|
|
@@ -78,6 +82,28 @@ def print_object(self, output):
|
|
|
78
82
|
output.print("Object.create(null)" if self.is_jshash else '{}')
|
|
79
83
|
|
|
80
84
|
def print_set(self, output):
|
|
85
|
+
# Check for spread items: {*a, 1, 2, *b}
|
|
86
|
+
has_spread = False
|
|
87
|
+
for item in self.items:
|
|
88
|
+
if is_node_type(item, AST_Spread):
|
|
89
|
+
has_spread = True
|
|
90
|
+
break
|
|
91
|
+
if has_spread:
|
|
92
|
+
# Compile as ρσ_set([...a, 1, 2, ...b])
|
|
93
|
+
output.print('ρσ_set')
|
|
94
|
+
output.with_parens(def():
|
|
95
|
+
output.with_square(def():
|
|
96
|
+
for i, item in enumerate(self.items):
|
|
97
|
+
if i:
|
|
98
|
+
output.comma()
|
|
99
|
+
if is_node_type(item, AST_Spread):
|
|
100
|
+
output.print('...')
|
|
101
|
+
item.expression.print(output)
|
|
102
|
+
else:
|
|
103
|
+
item.value.print(output)
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
return
|
|
81
107
|
if self.items.length is 0:
|
|
82
108
|
output.print('ρσ_set()')
|
|
83
109
|
return
|
package/src/output/loops.pyj
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# vim:fileencoding=utf-8
|
|
2
2
|
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
# globals: regenerate
|
|
4
3
|
from __python__ import hash_literals
|
|
5
4
|
|
|
6
5
|
from ast import AST_BaseCall, AST_SymbolRef, AST_Array, AST_Unary, AST_Number, has_calls, AST_Seq, AST_ListComprehension, AST_Starred, is_node_type
|
|
@@ -436,8 +435,6 @@ def print_list_comprehension(self, output):
|
|
|
436
435
|
output.with_block(def():
|
|
437
436
|
body_out = output
|
|
438
437
|
if is_generator:
|
|
439
|
-
if es5:
|
|
440
|
-
body_out = OutputStream({'beautify':True})
|
|
441
438
|
body_out.indent()
|
|
442
439
|
body_out.print('function* js_generator()'), body_out.space(), body_out.print('{')
|
|
443
440
|
body_out.newline()
|
|
@@ -485,12 +482,6 @@ def print_list_comprehension(self, output):
|
|
|
485
482
|
if is_generator:
|
|
486
483
|
output.set_indentation(previous_indentation)
|
|
487
484
|
body_out.newline(), body_out.indent(), body_out.print('}') # end js_generator
|
|
488
|
-
if es5:
|
|
489
|
-
transpiled = regenerate(body_out.get(), output.options.beautify).replace(/regeneratorRuntime.(wrap|mark)/g, 'ρσ_regenerator.regeneratorRuntime.$1')
|
|
490
|
-
if output.options.beautify:
|
|
491
|
-
ci = output.make_indent(0)
|
|
492
|
-
transpiled = [ci + x for x in transpiled.split('\n')].join('\n')
|
|
493
|
-
output.print(transpiled)
|
|
494
485
|
output.newline(), output.indent()
|
|
495
486
|
output.spaced('var', 'result', '=', 'js_generator.call(this)')
|
|
496
487
|
output.end_statement()
|
package/src/output/modules.pyj
CHANGED
|
@@ -18,7 +18,7 @@ def write_imports(module, output):
|
|
|
18
18
|
imports = []
|
|
19
19
|
for import_id in Object.keys(module.imports):
|
|
20
20
|
imports.push(module.imports[import_id])
|
|
21
|
-
imports.
|
|
21
|
+
imports.jssort(def(a, b):
|
|
22
22
|
a, b = a.import_order, b.import_order
|
|
23
23
|
return -1 if a < b else (1 if a > b else 0)
|
|
24
24
|
)
|
|
@@ -122,9 +122,6 @@ def prologue(module, output):
|
|
|
122
122
|
output.indent(), output.spaced('if(', 'typeof', 'HTMLCollection', '!==', '"undefined"', '&&', 'typeof', 'Symbol', '===', '"function")',
|
|
123
123
|
'NodeList.prototype[Symbol.iterator]', '=', 'HTMLCollection.prototype[Symbol.iterator]', '=', 'NamedNodeMap.prototype[Symbol.iterator]', '=', 'Array.prototype[Symbol.iterator]')
|
|
124
124
|
output.end_statement()
|
|
125
|
-
needs_yield = output.options.js_version < 6 and module.baselib['yield']
|
|
126
|
-
if needs_yield:
|
|
127
|
-
output.dump_yield()
|
|
128
125
|
# output the baselib
|
|
129
126
|
if not output.options.baselib_plain:
|
|
130
127
|
raise ValueError('The baselib is missing! Remember to set the baselib_plain field on the options for OutputStream')
|
|
@@ -186,7 +183,7 @@ def print_top_level(self, output):
|
|
|
186
183
|
write_imports(self, output)
|
|
187
184
|
write_main_name(output)
|
|
188
185
|
|
|
189
|
-
declare_vars(self.localvars, output)
|
|
186
|
+
declare_vars(self.localvars, output, "var" if output.options.repl_mode else "let")
|
|
190
187
|
display_body(self.body, True, output)
|
|
191
188
|
if self.comments_after and self.comments_after.length:
|
|
192
189
|
output_comments(self.comments_after, output)
|