diff --git a/ace-modes.d.ts b/ace-modes.d.ts
index 544811a4c8b..e1a88ebc78c 100644
--- a/ace-modes.d.ts
+++ b/ace-modes.d.ts
@@ -553,6 +553,9 @@ declare module "ace-code/src/mode/jssm_highlight_rules" {
declare module "ace-code/src/mode/jsx" {
export const Mode: new () => import(".").Ace.SyntaxMode;
}
+declare module "ace-code/src/mode/jsx_highlight_rules" {
+ export const JsxHighlightRules: new () => import(".").Ace.HighlightRules;
+}
declare module "ace-code/src/mode/julia" {
export const Mode: new () => import(".").Ace.SyntaxMode;
}
diff --git a/demo/kitchen-sink/docs/jsx.jsx b/demo/kitchen-sink/docs/jsx.jsx
index c74ead6cddb..fbbeb662689 100644
--- a/demo/kitchen-sink/docs/jsx.jsx
+++ b/demo/kitchen-sink/docs/jsx.jsx
@@ -1,9 +1,9 @@
-import * as React from "react";
-
-export default () => {
- return (
-
- Keywords here are not highlighted, for example class or instance.
-
- );
+/*EXPECTED
+hello world!
+*/
+class Test {
+ static function run() : void {
+ // console.log("hello world!");
+ log "hello world!";
+ }
}
\ No newline at end of file
diff --git a/src/ext/modelist.js b/src/ext/modelist.js
index 791174fe07d..96a03f35672 100644
--- a/src/ext/modelist.js
+++ b/src/ext/modelist.js
@@ -126,7 +126,7 @@ var supportedModes = {
Jack: ["jack"],
Jade: ["jade|pug"],
Java: ["java"],
- JavaScript: ["js|jsm|cjs|mjs"],
+ JavaScript: ["js|jsm|jsx|cjs|mjs"],
JEXL: ["jexl"],
JSON: ["json"],
JSON5: ["json5"],
diff --git a/src/mode/_test/tokens_jsx.json b/src/mode/_test/tokens_jsx.json
index 75f747fc08c..d1a740b0907 100644
--- a/src/mode/_test/tokens_jsx.json
+++ b/src/mode/_test/tokens_jsx.json
@@ -1,62 +1,51 @@
[[
+ "comment",
+ ["comment","/*EXPECTED"]
+],[
+ "comment",
+ ["comment","hello world!"]
+],[
"start",
- ["keyword","import"],
- ["text"," "],
- ["keyword.operator","*"],
- ["text"," "],
- ["identifier","as"],
- ["text"," "],
- ["identifier","React"],
+ ["comment","*/"]
+],[
+ "start",
+ ["keyword","class"],
["text"," "],
- ["keyword","from"],
+ ["language.support.class","Test"],
["text"," "],
- ["string","\"react\""],
- ["punctuation.operator",";"]
-],[
- "start"
+ ["paren.lparen","{"]
],[
"start",
- ["keyword","export"],
+ ["text"," "],
+ ["keyword","static"],
["text"," "],
- ["keyword","default"],
+ ["storage.type","function"],
["text"," "],
+ ["entity.name.function","run"],
["paren.lparen","("],
["paren.rparen",")"],
["text"," "],
- ["storage.type","=>"],
+ ["punctuation.operator",":"],
+ ["text"," "],
+ ["keyword","void"],
["text"," "],
["paren.lparen","{"]
],[
"start",
- ["text"," "],
- ["keyword","return"],
- ["text"," "],
- ["paren.lparen","("]
-],[
- ["jsx",1],
- ["text"," "],
- ["meta.tag.punctuation.tag-open.xml","<"],
- ["meta.tag.tag-name.xml","div"],
- ["text.tag-whitespace.xml"," "],
- ["entity.other.attribute-name.xml","variant"],
- ["keyword.operator.attribute-equals.xml","="],
- ["string.attribute-value.xml","\"p\""],
- ["meta.tag.punctuation.tag-close.xml",">"]
-],[
- ["jsx",1],
- ["string"," Keywords here are not highlighted, for example class or instance."]
+ ["text"," "],
+ ["comment","// console.log(\"hello world!\");"]
],[
"start",
- ["string"," "],
- ["meta.tag.punctuation.end-tag-open.xml",""],
- ["meta.tag.tag-name.xml","div"],
- ["meta.tag.punctuation.tag-close.xml",">"]
+ ["text"," "],
+ ["keyword","log"],
+ ["text"," "],
+ ["string","\"hello world!\""],
+ ["punctuation.operator",";"]
],[
"start",
- ["text"," "],
- ["paren.rparen",")"],
- ["punctuation.operator",";"]
+ ["text"," "],
+ ["paren.rparen","}"]
],[
- "no_regex",
+ "start",
["paren.rparen","}"]
]]
\ No newline at end of file
diff --git a/src/mode/jsx.js b/src/mode/jsx.js
index be92ef48b9b..e2d588beb8b 100644
--- a/src/mode/jsx.js
+++ b/src/mode/jsx.js
@@ -1,19 +1,52 @@
"use strict";
var oop = require("../lib/oop");
-var jsMode = require("./javascript").Mode;
+var TextMode = require("./text").Mode;
+var JsxHighlightRules = require("./jsx_highlight_rules").JsxHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
function Mode() {
- jsMode.call(this);
- this.$highlightRuleConfig = {jsx: true};
+ this.HighlightRules = JsxHighlightRules;
+ this.$outdent = new MatchingBraceOutdent();
+ this.$behaviour = this.$defaultBehaviour;
+ this.foldingRules = new CStyleFoldMode();
}
-oop.inherits(Mode, jsMode);
+oop.inherits(Mode, TextMode);
(function() {
- // disable jshint
- this.createWorker = function() {
- return null;
+
+ this.lineCommentStart = "//";
+ this.blockComment = {start: "/*", end: "*/"};
+
+ this.getNextLineIndent = function(state, line, tab) {
+ var indent = this.$getIndent(line);
+
+ var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+ var tokens = tokenizedLine.tokens;
+
+ if (tokens.length && tokens[tokens.length-1].type == "comment") {
+ return indent;
+ }
+
+ if (state == "start") {
+ var match = line.match(/^.*[\{\(\[]\s*$/);
+ if (match) {
+ indent += tab;
+ }
+ }
+
+ return indent;
};
+
+ this.checkOutdent = function(state, line, input) {
+ return this.$outdent.checkOutdent(line, input);
+ };
+
+ this.autoOutdent = function(state, doc, row) {
+ this.$outdent.autoOutdent(doc, row);
+ };
+
this.$id = "ace/mode/jsx";
}).call(Mode.prototype);
diff --git a/src/mode/jsx_highlight_rules.js b/src/mode/jsx_highlight_rules.js
new file mode 100644
index 00000000000..0fef0aa7f48
--- /dev/null
+++ b/src/mode/jsx_highlight_rules.js
@@ -0,0 +1,117 @@
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JsxHighlightRules = function() {
+ var keywords = lang.arrayToMap(
+ ("break|do|instanceof|typeof|case|else|new|var|catch|finally|return|void|continue|for|switch|default|while|function|this|" +
+ "if|throw|" +
+ "delete|in|try|" +
+ "class|extends|super|import|from|into|implements|interface|static|mixin|override|abstract|final|" +
+ "number|int|string|boolean|variant|" +
+ "log|assert").split("|")
+ );
+
+ var buildinConstants = lang.arrayToMap(
+ ("null|true|false|NaN|Infinity|__FILE__|__LINE__|undefined").split("|")
+ );
+
+ var reserved = lang.arrayToMap(
+ ("debugger|with|" +
+ "const|export|" +
+ "let|private|public|yield|protected|" +
+ "extern|native|as|operator|__fake__|__readonly__").split("|")
+ );
+
+ var identifierRe = "[a-zA-Z_][a-zA-Z0-9_]*\\b";
+
+ this.$rules = {
+ "start" : [
+ {
+ token : "comment",
+ regex : "\\/\\/.*$"
+ },
+ DocCommentHighlightRules.getStartRule("doc-start"),
+ {
+ token : "comment", // multi line comment
+ regex : "\\/\\*",
+ next : "comment"
+ }, {
+ token : "string.regexp",
+ regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
+ }, {
+ token : "string", // single line
+ regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+ }, {
+ token : "string", // single line
+ regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+ }, {
+ token : "constant.numeric", // hex
+ regex : "0[xX][0-9a-fA-F]+\\b"
+ }, {
+ token : "constant.numeric", // float
+ regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+ }, {
+ token : "constant.language.boolean",
+ regex : "(?:true|false)\\b"
+ }, {
+ token : [
+ "storage.type",
+ "text",
+ "entity.name.function"
+ ],
+ regex : "(function)(\\s+)(" + identifierRe + ")"
+ }, {
+ token : function(value) {
+ if (value == "this")
+ return "variable.language";
+ else if (value == "function")
+ return "storage.type";
+ else if (keywords.hasOwnProperty(value) || reserved.hasOwnProperty(value))
+ return "keyword";
+ else if (buildinConstants.hasOwnProperty(value))
+ return "constant.language";
+ else if (/^_?[A-Z][a-zA-Z0-9_]*$/.test(value))
+ return "language.support.class";
+ else
+ return "identifier";
+ },
+ // TODO: Unicode escape sequences
+ // TODO: Unicode identifiers
+ regex : identifierRe
+ }, {
+ token : "keyword.operator",
+ regex : "!|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+ }, {
+ token : "punctuation.operator",
+ regex : "\\?|\\:|\\,|\\;|\\."
+ }, {
+ token : "paren.lparen",
+ regex : "[[({<]"
+ }, {
+ token : "paren.rparen",
+ regex : "[\\])}>]"
+ }, {
+ token : "text",
+ regex : "\\s+"
+ }
+ ],
+ "comment" : [
+ {
+ token : "comment", // closing comment
+ regex : "\\*\\/",
+ next : "start"
+ }, {
+ defaultToken : "comment"
+ }
+ ]
+ };
+
+ this.embedRules(DocCommentHighlightRules, "doc-",
+ [ DocCommentHighlightRules.getEndRule("start") ]);
+};
+
+oop.inherits(JsxHighlightRules, TextHighlightRules);
+
+exports.JsxHighlightRules = JsxHighlightRules;