diff --git a/pgml-dashboard/src/api/cms.rs b/pgml-dashboard/src/api/cms.rs index ee1060d02..56e46757a 100644 --- a/pgml-dashboard/src/api/cms.rs +++ b/pgml-dashboard/src/api/cms.rs @@ -16,7 +16,7 @@ use crate::{ guards::Cluster, responses::{Response, ResponseOk, Template}, templates::docs::*, - utils::config, + utils::{config, markdown::SearchResult}, }; use serde::{Deserialize, Serialize}; use std::fmt; @@ -561,6 +561,40 @@ impl Collection { #[get("/search?", rank = 20)] async fn search(query: &str, site_search: &State) -> ResponseOk { let results = site_search.search(query, None).await.expect("Error performing search"); + + let results: Vec = results + .into_iter() + .map(|document| { + let snippet = if let Some(description) = document.description { + description + } else { + let author = document.author.unwrap_or_else(|| String::from("xzxzxz")); + // The heuristics used here are ok, not the best it will be better when we can just use the description field + document + .contents + .lines() + .find(|l| !l.is_empty() && !l.contains(&document.title) && !l.contains(&author) && l.len() > 30) + .unwrap_or("") + .split(' ') + .take(20) + .collect::>() + .join(" ") + + " ..." + }; + let path = document + .path + .to_str() + .unwrap_or_default() + .replace(".md", "") + .replace(&config::static_dir().display().to_string(), ""); + SearchResult { + title: document.title, + path, + snippet, + } + }) + .collect(); + ResponseOk( Template(Search { query: query.to_string(), diff --git a/pgml-dashboard/src/utils/markdown.rs b/pgml-dashboard/src/utils/markdown.rs index 2d4deea6a..5a674e836 100644 --- a/pgml-dashboard/src/utils/markdown.rs +++ b/pgml-dashboard/src/utils/markdown.rs @@ -1,6 +1,7 @@ use crate::api::cms::{DocType, Document}; use crate::{templates::docs::TocLink, utils::config}; use anyhow::Context; +use comrak::{format_html_with_plugins, parse_document, ComrakPlugins}; use std::cell::RefCell; use std::collections::HashMap; use std::path::PathBuf; @@ -21,6 +22,9 @@ use std::fmt; use std::sync::Mutex; use url::Url; +// Excluded paths in the pgml-cms directory +const EXCLUDED_DOCUMENT_PATHS: [&str; 1] = ["blog/README.md"]; + pub struct MarkdownHeadings { header_map: Arc>>, } @@ -1291,7 +1295,7 @@ impl SiteSearch { .collect() } - pub async fn search(&self, query: &str, doc_type: Option) -> anyhow::Result> { + pub async fn search(&self, query: &str, doc_type: Option) -> anyhow::Result> { let mut search = serde_json::json!({ "query": { // "full_text_search": { @@ -1323,10 +1327,8 @@ impl SiteSearch { "limit": 10 }); if let Some(doc_type) = doc_type { - search["query"]["filter"] = serde_json::json!({ - "doc_type": { - "$eq": doc_type - } + search["query"]["filter"]["doc_type"] = serde_json::json!({ + "$eq": doc_type }); } let results = self.collection.search_local(search.into(), &self.pipeline).await?; @@ -1334,18 +1336,10 @@ impl SiteSearch { results["results"] .as_array() .context("Error getting results from search")? - .into_iter() + .iter() .map(|r| { - let SearchResultWithoutSnippet { title, contents, path } = - serde_json::from_value(r["document"].clone())?; - let path = path - .replace(".md", "") - .replace(&config::static_dir().display().to_string(), ""); - Ok(SearchResult { - title, - path, - snippet: contents.split(' ').take(20).collect::>().join(" ") + " ...", - }) + let document: Document = serde_json::from_value(r["document"].clone())?; + Ok(document) }) .collect() } @@ -1358,6 +1352,24 @@ impl SiteSearch { .map(|path| async move { Document::from_path(&path).await }), ) .await?; + // Filter out documents who only have 1 line (this is usually just an empty document with the title as the first line) + // and documents that are in our excluded paths list + let documents: Vec = documents + .into_iter() + .filter(|f| { + !EXCLUDED_DOCUMENT_PATHS + .iter() + .any(|p| f.path == config::cms_dir().join(p)) + && !f + .contents + .lines() + .skip(1) + .collect::>() + .join("") + .trim() + .is_empty() + }) + .collect(); let documents: Vec = documents .into_iter() .map(|d| { diff --git a/pgml-dashboard/static/js/search.js b/pgml-dashboard/static/js/search.js index b08237435..02bd989b9 100644 --- a/pgml-dashboard/static/js/search.js +++ b/pgml-dashboard/static/js/search.js @@ -15,11 +15,16 @@ export default class extends Controller { this.target.addEventListener('shown.bs.modal', this.focusSearchInput) this.target.addEventListener('hidden.bs.modal', this.updateSearch) this.searchInput.addEventListener('input', (e) => this.search(e)) + + this.timer; } search(e) { + clearTimeout(this.timer); const query = e.currentTarget.value - this.searchFrame.src = `/search?query=${query}` + this.timer = setTimeout(() => { + this.searchFrame.src = `/search?query=${query}` + }, 250); } focusSearchInput = (e) => { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy