mirror of
https://github.com/jgm/pandoc.git
synced 2026-08-28 17:20:47 +08:00
Typst reader: support auto_identifiers extension.
Headings without an explicit label can now be assigned automatic identifiers based on the heading text, making them linkable in a generated table of contents. The extension is available for the typst reader but is off by default; enable it with `-f typst+auto_identifiers`. The related `gfm_auto_identifiers` and `ascii_identifiers` extensions are also made available. Closes #11041. Text.Pandoc.Readers.Typst.Parsing: PState gains sOptions, sIdentifiers, and sLogMessages fields, and now has HasReaderOptions, HasIdentifierList, and HasLogMessages instances, allowing reuse of the shared registerHeader. (Not an API change.) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -3673,7 +3673,7 @@ automatically assigned a unique identifier based on the heading text.
|
||||
This extension can be enabled/disabled for the following formats:
|
||||
|
||||
input formats
|
||||
: `markdown`, `latex`, `rst`, `mediawiki`, `textile`, `man`
|
||||
: `markdown`, `latex`, `rst`, `mediawiki`, `textile`, `man`, `typst`
|
||||
|
||||
output formats
|
||||
: `markdown`, `muse`
|
||||
|
||||
@@ -662,7 +662,8 @@ getAllExtensions f = universalExtensions <> getAll f
|
||||
getAll "mediawiki" = autoIdExtensions <>
|
||||
extensionsFromList
|
||||
[ Ext_smart ]
|
||||
getAll "typst" = extensionsFromList [Ext_citations, Ext_smart]
|
||||
getAll "typst" = autoIdExtensions <>
|
||||
extensionsFromList [Ext_citations, Ext_smart]
|
||||
getAll "djot" = extensionsFromList [Ext_sourcepos]
|
||||
getAll "man" = autoIdExtensions
|
||||
getAll _ = mempty
|
||||
|
||||
@@ -31,6 +31,7 @@ import Typst ( parseTypst, evaluateTypst )
|
||||
import Text.Pandoc.Error (PandocError(..))
|
||||
import Text.Pandoc.Translations (Term(References), translateTerm)
|
||||
import Text.Pandoc.Shared (tshow, blocksToInlines)
|
||||
import Text.Pandoc.Parsing (registerHeader, reportLogMessages)
|
||||
import Control.Monad.Except (throwError)
|
||||
import Control.Monad (MonadPlus (mplus), void, guard, foldM)
|
||||
import Control.Monad.Trans (lift)
|
||||
@@ -79,7 +80,7 @@ readTypst opts inp = do
|
||||
Right content -> do
|
||||
let content' = fixNesting content
|
||||
let labs = findLabels [content']
|
||||
runParserT pPandoc defaultPState{ sLabels = labs }
|
||||
runParserT pPandoc defaultPState{ sLabels = labs, sOptions = opts }
|
||||
inputName [content'] >>=
|
||||
either (throwError . PandocParseError . T.pack . show) pure
|
||||
|
||||
@@ -188,6 +189,7 @@ pPandoc = do
|
||||
(if null keywords
|
||||
then id
|
||||
else B.setMeta "keywords" keywords) $ meta
|
||||
reportLogMessages
|
||||
pure $ Pandoc meta' (B.toList bs)
|
||||
|
||||
pBlocks :: PandocMonad m => P m B.Blocks
|
||||
@@ -264,8 +266,9 @@ blockHandlers = M.fromList
|
||||
,("heading", \_ mbident fields -> do
|
||||
body <- getField "body" fields
|
||||
lev <- getField "level" fields <|> pure 1
|
||||
B.headerWith (fromMaybe "" mbident,[],[]) lev
|
||||
<$> pWithContents pInlines body)
|
||||
ils <- pWithContents pInlines body
|
||||
attr <- registerHeader (fromMaybe "" mbident,[],[]) ils
|
||||
pure $ B.headerWith attr lev ils)
|
||||
,("quote", \_ _ fields -> do
|
||||
getField "block" fields >>= guard
|
||||
body <- getField "body" fields >>= pWithContents pBlocks
|
||||
|
||||
@@ -16,10 +16,13 @@ module Text.Pandoc.Readers.Typst.Parsing
|
||||
where
|
||||
import Control.Monad (MonadPlus)
|
||||
import Control.Monad.Reader (lift)
|
||||
import Data.Default (def)
|
||||
import qualified Data.Foldable as F
|
||||
import qualified Data.Map as M
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.Sequence (Seq)
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as Set
|
||||
import Data.Text (Text)
|
||||
import Text.Parsec
|
||||
( ParsecT, getInput, setInput, tokenPrim )
|
||||
@@ -27,18 +30,38 @@ import Typst.Types
|
||||
( Identifier, Content(Elt), FromVal(..), Val(VNone) )
|
||||
import Text.Pandoc.Class.PandocMonad ( PandocMonad, report )
|
||||
import Text.Pandoc.Logging (LogMessage(..))
|
||||
import Text.Pandoc.Options (ReaderOptions)
|
||||
import Text.Pandoc.Parsing.Capabilities
|
||||
( HasReaderOptions(..), HasIdentifierList(..), HasLogMessages(..) )
|
||||
import Text.Pandoc.Definition
|
||||
|
||||
data PState = PState
|
||||
{ sLabels :: [Text]
|
||||
, sMeta :: Meta }
|
||||
, sMeta :: Meta
|
||||
, sOptions :: ReaderOptions
|
||||
, sIdentifiers :: Set Text
|
||||
, sLogMessages :: [LogMessage] }
|
||||
deriving (Show)
|
||||
|
||||
instance HasReaderOptions PState where
|
||||
extractReaderOptions = sOptions
|
||||
|
||||
instance HasIdentifierList PState where
|
||||
extractIdentifierList = sIdentifiers
|
||||
updateIdentifierList f st = st{ sIdentifiers = f (sIdentifiers st) }
|
||||
|
||||
instance HasLogMessages PState where
|
||||
addLogMessage m st = st{ sLogMessages = m : sLogMessages st }
|
||||
getLogMessages = reverse . sLogMessages
|
||||
|
||||
defaultPState :: PState
|
||||
defaultPState =
|
||||
PState
|
||||
{ sLabels = []
|
||||
, sMeta = mempty }
|
||||
, sMeta = mempty
|
||||
, sOptions = def
|
||||
, sIdentifiers = Set.empty
|
||||
, sLogMessages = [] }
|
||||
|
||||
type P m a = ParsecT [Content] PState m a
|
||||
-- state tracks a list of labels in the document
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
With `auto_identifiers` enabled, headings without an explicit label get
|
||||
automatic identifiers, with collisions disambiguated:
|
||||
|
||||
```
|
||||
% pandoc -f typst+auto_identifiers -t native
|
||||
= Introduction
|
||||
|
||||
Text.
|
||||
|
||||
== A Sub Section
|
||||
|
||||
= Introduction
|
||||
^D
|
||||
[ Header
|
||||
1 ( "introduction" , [] , [] ) [ Str "Introduction" ]
|
||||
, Para [ Str "Text." ]
|
||||
, Header
|
||||
2
|
||||
( "a-sub-section" , [] , [] )
|
||||
[ Str "A" , Space , Str "Sub" , Space , Str "Section" ]
|
||||
, Header
|
||||
1 ( "introduction-1" , [] , [] ) [ Str "Introduction" ]
|
||||
]
|
||||
```
|
||||
|
||||
The extension is off by default, so headings have no identifiers:
|
||||
|
||||
```
|
||||
% pandoc -f typst -t native
|
||||
= Introduction
|
||||
|
||||
Text.
|
||||
^D
|
||||
[ Header 1 ( "" , [] , [] ) [ Str "Introduction" ]
|
||||
, Para [ Str "Text." ]
|
||||
]
|
||||
```
|
||||
Reference in New Issue
Block a user