mapshaper 0.7.19 → 0.7.21
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/bin/mapshaper-gui +47 -3
- package/mapshaper.js +377 -52
- package/package.json +2 -2
- package/www/mapshaper-gui.js +121 -52
- package/www/mapshaper.js +377 -52
- package/www/modules.js +71 -0
- package/www/page.css +2 -0
- package/www/sponsor.html +3 -5
package/bin/mapshaper-gui
CHANGED
|
@@ -14,6 +14,7 @@ var defaultPort = 5555,
|
|
|
14
14
|
.option('-n, --name <name(s)>', 'rename input layer or layers')
|
|
15
15
|
.option('-c, --commands <string>', 'console commands to run initially')
|
|
16
16
|
.option('-t, --target <name>', 'name of layer to select initially')
|
|
17
|
+
.option('-w, --watch', 'watch input files and reload the browser on change')
|
|
17
18
|
.addOption(new commander.Option('-b, --blurb <text>',
|
|
18
19
|
'replace the default blurb on the import screen').hideHelp())
|
|
19
20
|
.argument('[file...]', 'data files to load')
|
|
@@ -30,9 +31,26 @@ var defaultPort = 5555,
|
|
|
30
31
|
port = parseInt(opts.port, 10) || defaultPort,
|
|
31
32
|
dataFiles = expandShapefiles(program.args),
|
|
32
33
|
probeCount = 0,
|
|
33
|
-
sessionId = null
|
|
34
|
+
sessionId = null,
|
|
35
|
+
sseClients = [],
|
|
36
|
+
reloadTimer = null;
|
|
34
37
|
validateFiles(dataFiles);
|
|
35
38
|
|
|
39
|
+
if (opts.watch && dataFiles.length > 0) {
|
|
40
|
+
dataFiles.forEach(function(file) {
|
|
41
|
+
if (isUrl(file)) return;
|
|
42
|
+
fs.watch(file, function() {
|
|
43
|
+
// debounce: editors often write files in multiple steps
|
|
44
|
+
clearTimeout(reloadTimer);
|
|
45
|
+
reloadTimer = setTimeout(function() {
|
|
46
|
+
sseClients.forEach(function(res) {
|
|
47
|
+
try { res.write('event: reload\ndata: changed\n\n'); } catch(e) {}
|
|
48
|
+
});
|
|
49
|
+
}, 150);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
36
54
|
process.on('uncaughtException', function(err) {
|
|
37
55
|
// added 'code' for Node.js v16
|
|
38
56
|
if (err.errno === 'EADDRINUSE' || err.code === 'EADDRINUSE') {
|
|
@@ -99,6 +117,18 @@ function startServer(port) {
|
|
|
99
117
|
serveFile(getDataFilePath(uri), response);
|
|
100
118
|
} else if (uri.indexOf('/save') === 0) {
|
|
101
119
|
saveContent(request, response);
|
|
120
|
+
} else if (uri == '/sse' && opts.watch) {
|
|
121
|
+
// Server-Sent Events endpoint for file-watch reload notifications
|
|
122
|
+
response.writeHead(200, {
|
|
123
|
+
'Content-Type': 'text/event-stream',
|
|
124
|
+
'Cache-Control': 'no-cache',
|
|
125
|
+
'Connection': 'keep-alive'
|
|
126
|
+
});
|
|
127
|
+
response.write('data: connected\n\n');
|
|
128
|
+
sseClients.push(response);
|
|
129
|
+
request.on('close', function() {
|
|
130
|
+
sseClients = sseClients.filter(function(c) { return c !== response; });
|
|
131
|
+
});
|
|
102
132
|
} else {
|
|
103
133
|
// serve a file from the web root. Translate directory paths (any URI
|
|
104
134
|
// ending in '/') to their index.html so that links like '/docs/' work
|
|
@@ -106,7 +136,21 @@ function startServer(port) {
|
|
|
106
136
|
if (uri.endsWith('/')) {
|
|
107
137
|
uri += 'index.html';
|
|
108
138
|
}
|
|
109
|
-
|
|
139
|
+
if (opts.watch && uri == '/index.html') {
|
|
140
|
+
// inject SSE reload script into index.html
|
|
141
|
+
var htmlPath = getAssetFilePath('/index.html');
|
|
142
|
+
fs.readFile(htmlPath, 'utf8', function(err, content) {
|
|
143
|
+
if (err) return serve404(response);
|
|
144
|
+
var script = '<script>(function(){' +
|
|
145
|
+
'var es=new EventSource("/sse");' +
|
|
146
|
+
'es.addEventListener("reload",function(){location.reload();});' +
|
|
147
|
+
'})();</script>';
|
|
148
|
+
content = content.replace('</body>', script + '\n</body>');
|
|
149
|
+
serveContent(content, response, 'text/html');
|
|
150
|
+
});
|
|
151
|
+
} else {
|
|
152
|
+
serveFile(getAssetFilePath(uri), response);
|
|
153
|
+
}
|
|
110
154
|
}
|
|
111
155
|
}).listen(port, 'localhost', function() {
|
|
112
156
|
if (process.env.MAPSHAPER_GUI_NO_OPEN) return;
|
|
@@ -165,7 +209,7 @@ function serveContent(content, response, mimeType) {
|
|
|
165
209
|
}
|
|
166
210
|
response.setHeader('Cache-Control', 'no-cache');
|
|
167
211
|
response.writeHead(200);
|
|
168
|
-
response.write(content, "
|
|
212
|
+
response.write(content, Buffer.isBuffer(content) ? undefined : "utf8");
|
|
169
213
|
response.end();
|
|
170
214
|
}
|
|
171
215
|
|