diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,21 @@
-Version 0.7.3.1 released 20 Mar 2010
+Version 0.7.3.3 released 21 Mar 2010
 
+* Reverted to handling math in MathML mode in the old way, using
+  a transform, rather than relying on pandoc's MathML writer option.
+  The latter was causing amazing CPU and memory usage, for reasons
+  I don't yet understand.  This should fix the problem for now.
+
+* Fixed caching for unicode page names.
+
+* Added max-page-size config option. Thanks to Jinjing Wang for the patch.
+
+* Prevented _expire/ from failing if the page is not cached.
+
+* Fixed URL encoding for pages. (Note: Don't use + for spaces;
+  that breaks the Ctrl-R cache expiration.)
+
+Version 0.7.3.2 released 20 Mar 2010
+
 * Fixed editing of pages when max-upload-size=0.
   max-upload-size should not double as max-page-size.
   Resolves Issue #96.
@@ -14,10 +30,7 @@
   (Based on a patch by gwern.)
 
 * Added markdown export.
-
-* Use pandoc's new MathML math mode for more efficient
-  MathML.
-
+    
 * Improved multi-wiki example code in haddocks.
 
 * Added session-timeout config setting.
@@ -36,7 +49,7 @@
 * Added pandoc-user-data config option, allowing the user
   to specify a directory with e.g. templates that override
   the defaults used for exported pages.
-
+    
 * Fix filesToClean GHC panic when loading plugins on GHC HEAD
 
 * Fixed problem with doubled // in updir links.
diff --git a/Network/Gitit/Cache.hs b/Network/Gitit/Cache.hs
--- a/Network/Gitit/Cache.hs
+++ b/Network/Gitit/Cache.hs
@@ -32,6 +32,7 @@
 import Network.Gitit.Types
 import Control.Monad
 import Control.Monad.Trans (liftIO)
+import Codec.Binary.UTF8.String (encodeString)
 
 -- | Expire a cached file, identified by its filename in the filestore.
 -- If there is an associated exported PDF, expire it too.
@@ -39,25 +40,23 @@
 expireCachedFile :: String -> GititServerPart ()
 expireCachedFile file = do
   cfg <- getConfig
-  let target = cacheDir cfg </> file
+  let target = encodeString $ cacheDir cfg </> file
   exists <- liftIO $ doesFileExist target
-  if exists
-     then liftIO $ do
-       removeFile target
-       expireCachedPDF (cacheDir cfg </> file)
-     else mzero
+  when exists $ liftIO $ do
+    liftIO $ removeFile target
+    expireCachedPDF target
 
 expireCachedPDF :: String -> IO ()
 expireCachedPDF file =
   when (takeExtension file == ".page") $ do
-     let pdfname = file ++ ".export.pdf"
-     exists <- doesFileExist pdfname
-     when exists $ removeFile pdfname
+    let pdfname = file ++ ".export.pdf"
+    exists <- doesFileExist pdfname
+    when exists $ removeFile pdfname
 
 lookupCache :: String -> GititServerPart (Maybe (ClockTime, B.ByteString))
 lookupCache file = do
   cfg <- getConfig
-  let target = cacheDir cfg </> file
+  let target = encodeString $ cacheDir cfg </> file
   exists <- liftIO $ doesFileExist target
   if exists
      then liftIO $ do
@@ -69,9 +68,9 @@
 cacheContents :: String -> B.ByteString -> GititServerPart ()
 cacheContents file contents = do
   cfg <- getConfig
-  let target = cacheDir cfg </> file
+  let target = encodeString $ cacheDir cfg </> file
   let targetDir = takeDirectory target
   liftIO $ do
     createDirectoryIfMissing True targetDir
-    B.writeFile (cacheDir cfg </> file) contents
-    expireCachedPDF (cacheDir cfg </> file)
+    B.writeFile target contents
+    expireCachedPDF target
diff --git a/Network/Gitit/Config.hs b/Network/Gitit/Config.hs
--- a/Network/Gitit/Config.hs
+++ b/Network/Gitit/Config.hs
@@ -83,6 +83,7 @@
       cfPlugins <- get cp "DEFAULT" "plugins"
       cfTableOfContents <- get cp "DEFAULT" "table-of-contents"
       cfMaxUploadSize <- get cp "DEFAULT" "max-upload-size"
+      cfMaxPageSize <- get cp "DEFAULT" "max-page-size"
       cfPort <- get cp "DEFAULT" "port"
       cfDebugMode <- get cp "DEFAULT" "debug-mode"
       cfFrontPage <- get cp "DEFAULT" "front-page"
@@ -154,6 +155,7 @@
         , pluginModules        = splitCommaList cfPlugins
         , tableOfContents      = cfTableOfContents
         , maxUploadSize        = readSize "max-upload-size" cfMaxUploadSize
