Commit 65122e1d3d218c5553cd9629f64cf9c1d8349a08

Golmote 2015-01-07T00:28:53

Merge pull request #429 from Golmote/prism-smarty Add Smarty language

diff --git a/components.js b/components.js
index 09e7284..1612878 100644
--- a/components.js
+++ b/components.js
@@ -268,6 +268,10 @@ var components = {
 		"powershell": {
 			"title": "PowerShell",
 			"owner": "nauzilus"
+		},
+		"smarty": {
+			"title": "Smarty",
+			"owner": "Golmote"
 		}
 	},
 	"plugins": {
diff --git a/components/prism-smarty.js b/components/prism-smarty.js
new file mode 100644
index 0000000..4466b2e
--- /dev/null
+++ b/components/prism-smarty.js
@@ -0,0 +1,124 @@
+/* TODO
+	Add support for variables inside double quoted strings
+	Add support for {php}
+*/
+
+(function(Prism) {
+
+	var smarty_pattern = /\{\*[\w\W]+?\*\}|\{[\w\W]+?\}/g;
+	var smarty_litteral_start = '{literal}';
+	var smarty_litteral_end = '{/literal}';
+	var smarty_litteral_mode = false;
+	
+	Prism.languages.smarty = Prism.languages.extend('markup', {
+		'smarty': {
+			pattern: smarty_pattern,
+			inside: {
+				'delimiter': {
+					pattern: /^\{|\}$/ig,
+					alias: 'punctuation'
+				},
+				'string': /(["'])(\\?.)*?\1/g,
+				'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,
+				'variable': [
+					/\$(?!\d)\w+/g,
+					/#(?!\d)\w+#/g,
+					{
+						pattern: /(\.|->)(?!\d)\w+/g,
+						lookbehind: true
+					},
+					{
+						pattern: /(\[)(?!\d)\w+(?=\])/g,
+						lookbehind: true
+					}
+				],
+				'function': [
+					{
+						pattern: /(\|\s*)@?(?!\d)\w+/,
+						lookbehind: true
+					},
+					/^\/?(?!\d)\w+/g,
+					/(?!\d)\w+(?=\()/g
+				],
+				'attr-name': {
+					// Value is made optional because it may have already been tokenized
+					pattern: /\w+\s*=\s*(?:(?!\d)\w+)?/g,
+					inside: {
+						"variable": {
+							pattern: /(=\s*)(?!\d)\w+/g,
+							lookbehind: true
+						},
+						"punctuation": /=/g
+					}
+				},
+				'punctuation': /[\[\]().,=\|:`]|\->/g,
+				'operator': [
+					/[+\-*\/%]|===?|[!<>]=?|&&|\|\|/g,
+					/\bis\s+(?:not\s+)?(?:div|even|odd)(?:\s+by)?\b/,
+					/\b(?:eq|neq?|gt|lt|gt?e|lt?e|not|mod|or|and)\b/g
+				],
+				'keyword': /\b(?:false|off|on|no|true|yes)\b/g,
+			}
+		}
+	});
+
+	// Comments are inserted at top so that they can
+	// surround markup
+	Prism.languages.insertBefore('smarty', 'tag', {
+		'smarty-comment': {
+			pattern: /\{\*[\w\W]*?\*\}/g,
+			alias: ['smarty','comment']
+		}
+	});
+
+	// Tokenize all inline Smarty expressions
+	Prism.hooks.add('before-highlight', function(env) {
+		if (env.language !== 'smarty') {
+			return;
+		}
+
+		env.tokenStack = [];
+
+		env.backupCode = env.code;
+		env.code = env.code.replace(smarty_pattern, function(match) {
+
+			// Smarty tags inside {literal} block are ignored
+			if(match === smarty_litteral_end) {
+				smarty_litteral_mode = false;
+			}
+
+			if(!smarty_litteral_mode) {
+				if(match === smarty_litteral_start) {
+					smarty_litteral_mode = true;
+				}
+				env.tokenStack.push(match);
+
+				return '___SMARTY' + env.tokenStack.length + '___';
+			}
+			return match;
+		});
+	});
+
+	// Restore env.code for other plugins (e.g. line-numbers)
+	Prism.hooks.add('before-insert', function(env) {
+		if (env.language === 'smarty') {
+			env.code = env.backupCode;
+			delete env.backupCode;
+		}
+	});
+
+	// Re-insert the tokens after highlighting
+	// and highlight them with defined grammar
+	Prism.hooks.add('after-highlight', function(env) {
+		if (env.language !== 'smarty') {
+			return;
+		}
+
+		for (var i = 0, t; t = env.tokenStack[i]; i++) {
+			env.highlightedCode = env.highlightedCode.replace('___SMARTY' + (i + 1) + '___', Prism.highlight(t, env.grammar, 'smarty'));
+		}
+
+		env.element.innerHTML = env.highlightedCode;
+	});
+
+}(Prism));
\ No newline at end of file
diff --git a/components/prism-smarty.min.js b/components/prism-smarty.min.js
new file mode 100644
index 0000000..08b7e8f
--- /dev/null
+++ b/components/prism-smarty.min.js
@@ -0,0 +1 @@
+!function(e){var t=/\{\*[\w\W]+?\*\}|\{[\w\W]+?\}/g,a="{literal}",n="{/literal}",o=!1;e.languages.smarty=e.languages.extend("markup",{smarty:{pattern:t,inside:{delimiter:{pattern:/^\{|\}$/gi,alias:"punctuation"},string:/(["'])(\\?.)*?\1/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,variable:[/\$(?!\d)\w+/g,/#(?!\d)\w+#/g,{pattern:/(\.|->)(?!\d)\w+/g,lookbehind:!0},{pattern:/(\[)(?!\d)\w+(?=\])/g,lookbehind:!0}],"function":[{pattern:/(\|\s*)@?(?!\d)\w+/,lookbehind:!0},/^\/?(?!\d)\w+/g,/(?!\d)\w+(?=\()/g],"attr-name":{pattern:/\w+\s*=\s*(?:(?!\d)\w+)?/g,inside:{variable:{pattern:/(=\s*)(?!\d)\w+/g,lookbehind:!0},punctuation:/=/g}},punctuation:/[\[\]().,=\|:`]|\->/g,operator:[/[+\-*\/%]|===?|[!<>]=?|&&|\|\|/g,/\bis\s+(?:not\s+)?(?:div|even|odd)(?:\s+by)?\b/,/\b(?:eq|neq?|gt|lt|gt?e|lt?e|not|mod|or|and)\b/g],keyword:/\b(?:false|off|on|no|true|yes)\b/g}}}),e.languages.insertBefore("smarty","tag",{"smarty-comment":{pattern:/\{\*[\w\W]*?\*\}/g,alias:["smarty","comment"]}}),e.hooks.add("before-highlight",function(e){"smarty"===e.language&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(t,function(t){return t===n&&(o=!1),o?t:(t===a&&(o=!0),e.tokenStack.push(t),"___SMARTY"+e.tokenStack.length+"___")}))}),e.hooks.add("before-insert",function(e){"smarty"===e.language&&(e.code=e.backupCode,delete e.backupCode)}),e.hooks.add("after-highlight",function(t){if("smarty"===t.language){for(var a,n=0;a=t.tokenStack[n];n++)t.highlightedCode=t.highlightedCode.replace("___SMARTY"+(n+1)+"___",e.highlight(a,t.grammar,"smarty"));t.element.innerHTML=t.highlightedCode}})}(Prism);
\ No newline at end of file