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.

0 lines
46 KiB

  1. import{NodeProp,Tree,IterMode,TreeFragment,Parser,NodeType,NodeSet}from"@lezer/common";import{StateEffect,StateField,Facet,EditorState,countColumn,combineConfig,RangeSet,RangeSetBuilder,Prec}from"@codemirror/state";import{ViewPlugin,logException,EditorView,Decoration,WidgetType,gutter,GutterMarker}from"@codemirror/view";import{tags,tagHighlighter,highlightTree,styleTags}from"@lezer/highlight";import{StyleModule}from"style-mod";var _a;const languageDataProp=new NodeProp;function defineLanguageFacet(baseData){return Facet.define({combine:baseData?values=>values.concat(baseData):undefined})}class Language{constructor(data,parser,extraExtensions=[],name=""){this.data=data;this.name=name;if(!EditorState.prototype.hasOwnProperty("tree"))Object.defineProperty(EditorState.prototype,"tree",{get(){return syntaxTree(this)}});this.parser=parser;this.extension=[language.of(this),EditorState.languageData.of((state,pos,side)=>state.facet(languageDataFacetAt(state,pos,side)))].concat(extraExtensions)}isActiveAt(state,pos,side=-1){return languageDataFacetAt(state,pos,side)==this.data}findRegions(state){let lang=state.facet(language);if((lang===null||lang===void 0?void 0:lang.data)==this.data)return[{from:0,to:state.doc.length}];if(!lang||!lang.allowsNesting)return[];let result=[];let explore=(tree,from)=>{if(tree.prop(languageDataProp)==this.data){result.push({from:from,to:from+tree.length});return}let mount=tree.prop(NodeProp.mounted);if(mount){if(mount.tree.prop(languageDataProp)==this.data){if(mount.overlay)for(let r of mount.overlay)result.push({from:r.from+from,to:r.to+from});else result.push({from:from,to:from+tree.length});return}else if(mount.overlay){let size=result.length;explore(mount.tree,mount.overlay[0].from+from);if(result.length>size)return}}for(let i=0;i<tree.children.length;i++){let ch=tree.children[i];if(ch instanceof Tree)explore(ch,tree.positions[i]+from)}};explore(syntaxTree(state),0);return result}get allowsNesting(){return true}}Language.setState=StateEffect.define();function languageDataFacetAt(state,pos,side){let topLang=state.facet(language);if(!topLang)return null;let facet=topLang.data;if(topLang.allowsNesting){for(let node=syntaxTree(state).topNode;node;node=node.enter(pos,side,IterMode.ExcludeBuffers))facet=node.type.prop(languageDataProp)||facet}return facet}class LRLanguage extends Language{constructor(data,parser,name){super(data,parser,[],name);this.parser=parser}static define(spec){let data=defineLanguageFacet(spec.languageData);return new LRLanguage(data,spec.parser.configure({props:[languageDataProp.add(type=>type.isTop?data:undefined)]}),spec.name)}configure(options,name){return new LRLanguage(this.data,this.parser.configure(options),name||this.name)}get allowsNesting(){return this.parser.hasWrappers()}}function syntaxTree(state){let field=state.field(Language.state,false);return field?field.tree:Tree.empty}function ensureSyntaxTree(state,upto,timeout=50){var _a;let parse=(_a=state.field(Language.state,false))===null||_a===void 0?void 0:_a.context;return!parse?null:parse.isDone(upto)||parse.work(timeout,upto)?parse.tree:null}function syntaxTreeAvailable(state,upto=state.doc.length){var _a;return((_a=state.field(Language.state,false))===null||_a===void 0?void 0:_a.context.isDone(upto))||false}function forceParsing(view,upto=view.viewport.to,timeout=100){let success=ensureSyntaxTree(view.state,upto,timeout);if(success!=syntaxTree(view.state))view.dispatch({});return!!success}function syntaxParserRunning(view){var _a;return((_a=view.plugin(parseWorker))===null||_a===void 0?void 0:_a.isWorking())||false}class DocInput{constructor(doc,length=doc.length){this.doc=doc;this.length=length;this.cursorPos=0;this.string="";this.cursor=doc.iter()}syncTo(pos){this.string=this.cursor.next(pos-this.cursorPos).value;this.cursorPos=pos+this.string.length;return this.cursorPos-this.string.length}chunk(pos){this.syncTo(pos);return this.string}get lineChunks(){return true}read(from,to){let stringStart=this.cursorPos-this.string.length;if(from<stringStart||to>=this.cursorPos)return this.doc.sliceString(from,to);else ret