Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

markdown additional Image width parameter for HTML/Epub, LaTeX/PDF output formats #350

Open
wants to merge 5 commits into from
@rwst

Hello,
this resolves #332 and provides implementations in the HTML and LaTeX writers.
It is dependent on the two patches

What does it do? The markdown

![alttext](image.jpg)

will produce markdown output

![alttext](image.jpg)@100

or HTML output

<div class="figure">
<img src="image.jpg" width="100%" alt="alttext" /><p class="caption">alttext</p>
</div>

or LaTeX output

\begin{figure}[htbp]
\centering
\includegraphics[width=1.0\textwidth]{image.jpg}
 \caption{alttext}
 \end{figure}

Any digits after the @ character will be interpreted as width percentage, atm

@jgm
Owner

I do appreciate the patch, but it is not going to be merged. In the future it would be better to discuss proposed syntax extensions on the pandoc-discuss list first, before coding anything. Image size syntax has been discussed before, and there are a number of intertwined issues that I haven't resolved. I don't want to make changes to the Pandoc type or especially the markdown syntax until I'm really convinced they're the best option. I think there are a couple of more natural and markdownish proposals than the one you implement here.

@zhou13

I really hope that we can adjust image's size in pandoc. This bug has already lasted for 2 years.... And this patch really solve the problem.

@shrutikapoor08

Since everyone is having an issue with the image sizing in Pandoc, I think it is really necessary to have this included in Pandoc.

@linquize

This is a +1 feature. We have been waiting for long time

@jgm
Owner

Why is it such a problem to resize the image itself? It just takes one call to ImageMagick's convert or mogrify command to do this. You can also set the DPI, so that a single image will render at the right size in both HTML and LaTeX. For example,

mogrify -density 150 -resize 300x300 my.jpg

will give you an image that displays on the web as 300x300 pixels, and as a 2 inch (300/150) square in LaTeX/PDF. Is the problem that the PDF image will then be too low-res? If so, one could easily create two images, one for the PDF and one for the HTML.

@adityam

Or just use a preprocessor like gpp. When I need more control over an image, I write

<##externalfigure filename|caption|height|width>

where externalfigure is a gpp macro that translates to the appropriate HTML and (in my case) ConTeXt syntax.

@shrutikapoor08

It is a problem because it is not intuitive and simple and it is contrary to what one expects out of pandoc markdown - simplicity. The whole purpose of using pandoc is to shred hard syntax or else one could have just used LaTeX itself.
Resizing an image is such a simple thing and it shouldn't require to install any third-party libraries/ modules.

