{build,wasmserve}: improvements
build: use parseIp4 instead resolveIp wasmserve: use ansi_to_html.js instead ansi_up.js wasmserve: handle build procces unexpected exits and more
This commit is contained in:
parent
b0cd4ec1a0
commit
8b50f076a6
5 changed files with 109 additions and 497 deletions
13
build.zig
13
build.zig
|
|
@ -107,6 +107,7 @@ pub fn build(b: *std.build.Builder) void {
|
||||||
.target = target,
|
.target = target,
|
||||||
.deps = example.packages,
|
.deps = example.packages,
|
||||||
.res_dirs = if (example.has_assets) &.{"examples/" ++ example.name ++ "/assets"} else null,
|
.res_dirs = if (example.has_assets) &.{"examples/" ++ example.name ++ "/assets"} else null,
|
||||||
|
.watch_paths = &.{"examples/" ++ example.name},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
example_app.setBuildMode(mode);
|
example_app.setBuildMode(mode);
|
||||||
|
|
@ -227,6 +228,7 @@ pub const App = struct {
|
||||||
step: *std.build.LibExeObjStep,
|
step: *std.build.LibExeObjStep,
|
||||||
platform: Platform,
|
platform: Platform,
|
||||||
res_dirs: ?[]const []const u8,
|
res_dirs: ?[]const []const u8,
|
||||||
|
watch_paths: ?[]const []const u8,
|
||||||
|
|
||||||
pub const Platform = enum {
|
pub const Platform = enum {
|
||||||
native,
|
native,
|
||||||
|
|
@ -244,6 +246,7 @@ pub const App = struct {
|
||||||
target: std.zig.CrossTarget,
|
target: std.zig.CrossTarget,
|
||||||
deps: ?[]const Pkg = null,
|
deps: ?[]const Pkg = null,
|
||||||
res_dirs: ?[]const []const u8 = null,
|
res_dirs: ?[]const []const u8 = null,
|
||||||
|
watch_paths: ?[]const []const u8 = null,
|
||||||
}) App {
|
}) App {
|
||||||
const target = (std.zig.system.NativeTargetInfo.detect(options.target) catch unreachable).target;
|
const target = (std.zig.system.NativeTargetInfo.detect(options.target) catch unreachable).target;
|
||||||
const platform = Platform.fromTarget(target);
|
const platform = Platform.fromTarget(target);
|
||||||
|
|
@ -297,6 +300,7 @@ pub const App = struct {
|
||||||
.name = options.name,
|
.name = options.name,
|
||||||
.platform = platform,
|
.platform = platform,
|
||||||
.res_dirs = options.res_dirs,
|
.res_dirs = options.res_dirs,
|
||||||
|
.watch_paths = options.watch_paths,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -367,14 +371,17 @@ pub const App = struct {
|
||||||
const address = std.process.getEnvVarOwned(app.b.allocator, "MACH_ADDRESS") catch app.b.allocator.dupe(u8, "127.0.0.1") catch unreachable;
|
const address = std.process.getEnvVarOwned(app.b.allocator, "MACH_ADDRESS") catch app.b.allocator.dupe(u8, "127.0.0.1") catch unreachable;
|
||||||
const port = std.process.getEnvVarOwned(app.b.allocator, "MACH_PORT") catch app.b.allocator.dupe(u8, "8080") catch unreachable;
|
const port = std.process.getEnvVarOwned(app.b.allocator, "MACH_PORT") catch app.b.allocator.dupe(u8, "8080") catch unreachable;
|
||||||
const address_parsed = std.net.Address.resolveIp(address, std.fmt.parseInt(u16, port, 10) catch unreachable) catch unreachable;
|
const address_parsed = std.net.Address.resolveIp(address, std.fmt.parseInt(u16, port, 10) catch unreachable) catch unreachable;
|
||||||
|
|
||||||
const wasmserve = @import("tools/wasmserve/wasmserve.zig");
|
const wasmserve = @import("tools/wasmserve/wasmserve.zig");
|
||||||
|
const install_step_name = if (std.mem.startsWith(u8, app.step.name, "example-"))
|
||||||
|
app.step.name
|
||||||
|
else
|
||||||
|
null;
|
||||||
const serve_step = wasmserve.serve(
|
const serve_step = wasmserve.serve(
|
||||||
app.step,
|
app.step,
|
||||||
.{
|
.{
|
||||||
.install_step_name = app.step.name,
|
.install_step_name = install_step_name,
|
||||||
.install_dir = web_install_dir,
|
.install_dir = web_install_dir,
|
||||||
.watch_paths = &.{"tools/wasmserve/wasmserve.zig"},
|
.watch_paths = app.watch_paths,
|
||||||
.listen_address = address_parsed,
|
.listen_address = address_parsed,
|
||||||
},
|
},
|
||||||
) catch unreachable;
|
) catch unreachable;
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ const esc = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
install_step_name: []const u8 = "install",
|
install_step_name: ?[]const u8 = null,
|
||||||
install_dir: ?build.InstallDir = null,
|
install_dir: ?build.InstallDir = null,
|
||||||
watch_paths: []const []const u8 = &.{},
|
watch_paths: ?[]const []const u8 = null,
|
||||||
listen_address: net.Address = net.Address.initIp4([4]u8{ 127, 0, 0, 1 }, 8080),
|
listen_address: ?net.Address = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn serve(step: *build.LibExeObjStep, options: Options) !*Wasmserve {
|
pub fn serve(step: *build.LibExeObjStep, options: Options) !*Wasmserve {
|
||||||
|
|
@ -31,15 +31,15 @@ pub fn serve(step: *build.LibExeObjStep, options: Options) !*Wasmserve {
|
||||||
.step = build.Step.init(.run, "wasmserve", step.builder.allocator, Wasmserve.make),
|
.step = build.Step.init(.run, "wasmserve", step.builder.allocator, Wasmserve.make),
|
||||||
.b = step.builder,
|
.b = step.builder,
|
||||||
.exe_step = step,
|
.exe_step = step,
|
||||||
.install_step_name = options.install_step_name,
|
.install_step_name = options.install_step_name orelse step.builder.getInstallStep().name,
|
||||||
.install_dir = install_dir,
|
.install_dir = install_dir,
|
||||||
.install_dir_iter = try fs.cwd().makeOpenPathIterable(step.builder.getInstallPath(install_dir, ""), .{}),
|
.install_dir_iter = try fs.cwd().makeOpenPathIterable(step.builder.getInstallPath(install_dir, ""), .{}),
|
||||||
.address = options.listen_address,
|
.address = options.listen_address orelse net.Address.initIp4([4]u8{ 127, 0, 0, 1 }, 8080),
|
||||||
.subscriber = null,
|
.subscriber = null,
|
||||||
.watch_paths = options.watch_paths,
|
.watch_paths = options.watch_paths orelse &.{"src"},
|
||||||
.mtimes = std.AutoHashMap(fs.File.INode, i128).init(step.builder.allocator),
|
.mtimes = std.AutoHashMap(fs.File.INode, i128).init(step.builder.allocator),
|
||||||
.status = .idle,
|
.notify_msg = null,
|
||||||
.notify_msg = try step.builder.allocator.alloc(u8, 0),
|
.build_per_stop_count = 0,
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
@ -55,13 +55,18 @@ const Wasmserve = struct {
|
||||||
subscriber: ?*net.StreamServer.Connection,
|
subscriber: ?*net.StreamServer.Connection,
|
||||||
watch_paths: []const []const u8,
|
watch_paths: []const []const u8,
|
||||||
mtimes: std.AutoHashMap(fs.File.INode, i128),
|
mtimes: std.AutoHashMap(fs.File.INode, i128),
|
||||||
status: Status,
|
notify_msg: ?NotifyMessage,
|
||||||
notify_msg: []u8,
|
build_per_stop_count: u5,
|
||||||
|
|
||||||
const Status = enum {
|
const NotifyMessage = struct {
|
||||||
idle,
|
const Event = enum {
|
||||||
built,
|
built,
|
||||||
build_error,
|
build_error,
|
||||||
|
stopped,
|
||||||
|
};
|
||||||
|
|
||||||
|
event: Event,
|
||||||
|
data: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn make(step: *build.Step) !void {
|
pub fn make(step: *build.Step) !void {
|
||||||
|
|
@ -132,6 +137,8 @@ const Wasmserve = struct {
|
||||||
_ = try conn.stream.write("HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Type: text/event-stream\r\nCache-Control: No-Cache\r\n\r\n");
|
_ = try conn.stream.write("HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Type: text/event-stream\r\nCache-Control: No-Cache\r\n\r\n");
|
||||||
self.subscriber = try self.b.allocator.create(net.StreamServer.Connection);
|
self.subscriber = try self.b.allocator.create(net.StreamServer.Connection);
|
||||||
self.subscriber.?.* = conn;
|
self.subscriber.?.* = conn;
|
||||||
|
if (self.notify_msg) |msg|
|
||||||
|
if (msg.event != .built)
|
||||||
self.notify();
|
self.notify();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -168,23 +175,7 @@ const Wasmserve = struct {
|
||||||
"\r\n",
|
"\r\n",
|
||||||
.{ file_size, file_mime },
|
.{ file_size, file_mime },
|
||||||
);
|
);
|
||||||
|
try fs.File.writeFileAll(.{ .handle = stream.handle }, file, .{});
|
||||||
const zero_iovec = &[0]std.os.iovec_const{};
|
|
||||||
var send_total: usize = 0;
|
|
||||||
while (true) {
|
|
||||||
const send_len = try std.os.sendfile(
|
|
||||||
stream.handle,
|
|
||||||
file.handle,
|
|
||||||
send_total,
|
|
||||||
file_size,
|
|
||||||
zero_iovec,
|
|
||||||
zero_iovec,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
if (send_len == 0)
|
|
||||||
break;
|
|
||||||
send_total += send_len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn respondError(stream: net.Stream, code: u32, desc: []const u8) !void {
|
fn respondError(stream: net.Stream, code: u32, desc: []const u8) !void {
|
||||||
|
|
@ -213,7 +204,7 @@ const Wasmserve = struct {
|
||||||
timer_loop: while (true) : (std.time.sleep(100 * std.time.ns_per_ms)) {
|
timer_loop: while (true) : (std.time.sleep(100 * std.time.ns_per_ms)) {
|
||||||
for (self.watch_paths) |path| {
|
for (self.watch_paths) |path| {
|
||||||
var dir = fs.cwd().openIterableDir(path, .{}) catch {
|
var dir = fs.cwd().openIterableDir(path, .{}) catch {
|
||||||
if (self.checkForUpdate(path)) |is_updated| {
|
if (self.checkForUpdate(fs.cwd(), path)) |is_updated| {
|
||||||
if (is_updated)
|
if (is_updated)
|
||||||
continue :timer_loop;
|
continue :timer_loop;
|
||||||
} else |err| logErr(err, @src());
|
} else |err| logErr(err, @src());
|
||||||
|
|
@ -230,7 +221,7 @@ const Wasmserve = struct {
|
||||||
continue;
|
continue;
|
||||||
}) |walk_entry| {
|
}) |walk_entry| {
|
||||||
if (walk_entry.kind != .File) continue;
|
if (walk_entry.kind != .File) continue;
|
||||||
if (self.checkForUpdate(walk_entry.path)) |is_updated| {
|
if (self.checkForUpdate(dir.dir, walk_entry.path)) |is_updated| {
|
||||||
if (is_updated)
|
if (is_updated)
|
||||||
continue :timer_loop;
|
continue :timer_loop;
|
||||||
} else |err| {
|
} else |err| {
|
||||||
|
|
@ -242,8 +233,8 @@ const Wasmserve = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checkForUpdate(self: *Wasmserve, path: []const u8) !bool {
|
fn checkForUpdate(self: *Wasmserve, p_dir: fs.Dir, path: []const u8) !bool {
|
||||||
const stat = try fs.cwd().statFile(path);
|
const stat = try p_dir.statFile(path);
|
||||||
const entry = try self.mtimes.getOrPut(stat.inode);
|
const entry = try self.mtimes.getOrPut(stat.inode);
|
||||||
if (entry.found_existing and stat.mtime > entry.value_ptr.*) {
|
if (entry.found_existing and stat.mtime > entry.value_ptr.*) {
|
||||||
std.log.info(esc.yellow ++ esc.underline ++ "{s}" ++ esc.reset ++ " updated", .{path});
|
std.log.info(esc.yellow ++ esc.underline ++ "{s}" ++ esc.reset ++ " updated", .{path});
|
||||||
|
|
@ -257,17 +248,19 @@ const Wasmserve = struct {
|
||||||
|
|
||||||
fn notify(self: *Wasmserve) void {
|
fn notify(self: *Wasmserve) void {
|
||||||
if (self.subscriber) |s| {
|
if (self.subscriber) |s| {
|
||||||
s.stream.writer().print("event: {s}\n", .{@tagName(self.status)}) catch |err| logErr(err, @src());
|
if (self.notify_msg) |msg| {
|
||||||
var lines = std.mem.split(u8, self.notify_msg, "\n");
|
s.stream.writer().print("event: {s}\n", .{@tagName(msg.event)}) catch |err| logErr(err, @src());
|
||||||
|
|
||||||
|
var lines = std.mem.split(u8, msg.data, "\n");
|
||||||
while (lines.next()) |line|
|
while (lines.next()) |line|
|
||||||
s.stream.writer().print("data: {s}\n", .{line}) catch |err| logErr(err, @src());
|
s.stream.writer().print("data: {s}\n", .{line}) catch |err| logErr(err, @src());
|
||||||
_ = s.stream.write("\n") catch |err| logErr(err, @src());
|
_ = s.stream.write("\n") catch |err| logErr(err, @src());
|
||||||
if (self.status == .built) self.status = .idle;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile(self: *Wasmserve) void {
|
fn compile(self: *Wasmserve) void {
|
||||||
std.log.info("Compiling...", .{});
|
std.log.info("Building...", .{});
|
||||||
const res = std.ChildProcess.exec(.{
|
const res = std.ChildProcess.exec(.{
|
||||||
.allocator = self.b.allocator,
|
.allocator = self.b.allocator,
|
||||||
.argv = &.{ self.b.zig_exe, "build", self.install_step_name, "--prominent-compile-errors", "--color", "on" },
|
.argv = &.{ self.b.zig_exe, "build", self.install_step_name, "--prominent-compile-errors", "--color", "on" },
|
||||||
|
|
@ -276,16 +269,35 @@ const Wasmserve = struct {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.b.allocator.free(res.stdout);
|
self.b.allocator.free(res.stdout);
|
||||||
self.b.allocator.free(self.notify_msg);
|
if (self.notify_msg) |msg|
|
||||||
std.debug.print("{s}", .{res.stderr});
|
if (msg.event == .build_error)
|
||||||
self.notify_msg = res.stderr;
|
self.b.allocator.free(msg.data);
|
||||||
|
|
||||||
switch (res.term) {
|
switch (res.term) {
|
||||||
.Exited => |code| {
|
.Exited => |code| {
|
||||||
self.status = if (code == 0) .built else .build_error;
|
if (code == 0) {
|
||||||
},
|
std.log.info("Built", .{});
|
||||||
// TODO: separate status and message
|
self.notify_msg = .{
|
||||||
else => {},
|
.event = .built,
|
||||||
|
.data = "",
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
std.log.err("Compile error", .{});
|
||||||
|
self.notify_msg = .{
|
||||||
|
.event = .build_error,
|
||||||
|
.data = res.stderr,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
.Signal, .Stopped, .Unknown => {
|
||||||
|
std.log.err("The build process has stopped unexpectedly", .{});
|
||||||
|
self.notify_msg = .{
|
||||||
|
.event = .stopped,
|
||||||
|
.data = "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
std.io.getStdErr().writeAll(res.stderr) catch |err| logErr(err, @src());
|
||||||
self.notify();
|
self.notify();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
1
tools/wasmserve/www/ansi_to_html.js
Normal file
1
tools/wasmserve/www/ansi_to_html.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
const defaults={fg:"#FFF",bg:"#000",newline:!1,stream:!1,colors:getDefaultColors()};function getDefaultColors(){const a={0:"#000",1:"#A00",2:"#0A0",3:"#A50",4:"#00A",5:"#A0A",6:"#0AA",7:"#AAA",8:"#555",9:"#F55",10:"#5F5",11:"#FF5",12:"#55F",13:"#F5F",14:"#5FF",15:"#FFF"};return range(0,5).forEach(b=>{range(0,5).forEach(c=>{range(0,5).forEach(d=>setStyleColor(b,c,d,a))})}),range(0,23).forEach(function(b){const c=toHexString(10*b+8);a[b+232]="#"+c+c+c}),a}function setStyleColor(a,c,d,e){const f=0<a?40*a+55:0,h=0<c?40*c+55:0,g=0<d?40*d+55:0;e[16+36*a+6*c+d]=toColorHexString([f,h,g])}function toHexString(a){let b=a.toString(16);for(;2>b.length;)b="0"+b;return b}function toColorHexString(a){const b=[];for(const c of a)b.push(toHexString(c));return"#"+b.join("")}function generateOutput(a,b,c,d){let e;return"text"===b?e=pushText(c,d):"display"===b?e=handleDisplay(a,c,d):"xterm256Foreground"===b?e=pushForegroundColor(a,d.colors[c]):"xterm256Background"===b?e=pushBackgroundColor(a,d.colors[c]):"rgb"==b&&(e=handleRgb(a,c)),e}function handleRgb(a,b){b=b.substring(2).slice(0,-1);const c=+b.substr(0,2),d=b.substring(5).split(";"),e=d.map(function(a){return("0"+(+a).toString(16)).substr(-2)}).join("");return pushStyle(a,(38==c?"color:#":"background-color:#")+e)}function handleDisplay(a,b,c){b=parseInt(b,10);const d={"-1":()=>"<br/>",0:()=>a.length&&resetStyles(a),1:()=>pushTag(a,"b"),3:()=>pushTag(a,"i"),4:()=>pushTag(a,"u"),8:()=>pushStyle(a,"display:none"),9:()=>pushTag(a,"strike"),22:()=>pushStyle(a,"font-weight:normal;text-decoration:none;font-style:normal"),23:()=>closeTag(a,"i"),24:()=>closeTag(a,"u"),39:()=>pushForegroundColor(a,c.fg),49:()=>pushBackgroundColor(a,c.bg),53:()=>pushStyle(a,"text-decoration:overline")};let e;return d[b]?e=d[b]():4<b&&7>b?e=pushTag(a,"blink"):29<b&&38>b?e=pushForegroundColor(a,c.colors[b-30]):39<b&&48>b?e=pushBackgroundColor(a,c.colors[b-40]):89<b&&98>b?e=pushForegroundColor(a,c.colors[8+(b-90)]):99<b&&108>b&&(e=pushBackgroundColor(a,c.colors[8+(b-100)])),e}function resetStyles(a){const b=a.slice(0);return a.length=0,b.reverse().map(function(a){return"</"+a+">"}).join("")}function range(a,b){const c=[];for(let d=a;d<=b;d++)c.push(d);return c}function notCategory(a){return function(b){return(null===a||b.category!==a)&&"all"!==a}}function categoryForCode(a){a=parseInt(a,10);let b=null;return 0===a?b="all":1===a?b="bold":2<a&&5>a?b="underline":4<a&&7>a?b="blink":8===a?b="hide":9===a?b="strike":29<a&&38>a||39===a||89<a&&98>a?b="foreground-color":(39<a&&48>a||49===a||99<a&&108>a)&&(b="background-color"),b}function pushText(a){return a}function pushTag(a,b,c){return c||(c=""),a.push(b),`<${b}${c?` style="${c}"`:""}>`}function pushStyle(a,b){return pushTag(a,"span",b)}function pushForegroundColor(a,b){return pushTag(a,"span","color:"+b)}function pushBackgroundColor(a,b){return pushTag(a,"span","background-color:"+b)}function closeTag(a,b){let c;if(a.slice(-1)[0]===b&&(c=a.pop()),c)return"</"+b+">"}function tokenize(a,b,c){function d(){return""}function e(a){return b.newline?c("display",-1):c("text",a),""}function f(b,c){c>h&&g||(g=!1,a=a.replace(b.pattern,b.sub))}let g=!1;const h=3,j=[{pattern:/^\x08+/,sub:d},{pattern:/^\x1b\[[012]?K/,sub:d},{pattern:/^\x1b\[\(B/,sub:d},{pattern:/^\x1b\[[34]8;2;\d+;\d+;\d+m/,sub:function(a){return c("rgb",a),""}},{pattern:/^\x1b\[38;5;(\d+)m/,sub:function(a,b){return c("xterm256Foreground",b),""}},{pattern:/^\x1b\[48;5;(\d+)m/,sub:function(a,b){return c("xterm256Background",b),""}},{pattern:/^\n/,sub:e},{pattern:/^\r+\n/,sub:e},{pattern:/^\r/,sub:e},{pattern:/^\x1b\[((?:\d{1,3};?)+|)m/,sub:function(a,b){g=!0,0===b.trim().length&&(b="0"),b=b.trimRight(";").split(";");for(const d of b)c("display",d);return""}},{pattern:/^\x1b\[\d?J/,sub:d},{pattern:/^\x1b\[\d{0,3};\d{0,3}f/,sub:d},{pattern:/^\x1b\[?[\d;]{0,3}/,sub:d},{pattern:/^(([^\x1b\x08\r\n])+)/,sub:function(a){return c("text",a),""}}],k=[];let{length:l}=a;outer:for(;0<l;){for(let b=0,c=0,d=j.length;c<d;b=++c){const c=j[b];if(f(c,b),a.length!==l){l=a.length;continue outer}}if(a.length===l)break;k.push(0),l=a.length}return k}function updateStickyStack(a,b,c){return"text"!==b&&(a=a.filter(notCategory(categoryForCode(c))),a.push({token:b,data:c,category:categoryForCode(c)})),a}class Filter{constructor(a){a=a||{},a.colors&&(a.colors=Object.assign({},defaults.colors,a.colors)),this.options=Object.assign({},defaults,a),this.stack=[],this.stickyStack=[]}toHtml(a){a="string"==typeof a?[a]:a;const{stack:b,options:c}=this,d=[];return this.stickyStack.forEach(a=>{const e=generateOutput(b,a.token,a.data,c);e&&d.push(e)}),tokenize(a.join(""),c,(a,e)=>{const f=generateOutput(b,a,e,c);f&&d.push(f),c.stream&&(this.stickyStack=updateStickyStack(this.stickyStack,a,e))}),b.length&&d.push(resetStyles(b)),d.join("")}}export default new Filter;
|
||||||
|
|
@ -1,416 +0,0 @@
|
||||||
/* ansi_up.js
|
|
||||||
* author : Dru Nelson
|
|
||||||
* license : MIT
|
|
||||||
* http://github.com/drudru/ansi_up
|
|
||||||
*
|
|
||||||
* NOTE: modifed to work with browser JS modules
|
|
||||||
*/
|
|
||||||
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
|
|
||||||
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
|
|
||||||
return cooked;
|
|
||||||
};
|
|
||||||
var PacketKind;
|
|
||||||
(function (PacketKind) {
|
|
||||||
PacketKind[PacketKind["EOS"] = 0] = "EOS";
|
|
||||||
PacketKind[PacketKind["Text"] = 1] = "Text";
|
|
||||||
PacketKind[PacketKind["Incomplete"] = 2] = "Incomplete";
|
|
||||||
PacketKind[PacketKind["ESC"] = 3] = "ESC";
|
|
||||||
PacketKind[PacketKind["Unknown"] = 4] = "Unknown";
|
|
||||||
PacketKind[PacketKind["SGR"] = 5] = "SGR";
|
|
||||||
PacketKind[PacketKind["OSCURL"] = 6] = "OSCURL";
|
|
||||||
})(PacketKind || (PacketKind = {}));
|
|
||||||
export default (function () {
|
|
||||||
function AnsiUp() {
|
|
||||||
this.VERSION = "5.1.0";
|
|
||||||
this.setup_palettes();
|
|
||||||
this._use_classes = false;
|
|
||||||
this.bold = false;
|
|
||||||
this.italic = false;
|
|
||||||
this.underline = false;
|
|
||||||
this.fg = this.bg = null;
|
|
||||||
this._buffer = '';
|
|
||||||
this._url_whitelist = { 'http': 1, 'https': 1 };
|
|
||||||
}
|
|
||||||
Object.defineProperty(AnsiUp.prototype, "use_classes", {
|
|
||||||
get: function () {
|
|
||||||
return this._use_classes;
|
|
||||||
},
|
|
||||||
set: function (arg) {
|
|
||||||
this._use_classes = arg;
|
|
||||||
},
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
Object.defineProperty(AnsiUp.prototype, "url_whitelist", {
|
|
||||||
get: function () {
|
|
||||||
return this._url_whitelist;
|
|
||||||
},
|
|
||||||
set: function (arg) {
|
|
||||||
this._url_whitelist = arg;
|
|
||||||
},
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
AnsiUp.prototype.setup_palettes = function () {
|
|
||||||
var _this = this;
|
|
||||||
this.ansi_colors =
|
|
||||||
[
|
|
||||||
[
|
|
||||||
{ rgb: [0, 0, 0], class_name: "ansi-black" },
|
|
||||||
{ rgb: [187, 0, 0], class_name: "ansi-red" },
|
|
||||||
{ rgb: [0, 187, 0], class_name: "ansi-green" },
|
|
||||||
{ rgb: [187, 187, 0], class_name: "ansi-yellow" },
|
|
||||||
{ rgb: [0, 0, 187], class_name: "ansi-blue" },
|
|
||||||
{ rgb: [187, 0, 187], class_name: "ansi-magenta" },
|
|
||||||
{ rgb: [0, 187, 187], class_name: "ansi-cyan" },
|
|
||||||
{ rgb: [255, 255, 255], class_name: "ansi-white" }
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{ rgb: [85, 85, 85], class_name: "ansi-bright-black" },
|
|
||||||
{ rgb: [255, 85, 85], class_name: "ansi-bright-red" },
|
|
||||||
{ rgb: [0, 255, 0], class_name: "ansi-bright-green" },
|
|
||||||
{ rgb: [255, 255, 85], class_name: "ansi-bright-yellow" },
|
|
||||||
{ rgb: [85, 85, 255], class_name: "ansi-bright-blue" },
|
|
||||||
{ rgb: [255, 85, 255], class_name: "ansi-bright-magenta" },
|
|
||||||
{ rgb: [85, 255, 255], class_name: "ansi-bright-cyan" },
|
|
||||||
{ rgb: [255, 255, 255], class_name: "ansi-bright-white" }
|
|
||||||
]
|
|
||||||
];
|
|
||||||
this.palette_256 = [];
|
|
||||||
this.ansi_colors.forEach(function (palette) {
|
|
||||||
palette.forEach(function (rec) {
|
|
||||||
_this.palette_256.push(rec);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var levels = [0, 95, 135, 175, 215, 255];
|
|
||||||
for (var r = 0; r < 6; ++r) {
|
|
||||||
for (var g = 0; g < 6; ++g) {
|
|
||||||
for (var b = 0; b < 6; ++b) {
|
|
||||||
var col = { rgb: [levels[r], levels[g], levels[b]], class_name: 'truecolor' };
|
|
||||||
this.palette_256.push(col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var grey_level = 8;
|
|
||||||
for (var i = 0; i < 24; ++i, grey_level += 10) {
|
|
||||||
var gry = { rgb: [grey_level, grey_level, grey_level], class_name: 'truecolor' };
|
|
||||||
this.palette_256.push(gry);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
AnsiUp.prototype.escape_txt_for_html = function (txt) {
|
|
||||||
return txt.replace(/[&<>"']/gm, function (str) {
|
|
||||||
if (str === "&")
|
|
||||||
return "&";
|
|
||||||
if (str === "<")
|
|
||||||
return "<";
|
|
||||||
if (str === ">")
|
|
||||||
return ">";
|
|
||||||
if (str === "\"")
|
|
||||||
return """;
|
|
||||||
if (str === "'")
|
|
||||||
return "'";
|
|
||||||
});
|
|
||||||
};
|
|
||||||
AnsiUp.prototype.append_buffer = function (txt) {
|
|
||||||
var str = this._buffer + txt;
|
|
||||||
this._buffer = str;
|
|
||||||
};
|
|
||||||
AnsiUp.prototype.get_next_packet = function () {
|
|
||||||
var pkt = {
|
|
||||||
kind: PacketKind.EOS,
|
|
||||||
text: '',
|
|
||||||
url: ''
|
|
||||||
};
|
|
||||||
var len = this._buffer.length;
|
|
||||||
if (len == 0)
|
|
||||||
return pkt;
|
|
||||||
var pos = this._buffer.indexOf("\x1B");
|
|
||||||
if (pos == -1) {
|
|
||||||
pkt.kind = PacketKind.Text;
|
|
||||||
pkt.text = this._buffer;
|
|
||||||
this._buffer = '';
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if (pos > 0) {
|
|
||||||
pkt.kind = PacketKind.Text;
|
|
||||||
pkt.text = this._buffer.slice(0, pos);
|
|
||||||
this._buffer = this._buffer.slice(pos);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if (pos == 0) {
|
|
||||||
if (len == 1) {
|
|
||||||
pkt.kind = PacketKind.Incomplete;
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
var next_char = this._buffer.charAt(1);
|
|
||||||
if ((next_char != '[') && (next_char != ']')) {
|
|
||||||
pkt.kind = PacketKind.ESC;
|
|
||||||
pkt.text = this._buffer.slice(0, 1);
|
|
||||||
this._buffer = this._buffer.slice(1);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if (next_char == '[') {
|
|
||||||
if (!this._csi_regex) {
|
|
||||||
this._csi_regex = rgx(__makeTemplateObject(["\n ^ # beginning of line\n #\n # First attempt\n (?: # legal sequence\n \u001B[ # CSI\n ([<-?]?) # private-mode char\n ([d;]*) # any digits or semicolons\n ([ -/]? # an intermediate modifier\n [@-~]) # the command\n )\n | # alternate (second attempt)\n (?: # illegal sequence\n \u001B[ # CSI\n [ -~]* # anything legal\n ([\0-\u001F:]) # anything illegal\n )\n "], ["\n ^ # beginning of line\n #\n # First attempt\n (?: # legal sequence\n \\x1b\\[ # CSI\n ([\\x3c-\\x3f]?) # private-mode char\n ([\\d;]*) # any digits or semicolons\n ([\\x20-\\x2f]? # an intermediate modifier\n [\\x40-\\x7e]) # the command\n )\n | # alternate (second attempt)\n (?: # illegal sequence\n \\x1b\\[ # CSI\n [\\x20-\\x7e]* # anything legal\n ([\\x00-\\x1f:]) # anything illegal\n )\n "]));
|
|
||||||
}
|
|
||||||
var match = this._buffer.match(this._csi_regex);
|
|
||||||
if (match === null) {
|
|
||||||
pkt.kind = PacketKind.Incomplete;
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if (match[4]) {
|
|
||||||
pkt.kind = PacketKind.ESC;
|
|
||||||
pkt.text = this._buffer.slice(0, 1);
|
|
||||||
this._buffer = this._buffer.slice(1);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if ((match[1] != '') || (match[3] != 'm'))
|
|
||||||
pkt.kind = PacketKind.Unknown;
|
|
||||||
else
|
|
||||||
pkt.kind = PacketKind.SGR;
|
|
||||||
pkt.text = match[2];
|
|
||||||
var rpos = match[0].length;
|
|
||||||
this._buffer = this._buffer.slice(rpos);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if (next_char == ']') {
|
|
||||||
if (len < 4) {
|
|
||||||
pkt.kind = PacketKind.Incomplete;
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if ((this._buffer.charAt(2) != '8')
|
|
||||||
|| (this._buffer.charAt(3) != ';')) {
|
|
||||||
pkt.kind = PacketKind.ESC;
|
|
||||||
pkt.text = this._buffer.slice(0, 1);
|
|
||||||
this._buffer = this._buffer.slice(1);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if (!this._osc_st) {
|
|
||||||
this._osc_st = rgxG(__makeTemplateObject(["\n (?: # legal sequence\n (\u001B\\) # ESC | # alternate\n (\u0007) # BEL (what xterm did)\n )\n | # alternate (second attempt)\n ( # illegal sequence\n [\0-\u0006] # anything illegal\n | # alternate\n [\b-\u001A] # anything illegal\n | # alternate\n [\u001C-\u001F] # anything illegal\n )\n "], ["\n (?: # legal sequence\n (\\x1b\\\\) # ESC \\\n | # alternate\n (\\x07) # BEL (what xterm did)\n )\n | # alternate (second attempt)\n ( # illegal sequence\n [\\x00-\\x06] # anything illegal\n | # alternate\n [\\x08-\\x1a] # anything illegal\n | # alternate\n [\\x1c-\\x1f] # anything illegal\n )\n "]));
|
|
||||||
}
|
|
||||||
this._osc_st.lastIndex = 0;
|
|
||||||
{
|
|
||||||
var match_1 = this._osc_st.exec(this._buffer);
|
|
||||||
if (match_1 === null) {
|
|
||||||
pkt.kind = PacketKind.Incomplete;
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if (match_1[3]) {
|
|
||||||
pkt.kind = PacketKind.ESC;
|
|
||||||
pkt.text = this._buffer.slice(0, 1);
|
|
||||||
this._buffer = this._buffer.slice(1);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var match_2 = this._osc_st.exec(this._buffer);
|
|
||||||
if (match_2 === null) {
|
|
||||||
pkt.kind = PacketKind.Incomplete;
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
if (match_2[3]) {
|
|
||||||
pkt.kind = PacketKind.ESC;
|
|
||||||
pkt.text = this._buffer.slice(0, 1);
|
|
||||||
this._buffer = this._buffer.slice(1);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!this._osc_regex) {
|
|
||||||
this._osc_regex = rgx(__makeTemplateObject(["\n ^ # beginning of line\n #\n \u001B]8; # OSC Hyperlink\n [ -:<-~]* # params (excluding ;)\n ; # end of params\n ([!-~]{0,512}) # URL capture\n (?: # ST\n (?:\u001B\\) # ESC | # alternate\n (?:\u0007) # BEL (what xterm did)\n )\n ([ -~]+) # TEXT capture\n \u001B]8;; # OSC Hyperlink End\n (?: # ST\n (?:\u001B\\) # ESC | # alternate\n (?:\u0007) # BEL (what xterm did)\n )\n "], ["\n ^ # beginning of line\n #\n \\x1b\\]8; # OSC Hyperlink\n [\\x20-\\x3a\\x3c-\\x7e]* # params (excluding ;)\n ; # end of params\n ([\\x21-\\x7e]{0,512}) # URL capture\n (?: # ST\n (?:\\x1b\\\\) # ESC \\\n | # alternate\n (?:\\x07) # BEL (what xterm did)\n )\n ([\\x20-\\x7e]+) # TEXT capture\n \\x1b\\]8;; # OSC Hyperlink End\n (?: # ST\n (?:\\x1b\\\\) # ESC \\\n | # alternate\n (?:\\x07) # BEL (what xterm did)\n )\n "]));
|
|
||||||
}
|
|
||||||
var match = this._buffer.match(this._osc_regex);
|
|
||||||
if (match === null) {
|
|
||||||
pkt.kind = PacketKind.ESC;
|
|
||||||
pkt.text = this._buffer.slice(0, 1);
|
|
||||||
this._buffer = this._buffer.slice(1);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
pkt.kind = PacketKind.OSCURL;
|
|
||||||
pkt.url = match[1];
|
|
||||||
pkt.text = match[2];
|
|
||||||
var rpos = match[0].length;
|
|
||||||
this._buffer = this._buffer.slice(rpos);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
AnsiUp.prototype.ansi_to_html = function (txt) {
|
|
||||||
this.append_buffer(txt);
|
|
||||||
var blocks = [];
|
|
||||||
while (true) {
|
|
||||||
var packet = this.get_next_packet();
|
|
||||||
if ((packet.kind == PacketKind.EOS)
|
|
||||||
|| (packet.kind == PacketKind.Incomplete))
|
|
||||||
break;
|
|
||||||
if ((packet.kind == PacketKind.ESC)
|
|
||||||
|| (packet.kind == PacketKind.Unknown))
|
|
||||||
continue;
|
|
||||||
if (packet.kind == PacketKind.Text)
|
|
||||||
blocks.push(this.transform_to_html(this.with_state(packet)));
|
|
||||||
else if (packet.kind == PacketKind.SGR)
|
|
||||||
this.process_ansi(packet);
|
|
||||||
else if (packet.kind == PacketKind.OSCURL)
|
|
||||||
blocks.push(this.process_hyperlink(packet));
|
|
||||||
}
|
|
||||||
return blocks.join("");
|
|
||||||
};
|
|
||||||
AnsiUp.prototype.with_state = function (pkt) {
|
|
||||||
return { bold: this.bold, italic: this.italic, underline: this.underline, fg: this.fg, bg: this.bg, text: pkt.text };
|
|
||||||
};
|
|
||||||
AnsiUp.prototype.process_ansi = function (pkt) {
|
|
||||||
var sgr_cmds = pkt.text.split(';');
|
|
||||||
while (sgr_cmds.length > 0) {
|
|
||||||
var sgr_cmd_str = sgr_cmds.shift();
|
|
||||||
var num = parseInt(sgr_cmd_str, 10);
|
|
||||||
if (isNaN(num) || num === 0) {
|
|
||||||
this.fg = this.bg = null;
|
|
||||||
this.bold = false;
|
|
||||||
this.italic = false;
|
|
||||||
this.underline = false;
|
|
||||||
}
|
|
||||||
else if (num === 1) {
|
|
||||||
this.bold = true;
|
|
||||||
}
|
|
||||||
else if (num === 3) {
|
|
||||||
this.italic = true;
|
|
||||||
}
|
|
||||||
else if (num === 4) {
|
|
||||||
this.underline = true;
|
|
||||||
}
|
|
||||||
else if (num === 22) {
|
|
||||||
this.bold = false;
|
|
||||||
}
|
|
||||||
else if (num === 23) {
|
|
||||||
this.italic = false;
|
|
||||||
}
|
|
||||||
else if (num === 24) {
|
|
||||||
this.underline = false;
|
|
||||||
}
|
|
||||||
else if (num === 39) {
|
|
||||||
this.fg = null;
|
|
||||||
}
|
|
||||||
else if (num === 49) {
|
|
||||||
this.bg = null;
|
|
||||||
}
|
|
||||||
else if ((num >= 30) && (num < 38)) {
|
|
||||||
this.fg = this.ansi_colors[0][(num - 30)];
|
|
||||||
}
|
|
||||||
else if ((num >= 40) && (num < 48)) {
|
|
||||||
this.bg = this.ansi_colors[0][(num - 40)];
|
|
||||||
}
|
|
||||||
else if ((num >= 90) && (num < 98)) {
|
|
||||||
this.fg = this.ansi_colors[1][(num - 90)];
|
|
||||||
}
|
|
||||||
else if ((num >= 100) && (num < 108)) {
|
|
||||||
this.bg = this.ansi_colors[1][(num - 100)];
|
|
||||||
}
|
|
||||||
else if (num === 38 || num === 48) {
|
|
||||||
if (sgr_cmds.length > 0) {
|
|
||||||
var is_foreground = (num === 38);
|
|
||||||
var mode_cmd = sgr_cmds.shift();
|
|
||||||
if (mode_cmd === '5' && sgr_cmds.length > 0) {
|
|
||||||
var palette_index = parseInt(sgr_cmds.shift(), 10);
|
|
||||||
if (palette_index >= 0 && palette_index <= 255) {
|
|
||||||
if (is_foreground)
|
|
||||||
this.fg = this.palette_256[palette_index];
|
|
||||||
else
|
|
||||||
this.bg = this.palette_256[palette_index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mode_cmd === '2' && sgr_cmds.length > 2) {
|
|
||||||
var r = parseInt(sgr_cmds.shift(), 10);
|
|
||||||
var g = parseInt(sgr_cmds.shift(), 10);
|
|
||||||
var b = parseInt(sgr_cmds.shift(), 10);
|
|
||||||
if ((r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255)) {
|
|
||||||
var c = { rgb: [r, g, b], class_name: 'truecolor' };
|
|
||||||
if (is_foreground)
|
|
||||||
this.fg = c;
|
|
||||||
else
|
|
||||||
this.bg = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
AnsiUp.prototype.transform_to_html = function (fragment) {
|
|
||||||
var txt = fragment.text;
|
|
||||||
if (txt.length === 0)
|
|
||||||
return txt;
|
|
||||||
txt = this.escape_txt_for_html(txt);
|
|
||||||
if (!fragment.bold && !fragment.italic && !fragment.underline && fragment.fg === null && fragment.bg === null)
|
|
||||||
return txt;
|
|
||||||
var styles = [];
|
|
||||||
var classes = [];
|
|
||||||
var fg = fragment.fg;
|
|
||||||
var bg = fragment.bg;
|
|
||||||
if (fragment.bold)
|
|
||||||
styles.push('font-weight:bold');
|
|
||||||
if (fragment.italic)
|
|
||||||
styles.push('font-style:italic');
|
|
||||||
if (fragment.underline)
|
|
||||||
styles.push('text-decoration:underline');
|
|
||||||
if (!this._use_classes) {
|
|
||||||
if (fg)
|
|
||||||
styles.push("color:rgb(" + fg.rgb.join(',') + ")");
|
|
||||||
if (bg)
|
|
||||||
styles.push("background-color:rgb(" + bg.rgb + ")");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (fg) {
|
|
||||||
if (fg.class_name !== 'truecolor') {
|
|
||||||
classes.push(fg.class_name + "-fg");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
styles.push("color:rgb(" + fg.rgb.join(',') + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bg) {
|
|
||||||
if (bg.class_name !== 'truecolor') {
|
|
||||||
classes.push(bg.class_name + "-bg");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
styles.push("background-color:rgb(" + bg.rgb.join(',') + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var class_string = '';
|
|
||||||
var style_string = '';
|
|
||||||
if (classes.length)
|
|
||||||
class_string = " class=\"" + classes.join(' ') + "\"";
|
|
||||||
if (styles.length)
|
|
||||||
style_string = " style=\"" + styles.join(';') + "\"";
|
|
||||||
return "<span" + style_string + class_string + ">" + txt + "</span>";
|
|
||||||
};
|
|
||||||
;
|
|
||||||
AnsiUp.prototype.process_hyperlink = function (pkt) {
|
|
||||||
var parts = pkt.url.split(':');
|
|
||||||
if (parts.length < 1)
|
|
||||||
return '';
|
|
||||||
if (!this._url_whitelist[parts[0]])
|
|
||||||
return '';
|
|
||||||
var result = "<a href=\"" + this.escape_txt_for_html(pkt.url) + "\">" + this.escape_txt_for_html(pkt.text) + "</a>";
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
return AnsiUp;
|
|
||||||
}());
|
|
||||||
function rgx(tmplObj) {
|
|
||||||
var subst = [];
|
|
||||||
for (var _i = 1; _i < arguments.length; _i++) {
|
|
||||||
subst[_i - 1] = arguments[_i];
|
|
||||||
}
|
|
||||||
var regexText = tmplObj.raw[0];
|
|
||||||
var wsrgx = /^\s+|\s+\n|\s*#[\s\S]*?\n|\n/gm;
|
|
||||||
var txt2 = regexText.replace(wsrgx, '');
|
|
||||||
return new RegExp(txt2);
|
|
||||||
}
|
|
||||||
function rgxG(tmplObj) {
|
|
||||||
var subst = [];
|
|
||||||
for (var _i = 1; _i < arguments.length; _i++) {
|
|
||||||
subst[_i - 1] = arguments[_i];
|
|
||||||
}
|
|
||||||
var regexText = tmplObj.raw[0];
|
|
||||||
var wsrgx = /^\s+|\s+\n|\s*#[\s\S]*?\n|\n/gm;
|
|
||||||
var txt2 = regexText.replace(wsrgx, '');
|
|
||||||
return new RegExp(txt2, 'g');
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import AnsiUp from "./ansi_up.js";
|
import ansi_to_html from "./ansi_to_html.js";
|
||||||
const ansiup = new AnsiUp;
|
|
||||||
|
|
||||||
let evtSource = new EventSource("/notify");
|
let evtSource = new EventSource("/notify");
|
||||||
|
|
||||||
|
|
@ -8,25 +7,35 @@ function setup() {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
evtSource.addEventListener("build_error", function (e) {
|
evtSource.addEventListener("build_error", function (e) {
|
||||||
|
createErrorScreen("An error occurred while building:", e.data)
|
||||||
|
});
|
||||||
|
evtSource.addEventListener("stopped", function (e) {
|
||||||
|
createErrorScreen("The build process has stopped unexpectedly:", e.data)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createErrorScreen(msg, data) {
|
||||||
if (document.getElementById("error-screen") == null) {
|
if (document.getElementById("error-screen") == null) {
|
||||||
let es = document.createElement("div");
|
let es = document.createElement("div");
|
||||||
es.id = "error-screen";
|
es.id = "error-screen";
|
||||||
es.style.cssText = error_screen_css;
|
es.style.cssText = error_screen_css;
|
||||||
let h2 = document.createElement("h2");
|
let h2 = document.createElement("h2");
|
||||||
let pre = document.createElement("pre");
|
let pre = document.createElement("pre");
|
||||||
h2.textContent = "An error occurred while building:";
|
h2.textContent = msg;
|
||||||
h2.style.cssText = error_screen_h2_css;
|
h2.style.cssText = error_screen_h2_css;
|
||||||
pre.innerHTML = ansiup.ansi_to_html(e.data);
|
pre.innerHTML = ansi_to_html.toHtml(data);
|
||||||
pre.style.cssText = error_screen_pre_css;
|
pre.style.cssText = error_screen_pre_css;
|
||||||
es.appendChild(h2);
|
es.appendChild(h2);
|
||||||
es.appendChild(pre);
|
es.appendChild(pre);
|
||||||
document.body.appendChild(es);
|
document.body.appendChild(es);
|
||||||
console.error(e.data);
|
|
||||||
|
// atm ANSI escape codes only works in chromium based browsers
|
||||||
|
if (!!window.chrome)
|
||||||
|
console.log(data);
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("error-screen").
|
document.getElementById("error-screen").
|
||||||
getElementsByTagName("pre").innerHTML = ansiup.ansi_to_html(e.data);
|
getElementsByTagName("pre").innerHTML = ansi_to_html.toHtml(data);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const error_screen_css =
|
const error_screen_css =
|
||||||
|
|
@ -35,23 +44,22 @@ const error_screen_css =
|
||||||
"height: 100vh;" +
|
"height: 100vh;" +
|
||||||
"top: 0;" +
|
"top: 0;" +
|
||||||
"left: 0;" +
|
"left: 0;" +
|
||||||
"background: rgba(0, 0, 0, 0.85);" +
|
"background: rgba(0, 0, 0, 0.8);" +
|
||||||
"font-family: system-ui, monospace;" +
|
"font-family: system-ui, monospace;" +
|
||||||
"font-size: 16pt;" +
|
"font-size: 16pt;" +
|
||||||
"padding: 20px;" +
|
"padding: 20px;" +
|
||||||
"box-sizing: border-box;";
|
"box-sizing: border-box;" +
|
||||||
|
|
||||||
const error_screen_h2_css =
|
|
||||||
"color: white;" +
|
"color: white;" +
|
||||||
"margin-top: 0;";
|
"z-index: 1;";
|
||||||
|
|
||||||
|
const error_screen_h2_css = "margin-top: 0;";
|
||||||
|
|
||||||
const error_screen_pre_css =
|
const error_screen_pre_css =
|
||||||
"border: 2px solid rgb(205, 92, 92);" +
|
"border-top: 8px solid #A00;" +
|
||||||
"padding: 10px;" +
|
"padding: 10px;" +
|
||||||
"background: rgba(0, 0, 0, 0.5);" +
|
"background: black;" +
|
||||||
"font-size: 12pt;" +
|
"font-size: 12pt;" +
|
||||||
"white-space: pre-wrap;" +
|
"white-space: pre-wrap;" +
|
||||||
"overflow: hidden;" +
|
"overflow: hidden;";
|
||||||
"color: lightgray;";
|
|
||||||
|
|
||||||
export default setup;
|
export default setup;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue