Simple spoilers.

This commit is contained in:
Azareal 2019-11-07 07:15:43 +10:00
parent 5441adb7fc
commit cc76d399e5
10 changed files with 135 additions and 37 deletions

View File

@ -143,14 +143,14 @@ func PreparseMessage(msg string) string {
// There are a few useful cases for having spaces, but I'd like to stop the WYSIWYG from inserting random lines here and there // There are a few useful cases for having spaces, but I'd like to stop the WYSIWYG from inserting random lines here and there
msg = SanitiseBody(msg) msg = SanitiseBody(msg)
var runes = []rune(msg) runes := []rune(msg)
msg = "" msg = ""
// TODO: We can maybe reduce the size of this by using an offset? // TODO: We can maybe reduce the size of this by using an offset?
// TODO: Move some of these closures out of this function to make things a little more efficient // TODO: Move some of these closures out of this function to make things a little more efficient
var allowedTags = [][]string{ allowedTags := [][]string{
'e': []string{"m"}, 'e': []string{"m"},
's': []string{"", "trong", "pan"}, 's': []string{"", "trong", "poiler", "pan"},
'd': []string{"el"}, 'd': []string{"el"},
'u': []string{""}, 'u': []string{""},
'b': []string{"", "lockquote"}, 'b': []string{"", "lockquote"},
@ -159,7 +159,7 @@ func PreparseMessage(msg string) string {
//'p': []string{""}, //'p': []string{""},
'g': []string{""}, // Quick and dirty fix for Grammarly 'g': []string{""}, // Quick and dirty fix for Grammarly
} }
var buildLitMatch = func(tag string) func(*TagToAction, bool, int, []rune) (int, string) { buildLitMatch := func(tag string) func(*TagToAction, bool, int, []rune) (int, string) {
return func(action *TagToAction, open bool, _ int, _ []rune) (int, string) { return func(action *TagToAction, open bool, _ int, _ []rune) (int, string) {
if open { if open {
action.Depth++ action.Depth++
@ -172,11 +172,12 @@ func PreparseMessage(msg string) string {
return -1, "</" + tag + ">" return -1, "</" + tag + ">"
} }
} }
var tagToAction = [][]*TagToAction{ tagToAction := [][]*TagToAction{
'e': []*TagToAction{&TagToAction{"m", buildLitMatch("em"), 0, false}}, 'e': []*TagToAction{&TagToAction{"m", buildLitMatch("em"), 0, false}},
's': []*TagToAction{ 's': []*TagToAction{
&TagToAction{"", buildLitMatch("del"), 0, false}, &TagToAction{"", buildLitMatch("del"), 0, false},
&TagToAction{"trong", buildLitMatch("strong"), 0, false}, &TagToAction{"trong", buildLitMatch("strong"), 0, false},
&TagToAction{"poiler", buildLitMatch("spoiler"), 0, false},
// Hides the span tags Trumbowyg loves blasting out randomly // Hides the span tags Trumbowyg loves blasting out randomly
&TagToAction{"pan", func(act *TagToAction, open bool, i int, runes []rune) (int, string) { &TagToAction{"pan", func(act *TagToAction, open bool, i int, runes []rune) (int, string) {
if open { if open {
@ -727,7 +728,7 @@ func validatedURLBytes(data []byte) (url []byte) {
// ? - There should only be one : and that's only if the URL is on a non-standard port. Same for ?s. // ? - There should only be one : and that's only if the URL is on a non-standard port. Same for ?s.
for ; datalen > i; i++ { for ; datalen > i; i++ {
ch := data[i] //char ch := data[i] // char
if ch != '\\' && ch != '_' && ch != ':' && ch != '?' && ch != '&' && ch != '=' && ch != ';' && ch != '@' && ch != '#' && ch != ']' && !(ch > 44 && ch < 58) && !(ch > 64 && ch < 92) && !(ch > 96 && ch < 123) { // 90 is Z, 91 is [ if ch != '\\' && ch != '_' && ch != ':' && ch != '?' && ch != '&' && ch != '=' && ch != ';' && ch != '@' && ch != '#' && ch != ']' && !(ch > 44 && ch < 58) && !(ch > 64 && ch < 92) && !(ch > 96 && ch < 123) { // 90 is Z, 91 is [
return InvalidURL return InvalidURL
} }

View File

@ -24,13 +24,14 @@ var bbcodeURL *regexp.Regexp
var bbcodeURLLabel *regexp.Regexp var bbcodeURLLabel *regexp.Regexp
var bbcodeQuotes *regexp.Regexp var bbcodeQuotes *regexp.Regexp
var bbcodeCode *regexp.Regexp var bbcodeCode *regexp.Regexp
var bbcodeSpoiler *regexp.Regexp
func init() { func init() {
c.Plugins.Add(&c.Plugin{UName: "bbcode", Name: "BBCode", Author: "Azareal", URL: "https://github.com/Azareal", Init: InitBbcode, Deactivate: deactivateBbcode}) c.Plugins.Add(&c.Plugin{UName: "bbcode", Name: "BBCode", Author: "Azareal", URL: "https://github.com/Azareal", Init: InitBbcode, Deactivate: deactivateBbcode})
} }
func InitBbcode(plugin *c.Plugin) error { func InitBbcode(pl *c.Plugin) error {
plugin.AddHook("parse_assign", BbcodeFullParse) pl.AddHook("parse_assign", BbcodeFullParse)
bbcodeInvalidNumber = []byte("<red>[Invalid Number]</red>") bbcodeInvalidNumber = []byte("<red>[Invalid Number]</red>")
bbcodeNoNegative = []byte("<red>[No Negative Numbers]</red>") bbcodeNoNegative = []byte("<red>[No Negative Numbers]</red>")
@ -46,13 +47,14 @@ func InitBbcode(plugin *c.Plugin) error {
bbcodeURLLabel = regexp.MustCompile(`(?s)\[url=` + urlpattern + `\](.*)\[/url\]`) bbcodeURLLabel = regexp.MustCompile(`(?s)\[url=` + urlpattern + `\](.*)\[/url\]`)
bbcodeQuotes = regexp.MustCompile(`\[quote\](.*)\[/quote\]`) bbcodeQuotes = regexp.MustCompile(`\[quote\](.*)\[/quote\]`)
bbcodeCode = regexp.MustCompile(`\[code\](.*)\[/code\]`) bbcodeCode = regexp.MustCompile(`\[code\](.*)\[/code\]`)
bbcodeSpoiler = regexp.MustCompile(`\[spoiler\](.*)\[/spoiler\]`)
bbcodeRandom = rand.New(rand.NewSource(time.Now().UnixNano())) bbcodeRandom = rand.New(rand.NewSource(time.Now().UnixNano()))
return nil return nil
} }
func deactivateBbcode(plugin *c.Plugin) { func deactivateBbcode(pl *c.Plugin) {
plugin.RemoveHook("parse_assign", BbcodeFullParse) pl.RemoveHook("parse_assign", BbcodeFullParse)
} }
func BbcodeRegexParse(msg string) string { func BbcodeRegexParse(msg string) string {
@ -63,6 +65,7 @@ func BbcodeRegexParse(msg string) string {
msg = bbcodeURL.ReplaceAllString(msg, "<a href=''$1$2//$3' rel='ugc'>$1$2//$3</i>") msg = bbcodeURL.ReplaceAllString(msg, "<a href=''$1$2//$3' rel='ugc'>$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href=''$1$2//$3' rel='ugc'>$4</i>") msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href=''$1$2//$3' rel='ugc'>$4</i>")
msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>") msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>")
msg = bbcodeSpoiler.ReplaceAllString(msg, "<spoiler>$1</spoiler>")
msg = bbcodeH1.ReplaceAllString(msg, "<h2>$1</h2>") msg = bbcodeH1.ReplaceAllString(msg, "<h2>$1</h2>")
//msg = bbcodeCode.ReplaceAllString(msg,"<span class='codequotes'>$1</span>") //msg = bbcodeCode.ReplaceAllString(msg,"<span class='codequotes'>$1</span>")
return msg return msg
@ -199,6 +202,7 @@ func BbcodeParseWithoutCode(msg string) string {
msg = string(msgbytes) msg = string(msgbytes)
msg = bbcodeURL.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$1$2//$3</i>") msg = bbcodeURL.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$4</i>") msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$4</i>")
msg = bbcodeSpoiler.ReplaceAllString(msg, "<spoiler>$1</spoiler>")
msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>") msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>")
return bbcodeCode.ReplaceAllString(msg, "<span class='codequotes'>$1</span>") return bbcodeCode.ReplaceAllString(msg, "<span class='codequotes'>$1</span>")
} }
@ -328,6 +332,7 @@ func BbcodeFullParse(msg string) string {
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$4</i>") msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='ugc'>$4</i>")
msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>") msg = bbcodeQuotes.ReplaceAllString(msg, "<blockquote>$1</blockquote>")
msg = bbcodeCode.ReplaceAllString(msg, "<span class='codequotes'>$1</span>") msg = bbcodeCode.ReplaceAllString(msg, "<span class='codequotes'>$1</span>")
msg = bbcodeSpoiler.ReplaceAllString(msg, "<spoiler>$1</spoiler>")
msg = bbcodeH1.ReplaceAllString(msg, "<h2>$1</h2>") msg = bbcodeH1.ReplaceAllString(msg, "<h2>$1</h2>")
} else { } else {
msg = string(msgbytes[0 : len(msgbytes)-10]) msg = string(msgbytes[0 : len(msgbytes)-10])

View File

@ -19,6 +19,8 @@ var markdownStrikeTagOpen []byte
var markdownStrikeTagClose []byte var markdownStrikeTagClose []byte
var markdownQuoteTagOpen []byte var markdownQuoteTagOpen []byte
var markdownQuoteTagClose []byte var markdownQuoteTagClose []byte
var markdownSpoilerTagOpen []byte
var markdownSpoilerTagClose []byte
var markdownH1TagOpen []byte var markdownH1TagOpen []byte
var markdownH1TagClose []byte var markdownH1TagClose []byte
@ -26,8 +28,8 @@ func init() {
c.Plugins.Add(&c.Plugin{UName: "markdown", Name: "Markdown", Author: "Azareal", URL: "https://github.com/Azareal", Init: InitMarkdown, Deactivate: deactivateMarkdown}) c.Plugins.Add(&c.Plugin{UName: "markdown", Name: "Markdown", Author: "Azareal", URL: "https://github.com/Azareal", Init: InitMarkdown, Deactivate: deactivateMarkdown})
} }
func InitMarkdown(plugin *c.Plugin) error { func InitMarkdown(pl *c.Plugin) error {
plugin.AddHook("parse_assign", MarkdownParse) pl.AddHook("parse_assign", MarkdownParse)
markdownUnclosedElement = []byte("<red>[Unclosed Element]</red>") markdownUnclosedElement = []byte("<red>[Unclosed Element]</red>")
@ -41,13 +43,15 @@ func InitMarkdown(plugin *c.Plugin) error {
markdownStrikeTagClose = []byte("</s>") markdownStrikeTagClose = []byte("</s>")
markdownQuoteTagOpen = []byte("<blockquote>") markdownQuoteTagOpen = []byte("<blockquote>")
markdownQuoteTagClose = []byte("</blockquote>") markdownQuoteTagClose = []byte("</blockquote>")
markdownSpoilerTagOpen = []byte("<spoiler>")
markdownSpoilerTagClose = []byte("</spoiler>")
markdownH1TagOpen = []byte("<h2>") markdownH1TagOpen = []byte("<h2>")
markdownH1TagClose = []byte("</h2>") markdownH1TagClose = []byte("</h2>")
return nil return nil
} }
func deactivateMarkdown(plugin *c.Plugin) { func deactivateMarkdown(pl *c.Plugin) {
plugin.RemoveHook("parse_assign", MarkdownParse) pl.RemoveHook("parse_assign", MarkdownParse)
} }
// An adapter for the parser, so that the parser can call itself recursively. // An adapter for the parser, so that the parser can call itself recursively.
@ -251,6 +255,12 @@ func _markdownParse(msg string, n int) string {
if breaking { if breaking {
break break
} }
// TODO: Might need to be double pipe
case '|':
simpleMatch('|', markdownSpoilerTagOpen, markdownSpoilerTagClose)
if breaking {
break
}
case 10: // newline case 10: // newline
if (index + 1) >= len(msg) { if (index + 1) >= len(msg) {
break break
@ -284,8 +294,8 @@ func _markdownParse(msg string, n int) string {
return string(outbytes) return string(outbytes)
} }
func isMarkdownStartChar(char byte) bool { func isMarkdownStartChar(ch byte) bool { // char
return char == '\\' || char == '~' || char == '_' || char == 10 || char == '`' || char == '*' return ch == '\\' || ch == '~' || ch == '_' || ch == 10 || ch == '`' || ch == '*' || ch == '|'
} }
func markdownFindChar(data string, index int, char byte) bool { func markdownFindChar(data string, index int, char byte) bool {

View File

@ -60,6 +60,8 @@ func TestPreparser(t *testing.T) {
l.Add("<em>hi</em>", "<em>hi</em>") l.Add("<em>hi</em>", "<em>hi</em>")
l.Add("<i>hi</i>", "<em>hi</em>") l.Add("<i>hi</i>", "<em>hi</em>")
l.Add("<strong>hi</strong>", "<strong>hi</strong>") l.Add("<strong>hi</strong>", "<strong>hi</strong>")
l.Add("<spoiler>hi</spoiler>", "<spoiler>hi</spoiler>")
l.Add("<g>hi</g>", "hi") // Grammarly fix
l.Add("<b><i>hi</i></b>", "<strong><em>hi</em></strong>") l.Add("<b><i>hi</i></b>", "<strong><em>hi</em></strong>")
l.Add("<strong><em>hi</em></strong>", "<strong><em>hi</em></strong>") l.Add("<strong><em>hi</em></strong>", "<strong><em>hi</em></strong>")
l.Add("<b><i><b>hi</b></i></b>", "<strong><em><strong>hi</strong></em></strong>") l.Add("<b><i><b>hi</b></i></b>", "<strong><em><strong>hi</strong></em></strong>")

View File

@ -59,6 +59,7 @@ func TestBBCodeRender(t *testing.T) {
//l.Add("[b][b][b]hi", "[b][b][b]hi") //l.Add("[b][b][b]hi", "[b][b][b]hi")
//l.Add("[/b]hi", "[/b]hi") //l.Add("[/b]hi", "[/b]hi")
} }
l.Add("[spoiler]hi[/spoiler]", "<spoiler>hi</spoiler>")
l.Add("[code]hi[/code]", "<span class='codequotes'>hi</span>") l.Add("[code]hi[/code]", "<span class='codequotes'>hi</span>")
l.Add("[code][b]hi[/b][/code]", "<span class='codequotes'>[b]hi[/b]</span>") l.Add("[code][b]hi[/b][/code]", "<span class='codequotes'>[b]hi[/b]</span>")
l.Add("[code][b]hi[/code][/b]", "<span class='codequotes'>[b]hi</span>[/b]") l.Add("[code][b]hi[/code][/b]", "<span class='codequotes'>[b]hi</span>[/b]")
@ -91,13 +92,13 @@ func TestBBCodeRender(t *testing.T) {
t.Error("Expected:", "'"+expects+"'") t.Error("Expected:", "'"+expects+"'")
} }
} }
f("[rand][/rand]","<red>[Invalid Number]</red>[rand][/rand]") f("[rand][/rand]", "<red>[Invalid Number]</red>[rand][/rand]")
f("[rand]-1[/rand]","<red>[No Negative Numbers]</red>[rand]-1[/rand]") f("[rand]-1[/rand]", "<red>[No Negative Numbers]</red>[rand]-1[/rand]")
f("[rand]-01[/rand]","<red>[No Negative Numbers]</red>[rand]-01[/rand]") f("[rand]-01[/rand]", "<red>[No Negative Numbers]</red>[rand]-01[/rand]")
f("[rand]NaN[/rand]","<red>[Invalid Number]</red>[rand]NaN[/rand]") f("[rand]NaN[/rand]", "<red>[Invalid Number]</red>[rand]NaN[/rand]")
f("[rand]Inf[/rand]","<red>[Invalid Number]</red>[rand]Inf[/rand]") f("[rand]Inf[/rand]", "<red>[Invalid Number]</red>[rand]Inf[/rand]")
f("[rand]+[/rand]","<red>[Invalid Number]</red>[rand]+[/rand]") f("[rand]+[/rand]", "<red>[Invalid Number]</red>[rand]+[/rand]")
f("[rand]1+1[/rand]","<red>[Invalid Number]</red>[rand]1+1[/rand]") f("[rand]1+1[/rand]", "<red>[Invalid Number]</red>[rand]1+1[/rand]")
msg := "[rand]1[/rand]" msg := "[rand]1[/rand]"
t.Log("Testing string '" + msg + "'") t.Log("Testing string '" + msg + "'")
@ -240,6 +241,7 @@ func TestMarkdownRender(t *testing.T) {
l.Add("~~~", "~~~") l.Add("~~~", "~~~")
l.Add("~~~~", "~~~~") l.Add("~~~~", "~~~~")
l.Add("~~~~~", "~~~~~") l.Add("~~~~~", "~~~~~")
l.Add("|hi|", "<spoiler>hi</spoiler>")
l.Add("__", "__") l.Add("__", "__")
l.Add("___", "___") l.Add("___", "___")
l.Add("_ _", "<u> </u>") l.Add("_ _", "<u> </u>")

View File

@ -905,6 +905,14 @@ function mainInit(){
this.innerText = formattedTime; this.innerText = formattedTime;
}); });
$("spoiler").addClass("hide_spoil");
$(".hide_spoil").click(function(event) {
event.stopPropagation();
event.preventDefault();
$(this).removeClass("hide_spoil");
$(this).unbind("click");
});
this.onkeyup = function(event) { this.onkeyup = function(event) {
if(event.which == 37) this.querySelectorAll("#prevFloat a")[0].click(); if(event.which == 37) this.querySelectorAll("#prevFloat a")[0].click();
if(event.which == 39) this.querySelectorAll("#nextFloat a")[0].click(); if(event.which == 39) this.querySelectorAll("#nextFloat a")[0].click();

View File

@ -1246,6 +1246,25 @@ red {
margin-bottom: 14px; margin-bottom: 14px;
} }
.hide_spoil {
background-color: lightgrey;
color: lightgrey;
}
.hide_spoil img {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 50px;
white-space: nowrap;
width: 1px;
background-color: lightgrey;
}
.hide_spoil img {
content: " ";
}
#ip_search_container .rowlist:not(.has_items) { #ip_search_container .rowlist:not(.has_items) {
display: block; display: block;
} }

View File

@ -221,10 +221,7 @@ li a {
display: flex; display: flex;
padding: 12px; padding: 12px;
} }
.sidebar .rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem { .sidebar .rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem, .sidebar .search {
margin-left: 12px;
}
.sidebar .search {
margin-left: 12px; margin-left: 12px;
} }
.widget_search:first-child { .widget_search:first-child {
@ -253,15 +250,12 @@ li a {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
} }
.colstack_right .colstack_item:not(.colstack_head):not(.rowhead) .rowitem:not(:last-child) { .colstack_right .colstack_item:not(.colstack_head):not(.rowhead) .rowitem:not(:last-child), .rowmsg {
margin-bottom: 8px; margin-bottom: 8px;
} }
.colstack_right .colstack_head:not(:first-child) { .colstack_right .colstack_head:not(:first-child) {
margin-top: 16px; margin-top: 16px;
} }
.rowmsg {
margin-bottom: 8px;
}
h1, h2, h3, h4, h5 { h1, h2, h3, h4, h5 {
-webkit-margin-before: 0; -webkit-margin-before: 0;
@ -912,6 +906,24 @@ blockquote:first-child {
red { red {
color: red; color: red;
} }
.hide_spoil {
background-color: grey;
color: grey;
}
.hide_spoil img {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 50px;
white-space: nowrap;
width: 1px;
background-color: grey;
}
.hide_spoil img {
content: " ";
}
.update_buttons { .update_buttons {
display: flex; display: flex;
background-color: #444444; background-color: #444444;

View File

@ -303,7 +303,6 @@ red {
float: right; float: right;
color: var(--dim-text-color); color: var(--dim-text-color);
} }
.real_username { .real_username {
float: left; float: left;
margin-right: 7px; margin-right: 7px;
@ -361,6 +360,25 @@ red {
margin-left: 3px; margin-left: 3px;
} }
.hide_spoil {
background-color: grey;
color: grey;
}
.hide_spoil img {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 50px;
white-space: nowrap;
width: 1px;
background-color: grey;
}
.hide_spoil img {
content: " ";
}
.formrow.real_first_child, .formrow:first-child { .formrow.real_first_child, .formrow:first-child {
margin-top: 8px; margin-top: 8px;
} }

View File

@ -3,12 +3,10 @@
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
} }
body { body {
font-family: arial; font-family: arial;
padding-bottom: 8px; padding-bottom: 8px;
} }
/* Patch for Edge, until they fix emojis in arial x.x */ /* Patch for Edge, until they fix emojis in arial x.x */
@supports (-ms-ime-align:auto) { .user_content { font-family: Segoe UI Emoji, arial; } } @supports (-ms-ime-align:auto) { .user_content { font-family: Segoe UI Emoji, arial; } }
@ -227,7 +225,6 @@ main > *:last-child {
padding-bottom: 12px; padding-bottom: 12px;
font-size: 16px; font-size: 16px;
} }
/*.grid_istat { /*.grid_istat {
margin-bottom: 5px; margin-bottom: 5px;
}*/ }*/
@ -285,7 +282,6 @@ h1, h2, h3, h4, h5 {
.rowitem:not(:last-child) { .rowitem:not(:last-child) {
border-bottom: 1px solid hsl(0,0%,85%); border-bottom: 1px solid hsl(0,0%,85%);
} }
.rowitem a { .rowitem a {
text-decoration: none; text-decoration: none;
color: black; color: black;
@ -378,7 +374,6 @@ h1, h2, h3, h4, h5 {
width: 100%; width: 100%;
background-color: white; background-color: white;
} }
/* Clearfix */ /* Clearfix */
.formrow:before, .formrow:after { .formrow:before, .formrow:after {
content: " "; content: " ";
@ -803,6 +798,32 @@ red {
padding-right: 5px; padding-right: 5px;
} }
.hide_spoil {
background-color: rgb(220,220,220);
color: rgb(220,220,220) !important;
}
.hide_spoil img {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 50px;
white-space: nowrap;
width: 1px;
background-color: rgb(220,220,220);
}
.hide_spoil img {
content: " ";
}
.staff_post .hide_spoil {
background-color: rgb(240,180,240); /*rgb(255, 234, 255)*/
color: rgb(240,180,240) !important;
}
.staff_post .hide_spoil img {
background-color: rgb(240,180,240);
}
blockquote { blockquote {
border: 1px solid hsl(0, 0%, 80%); border: 1px solid hsl(0, 0%, 80%);
background: white; background: white;