Jacky Zhao
2021-12-28 e4caa0d1d7fb3bdca6dee07fee299a3acdf40043
layouts/partials/search.html
@@ -1,7 +1,6 @@
<div id="search-container">
    <div id="search-space">
        <input autoComplete="off" id="search-bar" name="search" type="text" aria-label="Search"
               placeholder="Search for something...">
        <input autocomplete="off" id="search-bar" name="search" type="text" aria-label="Search" placeholder="Search for something...">
        <div id="results-container">
        </div>
    </div>
@@ -68,22 +67,42 @@
    };
</script>
<script>
    const contentIndex = new FlexSearch.Worker({
        tokenize: "reverse",
    const contentIndex = new FlexSearch.Document({
        cache: true,
        charset: "latin:extra",
        suggest: true,
        optimize: true,
        worker: true,
        document: {
            index: [{
                field: "content",
                tokenize: "strict",
                context: {
                    resolution: 5,
                    depth: 3,
                    bidirectional: true
                },
                suggest: true,
            }, {
                field: "title",
                tokenize: "forward",
            }]
        }
    })
    const scrapedContent = {{$.Site.Data.contentIndex}}
    for (const [key, value] of Object.entries(scrapedContent)) {
        contentIndex.add(key, value.content)
        contentIndex.add({
            id: key,
            title: value.title,
            content: removeMarkdown(value.content),
        })
    }
    const highlight = (content, term) => {
        const highlightWindow = 15
        const highlightWindow = 20
        const tokenizedTerm = term.split(/\s+/).filter(t => t !== "")
        const splitText = content.split(/\s+/).filter(t => t !== "")
        const includesCheck = (token) => tokenizedTerm.some(term => token.toLowerCase().includes(term.toLowerCase()))
        const includesCheck = (token) => tokenizedTerm.some(term => token.toLowerCase().startsWith(term.toLowerCase()))
        const occurrencesIndices = splitText
            .map(includesCheck)
@@ -116,8 +135,7 @@
    }
    const resultToHTML = ({url, title, content, term}) => {
        const md = content.split("---")[2]
        const text = removeMarkdown(md)
        const text = removeMarkdown(content)
        const resultTitle = highlight(title, term)
        const resultText = highlight(text, term)
        return `<button class="result-card" id="${url}">
@@ -127,9 +145,16 @@
    }
    const redir = (id, term) => {
        window.location.href = {{.Site.BaseURL}} + `${id}#:~:text=${encodeURIComponent(term)}`
        window.location.href = "{{.Site.BaseURL}}" + `${id}#:~:text=${encodeURIComponent(term)}`
    }
    const fetch = id => ({
        id,
        url: id,
        title: scrapedContent[id].title,
        content: scrapedContent[id].content
    })
    const source = document.getElementById('search-bar')
    const results = document.getElementById("results-container")
    let term
@@ -141,23 +166,33 @@
    })
    source.addEventListener('input', (e) => {
        term = e.target.value
        contentIndex.search(term, {
            limit: 20,
            depth: 3,
            suggest: true,
        }).then(searchResults => {
            const resultIds = [...new Set(searchResults)]
            const finalResults = resultIds.map(id => ({
                url: id,
                title: scrapedContent[id].title,
                content: scrapedContent[id].content
            }))
        contentIndex.search(term, [
            {
                field: "content",
                limit: 10,
                suggest: true,
            },
            {
                field: "title",
                limit: 5,
            }
        ]).then(searchResults => {
            const getByField = field => {
                const results = searchResults.filter(x => x.field === field)
                if (results.length === 0) {
                    return []
                } else {
                    return [...results[0].result]
                }
            }
            const allIds = new Set([...getByField('title'), ...getByField('content')])
            const finalResults = [...allIds].map(fetch)
            // display
            if (finalResults.length === 0) {
                results.innerHTML = `<div class="result-card">
            <p>No results.</p>
        </div>`
                    <p>No results.</p>
                </div>`
            } else {
                results.innerHTML = finalResults
                    .map(result => resultToHTML({
@@ -175,7 +210,6 @@
    const searchContainer = document.getElementById("search-container")
    function openSearch() {
        if (searchContainer.style.display === "none" || searchContainer.style.display === "") {
            source.value = ""
@@ -218,4 +252,4 @@
        })
    })
</script>
</script>