Skip to content

Commit

Permalink
Shared: makeSections behavior changes.
Browse files Browse the repository at this point in the history
+ 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.
  • Loading branch information
jgm committed Feb 4, 2024
1 parent 6fc8a80 commit 03bb426
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 20 deletions.
2 changes: 1 addition & 1 deletion pandoc-lua-engine/test/lua/module/pandoc-structure.lua
Expand Up @@ -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)
},

Expand Down
29 changes: 16 additions & 13 deletions src/Text/Pandoc/Shared.hs
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
17 changes: 11 additions & 6 deletions src/Text/Pandoc/Writers/HTML.hs
Expand Up @@ -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
Expand Down
68 changes: 68 additions & 0 deletions 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>
```

0 comments on commit 03bb426

Please sign in to comment.