devtools/cmd/css: generate github styles in separate file

This change modifies the script used to generate github styles to save
to a separate css file while converting the px values to rem. Note
thatthe generated styles is formatted properly after run with prettier.

Change-Id: I860e4512a5ff281a6d53210293cb310d5c5e074c
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/258257
Trust: Miguel Acero <acero@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
diff --git a/content/static/css/readme.css b/content/static/css/readme.css
index d83a171..cae35a1 100644
--- a/content/static/css/readme.css
+++ b/content/static/css/readme.css
@@ -1,13 +1,13 @@
 /*
- * Copyright 2020 The Go Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file.
- */
+* Copyright 2019-2020 The Go Authors. All rights reserved.
+* Use of this source code is governed by a BSD-style
+* license that can be found in the LICENSE file.
+*/
 
 /* ---------- */
 /*
 /* The CSS classes below are generated using devtools/cmd/css/main.go
-/* To update, delete the contents below and and run go run devtools/cmd/css/main.go
+/* If the generated CSS already exists, the file is overwritten
 /*
 /* ---------- */
 
@@ -77,11 +77,11 @@
 }
 .Overview-readmeContent hr {
   height: 0;
-  margin: 15px 0;
+  margin: 0.9375rem 0;
   overflow: hidden;
   background: transparent;
   border: 0;
-  border-bottom: 1px solid #dfe2e5;
+  border-bottom: 0.0625rem solid #dfe2e5;
 }
 .Overview-readmeContent hr:after,
 .Overview-readmeContent hr:before {
@@ -104,15 +104,15 @@
 }
 .Overview-readmeContent kbd {
   display: inline-block;
-  padding: 3px 5px;
-  font: 11px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
-  line-height: 10px;
+  padding: 0.1875rem 0.3125rem;
+  font: 0.6875rem SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
+  line-height: 0.625rem;
   color: #444d56;
   vertical-align: middle;
   background-color: #fafbfc;
-  border: 1px solid #d1d5da;
-  border-radius: 3px;
-  box-shadow: inset 0 -1px 0 #d1d5da;
+  border: 0.0625rem solid #d1d5da;
+  border-radius: 0.1875rem;
+  box-shadow: inset 0 -0.0625rem 0 #d1d5da;
 }
 .Overview-readmeContent h1,
 .Overview-readmeContent h2,
