@ -0,0 +1,45 @@ |
|||||||
|
var dimensions = { |
||||||
|
|
||||||
|
width:0, |
||||||
|
|
||||||
|
height:0, |
||||||
|
|
||||||
|
getWidth: function () { |
||||||
|
if (window.innerWidth) { |
||||||
|
return window.innerWidth; |
||||||
|
} |
||||||
|
if (document.documentElement && document.documentElement.clientHeight){ |
||||||
|
return document.documentElement.clientWidth; |
||||||
|
} |
||||||
|
if (document.body) { |
||||||
|
return document.body.clientWidth; |
||||||
|
} |
||||||
|
return 0; |
||||||
|
}, |
||||||
|
|
||||||
|
getHeight: function () { |
||||||
|
if (window.innerWidth) { |
||||||
|
return window.innerHeight; |
||||||
|
} |
||||||
|
if (document.documentElement && document.documentElement.clientHeight){ |
||||||
|
return document.documentElement.clientHeight; |
||||||
|
} |
||||||
|
if (document.body) { |
||||||
|
return document.body.clientHeight; |
||||||
|
} |
||||||
|
return 0; |
||||||
|
}, |
||||||
|
|
||||||
|
update: function () { |
||||||
|
var curW = this.getWidth() |
||||||
|
var curH = this.getHeight() |
||||||
|
if (curW!=this.width||curH!=this.height){ |
||||||
|
this.width=curW |
||||||
|
this.height=curH |
||||||
|
return true |
||||||
|
} |
||||||
|
else { |
||||||
|
return false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,189 @@ |
|||||||
|
// (function(){
|
||||||
|
|
||||||
|
// var color = "rgb(255,133,0)"
|
||||||
|
// var color = "rgb(55,110,79)"
|
||||||
|
var color="white" |
||||||
|
|
||||||
|
// var color = "rgb(255,221,21)"
|
||||||
|
// var color = '#'+(16777216+Math.floor(Math.random()*16777215)).toString(16).slice(1)
|
||||||
|
// document.styleSheets[0].insertRule("a {color: "+color+"}",0)
|
||||||
|
|
||||||
|
var lasttime, |
||||||
|
canvas = document.getElementById('canvas'), |
||||||
|
ctx = canvas.getContext('2d'); |
||||||
|
|
||||||
|
// canvas.style['background-color'] = color;
|
||||||
|
|
||||||
|
var logo = new Image(), logo_small = new Image() |
||||||
|
logo.src = 'img/logo.png' |
||||||
|
logo_small.src = 'img/logo.png' |
||||||
|
|
||||||
|
|
||||||
|
// var pixelRatio = (function(context) {
|
||||||
|
// var backingStore = context.backingStorePixelRatio ||
|
||||||
|
// context.webkitBackingStorePixelRatio ||
|
||||||
|
// context.mozBackingStorePixelRatio ||
|
||||||
|
// context.msBackingStorePixelRatio ||
|
||||||
|
// context.oBackingStorePixelRatio ||
|
||||||
|
// context.backingStorePixelRatio || 1;
|
||||||
|
|
||||||
|
// return (window.devicePixelRatio || 1) / backingStore;
|
||||||
|
// })(ctx);
|
||||||
|
|
||||||
|
function app1(p,a,c1,c2){ |
||||||
|
var l = Math.cos(a)*p[c1]+Math.sin(a)*p[c2] |
||||||
|
var k = -Math.sin(a)*p[c1]+Math.cos(a)*p[c2] |
||||||
|
p[c1] = l |
||||||
|
p[c2] = k |
||||||
|
} |
||||||
|
|
||||||
|
function app2(p,a,c1,c2){ |
||||||
|
var l = Math.cos(a)*p[c1]-Math.sin(a)*p[c2] |
||||||
|
var k = Math.sin(a)*p[c1]+Math.cos(a)*p[c2] |
||||||
|
p[c1] = l |
||||||
|
p[c2] = k |
||||||
|
} |
||||||
|
|
||||||
|
var _edges |
||||||
|
function tesseractedges(){ |
||||||
|
if(!_edges){ |
||||||
|
var m = tesseractwithrotation(0,0,0,0,0,0) |
||||||
|
var edges = [] |
||||||
|
var indicies = ['x','y','z','w'] |
||||||
|
for (var i = 0; i < m.length; i++) { |
||||||
|
for (var j = i+1; j < m.length; j++) { |
||||||
|
var count = 0 |
||||||
|
for (var k = 0; k < 4; k++) { |
||||||
|
if (m[i][indicies[k]] === m[j][indicies[k]]) count++ |
||||||
|
}; |
||||||
|
if (count === 3) edges.push([i,j]) |
||||||
|
} |
||||||
|
} |
||||||
|
_edges = edges |
||||||
|
} |
||||||
|
return _edges |
||||||
|
} |
||||||
|
|
||||||
|
function tesseractwithrotation(a,b,c,d,e,f) { |
||||||
|
var verticies = [] |
||||||
|
for (var i = 0; i < 16; i++) { |
||||||
|
var p = { |
||||||
|
x: (i&1)*2 - 1, |
||||||
|
y: ((i>>1)&1)*2 - 1, |
||||||
|
z: ((i>>2)&1)*2 - 1, |
||||||
|
w: ((i>>3)&1)*2 - 1 |
||||||
|
} |
||||||
|
app1(p,a,'x','y') |
||||||
|
app1(p,b,'y','z') |
||||||
|
app1(p,c,'x','w') |
||||||
|
app2(p,d,'x','z') |
||||||
|
app2(p,e,'y','w') |
||||||
|
app2(p,f,'z','w') |
||||||
|
verticies.push(p) |
||||||
|
} |
||||||
|
return verticies |
||||||
|
} |
||||||
|
|
||||||
|
function project(point, size){ |
||||||
|
return { |
||||||
|
x: (point.x+Math.SQRT2*point.z)*size, |
||||||
|
y: (point.y+Math.SQRT2*point.w)*size |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function init () { |
||||||
|
fixdim() |
||||||
|
lasttime = new Date().getTime() |
||||||
|
requestAnimationFrame(main) |
||||||
|
} |
||||||
|
|
||||||
|
function fixdim() { |
||||||
|
if(dimensions.update()){ |
||||||
|
var displaywidth = Math.sqrt(dimensions.width)*18//dimensions.width > 900 ? 900 : 450
|
||||||
|
var displayheight = displaywidth * 4/15//dimensions.width > 900 ? 250 : 125
|
||||||
|
canvas.width = displaywidth*window.devicePixelRatio |
||||||
|
canvas.style.width = displaywidth |
||||||
|
canvas.height = displayheight*window.devicePixelRatio |
||||||
|
canvas.style.height = displayheight |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function drawtesseract(tesseract, opts){ |
||||||
|
var edges = tesseractedges() |
||||||
|
for (var i = 0; i < tesseract.length; i++) { |
||||||
|
var proj = project(tesseract[i], opts.size) |
||||||
|
ctx.beginPath() |
||||||
|
ctx.arc(proj.x + opts.x, proj.y + opts.y, opts.corner_radius, 0, 2 * Math.PI) |
||||||
|
ctx.fill() |
||||||
|
}; |
||||||
|
ctx.lineWidth = opts.line_width || 1 |
||||||
|
ctx.beginPath() |
||||||
|
for (var i = 0; i < edges.length; i++) { |
||||||
|
var v1 = project(tesseract[edges[i][0]], opts.size), |
||||||
|
v2 = project(tesseract[edges[i][1]], opts.size) |
||||||
|
ctx.moveTo(v1.x+opts.x,v1.y+opts.y) |
||||||
|
ctx.lineTo(v2.x+opts.x,v2.y+opts.y) |
||||||
|
}; |
||||||
|
ctx.stroke() |
||||||
|
} |
||||||
|
|
||||||
|
var as = -.371, df = -.01, gh = .12; |
||||||
|
|
||||||
|
var asdf = 120 |
||||||
|
var sdfg = .01 |
||||||
|
|
||||||
|
var x = 10, y=10,w = 10,h = 10 |
||||||
|
|
||||||
|
function main (time) { |
||||||
|
fixdim() |
||||||
|
ctx.clearRect(0,0,canvas.width,canvas.height) |
||||||
|
|
||||||
|
var t = time/10000 |
||||||
|
|
||||||
|
// "rgb(0,140,255)"
|
||||||
|
// ctx.strokeStyle = '#444'
|
||||||
|
// ctx.fillStyle = "rgb(0,140,255)"
|
||||||
|
ctx.strokeStyle = ctx.fillStyle = color |
||||||
|
var sm = 1 |
||||||
|
|
||||||
|
// var m = tesseractwithrotation( 0,0,0,mouse.x/100 ,mouse.y/100, 0)
|
||||||
|
var m = tesseractwithrotation(t, t*2, t*3, mouse.x/100 , mouse.y/100, 0) |
||||||
|
|
||||||
|
drawtesseract(m, { |
||||||
|
x: as*canvas.width + canvas.width/2, |
||||||
|
y: df*canvas.height + canvas.height/2, |
||||||
|
size: gh*canvas.height, |
||||||
|
corner_radius: 0, |
||||||
|
line_width: 2 |
||||||
|
}) |
||||||
|
|
||||||
|
ctx.beginPath() |
||||||
|
// ctx.fillStyle = 'red'
|
||||||
|
// ctx.fillRect(
|
||||||
|
// (as+.5 - .0058)*canvas.width,
|
||||||
|
// (df+.002+.5-.164)*canvas.height,// + canvas.height/2 - asdf/2,
|
||||||
|
// .0058*2*canvas.width,
|
||||||
|
// .164*2*canvas.height
|
||||||
|
// )
|
||||||
|
// ctx.fillRect(
|
||||||
|
// 0.0951*canvas.width,
|
||||||
|
// 0.0871*canvas.width,
|
||||||
|
// 0.0673*canvas.width,
|
||||||
|
// 0.0109*canvas.width
|
||||||
|
// )
|
||||||
|
|
||||||
|
// ctx.fill()
|
||||||
|
|
||||||
|
// var m = tesseractwithrotation(0,0,0, mouse.x/100 , mouse.y/100, 0)
|
||||||
|
// var m = tesseractwithrotation(t, t*2, t*3, mouse.x/100 , mouse.y/100, 0)
|
||||||
|
// var k = tesseractwithrotation(t, t*2, t*3, mouse.x/100+.08, mouse.y/100, 0)
|
||||||
|
|
||||||
|
|
||||||
|
lasttime = time |
||||||
|
requestAnimationFrame(main) |
||||||
|
} |
||||||
|
|
||||||
|
init() |
||||||
|
|
||||||
|
// })()
|
@ -0,0 +1,56 @@ |
|||||||
|
var mouse = { |
||||||
|
x: 0, |
||||||
|
y: 0, |
||||||
|
direction:0, |
||||||
|
|
||||||
|
start: { |
||||||
|
x:0, |
||||||
|
y:0 |
||||||
|
}, |
||||||
|
|
||||||
|
dragging: false, |
||||||
|
|
||||||
|
set: function (x,y) { |
||||||
|
mouse.x = x |
||||||
|
mouse.y = y |
||||||
|
mouse.direction = Math.atan2(y-mouse.start.y,x-mouse.start.x) |
||||||
|
}, |
||||||
|
|
||||||
|
coords: function (e) { |
||||||
|
// e.preventDefault();
|
||||||
|
if(e.pageX){ |
||||||
|
mouse.set(e.pageX,e.pageY) |
||||||
|
} |
||||||
|
else if(e.offsetX) { |
||||||
|
mouse.set(e.offsetX,e.offsetY) |
||||||
|
} |
||||||
|
else if(e.layerX) { |
||||||
|
mouse.set(e.layerX,e.layerY) |
||||||
|
} |
||||||
|
else if(e.targetTouches && e.targetTouches.length > 0){ |
||||||
|
mouse.set(e.targetTouches[0].pageX,e.targetTouches[0].pageY) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
down: function (e) { |
||||||
|
mouse.coords(e) |
||||||
|
mouse.start.x=mouse.x |
||||||
|
mouse.start.y=mouse.y |
||||||
|
mouse.dragging = true |
||||||
|
// console.log(e)
|
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
up: function (e) { |
||||||
|
mouse.coords(e) |
||||||
|
mouse.dragging = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
document.addEventListener("touchstart", mouse.down, true); |
||||||
|
document.addEventListener("touchend", mouse.up, true); |
||||||
|
document.addEventListener("touchmove", mouse.coords, true); |
||||||
|
|
||||||
|
document.addEventListener("mousedown", mouse.down, true); |
||||||
|
document.addEventListener("mouseup", mouse.up, true); |
||||||
|
document.addEventListener("mousemove", mouse.coords, true); |
@ -0,0 +1,27 @@ |
|||||||
|
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
||||||
|
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
|
||||||
|
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
|
||||||
|
// MIT license
|
||||||
|
|
||||||
|
;(function() { |
||||||
|
var lastTime = 0; |
||||||
|
var vendors = ['ms', 'moz', 'webkit', 'o']; |
||||||
|
if(typeof window != "undefined"){ |
||||||
|
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { |
||||||
|
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; |
||||||
|
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] |
||||||
|
|| window[vendors[x]+'CancelRequestAnimationFrame']; |
||||||
|
} |
||||||
|
if (!window.requestAnimationFrame) |
||||||
|
window.requestAnimationFrame = function(callback, element) { |
||||||
|
var currTime = new Date().getTime(); |
||||||
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime)); |
||||||
|
var id = window.setTimeout(function() { callback(currTime + timeToCall); }, |
||||||
|
timeToCall); |
||||||
|
lastTime = currTime + timeToCall; |
||||||
|
return id; |
||||||
|
}; |
||||||
|
if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; |
||||||
|
} |
||||||
|
}()); |
||||||
|
|
@ -0,0 +1,327 @@ |
|||||||
|
/* BASICS */ |
||||||
|
|
||||||
|
.CodeMirror { |
||||||
|
/* Set height, width, borders, and global font properties here */ |
||||||
|
font-family: monospace; |
||||||
|
height: auto; |
||||||
|
color: black; |
||||||
|
padding: 10px; |
||||||
|
padding-top: 5px; |
||||||
|
} |
||||||
|
|
||||||
|
/* PADDING */ |
||||||
|
|
||||||
|
.CodeMirror-lines { |
||||||
|
padding: 4px 0; /* Vertical padding around content */ |
||||||
|
} |
||||||
|
.CodeMirror pre { |
||||||
|
padding: 0 4px; /* Horizontal padding of content */ |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { |
||||||
|
background-color: white; /* The little square between H and V scrollbars */ |
||||||
|
} |
||||||
|
|
||||||
|
/* GUTTER */ |
||||||
|
|
||||||
|
.CodeMirror-gutters { |
||||||
|
border-right: 1px solid #ddd; |
||||||
|
background-color: #f7f7f7; |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
.CodeMirror-linenumbers {} |
||||||
|
.CodeMirror-linenumber { |
||||||
|
padding: 0 3px 0 5px; |
||||||
|
min-width: 20px; |
||||||
|
text-align: right; |
||||||
|
color: #999; |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-guttermarker { color: black; } |
||||||
|
.CodeMirror-guttermarker-subtle { color: #999; } |
||||||
|
|
||||||
|
/* CURSOR */ |
||||||
|
|
||||||
|
.CodeMirror div.CodeMirror-cursor { |
||||||
|
border-left: 1px solid black; |
||||||
|
} |
||||||
|
/* Shown when moving in bi-directional text */ |
||||||
|
.CodeMirror div.CodeMirror-secondarycursor { |
||||||
|
border-left: 1px solid silver; |
||||||
|
} |
||||||
|
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor { |
||||||
|
width: auto; |
||||||
|
border: 0; |
||||||
|
background: #7e7; |
||||||
|
} |
||||||
|
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors { |
||||||
|
z-index: 1; |
||||||
|
} |
||||||
|
|
||||||
|
.cm-animate-fat-cursor { |
||||||
|
width: auto; |
||||||
|
border: 0; |
||||||
|
-webkit-animation: blink 1.06s steps(1) infinite; |
||||||
|
-moz-animation: blink 1.06s steps(1) infinite; |
||||||
|
animation: blink 1.06s steps(1) infinite; |
||||||
|
} |
||||||
|
@-moz-keyframes blink { |
||||||
|
0% { background: #7e7; } |
||||||
|
50% { background: none; } |
||||||
|
100% { background: #7e7; } |
||||||
|
} |
||||||
|
@-webkit-keyframes blink { |
||||||
|
0% { background: #7e7; } |
||||||
|
50% { background: none; } |
||||||
|
100% { background: #7e7; } |
||||||
|
} |
||||||
|
@keyframes blink { |
||||||
|
0% { background: #7e7; } |
||||||
|
50% { background: none; } |
||||||
|
100% { background: #7e7; } |
||||||
|
} |
||||||
|
|
||||||
|
/* Can style cursor different in overwrite (non-insert) mode */ |
||||||
|
div.CodeMirror-overwrite div.CodeMirror-cursor {} |
||||||
|
|
||||||
|
.cm-tab { display: inline-block; text-decoration: inherit; } |
||||||
|
|
||||||
|
.CodeMirror-ruler { |
||||||
|
border-left: 1px solid #ccc; |
||||||
|
position: absolute; |
||||||
|
} |
||||||
|
|
||||||
|
/* DEFAULT THEME */ |
||||||
|
|
||||||
|
.cm-s-default .cm-header {color: blue;} |
||||||
|
.cm-s-default .cm-quote {color: #090;} |
||||||
|
.cm-negative {color: #d44;} |
||||||
|
.cm-positive {color: #292;} |
||||||
|
.cm-header, .cm-strong {font-weight: bold;} |
||||||
|
.cm-em {font-style: italic;} |
||||||
|
.cm-link {text-decoration: underline;} |
||||||
|
.cm-strikethrough {text-decoration: line-through;} |
||||||
|
|
||||||
|
.cm-s-default .cm-keyword {color: #f90;} |
||||||
|
.cm-s-default .cm-atom {color: #219;} |
||||||
|
.cm-s-default .cm-number {color: #164;} |
||||||
|
.cm-s-default .cm-def {color: #00f;} |
||||||
|
.cm-s-default .cm-variable, |
||||||
|
.cm-s-default .cm-punctuation {} |
||||||
|
.cm-s-default .cm-property {color: #4CA2F2;} |
||||||
|
.cm-s-default .cm-operator {} |
||||||
|
.cm-s-default .cm-variable-2 {color: #05a;} |
||||||
|
.cm-s-default .cm-variable-3 {color: #085;} |
||||||
|
.cm-s-default .cm-comment {color: #a50;} |
||||||
|
.cm-s-default .cm-string {color: #a11;} |
||||||
|
.cm-s-default .cm-string-2 {color: #f50;} |
||||||
|
.cm-s-default .cm-meta {color: #555;} |
||||||
|
.cm-s-default .cm-qualifier {color: #555;} |
||||||
|
.cm-s-default .cm-builtin {color: #30a;} |
||||||
|
.cm-s-default .cm-bracket {color: #997;} |
||||||
|
.cm-s-default .cm-tag {color: #170;} |
||||||
|
.cm-s-default .cm-attribute {color: #00c;} |
||||||
|
.cm-s-default .cm-hr {color: #999;} |
||||||
|
.cm-s-default .cm-link {color: #00c;} |
||||||
|
|
||||||
|
.cm-s-default .cm-error {color: #f00;} |
||||||
|
.cm-invalidchar {color: #f00;} |
||||||
|
|
||||||
|
.CodeMirror-composing { border-bottom: 2px solid; } |
||||||
|
|
||||||
|
/* Default styles for common addons */ |
||||||
|
|
||||||
|
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} |
||||||
|
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} |
||||||
|
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } |
||||||
|
.CodeMirror-activeline-background {background: #e8f2ff;} |
||||||
|
|
||||||
|
/* STOP */ |
||||||
|
|
||||||
|
/* The rest of this file contains styles related to the mechanics of |
||||||
|
the editor. You probably shouldn't touch them. */ |
||||||
|
|
||||||
|
.CodeMirror { |
||||||
|
position: relative; |
||||||
|
overflow: hidden; |
||||||
|
background: white; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-scroll { |
||||||
|
overflow: scroll !important; /* Things will break if this is overridden */ |
||||||
|
/* 30px is the magic margin used to hide the element's real scrollbars */ |
||||||
|
/* See overflow: hidden in .CodeMirror */ |
||||||
|
margin-bottom: -30px; margin-right: -30px; |
||||||
|
padding-bottom: 30px; |
||||||
|
/*height: 100%;*/ |
||||||
|
outline: none; /* Prevent dragging from highlighting the element */ |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
.CodeMirror-sizer { |
||||||
|
position: relative; |
||||||
|
border-right: 30px solid transparent; |
||||||
|
} |
||||||
|
|
||||||
|
/* The fake, visible scrollbars. Used to force redraw during scrolling |
||||||
|
before actuall scrolling happens, thus preventing shaking and |
||||||
|
flickering artifacts. */ |
||||||
|
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { |
||||||
|
position: absolute; |
||||||
|
z-index: 6; |
||||||
|
display: none; |
||||||
|
} |
||||||
|
.CodeMirror-vscrollbar { |
||||||
|
right: 0; top: 0; |
||||||
|
overflow-x: hidden; |
||||||
|
overflow-y: scroll; |
||||||
|
} |
||||||
|
.CodeMirror-hscrollbar { |
||||||
|
bottom: 0; left: 0; |
||||||
|
overflow-y: hidden; |
||||||
|
overflow-x: scroll; |
||||||
|
} |
||||||
|
.CodeMirror-scrollbar-filler { |
||||||
|
right: 0; bottom: 0; |
||||||
|
} |
||||||
|
.CodeMirror-gutter-filler { |
||||||
|
left: 0; bottom: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-gutters { |
||||||
|
position: absolute; left: 0; top: 0; |
||||||
|
z-index: 3; |
||||||
|
} |
||||||
|
.CodeMirror-gutter { |
||||||
|
white-space: normal; |
||||||
|
height: 100%; |
||||||
|
display: inline-block; |
||||||
|
margin-bottom: -30px; |
||||||
|
/* Hack to make IE7 behave */ |
||||||
|
*zoom:1; |
||||||
|
*display:inline; |
||||||
|
} |
||||||
|
.CodeMirror-gutter-wrapper { |
||||||
|
position: absolute; |
||||||
|
z-index: 4; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
.CodeMirror-gutter-elt { |
||||||
|
position: absolute; |
||||||
|
cursor: default; |
||||||
|
z-index: 4; |
||||||
|
} |
||||||
|
.CodeMirror-gutter-wrapper { |
||||||
|
-webkit-user-select: none; |
||||||
|
-moz-user-select: none; |
||||||
|
user-select: none; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-lines { |
||||||
|
cursor: text; |
||||||
|
min-height: 1px; /* prevents collapsing before first draw */ |
||||||
|
} |
||||||
|
.CodeMirror pre { |
||||||
|
/* Reset some styles that the rest of the page might have set */ |
||||||
|
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; |
||||||
|
border-width: 0; |
||||||
|
background: transparent; |
||||||
|
font-family: inherit; |
||||||
|
font-size: inherit; |
||||||
|
margin: 0; |
||||||
|
white-space: pre; |
||||||
|
word-wrap: normal; |
||||||
|
line-height: inherit; |
||||||
|
color: inherit; |
||||||
|
z-index: 2; |
||||||
|
position: relative; |
||||||
|
overflow: visible; |
||||||
|
-webkit-tap-highlight-color: transparent; |
||||||
|
} |
||||||
|
.CodeMirror-wrap pre { |
||||||
|
word-wrap: break-word; |
||||||
|
white-space: pre-wrap; |
||||||
|
word-break: normal; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-linebackground { |
||||||
|
position: absolute; |
||||||
|
left: 0; right: 0; top: 0; bottom: 0; |
||||||
|
z-index: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-linewidget { |
||||||
|
position: relative; |
||||||
|
z-index: 2; |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-widget {} |
||||||
|
|
||||||
|
.CodeMirror-code { |
||||||
|
outline: none; |
||||||
|
} |
||||||
|
|
||||||
|
/* Force content-box sizing for the elements where we expect it */ |
||||||
|
.CodeMirror-scroll, |
||||||
|
.CodeMirror-sizer, |
||||||
|
.CodeMirror-gutter, |
||||||
|
.CodeMirror-gutters, |
||||||
|
.CodeMirror-linenumber { |
||||||
|
-moz-box-sizing: content-box; |
||||||
|
box-sizing: content-box; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-measure { |
||||||
|
position: absolute; |
||||||
|
width: 100%; |
||||||
|
height: 0; |
||||||
|
overflow: hidden; |
||||||
|
visibility: hidden; |
||||||
|
} |
||||||
|
.CodeMirror-measure pre { position: static; } |
||||||
|
|
||||||
|
.CodeMirror div.CodeMirror-cursor { |
||||||
|
position: absolute; |
||||||
|
border-right: none; |
||||||
|
width: 0; |
||||||
|
} |
||||||
|
|
||||||
|
div.CodeMirror-cursors { |
||||||
|
visibility: hidden; |
||||||
|
position: relative; |
||||||
|
z-index: 3; |
||||||
|
} |
||||||
|
.CodeMirror-focused div.CodeMirror-cursors { |
||||||
|
visibility: visible; |
||||||
|
} |
||||||
|
|
||||||
|
.CodeMirror-selected { background: #d9d9d9; } |
||||||
|
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } |
||||||
|
.CodeMirror-crosshair { cursor: crosshair; } |
||||||
|
.CodeMirror ::selection { background: #d7d4f0; } |
||||||
|
.CodeMirror ::-moz-selection { background: #d7d4f0; } |
||||||
|
|
||||||
|
.cm-searching { |
||||||
|
background: #ffa; |
||||||
|
background: rgba(255, 255, 0, .4); |
||||||
|
} |
||||||
|
|
||||||
|
/* IE7 hack to prevent it from returning funny offsetTops on the spans */ |
||||||
|
.CodeMirror span { *vertical-align: text-bottom; } |
||||||
|
|
||||||
|
/* Used to force a border model for a node */ |
||||||
|
.cm-force-border { padding-right: .1px; } |
||||||
|
|
||||||
|
@media print { |
||||||
|
/* Hide the cursor when printing */ |
||||||
|
.CodeMirror div.CodeMirror-cursors { |
||||||
|
visibility: hidden; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* See issue #2901 */ |
||||||
|
.cm-tab-wrap-hack:after { content: ''; } |
||||||
|
|
||||||
|
/* Help users use markselection to safely style text background */ |
||||||
|
span.CodeMirror-selectedtext { background: none; } |
@ -0,0 +1,704 @@ |
|||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
// TODO actually recognize syntax of TypeScript constructs
|
||||||
|
|
||||||
|
(function(mod) { |
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror")); |
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror"], mod); |
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror); |
||||||
|
})(function(CodeMirror) { |
||||||
|
"use strict"; |
||||||
|
|
||||||
|
CodeMirror.defineMode("javascript", function(config, parserConfig) { |
||||||
|
var indentUnit = config.indentUnit; |
||||||
|
var statementIndent = parserConfig.statementIndent; |
||||||
|
var jsonldMode = parserConfig.jsonld; |
||||||
|
var jsonMode = parserConfig.json || jsonldMode; |
||||||
|
var isTS = parserConfig.typescript; |
||||||
|
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; |
||||||
|
|
||||||
|
// Tokenizer
|
||||||
|
|
||||||
|
var keywords = function(){ |
||||||
|
function kw(type) {return {type: type, style: "keyword"};} |
||||||
|
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); |
||||||
|
var operator = kw("operator"), atom = {type: "atom", style: "atom"}; |
||||||
|
|
||||||
|
var jsKeywords = { |
||||||
|
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, |
||||||
|
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C, |
||||||
|
"var": kw("var"), "const": kw("var"), "let": kw("var"), |
||||||
|
"function": kw("function"), "catch": kw("catch"), |
||||||
|
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), |
||||||
|
"in": operator, "typeof": operator, "instanceof": operator, |
||||||
|
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, |
||||||
|
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"), |
||||||
|
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C |
||||||
|
}; |
||||||
|
|
||||||
|
// Extend the 'normal' keywords with the TypeScript language extensions
|
||||||
|
if (isTS) { |
||||||
|
var type = {type: "variable", style: "variable-3"}; |
||||||
|
var tsKeywords = { |
||||||
|
// object-like things
|
||||||
|
"interface": kw("interface"), |
||||||
|
"extends": kw("extends"), |
||||||
|
"constructor": kw("constructor"), |
||||||
|
|
||||||
|
// scope modifiers
|
||||||
|
"public": kw("public"), |
||||||
|
"private": kw("private"), |
||||||
|
"protected": kw("protected"), |
||||||
|
"static": kw("static"), |
||||||
|
|
||||||
|
// types
|
||||||
|
"string": type, "number": type, "bool": type, "any": type |
||||||
|
}; |
||||||
|
|
||||||
|
for (var attr in tsKeywords) { |
||||||
|
jsKeywords[attr] = tsKeywords[attr]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return jsKeywords; |
||||||
|
}(); |
||||||
|
|
||||||
|
var isOperatorChar = /[+\-*&%=<>!?|~^]/; |
||||||
|
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; |
||||||
|
|
||||||
|
function readRegexp(stream) { |
||||||
|
var escaped = false, next, inSet = false; |
||||||
|
while ((next = stream.next()) != null) { |
||||||
|
if (!escaped) { |
||||||
|
if (next == "/" && !inSet) return; |
||||||
|
if (next == "[") inSet = true; |
||||||
|
else if (inSet && next == "]") inSet = false; |
||||||
|
} |
||||||
|
escaped = !escaped && next == "\\"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Used as scratch variables to communicate multiple values without
|
||||||
|
// consing up tons of objects.
|
||||||
|
var type, content; |
||||||
|
function ret(tp, style, cont) { |
||||||
|
type = tp; content = cont; |
||||||
|
return style; |
||||||
|
} |
||||||
|
function tokenBase(stream, state) { |
||||||
|
var ch = stream.next(); |
||||||
|
if (ch == '"' || ch == "'") { |
||||||
|
state.tokenize = tokenString(ch); |
||||||
|
return state.tokenize(stream, state); |
||||||
|
} else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { |
||||||
|
return ret("number", "number"); |
||||||
|
} else if (ch == "." && stream.match("..")) { |
||||||
|
return ret("spread", "meta"); |
||||||
|
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { |
||||||
|
return ret(ch); |
||||||
|
} else if (ch == "=" && stream.eat(">")) { |
||||||
|
return ret("=>", "operator"); |
||||||
|
} else if (ch == "0" && stream.eat(/x/i)) { |
||||||
|
stream.eatWhile(/[\da-f]/i); |
||||||
|
return ret("number", "number"); |
||||||
|
} else if (/\d/.test(ch)) { |
||||||
|
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); |
||||||
|
return ret("number", "number"); |
||||||
|
} else if (ch == "/") { |
||||||
|
if (stream.eat("*")) { |
||||||
|
state.tokenize = tokenComment; |
||||||
|
return tokenComment(stream, state); |
||||||
|
} else if (stream.eat("/")) { |
||||||
|
stream.skipToEnd(); |
||||||
|
return ret("comment", "comment"); |
||||||
|
} else if (state.lastType == "operator" || state.lastType == "keyword c" || |
||||||
|
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { |
||||||
|
readRegexp(stream); |
||||||
|
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); |
||||||
|
return ret("regexp", "string-2"); |
||||||
|
} else { |
||||||
|
stream.eatWhile(isOperatorChar); |
||||||
|
return ret("operator", "operator", stream.current()); |
||||||
|
} |
||||||
|
} else if (ch == "`") { |
||||||
|
state.tokenize = tokenQuasi; |
||||||
|
return tokenQuasi(stream, state); |
||||||
|
} else if (ch == "#") { |
||||||
|
stream.skipToEnd(); |
||||||
|
return ret("error", "error"); |
||||||
|
} else if (isOperatorChar.test(ch)) { |
||||||
|
stream.eatWhile(isOperatorChar); |
||||||
|
return ret("operator", "operator", stream.current()); |
||||||
|
} else if (wordRE.test(ch)) { |
||||||
|
stream.eatWhile(wordRE); |
||||||
|
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; |
||||||
|
return (known && state.lastType != ".") ? ret(known.type, known.style, word) : |
||||||
|
ret("variable", "variable", word); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function tokenString(quote) { |
||||||
|
return function(stream, state) { |
||||||
|
var escaped = false, next; |
||||||
|
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ |
||||||
|
state.tokenize = tokenBase; |
||||||
|
return ret("jsonld-keyword", "meta"); |
||||||
|
} |
||||||
|
while ((next = stream.next()) != null) { |
||||||
|
if (next == quote && !escaped) break; |
||||||
|
escaped = !escaped && next == "\\"; |
||||||
|
} |
||||||
|
if (!escaped) state.tokenize = tokenBase; |
||||||
|
return ret("string", "string"); |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
function tokenComment(stream, state) { |
||||||
|
var maybeEnd = false, ch; |
||||||
|
while (ch = stream.next()) { |
||||||
|
if (ch == "/" && maybeEnd) { |
||||||
|
state.tokenize = tokenBase; |
||||||
|
break; |
||||||
|
} |
||||||
|
maybeEnd = (ch == "*"); |
||||||
|
} |
||||||
|
return ret("comment", "comment"); |
||||||
|
} |
||||||
|
|
||||||
|
function tokenQuasi(stream, state) { |
||||||
|
var escaped = false, next; |
||||||
|
while ((next = stream.next()) != null) { |
||||||
|
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { |
||||||
|
state.tokenize = tokenBase; |
||||||
|
break; |
||||||
|
} |
||||||
|
escaped = !escaped && next == "\\"; |
||||||
|
} |
||||||
|
return ret("quasi", "string-2", stream.current()); |
||||||
|
} |
||||||
|
|
||||||
|
var brackets = "([{}])"; |
||||||
|
// This is a crude lookahead trick to try and notice that we're
|
||||||
|
// parsing the argument patterns for a fat-arrow function before we
|
||||||
|
// actually hit the arrow token. It only works if the arrow is on
|
||||||
|
// the same line as the arguments and there's no strange noise
|
||||||
|
// (comments) in between. Fallback is to only notice when we hit the
|
||||||
|
// arrow, and not declare the arguments as locals for the arrow
|
||||||
|
// body.
|
||||||
|
function findFatArrow(stream, state) { |
||||||
|
if (state.fatArrowAt) state.fatArrowAt = null; |
||||||
|
var arrow = stream.string.indexOf("=>", stream.start); |
||||||
|
if (arrow < 0) return; |
||||||
|
|
||||||
|
var depth = 0, sawSomething = false; |
||||||
|
for (var pos = arrow - 1; pos >= 0; --pos) { |
||||||
|
var ch = stream.string.charAt(pos); |
||||||
|
var bracket = brackets.indexOf(ch); |
||||||
|
if (bracket >= 0 && bracket < 3) { |
||||||
|
if (!depth) { ++pos; break; } |
||||||
|
if (--depth == 0) break; |
||||||
|
} else if (bracket >= 3 && bracket < 6) { |
||||||
|
++depth; |
||||||
|
} else if (wordRE.test(ch)) { |
||||||
|
sawSomething = true; |
||||||
|
} else if (/["'\/]/.test(ch)) { |
||||||
|
return; |
||||||
|
} else if (sawSomething && !depth) { |
||||||
|
++pos; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (sawSomething && !depth) state.fatArrowAt = pos; |
||||||
|
} |
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; |
||||||
|
|
||||||
|
function JSLexical(indented, column, type, align, prev, info) { |
||||||
|
this.indented = indented; |
||||||
|
this.column = column; |
||||||
|
this.type = type; |
||||||
|
this.prev = prev; |
||||||
|
this.info = info; |
||||||
|
if (align != null) this.align = align; |
||||||
|
} |
||||||
|
|
||||||
|
function inScope(state, varname) { |
||||||
|
for (var v = state.localVars; v; v = v.next) |
||||||
|
if (v.name == varname) return true; |
||||||
|
for (var cx = state.context; cx; cx = cx.prev) { |
||||||
|
for (var v = cx.vars; v; v = v.next) |
||||||
|
if (v.name == varname) return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function parseJS(state, style, type, content, stream) { |
||||||
|
var cc = state.cc; |
||||||
|
// Communicate our context to the combinators.
|
||||||
|
// (Less wasteful than consing up a hundred closures on every call.)
|
||||||
|
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style; |
||||||
|
|
||||||
|
if (!state.lexical.hasOwnProperty("align")) |
||||||
|
state.lexical.align = true; |
||||||
|
|
||||||
|
while(true) { |
||||||
|
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; |
||||||
|
if (combinator(type, content)) { |
||||||
|
while(cc.length && cc[cc.length - 1].lex) |
||||||
|
cc.pop()(); |
||||||
|
if (cx.marked) return cx.marked; |
||||||
|
if (type == "variable" && inScope(state, content)) return "variable-2"; |
||||||
|
return style; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Combinator utils
|
||||||
|
|
||||||
|
var cx = {state: null, column: null, marked: null, cc: null}; |
||||||
|
function pass() { |
||||||
|
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); |
||||||
|
} |
||||||
|
function cont() { |
||||||
|
pass.apply(null, arguments); |
||||||
|
return true; |
||||||
|
} |
||||||
|
function register(varname) { |
||||||
|
function inList(list) { |
||||||
|
for (var v = list; v; v = v.next) |
||||||
|
if (v.name == varname) return true; |
||||||
|
return false; |
||||||
|
} |
||||||
|
var state = cx.state; |
||||||
|
if (state.context) { |
||||||
|
cx.marked = "def"; |
||||||
|
if (inList(state.localVars)) return; |
||||||
|
state.localVars = {name: varname, next: state.localVars}; |
||||||
|
} else { |
||||||
|
if (inList(state.globalVars)) return; |
||||||
|
if (parserConfig.globalVars) |
||||||
|
state.globalVars = {name: varname, next: state.globalVars}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Combinators
|
||||||
|
|
||||||
|
var defaultVars = {name: "this", next: {name: "arguments"}}; |
||||||
|
function pushcontext() { |
||||||
|
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; |
||||||
|
cx.state.localVars = defaultVars; |
||||||
|
} |
||||||
|
function popcontext() { |
||||||
|
cx.state.localVars = cx.state.context.vars; |
||||||
|
cx.state.context = cx.state.context.prev; |
||||||
|
} |
||||||
|
function pushlex(type, info) { |
||||||
|
var result = function() { |
||||||
|
var state = cx.state, indent = state.indented; |
||||||
|
if (state.lexical.type == "stat") indent = state.lexical.indented; |
||||||
|
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) |
||||||
|
indent = outer.indented; |
||||||
|
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); |
||||||
|
}; |
||||||
|
result.lex = true; |
||||||
|
return result; |
||||||
|
} |
||||||
|
function poplex() { |
||||||
|
var state = cx.state; |
||||||
|
if (state.lexical.prev) { |
||||||
|
if (state.lexical.type == ")") |
||||||
|
state.indented = state.lexical.indented; |
||||||
|
state.lexical = state.lexical.prev; |
||||||
|
} |
||||||
|
} |
||||||
|
poplex.lex = true; |
||||||
|
|
||||||
|
function expect(wanted) { |
||||||
|
function exp(type) { |
||||||
|
if (type == wanted) return cont(); |
||||||
|
else if (wanted == ";") return pass(); |
||||||
|
else return cont(exp); |
||||||
|
}; |
||||||
|
return exp; |
||||||
|
} |
||||||
|
|
||||||
|
function statement(type, value) { |
||||||
|
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); |
||||||
|
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); |
||||||
|
if (type == "keyword b") return cont(pushlex("form"), statement, poplex); |
||||||
|
if (type == "{") return cont(pushlex("}"), block, poplex); |
||||||
|
if (type == ";") return cont(); |
||||||
|
if (type == "if") { |
||||||
|
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) |
||||||
|
cx.state.cc.pop()(); |
||||||
|
return cont(pushlex("form"), expression, statement, poplex, maybeelse); |
||||||
|
} |
||||||
|
if (type == "function") return cont(functiondef); |
||||||
|
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); |
||||||
|
if (type == "variable") return cont(pushlex("stat"), maybelabel); |
||||||
|
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), |
||||||
|
block, poplex, poplex); |
||||||
|
if (type == "case") return cont(expression, expect(":")); |
||||||
|
if (type == "default") return cont(expect(":")); |
||||||
|
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), |
||||||
|
statement, poplex, popcontext); |
||||||
|
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex); |
||||||
|
if (type == "class") return cont(pushlex("form"), className, poplex); |
||||||
|
if (type == "export") return cont(pushlex("form"), afterExport, poplex); |
||||||
|
if (type == "import") return cont(pushlex("form"), afterImport, poplex); |
||||||
|
return pass(pushlex("stat"), expression, expect(";"), poplex); |
||||||
|
} |
||||||
|
function expression(type) { |
||||||
|
return expressionInner(type, false); |
||||||
|
} |
||||||
|
function expressionNoComma(type) { |
||||||
|
return expressionInner(type, true); |
||||||
|
} |
||||||
|
function expressionInner(type, noComma) { |
||||||
|
if (cx.state.fatArrowAt == cx.stream.start) { |
||||||
|
var body = noComma ? arrowBodyNoComma : arrowBody; |
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); |
||||||
|
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); |
||||||
|
} |
||||||
|
|
||||||
|
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; |
||||||
|
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); |
||||||
|
if (type == "function") return cont(functiondef, maybeop); |
||||||
|
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); |
||||||
|
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); |
||||||
|
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); |
||||||
|
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); |
||||||
|
if (type == "{") return contCommasep(objprop, "}", null, maybeop); |
||||||
|
if (type == "quasi") { return pass(quasi, maybeop); } |
||||||
|
return cont(); |
||||||
|
} |
||||||
|
function maybeexpression(type) { |
||||||
|
if (type.match(/[;\}\)\],]/)) return pass(); |
||||||
|
return pass(expression); |
||||||
|
} |
||||||
|
function maybeexpressionNoComma(type) { |
||||||
|
if (type.match(/[;\}\)\],]/)) return pass(); |
||||||
|
return pass(expressionNoComma); |
||||||
|
} |
||||||
|
|
||||||
|
function maybeoperatorComma(type, value) { |
||||||
|
if (type == ",") return cont(expression); |
||||||
|
return maybeoperatorNoComma(type, value, false); |
||||||
|
} |
||||||
|
function maybeoperatorNoComma(type, value, noComma) { |
||||||
|
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; |
||||||
|
var expr = noComma == false ? expression : expressionNoComma; |
||||||
|
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); |
||||||
|
if (type == "operator") { |
||||||
|
if (/\+\+|--/.test(value)) return cont(me); |
||||||
|
if (value == "?") return cont(expression, expect(":"), expr); |
||||||
|
return cont(expr); |
||||||
|
} |
||||||
|
if (type == "quasi") { return pass(quasi, me); } |
||||||
|
if (type == ";") return; |
||||||
|
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); |
||||||
|
if (type == ".") return cont(property, me); |
||||||
|
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); |
||||||
|
} |
||||||
|
function quasi(type, value) { |
||||||
|
if (type != "quasi") return pass(); |
||||||
|
if (value.slice(value.length - 2) != "${") return cont(quasi); |
||||||
|
return cont(expression, continueQuasi); |
||||||
|
} |
||||||
|
function continueQuasi(type) { |
||||||
|
if (type == "}") { |
||||||
|
cx.marked = "string-2"; |
||||||
|
cx.state.tokenize = tokenQuasi; |
||||||
|
return cont(quasi); |
||||||
|
} |
||||||
|
} |
||||||
|
function arrowBody(type) { |
||||||
|
findFatArrow(cx.stream, cx.state); |
||||||
|
return pass(type == "{" ? statement : expression); |
||||||
|
} |
||||||
|
function arrowBodyNoComma(type) { |
||||||
|
findFatArrow(cx.stream, cx.state); |
||||||
|
return pass(type == "{" ? statement : expressionNoComma); |
||||||
|
} |
||||||
|
function maybelabel(type) { |
||||||
|
if (type == ":") return cont(poplex, statement); |
||||||
|
return pass(maybeoperatorComma, expect(";"), poplex); |
||||||
|
} |
||||||
|
function property(type) { |
||||||
|
if (type == "variable") {cx.marked = "property"; return cont();} |
||||||
|
} |
||||||
|
function objprop(type, value) { |
||||||
|
if (type == "variable" || cx.style == "keyword") { |
||||||
|
cx.marked = "property"; |
||||||
|
if (value == "get" || value == "set") return cont(getterSetter); |
||||||
|
return cont(afterprop); |
||||||
|
} else if (type == "number" || type == "string") { |
||||||
|
cx.marked = jsonldMode ? "property" : (cx.style + " property"); |
||||||
|
return cont(afterprop); |
||||||
|
} else if (type == "jsonld-keyword") { |
||||||
|
return cont(afterprop); |
||||||
|
} else if (type == "[") { |
||||||
|
return cont(expression, expect("]"), afterprop); |
||||||
|
} |
||||||
|
} |
||||||
|
function getterSetter(type) { |
||||||
|
if (type != "variable") return pass(afterprop); |
||||||
|
cx.marked = "property"; |
||||||
|
return cont(functiondef); |
||||||
|
} |
||||||
|
function afterprop(type) { |
||||||
|
if (type == ":") return cont(expressionNoComma); |
||||||
|
if (type == "(") return pass(functiondef); |
||||||
|
} |
||||||
|
function commasep(what, end) { |
||||||
|
function proceed(type) { |
||||||
|
if (type == ",") { |
||||||
|
var lex = cx.state.lexical; |
||||||
|
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; |
||||||
|
return cont(what, proceed); |
||||||
|
} |
||||||
|
if (type == end) return cont(); |
||||||
|
return cont(expect(end)); |
||||||
|
} |
||||||
|
return function(type) { |
||||||
|
if (type == end) return cont(); |
||||||
|
return pass(what, proceed); |
||||||
|
}; |
||||||
|
} |
||||||
|
function contCommasep(what, end, info) { |
||||||
|
for (var i = 3; i < arguments.length; i++) |
||||||
|
cx.cc.push(arguments[i]); |
||||||
|
return cont(pushlex(end, info), commasep(what, end), poplex); |
||||||
|
} |
||||||
|
function block(type) { |
||||||
|
if (type == "}") return cont(); |
||||||
|
return pass(statement, block); |
||||||
|
} |
||||||
|
function maybetype(type) { |
||||||
|
if (isTS && type == ":") return cont(typedef); |
||||||
|
} |
||||||
|
function maybedefault(_, value) { |
||||||
|
if (value == "=") return cont(expressionNoComma); |
||||||
|
} |
||||||
|
function typedef(type) { |
||||||
|
if (type == "variable") {cx.marked = "variable-3"; return cont();} |
||||||
|
} |
||||||
|
function vardef() { |
||||||
|
return pass(pattern, maybetype, maybeAssign, vardefCont); |
||||||
|
} |
||||||
|
function pattern(type, value) { |
||||||
|
if (type == "variable") { register(value); return cont(); } |
||||||
|
if (type == "[") return contCommasep(pattern, "]"); |
||||||
|
if (type == "{") return contCommasep(proppattern, "}"); |
||||||
|
} |
||||||
|
function proppattern(type, value) { |
||||||
|
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { |
||||||
|
register(value); |
||||||
|
return cont(maybeAssign); |
||||||
|
} |
||||||
|
if (type == "variable") cx.marked = "property"; |
||||||
|
return cont(expect(":"), pattern, maybeAssign); |
||||||
|
} |
||||||
|
function maybeAssign(_type, value) { |
||||||
|
if (value == "=") return cont(expressionNoComma); |
||||||
|
} |
||||||
|
function vardefCont(type) { |
||||||
|
if (type == ",") return cont(vardef); |
||||||
|
} |
||||||
|
function maybeelse(type, value) { |
||||||
|
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); |
||||||
|
} |
||||||
|
function forspec(type) { |
||||||
|
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); |
||||||
|
} |
||||||
|
function forspec1(type) { |
||||||
|
if (type == "var") return cont(vardef, expect(";"), forspec2); |
||||||
|
if (type == ";") return cont(forspec2); |
||||||
|
if (type == "variable") return cont(formaybeinof); |
||||||
|
return pass(expression, expect(";"), forspec2); |
||||||
|
} |
||||||
|
function formaybeinof(_type, value) { |
||||||
|
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } |
||||||
|
return cont(maybeoperatorComma, forspec2); |
||||||
|
} |
||||||
|
function forspec2(type, value) { |
||||||
|
if (type == ";") return cont(forspec3); |
||||||
|
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } |
||||||
|
return pass(expression, expect(";"), forspec3); |
||||||
|
} |
||||||
|
function forspec3(type) { |
||||||
|
if (type != ")") cont(expression); |
||||||
|
} |
||||||
|
function functiondef(type, value) { |
||||||
|
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} |
||||||
|
if (type == "variable") {register(value); return cont(functiondef);} |
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext); |
||||||
|
} |
||||||
|
function funarg(type) { |
||||||
|
if (type == "spread") return cont(funarg); |
||||||
|
return pass(pattern, maybetype, maybedefault); |
||||||
|
} |
||||||
|
function className(type, value) { |
||||||
|
if (type == "variable") {register(value); return cont(classNameAfter);} |
||||||
|
} |
||||||
|
function classNameAfter(type, value) { |
||||||
|
if (value == "extends") return cont(expression, classNameAfter); |
||||||
|
if (type == "{") return cont(pushlex("}"), classBody, poplex); |
||||||
|
} |
||||||
|
function classBody(type, value) { |
||||||
|
if (type == "variable" || cx.style == "keyword") { |
||||||
|
if (value == "static") { |
||||||
|
cx.marked = "keyword"; |
||||||
|
return cont(classBody); |
||||||
|
} |
||||||
|
cx.marked = "property"; |
||||||
|
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody); |
||||||
|
return cont(functiondef, classBody); |
||||||
|
} |
||||||
|
if (value == "*") { |
||||||
|
cx.marked = "keyword"; |
||||||
|
return cont(classBody); |
||||||
|
} |
||||||
|
if (type == ";") return cont(classBody); |
||||||
|
if (type == "}") return cont(); |
||||||
|
} |
||||||
|
function classGetterSetter(type) { |
||||||
|
if (type != "variable") return pass(); |
||||||
|
cx.marked = "property"; |
||||||
|
return cont(); |
||||||
|
} |
||||||
|
function afterModule(type, value) { |
||||||
|
if (type == "string") return cont(statement); |
||||||
|
if (type == "variable") { register(value); return cont(maybeFrom); } |
||||||
|
} |
||||||
|
function afterExport(_type, value) { |
||||||
|
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } |
||||||
|
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } |
||||||
|
return pass(statement); |
||||||
|
} |
||||||
|
function afterImport(type) { |
||||||
|
if (type == "string") return cont(); |
||||||
|
return pass(importSpec, maybeFrom); |
||||||
|
} |
||||||
|
function importSpec(type, value) { |
||||||
|
if (type == "{") return contCommasep(importSpec, "}"); |
||||||
|
if (type == "variable") register(value); |
||||||
|
if (value == "*") cx.marked = "keyword"; |
||||||
|
return cont(maybeAs); |
||||||
|
} |
||||||
|
function maybeAs(_type, value) { |
||||||
|
if (value == "as") { cx.marked = "keyword"; return cont(importSpec); } |
||||||
|
} |
||||||
|
function maybeFrom(_type, value) { |
||||||
|
if (value == "from") { cx.marked = "keyword"; return cont(expression); } |
||||||
|
} |
||||||
|
function arrayLiteral(type) { |
||||||
|
if (type == "]") return cont(); |
||||||
|
return pass(expressionNoComma, maybeArrayComprehension); |
||||||
|
} |
||||||
|
function maybeArrayComprehension(type) { |
||||||
|
if (type == "for") return pass(comprehension, expect("]")); |
||||||
|
if (type == ",") return cont(commasep(maybeexpressionNoComma, "]")); |
||||||
|
return pass(commasep(expressionNoComma, "]")); |
||||||
|
} |
||||||
|
function comprehension(type) { |
||||||
|
if (type == "for") return cont(forspec, comprehension); |
||||||
|
if (type == "if") return cont(expression, comprehension); |
||||||
|
} |
||||||
|
|
||||||
|
function isContinuedStatement(state, textAfter) { |
||||||
|
return state.lastType == "operator" || state.lastType == "," || |
||||||
|
isOperatorChar.test(textAfter.charAt(0)) || |
||||||
|
/[,.]/.test(textAfter.charAt(0)); |
||||||
|
} |
||||||
|
|
||||||
|
// Interface
|
||||||
|
|
||||||
|
return { |
||||||
|
startState: function(basecolumn) { |
||||||
|
var state = { |
||||||
|
tokenize: tokenBase, |
||||||
|
lastType: "sof", |
||||||
|
cc: [], |
||||||
|
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), |
||||||
|
localVars: parserConfig.localVars, |
||||||
|
context: parserConfig.localVars && {vars: parserConfig.localVars}, |
||||||
|
indented: 0 |
||||||
|
}; |
||||||
|
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") |
||||||
|
state.globalVars = parserConfig.globalVars; |
||||||
|
return state; |
||||||
|
}, |
||||||
|
|
||||||
|
token: function(stream, state) { |
||||||
|
if (stream.sol()) { |
||||||
|
if (!state.lexical.hasOwnProperty("align")) |
||||||
|
state.lexical.align = false; |
||||||
|
state.indented = stream.indentation(); |
||||||
|
findFatArrow(stream, state); |
||||||
|
} |
||||||
|
if (state.tokenize != tokenComment && stream.eatSpace()) return null; |
||||||
|
var style = state.tokenize(stream, state); |
||||||
|
if (type == "comment") return style; |
||||||
|
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; |
||||||
|
return parseJS(state, style, type, content, stream); |
||||||
|
}, |
||||||
|
|
||||||
|
indent: function(state, textAfter) { |
||||||
|
if (state.tokenize == tokenComment) return CodeMirror.Pass; |
||||||
|
if (state.tokenize != tokenBase) return 0; |
||||||
|
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; |
||||||
|
// Kludge to prevent 'maybelse' from blocking lexical scope pops
|
||||||
|
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { |
||||||
|
var c = state.cc[i]; |
||||||
|
if (c == poplex) lexical = lexical.prev; |
||||||
|
else if (c != maybeelse) break; |
||||||
|
} |
||||||
|
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; |
||||||
|
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") |
||||||
|
lexical = lexical.prev; |
||||||
|
var type = lexical.type, closing = firstChar == type; |
||||||
|
|
||||||
|
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); |
||||||
|
else if (type == "form" && firstChar == "{") return lexical.indented; |
||||||
|
else if (type == "form") return lexical.indented + indentUnit; |
||||||
|
else if (type == "stat") |
||||||
|
return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); |
||||||
|
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) |
||||||
|
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); |
||||||
|
else if (lexical.align) return lexical.column + (closing ? 0 : 1); |
||||||
|
else return lexical.indented + (closing ? 0 : indentUnit); |
||||||
|
}, |
||||||
|
|
||||||
|
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, |
||||||
|
blockCommentStart: jsonMode ? null : "/*", |
||||||
|
blockCommentEnd: jsonMode ? null : "*/", |
||||||
|
lineComment: jsonMode ? null : "//", |
||||||
|
fold: "brace", |
||||||
|
closeBrackets: "()[]{}''\"\"``", |
||||||
|
|
||||||
|
helperType: jsonMode ? "json" : "javascript", |
||||||
|
jsonldMode: jsonldMode, |
||||||
|
jsonMode: jsonMode |
||||||
|
}; |
||||||
|
}); |
||||||
|
|
||||||
|
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); |
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/javascript", "javascript"); |
||||||
|
CodeMirror.defineMIME("text/ecmascript", "javascript"); |
||||||
|
CodeMirror.defineMIME("application/javascript", "javascript"); |
||||||
|
CodeMirror.defineMIME("application/x-javascript", "javascript"); |
||||||
|
CodeMirror.defineMIME("application/ecmascript", "javascript"); |
||||||
|
CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); |
||||||
|
CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); |
||||||
|
CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); |
||||||
|
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); |
||||||
|
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); |
||||||
|
|
||||||
|
}); |
@ -1,3 +0,0 @@ |
|||||||
browserify worker_src/worker.js -o worker/wumbo.js |
|
||||||
cat worker_src/madeline.js worker/wumbo.js > worker/worker.js |
|
||||||
rm worker/wumbo.js |
|
@ -0,0 +1,79 @@ |
|||||||
|
#wow { |
||||||
|
box-shadow: 0px 0px 20px 0px rgba(0,0,0,.2); |
||||||
|
background-color: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
#splash { |
||||||
|
border-bottom: solid 1px #ddd; |
||||||
|
/*background-color: #222*/ |
||||||
|
} |
||||||
|
|
||||||
|
#desc { |
||||||
|
color: #444; |
||||||
|
} |
||||||
|
|
||||||
|
.header { |
||||||
|
background-color: #27C6F9; |
||||||
|
} |
||||||
|
|
||||||
|
#marterial { |
||||||
|
background: linear-gradient(#27C6F9 80%, #0CB5EB 100%); |
||||||
|
} |
||||||
|
|
||||||
|
#runbutton { |
||||||
|
color: #27C6F9; |
||||||
|
cursor: pointer; |
||||||
|
-webkit-transition: all 0.7s ease; |
||||||
|
transition: all 0.7s ease; |
||||||
|
} |
||||||
|
|
||||||
|
#runbutton:hover { |
||||||
|
text-shadow: 0px 0px 10px #27C6F9; |
||||||
|
} |
||||||
|
|
||||||
|
#wow { |
||||||
|
box-shadow: 0px 0px 20px -2px rgba(0,0,0,.2); |
||||||
|
} |
||||||
|
|
||||||
|
#hint { |
||||||
|
font-size: 10px; |
||||||
|
color: #aaa; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
a { |
||||||
|
color: #f90; |
||||||
|
} |
||||||
|
|
||||||
|
button { |
||||||
|
color: #000; |
||||||
|
background: #fff; |
||||||
|
border-radius: 5px; |
||||||
|
border: solid 1px #fff; |
||||||
|
} |
||||||
|
|
||||||
|
button:hover { |
||||||
|
background: rgba(255,255,255,1); |
||||||
|
border: solid 1px #ddd; |
||||||
|
} |
||||||
|
|
||||||
|
@media (max-width: 914px) { |
||||||
|
button{ |
||||||
|
color: #fff; |
||||||
|
background-color: rgba(0,0,0,0) |
||||||
|
} |
||||||
|
|
||||||
|
button:hover { |
||||||
|
background: rgba(255,255,255,.3); |
||||||
|
border: solid 1px #fff; |
||||||
|
} |
||||||
|
|
||||||
|
#desc { |
||||||
|
color: rgba(255,255,255,.9); |
||||||
|
} |
||||||
|
|
||||||
|
#splash { |
||||||
|
background-color: #27C6F9; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,210 @@ |
|||||||
|
.fullscreen { |
||||||
|
width:100%; |
||||||
|
min-height: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
#runwrap { |
||||||
|
position: relative; |
||||||
|
right:0px; |
||||||
|
width: 100%; |
||||||
|
height: 0px; |
||||||
|
text-align: right; |
||||||
|
background: green; |
||||||
|
z-index: 2; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#run, #running { |
||||||
|
width: 100%; |
||||||
|
height: 42px; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
#run { |
||||||
|
display: none |
||||||
|
} |
||||||
|
|
||||||
|
#runbutton { |
||||||
|
padding-top: 6px; |
||||||
|
padding-bottom: 10px; |
||||||
|
font-weight: 500; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
a { |
||||||
|
text-decoration: none; |
||||||
|
/*font-weight: bold;*/ |
||||||
|
} |
||||||
|
|
||||||
|
#display { |
||||||
|
position: absolute; |
||||||
|
/*background: rgba(0,0,255,.1);*/ |
||||||
|
} |
||||||
|
|
||||||
|
#marterial { |
||||||
|
position: absolute; |
||||||
|
width: 100%; |
||||||
|
height: 90px; |
||||||
|
z-index: -1; |
||||||
|
} |
||||||
|
|
||||||
|
#out { |
||||||
|
padding: 10px; |
||||||
|
padding-bottom: 0px; |
||||||
|
text-align: center; |
||||||
|
font-family: monospace; |
||||||
|
} |
||||||
|
|
||||||
|
#hint { |
||||||
|
text-align: left; |
||||||
|
padding-left: 14px |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#prog { |
||||||
|
width: 400px; |
||||||
|
max-width: 100%; |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
#drag { |
||||||
|
padding: 10px; |
||||||
|
/*padding-top: 0px;*/ |
||||||
|
text-align: center |
||||||
|
} |
||||||
|
|
||||||
|
#logo { |
||||||
|
text-align: center; |
||||||
|
padding-top: 5%; |
||||||
|
} |
||||||
|
|
||||||
|
#to_ocr { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
#wow { |
||||||
|
border-radius: 5px; |
||||||
|
overflow: hidden; |
||||||
|
width:500px; |
||||||
|
margin-top: 10px; |
||||||
|
text-align: left |
||||||
|
} |
||||||
|
|
||||||
|
#canvas { |
||||||
|
margin-left: auto; |
||||||
|
margin-right: auto; |
||||||
|
pointer-events:none; |
||||||
|
z-index: 0; |
||||||
|
background-image: url(../img/logowhite.png); |
||||||
|
background-size: cover; |
||||||
|
} |
||||||
|
|
||||||
|
#splash { |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
#desc { |
||||||
|
text-align: left; |
||||||
|
font-size: 18px; |
||||||
|
} |
||||||
|
|
||||||
|
#demo { |
||||||
|
} |
||||||
|
|
||||||
|
#notconvinced { |
||||||
|
max-width: 960; |
||||||
|
|
||||||
|
margin-left: auto; |
||||||
|
margin-right: auto; |
||||||
|
margin-top: 8%; |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
.randombold { |
||||||
|
font-size: 18px; |
||||||
|
/*font-family: Georgia;*/ |
||||||
|
letter-spacing: .8px; |
||||||
|
line-height: 37px; |
||||||
|
} |
||||||
|
|
||||||
|
.rant { |
||||||
|
padding-left: 8%; |
||||||
|
padding-right: 8%; |
||||||
|
} |
||||||
|
/*#editor { |
||||||
|
border-radius: 5px 5px 0px 0px; |
||||||
|
} |
||||||
|
*/ |
||||||
|
#code { |
||||||
|
text-align: center; |
||||||
|
width: 335px; |
||||||
|
border-radius: 5px; |
||||||
|
margin-right: 40px; |
||||||
|
margin-left: 40px; |
||||||
|
margin-top: 140px; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#fork { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
border: 0; |
||||||
|
width: 149px; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#two { |
||||||
|
width: 100%; |
||||||
|
paddin-left: 8%; |
||||||
|
paddin-right: 8%; |
||||||
|
display: flex; |
||||||
|
flex-wrap: wrap; |
||||||
|
justify-content: center; |
||||||
|
margin-bottom: 8%; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body { |
||||||
|
padding: 0px; |
||||||
|
margin: 0px; |
||||||
|
font-family: Lato;/*, Helvetica, Arial, sans-serif;*/ |
||||||
|
font-weight: 300; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
button { |
||||||
|
|
||||||
|
height: 60px; |
||||||
|
width: 240px; |
||||||
|
|
||||||
|
margin-top: 10px; |
||||||
|
|
||||||
|
font: inherit; |
||||||
|
font-size: 30px; |
||||||
|
|
||||||
|
-webkit-transition: all 0.7s ease; |
||||||
|
transition: all 0.7s ease; |
||||||
|
|
||||||
|
outline: 0; |
||||||
|
} |
||||||
|
|
||||||
|
button:hover { |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
@media (max-width: 914px) { |
||||||
|
#marterial { |
||||||
|
height: 300px; |
||||||
|
} |
||||||
|
|
||||||
|
#code { |
||||||
|
margin-top: 20px; |
||||||
|
margin-bottom: 20px |
||||||
|
} |
||||||
|
} |
@ -1,24 +0,0 @@ |
|||||||
<canvas id="c"></canvas> |
|
||||||
<script type="text/javascript" src="./lib/Tesseract.js"></script> |
|
||||||
<script type="text/javascript"> |
|
||||||
var canvas = document.getElementById('c') |
|
||||||
canvas.width = 400 |
|
||||||
canvas.height = 400 |
|
||||||
var ctx = canvas.getContext('2d'); |
|
||||||
ctx.font = '30px "Arial Black"' |
|
||||||
ctx.fillText('Hell0 World', 100, 40) |
|
||||||
// ctx.fillText("囚犯離奇掙脫囚犯離奇掙脫", 100, 40) |
|
||||||
ctx.font = '30px "Times New Roman"' |
|
||||||
ctx.fillText('from beyond', 100, 80) |
|
||||||
// ctx.fillText('2小時可換乘2次2小時可換乘2次', 100, 80) |
|
||||||
ctx.font = '30px sans-serif' |
|
||||||
ctx.fillText('the Cosmic Void', 100, 120) |
|
||||||
|
|
||||||
Tesseract.recognize(canvas,{ |
|
||||||
tessedit_char_blacklist:'e', |
|
||||||
progress: function(e){ |
|
||||||
console.log(e) |
|
||||||
} |
|
||||||
}).then( function(d){ console.log(d) } ) |
|
||||||
|
|
||||||
</script> |
|
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 1.6 MiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 953 KiB |
After Width: | Height: | Size: 357 KiB |
@ -0,0 +1,208 @@ |
|||||||
|
<html> |
||||||
|
<head> |
||||||
|
<title>Wau Demo</title> |
||||||
|
<link rel="stylesheet" type="text/css" href="./css/wau.css"> |
||||||
|
<link rel="stylesheet" type="text/css" href="./css/color.css"> |
||||||
|
|
||||||
|
<script src="codemirror/codemirror.js"></script> |
||||||
|
<link rel="stylesheet" href="codemirror/codemirror.css"> |
||||||
|
<script src="codemirror/javascript.js"></script> |
||||||
|
|
||||||
|
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Lato:300,400' rel='stylesheet' type='text/css'> |
||||||
|
|
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<!-- <a href="https://github.com/you"><img id="fork" src="img/fork.png" alt="Fork me on GitHub"></a> --> |
||||||
|
|
||||||
|
<div id="splash" class="fullscreen"> |
||||||
|
<div id="logo" class="header"> |
||||||
|
<canvas id="canvas"></canvas> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div id ="marterial" class="header"></div> |
||||||
|
|
||||||
|
<div id="two"> |
||||||
|
<div id="code"> |
||||||
|
<div id="desc"> |
||||||
|
Tesseract.js is a <b>pure javascript</b> version of the <a href="https://github.com/tesseract-ocr/Tesseract">Tesseract OCR Engine</a>. It can recognize <b>over 20 languages</b>, including <b>English</b>, <b>Chinese</b>, and <b>Meme</b>. |
||||||
|
</div> |
||||||
|
<br> |
||||||
|
<button>Download</button><br> |
||||||
|
<a href="https://github.com/naptha/tesseract.js"><button>View on Github</button></a> |
||||||
|
</div> |
||||||
|
<div id="wow"> |
||||||
|
|
||||||
|
<div id='editor'></div> |
||||||
|
<div id="hint"> |
||||||
|
Hint: you can, like, edit this code yo |
||||||
|
</div> |
||||||
|
<div id ="running"> |
||||||
|
<div id="out">Initializing Magic...</div> |
||||||
|
<progress id="prog" value="0" max="1"></progress> |
||||||
|
</div> |
||||||
|
<div id = "run"> |
||||||
|
|
||||||
|
<div id="runbutton">Run Code</div> |
||||||
|
</div> |
||||||
|
<canvas id="display"></canvas> |
||||||
|
<img src="img/poem.png" width = "500px" id ="to_ocr"> |
||||||
|
<div id="drag"> |
||||||
|
<a href="">New Image</a> (or drop an image on this page) |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
<div id="notconvinced" class="fullscreen"> |
||||||
|
<div class="rant randombold"> |
||||||
|
"Last time I got here, before I <b>even</b> arrived, they had ‘fuck <b>Kanye’</b> on the motherfuckin’ <b>port-a-potties.</b> But this year, we gon’ piss on ‘em, on they motherfuckin’ port-a-potties. How many of <b>y'all</b> don't give a fuck about <b>what</b> the press <b>say?</b> It's 2014. College Dropout came out 2004. I want y'all to know, <b>every</b> time I go to the studio, every time I <b>do</b> <b>an</b> <b>interview,</b> every time I make a motherfuckin' <b>t-shirt,</b> the thing <b>I</b> do, I give it <b>everything</b> <b>I</b> got. And when I talk that shit, it's so that <b>you</b> can talk that shit. If you a fan of me, you a fan of your motherfuckin' self. You can do something that'll change the world. Look at how they try to make me look. They <b>try</b> to make me look crazy.", |
||||||
|
<b></b> "I <b>need</b> a new cool. <b>What's</b> the new shit out? What's the new shit <b>out</b> <b>with</b> the most commercials at the Super Bowl? <b>Let's</b> <b>just</b> stop the music and play a Bruno Mars song right <b>now,</b> how about that? <b>They</b> told me I would never play at the Super Bowl. They told me I could never play at the Super Bowl. Not until I'm <b>super</b> old. Not until I'm <b>super</b> old... They told me I would never play at the <b>Super</b> Bowl. They told <b>me</b> I would never play at the <b>Super</b> <b>Bowl,</b> at least not until I'm super old. So I think it's time–hold up, f—k that toast.", |
||||||
|
<b></b> "I know people get mad at me when I compare myself, but that's the only way I <b>can</b> explain what <b>my</b> aspirations are. When I'm talkin' 'bout Walt Disney, when I'm talkin' 'bout Howard Hughes, when I'm talkin' 'bout Henry Ford, when I'm talkin' 'bout Beethoven, when I talk about <b>Mozart,</b> when I talk about Shakespeare, and they all had their time on this earth. And I'm only 37. And right now I'm rockin' to 90,000, of y'all motherfuckers <b>right</b> now. So I ain't goin' at anybody on the radio. I'm goin' <b>after</b> Shakespeare. I'm <b>goin'</b> after <b>Walt</b> Disney. I'm <b>going</b> after <b>Howard</b> Hughes. I'm going after David Stern. I'm goin' <b>after</b> Henry Ford. I'm going <b>after</b> Elon Musk. Okay, he is living, but he's my boy.", |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<!-- |
||||||
|
<script src="./core/temple.js"></script> |
||||||
|
|
||||||
|
--> |
||||||
|
<script src="https://rawgit.com/naptha/tesseract.js/master/lib/Tesseract.js"></script> |
||||||
|
|
||||||
|
<script> |
||||||
|
var prog = document.getElementById('prog') |
||||||
|
var out = document.getElementById('out') |
||||||
|
|
||||||
|
var disp = document.getElementById('display') |
||||||
|
var dctx = disp.getContext('2d') |
||||||
|
disp.width = 0 |
||||||
|
disp.height = 0 |
||||||
|
|
||||||
|
document.getElementById('runbutton').onclick = function(){ |
||||||
|
setrunning(0) |
||||||
|
run(myCodeMirror) |
||||||
|
} |
||||||
|
|
||||||
|
function show_progress(p){ |
||||||
|
|
||||||
|
if(p.loaded_lang_model) prog.value = p.loaded_lang_model |
||||||
|
if(p.recognized) prog.value = p.recognized |
||||||
|
setrunning(p.recognized) |
||||||
|
out.innerText = JSON.stringify(p) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function setrunning(v){ |
||||||
|
if (v == 1) { |
||||||
|
document.getElementById('running').style.display = 'none' |
||||||
|
document.getElementById('run').style.display = 'block' |
||||||
|
// out.style.visibility = 'hidden' |
||||||
|
} |
||||||
|
else { |
||||||
|
document.getElementById('running').style.display = 'block' |
||||||
|
document.getElementById('run').style.display = 'none' |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function display(result) { |
||||||
|
console.log(result) |
||||||
|
|
||||||
|
disp.width = document.getElementById('to_ocr').naturalWidth |
||||||
|
disp.height = document.getElementById('to_ocr').naturalHeight |
||||||
|
|
||||||
|
disp.style.width = document.getElementById('to_ocr').offsetWidth |
||||||
|
disp.style.height = document.getElementById('to_ocr').offsetHeight |
||||||
|
|
||||||
|
|
||||||
|
dctx.shadowColor = "#fff" |
||||||
|
dctx.shadowOffsetX = 0; |
||||||
|
dctx.shadowOffsetY = 0; |
||||||
|
dctx.shadowBlur = 10; |
||||||
|
|
||||||
|
var m = result.words.map(function(w){ |
||||||
|
|
||||||
|
var b = w.bbox |
||||||
|
|
||||||
|
var k = (function(){ |
||||||
|
|
||||||
|
dctx.font = '20px Comic Sans MS' |
||||||
|
dctx.font = 20*(b.x1-b.x0)/dctx.measureText(w.text).width+"px Comic Sans MS" |
||||||
|
|
||||||
|
// dctx.fillStyle="rgba(255,255,255,.01)" |
||||||
|
// dctx.fillRect(b.x0,b.y0,b.x1-b.x0, b.y1-b.y0) |
||||||
|
dctx.fillStyle="rgba(255,0,255,.1)" |
||||||
|
dctx.fillText(w.text, b.x0, w.baseline.y0); |
||||||
|
|
||||||
|
// dctx.strokeStyle = "rgba(255,255,255,.1)" |
||||||
|
// dctx.strokeText(w.text, b.x0, w.baseline.y0); |
||||||
|
}) |
||||||
|
|
||||||
|
// k() |
||||||
|
return k |
||||||
|
}) |
||||||
|
|
||||||
|
var times = 0 |
||||||
|
function draw(i){ |
||||||
|
times++ |
||||||
|
for (var j = 0; j < i; j++) { |
||||||
|
m[j]() |
||||||
|
}; |
||||||
|
if(times<200){ |
||||||
|
setTimeout(function(){ |
||||||
|
if(i+1<m.length){ |
||||||
|
draw(i+1) |
||||||
|
} |
||||||
|
else { |
||||||
|
draw(i) |
||||||
|
} |
||||||
|
},10) |
||||||
|
} |
||||||
|
else{ |
||||||
|
console.log('done') |
||||||
|
} |
||||||
|
} |
||||||
|
draw(0) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
window.onresize = function() { |
||||||
|
disp.style.width = document.getElementById('to_ocr').offsetWidth |
||||||
|
disp.style.height = document.getElementById('to_ocr').offsetHeight |
||||||
|
} |
||||||
|
|
||||||
|
function run(c){ |
||||||
|
eval(c.getValue()) |
||||||
|
} |
||||||
|
|
||||||
|
var val = |
||||||
|
"var img = document.querySelector('img#to_ocr')\n\ |
||||||
|
\n\ |
||||||
|
Tesseract\n\ |
||||||
|
.recognize( img, {progress: show_progress} )\n\ |
||||||
|
.then( display )" |
||||||
|
|
||||||
|
var myCodeMirror = CodeMirror(document.getElementById('editor'),{ |
||||||
|
// lineNumbers: true, |
||||||
|
viewportMargin: Infinity, |
||||||
|
value: val |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var img = document.getElementById('to_ocr') |
||||||
|
|
||||||
|
if (img.complete) { |
||||||
|
run(myCodeMirror) |
||||||
|
} else{ |
||||||
|
img.onload = function(){ |
||||||
|
run(myCodeMirror) |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<script src="animation/raf.js"></script> |
||||||
|
<script src="animation/mouse.js"></script> |
||||||
|
<script src="animation/dimensions.js"></script> |
||||||
|
<script src="animation/main.js"></script> |
||||||
|
</body> |
||||||
|
</html> |
@ -1,79 +0,0 @@ |
|||||||
var Tesseract = {} |
|
||||||
|
|
||||||
Tesseract.recognize = function(image, options, callback){ |
|
||||||
var lang = options.lang |
|
||||||
if(typeof lang === "undefined"){ |
|
||||||
lang = 'eng' |
|
||||||
} |
|
||||||
|
|
||||||
if (typeof options === 'string') { |
|
||||||
lang = options |
|
||||||
options = {} |
|
||||||
} |
|
||||||
|
|
||||||
if (typeof options === "function") { |
|
||||||
callback = options |
|
||||||
options = {} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
if(image.getContext){ |
|
||||||
image = image.getContext('2d'); |
|
||||||
}else if(image.tagName == "IMG" || image.tagName == "VIDEO"){ |
|
||||||
var c = document.createElement('canvas'); |
|
||||||
if(image.tagName == "IMG"){ |
|
||||||
c.width = image.naturalWidth; |
|
||||||
c.height = image.naturalHeight; |
|
||||||
}else if(image.tagName == "VIDEO"){ |
|
||||||
c.width = image.videoWidth; |
|
||||||
c.height = image.videoHeight; |
|
||||||
} |
|
||||||
var ctx = c.getContext('2d'); |
|
||||||
ctx.drawImage(image, 0, 0); |
|
||||||
image = ctx; |
|
||||||
} |
|
||||||
if(image.getImageData) image = image.getImageData(0, 0, image.canvas.width, image.canvas.height); |
|
||||||
|
|
||||||
|
|
||||||
var blob = new Blob(["importScripts('https://cdn.rawgit.com/naptha/tesseract.js/master/worker/worker.js');"]); |
|
||||||
|
|
||||||
var worker = new Worker(window.URL.createObjectURL(blob)); |
|
||||||
|
|
||||||
var progress = (function(){ |
|
||||||
if(typeof options.progress === 'function'){ |
|
||||||
var p = options.progress |
|
||||||
delete options.progress |
|
||||||
return p |
|
||||||
} |
|
||||||
return function(){} |
|
||||||
})() |
|
||||||
|
|
||||||
|
|
||||||
if(typeof callback === "function"){ |
|
||||||
worker.onmessage = function(e){ |
|
||||||
if(e.data.progress){ |
|
||||||
progress(e.data.progress) |
|
||||||
} |
|
||||||
else{ |
|
||||||
callback(e.data.err, e.data.result) |
|
||||||
} |
|
||||||
} |
|
||||||
worker.postMessage({image: image, lang: lang}) |
|
||||||
} |
|
||||||
else { |
|
||||||
return new Promise(function(resolve, reject){ |
|
||||||
worker.onmessage = function(e){ |
|
||||||
if(e.data.progress){ |
|
||||||
progress(e.data.progress) |
|
||||||
} |
|
||||||
else if(e.data.err){ |
|
||||||
reject(e.data.err) |
|
||||||
} |
|
||||||
else { |
|
||||||
resolve(e.data.result) |
|
||||||
} |
|
||||||
} |
|
||||||
worker.postMessage({image: image, lang: lang, options: options}) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
@ -1,24 +0,0 @@ |
|||||||
{ |
|
||||||
"name": "tesseract.js", |
|
||||||
"version": "1.0.0", |
|
||||||
"description": "", |
|
||||||
"main": "Tesseract.js", |
|
||||||
"dependencies": { |
|
||||||
"level-js": "^2.1.6", |
|
||||||
"pako": "^0.2.7" |
|
||||||
}, |
|
||||||
"devDependencies": {}, |
|
||||||
"scripts": { |
|
||||||
"test": "echo \"Error: no test specified\" && exit 1" |
|
||||||
}, |
|
||||||
"repository": { |
|
||||||
"type": "git", |
|
||||||
"url": "https://github.com/naptha/tesseract.js.git" |
|
||||||
}, |
|
||||||
"author": "", |
|
||||||
"license": "ISC", |
|
||||||
"bugs": { |
|
||||||
"url": "https://github.com/naptha/tesseract.js/issues" |
|
||||||
}, |
|
||||||
"homepage": "https://github.com/naptha/tesseract.js" |
|
||||||
} |
|
@ -1,394 +0,0 @@ |
|||||||
var db = (require('level-js'))('./tessdata') |
|
||||||
// var db = leveljs('./tessdata')
|
|
||||||
|
|
||||||
var filesizes = {"afr": 1079573, "ara": 1701536, "aze": 1420865, "bel": 1276820, "ben": 6772012, "bul": 1605615, "cat": 1652368, "ces": 1035441, "chi_sim": 17710414, "chi_tra": 24717749, "chr": 320649, "dan-frak": 677656, "dan": 1972936, "deu-frak": 822644, "deu": 991656, "ell": 859719, "eng": 9453554, "enm": 619254, "epo": 1241212, "equ": 821130, "est": 1905040, "eus": 1641190, "fin": 979418, "fra": 1376221, "frk": 5912963, "frm": 5147082, "glg": 1674938, "grc": 3012615, "heb": 1051501, "hin": 6590065, "hrv": 1926995, "hun": 3074473, "ind": 1874776, "isl": 1634041, "ita": 948593, "ita_old": 3436571, "jpn": 13507168, "kan": 4390317, "kor": 5353098, "lav": 1843944, "lit": 1779240, "mal": 5966263, "meme": 88453, "mkd": 1163087, "mlt": 1463001, "msa": 1665427, "nld": 1134708, "nor": 2191610, "osd": 4274649, "pol": 7024662, "por": 909359, "ron": 915680, "rus": 5969957, "slk-frak": 289885, "slk": 2217342, "slv": 1611338, "spa": 883170, "spa_old": 5647453, "sqi": 1667041, "srp": 1770244, "swa": 757916, "swe": 2451917, "tam": 3498763, "tel": 5795246, "tgl": 1496256, "tha": 3811136, "tur": 3563264, "ukr": 937566, "vie": 2195922} |
|
||||||
|
|
||||||
var pako = require('pako') |
|
||||||
|
|
||||||
var recognize = (function createTesseractInstance(){ |
|
||||||
|
|
||||||
var Module = Tesseract304({ |
|
||||||
TOTAL_MEMORY: 6*16777216, //must be a multiple of 10 megabytes
|
|
||||||
TesseractProgress: function(percent){ |
|
||||||
postMessage({ |
|
||||||
'progress': { |
|
||||||
'recognized': Math.max(0,(percent-30)/70) |
|
||||||
} |
|
||||||
}) |
|
||||||
}//,
|
|
||||||
// onRuntimeInitialized: function(){
|
|
||||||
// console.log('wau')
|
|
||||||
// }
|
|
||||||
}) |
|
||||||
|
|
||||||
var base = new Module.TessBaseAPI() |
|
||||||
var loaded_langs = [] |
|
||||||
var loadLanguage = function(lang, cb){ // NodeJS style callback
|
|
||||||
if(loaded_langs.indexOf(lang) != -1){ |
|
||||||
cb(null, lang) |
|
||||||
} |
|
||||||
else{ |
|
||||||
Module.FS_createPath("/","tessdata",true,true) |
|
||||||
|
|
||||||
var downloadlang = function(shouldcache){ |
|
||||||
postMessage({ |
|
||||||
'progress': { |
|
||||||
'loaded_lang_model': 0, |
|
||||||
cached: false, |
|
||||||
requesting: true |
|
||||||
} |
|
||||||
}) |
|
||||||
var xhr = new XMLHttpRequest(); |
|
||||||
xhr.open('GET', 'https://cdn.rawgit.com/naptha/tessdata/gh-pages/3.02/'+lang+'.traineddata.gz', true); |
|
||||||
xhr.responseType = 'arraybuffer'; |
|
||||||
xhr.onerror = function(){ cb(xhr, null) } |
|
||||||
xhr.onprogress = function(e){ |
|
||||||
postMessage({ |
|
||||||
'progress': { |
|
||||||
'loaded_lang_model': e.loaded/filesizes[lang], |
|
||||||
cached: false |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
xhr.onload = function(){ |
|
||||||
if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { |
|
||||||
postMessage({ |
|
||||||
'progress': 'unzipping_lang_model' |
|
||||||
}) |
|
||||||
|
|
||||||
var response = new Uint8Array(xhr.response) |
|
||||||
|
|
||||||
var data = pako.inflate(response) |
|
||||||
postMessage({ |
|
||||||
'progress': 'unzipped_lang_model' |
|
||||||
}) |
|
||||||
|
|
||||||
Module.FS_createDataFile('tessdata', lang +".traineddata", data, true, false); |
|
||||||
|
|
||||||
if(shouldcache){ |
|
||||||
db.put(lang, response, function(err){ |
|
||||||
console.log('cached lang') |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
loaded_langs.push(lang) |
|
||||||
|
|
||||||
cb(null, lang) |
|
||||||
} else cb(xhr, null); |
|
||||||
} |
|
||||||
xhr.send(null) |
|
||||||
} |
|
||||||
|
|
||||||
db.open({compression: false},function(err){ |
|
||||||
if (err) { |
|
||||||
downloadlang(false) |
|
||||||
} |
|
||||||
else { |
|
||||||
db.get(lang, function (err, value) { |
|
||||||
|
|
||||||
// err = true
|
|
||||||
|
|
||||||
if (err) { |
|
||||||
downloadlang(true) |
|
||||||
} |
|
||||||
else { |
|
||||||
value = pako.inflate(value) |
|
||||||
|
|
||||||
postMessage({ |
|
||||||
'progress': { |
|
||||||
loaded_lang_model:1, |
|
||||||
cached: true |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
Module.FS_createDataFile('tessdata', lang +".traineddata", value, true, false); |
|
||||||
loaded_langs.push(lang) |
|
||||||
cb(null, lang) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
function circularize(page){ |
|
||||||
page.paragraphs = [] |
|
||||||
page.lines = [] |
|
||||||
page.words = [] |
|
||||||
page.symbols = [] |
|
||||||
|
|
||||||
page.blocks.forEach(function(block){ |
|
||||||
block.page = page; |
|
||||||
|
|
||||||
block.lines = [] |
|
||||||
block.words = [] |
|
||||||
block.symbols = [] |
|
||||||
|
|
||||||
block.paragraphs.forEach(function(para){ |
|
||||||
para.block = block; |
|
||||||
para.page = page; |
|
||||||
|
|
||||||
para.words = [] |
|
||||||
para.symbols = [] |
|
||||||
|
|
||||||
para.lines.forEach(function(line){ |
|
||||||
line.paragraph = para; |
|
||||||
line.block = block; |
|
||||||
line.page = page; |
|
||||||
|
|
||||||
line.symbols = [] |
|
||||||
|
|
||||||
line.words.forEach(function(word){ |
|
||||||
word.line = line; |
|
||||||
word.paragraph = para; |
|
||||||
word.block = block; |
|
||||||
word.page = page; |
|
||||||
word.symbols.forEach(function(sym){ |
|
||||||
sym.word = word; |
|
||||||
sym.line = line; |
|
||||||
sym.paragraph = para; |
|
||||||
sym.block = block; |
|
||||||
sym.page = page; |
|
||||||
|
|
||||||
sym.line.symbols.push(sym) |
|
||||||
sym.paragraph.symbols.push(sym) |
|
||||||
sym.block.symbols.push(sym) |
|
||||||
sym.page.symbols.push(sym) |
|
||||||
}) |
|
||||||
word.paragraph.words.push(word) |
|
||||||
word.block.words.push(word) |
|
||||||
word.page.words.push(word) |
|
||||||
}) |
|
||||||
line.block.lines.push(line) |
|
||||||
line.page.lines.push(line) |
|
||||||
}) |
|
||||||
para.page.paragraphs.push(para) |
|
||||||
}) |
|
||||||
}) |
|
||||||
return page |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function DumpLiterallyEverything(){ |
|
||||||
var ri = base.GetIterator(); |
|
||||||
var blocks = []; |
|
||||||
var block, para, textline, word, symbol; |
|
||||||
|
|
||||||
function enumToString(value, prefix){ |
|
||||||
return (Object.keys(Module) |
|
||||||
.filter(function(e){ return e.startsWith(prefix + '_') }) |
|
||||||
.filter(function(e){ return Module[e] === value }) |
|
||||||
.map(function(e){ return e.slice(prefix.length + 1) })[0]) |
|
||||||
} |
|
||||||
|
|
||||||
ri.Begin() |
|
||||||
do { |
|
||||||
if(ri.IsAtBeginningOf(Module.RIL_BLOCK)){ |
|
||||||
var poly = ri.BlockPolygon(); |
|
||||||
var polygon = null; |
|
||||||
// BlockPolygon() returns null when automatic page segmentation is off
|
|
||||||
if(Module.getPointer(poly) > 0){ |
|
||||||
var n = poly.get_n(), |
|
||||||
px = poly.get_x(), |
|
||||||
py = poly.get_y(), |
|
||||||
polygon = []; |
|
||||||
for(var i = 0; i < n; i++){ |
|
||||||
polygon.push([px.getValue(i), py.getValue(i)]); |
|
||||||
} |
|
||||||
Module._ptaDestroy(Module.getPointer(poly)); |
|
||||||
} |
|
||||||
|
|
||||||
block = { |
|
||||||
paragraphs: [], |
|
||||||
|
|
||||||
text: ri.GetUTF8Text(Module.RIL_BLOCK), |
|
||||||
confidence: ri.Confidence(Module.RIL_BLOCK), |
|
||||||
baseline: ri.getBaseline(Module.RIL_BLOCK), |
|
||||||
bbox: ri.getBoundingBox(Module.RIL_BLOCK), |
|
||||||
|
|
||||||
blocktype: enumToString(ri.BlockType(), 'PT'), |
|
||||||
polygon: polygon |
|
||||||
} |
|
||||||
blocks.push(block) |
|
||||||
} |
|
||||||
if(ri.IsAtBeginningOf(Module.RIL_PARA)){ |
|
||||||
para = { |
|
||||||
lines: [], |
|
||||||
|
|
||||||
text: ri.GetUTF8Text(Module.RIL_PARA), |
|
||||||
confidence: ri.Confidence(Module.RIL_PARA), |
|
||||||
baseline: ri.getBaseline(Module.RIL_PARA), |
|
||||||
bbox: ri.getBoundingBox(Module.RIL_PARA), |
|
||||||
|
|
||||||
is_ltr: !!ri.ParagraphIsLtr() |
|
||||||
} |
|
||||||
block.paragraphs.push(para) |
|
||||||
} |
|
||||||
if(ri.IsAtBeginningOf(Module.RIL_TEXTLINE)){ |
|
||||||
textline = { |
|
||||||
words: [], |
|
||||||
|
|
||||||
text: ri.GetUTF8Text(Module.RIL_TEXTLINE), |
|
||||||
confidence: ri.Confidence(Module.RIL_TEXTLINE), |
|
||||||
baseline: ri.getBaseline(Module.RIL_TEXTLINE), |
|
||||||
bbox: ri.getBoundingBox(Module.RIL_TEXTLINE) |
|
||||||
} |
|
||||||
para.lines.push(textline) |
|
||||||
} |
|
||||||
if(ri.IsAtBeginningOf(Module.RIL_WORD)){ |
|
||||||
var fontInfo = ri.getWordFontAttributes(), |
|
||||||
wordDir = ri.WordDirection(); |
|
||||||
word = { |
|
||||||
symbols: [], |
|
||||||
choices: [], |
|
||||||
|
|
||||||
text: ri.GetUTF8Text(Module.RIL_WORD), |
|
||||||
confidence: ri.Confidence(Module.RIL_WORD), |
|
||||||
baseline: ri.getBaseline(Module.RIL_WORD), |
|
||||||
bbox: ri.getBoundingBox(Module.RIL_WORD), |
|
||||||
|
|
||||||
is_numeric: !!ri.WordIsNumeric(), |
|
||||||
in_dictionary: !!ri.WordIsFromDictionary(), |
|
||||||
direction: enumToString(wordDir, 'DIR'), |
|
||||||
language: ri.WordRecognitionLanguage(), |
|
||||||
|
|
||||||
is_bold: fontInfo.is_bold, |
|
||||||
is_italic: fontInfo.is_italic, |
|
||||||
is_underlined: fontInfo.is_underlined, |
|
||||||
is_monospace: fontInfo.is_monospace, |
|
||||||
is_serif: fontInfo.is_serif, |
|
||||||
is_smallcaps: fontInfo.is_smallcaps, |
|
||||||
font_size: fontInfo.pointsize, |
|
||||||
font_id: fontInfo.font_id, |
|
||||||
font_name: fontInfo.font_name, |
|
||||||
} |
|
||||||
var wc = new Module.WordChoiceIterator(ri); |
|
||||||
do { |
|
||||||
word.choices.push({ |
|
||||||
text: wc.GetUTF8Text(), |
|
||||||
confidence: wc.Confidence() |
|
||||||
}) |
|
||||||
} while (wc.Next()); |
|
||||||
Module.destroy(wc) |
|
||||||
textline.words.push(word) |
|
||||||
} |
|
||||||
|
|
||||||
var image = null; |
|
||||||
// var pix = ri.GetBinaryImage(Module.RIL_SYMBOL)
|
|
||||||
// var image = pix2array(pix);
|
|
||||||
// // for some reason it seems that things stop working if you destroy pics
|
|
||||||
// Module._pixDestroy(Module.getPointer(pix));
|
|
||||||
if(ri.IsAtBeginningOf(Module.RIL_SYMBOL)){ |
|
||||||
symbol = { |
|
||||||
choices: [], |
|
||||||
image: image, |
|
||||||
|
|
||||||
text: ri.GetUTF8Text(Module.RIL_SYMBOL), |
|
||||||
confidence: ri.Confidence(Module.RIL_SYMBOL), |
|
||||||
baseline: ri.getBaseline(Module.RIL_SYMBOL), |
|
||||||
bbox: ri.getBoundingBox(Module.RIL_SYMBOL), |
|
||||||
|
|
||||||
is_superscript: !!ri.SymbolIsSuperscript(), |
|
||||||
is_subscript: !!ri.SymbolIsSubscript(), |
|
||||||
is_dropcap: !!ri.SymbolIsDropcap(), |
|
||||||
} |
|
||||||
word.symbols.push(symbol) |
|
||||||
var ci = new Module.ChoiceIterator(ri); |
|
||||||
do { |
|
||||||
symbol.choices.push({ |
|
||||||
text: ci.GetUTF8Text(), |
|
||||||
confidence: ci.Confidence() |
|
||||||
}) |
|
||||||
} while (ci.Next()); |
|
||||||
Module.destroy(ci) |
|
||||||
} |
|
||||||
} while (ri.Next(Module.RIL_SYMBOL)); |
|
||||||
Module.destroy(ri) |
|
||||||
|
|
||||||
return { |
|
||||||
text: base.GetUTF8Text(), |
|
||||||
html: base.GetHOCRText(), |
|
||||||
|
|
||||||
confidence: base.MeanTextConf(), |
|
||||||
|
|
||||||
blocks: blocks, |
|
||||||
|
|
||||||
psm: enumToString(base.GetPageSegMode(), 'PSM'), |
|
||||||
oem: enumToString(base.oem(), 'OEM'), |
|
||||||
version: base.Version(), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function recognize(image, lang, options,cb){ |
|
||||||
var width, height; |
|
||||||
if(image.data){ |
|
||||||
var src = image.data; |
|
||||||
width = image.width, height = image.height; |
|
||||||
var dst = new Uint8Array(width * height); |
|
||||||
var srcLength = src.length | 0, srcLength_16 = (srcLength - 16) | 0; |
|
||||||
|
|
||||||
for (var i = 0, j = 0; i <= srcLength_16; i += 16, j += 4) { |
|
||||||
// convert to grayscale 4 pixels at a time; eveything with alpha get put in front of 50% gray
|
|
||||||
dst[j] = (((src[i] * 77 + src[i+1] * 151 + src[i+2] * 28) * src[i+3]) + ((255-src[i+3]) << 15) + 32768) >> 16 |
|
||||||
dst[j+1] = (((src[i+4] * 77 + src[i+5] * 151 + src[i+6] * 28) * src[i+7]) + ((255-src[i+7]) << 15) + 32768) >> 16 |
|
||||||
dst[j+2] = (((src[i+8] * 77 + src[i+9] * 151 + src[i+10] * 28) * src[i+11]) + ((255-src[i+11]) << 15) + 32768) >> 16 |
|
||||||
dst[j+3] = (((src[i+12] * 77 + src[i+13] * 151 + src[i+14] * 28) * src[i+15]) + ((255-src[i+15]) << 15) + 32768) >> 16 |
|
||||||
|
|
||||||
} |
|
||||||
for (; i < srcLength; i += 4, ++j) //finish up
|
|
||||||
dst[j] = (((src[i] * 77 + src[i+1] * 151 + src[i+2] * 28) * src[i+3]) + ((255-src[i+3]) << 15) + 32768) >> 16 |
|
||||||
|
|
||||||
image = dst; |
|
||||||
} |
|
||||||
else { |
|
||||||
throw 'Expected ImageData' |
|
||||||
} |
|
||||||
var ptr = Module.allocate(image, 'i8', Module.ALLOC_NORMAL); |
|
||||||
|
|
||||||
loadLanguage(lang, function(err, result){ |
|
||||||
|
|
||||||
if(err){ |
|
||||||
console.error("error loading", lang); |
|
||||||
Module._free(ptr); |
|
||||||
cb(err, null) |
|
||||||
} |
|
||||||
else { |
|
||||||
base.Init(null, lang) |
|
||||||
for (var option in options) { |
|
||||||
if (options.hasOwnProperty(option)) { |
|
||||||
base.SetVariable(option, options[option]); |
|
||||||
postMessage({ |
|
||||||
progress: { |
|
||||||
set_variable: { |
|
||||||
variable: option, |
|
||||||
value: options[option] |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
base.SetImage(Module.wrapPointer(ptr), width, height, 1, width) |
|
||||||
base.SetRectangle(0, 0, width, height) |
|
||||||
// base.GetUTF8Text()
|
|
||||||
base.Recognize(null) |
|
||||||
var everything = circularize(DumpLiterallyEverything()) |
|
||||||
base.End(); |
|
||||||
Module._free(ptr); |
|
||||||
cb(null, everything) |
|
||||||
|
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
return recognize |
|
||||||
})() |
|
||||||
|
|
||||||
onmessage = function(e) { |
|
||||||
recognize(e.data.image, e.data.lang, e.data.options, function(err, result){ |
|
||||||
postMessage({err:err, result: result}) |
|
||||||
}) |
|
||||||
} |
|