1
0
mirror of https://github.com/makew0rld/amfora.git synced 2024-06-21 19:35:23 +00:00

🔀 Merge branch 'master' into feeds

This commit is contained in:
makeworld 2020-09-01 22:26:34 -04:00
commit 0f5458c730
19 changed files with 326 additions and 80 deletions

26
.github/workflows/goreleaser.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: goreleaser
on:
push:
tags:
- v*
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.15
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
version: 0.x
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

3
.gitignore vendored
View File

@ -1,7 +1,8 @@
# Binaries
amfora
amfora-*
build/
build
dist
# Recording
rec.yml

View File

@ -41,3 +41,6 @@ linters-settings:
gocritic:
disabled-checks:
- ifElseChain
goconst:
# minimal length of string constant, 3 by default
min-len: 5

59
.goreleaser.yml Normal file
View File

@ -0,0 +1,59 @@
project_name: amfora
env:
- GO111MODULE=on
before:
hooks:
- go mod download
- go generate ./...
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
- freebsd
- netbsd
- openbsd
goarch:
- 386
- amd64
- arm64
- arm
goarm:
- 6
- 7
ignore:
- goos: darwin
goarch: 386
- goos: freebsd
goarch: arm
- goos: freebsd
goarch: arm64
- goos: netbsd
goarch: arm
- goos: netbsd
goarch: arm64
- goos: openbsd
goarch: arm
- goos: openbsd
goarch: arm64
archives:
- format: binary
replacements:
darwin: macOS
386: 32-bit
amd64: 64-bit
milestones:
- close: true
changelog:
skip: true

View File

