more quick answers
* notepad * fix config * mdn docs * search bar fix
This commit is contained in:
parent
99a28ce8d3
commit
25760146a3
@ -14,17 +14,17 @@ pub struct Config {
|
|||||||
impl Config {
|
impl Config {
|
||||||
pub fn read_or_create() -> eyre::Result<Self> {
|
pub fn read_or_create() -> eyre::Result<Self> {
|
||||||
let default_config_str = include_str!("../default-config.toml");
|
let default_config_str = include_str!("../default-config.toml");
|
||||||
let default_config = toml::from_str(default_config_str)?;
|
let mut config: Config = toml::from_str(default_config_str)?;
|
||||||
|
|
||||||
let config_path = Path::new("config.toml");
|
let config_path = Path::new("config.toml");
|
||||||
if config_path.exists() {
|
if config_path.exists() {
|
||||||
let mut given_config = toml::from_str::<Config>(&fs::read_to_string(config_path)?)?;
|
let given_config = toml::from_str::<Config>(&fs::read_to_string(config_path)?)?;
|
||||||
given_config.update(default_config);
|
config.update(given_config);
|
||||||
Ok(given_config)
|
Ok(config)
|
||||||
} else {
|
} else {
|
||||||
println!("No config found, creating one at {config_path:?}");
|
println!("No config found, creating one at {config_path:?}");
|
||||||
fs::write(config_path, default_config_str)?;
|
fs::write(config_path, default_config_str)?;
|
||||||
Ok(default_config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
pub mod dictionary;
|
pub mod dictionary;
|
||||||
pub mod fend;
|
pub mod fend;
|
||||||
pub mod ip;
|
pub mod ip;
|
||||||
|
pub mod notepad;
|
||||||
pub mod numbat;
|
pub mod numbat;
|
||||||
pub mod thesaurus;
|
pub mod thesaurus;
|
||||||
pub mod timezone;
|
pub mod timezone;
|
||||||
|
13
src/engines/answer/notepad.rs
Normal file
13
src/engines/answer/notepad.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use crate::engines::{EngineResponse, SearchQuery};
|
||||||
|
|
||||||
|
use super::regex;
|
||||||
|
|
||||||
|
pub fn request(query: &SearchQuery) -> EngineResponse {
|
||||||
|
if !regex!("(note|text|code) ?(pad|book|edit(or|er)?)").is_match(&query.query.to_lowercase()) {
|
||||||
|
return EngineResponse::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
EngineResponse::answer_html(
|
||||||
|
r#"<div contenteditable id='notepad' placeholder='Notes' style='width:100%;color:white;outline:none;min-height:4em;font-size:12px;'></div>"#.to_string()
|
||||||
|
)
|
||||||
|
}
|
@ -38,6 +38,7 @@ engines! {
|
|||||||
Dictionary = "dictionary",
|
Dictionary = "dictionary",
|
||||||
Fend = "fend",
|
Fend = "fend",
|
||||||
Ip = "ip",
|
Ip = "ip",
|
||||||
|
Notepad = "notepad",
|
||||||
Numbat = "numbat",
|
Numbat = "numbat",
|
||||||
Thesaurus = "thesaurus",
|
Thesaurus = "thesaurus",
|
||||||
Timezone = "timezone",
|
Timezone = "timezone",
|
||||||
@ -46,6 +47,7 @@ engines! {
|
|||||||
// post-search
|
// post-search
|
||||||
DocsRs = "docs_rs",
|
DocsRs = "docs_rs",
|
||||||
GitHub = "github",
|
GitHub = "github",
|
||||||
|
Mdn = "mdn",
|
||||||
StackExchange = "stackexchange",
|
StackExchange = "stackexchange",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +65,7 @@ engine_requests! {
|
|||||||
Dictionary => answer::dictionary::request, parse_response,
|
Dictionary => answer::dictionary::request, parse_response,
|
||||||
Fend => answer::fend::request, None,
|
Fend => answer::fend::request, None,
|
||||||
Ip => answer::ip::request, None,
|
Ip => answer::ip::request, None,
|
||||||
|
Notepad => answer::notepad::request, None,
|
||||||
Numbat => answer::numbat::request, None,
|
Numbat => answer::numbat::request, None,
|
||||||
Thesaurus => answer::thesaurus::request, parse_response,
|
Thesaurus => answer::thesaurus::request, parse_response,
|
||||||
Timezone => answer::timezone::request, None,
|
Timezone => answer::timezone::request, None,
|
||||||
@ -77,9 +80,10 @@ engine_autocomplete_requests! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
engine_postsearch_requests! {
|
engine_postsearch_requests! {
|
||||||
StackExchange => postsearch::stackexchange::request, parse_response,
|
|
||||||
GitHub => postsearch::github::request, parse_response,
|
|
||||||
DocsRs => postsearch::docs_rs::request, parse_response,
|
DocsRs => postsearch::docs_rs::request, parse_response,
|
||||||
|
GitHub => postsearch::github::request, parse_response,
|
||||||
|
Mdn => postsearch::mdn::request, parse_response,
|
||||||
|
StackExchange => postsearch::stackexchange::request, parse_response,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Engine {
|
impl fmt::Display for Engine {
|
||||||
|
@ -4,4 +4,5 @@
|
|||||||
|
|
||||||
pub mod docs_rs;
|
pub mod docs_rs;
|
||||||
pub mod github;
|
pub mod github;
|
||||||
|
pub mod mdn;
|
||||||
pub mod stackexchange;
|
pub mod stackexchange;
|
||||||
|
54
src/engines/postsearch/mdn.rs
Normal file
54
src/engines/postsearch/mdn.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use scraper::{Html, Selector};
|
||||||
|
|
||||||
|
use crate::engines::{HttpResponse, Response, CLIENT};
|
||||||
|
|
||||||
|
pub fn request(response: &Response) -> Option<reqwest::RequestBuilder> {
|
||||||
|
for search_result in response.search_results.iter().take(8) {
|
||||||
|
if search_result
|
||||||
|
.url
|
||||||
|
.starts_with("https://developer.mozilla.org/en-US/docs/Web")
|
||||||
|
{
|
||||||
|
return Some(CLIENT.get(search_result.url.as_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_response(HttpResponse { res, body }: &HttpResponse) -> Option<String> {
|
||||||
|
let url = res.url().clone();
|
||||||
|
|
||||||
|
let dom = Html::parse_document(body);
|
||||||
|
|
||||||
|
let page_title = dom
|
||||||
|
.select(&Selector::parse("header > h1").unwrap())
|
||||||
|
.next()?
|
||||||
|
.text()
|
||||||
|
.collect::<String>()
|
||||||
|
.trim()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let doc_query = Selector::parse(".section-content").unwrap();
|
||||||
|
|
||||||
|
let doc_html = dom
|
||||||
|
.select(&doc_query)
|
||||||
|
.next()
|
||||||
|
.map(|doc| doc.inner_html())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let doc_html = ammonia::Builder::default()
|
||||||
|
.link_rel(None)
|
||||||
|
.url_relative(ammonia::UrlRelative::RewriteWithBase(url.clone()))
|
||||||
|
.clean(&doc_html)
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let title_html = format!(
|
||||||
|
r#"<h2><a href="{url}">{title}</a></h2>"#,
|
||||||
|
url = html_escape::encode_quoted_attribute(&url.to_string()),
|
||||||
|
title = html_escape::encode_safe(&page_title),
|
||||||
|
);
|
||||||
|
|
||||||
|
Some(format!(
|
||||||
|
r#"{title_html}<div class="infobox-mdn-article">{doc_html}</div>"#
|
||||||
|
))
|
||||||
|
}
|
@ -109,6 +109,15 @@ document.addEventListener("keydown", (e) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the currently selected element is not the search bar and is contenteditable, don't do anything
|
||||||
|
const focusedEl = document.querySelector(":focus");
|
||||||
|
if (
|
||||||
|
focusedEl &&
|
||||||
|
(focusedEl.tagName == "input" ||
|
||||||
|
focusedEl.getAttribute("contenteditable") !== null)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
// if the user starts typing but they don't have focus on the input, focus it
|
// if the user starts typing but they don't have focus on the input, focus it
|
||||||
|
|
||||||
// no modifier keys
|
// no modifier keys
|
||||||
|
Loading…
Reference in New Issue
Block a user