diff --git a/MANUAL.txt b/MANUAL.txt index 1da9ef62e..27628cd6e 100644 --- a/MANUAL.txt +++ b/MANUAL.txt @@ -138,8 +138,8 @@ When using LaTeX, the following packages need to be available [`amsfonts`], [`amsmath`], [`lm`], [`unicode-math`], [`iftex`], [`listings`] (if the `--listings` option is used), [`fancyvrb`], [`longtable`], -[`booktabs`], [`multirow`] (if the document contains a table with -cells that cross multiple rows), [`graphicx`] (if the document +[`caption`], [`booktabs`], [`multirow`] (if the document contains a table +with cells that cross multiple rows), [`graphicx`] (if the document contains images), [`bookmark`], [`xcolor`], [`soul`], [`geometry`] (with the `geometry` variable set), [`setspace`] (with `linestretch`), and @@ -191,6 +191,7 @@ better line breaks in URLs), and [`footnotehyper`] or [`lua-ul`]: https://ctan.org/pkg/lua-ul [`luatexja`]: https://ctan.org/pkg/luatexja [`longtable`]: https://ctan.org/pkg/longtable +[`caption`]: https://ctan.org/pkg/caption [`mathspec`]: https://ctan.org/pkg/mathspec [`microtype`]: https://ctan.org/pkg/microtype [`multirow`]: https://ctan.org/pkg/multirow @@ -5005,6 +5006,21 @@ of the caption. (For the syntax, see : Here's the caption. {#ident .class key="value"} +### Table placement in LaTeX ### + +By default, pandoc will render tables in LaTeX using the `longtable` +environment. The tables will not "float" and they can span page boundaries. +If you prefer standard "floating" tables (which are limited to what can +fit on one page), add the `float` class to the table's attributes +(which can be specified after the caption). Optionally, the `latex-placement` +attribute may be used to pass parameters affecting the float placement: + + : The caption of the table. {#ident .float latex-placement="ht"} + +Note that `longtable` does not work with two-column layouts, so if you +are producing a two-column document using LaTeX, you will need to specify +the `float` class on every table (or use a Lua filter to add it automatically). + ## Metadata blocks ### Extension: `pandoc_title_block` ### diff --git a/data/templates/common.latex b/data/templates/common.latex index 1f26b339f..f7dee4217 100644 --- a/data/templates/common.latex +++ b/data/templates/common.latex @@ -69,6 +69,8 @@ $-- tables $-- $if(tables)$ \usepackage{longtable,booktabs,array} +\usepackage{caption} +\captionsetup[table]{skip=6pt} \newcounter{none} % for unnumbered tables $if(multirow)$ \usepackage{multirow} diff --git a/src/Text/Pandoc/PDF.hs b/src/Text/Pandoc/PDF.hs index 5bdda0770..972425091 100644 --- a/src/Text/Pandoc/PDF.hs +++ b/src/Text/Pandoc/PDF.hs @@ -305,6 +305,8 @@ tex2pdf program args tmpDir source = do x | "! Package inputenc Error" `BC.isPrefixOf` x && program /= "xelatex" -> "\nTry running pandoc with --pdf-engine=xelatex." + "! Package longtable Error: longtable not in 1-column mode." + -> "\nTry adding the .float class attribute to your tables." _ -> "" return $ Left $ logmsg <> extramsg (ExitSuccess, Nothing) -> return $ Left "" diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index c9155d86d..f66f1314a 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -56,7 +56,7 @@ import Text.Pandoc.Shared import Text.Pandoc.URI import Text.Pandoc.Slides import Text.Pandoc.Walk (query, walk, walkM) -import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) +import Text.Pandoc.Writers.LaTeX.Util (getAccumulatedNotes) import Text.Pandoc.Writers.LaTeX.Caption (getCaption) import Text.Pandoc.Writers.LaTeX.Table (tableToLaTeX) import Text.Pandoc.Writers.LaTeX.Citation (citationsToNatbib, @@ -65,7 +65,7 @@ import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState (..), startingState, PdfStandard (..)) import Text.Pandoc.Writers.LaTeX.Lang (toBabel) import Text.Pandoc.Writers.LaTeX.Util (stringToLaTeX, StringContext(..), - toLabel, inCmd, + toLabel, inCmd, withExternalNotes, wrapDiv, hypertarget, labelFor, getListingsLanguage, mbBraced) import Text.Pandoc.Writers.Shared @@ -663,7 +663,7 @@ blockToLaTeX (DefinitionList lst) = do let spacing = if all (isTightList . snd) lst then text "\\tightlist" else empty - notes <- notesToLaTeX <$> gets stNotes + notes <- getAccumulatedNotes return $ text ("\\begin{description}" <> inc) $$ spacing $$ vcat items $$ "\\end{description}" $$ notes blockToLaTeX HorizontalRule = @@ -679,7 +679,7 @@ blockToLaTeX (Table attr blkCapt specs thead tbodies tfoot) = (Ann.toTable attr blkCapt specs thead tbodies tfoot) blockToLaTeX (Figure (ident, _, kvs) captnode body) = do opts <- gets stOptions - (capt, captForLof, footnotes) <- getCaption inlineListToLaTeX True captnode + (capt, captForLof) <- withExternalNotes $ getCaption inlineListToLaTeX captnode lab <- labelFor ident let caption = "\\caption" <> captForLof <> braces capt <> lab placement = case lookup "latex-placement" kvs of @@ -705,6 +705,7 @@ blockToLaTeX (Figure (ident, _, kvs) captnode body) = do Table {} -> Any True _ -> Any False) st <- get + footnotes <- getAccumulatedNotes return $ (case () of _ | containsTable body -> -- placing a longtable in a figure or center environment does @@ -764,10 +765,9 @@ listItemToLaTeX isOrdered lst defListItemToLaTeX :: PandocMonad m => ([Inline], [[Block]]) -> LW m (Doc Text) defListItemToLaTeX (term, defs) = do -- needed to turn off 'listings' because it breaks inside \item[...]: - oldExternalNotes <- gets stExternalNotes - modify $ \s -> s{stInItem = True, stExternalNotes = True} - term' <- inlineListToLaTeX term - modify $ \s -> s{stInItem = False, stExternalNotes = oldExternalNotes} + modify $ \s -> s{ stInItem = True } + term' <- withExternalNotes $ inlineListToLaTeX term + modify $ \s -> s{ stInItem = False } -- put braces around term if it contains an internal link, -- since otherwise we get bad bracket interactions: \item[\hyperref[..] let isInternalLink (Link _ _ (src,_)) diff --git a/src/Text/Pandoc/Writers/LaTeX/Caption.hs b/src/Text/Pandoc/Writers/LaTeX/Caption.hs index 9a63fee3c..12eed73f2 100644 --- a/src/Text/Pandoc/Writers/LaTeX/Caption.hs +++ b/src/Text/Pandoc/Writers/LaTeX/Caption.hs @@ -21,29 +21,20 @@ import Text.Pandoc.Definition import Text.DocLayout (Doc, brackets, empty) import Text.Pandoc.Shared import Text.Pandoc.Walk -import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) -import Text.Pandoc.Writers.LaTeX.Types - ( LW, WriterState (stExternalNotes, stNotes, stInCaption) ) +import Text.Pandoc.Writers.LaTeX.Types ( LW, WriterState (stInCaption) ) --- | Produces the components of a LaTeX 'caption' command. Returns a triple --- containing the caption text, the short caption for the list of --- figures/tables, and the footnote definitions. +-- | Produces the components of a LaTeX 'caption' command. Returns a pair +-- containing the caption text and the short caption for the list of +-- figures/tables. getCaption :: PandocMonad m => ([Inline] -> LW m (Doc Text)) -- ^ inlines converter - -> Bool -- ^ whether to extract notes -> Caption - -> LW m (Doc Text, Doc Text, Doc Text) -getCaption inlineListToLaTeX externalNotes (Caption maybeShort long) = do + -> LW m (Doc Text, Doc Text) +getCaption inlineListToLaTeX (Caption maybeShort long) = do modify $ \st -> st{ stInCaption = True } let long' = blocksToInlines long - oldExternalNotes <- gets stExternalNotes - modify $ \st -> st{ stExternalNotes = externalNotes, stNotes = [] } capt <- inlineListToLaTeX long' - footnotes <- if externalNotes - then notesToLaTeX <$> gets stNotes - else return empty - modify $ \st -> st{ stExternalNotes = oldExternalNotes, stNotes = [] } -- We can't have footnotes in the list of figures/tables, so remove them: let getNote (Note _) = Any True getNote _ = Any False @@ -55,4 +46,4 @@ getCaption inlineListToLaTeX externalNotes (Caption maybeShort long) = do else return empty Just short -> toShortCapt short modify $ \st -> st{ stInCaption = False } - return (capt, captForLof, footnotes) + return (capt, captForLof) diff --git a/src/Text/Pandoc/Writers/LaTeX/Table.hs b/src/Text/Pandoc/Writers/LaTeX/Table.hs index 2e32d0b3f..2d51b06fa 100644 --- a/src/Text/Pandoc/Writers/LaTeX/Table.hs +++ b/src/Text/Pandoc/Writers/LaTeX/Table.hs @@ -1,5 +1,7 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleContexts #-} {- | Module : Text.Pandoc.Writers.LaTeX.Table Copyright : Copyright (C) 2006-2024 John MacFarlane @@ -24,17 +26,17 @@ import qualified Data.Text as T import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition import Text.DocLayout - ( Doc, braces, cr, empty, hcat, hsep, isEmpty, literal, nest - , text, vcat, ($$) ) + ( Doc, braces, brackets, cr, empty, hcat, hsep, isEmpty, literal, nest + , text, vcat, ($$)) import Text.Pandoc.Shared (splitBy, tshow) import Text.Pandoc.Walk (walk, query) import Data.Monoid (Any(..)) import Text.Pandoc.Writers.LaTeX.Caption (getCaption) -import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) import Text.Pandoc.Writers.LaTeX.Types - ( LW, WriterState (stBeamer, stExternalNotes, stInMinipage, stMultiRow - , stNotes, stTable, stOptions) ) -import Text.Pandoc.Writers.LaTeX.Util (labelFor) + ( LW, WriterState (stBeamer, stInMinipage, stMultiRow + , stTable, stOptions) ) +import Text.Pandoc.Writers.LaTeX.Util (labelFor, withExternalNotes, + getAccumulatedNotes) import Text.Printf (printf) import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.Writers.AnnotatedTable as Ann @@ -46,30 +48,103 @@ tableToLaTeX :: PandocMonad m -> Ann.Table -> LW m (Doc Text) tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do + let (Ann.Table (ident, classes, kvs) caption specs thead tbodies tfoot) = tbl + let placement = brackets $ maybe mempty (text . T.unpack) + $ lookup "latex-placement" kvs + -- if the float class is included in table attributes, we generate a floating + -- table environment; otherwise we use longtable + beamer <- gets stBeamer + let float = "float" `elem` classes + let renderTable = do + capt <- captionToLaTeX inlnsToLaTeX caption ident + let isSimpleTable = + all ((== ColWidthDefault) . snd) specs && + all (all isSimpleCell) + (mconcat [ headRows thead + , concatMap bodyRows tbodies + , footRows tfoot + ]) + let colDesc' = colDescriptors isSimpleTable tbl + let colDesc = braces ("@{}" <> colDesc' <> "@{}") + -- the @{} removes extra space at beginning and end + let colCount = ColumnCount $ length specs + let mkHead = headToLaTeX blksToLaTeX isSimpleTable colCount + let mkRow = rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell + if float + then tableToLaTeXTable placement colDesc mkHead mkRow capt thead tbodies tfoot + else tableToLaTeXLongtable colDesc mkHead mkRow capt thead tbodies tfoot + -- See #5367 -- footnotehyper/footnote don't work in beamer, + -- so we need to produce the notes outside the table... + if float || beamer + then ($$) <$> withExternalNotes renderTable <*> getAccumulatedNotes + else renderTable + +tableToLaTeXTable :: PandocMonad m + => Doc Text + -> Doc Text + -> (Ann.TableHead -> LW m (Doc Text)) + -> ([Ann.Cell] -> LW m (Doc Text)) + -> Doc Text + -> Ann.TableHead + -> [Ann.TableBody] + -> Ann.TableFoot + -> LW m (Doc Text) +tableToLaTeXTable placement colDesc mkHead mkRow capt thead tbodies tfoot = do + opts <- gets stOptions + let hasTopCaption = not (isEmpty capt) && + writerTableCaptionPosition opts == CaptionAbove + let hasBottomCaption = not (isEmpty capt) && + writerTableCaptionPosition opts == CaptionBelow + head' <- if isEmptyHead thead + then return "\\toprule\\noalign{}" + else mkHead thead + rows' <- mapM mkRow $ mconcat (map bodyRows tbodies) + lastfoot <- mapM mkRow $ footRows tfoot + let foot' = (if isEmptyFoot tfoot + then mempty + else "\\midrule\\noalign{}" $$ vcat lastfoot) + $$ "\\bottomrule\\noalign{}" + modify $ \s -> s{ stTable = True } + let makeUnnumbered x = "{\\def\\LTcaptype{none} % do not increment counter" $$ x $$ "}" + return + $ (if null capt then makeUnnumbered else id) + $ "\\begin{table}" <> placement + $$ "\\centering" + $$ (if hasTopCaption + then capt <> "\\tabularnewline" + else mempty) + $$ "\\begin{tabular}" <> colDesc + $$ head' + $$ vcat rows' + $$ foot' + $$ "\\end{tabular}" + $$ (if hasBottomCaption + then capt <> "\\tabularnewline" + else mempty) + $$ "\\end{table}" + + +tableToLaTeXLongtable :: PandocMonad m + => Doc Text + -> (Ann.TableHead -> LW m (Doc Text)) + -> ([Ann.Cell] -> LW m (Doc Text)) + -> Doc Text + -> Ann.TableHead + -> [Ann.TableBody] + -> Ann.TableFoot + -> LW m (Doc Text) +tableToLaTeXLongtable colDesc mkHead mkRow capt thead tbodies tfoot = do opts <- gets stOptions - let (Ann.Table (ident, _, _) caption specs thead tbodies tfoot) = tbl - CaptionDocs capt captNotes <- captionToLaTeX inlnsToLaTeX caption ident let hasTopCaption = not (isEmpty capt) && writerTableCaptionPosition opts == CaptionAbove let hasBottomCaption = not (isEmpty capt) && writerTableCaptionPosition opts == CaptionBelow - let isSimpleTable = - all ((== ColWidthDefault) . snd) specs && - all (all isSimpleCell) - (mconcat [ headRows thead - , concatMap bodyRows tbodies - , footRows tfoot - ]) - let removeNote (Note _) = Span ("", [], []) [] - removeNote x = x - let colCount = ColumnCount $ length specs -- The first head is not repeated on the following pages. If we were to just -- use a single head, without a separate first head, then the caption would be -- repeated on all pages that contain a part of the table. We avoid this by -- making the caption part of the first head. The downside is that we must -- duplicate the header rows for this. head' <- do - let mkHead = headToLaTeX blksToLaTeX isSimpleTable colCount case (hasTopCaption, isEmptyHead thead) of (False, True) -> return "\\toprule\\noalign{}" (False, False) -> mkHead thead @@ -79,15 +154,15 @@ tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do (True, False) -> do -- avoid duplicate notes in head and firsthead: firsthead <- mkHead thead + let removeNote (Note _) = Span ("", [], []) [] + removeNote x = x repeated <- mkHead (walk removeNote thead) return $ capt <> "\\tabularnewline" $$ firsthead $$ "\\endfirsthead" $$ repeated - rows' <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $ - mconcat (map bodyRows tbodies) - lastfoot <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $ - footRows tfoot + rows' <- mapM mkRow $ mconcat (map bodyRows tbodies) + lastfoot <- mapM mkRow $ footRows tfoot let foot' = (if isEmptyFoot tfoot then mempty else "\\midrule\\noalign{}" $$ vcat lastfoot) @@ -96,14 +171,11 @@ tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do then "\\tabularnewline" $$ capt else mempty) modify $ \s -> s{ stTable = True } - notes <- notesToLaTeX <$> gets stNotes beamer <- gets stBeamer let makeUnnumbered x = "{\\def\\LTcaptype{none} % do not increment counter" $$ x $$ "}" return $ (if null capt then makeUnnumbered else id) - $ "\\begin{longtable}[]" <> - braces ("@{}" <> colDescriptors isSimpleTable tbl <> "@{}") - -- the @{} removes extra space at beginning and end + $ "\\begin{longtable}[]" <> colDesc $$ head' $$ "\\endhead" $$ vcat @@ -120,8 +192,6 @@ tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do , vcat rows' ]) $$ "\\end{longtable}" - $$ captNotes - $$ notes isSimpleCell :: Ann.Cell -> Bool isSimpleCell (Ann.Cell _ _ (Cell _attr _align _rowspan _colspan blocks)) = @@ -184,28 +254,18 @@ colAlign = \case AlignCenter -> "c" AlignDefault -> "l" -data CaptionDocs = - CaptionDocs - { captionCommand :: Doc Text - , captionNotes :: Doc Text - } - captionToLaTeX :: PandocMonad m => ([Inline] -> LW m (Doc Text)) -> Caption -> Text -- ^ table identifier (label) - -> LW m CaptionDocs + -> LW m (Doc Text) captionToLaTeX inlnsToLaTeX caption ident = do - (captionText, captForLot, captNotes) <- getCaption inlnsToLaTeX False caption + (captionText, captForLot) <- getCaption inlnsToLaTeX caption label <- labelFor ident - return $ CaptionDocs - { captionNotes = captNotes - , captionCommand = if isEmpty captionText && isEmpty label - then empty - else "\\caption" <> captForLot <> - braces captionText - <> label - } + return $ if isEmpty captionText && isEmpty label + then empty + else "\\caption" <> captForLot <> + braces captionText <> label type BlocksWriter m = [Block] -> LW m (Doc Text) @@ -322,11 +382,6 @@ cellToLaTeX blockListToLaTeX isSimpleTable colCount celltype annotatedCell = do let align = case align' of AlignDefault -> specAlign _ -> align' - beamer <- gets stBeamer - externalNotes <- gets stExternalNotes - -- See #5367 -- footnotehyper/footnote don't work in beamer, - -- so we need to produce the notes outside the table... - modify $ \st -> st{ stExternalNotes = beamer } let isPlainOrPara = \case Para{} -> True Plain{} -> True @@ -352,7 +407,6 @@ cellToLaTeX blockListToLaTeX isSimpleTable colCount celltype annotatedCell = do (if hasLineBreaks then "\\strut" else mempty) <> cr <> "\\end{minipage}" - modify $ \st -> st{ stExternalNotes = externalNotes } when (rowspan /= RowSpan 1) $ modify (\st -> st{ stMultiRow = True }) let inMultiColumn x = case colspan of diff --git a/src/Text/Pandoc/Writers/LaTeX/Util.hs b/src/Text/Pandoc/Writers/LaTeX/Util.hs index d8abb2a61..fad47e84b 100644 --- a/src/Text/Pandoc/Writers/LaTeX/Util.hs +++ b/src/Text/Pandoc/Writers/LaTeX/Util.hs @@ -18,6 +18,8 @@ module Text.Pandoc.Writers.LaTeX.Util ( , labelFor , getListingsLanguage , mbBraced + , withExternalNotes + , getAccumulatedNotes ) where @@ -27,6 +29,7 @@ import Text.Pandoc.Class (PandocMonad, toLang) import Text.Pandoc.Options (WriterOptions(..), isEnabled) import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState(..)) import Text.Pandoc.Writers.LaTeX.Lang (toBabel) +import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) import Text.Pandoc.Highlighting (toListingsLanguage) import Text.DocLayout import Text.Pandoc.Definition @@ -285,3 +288,20 @@ mbBraced :: Text -> Text mbBraced x = if not (T.all isAlphaNum x) then "{" <> x <> "}" else x + +withExternalNotes :: PandocMonad m + => LW m a + -> LW m a +withExternalNotes p = do + oldExternalNotes <- gets stExternalNotes + modify $ \st -> st{ stExternalNotes = True } + res <- p + modify $ \st -> st{ stExternalNotes = oldExternalNotes } + return res + +getAccumulatedNotes :: PandocMonad m + => LW m (Doc Text) +getAccumulatedNotes = do + res <- notesToLaTeX <$> gets stNotes + modify $ \st -> st{ stNotes = [] } + return res diff --git a/test/command/1023.md b/test/command/1023.md new file mode 100644 index 000000000..da8243bb7 --- /dev/null +++ b/test/command/1023.md @@ -0,0 +1,129 @@ +``` +% pandoc -t latex +: Here's the caption. +It may span multiple lines. {.float #ident latex-placement="ht"} + +--------------------------------------------------------------- + Centered Left Right + Header Aligned Aligned Default aligned +---------- --------- ----------- --------------------------- + First row 12.0 Example of a row that spans + multiple lines. + + Second row 5.0 Here's another one. Note + the blank line between rows. +--------------------------------------------------------------- +^D +\begin{table}[ht] +\centering +\caption{Here's the caption. It may span multiple +lines.}\label{ident}\tabularnewline +\begin{tabular}{@{} + >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1667}} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1528}} + >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1806}} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3889}}@{}} +\toprule\noalign{} +\begin{minipage}[b]{\linewidth}\centering +Centered Header +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Left Aligned +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedleft +Right Aligned +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Default aligned +\end{minipage} \\ +\midrule\noalign{} +First & row & 12.0 & Example of a row that spans multiple lines. \\ +Second & row & 5.0 & Here's another one. Note the blank line between +rows. \\ +\bottomrule\noalign{} +\end{tabular} +\end{table} + +``` + +``` +% pandoc -t latex +: Simple table with no column headers {.float #ident} + +------- ------ ---------- ------- + 12 12 12 12 + 123 123 123 123 + 1 1 1 1 +------- ------ ---------- ------- +^D +\begin{table}[] +\centering +\caption{Simple table with no column +headers}\label{ident}\tabularnewline +\begin{tabular}{@{}rlcr@{}} +\toprule\noalign{} +12 & 12 & 12 & 12 \\ +123 & 123 & 123 & 123 \\ +1 & 1 & 1 & 1 \\ +\bottomrule\noalign{} +\end{tabular} +\end{table} + +``` + +``` +% pandoc -t latex ++--------------------+---------------------+---------------+---------------+ +| Name^[In English.] | Capital | Population\ | Area\ | +| | | (in 2018) | (in km^2^) | ++:==================:+:====================+:==============+:==============+ +| Denmark | Copenhagen | 5,809,502 | 43,094 | ++--------------------+---------------------+---------------+---------------+ +| Finland | Helsinki | 5,537,364 | 338,145 | ++--------------------+---------------------+---------------+---------------+ +| Iceland^[Brrr.] | Reykjavik | 343,518 | 103,000 | ++--------------------+---------------------+---------------+---------------+ +| Norway | Oslo | 5,372,191 | 323,802 | ++--------------------+---------------------+---------------+---------------+ +| Sweden | Stockholm | 10,313,447 | 450,295 | ++====================+=====================+===============+===============+ +| Total | | 27,376,022 | 1,258,336 | ++====================+=====================+===============+===============+ + +: States belonging to the *Nordics.* {#nordics source="wikipedia" .float} +^D +\begin{table}[] +\centering +\caption{States belonging to the +\emph{Nordics.}}\label{nordics}\tabularnewline +\begin{tabular}{@{} + >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2727}} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2857}} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2078}} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2078}}@{}} +\toprule\noalign{} +\begin{minipage}[b]{\linewidth}\centering +Name\footnotemark{} +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Capital +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Population\\ +(in 2018)\strut +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Area\\ +(in km\textsuperscript{2})\strut +\end{minipage} \\ +\midrule\noalign{} +Denmark & Copenhagen & 5,809,502 & 43,094 \\ +Finland & Helsinki & 5,537,364 & 338,145 \\ +Iceland\footnotemark{} & Reykjavik & 343,518 & 103,000 \\ +Norway & Oslo & 5,372,191 & 323,802 \\ +Sweden & Stockholm & 10,313,447 & 450,295 \\ +\midrule\noalign{} +Total & & 27,376,022 & 1,258,336 \\ +\bottomrule\noalign{} +\end{tabular} +\end{table} +\addtocounter{footnote}{-1} +\footnotetext{In English.} +\addtocounter{footnote}{1} +\footnotetext{Brrr.} + +```