1 module jssplitter;
2 
3 import std.array;
4 import std.algorithm;
5 import std.stdio;
6 import std..string;
7 import std.json;
8 
9 enum Type {
10 	undefined,
11 	strings,
12 	call,
13 	json,
14 	digit,
15 	mustache,
16 	unknown,
17 }
18 
19 Type findType(string[] lines) {
20 	Type type = Type.undefined;
21 	foreach(l; lines) {
22 		bool isCall = l.indexOf("#{") != -1;
23 		bool isMustache = l.indexOf("{{") != -1;
24 		bool isJson = l.endsWith(": {") || l.endsWith(": [");
25 		bool isDigit = l.indexOf("##") != -1 || l.indexOf(".#") != -1;
26 
27 		Type t;
28 		if(isCall && !isMustache && !isJson && !isDigit) {
29 			t = Type.call;
30 		} else if(!isCall && isMustache && !isJson && !isDigit) {
31 			t = Type.mustache;
32 		} else if(!isCall && !isMustache && isJson && !isDigit) {
33 			t = Type.json;
34 		} else if(!isCall && !isMustache && !isJson && isDigit) {
35 			t = Type.digit;
36 		} else {
37 			t = Type.strings;
38 		}
39 
40 		//writefln("%20s %s", t, l);
41 
42 		if(type == Type.undefined) {
43 			type = t;
44 			continue;
45 		} else if(t != type && type != Type.json) {
46 			type = Type.unknown;
47 			break;
48 		}
49 	}
50 	return type;
51 }
52 
53 string removeLicense(string code) {
54 	if(code.startsWith("/*")) {
55 		code = code[code.indexOf("*/", 2) + 2 .. $].stripLeft();
56 	}
57 	return code;
58 }
59 
60 struct TypeLines {
61 	Type type;
62 	string[] lines;
63 }
64 
65 TypeLines jssplit(string input) {
66 	string[] lines = split(input.removeLicense(), "\n")
67 		.map!(a => a.strip("\", \t\n\r"))
68 		.filter!(a => !a.empty && !a.startsWith("//"))
69 		.array;
70 
71 	if(lines.length < 3) {
72 		//writeln("\t\tshort");
73 		return TypeLines(Type.undefined, []);
74 	}
75 	assert(lines.front.startsWith("module[\"exports\"] = ")
76 				|| lines.front.startsWith("module.exports = ")
77 				|| lines.front.startsWith("module['exports'] = ")
78 			, lines.front ~ "\n" ~ input);
79 	lines = lines[1 .. $]
80 		.map!(a => {
81 			if(!a.empty && a[$ - 1] == '\'') {
82 				a = a[0 .. $ - 1];
83 			}
84 			if(!a.empty && a[0] == '\'') {
85 				a = a[1 .. $];
86 			}
87 			return a;
88 		}())
89 		.array;
90 	//writeln(lines);
91 	assert(lines.back.startsWith("];")
92             || lines.back.startsWith("}")
93             || lines.back.startsWith("]"),
94 			lines.back ~ "\n" ~ input);
95 	lines = lines[0 .. $ - 1];
96 
97 	Type type = findType(lines);
98 	if(type == Type.unknown) {
99 		//writefln("unknown %(%s\n%)", lines);
100 	}
101 
102 	return TypeLines(type, lines);
103 }