diff --git a/TODO.md b/TODO.md index 2a863243..2f81d77b 100644 --- a/TODO.md +++ b/TODO.md @@ -9,9 +9,7 @@ More moderation features. E.g. Move, Approval Queue (Posts made by users in cert Add a simple anti-spam measure. I have quite a few ideas in mind, but it'll take a while to implement the more advanced ones, so I'd like to put off some of those to a later date and focus on the basics. E.g. CAPTCHAs, hidden fields, etc. -Add a modern alert system. - -Add per-forum permissions to finish up the foundations of the permissions system. +Add more granular permissions management to the Forum Manager. Add a *better* plugin system. E.g. Allow for plugins written in Javascript and ones written in Go. Also, we need to add many, many, many more plugin hooks. diff --git a/images/alerts.png b/images/alerts.png new file mode 100644 index 00000000..a26240bc Binary files /dev/null and b/images/alerts.png differ diff --git a/images/new-panel-theme-list.png b/images/new-panel-theme-list.png new file mode 100644 index 00000000..0f040466 Binary files /dev/null and b/images/new-panel-theme-list.png differ diff --git a/images/tempra-cursive.png b/images/tempra-cursive.png new file mode 100644 index 00000000..fed58034 Binary files /dev/null and b/images/tempra-cursive.png differ diff --git a/mod_routes.go b/mod_routes.go index fe6692d6..d196a521 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -1410,15 +1410,21 @@ func route_panel_themes(w http.ResponseWriter, r *http.Request){ return } - var themeList []interface{} + var pThemeList []Theme + var vThemeList []Theme for _, theme := range themes { if theme.HideFromThemes { continue } - themeList = append(themeList,theme) + if theme.ForkOf == "" { + pThemeList = append(pThemeList,theme) + } else { + vThemeList = append(vThemeList,theme) + } + } - pi := Page{"Theme Manager",user,noticeList,themeList,nil} + pi := ThemesPage{"Theme Manager",user,noticeList,pThemeList,vThemeList,nil} err := templates.ExecuteTemplate(w,"panel-themes.html",pi) if err != nil { log.Print(err) diff --git a/pages.go b/pages.go index db61fa48..e6c584dc 100644 --- a/pages.go +++ b/pages.go @@ -1,4 +1,6 @@ package main +//import "fmt" +import "bytes" import "strings" import "regexp" @@ -73,6 +75,16 @@ type CreateTopicPage struct ExtData interface{} } +type ThemesPage struct +{ + Title string + CurrentUser User + NoticeList []string + PrimaryThemes []Theme + VariantThemes []Theme + ExtData interface{} +} + type PageSimple struct { Title string @@ -85,6 +97,12 @@ type AreYouSure struct Message string } +var space_gap []byte = []byte(" ") +var http_prot_b []byte = []byte("http://") +var invalid_url []byte = []byte("[Invalid URL]") +var url_open []byte = []byte("") +var url_close []byte = []byte("") var urlpattern string = `(?s)([ {1}])((http|https|ftp|mailto)*)(:{??)\/\/([\.a-zA-Z\/]+)([ {1}])` var url_reg *regexp.Regexp @@ -144,6 +162,89 @@ func preparse_message(msg string) string { } func parse_message(msg string) string { + msg = strings.Replace(msg,":)","😀",-1) + msg = strings.Replace(msg,":D","😃",-1) + msg = strings.Replace(msg,":P","😛",-1) + //msg = url_reg.ReplaceAllString(msg,"$2$3//$4") + + // Search for URLs in the messages... + var msgbytes = []byte(msg) + outbytes := make([]byte, len(msgbytes)) + msgbytes = append(msgbytes,space_gap...) + //fmt.Println(`"`+string(msgbytes)+`"`) + lastItem := 0 + i := 0 + for ; len(msgbytes) > (i + 1); i++ { + if i==0 || msgbytes[i] == 10 || (msgbytes[i] == ' ' && msgbytes[i + 1] != ' ') { + i++ + if msgbytes[i] != 'h' && msgbytes[i] != 'f' && msgbytes[i] != 'g' && msgbytes[i + 1] != 't' { + continue + } + if msgbytes[i + 2] == 't' && msgbytes[i + 3] == 'p' { + if msgbytes[i + 4] == 's' && msgbytes[i + 5] == ':' && msgbytes[i + 6] == '/' && msgbytes[i + 7] == '/' { + // Do nothing + } else if msgbytes[i + 4] == ':' && msgbytes[i + 5] == '/' && msgbytes[i + 6] == '/' { + // Do nothing + } else { + continue + } + } else if msgbytes[i + 2] == 'p' && msgbytes[i + 3] == ':' && msgbytes[i + 4] == '/' && msgbytes[i + 5] == '/' { + // Do nothing + } else if msgbytes[i + 1] == 'i' && msgbytes[i + 2] == 't' && msgbytes[i + 3] == ':' && msgbytes[i + 4] == '/' && msgbytes[i + 5] == '/' { + // Do nothing + } else { + continue + } + + outbytes = append(outbytes,msgbytes[lastItem:i]...) + url_len := partial_url_bytes_len(msgbytes[i:]) + if msgbytes[i + url_len] != ' ' && msgbytes[i + url_len] != 10 { + outbytes = append(outbytes,invalid_url...) + i += url_len + continue + } + //fmt.Println("Parsed URL:") + //fmt.Println("`"+string(msgbytes[i:i + url_len])+"`") + //fmt.Println("-----") + outbytes = append(outbytes, url_open...) + outbytes = append(outbytes, msgbytes[i:i + url_len]...) + outbytes = append(outbytes, url_open2...) + outbytes = append(outbytes, msgbytes[i:i + url_len]...) + outbytes = append(outbytes, url_close...) + i += url_len + lastItem = i + } + } + + if lastItem != i && len(outbytes) != 0 { + //fmt.Println("lastItem:") + //fmt.Println(msgbytes[lastItem]) + //fmt.Println("lastItem index:") + //fmt.Println(lastItem) + //fmt.Println("i:") + //fmt.Println(i) + //fmt.Println("lastItem to end:") + //fmt.Println(msgbytes[lastItem:]) + //fmt.Println("-----") + calclen := len(msgbytes) - 10 + if calclen <= lastItem { + calclen = lastItem + } + outbytes = append(outbytes, msgbytes[lastItem:calclen]...) + msg = string(outbytes) + } + //fmt.Println(`"`+string(outbytes)+`"`) + //fmt.Println(`"`+msg+`"`) + + msg = strings.Replace(msg,"\n","
",-1) + if hooks["parse_assign"] != nil { + out := run_hook("parse_assign", msg) + msg = out.(string) + } + return msg +} + +func regex_parse_message(msg string) string { msg = strings.Replace(msg,":)","😀",-1) msg = strings.Replace(msg,":D","😃",-1) msg = strings.Replace(msg,":P","😛",-1) @@ -154,4 +255,144 @@ func parse_message(msg string) string { msg = out.(string) } return msg -} \ No newline at end of file +} + +// 6, 7, 8, 6, 7 +// ftp://, http://, https:// git://, mailto: (not a URL, just here for length comparison purposes) +func validate_url_bytes(data []byte) bool { + datalen := len(data) + i := 0 + + if datalen >= 6 { + if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + i = 6 + } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + i = 7 + } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + i = 8 + } + } + + for ;datalen > i; i++ { + if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { + return false + } + } + return true +} + +func validated_url_bytes(data []byte) (url []byte) { + datalen := len(data) + i := 0 + + if datalen >= 6 { + if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + i = 6 + } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + i = 7 + } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + i = 8 + } + } + + for ;datalen > i; i++ { + if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { + return invalid_url + } + } + + url = append(url, data...) + return url +} + +func partial_url_bytes(data []byte) (url []byte) { + datalen := len(data) + i := 0 + end := datalen - 1 + + if datalen >= 6 { + if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + i = 6 + } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + i = 7 + } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + i = 8 + } + } + + for ;end >= i; i++ { + if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { + end = i + } + } + + url = append(url, data[0:end]...) + return url +} + +func partial_url_bytes_len(data []byte) int { + datalen := len(data) + i := 0 + + if datalen >= 6 { + //fmt.Println(data[0:5]) + //fmt.Println(string(data[0:5])) + if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + i = 6 + } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + i = 7 + //fmt.Println("http") + } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + i = 8 + } else { + //fmt.Println("no protocol") + } + } + + for ;datalen > i; i++ { + if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { + //fmt.Println("Trimmed Length") + //fmt.Println(i) + //fmt.Println("Full Length") + //fmt.Println(i) + //fmt.Println("Data Length:") + //fmt.Println(datalen) + //fmt.Println("Bad Character:") + //fmt.Println(data[i]) + return i + } + } + + //fmt.Println("Data Length:") + //fmt.Println(datalen) + return datalen +} + +func parse_media_bytes(data []byte) (protocol []byte, url []byte) { + datalen := len(data) + i := 0 + + if datalen >= 6 { + if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + i = 6 + protocol = data[0:2] + } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + i = 7 + protocol = []byte("http") + } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + i = 8 + protocol = []byte("https") + } + } + + for ;datalen > i; i++ { + if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { + return []byte(""), invalid_url + } + } + + if len(protocol) == 0 { + protocol = []byte("http") + } + return protocol, data[i:] +} diff --git a/plugin_bbcode.go b/plugin_bbcode.go index 75ade75a..3a7d8281 100644 --- a/plugin_bbcode.go +++ b/plugin_bbcode.go @@ -9,13 +9,8 @@ import "time" import "math/rand" var random *rand.Rand -var bbcode_invalid_url []byte var bbcode_invalid_number []byte var bbcode_missing_tag []byte -var bbcode_url_open []byte -var bbcode_url_open2 []byte -var bbcode_url_close []byte -var bbcode_space_gap []byte var bbcode_bold *regexp.Regexp var bbcode_italic *regexp.Regexp @@ -23,6 +18,7 @@ var bbcode_underline *regexp.Regexp var bbcode_strikethrough *regexp.Regexp var bbcode_url *regexp.Regexp var bbcode_url_label *regexp.Regexp +var bbcode_quotes *regexp.Regexp func init() { plugins["bbcode"] = NewPlugin("bbcode","BBCode","Azareal","http://github.com/Azareal","","","",init_bbcode,nil,deactivate_bbcode) @@ -32,13 +28,8 @@ func init_bbcode() { //plugins["bbcode"].AddHook("parse_assign", bbcode_parse_without_code) plugins["bbcode"].AddHook("parse_assign", bbcode_full_parse) - bbcode_invalid_url = []byte("[Invalid URL]") bbcode_invalid_number = []byte("[Invalid Number]") bbcode_missing_tag = []byte("[Missing Tag]") - bbcode_url_open = []byte("") - bbcode_url_close = []byte("") - bbcode_space_gap = []byte(" ") bbcode_bold = regexp.MustCompile(`(?s)\[b\](.*)\[/b\]`) bbcode_italic = regexp.MustCompile(`(?s)\[i\](.*)\[/i\]`) @@ -47,6 +38,7 @@ func init_bbcode() { urlpattern := `(http|https|ftp|mailto*)(:??)\/\/([\.a-zA-Z\/]+)` bbcode_url = regexp.MustCompile(`\[url\]` + urlpattern + `\[/url\]`) bbcode_url_label = regexp.MustCompile(`(?s)\[url=` + urlpattern + `\](.*)\[/url\]`) + bbcode_quotes = regexp.MustCompile(`\[quote\](.*)\[/quote\]`) random = rand.New(rand.NewSource(time.Now().UnixNano())) } @@ -64,6 +56,7 @@ func bbcode_regex_parse(data interface{}) interface{} { msg = bbcode_strikethrough.ReplaceAllString(msg,"$1") msg = bbcode_url.ReplaceAllString(msg,"$1$2//$3") msg = bbcode_url_label.ReplaceAllString(msg,"$4") + msg = bbcode_quotes.ReplaceAllString(msg,"
$1
") return msg } @@ -177,6 +170,7 @@ func bbcode_parse_without_code(data interface{}) interface{} { if complex_bbc { msg = bbcode_url.ReplaceAllString(msg,"
$1$2//$3") msg = bbcode_url_label.ReplaceAllString(msg,"$4") + msg = bbcode_quotes.ReplaceAllString(msg,"
$1
") } return string(msgbytes) } @@ -184,6 +178,9 @@ func bbcode_parse_without_code(data interface{}) interface{} { // Does every type of BBCode func bbcode_full_parse(data interface{}) interface{} { msg := data.(string) + //fmt.Println("BBCode PrePre String:") + //fmt.Println("`"+msg+"`") + //fmt.Println("----") msgbytes := []byte(msg) has_u := false has_b := false @@ -191,7 +188,10 @@ func bbcode_full_parse(data interface{}) interface{} { has_s := false has_c := false complex_bbc := false - msgbytes = append(msgbytes,bbcode_space_gap...) + msgbytes = append(msgbytes,space_gap...) + //fmt.Println("BBCode Simple Pre:") + //fmt.Println("`"+string(msgbytes)+"`") + //fmt.Println("----") for i := 0; i < len(msgbytes); i++ { if msgbytes[i] == '[' { if msgbytes[i + 2] != ']' { @@ -275,59 +275,36 @@ func bbcode_full_parse(data interface{}) interface{} { var start int var lastTag int outbytes := make([]byte, len(msgbytes)) - //fmt.Println(string(msgbytes)) + //fmt.Println("BBCode Pre:") + //fmt.Println("`"+string(msgbytes)+"`") + //fmt.Println("----") for ; i < len(msgbytes); i++ { MainLoop: if msgbytes[i] == '[' { OuterComplex: if msgbytes[i + 1] == 'u' { if msgbytes[i+2] == 'r' && msgbytes[i+3] == 'l' && msgbytes[i+4] == ']' { - outbytes = append(outbytes, msgbytes[lastTag:i]...) start = i + 5 + outbytes = append(outbytes, msgbytes[lastTag:i]...) i = start - if msgbytes[i] == 'h' { - if msgbytes[i+1] == 't' && msgbytes[i+2] == 't' && msgbytes[i+3] == 'p' { - if bytes.Equal(msgbytes[i + 4:i + 7],[]byte("s://")) { - i += 7 - } else if msgbytes[i+4] == ':' && msgbytes[i+5] == '/' && msgbytes[i+6] == '/' { - i += 6 - } else { - outbytes = append(outbytes, bbcode_invalid_url...) - continue - } - } - } else if msgbytes[i] == 'f' { - if bytes.Equal(msgbytes[i+1:i+5],[]byte("tp://")) { - i += 5 - } + i += partial_url_bytes_len(msgbytes[start:]) + + //fmt.Println("Partial Bytes:") + //fmt.Println(string(msgbytes[start:])) + //fmt.Println("-----") + if !bytes.Equal(msgbytes[i:i+6],[]byte("[/url]")) { + //fmt.Println("Invalid Bytes:") + //fmt.Println(string(msgbytes[i:i+6])) + //fmt.Println("-----") + outbytes = append(outbytes, invalid_url...) + goto MainLoop } - for ;; i++ { - if len(msgbytes) < (i + 10) { - //fmt.Println(msglen) - //fmt.Println(i+6) - outbytes = append(outbytes, bbcode_missing_tag...) - goto OuterComplex - } else if msgbytes[i] == '[' { - if !bytes.Equal(msgbytes[i+1:i+6],[]byte("/url]")) { - //log.Print("Not the URL closing tag!") - //fmt.Println(msgbytes[i + 1:i + 6]) - outbytes = append(outbytes, bbcode_missing_tag...) - goto OuterComplex - } - break - } else if msgbytes[i] != '\\' && msgbytes[i] != '_' && !(msgbytes[i] > 44 && msgbytes[i] < 58) && !(msgbytes[i] > 64 && msgbytes[i] < 91) && !(msgbytes[i] > 96 && msgbytes[i] < 123) { - outbytes = append(outbytes, bbcode_invalid_url...) - //log.Print("Weird character") - //fmt.Println(msgbytes[i]) - goto MainLoop - } - } - outbytes = append(outbytes, bbcode_url_open...) + outbytes = append(outbytes, url_open...) outbytes = append(outbytes, msgbytes[start:i]...) - outbytes = append(outbytes, bbcode_url_open2...) + outbytes = append(outbytes, url_open2...) outbytes = append(outbytes, msgbytes[start:i]...) - outbytes = append(outbytes, bbcode_url_close...) + outbytes = append(outbytes, url_close...) i += 6 lastTag = i } @@ -367,15 +344,25 @@ func bbcode_full_parse(data interface{}) interface{} { //fmt.Println(string(outbytes)) if lastTag != i { outbytes = append(outbytes, msgbytes[lastTag:]...) - } - if len(outbytes) != 0 { - return string(outbytes[0:len(msgbytes) - 10]) + //fmt.Println("Outbytes:") + //fmt.Println(`"`+string(outbytes)+`"`) + //fmt.Println("----") + } + + if len(outbytes) != 0 { + //fmt.Println("BBCode Post:") + //fmt.Println(`"`+string(outbytes[0:len(outbytes) - 10])+`"`) + //fmt.Println("----") + msg = string(outbytes[0:len(outbytes) - 10]) + } else { + msg = string(msgbytes[0:len(msgbytes) - 10]) } - msg = string(msgbytes[0:len(msgbytes) - 10]) //msg = bbcode_url.ReplaceAllString(msg,"
$1$2//$3") msg = bbcode_url_label.ReplaceAllString(msg,"$4") + msg = bbcode_quotes.ReplaceAllString(msg,"
$1
") // Convert [code] into class="codequotes" + //fmt.Println("guuuaaaa") } else { msg = string(msgbytes[0:len(msgbytes) - 10]) } diff --git a/routes.go b/routes.go index 59e6eae0..1e778aeb 100644 --- a/routes.go +++ b/routes.go @@ -780,7 +780,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { } _, err = users.CascadeGet(createdBy) - if err != nil && err != sql.ErrNoRows { + if err != nil && err == sql.ErrNoRows { LocalError("The target user doesn't exist",w,r,user) return } else if err != nil { diff --git a/template_list.go b/template_list.go index ae8162f9..660ede29 100644 --- a/template_list.go +++ b/template_list.go @@ -67,7 +67,7 @@ var topic_8 []byte = []byte(`
-

`) var topic_51 []byte = []byte(` -

`) -var topic_57 []byte = []byte(`



+var topic_57 []byte = []byte(`

`) var topic_59 []byte = []byte(`  @@ -162,7 +162,7 @@ var topic_71 []byte = []byte(`😀`) var topic_73 []byte = []byte(``) var topic_74 []byte = []byte(``) -var topic_75 []byte = []byte(``) +var topic_75 []byte = []byte(``) var topic_76 []byte = []byte(`👑`) var topic_77 []byte = []byte(`
diff --git a/templates/panel-themes.html b/templates/panel-themes.html index 26f7ca6e..7e0c1a6a 100644 --- a/templates/panel-themes.html +++ b/templates/panel-themes.html @@ -2,10 +2,28 @@ {{template "panel-menu.html" . }}
- +
- {{range .ItemList}} + {{range .PrimaryThemes}} +
+ + {{.FriendlyName}}
+ Author: {{.Creator}} +
+ + {{if .MobileFriendly}}📱{{end}} + {{if .Tag}}{{.Tag}}{{end}} + {{if .Active}}Default{{else}}Make Default{{end}} + +
+ {{end}} +
+
+ +
+
+ {{range .VariantThemes}}
{{.FriendlyName}}
diff --git a/templates/topic.html b/templates/topic.html index 0d8c407c..747eb562 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -4,7 +4,7 @@ {{end}}
-
+
{{.Topic.Title}} {{if .Topic.Is_Closed}}🔒︎{{end}} {{if .CurrentUser.Perms.EditTopic}} @@ -21,7 +21,7 @@

{{.Topic.Content}}

-

+ {{.Topic.CreatedByName}}  {{if .CurrentUser.Perms.LikeItem}} {{end}} {{if .CurrentUser.Perms.EditTopic}} {{end}} @@ -29,19 +29,19 @@ {{if .CurrentUser.Perms.PinTopic}}{{if .Topic.Sticky}}{{else}} {{end}}{{end}}   {{if .Topic.LikeCount}}{{.Topic.LikeCount}}😀{{end}} - {{if .Topic.Tag}}{{.Topic.Tag}}{{else}}{{.Topic.Level}}👑{{end}} + {{if .Topic.Tag}}{{.Topic.Tag}}{{else}}{{.Topic.Level}}👑{{end}}

{{range .ItemList}} -
-

{{.ContentHtml}}



+
+

{{.ContentHtml}}

{{.CreatedByName}}  {{if $.CurrentUser.Perms.LikeItem}} {{end}} {{if $.CurrentUser.Perms.EditReply}} {{end}} {{if $.CurrentUser.Perms.DeleteReply}} {{end}}   {{if .LikeCount}}{{.LikeCount}}😀{{end}} - {{if .Tag}}{{.Tag}}{{else}}{{.Level}}👑{{end}} + {{if .Tag}}{{.Tag}}{{else}}{{.Level}}👑{{end}}
{{end}}
{{if .CurrentUser.Perms.CreateReply}} diff --git a/themes.go b/themes.go index a7217a96..4563dcd7 100644 --- a/themes.go +++ b/themes.go @@ -27,6 +27,7 @@ type Theme struct MobileFriendly bool Disabled bool HideFromThemes bool + ForkOf string Tag string Settings map[string]ThemeSetting Templates []TemplateMapping diff --git a/themes/cosmo-classic/theme.json b/themes/cosmo-classic/theme.json index 1c8bdbe3..6401d3bf 100644 --- a/themes/cosmo-classic/theme.json +++ b/themes/cosmo-classic/theme.json @@ -5,7 +5,7 @@ "Creator": "Azareal", "Disabled": true, "HideFromThemes": true, - "Tag": "WIP", + "Tag": "🏗️", "Templates": [ { "Name": "topic", diff --git a/themes/cosmo-conflux/public/main.css b/themes/cosmo-conflux/public/main.css index 9b761bb0..570b6846 100644 --- a/themes/cosmo-conflux/public/main.css +++ b/themes/cosmo-conflux/public/main.css @@ -450,6 +450,15 @@ button .big { padding: 6px; }*/ font-size: 15px; } +.postQuote { + padding: 5px; + border: 1px solid rgb(200,200,200); + display: inline-block; + margin-bottom: 5px; + width: 100%; + background: rgb(250,250,250); +} + .threadHidden { background: orange; } .threadDeleted { background: rgba(255,0,0,0.5); } diff --git a/themes/cosmo-conflux/theme.json b/themes/cosmo-conflux/theme.json index 9dc15c44..a1cd21f3 100644 --- a/themes/cosmo-conflux/theme.json +++ b/themes/cosmo-conflux/theme.json @@ -4,6 +4,7 @@ "Version": "Coming Soon", "Creator": "Azareal", "FullImage": "cosmo-conflux.png", + "ForkOf": "cosmo", "MobileFriendly": true, "Templates": [ { diff --git a/themes/cosmo/public/main.css b/themes/cosmo/public/main.css index 3ccdc7c1..24555ba9 100644 --- a/themes/cosmo/public/main.css +++ b/themes/cosmo/public/main.css @@ -439,6 +439,16 @@ button .big { padding: 6px; }*/ font-size: 15px; } +.postQuote { + border-radius: 4px; + padding: 5px; + border: 1px solid rgb(200,200,200); + display: inline-block; + margin-bottom: 5px; + width: 100%; + background: rgb(250,250,250); +} + .threadHidden { background: orange; } .threadDeleted { background: rgba(255,0,0,0.5); } diff --git a/themes/tempra-conflux/public/main.css b/themes/tempra-conflux/public/main.css index 26130f15..4e3faaa9 100644 --- a/themes/tempra-conflux/public/main.css +++ b/themes/tempra-conflux/public/main.css @@ -353,6 +353,19 @@ button.username position: relative; top: -0.25px; } + +.postQuote { + border: rgb(200,200,210); + background: rgb(245,245,255); + padding: 3px; + margin: 0px; + display: inline-block; + width: 100%; + margin-bottom: 5px; + border-style: solid; + border-width: 1px; +} + .tag-mini { text-transform: none; diff --git a/themes/tempra-cursive/public/main.css b/themes/tempra-cursive/public/main.css new file mode 100644 index 00000000..c1724ed1 --- /dev/null +++ b/themes/tempra-cursive/public/main.css @@ -0,0 +1,497 @@ +* { + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +body +{ + font-family: cursive; + padding-bottom: 8px; +} + +/* Patch for Edge */ +@supports (-ms-ime-align:auto) { + .user_content { font-family: Segoe UI Emoji, arial; } +} + +ul +{ + padding-left: 0px; + padding-right: 0px; + height: 28px; + list-style-type: none; + border: 1px solid #ccc; + background-color: white; +} +li +{ + height: 26px; + padding-left: 10px; + padding-top: 5px; + padding-bottom: 5px; + font-weight: bold; + text-transform: uppercase; +} +li:hover { background: rgb(250,250,250); } +li a +{ + text-decoration: none; + color: #515151; +} +/*li a:hover { color: #7a7a7a; }*/ +.menu_left +{ + float: left; + border-right: 1px solid #ccc; + padding-right: 10px; + font-family: cursive; + padding-top: 2px; +} +.menu_right +{ + float: right; + border-left: 1px solid #ccc; + padding-right: 10px; +} + +.menu_alerts { + padding-left: 7px; + padding-top: 2px; + color: rgb(80,80,80); +} +.menu_alerts .alert_counter { + position:relative; + font-size: 9px; + top: -24px; + background-color: rgb(140,0,0); + color: white; + padding: 3px; + width: 14px; + left: 10px; + line-height: 8px; + border-radius: 20px; + padding-top: 2.5px; + height: 14px; + opacity: 0.8; + text-align: center; +} +.menu_alerts .alert_counter:empty { + display: none; +} + +.selectedAlert { + background: white; + color: black; +} +.selectedAlert:hover { + background: white; + color: black; +} +.menu_alerts .alertList { + display: none; + text-transform: none; +} +.selectedAlert .alertList { + position: absolute; + top: 43px; + display: block; + background: white; + font-size: 10px; + line-height: 16px; + width: 135px; + right: calc(5% + 7px); + border-top: 1px solid #ccc; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} +.alertItem { + padding: 8px; + overflow: hidden; + text-overflow: ellipsis; +} +.alertItem.withAvatar { + background-size: auto 56px; + background-repeat: no-repeat; + text-align: right; + padding-right: 12px; + height: 46px; +} +.alertItem.withAvatar:not(:last-child) { + border-bottom: 1px solid rgb(230,230,230); +} +.alertItem.withAvatar .text { + overflow: hidden; + text-overflow: ellipsis; + float: right; + width: calc(100% - 20px); + height: 30px; +} + +.container +{ + width: 90%; + padding: 0px; + margin-left: auto; + margin-right: auto; +} + +.rowblock +{ + border: 1px solid #ccc; + width: 100%; + padding: 0px; + padding-top: 0px; +} +.rowblock:empty { display: none; } + +.colblock_left +{ + border: 1px solid #ccc; + padding: 0px; + padding-top: 0px; + width: 30%; + float: left; + margin-right: 8px; +} +.colblock_right +{ + border: 1px solid #ccc; + padding: 0px; + padding-top: 0px; + width: 65%; + overflow: hidden; + word-wrap: break-word; +} +.colblock_left:empty { display: none; } +.colblock_right:empty { display: none; } + +.rowhead { font-family: cursive; } +.rowitem +{ + width: 100%; + padding-left: 8px; + padding-right: 8px; + padding-top: 17px; + padding-bottom: 12px; + font-weight: bold; + text-transform: uppercase; + background-color: white; +} +.rowitem.passive +{ + font-weight: normal; + text-transform: none; +} +.rowitem:not(:last-child) +{ + border-bottom: 1px dotted #ccc; +} +.rowitem a +{ + text-decoration: none; + color: black; +} +.rowitem a:hover { color: silver; } +.opthead { display: none; } + +.col_left +{ + width: 30%; + float: left; +} +.col_right +{ + width: 69%; + overflow: hidden; +} +.colitem +{ + padding-left: 8px; + padding-right: 8px; + padding-top: 17px; + padding-bottom: 12px; + font-weight: bold; + text-transform: uppercase; +} +.colitem.passive +{ + font-weight: normal; + text-transform: none; +} +.colitem a +{ + text-decoration: none; + color: black; +} +.colitem a:hover { color: silver; } + +.formrow +{ + width: 100%; + background-color: white; +} + +/* Clearfix */ +.formrow:before, .formrow:after { + content: " "; + display: table; +} +.formrow:after { clear: both; } + +.formrow:not(:last-child) +{ + border-bottom: 1px dotted #ccc; +} + +.formitem +{ + float: left; + padding-left: 8px; + padding-right: 8px; + padding-top: 13px; + padding-bottom: 8px; + font-weight: bold; +} + +.formitem:first-child { font-weight: bold; } +.formitem:not(:last-child) { border-right: 1px dotted #ccc; } +.formitem.invisible_border { border: none; } + +/* Mostly for textareas */ +.formitem:only-child { width: 100%; } +.formitem textarea +{ + width: 100%; + height: 100px; + outline-color: #8e8e8e; +} +.formitem:has-child() +{ + margin: 0 auto; + float: none; +} + +button +{ + background: white; + border: 1px solid #8e8e8e; +} + +/* Topics */ +.topic_status +{ + text-transform: none; + margin-left: 8px; + padding-left: 2px; + padding-right: 2px; + padding-top: 2px; + padding-bottom: 2px; + background-color: #E8E8E8; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */ + color: #505050; /* 80,80,80 */ + border-radius: 2px; +} +.topic_status:empty { display: none; } + +.username +{ + text-transform: none; + margin-left: 0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 2px; + padding-bottom: 2px; + color: #505050; /* 80,80,80 */ + font-size: 15px; + background: none; +} +button.username +{ + position: relative; + top: -0.25px; +} +.username.level { color: #303030; } +.username.real_username { color: #404040; font-size: 17px; padding-right: 4px; } +.username.real_username:hover { color: black; } + +.tag-text { + padding-top: 23px; + display: inline-block; +} + +.post_item > .username { + padding-top: 23px; + display: inline-block; +} + +.tag-mini +{ + text-transform: none; + margin-left: 0px; + padding-left: 3px; + padding-right: 3px; + padding-top: 1.5px; + padding-bottom: 0px; + color: #505050; /* 80,80,80 */ + background-color: #FFFFFF; + border-style: dotted; + border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */ + border-width: 1px; + font-size: 10px; +} + +.post_item > .mod_button > button { + font-size: 15px; + color: #202020; + opacity: 0.7; + border: none; +} +.post_item > .mod_button > button:hover { + opacity: 0.9; +} + +.postQuote { + border: 1px solid #ccc; + background: white; + padding: 3px; + margin: 0px; + display: inline-block; + width: 100%; + margin-bottom: 5px; +} + +.level { + float: right; + color: #505050; + border-left: none; + padding-left: 3px; + padding-right: 5px; + font-size: 16px; +} + +.show_on_edit { display: none; } +.alert +{ + display: block; + padding: 5px; + margin-bottom: 10px; + border: 1px solid #ccc; +} +.alert_success +{ + display: block; + padding: 5px; + border: 1px solid A2FC00; + margin-bottom: 10px; + background-color: DAF7A6; +} +.alert_error +{ + display: block; + padding: 5px; + border: 1px solid #FF004B; + margin-bottom: 8px; + background-color: #FEB7CC; +} +.prev_button, .next_button { + position: fixed; + top: 50%; + font-size: 30px; + border-width: 1px; + background-color: #FFFFFF; + border-style: dotted; + border-color: #505050; + padding: 0px; + padding-left: 5px; + padding-right: 5px; + z-index: 100; +} + +.prev_button a, .next_button a { + line-height: 28px; + margin-top: 2px; + margin-bottom: 0px; + display: block; + text-decoration: none; + color: #505050; +} +.prev_button { left: 14px; } +.next_button { right: 14px; } + +@media (max-width: 880px) { + li { height: 25px; font-size: 15px; padding-left: 7px; } + ul { height: 26px; margin-top: 8px; } + .menu_left { padding-right: 7px; } + .menu_right { padding-right: 7px; } + body { padding-left: 4px; padding-right: 4px; margin: 0px !important; width: 100% !important; height: 100% !important; overflow-x: hidden; } + .container { width: auto; } + .selectedAlert .alertList { top: 33px; right: 4px; } +} + +@media (max-width: 810px) { + li { font-weight: normal; text-transform: none; } + .rowitem { text-transform: none; } + /*.rowhead { font-family: arial; } + .menu_left { font-family: arial; }*/ + body { font-family: arial; } + .level { font-size: 17px; } +} + +@media (max-width: 620px) { + li + { + padding-left: 5px; + padding-top: 2px; + padding-bottom: 2px; + height: 23px; + } + ul { height: 24px; } + .menu_left { padding-right: 5px; } + .menu_right { padding-right: 5px; } + .menu_create_topic { display: none;} + .menu_alerts { padding-left: 4px; padding-right: 4px; } + .hide_on_mobile { display: none; } + .prev_button, .next_button { top: auto; bottom: 5px; } +} + +@media (max-width: 470px) { + .menu_overview { display: none; } + .menu_profile { display: none; } + .hide_on_micro { display: none; } + .post_container { + overflow: visible !important; + } + .post_item { + background-position: 0px 2px !important; + background-size: 64px 64px !important; + padding-left: 2px !important; + min-height: 96px; + position: relative !important; + } + .post_item > .user_content { + margin-left: 75px !important; + width: 100% !important; + } + .post_item > .mod_button { + float: right !important; + margin-left: 2px !important; + position: relative; + top: -14px; + } + .post_item > .mod_button > button { + opacity: 1; + } + .post_item > .real_username { + position: absolute; + top: 70px; + float: left; + margin-top: -2px; + padding-top: 3px !important; + margin-right: 2px; + width: 60px; + font-size: 15px; + text-align: center; + } + .container { width: 100% !important; } +} \ No newline at end of file diff --git a/themes/tempra-cursive/tempra-cursive.png b/themes/tempra-cursive/tempra-cursive.png new file mode 100644 index 00000000..fed58034 Binary files /dev/null and b/themes/tempra-cursive/tempra-cursive.png differ diff --git a/themes/tempra-cursive/theme.json b/themes/tempra-cursive/theme.json new file mode 100644 index 00000000..a6c91fe1 --- /dev/null +++ b/themes/tempra-cursive/theme.json @@ -0,0 +1,10 @@ +{ + "Name": "tempra-cursive", + "FriendlyName": "Tempra Cursive", + "Version": "0.0.1", + "Creator": "Azareal", + "FullImage": "tempra-cursive.png", + "ForkOf": "tempra-simple", + "Tag": "🏗️", + "MobileFriendly": true +} \ No newline at end of file diff --git a/themes/tempra-simple/public/main.css b/themes/tempra-simple/public/main.css index 7a3014d4..826446b3 100644 --- a/themes/tempra-simple/public/main.css +++ b/themes/tempra-simple/public/main.css @@ -316,6 +316,12 @@ button.username .username.level { color: #303030; } .username.real_username { color: #404040; font-size: 17px; } .username.real_username:hover { color: black; } + +.post_item > .username { + margin-top: 44.2px; + display: inline-block; +} + .tag-mini { text-transform: none; @@ -341,6 +347,25 @@ button.username opacity: 0.9; } +.postQuote { + border: 1px solid #ccc; + background: white; + padding: 3px; + margin: 0px; + display: inline-block; + width: 100%; + margin-bottom: 5px; +} + +.level { + float: right; + color: #505050; + border-left: none; + padding-left: 5px; + padding-right: 5px; + font-size: 17px; +} + .show_on_edit { display: none; } .alert { @@ -401,11 +426,7 @@ button.username } @media (max-width: 810px) { - li - { - font-weight: normal; - text-transform: none; - } + li { font-weight: normal; text-transform: none; } .rowitem { text-transform: none; } } @@ -450,9 +471,7 @@ button.username position: relative; top: -14px; } - .post_item > .mod_button > button { - opacity: 1; - } + .post_item > .mod_button > button { opacity: 1; } .post_item > .real_username { position: absolute; top: 70px;