diff options
| author | John MacFarlane <[email protected]> | 2024-02-03 22:19:29 -0800 |
|---|---|---|
| committer | John MacFarlane <[email protected]> | 2024-02-03 22:19:29 -0800 |
| commit | 03bb426a4a65918bfd6fbd63d5bb32a657df5568 (patch) | |
| tree | ebd0629088e86f25c35467c46ba19ac1ce37ec36 | |
| parent | 6fc8a80c2cdeaf71b7fe6d20c35b46ef562ca67c (diff) | |
Shared: `makeSections` behavior changes.
+ When the optional base level parameter is provided, we no
longer ensure that the sequence of heading levels is gapless
[behavior change]. Instead, we set the lowest heading level to
the specified base level, and adjust the others accordingly. If
an author wants to skip a level, e.g. from level 1 to level 3,
they can do that. In general, the heading levels specified
in the source document are preserved; `makeSections` only
puts them into a hierarchical structure. Closes #9398.
+ Section numbers are now assigned so that the top level
gets `1`, no matter what heading level is used. So, even
if the top heading level is 2, numbers will be `1`, `2`, etc.
rather than `0.1`, `0.2`, as in the past. Closes #5071.
+ We revert to the old behavior when the `--number-offset` option
is used. So, for example, if a document begins with a level-3
heading, and `--number-offset=1,2` is used, the top-level section
numbers will be `1.2.1`, `1.2.2`, etc. This is mainly for
backwards-compatibility.
| -rw-r--r-- | pandoc-lua-engine/test/lua/module/pandoc-structure.lua | 2 | ||||
| -rw-r--r-- | src/Text/Pandoc/Shared.hs | 29 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/HTML.hs | 17 | ||||
| -rw-r--r-- | test/command/5071.md | 68 |
4 files changed, 96 insertions, 20 deletions
diff --git a/pandoc-lua-engine/test/lua/module/pandoc-structure.lua b/pandoc-lua-engine/test/lua/module/pandoc-structure.lua index 17209c7f8..af19785c9 100644 --- a/pandoc-lua-engine/test/lua/module/pandoc-structure.lua +++ b/pandoc-lua-engine/test/lua/module/pandoc-structure.lua @@ -48,7 +48,7 @@ return { assert.are_equal('Div', hblks[1].t) assert.are_equal('Header', hblks[1].content[1].t) assert.are_equal('1', hblks[1].content[1].attributes['number']) - assert.are_equal('1.1', hblks[1].content[3].attributes['number']) + assert.are_equal('1.0.1', hblks[1].content[3].attributes['number']) end) }, diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs index b18ec98c5..1c26e143f 100644 --- a/src/Text/Pandoc/Shared.hs +++ b/src/Text/Pandoc/Shared.hs @@ -96,8 +96,9 @@ import Data.Char (isAlpha, isLower, isSpace, isUpper, toLower, isAlphaNum, import Data.List (find, foldl', groupBy, intercalate, intersperse, union, sortOn) import qualified Data.Map as M -import Data.Maybe (mapMaybe, fromMaybe) -import Data.Monoid (Any (..)) +import Data.Maybe (mapMaybe) +import Data.Monoid (Any (..) ) +import Data.Semigroup (Min (..)) import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr) import qualified Data.Set as Set import qualified Data.Text as T @@ -507,26 +508,28 @@ textToIdentifier exts = -- element a Header). If the 'numbering' parameter is True, Header -- numbers are added via the number attribute on the header. -- If the baseLevel parameter is Just n, Header levels are --- adjusted to be gapless starting at level n. +-- adjusted so that the lowest header level is n. +-- (There may still be gaps in header level if the author leaves them.) makeSections :: Bool -> Maybe Int -> [Block] -> [Block] makeSections numbering mbBaseLevel bs = - S.evalState (go bs) (mbBaseLevel, []) + S.evalState (go bs) [] where - go :: [Block] -> S.State (Maybe Int, [Int]) [Block] + getLevel (Header level _ _) = Min level + getLevel _ = Min 99 + minLevel = getMin $ query getLevel bs + go :: [Block] -> S.State [Int] [Block] go (Header level (ident,classes,kvs) title':xs) = do - (mbLevel, lastnum) <- S.get - let level' = fromMaybe level mbLevel + lastnum <- S.get + let level' = maybe level (\n -> n + level - minLevel) mbBaseLevel let adjustNum lev numComponent - | lev < level' = numComponent - | lev == level' = numComponent + 1 + | lev < level = numComponent + | lev == level = numComponent + 1 | otherwise = 0 - let newnum = zipWith adjustNum [(fromMaybe 1 mbBaseLevel)..level'] + let newnum = zipWith adjustNum [minLevel..level] (lastnum ++ repeat 0) - unless (null newnum) $ S.modify $ \(mbl, _) -> (mbl, newnum) + unless (null newnum) $ S.put newnum let (sectionContents, rest) = break (headerLtEq level) xs - S.modify $ \(_, ln) -> (fmap (+ 1) mbLevel, ln) sectionContents' <- go sectionContents - S.modify $ \(_, ln) -> (mbLevel, ln) rest' <- go rest let kvs' = -- don't touch number if already present case lookup "number" kvs of diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs index 18e10f102..c7a4703ae 100644 --- a/src/Text/Pandoc/Writers/HTML.hs +++ b/src/Text/Pandoc/Writers/HTML.hs @@ -721,17 +721,22 @@ adjustNumbers opts doc = then doc else walk go doc where - go (Div (ident,"section":classes,kvs) lst) = - Div (ident,"section":classes,map fixnum kvs) lst + go (Div (ident,"section":classes,kvs) lst@(Header level _ _ : _)) = + Div (ident,"section":classes,map (fixnum level) kvs) lst go (Header level (ident,classes,kvs) lst) = - Header level (ident,classes,map fixnum kvs) lst + Header level (ident,classes,map (fixnum level) kvs) lst go x = x - fixnum ("number",num) = ("number", + fixnum level ("number",num) = ("number", showSecNum $ zipWith (+) (writerNumberOffset opts ++ repeat 0) - (map (fromMaybe 0 . safeRead) $ + (padTo level $ + map (fromMaybe 0 . safeRead) $ T.split (=='.') num)) - fixnum x = x + fixnum _ x = x + padTo n xs = + case n - length xs of + x | x > 0 -> replicate x 0 ++ xs + | otherwise -> xs showSecNum = T.intercalate "." . map tshow blockToHtmlInner :: PandocMonad m => WriterOptions -> Block -> StateT WriterState m Html diff --git a/test/command/5071.md b/test/command/5071.md new file mode 100644 index 000000000..6bbeb85fc --- /dev/null +++ b/test/command/5071.md @@ -0,0 +1,68 @@ +``` +% pandoc -f markdown -t html --number-sections +## First section + +### Subhead + +##### Subhead with gap + +## Second section +^D +<h2 data-number="1" id="first-section"><span +class="header-section-number">1</span> First section</h2> +<h3 data-number="1.1" id="subhead"><span +class="header-section-number">1.1</span> Subhead</h3> +<h5 data-number="1.1.0.1" id="subhead-with-gap"><span +class="header-section-number">1.1.0.1</span> Subhead with gap</h5> +<h2 data-number="2" id="second-section"><span +class="header-section-number">2</span> Second section</h2> + +``` + +``` +% pandoc -f markdown -t html --number-sections +## First section + +### Subhead + +# Higher-level section + +## Sub +^D +<h2 data-number="0.1" id="first-section"><span +class="header-section-number">0.1</span> First section</h2> +<h3 data-number="0.1.1" id="subhead"><span +class="header-section-number">0.1.1</span> Subhead</h3> +<h1 data-number="1" id="higher-level-section"><span +class="header-section-number">1</span> Higher-level section</h1> +<h2 data-number="1.1" id="sub"><span +class="header-section-number">1.1</span> Sub</h2> +``` + +For backwards compatibility, we want it to work the old way, +giving numbers like 0.1, when `--number-offset` is used: +``` +% pandoc -f markdown -t html --number-sections --number-offset=2,2,2 +## First section + +### Subhead +^D +<h2 data-number="2.3" id="first-section"><span +class="header-section-number">2.3</span> First section</h2> +<h3 data-number="2.3.3" id="subhead"><span +class="header-section-number">2.3.3</span> Subhead</h3> + +``` + +``` +% pandoc -f markdown -t html --number-sections --number-offset=0,2,2 +## First section + +### Subhead +^D +<h2 data-number="0.3" id="first-section"><span +class="header-section-number">0.3</span> First section</h2> +<h3 data-number="0.3.3" id="subhead"><span +class="header-section-number">0.3.3</span> Subhead</h3> + +``` |
