A Wikiful of Hacks: Hacks.Wiki is an experiment to organise quick hacks, notes, bookmarks and tools into an easy-to-build-and-maintain “Digital Garden”.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1 lines
36 KiB

const DefaultBufferLength=1024;let nextPropID=0;class Range{constructor(from,to){this.from=from;this.to=to}}class NodeProp{constructor(config={}){this.id=nextPropID++;this.perNode=!!config.perNode;this.deserialize=config.deserialize||(()=>{throw new Error("This node type doesn't define a deserialize function")})}add(match){if(this.perNode)throw new RangeError("Can't add per-node props to node types");if(typeof match!="function")match=NodeType.match(match);return type=>{let result=match(type);return result===undefined?null:[this,result]}}}NodeProp.closedBy=new NodeProp({deserialize:str=>str.split(" ")});NodeProp.openedBy=new NodeProp({deserialize:str=>str.split(" ")});NodeProp.group=new NodeProp({deserialize:str=>str.split(" ")});NodeProp.contextHash=new NodeProp({perNode:true});NodeProp.lookAhead=new NodeProp({perNode:true});NodeProp.mounted=new NodeProp({perNode:true});class MountedTree{constructor(tree,overlay,parser){this.tree=tree;this.overlay=overlay;this.parser=parser}}const noProps=Object.create(null);class NodeType{constructor(name,props,id,flags=0){this.name=name;this.props=props;this.id=id;this.flags=flags}static define(spec){let props=spec.props&&spec.props.length?Object.create(null):noProps;let flags=(spec.top?1:0)|(spec.skipped?2:0)|(spec.error?4:0)|(spec.name==null?8:0);let type=new NodeType(spec.name||"",props,spec.id,flags);if(spec.props)for(let src of spec.props){if(!Array.isArray(src))src=src(type);if(src){if(src[0].perNode)throw new RangeError("Can't store a per-node prop on a node type");props[src[0].id]=src[1]}}return type}prop(prop){return this.props[prop.id]}get isTop(){return(this.flags&1)>0}get isSkipped(){return(this.flags&2)>0}get isError(){return(this.flags&4)>0}get isAnonymous(){return(this.flags&8)>0}is(name){if(typeof name=="string"){if(this.name==name)return true;let group=this.prop(NodeProp.group);return group?group.indexOf(name)>-1:false}return this.id==name}static match(map){let direct=Object.create(null);for(let prop in map)for(let name of prop.split(" "))direct[name]=map[prop];return node=>{for(let groups=node.prop(NodeProp.group),i=-1;i<(groups?groups.length:0);i++){let found=direct[i<0?node.name:groups[i]];if(found)return found}}}}NodeType.none=new NodeType("",Object.create(null),0,8);class NodeSet{constructor(types){this.types=types;for(let i=0;i<types.length;i++)if(types[i].id!=i)throw new RangeError("Node type ids should correspond to array positions when creating a node set")}extend(...props){let newTypes=[];for(let type of this.types){let newProps=null;for(let source of props){let add=source(type);if(add){if(!newProps)newProps=Object.assign({},type.props);newProps[add[0].id]=add[1]}}newTypes.push(newProps?new NodeType(type.name,newProps,type.id,type.flags):type)}return new NodeSet(newTypes)}}const CachedNode=new WeakMap,CachedInnerNode=new WeakMap;var IterMode;(function(IterMode){IterMode[IterMode["ExcludeBuffers"]=1]="ExcludeBuffers";IterMode[IterMode["IncludeAnonymous"]=2]="IncludeAnonymous";IterMode[IterMode["IgnoreMounts"]=4]="IgnoreMounts";IterMode[IterMode["IgnoreOverlays"]=8]="IgnoreOverlays"})(IterMode||(IterMode={}));class Tree{constructor(type,children,positions,length,props){this.type=type;this.children=children;this.positions=positions;this.length=length;this.props=null;if(props&&props.length){this.props=Object.create(null);for(let[prop,value]of props)this.props[typeof prop=="number"?prop:prop.id]=value}}toString(){let mounted=this.prop(NodeProp.mounted);if(mounted&&!mounted.overlay)return mounted.tree.toString();let children="";for(let ch of this.children){let str=ch.toString();if(str){if(children)children+=",";children+=str}}return!this.type.name?children:(/\W/.test(this.type.name)&&!this.type.isError?JSON.stringify(this.type.name):this.type.name)+(children.length?"("+children+")":"")}cursor(mode=0){return new TreeCursor(this.topNode,mode)}cursorAt(pos,side=0,mode=0){let scope=CachedNode.get(this)||this.topNode;let cursor=new TreeCursor(scope);cursor.moveTo(pos,side);CachedNode.set(this,cursor._tree);return cursor}get topNode(){return new TreeNode(this,0,0,null)}resolve(pos,side=0){let node=resolveNode(CachedNode.get(this)||this.topNode,pos,side,false);CachedNode.set(this,node);return node}resolveInner(pos,side=0){let node=resolveNode(CachedInnerNode.get(this)||this.topNode,pos,side,true);CachedInnerNode.set(this,node);return node}iterate(spec){let{enter,leave,from=0,to=this.length}=spec;for(let c=this.cursor((spec.mode||0)|IterMode.IncludeAnonymous);;){let entered=false;if(c.from<=to&&c.to>=from&&(c.type.isAnonymous||enter(c)!==false)){if(c.firstChild())continue;entered=true}for(;;){if(entered&&leave&&!c.type.isAnonymous)leave(c);if(c.nextSibling())break;if(!c.parent())return;entered=true}}}prop(prop){return!prop.perNode?this.type.prop(prop):this.props?this.props[prop.id]:undefined}get propValues(){let result=[];if(this.props)for(let id in this.props)result.push([+id,this.props[id]]);return result}balance(config={}){return this.children.length<=8?this:balanceRange(NodeType.none,this.children,this.positions,0,this.children.length,0,this.length,(children,positions,length)=>new Tree(this.type,children,positions,length,this.propValues),config.makeTree||((children,positions,length)=>new Tree(NodeType.none,children,positions,length)))}static build(data){return buildTree(data)}}Tree.empty=new Tree(NodeType.none,[],[],0);class FlatBufferCursor{constructor(buffer,index){this.buffer=buffer;this.index=index}get id(){return this.buffer[this.index-4]}get start(){return this.buffer[this.index-3]}get end(){return this.buffer[this.index-2]}get size(){return this.buffer[this.index-1]}get pos(){return this.index}next(){this.index-=4}fork(){return new FlatBufferCursor(this.buffer,this.index)}}class TreeBuffer{constructor(buffer,length,set){this.buffer=buffer;this.length=length;this.set=set}get type(){return NodeType.none}toString(){let result=[];for(let index=0;index<this.buffer.length;){result.push(this.childString(index));index=this.buffer[index+3]}return result.join(",")}childString(index){let id=this.buffer[index],endIndex=this.buffer[index+3];let type=this.set.types[id],result=type.name;if(/\W/.test(result)&&!type.isError)result=JSON.stringify(result);index+=4;if(endIndex==index)return result;let children=[];while(index<endIndex){children.push(this.childString(index));index=this.buffer[index+3]}return result+"("+children.join(",")+")"}findChild(startIndex,endIndex,dir,pos,side){let{buffer}=this,pick=-1;for(let i=startIndex;i!=endIndex;i=buffer[i+3]){if(checkSide(side,pos,buffer[i+1],buffer[i+2])){pick=i;if(dir>0)break}}return pick}slice(startI,endI,from,to){let b=this.buffer;let copy=new Uint16Array(endI-startI);for(let i=startI,j=0;i<endI;){copy[j++]=b[i++];copy[j++]=b[i++]-from;copy[j++]=b[i++]-from;copy[j++]=b[i++]-startI}return new TreeBuffer(copy,to-from,this.set)}}function checkSide(side,pos,from,to){switch(side){case-2:return from<pos;case-1:return to>=pos&&from<pos;case 0:return from<pos&&to>pos;case 1:return from<=pos&&to>pos;case 2:return to>pos;case 4:return true}}function enterUnfinishedNodesBefore(node,pos){let scan=node.childBefore(pos);while(scan){let last=scan.lastChild;if(!last||last.to!=scan.to)break;if(last.type.isError&&last.from==last.to){node=scan;scan=last.prevSibling}else{scan=last}}return node}function resolveNode(node,pos,side,overlays){var _a;while(node.from==node.to||(side<1?node.from>=pos:node.from>pos)||(side>-1?node.to<=pos:node.to<pos)){let parent=!overlays&&node instanceof TreeNode&&node.index<0?null:node.parent;if(!parent)return node;node=parent}let mode=overlays?0:IterMode.IgnoreOverlays;if(overlays)for(let scan=node,parent=scan.parent;parent;scan=parent,parent=scan.parent){if(scan instanceof TreeNode&&scan.index<0&&((_a=parent.enter(pos,side,mode))===null||_a===void 0?void 0:_a.from)!=scan.from)node=parent}for(;;){let inner=node.enter(pos,side,mode);if(!inner)return node;node=inner}}class TreeNode{constructor(_tree,from,index,_parent){this._tree=_tree;this.from=from;this.index=index;this._parent=_parent}get type(){return this._tree.type}get name(){return this._tree.type.name}get to(){return this.from+this._tree.length}nextChild(i,dir,pos,side,mode=0){for(let parent=this;;){for(let{children,positions}=parent._tree,e=dir>0?children.length:-1;i!=e;i+=dir){let next=children[i],start=positions[i]+parent.from;if(!checkSide(side,pos,start,start+next.length))continue;if(next instanceof TreeBuffer){if(mode&IterMode.ExcludeBuffers)continue;let index=next.findChild(0,next.buffer.length,dir,pos-start,side);if(index>-1)return new BufferNode(new BufferContext(parent,next,i,start),null,index)}else if(mode&IterMode.IncludeAnonymous||(!next.type.isAnonymous||hasChild(next))){let mounted;if(!(mode&IterMode.IgnoreMounts)&&next.props&&(mounted=next.prop(NodeProp.mounted))&&!mounted.overlay)return new TreeNode(mounted.tree,start,i,parent);let inner=new TreeNode(next,start,i,parent);return mode&IterMode.IncludeAnonymous||!inner.type.isAnonymous?inner:inner.nextChild(dir<0?next.children.length-1:0,dir,pos,side)}}if(mode&IterMode.IncludeAnonymous||!parent.type.isAnonymous)return null;if(parent.index>=0)i=parent.index+dir;else i=dir<0?-1:parent._parent._tree.children.length;parent=parent._parent;if(!parent)return null}}get firstChild(){return this.nextChild(0,1,0,4)}get lastChild(){return this.nextChild(this._tree.children.length-1,-1,0,4)}childAfter(pos){return this.nextChild(0,1,pos,2)}childBefore(pos){return this.nextChild(this._tree.children.length-1,-1,pos,-2)}enter(pos,side,mode=0){let mounted;if(!(mode&IterMode.IgnoreOverlays)&&(mounted=this._tree.prop(NodeProp.mounted))&&mounted.overlay){let rPos=pos-this.from;for(let{from,to}of mounted.overlay){if((side>0?from<=rPos:from<rPos)&&(side<0?to>=rPos:to>rPos))return new TreeNode(mounted.tree,mounted.overlay[0].from+this.from,-1,this)}}return this.nextChild(0,1,pos,side,mode)}nextSignificantParent(){let val=this;while(val.type.isAnonymous&&val._parent)val=val._parent;return val}get parent(){return this._parent?this._parent.nextSignificantParent():null}get nextSibling(){return this._parent&&this.index>=0?this._parent.nextChild(this.index+1,1,0,4):null}get prevSibling(){return this._parent&&this.index>=0?this._parent.nextChild(this.index-1,-1,0,4):null}cursor(mode=0){return new TreeCursor(this,mode)}get tree(){return this._tree}toTree(){return this._tree}resolve(pos,side=0){return resolveNode(this,pos,side,false)}resolveInner(pos,side=0){return resolveNode(this,pos,side,true)}enterUnfinishedNodesBefore(pos){return enterUnfinishedNodesBefore(this,pos)}getChild(type,before=null,after=null){let r=getChildren(this,type,before,after);return r.length?r[0]:null}getChildren(type,before=null,after=null){return getChildren(this,type,before,after)}toString(){return this._tree.toString()}get node(){return this}matchContext(context){return matchNodeContext(this,context)}}function getChildren(node,type,before,after){let cur=node.cursor(),result=[];if(!cur.firstChild())return result;if(before!=null)while(!cur.type.is(before))if(!cur.nextSibling())return result;for(;;){if(after!=null&&cur.type.is(after))return result;if(cur.type.is(type))result.push(cur.node);if(!cur.nextSibling())return after==null?result:[]}}function matchNodeContext(node,context,i=context.length-1){for(let p=node.parent;i>=0;p=p.parent){if(!p)return false;if(!p.type.isAnonymous){if(context[i]&&context[i]!=p.name)return false;i--}}return true}class BufferContext{constructor(parent,buffer,index,start){this.parent=parent;this.buffer=buffer;this.index=index;this.start=start}}class BufferNode{constructor(context,_parent,index){this.context=context;this._parent=_parent;this.index=index;this.type=context.buffer.set.types[context.buffer.buffer[index]]}get name(){return this.type.name}get from(){return this.context.start+this.context.buffer.buffer[this.index+1]}get to(){return this.context.start+this.context.buffer.buffer[this.index+2]}child(dir,pos,side){let{buffer}=this.context;let index=buffer.findChild(this.index+4,buffer.buffer[this.index+3],dir,pos-this.context.start,side);return index<0?null:new BufferNode(this.context,this,index)}get firstChild(){return this.child(1,0,4)}get lastChild(){return this.child(-1,0,4)}childAfter(pos){return this.child(1,pos,2)}childBefore(pos){return this.child(-1,pos,-2)}enter(pos,side,mode=0){if(mode&IterMode.ExcludeBuffers)return null;let{buffer}=this.context;let index=buffer.findChild(this.index+4,buffer.buffer[this.index+3],side>0?1:-1,pos-this.context.start,side);return index<0?null:new BufferNode(this.context,this,index)}get parent(){return this._parent||this.context.parent.nextSignificantParent()}externalSibling(dir){return this._parent?null:this.context.parent.nextChild(this.context.index+dir,dir,0,4)}get nextSibling(){let{buffer}=this.context;let after=buffer.buffer[this.index+3];if(after<(this._parent?buffer.buffer[this._parent.index+3]:buffer.buffer.length))return new BufferNode(this.context,this._parent,after);return this.externalSibling(1)}get prevSibling(){let{buffer}=this.context;let parentStart=this._parent?this._parent.index+4:0;if(this.index==parentStart)return this.externalSibling(-1);return new BufferNode(this.context,this._parent,buffer.findChild(parentStart,this.index,-1,0,4))}cursor(mode=0){return new TreeCursor(this,mode)}get tree(){return null}toTree(){let children=[],positions=[];let{buffer}=this.context;let startI=this.index+4,endI=buffer.buffer[this.index+3];if(endI>startI){let from=buffer.buffer[this.index+1],to=buffer.buffer[this.index+2];children.push(buffer.slice(startI,endI,from,to));positions.push(0)}return new Tree(this.type,children,positions,this.to-this.from)}resolve(pos,side=0){return resolveNode(this,pos,side,false)}resolveInner(pos,side=0){return resolveNode(this,pos,side,true)}enterUnfinishedNodesBefore(pos){return enterUnfinishedNodesBefore(this,pos)}toString(){return this.context.buffer.childString(this.index)}getChild(type,before=null,after=null){let r=getChildren(this,type,before,after);return r.length?r[0]:null}getChildren(type,before=null,after=null){return getChildren(this,type,before,after)}get node(){return this}matchContext(context){return matchNodeContext(this,context)}}class TreeCursor{constructor(node,mode=0){this.mode=mode;this.buffer=null;this.stack=[];this.index=0;this.bufferNode=null;if(node instanceof TreeNode){this.yieldNode(node)}else{this._tree=node.context.parent;this.buffer=node.context;for(let n=node._parent;n;n=n._parent)this.stack.unshift(n.index);this.bufferNode=node;this.yieldBuf(node.index)}}get name(){return this.type.name}yieldNode(node){if(!node)return false;this._tree=node;this.type=node.type;this.from=node.from;this.to=node.to;return true}yieldBuf(index,type){this.index=index;let{start,buffer}=this.buffer;this.type=type||buffer.set.types[buffer.buffer[index]];this.from=start+buffer.buffer[index+1];this.to=start+buffer.buffer[index+2];return true}yield(node){if(!node)return false;if(node instanceof TreeNode){this.buffer=null;return this.yieldNode(node)}this.buffer=node.context;return this.yieldBuf(node.index,node.type)}toString(){return this.buffer?this.buffer.buffer.childString(this.index):this._tree.toString()}enterChild(dir,pos,side){if(!this.buffer)return this.yield(this._tree.nextChild(dir<0?this._tree._tree.children.length-1:0,dir,pos,side,this.mode));let{buffer}=this.buffer;let index=buffer.findChild(this.index+4,buffer.buffer[this.index+3],dir,pos-this.buffer.start,side);if(index<0)return false;this.stack.push(this.index);return this.yieldBuf(index)}firstChild(){return this.enterChild(1,0,4)}lastChild(){return this.enterChild(-1,0,4)}childAfter(pos){return this.enterChild(1,pos,2)}childBefore(pos){return this.enterChild(-1,pos,-2)}enter(pos,side,mode=this.mode){if(!this.buffer)return this.yield(this._tree.enter(pos,side,mode));return mode&IterMode.ExcludeBuffers?false:this.enterChild(1,pos,side)}parent(){if(!this.buffer)return this.yieldNode(this.mode&IterMode.IncludeAnonymous?this._tree._parent:this._tree.parent);if(this.stack.length)return this.yieldBuf(this.stack.pop());let parent=this.mode&IterMode.IncludeAnonymous?this.buffer.parent:this.buffer.parent.nextSignificantParent();this.buffer=null;return this.yieldNode(parent)}sibling(dir){if(!this.buffer)return!this._tree._parent?false:this.yield(this._tree.index<0?null:this._tree._parent.nextChild(this._tree.index+dir,dir,0,4,this.mode));let{buffer}=this.buffer,d=this.stack.length-1;if(dir<0){let parentStart=d<0?0:this.stack[d]+4;if(this.index!=parentStart)return this.yieldBuf(buffer.findChild(parentStart,this.index,-1,0,4))}else{let after=buffer.buffer[this.index+3];if(after<(d<0?buffer.buffer.length:buffer.buffer[this.stack[d]+3]))return this.yieldBuf(after)}return d<0?this.yield(this.buffer.parent.nextChild(this.buffer.index+dir,dir,0,4,this.mode)):false}nextSibling(){return this.sibling(1)}prevSibling(){return this.sibling(-1)}atLastNode(dir){let index,parent,{buffer}=this;if(buffer){if(dir>0){if(this.index<buffer.buffer.buffer.length)return false}else{for(let i=0;i<this.index;i++)if(buffer.buffer.buffer[i+3]<this.index)return false}({index,parent}=buffer)}else{({index,_parent:parent}=this._tree)}for(;parent;{index,_parent:parent}=parent){if(index>-1)for(let i=index+dir,e=dir<0?-1:parent._tree.children.length;i!=e;i+=dir){let child=parent._tree.children[i];if(this.mode&IterMode.IncludeAnonymous||child instanceof TreeBuffer||!child.type.isAnonymous||hasChild(child))return false}}return true}move(dir,enter){if(enter&&this.enterChild(dir,0,4))return true;for(;;){if(this.sibling(dir))return true;if(this.atLastNode(dir)||!this.parent())return false}}next(enter=true){return this.move(1,enter)}prev(enter=true){return this.move(-1,enter)}moveTo(pos,side=0){while(this.from==this.to||(side<1?this.from>=pos:this.from>pos)||(side>-1?this.to<=pos:this.to<pos))if(!this.parent())break;while(this.enterChild(1,pos,side)){}return this}get node(){if(!this.buffer)return this._tree;let cache=this.bufferNode,result=null,depth=0;if(cache&&cache.context==this.buffer){scan:for(let index=this.index,d=this.stack.length;d>=0;){for(let c=cache;c;c=c._parent)if(c.index==index){if(index==this.index)return c;result=c;depth=d+1;break scan}index=this.stack[--d]}}for(let i=depth;i<this.stack.length;i++)result=new BufferNode(this.buffer,result,this.stack[i]);return this.bufferNode=new BufferNode(this.buffer,result,this.index)}get tree(){return this.buffer?null:this._tree._tree}iterate(enter,leave){for(let depth=0;;){let mustLeave=false;if(this.type.isAnonymous||enter(this)!==false){if(this.firstChild()){depth++;continue}if(!this.type.isAnonymous)mustLeave=true}for(;;){if(mustLeave&&leave)leave(this);mustLeave=this.type.isAnonymous;if(this.nextSibling())break;if(!depth)return;this.parent();depth--;mustLeave=true}}}matchContext(context){if(!this.buffer)return matchNodeContext(this.node,context);let{buffer}=this.buffer,{types}=buffer.set;for(let i=context.length-1,d=this.stack.length-1;i>=0;d--){if(d<0)return matchNodeContext(this.node,context,i);let type=types[buffer.buffer[this.stack[d]]];if(!type.isAnonymous){if(context[i]&&context[i]!=type.name)return false;i--}}return true}}function hasChild(tree){return tree.children.some(ch=>ch instanceof TreeBuffer||!ch.type.isAnonymous||hasChild(ch))}function buildTree(data){var _a;let{buffer,nodeSet,maxBufferLength=DefaultBufferLength,reused=[],minRepeatType=nodeSet.types.length}=data;let cursor=Array.isArray(buffer)?new FlatBufferCursor(buffer,buffer.length):buffer;let types=nodeSet.types;let contextHash=0,lookAhead=0;function takeNode(parentStart,minPos,children,positions,inRepeat){let{id,start,end,size}=cursor;let lookAheadAtStart=lookAhead;while(size<0){cursor.next();if(size==-1){let node=reused[id];children.push(node);positions.push(start-parentStart);return}else if(size==-3){contextHash=id;return}else if(size==-4){lookAhead=id;return}else{throw new RangeError(`Unrecognized record size: ${size}`)}}let type=types[id],node,buffer;let startPos=start-parentStart;if(end-start<=maxBufferLength&&(buffer=findBufferSize(cursor.pos-minPos,inRepeat))){let data=new Uint16Array(buffer.size-buffer.skip);let endPos=cursor.pos-buffer.size,index=data.length;while(cursor.pos>endPos)index=copyToBuffer(buffer.start,data,index);node=new TreeBuffer(data,end-buffer.start,nodeSet);startPos=buffer.start-parentStart}else{let endPos=cursor.pos-size;cursor.next();let localChildren=[],localPositions=[];let localInRepeat=id>=minRepeatType?id:-1;let lastGroup=0,lastEnd=end;while(cursor.pos>endPos){if(localInRepeat>=0&&cursor.id==localInRepeat&&cursor.size>=0){if(cursor.end<=lastEnd-maxBufferLength){makeRepeatLeaf(localChildren,localPositions,start,lastGroup,cursor.end,lastEnd,localInRepeat,lookAheadAtStart);lastGroup=localChildren.length;lastEnd=cursor.end}cursor.next()}else{takeNode(start,endPos,localChildren,localPositions,localInRepeat)}}if(localInRepeat>=0&&lastGroup>0&&lastGroup<localChildren.length)makeRepeatLeaf(localChildren,localPositions,start,lastGroup,start,lastEnd,localInRepeat,lookAheadAtStart);localChildren.reverse();localPositions.reverse();if(localInRepeat>-1&&lastGroup>0){let make=makeBalanced(type);node=balanceRange(type,localChildren,localPositions,0,localChildren.length,0,end-start,make,make)}else{node=makeTree(type,localChildren,localPositions,end-start,lookAheadAtStart-end)}}children.push(node);positions.push(startPos)}function makeBalanced(type){return(children,positions,length)=>{let lookAhead=0,lastI=children.length-1,last,lookAheadProp;if(lastI>=0&&(last=children[lastI])instanceof Tree){if(!lastI&&last.type==type&&last.length==length)return last;if(lookAheadProp=last.prop(NodeProp.lookAhead))lookAhead=positions[lastI]+last.length+lookAheadProp}return makeTree(type,children,positions,length,lookAhead)}}function makeRepeatLeaf(children,positions,base,i,from,to,type,lookAhead){let localChildren=[],localPositions=[];while(children.length>i){localChildren.push(children.pop());localPositions.push(positions.pop()+base-from)}children.push(makeTree(nodeSet.types[type],localChildren,localPositions,to-from,lookAhead-to));positions.push(from-base)}function makeTree(type,children,positions,length,lookAhead=0,props){if(contextHash){let pair=[NodeProp.contextHash,contextHash];props=props?[pair].concat(props):[pair]}if(lookAhead>25){let pair=[NodeProp.lookAhead,lookAhead];props=props?[pair].concat(props):[pair]}return new Tree(type,children,positions,length,props)}function findBufferSize(maxSize,inRepeat){let fork=cursor.fork();let size=0,start=0,skip=0,minStart=fork.end-maxBufferLength;let result={size:0,start:0,skip:0};scan:for(let minPos=fork.pos-maxSize;fork.pos>minPos;){let nodeSize=fork.size;if(fork.id==inRepeat&&nodeSize>=0){result.size=size;result.start=start;result.skip=skip;skip+=4;size+=4;fork.next();continue}let startPos=fork.pos-nodeSize;if(nodeSize<0||startPos<minPos||fork.start<minStart)break;let localSkipped=fork.id>=minRepeatType?4:0;let nodeStart=fork.start;fork.next();while(fork.pos>startPos){if(fork.size<0){if(fork.size==-3)localSkipped+=4;else break scan}else if(fork.id>=minRepeatType){localSkipped+=4}fork.next()}start=nodeStart;size+=nodeSize;skip+=localSkipped}if(inRepeat<0||size==maxSize){result.size=size;result.start=start;result.skip=skip}return result.size>4?result:undefined}function copyToBuffer(bufferStart,buffer,index){let{id,start,end,size}=cursor;cursor.next();if(size>=0&&id<minRepeatType){let startIndex=index;if(size>4){let endPos=cursor.pos-(size-4);while(cursor.pos>endPos)index=copyToBuffer(bufferStart,buffer,index)}buffer[--index]=startIndex;buffer[--index]=end-bufferStart;buffer[--index]=start-bufferStart;buffer[--index]=id}else if(size==-3){contextHash=id}else if(size==-4){lookAhead=id}return index}let children=[],positions=[];while(cursor.pos>0)takeNode(data.start||0,data.bufferStart||0,children,positions,-1);let length=(_a=data.length)!==null&&_a!==void 0?_a:children.length?positions[0]+children[0].length:0;return new Tree(types[data.topID],children.reverse(),positions.reverse(),length)}const nodeSizeCache=new WeakMap;function nodeSize(balanceType,node){if(!balanceType.isAnonymous||node instanceof TreeBuffer||node.type!=balanceType)return 1;let size=nodeSizeCache.get(node);if(size==null){size=1;for(let child of node.children){if(child.type!=balanceType||!(child instanceof Tree)){size=1;break}size+=nodeSize(balanceType,child)}nodeSizeCache.set(node,size)}return size}function balanceRange(balanceType,children,positions,from,to,start,length,mkTop,mkTree){let total=0;for(let i=from;i<to;i++)total+=nodeSize(balanceType,children[i]);let maxChild=Math.ceil(total*1.5/8);let localChildren=[],localPositions=[];function divide(children,positions,from,to,offset){for(let i=from;i<to;){let groupFrom=i,groupStart=positions[i],groupSize=nodeSize(balanceType,children[i]);i++;for(;i<to;i++){let nextSize=nodeSize(balanceType,children[i]);if(groupSize+nextSize>=maxChild)break;groupSize+=nextSize}if(i==groupFrom+1){if(groupSize>maxChild){let only=children[groupFrom];divide(only.children,only.positions,0,only.children.length,positions[groupFrom]+offset);continue}localChildren.push(children[groupFrom])}else{let length=positions[i-1]+children[i-1].length-groupStart;localChildren.push(balanceRange(balanceType,children,positions,groupFrom,i,groupStart,length,null,mkTree))}localPositions.push(groupStart+offset-start)}}divide(children,positions,from,to,0);return(mkTop||mkTree)(localChildren,localPositions,length)}class NodeWeakMap{constructor(){this.map=new WeakMap}setBuffer(buffer,index,value){let inner=this.map.get(buffer);if(!inner)this.map.set(buffer,inner=new Map);inner.set(index,value)}getBuffer(buffer,index){let inner=this.map.get(buffer);return inner&&inner.get(index)}set(node,value){if(node instanceof BufferNode)this.setBuffer(node.context.buffer,node.index,value);else if(node instanceof TreeNode)this.map.set(node.tree,value)}get(node){return node instanceof BufferNode?this.getBuffer(node.context.buffer,node.index):node instanceof TreeNode?this.map.get(node.tree):undefined}cursorSet(cursor,value){if(cursor.buffer)this.setBuffer(cursor.buffer.buffer,cursor.index,value);else this.map.set(cursor.tree,value)}cursorGet(cursor){return cursor.buffer?this.getBuffer(cursor.buffer.buffer,cursor.index):this.map.get(cursor.tree)}}class TreeFragment{constructor(from,to,tree,offset,openStart=false,openEnd=false){this.from=from;this.to=to;this.tree=tree;this.offset=offset;this.open=(openStart?1:0)|(openEnd?2:0)}get openStart(){return(this.open&1)>0}get openEnd(){return(this.open&2)>0}static addTree(tree,fragments=[],partial=false){let result=[new TreeFragment(0,tree.length,tree,0,false,partial)];for(let f of fragments)if(f.to>tree.length)result.push(f);return result}static applyChanges(fragments,changes,minGap=128){if(!changes.length)return fragments;let result=[];let fI=1,nextF=fragments.length?fragments[0]:null;for(let cI=0,pos=0,off=0;;cI++){let nextC=cI<changes.length?changes[cI]:null;let nextPos=nextC?nextC.fromA:1e9;if(nextPos-pos>=minGap)while(nextF&&nextF.from<nextPos){let cut=nextF;if(pos>=cut.from||nextPos<=cut.to||off){let fFrom=Math.max(cut.from,pos)-off,fTo=Math.min(cut.to,nextPos)-off;cut=fFrom>=fTo?null:new TreeFragment(fFrom,fTo,cut.tree,cut.offset+off,cI>0,!!nextC)}if(cut)result.push(cut);if(nextF.to>nextPos)break;nextF=fI<fragments.length?fragments[fI++]:null}if(!nextC)break;pos=nextC.toA;off=nextC.toA-nextC.toB}return result}}class Parser{startParse(input,fragments,ranges){if(typeof input=="string")input=new StringInput(input);ranges=!ranges?[new Range(0,input.length)]:ranges.length?ranges.map(r=>new Range(r.from,r.to)):[new Range(0,0)];return this.createParse(input,fragments||[],ranges)}parse(input,fragments,ranges){let parse=this.startParse(input,fragments,ranges);for(;;){let done=parse.advance();if(done)return done}}}class StringInput{constructor(string){this.string=string}get length(){return this.string.length}chunk(from){return this.string.slice(from)}get lineChunks(){return false}read(from,to){return this.string.slice(from,to)}}function parseMixed(nest){return(parse,input,fragments,ranges)=>new MixedParse(parse,nest,input,fragments,ranges)}class InnerParse{constructor(parser,parse,overlay,target,ranges){this.parser=parser;this.parse=parse;this.overlay=overlay;this.target=target;this.ranges=ranges}}class ActiveOverlay{constructor(parser,predicate,mounts,index,start,target,prev){this.parser=parser;this.predicate=predicate;this.mounts=mounts;this.index=index;this.start=start;this.target=target;this.prev=prev;this.depth=0;this.ranges=[]}}const stoppedInner=new NodeProp({perNode:true});class MixedParse{constructor(base,nest,input,fragments,ranges){this.nest=nest;this.input=input;this.fragments=fragments;this.ranges=ranges;this.inner=[];this.innerDone=0;this.baseTree=null;this.stoppedAt=null;this.baseParse=base}advance(){if(this.baseParse){let done=this.baseParse.advance();if(!done)return null;this.baseParse=null;this.baseTree=done;this.startInner();if(this.stoppedAt!=null)for(let inner of this.inner)inner.parse.stopAt(this.stoppedAt)}if(this.innerDone==this.inner.length){let result=this.baseTree;if(this.stoppedAt!=null)result=new Tree(result.type,result.children,result.positions,result.length,result.propValues.concat([[stoppedInner,this.stoppedAt]]));return result}let inner=this.inner[this.innerDone],done=inner.parse.advance();if(done){this.innerDone++;let props=Object.assign(Object.create(null),inner.target.props);props[NodeProp.mounted.id]=new MountedTree(done,inner.overlay,inner.parser);inner.target.props=props}return null}get parsedPos(){if(this.baseParse)return 0;let pos=this.input.length;for(let i=this.innerDone;i<this.inner.length;i++){if(this.inner[i].ranges[0].from<pos)pos=Math.min(pos,this.inner[i].parse.parsedPos)}return pos}stopAt(pos){this.stoppedAt=pos;if(this.baseParse)this.baseParse.stopAt(pos);else for(let i=this.innerDone;i<this.inner.length;i++)this.inner[i].parse.stopAt(pos)}startInner(){let fragmentCursor=new FragmentCursor(this.fragments);let overlay=null;let covered=null;let cursor=new TreeCursor(new TreeNode(this.baseTree,this.ranges[0].from,0,null),IterMode.IncludeAnonymous|IterMode.IgnoreMounts);scan:for(let nest,isCovered;this.stoppedAt==null||cursor.from<this.stoppedAt;){let enter=true,range;if(fragmentCursor.hasNode(cursor)){if(overlay){let match=overlay.mounts.find(m=>m.frag.from<=cursor.from&&m.frag.to>=cursor.to&&m.mount.overlay);if(match)for(let r of match.mount.overlay){let from=r.from+match.pos,to=r.to+match.pos;if(from>=cursor.from&&to<=cursor.to&&!overlay.ranges.some(r=>r.from<to&&r.to>from))overlay.ranges.push({from:from,to:to})}}enter=false}else if(covered&&(isCovered=checkCover(covered.ranges,cursor.from,cursor.to))){enter=isCovered!=2}else if(!cursor.type.isAnonymous&&cursor.from<cursor.to&&(nest=this.nest(cursor,this.input))){if(!cursor.tree)materialize(cursor);let oldMounts=fragmentCursor.findMounts(cursor.from,nest.parser);if(typeof nest.overlay=="function"){overlay=new ActiveOverlay(nest.parser,nest.overlay,oldMounts,this.inner.length,cursor.from,cursor.tree,overlay)}else{let ranges=punchRanges(this.ranges,nest.overlay||[new Range(cursor.from,cursor.to)]);if(ranges.length)this.inner.push(new InnerParse(nest.parser,nest.parser.startParse(this.input,enterFragments(oldMounts,ranges),ranges),nest.overlay?nest.overlay.map(r=>new Range(r.from-cursor.from,r.to-cursor.from)):null,cursor.tree,ranges));if(!nest.overlay)enter=false;else if(ranges.length)covered={ranges:ranges,depth:0,prev:covered}}}else if(overlay&&(range=overlay.predicate(cursor))){if(range===true)range=new Range(cursor.from,cursor.to);if(range.from<range.to)overlay.ranges.push(range)}if(enter&&cursor.firstChild()){if(overlay)overlay.depth++;if(covered)covered.depth++}else{for(;;){if(cursor.nextSibling())break;if(!cursor.parent())break scan;if(overlay&&!--overlay.depth){let ranges=punchRanges(this.ranges,overlay.ranges);if(ranges.length)this.inner.splice(overlay.index,0,new InnerParse(overlay.parser,overlay.parser.startParse(this.input,enterFragments(overlay.mounts,ranges),ranges),overlay.ranges.map(r=>new Range(r.from-overlay.start,r.to-overlay.start)),overlay.target,ranges));overlay=overlay.prev}if(covered&&!--covered.depth)covered=covered.prev}}}}}function checkCover(covered,from,to){for(let range of covered){if(range.from>=to)break;if(range.to>from)return range.from<=from&&range.to>=to?2:1}return 0}function sliceBuf(buf,startI,endI,nodes,positions,off){if(startI<endI){let from=buf.buffer[startI+1],to=buf.buffer[endI-2];nodes.push(buf.slice(startI,endI,from,to));positions.push(from-off)}}function materialize(cursor){let{node}=cursor,depth=0;do{cursor.parent();depth++}while(!cursor.tree);let i=0,base=cursor.tree,off=0;for(;;i++){off=base.positions[i]+cursor.from;if(off<=node.from&&off+base.children[i].length>=node.to)break}let buf=base.children[i],b=buf.buffer;function split(startI,endI,type,innerOffset,length){let i=startI;while(b[i+2]+off<=node.from)i=b[i+3];let children=[],positions=[];sliceBuf(buf,startI,i,children,positions,innerOffset);let from=b[i+1],to=b[i+2];let isTarget=from+off==node.from&&to+off==node.to&&b[i]==node.type.id;children.push(isTarget?node.toTree():split(i+4,b[i+3],buf.set.types[b[i]],from,to-from));positions.push(from-innerOffset);sliceBuf(buf,b[i+3],endI,children,positions,innerOffset);return new Tree(type,children,positions,length)}base.children[i]=split(0,b.length,NodeType.none,0,buf.length);for(let d=0;d<=depth;d++)cursor.childAfter(node.from)}class StructureCursor{constructor(root,offset){this.offset=offset;this.done=false;this.cursor=root.cursor(IterMode.IncludeAnonymous|IterMode.IgnoreMounts)}moveTo(pos){let{cursor}=this,p=pos-this.offset;while(!this.done&&cursor.from<p){if(cursor.to>=pos&&cursor.enter(p,1,IterMode.IgnoreOverlays|IterMode.ExcludeBuffers));else if(!cursor.next(false))this.done=true}}hasNode(cursor){this.moveTo(cursor.from);if(!this.done&&this.cursor.from+this.offset==cursor.from&&this.cursor.tree){for(let tree=this.cursor.tree;;){if(tree==cursor.tree)return true;if(tree.children.length&&tree.positions[0]==0&&tree.children[0]instanceof Tree)tree=tree.children[0];else break}}return false}}class FragmentCursor{constructor(fragments){var _a;this.fragments=fragments;this.curTo=0;this.fragI=0;if(fragments.length){let first=this.curFrag=fragments[0];this.curTo=(_a=first.tree.prop(stoppedInner))!==null&&_a!==void 0?_a:first.to;this.inner=new StructureCursor(first.tree,-first.offset)}else{this.curFrag=this.inner=null}}hasNode(node){while(this.curFrag&&node.from>=this.curTo)this.nextFrag();return this.curFrag&&this.curFrag.from<=node.from&&this.curTo>=node.to&&this.inner.hasNode(node)}nextFrag(){var _a;this.fragI++;if(this.fragI==this.fragments.length){this.curFrag=this.inner=null}else{let frag=this.curFrag=this.fragments[this.fragI];this.curTo=(_a=frag.tree.prop(stoppedInner))!==null&&_a!==void 0?_a:frag.to;this.inner=new StructureCursor(frag.tree,-frag.offset)}}findMounts(pos,parser){var _a;let result=[];if(this.inner){this.inner.cursor.moveTo(pos,1);for(let pos=this.inner.cursor.node;pos;pos=pos.parent){let mount=(_a=pos.tree)===null||_a===void 0?void 0:_a.prop(NodeProp.mounted);if(mount&&mount.parser==parser){for(let i=this.fragI;i<this.fragments.length;i++){let frag=this.fragments[i];if(frag.from>=pos.to)break;if(frag.tree==this.curFrag.tree)result.push({frag:frag,pos:pos.from-frag.offset,mount:mount})}}}}return result}}function punchRanges(outer,ranges){let copy=null,current=ranges;for(let i=1,j=0;i<outer.length;i++){let gapFrom=outer[i-1].to,gapTo=outer[i].from;for(;j<current.length;j++){let r=current[j];if(r.from>=gapTo)break;if(r.to<=gapFrom)continue;if(!copy)current=copy=ranges.slice();if(r.from<gapFrom){copy[j]=new Range(r.from,gapFrom);if(r.to>gapTo)copy.splice(j+1,0,new Range(gapTo,r.to))}else if(r.to>gapTo){copy[j--]=new Range(gapTo,r.to)}else{copy.splice(j--,1)}}}return current}function findCoverChanges(a,b,from,to){let iA=0,iB=0,inA=false,inB=false,pos=-1e9;let result=[];for(;;){let nextA=iA==a.length?1e9:inA?a[iA].to:a[iA].from;let nextB=iB==b.length?1e9:inB?b[iB].to:b[iB].from;if(inA!=inB){let start=Math.max(pos,from),end=Math.min(nextA,nextB,to);if(start<end)result.push(new Range(start,end))}pos=Math.min(nextA,nextB);if(pos==1e9)break;if(nextA==pos){if(!inA)inA=true;else{inA=false;iA++}}if(nextB==pos){if(!inB)inB=true;else{inB=false;iB++}}}return result}function enterFragments(mounts,ranges){let result=[];for(let{pos,mount,frag}of mounts){let startPos=pos+(mount.overlay?mount.overlay[0].from:0),endPos=startPos+mount.tree.length;let from=Math.max(frag.from,startPos),to=Math.min(frag.to,endPos);if(mount.overlay){let overlay=mount.overlay.map(r=>new Range(r.from+pos,r.to+pos));let changes=findCoverChanges(ranges,overlay,from,to);for(let i=0,pos=from;;i++){let last=i==changes.length,end=last?to:changes[i].from;if(end>pos)result.push(new TreeFragment(pos,end,mount.tree,-startPos,frag.from>=pos||frag.openStart,frag.to<=end||frag.openEnd));if(last)break;pos=changes[i].to}}else{result.push(new TreeFragment(from,to,mount.tree,-startPos,frag.from>=startPos||frag.openStart,frag.to<=endPos||frag.openEnd))}}return result}export{DefaultBufferLength,IterMode,MountedTree,NodeProp,NodeSet,NodeType,NodeWeakMap,Parser,Tree,TreeBuffer,TreeCursor,TreeFragment,parseMixed};