Commit fbe82b863244bbc84afe68109f5c042f4c49c14f

Mattias 2018-02-05T08:36:19

added tsx support (#1280) * added tsx support * fixed order in components.js and added tsx example file * escape less than and capitalize tsx

diff --git a/components.js b/components.js
index 8654594..4af537a 100644
--- a/components.js
+++ b/components.js
@@ -506,6 +506,10 @@ var components = {
 			"require": ["markup", "javascript"],
 			"owner": "vkbansal"
 		},
+		"tsx": {
+			"title": "React TSX", 
+			"require": ["jsx", "typescript"]
+		},
 		"renpy": {
 			"title": "Ren'py",
 			"owner": "HyuchiaDiego"
diff --git a/components/prism-tsx.js b/components/prism-tsx.js
new file mode 100644
index 0000000..d566701
--- /dev/null
+++ b/components/prism-tsx.js
@@ -0,0 +1,2 @@
+var typescript = Prism.util.clone(Prism.languages.typescript);
+Prism.languages.tsx = Prism.languages.extend('jsx', typescript);
\ No newline at end of file
diff --git a/components/prism-tsx.min.js b/components/prism-tsx.min.js
new file mode 100644
index 0000000..deb84d3
--- /dev/null
+++ b/components/prism-tsx.min.js
@@ -0,0 +1 @@
+var typescript=Prism.util.clone(Prism.languages.typescript);Prism.languages.tsx=Prism.languages.extend("jsx",typescript);
\ No newline at end of file
diff --git a/examples/prism-tsx.html b/examples/prism-tsx.html
new file mode 100644
index 0000000..636aa3f
--- /dev/null
+++ b/examples/prism-tsx.html
@@ -0,0 +1,34 @@
+<h1>React TSX</h1>
+<p>To use this language, use the class "language-tsx".</p>
+
+<h2>Full example</h2>
+<pre><code>import * as React from 'react';
+
+interface IState {
+	clicks: number;
+}
+
+export class Clicker extends React.Component&lt;any, IState> {
+	constructor(props) {
+		super(props);
+
+		this.state = {
+			clicks: 0,
+		};
+	}
+
+	public clickHandler = () => {
+		this.setState({ clicks: this.state.clicks + 1 });
+	}
+
+	public render() {
+		return (
+			&lt;div>
+				&lt;p>You have clicked the button {this.state.clicks} time(s).&lt;/p>
+				&lt;p>
+					&lt;button onClick={this.clickHandler}>click me&lt;/button>
+				&lt;/p>
+			&lt;/div>
+		);
+	}
+}</code></pre>
diff --git a/plugins/autoloader/prism-autoloader.js b/plugins/autoloader/prism-autoloader.js
index 0d4a570..ed1ded5 100644
--- a/plugins/autoloader/prism-autoloader.js
+++ b/plugins/autoloader/prism-autoloader.js
@@ -4,7 +4,7 @@
 	}
 
 	// The dependencies map is built automatically with gulp
-	var lang_dependencies = /*languages_placeholder[*/{"javascript":"clike","actionscript":"javascript","arduino":"cpp","aspnet":"markup","bison":"c","c":"clike","csharp":"clike","cpp":"c","coffeescript":"javascript","crystal":"ruby","css-extras":"css","d":"clike","dart":"clike","django":"markup","fsharp":"clike","flow":"javascript","glsl":"clike","go":"clike","groovy":"clike","haml":"ruby","handlebars":"markup","haxe":"clike","java":"clike","jolie":"clike","kotlin":"clike","less":"css","markdown":"markup","n4js":"javascript","nginx":"clike","objectivec":"c","opencl":"cpp","parser":"markup","php":"clike","php-extras":"php","processing":"clike","protobuf":"clike","pug":"javascript","qore":"clike","jsx":["markup","javascript"],"reason":"clike","ruby":"clike","sass":"css","scss":"css","scala":"java","smarty":"markup","swift":"clike","textile":"markup","twig":"markup","typescript":"javascript","vbnet":"basic","wiki":"markup","xeora":"markup"}/*]*/;
+	var lang_dependencies = /*languages_placeholder[*/{"javascript":"clike","actionscript":"javascript","arduino":"cpp","aspnet":"markup","bison":"c","c":"clike","csharp":"clike","cpp":"c","coffeescript":"javascript","crystal":"ruby","css-extras":"css","d":"clike","dart":"clike","django":"markup","fsharp":"clike","flow":"javascript","glsl":"clike","go":"clike","groovy":"clike","haml":"ruby","handlebars":"markup","haxe":"clike","java":"clike","jolie":"clike","kotlin":"clike","less":"css","markdown":"markup","n4js":"javascript","nginx":"clike","objectivec":"c","opencl":"cpp","parser":"markup","php":"clike","php-extras":"php","processing":"clike","protobuf":"clike","pug":"javascript","qore":"clike","jsx":["markup","javascript"],"reason":"clike","ruby":"clike","sass":"css","scss":"css","scala":"java","smarty":"markup","swift":"clike","textile":"markup","tsx":["jsx","typescript"],"twig":"markup","typescript":"javascript","vbnet":"basic","wiki":"markup","xeora":"markup"}/*]*/;
 
 	var lang_data = {};
 
diff --git a/plugins/autoloader/prism-autoloader.min.js b/plugins/autoloader/prism-autoloader.min.js
index fd3f225..6812a9f 100644
--- a/plugins/autoloader/prism-autoloader.min.js
+++ b/plugins/autoloader/prism-autoloader.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&document.createElement){var e={javascript:"clike",actionscript:"javascript",arduino:"cpp",aspnet:"markup",bison:"c",c:"clike",csharp:"clike",cpp:"c",coffeescript:"javascript",crystal:"ruby","css-extras":"css",d:"clike",dart:"clike",django:"markup",fsharp:"clike",flow:"javascript",glsl:"clike",go:"clike",groovy:"clike",haml:"ruby",handlebars:"markup",haxe:"clike",java:"clike",jolie:"clike",kotlin:"clike",less:"css",markdown:"markup",n4js:"javascript",nginx:"clike",objectivec:"c",opencl:"cpp",parser:"markup",php:"clike","php-extras":"php",processing:"clike",protobuf:"clike",pug:"javascript",qore:"clike",jsx:["markup","javascript"],reason:"clike",ruby:"clike",sass:"css",scss:"css",scala:"java",smarty:"markup",swift:"clike",textile:"markup",twig:"markup",typescript:"javascript",vbnet:"basic",wiki:"markup",xeora:"markup"},a={},c="none",s=document.getElementsByTagName("script");s=s[s.length-1];var r="components/";if(s.hasAttribute("data-autoloader-path")){var t=s.getAttribute("data-autoloader-path").trim();t.length>0&&!/^[a-z]+:\/\//i.test(s.src)&&(r=t.replace(/\/?$/,"/"))}else/[\w-]+\.js$/.test(s.src)&&(r=s.src.replace(/[\w-]+\.js$/,"components/"));var n=Prism.plugins.autoloader={languages_path:r,use_minified:!0},s=function(e,a,c){var s=document.createElement("script");s.src=e,s.async=!0,s.onload=function(){document.body.removeChild(s),a&&a()},s.onerror=function(){document.body.removeChild(s),c&&c()},document.body.appendChild(s)},i=function(e){return n.languages_path+"prism-"+e+(n.use_minified?".min":"")+".js"},l=function(e,c){var s=a[e];s||(s=a[e]={});var r=c.getAttribute("data-dependencies");!r&&c.parentNode&&"pre"===c.parentNode.tagName.toLowerCase()&&(r=c.parentNode.getAttribute("data-dependencies")),r=r?r.split(/\s*,\s*/g):[],o(r,function(){u(e,function(){Prism.highlightElement(c)})})},o=function(e,a,c){"string"==typeof e&&(e=[e]);var s=0,r=e.length,t=function(){r>s?u(e[s],function(){s++,t()},function(){c&&c(e[s])}):s===r&&a&&a(e)};t()},u=function(c,r,t){var n=function(){var e=!1;c.indexOf("!")>=0&&(e=!0,c=c.replace("!",""));var n=a[c];if(n||(n=a[c]={}),r&&(n.success_callbacks||(n.success_callbacks=[]),n.success_callbacks.push(r)),t&&(n.error_callbacks||(n.error_callbacks=[]),n.error_callbacks.push(t)),!e&&Prism.languages[c])p(c);else if(!e&&n.error)k(c);else if(e||!n.loading){n.loading=!0;var l=i(c);s(l,function(){n.loading=!1,p(c)},function(){n.loading=!1,n.error=!0,k(c)})}},l=e[c];l&&l.length?o(l,n):n()},p=function(e){a[e]&&a[e].success_callbacks&&a[e].success_callbacks.length&&a[e].success_callbacks.forEach(function(a){a(e)})},k=function(e){a[e]&&a[e].error_callbacks&&a[e].error_callbacks.length&&a[e].error_callbacks.forEach(function(a){a(e)})};Prism.hooks.add("complete",function(e){e.element&&e.language&&!e.grammar&&e.language!==c&&l(e.language,e.element)})}}();
\ No newline at end of file
+!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&document.createElement){var e={javascript:"clike",actionscript:"javascript",arduino:"cpp",aspnet:"markup",bison:"c",c:"clike",csharp:"clike",cpp:"c",coffeescript:"javascript",crystal:"ruby","css-extras":"css",d:"clike",dart:"clike",django:"markup",fsharp:"clike",flow:"javascript",glsl:"clike",go:"clike",groovy:"clike",haml:"ruby",handlebars:"markup",haxe:"clike",java:"clike",jolie:"clike",kotlin:"clike",less:"css",markdown:"markup",n4js:"javascript",nginx:"clike",objectivec:"c",opencl:"cpp",parser:"markup",php:"clike","php-extras":"php",processing:"clike",protobuf:"clike",pug:"javascript",qore:"clike",jsx:["markup","javascript"],reason:"clike",ruby:"clike",sass:"css",scss:"css",scala:"java",smarty:"markup",swift:"clike",textile:"markup",tsx:["jsx","typescript"],twig:"markup",typescript:"javascript",vbnet:"basic",wiki:"markup",xeora:"markup"},a={},c="none",s=document.getElementsByTagName("script");s=s[s.length-1];var r="components/";if(s.hasAttribute("data-autoloader-path")){var t=s.getAttribute("data-autoloader-path").trim();t.length>0&&!/^[a-z]+:\/\//i.test(s.src)&&(r=t.replace(/\/?$/,"/"))}else/[\w-]+\.js$/.test(s.src)&&(r=s.src.replace(/[\w-]+\.js$/,"components/"));var n=Prism.plugins.autoloader={languages_path:r,use_minified:!0},s=function(e,a,c){var s=document.createElement("script");s.src=e,s.async=!0,s.onload=function(){document.body.removeChild(s),a&&a()},s.onerror=function(){document.body.removeChild(s),c&&c()},document.body.appendChild(s)},i=function(e){return n.languages_path+"prism-"+e+(n.use_minified?".min":"")+".js"},l=function(e,c){var s=a[e];s||(s=a[e]={});var r=c.getAttribute("data-dependencies");!r&&c.parentNode&&"pre"===c.parentNode.tagName.toLowerCase()&&(r=c.parentNode.getAttribute("data-dependencies")),r=r?r.split(/\s*,\s*/g):[],o(r,function(){p(e,function(){Prism.highlightElement(c)})})},o=function(e,a,c){"string"==typeof e&&(e=[e]);var s=0,r=e.length,t=function(){r>s?p(e[s],function(){s++,t()},function(){c&&c(e[s])}):s===r&&a&&a(e)};t()},p=function(c,r,t){var n=function(){var e=!1;c.indexOf("!")>=0&&(e=!0,c=c.replace("!",""));var n=a[c];if(n||(n=a[c]={}),r&&(n.success_callbacks||(n.success_callbacks=[]),n.success_callbacks.push(r)),t&&(n.error_callbacks||(n.error_callbacks=[]),n.error_callbacks.push(t)),!e&&Prism.languages[c])u(c);else if(!e&&n.error)k(c);else if(e||!n.loading){n.loading=!0;var l=i(c);s(l,function(){n.loading=!1,u(c)},function(){n.loading=!1,n.error=!0,k(c)})}},l=e[c];l&&l.length?o(l,n):n()},u=function(e){a[e]&&a[e].success_callbacks&&a[e].success_callbacks.length&&a[e].success_callbacks.forEach(function(a){a(e)})},k=function(e){a[e]&&a[e].error_callbacks&&a[e].error_callbacks.length&&a[e].error_callbacks.forEach(function(a){a(e)})};Prism.hooks.add("complete",function(e){e.element&&e.language&&!e.grammar&&e.language!==c&&l(e.language,e.element)})}}();
\ No newline at end of file
diff --git a/plugins/show-language/prism-show-language.js b/plugins/show-language/prism-show-language.js
index 082765e..5f0e371 100644
--- a/plugins/show-language/prism-show-language.js
+++ b/plugins/show-language/prism-show-language.js
@@ -11,7 +11,7 @@ if (!Prism.plugins.toolbar) {
 }
 
 // The languages map is built automatically with gulp
-var Languages = /*languages_placeholder[*/{"html":"HTML","xml":"XML","svg":"SVG","mathml":"MathML","css":"CSS","clike":"C-like","javascript":"JavaScript","abap":"ABAP","actionscript":"ActionScript","apacheconf":"Apache Configuration","apl":"APL","applescript":"AppleScript","asciidoc":"AsciiDoc","asm6502":"6502 Assembly","aspnet":"ASP.NET (C#)","autohotkey":"AutoHotkey","autoit":"AutoIt","basic":"BASIC","csharp":"C#","cpp":"C++","coffeescript":"CoffeeScript","csp":"Content-Security-Policy","css-extras":"CSS Extras","django":"Django/Jinja2","fsharp":"F#","glsl":"GLSL","graphql":"GraphQL","http":"HTTP","hpkp":"HTTP Public-Key-Pins","hsts":"HTTP Strict-Transport-Security","ichigojam":"IchigoJam","inform7":"Inform 7","json":"JSON","latex":"LaTeX","livescript":"LiveScript","lolcode":"LOLCODE","matlab":"MATLAB","mel":"MEL","n4js":"N4JS","nasm":"NASM","nginx":"nginx","nsis":"NSIS","objectivec":"Objective-C","ocaml":"OCaml","opencl":"OpenCL","parigp":"PARI/GP","php":"PHP","php-extras":"PHP Extras","powershell":"PowerShell","properties":".properties","protobuf":"Protocol Buffers","jsx":"React JSX","renpy":"Ren'py","rest":"reST (reStructuredText)","sas":"SAS","sass":"Sass (Sass)","scss":"Sass (Scss)","sql":"SQL","typescript":"TypeScript","vbnet":"VB.Net","vhdl":"VHDL","vim":"vim","wiki":"Wiki markup","xojo":"Xojo (REALbasic)","yaml":"YAML"}/*]*/;
+var Languages = /*languages_placeholder[*/{"html":"HTML","xml":"XML","svg":"SVG","mathml":"MathML","css":"CSS","clike":"C-like","javascript":"JavaScript","abap":"ABAP","actionscript":"ActionScript","apacheconf":"Apache Configuration","apl":"APL","applescript":"AppleScript","asciidoc":"AsciiDoc","asm6502":"6502 Assembly","aspnet":"ASP.NET (C#)","autohotkey":"AutoHotkey","autoit":"AutoIt","basic":"BASIC","csharp":"C#","cpp":"C++","coffeescript":"CoffeeScript","csp":"Content-Security-Policy","css-extras":"CSS Extras","django":"Django/Jinja2","fsharp":"F#","glsl":"GLSL","graphql":"GraphQL","http":"HTTP","hpkp":"HTTP Public-Key-Pins","hsts":"HTTP Strict-Transport-Security","ichigojam":"IchigoJam","inform7":"Inform 7","json":"JSON","latex":"LaTeX","livescript":"LiveScript","lolcode":"LOLCODE","matlab":"MATLAB","mel":"MEL","n4js":"N4JS","nasm":"NASM","nginx":"nginx","nsis":"NSIS","objectivec":"Objective-C","ocaml":"OCaml","opencl":"OpenCL","parigp":"PARI/GP","php":"PHP","php-extras":"PHP Extras","powershell":"PowerShell","properties":".properties","protobuf":"Protocol Buffers","jsx":"React JSX","renpy":"Ren'py","rest":"reST (reStructuredText)","sas":"SAS","sass":"Sass (Sass)","scss":"Sass (Scss)","sql":"SQL","tsx":"React Tsx","typescript":"TypeScript","vbnet":"VB.Net","vhdl":"VHDL","vim":"vim","wiki":"Wiki markup","xojo":"Xojo (REALbasic)","yaml":"YAML"}/*]*/;
 Prism.plugins.toolbar.registerButton('show-language', function(env) {
 	var pre = env.element.parentNode;
 	if (!pre || !/pre/i.test(pre.nodeName)) {
diff --git a/plugins/show-language/prism-show-language.min.js b/plugins/show-language/prism-show-language.min.js
index f773d83..5a17ddd 100644
--- a/plugins/show-language/prism-show-language.min.js
+++ b/plugins/show-language/prism-show-language.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document){if(!Prism.plugins.toolbar)return console.warn("Show Languages plugin loaded before Toolbar plugin."),void 0;var e={html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",css:"CSS",clike:"C-like",javascript:"JavaScript",abap:"ABAP",actionscript:"ActionScript",apacheconf:"Apache Configuration",apl:"APL",applescript:"AppleScript",asciidoc:"AsciiDoc",asm6502:"6502 Assembly",aspnet:"ASP.NET (C#)",autohotkey:"AutoHotkey",autoit:"AutoIt",basic:"BASIC",csharp:"C#",cpp:"C++",coffeescript:"CoffeeScript",csp:"Content-Security-Policy","css-extras":"CSS Extras",django:"Django/Jinja2",fsharp:"F#",glsl:"GLSL",graphql:"GraphQL",http:"HTTP",hpkp:"HTTP Public-Key-Pins",hsts:"HTTP Strict-Transport-Security",ichigojam:"IchigoJam",inform7:"Inform 7",json:"JSON",latex:"LaTeX",livescript:"LiveScript",lolcode:"LOLCODE",matlab:"MATLAB",mel:"MEL",n4js:"N4JS",nasm:"NASM",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",parigp:"PARI/GP",php:"PHP","php-extras":"PHP Extras",powershell:"PowerShell",properties:".properties",protobuf:"Protocol Buffers",jsx:"React JSX",renpy:"Ren'py",rest:"reST (reStructuredText)",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)",sql:"SQL",typescript:"TypeScript",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim",wiki:"Wiki markup",xojo:"Xojo (REALbasic)",yaml:"YAML"};Prism.plugins.toolbar.registerButton("show-language",function(t){var a=t.element.parentNode;if(a&&/pre/i.test(a.nodeName)){var s=a.getAttribute("data-language")||e[t.language]||t.language.substring(0,1).toUpperCase()+t.language.substring(1),i=document.createElement("span");return i.textContent=s,i}})}}();
\ No newline at end of file
+!function(){if("undefined"!=typeof self&&self.Prism&&self.document){if(!Prism.plugins.toolbar)return console.warn("Show Languages plugin loaded before Toolbar plugin."),void 0;var e={html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",css:"CSS",clike:"C-like",javascript:"JavaScript",abap:"ABAP",actionscript:"ActionScript",apacheconf:"Apache Configuration",apl:"APL",applescript:"AppleScript",asciidoc:"AsciiDoc",asm6502:"6502 Assembly",aspnet:"ASP.NET (C#)",autohotkey:"AutoHotkey",autoit:"AutoIt",basic:"BASIC",csharp:"C#",cpp:"C++",coffeescript:"CoffeeScript",csp:"Content-Security-Policy","css-extras":"CSS Extras",django:"Django/Jinja2",fsharp:"F#",glsl:"GLSL",graphql:"GraphQL",http:"HTTP",hpkp:"HTTP Public-Key-Pins",hsts:"HTTP Strict-Transport-Security",ichigojam:"IchigoJam",inform7:"Inform 7",json:"JSON",latex:"LaTeX",livescript:"LiveScript",lolcode:"LOLCODE",matlab:"MATLAB",mel:"MEL",n4js:"N4JS",nasm:"NASM",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",parigp:"PARI/GP",php:"PHP","php-extras":"PHP Extras",powershell:"PowerShell",properties:".properties",protobuf:"Protocol Buffers",jsx:"React JSX",renpy:"Ren'py",rest:"reST (reStructuredText)",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)",sql:"SQL",tsx:"React Tsx",typescript:"TypeScript",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim",wiki:"Wiki markup",xojo:"Xojo (REALbasic)",yaml:"YAML"};Prism.plugins.toolbar.registerButton("show-language",function(t){var a=t.element.parentNode;if(a&&/pre/i.test(a.nodeName)){var s=a.getAttribute("data-language")||e[t.language]||t.language.substring(0,1).toUpperCase()+t.language.substring(1),i=document.createElement("span");return i.textContent=s,i}})}}();
\ No newline at end of file
diff --git a/tests/languages/tsx/tag_feature.test b/tests/languages/tsx/tag_feature.test
new file mode 100644
index 0000000..71d779e
--- /dev/null
+++ b/tests/languages/tsx/tag_feature.test
@@ -0,0 +1,106 @@
+var myDivElement = <div className="foo" />;
+var myElement = <MyComponent someProperty={true} />;
+<div {...foo}>
+class Test extends Component {
+	render() {
+		return <p onClick={this.clickHandler}>Hello world.</p>;
+	}
+}
+
+----------------------------------------------------
+
+[
+	["keyword", "var"],
+	" myDivElement ",
+	["operator", "="],
+	["tag", [
+		["tag", [
+			["punctuation", "<"],
+			"div"
+		]],
+		["attr-name", ["className"]],
+		["attr-value", [
+			["punctuation", "="],
+			["punctuation", "\""],
+			"foo",
+			["punctuation", "\""]
+		]],
+		["punctuation", "/>"]
+	]],
+	["punctuation", ";"],
+
+	["keyword", "var"],
+	" myElement ",
+	["operator", "="],
+	["tag", [
+		["tag", [
+			["punctuation", "<"],
+			"MyComponent"
+		]],
+		["attr-name", ["someProperty"]],
+		["script", [
+			 ["punctuation", "="],
+			 ["punctuation", "{"],
+			 ["boolean", "true"],
+			 ["punctuation", "}"]
+		]],
+		["punctuation", "/>"]
+	]],
+	["punctuation", ";"],
+	["tag", [
+		["tag", [
+			["punctuation", "<"],
+			"div"
+		]],
+		["spread", [
+			["punctuation", "{"],
+			["punctuation", "..."],
+			["attr-value", "foo"],
+			["punctuation", "}"]
+		]],
+		["punctuation", ">"]
+	]],
+
+	["keyword",  "class"],
+	["class-name", ["Test"]],
+	["keyword", "extends"],
+	["class-name", ["Component"]],
+	["punctuation", "{"],
+	["function", "render"],
+	["punctuation", "("],
+	["punctuation", ")"],
+	["punctuation", "{"],
+	["keyword","return"],
+	["tag", [
+		["tag", [
+			["punctuation", "<"],
+			"p"
+		]],
+		["attr-name", ["onClick"]],
+		["script", [
+			["punctuation", "="],
+			["punctuation", "{"],
+			["keyword", "this"],
+			["punctuation", "."],
+			"clickHandler",
+			["punctuation", "}"]
+		]],
+		["punctuation", ">"]
+	]],
+	"Hello world",
+	["punctuation", "."],
+	["tag", [
+		["tag", [
+			["punctuation", "</"],
+			"p"
+		]],
+		["punctuation", ">"]
+	]],
+	["punctuation", ";"],
+	["punctuation", "}"],
+	["punctuation","}"]
+]
+
+----------------------------------------------------
+
+Checks for TSX tags.
\ No newline at end of file