a minimal netron for onnx

1123
ZhangGe6 4 years ago
commit d00a6f792f

@ -0,0 +1,34 @@
import argparse
import sys
import os
from .server import start
from .server import stop
from .server import status
from .server import wait
from .server import serve
from .__version__ import __version__
def main():
parser = argparse.ArgumentParser(description='Viewer for neural network, deep learning and machine learning models.')
parser.add_argument('file', metavar='MODEL_FILE', help='model file to serve', nargs='?', default=None)
parser.add_argument('-v', '--version', help="print version", action='store_true')
parser.add_argument('-b', '--browse', help='launch web browser', action='store_true')
parser.add_argument('-p', '--port', help='port to serve', type=int)
parser.add_argument('--host', help="host to serve")
parser.add_argument('--log', help='log details to console', action='store_true')
args = parser.parse_args()
if args.file and not os.path.exists(args.file):
print("Model file '" + args.file + "' does not exist.")
sys.exit(2)
if args.version:
print(__version__)
sys.exit(0)
address = (args.host, args.port) if args.host else args.port if args.port else None
start(args.file, address=address, browse=args.browse, log=args.log)
wait()
sys.exit(0)
if __name__ == '__main__':
main()

@ -0,0 +1 @@
__version__ = '0.0.0'

1033
app.js

File diff suppressed because it is too large Load Diff

@ -0,0 +1,678 @@
var base = base || {};
base.Int64 = class Int64 {
constructor(low, high) {
this.low = low | 0;
this.high = high | 0;
}
static create(value) {
if (isNaN(value)) {
return base.Int64.zero;
}
if (value <= -9223372036854776000) {
return base.Int64.min;
}
if (value + 1 >= 9223372036854776000) {
return base.Int64.max;
}
if (value < 0) {
return base.Int64.create(-value).negate();
}
return new base.Int64((value % 4294967296) | 0, (value / 4294967296));
}
get isZero() {
return this.low === 0 && this.high === 0;
}
get isNegative() {
return this.high < 0;
}
negate() {
if (this.equals(base.Int64.min)) {
return base.Int64.min;
}
return this.not().add(base.Int64.one);
}
not() {
return new Int64(~this.low, ~this.high);
}
equals(other) {
if (!(other instanceof base.Int64) && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) {
return false;
}
return this.high === other.high && this.low === other.low;
}
compare(other) {
if (this.equals(other)) {
return 0;
}
const thisNeg = this.isNegative;
const otherNeg = other.isNegative;
if (thisNeg && !otherNeg) {
return -1;
}
if (!thisNeg && otherNeg) {
return 1;
}
return this.subtract(other).isNegative ? -1 : 1;
}
add(other) {
return base.Utility.add(this, other, false);
}
subtract(other) {
return base.Utility.subtract(this, other, false);
}
multiply(other) {
return base.Utility.multiply(this, other, false);
}
divide(other) {
return base.Utility.divide(this, other, false);
}
toInteger() {
return this.low;
}
toNumber() {
if (this.high === 0) {
return this.low >>> 0;
}
if (this.high === -1) {
return this.low;
}
return (this.high * 4294967296) + (this.low >>> 0);
}
toString(radix) {
const r = radix || 10;
if (r < 2 || r > 16) {
throw RangeError('radix');
}
if (this.isZero) {
return '0';
}
if (this.high < 0) {
if (this.equals(base.Int64.min)) {
const r = new Int64(radix, 0);
const div = this.divide(r);
const remainder = div.multiply(r).subtract(this);
return div.toString(r) + (remainder.low >>> 0).toString(r);
}
return '-' + this.negate().toString(r);
}
if (this.high === 0) {
return this.low.toString(radix);
}
return base.Utility.text(this, false, r);
}
};
base.Int64.min = new base.Int64(0, -2147483648);
base.Int64.zero = new base.Int64(0, 0);
base.Int64.one = new base.Int64(1, 0);
base.Int64.power24 = new base.Int64(1 << 24, 0);
base.Int64.max = new base.Int64(0, 2147483647);
base.Uint64 = class Uint64 {
constructor(low, high) {
this.low = low | 0;
this.high = high | 0;
}
static create(value) {
if (isNaN(value)) {
return base.Uint64.zero;
}
if (value < 0) {
return base.Uint64.zero;
}
if (value >= 18446744073709552000) {
return base.Uint64.max;
}
if (value < 0) {
return base.Uint64.create(-value).negate();
}
return new base.Uint64((value % 4294967296) | 0, (value / 4294967296));
}
get isZero() {
return this.low === 0 && this.high === 0;
}
get isNegative() {
return false;
}
negate() {
return this.not().add(base.Int64.one);
}
not() {
return new base.Uint64(~this.low, ~this.high);
}
equals(other) {
if (!(other instanceof base.Uint64) && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) {
return false;
}
return this.high === other.high && this.low === other.low;
}
compare(other) {
if (this.equals(other)) {
return 0;
}
const thisNeg = this.isNegative;
const otherNeg = other.isNegative;
if (thisNeg && !otherNeg) {
return -1;
}
if (!thisNeg && otherNeg) {
return 1;
}
return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
}
add(other) {
return base.Utility.add(this, other, true);
}
subtract(other) {
return base.Utility.subtract(this, other, true);
}
multiply(other) {
return base.Utility.multiply(this, other, true);
}
divide(other) {
return base.Utility.divide(this, other, true);
}
toInteger() {
return this.low >>> 0;
}
toNumber() {
if (this.high === 0) {
return this.low >>> 0;
}
return ((this.high >>> 0) * 4294967296) + (this.low >>> 0);
}
toString(radix) {
const r = radix || 10;
if (r < 2 || 36 < r) {
throw RangeError('radix');
}
if (this.isZero) {
return '0';
}
if (this.high === 0) {
return this.low.toString(radix);
}
return base.Utility.text(this, true, r);
}
};
base.Utility = class {
static add(a, b, unsigned) {
const a48 = a.high >>> 16;
const a32 = a.high & 0xFFFF;
const a16 = a.low >>> 16;
const a00 = a.low & 0xFFFF;
const b48 = b.high >>> 16;
const b32 = b.high & 0xFFFF;
const b16 = b.low >>> 16;
const b00 = b.low & 0xFFFF;
let c48 = 0;
let c32 = 0;
let c16 = 0;
let c00 = 0;
c00 += a00 + b00;
c16 += c00 >>> 16;
c00 &= 0xFFFF;
c16 += a16 + b16;
c32 += c16 >>> 16;
c16 &= 0xFFFF;
c32 += a32 + b32;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c48 += a48 + b48;
c48 &= 0xFFFF;
return base.Utility._create((c16 << 16) | c00, (c48 << 16) | c32, unsigned);
}
static subtract(a, b, unsigned) {
return base.Utility.add(a, b.negate(), unsigned);
}
static multiply(a, b, unsigned) {
if (a.isZero) {
return base.Int64.zero;
}
if (b.isZero) {
return base.Int64.zero;
}
if (a.equals(base.Int64.min)) {
return b.isOdd() ? base.Int64.min : base.Int64.zero;
}
if (b.equals(base.Int64.min)) {
return b.isOdd() ? base.Int64.min : base.Int64.zero;
}
if (a.isNegative) {
if (b.isNegative) {
return this.negate().multiply(b.negate());
}
else {
return this.negate().multiply(b).negate();
}
}
else if (b.isNegative) {
return this.multiply(b.negate()).negate();
}
if (a.compare(base.Int64.power24) < 0 && b.compare(base.Int64.power24) < 0) {
return unsigned ? base.Uint64.create(a.toNumber() * b.toNumber()) : base.Int64.create(a.toNumber() * b.toNumber());
}
const a48 = a.high >>> 16;
const a32 = a.high & 0xFFFF;
const a16 = a.low >>> 16;
const a00 = a.low & 0xFFFF;
const b48 = b.high >>> 16;
const b32 = b.high & 0xFFFF;
const b16 = b.low >>> 16;
const b00 = b.low & 0xFFFF;
let c48 = 0;
let c32 = 0;
let c16 = 0;
let c00 = 0;
c00 += a00 * b00;
c16 += c00 >>> 16;
c00 &= 0xFFFF;
c16 += a16 * b00;
c32 += c16 >>> 16;
c16 &= 0xFFFF;
c16 += a00 * b16;
c32 += c16 >>> 16;
c16 &= 0xFFFF;
c32 += a32 * b00;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c32 += a16 * b16;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c32 += a00 * b32;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
c48 &= 0xFFFF;
return base.Utility._create((c16 << 16) | c00, (c48 << 16) | c32, unsigned);
}
static divide(a, b, unsigned) {
if (b.isZero) {
throw Error('Division by zero.');
}
if (a.isZero) {
return unsigned ? base.Uint64.zero : base.Int64.zero;
}
let approx;
let remainder;
let result;
if (!unsigned) {
if (a.equals(base.Int64.min)) {
if (b.equals(base.Int64.one) || b.equals(base.Int64.negativeOne)) {
return base.Int64.min;
}
else if (b.equals(base.Int64.min)) {
return base.Int64.one;
}
else {
const half = base.Utility._shiftRight(a, unsigned, 1);
const halfDivide = half.divide(b);
approx = base.Utility._shiftLeft(halfDivide, halfDivide instanceof base.Uint64, 1);
if (approx.eq(base.Int64.zero)) {
return b.isNegative ? base.Int64.one : base.Int64.negativeOne;
}
else {
remainder = a.subtract(b.multiply(approx));
result = approx.add(remainder.divide(b));
return result;
}
}
}
else if (b.equals(base.Int64.min)) {
return unsigned ? base.Uint64.zero : base.Int64.zero;
}
if (a.isNegative) {
if (b.isNegative) {
return this.negate().divide(b.negate());
}
return a.negate().divide(b).negate();
}
else if (b.isNegative) {
return a.divide(b.negate()).negate();
}
result = base.Int64.zero;
}
else {
if (!(b instanceof base.Uint64)) {
b = new base.Uint64(b.low, b.high);
}
if (b.compare(a) > 0) {
return base.Int64.zero;
}
if (b.compare(base.Utility._shiftRight(a, unsigned, 1)) > 0) {
return base.Uint64.one;
}
result = base.Uint64.zero;
}
remainder = a;
while (remainder.compare(b) >= 0) {
let approx = Math.max(1, Math.floor(remainder.toNumber() / b.toNumber()));
const log2 = Math.ceil(Math.log(approx) / Math.LN2);
const delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
let approxResult = base.Int64.create(approx);
let approxRemainder = approxResult.multiply(b);
while (approxRemainder.isNegative || approxRemainder.compare(remainder) > 0) {
approx -= delta;
approxResult = unsigned ? base.Uint64.create(approx) : base.Int64.create(approx);
approxRemainder = approxResult.multiply(b);
}
if (approxResult.isZero) {
approxResult = base.Int64.one;
}
result = result.add(approxResult);
remainder = remainder.subtract(approxRemainder);
}
return result;
}
static text(value, unsigned, radix) {
const power = unsigned ? base.Uint64.create(Math.pow(radix, 6)) : base.Int64.create(Math.pow(radix, 6));
let remainder = value;
let result = '';
for (;;) {
const remainderDiv = remainder.divide(power);
const intval = remainder.subtract(remainderDiv.multiply(power)).toInteger() >>> 0;
let digits = intval.toString(radix);
remainder = remainderDiv;
if (remainder.low === 0 && remainder.high === 0) {
return digits + result;
}
while (digits.length < 6) {
digits = '0' + digits;
}
result = '' + digits + result;
}
}
static _shiftLeft(value, unsigned, shift) {
return base.Utility._create(value.low << shift, (value.high << shift) | (value.low >>> (32 - shift)), unsigned);
}
static _shiftRight(value, unsigned, shift) {
return base.Utility._create((value.low >>> shift) | (value.high << (32 - shift)), value.high >> shift, unsigned);
}
static _create(low, high, unsigned) {
return unsigned ? new base.Uint64(low, high) : new base.Int64(low, high);
}
};
base.Uint64.zero = new base.Uint64(0, 0);
base.Uint64.one = new base.Uint64(1, 0);
base.Uint64.max = new base.Uint64(-1, -1);
if (!DataView.prototype.getFloat16) {
DataView.prototype.getFloat16 = function(byteOffset, littleEndian) {
const value = this.getUint16(byteOffset, littleEndian);
const e = (value & 0x7C00) >> 10;
let f = value & 0x03FF;
if (e == 0) {
f = 0.00006103515625 * (f / 1024);
}
else if (e == 0x1F) {
f = f ? NaN : Infinity;
}
else {
f = DataView.__float16_pow[e] * (1 + (f / 1024));
}
return value & 0x8000 ? -f : f;
};
DataView.__float16_pow = {
1: 1/16384, 2: 1/8192, 3: 1/4096, 4: 1/2048, 5: 1/1024, 6: 1/512, 7: 1/256, 8: 1/128,
9: 1/64, 10: 1/32, 11: 1/16, 12: 1/8, 13: 1/4, 14: 1/2, 15: 1, 16: 2,
17: 4, 18: 8, 19: 16, 20: 32, 21: 64, 22: 128, 23: 256, 24: 512,
25: 1024, 26: 2048, 27: 4096, 28: 8192, 29: 16384, 30: 32768, 31: 65536
};
}
if (!DataView.prototype.setFloat16) {
DataView.prototype.setFloat16 = function(byteOffset, value, littleEndian) {
DataView.__float16_float[0] = value;
value = DataView.__float16_int[0];
const s = (value >>> 16) & 0x8000;
const e = (value >>> 23) & 0xff;
const f = value & 0x7fffff;
const v = s | DataView.__float16_base[e] | (f >> DataView.__float16_shift[e]);
this.setUint16(byteOffset, v, littleEndian);
};
DataView.__float16_float = new Float32Array(1);
DataView.__float16_int = new Uint32Array(DataView.__float16_float.buffer, 0, DataView.__float16_float.length);
DataView.__float16_base = new Uint32Array(256);
DataView.__float16_shift = new Uint32Array(256);
for (let i = 0; i < 256; ++i) {
const e = i - 127;
if (e < -27) {
DataView.__float16_base[i] = 0x0000;
DataView.__float16_shift[i] = 24;
}
else if (e < -14) {
DataView.__float16_base[i] = 0x0400 >> -e - 14;
DataView.__float16_shift[i] = -e - 1;
}
else if (e <= 15) {
DataView.__float16_base[i] = e + 15 << 10;
DataView.__float16_shift[i] = 13;
}
else if (e < 128) {
DataView.__float16_base[i] = 0x7c00;
DataView.__float16_shift[i] = 24;
}
else {
DataView.__float16_base[i] = 0x7c00;
DataView.__float16_shift[i] = 13;
}
}
}
DataView.prototype.getInt64 = DataView.prototype.getInt64 || function(byteOffset, littleEndian) {
return littleEndian ?
new base.Int64(this.getUint32(byteOffset, true), this.getUint32(byteOffset + 4, true)) :
new base.Int64(this.getUint32(byteOffset + 4, true), this.getUint32(byteOffset, true));
};
DataView.prototype.setInt64 = DataView.prototype.setInt64 || function(byteOffset, value, littleEndian) {
if (littleEndian) {
this.setUint32(byteOffset, value.low, true);
this.setUint32(byteOffset + 4, value.high, true);
}
else {
this.setUint32(byteOffset + 4, value.low, false);
this.setUint32(byteOffset, value.high, false);
}
};
DataView.prototype.getUint64 = DataView.prototype.getUint64 || function(byteOffset, littleEndian) {
return littleEndian ?
new base.Uint64(this.getUint32(byteOffset, true), this.getUint32(byteOffset + 4, true)) :
new base.Uint64(this.getUint32(byteOffset + 4, true), this.getUint32(byteOffset, true));
};
DataView.prototype.setUint64 = DataView.prototype.setUint64 || function(byteOffset, value, littleEndian) {
if (littleEndian) {
this.setUInt32(byteOffset, value.low, true);
this.setUInt32(byteOffset + 4, value.high, true);
}
else {
this.setUInt32(byteOffset + 4, value.low, false);
this.setUInt32(byteOffset, value.high, false);
}
};
DataView.prototype.getBits = DataView.prototype.getBits || function(offset, bits /*, signed */) {
offset = offset * bits;
const available = (this.byteLength << 3) - offset;
if (bits > available) {
throw new RangeError();
}
let value = 0;
let index = 0;
while (index < bits) {
const remainder = offset & 7;
const size = Math.min(bits - index, 8 - remainder);
value <<= size;
value |= (this.getUint8(offset >> 3) >> (8 - size - remainder)) & ~(0xff << size);
offset += size;
index += size;
}
return value;
};
base.BinaryReader = class {
constructor(data) {
this._buffer = data instanceof Uint8Array ? data : data.peek();
this._position = 0;
this._length = this._buffer.length;
this._view = new DataView(this._buffer.buffer, this._buffer.byteOffset, this._buffer.byteLength);
this._utf8 = new TextDecoder('utf-8');
}
get length() {
return this._length;
}
get position() {
return this._position;
}
seek(position) {
this._position = position >= 0 ? position : this._length + position;
if (this._position > this._length || this._position < 0) {
throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
}
}
skip(offset) {
this._position += offset;
if (this._position > this._length) {
throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
}
}
read(length) {
if (this._position === 0 && length === undefined) {
this._position = this._length;
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
return this._buffer.slice(position, this._position);
}
byte() {
const position = this._position;
this.skip(1);
return this._buffer[position];
}
int8() {
const position = this._position;
this.skip(1);
return this._view.getInt8(position, true);
}
int16() {
const position = this._position;
this.skip(2);
return this._view.getInt16(position, true);
}
int32() {
const position = this._position;
this.skip(4);
return this._view.getInt32(position, true);
}
int64() {
const position = this._position;
this.skip(8);
return this._view.getInt64(position, true).toNumber();
}
uint16() {
const position = this._position;
this.skip(2);
return this._view.getUint16(position, true);
}
uint32() {
const position = this._position;
this.skip(4);
return this._view.getUint32(position, true);
}
uint64() {
const position = this._position;
this.skip(8);
return this._view.getUint64(position, true).toNumber();
}
float32() {
const position = this._position;
this.skip(4);
return this._view.getFloat32(position, true);
}
float64() {
const position = this._position;
this.skip(8);
return this._view.getFloat64(position, true);
}
string() {
const length = this.uint32();
const position = this._position;
this.skip(length);
const data = this._buffer.subarray(position, this._position);
return this._utf8.decode(data);
}
};
if (typeof window !== 'undefined' && typeof window.Long != 'undefined') {
window.long = { Long: window.Long };
window.Int64 = base.Int64;
window.Uint64 = base.Uint64;
}
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.Int64 = base.Int64;
module.exports.Uint64 = base.Uint64;
module.exports.BinaryReader = base.BinaryReader;
}

2246
dagre.js

File diff suppressed because it is too large Load Diff