@@ -124,38 +124,38 @@
   margin-bottom: 0;
 }
 .Overview-readmeContent h1 {
-  font-size: 32px;
+  font-size: 2rem;
 }
 .Overview-readmeContent h1,
 .Overview-readmeContent h2 {
   font-weight: 600;
 }
 .Overview-readmeContent h2 {
-  font-size: 24px;
+  font-size: 1.5rem;
 }
 .Overview-readmeContent h3 {
-  font-size: 20px;
+  font-size: 1.25rem;
 }
 .Overview-readmeContent h3,
 .Overview-readmeContent h4 {
   font-weight: 600;
 }
 .Overview-readmeContent h4 {
-  font-size: 16px;
+  font-size: 1rem;
 }
 .Overview-readmeContent h5 {
-  font-size: 14px;
+  font-size: 0.875rem;
 }
 .Overview-readmeContent h5,
 .Overview-readmeContent h6 {
   font-weight: 600;
 }
 .Overview-readmeContent h6 {
-  font-size: 12px;
+  font-size: 0.75rem;
 }
 .Overview-readmeContent p {
   margin-top: 0;
-  margin-bottom: 10px;
+  margin-bottom: 0.625rem;
 }
 .Overview-readmeContent blockquote {
   margin: 0;
@@ -182,7 +182,7 @@
 .Overview-readmeContent code,
 .Overview-readmeContent pre {
   font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
-  font-size: 12px;
+  font-size: 0.75rem;
 }
 .Overview-readmeContent pre {
   margin-top: 0;
@@ -204,15 +204,15 @@
 }
 .Overview-readmeContent kbd {
   display: inline-block;
-  padding: 3px 5px;
-  font: 11px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
-  line-height: 10px;
+  padding: 0.1875rem 0.3125rem;
+  font: 0.6875rem SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
+  line-height: 0.625rem;
   color: #444d56;
   vertical-align: middle;
   background-color: #fafbfc;
-  border: 1px solid #d1d5da;
-  border-radius: 3px;
-  box-shadow: inset 0 -1px 0 #d1d5da;
+  border: 0.0625rem solid #d1d5da;
+  border-radius: 0.1875rem;
+  box-shadow: inset 0 -0.0625rem 0 #d1d5da;
 }
 .Overview-readmeContent a:not([href]) {
   color: inherit;
@@ -227,12 +227,12 @@
 .Overview-readmeContent table,
 .Overview-readmeContent ul {
   margin-top: 0;
-  margin-bottom: 16px;
+  margin-bottom: 1rem;
 }
 .Overview-readmeContent hr {
   height: 0.25em;
   padding: 0;
-  margin: 24px 0;
+  margin: 1.5rem 0;
   background-color: #e1e4e8;
   border: 0;
 }
@@ -253,8 +253,8 @@
 .Overview-readmeContent h4,
 .Overview-readmeContent h5,
 .Overview-readmeContent h6 {
-  margin-top: 24px;
-  margin-bottom: 16px;
+  margin-top: 1.5rem;
+  margin-bottom: 1rem;
   font-weight: 600;
   line-height: 1.25;
 }
@@ -264,7 +264,7 @@
 .Overview-readmeContent h1,
 .Overview-readmeContent h2 {
   padding-bottom: 0.3em;
-  border-bottom: 1px solid #eaecef;
+  border-bottom: 0.0625rem solid #eaecef;
 }
 .Overview-readmeContent h2 {
   font-size: 1.5em;
@@ -297,7 +297,7 @@
   word-wrap: break-all;
 }
 .Overview-readmeContent li > p {
-  margin-top: 16px;
+  margin-top: 1rem;
 }
 .Overview-readmeContent li + li {
   margin-top: 0.25em;
@@ -307,14 +307,14 @@
 }
 .Overview-readmeContent dl dt {
   padding: 0;
-  margin-top: 16px;
+  margin-top: 1rem;
   font-size: 1em;
   font-style: italic;
   font-weight: 600;
 }
 .Overview-readmeContent dl dd {
-  padding: 0 16px;
-  margin-bottom: 16px;
+  padding: 0 1rem;
+  margin-bottom: 1rem;
 }
 .Overview-readmeContent table {
   display: block;
@@ -326,12 +326,12 @@
 }
 .Overview-readmeContent table td,
 .Overview-readmeContent table th {
-  padding: 6px 13px;
-  border: 1px solid #dfe2e5;
+  padding: 0.375rem 0.8125rem;
+  border: 0.0625rem solid #dfe2e5;
 }
 .Overview-readmeContent table tr {
   background-color: #fff;
-  border-top: 1px solid #c6cbd1;
+  border-top: 0.0625rem solid #c6cbd1;
 }
 .Overview-readmeContent table tr:nth-child(2n) {
   background-color: #f6f8fa;
@@ -342,17 +342,17 @@
   background-color: #fff;
 }
 .Overview-readmeContent img[align='right'] {
-  padding-left: 20px;
+  padding-left: 1.25rem;
 }
 .Overview-readmeContent img[align='left'] {
-  padding-right: 20px;
+  padding-right: 1.25rem;
 }
 .Overview-readmeContent code {
   padding: 0.2em 0.4em;
   margin: 0;
   font-size: 85%;
   background-color: rgba(27, 31, 35, 0.05);
-  border-radius: 3px;
+  border-radius: 0.1875rem;
 }
 .Overview-readmeContent pre {
   word-wrap: normal;
@@ -367,12 +367,12 @@
   border: 0;
 }
 .Overview-readmeContent pre {
-  padding: 16px;
+  padding: 1rem;
   overflow: auto;
   font-size: 85%;
   line-height: 1.45;
   background-color: #f6f8fa;
-  border-radius: 3px;
+  border-radius: 0.1875rem;
 }
 .Overview-readmeContent pre code {
   display: inline;
@@ -388,6 +388,6 @@
 
 /* ---------- */
 /*
-/* End output from content/static/css/main.go.
+/* End output from devtools/cmd/css/main.go
 /*
 /* ---------- */
diff --git a/devtools/cmd/css/main.go b/devtools/cmd/css/main.go
index 0418488..6324c15 100644
--- a/devtools/cmd/css/main.go
+++ b/devtools/cmd/css/main.go
@@ -14,17 +14,26 @@
 	"bufio"
 	"flag"
 	"fmt"
+	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
+	"regexp"
+	"strconv"
 	"strings"
 )
 
 const (
-	cssFile              = "content/static/css/stylesheet.css"
+	cssFile              = "content/static/css/readme.css"
 	githubStylesheet     = "https://raw.githubusercontent.com/sindresorhus/github-markdown-css/gh-pages/github-markdown.css"
 	githubREADMEClass    = ".markdown-body"
 	discoveryREADMEClass = ".Overview-readmeContent"
+	copyright            = `/*
+* Copyright 2019-2020 The Go Authors. All rights reserved.
+* Use of this source code is governed by a BSD-style
+* license that can be found in the LICENSE file.
+*/
+`
 )
 
 var write = flag.Bool("write", false, "append modifications to content/static/css/stylesheet.css")
@@ -53,6 +62,9 @@
 		if atPropertyStart && shouldIncludeProperty(text) {
 			includeProperty = true
 		}
+		if remString := replaceValueWithRems(text); remString != "" {
+			text = remString
+		}
 		if text == "}" {
 			if includeProperty {
 				properties = append(properties, curr+text+"\n")
@@ -72,6 +84,10 @@
 		log.Fatal(err)
 	}
 
+	if err := ioutil.WriteFile(cssFile, []byte(copyright), 0644); err != nil {
+		log.Fatalf("ioutil.WriteFile(f, '', 0644): %v", err)
+	}
+
 	file, err := os.OpenFile(cssFile, os.O_WRONLY|os.O_APPEND, 0644)
 	if err != nil {
 		log.Fatalf("os.OpenFile(f, os.O_WRONLY|os.O_APPEND, 0644): %v", err)
@@ -92,7 +108,7 @@
 /* ---------- */
 /*
 /* The CSS classes below are generated using devtools/cmd/css/main.go
-/* To update, delete the contents below and and run go run devtools/cmd/css/main.go
+/* If the generated CSS already exists, the file is overwritten
 /*
 /* ---------- */`
 	contentsToWrite += "\n\n"
@@ -104,7 +120,7 @@
 	contentsToWrite += `
 /* ---------- */
 /*
-/* End output from content/static/css/main.go.
+/* End output from devtools/cmd/css/main.go
 /*
 /* ---------- */`
 
@@ -132,3 +148,38 @@
 	}
 	return true
 }
+
+// pxToRem returns the number value of a px string to a rem string.
+func pxToRem(value string) string {
+	valueNum, err := strconv.ParseFloat(value, 32)
+	if err != nil {
+		return ""
+	}
+	valueNum = valueNum / 16
+	return fmt.Sprintf("%frem", valueNum)
+}
+
+// replaceValueWithRems replaces the px values in a line of css with rems.
+// e.g: padding: 25px 10px => padding:
+func replaceValueWithRems(line string) string {
+	var cssLine string
+	valueRegex := regexp.MustCompile(`([-+]?[0-9]*\.?[0-9]+)px`)
+	matches := valueRegex.FindAllStringSubmatchIndex(line, -1)
+	for idx, m := range matches {
+		// e.g: "padding: 6px 13px;" => "padding: 0.375rem 0.8125rem;"
+		//       padding: [valueStartIdx][numStartIdx]25[numEndIdx]px[valueEndIdx] 10em;
+		// The value here is the full string "25px" and num is just "25".
+		valueStartIdx, valueEndIdx, numStartIdx, numEndIdx := m[0], m[1], m[2], m[3]
+		if idx == 0 {
+			cssLine += line[0:valueStartIdx]
+		}
+		cssLine += pxToRem(line[numStartIdx:numEndIdx])
+		if idx == len(matches)-1 {
+			cssLine += line[valueEndIdx:]
+		} else {
+			// If there are more matches for "px", add up until the start of the next match.
+			cssLine += line[valueEndIdx:matches[idx+1][0]]
+		}
+	}
+	return cssLine
+}