Merge branch 'origin/proxy_v2' into origin/proxy_v2

This commit is contained in:
Damian
2023-12-01 11:26:44 -06:00
committed by GitHub
13 changed files with 190 additions and 73 deletions

View File

@@ -12,16 +12,16 @@ tmp_dir = "tmp"
exclude_regex = ["_test.go"] exclude_regex = ["_test.go"]
exclude_unchanged = false exclude_unchanged = false
follow_symlink = false follow_symlink = false
full_bin = "RULESET=./ruleset.yaml ./tmp/main" full_bin = "./tmp/main --ruleset ./ruleset.yaml"
include_dir = [] include_dir = []
include_ext = ["go", "tpl", "tmpl", "yaml", "html"] include_ext = ["go", "tpl", "tmpl", "yaml", "html", "js"]
include_file = [] include_file = []
kill_delay = "0s" kill_delay = "0s"
log = "build-errors.log" log = "build-errors.log"
poll = false poll = false
poll_interval = 0 poll_interval = 0
post_cmd = [] post_cmd = []
pre_cmd = ["echo 'dev' > handlers/VERSION"] pre_cmd = ["git rev-parse --short HEAD > handlers/VERSION; git rev-parse --short HEAD > cmd/VERSION"]
rerun = false rerun = false
rerun_delay = 500 rerun_delay = 500
send_interrupt = false send_interrupt = false

View File

@@ -4,6 +4,7 @@ on:
push: push:
paths: paths:
- "handlers/form.html" - "handlers/form.html"
- "proxychain/responsemodifiers/generate_readable_outline.html"
workflow_dispatch: workflow_dispatch:
jobs: jobs:

View File

@@ -210,12 +210,12 @@ func main() {
RulesetPath: *ruleset, RulesetPath: *ruleset,
} }
app.Get("api/content/*", handlers.NewAPIOutlineHandler("api/outline/*", proxyOpts)) app.Get("api/content/*", handlers.NewAPIContentHandler("api/outline/*", proxyOpts))
app.Get("outline/*", handlers.NewOutlineHandler("outline/*", proxyOpts)) app.Get("outline/*", handlers.NewOutlineHandler("outline/*", proxyOpts))
app.All("/*", handlers.NewProxySiteHandler(proxyOpts)) app.All("/*", handlers.NewProxySiteHandler(proxyOpts))
fmt.Println(cli.StartupMessage("1.0.0", *port, *ruleset)) fmt.Println(cli.StartupMessage(version, *port, *ruleset))
log.Fatal(app.Listen(":" + *port)) log.Fatal(app.Listen(":" + *port))
} }

View File