+        , maxPageSize          = readSize "max-page-size" cfMaxPageSize
         , portNumber           = readNumber "port" cfPort
         , debugMode            = cfDebugMode
         , frontPage            = cfFrontPage
diff --git a/Network/Gitit/ContentTransformer.hs b/Network/Gitit/ContentTransformer.hs
--- a/Network/Gitit/ContentTransformer.hs
+++ b/Network/Gitit/ContentTransformer.hs
@@ -80,18 +80,17 @@
 import qualified Data.FileStore as FS
 import Data.Maybe (mapMaybe)
 import Text.Pandoc hiding (MathML)
-import qualified Text.Pandoc as Pandoc
 import Text.Pandoc.Shared (ObfuscationMethod(..))
 import Text.XHtml hiding ( (</>), dir, method, password, rev )
 import Text.Highlighting.Kate
 import Data.Maybe (isNothing)
-import Codec.Binary.UTF8.String (encodeString)
 import System.FilePath
 import Control.Monad.State
 import Control.Exception (throwIO, catch)
-import Network.URI (isUnescapedInURI, escapeURIString)
 import qualified Data.ByteString as S (concat) 
 import qualified Data.ByteString.Lazy as L (toChunks, fromChunks)
+import Text.XML.Light
+import Text.TeXMath
 
 --
 -- ContentTransformer runners
@@ -336,15 +335,11 @@
   base' <- lift getWikiBase
   toc <- liftM ctxTOC get
   bird <- liftM ctxBirdTracks get
