typst 0.3.0.0 → 0.3.1.0
raw patch · 9 files changed
+156/−36 lines, 9 filesdep ~toml-parserdep ~typst-symbols
Dependency ranges changed: toml-parser, typst-symbols
Files
- CHANGELOG.md +23/−0
- src/Typst/Evaluate.hs +30/−14
- src/Typst/Methods.hs +2/−0
- src/Typst/Module/Standard.hs +10/−1
- src/Typst/Parse.hs +2/−1
- src/Typst/Regex.hs +32/−15
- src/Typst/Types.hs +24/−1
- test/out/compute/data-08.out +31/−2
- typst.cabal +2/−2
CHANGELOG.md view
@@ -1,5 +1,28 @@ # Revision history for typst-hs +## 0.3.1.0++ * Allow multiplying a ratio by a length.++ * Use `symModule` and `mathModule` directly when evaluating+ Equation instead of looking up `sym` and `math`.++ * Fix parsing of escapes in string literals. Symbols in general+ can't be escaped. There is just a small list of valid escapes.++ * Fix bugs in converting typst regexes to TDFA's format.++ * Allow Symbol to be regex replacement text.++ * Allow VString and VSymbol to be +'d.++ * Update for toml-parser-1.2.0.0 API changes (#9, Eric Mertens).++ * Derive the decoder for typst.toml (#7, Eric Mertens)++ * Implement typst's `toml()` function (#8, Eric Mertens).++ ## 0.3.0.0 * We now target typst 0.6.
src/Typst/Evaluate.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-}@@ -26,11 +27,13 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as TE import qualified Data.Vector as V+import GHC.Generics (Generic) import System.FilePath (replaceFileName, takeBaseName, takeDirectory, (</>)) import Text.Parsec import Typst.Bind (destructuringBind) import Typst.Methods (getMethod)-import Typst.Module.Standard (loadFileText, standardModule)+import Typst.Module.Standard (loadFileText, standardModule, symModule)+import Typst.Module.Math (mathModule) import Typst.Parse (parseTypst) import Typst.Regex (match) import Typst.Show (applyShowRules)@@ -38,6 +41,8 @@ import Typst.Types import Typst.Util (makeFunction, nthArg) import qualified Toml as Toml+import qualified Toml.FromValue as Toml+import qualified Toml.FromValue.Generic as Toml -- import Debug.Trace @@ -233,10 +238,8 @@ [("level", VInteger (fromIntegral level))] } Equation display ms -> inBlock BlockScope $ do- VModule _ mathmod <- lookupIdentifier "math"- importModule mathmod- VModule _ symmod <- lookupIdentifier "sym"- importModule symmod+ importModule mathModule+ importModule symModule oldMath <- evalMath <$> getState updateState $ \st -> st {evalMath = True} content <- pInnerContents ms@@ -888,6 +891,24 @@ pure res pure fn +-- | Type of TOML configuration file used in 'findPackageEntryPoint' saved as `typst.toml`+data Config = Config {+ package :: PackageConfig++} deriving (Show, Generic)++data PackageConfig = PackageConfig {+ entrypoint :: String+} deriving (Show, Generic)++-- | Derived generically from record field names+instance Toml.FromValue Config where+ fromValue = Toml.parseTableFromValue Toml.genericParseTable++-- | Derived generically from record field names+instance Toml.FromValue PackageConfig where+ fromValue = Toml.parseTableFromValue Toml.genericParseTable+ findPackageEntryPoint :: Monad m => Text -> MP m FilePath findPackageEntryPoint modname = do let (namespace, rest) = break (=='/') (drop 1 $ T.unpack modname)@@ -931,15 +952,10 @@ "\nCompile with typst compile to bring the package into your local cache." -- TODO? fetch from CDN if not present in cache? tomlString <- T.unpack . TE.decodeUtf8 <$> lift (loadBytes operations tomlPath)- case Toml.parse tomlString of- Left e -> fail e- Right toptbl ->- case M.lookup "package" toptbl of- Just (Toml.Table tbl) ->- case M.lookup "entrypoint" tbl of- Just (Toml.String f) -> pure $ replaceFileName tomlPath f- _ -> fail "Could not find entrypoint"- _ -> fail "Could not find [package] table"+ case Toml.decode tomlString of+ Toml.Failure e -> fail (unlines ("Failure loading typst.toml" : e))+ Toml.Success _warnings cfg -> -- ignores warnings like unused keys in TOML+ pure (replaceFileName tomlPath (entrypoint (package cfg))) loadModule :: Monad m => Text -> MP m (Seq Content, (Identifier, M.Map Identifier Val))
src/Typst/Methods.hs view
@@ -234,6 +234,8 @@ case replacement of VString r -> pure $ VString $ replaceRegex patt mbCount (const r) t+ VSymbol (Symbol r _ _) ->+ pure $ VString $ replaceRegex patt mbCount (const r) t VFunction _ _ f -> pure $ VString $
src/Typst/Module/Standard.hs view
@@ -6,6 +6,7 @@ module Typst.Module.Standard ( standardModule,+ symModule, loadFileText, applyPureFunction )@@ -32,6 +33,7 @@ import Text.Parsec (getPosition, getState, updateState, runParserT) import Text.Read (readMaybe) import qualified Text.XML as XML+import qualified Toml import Typst.Emoji (typstEmojis) import Typst.Module.Calc (calcModule) import Typst.Module.Math (mathModule)@@ -549,7 +551,14 @@ t <- lift $ loadFileText fp pure $ VString t ),- ("toml", makeFunction $ fail "unimplemented toml"),+ ( "toml",+ makeFunction $ do+ fp <- nthArg 1+ t <- lift $ loadFileText fp+ case Toml.decode (T.unpack t) of+ Toml.Failure e -> fail (unlines ("toml errors:" : e))+ Toml.Success _ v -> pure v+ ), ( "xml", makeFunction $ do fp <- nthArg 1
src/Typst/Parse.hs view
@@ -579,7 +579,8 @@ try $ char '\\' *> ( uniEsc- <|> satisfy isSpecial+ <|> ('\\' <$ char '\\')+ <|> ('"' <$ char '"') <|> ('\n' <$ char 'n') <|> ('\t' <$ char 't') <|> ('\r' <$ char 'r')
src/Typst/Regex.hs view
@@ -84,22 +84,39 @@ where (caseSensitive, t') = if "(?i)" `T.isPrefixOf` t- then (False, T.pack . go . T.unpack $ T.drop 4 t)- else (True, T.pack . go . T.unpack $ t)+ then (False, T.pack . go False . T.unpack $ T.drop 4 t)+ else (True, T.pack . go False . T.unpack $ t) compopts = TDFA.defaultCompOpt {TDFA.caseSensitive = caseSensitive}- -- handle things not supported in TFFA (posix) regexes, e.g. \d \w \s, +, ?- go [] = []- go ('?' : cs) = "{0,1}" ++ go cs- go ('+' : cs) = "{1,}" ++ go cs- go ('\\' : c : cs)- | c == 'd' = "[[:digit:]]" ++ go cs- | c == 'D' = "[^[:digit:]]" ++ go cs- | c == 's' = "[[:space:]]" ++ go cs- | c == 'S' = "[^[:space:]]" ++ go cs- | c == 'w' = "[[:word:]]" ++ go cs- | c == 'W' = "[^[:word:]]" ++ go cs- | otherwise = '\\' : c : go cs- go (c : cs) = c : go cs++ -- Handle things not supported in TFFA posix regexes, e.g. \d \w \s, +, ?+ -- Note that we have to track whether we're in a character class, because+ -- the expansions will be different in that case. The first+ -- parameter of `go` is True if in a character class.+ go _ [] = []+ go True (']' : cs) = ']' : go False cs+ go False ('[' : cs) = '[' :+ case cs of+ '^':']':ds -> '^' : ']' : go True ds+ '^':'\\':']':ds -> '^' : ']' : go True ds+ ']':ds -> ']' : go True ds+ '\\':']':ds -> ']' : go True ds+ _ -> go True cs+ go False ('?' : cs) = "{0,1}" ++ go False cs+ go False ('+' : cs) = "{1,}" ++ go False cs+ go inCharClass ('\\' : c : cs)+ = let f = if inCharClass+ then id+ else \x -> "[" ++ x ++ "]"+ r = case c of+ 'd' -> f "[:digit:]"+ 'D' -> f "^[:digit:]"+ 's' -> f "[:space:]"+ 'S' -> f "^[:space:]"+ 'w' -> f "[:word:]"+ 'W' -> f "^[:word:]"+ _ -> ['\\', c]+ in r ++ go inCharClass cs+ go inCharClass (c : cs) = c : go inCharClass cs match :: TDFA.RegexContext Regex source target => RE -> source -> target match (RE _ re) t = TDFA.match re t
src/Typst/Types.hs view
@@ -70,11 +70,14 @@ import Data.Vector (Vector) import qualified Data.Vector as V import Text.Parsec+import qualified Toml+import qualified Toml.FromValue as Toml+import qualified Toml.Pretty as Toml import qualified Text.PrettyPrint as P import Text.Read (readMaybe) import Typst.Regex (RE, makeLiteralRE) import Typst.Syntax (Identifier (..), Markup)-import Data.Time (UTCTime, Day, DiffTime)+import Data.Time (UTCTime, Day, DiffTime, timeOfDayToTime, localDay, localTimeOfDay) import Data.Time.Format (defaultTimeLocale, formatTime) import System.Directory (XdgDirectory(..)) @@ -120,6 +123,22 @@ parseJSON (Aeson.Bool b) = pure $ VBoolean b parseJSON Aeson.Null = pure VNone +instance Toml.FromValue Val where+ fromValue = pure . tomlToVal++tomlToVal :: Toml.Value -> Val+tomlToVal (Toml.Bool x) = VBoolean x+tomlToVal (Toml.Integer x) = VInteger x+tomlToVal (Toml.String x) = VString (T.pack x)+tomlToVal (Toml.Float x) = VFloat x+tomlToVal (Toml.TimeOfDay x) = VDateTime Nothing (Just (timeOfDayToTime x))+tomlToVal (Toml.Day x) = VDateTime (Just x) Nothing+tomlToVal (Toml.LocalTime x) = VDateTime (Just (localDay x)) (Just (timeOfDayToTime (localTimeOfDay x)))+tomlToVal (Toml.Array x) = VArray (V.fromList (map tomlToVal x))+tomlToVal (Toml.Table x) = VDict (OM.fromList [(Identifier (T.pack k), tomlToVal v) | (k,v) <- M.assocs x])+ -- 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)))+ data ValType = TNone | TAuto@@ -386,6 +405,8 @@ maybePlus (VContent c1) (VContent c2) = pure $ VContent (c1 <> c2) maybePlus (VString s1) (VContent c2) = pure $ VContent (Txt s1 Seq.<| c2) maybePlus (VContent c1) (VString s2) = pure $ VContent (c1 Seq.|> Txt s2)+ maybePlus (VString s1) sym@(VSymbol{}) = pure $ VString (s1 <> repr sym)+ maybePlus sym@(VSymbol{}) (VString s2) = pure $ VString (repr sym <> s2) maybePlus (VLength l1) (VLength l2) = pure $ VLength (l1 <> l2) maybePlus (VLength l1) (VRatio r1) = pure $ VLength (l1 <> LRatio r1) maybePlus (VRatio r1) (VLength l1) = pure $ VLength (l1 <> LRatio r1)@@ -422,6 +443,8 @@ | i >= 0 = pure $ VContent (mconcat $ replicate (fromIntegral i) c) maybeTimes (VInteger i) (VLength l) = pure $ VLength $ timesLength (fromIntegral i) l maybeTimes (VLength l) (VInteger i) = pure $ VLength $ timesLength (fromIntegral i) l+ maybeTimes (VRatio r) (VLength l) = pure $ VLength $ timesLength (fromRational r) l+ maybeTimes (VLength l) (VRatio r) = pure $ VLength $ timesLength (fromRational r) l maybeTimes (VFloat f) (VLength l) = pure $ VLength $ timesLength f l maybeTimes (VLength l) (VFloat f) = pure $ VLength $ timesLength f l maybeTimes (VInteger i) (VAngle a) = pure $ VAngle (fromIntegral i * a)
test/out/compute/data-08.out view
@@ -169,5 +169,34 @@ ]) , ParBreak ]-"test/typ/compute/data-08.typ" (line 3, column 2):-unimplemented toml+--- evaluated ---+{ text(body: [+]), + text(body: [+]), + text(body: [✅]), + text(body: [+]), + text(body: [✅]), + text(body: [+]), + text(body: [✅]), + text(body: [+]), + text(body: [✅]), + text(body: [+]), + text(body: [✅]), + text(body: [+]), + text(body: [✅]), + text(body: [+]), + text(body: [✅]), + text(body: [+]), + text(body: [✅]), + text(body: [+]), + text(body: [✅]), + parbreak() }
typst.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: typst-version: 0.3.0.0+version: 0.3.1.0 synopsis: Parsing and evaluating typst syntax. description: A library for parsing and evaluating typst syntax. Typst (<https://typst.app>) is a document layout and@@ -70,7 +70,7 @@ scientific, xml-conduit, yaml,- toml-parser,+ toml-parser ^>= 1.2.0.0, regex-tdfa, array, time,