Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

blog state

Back to all declarations

author

.uverse.address

author is the only address allowed to write. Deliberately a constant rather than transferable ownership: this is one person's blog, and the same address is the only one the chain lets redeploy the realm anyway, so a second owner could publish posts it could never restore after a wipe.

Value

<gnolang.StringValue>

realmPath

untyped string

realmPath is this realm's own path, used to build the links Render emits.

Value

"gno.land/r/moul/blog"

maxSlugLen

untyped bigint

maxSlugLen bounds a slug so a permalink stays typable and a key stays cheap.

Value

(64 <untyped> bigint)

excerptLen

untyped bigint

excerptLen is how much of a post body the index shows.

Value

(200 <untyped> bigint)

introKey

untyped string

introKey is the manifest key of the index header. It starts with '!', which validSlug rejects, so it can never collide with a post.

Value

"!intro"

introSlug

untyped string

introSlug is refused as a post slug. Not because this realm needs it: the intro lives in its own variable. It is refused so that the local half stays representable, where a post is \<slug>.md and the header is intro.md. A post published at this slug by a hand-written transaction would have no file it could live in, and tools/gnoblog would report it as an extra forever.

Value

"intro"

post

type

Value

blog.post

intro

string

// markdown shown above the index

Value

"# moul's blog\n\nNotes on gno.land, from someone building on it. Short, specific, mostly about\nthings I made for myself and then found out other people wanted too.\n\nNothing here is official. It is one person's working notes."

rev

int

// total writes accepted, bumped by every mutation

Value

3

validSlug

func(slug string) bool

validSlug reports whether slug is a legal permalink: 1..maxSlugLen bytes of \[a-z0-9.\_-]. The character set excludes ':' and '/' so a slug can never break out of its own render path, and excludes uppercase so a post has exactly one URL.

Open
OID
0214cf…221c:13
validSlug details

Inspect func

validDate

func(date string) bool