-  cfg <- lift getConfig
   return $ writeHtml defaultWriterOptions{
                         writerStandalone = True
                       , writerTemplate = "$if(toc)$\n$toc$\n$endif$\n$body$"
-                      , writerHTMLMathMethod =
-                            case mathMethod cfg of
-                                 MathML -> Pandoc.MathML Nothing
-                                 _      -> JsMath (Just $ base' ++
-                                                      "/js/jsMath/easy/load.js")
+                      , writerHTMLMathMethod = JsMath
+                               (Just $ base' ++ "/js/jsMath/easy/load.js")
                       , writerTableOfContents = toc
                       , writerLiterateHaskell = bird
                       -- note: javascript obfuscation gives problems on preview
@@ -404,7 +399,12 @@
 applyPageTransforms :: Pandoc -> ContentTransformer Pandoc 
 applyPageTransforms c = do
   xforms <- getPageTransforms
-  foldM applyTransform c (wikiLinksTransform : xforms)
+  cfg <- lift getConfig
+  params <- getParams
+  let xforms' = case mathMethod cfg of
+                      MathML -> mathMLTransform (pFormat params) : xforms
+                      _      -> xforms
+  foldM applyTransform c (wikiLinksTransform : xforms')
 
 -- | Applies all the pre-parse transform plugins to a Page object.
 applyPreParseTransforms :: Page -> ContentTransformer Page
@@ -446,7 +446,9 @@
   updateLayout $ \l ->
     case mathMethod conf of
          JsMathScript -> addScripts l ["jsMath/easy/load.js"]
-         MathML       -> addScripts l ["MathMLinHTML.js"]
+         -- for MathML, the script is added by mathMLTransform, only
+         -- if the page contains math:
+         MathML       -> l
          RawTeX       -> l
   return c
 
@@ -505,9 +507,31 @@
   Link ref (inlinesToURL ref, "Go to wiki page")
 convertWikiLinks x = x
 
+mathMLTransform :: String -> Pandoc -> PluginM Pandoc
+mathMLTransform format inp | format `elem` ["","S5"] = do
+  let (Pandoc m blks, mathUsed) = runState (processWithM convertTeXMathToMathML inp) False
+  let scriptLink = RawHtml "<script type=\"text/javascript\" src=\"/js/MathMLinHTML.js\"></script>"
+  let blks' = if mathUsed
+                 then blks ++ [scriptLink]
+                 else blks
+  return $ Pandoc m blks'
+mathMLTransform _ inp = return inp
+
+-- | Convert math to MathML.  We put this in a Writer monad
+-- to keep track of whether we've actually got any MathML; if not,
+-- we can avoid linking a script.
+convertTeXMathToMathML :: Inline -> State Bool Inline
+convertTeXMathToMathML (Math t x) = do
+  case texMathToMathML t' x of
+       Left _  -> return $ Math t x
+       Right v -> put True >> return (HtmlInline $ showXml v)
+    where t' = if t == DisplayMath then DisplayBlock else DisplayInline
+          showXml = ppcElement (useShortEmptyTags (const False) defaultConfigPP)
+convertTeXMathToMathML x = return x
+
 -- | Derives a URL from a list of Pandoc Inline elements.
 inlinesToURL :: [Inline] -> String
-inlinesToURL = escapeURIString isUnescapedInURI  . encodeString . inlinesToString
+inlinesToURL = urlForPage . inlinesToString
 
 -- | Convert a list of inlines into a string.
 inlinesToString :: [Inline] -> String
diff --git a/Network/Gitit/Framework.hs b/Network/Gitit/Framework.hs
--- a/Network/Gitit/Framework.hs
+++ b/Network/Gitit/Framework.hs
@@ -60,7 +60,7 @@
 import Network.Gitit.State
 import Network.Gitit.Types
 import Data.FileStore
-import Data.Char (toLower, isAscii)
+import Data.Char (toLower)
 import Control.Monad (mzero, liftM, MonadPlus)
 import qualified Data.Map as M
 import Data.ByteString.UTF8 (toString)
@@ -71,6 +71,7 @@
 import Text.Highlighting.Kate
 import Text.ParserCombinators.Parsec
 import Network.URL (decString, encString)
+import Network.URI (isUnescapedInURI)
 import Happstack.Crypto.Base64 (decode)
 import Network.HTTP (urlEncodeVars)
 
@@ -272,8 +273,7 @@
 -- the wiki base.
 urlForPage :: String -> String
 urlForPage page = "/" ++
-  encString True (\c -> isAscii c && (c `notElem` "?&")) page
--- / and @ are left unescaped so that browsers recognize relative URLs and talk pages correctly
+  encString False isUnescapedInURI page
 
 -- | Returns the filestore path of the file containing the page's source.
 pathForPage :: String -> FilePath
diff --git a/Network/Gitit/Handlers.hs b/Network/Gitit/Handlers.hs
--- a/Network/Gitit/Handlers.hs
+++ b/Network/Gitit/Handlers.hs
@@ -618,6 +618,8 @@
   if null . filter (not . isSpace) $ logMsg
      then withMessages ["Description cannot be empty."] editPage
      else do
+       when (length editedText > fromIntegral (maxPageSize cfg)) $
+          error "Page exceeds maximum size."
        -- check SHA1 in case page has been modified, merge
        modifyRes <- if null oldSHA1
                        then liftIO $ create fs (pathForPage page)
@@ -745,7 +747,8 @@
 expireCache = do
   page <- getPage
   -- try it as a page first, then as an uploaded file
-  expireCachedFile (pathForPage page) `mplus` expireCachedFile page
+  expireCachedFile (pathForPage page)
+  expireCachedFile page
   ok $ toResponse ()
 
 feedHandler :: Handler
diff --git a/Network/Gitit/Types.hs b/Network/Gitit/Types.hs
--- a/Network/Gitit/Types.hs
+++ b/Network/Gitit/Types.hs
@@ -82,8 +82,10 @@
   pluginModules        :: [String],
   -- | Show table of contents on each page?
   tableOfContents      :: Bool,
-  -- | Max size of pages and file uploads
+  -- | Max size of file uploads
   maxUploadSize        :: Integer,
+  -- | Max size of page uploads
+  maxPageSize          :: Integer,
   -- | Port number to serve content on
   portNumber           :: Int,
   -- | Print debug info to the console?
diff --git a/data/default.conf b/data/default.conf
--- a/data/default.conf
+++ b/data/default.conf
@@ -50,7 +50,7 @@
 # rendered correctly if RST is selected. The same goes for LaTeX and
 # HTML.
 
-math: RawTeX
+math: MathML
 # specifies how LaTeX math is to be displayed.  Possible values
 # are MathML, raw, and jsMath.  If mathml is selected, gitit will
 # convert LaTeX math to MathML and link in a script, MathMLinHTML.js,
@@ -131,6 +131,9 @@
 # To disable uploads, set this to 0K.
 # This will result in the uploads link disappearing 
 # and the _upload url becoming inactive.
+
+max-page-size: 100K
+# specifies an upper limit on the size (in bytes) of pages
 
 debug-mode: no
 # if "yes", causes debug information to be logged while gitit is running.
diff --git a/gitit.cabal b/gitit.cabal
--- a/gitit.cabal
+++ b/gitit.cabal
@@ -1,5 +1,5 @@
 name:                gitit
-version:             0.7.3.2
+version:             0.7.3.3
 Cabal-version:       >= 1.2
 build-type:          Simple
 synopsis:            Wiki using happstack, git or darcs, and pandoc.
@@ -125,7 +125,7 @@
                      happstack-util >= 0.3.2 && < 0.5, xml >= 1.3.5,
                      hslogger >= 1 && < 1.1, ConfigFile >= 1 && < 1.1,
                      feed >= 0.3.6 && < 0.4,
-                     cautious-file >= 0.1.5 && < 0.2
+                     cautious-file >= 0.1.5 && < 0.2, texmath
   if impl(ghc >= 6.10)
     build-depends:   base >= 4, syb
   if flag(plugins)