@qris
  • Yes I can manually munge each image file, but couldn't Pandoc behave sensibly by default, as @shrutikapoor08 suggested? That would make it easier to use.
  • What if I can't find a single DPI setting that's appropriate for all output formats? e.g. a Beamer presentation and a printable document might want images at different sizes, but changing the DPI value in the image file affects both.
  • A documented means of controlling/overriding the image size would be extremely useful. (I don't know Latex well)
  • A solution independent of markup language would be useful, as I use RST and not Markdown, so the above patches won't help me.
  • Something I can add to the Pandoc template would be ideal.
@nichtich

The image size could depend on output format, so coding it in Markdown may be the wrong place. Pandoc is for text - maybe we need some kind of "panimage" to convert one image to different output formats, suitable for inclusion in PDF, HTML etc. One could also include videos this way. Anyway this feature is important but out of the core scope of Pandoc.

@jgm
Owner
@nichtich

Use of convert or mogrify together with Pandoc could still be simplified. For instance one should be able to scale an image to a specific width and height in mm or inch without having to calculate DPI and pixel. To improve usability we might need to collect use cases. For instance for slides one might want to scale some images to 100% width or 100% height, for PDF image size should be set in cm or inch, and for HTML/EPUB one needs size in pixel. Having to set all these values manually for all images feels wrong, both if specified in Markdown or if set in the image files.

@sstadelman

I've looked at a lot of solutions, and this is by far the cleanest. nicely done

@metasim

+1 for /some/ sort of solution.

@Who8MyLunch

It would be great to have an elegant solution for this problem.

@thriveth

I second the call for an implementation of this. It doesn't have to be super fancy. Just a percentage is fine.

@mb21

Note that the discussion on image dimensions is concentrated in this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
2  src/Text/Pandoc/Readers/HTML.hs
@@ -350,7 +350,7 @@ pImage = do
let url = fromAttrib "src" tag
let title = fromAttrib "title" tag
let alt = fromAttrib "alt" tag
- return [Image (toList $ text alt) (escapeURI url, title)]
+ return [Image (toList $ text alt) (escapeURI url, title) "100"]
pCode :: TagParser [Inline]
pCode = try $ do
View
2  src/Text/Pandoc/Readers/LaTeX.hs
@@ -906,7 +906,7 @@ image = try $ do
let (src,tit) = case args' of
[] -> ("", "")
(x:_) -> (stripFirstAndLast x, "")
- return $ Image [Str "image"] (escapeURI src, tit)
+ return $ Image [Str "image"] (escapeURI src, tit) "100"
footnote :: GenParser Char ParserState Inline
footnote = try $ do
View
3  src/Text/Pandoc/Readers/Markdown.hs
@@ -1199,7 +1199,8 @@ image :: GenParser Char ParserState Inline
image = try $ do
char '!'
(Link lab src) <- link
- return $ Image lab src
+ width <- option [] (try $ char '@' >> many digit)
+ return $ Image lab src (if (null width) then "100" else width)
note :: GenParser Char ParserState Inline
note = try $ do
View
6 src/Text/Pandoc/Readers/RST.hs
@@ -256,8 +256,8 @@ imageBlock = try $ do
optional blanklines
case lookup "alt" fields of
Just alt -> return $ Plain [Image [Str $ removeTrailingSpace alt]
- (src, "")]
- Nothing -> return $ Plain [Image [Str "image"] (src, "")]
+ (src, "") "100"]
+ Nothing -> return $ Plain [Image [Str "image"] (src, "") "100"]
--
-- header blocks
--
@@ -868,7 +868,7 @@ image = try $ do
(src,tit) <- case lookupKeySrc keyTable (toKey ref) of
Nothing -> fail "no corresponding key"
Just target -> return target
- return $ Image (normalizeSpaces ref) (src, tit)
+ return $ Image (normalizeSpaces ref) (src, tit) "100"
note :: GenParser Char ParserState Inline
note = try $ do
View
2  src/Text/Pandoc/Readers/Textile.hs
@@ -481,7 +481,7 @@ image = try $ do
src <- manyTill anyChar (lookAhead $ oneOf "!(")
alt <- option "" (try $ (char '(' >> manyTill anyChar (char ')')))
char '!'
- return $ Image [Str alt] (src, alt)
+ return $ Image [Str alt] (src, alt) "100"
-- | Any special symbol defined in specialChars
symbol :: GenParser Char ParserState Inline
View
2  src/Text/Pandoc/Writers/AsciiDoc.hs
@@ -353,7 +353,7 @@ inlineToAsciiDoc opts (Link txt (src', _tit)) = do
return $ if useAuto
then text srcSuffix
else prefix <> text src <> "[" <> linktext <> "]"
-inlineToAsciiDoc opts (Image alternate (src', tit)) = do
+inlineToAsciiDoc opts (Image alternate (src', tit) _) = do
-- image:images/logo.png[Company logo, title="blah"]
let txt = if (null alternate) || (alternate == [Str ""])
then [Str "image"]
View
4 src/Text/Pandoc/Writers/ConTeXt.hs
@@ -113,7 +113,7 @@ blockToConTeXt :: Block
-> State WriterState Doc
blockToConTeXt Null = return empty
blockToConTeXt (Plain lst) = inlineListToConTeXt lst
-blockToConTeXt (Para [Image txt (src,_)]) = do
+blockToConTeXt (Para [Image txt (src,_) size]) = do
capt <- inlineListToConTeXt txt
return $ blankline $$ "\\placefigure[here,nonumber]" <> braces capt <>
braces ("\\externalfigure" <> brackets (text src)) <> blankline
@@ -284,7 +284,7 @@ inlineToConTeXt (Link txt (src, _)) = do
brackets (text $ escapeStringUsing [('#',"\\#")] src) <>
brackets empty <> brackets label <>
"\\from" <> brackets (text ref)
-inlineToConTeXt (Image _ (src, _)) = do
+inlineToConTeXt (Image _ (src, _) _) = do
let src' = if isAbsoluteURI src
then src
else unEscapeString src
View
4 src/Text/Pandoc/Writers/Docbook.hs
@@ -135,7 +135,7 @@ blockToDocbook :: WriterOptions -> Block -> Doc
blockToDocbook _ Null = empty
blockToDocbook _ (Header _ _) = empty -- should not occur after hierarchicalize
blockToDocbook opts (Plain lst) = inlinesToDocbook opts lst
-blockToDocbook opts (Para [Image txt (src,_)]) =
+blockToDocbook opts (Para [Image txt (src,_) _]) =
let capt = inlinesToDocbook opts txt
in inTagsIndented "figure" $
inTagsSimple "title" capt $$
@@ -272,7 +272,7 @@ inlineToDocbook opts (Link txt (src, _)) =
then inTags False "link" [("linkend", drop 1 src)]
else inTags False "ulink" [("url", src)]) $
inlinesToDocbook opts txt
-inlineToDocbook _ (Image _ (src, tit)) =
+inlineToDocbook _ (Image _ (src, tit) _ ) =
let titleDoc = if null tit
then empty
else inTagsIndented "objectinfo" $
View
6 src/Text/Pandoc/Writers/EPUB.hs
@@ -236,9 +236,9 @@ transformInlines :: HTMLMathMethod
-> IORef [(FilePath, FilePath)] -- ^ (oldpath, newpath) images
-> [Inline]
-> IO [Inline]
-transformInlines _ _ _ (Image lab (src,_) : xs) | isNothing (imageTypeOf src) =
+transformInlines _ _ _ (Image lab (src,_) _ : xs) | isNothing (imageTypeOf src) =
return $ Emph lab : xs
-transformInlines _ sourceDir picsRef (Image lab (src,tit) : xs) = do
+transformInlines _ sourceDir picsRef (Image lab (src,tit) size : xs) = do
let src' = unEscapeString src
pics <- readIORef picsRef
let oldsrc = sourceDir </> src'
@@ -249,7 +249,7 @@ transformInlines _ sourceDir picsRef (Image lab (src,tit) : xs) = do
let new = "images/img" ++ show (length pics) ++ ext
modifyIORef picsRef ( (oldsrc, new): )
return new
- return $ Image lab (newsrc, tit) : xs
+ return $ Image lab (newsrc, tit) size : xs
transformInlines (MathML _) _ _ (x@(Math _ _) : xs) = do
let writeHtmlInline opts z = removeTrailingSpace $
writeHtmlString opts $ Pandoc (Meta [] [] []) [Plain [z]]
View
16 src/Text/Pandoc/Writers/HTML.hs
@@ -332,8 +332,8 @@ treatAsImage fp =
blockToHtml :: WriterOptions -> Block -> State WriterState Html
blockToHtml _ Null = return noHtml
blockToHtml opts (Plain lst) = inlineListToHtml opts lst
-blockToHtml opts (Para [Image txt (s,tit)]) = do
- img <- inlineToHtml opts (Image txt (s,tit))
+blockToHtml opts (Para [Image txt (s,tit) w]) = do
+ img <- inlineToHtml opts (Image txt (s,tit) w)
capt <- inlineListToHtml opts txt
return $ if writerHtml5 opts
then tag "figure" <<
@@ -611,22 +611,28 @@ inlineToHtml opts inline =
return $ anchor ! ([href s] ++
if null tit then [] else [title tit]) $
linkText
- (Image txt (s,tit)) | treatAsImage s -> do
+ (Image txt (s,tit) w) | treatAsImage s -> do
let alternate' = stringify txt
let attributes = [src s] ++
(if null tit
then []
else [title tit]) ++
+ (if null w
+ then []
+ else  [width (w ++ "%")]) ++
if null txt
then []
else [alt alternate']
return $ image ! attributes
-- note: null title included, as in Markdown.pl
- (Image _ (s,tit)) -> do
+ (Image _ (s,tit) w) -> do
let attributes = [src s] ++
(if null tit
then []
- else [title tit])
+ else [title tit]) ++
+ (if null w
+ then []
+ else [width (w ++ "%")])
return $ itag "embed" ! attributes
-- note: null title included, as in Markdown.pl
(Note contents) -> do
View
9 src/Text/Pandoc/Writers/LaTeX.hs
@@ -168,9 +168,9 @@ blockToLaTeX :: Block -- ^ Block to convert
-> State WriterState Doc
blockToLaTeX Null = return empty
blockToLaTeX (Plain lst) = inlineListToLaTeX lst
-blockToLaTeX (Para [Image txt (src,tit)]) = do
+blockToLaTeX (Para [Image txt (src,tit) size]) = do
capt <- inlineListToLaTeX txt
- img <- inlineToLaTeX (Image txt (src,tit))
+ img <- inlineToLaTeX (Image txt (src,tit) size)
return $ "\\begin{figure}[htbp]" $$ "\\centering" $$ img $$
("\\caption{" <> capt <> char '}') $$ "\\end{figure}" $$ blankline
blockToLaTeX (Para lst) = do
@@ -436,12 +436,13 @@ inlineToLaTeX (Link txt (src, _)) =
_ -> do contents <- inlineListToLaTeX txt
return $ text ("\\href{" ++ stringToLaTeX True src ++ "}{") <>
contents <> char '}'
-inlineToLaTeX (Image _ (source, _)) = do
+inlineToLaTeX (Image _ (source, _) w) = do
modify $ \s -> s{ stGraphics = True }
let source' = if isAbsoluteURI source
then source
else unEscapeString source
- return $ "\\includegraphics" <> braces (text source')
+ let widthOption = text ("\\includegraphics[width=" ++ (show ((read w)/100.0::Float)) ++ "\\textwidth]")
+ return $ widthOption <> braces (text source')
inlineToLaTeX (Note contents) = do
modify (\s -> s{stInNote = True})
contents' <- blockListToLaTeX contents
View
2  src/Text/Pandoc/Writers/Man.hs
@@ -326,7 +326,7 @@ inlineToMan opts (Link txt (src, _)) = do
[Code _ s]
| s == srcSuffix -> char '<' <> text srcSuffix <> char '>'
_ -> linktext <> text " (" <> text src <> char ')'
-inlineToMan opts (Image alternate (source, tit)) = do
+inlineToMan opts (Image alternate (source, tit) _) = do
let txt = if (null alternate) || (alternate == [Str ""]) ||
(alternate == [Str source]) -- to prevent autolinks
then [Str "image"]
View
7 src/Text/Pandoc/Writers/Markdown.hs
@@ -77,7 +77,7 @@ plainify = bottomUp go
go (Math _ s) = Str s
go (RawInline _ _) = Str ""
go (Link xs _) = SmallCaps xs
- go (Image xs _) = SmallCaps $ [Str "["] ++ xs ++ [Str "]"]
+ go (Image xs _ _) = SmallCaps $ [Str "["] ++ xs ++ [Str "]@"]
go (Cite _ cits) = SmallCaps cits
go x = x
@@ -518,13 +518,14 @@ inlineToMarkdown opts (Link txt (src', tit)) = do
in first <> second
else "[" <> linktext <> "](" <>
text src <> linktitle <> ")"
-inlineToMarkdown opts (Image alternate (source, tit)) = do
+inlineToMarkdown opts (Image alternate (source, tit) size) = do
let txt = if (null alternate) || (alternate == [Str ""]) ||
(alternate == [Str source]) -- to prevent autolinks
then [Str "image"]
else alternate
linkPart <- inlineToMarkdown opts (Link txt (source, tit))
- return $ "!" <> linkPart
+ sizePart <- inlineToMarkdown opts (Str ("@" ++ size))
+ return $ "!" <> linkPart <> sizePart
inlineToMarkdown _ (Note contents) = do
modify (\st -> st{ stNotes = contents : stNotes st })
st <- get
View
4 src/Text/Pandoc/Writers/MediaWiki.hs
@@ -80,7 +80,7 @@ blockToMediaWiki _ Null = return ""
blockToMediaWiki opts (Plain inlines) =
inlineListToMediaWiki opts inlines
-blockToMediaWiki opts (Para [Image txt (src,tit)]) = do
+blockToMediaWiki opts (Para [Image txt (src,tit) size]) = do
capt <- inlineListToMediaWiki opts txt
let opt = if null txt
then ""
@@ -388,7 +388,7 @@ inlineToMediaWiki opts (Link txt (src, _)) = do
where src' = case src of
'/':xs -> xs -- with leading / it's a
_ -> src -- link to a help page
-inlineToMediaWiki opts (Image alt (source, tit)) = do
+inlineToMediaWiki opts (Image alt (source, tit) size) = do
alt' <- inlineListToMediaWiki opts alt
let txt = if (null tit)
then if null alt
View
4 src/Text/Pandoc/Writers/ODT.hs
@@ -100,13 +100,13 @@ writeODT mbRefOdt opts doc = do
return $ fromArchive archive'
transformPic :: FilePath -> IORef [Entry] -> Inline -> IO Inline
-transformPic sourceDir entriesRef (Image lab (src,tit)) = do
+transformPic sourceDir entriesRef (Image lab (src,tit) size) = do
let src' = unEscapeString src
entries <- readIORef entriesRef
let newsrc = "Pictures/" ++ show (length entries) ++ takeExtension src'
catch (readEntry [] (sourceDir </> src') >>= \entry ->
modifyIORef entriesRef (entry{ eRelativePath = newsrc } :) >>
- return (Image lab (newsrc, tit)))
+ return (Image lab (newsrc, tit) size))
(\_ -> return (Emph lab))
transformPic _ _ x = return x
View
2  src/Text/Pandoc/Writers/OpenDocument.hs
@@ -382,7 +382,7 @@ inlineToOpenDocument o ils
| RawInline "html" s <- ils = preformatted s -- for backwards compat.
| RawInline _ _ <- ils = return empty
| Link l (s,t) <- ils = mkLink s t <$> inlinesToOpenDocument o l
- | Image _ (s,_) <- ils = return $ mkImg s
+ | Image _ (s,_) _ <- ils = return $ mkImg s
| Note l <- ils = mkNote l
| otherwise = return empty
where
View
6 src/Text/Pandoc/Writers/Org.hs
@@ -108,9 +108,9 @@ blockToOrg :: Block -- ^ Block element
-> State WriterState Doc
blockToOrg Null = return empty
blockToOrg (Plain inlines) = inlineListToOrg inlines
-blockToOrg (Para [Image txt (src,tit)]) = do
+blockToOrg (Para [Image txt (src,tit) size]) = do
capt <- inlineListToOrg txt
- img <- inlineToOrg (Image txt (src,tit))
+ img <- inlineToOrg (Image txt (src,tit) size)
return $ "#+CAPTION: " <> capt <> blankline <> img
blockToOrg (Para inlines) = do
contents <- inlineListToOrg inlines
@@ -272,7 +272,7 @@ inlineToOrg (Link txt (src, _)) = do
_ -> do contents <- inlineListToOrg txt
modify $ \s -> s{ stLinks = True }
return $ "[[" <> text src <> "][" <> contents <> "]]"
-inlineToOrg (Image _ (source', _)) = do
+inlineToOrg (Image _ (source', _) _) = do
let source = unescapeURI source'
modify $ \s -> s{ stImages = True }
return $ "[[" <> text source <> "]]"
View
4 src/Text/Pandoc/Writers/RST.hs
@@ -139,7 +139,7 @@ blockToRST :: Block -- ^ Block element
-> State WriterState Doc
blockToRST Null = return empty
blockToRST (Plain inlines) = inlineListToRST inlines
-blockToRST (Para [Image txt (src,tit)]) = do
+blockToRST (Para [Image txt (src,tit) size]) = do
capt <- inlineListToRST txt
let fig = "figure:: " <> text src
let align = ":align: center"
@@ -311,7 +311,7 @@ inlineToRST (Link txt (src', tit)) = do
modify $ \st -> st { stLinks = refs' }
return $ "`" <> linktext <> "`_"
else return $ "`" <> linktext <> " <" <> text src <> ">`_"
-inlineToRST (Image alternate (source', tit)) = do
+inlineToRST (Image alternate (source', tit) size) = do
let source = unescapeURI source'
pics <- get >>= return . stImages
let labelsUsed = map fst pics
View
4 src/Text/Pandoc/Writers/RTF.hs
@@ -42,7 +42,7 @@ import Network.URI ( isAbsoluteURI, unEscapeString )
-- | Convert Image inlines into a raw RTF embedded image, read from a file.
-- If file not found or filetype not jpeg or png, leave the inline unchanged.
rtfEmbedImage :: Inline -> IO Inline
-rtfEmbedImage x@(Image _ (src,_)) = do
+rtfEmbedImage x@(Image _ (src,_) _) = do
let ext = map toLower (takeExtension src)
if ext `elem` [".jpg",".jpeg",".png"] && not (isAbsoluteURI src)
then do
@@ -302,7 +302,7 @@ inlineToRTF Space = " "
inlineToRTF (Link text (src, _)) =
"{\\field{\\*\\fldinst{HYPERLINK \"" ++ (codeStringToRTF src) ++
"\"}}{\\fldrslt{\\ul\n" ++ (inlineListToRTF text) ++ "\n}}}\n"
-inlineToRTF (Image _ (source, _)) =
+inlineToRTF (Image _ (source, _) _) =
"{\\cf1 [image: " ++ source ++ "]\\cf0}"
inlineToRTF (Note contents) =
"{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " ++
View
6 src/Text/Pandoc/Writers/Texinfo.hs
@@ -111,9 +111,9 @@ blockToTexinfo Null = return empty
blockToTexinfo (Plain lst) =
inlineListToTexinfo lst
-blockToTexinfo (Para [Image txt (src,tit)]) = do
+blockToTexinfo (Para [Image txt (src,tit) size]) = do
capt <- inlineListToTexinfo txt
- img <- inlineToTexinfo (Image txt (src,tit))
+ img <- inlineToTexinfo (Image txt (src,tit) size)
return $ text "@float" $$ img $$ (text "@caption{" <> capt <> char '}') $$
text "@end float"
@@ -409,7 +409,7 @@ inlineToTexinfo (Link txt (src, _)) = do
return $ text ("@uref{" ++ src1 ++ ",") <> contents <>
char '}'
-inlineToTexinfo (Image alternate (source, _)) = do
+inlineToTexinfo (Image alternate (source, _) _) = do
content <- inlineListToTexinfo alternate
return $ text ("@image{" ++ base ++ ",,,") <> content <> text "," <>
text (ext ++ "}")
View
6 src/Text/Pandoc/Writers/Textile.hs
@@ -96,9 +96,9 @@ blockToTextile _ Null = return ""
blockToTextile opts (Plain inlines) =
inlineListToTextile opts inlines
-blockToTextile opts (Para [Image txt (src,tit)]) = do
+blockToTextile opts (Para [Image txt (src,tit) size]) = do
capt <- blockToTextile opts (Para txt)
- im <- inlineToTextile opts (Image txt (src,tit))
+ im <- inlineToTextile opts (Image txt (src,tit) size)
return $ im ++ "\n" ++ capt
blockToTextile opts (Para inlines) = do
@@ -403,7 +403,7 @@ inlineToTextile opts (Link txt (src, _)) = do
_ -> inlineListToTextile opts txt
return $ "\"" ++ label ++ "\":" ++ src
-inlineToTextile opts (Image alt (source, tit)) = do
+inlineToTextile opts (Image alt (source, tit) size) = do
alt' <- inlineListToTextile opts alt
let txt = if null tit
then if null alt'
Something went wrong with that request. Please try again.