#? stdtmpl | standard # #template `!`(idx: untyped): untyped = # row[idx] #end template # # #proc genThreadsList(c: TForumData, count: var int): string = # const queryModAdmin = sql"""select id, name, views, modified from thread # where id in (select thread from post where author in # (select id from person where status not in ('Spammer') or id = ?)) # order by modified desc limit ?, ?""" # const query = sql"""select id, name, views, modified from thread # where id in (select thread from post where author in # (select id from person where status not in ('Moderated', 'Spammer') or id = ?)) # order by modified desc limit ?, ?""" # const threadId = 0 # const name = 1 # const views = 2 # # result = "" # count = 0
Topic
Users
Details
Activity
# for row in rows(db, if c.rank >= Moderator: queryModAdmin else: query, # c.userId, $((c.pageNum-1) * ThreadsPerPage), $ThreadsPerPage): # inc(count)
${xmlEncode(!name)} ${genPagenumLocalNav(c, (!threadid).parseInt)}
#let users = getAllRows(db, # sql("select distinct name, email from person where id in " & # "(select author from post where thread = ?)"), !threadId)
#for i in 0 .. min(6, users.len-1): #end for
#let latestReplyAuthor = getValue(db, sql("select name from person where id = " & # "(select author from post where id = " & # "(select max(id) from post where thread = ?))"), !threadId) #let replyProfileUrl = c.req.makeUri("profile/", false) & # xmlEncode(latestReplyAuthor) # let posts = getValue(db, sql"select count(*) from post where thread = ?", !threadId)
${xmlEncode(!views)}
$posts
#let latestReplyDate = getValue(db, sql("SELECT strftime('%s', " & # "(select creation from post where id = (select max(id) from post where thread = ?)))"), !threadId) #let timeStr = formatTimestamp(latestReplyDate.parseInt())
$latestReplyAuthor replied $timeStr
# end for
#end proc # # #proc genPostPreview(c: TForumData, # title, content, author, date: string): string = # result = ""
#let profileUrl = c.req.makeUri("profile/", false) & xmlEncode(author) ${xmlEncode(author)}
#try: ${content.rstToHtml} #except EParseError: # c.errorMsg = getCurrentExceptionMsg() #end ${xmlEncode(date)}
#end proc # # #proc genPostsList(c: TForumData, threadId: string, count: var int): string = # let query = sql("""select p.id, u.name, p.header, p.content, p.creation, p.author, u.email from post p, # person u # where u.id = p.author and p.thread = ? and $# # and (u.status <> 'Spammer' or p.author = ?) # order by p.id limit ?, ?""" % # (if c.rank >= Moderator: "(1 or u.id = ?)" else: "(u.status <> 'Moderated' or p.author = ?)")) # const postId = 0 # const userName = 1 # const postHeader = 2 # const postContent = 3 # const postCreation = 4 # const postAuthor = 5 # const userEmail = 6 # result = "" # count = 0 # let posts = getAllRows(db, query, threadId, c.userId, c.userId, $((c.pageNum-1) * PostsPerPage), $PostsPerPage) # if posts.len < 1: return "" # end if
forum index > ${posts[0][postHeader]}
# for row in posts: # inc(count)
#let profileUrl = c.req.makeUri("profile/", false) & xmlEncode(!userName)
${genGravatar(!userEmail)}
${xmlEncode(!userName)} #if c.userId == !postAuthor and c.currentPost.subject.len == 0:
Edit post #elif c.rank >= Moderator and c.currentPost.subject.len == 0:
Edit post #end if
#try: ${(!postContent).rstToHtml} #except EParseError: # c.errorMsg = getCurrentExceptionMsg() #end ${xmlEncode(!postCreation)}
# end for
#end proc # #proc genMarkHelp(): string #end proc #proc genFormPost(c: TForumData, action: string, # topText, title, content: string, isEdit: bool): string = # result = ""
forum index > $topText
#if action == "doreply": ${hiddenField(c, "subject", title)} #else: ${fieldValid(c, "subject", "Subject:")} ${textWidget(c, "subject", title, maxlength=100)}
#end if ${fieldValid(c, "content", "Content:")}
${textAreaWidget(c, "content", content)}
${formSession(c, action)} # if isEdit: Delete Post
# end if #if c.errorMsg != "":
$c.errorMsg
#end if
${genMarkHelp()}
#end proc # # #proc genFormRegister(c: TForumData): string = # result = ""
forum index > Register
#if useCaptcha: #end if
${fieldValid(c, "name", "Username:")} ${textWidget(c, "name", reuseText, maxlength=20)}
${fieldValid(c, "new_password", "Password:")}
${fieldValid(c, "email", "E-Mail:")} ${textWidget(c, "email", reuseText, maxlength=300)}
${fieldValid(c, "g-recaptcha-response", "Captcha:")} ${captcha.render(includeNoScript=true)}
#if c.errorMsg != "":
$c.errorMsg
#end if
#end proc # #proc genFormSetRank(c: TForumData; ui: TUserInfo): string = # result = ""
Reason ${textWidget(c, "reason", ui.ban, maxlength=100)}
Rank
#end proc # #proc genFormLogin(c: TForumData): string = # result = "" # if not c.loggedIn:
Username:
Password:
$c.loginErrorMsg # else: You're already logged in! # end if #end proc # # #proc genListOnline(c: TForumData, stats: TForumStats): string = # result = "" # var active: seq[string] = @[] # for i in stats.activeUsers: # active.add(i.nick) # end for # let profileUrl = c.req.makeUri("profile/", false) & # xmlEncode(stats.newestMember.nick) ${stats.activeUsers.len} of ${stats.totalUsers} users online  |  ${stats.totalThreads} threads  |  ${stats.totalPosts} posts  |  newest member: ${stats.newestMember.nick} #end proc # # # # #proc genSearchResults(c: TForumData, # results: iterator: db_sqlite.Row {.closure, tags: [ReadDbEffect].}, # count: var int): string = # const threadId = 0 # const threadName = 1 # const postId = 2 # const postHeader = 3 # const postContent = 4 # const userName = 5 # const postCreation = 6 # const postAuthor = 7 # const userEmail = 8 # const what = 9 # result = "" # count = 0 # var whCount: array[bool, int]
Search results for: ${xmlEncode(c.search.replace(""","\""))}.
# for row in results(): # inc(count) # let isThread = !what == "0" # inc(whCount[isThread]) # let postUrl = c.genThreadUrl(!postId,"",!threadId,"") # let threadUrl = c.genThreadUrl("","",!threadId) # var headersDiffer = false
#let profileUrl = c.req.makeUri("profile/", false) & xmlEncode(!userName)
${genGravatar(!userEmail, 40)}
${xmlEncode(!userName)}
#if c.userId == !postAuthor and c.currentPost.subject.len == 0:
Edit post #elif c.rank >= Moderator and c.currentPost.subject.len == 0:
Edit post #end if
#if !postHeader != "": #end if #if not isThread: #try: ${(!postContent).rstToHtml} #except EParseError: # c.errorMsg = getCurrentExceptionMsg() ${xmlEncode(!postContent)} #end #end if ${xmlEncode(!postCreation)}
# end for
# if c.pageNum > 1:
# end if # if whCount[true] == ThreadsPerPage or whCount[false] == ThreadsPerPage:
# end if #end proc # # #proc genFormResetPassword(c: TForumData): string = # result = ""
forum index > Reset Password
#if useCaptcha: #end if
${fieldValid(c, "nick", "Your nickname:")}
${fieldValid(c, "g-recaptcha-response", "Captcha:")} ${captcha.render(includeNoScript=true)}
#if c.errorMsg != "":
$c.errorMsg
#end if
#end proc #proc genMarkHelp(): string = #result = ""

nimforum uses a slightly-customized version of reStructuredText for formatting. See below for some basics, or check this link for a more detailed help reference.

you type: you see:
*italics* italics
**bold** bold
`nim! <http://nim-lang.org>`_ nim!
* item 1
* item 2
* item 3
  • item 1
  • item 2
  • item 3
> quoted text
quoted text
The forum supports the Github Markdown syntax
for code listings:

```nim
if 1 * 2 < 3:
  echo "hello, world!"
```
The forum supports the Github Markdown syntax
for code listings:
if 1*2 < 3:
  echo "hello, world!"
                    
A horizontal rule can be created
----
but it needs text after it
A horizontal rule can be created
but it needs text after it
#end proc