Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 31 additions & 14 deletions src/Text/Pandoc/Writers/Typst.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import Control.Monad.State ( StateT, evalStateT, gets, modify )
import Text.Pandoc.Writers.Shared ( lookupMetaInlines, lookupMetaString,
metaToContext, defField, resetField,
setupTranslations )
import Text.Pandoc.Shared (isTightList, orderedListMarkers, tshow)
import Text.Pandoc.Shared (isTightList, orderedListMarkers, stringify, tshow)
import Text.Pandoc.Highlighting (highlight, formatTypstBlock, formatTypstInline,
styleToTypst)
import Text.Pandoc.Translations (Term(Abstract), translateTerm)
Expand Down Expand Up @@ -365,10 +365,16 @@ blockToTypst block =
opts <- gets stOptions
contents <- case blocks of
-- don't need #box around block-level image
[Para [Image attr _ (src, _)]]
-> pure $ mkImage opts False src attr
[Plain [Image attr _ (src, _)]]
-> pure $ mkImage opts False src attr
[Para [Image attr imgInlines (src, _)]]
-> let mbAlt = if null imgInlines
then Nothing
else Just (stringify imgInlines)
in pure $ mkImage opts False src attr mbAlt
[Plain [Image attr imgInlines (src, _)]]
-> let mbAlt = if null imgInlines
then Nothing
else Just (stringify imgInlines)
in pure $ mkImage opts False src attr mbAlt
_ -> brackets <$> blocksToTypst blocks
let lab = toLabel FreestandingLabel ident
return $ "#figure(" <> nest 2 ((contents <> ",")
Expand Down Expand Up @@ -529,34 +535,45 @@ inlineToTypst inline =
(if inlines == [Str src]
then mempty
else nowrap $ brackets contents)
Image attr _inlines (src,_tit) -> do
opts <- gets stOptions
pure $ mkImage opts True src attr
Image attr imgInlines (src,_tit) -> do
opts <- gets stOptions
let mbAlt = if null imgInlines
then Nothing
else Just (stringify imgInlines)
pure $ mkImage opts True src attr mbAlt
Note blocks -> do
contents <- blocksToTypst blocks
return $ "#footnote" <> brackets (chomp contents)

-- see #9104; need box or image is treated as block-level
mkImage :: WriterOptions -> Bool -> Text -> Attr -> Doc Text
mkImage opts useBox src attr
mkImage :: WriterOptions -> Bool -> Text -> Attr -> Maybe Text -> Doc Text
mkImage opts useBox src (ident, cls, kvs) mbAlt
| useBox = "#box" <> parens coreImage
| otherwise = coreImage
where
src' = T.pack $ unEscapeString $ T.unpack src -- #9389
showDim (Pixel a) = literal (showInInch opts (Pixel a) <> "in")
showDim dim = text (show dim)
-- Priority: explicit alt attribute > inlines from markdown
-- Empty alt="" is preserved (indicates decorative image)
altText = case lookup "alt" kvs of
Just alt -> Just alt
Nothing -> mbAlt
altAttr = case altText of
Just alt | not (T.null alt) -> ", alt: " <> doubleQuoted alt
_ -> mempty
dimAttrs =
(case dimension Height attr of
(case dimension Height (ident, cls, kvs) of
Nothing -> mempty
Just dim -> ", height: " <> showDim dim) <>
(case dimension Width attr of
(case dimension Width (ident, cls, kvs) of
Nothing -> mempty
Just dim -> ", width: " <> showDim dim)
isData = "data:" `T.isPrefixOf` src'
dataSvg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><image xlink:href=\"" <> src' <> "\" /></svg>"
coreImage
| isData = "image.decode" <> parens(doubleQuoted dataSvg <> dimAttrs)
| otherwise = "image" <> parens (doubleQuoted src' <> dimAttrs)
| isData = "image.decode" <> parens(doubleQuoted dataSvg <> altAttr <> dimAttrs)
| otherwise = "image" <> parens (doubleQuoted src' <> altAttr <> dimAttrs)

textstyle :: PandocMonad m => Doc Text -> [Inline] -> TW m (Doc Text)
textstyle s inlines = do
Expand Down
11 changes: 6 additions & 5 deletions test/command/9236.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,26 @@
And inline: ![minimal](command/minimal.svg){height=2in} and
![minimal](command/minimal.svg).
^D
#figure(image("command/minimal.svg", width: 3in),
#figure(image("command/minimal.svg", alt: "minimal", width: 3in),
caption: [
minimal
]
)

#figure(image("command/minimal.svg", height: 2in, width: 3in),
#figure(image("command/minimal.svg", alt: "minimal", height: 2in, width: 3in),
caption: [
minimal
]
)

#figure(image("command/minimal.svg"),
#figure(image("command/minimal.svg", alt: "minimal"),
caption: [
minimal
]
)

And inline: #box(image("command/minimal.svg", height: 2in)) and
#box(image("command/minimal.svg")).
And inline:
#box(image("command/minimal.svg", alt: "minimal", height: 2in)) and
#box(image("command/minimal.svg", alt: "minimal")).

```
78 changes: 78 additions & 0 deletions test/command/typst-image-alt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
```
% pandoc -f markdown-implicit_figures -t typst
![Alt text from inlines](image.png)
^D
#box(image("image.png", alt: "Alt text from inlines"))
```

```
% pandoc -f markdown-implicit_figures -t typst
![](image.png){alt="Explicit alt attribute"}
^D
#box(image("image.png", alt: "Explicit alt attribute"))
```

```
% pandoc -f markdown-implicit_figures -t typst
![Inlines ignored](image.png){alt="Explicit wins"}
^D
#box(image("image.png", alt: "Explicit wins"))
```

```
% pandoc -f markdown-implicit_figures -t typst
![](image.png)
^D
#box(image("image.png"))
```

```
% pandoc -f markdown-implicit_figures -t typst
![Inlines ignored for decorative](image.png){alt=""}
^D
#box(image("image.png"))
```

```
% pandoc -t typst
![Caption text](image.png){alt="Alt text describing the image"}

^D
#figure(image("image.png", alt: "Alt text describing the image"),
caption: [
Caption text
]
)
```

```
% pandoc -t typst
![Caption only](image.png)

^D
#figure(image("image.png", alt: "Caption only"),
caption: [
Caption only
]
)
```

```
% pandoc -f markdown -t typst
![Caption](test.png){alt="A \"quoted\" phrase and C:\\path\\file"}
^D
#figure(image("test.png", alt: "A \"quoted\" phrase and C:\\path\\file"),
caption: [
Caption
]
)

```

```
% pandoc -f html -t typst
<img src="data:image/png;base64,iVBORw0KGgo=" alt="A small red dot">
^D
#box(image.decode("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><image xlink:href=\"data:image/png;base64,iVBORw0KGgo=\" /></svg>", alt: "A small red dot"))

```
4 changes: 2 additions & 2 deletions test/writer.typst
Original file line number Diff line number Diff line change
Expand Up @@ -837,13 +837,13 @@ or here: <http://example.com/>
<images>
From "Voyage dans la Lune" by Georges Melies (1902):

#figure(image("lalune.jpg"),
#figure(image("lalune.jpg", alt: "lalune"),
caption: [
lalune
]
)

Here is a movie #box(image("movie.jpg")) icon.
Here is a movie #box(image("movie.jpg", alt: "movie")) icon.

#horizontalrule

Expand Down