-
Notifications
You must be signed in to change notification settings - Fork 27
/
nuvolamergejs.py
executable file
·125 lines (105 loc) · 4.42 KB
/
nuvolamergejs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/python
# coding: utf-8
# Copyright 2014-2019 Jiří Janoušek <janousek.jiri@gmail.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
from codecs import open
class Source:
def __init__(self, name, path, requires, data):
self.path = path
self.name = name
self.requires = requires
self.data = data
self.merged = False
self.visited = 0
class RecursionError(Exception):
def __init__(self, path):
Exception.__init__(self, "Maximal recursion depth reached at '%s'." % path)
class ParseError(Exception):
def __init__(self, path, lineno, line):
Exception.__init__(self, "Parse error %s:%d %s" % (path, lineno, line))
class NotFoundError(Exception):
def __init__(self, path, requirement):
Exception.__init__(self, "File '%s' requires dependency '%s' that hasn't been found." % (path, requirement))
def parse_sources(files):
sources = {}
for path in files:
name = os.path.basename(path).rsplit(".", 1)[0]
requires = []
data = []
head = True
with open(path, encoding="utf-8") as f:
lineno = 0
for line in f:
bare_line = line.strip()
lineno += 1
if bare_line and not bare_line.startswith(("/*", "*", "//")):
if head:
if bare_line.startswith("require("):
for q in ('"', "'"):
parts = bare_line.split(q)
if len(parts) == 3:
requires.append(parts[1])
break
else:
raise ParseError(path, lineno, bare_line)
else:
head = False
data.append(line)
else:
data.append(line)
sources[name] = Source(name, path, requires, data)
return sources
def add_source(output, sources, source):
source.visited += 1
if source.visited > 25:
raise RecursionError(source.path)
if not source.merged:
for dep_name in source.requires:
dep_source = sources.get(dep_name)
if not dep_source:
raise NotFoundError(source.path, dep_name)
add_source(output, sources, dep_source)
if not source.merged:
output.append("// Included file '%s'\n" % source.path)
output.extend(source.data)
source.merged = True
def merge_sources(sources, main):
output = [
"var global = (function (){return (function(){return this;}).call(null);})();\n",
"(function(Nuvola)\n{\n 'use strict';\n"]
main = sources.get(main)
if main:
add_source(output, sources, main)
for source in sources.values():
add_source(output, sources, source)
output.append("})(this); // function(Nuvola)\n")
return "".join(output)
def mergejs(sources, main="main"):
sources = parse_sources(sources)
output = merge_sources(sources, main)
return output
if __name__ == "__main__":
import sys
files = sys.argv[1:]
output = mergejs(files)
print(output)