PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/moul/x/wiki/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / x / wiki
Files
18 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/x/wiki/v0
gno
0.9

Files (18)

  • README.mdmarkdown
  • gnomod.tomltoml
  • diff.gnogno
  • doc.gnogno
  • links.gnogno
  • page.gnogno
  • render.gnogno
  • revision.gnogno
  • talk.gnogno
  • title.gnogno
  • wiki.gnogno
  • diff_test.gnogno
  • limits_test.gnogno
  • links_test.gnogno
  • render_test.gnogno
  • talk_test.gnogno
  • title_test.gnogno
  • wiki_test.gnogno
  • links_test.gnogno
    1package wiki23import (4	"testing"56	"gno.land/p/nt/markdown/sanitize/v0"7	"gno.land/p/nt/uassert/v0"8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    )
    9
    10func TestScanLinks(t *testing.T) {
    11 cases := []struct {
    12 name string
    13 in string
    14 targets []string
    15 labels []string
    16 explicits []bool
    17 }{
    18 {"none", "plain text", nil, nil, nil},
    19 {"one", "see [[Gno land]] here", []string{"Gno land"}, []string{""}, []bool{false}},
    20 {"labelled", "[[Gno land|the chain]]", []string{"Gno land"}, []string{"the chain"}, []bool{false}},
    21 {"two", "[[A]] and [[B]]", []string{"A", "B"}, []string{"", ""}, []bool{false, false}},
    22 {"category", "[[Category:Chains]]", []string{"Category:Chains"}, []string{""}, []bool{false}},
    23 {"explicit category", "[[:Category:Chains]]", []string{"Category:Chains"}, []string{""}, []bool{true}},
    24 {"whitespace is trimmed", "[[ A | b ]]", []string{"A"}, []string{"b"}, []bool{false}},
    25 {"unclosed is not a link", "[[A", nil, nil, nil},
    26 {"empty is not a link", "[[]]", nil, nil, nil},
    27 {"newline inside is not a link", "[[A\nB]]", nil, nil, nil},
    28 {"nested opener wins", "[[a [[b]]", []string{"b"}, []string{""}, []bool{false}},
    29 }
    30 for _, tc := range cases {
    31 got := ScanLinks(tc.in, "[[", "]]")
    32 if !uassert.Equal(t, len(tc.targets), len(got), tc.name) {
    33 continue
    34 }
    35 for i, l := range got {
    36 uassert.Equal(t, tc.targets[i], l.Target, tc.name)
    37 uassert.Equal(t, tc.labels[i], l.Label, tc.name)
    38 uassert.Equal(t, tc.explicits[i], l.Explicit, tc.name)
    39 }
    40 }
    41}
    42
    43func TestScanLinksOffsets(t *testing.T) {
    44 in := "see [[A]] end"
    45 got := ScanLinks(in, "[[", "]]")
    46 uassert.Equal(t, 1, len(got))
    47 uassert.Equal(t, "[[A]]", in[got[0].Start:got[0].End])
    48}
    49
    50// TestScanLinksAfterSanitize is the reason ScanLinks takes its delimiters as
    51// parameters: the sanitizer escapes every "[", so the rendering pass has to
    52// look for a different byte sequence than the indexing pass.
    53func TestScanLinksAfterSanitize(t *testing.T) {
    54 escaped := sanitize.BlockRich("see [[Gno land|the chain]] here\n")
    55 uassert.Equal(t, 0, len(ScanLinks(escaped, "[[", "]]")),
    56 "the raw delimiters must find nothing in sanitized text")
    57 got := ScanLinks(escaped, `\[\[`, `\]\]`)
    58 uassert.Equal(t, 1, len(got))
    59 uassert.Equal(t, "Gno land", got[0].Target)
    60 uassert.Equal(t, "the chain", got[0].Label)
    61}
    62
    63func TestRedirectTarget(t *testing.T) {
    64 cases := []struct{ in, want string }{
    65 {"#REDIRECT [[Gno land]]\n", "Gno land"},
    66 {"#redirect [[gno_land]]", "Gno land"},
    67 {" #REDIRECT [[User:Gno land]] \nrest", "User:Gno land"},
    68 {"not a redirect [[Gno land]]", ""},
    69 {"#REDIRECT no link", ""},
    70 {"#REDIRECT [[bad|title]]", "Bad"},
    71 {"text\n#REDIRECT [[Gno land]]", ""},
    72 {"", ""},
    73 }
    74 for _, tc := range cases {
    75 uassert.Equal(t, tc.want, redirectTarget(tc.in), tc.in)
    76 }
    77}
    78
    79func TestRewriteLinks(t *testing.T) {
    80 c := Ctx{
    81 Base: "/r/moul/x/wiki/v0",
    82 Exists: func(tt Title) bool { return tt.Name == "Gno land" },
    83 }
    84
    85 body := sanitize.BlockRich("See [[Gno land]], [[Missing page]] and [[Gno land|the chain]].\n" +
    86 "[[Category:Chains]]\n")
    87 got := RewriteLinks(c, body)
    88
    89 uassert.True(t, contains(got, "[Gno land](/r/moul/x/wiki/v0:Gno_land)"), "existing page links plainly")
    90 uassert.True(t, contains(got, "[Missing page](/r/moul/x/wiki/v0:Missing_page) ⁺"), "a redlink is marked")
    91 uassert.True(t, contains(got, "[the chain](/r/moul/x/wiki/v0:Gno_land)"), "labels are honored")
    92 uassert.False(t, contains(got, "Category:Chains"), "category declarations leave the flow")
    93}
    94
    95func TestRewriteLinksEscapesURLs(t *testing.T) {
    96 c := Ctx{Base: "/r/moul/x/wiki/v0"}
    97 got := RewriteLinks(c, sanitize.BlockRich("[[Mercury (planet)]]\n"))
    98 // An unescaped ")" would terminate the markdown destination early and
    99 // leave "planet))" as visible text.
    100 uassert.True(t, contains(got, "(/r/moul/x/wiki/v0:Mercury_%28planet%29)"), got)
    101}
    102
    103func TestRewriteLinksLeavesNonTitlesAlone(t *testing.T) {
    104 c := Ctx{Base: "/r/moul/x/wiki/v0"}
    105 // "[[ ]]" has no usable target, and "[[a/b]]" is not a legal title: both
    106 // must render as the literal text the author typed, never as a link.
    107 got := RewriteLinks(c, sanitize.BlockRich("[[a/b]]\n"))
    108 uassert.True(t, contains(got, `\[\[a/b\]\]`), got)
    109}
    110
    111func contains(haystack, needle string) bool {
    112 for i := 0; i+len(needle) <= len(haystack); i++ {
    113 if haystack[i:i+len(needle)] == needle {
    114 return true
    115 }
    116 }
    117 return false
    118}
    119