2017-11-10 03:33:11 +00:00
package common
2017-08-27 09:33:45 +00:00
2017-10-14 07:39:22 +00:00
import (
2019-05-13 09:17:44 +00:00
"fmt"
2017-10-14 07:39:22 +00:00
"html/template"
2018-04-22 12:33:56 +00:00
"io"
2017-10-14 07:39:22 +00:00
"log"
2018-03-21 05:56:33 +00:00
"path/filepath"
2019-10-12 22:49:08 +00:00
"runtime"
2018-03-12 04:52:47 +00:00
"strconv"
2018-03-21 05:56:33 +00:00
"strings"
"sync"
2017-10-14 07:39:22 +00:00
"time"
2017-11-11 04:06:16 +00:00
2018-10-27 03:21:02 +00:00
"github.com/Azareal/Gosora/common/alerts"
2019-10-12 22:49:08 +00:00
p "github.com/Azareal/Gosora/common/phrases"
2019-12-08 03:40:56 +00:00
tmpl "github.com/Azareal/Gosora/common/templates"
qgen "github.com/Azareal/Gosora/query_gen"
2017-10-14 07:39:22 +00:00
)
2017-08-27 09:33:45 +00:00
2018-12-14 04:08:53 +00:00
var Ctemplates [ ] string // TODO: Use this to filter out top level templates we don't need
2019-02-10 05:52:26 +00:00
var DefaultTemplates = template . New ( "" )
var DefaultTemplateFuncMap map [ string ] interface { }
//var Templates = template.New("")
2018-04-22 12:33:56 +00:00
var PrebuildTmplList [ ] func ( User , * Header ) CTmpl
2017-11-10 03:33:11 +00:00
2018-12-14 04:08:53 +00:00
func skipCTmpl ( key string ) bool {
for _ , tmpl := range Ctemplates {
if strings . HasSuffix ( key , "/" + tmpl + ".html" ) {
return true
}
}
return false
}
2017-11-10 03:33:11 +00:00
type CTmpl struct {
Name string
Filename string
Path string
StructName string
Data interface { }
2017-11-11 06:33:08 +00:00
Imports [ ] string
2017-11-10 03:33:11 +00:00
}
2017-08-27 09:33:45 +00:00
2019-02-10 05:52:26 +00:00
func genIntTmpl ( name string ) func ( pi interface { } , w io . Writer ) error {
return func ( pi interface { } , w io . Writer ) error {
2019-06-16 07:26:31 +00:00
theme := Themes [ DefaultThemeBox . Load ( ) . ( string ) ]
mapping , ok := theme . TemplatesMap [ name ]
2019-02-10 05:52:26 +00:00
if ! ok {
mapping = name
}
return DefaultTemplates . ExecuteTemplate ( w , mapping + ".html" , pi )
2017-08-27 09:33:45 +00:00
}
}
2019-02-10 05:52:26 +00:00
// TODO: Refactor the template trees to not need these
2017-09-10 16:57:22 +00:00
// nolint
2019-02-10 05:52:26 +00:00
var Template_topic_handle = genIntTmpl ( "topic" )
var Template_topic_guest_handle = Template_topic_handle
var Template_topic_member_handle = Template_topic_handle
var Template_topic_alt_handle = genIntTmpl ( "topic" )
var Template_topic_alt_guest_handle = Template_topic_alt_handle
var Template_topic_alt_member_handle = Template_topic_alt_handle
2017-08-27 09:33:45 +00:00
2017-09-10 16:57:22 +00:00
// nolint
2019-02-10 05:52:26 +00:00
var Template_topics_handle = genIntTmpl ( "topics" )
2018-11-28 21:46:53 +00:00
var Template_topics_guest_handle = Template_topics_handle
var Template_topics_member_handle = Template_topics_handle
2017-08-27 09:33:45 +00:00
2017-09-10 16:57:22 +00:00
// nolint
2019-02-10 05:52:26 +00:00
var Template_forum_handle = genIntTmpl ( "forum" )
2018-12-14 04:08:53 +00:00
var Template_forum_guest_handle = Template_forum_handle
var Template_forum_member_handle = Template_forum_handle
2017-08-27 09:33:45 +00:00
2017-09-10 16:57:22 +00:00
// nolint
2019-02-10 05:52:26 +00:00
var Template_forums_handle = genIntTmpl ( "forums" )
2018-12-17 04:58:55 +00:00
var Template_forums_guest_handle = Template_forums_handle
var Template_forums_member_handle = Template_forums_handle
2017-08-27 09:33:45 +00:00
2017-09-10 16:57:22 +00:00
// nolint
2019-02-10 05:52:26 +00:00
var Template_profile_handle = genIntTmpl ( "profile" )
2018-12-14 04:08:53 +00:00
var Template_profile_guest_handle = Template_profile_handle
var Template_profile_member_handle = Template_profile_handle
2017-08-27 09:33:45 +00:00
2017-09-10 16:57:22 +00:00
// nolint
2019-02-10 05:52:26 +00:00
var Template_create_topic_handle = genIntTmpl ( "create_topic" )
var Template_login_handle = genIntTmpl ( "login" )
var Template_register_handle = genIntTmpl ( "register" )
var Template_error_handle = genIntTmpl ( "error" )
var Template_ip_search_handle = genIntTmpl ( "ip_search" )
var Template_account_handle = genIntTmpl ( "account" )
2018-10-27 03:21:02 +00:00
2020-03-15 07:06:44 +00:00
func tmplInitUsers ( ) ( * User , * User , * User ) {
2018-07-28 12:52:23 +00:00
avatar , microAvatar := BuildAvatar ( 62 , "" )
2020-03-15 07:06:44 +00:00
u := User { 62 , BuildProfileURL ( "fake-user" , 62 ) , "Fake User" , "compiler@localhost" , 0 , false , false , false , false , false , false , GuestPerms , make ( map [ string ] bool ) , "" , false , "" , avatar , microAvatar , "" , "" , 0 , 0 , 0 , 0 , StartTime , "0.0.0.0.0" , 0 , 0 , nil }
2018-07-28 12:52:23 +00:00
2017-09-10 16:57:22 +00:00
// TODO: Do a more accurate level calculation for this?
2018-07-28 12:52:23 +00:00
avatar , microAvatar = BuildAvatar ( 1 , "" )
2020-03-15 07:06:44 +00:00
u2 := User { 1 , BuildProfileURL ( "admin-alice" , 1 ) , "Admin Alice" , "alice@localhost" , 1 , true , true , true , true , false , false , AllPerms , make ( map [ string ] bool ) , "" , true , "" , avatar , microAvatar , "" , "" , 58 , 1000 , 0 , 1000 , StartTime , "127.0.0.1" , 0 , 0 , nil }
2018-07-28 12:52:23 +00:00
avatar , microAvatar = BuildAvatar ( 2 , "" )
2020-03-15 07:06:44 +00:00
u3 := User { 2 , BuildProfileURL ( "admin-fred" , 62 ) , "Admin Fred" , "fred@localhost" , 1 , true , true , true , true , false , false , AllPerms , make ( map [ string ] bool ) , "" , true , "" , avatar , microAvatar , "" , "" , 42 , 900 , 0 , 900 , StartTime , "::1" , 0 , 0 , nil }
return & u , & u2 , & u3
2018-06-24 13:49:29 +00:00
}
2020-03-15 07:06:44 +00:00
func tmplInitHeaders ( user , user2 , user3 * User ) ( * Header , * Header , * Header ) {
2018-04-22 12:33:56 +00:00
header := & Header {
2019-02-28 07:28:17 +00:00
Site : Site ,
Settings : SettingBox . Load ( ) . ( SettingMap ) ,
Themes : Themes ,
Theme : Themes [ DefaultThemeBox . Load ( ) . ( string ) ] ,
CurrentUser : user ,
NoticeList : [ ] string { "test" } ,
2019-04-02 07:43:11 +00:00
Stylesheets : [ ] string { "panel.css" } ,
Scripts : [ ] string { "whatever.js" } ,
PreScriptsAsync : [ ] string { "whatever.js" } ,
ScriptsAsync : [ ] string { "whatever.js" } ,
2017-08-27 09:33:45 +00:00
Widgets : PageWidgets {
LeftSidebar : template . HTML ( "lalala" ) ,
} ,
}
2020-03-15 07:06:44 +00:00
buildHeader := func ( user * User ) * Header {
2019-08-31 22:17:37 +00:00
head := & Header { Site : Site }
2018-11-17 02:36:02 +00:00
* head = * header
head . CurrentUser = user
return head
}
2018-05-27 09:36:35 +00:00
2018-11-17 02:36:02 +00:00
return header , buildHeader ( user2 ) , buildHeader ( user3 )
2018-06-24 13:49:29 +00:00
}
2018-11-26 05:08:10 +00:00
type TmplLoggedin struct {
Stub string
Guest string
Member string
}
2018-12-17 04:58:55 +00:00
type nobreak interface { }
2019-02-10 05:52:26 +00:00
type TItem struct {
Expects string
ExpectsInt interface { }
LoggedIn bool
}
type TItemHold map [ string ] TItem
2020-02-11 07:01:13 +00:00
func ( h TItemHold ) Add ( name , expects string , expectsInt interface { } ) {
2019-10-18 00:35:13 +00:00
h [ name ] = TItem { expects , expectsInt , true }
2019-02-10 05:52:26 +00:00
}
2020-02-11 07:01:13 +00:00
func ( h TItemHold ) AddStd ( name , expects string , expectsInt interface { } ) {
2019-10-18 00:35:13 +00:00
h [ name ] = TItem { expects , expectsInt , false }
2019-02-10 05:52:26 +00:00
}
2018-06-24 13:49:29 +00:00
// ? - Add template hooks?
func CompileTemplates ( ) error {
2019-02-10 05:52:26 +00:00
log . Print ( "Compiling the templates" )
// TODO: Implement per-theme template overrides here too
2019-08-31 22:17:37 +00:00
overriden := make ( map [ string ] map [ string ] bool )
2019-02-10 05:52:26 +00:00
for _ , theme := range Themes {
overriden [ theme . Name ] = make ( map [ string ] bool )
log . Printf ( "theme.OverridenTemplates: %+v\n" , theme . OverridenTemplates )
for _ , override := range theme . OverridenTemplates {
overriden [ theme . Name ] [ override ] = true
}
}
log . Printf ( "overriden: %+v\n" , overriden )
2019-10-18 00:35:13 +00:00
config := tmpl . CTemplateConfig {
2019-12-08 03:40:56 +00:00
Minify : Config . MinifyTemplates ,
Debug : Dev . DebugMode ,
2019-10-18 00:35:13 +00:00
SuperDebug : Dev . TemplateDebug ,
}
2019-02-28 07:28:17 +00:00
c := tmpl . NewCTemplateSet ( "normal" )
2018-06-24 13:49:29 +00:00
c . SetConfig ( config )
c . SetBaseImportMap ( map [ string ] string {
2018-10-27 03:21:02 +00:00
"io" : "io" ,
2019-08-20 22:32:10 +00:00
"github.com/Azareal/Gosora/common" : "c github.com/Azareal/Gosora/common" ,
2018-06-24 13:49:29 +00:00
} )
c . SetBuildTags ( "!no_templategen" )
2019-02-10 05:52:26 +00:00
c . SetOverrideTrack ( overriden )
c . SetPerThemeTmpls ( make ( map [ string ] bool ) )
2018-06-24 13:49:29 +00:00
2019-02-10 05:52:26 +00:00
log . Print ( "Compiling the default templates" )
var wg sync . WaitGroup
2019-10-12 22:49:08 +00:00
if err := compileTemplates ( & wg , c , "" ) ; err != nil {
2017-08-27 09:33:45 +00:00
return err
}
2019-02-10 05:52:26 +00:00
oroots := c . GetOverridenRoots ( )
log . Printf ( "oroots: %+v\n" , oroots )
2018-11-26 05:08:10 +00:00
2019-02-10 05:52:26 +00:00
log . Print ( "Compiling the per-theme templates" )
for theme , tmpls := range oroots {
2019-02-28 07:28:17 +00:00
c . ResetLogs ( "normal-" + theme )
2019-02-10 05:52:26 +00:00
c . SetThemeName ( theme )
c . SetPerThemeTmpls ( tmpls )
log . Print ( "theme: " , theme )
log . Printf ( "perThemeTmpls: %+v\n" , tmpls )
2019-10-12 22:49:08 +00:00
err := compileTemplates ( & wg , c , theme )
2019-02-10 05:52:26 +00:00
if err != nil {
return err
}
2017-08-27 09:33:45 +00:00
}
2019-02-10 05:52:26 +00:00
writeTemplateList ( c , & wg , "./" )
return nil
}
2017-08-27 09:33:45 +00:00
2020-02-11 07:01:13 +00:00
func compileCommons ( c * tmpl . CTemplateSet , head , head2 * Header , forumList [ ] Forum , o TItemHold ) error {
2019-02-10 05:52:26 +00:00
// TODO: Add support for interface{}s
_ , user2 , user3 := tmplInitUsers ( )
now := time . Now ( )
// Convienience function to save a line here and there
2019-08-31 22:17:37 +00:00
htitle := func ( name string ) * Header {
2019-10-12 22:49:08 +00:00
head . Title = name
return head
2017-08-27 09:33:45 +00:00
}
2019-08-31 22:17:37 +00:00
/ * htitle2 := func ( name string ) * Header {
2019-10-12 22:49:08 +00:00
head2 . Title = name
return head2
2019-02-10 05:52:26 +00:00
} * /
2017-08-27 09:33:45 +00:00
var topicsList [ ] * TopicsRow
2020-03-15 07:06:44 +00:00
topicsList = append ( topicsList , & TopicsRow { 1 , "topic-title" , "Topic Title" , "The topic content." , 1 , false , false , now , now , user3 . ID , 1 , 1 , "" , "127.0.0.1" , 1 , 0 , 1 , 1 , 0 , "classname" , 0 , "" , user2 , "" , 0 , user3 , "General" , "/forum/general.2" , nil } )
2019-02-10 05:52:26 +00:00
topicListPage := TopicListPage { htitle ( "Topic List" ) , topicsList , forumList , Config . DefaultForum , TopicListSort { "lastupdated" , false } , Paginator { [ ] int { 1 } , 1 , 1 } }
2019-10-12 22:49:08 +00:00
o . Add ( "topics" , "c.TopicListPage" , topicListPage )
2017-08-27 09:33:45 +00:00
2017-11-11 05:22:33 +00:00
forumItem := BlankForum ( 1 , "general-forum.1" , "General Forum" , "Where the general stuff happens" , true , "all" , 0 , "" , 0 )
2019-02-10 05:52:26 +00:00
forumPage := ForumPage { htitle ( "General Forum" ) , topicsList , forumItem , Paginator { [ ] int { 1 } , 1 , 1 } }
2019-10-12 22:49:08 +00:00
o . Add ( "forum" , "c.ForumPage" , forumPage )
o . Add ( "forums" , "c.ForumsPage" , ForumsPage { htitle ( "Forum List" ) , forumList } )
2017-08-27 09:33:45 +00:00
2019-02-10 05:52:26 +00:00
poll := Poll { ID : 1 , Type : 0 , Options : map [ int ] string { 0 : "Nothing" , 1 : "Something" } , Results : map [ int ] int { 0 : 5 , 1 : 2 } , QuickOptions : [ ] PollOption {
PollOption { 0 , "Nothing" } ,
PollOption { 1 , "Something" } ,
} , VoteCount : 7 }
avatar , microAvatar := BuildAvatar ( 62 , "" )
miniAttach := [ ] * MiniAttachment { & MiniAttachment { Path : "/" } }
2019-12-08 03:40:56 +00:00
topic := TopicUser { 1 , "blah" , "Blah" , "Hey there!" , 0 , false , false , now , now , 1 , 1 , 0 , "" , "127.0.0.1" , 1 , 0 , 1 , 0 , "classname" , poll . ID , "weird-data" , BuildProfileURL ( "fake-user" , 62 ) , "Fake User" , Config . DefaultGroup , avatar , microAvatar , 0 , "" , "" , "" , 58 , false , miniAttach , nil , false }
2019-05-17 08:40:41 +00:00
var replyList [ ] * ReplyUser
reply := Reply { 1 , 1 , "Yo!" , 1 , Config . DefaultGroup , now , 0 , 0 , 1 , "::1" , true , 1 , 1 , "" }
2019-12-08 03:40:56 +00:00
ru := & ReplyUser { ClassName : "" , Reply : reply , CreatedByName : "Alice" , Avatar : avatar , Level : 0 , Attachments : miniAttach }
2019-05-19 01:01:11 +00:00
ru . Init ( )
2019-05-17 08:40:41 +00:00
replyList = append ( replyList , ru )
2019-02-10 05:52:26 +00:00
tpage := TopicPage { htitle ( "Topic Name" ) , replyList , topic , & Forum { ID : 1 , Name : "Hahaha" } , poll , Paginator { [ ] int { 1 } , 1 , 1 } }
tpage . Forum . Link = BuildForumURL ( NameToSlug ( tpage . Forum . Name ) , tpage . Forum . ID )
2019-10-12 22:49:08 +00:00
o . Add ( "topic" , "c.TopicPage" , tpage )
2020-03-11 03:26:33 +00:00
o . Add ( "topic_mini" , "c.TopicPage" , tpage )
2019-10-12 22:49:08 +00:00
o . Add ( "topic_alt" , "c.TopicPage" , tpage )
2020-03-11 03:26:33 +00:00
o . Add ( "topic_alt_mini" , "c.TopicPage" , tpage )
2019-02-10 05:52:26 +00:00
return nil
}
2018-03-08 03:59:47 +00:00
2019-02-10 05:52:26 +00:00
func compileTemplates ( wg * sync . WaitGroup , c * tmpl . CTemplateSet , themeName string ) error {
// Schemas to train the template compiler on what to expect
// TODO: Add support for interface{}s
user , user2 , user3 := tmplInitUsers ( )
header , header2 , _ := tmplInitHeaders ( user , user2 , user3 )
now := time . Now ( )
2017-11-11 06:33:08 +00:00
2019-05-19 01:01:11 +00:00
/ * poll := Poll { ID : 1 , Type : 0 , Options : map [ int ] string { 0 : "Nothing" , 1 : "Something" } , Results : map [ int ] int { 0 : 5 , 1 : 2 } , QuickOptions : [ ] PollOption {
2019-02-10 05:52:26 +00:00
PollOption { 0 , "Nothing" } ,
PollOption { 1 , "Something" } ,
2019-05-19 01:01:11 +00:00
} , VoteCount : 7 } * /
//avatar, microAvatar := BuildAvatar(62, "")
2019-02-10 05:52:26 +00:00
miniAttach := [ ] * MiniAttachment { & MiniAttachment { Path : "/" } }
2019-05-17 08:40:41 +00:00
var replyList [ ] * ReplyUser
2019-05-19 01:01:11 +00:00
//topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, now, now, 1, 1, 0, "", "127.0.0.1", 1, 0, 1, 0, "classname", poll.ID, "weird-data", BuildProfileURL("fake-user", 62), "Fake User", Config.DefaultGroup, avatar, microAvatar, 0, "", "", "", "", "", 58, false, miniAttach, nil}
2019-02-10 05:52:26 +00:00
// TODO: Do we want the UID on this to be 0?
2019-05-19 01:01:11 +00:00
//avatar, microAvatar = BuildAvatar(0, "")
2019-05-17 08:40:41 +00:00
reply := Reply { 1 , 1 , "Yo!" , 1 , Config . DefaultGroup , now , 0 , 0 , 1 , "::1" , true , 1 , 1 , "" }
2019-12-08 03:40:56 +00:00
ru := & ReplyUser { ClassName : "" , Reply : reply , CreatedByName : "Alice" , Avatar : "" , Level : 0 , Attachments : miniAttach }
2019-05-19 01:01:11 +00:00
ru . Init ( )
2019-05-17 08:40:41 +00:00
replyList = append ( replyList , ru )
2018-03-08 03:59:47 +00:00
2019-05-27 09:00:40 +00:00
// TODO: Use a dummy forum list to avoid o(n) problems
var forumList [ ] Forum
forums , err := Forums . GetAll ( )
if err != nil {
return err
}
for _ , forum := range forums {
forumList = append ( forumList , * forum )
}
2019-02-10 05:52:26 +00:00
// Convienience function to save a line here and there
2019-08-31 22:17:37 +00:00
htitle := func ( name string ) * Header {
2019-02-10 05:52:26 +00:00
header . Title = name
return header
}
2019-09-29 04:56:39 +00:00
t := TItemHold ( make ( map [ string ] TItem ) )
err = compileCommons ( c , header , header2 , forumList , t )
2018-03-08 03:59:47 +00:00
if err != nil {
return err
}
2020-03-15 07:06:44 +00:00
ppage := ProfilePage { htitle ( "User 526" ) , replyList , * user , 0 , 0 , false , false , false } // TODO: Use the score from user to generate the currentScore and nextScore
2019-09-29 04:56:39 +00:00
t . Add ( "profile" , "c.ProfilePage" , ppage )
2019-02-10 05:52:26 +00:00
2019-05-27 09:00:40 +00:00
var topicsList [ ] * TopicsRow
2020-03-15 07:06:44 +00:00
topicsList = append ( topicsList , & TopicsRow { 1 , "topic-title" , "Topic Title" , "The topic content." , 1 , false , false , now , now , user3 . ID , 1 , 1 , "" , "127.0.0.1" , 1 , 0 , 1 , 1 , 0 , "classname" , 0 , "" , user2 , "" , 0 , user3 , "General" , "/forum/general.2" , nil } )
2019-05-27 09:00:40 +00:00
topicListPage := TopicListPage { htitle ( "Topic List" ) , topicsList , forumList , Config . DefaultForum , TopicListSort { "lastupdated" , false } , Paginator { [ ] int { 1 } , 1 , 1 } }
forumItem := BlankForum ( 1 , "general-forum.1" , "General Forum" , "Where the general stuff happens" , true , "all" , 0 , "" , 0 )
forumPage := ForumPage { htitle ( "General Forum" ) , topicsList , forumItem , Paginator { [ ] int { 1 } , 1 , 1 } }
// Experimental!
2019-12-08 03:40:56 +00:00
for _ , tmpl := range strings . Split ( Dev . ExtraTmpls , "," ) {
sp := strings . Split ( tmpl , ":" )
2019-05-27 09:00:40 +00:00
if len ( sp ) < 2 {
continue
}
typ := "0"
if len ( sp ) == 3 {
typ = sp [ 2 ]
}
var pi interface { }
switch sp [ 1 ] {
2019-08-20 22:32:10 +00:00
case "c.TopicListPage" :
2019-05-27 09:00:40 +00:00
pi = topicListPage
2019-08-20 22:32:10 +00:00
case "c.ForumPage" :
2019-05-27 09:00:40 +00:00
pi = forumPage
2019-08-20 22:32:10 +00:00
case "c.ProfilePage" :
2019-05-27 09:00:40 +00:00
pi = ppage
2019-08-20 22:32:10 +00:00
case "c.Page" :
2019-05-27 09:00:40 +00:00
pi = Page { htitle ( "Something" ) , tList , nil }
default :
continue
}
if typ == "1" {
2019-09-29 04:56:39 +00:00
t . Add ( sp [ 0 ] , sp [ 1 ] , pi )
2019-05-27 09:00:40 +00:00
} else {
2019-09-29 04:56:39 +00:00
t . AddStd ( sp [ 0 ] , sp [ 1 ] , pi )
2019-05-27 09:00:40 +00:00
}
}
2019-09-29 04:56:39 +00:00
t . AddStd ( "login" , "c.Page" , Page { htitle ( "Login Page" ) , tList , nil } )
2019-10-29 22:13:45 +00:00
t . AddStd ( "register" , "c.Page" , Page { htitle ( "Registration Page" ) , tList , false } )
2019-09-29 04:56:39 +00:00
t . AddStd ( "error" , "c.ErrorPage" , ErrorPage { htitle ( "Error" ) , "A problem has occurred in the system." } )
2019-02-10 05:52:26 +00:00
2020-03-15 07:06:44 +00:00
ipSearchPage := IPSearchPage { htitle ( "IP Search" ) , map [ int ] * User { 1 : user2 } , "::1" }
2019-09-29 04:56:39 +00:00
t . AddStd ( "ip_search" , "c.IPSearchPage" , ipSearchPage )
2019-02-10 05:52:26 +00:00
2018-12-17 04:58:55 +00:00
var inter nobreak
accountPage := Account { header , "dashboard" , "account_own_edit" , inter }
2019-09-29 04:56:39 +00:00
t . AddStd ( "account" , "c.Account" , accountPage )
2019-08-20 22:32:10 +00:00
2020-03-15 07:06:44 +00:00
parti := [ ] * User { user }
2020-02-12 09:11:27 +00:00
convo := & Conversation { 1 , BuildConvoURL ( 1 ) , user . ID , time . Now ( ) , 0 , time . Now ( ) }
2020-03-15 07:06:44 +00:00
convoItems := [ ] ConvoViewRow { ConvoViewRow { & ConversationPost { 1 , 1 , "hey" , "" , user . ID } , user , "" , 4 , true } }
2020-02-11 07:01:13 +00:00
convoPage := ConvoViewPage { header , convo , convoItems , parti , true , Paginator { [ ] int { 1 } , 1 , 1 } }
2019-09-29 04:56:39 +00:00
t . AddStd ( "convo" , "c.ConvoViewPage" , convoPage )
2018-10-27 03:21:02 +00:00
2020-03-15 07:06:44 +00:00
convos := [ ] * ConversationExtra { & ConversationExtra { & Conversation { } , [ ] * User { user } } }
2020-02-12 09:11:27 +00:00
var cRows [ ] ConvoListRow
for _ , convo := range convos {
cRows = append ( cRows , ConvoListRow { convo , convo . Users , false } )
}
convoListPage := ConvoListPage { header , cRows , Paginator { [ ] int { 1 } , 1 , 1 } }
2019-09-29 04:56:39 +00:00
t . AddStd ( "convos" , "c.ConvoListPage" , convoListPage )
2019-08-31 22:17:37 +00:00
2019-04-29 01:28:55 +00:00
basePage := & BasePanelPage { header , PanelStats { } , "dashboard" , ReportForumID }
2019-09-29 04:56:39 +00:00
t . AddStd ( "panel" , "c.Panel" , Panel { basePage , "panel_dashboard_right" , "" , "panel_dashboard" , inter } )
2019-12-08 03:40:56 +00:00
ges := [ ] GridElement { GridElement { "" , "" , "" , 1 , "grid_istat" , "" , "" , "" } }
t . AddStd ( "panel_dashboard" , "c.DashGrids" , DashGrids { ges , ges } )
2019-10-12 22:49:08 +00:00
goVersion := runtime . Version ( )
dbVersion := qgen . Builder . DbVersion ( )
var memStats runtime . MemStats
runtime . ReadMemStats ( & memStats )
2020-03-03 13:02:46 +00:00
debugTasks := DebugPageTasks { 0 , 0 , 0 , 0 , 0 }
2019-10-12 22:49:08 +00:00
debugCache := DebugPageCache { 1 , 1 , 1 , 2 , 2 , 2 , true }
2019-12-08 03:40:56 +00:00
debugDatabase := DebugPageDatabase { 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 }
debugDisk := DebugPageDisk { 1 , 1 , 1 , 1 , 1 , 1 }
2020-02-23 09:08:47 +00:00
dpage := PanelDebugPage { basePage , goVersion , dbVersion , "0s" , 1 , qgen . Builder . GetAdapter ( ) . GetName ( ) , 1 , 1 , debugTasks , memStats , debugCache , debugDatabase , debugDisk }
2019-10-12 22:49:08 +00:00
t . AddStd ( "panel_debug" , "c.PanelDebugPage" , dpage )
2019-09-29 04:56:39 +00:00
//t.AddStd("panel_analytics", "c.PanelAnalytics", Panel{basePage, "panel_dashboard_right","panel_dashboard", inter})
2019-04-29 01:28:55 +00:00
2019-08-31 22:17:37 +00:00
writeTemplate := func ( name string , content interface { } ) {
2018-03-21 05:56:33 +00:00
log . Print ( "Writing template '" + name + "'" )
2020-02-11 07:01:13 +00:00
writeTmpl := func ( name , content string ) {
2018-11-26 05:08:10 +00:00
if content == "" {
2019-02-10 05:52:26 +00:00
return //log.Fatal("No content body for " + name)
2018-11-26 05:08:10 +00:00
}
2018-03-21 05:56:33 +00:00
err := writeFile ( "./template_" + name + ".go" , content )
if err != nil {
log . Fatal ( err )
}
2018-11-26 05:08:10 +00:00
}
wg . Add ( 1 )
go func ( ) {
2019-02-10 05:52:26 +00:00
tname := themeName
if tname != "" {
tname = "_" + tname
}
2018-11-26 05:08:10 +00:00
switch content := content . ( type ) {
case string :
2019-02-10 05:52:26 +00:00
writeTmpl ( name + tname , content )
2018-11-26 05:08:10 +00:00
case TmplLoggedin :
2019-02-10 05:52:26 +00:00
writeTmpl ( name + tname , content . Stub )
writeTmpl ( name + tname + "_guest" , content . Guest )
writeTmpl ( name + tname + "_member" , content . Member )
2018-11-26 05:08:10 +00:00
}
2018-03-21 05:56:33 +00:00
wg . Done ( )
} ( )
}
2018-03-08 03:59:47 +00:00
// Let plugins register their own templates
DebugLog ( "Registering the templates for the plugins" )
2019-02-10 05:52:26 +00:00
config := c . GetConfig ( )
2018-03-08 03:59:47 +00:00
config . SkipHandles = true
c . SetConfig ( config )
2017-11-11 04:06:16 +00:00
for _ , tmplfunc := range PrebuildTmplList {
2020-03-15 07:06:44 +00:00
tmplItem := tmplfunc ( * user , header )
2019-02-10 05:52:26 +00:00
varList := make ( map [ string ] tmpl . VarItem )
2017-11-11 06:33:08 +00:00
compiledTmpl , err := c . Compile ( tmplItem . Filename , tmplItem . Path , tmplItem . StructName , tmplItem . Data , varList , tmplItem . Imports ... )
2017-11-10 03:33:11 +00:00
if err != nil {
return err
}
2018-03-21 05:56:33 +00:00
writeTemplate ( tmplItem . Name , compiledTmpl )
2017-11-10 03:33:11 +00:00
}
2017-08-27 09:33:45 +00:00
log . Print ( "Writing the templates" )
2019-09-29 04:56:39 +00:00
for name , titem := range t {
2019-02-10 05:52:26 +00:00
log . Print ( "Writing " + name )
varList := make ( map [ string ] tmpl . VarItem )
if titem . LoggedIn {
stub , guest , member , err := c . CompileByLoggedin ( name + ".html" , "templates/" , titem . Expects , titem . ExpectsInt , varList )
if err != nil {
return err
}
writeTemplate ( name , TmplLoggedin { stub , guest , member } )
} else {
tmpl , err := c . Compile ( name + ".html" , "templates/" , titem . Expects , titem . ExpectsInt , varList )
if err != nil {
return err
}
writeTemplate ( name , tmpl )
}
}
2019-05-27 09:00:40 +00:00
2018-04-22 12:33:56 +00:00
return nil
}
2019-02-28 07:28:17 +00:00
// ? - Add template hooks?
2018-04-22 12:33:56 +00:00
func CompileJSTemplates ( ) error {
2019-02-28 07:28:17 +00:00
log . Print ( "Compiling the JS templates" )
// TODO: Implement per-theme template overrides here too
2019-08-31 22:17:37 +00:00
overriden := make ( map [ string ] map [ string ] bool )
2019-02-28 07:28:17 +00:00
for _ , theme := range Themes {
overriden [ theme . Name ] = make ( map [ string ] bool )
log . Printf ( "theme.OverridenTemplates: %+v\n" , theme . OverridenTemplates )
for _ , override := range theme . OverridenTemplates {
overriden [ theme . Name ] [ override ] = true
}
}
log . Printf ( "overriden: %+v\n" , overriden )
2019-09-29 04:56:39 +00:00
config := tmpl . CTemplateConfig {
2019-12-08 03:40:56 +00:00
Minify : Config . MinifyTemplates ,
Debug : Dev . DebugMode ,
SuperDebug : Dev . TemplateDebug ,
SkipHandles : true ,
2019-09-29 04:56:39 +00:00
SkipTmplPtrMap : true ,
2019-12-08 03:40:56 +00:00
SkipInitBlock : false ,
PackageName : "tmpl" ,
2019-09-29 04:56:39 +00:00
}
2019-02-28 07:28:17 +00:00
c := tmpl . NewCTemplateSet ( "js" )
c . SetConfig ( config )
c . SetBuildTags ( "!no_templategen" )
c . SetOverrideTrack ( overriden )
c . SetPerThemeTmpls ( make ( map [ string ] bool ) )
log . Print ( "Compiling the default templates" )
var wg sync . WaitGroup
err := compileJSTemplates ( & wg , c , "" )
if err != nil {
return err
}
oroots := c . GetOverridenRoots ( )
log . Printf ( "oroots: %+v\n" , oroots )
log . Print ( "Compiling the per-theme templates" )
for theme , tmpls := range oroots {
c . SetThemeName ( theme )
c . SetPerThemeTmpls ( tmpls )
log . Print ( "theme: " , theme )
log . Printf ( "perThemeTmpls: %+v\n" , tmpls )
err = compileJSTemplates ( & wg , c , theme )
if err != nil {
return err
}
}
2019-08-20 22:32:10 +00:00
dirPrefix := "./tmpl_client/"
2019-02-28 07:28:17 +00:00
writeTemplateList ( c , & wg , dirPrefix )
return nil
}
func compileJSTemplates ( wg * sync . WaitGroup , c * tmpl . CTemplateSet , themeName string ) error {
user , user2 , user3 := tmplInitUsers ( )
header , _ , _ := tmplInitHeaders ( user , user2 , user3 )
now := time . Now ( )
2019-08-20 22:32:10 +00:00
varList := make ( map [ string ] tmpl . VarItem )
2019-02-28 07:28:17 +00:00
c . SetBaseImportMap ( map [ string ] string {
"io" : "io" ,
"github.com/Azareal/Gosora/common/alerts" : "github.com/Azareal/Gosora/common/alerts" ,
} )
// TODO: Check what sort of path is sent exactly and use it here
alertItem := alerts . AlertItem { Avatar : "" , ASID : 1 , Path : "/" , Message : "uh oh, something happened" }
alertTmpl , err := c . Compile ( "alert.html" , "templates/" , "alerts.AlertItem" , alertItem , varList )
if err != nil {
return err
}
c . SetBaseImportMap ( map [ string ] string {
"io" : "io" ,
2019-08-20 22:32:10 +00:00
"github.com/Azareal/Gosora/common" : "c github.com/Azareal/Gosora/common" ,
2019-02-28 07:28:17 +00:00
} )
// TODO: Fix the import loop so we don't have to use this hack anymore
c . SetBuildTags ( "!no_templategen,tmplgentopic" )
2019-09-29 04:56:39 +00:00
t := TItemHold ( make ( map [ string ] TItem ) )
2019-02-28 07:28:17 +00:00
2020-03-15 07:06:44 +00:00
topicsRow := & TopicsRow { 1 , "topic-title" , "Topic Title" , "The topic content." , 1 , false , false , now , now , user3 . ID , 1 , 1 , "" , "::1" , 1 , 0 , 1 , 0 , 1 , "classname" , 0 , "" , user2 , "" , 0 , user3 , "General" , "/forum/general.2" , nil }
2019-09-29 04:56:39 +00:00
t . AddStd ( "topics_topic" , "c.TopicsRow" , topicsRow )
2019-02-28 07:28:17 +00:00
poll := Poll { ID : 1 , Type : 0 , Options : map [ int ] string { 0 : "Nothing" , 1 : "Something" } , Results : map [ int ] int { 0 : 5 , 1 : 2 } , QuickOptions : [ ] PollOption {
PollOption { 0 , "Nothing" } ,
PollOption { 1 , "Something" } ,
} , VoteCount : 7 }
avatar , microAvatar := BuildAvatar ( 62 , "" )
miniAttach := [ ] * MiniAttachment { & MiniAttachment { Path : "/" } }
2020-02-18 23:04:14 +00:00
topic := TopicUser { 1 , "blah" , "Blah" , "Hey there!" , 62 , false , false , now , now , 1 , 1 , 0 , "" , "::1" , 1 , 0 , 1 , 0 , "classname" , poll . ID , "weird-data" , BuildProfileURL ( "fake-user" , 62 ) , "Fake User" , Config . DefaultGroup , avatar , microAvatar , 0 , "" , "" , "" , 58 , false , miniAttach , nil , false }
2019-05-17 08:40:41 +00:00
var replyList [ ] * ReplyUser
2019-02-28 07:28:17 +00:00
// TODO: Do we really want the UID here to be zero?
avatar , microAvatar = BuildAvatar ( 0 , "" )
2019-05-17 08:40:41 +00:00
reply := Reply { 1 , 1 , "Yo!" , 1 , Config . DefaultGroup , now , 0 , 0 , 1 , "::1" , true , 1 , 1 , "" }
2019-12-08 03:40:56 +00:00
ru := & ReplyUser { ClassName : "" , Reply : reply , CreatedByName : "Alice" , Avatar : avatar , Level : 0 , Attachments : miniAttach }
2019-05-19 01:01:11 +00:00
ru . Init ( )
2019-05-17 08:40:41 +00:00
replyList = append ( replyList , ru )
2019-02-28 07:28:17 +00:00
varList = make ( map [ string ] tmpl . VarItem )
header . Title = "Topic Name"
tpage := TopicPage { header , replyList , topic , & Forum { ID : 1 , Name : "Hahaha" } , poll , Paginator { [ ] int { 1 } , 1 , 1 } }
tpage . Forum . Link = BuildForumURL ( NameToSlug ( tpage . Forum . Name ) , tpage . Forum . ID )
2019-09-29 04:56:39 +00:00
t . AddStd ( "topic_posts" , "c.TopicPage" , tpage )
t . AddStd ( "topic_alt_posts" , "c.TopicPage" , tpage )
2019-02-28 07:28:17 +00:00
itemsPerPage := 25
_ , page , lastPage := PageOffset ( 20 , 1 , itemsPerPage )
2019-06-04 05:48:12 +00:00
pageList := Paginate ( page , lastPage , 5 )
2019-09-29 04:56:39 +00:00
t . AddStd ( "paginator" , "c.Paginator" , Paginator { pageList , page , lastPage } )
t . AddStd ( "topic_c_edit_post" , "c.TopicCEditPost" , TopicCEditPost { ID : 0 , Source : "" , Ref : "" } )
t . AddStd ( "topic_c_attach_item" , "c.TopicCAttachItem" , TopicCAttachItem { ID : 1 , ImgSrc : "" , Path : "" , FullPath : "" } )
2019-12-08 03:40:56 +00:00
t . AddStd ( "topic_c_poll_input" , "c.TopicCPollInput" , TopicCPollInput { Index : 0 } )
2019-02-28 07:28:17 +00:00
2020-03-15 07:06:44 +00:00
parti := [ ] * User { user }
2020-02-12 09:11:27 +00:00
convo := & Conversation { 1 , BuildConvoURL ( 1 ) , user . ID , time . Now ( ) , 0 , time . Now ( ) }
2020-03-15 07:06:44 +00:00
convoItems := [ ] ConvoViewRow { ConvoViewRow { & ConversationPost { 1 , 1 , "hey" , "" , user . ID } , user , "" , 4 , true } }
2020-02-11 07:01:13 +00:00
convoPage := ConvoViewPage { header , convo , convoItems , parti , true , Paginator { [ ] int { 1 } , 1 , 1 } }
2019-09-29 04:56:39 +00:00
t . AddStd ( "convo" , "c.ConvoViewPage" , convoPage )
2019-04-15 01:54:13 +00:00
2019-09-29 04:56:39 +00:00
t . AddStd ( "notice" , "string" , "nonono" )
2019-04-27 06:32:26 +00:00
2019-08-31 22:17:37 +00:00
dirPrefix := "./tmpl_client/"
2020-02-11 07:01:13 +00:00
writeTemplate := func ( name , content string ) {
2019-02-28 07:28:17 +00:00
log . Print ( "Writing template '" + name + "'" )
if content == "" {
return //log.Fatal("No content body")
}
wg . Add ( 1 )
go func ( ) {
tname := themeName
if tname != "" {
tname = "_" + tname
}
2019-04-28 10:08:05 +00:00
err := writeFile ( dirPrefix + "template_" + name + tname + ".jgo" , content )
2019-02-28 07:28:17 +00:00
if err != nil {
log . Fatal ( err )
}
wg . Done ( )
} ( )
}
log . Print ( "Writing the templates" )
2019-09-29 04:56:39 +00:00
for name , titem := range t {
2019-02-28 07:28:17 +00:00
log . Print ( "Writing " + name )
varList := make ( map [ string ] tmpl . VarItem )
tmpl , err := c . Compile ( name + ".html" , "templates/" , titem . Expects , titem . ExpectsInt , varList )
if err != nil {
return err
}
writeTemplate ( name , tmpl )
}
writeTemplate ( "alert" , alertTmpl )
/ * //writeTemplate("forum", forumTmpl)
writeTemplate ( "topic_posts" , topicPostsTmpl )
writeTemplate ( "topic_alt_posts" , topicAltPostsTmpl )
writeTemplateList ( c , & wg , dirPrefix ) * /
return nil
}
2019-02-10 05:52:26 +00:00
func getTemplateList ( c * tmpl . CTemplateSet , wg * sync . WaitGroup , prefix string ) string {
2019-02-28 07:28:17 +00:00
DebugLog ( "in getTemplateList" )
2019-02-10 05:52:26 +00:00
pout := "\n// nolint\nfunc init() {\n"
2019-08-31 22:17:37 +00:00
tFragCount := make ( map [ string ] int )
bodyMap := make ( map [ string ] string ) //map[body]fragmentPrefix
//tmplMap := make(map[string]map[string]string) // map[tmpl]map[body]fragmentPrefix
tmpCount := 0
2019-02-10 05:52:26 +00:00
for _ , frag := range c . FragOut {
front := frag . TmplName + "_frags[" + strconv . Itoa ( frag . Index ) + "]"
2019-02-28 07:28:17 +00:00
DebugLog ( "front: " , front )
DebugLog ( "frag.Body: " , frag . Body )
2019-02-10 05:52:26 +00:00
/ * bodyMap , tok := tmplMap [ frag . TmplName ]
if ! tok {
tmplMap [ frag . TmplName ] = make ( map [ string ] string )
bodyMap = tmplMap [ frag . TmplName ]
} * /
fp , ok := bodyMap [ frag . Body ]
if ! ok {
bodyMap [ frag . Body ] = front
var bits string
2020-03-05 04:43:40 +00:00
DebugLog ( "encoding f.Body" )
2019-02-10 05:52:26 +00:00
for _ , char := range [ ] byte ( frag . Body ) {
if char == '\'' {
bits += "'\\" + string ( char ) + "',"
2019-02-28 07:28:17 +00:00
} else if char < 32 {
bits += strconv . Itoa ( int ( char ) ) + ","
2019-02-10 05:52:26 +00:00
} else {
bits += "'" + string ( char ) + "',"
}
}
tmpStr := strconv . Itoa ( tmpCount )
pout += "arr_" + tmpStr + " := [...]byte{" + bits + "}\n"
pout += front + " = arr_" + tmpStr + "[:]\n"
tmpCount ++
//pout += front + " = []byte(`" + frag.Body + "`)\n"
} else {
2019-02-28 07:28:17 +00:00
DebugLog ( "encoding cached index " + fp )
2019-02-10 05:52:26 +00:00
pout += front + " = " + fp + "\n"
}
_ , ok = tFragCount [ frag . TmplName ]
if ! ok {
tFragCount [ frag . TmplName ] = 0
}
tFragCount [ frag . TmplName ] ++
}
out := "package " + c . GetConfig ( ) . PackageName + "\n\n"
2019-08-31 22:17:37 +00:00
getterstr := "\n// nolint\nGetFrag = func(name string) [][]byte {\nswitch(name) {\n"
2019-02-10 05:52:26 +00:00
for templateName , count := range tFragCount {
2020-03-03 13:02:46 +00:00
//out += "var " + templateName + "_frags = make([][]byte," + strconv.Itoa(count) + ")\n"
out += "var " + templateName + "_frags [" + strconv . Itoa ( count ) + "][]byte\n"
2019-02-10 05:52:26 +00:00
getterstr += "\tcase \"" + templateName + "\":\n"
2020-03-03 13:02:46 +00:00
//getterstr += "\treturn " + templateName + "_frags\n"
getterstr += "\treturn " + templateName + "_frags[:]\n"
2019-02-10 05:52:26 +00:00
}
getterstr += "}\nreturn nil\n}\n"
out += pout + "\n" + getterstr + "}\n"
return out
}
2018-04-22 12:33:56 +00:00
func writeTemplateList ( c * tmpl . CTemplateSet , wg * sync . WaitGroup , prefix string ) {
log . Print ( "Writing template list" )
2018-03-21 05:56:33 +00:00
wg . Add ( 1 )
2017-08-27 09:33:45 +00:00
go func ( ) {
2019-02-10 05:52:26 +00:00
err := writeFile ( prefix + "template_list.go" , getTemplateList ( c , wg , prefix ) )
2017-08-27 09:33:45 +00:00
if err != nil {
log . Fatal ( err )
}
2018-03-21 05:56:33 +00:00
wg . Done ( )
2017-08-27 09:33:45 +00:00
} ( )
2018-03-21 05:56:33 +00:00
wg . Wait ( )
2018-04-22 12:33:56 +00:00
}
func arithToInt64 ( in interface { } ) ( out int64 ) {
switch in := in . ( type ) {
case int64 :
out = in
case int32 :
out = int64 ( in )
case int :
out = int64 ( in )
case uint32 :
out = int64 ( in )
case uint16 :
out = int64 ( in )
case uint8 :
out = int64 ( in )
case uint :
out = int64 ( in )
}
return out
}
2020-02-11 07:01:13 +00:00
func arithDuoToInt64 ( left , right interface { } ) ( leftInt , rightInt int64 ) {
2018-04-22 12:33:56 +00:00
return arithToInt64 ( left ) , arithToInt64 ( right )
2017-08-27 09:33:45 +00:00
}
2019-02-10 05:52:26 +00:00
func initDefaultTmplFuncMap ( ) {
2017-09-10 16:57:22 +00:00
// TODO: Add support for floats
2017-08-27 09:33:45 +00:00
fmap := make ( map [ string ] interface { } )
2020-02-11 07:01:13 +00:00
fmap [ "add" ] = func ( left , right interface { } ) interface { } {
2018-04-22 12:33:56 +00:00
leftInt , rightInt := arithDuoToInt64 ( left , right )
2017-09-10 16:57:22 +00:00
return leftInt + rightInt
2017-08-27 09:33:45 +00:00
}
2020-02-11 07:01:13 +00:00
fmap [ "subtract" ] = func ( left , right interface { } ) interface { } {
2018-04-22 12:33:56 +00:00
leftInt , rightInt := arithDuoToInt64 ( left , right )
2017-09-10 16:57:22 +00:00
return leftInt - rightInt
2017-08-27 09:33:45 +00:00
}
2020-02-11 07:01:13 +00:00
fmap [ "multiply" ] = func ( left , right interface { } ) interface { } {
2018-04-22 12:33:56 +00:00
leftInt , rightInt := arithDuoToInt64 ( left , right )
2017-09-10 16:57:22 +00:00
return leftInt * rightInt
2017-08-27 09:33:45 +00:00
}
2020-02-11 07:01:13 +00:00
fmap [ "divide" ] = func ( left , right interface { } ) interface { } {
2018-04-22 12:33:56 +00:00
leftInt , rightInt := arithDuoToInt64 ( left , right )
2017-09-10 16:57:22 +00:00
if leftInt == 0 || rightInt == 0 {
2017-08-27 09:33:45 +00:00
return 0
}
2017-09-10 16:57:22 +00:00
return leftInt / rightInt
2017-08-27 09:33:45 +00:00
}
2020-02-11 07:01:13 +00:00
fmap [ "dock" ] = func ( dock , headerInt interface { } ) interface { } {
2018-04-22 12:33:56 +00:00
return template . HTML ( BuildWidget ( dock . ( string ) , headerInt . ( * Header ) ) )
2017-11-29 02:34:02 +00:00
}
2020-02-11 07:01:13 +00:00
fmap [ "hasWidgets" ] = func ( dock , headerInt interface { } ) interface { } {
2019-02-28 09:31:13 +00:00
return HasWidgets ( dock . ( string ) , headerInt . ( * Header ) )
}
2018-11-17 02:36:02 +00:00
fmap [ "elapsed" ] = func ( startedAtInt interface { } ) interface { } {
return time . Since ( startedAtInt . ( time . Time ) ) . String ( )
}
2018-03-08 03:59:47 +00:00
fmap [ "lang" ] = func ( phraseNameInt interface { } ) interface { } {
phraseName , ok := phraseNameInt . ( string )
if ! ok {
panic ( "phraseNameInt is not a string" )
}
2018-06-17 07:28:18 +00:00
// TODO: Log non-existent phrases?
2019-10-12 22:49:08 +00:00
return template . HTML ( p . GetTmplPhrase ( phraseName ) )
2017-08-27 09:33:45 +00:00
}
2018-03-08 03:59:47 +00:00
2018-12-14 04:08:53 +00:00
// TODO: Implement this in the template generator too
fmap [ "langf" ] = func ( phraseNameInt interface { } , args ... interface { } ) interface { } {
phraseName , ok := phraseNameInt . ( string )
if ! ok {
panic ( "phraseNameInt is not a string" )
}
// TODO: Log non-existent phrases?
// TODO: Optimise TmplPhrasef so we don't use slow Sprintf there
2019-10-12 22:49:08 +00:00
return template . HTML ( p . GetTmplPhrasef ( phraseName , args ... ) )
2018-12-14 04:08:53 +00:00
}
2018-10-10 07:33:51 +00:00
fmap [ "level" ] = func ( levelInt interface { } ) interface { } {
level , ok := levelInt . ( int )
if ! ok {
panic ( "levelInt is not an integer" )
}
2019-10-12 22:49:08 +00:00
return template . HTML ( p . GetLevelPhrase ( level ) )
2018-10-10 07:33:51 +00:00
}
2019-05-13 09:17:44 +00:00
fmap [ "bunit" ] = func ( byteInt interface { } ) interface { } {
var byteFloat float64
var unit string
switch bytes := byteInt . ( type ) {
case int :
byteFloat , unit = ConvertByteUnit ( float64 ( bytes ) )
case int64 :
byteFloat , unit = ConvertByteUnit ( float64 ( bytes ) )
case uint64 :
byteFloat , unit = ConvertByteUnit ( float64 ( bytes ) )
2019-06-01 12:31:48 +00:00
case float64 :
byteFloat , unit = ConvertByteUnit ( bytes )
2019-05-13 09:17:44 +00:00
default :
panic ( "bytes is not an int, int64 or uint64" )
}
return fmt . Sprintf ( "%.1f" , byteFloat ) + unit
}
2018-12-14 04:08:53 +00:00
fmap [ "abstime" ] = func ( timeInt interface { } ) interface { } {
time , ok := timeInt . ( time . Time )
if ! ok {
panic ( "timeInt is not a time.Time" )
}
return time . Format ( "2006-01-02 15:04:05" )
}
2018-12-27 05:42:41 +00:00
fmap [ "reltime" ] = func ( timeInt interface { } ) interface { } {
time , ok := timeInt . ( time . Time )
if ! ok {
panic ( "timeInt is not a time.Time" )
}
return RelativeTime ( time )
}
2018-03-31 05:25:27 +00:00
fmap [ "scope" ] = func ( name interface { } ) interface { } {
return ""
2018-07-13 11:27:58 +00:00
}
2020-02-11 07:01:13 +00:00
fmap [ "dyntmpl" ] = func ( nameInt , pageInt , headerInt interface { } ) interface { } {
2018-07-13 11:27:58 +00:00
header := headerInt . ( * Header )
2018-12-08 00:45:27 +00:00
err := header . Theme . RunTmpl ( nameInt . ( string ) , pageInt , header . Writer )
2018-07-13 11:27:58 +00:00
if err != nil {
return err
}
return ""
2018-03-31 05:25:27 +00:00
}
2020-02-18 23:04:14 +00:00
fmap [ "ptmpl" ] = func ( nameInt , pageInt , headerInt interface { } ) interface { } {
header := headerInt . ( * Header )
err := header . Theme . RunTmpl ( nameInt . ( string ) , pageInt , header . Writer )
if err != nil {
return err
}
return ""
}
fmap [ "js" ] = func ( ) interface { } {
return false
}
2019-04-27 06:32:26 +00:00
fmap [ "flush" ] = func ( ) interface { } {
return nil
}
2019-02-10 05:52:26 +00:00
DefaultTemplateFuncMap = fmap
}
2019-09-29 04:56:39 +00:00
func loadTemplates ( t * template . Template , themeName string ) error {
t . Funcs ( DefaultTemplateFuncMap )
tFiles , err := filepath . Glob ( "templates/*.html" )
2018-03-21 05:56:33 +00:00
if err != nil {
return err
}
2019-12-08 03:40:56 +00:00
2019-09-29 04:56:39 +00:00
tFileMap := make ( map [ string ] int )
for index , path := range tFiles {
2018-03-21 05:56:33 +00:00
path = strings . Replace ( path , "\\" , "/" , - 1 )
log . Print ( "templateFile: " , path )
2018-12-14 04:08:53 +00:00
if skipCTmpl ( path ) {
log . Print ( "skipping" )
continue
}
2019-09-29 04:56:39 +00:00
tFileMap [ path ] = index
2018-03-21 05:56:33 +00:00
}
overrideFiles , err := filepath . Glob ( "templates/overrides/*.html" )
if err != nil {
return err
}
for _ , path := range overrideFiles {
path = strings . Replace ( path , "\\" , "/" , - 1 )
log . Print ( "overrideFile: " , path )
2018-12-14 04:08:53 +00:00
if skipCTmpl ( path ) {
log . Print ( "skipping" )
continue
}
2019-09-29 04:56:39 +00:00
index , ok := tFileMap [ "templates/" + strings . TrimPrefix ( path , "templates/overrides/" ) ]
2018-03-21 05:56:33 +00:00
if ! ok {
log . Print ( "not ok: templates/" + strings . TrimPrefix ( path , "templates/overrides/" ) )
2019-09-29 04:56:39 +00:00
tFiles = append ( tFiles , path )
2018-03-21 05:56:33 +00:00
continue
}
2019-09-29 04:56:39 +00:00
tFiles [ index ] = path
2018-03-21 05:56:33 +00:00
}
2017-11-11 05:22:33 +00:00
2019-02-10 05:52:26 +00:00
if themeName != "" {
overrideFiles , err := filepath . Glob ( "./themes/" + themeName + "/overrides/*.html" )
if err != nil {
return err
}
for _ , path := range overrideFiles {
path = strings . Replace ( path , "\\" , "/" , - 1 )
log . Print ( "overrideFile: " , path )
if skipCTmpl ( path ) {
log . Print ( "skipping" )
continue
}
2019-09-29 04:56:39 +00:00
index , ok := tFileMap [ "templates/" + strings . TrimPrefix ( path , "themes/" + themeName + "/overrides/" ) ]
2019-02-10 05:52:26 +00:00
if ! ok {
log . Print ( "not ok: templates/" + strings . TrimPrefix ( path , "themes/" + themeName + "/overrides/" ) )
2019-09-29 04:56:39 +00:00
tFiles = append ( tFiles , path )
2019-02-10 05:52:26 +00:00
continue
}
2019-09-29 04:56:39 +00:00
tFiles [ index ] = path
2019-02-10 05:52:26 +00:00
}
}
2019-09-29 04:56:39 +00:00
template . Must ( t . ParseFiles ( tFiles ... ) )
template . Must ( t . ParseGlob ( "pages/*" ) )
2017-11-11 05:22:33 +00:00
return nil
2017-08-27 09:33:45 +00:00
}
2019-02-10 05:52:26 +00:00
func InitTemplates ( ) error {
DebugLog ( "Initialising the template system" )
initDefaultTmplFuncMap ( )
// The interpreted templates...
DebugLog ( "Loading the template files..." )
return loadTemplates ( DefaultTemplates , "" )
}