validDate reports whether date is exactly YYYY-MM-DD. The format is not cosmetic: \`order\` relies on lexical order being chronological order, so a date of any other shape would silently sort into the wrong place.

Open
OID
0214cf…221c:14
validDate details

Inspect func

orderKey

func(date string, slug string) string

orderKey is the key a post takes in \`order\`. The slug is appended so two posts published on the same day do not collide.

Open
OID
0214cf…221c:15
orderKey details

Inspect func

splitTags

func(tags string) []string

splitTags normalizes a comma-separated tag list: trimmed, lowercased, deduplicated, empties dropped. It returns the canonical string that gets stored, so the hash a client computes locally matches the one on chain.

Open
OID
0214cf…221c:16
splitTags details

Inspect func

joinTags

func(tags []string) string
Open
OID
0214cf…221c:17
joinTags details

Inspect func

record

func(title string, date string, tags string, body string) string

record is the canonical serialization a post hashes to. Both this realm and tools/gnoblog build it the same way, which is what lets one Manifest() read decide whether a local file needs a transaction at all.

Open
OID
0214cf…221c:18
record details

Inspect func

Set

func(slug string, title string, date string, tags string, body string)

Set creates or replaces the post at slug. This is the ordinary publish: one post, one transaction, idempotent. Changing the date moves the post in the index, so the old order entry is removed before the new one is written.

Open
OID
0214cf…221c:20
Set details

Inspect func

Append

func(slug string, body string)

Append adds to the end of a post's body. It exists for a body too large to fit in one transaction: Set the first chunk, Append the rest. An ordinary edit uses Set, which is idempotent and therefore safe to retry.

Open
OID
0214cf…221c:21
Append details

Inspect func

Delete

func(slug string)

Delete removes a post and its index entry.

Open
OID
0214cf…221c:22
Delete details

Inspect func

SetIntro

func(body string)

SetIntro replaces the markdown shown above the index. Passing "" restores the built-in header.

Open
OID
0214cf…221c:23
SetIntro details

Inspect func

Get

func(slug string) string

Get returns a post's raw markdown body, or "" when there is no such post.

Open
OID
0214cf…221c:24
Get details

Inspect func

Count

func() int

Count returns the number of published posts.

Open
OID
0214cf…221c:25
Count details

Inspect func

Revision

func() int

Revision returns the total number of writes this realm has accepted. It changes on every mutation, so a client can cheaply tell "nothing moved".

Open
OID
0214cf…221c:26
Revision details

Inspect func

Manifest

func() string

Manifest returns one tab-separated line per post, plus one for the intro: <slug>\t<rev>\t<date>\t<len of body>\t<sha256 of the canonical record> It is the diff surface tools/gnoblog reads with a single vm/qeval: the hash covers the title, date, tags and body together, so one read says exactly which local file needs a transaction without downloading a single body. The intro is reported under the key "!intro" with an empty date. '!' is not a legal slug character, so that row can never be confused with a post.

Open
OID
0214cf…221c:27
Manifest details

Inspect func

linkPrefix

untyped string

linkPrefix is what a permalink starts with. gnoweb addresses a realm's render path with ':' after the package path, so this is realmPath with the leading "gno.land" dropped and the separator appended.

Value

"/r/moul/blog:"

defaultIntro

untyped string

defaultIntro is the header shown before SetIntro has ever been called, i.e. right after the first deploy or after a redeploy wiped the state.

Value

"# moul's blog\n\nNotes on gno.land, from the person building on it.\n"

Render

func(path string) string

Render serves three views: "" the index, newest first "<slug>" one post "t/<tag>" every post carrying a tag

Open
OID
0214cf…221c:28
Render details

Inspect func

renderTag

func(tag string) string
Open
OID
0214cf…221c:32
renderTag details

Inspect func

renderPost

func(slug string) string
Open
OID
0214cf…221c:33
renderPost details

Inspect func

entry

func(p *blog.post) string

entry is one row of a listing: linked title, byline, excerpt.

Open
OID
0214cf…221c:34
entry details

Inspect func

byline

func(p *blog.post) string

byline is the date plus the post's tags as links, on one line.

Open
OID
0214cf…221c:35
byline details

Inspect func

hasTag

func(p *blog.post, tag string) bool
Open
OID
0214cf…221c:36
hasTag details

Inspect func

firstLine

func(body string) string

firstLine returns the first non-empty, non-heading line of a body, which is what an excerpt should show: a post that opens with "## Something" would otherwise preview its own heading.

Open
OID
0214cf…221c:37
firstLine details

Inspect func
author : .uverse.address =<gnolang.StringValue>
realmPath : untyped string ="gno.land/r/moul/blog"
maxSlugLen : untyped bigint =(64 <untyped> bigint)
excerptLen : untyped bigint =(200 <untyped> bigint)
introKey : untyped string ="!intro"
introSlug : untyped string ="intro"
post : type =blog.post
posts : *v0.Tree Inspect
order : *v0.Tree Inspect
intro : string ="# moul's blog\n\nNotes on gno.land, from someone building on it. Short, specific, mostly about\nthings I made for myself and then found out other people wanted too.\n\nNothing here is official. It is one person's working notes."
rev : int =3
assertAuthor : func() Inspect
validSlug : func(slug string) bool Inspect
validDate : func(date string) bool Inspect
orderKey : func(date string, slug string) string Inspect
splitTags : func(tags string) []string Inspect
joinTags : func(tags []string) string Inspect
record : func(title string, date string, tags string, body string) string Inspect
hashOf : func(s string) string Inspect
Set : func(slug string, title string, date string, tags string, body string) Inspect
Append : func(slug string, body string) Inspect
Delete : func(slug string) Inspect
SetIntro : func(body string) Inspect
Get : func(slug string) string Inspect
Count : func() int Inspect
Revision : func() int Inspect
Manifest : func() string Inspect
linkPrefix : untyped string ="/r/moul/blog:"
defaultIntro : untyped string ="# moul's blog\n\nNotes on gno.land, from the person building on it.\n"
Render : func(path string) string Inspect
header : func() string Inspect
renderIndex : func() string Inspect
renderTag : func(tag string) string Inspect
renderPost : func(slug string) string Inspect
entry : func(p *blog.post) string Inspect
byline : func(p *blog.post) string Inspect
hasTag : func(p *blog.post, tag string) bool Inspect
firstLine : func(body string) string Inspect