@ -4,25 +4,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [v1.5.0] - 2020-09-01
### Added
- **Proxy support** - see the `[proxies]` section in the config (#66, #80)
- **Emoji favicons** can now be seen if `emoji_favicons` is enabled in the config (#62)
- **Proxy support** - specify a proxy in the config for all requests to go through it (#66)
- The `shift_numbers` key in the config was added, so that non US keyboard users can navigate tabs (#64)
- `shift_numbers` key in the config was added, so that non US keyboard users can navigate tabs (#64)
- <kbd>F1</kbd> and <kbd>F2</kbd> keys for navigating to the previous and next tabs (#64)
- Resolving any relative path (starting with a `.`) in the bottom bar is supported, not just `..` (#71)
- Set programs in config to open other schemes like `gopher://` or `magnet:` (#74)
- Resolving any relative path (starts with a `.`) in the bottom bar is supported, not just `..` (#71)
- You can now set external programs in the config to open other schemes, like `gopher://` or `magnet:` (#74)
- Auto-redirecting can be enabled - redirect within Gemini up to 5 times automatically (#75)
- Help page now documents paging keys (#78)
- The new tab page can be customized by creating a gemtext file called `newtab.gmi` in the config directory (#67, #83)
### Changed
- Update to [go-gemini](https://github.com/makeworld-the-better-one/go-gemini) v0.8.4
### Fixed
- Two digit (and higher) link texts are now in line with one digit ones (#60)
- Race condition when reloading pages, could have caused the cache to still be used
- Race condition when reloading pages that could have caused the cache to still be used
- Prevent panic (crash) when the server sends an error with an empty meta string (#73)
- URLs with with colon-only schemes (like `mailto:`) are properly recognized
- You can no longer navigate through the history when the help page is open (#55, #78)
## [1.4.0] - 2020-07-28

View File

@ -61,12 +61,14 @@ This section is for programmers who want to install from source. Make sure you'r
Install latest release:
```
GO111MODULE=on go get github.com/makeworld-the-better-one/amfora
go env -w GO111MODULE=on
go get github.com/makeworld-the-better-one/amfora
```
Install latest commit:
```
GO111MODULE=on go get github.com/makeworld-the-better-one/amfora@master
go env -w GO111MODULE=on
go get github.com/makeworld-the-better-one/amfora@master
```
## Usage
@ -95,15 +97,14 @@ Features in *italics* are in the master branch, but not in the latest release.
- [x] Bookmarks
- [x] Download pages and arbitrary data
- [x] Theming
- [x] *Emoji favicons*
- [x] Emoji favicons
- See `gemini://mozz.us/files/rfc_gemini_favicon.gmi` for details
- [x] *Proxying*
- All requests can optionally be sent through another server
- A gemini proxy server implementation currently does not exist, but Amfora will support it when it does!
- Disabled by default, enable in config
- [x] Proxying
- Schemes like Gopher or HTTP can be proxied through a Gemini server
- [x] *Subscribe to RSS and Atom feeds and display them*
- Subscribing to page changes, similar to how Spacewalk works, is also supported
- [ ] Support Markdown rendering
- [ ] Search in pages with <kbd>Ctrl-F</kbd>
- Subscribing to page changes, similar to how Spacewalk works, will also be supported
- [ ] Stream support
- [ ] Full client certificate UX within the client
- Create transient and permanent certs within the client, per domain
- Manage and browse them
@ -118,6 +119,14 @@ The config file is written in the intuitive [TOML](https://github.com/toml-lang/
On Windows, the file is in `%APPDATA%\amfora\config.toml`, which usually expands to `C:\Users\<username>\AppData\Roaming\amfora\config.toml`.
## Known Bugs
- Pasting on Windows is truncated, the full paste content won't be added. ([#43](https://github.com/makeworld-the-better-one/amfora/issues/43))
- ANSI codes aren't displaying properly ([#59](https://github.com/makeworld-the-better-one/amfora/issues/59))
You can also check out [all the issues with the bug label](https://github.com/makeworld-the-better-one/amfora/issues?q=is%3Aopen+is%3Aissue+label%3Abug).
## Libraries
Amfora ❤️ open source!

View File

@ -9,7 +9,11 @@ import (
"github.com/makeworld-the-better-one/amfora/feeds"
)
var version = "1.5.0-unreleased"
var (
version = "1.5.0"
commit = "unknown"
builtBy = "unknown"
)
func main() {
// err := logger.Init()
@ -19,7 +23,9 @@ func main() {
if len(os.Args) > 1 {
if os.Args[1] == "--version" || os.Args[1] == "-v" {
fmt.Println("amfora v" + version)
fmt.Println("Amfora", version)
fmt.Println("Commit:", commit)
fmt.Println("Built by:", builtBy)
return
}
if os.Args[1] == "--help" || os.Args[1] == "-h" {

View File

@ -2,31 +2,43 @@
package client
import (
"net"
"net/url"
"github.com/makeworld-the-better-one/go-gemini"
"github.com/spf13/viper"
)
// Fetch returns response data and an error.
// The error text is human friendly and should be displayed.
func Fetch(u string) (*gemini.Response, error) {
var res *gemini.Response
var err error
if viper.GetString("a-general.proxy") == "" {
res, err = gemini.Fetch(u)
} else {
res, err = gemini.FetchWithHost(viper.GetString("a-general.proxy"), u)
}
res, err := gemini.Fetch(u)
if err != nil {
return nil, err
}
parsed, _ := url.Parse(u)
ok := handleTofu(parsed.Hostname(), parsed.Port(), res.Cert)
if !ok {
return res, ErrTofu
}
return res, err
}
// FetchWithProxy is the same as Fetch, but uses a proxy.
func FetchWithProxy(proxyHostname, proxyPort, u string) (*gemini.Response, error) {
res, err := gemini.FetchWithHost(net.JoinHostPort(proxyHostname, proxyPort), u)
if err != nil {
return nil, err
}
// Only associate the returned cert with the proxy
ok := handleTofu(proxyHostname, proxyPort, res.Cert)
if !ok {
return res, ErrTofu
}
return res, nil
}

View File

@ -22,6 +22,9 @@ var amforaAppData string // Where amfora files are stored on Windows - cached he
var configDir string
var configPath string
var NewTabPath string
var CustomNewTab bool
var TofuStore = viper.New()
var tofuDBDir string
var tofuDBPath string
@ -74,6 +77,13 @@ func Init() error {
}
configPath = filepath.Join(configDir, "config.toml")
// Search for a custom new tab
NewTabPath = filepath.Join(configDir, "newtab.gmi")
CustomNewTab = false
if _, err := os.Stat(NewTabPath); err == nil {
CustomNewTab = true
}
// Store TOFU db directory and file paths
if runtime.GOOS == "windows" {
// Windows just stores it in APPDATA along with other stuff

View File

@ -21,8 +21,8 @@ home = "gemini://gemini.circumlunar.space"
# If set to false, a prompt will be shown before following redirects.
auto_redirect = false
# What command to run to open a HTTP URL. Set to "default" to try to guess the browser,
# or set to "off" to not open HTTP URLs.
# What command to run to open a HTTP(S) URL. Set to "default" to try to guess the browser,
# or set to "off" to not open HTTP(S) URLs.
# If a command is set, than the URL will be added (in quotes) to the end of the command.
# A space will be prepended if necessary.
http = "default"
@ -55,12 +55,6 @@ page_max_time = 10
# Whether to replace tab numbers with emoji favicons, which are cached.
emoji_favicons = false
# Proxy server, through which all requests would be sent.
# String should be a host: a domain/IP with an optional port. Port 1965 is assumed otherwise.
# The proxy server needs to be a Gemini server that supports proxying.
# By default it is empty, which disables the proxy.
proxy = ""
[keybindings]
# In the future there will be more settings here.
@ -74,10 +68,13 @@ shift_numbers = "!@#$%^&*()"
# Allows setting the commands to run for various URL schemes.
# E.g. to open FTP URLs with FileZilla set the following key:
# ftp = "filezilla"
# You can set any scheme to "off" to disable handling it.
# You can set any scheme to "off" or "" to disable handling it, or
# just leave the key unset.
#
# DO NOT use this for setting the HTTP command.
# Use the http setting in the "a-general" section above
# Use the http setting in the "a-general" section above.
#
# NOTE: These settings are override by the ones in the proxies section.
# This is a special key that defines the handler for all URL schemes for which
# no handler is defined.
@ -93,6 +90,20 @@ max_size = 0 # Size in bytes
max_pages = 30 # The maximum number of pages the cache will store
[proxies]
# Allows setting a Gemini proxy for different schemes.
# The settings are similar to the url-handlers section above.
# E.g. to open a gopher page by connecting to a Gemini proxy server:
# gopher = "example.com:123"
#
# Port 1965 is assumed if no port is specified.
#
# NOTE: These settings override any external handlers specified in
# the url-handlers section.
#
# Note that HTTP and HTTPS are treated as separate protocols here.
[theme]
# This section is for changing the COLORS used in Amfora.
# These colors only apply if 'color' is enabled above.

View File

@ -18,8 +18,8 @@ home = "gemini://gemini.circumlunar.space"
# If set to false, a prompt will be shown before following redirects.
auto_redirect = false
# What command to run to open a HTTP URL. Set to "default" to try to guess the browser,
# or set to "off" to not open HTTP URLs.
# What command to run to open a HTTP(S) URL. Set to "default" to try to guess the browser,
# or set to "off" to not open HTTP(S) URLs.
# If a command is set, than the URL will be added (in quotes) to the end of the command.
# A space will be prepended if necessary.
http = "default"
@ -52,12 +52,6 @@ page_max_time = 10
# Whether to replace tab numbers with emoji favicons, which are cached.
emoji_favicons = false
# Proxy server, through which all requests would be sent.
# String should be a host: a domain/IP with an optional port. Port 1965 is assumed otherwise.
# The proxy server needs to be a Gemini server that supports proxying.
# By default it is empty, which disables the proxy.
proxy = ""
[keybindings]
# In the future there will be more settings here.
@ -71,10 +65,13 @@ shift_numbers = "!@#$%^&*()"
# Allows setting the commands to run for various URL schemes.
# E.g. to open FTP URLs with FileZilla set the following key:
# ftp = "filezilla"
# You can set any scheme to "off" to disable handling it.
# You can set any scheme to "off" or "" to disable handling it, or
# just leave the key unset.
#
# DO NOT use this for setting the HTTP command.
# Use the http setting in the "a-general" section above
# Use the http setting in the "a-general" section above.
#
# NOTE: These settings are override by the ones in the proxies section.
# This is a special key that defines the handler for all URL schemes for which
# no handler is defined.
@ -90,6 +87,20 @@ max_size = 0 # Size in bytes
max_pages = 30 # The maximum number of pages the cache will store
[proxies]
# Allows setting a Gemini proxy for different schemes.
# The settings are similar to the url-handlers section above.
# E.g. to open a gopher page by connecting to a Gemini proxy server:
# gopher = "example.com:123"
#
# Port 1965 is assumed if no port is specified.
#
# NOTE: These settings override any external handlers specified in
# the url-handlers section.
#
# Note that HTTP and HTTPS are treated as separate protocols here.
[theme]
# This section is for changing the COLORS used in Amfora.
# These colors only apply if 'color' is enabled above.

View File

@ -116,7 +116,7 @@ func Bookmarks(t *tab) {
bkmkPageRaw += fmt.Sprintf("=> %s %s\r\n", keys[i], m[keys[i]])
}
// Render and display
content, links := renderer.RenderGemini(bkmkPageRaw, textWidth(), leftMargin())
content, links := renderer.RenderGemini(bkmkPageRaw, textWidth(), leftMargin(), false)
page := structs.Page{
Raw: bkmkPageRaw,
Content: content,

View File

@ -51,8 +51,6 @@ var tabRow = cview.NewTextView().
var layout = cview.NewFlex().
SetDirection(cview.FlexRow)
var renderedNewTabContent string
var newTabLinks []string
var newTabPage structs.Page
var App = cview.NewApplication().
@ -202,7 +200,8 @@ func Init() {
})
// Render the default new tab content ONCE and store it for later
renderedNewTabContent, newTabLinks = renderer.RenderGemini(newTabContent, textWidth(), leftMargin())
newTabContent := getNewTabContent()
renderedNewTabContent, newTabLinks := renderer.RenderGemini(newTabContent, textWidth(), leftMargin(), false)
newTabPage = structs.Page{
Raw: newTabContent,
Content: renderedNewTabContent,
@ -232,6 +231,11 @@ func Init() {
// It's focused on a modal right now, nothing should interrupt
return event
}
_, ok = App.GetFocus().(*cview.Table)
if ok {
// It's focused on help right now
return event
}
if tabs[curTab].mode == tabModeDone {
// All the keys and operations that can only work while NOT loading
@ -514,6 +518,24 @@ func SwitchTab(tab int) {
}
func Reload() {
if tabs[curTab].page.URL == "about:newtab" && config.CustomNewTab {
// Re-render new tab, similar to Init()
newTabContent := getNewTabContent()
tmpTermW := termW
renderedNewTabContent, newTabLinks := renderer.RenderGemini(newTabContent, textWidth(), leftMargin(), false)
newTabPage = structs.Page{
Raw: newTabContent,
Content: renderedNewTabContent,
Links: newTabLinks,
URL: "about:newtab",
Width: tmpTermW,
Mediatype: structs.TextGemini,
}
temp := newTabPage // Copy
setPage(tabs[curTab], &temp)
return
}
if !tabs[curTab].hasContent() {
return
}

View File

@ -54,7 +54,7 @@ func Feeds(t *tab) {
feedPageRaw += fmt.Sprintf("=>%s %s - %s\n", entry.URL, entry.Author, entry.Title)
}
content, links := renderer.RenderGemini(feedPageRaw, textWidth(), leftMargin())
content, links := renderer.RenderGemini(feedPageRaw, textWidth(), leftMargin(), false)
page := structs.Page{
Raw: feedPageRaw,
Content: content,

View File

@ -12,12 +12,14 @@ var helpCells = strings.TrimSpace(`
?|Bring up this help. You can scroll!
Esc|Leave the help
Arrow keys, h/j/k/l|Scroll and move a page.
PgUp, u|Go up a page in document
PgDn, d|Go down a page in document
g|Go to top of document
G|Go to bottom of document
Tab|Navigate to the next item in a popup.
Shift-Tab|Navigate to the previous item in a popup.
b, Alt-Left|Go back in the history
f, Alt-Right|Go forward in the history
g|Go to top of document
G|Go to bottom of document
spacebar|Open bar at the bottom - type a URL, link number, search term.
|You can also type two dots (..) to go up a directory in the URL.
|Typing new:N will open link number N in a new tab
@ -60,7 +62,7 @@ func Help() {
func helpInit() {
// Populate help table
helpTable.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyEsc {
if key == tcell.KeyEsc || key == tcell.KeyEnter {
tabPages.SwitchToPage(strconv.Itoa(curTab))
App.SetFocus(tabs[curTab].view)
App.Draw()

View File

@ -1,12 +1,20 @@
//nolint
package display
var newTabContent = `# New Tab
import (
"io/ioutil"
"github.com/makeworld-the-better-one/amfora/config"
)
//nolint
var defaultNewTabContent = `# New Tab
You've opened a new tab. Use the bar at the bottom to browse around. You can start typing in it by pressing the space key.
Press the ? key at any time to bring up the help, and see other keybindings. Most are what you expect.
You can customize this page by creating a gemtext file called newtab.gmi, in Amfora's configuration folder.
Happy browsing!
=> about:bookmarks Bookmarks
@ -14,3 +22,12 @@ Happy browsing!
=> //gemini.circumlunar.space Project Gemini
=> https://github.com/makeworld-the-better-one/amfora Amfora homepage [HTTPS]
`
// Read the new tab content from a file if it exists or fallback to a default page.
func getNewTabContent() string {
data, err := ioutil.ReadFile(config.NewTabPath)
if err == nil {
return string(data)
}
return defaultNewTabContent
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/url"
"os/exec"
"strconv"
@ -77,7 +78,11 @@ func reformatPage(p *structs.Page) {
switch p.Mediatype {
case structs.TextGemini:
// Links are not recorded because they won't change
rendered, _ = renderer.RenderGemini(p.Raw, textWidth(), leftMargin())
proxied := true
if strings.HasPrefix(p.URL, "gemini") || strings.HasPrefix(p.URL, "about") {
proxied = false
}
rendered, _ = renderer.RenderGemini(p.Raw, textWidth(), leftMargin(), proxied)
case structs.TextPlain:
rendered = renderer.RenderPlainText(p.Raw, leftMargin())
case structs.TextAnsi:
@ -167,6 +172,7 @@ func handleHTTP(u string, showInfo bool) {
func handleOther(u string) {
// The URL should have a scheme due to a previous call to normalizeURL
parsed, _ := url.Parse(u)
// Search for a handler for the URL scheme
handler := strings.TrimSpace(viper.GetString("url-handlers." + parsed.Scheme))
if len(handler) == 0 {
@ -330,15 +336,36 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
return ret("", false)
}
proxy := strings.TrimSpace(viper.GetString("proxies." + parsed.Scheme))
usingProxy := false
proxyHostname, proxyPort, err := net.SplitHostPort(proxy)
if err != nil {
// Error likely means there's no port in the host
proxyHostname = proxy
proxyPort = "1965"
}
if strings.HasPrefix(u, "http") {
handleHTTP(u, true)
return ret("", false)
if proxy == "" || proxy == "off" {
// No proxy available
handleHTTP(u, true)
return ret("", false)
}
usingProxy = true
}
if !strings.HasPrefix(u, "gemini") {
handleOther(u)
return ret("", false)
if !strings.HasPrefix(u, "http") && !strings.HasPrefix(u, "gemini") {
// Not a Gemini URL
if proxy == "" || proxy == "off" {
// No proxy available
handleOther(u)
return ret("", false)
}
usingProxy = true
}
// Gemini URL
// Gemini URL, or one with a Gemini proxy available
// Load page from cache if possible
page, ok := cache.GetPage(u)
@ -352,7 +379,12 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
t.mode = tabModeLoading
App.Draw()
res, err := client.Fetch(u)
var res *gemini.Response
if usingProxy {
res, err = client.FetchWithProxy(proxyHostname, proxyPort, u)
} else {
res, err = client.Fetch(u)
}
// Loading may have taken a while, make sure tab is still valid
if !isValidTab(t) {
@ -360,20 +392,32 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
}
if errors.Is(err, client.ErrTofu) {
if Tofu(parsed.Host, client.GetExpiry(parsed.Hostname(), parsed.Port())) {
// They want to continue anyway
client.ResetTofuEntry(parsed.Hostname(), parsed.Port(), res.Cert)
// Response can be used further down, no need to reload
if usingProxy {
// They are using a proxy
if Tofu(proxy, client.GetExpiry(proxyHostname, proxyPort)) {
// They want to continue anyway
client.ResetTofuEntry(proxyHostname, proxyPort, res.Cert)
// Response can be used further down, no need to reload
} else {
// They don't want to continue
return ret("", false)
}
} else {
// They don't want to continue
return ret("", false)
if Tofu(parsed.Host, client.GetExpiry(parsed.Hostname(), parsed.Port())) {
// They want to continue anyway
client.ResetTofuEntry(parsed.Hostname(), parsed.Port(), res.Cert)
// Response can be used further down, no need to reload
} else {
// They don't want to continue
return ret("", false)
}
}
} else if err != nil {
Error("URL Fetch Error", err.Error())
return ret("", false)
}
if renderer.CanDisplay(res) {
page, err := renderer.MakePage(u, res, textWidth(), leftMargin())
page, err := renderer.MakePage(u, res, textWidth(), leftMargin(), usingProxy)
// Rendering may have taken a while, make sure tab is still valid
if !isValidTab(t) {
return ret("", false)

View File

@ -57,7 +57,7 @@ func CanDisplay(res *gemini.Response) bool {
// MakePage creates a formatted, rendered Page from the given network response and params.
// You must set the Page.Width value yourself.
func MakePage(url string, res *gemini.Response, width, leftMargin int) (*structs.Page, error) {
func MakePage(url string, res *gemini.Response, width, leftMargin int, proxied bool) (*structs.Page, error) {
if !CanDisplay(res) {
return nil, ErrCantDisplay
}
@ -102,7 +102,7 @@ func MakePage(url string, res *gemini.Response, width, leftMargin int) (*structs
}
if mediatype == "text/gemini" {
rendered, links := RenderGemini(utfText, width, leftMargin)
rendered, links := RenderGemini(utfText, width, leftMargin, proxied)
return &structs.Page{
Mediatype: structs.TextGemini,
URL: url,

View File

@ -87,13 +87,17 @@ func tagLines(s, start, end string) string {
// convertRegularGemini converts non-preformatted blocks of text/gemini
// into a cview-compatible format.
// Since this only works on non-preformatted blocks, RenderGemini
// should always be used instead.
//
// It also returns a slice of link URLs.
// numLinks is the number of links that exist so far.
// width is the number of columns to wrap to.
//
// Since this only works on non-preformatted blocks, RenderGemini
// should always be used instead.
func convertRegularGemini(s string, numLinks, width int) (string, []string) {
//
// proxied is whether the request is through the gemini:// scheme.
// If it's not a gemini:// page, set this to true.
func convertRegularGemini(s string, numLinks, width int, proxied bool) (string, []string) {
links := make([]string, 0)
lines := strings.Split(s, "\n")
wrappedLines := make([]string, 0) // Final result
@ -175,7 +179,8 @@ func convertRegularGemini(s string, numLinks, width int) (string, []string) {
if viper.GetBool("a-general.color") {
pU, err := urlPkg.Parse(url)
if err == nil && (pU.Scheme == "" || pU.Scheme == "gemini" || pU.Scheme == "about") {
if !proxied && err == nil &&
(pU.Scheme == "" || pU.Scheme == "gemini" || pU.Scheme == "about") {
// A gemini link
// Add the link text in blue (in a region), and a gray link number to the left of it
// Those are the default colors, anyway
@ -267,7 +272,10 @@ func convertRegularGemini(s string, numLinks, width int) (string, []string) {
//
// width is the number of columns to wrap to.
// leftMargin is the number of blank spaces to prepend to each line.
func RenderGemini(s string, width, leftMargin int) (string, []string) {
//
// proxied is whether the request is through the gemini:// scheme.
// If it's not a gemini:// page, set this to true.
func RenderGemini(s string, width, leftMargin int, proxied bool) (string, []string) {
s = cview.Escape(s)
if viper.GetBool("a-general.color") {
s = cview.TranslateANSI(s)
@ -292,7 +300,7 @@ func RenderGemini(s string, width, leftMargin int) (string, []string) {
)
} else {
// Not preformatted, regular text
ren, lks := convertRegularGemini(buf, len(links), width)
ren, lks := convertRegularGemini(buf, len(links), width, proxied)
links = append(links, lks...)
rendered += ren
}
@ -310,7 +318,7 @@ func RenderGemini(s string, width, leftMargin int) (string, []string) {
} else {
// Not preformatted, regular text
// Same code as in the loop above
ren, lks := convertRegularGemini(buf, len(links), width)
ren, lks := convertRegularGemini(buf, len(links), width, proxied)
links = append(links, lks...)
rendered += ren
}