Merge branch 'main' into dev

This commit is contained in:
Svilen Markov
2025-04-22 23:17:24 +01:00
8 changed files with 22 additions and 10 deletions

View File

@@ -997,6 +997,7 @@ Preview:
| search-engine | string | no | duckduckgo | | search-engine | string | no | duckduckgo |
| new-tab | boolean | no | false | | new-tab | boolean | no | false |
| autofocus | boolean | no | false | | autofocus | boolean | no | false |
| target | string | no | _blank |
| placeholder | string | no | Type here to search… | | placeholder | string | no | Type here to search… |
| bangs | array | no | | | bangs | array | no | |
@@ -1018,6 +1019,9 @@ When set to `true`, swaps the shortcuts for showing results in the same or new t
##### `autofocus` ##### `autofocus`
When set to `true`, automatically focuses the search input on page load. When set to `true`, automatically focuses the search input on page load.
##### `target`
The target to use when opening the search results in a new tab. Possible values are `_blank`, `_self`, `_parent` and `_top`.
##### `placeholder` ##### `placeholder`
When set, modifies the text displayed in the input field before typing. When set, modifies the text displayed in the input field before typing.

View File

@@ -378,6 +378,7 @@ The following helper functions provided by Glance are available:
- `offsetNow(offset string) time.Time`: Returns the current time with an offset. The offset can be positive or negative and must be in the format "3h" "-1h" or "2h30m10s". - `offsetNow(offset string) time.Time`: Returns the current time with an offset. The offset can be positive or negative and must be in the format "3h" "-1h" or "2h30m10s".
- `duration(str string) time.Duration`: Parses a string such as `1h`, `24h`, `5h30m`, etc into a `time.Duration`. - `duration(str string) time.Duration`: Parses a string such as `1h`, `24h`, `5h30m`, etc into a `time.Duration`.
- `parseTime(layout string, s string) time.Time`: Parses a string into time.Time. The layout must be provided in Go's [date format](https://pkg.go.dev/time#pkg-constants). You can alternatively use these values instead of the literal format: "unix", "RFC3339", "RFC3339Nano", "DateTime", "DateOnly". - `parseTime(layout string, s string) time.Time`: Parses a string into time.Time. The layout must be provided in Go's [date format](https://pkg.go.dev/time#pkg-constants). You can alternatively use these values instead of the literal format: "unix", "RFC3339", "RFC3339Nano", "DateTime", "DateOnly".
- `parseLocalTime(layout string, s string) time.Time`: Same as the above, except in the absence of a timezone, it will use the local timezone instead of UTC.
- `parseRelativeTime(layout string, s string) time.Time`: A shorthand for `{{ .String "date" | parseTime "rfc3339" | toRelativeTime }}`. - `parseRelativeTime(layout string, s string) time.Time`: A shorthand for `{{ .String "date" | parseTime "rfc3339" | toRelativeTime }}`.
- `add(a, b float) float`: Adds two numbers. - `add(a, b float) float`: Adds two numbers.
- `sub(a, b float) float`: Subtracts two numbers. - `sub(a, b float) float`: Subtracts two numbers.

View File

@@ -136,7 +136,7 @@ func cliMountpointInfo(requestedPath string) int {
fmt.Println("Path:", usage.Path) fmt.Println("Path:", usage.Path)
fmt.Println("FS type:", ternary(usage.Fstype == "", "unknown", usage.Fstype)) fmt.Println("FS type:", ternary(usage.Fstype == "", "unknown", usage.Fstype))
fmt.Printf("Used percent: %.1f%%", usage.UsedPercent) fmt.Printf("Used percent: %.1f%%\n", usage.UsedPercent)
return 0 return 0
} }

View File

