diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,30 @@
 # Revision history for typst-hs
 
+## 0.5.0.3
+
+  * Support grid.(cell,header,footer,hline,vline) (#44).
+
+  * Support table.(cell,vline,hline,header,footer) (#44).
+
+  * Allow space after equation in code (#43).
+
+  * Treat unicode whitespace characters as whitespace (#43).
+
+  * Allow raw (backticked) content as code expression (#43).
+
+  * Allow colon in label (#43).
+
+  * Allow line comments at end of file (#43).
+
+  * Depend on typst-symbols 0.1.6.
+
+  * Add Haddock docs to parts of the public API (Eli Adelhult,
+    Leopold Wigratt).
+
+  * Avoid backtracking in `pDictExpr` (Jonathan Widén).
+
+  * Allow colon in dict literal (Jonathan Widén) (#43, #45).
+
 ## 0.5.0.2
 
   * Fix parsing of field access in math (#41). `$plus.circle_2$`
diff --git a/src/Typst/Module/Standard.hs b/src/Typst/Module/Standard.hs
--- a/src/Typst/Module/Standard.hs
+++ b/src/Typst/Module/Standard.hs
@@ -135,7 +135,6 @@
     makeElement Nothing "box" [("body", One TContent)],
     makeElement Nothing "colbreak" [],
     makeElement Nothing "columns" [("count", One TInteger), ("body", One TContent)],
-    makeElement Nothing "grid" [("children", Many TContent)],
     makeElement Nothing "h" [("amount", One (TLength :|: TRatio :|: TFraction))],
     makeElement Nothing "v" [("amount", One (TLength :|: TRatio :|: TFraction))],
     makeElement Nothing "hide" [("body", One TContent)],
@@ -172,7 +171,24 @@
       Nothing
       "stack"
       [("children", Many (TLength :|: TRatio :|: TFraction :|: TContent))],
-    makeElement Nothing "table" [("children", Many TContent)],
+    makeElementWithScope Nothing
+      "table"
+      [("children", Many TContent)]
+      [ makeElement (Just "table") "cell" [ ("body", One TContent) ]
+      , makeElement (Just "table") "hline" []
+      , makeElement (Just "table") "vline" []
+      , makeElement (Just "table") "header" [ ("children", Many TContent) ]
+      , makeElement (Just "table") "footer" [ ("children", Many TContent) ]
+      ],
+    makeElementWithScope Nothing
+      "grid"
+      [("children", Many TContent)]
+      [ makeElement (Just "grid") "cell" [ ("body", One TContent) ]
+      , makeElement (Just "grid") "hline" []
+      , makeElement (Just "grid") "vline" []
+      , makeElement (Just "grid") "header" [ ("children", Many TContent) ]
+      , makeElement (Just "grid") "footer" [ ("children", Many TContent) ]
+      ],
     makeElementWithScope
       Nothing
       "terms"
diff --git a/src/Typst/Parse.hs b/src/Typst/Parse.hs
--- a/src/Typst/Parse.hs
+++ b/src/Typst/Parse.hs
@@ -24,7 +24,13 @@
 
 -- import Debug.Trace
 
-parseTypst :: FilePath -> Text -> Either ParseError [Markup]
+-- | Parse text into a list of 'Markup' (or a Parsec @ParseError@).
+parseTypst ::
+  -- | Filepath to Typst source text, only used for error messages
+  FilePath ->
+  -- | The Typst source text 
+  Text ->
+  Either ParseError [Markup]
 parseTypst fp inp =
   case runParser (spaces *> many pMarkup <* pEndOfContent) initialState fp inp of
     Left e -> Left e
@@ -60,8 +66,8 @@
   inp <- getInput
   allowNewlines <- stAllowNewlines <$> getState
   let isSp c
-        | allowNewlines > 0 = c == ' ' || c == '\t' || c == '\n' || c == '\r'
-        | otherwise = c == ' ' || c == '\t'
+        | allowNewlines > 0 = isSpace c
+        | otherwise = isSpace c && c /= '\r' && c /= '\n'
   ( skipMany1 (void (satisfy isSp) <|> void pComment)
       *> updateState (\st -> st {stBeforeSpace = Just (p1, inp)})
     )
@@ -457,7 +463,7 @@
 pLineComment = do
   void $ string "//"
   skipMany (satisfy (\c -> c /= '\n' && c /= '\r'))
-  void endOfLine
+  void endOfLine <|> eof
 
 pBlockComment :: P ()
 pBlockComment = do
@@ -506,7 +512,7 @@
 pBlankline :: P ()
 pBlankline = try $ do
   skipMany spaceChar
-  void (lookAhead (endOfLine)) <|> pEndOfContent
+  void (lookAhead endOfLine) <|> pEndOfContent
 
 pRawInline :: P Markup
 pRawInline =
@@ -644,7 +650,8 @@
   Label . T.pack
     <$> try
       ( char '<'
-          *> many1 (satisfy isIdentContinue <|> char '_' <|> char '.')
+          *> many1 (satisfy isIdentContinue <|>
+                    char '_' <|> char '.' <|> char ':')
           <* char '>'
       )
 
@@ -765,19 +772,14 @@
     <|> pArrayExpr
     <|> pDictExpr
     <|> inParens pExpr
-    <|> (Block . Content . (: []) <$> pEquation)
     <|> pLabel
+    <|> (Block . Content . (: [])
+         <$> lexeme (pRawBlock <|> pRawInline <|> pEquation))
     <|> pBlock
 
 pLiteral :: P Expr
 pLiteral =
-  Literal
-    <$> ( pNone
-            <|> pAuto
-            <|> pBoolean
-            <|> pNumeric
-            <|> pStr
-        )
+  Literal <$> ( pNone <|> pAuto <|> pBoolean <|> pNumeric <|> pStr )
 
 fieldAccess :: Operator Text PState Identity Expr
 fieldAccess = Postfix (FieldAccess <$> try (sym "." *> pIdent))
@@ -988,12 +990,11 @@
       )
         <|> (Array [] <$ optional (void $ sym ","))
 
--- dict-expr ::= '(' (':' | (pair (',' pair)* ','?)) ')'
+-- dict-expr ::= '(' (':' | ':'? (pair (',' pair)* ','?)) ')'
 -- pair ::= (ident | str) ':' expr
 pDictExpr :: P Expr
-pDictExpr = try $ inParens (pEmptyDict <|> pNonemptyDict)
+pDictExpr = try $ inParens (sym ":" *> (pNonemptyDict <|> pure (Dict mempty)) <|> pNonemptyDict)
   where
-    pEmptyDict = Dict mempty <$ sym ":"
     pNonemptyDict = Dict <$> sepEndBy1 (pSpread <|> pPair) (sym ",")
     pPair = Reg <$> ((,) <$> pExpr <*> try (sym ":" *> pExpr))
 
@@ -1045,9 +1046,7 @@
 pArg = pKeyValArg <|> pSpreadArg <|> pNormalArg
   where
     pKeyValArg = KeyValArg <$> try (pIdentifier <* sym ":") <*> pExpr
-    pNormalArg =
-      NormalArg
-        <$> ((Block . Content . (: []) <$> lexeme (pRawBlock <|> pRawInline)) <|> pExpr)
+    pNormalArg = NormalArg <$> pExpr
     pSpreadArg = SpreadArg <$> try (string ".." *> pExpr)
 
 -- params ::= '(' (param (',' param)* ','?)? ')'
diff --git a/src/Typst/Regex.hs b/src/Typst/Regex.hs
--- a/src/Typst/Regex.hs
+++ b/src/Typst/Regex.hs
@@ -28,6 +28,8 @@
 
 -- import Debug.Trace
 
+-- | A regular expression. Note that typst-hs does not use the same Regex engine
+-- as Typst. See issue [#28](https://github.com/jgm/typst-hs/issues/28).
 data RE = RE !Text !Regex
   deriving (Typeable)
 
diff --git a/src/Typst/Types.hs b/src/Typst/Types.hs
--- a/src/Typst/Types.hs
+++ b/src/Typst/Types.hs
@@ -82,31 +82,62 @@
 import Data.Time.Format (defaultTimeLocale, formatTime)
 import System.Directory (XdgDirectory(..))
 
+-- | A Typst value. More documentation can be found in the 
+-- [Foundations chapter](https://typst.app/docs/reference/foundations/)
+-- of the Typst reference manual. A more concise (but somewhat outdated) 
+-- summary can also be found in 
+-- [L. Mädje "Typst: a programmable markup language for typesetting", page 32-33](https://www.user.tu-berlin.de/laurmaedje/programmable-markup-language-for-typesetting.pdf).
 data Val
+  -- | The @none@ value, indicates the absence of any other value.
   = VNone
+  -- | The @auto@ value, used to automatically set an appropriate value.
   | VAuto
+  -- | A @bool@ value.
   | VBoolean !Bool
+  -- | An @int@ value.
   | VInteger !Integer
+  -- | A @float@ value.
   | VFloat !Double
+  -- | A @ratio@ value, a proportion of a certain whole, for example @50%@.
   | VRatio !Rational
+  -- | A @length@ or a @relative@ value.
   | VLength !Length
+  -- | An @alignment@ value, indicating the alignment of some content along both
+  -- the horizontal and vertical axes.
   | VAlignment (Maybe Horiz) (Maybe Vert)
-  | VAngle !Double -- degrees
+  -- | An @angle@ value (expressed internally in degrees).
+  | VAngle !Double
+  -- | A @fraction@ value, defining the proportions of remaing space is 
+  -- to be distributed, e.g. @2 fr@.
   | VFraction !Double
+  -- | A @color@ value. Not all Typst color spaces are supported; 
+  -- only @rgb@, @cmyk@, and @luma@ are available. 
+  -- See issue [#35](https://github.com/jgm/typst-hs/issues/35#issuecomment-1926182040).
   | VColor !Color
+  -- | A @symbol@ value, representing a Unicode symbol.
   | VSymbol !Symbol
+  -- | A UTF-8 encoded text @string@.
   | VString !Text
+  -- | A @regex@ (regular expression). See 'RE' for details.
   | VRegex !RE
+  -- | A @datetime@ value, a date, a time, or a combination of both.
   | VDateTime (Maybe Day) (Maybe DiffTime)
+  -- | A @content@ value, see 'Content' for more details.
   | VContent (Seq Content)
+  -- | An @array@ value, for example @(10, 20, 30)@.
   | VArray (Vector Val)
+  -- | A @dictionary@ value, for example @(a:20, b:30)@.
   | VDict (OM.OMap Identifier Val)
   | VTermItem (Seq Content) (Seq Content)
+  -- | A @direction@ to lay out content.
   | VDirection Direction
+  -- | A Typst function.
   | VFunction (Maybe Identifier) (M.Map Identifier Val) Function
   | -- first param is Just ident if element function
     -- second param is a map of subfunctions in this function's scope
+    -- | Positional and named function arguments
     VArguments Arguments
+  -- | A @label@ to some element, for example @<hello>@. 
   | VLabel !Text
   | VCounter !Counter
   | VSelector !Selector
@@ -142,6 +173,7 @@
   -- typst specifies that unsupported datetimes map to strings and we don't have a place for the timezone
 tomlToVal v@Toml.ZonedTime'{} = VString (T.pack (show (Toml.prettyValue v)))
 
+-- | A Typst type, see documentation for 'Val'.
 data ValType
   = TNone
   | TAuto
@@ -768,7 +800,11 @@
   | Luma Rational
   deriving (Show, Eq, Ord, Typeable)
 
-data Direction = Ltr | Rtl | Ttb | Btt
+data Direction 
+  = Ltr -- ^ Left to right
+  | Rtl -- ^ Right to left
+  | Ttb -- ^ Top to bottom
+  | Btt -- ^ Bottom to top
   deriving (Show, Eq, Ord, Typeable)
 
 prettyVal :: Val -> P.Doc
diff --git a/test/out/compiler/spread-09.out b/test/out/compiler/spread-09.out
--- a/test/out/compiler/spread-09.out
+++ b/test/out/compiler/spread-09.out
@@ -1,3 +1,127 @@
-"test/typ/compiler/spread-09.typ" (line 14, column 9):
-unexpected ":"
-expecting "//", "/*", "none", "auto", "true", "false", "0b", "0x", "0o", digit, ".", "\"", "let", "set", "show", "if", "while", "for", "import", "include", "break", "continue", "return", "(", "$", "<", "{" or "["
+--- parse tree ---
+[ Code
+    "test/typ/compiler/spread-09.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/compiler/spread-09.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/compiler/spread-09.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Comment
+, Code
+    "test/typ/compiler/spread-09.typ"
+    ( line 3 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "l")))
+              (Array
+                 [ Reg (Literal (Int 1))
+                 , Reg (Literal (Int 2))
+                 , Reg (Literal (Int 3))
+                 ])
+          , Let
+              (BasicBind (Just (Identifier "r")))
+              (Array
+                 [ Reg (Literal (Int 5))
+                 , Reg (Literal (Int 6))
+                 , Reg (Literal (Int 7))
+                 ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (Array
+                     [ Spr (Ident (Identifier "l"))
+                     , Reg (Literal (Int 4))
+                     , Spr (Ident (Identifier "r"))
+                     ])
+              , NormalArg
+                  (FuncCall
+                     (Ident (Identifier "range"))
+                     [ NormalArg (Literal (Int 1)) , NormalArg (Literal (Int 8)) ])
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg (Dict [ Spr (Literal None) ]) , NormalArg (Array []) ]
+          ]))
+, ParBreak
+, Code
+    "test/typ/compiler/spread-09.typ"
+    ( line 10 , column 2 )
+    (Block
+       (CodeBlock
+          [ Let
+              (BasicBind (Just (Identifier "x")))
+              (Dict [ Reg ( Ident (Identifier "a") , Literal (Int 1) ) ])
+          , Let
+              (BasicBind (Just (Identifier "y")))
+              (Dict [ Reg ( Ident (Identifier "b") , Literal (Int 2) ) ])
+          , Let
+              (BasicBind (Just (Identifier "z")))
+              (Dict [ Reg ( Ident (Identifier "a") , Literal (Int 3) ) ])
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (Dict
+                     [ Spr (Ident (Identifier "x"))
+                     , Spr (Ident (Identifier "y"))
+                     , Spr (Ident (Identifier "z"))
+                     ])
+              , NormalArg
+                  (Dict
+                     [ Reg ( Ident (Identifier "a") , Literal (Int 3) )
+                     , Reg ( Ident (Identifier "b") , Literal (Int 2) )
+                     ])
+              ]
+          , FuncCall
+              (Ident (Identifier "test"))
+              [ NormalArg
+                  (Dict
+                     [ Spr (Dict [ Reg ( Ident (Identifier "a") , Literal (Int 1) ) ])
+                     , Reg ( Ident (Identifier "b") , Literal (Int 2) )
+                     ])
+              , NormalArg
+                  (Dict
+                     [ Reg ( Ident (Identifier "a") , Literal (Int 1) )
+                     , Reg ( Ident (Identifier "b") , Literal (Int 2) )
+                     ])
+              ]
+          ]))
+, ParBreak
+]
+"test/typ/compiler/spread-09.typ" (line 3, column 2):
+unexpected end of input
+expecting end of input
+Could not spread TNone into dictionary
diff --git a/test/out/regression/issue43.out b/test/out/regression/issue43.out
new file mode 100644
--- /dev/null
+++ b/test/out/regression/issue43.out
@@ -0,0 +1,124 @@
+--- parse tree ---
+[ Code
+    "test/typ/regression/issue43.typ"
+    ( line 1 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "test")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") , NormalParam (Identifier "y") ]
+          (Block
+             (CodeBlock
+                [ If
+                    [ ( Equals (Ident (Identifier "x")) (Ident (Identifier "y"))
+                      , Block (Content [ Text "\9989" ])
+                      )
+                    , ( Literal (Boolean True)
+                      , Block
+                          (Content
+                             [ Text "\10060"
+                             , Text "("
+                             , Code
+                                 "test/typ/regression/issue43.typ"
+                                 ( line 1 , column 47 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "x")) ])
+                             , Space
+                             , Text "/"
+                             , Text "="
+                             , Space
+                             , Code
+                                 "test/typ/regression/issue43.typ"
+                                 ( line 1 , column 59 )
+                                 (FuncCall
+                                    (Ident (Identifier "repr"))
+                                    [ NormalArg (Ident (Identifier "y")) ])
+                             , Text ")"
+                             ])
+                      )
+                    ]
+                ]))))
+, SoftBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 2 , column 1 )
+    (Label "foo:bar")
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 4 , column 2 )
+    (Let (BasicBind (Just (Identifier "a"))) (Literal (String "a")))
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 6 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "w")))
+       (FuncExpr
+          [ NormalParam (Identifier "x") ]
+          (Plus
+             (Block (Content [ Equation False [ Text "x" ] ]))
+             (Ident (Identifier "x")))))
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 8 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "x")))
+       (Block (Content [ RawInline "hello" ])))
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 10 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "a")))
+       (Dict [ Reg ( Ident (Identifier "a") , Literal (Int 1) ) ]))
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 12 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "b")))
+       (Dict [ Reg ( Ident (Identifier "b") , Literal (Int 2) ) ]))
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 14 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "c")))
+       (Dict [ Reg ( Ident (Identifier "c") , Literal (Int 3) ) ]))
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 16 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "d")))
+       (Dict [ Spr (Ident (Identifier "a")) ]))
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 18 , column 2 )
+    (Let
+       (BasicBind (Just (Identifier "e")))
+       (Dict [ Spr (Ident (Identifier "b")) ]))
+, ParBreak
+, Code
+    "test/typ/regression/issue43.typ"
+    ( line 20 , column 2 )
+    (Let (BasicBind (Just (Identifier "f"))) (Dict []))
+, ParBreak
+]
+--- evaluated ---
+document(body: { text(body: [
+]), 
+                 <foo:bar>, 
+                 parbreak(), 
+                 parbreak(), 
+                 parbreak(), 
+                 parbreak(), 
+                 parbreak(), 
+                 parbreak(), 
+                 parbreak(), 
+                 parbreak(), 
+                 parbreak(), 
+                 parbreak() })
diff --git a/test/typ/regression/issue43.typ b/test/typ/regression/issue43.typ
new file mode 100644
--- /dev/null
+++ b/test/typ/regression/issue43.typ
@@ -0,0 +1,19 @@
+<foo:bar>
+
+#let a = "a"
+
+#let w = x => $x$ + x
+
+#let x = `hello`
+
+#let a = (a:1)
+
+#let b = (:b:2)
+
+#let c = ( : c : 3)
+
+#let d = (:..a)
+
+#let e = ( : ..b)
+
+#let f = (:)
diff --git a/typst.cabal b/typst.cabal
--- a/typst.cabal
+++ b/typst.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               typst
-version:            0.5.0.2
+version:            0.5.0.3
 synopsis:           Parsing and evaluating typst syntax.
 description:        A library for parsing and evaluating typst syntax.
                     Typst (<https://typst.app>) is a document layout and
@@ -56,7 +56,7 @@
 
     -- other-extensions:
     build-depends:    base >= 4.14 && <= 5,
-                      typst-symbols >= 0.1.5 && < 0.1.6,
+                      typst-symbols >= 0.1.6 && < 0.1.7,
                       mtl,
                       vector,
                       parsec,
