jsx.js 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. (function(mod){if(typeof exports=="object"&&typeof module=="object")
  2. mod(require("../../lib/codemirror"),require("../xml/xml"),require("../javascript/javascript"))
  3. else if(typeof define=="function"&&define.amd)
  4. define(["../../lib/codemirror","../xml/xml","../javascript/javascript"],mod)
  5. else
  6. mod(CodeMirror)})(function(CodeMirror){"use strict"
  7. function Context(state,mode,depth,prev){this.state=state;this.mode=mode;this.depth=depth;this.prev=prev}
  8. function copyContext(context){return new Context(CodeMirror.copyState(context.mode,context.state),context.mode,context.depth,context.prev&&copyContext(context.prev))}
  9. CodeMirror.defineMode("jsx",function(config,modeConfig){var xmlMode=CodeMirror.getMode(config,{name:"xml",allowMissing:true,multilineTagIndentPastTag:false,allowMissingTagName:true})
  10. var jsMode=CodeMirror.getMode(config,modeConfig&&modeConfig.base||"javascript")
  11. function flatXMLIndent(state){var tagName=state.tagName
  12. state.tagName=null
  13. var result=xmlMode.indent(state,"","")
  14. state.tagName=tagName
  15. return result}
  16. function token(stream,state){if(state.context.mode==xmlMode)
  17. return xmlToken(stream,state,state.context)
  18. else
  19. return jsToken(stream,state,state.context)}
  20. function xmlToken(stream,state,cx){if(cx.depth==2){if(stream.match(/^.*?\*\//))cx.depth=1
  21. else stream.skipToEnd()
  22. return"comment"}
  23. if(stream.peek()=="{"){xmlMode.skipAttribute(cx.state)
  24. var indent=flatXMLIndent(cx.state),xmlContext=cx.state.context
  25. if(xmlContext&&stream.match(/^[^>]*>\s*$/,false)){while(xmlContext.prev&&!xmlContext.startOfLine)
  26. xmlContext=xmlContext.prev
  27. if(xmlContext.startOfLine)indent-=config.indentUnit
  28. else if(cx.prev.state.lexical)indent=cx.prev.state.lexical.indented}else if(cx.depth==1){indent+=config.indentUnit}
  29. state.context=new Context(CodeMirror.startState(jsMode,indent),jsMode,0,state.context)
  30. return null}
  31. if(cx.depth==1){if(stream.peek()=="<"){xmlMode.skipAttribute(cx.state)
  32. state.context=new Context(CodeMirror.startState(xmlMode,flatXMLIndent(cx.state)),xmlMode,0,state.context)
  33. return null}else if(stream.match("//")){stream.skipToEnd()
  34. return"comment"}else if(stream.match("/*")){cx.depth=2
  35. return token(stream,state)}}
  36. var style=xmlMode.token(stream,cx.state),cur=stream.current(),stop
  37. if(/\btag\b/.test(style)){if(/>$/.test(cur)){if(cx.state.context)cx.depth=0
  38. else state.context=state.context.prev}else if(/^</.test(cur)){cx.depth=1}}else if(!style&&(stop=cur.indexOf("{"))>-1){stream.backUp(cur.length-stop)}
  39. return style}
  40. function jsToken(stream,state,cx){if(stream.peek()=="<"&&jsMode.expressionAllowed(stream,cx.state)){jsMode.skipExpression(cx.state)
  41. state.context=new Context(CodeMirror.startState(xmlMode,jsMode.indent(cx.state,"","")),xmlMode,0,state.context)
  42. return null}
  43. var style=jsMode.token(stream,cx.state)
  44. if(!style&&cx.depth!=null){var cur=stream.current()
  45. if(cur=="{"){cx.depth++}else if(cur=="}"){if(--cx.depth==0)state.context=state.context.prev}}
  46. return style}
  47. return{startState:function(){return{context:new Context(CodeMirror.startState(jsMode),jsMode)}},copyState:function(state){return{context:copyContext(state.context)}},token:token,indent:function(state,textAfter,fullLine){return state.context.mode.indent(state.context.state,textAfter,fullLine)},innerMode:function(state){return state.context}}},"xml","javascript")
  48. CodeMirror.defineMIME("text/jsx","jsx")
  49. CodeMirror.defineMIME("text/typescript-jsx",{name:"jsx",base:{name:"javascript",typescript:true}})});