-
Notifications
You must be signed in to change notification settings - Fork 4
/
LunrIndexer.cs
69 lines (56 loc) · 2.56 KB
/
LunrIndexer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using MemoirsTheme.Pipelines;
using Statiq.Common;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Index = Lunr.Index;
namespace MemoirsTheme.Modules
{
public class LunrIndexer : Module
{
private static readonly Regex StripHtmlAndSpecialChars = new Regex(@"<[^>]+>|&[a-zA-Z]{2,};|&#\d+;|[^a-zA-Z-#]", RegexOptions.Compiled);
protected override async Task<IEnumerable<IDocument>> ExecuteContextAsync(IExecutionContext context)
{
if (context.Inputs.Length == 0)
{
throw new InvalidOperationException($"No input documents available. Cannot build a search index for pipeline {context.PipelineName}");
}
var documents = new Dictionary<string,object>();
Index idx = await Index.Build(async builder =>
{
builder.ReferenceField = "id";
builder
.AddField("title")
.AddField("content")
.AddField("tags")
.AddField("description");
foreach (IDocument doc in context.Inputs)
{
var searchItem = doc[SearchIndex.SearchItemKey] as LunrIndexDocItem;
if (searchItem == null)
continue;
var id = Guid.NewGuid().ToString("D");
var content = StripHtmlAndSpecialChars.Replace(searchItem.Content, " ").Trim();
documents.Add(id, new
{
url = searchItem.GetLink(context, false),
title = searchItem.Title,
body = searchItem.Description
});
var lunrDoc = new global::Lunr.Document
{
{"id", id},
{"title", searchItem.Title},
{"content", content},
{"tags", searchItem.Tags},
{"description", searchItem.Description}
};
await builder.Add(lunrDoc);
}
});
return new[] { context.CreateDocument(destination: "index.js",
$@"var documents={System.Text.Json.JsonSerializer.Serialize(documents)};{Environment.NewLine}var data='{idx.ToJson()}';{Environment.NewLine}") };
}
}
}