import{parser}from"@lezer/javascript";import{syntaxTree,LRLanguage,indentNodeProp,continuedIndent,flatIndent,delimitedIndent,foldNodeProp,foldInside,LanguageSupport}from"@codemirror/language";import{EditorSelection}from"@codemirror/state";import{EditorView}from"@codemirror/view";import{snippetCompletion,ifNotIn,completeFromList}from"@codemirror/autocomplete";import{NodeWeakMap,IterMode}from"@lezer/common";const snippets=[snippetCompletion("function ${name}(${params}) {\n\t${}\n}",{label:"function",detail:"definition",type:"keyword"}),snippetCompletion("for (let ${index} = 0; ${index} < ${bound}; ${index}++) {\n\t${}\n}",{label:"for",detail:"loop",type:"keyword"}),snippetCompletion("for (let ${name} of ${collection}) {\n\t${}\n}",{label:"for",detail:"of loop",type:"keyword"}),snippetCompletion("do {\n\t${}\n} while (${})",{label:"do",detail:"loop",type:"keyword"}),snippetCompletion("while (${}) {\n\t${}\n}",{label:"while",detail:"loop",type:"keyword"}),snippetCompletion("try {\n\t${}\n} catch (${error}) {\n\t${}\n}",{label:"try",detail:"/ catch block",type:"keyword"}),snippetCompletion("if (${}) {\n\t${}\n}",{label:"if",detail:"block",type:"keyword"}),snippetCompletion("if (${}) {\n\t${}\n} else {\n\t${}\n}",{label:"if",detail:"/ else block",type:"keyword"}),snippetCompletion("class ${name} {\n\tconstructor(${params}) {\n\t\t${}\n\t}\n}",{label:"class",detail:"definition",type:"keyword"}),snippetCompletion('import {${names}} from "${module}"\n${}',{label:"import",detail:"named",type:"keyword"}),snippetCompletion('import ${name} from "${module}"\n${}',{label:"import",detail:"default",type:"keyword"})];const cache=new NodeWeakMap;const ScopeNodes=new Set(["Script","Block","FunctionExpression","FunctionDeclaration","ArrowFunction","MethodDeclaration","ForStatement"]);function defID(type){return(node,def)=>{let id=node.node.getChild("VariableDefinition");if(id)def(id,type);return true}}const functionContext=["FunctionDeclaration"];const gatherCompletions={FunctionDeclaration:defID("function"),ClassDeclaration:defID("class"),ClassExpression:()=>true,EnumDeclaration:defID("constant"),TypeAliasDeclaration:defID("type"),NamespaceDeclaration:defID("namespace"),VariableDefinition(node,def){if(!node.matchContext(functionContext))def(node,"variable")},TypeDefinition(node,def){def(node,"type")},__proto__:null};function getScope(doc,node){let cached=cache.get(node);if(cached)return cached;let completions=[],top=true;function def(node,type){let name=doc.sliceString(node.from,node.to);completions.push({label:name,type:type})}node.cursor(IterMode.IncludeAnonymous).iterate(node=>{if(top){top=false}else if(node.name){let gather=gatherCompletions[node.name];if(gather&&gather(node,def)||ScopeNodes.has(node.name))return false}else if(node.to-node.from>8192){for(let c of getScope(doc,node.node))completions.push(c);return false}});cache.set(node,completions);return completions}const Identifier=/^[\w$\xa1-\uffff][\w$\d\xa1-\uffff]*$/;const dontComplete=["TemplateString","String","RegExp","LineComment","BlockComment","VariableDefinition","TypeDefinition","Label","PropertyDefinition","PropertyName","PrivatePropertyDefinition","PrivatePropertyName"];function localCompletionSource(context){let inner=syntaxTree(context.state).resolveInner(context.pos,-1);if(dontComplete.indexOf(inner.name)>-1)return null;let isWord=inner.name=="VariableName"||inner.to-inner.from<20&&Identifier.test(context.state.sliceDoc(inner.from,inner.to));if(!isWord&&!context.explicit)return null;let options=[];for(let pos=inner;pos;pos=pos.parent){if(ScopeNodes.has(pos.name))options=options.concat(getScope(context.state.doc,pos))}return{options:options,from:isWord?inner.from:context.pos,validFor:Identifier}}function pathFor(read,member,name){var _a;let path=[];for(;;){let obj=member.firstChild,prop;if((obj===null||obj===void 0?void 0:obj.name)=="VariableName"){path.push(read(obj));return{path:path.reverse(),name:name}}else if((obj===null||obj===void 0?void 0:obj.name)=="MemberExpression"&&((_a=prop=obj.lastChild)===null||_a===void 0?void 0:_a.name)=="PropertyName"){path.push(read(prop));member=obj}else{return null}}}function completionPath(context){let read=node=>context.state.doc.sliceString(node.from,node.to);let inner=syntaxTree(context.state).resolveInner(context.pos,-1);if(inner.name=="PropertyName"){return pathFor(read,inner.parent,read(inner))}else if(dontComplete.indexOf(inner.name)>-1){return null}else if(inner.name=="VariableName"||inner.to-inner.from<20&&Identifier.test(read(inner))){return{path:[],name:read(inner)}}else if((inner.name=="."||inner.name=="?.")&&inner.parent.name=="MemberExpression"){return pathFor(read,inner.parent,"")}else if(inner.name=="MemberExpression"){return pathFor(read,inner,"")}else{return context.explicit?{path:[],name:""}:null}}function enumeratePropertyCompletions(obj,top){let options=[],seen=new Set;for(let depth=0;;depth++){for(let name of(Object.getOwnPropertyNames||Object.keys)(obj)){if(seen.has(name))continue;seen.add(name);let value;try{value=obj[name]}catch(_){continue}options.push({label:name,type:typeof value=="function"?/^[A-Z]/.test(name)?"class":top?"function":"method":top?"variable":"property",boost:-depth})}let next=Object.getPrototypeOf(obj);if(!next)return options;obj=next}}function scopeCompletionSource(scope){let cache=new Map;return context=>{let path=completionPath(context);if(!path)return null;let target=scope;for(let step of path.path){target=target[step];if(!target)return null}let options=cache.get(target);if(!options)cache.set(target,options=enumeratePropertyCompletions(target,!path.path.length));return{from:context.pos-path.name.length,options:options,validFor:Identifier}}}const javascriptLanguage=LRLanguage.define({name:"javascript",parser:parser.configure({props:[indentNodeProp.add({IfStatement:continuedIndent({except:/^\s*({|else\b)/}),TryStatement:continuedIndent({except:/^\s*({|catch\b|finally\b)/}),LabeledStatement:flatIndent,SwitchBody:context=>{let after=context.textAfter,closed=/^\s*\}/.test(after),isCase=/^\s*(case|default)\b/.test(after);return context.baseIndent+(closed?0:isCase?1:2)*context.unit},Block:delimitedIndent({closing:"}"}),ArrowFunction:cx=>cx.baseIndent+cx.unit,"TemplateString BlockComment":()=>null,"Statement Property":continuedIndent({except:/^{/}),JSXElement(context){let closed=/^\s*<\//.test(context.textAfter);return context.lineIndent(context.node.from)+(closed?0:context.unit)},JSXEscape(context){let closed=/\s*\}/.test(context.textAfter);return context.lineIndent(context.node.from)+(closed?0:context.unit)},"JSXOpenTag JSXSelfClosingTag"(context){return context.column(context.node.from)+context.unit}}),foldNodeProp.add({"Block ClassBody SwitchBody EnumBody ObjectExpression ArrayExpression":foldInside,BlockComment(tree){return{from:tree.from+2,to:tree.to-2}}})]}),languageData:{closeBrackets:{brackets:["(","[","{","'",'"',"`"]},commentTokens:{line:"//",block:{open:"/*",close:"*/"}},indentOnInput:/^\s*(?:case |default:|\{|\}|<\/)$/,wordChars:"$"}});const typescriptLanguage=javascriptLanguage.configure({dialect:"ts"},"typescript");const jsxLanguage=javascriptLanguage.configure({dialect:"jsx"});const tsxLanguage=javascriptLanguage.configure({dialect:"jsx ts"},"typescript");const keywords="break case const continue default delete export extends false finally in instanceof let new return static super switch this throw true typeof var yield".split(" ").map(kw=>({label:kw,type:"keyword"}));function javascript(config={}){let lang=config.jsx?config.typescript?tsxLanguage:jsxLanguage:config.typescript?typescriptLanguage:javascriptLanguage;return new LanguageSupport(lang,[javascriptLanguage.data.of({autocomplete:ifNotIn(dontComplete,completeFromList(snippets.concat(keywords)))}),javascriptLanguage.data.of({autocomplete:localCompletionSource}),config.jsx?autoCloseTags:[]])}function elementName(doc,tree,max=doc.length){if(!tree)return"";let name=tree.getChild("JSXIdentifier");return name?doc.sliceString(name.from,Math.min(name.to,max)):""}const android=typeof navigator=="object"&&/Android\b/.test(navigator.userAgent);const autoCloseTags=EditorView.inputHandler.of((view,from,to,text)=>{if((android?view.composing:view.compositionStarted)||view.state.readOnly||from!=to||text!=">"&&text!="/"||!javascriptLanguage.isActiveAt(view.state,from,-1))return false;let{state}=view;let changes=state.changeByRange(range=>{var _a,_b,_c;let{head}=range,around=syntaxTree(state).resolveInner(head,-1),name;if(around.name=="JSXStartTag")around=around.parent;if(text==">"&&around.name=="JSXFragmentTag"){return{range:EditorSelection.cursor(head+1),changes:{from:head,insert:`><>`}}}else if(text==">"&&around.name=="JSXIdentifier"){if(((_b=(_a=around.parent)===null||_a===void 0?void 0:_a.lastChild)===null||_b===void 0?void 0:_b.name)!="JSXEndTag"&&(name=elementName(state.doc,around.parent,head)))return{range:EditorSelection.cursor(head+1),changes:{from:head,insert:`>`}}}else if(text=="/"&&around.name=="JSXFragmentTag"){let empty=around.parent,base=empty===null||empty===void 0?void 0:empty.parent;if(empty.from==head-1&&((_c=base.lastChild)===null||_c===void 0?void 0:_c.name)!="JSXEndTag"&&(name=elementName(state.doc,base===null||base===void 0?void 0:base.firstChild,head))){let insert=`/${name}>`;return{range:EditorSelection.cursor(head+insert.length),changes:{from:head,insert:insert}}}}return{range:range}});if(changes.changes.empty)return false;view.dispatch(changes,{userEvent:"input.type",scrollIntoView:true});return true});function esLint(eslint,config){if(!config){config={parserOptions:{ecmaVersion:2019,sourceType:"module"},env:{browser:true,node:true,es6:true,es2015:true,es2017:true,es2020:true},rules:{}};eslint.getRules().forEach((desc,name)=>{if(desc.meta.docs.recommended)config.rules[name]=2})}return view=>{let{state}=view,found=[];for(let{from,to}of javascriptLanguage.findRegions(state)){let fromLine=state.doc.lineAt(from),offset={line:fromLine.number-1,col:from-fromLine.from,pos:from};for(let d of eslint.verify(state.sliceDoc(from,to),config))found.push(translateDiagnostic(d,state.doc,offset))}return found}}function mapPos(line,col,doc,offset){return doc.line(line+offset.line).from+col+(line==1?offset.col-1:-1)}function translateDiagnostic(input,doc,offset){let start=mapPos(input.line,input.column,doc,offset);let result={from:start,to:input.endLine!=null&&input.endColumn!=1?mapPos(input.endLine,input.endColumn,doc,offset):start,message:input.message,source:input.ruleId?"eslint:"+input.ruleId:"eslint",severity:input.severity==1?"warning":"error"};if(input.fix){let{range,text}=input.fix,from=range[0]+offset.pos-start,to=range[1]+offset.pos-start;result.actions=[{name:"fix",apply(view,start){view.dispatch({changes:{from:start+from,to:start+to,insert:text},scrollIntoView:true})}}]}return result}export{autoCloseTags,completionPath,esLint,javascript,javascriptLanguage,jsxLanguage,localCompletionSource,scopeCompletionSource,snippets,tsxLanguage,typescriptLanguage};