1{"version":3,"sources":["../../node_modules/codemirror/mode/crystal/crystal.js"],"names":["mod","exports","module","require","define","amd","CodeMirror","defineMode","config","wordRegExp","words","end","RegExp","join","chain","tokenize","stream","state","push","operators","conditionalOperators","indexingOperators","anotherOperators","idents","types","keywords","atomWords","indentKeywordsArray","indentKeywords","indentExpressionKeywordsArray","indentExpressionKeywords","dedentKeywordsArray","dedentKeywords","dedentPunctualsArray","dedentPunctuals","nextTokenizer","def","tokenFollowIdent","fun","macro","tokenMacroDef","class","tokenFollowType","struct","lib","enum","union","matching","[","{","(","<","tokenBase","eatSpace","lastToken","match","tokenMacro","peek","skipToEnd","matched","eat","current","test","blocks","indexOf","currentIndent","lastStyle","pop","hasOwnProperty","tokenNest","tokenQuote","style","embed","delim","next","tokenHereDoc","begin","started","length","nextStyle","escaped","ch","phrase","sol","startState","token","indent","textAfter","replace","indentUnit","fold","electricInput","concat","lineComment","defineMIME"],"mappings":"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","file":"crystal.min.js","sourcesContent":["// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: https://codemirror.net/LICENSE\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  CodeMirror.defineMode(\"crystal\", function(config) {\n    function wordRegExp(words, end) {\n      return new RegExp((end ? \"\" : \"^\") + \"(?:\" + words.join(\"|\") + \")\" + (end ? \"$\" : \"\\\\b\"));\n    }\n\n    function chain(tokenize, stream, state) {\n      state.tokenize.push(tokenize);\n      return tokenize(stream, state);\n    }\n\n    var operators = /^(?:[-+/%|&^]|\\*\\*?|[<>]{2})/;\n    var conditionalOperators = /^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/;\n    var indexingOperators = /^(?:\\[\\][?=]?)/;\n    var anotherOperators = /^(?:\\.(?:\\.{2})?|->|[?:])/;\n    var idents = /^[a-z_\\u009F-\\uFFFF][a-zA-Z0-9_\\u009F-\\uFFFF]*/;\n    var types = /^[A-Z_\\u009F-\\uFFFF][a-zA-Z0-9_\\u009F-\\uFFFF]*/;\n    var keywords = wordRegExp([\n      \"abstract\", \"alias\", \"as\", \"asm\", \"begin\", \"break\", \"case\", \"class\", \"def\", \"do\",\n      \"else\", \"elsif\", \"end\", \"ensure\", \"enum\", \"extend\", \"for\", \"fun\", \"if\",\n      \"include\", \"instance_sizeof\", \"lib\", \"macro\", \"module\", \"next\", \"of\", \"out\", \"pointerof\",\n      \"private\", \"protected\", \"rescue\", \"return\", \"require\", \"select\", \"sizeof\", \"struct\",\n      \"super\", \"then\", \"type\", \"typeof\", \"uninitialized\", \"union\", \"unless\", \"until\", \"when\", \"while\", \"with\",\n      \"yield\", \"__DIR__\", \"__END_LINE__\", \"__FILE__\", \"__LINE__\"\n    ]);\n    var atomWords = wordRegExp([\"true\", \"false\", \"nil\", \"self\"]);\n    var indentKeywordsArray = [\n      \"def\", \"fun\", \"macro\",\n      \"class\", \"module\", \"struct\", \"lib\", \"enum\", \"union\",\n      \"do\", \"for\"\n    ];\n    var indentKeywords = wordRegExp(indentKeywordsArray);\n    var indentExpressionKeywordsArray = [\"if\", \"unless\", \"case\", \"while\", \"until\", \"begin\", \"then\"];\n    var indentExpressionKeywords = wordRegExp(indentExpressionKeywordsArray);\n    var dedentKeywordsArray = [\"end\", \"else\", \"elsif\", \"rescue\", \"ensure\"];\n    var dedentKeywords = wordRegExp(dedentKeywordsArray);\n    var dedentPunctualsArray = [\"\\\\)\", \"\\\\}\", \"\\\\]\"];\n    var dedentPunctuals = new RegExp(\"^(?:\" + dedentPunctualsArray.join(\"|\") + \")$\");\n    var nextTokenizer = {\n      \"def\": tokenFollowIdent, \"fun\": tokenFollowIdent, \"macro\": tokenMacroDef,\n      \"class\": tokenFollowType, \"module\": tokenFollowType, \"struct\": tokenFollowType,\n      \"lib\": tokenFollowType, \"enum\": tokenFollowType, \"union\": tokenFollowType\n    };\n    var matching = {\"[\": \"]\", \"{\": \"}\", \"(\": \")\", \"<\": \">\"};\n\n    function tokenBase(stream, state) {\n      if (stream.eatSpace()) {\n        return null;\n      }\n\n      // Macros\n      if (state.lastToken != \"\\\\\" && stream.match(\"{%\", false)) {\n        return chain(tokenMacro(\"%\", \"%\"), stream, state);\n      }\n\n      if (state.lastToken != \"\\\\\" && stream.match(\"{{\", false)) {\n        return chain(tokenMacro(\"{\", \"}\"), stream, state);\n      }\n\n      // Comments\n      if (stream.peek() == \"#\") {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n\n      // Variables and keywords\n      var matched;\n      if (stream.match(idents)) {\n        stream.eat(/[?!]/);\n\n        matched = stream.current();\n        if (stream.eat(\":\")) {\n          return \"atom\";\n        } else if (state.lastToken == \".\") {\n          return \"property\";\n        } else if (keywords.test(matched)) {\n          if (indentKeywords.test(matched)) {\n            if (!(matched == \"fun\" && state.blocks.indexOf(\"lib\") >= 0) && !(matched == \"def\" && state.lastToken == \"abstract\")) {\n              state.blocks.push(matched);\n              state.currentIndent += 1;\n            }\n          } else if ((state.lastStyle == \"operator\" || !state.lastStyle) && indentExpressionKeywords.test(matched)) {\n            state.blocks.push(matched);\n            state.currentIndent += 1;\n          } else if (matched == \"end\") {\n            state.blocks.pop();\n            state.currentIndent -= 1;\n          }\n\n          if (nextTokenizer.hasOwnProperty(matched)) {\n            state.tokenize.push(nextTokenizer[matched]);\n          }\n\n          return \"keyword\";\n        } else if (atomWords.test(matched)) {\n          return \"atom\";\n        }\n\n        return \"variable\";\n      }\n\n      // Class variables and instance variables\n      // or attributes\n      if (stream.eat(\"@\")) {\n        if (stream.peek() == \"[\") {\n          return chain(tokenNest(\"[\", \"]\", \"meta\"), stream, state);\n        }\n\n        stream.eat(\"@\");\n        stream.match(idents) || stream.match(types);\n        return \"variable-2\";\n      }\n\n      // Constants and types\n      if (stream.match(types)) {\n        return \"tag\";\n      }\n\n      // Symbols or ':' operator\n      if (stream.eat(\":\")) {\n        if (stream.eat(\"\\\"\")) {\n          return chain(tokenQuote(\"\\\"\", \"atom\", false), stream, state);\n        } else if (stream.match(idents) || stream.match(types) ||\n                   stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators)) {\n          return \"atom\";\n        }\n        stream.eat(\":\");\n        return \"operator\";\n      }\n\n      // Strings\n      if (stream.eat(\"\\\"\")) {\n        return chain(tokenQuote(\"\\\"\", \"string\", true), stream, state);\n      }\n\n      // Strings or regexps or macro variables or '%' operator\n      if (stream.peek() == \"%\") {\n        var style = \"string\";\n        var embed = true;\n        var delim;\n\n        if (stream.match(\"%r\")) {\n          // Regexps\n          style = \"string-2\";\n          delim = stream.next();\n        } else if (stream.match(\"%w\")) {\n          embed = false;\n          delim = stream.next();\n        } else if (stream.match(\"%q\")) {\n          embed = false;\n          delim = stream.next();\n        } else {\n          if(delim = stream.match(/^%([^\\w\\s=])/)) {\n            delim = delim[1];\n          } else if (stream.match(/^%[a-zA-Z0-9_\\u009F-\\uFFFF]*/)) {\n            // Macro variables\n            return \"meta\";\n          } else {\n            // '%' operator\n            return \"operator\";\n          }\n        }\n\n        if (matching.hasOwnProperty(delim)) {\n          delim = matching[delim];\n        }\n        return chain(tokenQuote(delim, style, embed), stream, state);\n      }\n\n      // Here Docs\n      if (matched = stream.match(/^<<-('?)([A-Z]\\w*)\\1/)) {\n        return chain(tokenHereDoc(matched[2], !matched[1]), stream, state)\n      }\n\n      // Characters\n      if (stream.eat(\"'\")) {\n        stream.match(/^(?:[^']|\\\\(?:[befnrtv0'\"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\\{[0-9a-fA-F]{1,6}\\})))/);\n        stream.eat(\"'\");\n        return \"atom\";\n      }\n\n      // Numbers\n      if (stream.eat(\"0\")) {\n        if (stream.eat(\"x\")) {\n          stream.match(/^[0-9a-fA-F]+/);\n        } else if (stream.eat(\"o\")) {\n          stream.match(/^[0-7]+/);\n        } else if (stream.eat(\"b\")) {\n          stream.match(/^[01]+/);\n        }\n        return \"number\";\n      }\n\n      if (stream.eat(/^\\d/)) {\n        stream.match(/^\\d*(?:\\.\\d+)?(?:[eE][+-]?\\d+)?/);\n        return \"number\";\n      }\n\n      // Operators\n      if (stream.match(operators)) {\n        stream.eat(\"=\"); // Operators can follow assign symbol.\n        return \"operator\";\n      }\n\n      if (stream.match(conditionalOperators) || stream.match(anotherOperators)) {\n        return \"operator\";\n      }\n\n      // Parens and braces\n      if (matched = stream.match(/[({[]/, false)) {\n        matched = matched[0];\n        return chain(tokenNest(matched, matching[matched], null), stream, state);\n      }\n\n      // Escapes\n      if (stream.eat(\"\\\\\")) {\n        stream.next();\n        return \"meta\";\n      }\n\n      stream.next();\n      return null;\n    }\n\n    function tokenNest(begin, end, style, started) {\n      return function (stream, state) {\n        if (!started && stream.match(begin)) {\n          state.tokenize[state.tokenize.length - 1] = tokenNest(begin, end, style, true);\n          state.currentIndent += 1;\n          return style;\n        }\n\n        var nextStyle = tokenBase(stream, state);\n        if (stream.current() === end) {\n          state.tokenize.pop();\n          state.currentIndent -= 1;\n          nextStyle = style;\n        }\n\n        return nextStyle;\n      };\n    }\n\n    function tokenMacro(begin, end, started) {\n      return function (stream, state) {\n        if (!started && stream.match(\"{\" + begin)) {\n          state.currentIndent += 1;\n          state.tokenize[state.tokenize.length - 1] = tokenMacro(begin, end, true);\n          return \"meta\";\n        }\n\n        if (stream.match(end + \"}\")) {\n          state.currentIndent -= 1;\n          state.tokenize.pop();\n          return \"meta\";\n        }\n\n        return tokenBase(stream, state);\n      };\n    }\n\n    function tokenMacroDef(stream, state) {\n      if (stream.eatSpace()) {\n        return null;\n      }\n\n      var matched;\n      if (matched = stream.match(idents)) {\n        if (matched == \"def\") {\n          return \"keyword\";\n        }\n        stream.eat(/[?!]/);\n      }\n\n      state.tokenize.pop();\n      return \"def\";\n    }\n\n    function tokenFollowIdent(stream, state) {\n      if (stream.eatSpace()) {\n        return null;\n      }\n\n      if (stream.match(idents)) {\n        stream.eat(/[!?]/);\n      } else {\n        stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators);\n      }\n      state.tokenize.pop();\n      return \"def\";\n    }\n\n    function tokenFollowType(stream, state) {\n      if (stream.eatSpace()) {\n        return null;\n      }\n\n      stream.match(types);\n      state.tokenize.pop();\n      return \"def\";\n    }\n\n    function tokenQuote(end, style, embed) {\n      return function (stream, state) {\n        var escaped = false;\n\n        while (stream.peek()) {\n          if (!escaped) {\n            if (stream.match(\"{%\", false)) {\n              state.tokenize.push(tokenMacro(\"%\", \"%\"));\n              return style;\n            }\n\n            if (stream.match(\"{{\", false)) {\n              state.tokenize.push(tokenMacro(\"{\", \"}\"));\n              return style;\n            }\n\n            if (embed && stream.match(\"#{\", false)) {\n              state.tokenize.push(tokenNest(\"#{\", \"}\", \"meta\"));\n              return style;\n            }\n\n            var ch = stream.next();\n\n            if (ch == end) {\n              state.tokenize.pop();\n              return style;\n            }\n\n            escaped = embed && ch == \"\\\\\";\n          } else {\n            stream.next();\n            escaped = false;\n          }\n        }\n\n        return style;\n      };\n    }\n\n    function tokenHereDoc(phrase, embed) {\n      return function (stream, state) {\n        if (stream.sol()) {\n          stream.eatSpace()\n          if (stream.match(phrase)) {\n            state.tokenize.pop();\n            return \"string\";\n          }\n        }\n\n        var escaped = false;\n        while (stream.peek()) {\n          if (!escaped) {\n            if (stream.match(\"{%\", false)) {\n              state.tokenize.push(tokenMacro(\"%\", \"%\"));\n              return \"string\";\n            }\n\n            if (stream.match(\"{{\", false)) {\n              state.tokenize.push(tokenMacro(\"{\", \"}\"));\n              return \"string\";\n            }\n\n            if (embed && stream.match(\"#{\", false)) {\n              state.tokenize.push(tokenNest(\"#{\", \"}\", \"meta\"));\n              return \"string\";\n            }\n\n            escaped = embed && stream.next() == \"\\\\\";\n          } else {\n            stream.next();\n            escaped = false;\n          }\n        }\n\n        return \"string\";\n      }\n    }\n\n    return {\n      startState: function () {\n        return {\n          tokenize: [tokenBase],\n          currentIndent: 0,\n          lastToken: null,\n          lastStyle: null,\n          blocks: []\n        };\n      },\n\n      token: function (stream, state) {\n        var style = state.tokenize[state.tokenize.length - 1](stream, state);\n        var token = stream.current();\n\n        if (style && style != \"comment\") {\n          state.lastToken = token;\n          state.lastStyle = style;\n        }\n\n        return style;\n      },\n\n      indent: function (state, textAfter) {\n        textAfter = textAfter.replace(/^\\s*(?:\\{%)?\\s*|\\s*(?:%\\})?\\s*$/g, \"\");\n\n        if (dedentKeywords.test(textAfter) || dedentPunctuals.test(textAfter)) {\n          return config.indentUnit * (state.currentIndent - 1);\n        }\n\n        return config.indentUnit * state.currentIndent;\n      },\n\n      fold: \"indent\",\n      electricInput: wordRegExp(dedentPunctualsArray.concat(dedentKeywordsArray), true),\n      lineComment: '#'\n    };\n  });\n\n  CodeMirror.defineMIME(\"text/x-crystal\", \"crystal\");\n});\n"]}