-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR aimed to promote the use of a `p/` library for managing special help links from contracts. It also provided an opportunity for me to realize that our discussion about changing the `$` symbol would require some parsing and detection from the `gnoweb` perspective. If we want a simple library like this one, the goal should be to ideally craft a link to the current package without specifying the realm path. Relative URLs worked well with `?`, but they won't function with `$`. As an alternative, we can have this package look for `std.PrevRealm().PkgAddr` if it is not specified. cc @jeronimoalbi @thehowl @leohhhn Related with #2602 Related with #2876 --------- Signed-off-by: moul <[email protected]> Co-authored-by: Leon Hudak <[email protected]>
- Loading branch information
Showing
24 changed files
with
327 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module gno.land/p/moul/helplink | ||
|
||
require ( | ||
gno.land/p/demo/urequire v0.0.0-latest | ||
gno.land/p/moul/txlink v0.0.0-latest | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Package helplink provides utilities for creating help page links compatible | ||
// with Gnoweb, Gnobro, and other clients that support the Gno contracts' | ||
// flavored Markdown format. | ||
// | ||
// This package simplifies the generation of dynamic, context-sensitive help | ||
// links, enabling users to navigate relevant documentation seamlessly within | ||
// the Gno ecosystem. | ||
// | ||
// For a more lightweight alternative, consider using p/moul/txlink. | ||
// | ||
// The primary functions — Func, FuncURL, and Home — are intended for use with | ||
// the "relative realm". When specifying a custom Realm, you can create links | ||
// that utilize either the current realm path or a fully qualified path to | ||
// another realm. | ||
package helplink | ||
|
||
import ( | ||
"strings" | ||
|
||
"gno.land/p/moul/txlink" | ||
) | ||
|
||
const chainDomain = "gno.land" // XXX: std.ChainDomain (#2911) | ||
|
||
// Func returns a markdown link for the specific function with optional | ||
// key-value arguments, for the current realm. | ||
func Func(title string, fn string, args ...string) string { | ||
return Realm("").Func(title, fn, args...) | ||
} | ||
|
||
// FuncURL returns a URL for the specified function with optional key-value | ||
// arguments, for the current realm. | ||
func FuncURL(fn string, args ...string) string { | ||
return Realm("").FuncURL(fn, args...) | ||
} | ||
|
||
// Home returns the URL for the help homepage of the current realm. | ||
func Home() string { | ||
return Realm("").Home() | ||
} | ||
|
||
// Realm represents a specific realm for generating help links. | ||
type Realm string | ||
|
||
// prefix returns the URL prefix for the realm. | ||
func (r Realm) prefix() string { | ||
// relative | ||
if r == "" { | ||
return "" | ||
} | ||
|
||
// local realm -> /realm | ||
realm := string(r) | ||
if strings.Contains(realm, chainDomain) { | ||
return strings.TrimPrefix(realm, chainDomain) | ||
} | ||
|
||
// remote realm -> https://remote.land/realm | ||
return "https://" + string(r) | ||
} | ||
|
||
// Func returns a markdown link for the specified function with optional | ||
// key-value arguments. | ||
func (r Realm) Func(title string, fn string, args ...string) string { | ||
// XXX: escape title | ||
return "[" + title + "](" + r.FuncURL(fn, args...) + ")" | ||
} | ||
|
||
// FuncURL returns a URL for the specified function with optional key-value | ||
// arguments. | ||
func (r Realm) FuncURL(fn string, args ...string) string { | ||
tlr := txlink.Realm(r) | ||
return tlr.URL(fn, args...) | ||
} | ||
|
||
// Home returns the base help URL for the specified realm. | ||
func (r Realm) Home() string { | ||
return r.prefix() + "?help" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package helplink | ||
|
||
import ( | ||
"testing" | ||
|
||
"gno.land/p/demo/urequire" | ||
) | ||
|
||
func TestFunc(t *testing.T) { | ||
tests := []struct { | ||
title string | ||
fn string | ||
args []string | ||
want string | ||
realm Realm | ||
}{ | ||
{"Example", "foo", []string{"bar", "1", "baz", "2"}, "[Example](?help&__func=foo&bar=1&baz=2)", ""}, | ||
{"Realm Example", "foo", []string{"bar", "1", "baz", "2"}, "[Realm Example](/r/lorem/ipsum?help&__func=foo&bar=1&baz=2)", "gno.land/r/lorem/ipsum"}, | ||
{"Single Arg", "testFunc", []string{"key", "value"}, "[Single Arg](?help&__func=testFunc&key=value)", ""}, | ||
{"No Args", "noArgsFunc", []string{}, "[No Args](?help&__func=noArgsFunc)", ""}, | ||
{"Odd Args", "oddArgsFunc", []string{"key"}, "[Odd Args](?help&__func=oddArgsFunc)", ""}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.title, func(t *testing.T) { | ||
got := tt.realm.Func(tt.title, tt.fn, tt.args...) | ||
urequire.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} | ||
|
||
func TestFuncURL(t *testing.T) { | ||
tests := []struct { | ||
fn string | ||
args []string | ||
want string | ||
realm Realm | ||
}{ | ||
{"foo", []string{"bar", "1", "baz", "2"}, "?help&__func=foo&bar=1&baz=2", ""}, | ||
{"testFunc", []string{"key", "value"}, "?help&__func=testFunc&key=value", ""}, | ||
{"noArgsFunc", []string{}, "?help&__func=noArgsFunc", ""}, | ||
{"oddArgsFunc", []string{"key"}, "?help&__func=oddArgsFunc", ""}, | ||
{"foo", []string{"bar", "1", "baz", "2"}, "/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.land/r/lorem/ipsum"}, | ||
{"testFunc", []string{"key", "value"}, "/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.land/r/lorem/ipsum"}, | ||
{"noArgsFunc", []string{}, "/r/lorem/ipsum?help&__func=noArgsFunc", "gno.land/r/lorem/ipsum"}, | ||
{"oddArgsFunc", []string{"key"}, "/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.land/r/lorem/ipsum"}, | ||
{"foo", []string{"bar", "1", "baz", "2"}, "https://gno.world/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.world/r/lorem/ipsum"}, | ||
{"testFunc", []string{"key", "value"}, "https://gno.world/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.world/r/lorem/ipsum"}, | ||
{"noArgsFunc", []string{}, "https://gno.world/r/lorem/ipsum?help&__func=noArgsFunc", "gno.world/r/lorem/ipsum"}, | ||
{"oddArgsFunc", []string{"key"}, "https://gno.world/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.world/r/lorem/ipsum"}, | ||
} | ||
|
||
for _, tt := range tests { | ||
title := tt.fn | ||
t.Run(title, func(t *testing.T) { | ||
got := tt.realm.FuncURL(tt.fn, tt.args...) | ||
urequire.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} | ||
|
||
func TestHome(t *testing.T) { | ||
tests := []struct { | ||
realm Realm | ||
want string | ||
}{ | ||
{"", "?help"}, | ||
{"gno.land/r/lorem/ipsum", "/r/lorem/ipsum?help"}, | ||
{"gno.world/r/lorem/ipsum", "https://gno.world/r/lorem/ipsum?help"}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(string(tt.realm), func(t *testing.T) { | ||
got := tt.realm.Home() | ||
urequire.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module gno.land/p/moul/txlink | ||
|
||
require gno.land/p/demo/urequire v0.0.0-latest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Package txlink provides utilities for creating transaction-related links | ||
// compatible with Gnoweb, Gnobro, and other clients within the Gno ecosystem. | ||
// | ||
// This package is optimized for generating lightweight transaction links with | ||
// flexible arguments, allowing users to build dynamic links that integrate | ||
// seamlessly with various Gno clients. | ||
// | ||
// The primary function, URL, is designed to produce markdown links for | ||
// transaction functions in the current "relative realm". By specifying a custom | ||
// Realm, you can generate links that either use the current realm path or a | ||
// fully qualified path for another realm. | ||
// | ||
// This package is a streamlined alternative to helplink, providing similar | ||
// functionality for transaction links without the full feature set of helplink. | ||
package txlink | ||
|
||
import ( | ||
"std" | ||
"strings" | ||
) | ||
|
||
const chainDomain = "gno.land" // XXX: std.ChainDomain (#2911) | ||
|
||
// URL returns a URL for the specified function with optional key-value | ||
// arguments, for the current realm. | ||
func URL(fn string, args ...string) string { | ||
return Realm("").URL(fn, args...) | ||
} | ||
|
||
// Realm represents a specific realm for generating tx links. | ||
type Realm string | ||
|
||
// prefix returns the URL prefix for the realm. | ||
func (r Realm) prefix() string { | ||
// relative | ||
if r == "" { | ||
curPath := std.CurrentRealm().PkgPath() | ||
return strings.TrimPrefix(curPath, chainDomain) | ||
} | ||
|
||
// local realm -> /realm | ||
realm := string(r) | ||
if strings.Contains(realm, chainDomain) { | ||
return strings.TrimPrefix(realm, chainDomain) | ||
} | ||
|
||
// remote realm -> https://remote.land/realm | ||
return "https://" + string(r) | ||
} | ||
|
||
// URL returns a URL for the specified function with optional key-value | ||
// arguments. | ||
func (r Realm) URL(fn string, args ...string) string { | ||
// Start with the base query | ||
url := r.prefix() + "?help&__func=" + fn | ||
|
||
// Check if args length is even | ||
if len(args)%2 != 0 { | ||
// If not even, we can choose to handle the error here. | ||
// For example, we can just return the URL without appending | ||
// more args. | ||
return url | ||
} | ||
|
||
// Append key-value pairs to the URL | ||
for i := 0; i < len(args); i += 2 { | ||
key := args[i] | ||
value := args[i+1] | ||
// XXX: escape keys and args | ||
url += "&" + key + "=" + value | ||
} | ||
|
||
return url | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package txlink | ||
|
||
import ( | ||
"testing" | ||
|
||
"gno.land/p/demo/urequire" | ||
) | ||
|
||
func TestURL(t *testing.T) { | ||
tests := []struct { | ||
fn string | ||
args []string | ||
want string | ||
realm Realm | ||
}{ | ||
{"foo", []string{"bar", "1", "baz", "2"}, "?help&__func=foo&bar=1&baz=2", ""}, | ||
{"testFunc", []string{"key", "value"}, "?help&__func=testFunc&key=value", ""}, | ||
{"noArgsFunc", []string{}, "?help&__func=noArgsFunc", ""}, | ||
{"oddArgsFunc", []string{"key"}, "?help&__func=oddArgsFunc", ""}, | ||
{"foo", []string{"bar", "1", "baz", "2"}, "/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.land/r/lorem/ipsum"}, | ||
{"testFunc", []string{"key", "value"}, "/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.land/r/lorem/ipsum"}, | ||
{"noArgsFunc", []string{}, "/r/lorem/ipsum?help&__func=noArgsFunc", "gno.land/r/lorem/ipsum"}, | ||
{"oddArgsFunc", []string{"key"}, "/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.land/r/lorem/ipsum"}, | ||
{"foo", []string{"bar", "1", "baz", "2"}, "https://gno.world/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.world/r/lorem/ipsum"}, | ||
{"testFunc", []string{"key", "value"}, "https://gno.world/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.world/r/lorem/ipsum"}, | ||
{"noArgsFunc", []string{}, "https://gno.world/r/lorem/ipsum?help&__func=noArgsFunc", "gno.world/r/lorem/ipsum"}, | ||
{"oddArgsFunc", []string{"key"}, "https://gno.world/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.world/r/lorem/ipsum"}, | ||
} | ||
|
||
for _, tt := range tests { | ||
title := tt.fn | ||
t.Run(title, func(t *testing.T) { | ||
got := tt.realm.URL(tt.fn, tt.args...) | ||
urequire.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.