Skip to content

Commit

Permalink
Try #398:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] authored Dec 24, 2022
2 parents 7f54c4e + efae3f4 commit 7cf6b2d
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- UI
- Add source map for Stork [\#391](https://github.com/srid/emanote/pull/391)
- Workaround for Prism.js and Tailwind CSS both using `table` class [\#320](https://github.com/srid/emanote/pull/396)
- Add option to include YAML frontmatter in the Stork index [\#398](https://github.com/srid/emanote/pull/398)
- Features
- Timeline backlinks recognize flexible daily notes suffixed with arbitrary string [\#395](https://github.com/srid/emanote/issues/395)
- Misc
Expand Down
2 changes: 2 additions & 0 deletions default/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ template:
# Whether this node in the sidebar tree should remain collapsed by default
# (unless a route in it is active)
collapsed: true
stork:
frontmatter-handling: omit

pandoc:
# Rewrite the class specified in Pandoc's Div and Span nodes. You can specify the class using
Expand Down
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
template:
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).
3 changes: 2 additions & 1 deletion emanote.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 2.4
name: emanote
version: 1.0.1.5
version: 1.0.1.6
license: AGPL-3.0-only
copyright: 2022 Sridhar Ratnakumar
maintainer: [email protected]
Expand Down Expand Up @@ -104,6 +104,7 @@ common library-common
, containers
, data-default
, dependent-sum
, deriving-aeson
, directory
, ema >=0.9
, filepath
Expand Down
18 changes: 16 additions & 2 deletions src/Emanote/Model/Stork.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ module Emanote.Model.Stork
where

import Control.Monad.Logger (MonadLoggerIO)
import Data.Default (Default (def))
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
( Config (Config),
File (File),
Handling,
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 +27,8 @@ import System.FilePath ((</>))

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

storkFiles :: Model -> [File]
storkFiles model =
Expand All @@ -29,3 +38,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 def ("template" :| ["stork", "frontmatter-handling"]) indexRoute model
92 changes: 69 additions & 23 deletions src/Emanote/Model/Stork/Index.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,22 @@ module Emanote.Model.Stork.Index
readOrBuildStorkIndex,
File (File),
Input (Input),
Config (Config),
Handling,
)
where

import Control.Monad.Logger (MonadLoggerIO)
import Data.Default (Default (..))
import Data.Text qualified as T
import Data.Time (NominalDiffTime, diffUTCTime, getCurrentTime)
import Deriving.Aeson
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 All @@ -31,8 +35,8 @@ newIndex =
clearStorkIndex :: (MonadIO m) => IndexVar -> m ()
clearStorkIndex (IndexVar var) = atomically $ writeTVar var mempty

readOrBuildStorkIndex :: (MonadIO m, MonadLoggerIO m) => IndexVar -> Input -> m LByteString
readOrBuildStorkIndex (IndexVar indexVar) input = do
readOrBuildStorkIndex :: (MonadIO m, MonadLoggerIO m) => IndexVar -> Config -> m LByteString
readOrBuildStorkIndex (IndexVar indexVar) config = do
readTVarIO indexVar >>= \case
Just index -> do
logD "STORK: Returning cached search index"
Expand All @@ -41,7 +45,7 @@ readOrBuildStorkIndex (IndexVar indexVar) input = do
-- TODO: What if there are concurrent reads? We probably need a lock.
-- And we want to encapsulate this whole thing.
logW "STORK: Generating search index (this may be expensive)"
(diff, !index) <- timeIt $ runStork input
(diff, !index) <- timeIt $ runStork config
log $ toText $ "STORK: Done generating search index in " <> showGFloat (Just 2) diff "" <> " seconds"
atomically $ modifyTVar' indexVar $ \_ -> Just index
pure index
Expand All @@ -57,9 +61,9 @@ readOrBuildStorkIndex (IndexVar indexVar) input = do
storkBin :: FilePath
storkBin = $(staticWhich "stork")

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

newtype Input = Input
{ inputFiles :: [File]
newtype Config = Config
{ configInput :: Input
}
deriving stock (Eq, Show)

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

Expand All @@ -91,18 +101,54 @@ data File = File
}
deriving stock (Eq, Show)

fileCodec :: TomlCodec File
fileCodec =
File
<$> Toml.string "path"
.= filePath
<*> Toml.text "url"
.= fileUrl
<*> Toml.text "title"
.= fileTitle
data Handling
= Handling_Ignore
| Handling_Omit
| Handling_Parse
deriving stock (Eq, Show, Generic)
deriving
(FromJSON)
via CustomJSON
'[ ConstructorTagModifier '[StripPrefix "Handling_", CamelToSnake]
]
Handling

inputCodec :: TomlCodec Input
inputCodec =
Input
<$> Toml.list fileCodec "input.files"
.= inputFiles
instance Default Handling where
def = Handling_Omit

configCodec :: TomlCodec Config
configCodec =
Config
<$> Toml.table inputCodec "input"
.= configInput
where
inputCodec :: TomlCodec Input
inputCodec =
Input
<$> Toml.list fileCodec "files"
.= inputFiles
<*> Toml.diwrap (handlingCodec "frontmatter_handling")
.= inputFrontmatterHandling
fileCodec :: TomlCodec File
fileCodec =
File
<$> Toml.string "path"
.= filePath
<*> Toml.text "url"
.= fileUrl
<*> Toml.text "title"
.= fileTitle
handlingCodec :: Toml.Key -> TomlCodec Handling
handlingCodec = textBy showHandling parseHandling
where
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

0 comments on commit 7cf6b2d

Please sign in to comment.