Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/javascript/private/closure_make_deps.py
8666 views
1
# Licensed to the Software Freedom Conservancy (SFC) under one
2
# or more contributor license agreements. See the NOTICE file
3
# distributed with this work for additional information
4
# regarding copyright ownership. The SFC licenses this file
5
# to you under the Apache License, Version 2.0 (the
6
# "License"); you may not use this file except in compliance
7
# with the License. You may obtain a copy of the License at
8
#
9
# http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing,
12
# software distributed under the License is distributed on an
13
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
# KIND, either express or implied. See the License for the
15
# specific language governing permissions and limitations
16
# under the License.
17
18
"""Generate a Closure deps.js file by scanning JS sources for goog.provide/require/module calls.
19
20
Replaces the Node.js closure-make-deps wrapper to avoid npm symlink issues on Windows.
21
22
Usage: closure_make_deps.py <files_list> <output> <closure_path>
23
files_list - path to a file containing one JS source path per line
24
output - path to write the generated deps.js
25
closure_path - directory containing Closure Library's base.js (for computing relative paths)
26
"""
27
28
import os
29
import re
30
import sys
31
32
PROVIDE_RE = re.compile(r"goog\.provide\(\s*['\"]([^'\"]+)['\"]\s*\)")
33
MODULE_RE = re.compile(r"goog\.module\(\s*['\"]([^'\"]+)['\"]\s*\)")
34
REQUIRE_RE = re.compile(r"goog\.require\(\s*['\"]([^'\"]+)['\"]\s*\)")
35
36
37
def strip_comments(content):
38
"""Remove JS comments so regexes don't match goog.require() in documentation."""
39
content = re.sub(r"/\*.*?\*/", "", content, flags=re.DOTALL)
40
content = re.sub(r"//[^\n]*", "", content)
41
return content
42
43
44
def parse_js_file(path):
45
"""Extract goog.provide, goog.module, and goog.require namespaces from a JS file."""
46
with open(path, encoding="utf-8") as f:
47
content = f.read()
48
49
cleaned = strip_comments(content)
50
51
provides = sorted(PROVIDE_RE.findall(cleaned))
52
modules = sorted(MODULE_RE.findall(cleaned))
53
requires = sorted(REQUIRE_RE.findall(cleaned))
54
55
is_module = len(modules) > 0
56
all_provides = sorted(set(provides + modules))
57
58
return all_provides, requires, is_module
59
60
61
def main():
62
if len(sys.argv) < 4:
63
print(
64
"Usage: closure_make_deps.py <files_list> <output> <closure_path>",
65
file=sys.stderr,
66
)
67
sys.exit(1)
68
69
files_list_path = sys.argv[1]
70
output_path = sys.argv[2]
71
closure_path = sys.argv[3]
72
73
with open(files_list_path, encoding="utf-8") as f:
74
files = [line.strip() for line in f if line.strip()]
75
76
lines = []
77
for filepath in files:
78
provides, requires, is_module = parse_js_file(filepath)
79
80
rel_path = os.path.relpath(filepath, closure_path)
81
# deps.js is consumed in the browser, so always use forward slashes
82
rel_path = rel_path.replace(os.sep, "/")
83
84
provides_str = ", ".join(f"'{p}'" for p in provides)
85
requires_str = ", ".join(f"'{r}'" for r in requires)
86
87
if is_module:
88
line = f"goog.addDependency('{rel_path}', [{provides_str}], [{requires_str}], {{'module': 'goog'}});"
89
else:
90
line = f"goog.addDependency('{rel_path}', [{provides_str}], [{requires_str}]);"
91
92
lines.append((rel_path, line))
93
94
# Sort by relative path for deterministic output
95
lines.sort(key=lambda x: x[0])
96
97
with open(output_path, "w", encoding="utf-8") as f:
98
for _, line in lines:
99
f.write(line + "\n")
100
101
102
if __name__ == "__main__":
103
main()
104
105