summaryrefslogtreecommitdiff
path: root/source/Render/Html.hs
diff options
context:
space:
mode:
Diffstat (limited to 'source/Render/Html.hs')
-rw-r--r--source/Render/Html.hs169
1 files changed, 128 insertions, 41 deletions
diff --git a/source/Render/Html.hs b/source/Render/Html.hs
index 20ac33b..c37a278 100644
--- a/source/Render/Html.hs
+++ b/source/Render/Html.hs
@@ -4,7 +4,11 @@
{-# LANGUAGE RecordWildCards #-}
module Render.Html
- ( renderDocument
+ ( HtmlRenderIndex
+ , HtmlPagePresentation
+ , buildRenderIndex
+ , htmlPagePresentationSource
+ , renderDocument
, supportScriptAssetContents
) where
@@ -61,6 +65,21 @@ type AnchorMap = Map Marker Text
type BlockRenderInfo = (Int, Block, Text)
type PreviewMap = Map Marker PreviewEntry
+data HtmlRenderIndex = HtmlRenderIndex
+ !(Map Marker IndexedReferenceTarget)
+
+data HtmlPagePresentation = HtmlPagePresentation
+ { htmlPagePresentationSource :: !ResolvedSource
+ , pagePresentationBlockInfos :: ![BlockRenderInfo]
+ , pagePresentationAnchors :: !AnchorMap
+ , pagePresentationReferencedMarkers :: !(Set Marker)
+ }
+
+data IndexedReferenceTarget = IndexedReferenceTarget
+ !Int
+ !ResolvedSource
+ !ReferenceTarget
+
data ReferenceContext = ReferenceContext
{ referenceAnchors :: AnchorMap
, referencePreviews :: PreviewMap
@@ -112,36 +131,36 @@ referenceGroupThreshold = 5
renderDocument
:: HtmlRenderContext
-> Text
- -> [Block]
- -> [(ResolvedSource, [Block])]
+ -> HtmlRenderIndex
+ -> HtmlPagePresentation
-> Either HtmlRenderContextError Text
-renderDocument context hintsSource blocks sourceBlocks = do
- let indexedBlocks = zip [1 :: Int ..] blocks
- blockInfos =
- [ (index, block, blockAnchorId index block)
- | (index, block) <- indexedBlocks
- ]
- rootTargets =
- concatMap referenceTargetsOfBlockRenderInfo blockInfos
- anchors = Map.fromList
- [ (targetMarker, targetAnchorId)
- | ReferenceTarget{targetMarker, targetAnchorId} <-
- rootTargets
- ]
- referencedMarkers = collectReferencedMarkers blocks
+renderDocument
+ context
+ hintsSource
+ renderIndex
+ HtmlPagePresentation
+ { pagePresentationBlockInfos = blockInfos
+ , pagePresentationAnchors = anchors
+ , pagePresentationReferencedMarkers = referencedMarkers
+ } = do
previews <-
buildPreviewMap
context
referencedMarkers
anchors
- sourceBlocks
+ renderIndex
let result =
case formatMissingHintWarning missingHints of
Nothing -> rendered
Just warningText ->
trace (Text.unpack warningText) rendered
hints = parseHints hintsSource
- missingHints = collectMissingHints hints blocks
+ missingHints =
+ collectMissingHints
+ hints
+ [ block
+ | (_index, block, _blockId) <- blockInfos
+ ]
rendered = LazyText.toStrict (renderText (renderPage hints))
pageLabel = htmlCurrentPageLabel context
tocBlocks = [(index, blockId, block) | (index, block, blockId) <- blockInfos, includeInToc block]
@@ -182,6 +201,73 @@ renderDocument context hintsSource blocks sourceBlocks = do
("" :: Text)
Right result
+-- | Index every block target and every page's referenced markers once in
+-- deterministic source order. Rendering a page subsequently performs only
+-- marker lookups in the shared index.
+buildRenderIndex
+ :: NonEmpty (ResolvedSource, [Block])
+ -> (HtmlRenderIndex, NonEmpty HtmlPagePresentation)
+buildRenderIndex sourceBlocks =
+ ( HtmlRenderIndex
+ (Map.fromList
+ [ ( targetMarker target
+ , IndexedReferenceTarget ordinal source target
+ )
+ | (ordinal, (source, target)) <-
+ zip [1 :: Int ..] orderedTargets
+ ])
+ , pages
+ )
+ where
+ analysedPages =
+ uncurry analysePage <$> sourceBlocks
+ pages =
+ fst <$> analysedPages
+ orderedTargets =
+ [ (htmlPagePresentationSource page, target)
+ | (page, targets) <- NonEmpty.toList analysedPages
+ , target <- targets
+ ]
+
+ analysePage source blocks =
+ ( HtmlPagePresentation
+ { htmlPagePresentationSource = source
+ , pagePresentationBlockInfos = blockInfos
+ , pagePresentationAnchors =
+ Map.fromList
+ [ (targetMarker, targetAnchorId)
+ | ReferenceTarget
+ { targetMarker
+ , targetAnchorId
+ } <- targets
+ ]
+ , pagePresentationReferencedMarkers =
+ foldMap
+ (\(_blockInfo, _targets, references) -> references)
+ analysedBlocks
+ }
+ , targets
+ )
+ where
+ analysedBlocks =
+ [ ( blockInfo
+ , referenceTargetsOfBlockRenderInfo blockInfo
+ , collectReferencedMarkersOfBlock block
+ )
+ | (index, block) <- zip [1 :: Int ..] blocks
+ , let blockInfo =
+ (index, block, blockAnchorId index block)
+ ]
+ blockInfos =
+ [ blockInfo
+ | (blockInfo, _targets, _references) <- analysedBlocks
+ ]
+ targets =
+ concat
+ [ blockTargets
+ | (_blockInfo, blockTargets, _references) <- analysedBlocks
+ ]
+
pageStyles :: Text
pageStyles = Text.unlines
@@ -955,10 +1041,10 @@ referencePreviewScript = Text.unlines
, "})();"
]
-collectReferencedMarkers :: [Block] -> Set Marker
-collectReferencedMarkers =
- foldMap collectBlock
- where
+collectReferencedMarkersOfBlock :: Block -> Set Marker
+collectReferencedMarkersOfBlock =
+ collectBlock
+ where
collectBlock :: Block -> Set Marker
collectBlock = \case
BlockProof _start proof _end ->
@@ -2376,29 +2462,30 @@ buildPreviewMap
:: HtmlRenderContext
-> Set Marker
-> AnchorMap
- -> [(ResolvedSource, [Block])]
+ -> HtmlRenderIndex
-> Either HtmlRenderContextError PreviewMap
-buildPreviewMap context referencedMarkers anchors sourceBlocks =
+buildPreviewMap
+ context
+ referencedMarkers
+ anchors
+ (HtmlRenderIndex targetIndex) =
Map.fromList <$> traverse makePreviewEntry indexedTargets
where
targets =
- [ (source, target)
- | (source, blocks) <- sourceBlocks
- , let indexedBlocks = zip [1 :: Int ..] blocks
- , let blockInfos =
- [ (index, block, blockAnchorId index block)
- | (index, block) <- indexedBlocks
- ]
- , target <-
- concatMap
- referenceTargetsOfBlockRenderInfo
- blockInfos
- , targetMarker target `Set.member` referencedMarkers
- , targetMarker target `Map.notMember` anchors
- , source /= htmlCurrentSource context
- ]
+ List.sortOn targetOrdinal
+ [ indexed
+ | marker <- Set.toList referencedMarkers
+ , marker `Map.notMember` anchors
+ , Just indexed@(IndexedReferenceTarget _ source _target) <-
+ [Map.lookup marker targetIndex]
+ , source /= htmlCurrentSource context
+ ]
+ targetOrdinal (IndexedReferenceTarget ordinal _source _target) =
+ ordinal
+ sourceTarget (IndexedReferenceTarget _ordinal source target) =
+ (source, target)
indexedTargets =
- zip [1 :: Int ..] targets
+ zip [1 :: Int ..] (sourceTarget <$> targets)
makePreviewEntry (index, (source, target)) = do
previewSourceLabel <-