@@ -104,6 +104,7 @@ function setupSearchBoxes() {
for (let i = 0; i < searchWidgets.length; i++) { for (let i = 0; i < searchWidgets.length; i++) {
const widget = searchWidgets[i]; const widget = searchWidgets[i];
const defaultSearchUrl = widget.dataset.defaultSearchUrl; const defaultSearchUrl = widget.dataset.defaultSearchUrl;
const target = widget.dataset.target || "_blank";
const newTab = widget.dataset.newTab === "true"; const newTab = widget.dataset.newTab === "true";
const inputElement = widget.getElementsByClassName("search-input")[0]; const inputElement = widget.getElementsByClassName("search-input")[0];
const bangElement = widget.getElementsByClassName("search-bang")[0]; const bangElement = widget.getElementsByClassName("search-bang")[0];
@@ -143,7 +144,7 @@ function setupSearchBoxes() {
const url = searchUrlTemplate.replace("!QUERY!", encodeURIComponent(query)); const url = searchUrlTemplate.replace("!QUERY!", encodeURIComponent(query));
if (newTab && !event.ctrlKey || !newTab && event.ctrlKey) { if (newTab && !event.ctrlKey || !newTab && event.ctrlKey) {
window.open(url, '_blank').focus(); window.open(url, target).focus();
} else { } else {
window.location.href = url; window.location.href = url;
} }

View File

@@ -3,7 +3,7 @@
{{ define "widget-content-classes" }}widget-content-frameless{{ end }} {{ define "widget-content-classes" }}widget-content-frameless{{ end }}
{{ define "widget-content" }} {{ define "widget-content" }}
<div class="search widget-content-frame padding-inline-widget flex gap-15 items-center" data-default-search-url="{{ .SearchEngine }}" data-new-tab="{{ .NewTab }}"> <div class="search widget-content-frame padding-inline-widget flex gap-15 items-center" data-default-search-url="{{ .SearchEngine }}" data-new-tab="{{ .NewTab }}" data-target="{{ .Target }}">
<div class="search-bangs"> <div class="search-bangs">
{{ range .Bangs }} {{ range .Bangs }}
<input type="hidden" data-shortcut="{{ .Shortcut }}" data-title="{{ .Title }}" data-url="{{ .URL }}"> <input type="hidden" data-shortcut="{{ .Shortcut }}" data-title="{{ .Title }}" data-url="{{ .URL }}">

View File

@@ -454,11 +454,16 @@ var customAPITemplateFuncs = func() template.FuncMap {
return d return d
}, },
"parseTime": customAPIFuncParseTime, "parseTime": func(layout, value string) time.Time {
return customAPIFuncParseTimeInLocation(layout, value, time.UTC)
},
"parseLocalTime": func(layout, value string) time.Time {
return customAPIFuncParseTimeInLocation(layout, value, time.Local)
},
"toRelativeTime": dynamicRelativeTimeAttrs, "toRelativeTime": dynamicRelativeTimeAttrs,
"parseRelativeTime": func(layout, value string) template.HTMLAttr { "parseRelativeTime": func(layout, value string) template.HTMLAttr {
// Shorthand to do both of the above with a single function call // Shorthand to do both of the above with a single function call
return dynamicRelativeTimeAttrs(customAPIFuncParseTime(layout, value)) return dynamicRelativeTimeAttrs(customAPIFuncParseTimeInLocation(layout, value, time.UTC))
}, },
// The reason we flip the parameter order is so that you can chain multiple calls together like this: // The reason we flip the parameter order is so that you can chain multiple calls together like this:
// {{ .JSON.String "foo" | trimPrefix "bar" | doSomethingElse }} // {{ .JSON.String "foo" | trimPrefix "bar" | doSomethingElse }}
@@ -532,8 +537,8 @@ var customAPITemplateFuncs = func() template.FuncMap {
}, },
"sortByTime": func(key, layout, order string, results []decoratedGJSONResult) []decoratedGJSONResult { "sortByTime": func(key, layout, order string, results []decoratedGJSONResult) []decoratedGJSONResult {
sort.Slice(results, func(a, b int) bool { sort.Slice(results, func(a, b int) bool {
timeA := customAPIFuncParseTime(layout, results[a].String(key)) timeA := customAPIFuncParseTimeInLocation(layout, results[a].String(key), time.UTC)
timeB := customAPIFuncParseTime(layout, results[b].String(key)) timeB := customAPIFuncParseTimeInLocation(layout, results[b].String(key), time.UTC)
if order == "asc" { if order == "asc" {
return timeA.Before(timeB) return timeA.Before(timeB)
@@ -570,7 +575,7 @@ var customAPITemplateFuncs = func() template.FuncMap {
return funcs return funcs
}() }()
func customAPIFuncParseTime(layout, value string) time.Time { func customAPIFuncParseTimeInLocation(layout, value string, loc *time.Location) time.Time {
switch strings.ToLower(layout) { switch strings.ToLower(layout) {
case "unix": case "unix":
asInt, err := strconv.ParseInt(value, 10, 64) asInt, err := strconv.ParseInt(value, 10, 64)
@@ -589,7 +594,7 @@ func customAPIFuncParseTime(layout, value string) time.Time {
layout = time.DateOnly layout = time.DateOnly
} }
parsed, err := time.Parse(layout, value) parsed, err := time.ParseInLocation(layout, value, loc)
if err != nil { if err != nil {
return time.Unix(0, 0) return time.Unix(0, 0)
} }

View File

@@ -194,7 +194,7 @@ func fetchSubredditPosts(
var client requestDoer = defaultHTTPClient var client requestDoer = defaultHTTPClient
if requestUrlTemplate != "" { if requestUrlTemplate != "" {
requestUrl = strings.ReplaceAll(requestUrlTemplate, "{REQUEST-URL}", requestUrl) requestUrl = strings.ReplaceAll(requestUrlTemplate, "{REQUEST-URL}", url.QueryEscape(requestUrl))
} else if proxyClient != nil { } else if proxyClient != nil {
client = proxyClient client = proxyClient
} }

View File

@@ -20,6 +20,7 @@ type searchWidget struct {
SearchEngine string `yaml:"search-engine"` SearchEngine string `yaml:"search-engine"`
Bangs []SearchBang `yaml:"bangs"` Bangs []SearchBang `yaml:"bangs"`
NewTab bool `yaml:"new-tab"` NewTab bool `yaml:"new-tab"`
Target string `yaml:"target"`
Autofocus bool `yaml:"autofocus"` Autofocus bool `yaml:"autofocus"`
Placeholder string `yaml:"placeholder"` Placeholder string `yaml:"placeholder"`
} }