@@ -159,13 +159,17 @@ const handleFontChange = () => {
if (mainElement === null) { if (mainElement === null) {
return; return;
} }
const font = localStorage.getItem("font"); let font = localStorage.getItem("font");
if (font === "sans-serif") { if (font === null) {
mainElement.classList.add("font-sans"); localStorage.setItem("font", "sans-serif");
mainElement.classList.remove("font-serif"); font = "sans-serif";
} else { }
if (font === "serif") {
mainElement.classList.add("font-serif"); mainElement.classList.add("font-serif");
mainElement.classList.remove("font-sans"); mainElement.classList.remove("font-sans");
} else {
mainElement.classList.add("font-sans");
mainElement.classList.remove("font-serif");
} }
}; };
@@ -179,9 +183,10 @@ const changeFontSize = (node, classes) => {
"text-2xl", "text-2xl",
"text-3xl", "text-3xl",
"text-4xl", "text-4xl",
"sm:text-3xl", "text-5xl",
"sm:text-4xl", "lg:text-4xl",
"sm:text-5xl", "lg:text-5xl",
"lg:text-6xl",
]; ];
const currentClasses = sizes.filter((size) => node.classList.contains(size)); const currentClasses = sizes.filter((size) => node.classList.contains(size));
node.classList.remove(...currentClasses); node.classList.remove(...currentClasses);
@@ -192,9 +197,21 @@ const handleFontSizeChange = () => {
if (mainElement === null) { if (mainElement === null) {
return; return;
} }
const fontSize = localStorage.getItem("fontsize"); let fontSize = localStorage.getItem("fontsize");
if (fontSize === null) {
localStorage.setItem("fontsize", "text-base");
fontSize = "text-base";
}
if (fontSize === "text-sm") {
changeFontSize(document.querySelector("body"), ["text-sm"]);
} else if (fontSize === "text-lg") {
changeFontSize(document.querySelector("body"), ["text-lg"]);
} else {
changeFontSize(document.querySelector("body"), ["text-base"]);
}
const nodes = document.querySelectorAll( const nodes = document.querySelectorAll(
"h1, h2, h3, h4, code, pre, kbd, table" "h1, h2, h3, h4, h5, h6, code, pre, kbd, table"
); );
if (fontSize === "text-sm") { if (fontSize === "text-sm") {
changeFontSize(mainElement, ["text-sm"]); changeFontSize(mainElement, ["text-sm"]);
@@ -208,12 +225,13 @@ const handleFontSizeChange = () => {
switch (node.tagName) { switch (node.tagName) {
case "H1": { case "H1": {
if (fontSize === "text-sm") { if (fontSize === "text-sm") {
classes = ["text-2xl", "sm:text-3xl"]; classes = ["text-3xl", "lg:text-4xl"];
} else if (fontSize === "text-lg") { } else if (fontSize === "text-lg") {
classes = ["text-4xl", "sm:text-5xl"]; classes = ["text-5xl", "lg:text-6xl"];
} else { } else {
classes = ["text-3xl", "sm:text-4xl"]; classes = ["text-4xl", "lg:text-5xl"];
} }
break;
} }
case "H2": { case "H2": {
if (fontSize === "text-sm") { if (fontSize === "text-sm") {
@@ -235,7 +253,9 @@ const handleFontSizeChange = () => {
} }
break; break;
} }
case "H4": { case "H4":
case "H5":
case "H6": {
if (fontSize === "text-sm") { if (fontSize === "text-sm") {
classes = ["text-lg"]; classes = ["text-lg"];
} else if (fontSize === "text-lg") { } else if (fontSize === "text-lg") {
@@ -259,6 +279,13 @@ const handleFontSizeChange = () => {
break; break;
} }
default: { default: {
if (fontSize === "text-sm") {
classes = ["text-sm"];
} else if (fontSize === "text-lg") {
classes = ["text-lg"];
} else {
classes = ["text-base"];
}
break; break;
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -8,7 +8,7 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func NewAPIOutlineHandler(path string, opts *ProxyOptions) fiber.Handler { func NewAPIContentHandler(path string, opts *ProxyOptions) fiber.Handler {
// TODO: implement ruleset logic // TODO: implement ruleset logic
/* /*
var rs ruleset.RuleSet var rs ruleset.RuleSet

View File

@@ -5,9 +5,14 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/styles.css" /> <link rel="stylesheet" href="/styles.css" />
<title>ladder</title> <title>ladder</title>
<script src="/script.js" defer></script>
<script> <script>
const handleThemeChange = () => { const handleThemeChange = () => {
const theme = localStorage.getItem("theme"); let theme = localStorage.getItem("theme");
if (theme === null) {
localStorage.setItem("theme", "system");
theme = "system";
}
if ( if (
theme === "dark" || theme === "dark" ||
(theme === "system" && (theme === "system" &&
@@ -338,6 +343,5 @@
}); });
} }
</script> </script>
<script src="/script.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,6 +1,9 @@
package cli package cli
import "fmt" import (
"fmt"
"strings"
)
var art string = ` var art string = `
_____╬═╬____________________________________________ _____╬═╬____________________________________________
@@ -10,21 +13,30 @@ var art string = `
|___|╬═╬|___██▪ ▄█▀▀█ ▐█· ▐█▌▐█· ▐█▌▐▀▀▪▄▐▀▀▄ __|_| |___|╬═╬|___██▪ ▄█▀▀█ ▐█· ▐█▌▐█· ▐█▌▐▀▀▪▄▐▀▀▄ __|_|
|_|__╬═╬___|▐█▌▐▌▐█ ▪▐▌██. ██ ██. ██ ▐█▄▄▌▐█•█▌|___| |_|__╬═╬___|▐█▌▐▌▐█ ▪▐▌██. ██ ██. ██ ▐█▄▄▌▐█•█▌|___|
|___|╬═╬|___.▀▀▀ ▀ ▀ ▀▀▀▀▀• ▀▀▀▀▀• ▀▀▀ .▀ ▀__|_| |___|╬═╬|___.▀▀▀ ▀ ▀ ▀▀▀▀▀• ▀▀▀▀▀• ▀▀▀ .▀ ▀__|_|
|_|__╬═╬___|___|___|__ VERSION %s __|___|___|___| |_|__╬═╬___|___|___|_ VERSION %-7s__|___|___|___|
|___|╬═╬|____|___|___|___|___|___|___|___|___|___|_| |___|╬═╬|____|___|___|___|___|___|___|___|___|___|_|
╬═╬
╬═╬ %s
` `
func StartupMessage(version string, port string, ruleset string) string { func StartupMessage(version string, port string, ruleset string) string {
buf := fmt.Sprintf(art, version) version = strings.Trim(version, " ")
buf += fmt.Sprintf("\n > listening on http://localhost:%s\n", port) version = strings.Trim(version, "\n")
link := createHyperlink("http://localhost:" + port)
buf := fmt.Sprintf(art, version, link)
if ruleset == "" { if ruleset == "" {
buf += " ! no ruleset specified.\n > for better performance, use a ruleset using --ruleset\n" buf += "\n ! no ruleset specified.\n > for better performance, use a ruleset using --ruleset\n"
} else { } else {
buf += fmt.Sprintf(" > using ruleset: %s\n", ruleset) buf += fmt.Sprintf("\n > using ruleset: %s\n", ruleset)
} }
return colorizeNonASCII(buf) return colorizeNonASCII(buf)
} }
func createHyperlink(url string) string {
//return fmt.Sprintf("\033]8;;%s\a%s\033]8;;\a", url, url)
return fmt.Sprintf("\033[4m%s\033[0m", url)
}
func colorizeNonASCII(input string) string { func colorizeNonASCII(input string) string {
result := "" result := ""
for _, r := range input { for _, r := range input {

View File

@@ -27,6 +27,15 @@ type TextContent struct {
Data string `json:"data"` Data string `json:"data"`
} }
type ListContent struct {
Type string `json:"type"`
ListItems []ListItemContent `json:"listItems"`
}
type ListItemContent struct {
Data string `json:"data"`
}
type JSONDocument struct { type JSONDocument struct {
Success bool `json:"success"` Success bool `json:"success"`
Error ErrorDetails `json:"error"` Error ErrorDetails `json:"error"`
@@ -35,6 +44,7 @@ type JSONDocument struct {
Author string `json:"author"` Author string `json:"author"`
URL string `json:"url"` URL string `json:"url"`
Hostname string `json:"hostname"` Hostname string `json:"hostname"`
Image string `json:"image"`
Description string `json:"description"` Description string `json:"description"`
Sitename string `json:"sitename"` Sitename string `json:"sitename"`
Date string `json:"date"` Date string `json:"date"`
@@ -58,11 +68,13 @@ func ExtractResultToAPIResponse(extract *trafilatura.ExtractResult) *JSONDocumen
jsonDoc.Metadata.URL = extract.Metadata.URL jsonDoc.Metadata.URL = extract.Metadata.URL
jsonDoc.Metadata.Hostname = extract.Metadata.Hostname jsonDoc.Metadata.Hostname = extract.Metadata.Hostname
jsonDoc.Metadata.Description = extract.Metadata.Description jsonDoc.Metadata.Description = extract.Metadata.Description
jsonDoc.Metadata.Image = extract.Metadata.Image
jsonDoc.Metadata.Sitename = extract.Metadata.Sitename jsonDoc.Metadata.Sitename = extract.Metadata.Sitename
jsonDoc.Metadata.Date = extract.Metadata.Date.Format("2006-01-02") jsonDoc.Metadata.Date = extract.Metadata.Date.Format("2006-01-02")
jsonDoc.Metadata.Categories = extract.Metadata.Categories jsonDoc.Metadata.Categories = extract.Metadata.Categories
jsonDoc.Metadata.Tags = extract.Metadata.Tags jsonDoc.Metadata.Tags = extract.Metadata.Tags
jsonDoc.Metadata.License = extract.Metadata.License jsonDoc.Metadata.License = extract.Metadata.License
jsonDoc.Metadata.Hostname = extract.Metadata.Hostname
// Populate content // Populate content
if extract.ContentNode != nil { if extract.ContentNode != nil {
@@ -120,7 +132,34 @@ func parseContent(node *html.Node) []interface{} {
} }
content = append(content, text) content = append(content, text)
// continue with other tags case "h4":
text := TextContent{
Type: "h4",
Data: dom.InnerText(child),
}
content = append(content, text)
case "h5":
text := TextContent{
Type: "h5",
Data: dom.InnerText(child),
}
content = append(content, text)
case "ul", "ol":
list := ListContent{
Type: child.Data,
ListItems: []ListItemContent{},
}
for listItem := child.FirstChild; listItem != nil; listItem = listItem.NextSibling {
if listItem.Data == "li" {
listItemContent := ListItemContent{
Data: dom.InnerText(listItem),
}
list.ListItems = append(list.ListItems, listItemContent)
}
}
content = append(content, list)
default: default:
text := TextContent{ text := TextContent{

View File

@@ -69,12 +69,14 @@ func GenerateReadableOutline() proxychain.ResponseModification {
"Success": true, "Success": true,
"Image": extract.Metadata.Image, "Image": extract.Metadata.Image,
"Description": extract.Metadata.Description, "Description": extract.Metadata.Description,
"Sitename": extract.Metadata.Sitename,
"Hostname": extract.Metadata.Hostname, "Hostname": extract.Metadata.Hostname,
"Url": "/" + chain.Request.URL.String(), "Url": "/" + chain.Request.URL.String(),
"Title": extract.Metadata.Title, // todo: modify CreateReadableDocument so we don't have <h1> titles duplicated? "Title": extract.Metadata.Title, // todo: modify CreateReadableDocument so we don't have <h1> titles duplicated?
"Date": extract.Metadata.Date.String(), "Date": extract.Metadata.Date.String(),
"Author": extract.Metadata.Author, "Author": createWikipediaSearchLinks(extract.Metadata.Author),
"Body": distilledHTML, //"Author": extract.Metadata.Author,
"Body": distilledHTML,
} }
// ============================================================================ // ============================================================================
@@ -157,3 +159,34 @@ func rewriteHrefLinks(n *html.Node, baseURL string, apiPath string) {
} }
recurse(n) recurse(n)
} }
// createWikipediaSearchLinks takes in comma or semicolon separated terms,
// then turns them into <a> links searching for the term.
func createWikipediaSearchLinks(searchTerms string) string {
semiColonSplit := strings.Split(searchTerms, ";")
var links []string
for i, termGroup := range semiColonSplit {
commaSplit := strings.Split(termGroup, ",")
for _, term := range commaSplit {
trimmedTerm := strings.TrimSpace(term)
if trimmedTerm == "" {
continue
}
encodedTerm := url.QueryEscape(trimmedTerm)
wikiURL := fmt.Sprintf("https://en.wikipedia.org/w/index.php?search=%s", encodedTerm)
link := fmt.Sprintf("<a href=\"%s\">%s</a>", wikiURL, trimmedTerm)
links = append(links, link)
}
// If it's not the last element in semiColonSplit, add a comma to the last link
if i < len(semiColonSplit)-1 {
links[len(links)-1] = links[len(links)-1] + ","
}
}
return strings.Join(links, " ")
}

View File

@@ -7,7 +7,11 @@
<script src="/script.js" defer></script> <script src="/script.js" defer></script>
<script> <script>
const handleThemeChange = () => { const handleThemeChange = () => {
const theme = localStorage.getItem("theme"); let theme = localStorage.getItem("theme");
if (theme === null) {
localStorage.setItem("theme", "system");
theme = "system";
}
if ( if (
theme === "dark" || theme === "dark" ||
(theme === "system" && (theme === "system" &&
@@ -20,7 +24,7 @@
}; };
handleThemeChange(); handleThemeChange();
</script> </script>
<title>ladder | {{ .Title }}</title> <title>ladder | {{.Title}}</title>
</head> </head>
<body <body
@@ -31,9 +35,11 @@
<div <div
class="hover:drop-shadow-[0_0px_4px_rgba(122,167,209,.3)] transition-colors duration-300 focus:outline-none focus:ring focus:border-[#7AA7D1] ring-offset-2" class="hover:drop-shadow-[0_0px_4px_rgba(122,167,209,.3)] transition-colors duration-300 focus:outline-none focus:ring focus:border-[#7AA7D1] ring-offset-2"
> >
<div class="flex">
<a <a
href="/" href="/"
class="flex -ml-2 gap-1 h-8 font-extrabold tracking-tight hover:no-underline focus:outline-none focus:ring focus:border-[#7AA7D1] ring-offset-2" class="flex -ml-2 h-8 font-extrabold tracking-tight hover:no-underline focus:outline-none focus:ring focus:border-[#7AA7D1] ring-offset-2"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -50,10 +56,15 @@
d="M153.196 310.121L133.153 285.021C140.83 283.798 148.978 285.092 156.741 284.353L156.637 277.725L124.406 278.002C123.298 277.325 122.856 276.187 122.058 275.193L116.089 267.862C110.469 260.975 103.827 254.843 98.6026 247.669C103.918 246.839 105.248 246.537 111.14 246.523L129.093 246.327C130.152 238.785 128.62 240.843 122.138 240.758C111.929 240.623 110.659 242.014 105.004 234.661L97.9953 225.654C94.8172 221.729 91.2219 218.104 88.2631 214.005C84.1351 208.286 90.1658 209.504 94.601 209.489L236.752 209.545C257.761 209.569 268.184 211.009 285.766 221.678L285.835 206.051C285.837 197.542 286.201 189.141 284.549 180.748C280.22 158.757 260.541 143.877 240.897 135.739C238.055 134.561 232.259 133.654 235.575 129.851C244.784 119.288 263.680 111.990 277.085 111.105C288.697 109.828 301.096 113.537 311.75 117.703C360.649 136.827 393.225 183.042 398.561 234.866C402.204 270.253 391.733 308.356 367.999 335.1C332.832 374.727 269.877 384.883 223.294 360.397C206.156 351.388 183.673 333.299 175.08 316.6C173.511 313.551 174.005 313.555 170.443 313.52L160.641 313.449C158.957 313.435 156.263 314.031 155.122 312.487L153.196 310.121Z" d="M153.196 310.121L133.153 285.021C140.83 283.798 148.978 285.092 156.741 284.353L156.637 277.725L124.406 278.002C123.298 277.325 122.856 276.187 122.058 275.193L116.089 267.862C110.469 260.975 103.827 254.843 98.6026 247.669C103.918 246.839 105.248 246.537 111.14 246.523L129.093 246.327C130.152 238.785 128.62 240.843 122.138 240.758C111.929 240.623 110.659 242.014 105.004 234.661L97.9953 225.654C94.8172 221.729 91.2219 218.104 88.2631 214.005C84.1351 208.286 90.1658 209.504 94.601 209.489L236.752 209.545C257.761 209.569 268.184 211.009 285.766 221.678L285.835 206.051C285.837 197.542 286.201 189.141 284.549 180.748C280.22 158.757 260.541 143.877 240.897 135.739C238.055 134.561 232.259 133.654 235.575 129.851C244.784 119.288 263.680 111.990 277.085 111.105C288.697 109.828 301.096 113.537 311.75 117.703C360.649 136.827 393.225 183.042 398.561 234.866C402.204 270.253 391.733 308.356 367.999 335.1C332.832 374.727 269.877 384.883 223.294 360.397C206.156 351.388 183.673 333.299 175.08 316.6C173.511 313.551 174.005 313.555 170.443 313.52L160.641 313.449C158.957 313.435 156.263 314.031 155.122 312.487L153.196 310.121Z"
/> />
</svg> </svg>
<span class="text-3xl mr-1 text-[#7AA7D1] leading-8 align-middle"
>ladder | {{.Hostname}}</span
>
</a> </a>
<a
href="/https://{{.Hostname}}"
class="flex ml-1 h-8 font-extrabold tracking-tight hover:no-underline focus:outline-none focus:ring focus:border-[#7AA7D1] ring-offset-2"
>
<span class="text-3xl mr-1 text-[#7AA7D1] leading-8 align-middle">{{.Sitename}}</span>
</a>
</div>
</div> </div>
<div class="flex justify-center z-10"> <div class="flex justify-center z-10">
@@ -303,61 +314,46 @@
</div> </div>
<main class="flex flex-col space-y-3"> <main class="flex flex-col space-y-3">
{{ if not .Success}} {{if not .Success}}
<h1 <h1>
class="text-3xl sm:text-4xl font-extrabold text-slate-900 tracking-tight dark:text-slate-200"
>
Error Error
</h1> </h1>
<p <p>
class="leading-7 [&:not(:first-child)]:mt-6 text-slate-900 dark:text-slate-200"
>
There was a problem querying There was a problem querying
<a <a href="{{.Params}}">{{.Params}}</a>
href="{{ .Params }}"
class="hover:text-blue-500 hover:underline underline-offset-2 transition-colors duration-300"
>{{ .Params }}</a
>
</p> </p>
<code <code class="text-red-500 dark:text-red-400">
class="m-auto text-red-500 dark:text-red-400 relative rounded bg-slate-200 dark:bg-slate-800 px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold" {{.Error}}
>
{{ .Type }}: {{ .Message }}
<div class="my-2">Cause:</div>
{{ .Cause }}
</code> </code>
{{else}} {{else}}
<div class="flex flex-col gap-1 mt-3"> <div class="flex flex-col gap-1 mt-3">
<h1 <h1>
class="text-3xl sm:text-4xl font-extrabold text-slate-900 tracking-tight dark:text-slate-200" <a href="{{.Url}}" class="text-slate-900 dark:text-slate-200"> {{.Title}} </a>
>
<a href="{{.Url}}"> {{.Title}} </a>
</h1> </h1>
{{ if ne .Date "" }} {{if ne .Date ""}}
<small <small
class="text-sm font-medium leading-none text-slate-600 dark:text-slate-400" class="text-sm font-medium leading-none text-slate-600 dark:text-slate-400"
>{{.date}}</small >{{.Date}}</small
> >
{{ end }} {{ if ne .Author "" }} {{end}}
{{if ne .Author ""}}
<small <small
class="text-sm font-medium leading-none text-slate-600 dark:text-slate-400" class="text-sm font-medium leading-none text-slate-600 dark:text-slate-400"
>{{.Author}}</small >{{.Author}}</small
> >
{{ end }} {{end}}
</div> </div>
<div class="flex flex-col space-y-3"> <div class="flex flex-col space-y-3">
<div> <div>
<div class="grid grid-cols-1 justify-items-center"> <div class="grid grid-cols-1 justify-items-center">
<div><img src="{{.Image}}"/></div> <div><img src="{{.Image}}" alt="{{.Description}}" class="h-auto w-auto object-cover max-w-full mx-auto rounded-md shadow-md dark:shadow-slate-700"/></div>
<div class="text-xs text-gray-800">{{.Description}}</div> <div class="mt-2 text-sm text-slate-600 dark:text-slate-400">{{.Description}}</div>
</div> </div>
</div> </div>
<div>{{ .Body }}</div> <div>{{.Body}}</div>
{{ end }} {{end}}
<!-- Trick Tailwind into compiling these styles into styles.css -->
<!-- <div class="hidden text-xs text-sm text-base text-xl text-2xl text-3xl text-4xl sm:text-3xl sm:text-4xl sm:text-5xl"></div> -->
</main> </main>
<div class="my-2"></div> <div class="my-2"></div>

View File

@@ -7,7 +7,7 @@
@apply text-slate-600 dark:text-slate-400 hover:text-blue-500 dark:hover:text-blue-500 hover:underline underline-offset-2 transition-colors duration-300; @apply text-slate-600 dark:text-slate-400 hover:text-blue-500 dark:hover:text-blue-500 hover:underline underline-offset-2 transition-colors duration-300;
} }
h1 { h1 {
@apply text-3xl sm:text-4xl font-extrabold tracking-tight text-slate-900 dark:text-slate-200; @apply scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl text-slate-900 dark:text-slate-200;
} }
h2 { h2 {
@apply scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0 text-slate-900 dark:text-slate-200; @apply scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0 text-slate-900 dark:text-slate-200;
@@ -24,8 +24,9 @@
@apply leading-7 [&:not(:first-child)]:mt-6 text-slate-900 dark:text-slate-200; @apply leading-7 [&:not(:first-child)]:mt-6 text-slate-900 dark:text-slate-200;
} }
kbd, kbd,
pre,
code { code {
@apply relative rounded bg-slate-200 dark:bg-slate-800 px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold; @apply relative whitespace-break-spaces rounded bg-slate-200 dark:bg-slate-800 py-[0.2rem] font-mono text-sm font-semibold;
} }
blockquote { blockquote {
@apply mt-6 border-l-2 pl-6 italic; @apply mt-6 border-l-2 pl-6 italic;

View File

@@ -1,6 +1,10 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ["./handlers/**/*.html"], content: [
"./cmd/**/*.{html,js}",
"./handlers/**/*.{html,js}",
"./proxychain/**/*.{html,js}",
],
darkMode: "class", darkMode: "class",
theme: { theme: {
extend: {}, extend: {},