diff --git a/components.js b/components.js index 97a59fc7e1..7a221fc78a 100644 --- a/components.js +++ b/components.js @@ -223,6 +223,11 @@ var components = { "title": "Haskell", "owner": "bholst" }, + "haxe": { + "title": "Haxe", + "require": "clike", + "owner": "Golmote" + }, "http": { "title": "HTTP", "owner": "danielgtaylor" diff --git a/components/prism-haxe.js b/components/prism-haxe.js new file mode 100644 index 0000000000..70d9add988 --- /dev/null +++ b/components/prism-haxe.js @@ -0,0 +1,43 @@ +Prism.languages.haxe = Prism.languages.extend('clike', { + // Strings can be multi-line + 'string': { + pattern: /(["'])(?:(?!\1)[^\\]|\\[\s\S])*\1/, + inside: { + 'interpolation': { + pattern: /(^|[^\\])\$(?:\w+|\{[^}]+\})/, + lookbehind: true, + inside: { + 'interpolation': { + pattern: /^\$\w*/, + alias: 'variable' + } + // See rest below + } + } + } + }, + // The final look-ahead prevents highlighting of keywords if expressions such as "haxe.macro.Expr" + 'keyword': /\bthis\b|\b(?:abstract|as|break|case|cast|catch|class|continue|default|do|dynamic|else|enum|extends|extern|from|for|function|if|implements|import|in|inline|interface|macro|new|null|override|public|private|return|static|super|switch|throw|to|try|typedef|using|var|while)(?!\.)\b/, + 'operator': /\.{3}|\+\+?|-[->]?|[=!]=?|&&?|\|\|?|<[<=]?|>[>=]?|[*\/%~^]/ +}); +Prism.languages.insertBefore('haxe', 'class-name', { + 'regex': { + pattern: /~\/(?:[^\/\\\r\n]|\\.)+\/[igmsu]*/ + } +}); +Prism.languages.insertBefore('haxe', 'keyword', { + 'preprocessor': { + pattern: /#\w+/, + alias: 'builtin' + }, + 'metadata': { + pattern: /@:?\w+/, + alias: 'symbol' + }, + 'reification': { + pattern: /\$(?:\w+|(?=\{))/, + alias: 'variable' + } +}); +Prism.languages.haxe['string'].inside['interpolation'].inside.rest = Prism.util.clone(Prism.languages.haxe); +delete Prism.languages.haxe['class-name']; \ No newline at end of file diff --git a/components/prism-haxe.min.js b/components/prism-haxe.min.js new file mode 100644 index 0000000000..42f05b0cfa --- /dev/null +++ b/components/prism-haxe.min.js @@ -0,0 +1 @@ +Prism.languages.haxe=Prism.languages.extend("clike",{string:{pattern:/(["'])(?:(?!\1)[^\\]|\\[\s\S])*\1/,inside:{interpolation:{pattern:/(^|[^\\])\$(?:\w+|\{[^}]+\})/,lookbehind:!0,inside:{interpolation:{pattern:/^\$\w*/,alias:"variable"}}}}},keyword:/\bthis\b|\b(?:abstract|as|break|case|cast|catch|class|continue|default|do|dynamic|else|enum|extends|extern|from|for|function|if|implements|import|in|inline|interface|macro|new|null|override|public|private|return|static|super|switch|throw|to|try|typedef|using|var|while)(?!\.)\b/,operator:/\.{3}|\+\+?|-[->]?|[=!]=?|&&?|\|\|?|<[<=]?|>[>=]?|[*\/%~^]/}),Prism.languages.insertBefore("haxe","class-name",{regex:{pattern:/~\/(?:[^\/\\\r\n]|\\.)+\/[igmsu]*/}}),Prism.languages.insertBefore("haxe","keyword",{preprocessor:{pattern:/#\w+/,alias:"builtin"},metadata:{pattern:/@:?\w+/,alias:"symbol"},reification:{pattern:/\$(?:\w+|(?=\{))/,alias:"variable"}}),Prism.languages.haxe.string.inside.interpolation.inside.rest=Prism.util.clone(Prism.languages.haxe),delete Prism.languages.haxe["class-name"]; \ No newline at end of file diff --git a/examples/prism-haxe.html b/examples/prism-haxe.html new file mode 100644 index 0000000000..88f8e373f2 --- /dev/null +++ b/examples/prism-haxe.html @@ -0,0 +1,53 @@ +
To use this language, use the class "language-haxe".
+ +"Foo
+bar $baz"
+'Foo
+bar'
+"${4 + 2}"
+
+~/haxe/i
+~/[A-Z0-9._%-]+@[A-Z0-9.-]+.[A-Z][A-Z][A-Z]?/i
+~/(dog|fox)/g
+
+#if !debug
+ trace("ok");
+#elseif (debug_level > 3)
+ trace(3);
+#else
+ trace("debug level too low");
+#end
+
+@author("Nicolas")
+@debug
+class MyClass {
+ @range(1, 8)
+ var value:Int;
+
+ @broken
+ @:noCompletion
+ static function method() { }
+}
+
+macro static function add(e:Expr) {
+ return macro $e + $e;
+}
+
+There are certain edge cases where Prism will fail. + There are always such cases in every regex-based syntax highlighter. + However, Prism dares to be open and honest about them. + If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. +
+ +"foo // var"
+
+~/"foo"/
\ No newline at end of file
diff --git a/plugins/autoloader/prism-autoloader.js b/plugins/autoloader/prism-autoloader.js
index 85c02d7fec..0d04b72bc4 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","aspnet":"markup","bison":"c","c":"clike","csharp":"clike","cpp":"c","coffeescript":"javascript","crystal":"ruby","css-extras":"css","d":"clike","dart":"clike","fsharp":"clike","glsl":"clike","go":"clike","groovy":"clike","haml":"ruby","handlebars":"markup","jade":"javascript","java":"clike","less":"css","markdown":"markup","nginx":"clike","objectivec":"c","parser":"markup","php":"clike","php-extras":"php","processing":"clike","qore":"clike","jsx":["markup","javascript"],"ruby":"clike","sass":"css","scss":"css","scala":"java","smarty":"markup","swift":"clike","textile":"markup","twig":"markup","typescript":"javascript","wiki":"markup"}/*]*/;
+ var lang_dependencies = /*languages_placeholder[*/{"javascript":"clike","actionscript":"javascript","aspnet":"markup","bison":"c","c":"clike","csharp":"clike","cpp":"c","coffeescript":"javascript","crystal":"ruby","css-extras":"css","d":"clike","dart":"clike","fsharp":"clike","glsl":"clike","go":"clike","groovy":"clike","haml":"ruby","handlebars":"markup","haxe":"clike","jade":"javascript","java":"clike","less":"css","markdown":"markup","nginx":"clike","objectivec":"c","parser":"markup","php":"clike","php-extras":"php","processing":"clike","qore":"clike","jsx":["markup","javascript"],"ruby":"clike","sass":"css","scss":"css","scala":"java","smarty":"markup","swift":"clike","textile":"markup","twig":"markup","typescript":"javascript","wiki":"markup"}/*]*/;
var lang_data = {};
diff --git a/plugins/autoloader/prism-autoloader.min.js b/plugins/autoloader/prism-autoloader.min.js
index 59a1a57a25..ef40ff60e6 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",aspnet:"markup",bison:"c",c:"clike",csharp:"clike",cpp:"c",coffeescript:"javascript",crystal:"ruby","css-extras":"css",d:"clike",dart:"clike",fsharp:"clike",glsl:"clike",go:"clike",groovy:"clike",haml:"ruby",handlebars:"markup",jade:"javascript",java:"clike",less:"css",markdown:"markup",nginx:"clike",objectivec:"c",parser:"markup",php:"clike","php-extras":"php",processing:"clike",qore:"clike",jsx:["markup","javascript"],ruby:"clike",sass:"css",scss:"css",scala:"java",smarty:"markup",swift:"clike",textile:"markup",twig:"markup",typescript:"javascript",wiki:"markup"},c={},a=Prism.plugins.autoloader={languages_path:"components/",use_minified:!0},s=function(e,c,a){var s=document.createElement("script");s.src=e,s.async=!0,s.onload=function(){document.body.removeChild(s),c&&c()},s.onerror=function(){document.body.removeChild(s),a&&a()},document.body.appendChild(s)},r=function(e){return a.languages_path+"prism-"+e+(a.use_minified?".min":"")+".js"},n=function(e,a){var s=c[e];s||(s=c[e]={});var r=a.getAttribute("data-dependencies");!r&&a.parentNode&&"pre"===a.parentNode.tagName.toLowerCase()&&(r=a.parentNode.getAttribute("data-dependencies")),r=r?r.split(/\s*,\s*/g):[],i(r,function(){t(e,function(){Prism.highlightElement(a)})})},i=function(e,c,a){"string"==typeof e&&(e=[e]);var s=0,r=e.length,n=function(){r>s?t(e[s],function(){s++,n()},function(){a&&a(e[s])}):s===r&&c&&c(e)};n()},t=function(a,n,t){var u=function(){var e=!1;a.indexOf("!")>=0&&(e=!0,a=a.replace("!",""));var i=c[a];if(i||(i=c[a]={}),n&&(i.success_callbacks||(i.success_callbacks=[]),i.success_callbacks.push(n)),t&&(i.error_callbacks||(i.error_callbacks=[]),i.error_callbacks.push(t)),!e&&Prism.languages[a])l(a);else if(!e&&i.error)o(a);else if(e||!i.loading){i.loading=!0;var u=r(a);s(u,function(){i.loading=!1,l(a)},function(){i.loading=!1,i.error=!0,o(a)})}},p=e[a];p&&p.length?i(p,u):u()},l=function(e){c[e]&&c[e].success_callbacks&&c[e].success_callbacks.length&&c[e].success_callbacks.forEach(function(c){c(e)})},o=function(e){c[e]&&c[e].error_callbacks&&c[e].error_callbacks.length&&c[e].error_callbacks.forEach(function(c){c(e)})};Prism.hooks.add("complete",function(e){e.element&&e.language&&!e.grammar&&n(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",aspnet:"markup",bison:"c",c:"clike",csharp:"clike",cpp:"c",coffeescript:"javascript",crystal:"ruby","css-extras":"css",d:"clike",dart:"clike",fsharp:"clike",glsl:"clike",go:"clike",groovy:"clike",haml:"ruby",handlebars:"markup",haxe:"clike",jade:"javascript",java:"clike",less:"css",markdown:"markup",nginx:"clike",objectivec:"c",parser:"markup",php:"clike","php-extras":"php",processing:"clike",qore:"clike",jsx:["markup","javascript"],ruby:"clike",sass:"css",scss:"css",scala:"java",smarty:"markup",swift:"clike",textile:"markup",twig:"markup",typescript:"javascript",wiki:"markup"},c={},a=Prism.plugins.autoloader={languages_path:"components/",use_minified:!0},s=function(e,c,a){var s=document.createElement("script");s.src=e,s.async=!0,s.onload=function(){document.body.removeChild(s),c&&c()},s.onerror=function(){document.body.removeChild(s),a&&a()},document.body.appendChild(s)},r=function(e){return a.languages_path+"prism-"+e+(a.use_minified?".min":"")+".js"},n=function(e,a){var s=c[e];s||(s=c[e]={});var r=a.getAttribute("data-dependencies");!r&&a.parentNode&&"pre"===a.parentNode.tagName.toLowerCase()&&(r=a.parentNode.getAttribute("data-dependencies")),r=r?r.split(/\s*,\s*/g):[],i(r,function(){t(e,function(){Prism.highlightElement(a)})})},i=function(e,c,a){"string"==typeof e&&(e=[e]);var s=0,r=e.length,n=function(){r>s?t(e[s],function(){s++,n()},function(){a&&a(e[s])}):s===r&&c&&c(e)};n()},t=function(a,n,t){var u=function(){var e=!1;a.indexOf("!")>=0&&(e=!0,a=a.replace("!",""));var i=c[a];if(i||(i=c[a]={}),n&&(i.success_callbacks||(i.success_callbacks=[]),i.success_callbacks.push(n)),t&&(i.error_callbacks||(i.error_callbacks=[]),i.error_callbacks.push(t)),!e&&Prism.languages[a])l(a);else if(!e&&i.error)o(a);else if(e||!i.loading){i.loading=!0;var u=r(a);s(u,function(){i.loading=!1,l(a)},function(){i.loading=!1,i.error=!0,o(a)})}},p=e[a];p&&p.length?i(p,u):u()},l=function(e){c[e]&&c[e].success_callbacks&&c[e].success_callbacks.length&&c[e].success_callbacks.forEach(function(c){c(e)})},o=function(e){c[e]&&c[e].error_callbacks&&c[e].error_callbacks.length&&c[e].error_callbacks.forEach(function(c){c(e)})};Prism.hooks.add("complete",function(e){e.element&&e.language&&!e.grammar&&n(e.language,e.element)})}}();
\ No newline at end of file
diff --git a/tests/languages/haxe/keyword_feature.test b/tests/languages/haxe/keyword_feature.test
new file mode 100644
index 0000000000..6a26bd0962
--- /dev/null
+++ b/tests/languages/haxe/keyword_feature.test
@@ -0,0 +1,93 @@
+this
+abstract
+as
+break
+case
+cast
+catch
+class
+continue
+default
+do
+dynamic
+else
+enum
+extends
+extern
+from
+for
+function
+if
+implements
+import
+in
+inline
+interface
+macro
+new
+null
+override
+public
+private
+return
+static
+super
+switch
+throw
+to
+try
+typedef
+using
+var
+while
+
+----------------------------------------------------
+
+[
+ ["keyword", "this"],
+ ["keyword", "abstract"],
+ ["keyword", "as"],
+ ["keyword", "break"],
+ ["keyword", "case"],
+ ["keyword", "cast"],
+ ["keyword", "catch"],
+ ["keyword", "class"],
+ ["keyword", "continue"],
+ ["keyword", "default"],
+ ["keyword", "do"],
+ ["keyword", "dynamic"],
+ ["keyword", "else"],
+ ["keyword", "enum"],
+ ["keyword", "extends"],
+ ["keyword", "extern"],
+ ["keyword", "from"],
+ ["keyword", "for"],
+ ["keyword", "function"],
+ ["keyword", "if"],
+ ["keyword", "implements"],
+ ["keyword", "import"],
+ ["keyword", "in"],
+ ["keyword", "inline"],
+ ["keyword", "interface"],
+ ["keyword", "macro"],
+ ["keyword", "new"],
+ ["keyword", "null"],
+ ["keyword", "override"],
+ ["keyword", "public"],
+ ["keyword", "private"],
+ ["keyword", "return"],
+ ["keyword", "static"],
+ ["keyword", "super"],
+ ["keyword", "switch"],
+ ["keyword", "throw"],
+ ["keyword", "to"],
+ ["keyword", "try"],
+ ["keyword", "typedef"],
+ ["keyword", "using"],
+ ["keyword", "var"],
+ ["keyword", "while"]
+]
+
+----------------------------------------------------
+
+Checks for keywords.
\ No newline at end of file
diff --git a/tests/languages/haxe/metadata_feature.test b/tests/languages/haxe/metadata_feature.test
new file mode 100644
index 0000000000..312114d9a5
--- /dev/null
+++ b/tests/languages/haxe/metadata_feature.test
@@ -0,0 +1,15 @@
+@author("Nicolas")
+@debug
+@:noCompletion
+
+----------------------------------------------------
+
+[
+ ["metadata", "@author"], ["punctuation", "("], ["string", ["\"Nicolas\""]], ["punctuation", ")"],
+ ["metadata", "@debug"],
+ ["metadata", "@:noCompletion"]
+]
+
+----------------------------------------------------
+
+Checks for metadata.
\ No newline at end of file
diff --git a/tests/languages/haxe/operator_feature.test b/tests/languages/haxe/operator_feature.test
new file mode 100644
index 0000000000..6963f80066
--- /dev/null
+++ b/tests/languages/haxe/operator_feature.test
@@ -0,0 +1,29 @@
+...
++ ++
+- -- ->
+= ==
+! !=
+& &&
+| ||
+< <= <<
+> >= >>
+* / % ~ ^
+
+----------------------------------------------------
+
+[
+ ["operator", "..."],
+ ["operator", "+"], ["operator", "++"],
+ ["operator", "-"], ["operator", "--"], ["operator", "->"],
+ ["operator", "="], ["operator", "=="],
+ ["operator", "!"], ["operator", "!="],
+ ["operator", "&"], ["operator", "&&"],
+ ["operator", "|"], ["operator", "||"],
+ ["operator", "<"], ["operator", "<="], ["operator", "<<"],
+ ["operator", ">"], ["operator", ">="], ["operator", ">>"],
+ ["operator", "*"], ["operator", "/"], ["operator", "%"], ["operator", "~"], ["operator", "^"]
+]
+
+----------------------------------------------------
+
+Checks for operators.
\ No newline at end of file
diff --git a/tests/languages/haxe/preprocessor_feature.test b/tests/languages/haxe/preprocessor_feature.test
new file mode 100644
index 0000000000..3cadacf654
--- /dev/null
+++ b/tests/languages/haxe/preprocessor_feature.test
@@ -0,0 +1,17 @@
+#if
+#elseif
+#else
+#end
+
+----------------------------------------------------
+
+[
+ ["preprocessor", "#if"],
+ ["preprocessor", "#elseif"],
+ ["preprocessor", "#else"],
+ ["preprocessor", "#end"]
+]
+
+----------------------------------------------------
+
+Checks for preprocessor directives.
\ No newline at end of file
diff --git a/tests/languages/haxe/regex_feature.test b/tests/languages/haxe/regex_feature.test
new file mode 100644
index 0000000000..577cab7b9a
--- /dev/null
+++ b/tests/languages/haxe/regex_feature.test
@@ -0,0 +1,15 @@
+~/ha\/xe/i
+~/[A-Z0-9._%-]+@[A-Z0-9.-]+.[A-Z][A-Z][A-Z]?/i
+~/(dog|fox)/igmsu
+
+----------------------------------------------------
+
+[
+ ["regex", "~/ha\\/xe/i"],
+ ["regex", "~/[A-Z0-9._%-]+@[A-Z0-9.-]+.[A-Z][A-Z][A-Z]?/i"],
+ ["regex", "~/(dog|fox)/igmsu"]
+]
+
+----------------------------------------------------
+
+Checks for regexes.
\ No newline at end of file
diff --git a/tests/languages/haxe/reification_feature.test b/tests/languages/haxe/reification_feature.test
new file mode 100644
index 0000000000..6d382b7cc6
--- /dev/null
+++ b/tests/languages/haxe/reification_feature.test
@@ -0,0 +1,16 @@
+$e
+${4+2}
+
+----------------------------------------------------
+
+[
+ ["reification", "$e"],
+ ["reification", "$"],
+ ["punctuation", "{"],
+ ["number", "4"], ["operator", "+"], ["number", "2"],
+ ["punctuation", "}"]
+]
+
+----------------------------------------------------
+
+Checks for reification.
\ No newline at end of file
diff --git a/tests/languages/haxe/string_feature.test b/tests/languages/haxe/string_feature.test
new file mode 100644
index 0000000000..61f1985fcc
--- /dev/null
+++ b/tests/languages/haxe/string_feature.test
@@ -0,0 +1,37 @@
+""
+"Foo
+\"bar\"
+baz"
+"$bar ${4+2}"
+''
+'Foo
+\'bar\'
+baz'
+
+----------------------------------------------------
+
+[
+ ["string", ["\"\""]],
+ ["string", ["\"Foo\r\n\\\"bar\\\"\r\nbaz\""]],
+ ["string", [
+ "\"",
+ ["interpolation", [
+ ["interpolation", "$bar"]
+ ]],
+ ["interpolation", [
+ ["interpolation", "$"],
+ ["punctuation", "{"],
+ ["number", "4"],
+ ["operator", "+"],
+ ["number", "2"],
+ ["punctuation", "}"]
+ ]],
+ "\""
+ ]],
+ ["string", ["''"]],
+ ["string", ["'Foo\r\n\\'bar\\'\r\nbaz'"]]
+]
+
+----------------------------------------------------
+
+Checks for strings and string interpolation.
\ No newline at end of file