Skip to content

Commit

Permalink
Merge #398
Browse files Browse the repository at this point in the history
398: Include YAML frontmatter in the Stork index r=srid a=jfpedroza

This PR sets the `frontmatter_handling` setting in Stork to `Ignore` so the frontmatter is included in the searchable text.

See #397 


Co-authored-by: Jhon Pedroza <[email protected]>
Co-authored-by: Sridhar Ratnakumar <[email protected]>
  • Loading branch information
3 people authored Dec 24, 2022
2 parents 661b08c + 0ee0418 commit b39f130
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 9 deletions.
2 changes: 2 additions & 0 deletions default/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,5 @@ js:
emanote:
# Whether to automatically treat folder notes as a folgezettel parent of its contents
folder-folgezettel: true
stork:
frontmatter-handling: omit
20 changes: 18 additions & 2 deletions docs/guide/html-template/search.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,27 @@ Emanote provides client-side full-text search using [Stork](https://stork-search

You can trigger search input in one of the following ways:

- Press `Ctrl+K` (or `⌘K` on macOS).
- Press `Ctrl+K` (or `⌘K` on macOS).
- Click the lens icon on the sidebar (if using the 'book' [[html-template|template layout]]) or top-right corner (if using [[neuron-layout]]).

## Including frontmatter content in the search

By default, Stork doesn't include the text in the frontmatter as searchable.

This can be changed by adding the following to `index.yaml`:

```yaml
emanote:
stork:
frontmatter-handling: ignore
```
This allows you to search by the tags present in the frontmatter, but you will also get potentially undesired results when searching words like `order` or `date`.

The possible values are `ignore`, `omit` and `parse`. Default `omit`. See the Stork [docs](https://stork-search.net/docs/config-ref#frontmatter_handling).

## Known issues

- In live server mode, you may find that the browser will fetch remote assets (the wasm file) from files.stork-search.net. See details [here](https://github.com/jameslittle230/stork/issues/317#issuecomment-1258682222).

[^1]: The Stork index file can be accessed at [`-/stork.st`](-/stork.st).
[^1]: The Stork index file can be accessed at [`-/stork.st`](-/stork.st).
10 changes: 8 additions & 2 deletions src/Emanote/Model/Stork.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ where

import Control.Monad.Logger (MonadLoggerIO)
import Data.IxSet.Typed qualified as Ix
import Emanote.Model.Meta (lookupRouteMeta)
import Emanote.Model.Note qualified as N
import Emanote.Model.Stork.Index (File (File), Input (Input), readOrBuildStorkIndex)
import Emanote.Model.Stork.Index (File (File), Handling (Handling_Omit), Input (Input), readOrBuildStorkIndex)
import Emanote.Model.Title qualified as Tit
import Emanote.Model.Type (Model)
import Emanote.Model.Type qualified as M
Expand All @@ -19,7 +20,7 @@ import System.FilePath ((</>))

renderStorkIndex :: (MonadIO m, MonadLoggerIO m) => Model -> m LByteString
renderStorkIndex model = do
readOrBuildStorkIndex (model ^. M.modelStorkIndex) (Input $ storkFiles model)
readOrBuildStorkIndex (model ^. M.modelStorkIndex) (Input (storkFiles model) (frontmatterHandling model))

storkFiles :: Model -> [File]
storkFiles model =
Expand All @@ -29,3 +30,8 @@ storkFiles model =
((baseDir </>) $ R.withLmlRoute R.encodeRoute $ note ^. N.noteRoute)
(SR.siteRouteUrl model $ SR.lmlSiteRoute $ note ^. N.noteRoute)
(Tit.toPlain $ note ^. N.noteTitle)

frontmatterHandling :: Model -> Handling
frontmatterHandling model =
let indexRoute = M.modelIndexRoute model
in lookupRouteMeta Handling_Omit ("emanote" :| ["stork", "frontmatter-handling"]) indexRoute model
58 changes: 53 additions & 5 deletions src/Emanote/Model/Stork/Index.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ module Emanote.Model.Stork.Index
readOrBuildStorkIndex,
File (File),
Input (Input),
Handling (Handling_Ignore, Handling_Omit, Handling_Parse),
)
where

import Control.Monad.Logger (MonadLoggerIO)
import Data.Aeson (FromJSON, genericParseJSON)
import Data.Aeson qualified as Aeson
import Data.Text qualified as T
import Data.Time (NominalDiffTime, diffUTCTime, getCurrentTime)
import Emanote.Prelude (log, logD, logW)
import Numeric (showGFloat)
import Relude
import System.Process.ByteString (readProcessWithExitCode)
import System.Which (staticWhich)
import Toml (TomlCodec, encode, list, string, text, (.=))
import Toml (Key, TomlCodec, diwrap, encode, list, string, table, text, textBy, (.=))

-- | In-memory Stork index tracked in a @TVar@
newtype IndexVar = IndexVar (TVar (Maybe LByteString))
Expand Down Expand Up @@ -59,7 +62,7 @@ storkBin = $(staticWhich "stork")

runStork :: MonadIO m => Input -> m LByteString
runStork input = do
let storkToml = handleTomlandBug $ Toml.encode inputCodec input
let storkToml = handleTomlandBug $ Toml.encode configCodec $ Config input
(_, !index, _) <-
liftIO $
readProcessWithExitCode
Expand All @@ -79,8 +82,20 @@ runStork input = do
-- title (but why would they?)
T.replace "\\\\U" "\\U"

newtype Input = Input
{ inputFiles :: [File]
data Input = Input
{ inputFiles :: [File],
inputFrontmatterHandling :: Handling
}
deriving stock (Eq, Show)

data Handling
= Handling_Ignore
| Handling_Omit
| Handling_Parse
deriving stock (Eq, Show, Generic)

newtype Config = Config
{ configInput :: Input
}
deriving stock (Eq, Show)

Expand All @@ -101,8 +116,41 @@ fileCodec =
<*> Toml.text "title"
.= fileTitle

showHandling :: Handling -> Text
showHandling handling = case handling of
Handling_Ignore -> "Ignore"
Handling_Omit -> "Omit"
Handling_Parse -> "Parse"

parseHandling :: Text -> Either Text Handling
parseHandling handling = case handling of
"Ignore" -> Right Handling_Ignore
"Omit" -> Right Handling_Omit
"Parse" -> Right Handling_Parse
other -> Left $ "Unsupported value for frontmatter handling: " <> other

handlingCodec :: Toml.Key -> TomlCodec Handling
handlingCodec = textBy showHandling parseHandling

inputCodec :: TomlCodec Input
inputCodec =
Input
<$> Toml.list fileCodec "input.files"
<$> Toml.list fileCodec "files"
.= inputFiles
<*> Toml.diwrap (handlingCodec "frontmatter_handling")
.= inputFrontmatterHandling

configCodec :: TomlCodec Config
configCodec =
Config
<$> Toml.table inputCodec "input"
.= configInput

handlingJSONOptions :: Aeson.Options
handlingJSONOptions =
Aeson.defaultOptions
{ Aeson.constructorTagModifier = toString . T.toLower . T.replace "Handling_" "" . toText
}

instance FromJSON Handling where
parseJSON = genericParseJSON handlingJSONOptions

0 comments on commit b39f130

Please sign in to comment.