diff options
-rw-r--r-- | web/atward/src/index.html | 49 | ||||
-rw-r--r-- | web/atward/src/main.rs | 105 |
2 files changed, 139 insertions, 15 deletions
diff --git a/web/atward/src/index.html b/web/atward/src/index.html index 286bc6e546ad..a62d168bda0e 100644 --- a/web/atward/src/index.html +++ b/web/atward/src/index.html @@ -6,7 +6,28 @@ <link rel="icon" type="image/webp" href="https://tvl.fyi/static/favicon.webp"> <link rel="search" type="application/opensearchdescription+xml" title="TVL Search" href="https://at.tvl.fyi/opensearch.xml"> <title>TVL Search</title> -<body class="light"> +<script> + /* Initialise the state of all settings. */ + function loadSettings() { + loadSetting(document.getElementById('cs-setting'), 'cs'); + } + + /* Initialise the state of a setting from a cookie. */ + function loadSetting(checkbox, name) { + if (document.cookie.split(';').some(function(cookie) { + return cookie.indexOf(`${name}=true`) >= 0; + })) { + checkbox.checked = true; + } + } + + /* Persist the state of a checkbox in a cookie */ + function saveSetting(checkbox, name) { + console.log(`setting atward parameter '${name}' to ${checkbox.checked.toString()}`); + document.cookie = `${name}=${checkbox.checked.toString()};`; + } +</script> +<body class="light" onload="loadSettings();"> <header> <h1><a class="blog-title" href="/">atward</a></h1> <hr/> @@ -47,12 +68,28 @@ <li><kbd>cs=true</kbd> - use Sourcegraph instead of cgit to view code</li> </ul> </p> - <p class="cheddar-callout cheddar-todo"> - In <b>Firefox</b>, configuring query parameters is difficult as - users can not edit search engines directly. There are browser - extensions and other workarounds for this issue, but we do not - recommend any particular one. + <p> + In some browsers (like Firefox) users can not edit query + parameters for search engines. As an alternative configuration can + be supplied via cookies with the same names as the configuration + parameters. + </p> + <p> + The form below can set this configuration: + <form class="cheddar-callout cheddar-todo"> + <input type="checkbox" + id="cs-setting" + onchange="saveSetting(this, 'cs');" + > Use Sourcegraph instead of cgit</input> + </form> </p> + <noscript> + <p class="cheddar-callout cheddar-warning"> + The form above only works with Javascript enabled. Only a few + lines of Javascript are used, and they are licensed under a + free-software license (MIT). + </p> + </noscript> <h3>Source code</h3> <p> diff --git a/web/atward/src/main.rs b/web/atward/src/main.rs index 04beb02cd5d6..b29877c6c00e 100644 --- a/web/atward/src/main.rs +++ b/web/atward/src/main.rs @@ -5,7 +5,8 @@ //! browsers and attempts to send users to useful locations based on //! their search query (falling back to another search engine). use regex::Regex; -use rouille::Response; +use rouille::input::cookies; +use rouille::{Request, Response}; /// A query handler supported by atward. It consists of a pattern on /// which to match and trigger the query, and a function to execute @@ -23,6 +24,7 @@ struct Handler { } /// An Atward query supplied by a user. +#[derive(Debug, PartialEq)] struct Query { /// Query string itself. query: String, @@ -31,19 +33,38 @@ struct Query { cs: bool, } +/// Helper function for setting a parameter based on a query +/// parameter. +fn query_setting(req: &Request, config: &mut bool, param: &str) { + match req.get_param(param) { + Some(s) if s == "true" => *config = true, + Some(s) if s == "false" => *config = false, + _ => {} + } +} + impl Query { - fn from_request(req: &rouille::Request) -> Option<Query> { - let query = match req.get_param("q") { - Some(q) => q, + fn from_request(req: &Request) -> Option<Query> { + // First extract the actual search query ... + let mut query = match req.get_param("q") { + Some(query) => Query { query, cs: false }, None => return None, }; - let cs = match req.get_param("cs") { - Some(s) if s == "true" => true, - _ => false, - }; + // ... then apply settings to it. Settings in query parameters + // take precedence over cookies. + for cookie in cookies(req) { + match cookie { + ("cs", "true") => { + query.cs = true; + } + _ => {} + } + } - Some(Query { query, cs }) + query_setting(req, &mut query.cs, "cs"); + + Some(query) } } @@ -228,4 +249,70 @@ mod tests { None ); } + + #[test] + fn request_to_query() { + assert_eq!( + Query::from_request(&Request::fake_http("GET", "/?q=b%2F42", vec![], vec![])) + .expect("request should parse to a query"), + Query { + query: "b/42".to_string(), + cs: false, + }, + ); + + assert_eq!( + Query::from_request(&Request::fake_http("GET", "/", vec![], vec![])), + None + ); + } + + #[test] + fn settings_from_cookie() { + assert_eq!( + Query::from_request(&Request::fake_http( + "GET", + "/?q=b%2F42", + vec![("Cookie".to_string(), "cs=true;".to_string())], + vec![] + )) + .expect("request should parse to a query"), + Query { + query: "b/42".to_string(), + cs: true, + }, + ); + } + + #[test] + fn settings_from_query_parameter() { + assert_eq!( + Query::from_request(&Request::fake_http( + "GET", + "/?q=b%2F42&cs=true", + vec![], + vec![] + )) + .expect("request should parse to a query"), + Query { + query: "b/42".to_string(), + cs: true, + }, + ); + + // Query parameter should override cookie + assert_eq!( + Query::from_request(&Request::fake_http( + "GET", + "/?q=b%2F42&cs=false", + vec![("Cookie".to_string(), "cs=true;".to_string())], + vec![] + )) + .expect("request should parse to a query"), + Query { + query: "b/42".to_string(), + cs: false, + }, + ); + } } |