@@ -4,6 +4,7 @@ import Prelude
5import Docs.Search.Config (config)
5import Docs.Search.Config (config)
6import Docs.Search.Declarations (Declarations(..), mkDeclarations)
6import Docs.Search.Declarations (Declarations(..), mkDeclarations)
7+import Docs.Search.DocsJson (DocsJson)
7import Docs.Search.Extra ((>#>))
8import Docs.Search.Extra ((>#>))
8import Docs.Search.Index (getPartId)
9import Docs.Search.Index (getPartId)
9import Docs.Search.SearchResult (SearchResult)
10import Docs.Search.SearchResult (SearchResult)
@@ -26,7 +27,6 @@ import Data.Set as Set
26import Data.String.CodePoints (contains) as String
27import Data.String.CodePoints (contains) as String
27import Data.String.CodeUnits (singleton) as String
28import Data.String.CodeUnits (singleton) as String
28import Data.String.Common (replace) as String
29import Data.String.Common (replace) as String
29−import Data.String.Pattern (Pattern(..)) as String
30import Data.String.Pattern (Pattern(..), Replacement(..))
30import Data.String.Pattern (Pattern(..), Replacement(..))
31import Data.Traversable (for, for_)
31import Data.Traversable (for, for_)
32import Data.Tuple (Tuple(..), fst, snd)
32import Data.Tuple (Tuple(..), fst, snd)
@@ -38,7 +38,6 @@ import Node.Encoding (Encoding(UTF8))
38import Node.FS.Aff (exists, mkdir, readTextFile, readdir, stat, writeTextFile)
38import Node.FS.Aff (exists, mkdir, readTextFile, readdir, stat, writeTextFile)
39import Node.FS.Stats (isDirectory, isFile)
39import Node.FS.Stats (isDirectory, isFile)
40import Node.Process as Process
40import Node.Process as Process
41−import Docs.Search.DocsJson (DocsJson)
43main :: Effect Unit
42main :: Effect Unit
44main = launchAff_ mainAff
43main = launchAff_ mainAff
@@ -82,7 +81,7 @@ collectDocsJsons :: String -> Aff (Array DocsJson)
82collectDocsJsons outputDir = do
81collectDocsJsons outputDir = do
83 paths <- readdir outputDir
82 paths <- readdir outputDir
85− mbs <- for paths \moduleName -> do
84+ Array.catMaybes <$> for paths \moduleName -> do
86 let jsonFile = "output/" <> moduleName <> "/docs.json"
85 let jsonFile = "output/" <> moduleName <> "/docs.json"
87 doesExist <- fileExists jsonFile
86 doesExist <- fileExists jsonFile
88 if doesExist then do
87 if doesExist then do
@@ -103,8 +102,6 @@ collectDocsJsons outputDir = do
103 "Couldn't find docs.json for " <> moduleName
102 "Couldn't find docs.json for " <> moduleName
104 pure Nothing
103 pure Nothing
106− pure $ Array.catMaybes mbs
108writeTypeIndex :: TypeIndex -> Aff Unit
105writeTypeIndex :: TypeIndex -> Aff Unit
109writeTypeIndex typeIndex =
106writeTypeIndex typeIndex =
110 for_ entries \(Tuple typeShape results) -> do
107 for_ entries \(Tuple typeShape results) -> do
@@ -117,33 +114,34 @@ writeTypeIndex typeIndex =
117 entries :: Array _
114 entries :: Array _
118 entries = Map.toUnfoldableUnordered (unwrap typeIndex)
115 entries = Map.toUnfoldableUnordered (unwrap typeIndex)
120−writeIndex :: Declarations -> Aff Unit
117+-- | Get a mapping from index parts to index contents.
118+getIndex :: Declarations -> Map Int (Array (Tuple String (Array SearchResult)))
121−writeIndex (Declarations trie) = do
119+getIndex (Declarations trie) =
122− let
120+ Array.foldr insert mempty parts
123− prefixes :: Array (List Char)
122+ prefixes :: Array (List Char)
124− prefixes =
123+ prefixes =
125 Set.toUnfoldable $
124 Set.toUnfoldable $
126 List.foldr (\entry -> Set.insert (List.take 2 $ fst entry)) mempty $
125 List.foldr (\entry -> Set.insert (List.take 2 $ fst entry)) mempty $
127 Trie.entriesUnordered trie
126 Trie.entriesUnordered trie
130− :: Array { prefix :: List Char
129+ :: Array { prefix :: List Char
131− , results :: Array (Tuple String (Array SearchResult))
130+ , results :: Array (Tuple String (Array SearchResult))
133− parts = prefixes <#> \prefix ->
132+ parts = prefixes <#> \prefix ->
134− let results =
133+ let results =
135− Array.fromFoldable $
134+ Array.fromFoldable $
136− Trie.query prefix trie <#>
135+ Trie.query prefix trie <#>
137− \(Tuple path value) ->
136+ \(Tuple path value) ->
138− Tuple (path >#> String.singleton) (Array.fromFoldable value)
137+ Tuple (path >#> String.singleton) (Array.fromFoldable value)
140− { prefix, results }
139+ { prefix, results }
142− resultsMap :: Map Int (Array (Tuple String (Array SearchResult)))
143− resultsMap = Array.foldr insert mempty parts
145− insert part = Map.insertWith append (getPartId part.prefix) part.results
141+ insert part = Map.insertWith append (getPartId part.prefix) part.results
143+writeIndex :: Declarations -> Aff Unit
144+writeIndex = getIndex >>> \resultsMap -> do
147 for_ (Map.toUnfoldableUnordered resultsMap :: Array _)
145 for_ (Map.toUnfoldableUnordered resultsMap :: Array _)
148 \(Tuple indexPartId results) -> do
146 \(Tuple indexPartId results) -> do
149 let header =
147 let header =
@@ -153,17 +151,24 @@ writeIndex (Declarations trie) = do
153 writeTextFile UTF8 (config.mkIndexPartPath indexPartId) $
151 writeTextFile UTF8 (config.mkIndexPartPath indexPartId) $
154 header <> stringify (encodeJson results)
152 header <> stringify (encodeJson results)
154+patchHTML :: String -> Tuple Boolean String
157+ pattern = Pattern "</body>"
158+ patch = "<!-- Docs search index. -->" <>
159+ "<script type=\"text/javascript\" src=\"../docs-search-app.js\"></script>" <>
160+ "<script type=\"text/javascript\">" <>
161+ "window.DocsSearchTypeIndex = {};" <>
162+ "window.DocsSearchIndex = {};" <>
165+ in if not $ String.contains (Pattern patch) html
166+ then Tuple true $ String.replace pattern (Replacement patch) html
167+ else Tuple false html
156patchDocs :: Aff Unit
169patchDocs :: Aff Unit
157patchDocs = do
170patchDocs = do
158 let dirname = "generated-docs/"
171 let dirname = "generated-docs/"
159− pattern = Pattern "</body>"
160− patch = "<!-- Docs search index. -->" <>
161− "<script type=\"text/javascript\" src=\"../docs-search-app.js\"></script>" <>
162− "<script type=\"text/javascript\">" <>
163− "window.DocsSearchTypeIndex = {};" <>
164− "window.DocsSearchIndex = {};" <>
168 files <- readdir (dirname <> "html")
173 files <- readdir (dirname <> "html")
@@ -172,9 +177,10 @@ patchDocs = do
173 whenM (fileExists path) do
178 whenM (fileExists path) do
174 contents <- readTextFile UTF8 path
179 contents <- readTextFile UTF8 path
175− when (not $ String.contains (String.Pattern patch) contents) do
180+ case patchHTML contents of
181+ Tuple true patchedContents -> do
176− writeTextFile UTF8 path $
182+ writeTextFile UTF8 path patchedContents
177− String.replace pattern (Replacement patch) contents
183+ _ -> pure unit
179createDirectories :: Aff Unit
185createDirectories :: Aff Unit
180createDirectories = do
186createDirectories = do