diff --git a/compress.html b/compress.html
index b47526e9c4e3cb750084632600e393a466305f20..8f20d64ff1a9c5ca64a33ed6c2abc972f9ec220f 100644
--- a/compress.html
+++ b/compress.html
@@ -53,6 +53,7 @@
           <option value="http://codemirror.net/mode/haskell/haskell.js">haskell.js</option>
           <option value="http://codemirror.net/mode/htmlmixed/htmlmixed.js">htmlmixed.js</option>
           <option value="http://codemirror.net/mode/javascript/javascript.js">javascript.js</option>
+          <option value="http://codemirror.net/mode/jinja2/jinja2.js">jinja2.js</option>
           <option value="http://codemirror.net/mode/lua/lua.js">lua.js</option>
           <option value="http://codemirror.net/mode/php/php.js">php.js</option>
           <option value="http://codemirror.net/mode/plsql/plsql.js">plsql.js</option>
diff --git a/index.html b/index.html
index 9a473b93a99c91f2384c7df17f2b272ce975f3fb..95d4988589480ef47690483773bd3d5c06b516b8 100644
--- a/index.html
+++ b/index.html
@@ -57,6 +57,7 @@
       <li><a href="mode/sparql/index.html">SPARQL</a></li>
       <li><a href="mode/velocity/index.html">Velocity</a></li>
       <li><a href="mode/r/index.html">R</a></li>
+      <li><a href="mode/jinja2/index.html">Jinja2</a></li>
     </ul>
 
   </div><div class="left2 blk">
diff --git a/mode/jinja2/index.html b/mode/jinja2/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..ffb06e8ef8ed83ef5f1d49c31345c797bee582dc
--- /dev/null
+++ b/mode/jinja2/index.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+  <head>
+    <title>CodeMirror 2: Jinja2 mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="jinja2.js"></script>
+    <link rel="stylesheet" href="../../theme/default.css">
+    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
+    <link rel="stylesheet" href="../../css/docs.css">
+  </head>
+  <body>
+    <h1>CodeMirror 2: Jinja2 mode</h1>
+    <form><textarea id="code" name="code">
+&lt;html style="color: green"&gt;
+  &lt;!-- this is a comment --&gt;
+  &lt;head&gt;
+    &lt;title&gt;Jinja2 Example&lt;/title&gt;
+  &lt;/head&gt;
+  &lt;body&gt;
+    &lt;ul&gt;
+    {# this is a comment #}
+    {%- for item in li -%}
+      &lt;li&gt;
+        {{ item.label }}
+      &lt;/li&gt;
+    {% endfor -%}
+    &lt;/ul&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
+</textarea></form>
+    <script>
+      var editor =
+      CodeMirror.fromTextArea(document.getElementById("code"), {mode:
+        {name: "jinja2", htmlMode: true}});
+    </script>
+  </body>
+</html>
diff --git a/mode/jinja2/jinja2.js b/mode/jinja2/jinja2.js
new file mode 100644
index 0000000000000000000000000000000000000000..75419d84687ddbc59d4f9667ce626f458dc7e59e
--- /dev/null
+++ b/mode/jinja2/jinja2.js
@@ -0,0 +1,42 @@
+CodeMirror.defineMode("jinja2", function(config, parserConf) {
+    var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false", 
+                    "loop", "none", "self", "super", "if", "as", "not", "and",
+                    "else", "import", "with", "without", "context"];
+    keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
+
+    function tokenBase (stream, state) {
+        var ch = stream.next();
+        if (ch == "{") {
+            if (ch = stream.eat(/\{|%|#/)) {
+                stream.eat("-");
+                state.tokenize = inTag(ch);
+                return "tag";
+            }
+        }
+    }
+    function inTag (close) {
+        if (close == "{") {
+            close = "}";
+        }
+        return function (stream, state) {
+            var ch = stream.next();
+            if ((ch == close || (ch == "-" && stream.eat(close)))
+                && stream.eat("}")) {
+                state.tokenize = tokenBase;
+                return "tag";
+            }
+            if (stream.match(keywords)) {
+                return "keyword";
+            }
+            return close == "#" ? "comment" : "string";
+        };
+    }
+    return {
+        startState: function () {
+            return {tokenize: tokenBase};
+        },
+        token: function (stream, state) {
+            return state.tokenize(stream, state);
+        }
+    }; 
+});