@ -0,0 +1,315 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="Content-Security-Policy" content="script-src 'self';">
<title>Netron</title>
<link rel="stylesheet" type="text/css" href="view-grapher.css">
<link rel="stylesheet" type="text/css" href="view-sidebar.css">
<style>
html { touch-action: none; overflow: hidden; width: 100%; height: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; -webkit-text-rendering: optimizeLegibility; -moz-text-rendering: optimizeLegibility; -ms-text-rendering: optimizeLegibility; -o-text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-font-smoothing: antialiased; -ms-font-smoothing: antialiased; -o-font-smoothing: antialiased; }
body { touch-action: none; overflow: hidden; width: 100%; height: 100%; margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 12px; text-rendering: geometricPrecision; }
button { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; }
.center { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.select { user-select: text; -webkit-user-select: text; -moz-user-select: text; }
.open-file-dialog { display: none; }
.graph { display: flex; height: 100%; width: 100%; overflow: auto; outline: none; touch-action: pan-x pan-y; }
.canvas { margin: auto; flex-shrink: 0; text-rendering: geometricPrecision; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.toolbar { position: absolute; top: 10px; left: 10px; padding: 0; margin: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.toolbar button:focus { outline: 0; }
.toolbar-button { float: left; background: None; border-radius: 6px; border: 0; margin: 0; margin-right: 1px; padding: 0; fill: None; stroke: #777; cursor: pointer; width: 24px; height: 24px; }
.toolbar-back-button { float: left; background: #777; border-top-left-radius: 6px; border-bottom-left-radius: 6px; border: 0px solid; border-color: #777; margin: 2px 0 2px 8px; padding: 0 8px 0 8px; cursor: pointer; height: 20px; color: #ffffff; font-size: 11px; line-height: 0; transition: 0.1s; }
.toolbar-back-button:hover { background: #000000; border-color: #000000; }
.toolbar-name-button { float: left; background: rgba(255, 255, 255, 0.95); border-top-right-radius: 6px; border-bottom-right-radius: 6px; border: 1px solid #777; color: #777; border-left: 1px; border-left-color: #ffffff; margin: 2px 0 2px 0; padding: 0 12px 0 6px; cursor: pointer; width: auto; height: 20px; font-size: 11px; line-height: 0; transition: 0.1s; }
.toolbar-name-button:hover { color: #000000; }
.icon .border { stroke: #fff; }
.icon .stroke { stroke: #808080; }
.icon:hover .stroke { stroke: #000000; }
.dropdown { display: none; position: absolute; min-width: 225px; z-index: 1; border-radius: 4px; background-color: #f6f6f6; border: 1px solid rgba(0,0,0,.15); padding-top: 2px; padding-bottom: 2px; margin-left: 2px; overflow: hidden; }
.dropdown button { display: block; border: none; border-radius: 0; background-color: transparent; color: black; width: 100%; text-align: left; padding: 4px 12px 5px 12px; white-space: no-wrap; font-size: 12px; }
.dropdown button:hover { color: #ffffff; background-color: #2e6bd2; }
.dropdown .separator { margin-top: 2px; margin-bottom: 2px; border-top: 1px; border-bottom: 0; border-style: solid; border-color: #e5e5e5; }
.welcome { background-color: #ececec; color: #242424; }
.welcome .logo { width: 582px; height: 128px; }
.welcome .logo-text { top: -57px; width: 582px; transition: 0.1s; }
.welcome .logo-name { top: -170px; width: 582px; transition: 0.1s; }
.welcome .logo-icon { left: 248px; top: -18px; width: 106px; height: 106px; transition: 0.1s; }
.welcome .logo-spinner { left: 248px; top: -18px; width: 106px; height: 106px; display: none; }
.welcome .logo-stroke { stroke: #444444; }
.welcome .logo-fill { fill: #444444; }
.welcome .logo-border { stroke: #555555; }
.welcome .logo-glyph { fill: #444444; }
.welcome .logo-message { display: none; }
.welcome .logo-github { display: none; }
.welcome button { font-size: 12px; font-weight: bold; line-height: 1.25; text-align: center; vertical-align: middle; min-width: 60px; height: 32px; border-radius: 16px; transition: 0.1s; user-select: none; -webkit-user-select: none; -moz-user-select: none; color: #444444; background-color: #ececec; border: 1px solid #444444; }
.welcome button:hover { color: #ececec; background-color: #444444; cursor: pointer; transition: 0.2s; }
.welcome button:focus { outline: 0; }
.welcome .open-file-button { top: 170px; left: -150px; width: 125px; opacity: 1; }
.welcome .github-button { top: 170px; left: 150px; width: 125px; opacity: 1; }
.welcome .consent-accept-button { top: 220px; left: 0px; width: 125px; display: none; opacity: 0; }
.welcome .consent-message { top: 120px; left: 0px; font-size: 13px; text-align: center; line-height: 20px; color: #444444; display: none; opacity: 0; }
.welcome .graph { display: none; opacity: 0; }
.welcome.spinner .logo-spinner { display: block; -webkit-animation: orbit 0.5s infinite linear; animation: orbit 0.5s infinite linear; cursor: wait; }
@-webkit-keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
@keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
.welcome.spinner .logo-spinner-stroke { stroke: #ececec; }
.welcome.spinner .logo-name { display: none; }
.welcome.spinner .open-file-button { opacity: 0; display: none; }
.welcome.spinner .github-button { opacity: 0; display: none; }
.welcome.consent .logo-name { display: none; }
.welcome.consent .open-file-button { opacity: 0; display: none; }
.welcome.consent .github-button { opacity: 0; display: none; }
.welcome.consent .consent-accept-button { opacity: 1; display: block; }
.welcome.consent .consent-message { opacity: 1; display: block; }
.welcome.spinner .graph { display: flex; opacity: 0; }
.welcome .toolbar { display: none; }
.default { background-color: #ffffff; }
.default .logo { display: none; }
.default .graph { display: flex; opacity: 1; }
.default .toolbar { display: table; }
@media (prefers-color-scheme: dark) {
:root { color-scheme: dark; }
.default { background-color: #404040; }
.graph { background-color: #404040; }
.welcome { background-color: #1e1e1e; color: #888888; }
.welcome .logo-stroke { stroke: #888888; }
.welcome .logo-fill { fill: #888888; }
.welcome .logo-border { stroke: #000000; }
.welcome .logo-glyph { fill: #888888; }
.welcome .logo-spinner-stroke { stroke: #ffffff; }
.welcome .logo button { color: #888888; background-color: #1e1e1e; border-color: #888888; }
.welcome .logo button:hover { color: #1e1e1e; background-color: #888888; }
.welcome .consent-message { color: #888888; display: none; opacity: 0; }
.icon .border { stroke: #1d1d1d; }
.icon .stroke { stroke: #aaaaaa; }
.icon:hover .stroke { stroke: #dfdfdf; }
.dropdown { background-color: #373737; border-color: #000000; }
.dropdown button { color: #ffffff; }
.dropdown button:hover { color: #ffffff; background-color: #1d59d1; }
.dropdown .separator { border-color: #5a5a5a; }
.toolbar-back-button { background: #aaaaaa; border-color: #aaaaaa; color: #333333; }
.toolbar-back-button:hover { background: #dfdfdf; border-color: #dfdfdf; }
.toolbar-name-button { background: #404040; border-color: #aaaaaa; color: #cccccc; }
.toolbar-name-button:hover { color: #dfdfdf; }
}
@media all and (max-width: 640px) {
.welcome .logo { width: 240px; }
.welcome .logo-text { opacity: 0; }
.welcome .logo-name { opacity: 0; }
.welcome .logo-icon { left: 0; top: 0; width: 128px; height: 128px; }
.welcome .logo-spinner { left: 0; top: 0; width: 128px; height: 128px; }
.welcome .logo .open-file-button { top: 180px; left: 0; }
.welcome .logo .github-button { top: 270px; left: 0; }
.welcome .logo .consent-message { top: 140px; }
.welcome .logo .consent-accept-button { top: 310px; }
.about .logo { border-radius: 0; border-left: 0px; border-right: 0px; width: 100%; padding-left: 0; padding-right: 0; }
.about.desktop .logo { width: 320px; padding: 40px; }
}
@media only screen and (max-device-width: 1024px) {
.toolbar-button { width: 32px; height: 32px; }
.toolbar-back-button { margin-top: 6px; margin-bottom: 6px; }
.toolbar-name-button { margin-top: 6px; margin-bottom: 6px; }
}
</style>
</head>
<body class="welcome spinner">
<div id="graph" class="graph" tabindex="0">
<svg id="canvas" class="canvas" preserveaspectratio="xMidYMid meet" width="100%" height="100%"></svg>
</div>
<div id="sidebar" class="sidebar"></div>
<div id="toolbar" class="toolbar">
<button id="menu-button" class="toolbar-button" title="Model Properties">
<svg class="icon" viewbox="0 0 100 100">
<rect class="border" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="8"></rect>
<line class="border" x1="30" y1="37" x2="70" y2="37" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="30" y1="50" x2="70" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="30" y1="63" x2="70" y2="63" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<rect class="stroke" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="4"></rect>
<line class="stroke" x1="30" y1="37" x2="70" y2="37" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="30" y1="50" x2="70" y2="50" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="30" y1="63" x2="70" y2="63" stroke-width="4" stroke-linecap="round"></line>
</svg>
</button>
<button id="zoom-in-button" class="toolbar-button" title="Zoom In">
<svg class="icon" viewbox="0 0 100 100">
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
<line class="border" x1="50" y1="38" x2="50" y2="62" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square" stroke="#fff"></line>
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
<line class="stroke" x1="50" y1="38" x2="50" y2="62" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
</svg>
</button>
<button id="zoom-out-button" class="toolbar-button" title="Zoom Out">
<svg class="icon" viewbox="0 0 100 100">
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square" stroke="#fff"></line>
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
</svg>
</button>
<button id="back-button" class="toolbar-back-button" title="Back">
&#x276E;
</button>
<button id="name-button" class="toolbar-name-button" title="Name">
</button>
</div>
<div class="center logo">
<a href="https://github.com/lutzroeder/netron" target="blank_">
<svg class="center logo-text" viewbox="0 0 5120 1024">
<g transform="scale(9) translate(-44,-15)">
<g transform="matrix(100,0,0,100,60.9965,126)">
<path class="logo-glyph" d="M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(100,0,0,100,164.341,126)">
<path class="logo-glyph" d="M0.089,0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,0L0.089,0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(100,0,0,100,244.491,126)">
<path class="logo-glyph" d="M0.216,0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,0L0.216,0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(100,0,0,100,323.031,126)">
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,0L0.444,0L0.193,-0.341L0.154,-0.341L0.154,0L0.089,0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(100,0,0,100,520.979,126)">
<path class="logo-glyph" d="M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z" style="fill-rule:nonzero;"/>
</g>
</g>
</svg>
<svg class="center logo-icon" viewbox="0 0 1024 1024">
<circle class="logo-stroke" cx="512" cy="512" r="431" fill="none" stroke-width="32"></circle>
<circle class="logo-border" cx="512" cy="512" r="450" fill="none" stroke-width="6"></circle>
<circle class="logo-border" cx="512" cy="512" r="412" fill="none" stroke-width="6"></circle>
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="280" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="280" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="435" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="435" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="590" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="590" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="744" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="744" stroke-width="12"></line>
<line class="logo-stroke" x1="540" y1="280" x2="785" y2="512" stroke-width="12"></line>
<line class="logo-stroke" x1="540" y1="590" x2="785" y2="512" stroke-width="12"></line>
<line class="logo-stroke" x1="540" y1="435" x2="785" y2="512" stroke-width="12"></line>
<line class="logo-stroke" x1="540" y1="744" x2="785" y2="512" stroke-width="12"></line>
<g transform="translate(296, 392)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(296, 632)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(540, 280)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(540, 435)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(540, 590)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(540, 744)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(785, 512)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
</svg>
<svg id="logo-spinner" class="center logo-spinner" viewbox="0 0 1024 1024">
<g transform="translate(512, 512)" style="opacity: 1">
<path class="logo-spinner-stroke" d="M-431,0 A-431,-431 0 0,1 0,-431" stroke-width="24" fill="None"></path>
</g>
</svg>
</a>
<a href="https://www.lutzroeder.com" target="blank_">
<svg class="center logo-name" viewbox="0 0 5120 300">
<g transform="scale(5.8) translate(20, 0)">
<g transform="matrix(30,0,0,30,18.9123,38)">
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.154,-0.715L0.154,-0.061L0.399,-0.061L0.399,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,46.7613,38)">
<path class="logo-glyph" d="M0.086,-0.715L0.15,-0.715L0.15,-0.248C0.15,-0.177 0.166,-0.125 0.198,-0.091C0.23,-0.056 0.28,-0.039 0.346,-0.039C0.412,-0.039 0.46,-0.056 0.493,-0.091C0.525,-0.125 0.541,-0.177 0.541,-0.248L0.541,-0.715L0.606,-0.715L0.606,-0.269C0.606,-0.172 0.584,-0.1 0.542,-0.052C0.499,-0.005 0.433,0.019 0.346,0.019C0.259,0.019 0.193,-0.005 0.15,-0.052C0.107,-0.1 0.086,-0.172 0.086,-0.269L0.086,-0.715Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,83.5133,38)">
<path class="logo-glyph" d="M0.216,-0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,-0L0.216,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,114.421,38)">
<path class="logo-glyph" d="M0.012,-0L0.437,-0.656L0.074,-0.656L0.074,-0.715L0.548,-0.715L0.125,-0.06L0.505,-0.06L0.505,-0L0.012,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,171.777,38)">
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,203.607,38)">
<path class="logo-glyph" d="M0.437,-0.039C0.479,-0.039 0.519,-0.047 0.557,-0.063C0.595,-0.078 0.629,-0.101 0.659,-0.131C0.689,-0.161 0.712,-0.196 0.727,-0.234C0.743,-0.273 0.751,-0.313 0.751,-0.356C0.751,-0.399 0.743,-0.44 0.728,-0.478C0.712,-0.516 0.689,-0.55 0.659,-0.581C0.63,-0.611 0.596,-0.634 0.558,-0.649C0.52,-0.665 0.48,-0.673 0.437,-0.673C0.395,-0.673 0.355,-0.665 0.317,-0.649C0.28,-0.634 0.246,-0.611 0.216,-0.581C0.186,-0.55 0.163,-0.516 0.147,-0.478C0.132,-0.44 0.124,-0.399 0.124,-0.356C0.124,-0.313 0.132,-0.272 0.147,-0.234C0.163,-0.196 0.186,-0.161 0.216,-0.131C0.246,-0.101 0.279,-0.078 0.316,-0.062C0.354,-0.047 0.394,-0.039 0.437,-0.039ZM0.82,-0.356C0.82,-0.306 0.81,-0.258 0.791,-0.212C0.772,-0.167 0.744,-0.126 0.708,-0.091C0.671,-0.055 0.63,-0.028 0.583,-0.009C0.537,0.01 0.488,0.019 0.437,0.019C0.386,0.019 0.337,0.01 0.291,-0.009C0.245,-0.028 0.203,-0.055 0.167,-0.091C0.131,-0.127 0.103,-0.168 0.084,-0.213C0.065,-0.258 0.055,-0.306 0.055,-0.356C0.055,-0.407 0.065,-0.455 0.084,-0.501C0.103,-0.546 0.131,-0.587 0.167,-0.623C0.203,-0.659 0.244,-0.685 0.29,-0.704C0.335,-0.722 0.385,-0.731 0.437,-0.731C0.49,-0.731 0.539,-0.722 0.585,-0.703C0.631,-0.685 0.672,-0.658 0.708,-0.623C0.744,-0.587 0.772,-0.546 0.791,-0.501C0.81,-0.455 0.82,-0.407 0.82,-0.356Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,245.853,38)">
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,277.243,38)">
<path class="logo-glyph" d="M0.154,-0.056L0.245,-0.056C0.319,-0.056 0.371,-0.06 0.402,-0.069C0.433,-0.077 0.459,-0.091 0.481,-0.111C0.511,-0.139 0.534,-0.174 0.549,-0.215C0.564,-0.257 0.572,-0.305 0.572,-0.358C0.572,-0.413 0.564,-0.461 0.549,-0.502C0.533,-0.544 0.51,-0.578 0.48,-0.605C0.457,-0.625 0.429,-0.64 0.396,-0.648C0.364,-0.657 0.306,-0.661 0.224,-0.661L0.154,-0.661L0.154,-0.056ZM0.089,-0L0.089,-0.715L0.2,-0.715C0.299,-0.715 0.37,-0.71 0.412,-0.7C0.453,-0.69 0.489,-0.674 0.519,-0.65C0.559,-0.618 0.589,-0.578 0.61,-0.528C0.631,-0.478 0.641,-0.421 0.641,-0.357C0.641,-0.293 0.631,-0.236 0.61,-0.186C0.589,-0.136 0.559,-0.096 0.52,-0.066C0.489,-0.042 0.454,-0.025 0.414,-0.015C0.374,-0.005 0.31,-0 0.222,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,314.142,38)">
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,345.532,38)">
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,376.911,38)">
<path class="logo-glyph" d="M0.06,-0.468L0.155,-0.731L0.228,-0.699L0.1,-0.452L0.06,-0.468Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,401.549,38)">
<path class="logo-glyph" d="M0.034,-0.12L0.09,-0.15C0.1,-0.115 0.118,-0.087 0.144,-0.068C0.169,-0.049 0.2,-0.039 0.236,-0.039C0.281,-0.039 0.316,-0.052 0.342,-0.079C0.367,-0.106 0.38,-0.143 0.38,-0.19C0.38,-0.224 0.371,-0.253 0.354,-0.276C0.337,-0.299 0.3,-0.325 0.244,-0.355C0.172,-0.393 0.124,-0.427 0.101,-0.456C0.077,-0.485 0.065,-0.519 0.065,-0.56C0.065,-0.611 0.082,-0.652 0.116,-0.684C0.151,-0.716 0.195,-0.732 0.25,-0.732C0.286,-0.732 0.317,-0.724 0.344,-0.709C0.37,-0.694 0.392,-0.671 0.408,-0.641L0.358,-0.611C0.347,-0.631 0.333,-0.647 0.314,-0.658C0.295,-0.668 0.272,-0.674 0.246,-0.674C0.211,-0.674 0.183,-0.663 0.162,-0.643C0.141,-0.622 0.131,-0.594 0.131,-0.559C0.131,-0.509 0.172,-0.462 0.255,-0.419C0.27,-0.411 0.281,-0.405 0.289,-0.401C0.35,-0.367 0.391,-0.336 0.411,-0.306C0.432,-0.276 0.442,-0.237 0.442,-0.19C0.442,-0.126 0.423,-0.075 0.386,-0.037C0.348,0 0.297,0.019 0.233,0.019C0.186,0.019 0.146,0.007 0.113,-0.016C0.079,-0.039 0.053,-0.074 0.034,-0.12Z" style="fill-rule:nonzero;"/>
</g>
</g>
</svg>
</a>
<div class="center logo-message">
<div style="height: 30px; text-align: center;">Version <span id="version" class="select">{version}</span></div>
<div style="height: 30px; text-align: center;">Copyright &copy; <a href="https://www.lutzroeder.com" target="blank_">Lutz Roeder</a></div>
</div>
<a id="logo-github" class="center logo-github" href="https://github.com/lutzroeder/netron" target="blank_">
<svg viewbox="0 0 438.549 438.549">
<path class="logo-fill" d="M409.132,114.573c-19.608-33.596-46.205-60.194-79.798-79.8C295.736,15.166,259.057,5.365,219.271,5.365
c-39.781,0-76.472,9.804-110.063,29.408c-33.596,19.605-60.192,46.204-79.8,79.8C9.803,148.168,0,184.854,0,224.63
c0,47.78,13.94,90.745,41.827,128.906c27.884,38.164,63.906,64.572,108.063,79.227c5.14,0.954,8.945,0.283,11.419-1.996
c2.475-2.282,3.711-5.14,3.711-8.562c0-0.571-0.049-5.708-0.144-15.417c-0.098-9.709-0.144-18.179-0.144-25.406l-6.567,1.136
c-4.187,0.767-9.469,1.092-15.846,1c-6.374-0.089-12.991-0.757-19.842-1.999c-6.854-1.231-13.229-4.086-19.13-8.559
c-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559
c-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-0.951-2.568-2.098-3.711-3.429c-1.142-1.331-1.997-2.663-2.568-3.997
c-0.572-1.335-0.098-2.43,1.427-3.289c1.525-0.859,4.281-1.276,8.28-1.276l5.708,0.853c3.807,0.763,8.516,3.042,14.133,6.851
c5.614,3.806,10.229,8.754,13.846,14.842c4.38,7.806,9.657,13.754,15.846,17.847c6.184,4.093,12.419,6.136,18.699,6.136
c6.28,0,11.704-0.476,16.274-1.423c4.565-0.952,8.848-2.383,12.847-4.285c1.713-12.758,6.377-22.559,13.988-29.41
c-10.848-1.14-20.601-2.857-29.264-5.14c-8.658-2.286-17.605-5.996-26.835-11.14c-9.235-5.137-16.896-11.516-22.985-19.126
c-6.09-7.614-11.088-17.61-14.987-29.979c-3.901-12.374-5.852-26.648-5.852-42.826c0-23.035,7.52-42.637,22.557-58.817
c-7.044-17.318-6.379-36.732,1.997-58.24c5.52-1.715,13.706-0.428,24.554,3.853c10.85,4.283,18.794,7.952,23.84,10.994
c5.046,3.041,9.089,5.618,12.135,7.708c17.705-4.947,35.976-7.421,54.818-7.421s37.117,2.474,54.823,7.421l10.849-6.849
c7.419-4.57,16.18-8.758,26.262-12.565c10.088-3.805,17.802-4.853,23.134-3.138c8.562,21.509,9.325,40.922,2.279,58.24
c15.036,16.18,22.559,35.787,22.559,58.817c0,16.178-1.958,30.497-5.853,42.966c-3.9,12.471-8.941,22.457-15.125,29.979
c-6.191,7.521-13.901,13.85-23.131,18.986c-9.232,5.14-18.182,8.85-26.84,11.136c-8.662,2.286-18.415,4.004-29.263,5.146
c9.894,8.562,14.842,22.077,14.842,40.539v60.237c0,3.422,1.19,6.279,3.572,8.562c2.379,2.279,6.136,2.95,11.276,1.995
c44.163-14.653,80.185-41.062,108.068-79.226c27.88-38.161,41.825-81.126,41.825-128.906
C438.536,184.851,428.728,148.168,409.132,114.573z"/>
</svg>
</a>
<span class="center consent-message">This app uses cookies to report errors and anonymous usage information.</span>
<button id="consent-accept-button" class="center consent-accept-button">Accept</button>
<button id="open-file-button" class="center open-file-button" tabindex="0">Open Model&hellip;</button>
<button id="github-button" class="center github-button">GitHub</button>
<input type="file" id="open-file-dialog" class="open-file-dialog" multiple="false" accept="">
<!-- Preload fonts to workaround Chrome SVG layout issue -->
<div style="font-weight: normal; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
</div>
</body>
</html>

@ -0,0 +1,730 @@
var host = host || {};
const electron = require('electron');
const fs = require('fs');
const http = require('http');
const https = require('https');
const process = require('process');
const path = require('path');
const querystring = require('querystring');
host.ElectronHost = class {
constructor() {
process.on('uncaughtException', (err) => {
this.exception(err, true);
});
this._document = window.document;
this._window = window;
this._window.eval = global.eval = () => {
throw new Error('window.eval() not supported.');
};
this._window.addEventListener('unload', () => {
if (typeof __coverage__ !== 'undefined') {
const file = path.join('.nyc_output', path.basename(window.location.pathname, '.html')) + '.json';
/* eslint-disable no-undef */
fs.writeFileSync(file, JSON.stringify(__coverage__));
/* eslint-enable no-undef */
}
});
this._environment = electron.ipcRenderer.sendSync('get-environment', {});
this._queue = [];
}
get window() {
return this._window;
}
get document() {
return this._document;
}
get version() {
return this._environment.version;
}
get type() {
return 'Electron';
}
get agent() {
return 'any';
}
initialize(view) {
this._view = view;
electron.ipcRenderer.on('open', (_, data) => {
this._openPath(data.path);
});
return new Promise((resolve /*, reject */) => {
const accept = () => {
if (this._environment.package) {
this._telemetry = new host.Telemetry('UA-54146-13', this._getConfiguration('userId'), navigator.userAgent, this.type, this.version);
}
resolve();
};
const request = () => {
this._view.show('welcome consent');
const acceptButton = this.document.getElementById('consent-accept-button');
if (acceptButton) {
acceptButton.addEventListener('click', () => {
this._setConfiguration('consent', Date.now());
accept();
});
}
};
const time = this._getConfiguration('consent');
if (time && (Date.now() - time) < 30 * 24 * 60 * 60 * 1000) {
accept();
}
else {
this._request('https://ipinfo.io/json', { 'Content-Type': 'application/json' }, 2000).then((text) => {
try {
const json = JSON.parse(text);
const countries = ['AT', 'BE', 'BG', 'HR', 'CZ', 'CY', 'DK', 'EE', 'FI', 'FR', 'DE', 'EL', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'SK', 'ES', 'SE', 'GB', 'UK', 'GR', 'EU', 'RO'];
if (json && json.country && !countries.indexOf(json.country) !== -1) {
this._setConfiguration('consent', Date.now());
accept();
}
else {
request();
}
}
catch (err) {
request();
}
}).catch(() => {
request();
});
}
});
}
start() {
if (this._queue) {
const queue = this._queue;
delete this._queue;
if (queue.length > 0) {
const path = queue.pop();
this._openPath(path);
}
}
electron.ipcRenderer.on('export', (_, data) => {
this._view.export(data.file);
});
electron.ipcRenderer.on('cut', () => {
this._view.cut();
});
electron.ipcRenderer.on('copy', () => {
this._view.copy();
});
electron.ipcRenderer.on('paste', () => {
this._view.paste();
});
electron.ipcRenderer.on('selectall', () => {
this._view.selectAll();
});
electron.ipcRenderer.on('toggle', (sender, name) => {
this._view.toggle(name);
this._update(Object.assign({}, this._view.options));
});
electron.ipcRenderer.on('zoom-in', () => {
this.document.getElementById('zoom-in-button').click();
});
electron.ipcRenderer.on('zoom-out', () => {
this.document.getElementById('zoom-out-button').click();
});
electron.ipcRenderer.on('reset-zoom', () => {
this._view.resetZoom();
});
electron.ipcRenderer.on('show-properties', () => {
this.document.getElementById('menu-button').click();
});
electron.ipcRenderer.on('find', () => {
this._view.find();
});
this.document.getElementById('menu-button').addEventListener('click', () => {
this._view.showModelProperties();
});
const openFileButton = this.document.getElementById('open-file-button');
if (openFileButton) {
openFileButton.style.opacity = 1;
openFileButton.addEventListener('click', () => {
electron.ipcRenderer.send('open-file-dialog', {});
});
}
const githubButton = this.document.getElementById('github-button');
const githubLink = this.document.getElementById('logo-github');
if (githubButton && githubLink) {
githubButton.style.opacity = 1;
githubButton.addEventListener('click', () => {
this.openURL(githubLink.href);
});
}
this.document.addEventListener('dragover', (e) => {
e.preventDefault();
});
this.document.addEventListener('drop', (e) => {
e.preventDefault();
});
this.document.body.addEventListener('drop', (e) => {
e.preventDefault();
const paths = Array.from(e.dataTransfer.files).map(((file) => file.path));
if (paths.length > 0) {
electron.ipcRenderer.send('drop-paths', { paths: paths });
}
return false;
});
this._view.show('welcome');
}
environment(name) {
return this._environment[name];
}
error(message, detail) {
electron.ipcRenderer.sendSync('show-message-box', {
type: 'error',
message: message,
detail: detail,
});
}
confirm(message, detail) {
const result = electron.ipcRenderer.sendSync('show-message-box', {
type: 'question',
message: message,
detail: detail,
buttons: ['Yes', 'No'],
defaultId: 0,
cancelId: 1
});
return result === 0;
}
require(id) {
try {
return Promise.resolve(require(id));
}
catch (error) {
return Promise.reject(error);
}
}
save(name, extension, defaultPath, callback) {
const selectedFile = electron.ipcRenderer.sendSync('show-save-dialog', {
title: 'Export Tensor',
defaultPath: defaultPath,
buttonLabel: 'Export',
filters: [ { name: name, extensions: [ extension ] } ]
});
if (selectedFile) {
callback(selectedFile);
}
}
export(file, blob) {
const reader = new FileReader();
reader.onload = (e) => {
const data = new Uint8Array(e.target.result);
fs.writeFile(file, data, null, (err) => {
if (err) {
this.exception(err, false);
this.error('Error writing file.', err.message);
}
});
};
let err = null;
if (!blob) {
err = new Error("Export blob is '" + JSON.stringify(blob) + "'.");
}
else if (!(blob instanceof Blob)) {
err = new Error("Export blob type is '" + (typeof blob) + "'.");
}
if (err) {
this.exception(err, false);
this.error('Error exporting image.', err.message);
}
else {
reader.readAsArrayBuffer(blob);
}
}
request(file, encoding, base) {
return new Promise((resolve, reject) => {
const pathname = path.join(base || __dirname, file);
fs.stat(pathname, (err, stat) => {
if (err && err.code === 'ENOENT') {
reject(new Error("The file '" + file + "' does not exist."));
}
else if (err) {
reject(err);
}
else if (!stat.isFile()) {
reject(new Error("The path '" + file + "' is not a file."));
}
else if (stat && stat.size < 0x7ffff000) {
fs.readFile(pathname, encoding, (err, data) => {
if (err) {
reject(err);
}
else {
resolve(encoding ? data : new host.ElectronHost.BinaryStream(data));
}
});
}
else if (encoding) {
reject(new Error("The file '" + file + "' size (" + stat.size.toString() + ") for encoding '" + encoding + "' is greater than 2 GB."));
}
else {
resolve(new host.ElectronHost.FileStream(pathname, 0, stat.size, stat.mtimeMs));
}
});
});
}
openURL(url) {
electron.shell.openExternal(url);
}
exception(error, fatal) {
if (this._telemetry && error && error.telemetry !== false) {
try {
const name = error && error.name ? error.name + ': ' : '';
const message = error && error.message ? error.message : '(null)';
const description = [ name + message ];
if (error.stack) {
const format = (file, line, column) => {
return file.split('\\').join('/').split('/').pop() + ':' + line + ':' + column;
};
const match = error.stack.match(/\n {4}at (.*) \((.*):(\d*):(\d*)\)/);
if (match) {
description.push(match[1] + ' (' + format(match[2], match[3], match[4]) + ')');
}
else {
const match = error.stack.match(/\n {4}at (.*):(\d*):(\d*)/);
if (match) {
description.push('(' + format(match[1], match[2], match[3]) + ')');
}
}
}
this._telemetry.exception(description.join(' @ '), fatal);
}
catch (e) {
// continue regardless of error
}
}
}
screen(name) {
if (this._telemetry) {
try {
this._telemetry.screenview(name);
}
catch (e) {
// continue regardless of error
}
}
}
event(category, action, label, value) {
if (this._telemetry) {
try {
this._telemetry.event(category, action, label, value);
}
catch (e) {
// continue regardless of error
}
}
}
_context(location) {
const basename = path.basename(location);
const stat = fs.statSync(location);
if (stat.isFile()) {
const dirname = path.dirname(location);
return this.request(basename, null, dirname).then((stream) => {
return new host.ElectronHost.ElectronContext(this, dirname, basename, stream);
});
}
else if (stat.isDirectory()) {
const entries = new Map();
const walk = (dir) => {
for (const item of fs.readdirSync(dir)) {
const pathname = path.join(dir, item);
const stat = fs.statSync(pathname);
if (stat.isDirectory()) {
walk(pathname);
}
else if (stat.isFile()) {
const stream = new host.ElectronHost.FileStream(pathname, 0, stat.size, stat.mtimeMs);
const name = pathname.split(path.sep).join(path.posix.sep);
entries.set(name, stream);
}
}
};
walk(location);
return Promise.resolve(new host.ElectronHost.ElectronContext(this, location, basename, null, entries));
}
throw new Error("Unsupported path stat '" + JSON.stringify(stat) + "'.");
}
_openPath(path) {
if (this._queue) {
this._queue.push(path);
return;
}
if (path && this._view.accept(path)) {
this._view.show('welcome spinner');
this._context(path).then((context) => {
this._view.open(context).then((model) => {
this._view.show(null);
const options = Object.assign({}, this._view.options);
if (model) {
options.path = path;
}
this._update(options);
}).catch((error) => {
const options = Object.assign({}, this._view.options);
if (error) {
this._view.error(error, null, null);
options.path = null;
}
this._update(options);
});
}).catch((error) => {
this._view.error(error, 'Error while reading file.', null);
this._update({ path: null });
});
}
}
_request(location, headers, timeout) {
return new Promise((resolve, reject) => {
const url = new URL(location);
const protocol = url.protocol === 'https:' ? https : http;
const options = {};
options.headers = headers;
if (timeout) {
options.timeout = timeout;
}
const request = protocol.request(location, options, (response) => {
if (response.statusCode !== 200) {
const err = new Error("The web request failed with status code " + response.statusCode + " at '" + location + "'.");
err.type = 'error';
err.url = location;
err.status = response.statusCode;
reject(err);
}
else {
let data = '';
response.on('data', (chunk) => {
data += chunk;
});
response.on('err', (err) => {
reject(err);
});
response.on('end', () => {
resolve(data);
});
}
});
request.on("error", (err) => {
reject(err);
});
request.on("timeout", () => {
request.destroy();
const error = new Error("The web request timed out at '" + location + "'.");
error.type = 'timeout';
error.url = url;
reject(error);
});
request.end();
});
}
_getConfiguration(name) {
return electron.ipcRenderer.sendSync('get-configuration', { name: name });
}
_setConfiguration(name, value) {
electron.ipcRenderer.sendSync('set-configuration', { name: name, value: value });
}
_update(data) {
electron.ipcRenderer.send('update', data);
}
};
host.Telemetry = class {
constructor(trackingId, clientId, userAgent, applicationName, applicationVersion) {
this._params = {
aip: '1', // anonymizeIp
tid: trackingId,
cid: clientId,
ua: userAgent,
an: applicationName,
av: applicationVersion
};
}
screenview(screenName) {
const params = Object.assign({}, this._params);
params.cd = screenName;
this._send('screenview', params);
}
event(category, action, label, value) {
const params = Object.assign({}, this._params);
params.ec = category;
params.ea = action;
params.el = label;
params.ev = value;
this._send('event', params);
}
exception(description, fatal) {
const params = Object.assign({}, this._params);
params.exd = description;
if (fatal) {
params.exf = '1';
}
this._send('exception', params);
}
_send(type, params) {
params.t = type;
params.v = '1';
for (const param in params) {
if (params[param] === null || params[param] === undefined) {
delete params[param];
}
}
const body = querystring.stringify(params);
const options = {
method: 'POST',
host: 'www.google-analytics.com',
path: '/collect',
headers: { 'Content-Length': Buffer.byteLength(body) }
};
const request = https.request(options, (response) => {
response.on('error', (/* error */) => {});
});
request.setTimeout(5000, () => {
request.destroy();
});
request.on('error', (/* error */) => {});
request.write(body);
request.end();
}
};
host.ElectronHost.BinaryStream = class {
constructor(buffer) {
this._buffer = buffer;
this._length = buffer.length;
this._position = 0;
}
get position() {
return this._position;
}
get length() {
return this._length;
}
stream(length) {
const buffer = this.read(length);
return new host.ElectronHost.BinaryStream(buffer.slice(0));
}
seek(position) {
this._position = position >= 0 ? position : this._length + position;
if (this._position > this._buffer.length) {
throw new Error('Expected ' + (this._position - this._buffer.length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
}
}
skip(offset) {
this._position += offset;
if (this._position > this._buffer.length) {
throw new Error('Expected ' + (this._position - this._buffer.length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
}
}
peek(length) {
if (this._position === 0 && length === undefined) {
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
const end = this._position;
this.seek(position);
return this._buffer.subarray(position, end);
}
read(length) {
if (this._position === 0 && length === undefined) {
this._position = this._length;
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
return this._buffer.subarray(position, this._position);
}
byte() {
const position = this._position;
this.skip(1);
return this._buffer[position];
}
};
host.ElectronHost.FileStream = class {
constructor(file, start, length, mtime) {
this._file = file;
this._start = start;
this._length = length;
this._position = 0;
this._mtime = mtime;
}
get position() {
return this._position;
}
get length() {
return this._length;
}
stream(length) {
const file = new host.ElectronHost.FileStream(this._file, this._position, length, this._mtime);
this.skip(length);
return file;
}
seek(position) {
this._position = position >= 0 ? position : this._length + position;
}
skip(offset) {
this._position += offset;
if (this._position > this._length) {
throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
}
}
peek(length) {
length = length !== undefined ? length : this._length - this._position;
if (length < 0x10000000) {
const position = this._fill(length);
this._position -= length;
return this._buffer.subarray(position, position + length);
}
const position = this._position;
this.skip(length);
this.seek(position);
const buffer = new Uint8Array(length);
this._read(buffer, position);
return buffer;
}
read(length) {
length = length !== undefined ? length : this._length - this._position;
if (length < 0x10000000) {
const position = this._fill(length);
return this._buffer.subarray(position, position + length);
}
const position = this._position;
this.skip(length);
const buffer = new Uint8Array(length);
this._read(buffer, position);
return buffer;
}
byte() {
const position = this._fill(1);
return this._buffer[position];
}
_fill(length) {
if (this._position + length > this._length) {
throw new Error('Expected ' + (this._position + length - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
}
if (!this._buffer || this._position < this._offset || this._position + length > this._offset + this._buffer.length) {
this._offset = this._position;
this._buffer = new Uint8Array(Math.min(0x10000000, this._length - this._offset));
this._read(this._buffer, this._offset);
}
const position = this._position;
this._position += length;
return position - this._offset;
}
_read(buffer, offset) {
const descriptor = fs.openSync(this._file, 'r');
const stat = fs.statSync(this._file);
if (stat.mtimeMs != this._mtime) {
throw new Error("File '" + this._file + "' last modified time changed.");
}
try {
fs.readSync(descriptor, buffer, 0, buffer.length, offset + this._start);
}
finally {
fs.closeSync(descriptor);
}
}
};
host.ElectronHost.ElectronHost = class {
constructor(host, folder, identifier, stream, entries) {
this._host = host;
this._folder = folder;
this._identifier = identifier;
this._stream = stream;
this._entries = entries || new Map();
}
get identifier() {
return this._identifier;
}
get stream() {
return this._stream;
}
get entries() {
return this._entries;
}
request(file, encoding, base) {
return this._host.request(file, encoding, base === undefined ? this._folder : base);
}
require(id) {
return this._host.require(id);
}
exception(error, fatal) {
this._host.exception(error, fatal);
}
};
window.addEventListener('load', () => {
global.protobuf = require('./protobuf');
global.flatbuffers = require('./flatbuffers');
const view = require('./view');
window.__view__ = new view.View(new host.ElectronHost());
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

@ -0,0 +1,392 @@
var flatbuffers = {};
var json = json || require('./json');
flatbuffers.get = (name) => {
flatbuffers._map = flatbuffers._map || new Map();
if (!flatbuffers._map.has(name)) {
flatbuffers._map.set(name, {});
}
return flatbuffers._map.get(name);
};
flatbuffers.BinaryReader = class {
static open(data) {
return new flatbuffers.BinaryReader(data);
}
constructor(data) {
const buffer = data instanceof Uint8Array ? data : data.peek();
this._buffer = buffer;
this._position = 0;
this._dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
}
get root() {
return this.int32(this._position) + this._position;
}
get identifier() {
if (this._buffer.length >= 8) {
const buffer = this._buffer.slice(4, 8);
if (buffer.every((c) => c >= 32 && c <= 128)) {
return String.fromCharCode(...buffer);
}
}
return '';
}
bool(offset) {
return !!this.int8(offset);
}
bool_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.bool(position + offset) : defaultValue;
}
int8(offset) {
return this.uint8(offset) << 24 >> 24;
}
int8_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.int8(position + offset) : defaultValue;
}
uint8(offset) {
return this._buffer[offset];
}
uint8_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.uint8(position + offset) : defaultValue;
}
int16(offset) {
return this._dataView.getInt16(offset, true);
}
int16_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.int16(position + offset) : defaultValue;
}
uint16(offset) {
return this._dataView.getUint16(offset, true);
}
uint16_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.uint16(position + offset) : defaultValue;
}
int32(offset) {
return this._dataView.getInt32(offset, true);
}
int32_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.int32(position + offset) : defaultValue;
}
uint32(offset) {
return this._dataView.getUint32(offset, true);
}
uint32_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.int32(position + offset) : defaultValue;
}
int64(offset) {
return this._dataView.getInt64(offset, true);
}
int64_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.int64(position + offset) : defaultValue;
}
uint64(offset) {
return this._dataView.getUint64(offset, true);
}
uint64_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.uint64(position + offset) : defaultValue;
}
float32(offset) {
return this._dataView.getFloat32(offset, true);
}
float32_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.float32(position + offset) : defaultValue;
}
float64(offset) {
return this._dataView.getFloat64(offset, true);
}
float64_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.float64(position + offset) : defaultValue;
}
string(offset, encoding) {
offset += this.int32(offset);
const length = this.int32(offset);
var result = '';
var i = 0;
offset += 4;
if (encoding === 1) {
return this._buffer.subarray(offset, offset + length);
}
while (i < length) {
var codePoint;
// Decode UTF-8
const a = this.uint8(offset + i++);
if (a < 0xC0) {
codePoint = a;
}
else {
const b = this.uint8(offset + i++);
if (a < 0xE0) {
codePoint = ((a & 0x1F) << 6) | (b & 0x3F);
}
else {
const c = this.uint8(offset + i++);
if (a < 0xF0) {
codePoint = ((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F);
}
else {
const d = this.uint8(offset + i++);
codePoint = ((a & 0x07) << 18) | ((b & 0x3F) << 12) | ((c & 0x3F) << 6) | (d & 0x3F);
}
}
}
// Encode UTF-16
if (codePoint < 0x10000) {
result += String.fromCharCode(codePoint);
}
else {
codePoint -= 0x10000;
result += String.fromCharCode((codePoint >> 10) + 0xD800, (codePoint & ((1 << 10) - 1)) + 0xDC00);
}
}
return result;
}
string_(position, offset, defaultValue) {
offset = this._offset(position, offset);
return offset ? this.string(position + offset) : defaultValue;
}
bools_(position, offset) {
offset = this._offset(position, offset);
if (offset) {
const length = this._length(position + offset);
offset = this._vector(position + offset);
const array = new Array(length);
for (let i = 0; i < length; i++) {
array[i] = this.uint8(offset + i + 4) ? true : false;
}
return array;
}
return [];
}
int64s_(position, offset) {
offset = this._offset(position, offset);
if (offset) {
const length = this._length(position + offset);
offset = this._vector(position + offset);
const array = new Array(length);
for (let i = 0; i < length; i++) {
array[i] = this.int64(offset + (i << 3));
}
return array;
}
return [];
}
uint64s_(position, offset) {
offset = this._offset(position, offset);
if (offset) {
const length = this._length(position + offset);
offset = this._vector(position + offset);
const array = new Array(length);
for (let i = 0; i < length; i++) {
array[i] = this.uint64(offset + (i << 3));
}
return array;
}
return [];
}
strings_(position, offset) {
offset = this._offset(position, offset);
if (offset) {
const length = this._length(position + offset);
offset = this._vector(position + offset);
const array = new Array(length);
for (let i = 0; i < length; i++) {
array[i] = this.string(offset + i * 4);
}
return array;
}
return [];
}
struct(position, offset, decode) {
offset = this._offset(position, offset);
return offset ? decode(this, position + offset) : null;
}
table(position, offset, decode) {
offset = this._offset(position, offset);
return offset ? decode(this, this._indirect(position + offset)) : null;
}
union(position, offset, decode) {
const type_offset = this._offset(position, offset);
const type = type_offset ? this.uint8(position + type_offset) : 0;
offset = this._offset(position, offset + 2);
return offset ? decode(this, this._union(position + offset), type) : null;
}
typedArray(position, offset, type) {
offset = this._offset(position, offset);
return offset ? new type(this._buffer.buffer, this._buffer.byteOffset + this._vector(position + offset), this._length(position + offset)) : new type(0);
}
unionArray(/* position, offset, decode */) {
throw new flatbuffers.Error('Not implemented.');
}
structArray(position, offset, size, decode) {
offset = this._offset(position, offset);
const length = offset ? this._length(position + offset) : 0;
const list = new Array(length);
for (let i = 0; i < length; i++) {
list[i] = decode(this, this._indirect(this._vector(position + offset) + i * 4));
}
return list;
}
tableArray(position, offset, decode) {
offset = this._offset(position, offset);
const length = offset ? this._length(position + offset) : 0;
const list = new Array(length);
for (let i = 0; i < length; i++) {
list[i] = decode(this, this._indirect(this._vector(position + offset) + i * 4));
}
return list;
}
_offset(bb_pos, vtableOffset) {
var vtable = bb_pos - this.int32(bb_pos);
return vtableOffset < this.int16(vtable) ? this.int16(vtable + vtableOffset) : 0;
}
_indirect(offset) {
return offset + this.int32(offset);
}
_vector(offset) {
return offset + this.int32(offset) + 4;
}
_length(offset) {
return this.int32(offset + this.int32(offset));
}
_union(offset) {
return offset + this.int32(offset);
}
};
flatbuffers.TextReader = class {
static open(obj) {
return new flatbuffers.TextReader(obj);
}
constructor(obj) {
this._root = obj;
}
get root() {
return this._root;
}
value(obj, defaultValue) {
return obj !== undefined ? obj : defaultValue;
}
object(obj, decode) {
return obj !== undefined ? decode(this, obj) : obj;
}
array(obj) {
if (Array.isArray(obj)) {
const target = new Array(obj.length);
for (let i = 0; i < obj.length; i++) {
target[i] = obj[i];
}
return target;
}
if (!obj) {
return [];
}
throw new flatbuffers.Error('Inalid value array.');
}
typedArray(obj, type) {
if (Array.isArray(obj)) {
const target = new type(obj.length);
for (let i = 0; i < obj.length; i++) {
target[i] = obj[i];
}
return target;
}
if (!obj) {
return new type(0);
}
throw new flatbuffers.Error('Inalid typed array.');
}
objectArray(obj, decode) {
if (Array.isArray(obj)) {
const target = new Array(obj.length);
for (let i = 0; i < obj.length; i++) {
target[i] = decode(this, obj[i]);
}
return target;
}
if (!obj) {
return [];
}
throw new flatbuffers.Error('Inalid object array.');
}
};
flatbuffers.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'FlatBuffers Error';
this.message = message;
}
};
if (typeof module !== "undefined" && typeof module.exports === "object") {
module.exports.BinaryReader = flatbuffers.BinaryReader;
module.exports.TextReader = flatbuffers.TextReader;
module.exports.get = flatbuffers.get;
}

@ -0,0 +1,234 @@
var gzip = gzip || {};
var zip = zip || require('./zip');
gzip.Archive = class {
static open(data) {
const stream = data instanceof Uint8Array ? new gzip.BinaryReader(data) : data;
const signature = [ 0x1f, 0x8b ];
if (stream.length > 18 && stream.peek(2).every((value, index) => value === signature[index])) {
return new gzip.Archive(stream);
}
return null;
}
constructor(stream) {
const position = stream.position;
const entry = new gzip.Entry(stream);
this._entries = new Map([ [ entry.name, entry.stream ] ]);
stream.seek(position);
}
get entries() {
return this._entries;
}
};
gzip.Entry = class {
constructor(stream) {
const signature = [ 0x1f, 0x8b ];
if (stream.position + 2 > stream.length ||
!stream.read(2).every((value, index) => value === signature[index])) {
throw new gzip.Error('Invalid gzip signature.');
}
const string = () => {
let content = '';
while (stream.position < stream.length) {
const value = stream.byte();
if (value === 0x00) {
break;
}
content += String.fromCharCode(value);
}
return content;
};
const reader = new gzip.BinaryReader(stream.read(8));
const compressionMethod = reader.byte();
if (compressionMethod != 8) {
throw new gzip.Error("Invalid compression method '" + compressionMethod.toString() + "'.");
}
const flags = reader.byte();
reader.uint32(); // MTIME
reader.byte(); // XFL
reader.byte(); // OS
if ((flags & 4) != 0) { // FEXTRA
const xlen = stream.byte() | (stream.byte() << 8);
stream.skip(xlen);
}
this._name = (flags & 8) != 0 ? string() : ''; // FNAME
if ((flags & 16) != 0) { // FCOMMENT
string();
}
if ((flags & 1) != 0) { // FHCRC
stream.skip(2);
}
this._stream = new gzip.InflaterStream(stream);
}
get name() {
return this._name;
}
get stream() {
return this._stream;
}
};
gzip.InflaterStream = class {
constructor(stream) {
this._stream = stream.stream(stream.length - stream.position - 8);
const reader = new gzip.BinaryReader(stream.read(8));
reader.uint32(); // CRC32
this._length = reader.uint32(); // ISIZE
this._position = 0;
}
get position() {
return this._position;
}
get length() {
return this._length;
}
seek(position) {
if (this._buffer === undefined) {
this._inflate();
}
this._position = position >= 0 ? position : this._length + position;
}
skip(offset) {
if (this._buffer === undefined) {
this._inflate();
}
this._position += offset;
}
stream(length) {
return new gzip.BinaryReader(this.read(length));
}
peek(length) {
const position = this._position;
length = length !== undefined ? length : this._length - this._position;
this.skip(length);
const end = this._position;
this.seek(position);
if (position === 0 && length === this._length) {
return this._buffer;
}
return this._buffer.subarray(position, end);
}
read(length) {
const position = this._position;
length = length !== undefined ? length : this._length - this._position;
this.skip(length);
if (position === 0 && length === this._length) {
return this._buffer;
}
return this._buffer.subarray(position, this._position);
}
byte() {
const position = this._position;
this.skip(1);
return this._buffer[position];
}
_inflate() {
if (this._buffer === undefined) {
const buffer = this._stream.peek();
this._buffer = new zip.Inflater().inflateRaw(buffer, this._length);
delete this._stream;
}
}
};
gzip.BinaryReader = class {
constructor(buffer) {
this._buffer = buffer;
this._length = buffer.length;
this._position = 0;
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
}
get position() {
return this._position;
}
get length() {
return this._length;
}
create(buffer) {
return new gzip.BinaryReader(buffer);
}
stream(length) {
return this.create(this.read(length));
}
seek(position) {
this._position = position >= 0 ? position : this._length + position;
}
skip(offset) {
this._position += offset;
}
peek(length) {
if (this._position === 0 && length === undefined) {
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
const end = this._position;
this.seek(position);
return this._buffer.subarray(position, end);
}
read(length) {
if (this._position === 0 && length === undefined) {
this._position = this._length;
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
return this._buffer.subarray(position, this._position);
}
byte() {
const position = this._position;
this.skip(1);
return this._buffer[position];
}
uint16() {
const position = this._position;
this.skip(2);
return this._view.getUint16(position, true);
}
uint32() {
const position = this._position;
this.skip(4);
return this._view.getUint32(position, true);
}
};
gzip.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'Gzip Error';
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.Archive = gzip.Archive;
}

1464
hdf5.js

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

@ -0,0 +1,374 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<meta http-equiv="Content-Security-Policy" content="script-src 'self' www.google-analytics.com;">
<meta name="version" content="0.0.0">
<title>Netron</title>
<link rel="stylesheet" type="text/css" href="view-grapher.css">
<link rel="stylesheet" type="text/css" href="view-sidebar.css">
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
<link rel="icon" type="image/png" href="icon.png">
<link rel="apple-touch-icon" type="image/png" href="icon.png">
<link rel="apple-touch-icon-precomposed" type="image/png" href="icon.png">
<link rel="fluid-icon" type="image/png" href="icon.png">
<script type="text/javascript" src="dagre.js"></script>
<script type="text/javascript" src="base.js"></script>
<script type="text/javascript" src="text.js"></script>
<script type="text/javascript" src="json.js"></script>
<script type="text/javascript" src="xml.js"></script>
<script type="text/javascript" src="python.js"></script>
<script type="text/javascript" src="protobuf.js"></script>
<script type="text/javascript" src="flatbuffers.js"></script>
<script type="text/javascript" src="zip.js"></script>
<script type="text/javascript" src="gzip.js"></script>
<script type="text/javascript" src="tar.js"></script>
<script type="text/javascript" src="view-grapher.js"></script>
<script type="text/javascript" src="view-sidebar.js"></script>
<script type="text/javascript" src="view.js"></script>
<script type="text/javascript" src="index.js"></script>
<style>
html { touch-action: none; overflow: hidden; width: 100%; height: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; -webkit-text-rendering: optimizeLegibility; -moz-text-rendering: optimizeLegibility; -ms-text-rendering: optimizeLegibility; -o-text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-font-smoothing: antialiased; -ms-font-smoothing: antialiased; -o-font-smoothing: antialiased; }
body { touch-action: none; overflow: hidden; width: 100%; height: 100%; margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 12px; text-rendering: geometricPrecision; }
button { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; }
.center { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.select { user-select: text; -webkit-user-select: text; -moz-user-select: text; }
.open-file-dialog { display: none; }
.transparent { width: 100%; height: 100%; background-color: #000000; display: none; opacity: 0; }
.graph { display: flex; height: 100%; width: 100%; overflow: auto; outline: none; touch-action: pan-x pan-y; }
.canvas { margin: auto; flex-shrink: 0; text-rendering: geometricPrecision; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.toolbar { position: absolute; top: 10px; left: 10px; padding: 0; margin: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.toolbar button:focus { outline: 0; }
.toolbar-button { background: None; border-radius: 6px; border: 0; margin: 0; padding: 0; fill: None; stroke: #777; cursor: pointer; width: 24px; height: 24px; }
.toolbar-button { float: left; background: None; border-radius: 6px; border: 0; margin: 0; margin-right: 1px; padding: 0; fill: None; stroke: #777; cursor: pointer; width: 24px; height: 24px; }
.toolbar-back-button { float: left; background: #777; border-top-left-radius: 6px; border-bottom-left-radius: 6px; border: 0px solid; border-color: #777; margin: 2px 0 2px 8px; padding: 0 8px 0 8px; cursor: pointer; height: 20px; color: #ffffff; font-size: 11px; line-height: 0; transition: 0.1s; }
.toolbar-back-button:hover { background: #000000; border-color: #000000; }
.toolbar-name-button { float: left; background: rgba(255, 255, 255, 0.95); border-top-right-radius: 6px; border-bottom-right-radius: 6px; border: 1px solid #777; color: #777; border-left: 1px; border-left-color: #ffffff; margin: 2px 0 2px 0; padding: 0 12px 0 6px; cursor: pointer; width: auto; height: 20px; font-size: 11px; line-height: 0; transition: 0.1s; }
.toolbar-name-button:hover { color: #000000; }
.icon .border { stroke: #fff; }
.icon .stroke { stroke: #808080; }
.icon:hover .stroke { stroke: #000000; }
.dropdown { display: none; position: absolute; min-width: 225px; z-index: 1; border-radius: 4px; background-color: #f6f6f6; border: 1px solid rgba(0,0,0,.15); padding-top: 2px; padding-bottom: 2px; margin-left: 2px; overflow: hidden; }
.dropdown button { display: block; border: none; border-radius: 0; background-color: transparent; color: black; width: 100%; text-align: left; padding: 4px 12px 5px 12px; white-space: no-wrap; font-size: 12px; }
.dropdown button:hover { color: #ffffff; background-color: #2e6bd2; }
.dropdown .separator { margin-top: 2px; margin-bottom: 2px; border-top: 1px; border-bottom: 0; border-style: solid; border-color: #e5e5e5; }
.about { background-color: #ffffff; }
.about { overflow: hidden; }
.about .logo { background-color: #ececec; color: #242424; width: 320px; height: 170px; padding: 40px; opacity: 1.0; border-radius: 5px; border: 0.5px solid #cccccc; box-shadow: 0 0 30px #ddd; }
.about.desktop .logo { border: None; border-radius: 0px; }
.about.desktop .graph { display: none; opacity: 0; }
.about.desktop .transparent { display: none; opacity: 0; }
.about.desktop .toolbar { display: none; opacity: 0; }
.about .logo-name { opacity: 0; }
.about .logo-text { top: -130px; width: 320px; }
.about .logo-icon { left: 136px; top: -108px; width: 60px; height: 60px; }
.about .logo-stroke { stroke: #242424; }
.about .logo-fill { fill: #242424; }
.about .logo-border { stroke: #242424; }
.about .logo-glyph { fill: #242424; }
.about .logo-message { top: 112px; padding-left: 40px; padding-right: 40px; }
.about a { text-decoration: none; color: #242424; }
.about a:visited { color: inherit; }
.about a:hover { color: #242424; }
.about .logo-github { top: 130px; width: 24px; height: 24px; }
.about .open-file-button { display: none; }
.about .github-button { display: none; }
.about .consent-message { display: none; }
.about .consent-accept-button { display: none; }
.about .graph { display: flex; opacity: 1; }
.about .toolbar { display: block; opacity: 1; }
.about .transparent { display: block; opacity: 0.5; }
.welcome { background-color: #ececec; color: #242424; }
.welcome .logo { width: 582px; height: 128px; }
.welcome .logo-text { top: -57px; width: 582px; transition: 0.1s; }
.welcome .logo-name { top: -170px; width: 582px; transition: 0.1s; }
.welcome .logo-icon { left: 248px; top: -18px; width: 106px; height: 106px; transition: 0.1s; }
.welcome .logo-spinner { left: 248px; top: -18px; width: 106px; height: 106px; display: none; }
.welcome .logo-stroke { stroke: #444444; }
.welcome .logo-fill { fill: #444444; }
.welcome .logo-border { stroke: #555555; }
.welcome .logo-glyph { fill: #444444; }
.welcome .logo-message { display: none; }
.welcome .logo-github { display: none; }
.welcome button { font-size: 12px; font-weight: bold; line-height: 1.25; text-align: center; vertical-align: middle; min-width: 60px; height: 32px; border-radius: 16px; transition: 0.1s; user-select: none; -webkit-user-select: none; -moz-user-select: none; color: #444444; background-color: #ececec; border: 1px solid #444444; }
.welcome button:hover { color: #ececec; background-color: #444444; cursor: pointer; transition: 0.2s; }
.welcome button:focus { outline: 0; }
.welcome .open-file-button { top: 170px; left: -150px; width: 125px; opacity: 1; }
.welcome .github-button { top: 170px; left: 150px; width: 125px; opacity: 1; }
.welcome .consent-accept-button { top: 220px; left: 0px; width: 125px; display: none; opacity: 0; }
.welcome .consent-message { top: 120px; left: 0px; font-size: 13px; text-align: center; line-height: 20px; color: #444444; display: none; opacity: 0; }
.welcome .graph { display: none; opacity: 0; }
.welcome.spinner .logo-spinner { display: block; -webkit-animation: orbit 0.5s infinite linear; animation: orbit 0.5s infinite linear; cursor: wait; }
@-webkit-keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
@keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
.welcome.spinner .logo-spinner-stroke { stroke: #ececec; }
.welcome.spinner .logo-name { display: none; }
.welcome.spinner .open-file-button { opacity: 0; display: none; }
.welcome.spinner .github-button { opacity: 0; display: none; }
.welcome.consent .logo-name { display: none; }
.welcome.consent .open-file-button { opacity: 0; display: none; }
.welcome.consent .github-button { opacity: 0; display: none; }
.welcome.consent .consent-accept-button { opacity: 1; display: block; }
.welcome.consent .consent-message { opacity: 1; display: block; }
.welcome.spinner .graph { display: flex; opacity: 0; }
.welcome .toolbar { display: none; }
.default { background-color: #ffffff; }
.default .logo { display: none; }
.default .graph { display: flex; opacity: 1; }
.default .toolbar { display: table; }
@media (prefers-color-scheme: dark) {
:root { color-scheme: dark; }
.default { background-color: #404040; }
.graph { background-color: #404040; }
.about { background-color: #404040; }
.about .logo { background-color: #2d2d2d; color: #dfdfdf; border-color: #000000; box-shadow: 0 0 30px #333; }
.about a { color: #dfdfdf; }
.about a:hover { color: #ffffff; }
.about .logo-stroke { stroke: #dfdfdf; }
.about .logo-fill { fill: #dfdfdf; }
.about .logo-border { stroke: #dfdfdf; }
.about .logo-glyph { fill: #dfdfdf; }
.welcome { background-color: #1e1e1e; color: #888888; }
.welcome .logo-stroke { stroke: #888888; }
.welcome .logo-fill { fill: #888888; }
.welcome .logo-border { stroke: #000000; }
.welcome .logo-glyph { fill: #888888; }
.welcome .logo-spinner-stroke { stroke: #ffffff; }
.welcome .logo button { color: #888888; background-color: #1e1e1e; border-color: #888888; }
.welcome .logo button:hover { color: #1e1e1e; background-color: #888888; }
.welcome .consent-message { color: #888888; display: none; opacity: 0; }
.icon .border { stroke: #1d1d1d; }
.icon .stroke { stroke: #aaaaaa; }
.icon:hover .stroke { stroke: #dfdfdf; }
.dropdown { background-color: #373737; border-color: #000000; }
.dropdown button { color: #ffffff; }
.dropdown button:hover { color: #ffffff; background-color: #1d59d1; }
.dropdown .separator { border-color: #5a5a5a; }
.toolbar-back-button { background: #aaaaaa; border-color: #aaaaaa; color: #333333; }
.toolbar-back-button:hover { background: #dfdfdf; border-color: #dfdfdf; }
.toolbar-name-button { background: #404040; border-color: #aaaaaa; color: #cccccc; }
.toolbar-name-button:hover { color: #dfdfdf; }
}
@media all and (max-width: 640px) {
.welcome .logo { width: 240px; }
.welcome .logo-text { opacity: 0; }
.welcome .logo-name { opacity: 0; }
.welcome .logo-icon { left: 0; top: 0; width: 128px; height: 128px; }
.welcome .logo-spinner { left: 0; top: 0; width: 128px; height: 128px; }
.welcome .logo .open-file-button { top: 180px; left: 0; }
.welcome .logo .github-button { top: 270px; left: 0; }
.welcome .logo .consent-message { top: 140px; }
.welcome .logo .consent-accept-button { top: 310px; }
.about .logo { border-radius: 0; border-left: 0px; border-right: 0px; width: 100%; padding-left: 0; padding-right: 0; }
.about.desktop .logo { width: 320px; padding: 40px; }
}
@media only screen and (max-device-width: 1024px) {
.toolbar-button { width: 32px; height: 32px; }
.toolbar-back-button { margin-top: 6px; margin-bottom: 6px; }
.toolbar-name-button { margin-top: 6px; margin-bottom: 6px; }
}
</style>
</head>
<body class="welcome spinner">
<div id="graph" class="graph" tabindex="0">
<svg id="canvas" class="canvas" preserveaspectratio="xMidYMid meet" width="100%" height="100%"></svg>
</div>
<div id="sidebar" class="sidebar"></div>
<div id="toolbar" class="toolbar">
<button id="menu-button" class="toolbar-button" title="Menu">
<svg class="icon" viewbox="0 0 100 100">
<rect class="border" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="8"></rect>
<line class="border" x1="30" y1="37" x2="70" y2="37" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="30" y1="50" x2="70" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="30" y1="63" x2="70" y2="63" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<rect class="stroke" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="4"></rect>
<line class="stroke" x1="30" y1="37" x2="70" y2="37" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="30" y1="50" x2="70" y2="50" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="30" y1="63" x2="70" y2="63" stroke-width="4" stroke-linecap="round"></line>
</svg>
</button>
<button id="zoom-in-button" class="toolbar-button" title="Zoom In">
<svg class="icon" viewbox="0 0 100 100">
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
<line class="border" x1="50" y1="38" x2="50" y2="62" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square" stroke="#fff"></line>
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
<line class="stroke" x1="50" y1="38" x2="50" y2="62" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
</svg>
</button>
<button id="zoom-out-button" class="toolbar-button" title="Zoom Out">
<svg class="icon" viewbox="0 0 100 100">
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round" stroke="#fff"></line>
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square" stroke="#fff"></line>
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
</svg>
</button>
<button id="back-button" class="toolbar-back-button" title="Back">
&#x276E;
</button>
<button id="name-button" class="toolbar-name-button" title="Name">
</button>
<div id="menu-dropdown" class="dropdown"></div>
</div>
<div id="transparent" class="transparent"></div>
<div class="center logo">
<a href="https://github.com/lutzroeder/netron" target="blank_">
<svg class="center logo-text" viewbox="0 0 5120 1024">
<g transform="scale(9) translate(-44,-15)">
<g transform="matrix(100,0,0,100,60.9965,126)">
<path class="logo-glyph" d="M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(100,0,0,100,164.341,126)">
<path class="logo-glyph" d="M0.089,0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,0L0.089,0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(100,0,0,100,244.491,126)">
<path class="logo-glyph" d="M0.216,0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,0L0.216,0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(100,0,0,100,323.031,126)">
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,0L0.444,0L0.193,-0.341L0.154,-0.341L0.154,0L0.089,0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(100,0,0,100,520.979,126)">
<path class="logo-glyph" d="M0.089,0L0.089,-0.745L0.595,-0.147L0.595,-0.715L0.656,-0.715L0.656,0.021L0.15,-0.578L0.15,0L0.089,0Z" style="fill-rule:nonzero;"/>
</g>
</g>
</svg>
<svg class="center logo-icon" viewbox="0 0 1024 1024">
<circle class="logo-stroke" cx="512" cy="512" r="431" fill="none" stroke-width="32"></circle>
<circle class="logo-border" cx="512" cy="512" r="450" fill="none" stroke-width="6"></circle>
<circle class="logo-border" cx="512" cy="512" r="412" fill="none" stroke-width="6"></circle>
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="280" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="280" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="435" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="435" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="590" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="590" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="744" stroke-width="12"></line>
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="744" stroke-width="12"></line>
<line class="logo-stroke" x1="540" y1="280" x2="785" y2="512" stroke-width="12"></line>
<line class="logo-stroke" x1="540" y1="590" x2="785" y2="512" stroke-width="12"></line>
<line class="logo-stroke" x1="540" y1="435" x2="785" y2="512" stroke-width="12"></line>
<line class="logo-stroke" x1="540" y1="744" x2="785" y2="512" stroke-width="12"></line>
<g transform="translate(296, 392)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(296, 632)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(540, 280)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(540, 435)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(540, 590)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(540, 744)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
<g transform="translate(785, 512)">
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
</g>
</svg>
<svg id="logo-spinner" class="center logo-spinner" viewbox="0 0 1024 1024">
<g transform="translate(512, 512)" style="opacity: 1">
<path class="logo-spinner-stroke" d="M-431,0 A-431,-431 0 0,1 0,-431" stroke-width="24" fill="None"></path>
</g>
</svg>
</a>
<a href="https://www.lutzroeder.com" target="blank_">
<svg class="center logo-name" viewbox="0 0 5120 300">
<g transform="scale(5.8) translate(20, 0)">
<g transform="matrix(30,0,0,30,18.9123,38)">
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.154,-0.715L0.154,-0.061L0.399,-0.061L0.399,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,46.7613,38)">
<path class="logo-glyph" d="M0.086,-0.715L0.15,-0.715L0.15,-0.248C0.15,-0.177 0.166,-0.125 0.198,-0.091C0.23,-0.056 0.28,-0.039 0.346,-0.039C0.412,-0.039 0.46,-0.056 0.493,-0.091C0.525,-0.125 0.541,-0.177 0.541,-0.248L0.541,-0.715L0.606,-0.715L0.606,-0.269C0.606,-0.172 0.584,-0.1 0.542,-0.052C0.499,-0.005 0.433,0.019 0.346,0.019C0.259,0.019 0.193,-0.005 0.15,-0.052C0.107,-0.1 0.086,-0.172 0.086,-0.269L0.086,-0.715Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,83.5133,38)">
<path class="logo-glyph" d="M0.216,-0L0.216,-0.654L0.019,-0.654L0.019,-0.715L0.478,-0.715L0.478,-0.654L0.281,-0.654L0.281,-0L0.216,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,114.421,38)">
<path class="logo-glyph" d="M0.012,-0L0.437,-0.656L0.074,-0.656L0.074,-0.715L0.548,-0.715L0.125,-0.06L0.505,-0.06L0.505,-0L0.012,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,171.777,38)">
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,203.607,38)">
<path class="logo-glyph" d="M0.437,-0.039C0.479,-0.039 0.519,-0.047 0.557,-0.063C0.595,-0.078 0.629,-0.101 0.659,-0.131C0.689,-0.161 0.712,-0.196 0.727,-0.234C0.743,-0.273 0.751,-0.313 0.751,-0.356C0.751,-0.399 0.743,-0.44 0.728,-0.478C0.712,-0.516 0.689,-0.55 0.659,-0.581C0.63,-0.611 0.596,-0.634 0.558,-0.649C0.52,-0.665 0.48,-0.673 0.437,-0.673C0.395,-0.673 0.355,-0.665 0.317,-0.649C0.28,-0.634 0.246,-0.611 0.216,-0.581C0.186,-0.55 0.163,-0.516 0.147,-0.478C0.132,-0.44 0.124,-0.399 0.124,-0.356C0.124,-0.313 0.132,-0.272 0.147,-0.234C0.163,-0.196 0.186,-0.161 0.216,-0.131C0.246,-0.101 0.279,-0.078 0.316,-0.062C0.354,-0.047 0.394,-0.039 0.437,-0.039ZM0.82,-0.356C0.82,-0.306 0.81,-0.258 0.791,-0.212C0.772,-0.167 0.744,-0.126 0.708,-0.091C0.671,-0.055 0.63,-0.028 0.583,-0.009C0.537,0.01 0.488,0.019 0.437,0.019C0.386,0.019 0.337,0.01 0.291,-0.009C0.245,-0.028 0.203,-0.055 0.167,-0.091C0.131,-0.127 0.103,-0.168 0.084,-0.213C0.065,-0.258 0.055,-0.306 0.055,-0.356C0.055,-0.407 0.065,-0.455 0.084,-0.501C0.103,-0.546 0.131,-0.587 0.167,-0.623C0.203,-0.659 0.244,-0.685 0.29,-0.704C0.335,-0.722 0.385,-0.731 0.437,-0.731C0.49,-0.731 0.539,-0.722 0.585,-0.703C0.631,-0.685 0.672,-0.658 0.708,-0.623C0.744,-0.587 0.772,-0.546 0.791,-0.501C0.81,-0.455 0.82,-0.407 0.82,-0.356Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,245.853,38)">
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,277.243,38)">
<path class="logo-glyph" d="M0.154,-0.056L0.245,-0.056C0.319,-0.056 0.371,-0.06 0.402,-0.069C0.433,-0.077 0.459,-0.091 0.481,-0.111C0.511,-0.139 0.534,-0.174 0.549,-0.215C0.564,-0.257 0.572,-0.305 0.572,-0.358C0.572,-0.413 0.564,-0.461 0.549,-0.502C0.533,-0.544 0.51,-0.578 0.48,-0.605C0.457,-0.625 0.429,-0.64 0.396,-0.648C0.364,-0.657 0.306,-0.661 0.224,-0.661L0.154,-0.661L0.154,-0.056ZM0.089,-0L0.089,-0.715L0.2,-0.715C0.299,-0.715 0.37,-0.71 0.412,-0.7C0.453,-0.69 0.489,-0.674 0.519,-0.65C0.559,-0.618 0.589,-0.578 0.61,-0.528C0.631,-0.478 0.641,-0.421 0.641,-0.357C0.641,-0.293 0.631,-0.236 0.61,-0.186C0.589,-0.136 0.559,-0.096 0.52,-0.066C0.489,-0.042 0.454,-0.025 0.414,-0.015C0.374,-0.005 0.31,-0 0.222,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,314.142,38)">
<path class="logo-glyph" d="M0.089,-0L0.089,-0.715L0.443,-0.715L0.443,-0.654L0.154,-0.654L0.154,-0.43L0.443,-0.43L0.443,-0.369L0.154,-0.369L0.154,-0.061L0.443,-0.061L0.443,-0L0.089,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,345.532,38)">
<path class="logo-glyph" d="M0.154,-0.658L0.154,-0.394L0.219,-0.394C0.28,-0.394 0.322,-0.404 0.346,-0.423C0.37,-0.442 0.382,-0.475 0.382,-0.522C0.382,-0.571 0.369,-0.606 0.345,-0.627C0.32,-0.648 0.278,-0.658 0.219,-0.658L0.154,-0.658ZM0.523,-0L0.444,-0L0.193,-0.341L0.154,-0.341L0.154,-0L0.089,-0L0.089,-0.715L0.22,-0.715C0.298,-0.715 0.356,-0.699 0.394,-0.667C0.433,-0.634 0.452,-0.585 0.452,-0.52C0.452,-0.464 0.436,-0.421 0.403,-0.389C0.37,-0.357 0.324,-0.341 0.266,-0.341L0.523,-0Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,376.911,38)">
<path class="logo-glyph" d="M0.06,-0.468L0.155,-0.731L0.228,-0.699L0.1,-0.452L0.06,-0.468Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(30,0,0,30,401.549,38)">
<path class="logo-glyph" d="M0.034,-0.12L0.09,-0.15C0.1,-0.115 0.118,-0.087 0.144,-0.068C0.169,-0.049 0.2,-0.039 0.236,-0.039C0.281,-0.039 0.316,-0.052 0.342,-0.079C0.367,-0.106 0.38,-0.143 0.38,-0.19C0.38,-0.224 0.371,-0.253 0.354,-0.276C0.337,-0.299 0.3,-0.325 0.244,-0.355C0.172,-0.393 0.124,-0.427 0.101,-0.456C0.077,-0.485 0.065,-0.519 0.065,-0.56C0.065,-0.611 0.082,-0.652 0.116,-0.684C0.151,-0.716 0.195,-0.732 0.25,-0.732C0.286,-0.732 0.317,-0.724 0.344,-0.709C0.37,-0.694 0.392,-0.671 0.408,-0.641L0.358,-0.611C0.347,-0.631 0.333,-0.647 0.314,-0.658C0.295,-0.668 0.272,-0.674 0.246,-0.674C0.211,-0.674 0.183,-0.663 0.162,-0.643C0.141,-0.622 0.131,-0.594 0.131,-0.559C0.131,-0.509 0.172,-0.462 0.255,-0.419C0.27,-0.411 0.281,-0.405 0.289,-0.401C0.35,-0.367 0.391,-0.336 0.411,-0.306C0.432,-0.276 0.442,-0.237 0.442,-0.19C0.442,-0.126 0.423,-0.075 0.386,-0.037C0.348,0 0.297,0.019 0.233,0.019C0.186,0.019 0.146,0.007 0.113,-0.016C0.079,-0.039 0.053,-0.074 0.034,-0.12Z" style="fill-rule:nonzero;"/>
</g>
</g>
</svg>
</a>
<div class="center logo-message">
<div style="height: 30px; text-align: center;">Version <span id="version" class="select">{version}</span></div>
<div style="height: 30px; text-align: center;">Copyright &copy; <a href="https://www.lutzroeder.com" target="blank_">Lutz Roeder</a></div>
</div>
<a id="logo-github" class="center logo-github" href="https://github.com/lutzroeder/netron" target="blank_">
<svg viewbox="0 0 438.549 438.549">
<path class="logo-fill" d="M409.132,114.573c-19.608-33.596-46.205-60.194-79.798-79.8C295.736,15.166,259.057,5.365,219.271,5.365
c-39.781,0-76.472,9.804-110.063,29.408c-33.596,19.605-60.192,46.204-79.8,79.8C9.803,148.168,0,184.854,0,224.63
c0,47.78,13.94,90.745,41.827,128.906c27.884,38.164,63.906,64.572,108.063,79.227c5.14,0.954,8.945,0.283,11.419-1.996
c2.475-2.282,3.711-5.14,3.711-8.562c0-0.571-0.049-5.708-0.144-15.417c-0.098-9.709-0.144-18.179-0.144-25.406l-6.567,1.136
c-4.187,0.767-9.469,1.092-15.846,1c-6.374-0.089-12.991-0.757-19.842-1.999c-6.854-1.231-13.229-4.086-19.13-8.559
c-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559
c-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-0.951-2.568-2.098-3.711-3.429c-1.142-1.331-1.997-2.663-2.568-3.997
c-0.572-1.335-0.098-2.43,1.427-3.289c1.525-0.859,4.281-1.276,8.28-1.276l5.708,0.853c3.807,0.763,8.516,3.042,14.133,6.851
c5.614,3.806,10.229,8.754,13.846,14.842c4.38,7.806,9.657,13.754,15.846,17.847c6.184,4.093,12.419,6.136,18.699,6.136
c6.28,0,11.704-0.476,16.274-1.423c4.565-0.952,8.848-2.383,12.847-4.285c1.713-12.758,6.377-22.559,13.988-29.41
c-10.848-1.14-20.601-2.857-29.264-5.14c-8.658-2.286-17.605-5.996-26.835-11.14c-9.235-5.137-16.896-11.516-22.985-19.126
c-6.09-7.614-11.088-17.61-14.987-29.979c-3.901-12.374-5.852-26.648-5.852-42.826c0-23.035,7.52-42.637,22.557-58.817
c-7.044-17.318-6.379-36.732,1.997-58.24c5.52-1.715,13.706-0.428,24.554,3.853c10.85,4.283,18.794,7.952,23.84,10.994
c5.046,3.041,9.089,5.618,12.135,7.708c17.705-4.947,35.976-7.421,54.818-7.421s37.117,2.474,54.823,7.421l10.849-6.849
c7.419-4.57,16.18-8.758,26.262-12.565c10.088-3.805,17.802-4.853,23.134-3.138c8.562,21.509,9.325,40.922,2.279,58.24
c15.036,16.18,22.559,35.787,22.559,58.817c0,16.178-1.958,30.497-5.853,42.966c-3.9,12.471-8.941,22.457-15.125,29.979
c-6.191,7.521-13.901,13.85-23.131,18.986c-9.232,5.14-18.182,8.85-26.84,11.136c-8.662,2.286-18.415,4.004-29.263,5.146
c9.894,8.562,14.842,22.077,14.842,40.539v60.237c0,3.422,1.19,6.279,3.572,8.562c2.379,2.279,6.136,2.95,11.276,1.995
c44.163-14.653,80.185-41.062,108.068-79.226c27.88-38.161,41.825-81.126,41.825-128.906
C438.536,184.851,428.728,148.168,409.132,114.573z"/>
</svg>
</a>
<span class="center consent-message">This app uses cookies to report errors and anonymous usage information.</span>
<button id="consent-accept-button" class="center consent-accept-button">Accept</button>
<button id="open-file-button" class="center open-file-button">Open Model&hellip;</button>
<button id="github-button" class="center github-button">Download</button>
<input type="file" id="open-file-dialog" class="open-file-dialog" multiple="false" accept=".onnx, .ort, .pb, .meta, .tflite, .lite, .tfl, .keras, .h5, .hd5, .hdf5, .json, .model, .mar, .params, .param, .armnn, .mnn, .ncnn, .tnnproto, .tmfile, .ms, .om, .nn, .uff, .rknn, .xmodel, .kmodel, .paddle, .pdmodel, .pdparams, .nb, .dnn, .cmf, .mlmodel, .mlpackage, .caffemodel, .pbtxt, .prototxt, .pkl, .pt, .pth, .ptl, .t7, .joblib, .cfg, .xml, .zip, .tar">
<!-- Preload fonts to workaround Chrome SVG layout issue -->
<div style="font-weight: normal; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
</div>
</body>
</html>

1066
index.js

File diff suppressed because it is too large Load Diff

@ -0,0 +1,566 @@
var json = json || {};
var text = text || require('./text');
json.TextReader = class {
static open(data) {
const decoder = text.Decoder.open(data);
let state = 'start';
for (let i = 0; i < 0x1000; i++) {
const c = decoder.decode();
if (c === undefined || c === '\0') {
if (i === 0) {
return null;
}
break;
}
if (c <= ' ') {
if (c !== ' ' && c !== '\n' && c !== '\r' && c !== '\t') {
return null;
}
continue;
}
switch (state) {
case 'start':
if (c === '#') {
state = 'comment';
break;
}
if (c === '[') {
state = 'list';
break;
}
if (c === '{') {
state = 'object';
break;
}
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
state = '';
break;
}
return null;
case 'list':
if (c === '"' || c === '-' || c === '+' || c === '{' || c === '[' || (c >= '0' && c <= '9')) {
state = '';
break;
}
return null;
case 'object':
if (c != '"') {
return null;
}
state = '';
continue;
}
}
return new json.TextReader(data);
}
constructor(data) {
this._data = data;
this._escape = { '"': '"', '\\': '\\', '/': '/', b: '\b', f: '\f', n: '\n', r: '\r', t: '\t' };
}
read() {
const decoder = text.Decoder.open(this._data);
const stack = [];
this._decoder = decoder;
this._position = 0;
this._char = decoder.decode();
this._whitespace();
let obj = undefined;
let first = true;
for (;;) {
if (Array.isArray(obj)) {
this._whitespace();
let c = this._char;
if (c === ']') {
this._next();
this._whitespace();
if (stack.length > 0) {
obj = stack.pop();
first = false;
continue;
}
if (this._char !== undefined) {
this._unexpected();
}
return obj;
}
if (!first) {
if (this._char !== ',') {
this._unexpected();
}
this._next();
this._whitespace();
c = this._char;
}
first = false;
switch (c) {
case '{': {
this._next();
stack.push(obj);
const item = {};
obj.push(item);
obj = item;
first = true;
break;
}
case '[': {
this._next();
stack.push(obj);
const item = [];
obj.push(item);
obj = item;
first = true;
break;
}
default: {
obj.push(c === '"' ? this._string() : this._literal());
break;
}
}
}
else if (obj instanceof Object) {
this._whitespace();
let c = this._char;
if (c === '}') {
this._next();
this._whitespace();
if (stack.length > 0) {
obj = stack.pop();
first = false;
continue;
}
if (this._char !== undefined) {
this._unexpected();
}
return obj;
}
if (!first) {
if (this._char !== ',') {
this._unexpected();
}
this._next();
this._whitespace();
c = this._char;
}
first = false;
if (c === '"') {
const key = this._string();
switch (key) {
case '__proto__':
case 'constructor':
case 'prototype':
throw new json.Error("Invalid key '" + key + "'" + this._location());
}
this._whitespace();
if (this._char !== ':') {
this._unexpected();
}
this._next();
this._whitespace();
c = this._char;
switch (c) {
case '{': {
this._next();
stack.push(obj);
const value = {};
obj[key] = value;
obj = value;
first = true;
break;
}
case '[': {
this._next();
stack.push(obj);
const value = [];
obj[key] = value;
obj = value;
first = true;
break;
}
default: {
obj[key] = c === '"' ? this._string() : this._literal();
break;
}
}
this._whitespace();
continue;
}
this._unexpected();
}
else {
const c = this._char;
switch (c) {
case '{': {
this._next();
this._whitespace();
obj = {};
first = true;
break;
}
case '[': {
this._next();
this._whitespace();
obj = [];
first = true;
break;
}
default: {
const value = c === '"' ? this._string() : c >= '0' && c <= '9' ? this._number() : this._literal();
this._whitespace();
if (this._char !== undefined) {
this._unexpected();
}
return value;
}
}
}
}
}
_next() {
if (this._char === undefined) {
this._unexpected();
}
this._position = this._decoder.position;
this._char = this._decoder.decode();
}
_whitespace() {
while (this._char === ' ' || this._char === '\n' || this._char === '\r' || this._char === '\t') {
this._next();
}
}
_literal() {
const c = this._char;
if (c >= '0' && c <= '9') {
return this._number();
}
switch (c) {
case 't': this._expect('true'); return true;
case 'f': this._expect('false'); return false;
case 'n': this._expect('null'); return null;
case 'N': this._expect('NaN'); return NaN;
case 'I': this._expect('Infinity'); return Infinity;
case '-': return this._number();
}
this._unexpected();
}
_number() {
let value = '';
if (this._char === '-') {
value = '-';
this._next();
}
if (this._char === 'I') {
this._expect('Infinity');
return -Infinity;
}
const c = this._char;
if (c < '0' || c > '9') {
this._unexpected();
}
value += c;
this._next();
if (c === '0') {
const n = this._char;
if (n >= '0' && n <= '9') {
this._unexpected();
}
}
while (this._char >= '0' && this._char <= '9') {
value += this._char;
this._next();
}
if (this._char === '.') {
value += '.';
this._next();
const n = this._char;
if (n < '0' || n > '9') {
this._unexpected();
}
while (this._char >= '0' && this._char <= '9') {
value += this._char;
this._next();
}
}
if (this._char === 'e' || this._char === 'E') {
value += this._char;
this._next();
const s = this._char;
if (s === '-' || s === '+') {
value += this._char;
this._next();
}
const c = this._char;
if (c < '0' || c > '9') {
this._unexpected();
}
value += this._char;
this._next();
while (this._char >= '0' && this._char <= '9') {
value += this._char;
this._next();
}
}
return +value;
}
_string() {
let value = '';
this._next();
while (this._char != '"') {
if (this._char === '\\') {
this._next();
if (this._char === 'u') {
this._next();
let uffff = 0;
for (let i = 0; i < 4; i ++) {
const hex = parseInt(this._char, 16);
if (!isFinite(hex)) {
this._unexpected();
}
this._next();
uffff = uffff * 16 + hex;
}
value += String.fromCharCode(uffff);
}
else if (this._escape[this._char]) {
value += this._escape[this._char];
this._next();
}
else {
this._unexpected();
}
}
else if (this._char < ' ') {
this._unexpected();
}
else {
value += this._char;
this._next();
}
}
this._next();
return value;
}
_expect(value) {
for (let i = 0; i < value.length; i++) {
if (value[i] !== this._char) {
this._unexpected();
}
this._next();
}
}
_unexpected() {
let c = this._char;
if (c === undefined) {
throw new json.Error('Unexpected end of JSON input.');
}
else if (c === '"') {
c = 'string';
}
else if ((c >= '0' && c <= '9') || c === '-') {
c = 'number';
}
else {
if (c < ' ' || c > '\x7F') {
const name = Object.keys(this._escape).filter((key) => this._escape[key] === c);
c = (name.length === 1) ? '\\' + name : '\\u' + ('000' + c.charCodeAt(0).toString(16)).slice(-4);
}
c = "token '" + c + "'";
}
throw new json.Error('Unexpected ' + c + this._location());
}
_location() {
let line = 1;
let column = 1;
this._decoder.position = 0;
let c;
do {
if (this._decoder.position === this._position) {
return ' at ' + line.toString() + ':' + column.toString() + '.';
}
c = this._decoder.decode();
if (c === '\n') {
line++;
column = 1;
}
else {
column++;
}
}
while (c !== undefined);
return ' at ' + line.toString() + ':' + column.toString() + '.';
}
};
json.BinaryReader = class {
static open(data) {
const buffer = data instanceof Uint8Array ? data : data.peek();
return new json.BinaryReader(buffer);
}
constructor(buffer) {
this._buffer = buffer;
}
read() {
const buffer = this._buffer;
const length = buffer.length;
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const asciiDecoder = new TextDecoder('ascii');
const utf8Decoder = new TextDecoder('utf-8');
let position = 0;
const skip = (offset) => {
position += offset;
if (position > length) {
throw new json.Error('Expected ' + (position + length) + ' more bytes. The file might be corrupted. Unexpected end of file.', true);
}
};
const header = () => {
const start = position;
skip(4);
const size = view.getInt32(start, 4);
if (size < 5 || start + size > length || buffer[start + size - 1] != 0x00) {
throw new json.Error('Invalid file size.', true);
}
};
header();
const stack = [];
let obj = {};
for (;;) {
skip(1);
const type = buffer[position - 1];
if (type == 0x00) {
if (stack.length === 0) {
break;
}
obj = stack.pop();
continue;
}
const start = position;
position = buffer.indexOf(0x00, start) + 1;
const key = asciiDecoder.decode(buffer.subarray(start, position - 1));
let value = null;
switch (type) {
case 0x01: { // float64
const start = position;
skip(8);
value = view.getFloat64(start, true);
break;
}
case 0x02: { // string
skip(4);
const size = view.getInt32(position - 4, true);
const start = position;
skip(size);
value = utf8Decoder.decode(buffer.subarray(start, position - 1));
if (buffer[position - 1] != '0x00') {
throw new json.Error('String missing terminal 0.', true);
}
break;
}
case 0x03: { // object
header();
value = {};
break;
}
case 0x04: { // array
header();
value = [];
break;
}
case 0x05: { // bytes
const start = position;
skip(5);
const size = view.getInt32(start, true);
const subtype = buffer[start + 4];
if (subtype !== 0x00) {
throw new json.Error("Unknown binary subtype '" + subtype + "'.", true);
}
skip(size);
value = buffer.subarray(start + 5, position);
break;
}
case 0x08: { // boolean
skip(1);
value = buffer[position - 1];
if (value > 1) {
throw new json.Error("Invalid boolean value '" + value + "'.", true);
}
value = value === 1 ? true : false;
break;
}
case 0x0A:
value = null;
break;
case 0x10: {
const start = position;
skip(4);
value = view.getInt32(start, true);
break;
}
case 0x11: { // uint64
const start = position;
skip(8);
value = view.getUint64(start, true).toNumber();
break;
}
case 0x12: { // int64
const start = position;
skip(8);
value = view.getInt64(start, true).toNumber();
break;
}
default:
throw new json.Error("Unknown value type '" + type + "'.", true);
}
if (Array.isArray(obj)) {
if (obj.length !== parseInt(key, 10)) {
throw new json.Error("Invalid array index '" + key + "'.", true);
}
obj.push(value);
}
else {
switch (key) {
case '__proto__':
case 'constructor':
case 'prototype':
throw new json.Error("Invalid key '" + key + "' at " + position.toString() + "'.", true);
}
obj[key] = value;
}
if (type === 0x03 || type === 0x04) {
stack.push(obj);
obj = value;
}
}
if (position !== length) {
throw new json.Error("Unexpected data at '" + position.toString() + "'.", true);
}
return obj;
}
};
json.Error = class extends Error {
constructor(message, binary) {
super(message);
this.name = binary ? 'BSON Error' : 'JSON Error';
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.TextReader = json.TextReader;
module.exports.BinaryReader = json.BinaryReader;
}

@ -0,0 +1,567 @@
// Experimental
var numpy = numpy || {};
var python = python || require('./python');
numpy.ModelFactory = class {
match(context) {
const stream = context.stream;
const signature = [ 0x93, 0x4E, 0x55, 0x4D, 0x50, 0x59 ];
if (signature.length <= stream.length && stream.peek(signature.length).every((value, index) => value === signature[index])) {
return { name: 'npy' };
}
const entries = context.entries('zip');
if (entries.size > 0 && Array.from(entries.keys()).every((name) => name.endsWith('.npy'))) {
return { name: 'npz', value: entries };
}
const obj = context.open('pkl');
if (obj) {
if (numpy.Utility.isTensor(obj)) {
return { name: 'numpy.ndarray', value: obj };
}
if (Array.isArray(obj) && obj.every((obj) => obj && obj.__class__ && obj.__class__.__name__ === 'Network' && (obj.__class__.__module__ === 'dnnlib.tflib.network' || obj.__class__.__module__ === 'tfutil'))) {
return { name: 'dnnlib.tflib.network', value: obj };
}
const weights = numpy.Utility.weights(obj);
if (weights) {
return { name: 'pickle', value: weights };
}
}
return undefined;
}
open(context, match) {
let format = '';
const graphs = [];
switch (match.name) {
case 'npy': {
format = 'NumPy Array';
const execution = new python.Execution(null);
const stream = context.stream;
const buffer = stream.peek();
const bytes = execution.invoke('io.BytesIO', [ buffer ]);
const array = execution.invoke('numpy.load', [ bytes ]);
const layer = { type: 'numpy.ndarray', parameters: [ { name: 'value', tensor: { name: '', array: array } } ] };
graphs.push({ layers: [ layer ] });
break;
}
case 'npz': {
format = 'NumPy Zip';
const layers = new Map();
const execution = new python.Execution(null);
for (const entry of match.value) {
if (!entry[0].endsWith('.npy')) {
throw new numpy.Error("Invalid file name '" + entry.name + "'.");
}
const name = entry[0].replace(/\.npy$/, '');
const parts = name.split('/');
const parameterName = parts.pop();
const groupName = parts.join('/');
if (!layers.has(groupName)) {
layers.set(groupName, { name: groupName, parameters: [] });
}
const layer = layers.get(groupName);
const stream = entry[1];
const buffer = stream.peek();
const bytes = execution.invoke('io.BytesIO', [ buffer ]);
let array = execution.invoke('numpy.load', [ bytes ]);
if (array.dtype.byteorder === '|' && array.dtype.itemsize !== 1) {
if (array.dtype.kind !== 'O') {
throw new numpy.Error("Invalid data type '" + array.dataType + "'.");
}
const unpickler = python.Unpickler.open(array.data);
array = unpickler.load((name, args) => execution.invoke(name, args));
}
layer.parameters.push({
name: parameterName,
tensor: { name: name, array: array }
});
}
graphs.push({ layers: Array.from(layers.values()) });
break;
}
case 'pickle': {
format = 'NumPy Weights';
const layers = new Map();
const weights = match.value;
let separator = '.';
if (Array.from(weights.keys()).filter((key) => key.indexOf('_') !== -1) &&
Array.from(weights.keys()).every((key) => key.indexOf('_') > key.indexOf('.'))) {
separator = '_';
}
for (const pair of weights) {
const name = pair[0];
const array = pair[1];
const parts = name.split(separator);
const parameterName = parts.length > 1 ? parts.pop() : '?';
const layerName = parts.join(separator);
if (!layers.has(layerName)) {
layers.set(layerName, { name: layerName, parameters: [] });
}
const layer = layers.get(layerName);
layer.parameters.push({
name: parameterName,
tensor: { name: name, array: array }
});
}
graphs.push({ layers: Array.from(layers.values()) });
break;
}
case 'numpy.ndarray': {
format = 'NumPy NDArray';
const layer = {
type: 'numpy.ndarray',
parameters: [ { name: 'value', tensor: { name: '', array: match.value } } ]
};
graphs.push({ layers: [ layer ] });
break;
}
case 'dnnlib.tflib.network': {
format = 'dnnlib';
for (const obj of match.value) {
const layers = new Map();
for (const entry of obj.variables) {
const name = entry[0];
const value = entry[1];
if (numpy.Utility.isTensor(value)) {
const parts = name.split('/');
const parameterName = parts.length > 1 ? parts.pop() : '?';
const layerName = parts.join('/');
if (!layers.has(layerName)) {
layers.set(layerName, { name: layerName, parameters: [] });
}
const layer = layers.get(layerName);
layer.parameters.push({
name: parameterName,
tensor: { name: name, array: value }
});
}
}
graphs.push({ name: obj.name, layers: Array.from(layers.values()) });
}
break;
}
}
const model = new numpy.Model(format, graphs);
return Promise.resolve(model);
}
};
numpy.Model = class {
constructor(format, graphs) {
this._format = format;
this._graphs = graphs.map((graph) => new numpy.Graph(graph));
}
get format() {
return this._format;
}
get graphs() {
return this._graphs;
}
};
numpy.Graph = class {
constructor(graph) {
this._name = graph.name || '';
this._nodes = graph.layers.map((layer) => new numpy.Node(layer));
}
get name() {
return this._name;
}
get inputs() {
return [];
}
get outputs() {
return [];
}
get nodes() {
return this._nodes;
}
};
numpy.Parameter = class {
constructor(name, args) {
this._name = name;
this._arguments = args;
}
get name() {
return this._name;
}
get visible() {
return true;
}
get arguments() {
return this._arguments;
}
};
numpy.Argument = class {
constructor(name, initializer) {
if (typeof name !== 'string') {
throw new numpy.Error("Invalid argument identifier '" + JSON.stringify(name) + "'.");
}
this._name = name;
this._initializer = initializer || null;
}
get name() {
return this._name;
}
get type() {
return this._initializer.type;
}
get initializer() {
return this._initializer;
}
};
numpy.Node = class {
constructor(layer) {
this._name = layer.name || '';
this._type = { name: layer.type || 'Module' };
this._inputs = [];
for (const parameter of layer.parameters) {
const initializer = new numpy.Tensor(parameter.tensor.array);
this._inputs.push(new numpy.Parameter(parameter.name, [
new numpy.Argument(parameter.tensor.name || '', initializer)
]));
}
}
get type() {
return this._type;
}
get name() {
return this._name;
}
get inputs() {
return this._inputs;
}
get outputs() {
return [];
}
get attributes() {
return [];
}
};
numpy.Tensor = class {
constructor(array) {
this._type = new numpy.TensorType(array.dtype.name, new numpy.TensorShape(array.shape));
this._data = array.tobytes();
this._byteorder = array.dtype.byteorder;
this._itemsize = array.dtype.itemsize;
}
get type(){
return this._type;
}
get state() {
return this._context().state;
}
get value() {
const context = this._context();
if (context.state) {
return null;
}
context.limit = Number.MAX_SAFE_INTEGER;
return this._decode(context, 0);
}
toString() {
const context = this._context();
if (context.state) {
return '';
}
context.limit = 10000;
const value = this._decode(context, 0);
return numpy.Tensor._stringify(value, '', ' ');
}
_context() {
const context = {};
context.index = 0;
context.count = 0;
context.state = null;
if (this._byteorder !== '<' && this._byteorder !== '>' && this._type.dataType !== 'uint8' && this._type.dataType !== 'int8') {
context.state = 'Tensor byte order is not supported.';
return context;
}
if (!this._data || this._data.length == 0) {
context.state = 'Tensor data is empty.';
return context;
}
context.itemSize = this._itemsize;
context.dimensions = this._type.shape.dimensions;
context.dataType = this._type.dataType;
context.littleEndian = this._byteorder == '<';
context.data = this._data;
context.rawData = new DataView(this._data.buffer, this._data.byteOffset, this._data.byteLength);
return context;
}
_decode(context, dimension) {
const littleEndian = context.littleEndian;
const shape = context.dimensions.length == 0 ? [ 1 ] : context.dimensions;
const results = [];
const size = shape[dimension];
if (dimension == shape.length - 1) {
for (let i = 0; i < size; i++) {
if (context.count > context.limit) {
results.push('...');
return results;
}
if (context.rawData) {
switch (context.dataType) {
case 'float16':
results.push(context.rawData.getFloat16(context.index, littleEndian));
break;
case 'float32':
results.push(context.rawData.getFloat32(context.index, littleEndian));
break;
case 'float64':
results.push(context.rawData.getFloat64(context.index, littleEndian));
break;
case 'int8':
results.push(context.rawData.getInt8(context.index, littleEndian));
break;
case 'int16':
results.push(context.rawData.getInt16(context.index, littleEndian));
break;
case 'int32':
results.push(context.rawData.getInt32(context.index, littleEndian));
break;
case 'int64':
results.push(context.rawData.getInt64(context.index, littleEndian));
break;
case 'uint8':
results.push(context.rawData.getUint8(context.index, littleEndian));
break;
case 'uint16':
results.push(context.rawData.getUint16(context.index, littleEndian));
break;
case 'uint32':
results.push(context.rawData.getUint32(context.index, littleEndian));
break;
}
context.index += context.itemSize;
context.count++;
}
}
}
else {
for (let j = 0; j < size; j++) {
if (context.count > context.limit) {
results.push('...');
return results;
}
results.push(this._decode(context, dimension + 1));
}
}
if (context.dimensions.length == 0) {
return results[0];
}
return results;
}
static _stringify(value, indentation, indent) {
if (Array.isArray(value)) {
const result = [];
result.push(indentation + '[');
const items = value.map((item) => numpy.Tensor._stringify(item, indentation + indent, indent));
if (items.length > 0) {
result.push(items.join(',\n'));
}
result.push(indentation + ']');
return result.join('\n');
}
if (typeof value == 'string') {
return indentation + value;
}
if (value == Infinity) {
return indentation + 'Infinity';
}
if (value == -Infinity) {
return indentation + '-Infinity';
}
if (isNaN(value)) {
return indentation + 'NaN';
}
return indentation + value.toString();
}
};
numpy.TensorType = class {
constructor(dataType, shape) {
this._dataType = dataType;
this._shape = shape;
}
get dataType() {
return this._dataType || '?';
}
get shape() {
return this._shape;
}
toString() {
return this.dataType + this._shape.toString();
}
};
numpy.TensorShape = class {
constructor(dimensions) {
this._dimensions = dimensions;
}
get dimensions() {
return this._dimensions;
}
toString() {
if (!this._dimensions || this._dimensions.length == 0) {
return '';
}
return '[' + this._dimensions.join(',') + ']';
}
};
numpy.Utility = class {
static isTensor(obj) {
return obj && obj.__class__ &&
((obj.__class__.__module__ === 'numpy' && obj.__class__.__name__ === 'ndarray') ||
(obj.__class__.__module__ === 'numpy.core.memmap' && obj.__class__.__name__ === 'memmap'));
}
static weights(obj) {
const dict = (obj, key) => {
const dict = key === '' ? obj : obj[key];
if (dict) {
const weights = new Map();
if (dict instanceof Map) {
for (const pair of dict) {
const key = pair[0];
const obj = pair[1];
if (numpy.Utility.isTensor(obj)) {
weights.set(key, obj);
continue;
}
else if (obj instanceof Map && Array.from(obj).every((pair) => numpy.Utility.isTensor(pair[1]))) {
for (const pair of obj) {
weights.set(key + '.' + pair[0], pair[1]);
}
continue;
}
else if (key === '_metadata') {
continue;
}
return null;
}
return weights;
}
else if (!Array.isArray(dict)) {
const set = new Set([ 'weight_order', 'lr', 'model_iter', '__class__' ]);
for (const entry of Object.entries(dict)) {
const key = entry[0];
const value = entry[1];
if (key) {
if (numpy.Utility.isTensor(value)) {
weights.set(key, value);
continue;
}
if (set.has(key)) {
continue;
}
if (value && !Array.isArray(value) && Object.entries(value).every((entry) => numpy.Utility.isTensor(entry[1]))) {
const name = key;
for (const entry of Object.entries(value)) {
weights.set(name + '.' + entry[0], entry[1]);
}
continue;
}
}
return null;
}
return weights;
}
}
return null;
};
const list = (obj, key) => {
const list = key === '' ? obj : obj[key];
if (list && Array.isArray(list)) {
const weights = new Map();
for (let i = 0; i < list.length; i++) {
const obj = list[i];
if (numpy.Utility.isTensor(obj)) {
weights.set(i.toString(), obj);
continue;
}
else if (obj instanceof Map && Array.from(obj).every((pair) => numpy.Utility.isTensor(pair[1]))) {
for (const pair of obj) {
weights.set(i.toString() + '.' + pair[0], pair[1]);
}
continue;
}
return null;
}
return weights;
}
};
const keys = [ '', 'blobs', 'model' ];
for (const key of keys) {
const weights = dict(obj, key);
if (weights && weights.size > 0) {
return weights;
}
}
for (const key of keys) {
const weights = list(obj, key);
if (weights) {
return weights;
}
}
return null;
}
};
numpy.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'Error loading Chainer model.';
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.ModelFactory = numpy.ModelFactory;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -0,0 +1,401 @@
var $root = flatbuffers.get('ort');
$root.onnxruntime = $root.onnxruntime || {};
$root.onnxruntime.fbs = $root.onnxruntime.fbs || {};
$root.onnxruntime.fbs.AttributeType = {
UNDEFINED: 0,
FLOAT: 1,
INT: 2,
STRING: 3,
TENSOR: 4,
GRAPH: 5,
FLOATS: 6,
INTS: 7,
STRINGS: 8,
TENSORS: 9,
GRAPHS: 10,
SPARSE_TENSOR: 11,
SPARSE_TENSORS: 12
};
$root.onnxruntime.fbs.Shape = class Shape {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.Shape();
$.dim = reader.tableArray(position, 4, $root.onnxruntime.fbs.Dimension.decode);
return $;
}
};
$root.onnxruntime.fbs.Dimension = class Dimension {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.Dimension();
$.value = reader.table(position, 4, $root.onnxruntime.fbs.DimensionValue.decode);
$.denotation = reader.string_(position, 6, null);
return $;
}
};
$root.onnxruntime.fbs.DimensionValueType = {
UNKNOWN: 0,
VALUE: 1,
PARAM: 2
};
$root.onnxruntime.fbs.DimensionValue = class DimensionValue {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.DimensionValue();
$.dim_type = reader.int8_(position, 4, 0);
$.dim_value = reader.int64_(position, 6, 0);
$.dim_param = reader.string_(position, 8, null);
return $;
}
};
$root.onnxruntime.fbs.TensorDataType = {
UNDEFINED: 0,
FLOAT: 1,
UINT8: 2,
INT8: 3,
UINT16: 4,
INT16: 5,
INT32: 6,
INT64: 7,
STRING: 8,
BOOL: 9,
FLOAT16: 10,
DOUBLE: 11,
UINT32: 12,
UINT64: 13,
COMPLEX64: 14,
COMPLEX128: 15,
BFLOAT16: 16
};
$root.onnxruntime.fbs.TensorTypeAndShape = class TensorTypeAndShape {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.TensorTypeAndShape();
$.elem_type = reader.int32_(position, 4, 0);
$.shape = reader.table(position, 6, $root.onnxruntime.fbs.Shape.decode);
return $;
}
};
$root.onnxruntime.fbs.MapType = class MapType {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.MapType();
$.key_type = reader.int32_(position, 4, 0);
$.value_type = reader.table(position, 6, $root.onnxruntime.fbs.TypeInfo.decode);
return $;
}
};
$root.onnxruntime.fbs.SequenceType = class SequenceType {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.SequenceType();
$.elem_type = reader.table(position, 4, $root.onnxruntime.fbs.TypeInfo.decode);
return $;
}
};
$root.onnxruntime.fbs.NodeType = {
Primitive: 0,
Fused: 1
};
$root.onnxruntime.fbs.EdgeEnd = class EdgeEnd {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.EdgeEnd();
$.node_index = reader.uint32(position + 0);
$.src_arg_index = reader.int32(position + 4);
$.dst_arg_index = reader.int32(position + 8);
return $;
}
};
$root.onnxruntime.fbs.NodeEdge = class NodeEdge {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.NodeEdge();
$.node_index = reader.uint32_(position, 4, 0);
$.input_edges = reader.structArray(position, 6, undefined,$root.onnxruntime.fbs.EdgeEnd.decode);
$.output_edges = reader.structArray(position, 8, undefined,$root.onnxruntime.fbs.EdgeEnd.decode);
return $;
}
};
$root.onnxruntime.fbs.Node = class Node {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.Node();
$.name = reader.string_(position, 4, null);
$.doc_string = reader.string_(position, 6, null);
$.domain = reader.string_(position, 8, null);
$.since_version = reader.int32_(position, 10, 0);
$.index = reader.uint32_(position, 12, 0);
$.op_type = reader.string_(position, 14, null);
$.type = reader.int32_(position, 16, 0);
$.execution_provider_type = reader.string_(position, 18, null);
$.inputs = reader.strings_(position, 20);
$.outputs = reader.strings_(position, 22);
$.attributes = reader.tableArray(position, 24, $root.onnxruntime.fbs.Attribute.decode);
$.input_arg_counts = reader.typedArray(position, 26, Int32Array);
$.implicit_inputs = reader.strings_(position, 28);
return $;
}
};
$root.onnxruntime.fbs.ValueInfo = class ValueInfo {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.ValueInfo();
$.name = reader.string_(position, 4, null);
$.doc_string = reader.string_(position, 6, null);
$.type = reader.table(position, 8, $root.onnxruntime.fbs.TypeInfo.decode);
return $;
}
};
$root.onnxruntime.fbs.TypeInfoValue = class {
static decode(reader, position, type) {
switch (type) {
case 1: return $root.onnxruntime.fbs.TensorTypeAndShape.decode(reader, position);
case 2: return $root.onnxruntime.fbs.SequenceType.decode(reader, position);
case 3: return $root.onnxruntime.fbs.MapType.decode(reader, position);
}
return undefined;
}
static decodeText(reader, json, type) {
switch (type) {
case 'TensorTypeAndShape': return $root.onnxruntime.fbs.TensorTypeAndShape.decodeText(reader, json);
case 'SequenceType': return $root.onnxruntime.fbs.SequenceType.decodeText(reader, json);
case 'MapType': return $root.onnxruntime.fbs.MapType.decodeText(reader, json);
}
return undefined;
}
};
$root.onnxruntime.fbs.TypeInfo = class TypeInfo {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.TypeInfo();
$.denotation = reader.string_(position, 4, null);
$.value = reader.union(position, 6, $root.onnxruntime.fbs.TypeInfoValue.decode);
return $;
}
};
$root.onnxruntime.fbs.OperatorSetId = class OperatorSetId {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.OperatorSetId();
$.domain = reader.string_(position, 4, null);
$.version = reader.int64_(position, 6, 0);
return $;
}
};
$root.onnxruntime.fbs.Tensor = class Tensor {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.Tensor();
$.name = reader.string_(position, 4, null);
$.doc_string = reader.string_(position, 6, null);
$.dims = reader.int64s_(position, 8);
$.data_type = reader.int32_(position, 10, 0);
$.raw_data = reader.typedArray(position, 12, Uint8Array);
$.string_data = reader.strings_(position, 14);
return $;
}
};
$root.onnxruntime.fbs.SparseTensor = class SparseTensor {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.SparseTensor();
$.values = reader.table(position, 4, $root.onnxruntime.fbs.Tensor.decode);
$.indices = reader.table(position, 6, $root.onnxruntime.fbs.Tensor.decode);
$.dims = reader.int64s_(position, 8);
return $;
}
};
$root.onnxruntime.fbs.Attribute = class Attribute {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.Attribute();
$.name = reader.string_(position, 4, null);
$.doc_string = reader.string_(position, 6, null);
$.type = reader.int32_(position, 8, 0);
$.f = reader.float32_(position, 10, 0);
$.i = reader.int64_(position, 12, 0);
$.s = reader.string_(position, 14, null);
$.t = reader.table(position, 16, $root.onnxruntime.fbs.Tensor.decode);
$.g = reader.table(position, 18, $root.onnxruntime.fbs.Graph.decode);
$.floats = reader.typedArray(position, 20, Float32Array);
$.ints = reader.int64s_(position, 22);
$.strings = reader.strings_(position, 24);
$.tensors = reader.tableArray(position, 26, $root.onnxruntime.fbs.Tensor.decode);
$.graphs = reader.tableArray(position, 28, $root.onnxruntime.fbs.Graph.decode);
return $;
}
};
$root.onnxruntime.fbs.NodesToOptimizeIndices = class NodesToOptimizeIndices {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.NodesToOptimizeIndices();
$.node_indices = reader.typedArray(position, 4, Uint32Array);
$.num_inputs = reader.uint32_(position, 6, 0);
$.num_outputs = reader.uint32_(position, 8, 0);
$.has_variadic_input = reader.bool_(position, 10, false);
$.has_variadic_output = reader.bool_(position, 12, false);
$.num_variadic_inputs = reader.uint32_(position, 14, 0);
$.num_variadic_outputs = reader.uint32_(position, 16, 0);
return $;
}
};
$root.onnxruntime.fbs.NodeIndexAndKernelDefHash = class NodeIndexAndKernelDefHash {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.NodeIndexAndKernelDefHash();
$.node_index = reader.uint32_(position, 4, 0);
$.kernel_def_hash = reader.uint64_(position, 6, 0);
return $;
}
};
$root.onnxruntime.fbs.RuntimeOptimizationRecord = class RuntimeOptimizationRecord {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.RuntimeOptimizationRecord();
$.action_id = reader.string_(position, 4, null);
$.nodes_to_optimize_indices = reader.table(position, 6, $root.onnxruntime.fbs.NodesToOptimizeIndices.decode);
$.produced_nodes = reader.tableArray(position, 8, $root.onnxruntime.fbs.NodeIndexAndKernelDefHash.decode);
return $;
}
};
$root.onnxruntime.fbs.RuntimeOptimizationRecordContainerEntry = class RuntimeOptimizationRecordContainerEntry {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.RuntimeOptimizationRecordContainerEntry();
$.optimizer_name = reader.string_(position, 4, null);
$.runtime_optimization_records = reader.tableArray(position, 6, $root.onnxruntime.fbs.RuntimeOptimizationRecord.decode);
return $;
}
};
$root.onnxruntime.fbs.RuntimeOptimizations = class RuntimeOptimizations {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.RuntimeOptimizations();
$.records = reader.tableArray(position, 4, $root.onnxruntime.fbs.RuntimeOptimizationRecordContainerEntry.decode);
return $;
}
};
$root.onnxruntime.fbs.Graph = class Graph {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.Graph();
$.initializers = reader.tableArray(position, 4, $root.onnxruntime.fbs.Tensor.decode);
$.node_args = reader.tableArray(position, 6, $root.onnxruntime.fbs.ValueInfo.decode);
$.nodes = reader.tableArray(position, 8, $root.onnxruntime.fbs.Node.decode);
$.max_node_index = reader.uint32_(position, 10, 0);
$.node_edges = reader.tableArray(position, 12, $root.onnxruntime.fbs.NodeEdge.decode);
$.inputs = reader.strings_(position, 14);
$.outputs = reader.strings_(position, 16);
$.sparse_initializers = reader.tableArray(position, 18, $root.onnxruntime.fbs.SparseTensor.decode);
$.runtime_optimizations = reader.table(position, 20, $root.onnxruntime.fbs.RuntimeOptimizations.decode);
return $;
}
};
$root.onnxruntime.fbs.StringStringEntry = class StringStringEntry {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.StringStringEntry();
$.key = reader.string_(position, 4, null);
$.value = reader.string_(position, 6, null);
return $;
}
};
$root.onnxruntime.fbs.Model = class Model {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.Model();
$.ir_version = reader.int64_(position, 4, 0);
$.opset_import = reader.tableArray(position, 6, $root.onnxruntime.fbs.OperatorSetId.decode);
$.producer_name = reader.string_(position, 8, null);
$.producer_version = reader.string_(position, 10, null);
$.domain = reader.string_(position, 12, null);
$.model_version = reader.int64_(position, 14, 0);
$.doc_string = reader.string_(position, 16, null);
$.graph = reader.table(position, 18, $root.onnxruntime.fbs.Graph.decode);
$.graph_doc_string = reader.string_(position, 20, null);
$.metadata_props = reader.tableArray(position, 22, $root.onnxruntime.fbs.StringStringEntry.decode);
return $;
}
};
$root.onnxruntime.fbs.KernelCreateInfos = class KernelCreateInfos {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.KernelCreateInfos();
$.node_indices = reader.typedArray(position, 4, Uint32Array);
$.kernel_def_hashes = reader.uint64s_(position, 6);
return $;
}
};
$root.onnxruntime.fbs.SubGraphSessionState = class SubGraphSessionState {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.SubGraphSessionState();
$.graph_id = reader.string_(position, 4, null);
$.session_state = reader.table(position, 6, $root.onnxruntime.fbs.SessionState.decode);
return $;
}
};
$root.onnxruntime.fbs.SessionState = class SessionState {
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.SessionState();
$.kernels = reader.table(position, 4, $root.onnxruntime.fbs.KernelCreateInfos.decode);
$.sub_graph_session_states = reader.tableArray(position, 6, $root.onnxruntime.fbs.SubGraphSessionState.decode);
return $;
}
};
$root.onnxruntime.fbs.InferenceSession = class InferenceSession {
static identifier(reader) {
return reader.identifier === 'ORTM';
}
static create(reader) {
return $root.onnxruntime.fbs.InferenceSession.decode(reader, reader.root);
}
static decode(reader, position) {
const $ = new $root.onnxruntime.fbs.InferenceSession();
$.ort_version = reader.string_(position, 4, null);
$.model = reader.table(position, 6, $root.onnxruntime.fbs.Model.decode);
$.session_state = reader.table(position, 8, $root.onnxruntime.fbs.SessionState.decode);
return $;
}
};

2490
onnx.js

File diff suppressed because it is too large Load Diff

@ -0,0 +1,189 @@
// Experimental
var pickle = pickle || {};
var python = python || require('./python');
var zip = zip || require('./zip');
pickle.ModelFactory = class {
match(context) {
const stream = context.stream;
const signature = [ 0x80, undefined, 0x8a, 0x0a, 0x6c, 0xfc, 0x9c, 0x46, 0xf9, 0x20, 0x6a, 0xa8, 0x50, 0x19 ];
if (signature.length <= stream.length && stream.peek(signature.length).every((value, index) => signature[index] === undefined || signature[index] === value)) {
// Reject PyTorch models with .pkl file extension.
return undefined;
}
const obj = context.open('pkl');
if (obj !== undefined) {
return 'pickle';
}
return undefined;
}
open(context) {
return new Promise((resolve) => {
let format = 'Pickle';
const obj = context.open('pkl');
if (obj === null || obj === undefined) {
context.exception(new pickle.Error("Unknown Pickle null object in '" + context.identifier + "'."));
}
else if (Array.isArray(obj)) {
if (obj.length > 0 && obj[0] && obj.every((item) => item && item.__class__ && obj[0].__class__ && item.__class__.__module__ === obj[0].__class__.__module__ && item.__class__.__name__ === obj[0].__class__.__name__)) {
const type = obj[0].__class__.__module__ + "." + obj[0].__class__.__name__;
context.exception(new pickle.Error("Unknown Pickle '" + type + "' array object in '" + context.identifier + "'."));
}
else {
context.exception(new pickle.Error("Unknown Pickle array object in '" + context.identifier + "'."));
}
}
else if (obj && obj.__class__) {
const formats = new Map([
[ 'cuml.ensemble.randomforestclassifier.RandomForestClassifier', 'cuML' ]
]);
const type = obj.__class__.__module__ + "." + obj.__class__.__name__;
if (formats.has(type)) {
format = formats.get(type);
}
else {
context.exception(new pickle.Error("Unknown Pickle type '" + type + "' in '" + context.identifier + "'."));
}
}
else {
context.exception(new pickle.Error("Unknown Pickle object in '" + context.identifier + "'."));
}
resolve(new pickle.Model(obj, format));
});
}
};
pickle.Model = class {
constructor(value, format) {
this._format = format;
this._graphs = [ new pickle.Graph(value) ];
}
get format() {
return this._format;
}
get graphs() {
return this._graphs;
}
};
pickle.Graph = class {
constructor(obj) {
this._inputs = [];
this._outputs = [];
this._nodes = [];
if (Array.isArray(obj) && obj.every((item) => item.__class__)) {
for (const item of obj) {
this._nodes.push(new pickle.Node(item));
}
}
else if (obj && obj instanceof Map) {
for (const entry of obj) {
this._nodes.push(new pickle.Node(entry[1], entry[0]));
}
}
else if (obj && obj.__class__) {
this._nodes.push(new pickle.Node(obj));
}
else if (obj && Object(obj) === obj) {
this._nodes.push(new pickle.Node(obj));
}
}
get inputs() {
return this._inputs;
}
get outputs() {
return this._outputs;
}
get nodes() {
return this._nodes;
}
};
pickle.Node = class {
constructor(obj, name) {
this._name = name || '';
this._inputs = [];
this._outputs = [];
this._attributes = [];
if (Array.isArray(obj)) {
this._type = { name: 'List' };
this._attributes.push(new pickle.Attribute('value', obj));
}
else {
const type = obj.__class__ ? obj.__class__.__module__ + '.' + obj.__class__.__name__ : 'Object';
this._type = { name: type };
for (const key of Object.keys(obj)) {
const value = obj[key];
this._attributes.push(new pickle.Attribute(key, value));
}
}
}
get type() {
return this._type;
}
get name() {
return this._name;
}
get inputs() {
return this._inputs;
}
get outputs() {
return this._outputs;
}
get attributes() {
return this._attributes;
}
};
pickle.Attribute = class {
constructor(name, value) {
this._name = name;
this._value = value;
if (value && value.__class__) {
this._type = value.__class__.__module__ + '.' + value.__class__.__name__;
}
}
get name() {
return this._name;
}
get value() {
return this._value;
}
get type() {
return this._type;
}
};
pickle.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'Error loading Pickle model.';
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.ModelFactory = pickle.ModelFactory;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,298 @@
import codecs
import errno
import os
import random
import re
import socket
import sys
import threading
import webbrowser
import time
from .__version__ import __version__
if sys.version_info[0] > 2:
from urllib.parse import urlparse
from urllib.parse import unquote
from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
else:
from urlparse import urlparse
from urlparse import unquote
from BaseHTTPServer import HTTPServer
from BaseHTTPServer import BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
class HTTPRequestHandler(BaseHTTPRequestHandler):
def handler(self):
if not hasattr(self, 'mime_types_map'):
self.mime_types_map = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.png': 'image/png',
'.gif': 'image/gif',
'.jpg': 'image/jpeg',
'.ico': 'image/x-icon',
'.json': 'application/json',
'.pb': 'application/octet-stream',
'.ttf': 'font/truetype',
'.otf': 'font/opentype',
'.eot': 'application/vnd.ms-fontobject',
'.woff': 'font/woff',
'.woff2': 'application/font-woff2',
'.svg': 'image/svg+xml'
}
pathname = urlparse(self.path).path
folder = os.path.dirname(os.path.realpath(__file__))
location = folder + pathname
status_code = 0
headers = {}
buffer = None
data = '/data/'
if status_code == 0:
if pathname == '/':
meta = []
meta.append('<meta name="type" content="Python">')
meta.append('<meta name="version" content="' + __version__ + '">')
if self.file:
meta.append('<meta name="file" content="/data/' + self.file + '">')
with codecs.open(location + 'index.html', mode="r", encoding="utf-8") as open_file:
buffer = open_file.read()
buffer = re.sub(r'<meta name="version" content="\d+.\d+.\d+">', '\n'.join(meta), buffer)
buffer = buffer.encode('utf-8')
headers['Content-Type'] = 'text/html'
headers['Content-Length'] = len(buffer)
status_code = 200
elif pathname.startswith(data):
file = pathname[len(data):]
if file == self.file and self.data:
buffer = self.data
else:
file = self.folder + '/' + unquote(file)
status_code = 404
if os.path.exists(file):
with open(file, 'rb') as binary:
buffer = binary.read()
if buffer:
headers['Content-Type'] = 'application/octet-stream'
headers['Content-Length'] = len(buffer)
status_code = 200
else:
if os.path.exists(location) and not os.path.isdir(location):
extension = os.path.splitext(location)[1]
content_type = self.mime_types_map[extension]
if content_type:
with open(location, 'rb') as binary:
buffer = binary.read()
headers['Content-Type'] = content_type
headers['Content-Length'] = len(buffer)
status_code = 200
else:
status_code = 404
if self.log:
sys.stdout.write(str(status_code) + ' ' + self.command + ' ' + self.path + '\n')
sys.stdout.flush()
self.send_response(status_code)
for key in headers:
self.send_header(key, headers[key])
self.end_headers()
if self.command != 'HEAD':
if status_code == 404 and buffer is None:
self.wfile.write(bytes(status_code))
elif (status_code in (200, 404)) and buffer is not None:
self.wfile.write(buffer)
def do_GET(self):
self.handler()
def do_HEAD(self):
self.handler()
def log_message(self, format, *args):
return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
pass
class HTTPServerThread(threading.Thread):
def __init__(self, data, file, address, log):
threading.Thread.__init__(self)
self.address = address
self.url = 'http://' + address[0] + ':' + str(address[1])
self.file = file
self.server = ThreadedHTTPServer(address, HTTPRequestHandler)
self.server.timeout = 0.25
if file:
self.server.RequestHandlerClass.folder = os.path.dirname(file) if os.path.dirname(file) else '.'
self.server.RequestHandlerClass.file = os.path.basename(file)
else:
self.server.RequestHandlerClass.folder = ''
self.server.RequestHandlerClass.file = ''
self.server.RequestHandlerClass.data = data
self.server.RequestHandlerClass.log = log
self.terminate_event = threading.Event()
self.terminate_event.set()
self.stop_event = threading.Event()
def run(self):
self.stop_event.clear()
self.terminate_event.clear()
try:
while not self.stop_event.is_set():
self.server.handle_request()
except Exception:
pass
self.terminate_event.set()
self.stop_event.clear()
def stop(self):
if self.alive():
sys.stdout.write("Stopping " + self.url + "\n")
self.stop_event.set()
self.server.server_close()
self.terminate_event.wait(1000)
def alive(self):
return not self.terminate_event.is_set()
_thread_list = []
def _add_thread(thread):
global _thread_list
_thread_list.append(thread)
def _update_thread_list(address=None):
global _thread_list
_thread_list = [ thread for thread in _thread_list if thread.alive() ]
threads = _thread_list
if address is not None:
address = _make_address(address)
if address[1] is None:
threads = [ thread for thread in threads if address[0] == thread.address[0] ]
else:
threads = [ thread for thread in threads if address[0] == thread.address[0] and address[1] == thread.address[1] ]
return threads
def _make_address(address):
if address is None or isinstance(address, int):
port = address
address = ('localhost', port)
if isinstance(address, tuple) and len(address) == 2:
host = address[0]
port = address[1]
if isinstance(host, str) and (port is None or isinstance(port, int)):
return address
raise ValueError('Invalid address.')
def _make_port(address):
if address[1] is None or address[1] == 0:
ports = []
if address[1] != 0:
ports.append(8080)
ports.append(8081)
rnd = random.Random()
for _ in range(4):
port = rnd.randrange(15000, 25000)
if port not in ports:
ports.append(port)
ports.append(0)
for port in ports:
temp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
temp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
temp_socket.settimeout(1)
try:
temp_socket.bind((address[0], port))
sockname = temp_socket.getsockname()
address = (address[0], sockname[1])
return address
except:
pass
finally:
temp_socket.close()
if isinstance(address[1], int):
return address
raise ValueError('Failed to allocate port.')
def stop(address=None):
'''Stop serving model at address.
Args:
address (tuple, optional): A (host, port) tuple, or a port number.
'''
threads = _update_thread_list(address)
for thread in threads:
thread.stop()
_update_thread_list()
def status(adrress=None):
'''Is model served at address.
Args:
address (tuple, optional): A (host, port) tuple, or a port number.
'''
threads = _update_thread_list(adrress)
return len(threads) > 0
def wait():
'''Wait for console exit and stop all model servers.'''
try:
while len(_update_thread_list()) > 0:
time.sleep(1000)
except (KeyboardInterrupt, SystemExit):
sys.stdout.write('\n')
sys.stdout.flush()
stop()
def serve(file, data, address=None, browse=False, log=False):
'''Start serving model from file or data buffer at address and open in web browser.
Args:
file (string): Model file to serve. Required to detect format.
data (bytes): Model data to serve. None will load data from file.
log (bool, optional): Log details to console. Default: False
browse (bool, optional): Launch web browser. Default: True
address (tuple, optional): A (host, port) tuple, or a port number.
Returns:
A (host, port) address tuple.
'''
if not data and file and not os.path.exists(file):
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), file)
_update_thread_list()
address = _make_address(address)
if isinstance(address[1], int) and address[1] != 0:
stop(address)
else:
address = _make_port(address)
_update_thread_list()
thread = HTTPServerThread(data, file, address, log)
thread.start()
while not thread.alive():
time.sleep(10)
_add_thread(thread)
if file:
sys.stdout.write("Serving '" + file + "' at " + thread.url + "\n")
else:
sys.stdout.write("Serving at " + thread.url + "\n")
sys.stdout.flush()
if browse:
webbrowser.open(thread.url)
return address
def start(file=None, address=None, browse=True, log=False):
'''Start serving model file at address and open in web browser.
Args:
file (string): Model file to serve.
log (bool, optional): Log details to console. Default: False
browse (bool, optional): Launch web browser, Default: True
address (tuple, optional): A (host, port) tuple, or a port number.
Returns:
A (host, port) address tuple.
'''
return serve(file, None, browse=browse, address=address, log=log)

171
tar.js

@ -0,0 +1,171 @@
var tar = tar || {};
tar.Archive = class {
static open(data) {
const stream = data instanceof Uint8Array ? new tar.BinaryReader(data) : data;
if (stream.length > 512) {
const buffer = stream.peek(512);
const sum = buffer.map((value, index) => (index >= 148 && index < 156) ? 32 : value).reduce((a, b) => a + b, 0);
let checksum = '';
for (let i = 148; i < 156 && buffer[i] !== 0x00; i++) {
checksum += String.fromCharCode(buffer[i]);
}
checksum = parseInt(checksum, 8);
if (!isNaN(checksum) && sum === checksum) {
return new tar.Archive(stream);
}
}
return null;
}
constructor(stream) {
this._entries = new Map();
const position = stream.position;
while (stream.position < stream.length) {
const entry = new tar.Entry(stream);
if (entry.type === '0' || entry.type === '1' || entry.type === '2') {
this._entries.set(entry.name, entry.stream);
}
if (stream.position + 512 > stream.length ||
stream.peek(512).every((value) => value === 0x00)) {
break;
}
}
stream.seek(position);
}
get entries() {
return this._entries;
}
};
tar.Entry = class {
constructor(stream) {
const buffer = stream.read(512);
const reader = new tar.BinaryReader(buffer);
const sum = buffer.map((value, index) => (index >= 148 && index < 156) ? 32 : value).reduce((a, b) => a + b, 0);
let checksum = '';
for (let i = 148; i < 156 && buffer[i] !== 0x00; i++) {
checksum += String.fromCharCode(buffer[i]);
}
checksum = parseInt(checksum, 8);
if (isNaN(checksum) || sum !== checksum) {
throw new tar.Error('Invalid tar archive.');
}
this._name = reader.string(100);
reader.string(8); // file mode
reader.string(8); // owner
reader.string(8); // group
const size = parseInt(reader.string(12).trim(), 8);
reader.string(12); // timestamp
reader.string(8); // checksum
this._type = reader.string(1);
reader.string(100); // name of linked file
if (reader.string(6) === 'ustar') {
reader.string(2); // ustar version
reader.string(32); // owner user name
reader.string(32); // owner group name
reader.string(8); // device major number
reader.string(8); // device number number
this._name = reader.string(155) + this._name;
}
this._stream = stream.stream(size);
stream.read(((size % 512) != 0) ? (512 - (size % 512)) : 0);
}
get type() {
return this._type;
}
get name() {
return this._name;
}
get stream() {
return this._stream;
}
};
tar.BinaryReader = class {
constructor(buffer) {
this._buffer = buffer;
this._length = buffer.length;
this._position = 0;
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
}
get position() {
return this._position;
}
get length() {
return this._length;
}
create(buffer) {
return new tar.BinaryReader(buffer);
}
stream(length) {
return this.create(this.read(length));
}
seek(position) {
this._position = position >= 0 ? position : this._length + position;
}
skip(offset) {
this._position += offset;
}
peek(length) {
if (this._position === 0 && length === undefined) {
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
const end = this._position;
this.seek(position);
return this._buffer.subarray(position, end);
}
read(length) {
if (this._position === 0 && length === undefined) {
this._position = this._length;
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
return this._buffer.subarray(position, this._position);
}
string(length) {
const buffer = this.read(length);
let position = 0;
let content = '';
for (let i = 0; i < length; i++) {
const c = buffer[position++];
if (c === 0) {
break;
}
content += String.fromCharCode(c);
}
return content;
}
};
tar.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'tar Error';
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.Archive = tar.Archive;
}

@ -0,0 +1,292 @@
var text = text || {};
text.Decoder = class {
static open(data, encoding) {
if (typeof data === 'string') {
return new text.Decoder.String(data);
}
const assert = (encoding, condition) => {
if (encoding && encoding !== condition) {
throw new text.Error("Invalid encoding '" + encoding + "'.");
}
};
const buffer = data instanceof Uint8Array ? data : data.peek();
const length = buffer.length;
if (length >= 3 && buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
assert(encoding, 'utf-8');
return new text.Decoder.Utf8(buffer, 3, true);
}
if (length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe) {
assert(encoding, 'utf-16');
return new text.Decoder.Utf16LE(buffer, 2);
}
if (length >= 2 && buffer[0] === 0xfe && buffer[1] === 0xff) {
assert(encoding, 'utf-16');
return new text.Decoder.Utf16BE(buffer, 2);
}
if (length >= 4 && buffer[0] === 0x00 && buffer[1] === 0x00 && buffer[2] === 0xfe && buffer[3] === 0xff) {
throw new text.Error("Unsupported UTF-32 big-endian encoding.");
}
if (length >= 4 && buffer[0] === 0xff && buffer[1] === 0xfe && buffer[2] === 0x00 && buffer[3] === 0x00) {
throw new text.Error("Unsupported UTF-32 little-endian encoding.");
}
if (length >= 5 && buffer[0] === 0x2B && buffer[1] === 0x2F && buffer[2] === 0x76 && buffer[3] === 0x38 && buffer[4] === 0x2D) {
throw new text.Error("Unsupported UTF-7 encoding.");
}
if (length >= 4 && buffer[0] === 0x2B && buffer[1] === 0x2F && buffer[2] === 0x76 && (buffer[3] === 0x38 || buffer[3] === 0x39 || buffer[3] === 0x2B || buffer[3] === 0x2F)) {
throw new text.Error("Unsupported UTF-7 encoding.");
}
if (length >= 4 && buffer[0] === 0x84 && buffer[1] === 0x31 && buffer[2] === 0x95 && buffer[3] === 0x33) {
throw new text.Error("Unsupported GB-18030 encoding.");
}
if (length > 4 && (length % 2) == 0 && (buffer[0] === 0x00 || buffer[1] === 0x00 || buffer[2] === 0x00 || buffer[3] === 0x00)) {
const lo = new Uint32Array(256);
const hi = new Uint32Array(256);
for (let i = 0; i < length; i += 2) {
lo[buffer[i]]++;
hi[buffer[i + 1]]++;
}
if (lo[0x00] === 0 && (hi[0x00] / (length >> 1)) > 0.5) {
assert(encoding, 'utf-16');
return new text.Decoder.Utf16LE(buffer, 0);
}
if (hi[0x00] === 0 && (lo[0x00] / (length >> 1)) > 0.5) {
assert(encoding, 'utf-16');
return new text.Decoder.Utf16BE(buffer, 0);
}
}
if (encoding && (encoding.startsWith('iso-8859-') || encoding.startsWith('latin-'))) {
return new text.Decoder.Latin1(buffer, 0);
}
assert(encoding, 'utf-8');
return new text.Decoder.Utf8(buffer, 0, encoding === 'utf-8');
}
};
text.Decoder.String = class {
constructor(buffer) {
this.buffer = buffer ? buffer.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) : [];
this.position = 0;
this.length = this.buffer.length;
}
get encoding() {
return null;
}
decode() {
if (this.position < this.length) {
return this.buffer[this.position++];
}
return undefined;
}
};
text.Decoder.Utf8 = class {
constructor(buffer, position, fatal) {
this.position = position || 0;
this.buffer = buffer;
this.fatal = fatal;
}
get encoding() {
return 'utf-8';
}
decode() {
const c = this.buffer[this.position];
if (c === undefined) {
return c;
}
this.position++;
if (c < 0x80) {
return String.fromCodePoint(c);
}
if (c >= 0xC2 && c <= 0xDF) {
if (this.buffer[this.position] !== undefined) {
const c2 = this.buffer[this.position];
this.position++;
return String.fromCharCode(((c & 0x1F) << 6) | (c2 & 0x3F));
}
}
if (c >= 0xE0 && c <= 0xEF) {
if (this.buffer[this.position + 1] !== undefined) {
const c2 = this.buffer[this.position];
if ((c !== 0xE0 || c2 >= 0xA0) && (c !== 0xED || c2 <= 0x9f)) {
const c3 = this.buffer[this.position + 1];
if (c3 >= 0x80 && c3 < 0xFB) {
this.position += 2;
return String.fromCharCode(((c & 0x0F) << 12) | ((c2 & 0x3F) << 6) | ((c3 & 0x3F) << 0));
}
}
}
}
if (c >= 0xF0 && c <= 0xF4) {
if (this.buffer[this.position + 2] !== undefined) {
const c2 = this.buffer[this.position];
if (c2 >= 0x80 && c2 <= 0xBF) {
const c3 = this.buffer[this.position + 1];
if (c3 >= 0x80 && c3 <= 0xBF) {
const c4 = this.buffer[this.position + 2];
if (c4 >= 0x80 && c4 <= 0xBF) {
this.position += 3;
return String.fromCodePoint(((c & 0x07) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) | (c4 & 0x3F));
}
}
}
}
}
if (this.fatal) {
throw new text.Error('Invalid utf-8 character.');
}
return String.fromCharCode(0xfffd);
}
};
text.Decoder.Latin1 = class {
constructor(buffer, position) {
this.position = position || 0;
this.buffer = buffer;
}
get encoding() {
return 'latin-1';
}
decode() {
const c = this.buffer[this.position];
if (c === undefined) {
return c;
}
this.position++;
return String.fromCodePoint(c);
}
};
text.Decoder.Utf16LE = class {
constructor(buffer, position) {
this.buffer = buffer;
this.position = position || 0;
this.length = buffer.length;
}
get encoding() {
return 'utf-16';
}
decode() {
if (this.position + 1 < this.length) {
const c = this.buffer[this.position++] | (this.buffer[this.position++] << 8);
if (c < 0xD800 || c >= 0xDFFF) {
return String.fromCharCode(c);
}
if (c >= 0xD800 && c < 0xDBFF) {
if (this._position + 1 < this._length) {
const c2 = this._buffer[this._position++] | (this._buffer[this._position++] << 8);
if (c >= 0xDC00 || c < 0xDFFF) {
return String.fromCodePoint(0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff));
}
}
}
return String.fromCharCode(0xfffd);
}
return undefined;
}
};
text.Decoder.Utf16BE = class {
constructor(buffer, position) {
this.buffer = buffer;
this.position = position || 0;
this.length = buffer.length;
}
get encoding() {
return 'utf-16';
}
decode() {
if (this.position + 1 < this.length) {
const c = (this.buffer[this.position++] << 8) | this.buffer[this.position++];
if (c < 0xD800 || c >= 0xDFFF) {
return String.fromCharCode(c);
}
if (c >= 0xD800 && c < 0xDBFF) {
if (this._position + 1 < this._length) {
const c2 = (this._buffer[this._position++] << 8) | this._buffer[this._position++];
if (c >= 0xDC00 || c < 0xDFFF) {
return String.fromCodePoint(0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff));
}
}
}
return String.fromCharCode(0xfffd);
}
return undefined;
}
};
text.Reader = class {
constructor(data, length) {
this._decoder = text.Decoder.open(data);
this._position = 0;
this._length = length || Number.MAX_SAFE_INTEGER;
}
static open(data, length) {
return new text.Reader(data, length);
}
read() {
if (this._position >= this._length) {
return undefined;
}
let line = '';
let buffer = null;
for (;;) {
const c = this._decoder.decode();
if (c === undefined) {
this._length = this._position;
break;
}
this._position++;
if (this._position > this._length) {
break;
}
if (c === '\n') {
break;
}
line += c;
if (line.length >= 32) {
buffer = buffer || [];
buffer.push(line);
line = '';
}
}
if (buffer) {
buffer.push(line);
return buffer.join('');
}
return line;
}
};
text.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'Text Error';
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.Decoder = text.Decoder;
module.exports.Reader = text.Reader;
}

@ -0,0 +1,136 @@
.node path { stroke: #333; fill: none; stroke-width: 1px; }
.node line { stroke: #333; fill: none; stroke-width: 1px; }
.node-item path { stroke-width: 0; stroke: #000; fill: #fff; }
.node-item text { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 11px; text-rendering: geometricPrecision; }
.node-item-function path { fill: #fff; }
.node-item-function text { fill: #000; }
.node-item-function:hover { cursor: pointer; }
.node-item-function:hover path { fill: #eee; }
.node-item-type path { fill: #000; }
.node-item-type text { fill: #fff; }
.node-item-type:hover { cursor: pointer; }
.node-item-type:hover path { fill: #fff; }
.node-item-type:hover text { fill: #000; }
.node-item-type-constant path { fill: #eee; }
.node-item-type-constant text { fill: #000; }
.node-item-type-constant:hover path { fill: #fff; }
.node-item-type-control path { fill: #eee; }
.node-item-type-control text { fill: #000; }
.node-item-type-control:hover path { fill: #fff; }
.node-item-type-layer path { fill: rgb(51, 85, 136); }
.node-item-type-wrapper path { fill: rgb(238, 238, 238); }
.node-item-type-wrapper text { fill: rgb(0, 0, 0) }
.node-item-type-activation path { fill: rgb(112, 41, 33); }
.node-item-type-pool path { fill: rgb(51, 85, 51); }
.node-item-type-normalization path { fill: rgb(51, 85, 68); }
.node-item-type-dropout path { fill: rgb(69, 71, 112); }
.node-item-type-shape path { fill: rgb(108, 79, 71); }
.node-item-type-tensor path { fill: rgb(89, 66, 59); }
.node-item-type-transform path { fill: rgb(51, 85, 68); }
.node-item-type-data path { fill: rgb(85, 85, 85); }
.node-item-type-quantization path { fill: rgb(80, 40, 0); }
.node-item-type-custom path { fill: rgb(128, 128, 128); }
.node-item-input path { fill: #fff; }
.node-item-input:hover { cursor: pointer; }
.node-item-input:hover path { fill: #fff; }
.node-item-constant path { fill: #eee; }
.node-item-constant:hover { cursor: pointer; }
.node-item-constant:hover path { fill: #fff; }
.node-item-undefined path { fill: #f00; }
.node-item-undefined:hover { cursor: pointer; }
.node-item-undefined:hover path { fill: #fff; }
.node-attribute:hover { cursor: pointer; }
.node-attribute text { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 9px; font-weight: normal; text-rendering: geometricPrecision; }
.node-attribute path { fill: #fff; stroke-width: 0; stroke: #000; }
.node-attribute:hover path { fill: #f6f6f6; }
.graph-item-input path { fill: #eee; }
.graph-item-input:hover { cursor: pointer; }
.graph-item-input:hover path { fill: #fff; }
.graph-item-output path { fill: #eee; }
.graph-item-output:hover { cursor: pointer; }
.graph-item-output:hover path { fill: #fff; }
.edge-label { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 10px; }
.edge-path { stroke: #000; stroke-width: 1px; fill: none; marker-end: url("#arrowhead-vee"); }
#arrowhead-vee { fill: #000; }
.edge-path-control-dependency { stroke-dasharray: 3, 2; }
.cluster rect { stroke: #000; fill: #000; fill-opacity: 0.02; stroke-opacity: 0.06; stroke-width: 1px; }
.select .node.border { stroke: #e00; stroke-width: 2px; }
.select.edge-path { stroke: #e00; stroke-width: 2px; marker-end: url("#arrowhead-vee-select"); }
#arrowhead-vee-select { fill: #e00; }
@keyframes pulse { from { stroke-dashoffset: 100px; } to { stroke-dashoffset: 0; } }
@media (prefers-color-scheme: dark) {
.edge-label { fill: #b2b2b2; }
.edge-path { stroke: #888; }
#arrowhead-vee { fill: #888; }
.node path { stroke: #1d1d1d; }
.node line { stroke: #1d1d1d; }
.select .node.border { stroke: #b00; }
.select.edge-path { stroke: #b00; }
#arrowhead-vee-select { fill: #b00 }
.node-item-function path { fill: #404040; }
.node-item-function text { fill: #dfdfdfdf; }
.node-item-function:hover { cursor: pointer; }
.node-item-function:hover path { fill: #666666; }
.node-item-type path { fill: #303030; }
.node-item-type text { fill: #dfdfdf; }
.node-item-type:hover { cursor: pointer; }
.node-item-type:hover path { fill: #808080; }
.node-item-type:hover text { fill: #dfdfdf; }
.node-item path { stroke: #fff; }
.node-item text { fill: #dfdfdf; }
.node-attribute text { fill: #b2b2b2; }
.node-attribute path { fill: #2d2d2d; }
.node-attribute:hover path { fill: #666666; }
.graph-item-input path { fill: #404040; }
.graph-item-input:hover { cursor: pointer; }
.graph-item-input:hover path { fill: #666666; }
.graph-item-output path { fill: #404040; }
.graph-item-output:hover { cursor: pointer; }
.graph-item-output:hover path { fill: #666666; }
.node-item-input path { fill: #404040; }
.node-item-input:hover path { fill: #666666; }
.node-item-constant path { fill: #4b4b4b; }
.node-item-constant:hover path { fill: #666666; }
.node-item-type-layer path { fill: rgba(51, 85, 136, 0.7); }
.node-item-type-activation path { fill: rgba(75, 27, 22, 0.7); }
.node-item-type-activation path { fill: rgba(75, 27, 22, 0.7); }
.node-item-type-pool path { fill: rgba(51, 85, 51, 0.7); }
.node-item-type-pool path { fill: rgba(51, 85, 51, 0.7); }
.node-item-type-normalization path { fill: rgba(51, 85, 68, 0.7); }
.node-item-type-dropout path { fill: rgba(69, 71, 112, 0.7); }
.node-item-type-shape path { fill: rgba(108, 79, 71, 0.7); }
.node-item-type-tensor path { fill: rgba(89, 66, 59, 0.7); }
.node-item-type-transform path { fill: rgba(51, 85, 68, 0.7); }
.node-item-type-data path { fill: rgba(85, 85, 85, 0.7); }
.node-item-type-quantization path { fill: rgb(80, 40, 0, 0.7); }
.node-item-type-custom path { fill: rgb(64, 64, 64, 0.7); }
}

@ -0,0 +1,786 @@
var grapher = grapher || {};
var dagre = dagre || require('./dagre');
grapher.Graph = class {
constructor(compound, options) {
this._isCompound = compound;
this._options = options;
this._nodes = new Map();
this._edges = new Map();
this._children = {};
this._children['\x00'] = {};
this._parent = {};
// My code
this._modelNodeName2ViewNode = new Map();
this._modelNodeName2State = new Map();
}
get options() {
return this._options;
}
setNode(node) {
const key = node.name;
const value = this._nodes.get(key);
if (value) {
value.label = node;
}
else {
this._nodes.set(key, { v: key, label: node });
if (this._isCompound) {
this._parent[key] = '\x00';
this._children[key] = {};
this._children['\x00'][key] = true;
}
}
// My code
const modelNodeName = node.value.name;
// console.log(modelNodeName);
const viewNode = this._modelNodeName2ViewNode.get(modelNodeName);
if (viewNode) {
this._modelNodeName2ViewNode[modelNodeName] = node;
}
else {
this._modelNodeName2ViewNode.set(modelNodeName, node);
}
this._modelNodeName2State.set(modelNodeName, 'Exist');
}
setEdge(edge) {
if (!this._nodes.has(edge.v)) {
throw new grapher.Error();
}
if (!this._nodes.has(edge.w)) {
throw new grapher.Error();
}
const key = edge.v + ':' + edge.w;
if (!this._edges.has(key)) {
this._edges.set(key, { v: edge.v, w: edge.w, label: edge });
}
}
setParent(node, parent) {
if (!this._isCompound) {
throw new Error("Cannot set parent in a non-compound graph");
}
parent += "";
for (let ancestor = parent; ancestor; ancestor = this.parent(ancestor)) {
if (ancestor === node) {
throw new Error("Setting " + parent + " as parent of " + node + " would create a cycle");
}
}
delete this._children[this._parent[node]][node];
this._parent[node] = parent;
this._children[parent][node] = true;
return this;
}
get nodes() {
return this._nodes;
}
hasNode(key) {
return this._nodes.has(key);
}
node(key) {
return this._nodes.get(key);
}
get edges() {
return this._edges;
}
parent(key) {
if (this._isCompound) {
const parent = this._parent[key];
if (parent !== '\x00') {
return parent;
}
}
}
children(key) {
key = key === undefined ? '\x00' : key;
if (this._isCompound) {
const children = this._children[key];
if (children) {
return Object.keys(children);
}
}
else if (key === '\x00') {
return this.nodes.keys();
}
else if (this.hasNode(key)) {
return [];
}
}
build(document, origin) {
const createGroup = (name) => {
const element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
element.setAttribute('id', name);
element.setAttribute('class', name);
origin.appendChild(element);
return element;
};
const clusterGroup = createGroup('clusters');
const edgePathGroup = createGroup('edge-paths');
const edgeLabelGroup = createGroup('edge-labels');
const nodeGroup = createGroup('nodes');
// ====> 显示 边上的箭头
const edgePathGroupDefs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
edgePathGroup.appendChild(edgePathGroupDefs);
const marker = (id) => {
const element = document.createElementNS('http://www.w3.org/2000/svg', 'marker');
element.setAttribute('id', id);
element.setAttribute('viewBox', '0 0 10 10');
element.setAttribute('refX', 9);
element.setAttribute('refY', 5);
element.setAttribute('markerUnits', 'strokeWidth');
element.setAttribute('markerWidth', 8);
element.setAttribute('markerHeight', 6);
element.setAttribute('orient', 'auto');
const markerPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
markerPath.setAttribute('d', 'M 0 0 L 10 5 L 0 10 L 4 5 z');
markerPath.style.setProperty('stroke-width', 1);
element.appendChild(markerPath);
return element;
};
edgePathGroupDefs.appendChild(marker("arrowhead-vee"));
edgePathGroupDefs.appendChild(marker("arrowhead-vee-select"));
// <==== 显示 边上的箭头
// console.log(this.nodes)
for (const nodeId of this.nodes.keys()) {
const node = this.node(nodeId);
if (this.children(nodeId).length == 0) {
// node
// type(node.label) == view.Node
node.label.build(document, nodeGroup); // 如果注释TypeError Cannot read properties of undefined (reading 'setAttribute')
}
else {
// cluster
node.label.rectangle = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
if (node.label.rx) {
node.label.rectangle.setAttribute('rx', node.rx);
}
if (node.label.ry) {
node.label.rectangle.setAttribute('ry', node.ry);
}
node.label.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
node.label.element.setAttribute('class', 'cluster');
node.label.element.appendChild(node.label.rectangle);
clusterGroup.appendChild(node.label.element);
}
}
for (const edge of this.edges.values()) {
edge.label.build(document, edgePathGroup, edgeLabelGroup);
}
}
update() {
dagre.layout(this);
for (const nodeId of this.nodes.keys()) {
const node = this.node(nodeId);
if (this.children(nodeId).length == 0) {
// node
node.label.update(); // 让节点显示出来
}
// ===> 这段没有操作
else {
// cluster
const node = this.node(nodeId);
node.label.element.setAttribute('transform', 'translate(' + node.label.x + ',' + node.label.y + ')');
node.label.rectangle.setAttribute('x', - node.label.width / 2);
node.label.rectangle.setAttribute('y', - node.label.height / 2 );
node.label.rectangle.setAttribute('width', node.label.width);
node.label.rectangle.setAttribute('height', node.label.height);
}
// <=== 这段没有操作
}
// console.log(this.edges)
for (const edge of this.edges.values()) {
// console.log(edge.label)
edge.label.update(); // 让边显示出来
}
}
};
grapher.Node = class {
constructor() {
this._blocks = [];
}
header() {
const block = new grapher.Node.Header();
this._blocks.push(block);
return block;
}
list() {
const block = new grapher.Node.List();
this._blocks.push(block);
return block;
}
canvas() {
const block = new grapher.Node.Canvas();
this._blocks.push(block);
return block;
}
build(document, parent) {
this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
if (this.id) {
this.element.setAttribute('id', this.id);
}
this.element.setAttribute('class', this.class ? 'node ' + this.class : 'node');
this.element.style.opacity = 0;
parent.appendChild(this.element);
// ===> 配置每个节点的框边界
this.border = document.createElementNS('http://www.w3.org/2000/svg', 'path');
this.border.setAttribute('class', [ 'node', 'border' ].join(' '));
this.element.appendChild(this.border);
// <=== 配置每个节点的框边界
for (let i = 0; i < this._blocks.length; i++) {
const block = this._blocks[i];
block.first = i === 0;
block.last = i === this._blocks.length - 1;
block.build(document, this.element);
}
this.layout(); // 这一行注释后,边和节点全部乱成一团,报错一堆
}
layout() {
const width = Math.max(...this._blocks.map((block) => block.width));
let height = 0;
for (let i = 0; i < this._blocks.length; i++) {
const block = this._blocks[i];
block.y = height;
block.update(this.element, height, width, i == 0, i == this._blocks.length - 1);
height = height + block.height;
}
// 这一行画每个节点的框边界
this.border.setAttribute('d', grapher.Node.roundedRect(0, 0, width, height, true, true, true, true));
const nodeBox = this.element.getBBox();
this.width = nodeBox.width;
this.height = nodeBox.height;
}
update() {
// console.log(this)
// 没有这一行,所有节点都左对齐到左上角
// 这一行对所有节点框进行平移
this.element.setAttribute('transform', 'translate(' + (this.x - (this.width / 2)) + ',' + (this.y - (this.height / 2)) + ')');
// 设定不透明度
this.element.style.opacity = 1;
}
static roundedRect(x, y, width, height, r1, r2, r3, r4) {
const radius = 5;
r1 = r1 ? radius : 0;
r2 = r2 ? radius : 0;
r3 = r3 ? radius : 0;
r4 = r4 ? radius : 0;
return "M" + (x + r1) + "," + y +
"h" + (width - r1 - r2) +
"a" + r2 + "," + r2 + " 0 0 1 " + r2 + "," + r2 +
"v" + (height - r2 - r3) +
"a" + r3 + "," + r3 + " 0 0 1 " + -r3 + "," + r3 +
"h" + (r3 + r4 - width) +
"a" + r4 + "," + r4 + " 0 0 1 " + -r4 + "," + -r4 +
'v' + (-height + r4 + r1) +
"a" + r1 + "," + r1 + " 0 0 1 " + r1 + "," + -r1 +
"z";
}
};
grapher.Node.Header = class {
constructor() {
this._entries = [];
}
add(id, classList, content, tooltip, handler) {
const entry = new grapher.Node.Header.Entry(id, classList, content, tooltip, handler);
this._entries.push(entry);
return entry;
}
build(document, parent) {
this._document = document;
this.width = 0;
this.height = 0;
let x = 0;
const y = 0;
for (const entry of this._entries) {
entry.x = x;
entry.y = y;
entry.build(document, parent);
x += entry.width;
this.height = Math.max(entry.height, this.height);
this.width = Math.max(x, this.width);
}
if (!this.first) {
this.line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
parent.appendChild(this.line);
}
}
update(parent, top, width) {
const document = this._document;
const dx = width - this.width;
for (let i = 0; i < this._entries.length; i++) {
const entry = this._entries[i];
if (i == 0) {
entry.width = entry.width + dx;
}
else {
entry.x = entry.x + dx;
entry.tx = entry.tx + dx;
}
entry.y = entry.y + top;
}
for (let i = 0; i < this._entries.length; i++) {
const entry = this._entries[i];
entry.element.setAttribute('transform', 'translate(' + entry.x + ',' + entry.y + ')');
const r1 = i == 0 && this.first;
const r2 = i == this._entries.length - 1 && this.first;
const r3 = i == this._entries.length - 1 && this.last;
const r4 = i == 0 && this.last;
entry.path.setAttribute('d', grapher.Node.roundedRect(0, 0, entry.width, entry.height, r1, r2, r3, r4));
entry.text.setAttribute('x', 6);
entry.text.setAttribute('y', entry.ty);
}
for (let i = 0; i < this._entries.length; i++) {
const entry = this._entries[i];
if (i != 0) {
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('class', 'node');
line.setAttribute('x1', entry.x);
line.setAttribute('x2', entry.x);
line.setAttribute('y1', top);
line.setAttribute('y2', top + this.height);
parent.appendChild(line);
}
}
if (this.line) {
this.line.setAttribute('class', 'node');
this.line.setAttribute('x1', 0);
this.line.setAttribute('x2', width);
this.line.setAttribute('y1', top);
this.line.setAttribute('y2', top);
}
}
};
grapher.Node.Header.Entry = class {
constructor(id, classList, content, tooltip, handler) {
this.id = id;
this.classList = classList;
this.content = content;
this.tooltip = tooltip;
this.handler = handler;
this.events = {};
}
on(event, callback) {
this.events[event] = this.events[event] || [];
this.events[event].push(callback);
}
raise(event, data) {
if (this.events && this.events[event]) {
for (const callback of this.events[event]) {
callback(this, data);
}
}
}
build(document, parent) {
const yPadding = 4;
const xPadding = 7;
this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
parent.appendChild(this.element);
this.path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
this.text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
this.element.appendChild(this.path);
this.element.appendChild(this.text);
const classList = [ 'node-item' ];
if (this.classList) {
classList.push(...this.classList);
}
this.element.setAttribute('class', classList.join(' '));
if (this.id) {
this.element.setAttribute('id', this.id);
}
if (this.events.click) {
this.element.addEventListener('click', () => this.raise('click'));
}
if (this.tooltip) {
const titleElement = document.createElementNS('http://www.w3.org/2000/svg', 'title');
titleElement.textContent = this.tooltip;
this.element.appendChild(titleElement);
}
if (this.content) {
this.text.textContent = this.content;
}
const boundingBox = this.text.getBBox();
this.width = boundingBox.width + xPadding + xPadding;
this.height = boundingBox.height + yPadding + yPadding;
this.tx = xPadding;
this.ty = yPadding - boundingBox.y;
}
};
grapher.Node.List = class {
constructor() {
this._items = [];
this.events = {};
}
add(id, name, value, tooltip, separator) {
const item = new grapher.Node.List.Item(id, name, value, tooltip, separator);
this._items.push(item);
return item;
}
on(event, callback) {
this.events[event] = this.events[event] || [];
this.events[event].push(callback);
}
raise(event, data) {
if (this.events && this.events[event]) {
for (const callback of this.events[event]) {
callback(this, data);
}
}
}
build(document, parent) {
this._document = document;
this.width = 0;
this.height = 0;
const x = 0;
const y = 0;
this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
this.element.setAttribute('class', 'node-attribute');
if (this.events.click) {
this.element.addEventListener('click', () => this.raise('click'));
}
this.element.setAttribute('transform', 'translate(' + x + ',' + y + ')');
this.background = document.createElementNS('http://www.w3.org/2000/svg', 'path');
this.element.appendChild(this.background);
parent.appendChild(this.element);
this.height += 3;
for (const item of this._items) {
const yPadding = 1;
const xPadding = 6;
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
if (item.id) {
text.setAttribute('id', item.id);
}
text.setAttribute('xml:space', 'preserve');
this.element.appendChild(text);
if (item.tooltip) {
const title = document.createElementNS('http://www.w3.org/2000/svg', 'title');
title.textContent = item.tooltip;
text.appendChild(title);
}
const name = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
name.textContent = item.name;
if (item.separator.trim() != '=') {
name.style.fontWeight = 'bold';
}
text.appendChild(name);
const textValueElement = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
textValueElement.textContent = item.separator + item.value;
text.appendChild(textValueElement);
const size = text.getBBox();
const width = xPadding + size.width + xPadding;
this.width = Math.max(width, this.width);
text.setAttribute('x', x + xPadding);
text.setAttribute('y', this.height + yPadding - size.y);
this.height += yPadding + size.height + yPadding;
}
this.height += 3;
this.width = Math.max(75, this.width);
if (!this.first) {
this.line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
this.line.setAttribute('class', 'node');
this.element.appendChild(this.line);
}
}
update(parent, top, width) {
this.element.setAttribute('transform', 'translate(0,' + this.y + ')');
this.background.setAttribute('d', grapher.Node.roundedRect(0, 0, width, this.height, this.first, this.first, this.last, this.last));
if (this.line) {
this.line.setAttribute('x1', 0);
this.line.setAttribute('x2', width);
this.line.setAttribute('y1', 0);
this.line.setAttribute('y2', 0);
}
}
};
grapher.Node.List.Item = class {
constructor(id, name, value, tooltip, separator) {
this.id = id;
this.name = name;
this.value = value;
this.tooltip = tooltip;
this.separator = separator;
}
};
grapher.Node.Canvas = class {
constructor() {
this.width = 0;
this.height = 0;
}
build(/* document, parent */) {
}
update(/* parent, top, width , first, last */) {
}
};
grapher.Edge = class {
constructor(from, to) {
this.from = from;
this.to = to;
}
get arrowhead() {
return 'vee';
}
build(document, edgePathGroupElement, edgeLabelGroupElement) {
const createElement = (name) => {
return document.createElementNS('http://www.w3.org/2000/svg', name);
};
// 生成path对应的element
this.element = createElement('path');
if (this.id) {
this.element.setAttribute('id', this.id);
}
this.element.setAttribute('class', this.class ? 'edge-path ' + this.class : 'edge-path');
edgePathGroupElement.appendChild(this.element);
// 生成label对应的element
if (this.label) {
const tspan = createElement('tspan');
tspan.setAttribute('xml:space', 'preserve');
tspan.setAttribute('dy', '1em');
tspan.setAttribute('x', '1');
tspan.appendChild(document.createTextNode(this.label));
this.labelElement = createElement('text');
this.labelElement.appendChild(tspan);
this.labelElement.style.opacity = 0;
this.labelElement.setAttribute('class', 'edge-label');
if (this.id) {
this.labelElement.setAttribute('id', 'edge-label-' + this.id);
}
edgeLabelGroupElement.appendChild(this.labelElement);
const edgeBox = this.labelElement.getBBox();
this.width = edgeBox.width;
this.height = edgeBox.height;
}
}
update() {
const edgePath = grapher.Edge._computeCurvePath(this, this.from, this.to);
this.element.setAttribute('d', edgePath); // ===> 把边画出来
// ===> 让label显示出来
if (this.labelElement) {
this.labelElement.setAttribute('transform', 'translate(' + (this.x - (this.width / 2)) + ',' + (this.y - (this.height / 2)) + ')');
this.labelElement.style.opacity = 1;
}
// <=== 让label显示出来
}
static _computeCurvePath(edge, tail, head) {
const points = edge.points.slice(1, edge.points.length - 1);
points.unshift(grapher.Edge._intersectRect(tail, points[0]));
points.push(grapher.Edge._intersectRect(head, points[points.length - 1]));
const curve = new grapher.Edge.Curve(points);
return curve.path.data;
}
static _intersectRect(node, point) {
const x = node.x;
const y = node.y;
const dx = point.x - x;
const dy = point.y - y;
let w = node.width / 2;
let h = node.height / 2;
let sx;
let sy;
if (Math.abs(dy) * w > Math.abs(dx) * h) {
if (dy < 0) {
h = -h;
}
sx = dy === 0 ? 0 : h * dx / dy;
sy = h;
}
else {
if (dx < 0) {
w = -w;
}
sx = w;
sy = dx === 0 ? 0 : w * dy / dx;
}
return {
x: x + sx,
y: y + sy
};
}
};
grapher.Edge.Curve = class {
constructor(points) {
this._path = new grapher.Edge.Path();
this._x0 = NaN;
this._x1 = NaN;
this._y0 = NaN;
this._y1 = NaN;
this._state = 0;
for (let i = 0; i < points.length; i++) {
const point = points[i];
this.point(point.x, point.y);
if (i === points.length - 1) {
switch (this._state) {
case 3:
this.curve(this._x1, this._y1);
this._path.lineTo(this._x1, this._y1);
break;
case 2:
this._path.lineTo(this._x1, this._y1);
break;
}
if (this._line || (this._line !== 0 && this._point === 1)) {
this._path.closePath();
}
this._line = 1 - this._line;
}
}
}
get path() {
return this._path;
}
point(x, y) {
x = +x;
y = +y;
switch (this._state) {
case 0:
this._state = 1;
if (this._line) {
this._path.lineTo(x, y);
}
else {
this._path.moveTo(x, y);
}
break;
case 1:
this._state = 2;
break;
case 2:
this._state = 3;
this._path.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6);
this.curve(x, y);
break;
default:
this.curve(x, y);
break;
}
this._x0 = this._x1;
this._x1 = x;
this._y0 = this._y1;
this._y1 = y;
}
curve(x, y) {
this._path.bezierCurveTo(
(2 * this._x0 + this._x1) / 3,
(2 * this._y0 + this._y1) / 3,
(this._x0 + 2 * this._x1) / 3,
(this._y0 + 2 * this._y1) / 3,
(this._x0 + 4 * this._x1 + x) / 6,
(this._y0 + 4 * this._y1 + y) / 6
);
}
};
grapher.Edge.Path = class {
constructor() {
this._x0 = null;
this._y0 = null;
this._x1 = null;
this._y1 = null;
this._data = '';
}
moveTo(x, y) {
this._data += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
}
lineTo(x, y) {
this._data += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
}
bezierCurveTo(x1, y1, x2, y2, x, y) {
this._data += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
}
closePath() {
if (this._x1 !== null) {
this._x1 = this._x0;
this._y1 = this._y0;
this._data += "Z";
}
}
get data() {
return this._data;
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.Graph = grapher.Graph;
module.exports.Node = grapher.Node;
module.exports.Edge = grapher.Edge;
}

@ -0,0 +1,89 @@
.sidebar { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif; font-size: 12px; height: 100%; width: 0; position: fixed; transition: 0.2s; z-index: 1; top: 0; right: 0; background-color: #ececec; color: #242424; overflow: hidden; border-left: 1px solid #ccc; }
.sidebar-title { font-weight: bold; font-size: 12px; letter-spacing: 0.5px; height: 20px; margin: 0; padding: 20px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.sidebar-closebutton { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #777777; opacity: 1.0; display: block; transition: 0.2s; position: absolute; top: 0; right: 15px; margin-left: 50px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.sidebar-closebutton:hover { color: #242424; }
.sidebar-content { padding-left: 20px; padding-right: 20px; margin-bottom: 20px; overflow-y: auto; height: calc(100vh - 60px); }
.sidebar-view-title { font-weight: bold; font-size: 11px; line-height: 1.25; border-bottom: 1px solid #ececec; padding-bottom: 0.3em; margin-top: 0; margin-bottom: 16px; color: #333; user-select: none; -webkit-user-select: none; -moz-user-select: none; cursor: default; }
.sidebar-view-title-button { display: inline-block; color: #888; text-align: center; vertical-align: middle; font-weight: bold; width: 12px; height: 12px; font-size: 10px; line-height: 12px; border-radius: 50%; transform: translateY(-1px); padding: 1px; background: transparent; border: 1px solid #aaa; text-decoration: none; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.sidebar-view-title-button:hover { color: #333; border: 1px solid #333; }
.sidebar-view-header { font-weight: bold; font-size: 11px; text-transform: uppercase; line-height: 1.25; margin-top: 16px; margin-bottom: 16px; border-bottom: 1px solid #ececec; display: block; user-select: none; -webkit-user-select: none; -moz-user-select: none; cursor: default; }
.sidebar-view-item { margin-bottom: 0px; display: block; }
.sidebar-view-item-name { float: left; font-size: 11px; min-width: 95px; max-width: 95px; padding-right: 5px; padding-top: 7px; display: block; }
.sidebar-view-item-name input { color: #777; font-family: inherit; font-size: inherit; color: inherit; background-color: inherit; width: 100%; text-align: right; margin: 0; padding: 0; border: 0; outline: none; text-overflow: ellipsis; }
.sidebar-view-item-value-list { margin: 0; margin-left: 105px; overflow: hidden; display: block; padding: 0; }
.sidebar-view-item-value { font-size: 11px; background-color: #fcfcfc; border-radius: 2px; border: 1px solid #fcfcfc; margin-top: 3px; margin-bottom: 3px; overflow: auto; }
.sidebar-view-item-value-dark { background-color: #f8f8f8; border: 1px solid #f8f8f8; }
.sidebar-view-item-value b { font-weight: bold; }
.sidebar-view-item-value code { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
.sidebar-view-item-value pre { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; margin: 0; overflow: auto; white-space: pre; word-wrap: normal; display: block; }
.sidebar-view-item-value-line { padding: 4px 6px 4px 6px; }
.sidebar-view-item-value-line-link { padding: 4px 6px 4px 6px; cursor: default; }
.sidebar-view-item-value-line-link:hover { text-decoration: underline; }
.sidebar-view-item-value-line-border { padding: 4px 6px 4px 6px; border-top: 1px solid rgba(27, 31, 35, 0.05); }
.sidebar-view-item-value-line-content { white-space: pre; word-wrap: normal; overflow: auto; display: block; }
.sidebar-view-item-value-expander { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; float: right; color: #aaa; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; padding: 4px 6px 4px 6px; }
.sidebar-view-item-value-expander:hover { color: #000; }
.sidebar-view-item-select {
font-family: inherit; font-size: 12px;
background-color: #fcfcfc; border: #fcfcfc; color: #333;
border-radius: 2px; width: 100%; height: 23px; padding: 3px 12px 3px 7px;
margin-top: 3px; margin-bottom: 3px; box-sizing: border-box; outline: none;
-moz-box-sizing: border-box; -webkit-appearance: none; -moz-appearance: none;
background-image: linear-gradient(45deg, transparent 50%, #333 50%), linear-gradient(135deg, #333 50%, transparent 50%);
background-position: calc(100% - 12px) calc(10px), calc(100% - 7px) calc(10px);
background-size: 5px 5px, 5px 5px;
background-repeat: no-repeat;
}
.sidebar-view-separator { margin-bottom: 20px; }
.sidebar-view-find input[type=text] { font-family: inherit; font-size: 13px; padding: 4px 6px 4px 6px; background: #fff; border-radius: 4px; border: 1px solid #ccc; outline: 0; }
.sidebar-view-find ol { list-style-type: none; overflow-y: auto; margin: 8px 0 20px 0; padding: 0; }
.sidebar-view-find li { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; margin: 0; padding: 5px 8px 5px 8px; outline: 0; white-space: nowrap; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.sidebar-view-find li:not(:first-child) { border-top: 1px solid #f0f0f0; }
.sidebar-view-find li:hover { background: #eee; }
.sidebar-view-documentation { font-size: 13px; line-height: 1.5; margin: 0; }
.sidebar-view-documentation h1 { font-weight: bold; font-size: 13px; line-height: 1.25; border-bottom: 1px solid #e8e8e8; padding-bottom: 0.3em; margin-top: 0; margin-bottom: 16px; }
.sidebar-view-documentation h2 { font-weight: bold; font-size: 11px; line-height: 1.25; margin-top: 20px; margin-bottom: 16px; text-transform: uppercase; border: 0; }
.sidebar-view-documentation h3 { font-weight: bold; font-size: 11px; line-height: 1.25; }
.sidebar-view-documentation p { margin-top: 4px; margin-bottom: 4px; margin-left: 0px; }
.sidebar-view-documentation a { color: #237; }
.sidebar-view-documentation code { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; background-color: rgba(27, 31, 35, 0.05); padding: 0.2em 0.4em; margin: 0; border-radius: 3px; }
.sidebar-view-documentation pre { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; }
.sidebar-view-documentation pre code { font-size: 13px; padding: 16px; line-height: 1.45; background-color: transparent; padding: 0; border-radius: 0; }
.sidebar-view-documentation tt { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-weight: bold; font-size: 90%; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; padding: 0.2em 0.4em; margin: 0; }
.sidebar-view-documentation dl dt { font-size: 13px; font-weight: bold; padding: 0; margin-top: 16px; margin-left: 0px; }
.sidebar-view-documentation dd { padding: 0 16px; margin-left: 0; margin-bottom: 16px; }
.sidebar-view-documentation ul { margin-top: 6px; margin-bottom: 6px; padding-left: 20px; }
.sidebar-view-documentation blockquote { margin-left: 15px; margin-right: 15px; }
@media (prefers-color-scheme: dark) {
.sidebar html { color: #dfdfdf; }
.sidebar { background-color: #2d2d2d; color: #dfdfdf; border-left: 1px solid #000; }
.sidebar-closebutton { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #777777; opacity: 1.0; display: block; transition: 0.2s; position: absolute; top: 0; right: 15px; margin-left: 50px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
.sidebar-closebutton:hover { color: #ffffff; }
.sidebar-view-item-value { background-color: #383838; border-color: #383838; }
.sidebar-view-item-value-dark { background-color: #3e3e3e; border-color: #3e3e3e; }
.sidebar-view-item-value-line-border { border-color: rgba(0, 0, 0, 0.09); }
.sidebar-view-item-select { background-color: #383838; border: #383838; color: #dfdfdf; background-image: linear-gradient(45deg, transparent 50%, #aaa 50%), linear-gradient(135deg, #aaa 50%, transparent 50%); }
.sidebar-view-title { border-bottom-color: #2d2d2d; color: #dfdfdf; }
.sidebar-view-title-button { color: #888888; border-color: #888888; }
.sidebar-view-title-button:hover { color: #dfdfdf; border-color: #dfdfdf; }
.sidebar-view-header { border-bottom-color: #2d2d2d; color: #dfdfdf; }
.sidebar-view-documentation h1 { border-bottom: 1px solid #424242; color: #dfdfdf; }
.sidebar-view-documentation h2 { color: #dfdfdf; }
.sidebar-view-documentation p { color: #aaaaaa; }
.sidebar-view-documentation a { color: #6688aa; }
.sidebar-view-documentation tt { background-color:#1e1e1e; }
.sidebar-view-documentation code { background-color: #1e1e1e; }
.sidebar-view-documentation pre { background-color: #1e1e1e; }
.sidebar-view-find input[type=text] { background: #383838; color: #dfdfdf; border-color: #424242; }
.sidebar-view-find li:not(:first-child) { border-top: 1px solid #2a2a2a; }
.sidebar-view-find li:hover { background: #383838; }
}

File diff suppressed because it is too large Load Diff

2142
view.js

File diff suppressed because it is too large Load Diff

@ -0,0 +1,256 @@
// Experimental
var weka = weka || {};
var json = json || require('./json');
var java = {};
weka.ModelFactory = class {
match(context) {
try {
const stream = context.stream;
if (stream.length >= 5) {
const signature = [ 0xac, 0xed ];
if (stream.peek(2).every((value, index) => value === signature[index])) {
const reader = new java.io.InputObjectStream(stream);
const obj = reader.read();
if (obj && obj.$class && obj.$class.name) {
return 'weka';
}
}
}
}
catch (err) {
// continue regardless of error
}
return undefined;
}
open(context) {
return Promise.resolve().then(() => {
const reader = new java.io.InputObjectStream(context.stream);
const obj = reader.read();
throw new weka.Error("Unsupported type '" + obj.$class.name + "'.");
});
}
};
weka.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'Error loading Weka model.';
}
};
java.io = {};
java.io.InputObjectStream = class {
constructor(stream) {
// Object Serialization Stream Protocol
// https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/guide/serialization/spec/protocol.doc.html
if (stream.length < 5) {
throw new java.io.Error('Invalid stream size');
}
const signature = [ 0xac, 0xed ];
if (!stream.peek(2).every((value, index) => value === signature[index])) {
throw new java.io.Error('Invalid stream signature');
}
this._reader = new java.io.InputObjectStream.BinaryReader(stream.peek());
this._references = [];
this._reader.skip(2);
const version = this._reader.uint16();
if (version !== 0x0005) {
throw new java.io.Error("Unsupported version '" + version + "'.");
}
}
read() {
return this._object();
}
_object() {
const code = this._reader.byte();
switch (code) {
case 0x73: { // TC_OBJECT
const obj = {};
obj.$class = this._classDesc();
this._newHandle(obj);
this._classData(obj);
return obj;
}
case 0x74: { // TC_STRING
return this._newString(false);
}
}
throw new java.io.Error("Unsupported code '" + code + "'.");
}
_classDesc() {
const code = this._reader.byte();
switch (code) {
case 0x72: // TC_CLASSDESC
this._reader.skip(-1);
return this._newClassDesc();
case 0x71: // TC_REFERENCE
return this._references[this._reader.uint32() - 0x7e0000];
case 0x70: // TC_NULL
this._reader.byte();
return null;
}
throw new java.io.Error("Unsupported code '" + code + "'.");
}
_newClassDesc() {
const code = this._reader.byte();
switch (code) {
case 0x72: { // TC_CLASSDESC
const classDesc = {};
classDesc.name = this._reader.string(),
classDesc.id = this._reader.uint64().toString();
this._newHandle(classDesc);
classDesc.flags = this._reader.byte();
classDesc.fields = [];
const count = this._reader.uint16();
for (let i = 0; i < count; i++) {
const field = {};
field.type = String.fromCharCode(this._reader.byte());
field.name = this._reader.string();
if (field.type === '[' || field.type === 'L') {
field.classname = this._object();
}
classDesc.fields.push(field);
}
if (this._reader.byte() !== 0x78) {
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
}
classDesc.superClass = this._classDesc();
return classDesc;
}
case 0x7D: // TC_PROXYCLASSDESC
break;
}
throw new java.io.Error("Unsupported code '" + code + "'.");
}
_classData(/* obj */) {
/*
const classname = obj.$class.name;
let flags = obj.$class.flags;
let superClass = obj.$class.superClass;
while (superClass) {
flags |= superClass.flags;
superClass = superClass.superClass;
}
if (flags & 0x02) { // SC_SERIALIZABLE
debugger;
var customObject = objects[classname];
var hasReadObjectMethod = customObject && customObject.readObject;
if (flags & 0x01) { // SC_WRITE_METHOD
if (!hasReadObjectMethod) {
throw new Error('Class "'+ classname + '" dose not implement readObject()');
}
customObject.readObject(this, obj);
if (this._reader.byte() !== 0x78) { // TC_ENDBLOCKDATA
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
}
}
else {
if (hasReadObjectMethod) {
customObject.readObject(this, obj);
if (this._reader.byte() !== 0x78) { // TC_ENDBLOCKDATA
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
}
}
else {
this._nowrclass(obj);
}
}
}
else if (flags & 0x04) { // SC_EXTERNALIZABLE
if (flags & 0x08) { // SC_BLOCK_DATA
this._objectAnnotation(obj);
}
else {
this._externalContents();
}
}
else {
throw new Error('Illegal flags: ' + flags);
}
*/
}
_newString(long) {
const value = this._reader.string(long);
this._newHandle(value);
return value;
}
_newHandle(obj) {
this._references.push(obj);
}
};
java.io.InputObjectStream.BinaryReader = class {
constructor(buffer) {
this._buffer = buffer;
this._position = 0;
this._length = buffer.length;
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
this._decoder = new TextDecoder('utf-8');
}
skip(offset) {
this._position += offset;
if (this._position > this._end) {
throw new java.io.Error('Expected ' + (this._position - this._end) + ' more bytes. The file might be corrupted. Unexpected end of file.');
}
}
byte() {
const position = this._position;
this.skip(1);
return this._buffer[position];
}
uint16() {
const position = this._position;
this.skip(2);
return this._view.getUint16(position, false);
}
uint32() {
const position = this._position;
this.skip(4);
return this._view.getUint32(position, false);
}
uint64() {
const position = this._position;
this.skip(8);
return this._view.getUint64(position, false);
}
string(long) {
const size = long ? this.uint64().toNumber() : this.uint16();
const position = this._position;
this.skip(size);
return this._decoder.decode(this._buffer.subarray(position, this._position));
}
};
java.io.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'Error loading Object Serialization Stream Protocol.';
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.ModelFactory = weka.ModelFactory;
}

1790
xml.js

File diff suppressed because it is too large Load Diff

713
zip.js

@ -0,0 +1,713 @@
var zip = zip || {};
var zlib = zlib || {};
zip.Archive = class {
static open(data) {
const stream = data instanceof Uint8Array ? new zip.BinaryReader(data) : data;
if (stream.length > 2) {
const buffer = stream.peek(2);
if (buffer[0] === 0x78) { // zlib
const check = (buffer[0] << 8) + buffer[1];
if (check % 31 === 0) {
return new zlib.Archive(stream);
}
}
const signature = buffer[0] === 0x50 && buffer[1] === 0x4B;
const position = stream.position;
const seek = (content) => {
let position = stream.length;
do {
position = Math.max(0, position - 66000);
stream.seek(position);
const length = Math.min(stream.length - position, 66000 + 4);
const buffer = stream.read(length);
for (let i = buffer.length - 4; i >= 0; i--) {
if (content[0] === buffer[i] && content[1] === buffer[i + 1] && content[2] === buffer[i + 2] && content[3] === buffer[i + 3]) {
stream.seek(position + i + 4);
return true;
}
}
if (!signature) {
break;
}
}
while (position > 0);
return false;
};
if (!seek([ 0x50, 0x4B, 0x05, 0x06 ])) {
stream.seek(position);
if (!signature) {
return null;
}
throw new zip.Error('End of Zip central directory not found.');
}
const reader = new zip.BinaryReader(stream.read(16));
reader.skip(12);
let offset = reader.uint32(); // central directory offset
if (offset > stream.length) {
if (!seek([ 0x50, 0x4B, 0x06, 0x06 ])) {
stream.seek(position);
throw new zip.Error('End of Zip64 central directory not found.');
}
const reader = new zip.BinaryReader(stream.read(52));
reader.skip(44);
offset = reader.uint32();
if (reader.uint32() !== 0) {
stream.seek(position);
throw new zip.Error('Zip 64-bit central directory offset not supported.');
}
}
if (offset > stream.length) {
stream.seek(position);
throw new zip.Error('Invalid Zip central directory offset.');
}
stream.seek(offset);
const archive = new zip.Archive(stream);
stream.seek(position);
return archive;
}
return null;
}
constructor(stream) {
this._entries = new Map();
const headers = [];
const signature = [ 0x50, 0x4B, 0x01, 0x02 ];
while (stream.position + 4 < stream.length && stream.read(4).every((value, index) => value === signature[index])) {
const header = {};
const reader = new zip.BinaryReader(stream.read(42));
reader.uint16(); // version made by
reader.skip(2); // version needed to extract
const flags = reader.uint16();
if ((flags & 1) == 1) {
throw new zip.Error('Encrypted Zip entries not supported.');
}
header.encoding = flags & 0x800 ? 'utf-8' : 'ascii';
header.compressionMethod = reader.uint16();
reader.uint32(); // date
reader.uint32(); // crc32
header.compressedSize = reader.uint32();
header.size = reader.uint32();
header.nameLength = reader.uint16(); // file name length
const extraDataLength = reader.uint16();
const commentLength = reader.uint16();
header.disk = reader.uint16(); // disk number start
reader.uint16(); // internal file attributes
reader.uint32(); // external file attributes
header.localHeaderOffset = reader.uint32();
const nameBuffer = stream.read(header.nameLength);
const decoder = new TextDecoder(header.encoding);
header.name = decoder.decode(nameBuffer);
const extraData = stream.read(extraDataLength);
if (extraData.length > 0) {
const reader = new zip.BinaryReader(extraData);
while (reader.position < reader.length) {
const type = reader.uint16();
const length = reader.uint16();
switch (type) {
case 0x0001:
if (header.size === 0xffffffff) {
header.size = reader.uint32();
if (reader.uint32() !== 0) {
throw new zip.Error('Zip 64-bit offset not supported.');
}
}
if (header.compressedSize === 0xffffffff) {
header.compressedSize = reader.uint32();
if (reader.uint32() !== 0) {
throw new zip.Error('Zip 64-bit offset not supported.');
}
}
if (header.localHeaderOffset === 0xffffffff) {
header.localHeaderOffset = reader.uint32();
if (reader.uint32() !== 0) {
throw new zip.Error('Zip 64-bit offset not supported.');
}
}
if (header.disk === 0xffff) {
header.disk = reader.uint32();
}
break;
default:
reader.skip(length);
break;
}
}
}
stream.read(commentLength); // comment
headers.push(header);
}
for (const header of headers) {
if (header.size === 0 && header.name.endsWith('/')) {
continue;
}
const entry = new zip.Entry(stream, header);
this._entries.set(entry.name, entry.stream);
}
}
get entries() {
return this._entries;
}
};
zip.Entry = class {
constructor(stream, header) {
stream.seek(header.localHeaderOffset);
const signature = [ 0x50, 0x4B, 0x03, 0x04 ];
if (stream.position + 4 > stream.length || !stream.read(4).every((value, index) => value === signature[index])) {
throw new zip.Error('Invalid Zip local file header signature.');
}
const reader = new zip.BinaryReader(stream.read(26));
reader.skip(22);
header.nameLength = reader.uint16();
const extraDataLength = reader.uint16();
header.nameBuffer = stream.read(header.nameLength);
stream.skip(extraDataLength);
const decoder = new TextDecoder(header.encoding);
this._name = decoder.decode(header.nameBuffer);
this._stream = stream.stream(header.compressedSize);
switch (header.compressionMethod) {
case 0: { // stored
if (header.size !== header.compressedSize) {
throw new zip.Error('Invalid compression size.');
}
break;
}
case 8: { // deflate
this._stream = new zip.InflaterStream(this._stream, header.size);
break;
}
default:
throw new zip.Error('Invalid compression method.');
}
}
get name() {
return this._name;
}
get stream() {
return this._stream;
}
};
zip.Inflater = class {
inflateRaw(data, length) {
let buffer = null;
if (typeof process === 'object' && typeof process.versions == 'object' && typeof process.versions.node !== 'undefined') {
buffer = require('zlib').inflateRawSync(data);
}
else {
const reader = new zip.BitReader(data);
const writer = length === undefined ? new zip.BlockWriter() : new zip.BufferWriter(length);
if (!zip.Inflater._staticLengthTree) {
zip.Inflater._codeLengths = new Uint8Array(19);
zip.Inflater._codeOrder = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
zip.Inflater._lengthBase = [ 24, 32, 40, 48, 56, 64, 72, 80, 89, 105, 121, 137, 154, 186, 218, 250, 283, 347, 411, 475, 540, 668, 796, 924, 1053, 1309, 1565, 1821, 2064, 7992, 7992, 7992 ];
zip.Inflater._distanceBase = [ 16, 32, 48, 64, 81, 113, 146, 210, 275, 403, 532, 788, 1045, 1557, 2070, 3094, 4119, 6167, 8216, 12312, 16409, 24601, 32794, 49178, 65563, 98331, 131100, 196636, 262173, 393245, 1048560, 1048560 ];
}
let type;
do {
type = reader.bits(3);
switch (type >>> 1) {
case 0: { // uncompressed block
this._copyUncompressedBlock(reader, writer);
break;
}
case 1: { // block with fixed huffman trees
if (!zip.Inflater._staticLengthTree) {
zip.Inflater._staticLengthTree = zip.HuffmanTree.create(new Uint8Array([].concat.apply([], [[144, 8], [112, 9], [24, 7], [8, 8]].map((x) => [...Array(x[0])].map(() => x[1])))));
zip.Inflater._staticDistanceTree = zip.HuffmanTree.create(new Uint8Array([...Array(32)].map(() => 5)));
}
this._lengthTree = zip.Inflater._staticLengthTree;
this._distanceTree = zip.Inflater._staticDistanceTree;
this._inflateBlock(reader, writer);
break;
}
case 2: { // block with dynamic huffman trees
this._decodeTrees(reader);
this._inflateBlock(reader, writer);
break;
}
default: {
throw new zip.Error('Unknown block type.');
}
}
} while ((type & 1) == 0);
if (length !== undefined && length !== writer.length) {
throw new zip.Error('Invalid uncompressed size.');
}
buffer = writer.toBuffer();
}
if (length !== undefined && length !== buffer.length) {
throw new zip.Error('Invalid uncompressed size.');
}
return buffer;
}
_copyUncompressedBlock(reader, writer) {
const length = reader.uint16();
const inverseLength = reader.uint16();
if (length !== (~inverseLength & 0xffff)) {
throw new zip.Error('Invalid uncompressed block length.');
}
writer.write(reader.read(length));
}
_decodeTrees(reader) {
const hlit = reader.bits(5) + 257;
const hdist = reader.bits(5) + 1;
const hclen = reader.bits(4) + 4;
const codeLengths = zip.Inflater._codeLengths;
for (let i = 0; i < codeLengths.length; i++) {
codeLengths[i] = 0;
}
const codeOrder = zip.Inflater._codeOrder;
for (let i = 0; i < hclen; i++) {
codeLengths[codeOrder[i]] = reader.bits(3);
}
const codeTree = zip.HuffmanTree.create(codeLengths);
const codeMask = codeTree.length - 1;
const lengths = new Uint8Array(hlit + hdist);
let value = 0;
let length = 0;
for (let i = 0; i < hlit + hdist;) {
const code = codeTree[reader.bits16() & codeMask];
reader.position += code & 0x0f;
const literal = code >>> 4;
switch (literal) {
case 16: length = reader.bits(2) + 3; break;
case 17: length = reader.bits(3) + 3; value = 0; break;
case 18: length = reader.bits(7) + 11; value = 0; break;
default: length = 1; value = literal; break;
}
for (; length > 0; length--) {
lengths[i++] = value;
}
}
this._lengthTree = zip.HuffmanTree.create(lengths.subarray(0, hlit));
this._distanceTree = zip.HuffmanTree.create(lengths.subarray(hlit, hlit + hdist));
}
_inflateBlock(reader, writer) {
const lengthTree = this._lengthTree;
const distanceTree = this._distanceTree;
const lengthMask = lengthTree.length - 1;
const distanceMask = distanceTree.length - 1;
const buffer = writer.buffer;
const threshold = writer.threshold !== undefined ? writer.threshold : writer.length;
let position = writer.position;
for (;;) {
if (position > threshold) {
position = writer.push(position);
}
const code = lengthTree[reader.bits16() & lengthMask];
reader.position += code & 0x0f;
const literal = code >>> 4;
if (literal < 256) {
buffer[position++] = literal;
}
else if (literal === 256) {
writer.push(position);
return;
}
else {
let length = literal - 254;
if (literal > 264) {
const lengthBase = zip.Inflater._lengthBase[literal - 257];
length = (lengthBase >>> 3) + reader.bits(lengthBase & 0x07);
}
const code = distanceTree[reader.bits16() & distanceMask];
reader.position += code & 0x0f;
const distanceBase = zip.Inflater._distanceBase[code >>> 4];
const bits = distanceBase & 0x0f;
const distance = (distanceBase >>> 4) + (reader.bits16() & ((1 << bits) - 1));
reader.position += bits;
let offset = position - distance;
for (let i = 0; i < length; i++) {
buffer[position++] = buffer[offset++];
}
}
}
}
};
zip.HuffmanTree = class {
static create(tree) {
let bits = tree[0];
for (let i = 1; i < tree.length; ++i) {
if (tree[i] > bits) {
bits = tree[i];
}
}
// Algorithm from https://github.com/photopea/UZIP.js
let rev15 = zip.HuffmanTree._rev15;
if (!rev15) {
const length = 1 << 15;
rev15 = new Uint16Array(length);
for (let i = 0; i < length; i++) {
let x = i;
x = (((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1));
x = (((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2));
x = (((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4));
x = (((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8));
rev15[i] = (((x >>> 16) | (x << 16))) >>> 17;
}
zip.HuffmanTree._rev15 = rev15;
zip.HuffmanTree._bitLengthCounts = new Uint16Array(16);
zip.HuffmanTree._nextCodes = new Uint16Array(16);
}
const length = tree.length;
const bitLengthCounts = zip.HuffmanTree._bitLengthCounts;
for (let i = 0; i < 16; i++) {
bitLengthCounts[i] = 0;
}
for (let i = 0; i < length; i++) {
bitLengthCounts[tree[i]]++;
}
const nextCodes = zip.HuffmanTree._nextCodes;
let code = 0;
bitLengthCounts[0] = 0;
for (let i = 0; i < bits; i++) {
code = (code + bitLengthCounts[i]) << 1;
nextCodes[i + 1] = code;
}
const codes = new Uint16Array(length);
for (let i = 0; i < length; i++) {
const index = tree[i];
if (index !== 0) {
codes[i] = nextCodes[index];
nextCodes[index]++;
}
}
const shift = 15 - bits;
const table = new Uint16Array(1 << bits);
for (let i = 0; i < length; i++) {
const c = tree[i];
if (c !== 0) {
const value = (i << 4) | c;
const rest = bits - c;
let index = codes[i] << rest;
const max = index + (1 << rest);
for (; index != max; index++) {
table[rev15[index] >>> shift] = value;
}
}
}
return table;
}
};
zip.BitReader = class {
constructor(buffer) {
this.buffer = buffer;
this.position = 0;
}
bits(count) {
const offset = (this.position / 8) >> 0;
const shift = (this.position & 7);
this.position += count;
return ((this.buffer[offset] | (this.buffer[offset + 1] << 8)) >>> shift) & ((1 << count) - 1);
}
bits16() {
const offset = (this.position / 8) >> 0;
return ((this.buffer[offset] | (this.buffer[offset + 1] << 8) | (this.buffer[offset + 2] << 16)) >>> (this.position & 7));
}
read(length) {
this.position = (this.position + 7) & ~7; // align
const offset = (this.position / 8) >> 0;
this.position += length * 8;
return this.buffer.subarray(offset, offset + length);
}
uint16() {
this.position = (this.position + 7) & ~7; // align
const offset = (this.position / 8) >> 0;
this.position += 16;
return this.buffer[offset] | (this.buffer[offset + 1] << 8);
}
};
zip.BlockWriter = class {
constructor() {
this.blocks = [];
this.buffer = new Uint8Array(65536);
this.position = 0;
this.length = 0;
this.threshold = 0xf400;
}
push(position) {
this.blocks.push(new Uint8Array(this.buffer.subarray(this.position, position)));
this.length += position - this.position;
this.position = position;
return this._reset();
}
write(buffer) {
this.blocks.push(buffer);
const length = buffer.length;
this.length += length;
if (length > 32768) {
this.buffer.set(buffer.subarray(length - 32768, length), 0);
this.position = 32768;
}
else {
this._reset();
this.buffer.set(buffer, this.position);
this.position += length;
}
}
toBuffer() {
const buffer = new Uint8Array(this.length);
let offset = 0;
for (const block of this.blocks) {
buffer.set(block, offset);
offset += block.length;
}
return buffer;
}
_reset() {
if (this.position > 32768) {
this.buffer.set(this.buffer.subarray(this.position - 32768, this.position), 0);
this.position = 32768;
}
return this.position;
}
};
zip.BufferWriter = class {
constructor(length) {
this.buffer = new Uint8Array(length);
this.length = length;
this.position = 0;
}
push(position) {
this.position = position;
if (this.position > this.length) {
throw new zip.Error('Invalid size.');
}
return this.position;
}
write(buffer) {
this.buffer.set(buffer, this.position);
this.position += buffer.length;
if (this.position > this.length) {
throw new zip.Error('Invalid size.');
}
return this.position;
}
toBuffer() {
return this.buffer;
}
};
zip.InflaterStream = class {
constructor(stream, length) {
this._stream = stream;
this._offset = this._stream.position;
this._position = 0;
this._length = length;
}
get position() {
return this._position;
}
get length() {
if (this._length === undefined) {
this._inflate();
}
return this._length;
}
seek(position) {
if (this._buffer === undefined) {
this._inflate();
}
this._position = position >= 0 ? position : this._length + position;
}
skip(offset) {
if (this._buffer === undefined) {
this._inflate();
}
this._position += offset;
}
peek(length) {
const position = this._position;
length = length !== undefined ? length : this._length - position;
this.skip(length);
const end = this._position;
this.seek(position);
if (position === 0 && length === this._length) {
return this._buffer;
}
return this._buffer.subarray(position, end);
}
read(length) {
const position = this._position;
length = length !== undefined ? length : this._length - position;
this.skip(length);
if (position === 0 && length === this._length) {
return this._buffer;
}
return this._buffer.subarray(position, this._position);
}
byte() {
const position = this._position;
this.skip(1);
return this._buffer[position];
}
_inflate() {
if (this._buffer === undefined) {
const position = this._stream.position;
this._stream.seek(this._offset);
const buffer = this._stream.peek();
this._buffer = new zip.Inflater().inflateRaw(buffer, this._length);
this._length = this._buffer.length;
this._stream.seek(position);
delete this._stream;
}
}
};
zip.BinaryReader = class {
constructor(buffer) {
this._buffer = buffer;
this._length = buffer.length;
this._position = 0;
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
}
get position() {
return this._position;
}
get length() {
return this._length;
}
create(buffer) {
return new zip.BinaryReader(buffer);
}
stream(length) {
return this.create(this.read(length));
}
seek(position) {
this._position = position >= 0 ? position : this._length + position;
}
skip(offset) {
this._position += offset;
}
peek(length) {
if (this._position === 0 && length === undefined) {
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
const end = this._position;
this.seek(position);
return this._buffer.subarray(position, end);
}
read(length) {
if (this._position === 0 && length === undefined) {
this._position = this._length;
return this._buffer;
}
const position = this._position;
this.skip(length !== undefined ? length : this._length - this._position);
return this._buffer.subarray(position, this._position);
}
byte() {
const position = this._position;
this.skip(1);
return this._buffer[position];
}
uint16() {
const position = this._position;
this.skip(2);
return this._view.getUint16(position, true);
}
uint32() {
const position = this._position;
this.skip(4);
return this._view.getUint32(position, true);
}
};
zlib.Archive = class {
constructor(stream) {
const position = stream.position;
stream.read(2);
const entry = new zlib.Entry(stream);
this._entries = new Map([ [ entry.name, entry.stream ] ]);
stream.seek(position);
}
get entries() {
return this._entries;
}
};
zlib.Entry = class {
constructor(stream) {
this._stream = new zip.InflaterStream(stream);
}
get name() {
return '';
}
get stream() {
return this._stream;
}
};
zip.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'Zip Error';
this.stack = undefined;
}
};
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
module.exports.Archive = zip.Archive;
module.exports.Inflater = zip.Inflater;
}
Loading…
Cancel
Save