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

render.gno

2.35 Kb · 120 lines
  1package craft
  2
  3import (
  4	"net/url"
  5	"strconv"
  6	"strings"
  7)
  8
  9func Render(iURL string) string {
 10	u, err := url.Parse(iURL)
 11	if err != nil {
 12		return renderRecipeError("Invalid URL")
 13	}
 14
 15	switch u.Path {
 16	case "":
 17		return renderRecipeHome()
 18	case "recipe":
 19		return renderRecipeResult(u.Query().Get("recipe"))
 20	case "recipes":
 21		return renderRecipeList(u.Query().Get("page"))
 22	default:
 23		return renderRecipeError("Not found")
 24	}
 25}
 26
 27func renderRecipeHome() string {
 28	return `# AKKADIA Recipe
 29
 30Ingredients are bound to occupied occupancy bits from slot 0 upward.
 31
 32Current craft fee is ` + strconv.FormatInt(GetCraftFee(), 10) + `ugnot.
 33
 34Enter a recipe to find its item ID.
 35
 36<gno-form path="recipe">
 37  <gno-input name="recipe" placeholder="0013|iron:1|iron:2|stick:3" />
 38</gno-form>
 39
 40* [Browse Recipes](./craft:recipes)
 41`
 42}
 43
 44func renderRecipeList(rawPage string) string {
 45	page := 1
 46	if rawPage != "" {
 47		parsed, err := strconv.Atoi(rawPage)
 48		if err != nil || parsed < 1 {
 49			return renderRecipeError("Invalid page")
 50		}
 51		page = parsed
 52	}
 53
 54	count := 20
 55	if count > listLimit {
 56		count = listLimit
 57	}
 58
 59	output := `# Recipes
 60
 61[← Back](./craft:)
 62
 63`
 64	total := GetRecipeCount()
 65	if total == 0 {
 66		return output + `*No recipes stored yet.*
 67`
 68	}
 69
 70	rows := ListRecipes(page, count)
 71	if len(rows) == 0 {
 72		return renderRecipeError("Invalid page")
 73	}
 74	for _, row := range rows {
 75		output += "* " + formatRecipeCode(row["recipe"]) + " → " + row["itemId"] + "\n"
 76	}
 77	return output
 78}
 79
 80func renderRecipeResult(recipe string) string {
 81	if recipe == "" {
 82		return renderRecipeError("Recipe is required")
 83	}
 84
 85	canonical, _, errMsg := parseRecipe(recipe)
 86	if errMsg != "" {
 87		return renderRecipeError("Invalid recipe")
 88	}
 89	if !recipes.Has(canonical) {
 90		return renderRecipeError("Recipe not found")
 91	}
 92
 93	return `# Recipe Result
 94
 95* **Recipe**: ` + formatRecipeCode(canonical) + `
 96* **Item ID**: ` + strconv.FormatUint(uint64(mustGetRecipeItemID(canonical)), 10) + `
 97
 98[← Back](./craft:)
 99`
100}
101
102func renderRecipeError(message string) string {
103	return `# Error
104
105> ` + message + `
106
107[← Back](./craft:)
108`
109}
110
111// Recipes use | and - as syntax. A code span keeps those characters
112// literal so gnoweb does not show backslash escapes.
113func formatRecipeCode(recipe string) string {
114	recipe = strings.ReplaceAll(recipe, "\n", " ")
115	fence := "`"
116	for strings.Contains(recipe, fence) {
117		fence += "`"
118	}
119	return fence + recipe + fence
120}