Skip to content

Commit 3f280cd

Browse files
author
Yoshiki Shibukawa
committed
split and add jsx-profile-server command
1 parent 3ae600c commit 3f280cd

File tree

9 files changed

+9985
-92
lines changed

9 files changed

+9985
-92
lines changed

bin/jsx-profile-server

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#!/usr/bin/env node
2+
/***
3+
* JSX development server started by `make server`
4+
* includes JSX compiler for web (try/build/jsx-compiler.js).
5+
*
6+
*/
7+
8+
"use strict";
9+
10+
var http = require("http"),
11+
url = require("url"),
12+
path = require("path"),
13+
child_process = require("child_process"),
14+
fs = require("fs");
15+
16+
// version check
17+
try {
18+
var nodeVersionParts = process.version.match(/(\d+)/g);
19+
var nodeVersion = (+nodeVersionParts[0]) + (nodeVersionParts[1] / 1000) + (nodeVersionParts[2]/ (1000*1000));
20+
if(nodeVersion < 0.006) {
21+
throw new Error("Requires nodejs v0.6.0 or later");
22+
}
23+
}
24+
catch(e) {
25+
console.warn("Unexpected node.js version (>=0.6.0 required), because: %s", e.toString());
26+
}
27+
28+
function homeDir() {
29+
if (process.env.HOME) {
30+
return process.env.HOME;
31+
}
32+
return process.env.USERPROFILE;
33+
}
34+
35+
function mkdir(dir) {
36+
try {
37+
fs.mkdirSync(dir);
38+
} catch (e) {
39+
// FIXME ignore EEXIST only, but how?
40+
}
41+
}
42+
43+
function finish(response, uri, status, content_type, content) {
44+
var len = content.length;
45+
46+
var headers = {
47+
"Cache-Control" : "no-cache",
48+
"Content-Length" : len
49+
};
50+
if(content_type) {
51+
headers["Content-Type"] = content_type;
52+
}
53+
else if(/\.jsx$/.test(uri)) {
54+
headers["Content-Type"] = "text/plain";
55+
}
56+
else if(/\.js$/.test(uri)) {
57+
headers["Content-Type"] = "application/javascript";
58+
}
59+
else if(/\.css$/.test(uri)) {
60+
headers["Content-Type"] = "text/css";
61+
}
62+
else if(/\.png$/.test(uri)) {
63+
headers["Content-Type"] = "image/png";
64+
}
65+
else if(/\.jpe?g$/.test(uri)) {
66+
headers["Content-Type"] = "image/jpeg";
67+
}
68+
else if(/\//.test(uri) || /\.html$/.test(uri)) {
69+
headers["Content-Type"] = "text/html";
70+
}
71+
72+
console.log("%s %s %s %s (%s bytes)", (new Date()).toISOString(), status, headers["Content-Type"] || "(unknown type)", uri, len);
73+
74+
response.writeHead(status, headers);
75+
response.write(content, "binary");
76+
response.end();
77+
}
78+
79+
function serveFile(response, uri, filename) {
80+
fs.exists(filename, function(exists) {
81+
if(!exists) {
82+
finish(response, uri, 404, "text/plain", "404 Not Found\n");
83+
return;
84+
}
85+
86+
if (fs.statSync(filename).isDirectory()) {
87+
filename += '/index.html';
88+
}
89+
90+
fs.readFile(filename, "binary", function(err, content) {
91+
if(err) {
92+
finish(response, uri, 500, "text/plain", err + "\n");
93+
return;
94+
}
95+
96+
finish(response, uri, 200, undefined, content);
97+
});
98+
});
99+
}
100+
101+
function saveProfile(request, response) {
102+
response.setHeader("Access-Control-Allow-Origin", "*");
103+
response.setHeader("Access-Control-Allow-Methods", "POST,PUT,GET,OPTIONS");
104+
response.setHeader("Access-Control-Allow-Headers", "Content-Type,*");
105+
console.log(request.method);
106+
if (request.method != "POST" || request.method == "PUT") {
107+
response.end();
108+
return;
109+
}
110+
111+
function twodigits(s) {
112+
s = s.toString();
113+
while (s.length < 2) {
114+
s = "0" + s;
115+
}
116+
return s;
117+
}
118+
function YYYYmmddHHMMSS() {
119+
var d = new Date();
120+
return d.getFullYear() + '-' +
121+
twodigits(d.getMonth() + 1) + '-' +
122+
twodigits(d.getDate()) + '-' +
123+
twodigits(d.getHours()) +
124+
twodigits(d.getMinutes()) +
125+
twodigits(d.getSeconds());
126+
}
127+
128+
var body = "";
129+
// accumulate all data
130+
request.on("data", function (data) {
131+
body += data;
132+
});
133+
request.on("end", function () {
134+
// parse as JSON
135+
try {
136+
var json = JSON.parse(body);
137+
} catch (e) {
138+
response.writeHead(400, "Bad Request", {
139+
"Content-Type": "text/plain"
140+
});
141+
response.write("POST data is corrupt: " + e.toString());
142+
response.end();
143+
return;
144+
}
145+
// save
146+
var home = homeDir();
147+
mkdir(path.join(home, '.jsx'));
148+
mkdir(path.join(home, '.jsx', 'profile'));
149+
var id = YYYYmmddHHMMSS();
150+
console.log(id);
151+
152+
fs.writeFileSync(path.join(home, '.jsx', 'profile', id + '.json'), JSON.stringify(json));
153+
// send response
154+
response.writeHead(200, "OK", {
155+
"Location" : "http://" + request.headers.host + "/index.html?" + id,
156+
"Content-Type": "text/plain"
157+
});
158+
response.write("saved profile at http://" + request.headers.host + "/index.html?" + id);
159+
response.end();
160+
161+
console.info("[I] saved profile at http://" + request.headers.host + "/index.html?" + id);
162+
});
163+
}
164+
165+
function listProfileResults(request, response) {
166+
var home = homeDir();
167+
var profileDir = path.join(home, '.jsx', 'profile');
168+
var results = [];
169+
if (fs.existsSync(profileDir)) {
170+
results = fs.readdirSync(profileDir).filter(function (file) {
171+
return /\d{4}-\d{2}-\d{2}-\d{6}/.test(file);
172+
}).map(function (file) {
173+
return file.replace(/\.\w+$/, "");
174+
}).sort(function (a, b) {
175+
return b.localeCompare(a)
176+
});
177+
}
178+
response.writeHead(200, "OK", {
179+
"Content-Type": "application/json"
180+
});
181+
response.write(JSON.stringify(results), "utf8");
182+
response.end();
183+
}
184+
185+
function main(args) {
186+
var port = args[0] || "2012";
187+
188+
var httpd = http.createServer(function(request, response) {
189+
var uri = url.parse(request.url).pathname;
190+
if(uri === "/") {
191+
uri = 'index.html';
192+
}
193+
194+
// profiler stuff
195+
var filepath;
196+
if (/^\/post-profile\/?$/.test(uri)) {
197+
console.log("save-profile");
198+
return saveProfile(request, response);
199+
}
200+
else if (/\/\.profile\/results\.json$/.test(uri)) {
201+
console.log("list-profile");
202+
return listProfileResults(request, response);
203+
}
204+
else if (/\/\.profile\/\d{4}-\d{2}-\d{2}-\d{6}\.json/.test(uri)) {
205+
filepath = path.resolve(homeDir(), '.jsx', 'profile', uri.match(/\d{4}-\d{2}-\d{2}-\d{6}.json/)[0]);
206+
}
207+
else if (uri[0] === '/') {
208+
uri = uri.slice(1);
209+
filepath = path.resolve(__dirname, '..', 'etc', 'profiler', uri);
210+
}
211+
serveFile(response, uri, filepath);
212+
});
213+
httpd.listen(parseInt(port, 10));
214+
215+
console.log("Open http://localhost:" + port + "/");
216+
}
217+
218+
main(process.argv.slice(2));
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* jQuery treeTable stylesheet
2+
*
3+
* This file contains styles that are used to display the tree table. Each tree
4+
* table is assigned the +treeTable+ class.
5+
* ========================================================================= */
6+
7+
/* jquery.treeTable.collapsible
8+
* ------------------------------------------------------------------------- */
9+
.treeTable tr td .expander {
10+
cursor: pointer;
11+
padding: 0;
12+
zoom: 1; /* IE7 Hack */
13+
}
14+
15+
.treeTable tr td a.expander {
16+
background-position: left center;
17+
background-repeat: no-repeat;
18+
color: #000;
19+
text-decoration: none;
20+
}
21+
22+
.treeTable tr.collapsed td a.expander {
23+
background-image: url(../img/jquery-treetable/toggle-expand-dark.png);
24+
}
25+
26+
.treeTable tr.expanded td a.expander {
27+
background-image: url(../img/jquery-treetable/toggle-collapse-dark.png);
28+
}
29+
30+
/* jquery.treeTable.sortable
31+
* ------------------------------------------------------------------------- */
32+
.treeTable tr.selected, .treeTable tr.accept {
33+
background-color: #3875d7;
34+
}
35+
36+
.treeTable tr.selected a.expander, .treeTable tr.accept a.expander {
37+
color: #fff;
38+
}
39+
40+
.treeTable tr.collapsed.selected td a.expander, .treeTable tr.collapsed.accept td a.expander {
41+
background-image: url(../images/toggle-expand-light.png);
42+
}
43+
44+
.treeTable tr.expanded.selected td a.expander, .treeTable tr.expanded.accept td a.expander {
45+
background-image: url(../images/toggle-collapse-light.png);
46+
}
47+
48+
.treeTable .ui-draggable-dragging {
49+
color: #000;
50+
z-index: 1;
51+
}
52+
53+
/* Layout helper taken from jQuery UI. This way I don't have to require the
54+
* full jQuery UI CSS to be loaded. */
55+
.ui-helper-hidden { display: none; }
Loading
Loading

0 commit comments

Comments
 (0)