diff --git a/pandoc.hs b/pandoc.hs
index 1c0a49a73..0df4cc555 100644
--- a/pandoc.hs
+++ b/pandoc.hs
@@ -91,14 +91,16 @@ isTextFormat :: String -> Bool
 isTextFormat s = takeWhile (`notElem` "+-") s `notElem` ["odt","docx","epub","epub3"]
 
 externalFilter :: FilePath -> [String] -> Pandoc -> IO Pandoc
-externalFilter f args' d = E.catch
-  (do (exitcode, outbs, errbs) <- pipeProcess Nothing f args' $ encode d
+externalFilter f args' d = E.handle filterException $
+   do (exitcode, outbs, errbs) <- pipeProcess Nothing f args' $ encode d
       case exitcode of
            ExitSuccess    -> return $ either error id $ eitherDecode' outbs
-           ExitFailure _  -> err 83 $ "Error running filter `" ++ UTF8.toStringLazy outbs ++
-                                          UTF8.toStringLazy errbs ++  "'")
-  (\e -> let _ = (e :: E.SomeException)
-         in err 83 $ "Error running filter `" ++ f ++ "'")
+           ExitFailure _  -> err 83 $ "Error running filter " ++ f ++ "\n" ++
+                                          UTF8.toStringLazy outbs ++
+                                          UTF8.toStringLazy errbs
+ where filterException :: E.SomeException -> IO Pandoc
+       filterException e = err 83 $ "Error running filter " ++ f ++
+                                     "\n" ++ show e
 
 -- | Data structure for command line options.
 data Opt = Opt
diff --git a/scripts/caps.py b/scripts/caps.py
new file mode 100755
index 000000000..3ab8bc7a3
--- /dev/null
+++ b/scripts/caps.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+from pandoc import toJSONFilter
+
+def caps(key, value, format):
+  if key == 'Str':
+    return {'Str': value.upper()}
+
+if __name__ == "__main__":
+  toJSONFilter(caps)
diff --git a/scripts/comments.py b/scripts/comments.py
new file mode 100755
index 000000000..3767f973a
--- /dev/null
+++ b/scripts/comments.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+from pandoc import toJSONFilter
+import re
+
+incomment = False
+
+def comment(k,v,format=""):
+  global incomment
+  if k == 'RawBlock':
+    f, s = v
+    fmt = f['unFormat']
+    if fmt == "html":
+      if re.search("<!-- BEGIN COMMENT -->", s):
+        incomment = True
+        return []
+      elif re.search("<!-- END COMMENT -->", s):
+        incomment = False
+        return []
+  if incomment:
+    return []  # suppress anything in a comment
+
+if __name__ == "__main__":
+  toJSONFilter(comment)
diff --git a/scripts/deemph.py b/scripts/deemph.py
new file mode 100755
index 000000000..c1d532969
--- /dev/null
+++ b/scripts/deemph.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+from pandoc import walk, toJSONFilter
+from caps import caps
+
+def deemph(k,v,f):
+  if k == 'Emph' and f == 'html':
+    return walk(v,caps,f)
+
+if __name__ == "__main__":
+  toJSONFilter(deemph)
diff --git a/scripts/myemph.py b/scripts/myemph.py
new file mode 100755
index 000000000..92f6202b4
--- /dev/null
+++ b/scripts/myemph.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from pandoc import toJSONFilter, rawInline
+
+def myemph(k, v, f):
+  if k == 'Emph' and f == 'latex':
+    v.insert(0, rawInline("latex", "\\myemph{"))
+    v.append(rawInline("latex", "}"))
+    return v
+
+if __name__ == "__main__":
+  toJSONFilter(myemph)
diff --git a/scripts/pandoc.py b/scripts/pandoc.py
new file mode 100755
index 000000000..8bc3afc03
--- /dev/null
+++ b/scripts/pandoc.py
@@ -0,0 +1,49 @@
+import sys
+import json
+
+def walk(x, action, format = ""):
+  if isinstance(x, list):
+    array = []
+    for item in x:
+      if isinstance(item, dict):
+        for k in item:
+          res = action(k, item[k], format)
+          if res is None:
+            array.append(walk(item, action, format))
+          elif isinstance(res, list):
+            for z in res:
+              array.append(walk(z, action, format))
+          else:
+            array.append(walk(res, action, format))
+      else:
+        array.append(walk(item, action, format))
+    return array
+  elif isinstance(x, dict):
+    obj = {}
+    for k in x:
+      obj[k] = walk(x[k], action, format)
+    return obj
+  else:
+    return x
+
+def toJSONFilter(action):
+  doc = json.loads(sys.stdin.read())
+  if len(sys.argv) > 1:
+    format = sys.argv[1]
+  else:
+    format = ""
+  altered = walk(doc, action, format)
+  json.dump(altered, sys.stdout)
+
+def rawInline(format, s):
+  return {"RawInline": [{"unFormat": format}, s]}
+
+def rawBlock(format, s):
+  return {"RawBlock": [{"unFormat": format}, s]}
+
+def attributes(attrs):
+  attrs = attrs or []
+  ident = attrs["id"] or ""
+  classes = attrs["classes"] or []
+  keyvals = [x for x in attrs and x != "classes" and x != "id"]
+  return [ident, classes, keyvals]