Compare commits

...

25 commits

Author SHA1 Message Date
partisan
84a3c7e21e added particles.min.js 2024-09-29 21:22:02 +02:00
partisan
51bb3e0df8 changed button's behavior on the news site 2024-09-29 20:34:40 +02:00
partisan
6efb5b5d6f remove CDATA wrapper 2024-09-09 21:56:40 +02:00
partisan
08774dd6f4 smaller images/vids for blog 2024-09-09 20:55:45 +02:00
partisan
a77f93842a fixed favicon, updated image gallery 2024-09-03 20:12:33 +02:00
partisan
c81dd751e9 made font smaller 2024-08-31 11:48:32 +02:00
partisan
37a628ad09 added lazy loading to img for blogs 2024-08-29 22:48:35 +02:00
0f3895bebd Update README.md 2024-08-27 20:19:12 +00:00
partisan
aeb7bd7634 added img slider 2024-08-27 22:16:13 +02:00
partisan
0254061fa4 improved formatting to blog.css 2024-08-26 18:46:40 +02:00
partisan
492e0765af fix oopsie 2024-08-26 18:11:00 +02:00
partisan
469903dc9c fixed incorrect notifications and removed deprecated lib 2024-08-26 18:08:24 +02:00
partisan
0bc34bdbf0 limit acess to assets news folder 2024-08-26 11:05:34 +02:00
partisan
9b3b5a5419 fix rss images + more compatability hopefully 2024-08-26 10:39:50 +02:00
partisan
50a1a14f41 added "try search" 2024-08-25 22:06:29 +02:00
partisan
f2b72cc1b8 formatting fro blog site 2024-08-25 00:08:22 +02:00
partisan
4a13ba939e added /news-assets 2024-08-24 19:07:36 +02:00
partisan
5892c0af38 rss news 2024-08-22 22:10:47 +02:00
partisan
d69f561c55 oopsie 2024-08-22 19:10:14 +02:00
partisan
b890637222 updated blog 2024-08-16 14:46:31 +02:00
partisan
980008d8e5 Adde blog update 2024-08-16 14:46:02 +02:00
partisan
ef91b8a8ad added clickable logo 2024-08-14 14:54:40 +02:00
partisan
635d6589c9 added meta dag to not run darkreader 2024-08-14 14:36:27 +02:00
partisan
1d820b5590 added flag for port 2024-08-14 14:18:58 +02:00
03c7678499 Merge pull request 'new website' (#1) from blog-implementation into main
Reviewed-on: #1
2024-08-14 12:03:29 +00:00
34 changed files with 5985 additions and 5244 deletions

4
.gitignore vendored
View file

@ -1 +1,3 @@
elements.html elements.html
notified_entries.json
data/

View file

@ -1,22 +1,54 @@
# Spitfire Browser Website <p align="center">
<img src="https://weforgecode.xyz/Spitfire/Branding/raw/branch/main/icon5.svg" alt="Logo" width="64" height="64">
Spitfire Browser is a fast, secure, and elegant web browser built on Firefox. This repository contains the source code for the Spitfire Browser's official website. </p>
## TO-DO: <p align="center" style="font-size: 32px;">
<strong>Spitfire Browser Website</strong>
- [ ] Add screenshots </p>
- [ ] Add search-engine test <p align="center">
Unlike some other browser sites flexing with their 98.8% TypeScript (yikes), i keep it cool with minimal JavaScript just enough to get the job done.
- [ ] Add working downloads </p>
- [ ] Add blog/updates <p align="center">
Spitfire Browser's website is built without Next.js, TypeScript, and Tailwind CSS or any other BS.
### Based on: </p>
Stellar by HTML5 UP ## TO-DO:
html5up.net | @ajlkn
- [ ] Add browser download/screenshots for this web browser website (optional)
### Licence:
### Blog entries should be fromated this way:
This project is licensed under the Creative Commons Attribution 3.0 License (CCA 3.0). For more details, see the LICENSE file.
```md
[HEADER]
t: TITLE
d: SHORT-DESC
p: 2024-08-16 15:04
a: AUTHOR
[END]
# lorem ipsum
Vestibulum fermentum tortor id mi. Nullam at arcu a est sollicitudin euismod. Nullam faucibus mi quis velit. Mauris dictum facilisis augue. Nullam sapien sem, ornare ac, nonummy non, lobortis a enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Etiam commodo dui eget wisi. Mauris dictum facilisis augue. Etiam posuere lacus quis dolor. In sem justo, commodo ut, suscipit at, pharetra vitae, orci.
Vivamus luctus egestas leo. Phasellus faucibus molestie nisl. Etiam commodo dui eget wisi. Donec vitae arcu. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam neque. Suspendisse sagittis ultrices augue. Suspendisse nisl. Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. Phasellus rhoncus. Maecenas libero.
```
*default path:*
```
/data/news/1.md
/data/news/2.md
...
```
### Based on HTML template:
[Stellar](https://html5up.net/stellar) by HTML5 UP
html5up.net | @ajlkn
### Licence:
This project is licensed under the Creative Commons Attribution 3.0 License (CCA 3.0). For more details, see the LICENSE file.

View file

@ -1,5 +0,0 @@
# lorem ipsum
Vestibulum fermentum tortor id mi. Nullam at arcu a est sollicitudin euismod. Nullam faucibus mi quis velit. Mauris dictum facilisis augue. Nullam sapien sem, ornare ac, nonummy non, lobortis a enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Etiam commodo dui eget wisi. Mauris dictum facilisis augue. Etiam posuere lacus quis dolor. In sem justo, commodo ut, suscipit at, pharetra vitae, orci.
Vivamus luctus egestas leo. Phasellus faucibus molestie nisl. Etiam commodo dui eget wisi. Donec vitae arcu. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam neque. Suspendisse sagittis ultrices augue. Suspendisse nisl. Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. Phasellus rhoncus. Maecenas libero.

View file

@ -1,3 +0,0 @@
# lorem ipsum
Fusce nibh. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor. Aliquam in lorem sit amet leo accumsan lacinia. Fusce wisi. Curabitur sagittis hendrerit ante. Mauris elementum mauris vitae tortor. Nulla accumsan, elit sit amet varius semper, nulla mauris mollis quam, tempor suscipit diam nulla vel leo. Phasellus rhoncus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor. Aenean placerat. Nullam feugiat, turpis at pulvinar vulputate, erat libero tristique tellus, nec bibendum odio risus sit amet ante. Cras elementum. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Maecenas lorem. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.

View file

@ -1,3 +0,0 @@
# lorem ipsum
Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. Nulla turpis magna, cursus sit amet, suscipit a, interdum id, felis. Etiam dui sem, fermentum vitae, sagittis id, malesuada in, quam. Nullam faucibus mi quis velit. Aliquam erat volutpat. Duis bibendum, lectus ut viverra rhoncus, dolor nunc faucibus libero, eget facilisis enim ipsum id lacus. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis risus. In laoreet, magna id viverra tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Nam sed tellus id magna elementum tincidunt. Donec vitae arcu. Etiam bibendum elit eget erat.

View file

@ -1,3 +0,0 @@
# lorem ipsum
Mauris dictum facilisis augue. Nullam at arcu a est sollicitudin euismod. Praesent dapibus. Suspendisse sagittis ultrices augue. Integer imperdiet lectus quis justo. Duis bibendum, lectus ut viverra rhoncus, dolor nunc faucibus libero, eget facilisis enim ipsum id lacus. Pellentesque sapien. Fusce dui leo, imperdiet in, aliquam sit amet, feugiat eu, orci. Maecenas ipsum velit, consectetuer eu lobortis ut, dictum at dui. Etiam dictum tincidunt diam. Vestibulum fermentum tortor id mi. Phasellus enim erat, vestibulum vel, aliquam a, posuere eu, velit. Pellentesque pretium lectus id turpis. In sem justo, commodo ut, suscipit at, pharetra vitae, orci. Maecenas aliquet accumsan leo. Morbi leo mi, nonummy eget tristique non, rhoncus non leo. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

View file

@ -7,8 +7,6 @@ import (
"net/http" "net/http"
) )
const discordWebhookURL = "YOUR_DISCORD_WEBHOOK_URL" // Replace with your Discord webhook URL
type DiscordWebhookPayload struct { type DiscordWebhookPayload struct {
Content string `json:"content"` Content string `json:"content"`
} }

26
go.mod
View file

@ -1,13 +1,13 @@
module my-web module spitfire-browser-website
go 1.18 go 1.18
require ( require (
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 // indirect github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 // indirect
github.com/gorilla/feeds v1.2.0 // indirect github.com/gorilla/feeds v1.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/technoweenie/multipartstreamer v1.0.1 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect
golang.org/x/sys v0.4.0 // indirect golang.org/x/sys v0.4.0 // indirect
) )

1094
main.go

File diff suppressed because it is too large Load diff

100
rss.go
View file

@ -3,65 +3,119 @@ package main
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"strings"
"time" "time"
"github.com/gorilla/feeds" "github.com/gorilla/feeds"
"github.com/russross/blackfriday/v2"
) )
func generateRSSFeed(w http.ResponseWriter, blogs []Blog, siteURL string) { func generateAtomFeed(w http.ResponseWriter, blogs []Blog, siteURL string) {
feed := &feeds.Feed{ feed := &feeds.Feed{
Title: "My Blog", Title: "Spitfire News",
Link: &feeds.Link{Href: siteURL}, Link: &feeds.Link{Href: siteURL},
Description: "A blog about various topics.", Description: "Blog about Spitfire browser news/updates.", // Blog subtitle (Atom uses "subtitle" for description)
Author: &feeds.Author{Name: "Your Name", Email: "your-email@example.com"}, Author: &feeds.Author{Name: "Internet Addict", Email: "noone@none.no"},
Created: time.Now(), Created: time.Now(),
} }
// Add self link
feed.Link = &feeds.Link{Href: fmt.Sprintf("%s/rss", siteURL), Rel: "self"}
for _, blog := range blogs { for _, blog := range blogs {
for _, entry := range blog.Entries { for _, entry := range blog.Entries {
// Convert Markdown content to HTML
htmlContent := blackfriday.Run([]byte(entry.Content))
// Ensure all image paths are absolute URLs (Idiot proofing)
absoluteContent := strings.ReplaceAll(string(htmlContent), "src=\"/", fmt.Sprintf("src=\"%s/", siteURL))
// Ensure unique and stable ID
entryID := fmt.Sprintf("%s/%s/%d", siteURL, blog.Name, entry.Number)
// Create a summary if needed (using the first 200 characters of the content, for example)
summary := entry.Description
if summary == "" {
if len(entry.Content) > 200 {
summary = entry.Content[:200] + "..."
} else {
summary = entry.Content
}
}
feed.Items = append(feed.Items, &feeds.Item{ feed.Items = append(feed.Items, &feeds.Item{
Title: fmt.Sprintf("Entry %d", entry.Number), // Use entry number as title Title: entry.Title,
Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/%d", siteURL, blog.Name, entry.Number)}, Link: &feeds.Link{Href: entryID, Rel: "alternate"},
Description: entry.Content, Description: summary, // This can be used as the summary
Created: entry.Date, Author: &feeds.Author{Name: entry.Author},
Id: entryID,
Updated: entry.Date,
Content: absoluteContent,
}) })
} }
} }
rss, err := feed.ToRss() // Generate Atom feed with the correct content-type and charset
w.Header().Set("Content-Type", "application/atom+xml; charset=UTF-8")
atom, err := feed.ToAtom()
if err != nil { if err != nil {
http.Error(w, "Error generating RSS feed", http.StatusInternalServerError) http.Error(w, "Error generating Atom feed", http.StatusInternalServerError)
return return
} }
w.Header().Set("Content-Type", "application/rss+xml") w.Write([]byte(atom))
w.Write([]byte(rss))
} }
func generateBlogRSSFeed(w http.ResponseWriter, blog Blog, siteURL string) { func generateBlogAtomFeed(w http.ResponseWriter, blog Blog, siteURL string) {
feed := &feeds.Feed{ feed := &feeds.Feed{
Title: blog.Name, Title: blog.Name,
Link: &feeds.Link{Href: fmt.Sprintf("%s/%s", siteURL, blog.Name)}, Link: &feeds.Link{Href: fmt.Sprintf("%s/%s", siteURL, blog.Name)},
Description: blog.Name, Description: blog.Name, // Blog subtitle (Atom uses "subtitle" for description)
Author: &feeds.Author{Name: "Your Name", Email: "your-email@example.com"}, Author: &feeds.Author{Name: "Internet Addict", Email: "noone@none.no"},
Created: time.Now(), Created: time.Now(),
} }
// Add self link
feed.Link = &feeds.Link{Href: fmt.Sprintf("%s/%s/rss", siteURL, blog.Name), Rel: "self"}
for _, entry := range blog.Entries { for _, entry := range blog.Entries {
// Convert Markdown content to HTML
htmlContent := blackfriday.Run([]byte(entry.Content))
// Ensure all image paths are absolute URLs (Idiot proofing)
absoluteContent := strings.ReplaceAll(string(htmlContent), "src=\"/", fmt.Sprintf("src=\"%s/", siteURL))
// Ensure unique and stable ID
entryID := fmt.Sprintf("%s/%s/%d", siteURL, blog.Name, entry.Number)
// Create a summary if needed (using the first 200 characters of the content, for example)
summary := entry.Description
if summary == "" {
if len(entry.Content) > 200 {
summary = entry.Content[:200] + "..."
} else {
summary = entry.Content
}
}
feed.Items = append(feed.Items, &feeds.Item{ feed.Items = append(feed.Items, &feeds.Item{
Title: fmt.Sprintf("Entry %d", entry.Number), // Use entry number as title Title: entry.Title,
Link: &feeds.Link{Href: fmt.Sprintf("%s/%s/%d", siteURL, blog.Name, entry.Number)}, Link: &feeds.Link{Href: entryID, Rel: "alternate"},
Description: entry.Content, Description: summary, // This can be used as the summary
Created: entry.Date, Author: &feeds.Author{Name: entry.Author},
Id: entryID,
Updated: entry.Date,
Content: absoluteContent,
}) })
} }
rss, err := feed.ToRss() // Generate Atom feed with the correct content-type and charset
w.Header().Set("Content-Type", "application/atom+xml; charset=UTF-8")
atom, err := feed.ToAtom()
if err != nil { if err != nil {
http.Error(w, "Error generating RSS feed", http.StatusInternalServerError) http.Error(w, "Error generating Atom feed", http.StatusInternalServerError)
return return
} }
w.Header().Set("Content-Type", "application/rss+xml") w.Write([]byte(atom))
w.Write([]byte(rss))
} }

21
run.bat Normal file
View file

@ -0,0 +1,21 @@
@echo off
REM Default values
set PORT=8080
REM Parse command-line arguments
:parse_args
if "%~1"=="" goto run_app
if "%~1"=="-p" (
set PORT=%~2
shift
shift
goto parse_args
) else (
echo Unknown parameter passed: %~1
exit /b 1
)
:run_app
REM Run the Go application with the parsed flags
go run discord.go rss.go telegram.go save.go main.go -p=%PORT%

15
run.sh
View file

@ -1,3 +1,16 @@
#!/bin/bash
# Default values
PORT=8080
go run discord.go rss.go telegram.go main.go # Parse command-line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
-p|--port) PORT="$2"; shift ;;
*) echo "Unknown parameter passed: $1"; exit 1 ;;
esac
shift
done
# Run the Go application with the parsed flags
go run discord.go rss.go telegram.go save.go main.go -p=$PORT

50
save.go Normal file
View file

@ -0,0 +1,50 @@
package main
import (
"encoding/json"
"log"
"os"
"time"
)
func loadNotifiedEntries() {
file, err := os.Open(notifiedFilePath)
if err != nil {
if os.IsNotExist(err) {
return
}
log.Fatalf("Error loading notified entries: %v", err)
}
defer file.Close()
err = json.NewDecoder(file).Decode(&notifiedEntries)
if err != nil {
log.Fatalf("Error decoding notified entries: %v", err)
}
}
func saveNotifiedEntry(entryNumber int) {
notifiedEntries[entryNumber] = true
file, err := os.Create(notifiedFilePath)
if err != nil {
log.Fatalf("Error saving notified entries: %v", err)
}
defer file.Close()
err = json.NewEncoder(file).Encode(notifiedEntries)
if err != nil {
log.Fatalf("Error encoding notified entries: %v", err)
}
}
func checkAndSendNotifications() {
for _, blog := range blogs {
for _, entry := range blog.Entries {
if !entry.Notified && !time.Now().Before(entry.Date) {
sendNotifications(entry)
entry.Notified = true
saveNotifiedEntry(entry.Number)
}
}
}
}

51
static/css/blog.css Normal file
View file

@ -0,0 +1,51 @@
/* Global settings for images and videos */
img, video {
display: block;
width: 85%;
height: auto;
margin: 20px auto; /* Centers the image/video horizontally and adds space above and below */
border-radius: 10px; /* Add rounded corners */
}
/* Exclude images inside the .icons class from global settings */
ul.icons img {
display: inline; /* Override display: block */
width: auto; /* Override width: 100% */
border-radius: 0; /* Remove rounded corners */
margin-top: 0; /* Remove top margin */
margin-bottom: 0; /* Remove bottom margin */
}
/* Align blog text and links */
.align-blog p, a, em {
text-align: left;
font-size: 1em;
line-height: 1.6;
}
/* Increase margin top for all headings */
.align-blog h1,
.align-blog h2,
.align-blog h3,
.align-blog h4,
.align-blog h5,
.align-blog h6 {
margin-top: 30px; /* Adjust this value to increase space above headings */
}
/* Icons specific styles */
ul.icons {
cursor: default;
list-style: none;
padding-left: 0;
}
ul.icons li {
display: inline-block;
padding: 0 0.65em 0 0;
}
ul.icons li:last-child {
padding-right: 0 !important;
}

View file

@ -23,4 +23,20 @@
width: 48px; width: 48px;
height: 48px; height: 48px;
overflow: visible; overflow: visible;
} }
.the-slider img {
width: 90%;
height: auto;
margin: 0 auto;
border-radius: 10px;
}
#particles-js {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1; /* This value must be lower than other elements! */
}

View file

@ -1,64 +1,139 @@
.fancy-gallery { /* Adjust the gallery wrapper */
display: grid; .gallery-wrapper {
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); position: relative;
gap: 20px; width: 100%;
margin-top: 30px; max-width: 800px;
} margin: 0 auto; /* Center the gallery */
overflow: hidden; /* Ensure content is within bounds */
.gallery-item { }
position: relative;
overflow: hidden; .gallery-wrapper img {
border-radius: 15px; display: block;
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2); width: 100%;
transform: scale(1); height: auto;
transition: transform 0.4s ease-in-out, filter 0.4s ease-in-out; border: 1px solid #dddddd3d;
} }
.gallery-item img { /* Slick carousel specific styles */
width: 100%; .slick-prev, .slick-next {
height: 100%; background: #444; /* Button background color */
object-fit: cover; border: none; /* Remove any border */
transition: transform 0.6s ease, filter 0.6s ease; border-radius: 50%; /* Make the buttons circular */
} color: #fff; /* Text color */
font-size: 18px; /* Font size for the arrow */
.gallery-item::before { height: 40px; /* Button height */
content: ''; width: 40px; /* Button width */
position: absolute; line-height: 40px; /* Center text vertically */
top: 0; text-align: center; /* Center text horizontally */
left: 0; z-index: 1000; /* Make sure buttons are above the carousel images */
width: 100%; position: absolute;
height: 100%; top: 50%; /* Position vertically centered */
background: linear-gradient(45deg, rgba(255, 0, 150, 0.3), rgba(0, 204, 255, 0.3)); transform: translateY(-50%);
mix-blend-mode: overlay; }
opacity: 0;
transition: opacity 0.6s ease; .slick-prev {
} left: 0px;
}
.gallery-item:hover {
transform: scale(1.05); .slick-next {
filter: brightness(1.2); right: 0px;
} }
.gallery-item:hover img { /* Center the dots under the image */
transform: scale(1.1) rotate(2deg); .slick-dots {
filter: grayscale(20%) text-align: center;
} margin-top: 15px; /* Space between image and dots */
padding-left: 0;
.gallery-item:hover::before { list-style: none;
opacity: 1; }
}
.slick-dots li {
@keyframes pulse { display: inline-block; /* Align dots horizontally */
0%, 100% { margin: 0 8px; /* Space between dots */
transform: scale(1); }
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2);
} .slick-dots li button {
50% { background: #ccc; /* Dot background color */
transform: scale(1.02); border: none; /* Remove any border */
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3); border-radius: 50%; /* Make the dots circular */
} width: 12px; /* Dot width */
} height: 12px; /* Dot height */
position: relative;
.gallery-item { }
animation: pulse 5s infinite;
} .slick-dots li button::before {
content: '';
display: block;
width: 16px; /* Adjusted circle width */
height: 16px; /* Adjusted circle height */
border-radius: 50%;
background-color: transparent;
border: 2px solid #ccc; /* Circle border color */
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.slick-dots li.slick-active button::before {
background-color: #fff; /* Active dot background color */
border-color: #fff; /* Active dot border color */
}
/* This is what I get for global styling and using templates */
/* Override the border-radius to remove rounded corners */
.slick-prev, .slick-next {
border-radius: 0 !important;
background: none !important;
box-shadow: none !important;
}
/* If you want a specific shape, like a square or a different background */
.slick-prev, .slick-next {
border-radius: 0 !important;
background: transparent !important;
}
/* Ensure the active dot buttons are not rounded */
.slick-dots li button {
border-radius: 0 !important;
background: none !important;
}
.slick-dots li button::before {
border-radius: 0 !important;
}
/* General button override */
button[type="button"][role="tab"] {
border-radius: 0 !important;
background: none !important;
box-shadow: none !important;
border: none !important;
color: inherit !important;
padding: 0 !important;
}
/* Restore the round shape for the dots */
.slick-dots li button {
border-radius: 50% !important;
background: #ccc !important;
width: 12px;
height: 12px;
}
/* Ensure the pseudo-element is also circular */
.slick-dots li button::before {
border-radius: 50% !important;
background-color: transparent;
border: 2px solid #ccc;
width: 16px;
height: 16px;
}
/* Style for the active dot */
.slick-dots li.slick-active button::before {
background-color: #fff;
border-color: #fff;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because it is too large Load diff

2
static/css/slick.min.css vendored Normal file
View file

@ -0,0 +1,2 @@
.slick-slider{position:relative;display:block;box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-khtml-user-select:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.slick-list{position:relative;display:block;overflow:hidden;margin:0;padding:0}.slick-list:focus{outline:0}.slick-list.dragging{cursor:pointer;cursor:hand}.slick-slider .slick-list,.slick-slider .slick-track{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slick-track{position:relative;top:0;left:0;display:block;margin-left:auto;margin-right:auto}.slick-track:after,.slick-track:before{display:table;content:''}.slick-track:after{clear:both}.slick-loading .slick-track{visibility:hidden}.slick-slide{display:none;float:left;height:100%;min-height:1px}[dir=rtl] .slick-slide{float:right}.slick-slide img{display:block}.slick-slide.slick-loading img{display:none}.slick-slide.dragging img{pointer-events:none}.slick-initialized .slick-slide{display:block}.slick-loading .slick-slide{visibility:hidden}.slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.slick-arrow.slick-hidden{display:none}
/*# sourceMappingURL=/sm/fb3ed351cd5c0f1f30f88778ee1f9b056598e6d25ac4fdcab1eebcd8be521cd9.map */

BIN
static/images/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View file

@ -1,7 +1,7 @@
/* /*
Stellar by HTML5 UP Spitfire Browser by Internet Addict (https://weforgecode.xyz/Spitfire/Website)
html5up.net | @ajlkn Based on Stellar by HTML5 UP | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/ */
(function($) { (function($) {

9
static/js/particles.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,110 @@
{
"particles": {
"number": {
"value": 160,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": "#ffffff"
},
"shape": {
"type": "circle",
"stroke": {
"width": 0,
"color": "#000000"
},
"polygon": {
"nb_sides": 5
},
"image": {
"src": "img/github.svg",
"width": 100,
"height": 100
}
},
"opacity": {
"value": 1,
"random": true,
"anim": {
"enable": true,
"speed": 1,
"opacity_min": 0,
"sync": false
}
},
"size": {
"value": 3,
"random": true,
"anim": {
"enable": false,
"speed": 4,
"size_min": 0.3,
"sync": false
}
},
"line_linked": {
"enable": false,
"distance": 150,
"color": "#ffffff",
"opacity": 0.4,
"width": 1
},
"move": {
"enable": true,
"speed": 1,
"direction": "none",
"random": true,
"straight": false,
"out_mode": "out",
"bounce": false,
"attract": {
"enable": false,
"rotateX": 600,
"rotateY": 600
}
}
},
"interactivity": {
"detect_on": "canvas",
"events": {
"onhover": {
"enable": true,
"mode": "bubble"
},
"onclick": {
"enable": true,
"mode": "repulse"
},
"resize": true
},
"modes": {
"grab": {
"distance": 400,
"line_linked": {
"opacity": 1
}
},
"bubble": {
"distance": 250,
"size": 0,
"duration": 2,
"opacity": 0,
"speed": 3
},
"repulse": {
"distance": 400,
"duration": 0.4
},
"push": {
"particles_nb": 4
},
"remove": {
"particles_nb": 2
}
}
},
"retina_detect": true
}

View file

@ -0,0 +1,110 @@
{
"particles": {
"number": {
"value": 160,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": "#ffffff"
},
"shape": {
"type": "circle",
"stroke": {
"width": 0,
"color": "#000000"
},
"polygon": {
"nb_sides": 5
},
"image": {
"src": "img/github.svg",
"width": 10,
"height": 10
}
},
"opacity": {
"value": 0.7,
"random": true,
"anim": {
"enable": true,
"speed": 0.47948982282851027,
"opacity_min": 0,
"sync": false
}
},
"size": {
"value": 2,
"random": true,
"anim": {
"enable": false,
"speed": 4,
"size_min": 0.3,
"sync": false
}
},
"line_linked": {
"enable": false,
"distance": 150,
"color": "#ffffff",
"opacity": 0.4,
"width": 1
},
"move": {
"enable": true,
"speed": 0,
"direction": "none",
"random": true,
"straight": false,
"out_mode": "out",
"bounce": false,
"attract": {
"enable": false,
"rotateX": 600,
"rotateY": 600
}
}
},
"interactivity": {
"detect_on": "canvas",
"events": {
"onhover": {
"enable": true,
"mode": "bubble"
},
"onclick": {
"enable": true,
"mode": "repulse"
},
"resize": true
},
"modes": {
"grab": {
"distance": 400,
"line_linked": {
"opacity": 1
}
},
"bubble": {
"distance": 250,
"size": 0,
"duration": 2,
"opacity": 0,
"speed": 3
},
"repulse": {
"distance": 400,
"duration": 0.4
},
"push": {
"particles_nb": 4
},
"remove": {
"particles_nb": 2
}
}
},
"retina_detect": true
}

16
static/js/slick-conf.js Normal file
View file

@ -0,0 +1,16 @@
$(document).ready(function(){
$('.the-slider').slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
adaptiveHeight: true,
autoplay: true,
autoplaySpeed: 2000,
prevArrow: '<button type="button" class="slick-prev"></button>',
nextArrow: '<button type="button" class="slick-next"></button>',
customPaging: function(slider, i) {
return '<button type="button">' + '</button>';
}
});
});

1
static/js/slick.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,22 +1,22 @@
/// ///
/// Stellar by HTML5 UP // Spitfire Browser by Internet Addict (https://weforgecode.xyz/Spitfire/Website)
/// html5up.net | @ajlkn // Based on Stellar by HTML5 UP | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) // Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
/// ///
/* Icons */ /* Icons */
ul.icons { ul.icons {
cursor: default; cursor: default;
list-style: none; list-style: none;
padding-left: 0; padding-left: 0;
li { li {
display: inline-block; display: inline-block;
padding: 0 0.65em 0 0; padding: 0 0.65em 0 0;
&:last-child { &:last-child {
padding-right: 0 !important; padding-right: 0 !important;
} }
} }
} }

View file

@ -1,223 +1,223 @@
// breakpoints.scss v1.0 | @ajlkn | MIT licensed */ // breakpoints.scss v1.0 | @ajlkn | MIT licensed */
// Vars. // Vars.
/// Breakpoints. /// Breakpoints.
/// @var {list} /// @var {list}
$breakpoints: () !global; $breakpoints: () !global;
// Mixins. // Mixins.
/// Sets breakpoints. /// Sets breakpoints.
/// @param {map} $x Breakpoints. /// @param {map} $x Breakpoints.
@mixin breakpoints($x: ()) { @mixin breakpoints($x: ()) {
$breakpoints: $x !global; $breakpoints: $x !global;
} }
/// Wraps @content in a @media block targeting a specific orientation. /// Wraps @content in a @media block targeting a specific orientation.
/// @param {string} $orientation Orientation. /// @param {string} $orientation Orientation.
@mixin orientation($orientation) { @mixin orientation($orientation) {
@media screen and (orientation: #{$orientation}) { @media screen and (orientation: #{$orientation}) {
@content; @content;
} }
} }
/// Wraps @content in a @media block using a given query. /// Wraps @content in a @media block using a given query.
/// @param {string} $query Query. /// @param {string} $query Query.
@mixin breakpoint($query: null) { @mixin breakpoint($query: null) {
$breakpoint: null; $breakpoint: null;
$op: null; $op: null;
$media: null; $media: null;
// Determine operator, breakpoint. // Determine operator, breakpoint.
// Greater than or equal. // Greater than or equal.
@if (str-slice($query, 0, 2) == '>=') { @if (str-slice($query, 0, 2) == '>=') {
$op: 'gte'; $op: 'gte';
$breakpoint: str-slice($query, 3); $breakpoint: str-slice($query, 3);
} }
// Less than or equal. // Less than or equal.
@elseif (str-slice($query, 0, 2) == '<=') { @elseif (str-slice($query, 0, 2) == '<=') {
$op: 'lte'; $op: 'lte';
$breakpoint: str-slice($query, 3); $breakpoint: str-slice($query, 3);
} }
// Greater than. // Greater than.
@elseif (str-slice($query, 0, 1) == '>') { @elseif (str-slice($query, 0, 1) == '>') {
$op: 'gt'; $op: 'gt';
$breakpoint: str-slice($query, 2); $breakpoint: str-slice($query, 2);
} }
// Less than. // Less than.
@elseif (str-slice($query, 0, 1) == '<') { @elseif (str-slice($query, 0, 1) == '<') {
$op: 'lt'; $op: 'lt';
$breakpoint: str-slice($query, 2); $breakpoint: str-slice($query, 2);
} }
// Not. // Not.
@elseif (str-slice($query, 0, 1) == '!') { @elseif (str-slice($query, 0, 1) == '!') {
$op: 'not'; $op: 'not';
$breakpoint: str-slice($query, 2); $breakpoint: str-slice($query, 2);
} }
// Equal. // Equal.
@else { @else {
$op: 'eq'; $op: 'eq';
$breakpoint: $query; $breakpoint: $query;
} }
// Build media. // Build media.
@if ($breakpoint and map-has-key($breakpoints, $breakpoint)) { @if ($breakpoint and map-has-key($breakpoints, $breakpoint)) {
$a: map-get($breakpoints, $breakpoint); $a: map-get($breakpoints, $breakpoint);
// Range. // Range.
@if (type-of($a) == 'list') { @if (type-of($a) == 'list') {
$x: nth($a, 1); $x: nth($a, 1);
$y: nth($a, 2); $y: nth($a, 2);
// Max only. // Max only.
@if ($x == null) { @if ($x == null) {
// Greater than or equal (>= 0 / anything) // Greater than or equal (>= 0 / anything)
@if ($op == 'gte') { @if ($op == 'gte') {
$media: 'screen'; $media: 'screen';
} }
// Less than or equal (<= y) // Less than or equal (<= y)
@elseif ($op == 'lte') { @elseif ($op == 'lte') {
$media: 'screen and (max-width: ' + $y + ')'; $media: 'screen and (max-width: ' + $y + ')';
} }
// Greater than (> y) // Greater than (> y)
@elseif ($op == 'gt') { @elseif ($op == 'gt') {
$media: 'screen and (min-width: ' + ($y + 1) + ')'; $media: 'screen and (min-width: ' + ($y + 1) + ')';
} }
// Less than (< 0 / invalid) // Less than (< 0 / invalid)
@elseif ($op == 'lt') { @elseif ($op == 'lt') {
$media: 'screen and (max-width: -1px)'; $media: 'screen and (max-width: -1px)';
} }
// Not (> y) // Not (> y)
@elseif ($op == 'not') { @elseif ($op == 'not') {
$media: 'screen and (min-width: ' + ($y + 1) + ')'; $media: 'screen and (min-width: ' + ($y + 1) + ')';
} }
// Equal (<= y) // Equal (<= y)
@else { @else {
$media: 'screen and (max-width: ' + $y + ')'; $media: 'screen and (max-width: ' + $y + ')';
} }
} }
// Min only. // Min only.
@else if ($y == null) { @else if ($y == null) {
// Greater than or equal (>= x) // Greater than or equal (>= x)
@if ($op == 'gte') { @if ($op == 'gte') {
$media: 'screen and (min-width: ' + $x + ')'; $media: 'screen and (min-width: ' + $x + ')';
} }
// Less than or equal (<= inf / anything) // Less than or equal (<= inf / anything)
@elseif ($op == 'lte') { @elseif ($op == 'lte') {
$media: 'screen'; $media: 'screen';
} }
// Greater than (> inf / invalid) // Greater than (> inf / invalid)
@elseif ($op == 'gt') { @elseif ($op == 'gt') {
$media: 'screen and (max-width: -1px)'; $media: 'screen and (max-width: -1px)';
} }
// Less than (< x) // Less than (< x)
@elseif ($op == 'lt') { @elseif ($op == 'lt') {
$media: 'screen and (max-width: ' + ($x - 1) + ')'; $media: 'screen and (max-width: ' + ($x - 1) + ')';
} }
// Not (< x) // Not (< x)
@elseif ($op == 'not') { @elseif ($op == 'not') {
$media: 'screen and (max-width: ' + ($x - 1) + ')'; $media: 'screen and (max-width: ' + ($x - 1) + ')';
} }
// Equal (>= x) // Equal (>= x)
@else { @else {
$media: 'screen and (min-width: ' + $x + ')'; $media: 'screen and (min-width: ' + $x + ')';
} }
} }
// Min and max. // Min and max.
@else { @else {
// Greater than or equal (>= x) // Greater than or equal (>= x)
@if ($op == 'gte') { @if ($op == 'gte') {
$media: 'screen and (min-width: ' + $x + ')'; $media: 'screen and (min-width: ' + $x + ')';
} }
// Less than or equal (<= y) // Less than or equal (<= y)
@elseif ($op == 'lte') { @elseif ($op == 'lte') {
$media: 'screen and (max-width: ' + $y + ')'; $media: 'screen and (max-width: ' + $y + ')';
} }
// Greater than (> y) // Greater than (> y)
@elseif ($op == 'gt') { @elseif ($op == 'gt') {
$media: 'screen and (min-width: ' + ($y + 1) + ')'; $media: 'screen and (min-width: ' + ($y + 1) + ')';
} }
// Less than (< x) // Less than (< x)
@elseif ($op == 'lt') { @elseif ($op == 'lt') {
$media: 'screen and (max-width: ' + ($x - 1) + ')'; $media: 'screen and (max-width: ' + ($x - 1) + ')';
} }
// Not (< x and > y) // Not (< x and > y)
@elseif ($op == 'not') { @elseif ($op == 'not') {
$media: 'screen and (max-width: ' + ($x - 1) + '), screen and (min-width: ' + ($y + 1) + ')'; $media: 'screen and (max-width: ' + ($x - 1) + '), screen and (min-width: ' + ($y + 1) + ')';
} }
// Equal (>= x and <= y) // Equal (>= x and <= y)
@else { @else {
$media: 'screen and (min-width: ' + $x + ') and (max-width: ' + $y + ')'; $media: 'screen and (min-width: ' + $x + ') and (max-width: ' + $y + ')';
} }
} }
} }
// String. // String.
@else { @else {
// Missing a media type? Prefix with "screen". // Missing a media type? Prefix with "screen".
@if (str-slice($a, 0, 1) == '(') { @if (str-slice($a, 0, 1) == '(') {
$media: 'screen and ' + $a; $media: 'screen and ' + $a;
} }
// Otherwise, use as-is. // Otherwise, use as-is.
@else { @else {
$media: $a; $media: $a;
} }
} }
} }
// Output. // Output.
@media #{$media} { @media #{$media} {
@content; @content;
} }
} }

View file

@ -1,376 +1,376 @@
// vendor.scss v1.0 | @ajlkn | MIT licensed */ // vendor.scss v1.0 | @ajlkn | MIT licensed */
// Vars. // Vars.
/// Vendor prefixes. /// Vendor prefixes.
/// @var {list} /// @var {list}
$vendor-prefixes: ( $vendor-prefixes: (
'-moz-', '-moz-',
'-webkit-', '-webkit-',
'-ms-', '-ms-',
'' ''
); );
/// Properties that should be vendorized. /// Properties that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list} /// @var {list}
$vendor-properties: ( $vendor-properties: (
// Animation. // Animation.
'animation', 'animation',
'animation-delay', 'animation-delay',
'animation-direction', 'animation-direction',
'animation-duration', 'animation-duration',
'animation-fill-mode', 'animation-fill-mode',
'animation-iteration-count', 'animation-iteration-count',
'animation-name', 'animation-name',
'animation-play-state', 'animation-play-state',
'animation-timing-function', 'animation-timing-function',
// Appearance. // Appearance.
'appearance', 'appearance',
// Backdrop filter. // Backdrop filter.
'backdrop-filter', 'backdrop-filter',
// Background image options. // Background image options.
'background-clip', 'background-clip',
'background-origin', 'background-origin',
'background-size', 'background-size',
// Box sizing. // Box sizing.
'box-sizing', 'box-sizing',
// Clip path. // Clip path.
'clip-path', 'clip-path',
// Filter effects. // Filter effects.
'filter', 'filter',
// Flexbox. // Flexbox.
'align-content', 'align-content',
'align-items', 'align-items',
'align-self', 'align-self',
'flex', 'flex',
'flex-basis', 'flex-basis',
'flex-direction', 'flex-direction',
'flex-flow', 'flex-flow',
'flex-grow', 'flex-grow',
'flex-shrink', 'flex-shrink',
'flex-wrap', 'flex-wrap',
'justify-content', 'justify-content',
'order', 'order',
// Font feature. // Font feature.
'font-feature-settings', 'font-feature-settings',
'font-language-override', 'font-language-override',
'font-variant-ligatures', 'font-variant-ligatures',
// Font kerning. // Font kerning.
'font-kerning', 'font-kerning',
// Fragmented borders and backgrounds. // Fragmented borders and backgrounds.
'box-decoration-break', 'box-decoration-break',
// Grid layout. // Grid layout.
'grid-column', 'grid-column',
'grid-column-align', 'grid-column-align',
'grid-column-end', 'grid-column-end',
'grid-column-start', 'grid-column-start',
'grid-row', 'grid-row',
'grid-row-align', 'grid-row-align',
'grid-row-end', 'grid-row-end',
'grid-row-start', 'grid-row-start',
'grid-template-columns', 'grid-template-columns',
'grid-template-rows', 'grid-template-rows',
// Hyphens. // Hyphens.
'hyphens', 'hyphens',
'word-break', 'word-break',
// Masks. // Masks.
'mask', 'mask',
'mask-border', 'mask-border',
'mask-border-outset', 'mask-border-outset',
'mask-border-repeat', 'mask-border-repeat',
'mask-border-slice', 'mask-border-slice',
'mask-border-source', 'mask-border-source',
'mask-border-width', 'mask-border-width',
'mask-clip', 'mask-clip',
'mask-composite', 'mask-composite',
'mask-image', 'mask-image',
'mask-origin', 'mask-origin',
'mask-position', 'mask-position',
'mask-repeat', 'mask-repeat',
'mask-size', 'mask-size',
// Multicolumn. // Multicolumn.
'break-after', 'break-after',
'break-before', 'break-before',
'break-inside', 'break-inside',
'column-count', 'column-count',
'column-fill', 'column-fill',
'column-gap', 'column-gap',
'column-rule', 'column-rule',
'column-rule-color', 'column-rule-color',
'column-rule-style', 'column-rule-style',
'column-rule-width', 'column-rule-width',
'column-span', 'column-span',
'column-width', 'column-width',
'columns', 'columns',
// Object fit. // Object fit.
'object-fit', 'object-fit',
'object-position', 'object-position',
// Regions. // Regions.
'flow-from', 'flow-from',
'flow-into', 'flow-into',
'region-fragment', 'region-fragment',
// Scroll snap points. // Scroll snap points.
'scroll-snap-coordinate', 'scroll-snap-coordinate',
'scroll-snap-destination', 'scroll-snap-destination',
'scroll-snap-points-x', 'scroll-snap-points-x',
'scroll-snap-points-y', 'scroll-snap-points-y',
'scroll-snap-type', 'scroll-snap-type',
// Shapes. // Shapes.
'shape-image-threshold', 'shape-image-threshold',
'shape-margin', 'shape-margin',
'shape-outside', 'shape-outside',
// Tab size. // Tab size.
'tab-size', 'tab-size',
// Text align last. // Text align last.
'text-align-last', 'text-align-last',
// Text decoration. // Text decoration.
'text-decoration-color', 'text-decoration-color',
'text-decoration-line', 'text-decoration-line',
'text-decoration-skip', 'text-decoration-skip',
'text-decoration-style', 'text-decoration-style',
// Text emphasis. // Text emphasis.
'text-emphasis', 'text-emphasis',
'text-emphasis-color', 'text-emphasis-color',
'text-emphasis-position', 'text-emphasis-position',
'text-emphasis-style', 'text-emphasis-style',
// Text size adjust. // Text size adjust.
'text-size-adjust', 'text-size-adjust',
// Text spacing. // Text spacing.
'text-spacing', 'text-spacing',
// Transform. // Transform.
'transform', 'transform',
'transform-origin', 'transform-origin',
// Transform 3D. // Transform 3D.
'backface-visibility', 'backface-visibility',
'perspective', 'perspective',
'perspective-origin', 'perspective-origin',
'transform-style', 'transform-style',
// Transition. // Transition.
'transition', 'transition',
'transition-delay', 'transition-delay',
'transition-duration', 'transition-duration',
'transition-property', 'transition-property',
'transition-timing-function', 'transition-timing-function',
// Unicode bidi. // Unicode bidi.
'unicode-bidi', 'unicode-bidi',
// User select. // User select.
'user-select', 'user-select',
// Writing mode. // Writing mode.
'writing-mode', 'writing-mode',
); );
/// Values that should be vendorized. /// Values that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list} /// @var {list}
$vendor-values: ( $vendor-values: (
// Cross fade. // Cross fade.
'cross-fade', 'cross-fade',
// Element function. // Element function.
'element', 'element',
// Filter function. // Filter function.
'filter', 'filter',
// Flexbox. // Flexbox.
'flex', 'flex',
'inline-flex', 'inline-flex',
// Grab cursors. // Grab cursors.
'grab', 'grab',
'grabbing', 'grabbing',
// Gradients. // Gradients.
'linear-gradient', 'linear-gradient',
'repeating-linear-gradient', 'repeating-linear-gradient',
'radial-gradient', 'radial-gradient',
'repeating-radial-gradient', 'repeating-radial-gradient',
// Grid layout. // Grid layout.
'grid', 'grid',
'inline-grid', 'inline-grid',
// Image set. // Image set.
'image-set', 'image-set',
// Intrinsic width. // Intrinsic width.
'max-content', 'max-content',
'min-content', 'min-content',
'fit-content', 'fit-content',
'fill', 'fill',
'fill-available', 'fill-available',
'stretch', 'stretch',
// Sticky position. // Sticky position.
'sticky', 'sticky',
// Transform. // Transform.
'transform', 'transform',
// Zoom cursors. // Zoom cursors.
'zoom-in', 'zoom-in',
'zoom-out', 'zoom-out',
); );
// Functions. // Functions.
/// Removes a specific item from a list. /// Removes a specific item from a list.
/// @author Hugo Giraudel /// @author Hugo Giraudel
/// @param {list} $list List. /// @param {list} $list List.
/// @param {integer} $index Index. /// @param {integer} $index Index.
/// @return {list} Updated list. /// @return {list} Updated list.
@function remove-nth($list, $index) { @function remove-nth($list, $index) {
$result: null; $result: null;
@if type-of($index) != number { @if type-of($index) != number {
@warn "$index: #{quote($index)} is not a number for `remove-nth`."; @warn "$index: #{quote($index)} is not a number for `remove-nth`.";
} }
@else if $index == 0 { @else if $index == 0 {
@warn "List index 0 must be a non-zero integer for `remove-nth`."; @warn "List index 0 must be a non-zero integer for `remove-nth`.";
} }
@else if abs($index) > length($list) { @else if abs($index) > length($list) {
@warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`.";
} }
@else { @else {
$result: (); $result: ();
$index: if($index < 0, length($list) + $index + 1, $index); $index: if($index < 0, length($list) + $index + 1, $index);
@for $i from 1 through length($list) { @for $i from 1 through length($list) {
@if $i != $index { @if $i != $index {
$result: append($result, nth($list, $i)); $result: append($result, nth($list, $i));
} }
} }
} }
@return $result; @return $result;
} }
/// Replaces a substring within another string. /// Replaces a substring within another string.
/// @author Hugo Giraudel /// @author Hugo Giraudel
/// @param {string} $string String. /// @param {string} $string String.
/// @param {string} $search Substring. /// @param {string} $search Substring.
/// @param {string} $replace Replacement. /// @param {string} $replace Replacement.
/// @return {string} Updated string. /// @return {string} Updated string.
@function str-replace($string, $search, $replace: '') { @function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search); $index: str-index($string, $search);
@if $index { @if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
} }
@return $string; @return $string;
} }
/// Replaces a substring within each string in a list. /// Replaces a substring within each string in a list.
/// @param {list} $strings List of strings. /// @param {list} $strings List of strings.
/// @param {string} $search Substring. /// @param {string} $search Substring.
/// @param {string} $replace Replacement. /// @param {string} $replace Replacement.
/// @return {list} Updated list of strings. /// @return {list} Updated list of strings.
@function str-replace-all($strings, $search, $replace: '') { @function str-replace-all($strings, $search, $replace: '') {
@each $string in $strings { @each $string in $strings {
$strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace)); $strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace));
} }
@return $strings; @return $strings;
} }
// Mixins. // Mixins.
/// Wraps @content in vendorized keyframe blocks. /// Wraps @content in vendorized keyframe blocks.
/// @param {string} $name Name. /// @param {string} $name Name.
@mixin keyframes($name) { @mixin keyframes($name) {
@-moz-keyframes #{$name} { @content; } @-moz-keyframes #{$name} { @content; }
@-webkit-keyframes #{$name} { @content; } @-webkit-keyframes #{$name} { @content; }
@-ms-keyframes #{$name} { @content; } @-ms-keyframes #{$name} { @content; }
@keyframes #{$name} { @content; } @keyframes #{$name} { @content; }
} }
/// Vendorizes a declaration's property and/or value(s). /// Vendorizes a declaration's property and/or value(s).
/// @param {string} $property Property. /// @param {string} $property Property.
/// @param {mixed} $value String/list of value(s). /// @param {mixed} $value String/list of value(s).
@mixin vendor($property, $value) { @mixin vendor($property, $value) {
// Determine if property should expand. // Determine if property should expand.
$expandProperty: index($vendor-properties, $property); $expandProperty: index($vendor-properties, $property);
// Determine if value should expand (and if so, add '-prefix-' placeholder). // Determine if value should expand (and if so, add '-prefix-' placeholder).
$expandValue: false; $expandValue: false;
@each $x in $value { @each $x in $value {
@each $y in $vendor-values { @each $y in $vendor-values {
@if $y == str-slice($x, 1, str-length($y)) { @if $y == str-slice($x, 1, str-length($y)) {
$value: set-nth($value, index($value, $x), '-prefix-' + $x); $value: set-nth($value, index($value, $x), '-prefix-' + $x);
$expandValue: true; $expandValue: true;
} }
} }
} }
// Expand property? // Expand property?
@if $expandProperty { @if $expandProperty {
@each $vendor in $vendor-prefixes { @each $vendor in $vendor-prefixes {
#{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; #{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
} }
} }
// Expand just the value? // Expand just the value?
@elseif $expandValue { @elseif $expandValue {
@each $vendor in $vendor-prefixes { @each $vendor in $vendor-prefixes {
#{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; #{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
} }
} }
// Neither? Treat them as a normal declaration. // Neither? Treat them as a normal declaration.
@else { @else {
#{$property}: #{$value}; #{$property}: #{$value};
} }
} }

View file

@ -24,3 +24,19 @@ func startTelegramBot() {
} }
} }
} }
func sendTelegramNotification(message string) {
if bot == nil {
log.Println("Telegram bot is not initialized")
return
}
// Replace with the actual chat ID you want to send messages to
chatID := int64(YOUR_TELEGRAM_CHAT_ID)
msg := tgbotapi.NewMessage(chatID, message)
_, err := bot.Send(msg)
if err != nil {
log.Printf("Error sending Telegram notification: %v", err)
}
}

View file

@ -1,18 +1,19 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<!-- <!--
Stellar by HTML5 UP Spitfire Browser by Internet Addict (https://weforgecode.xyz/Spitfire/Website)
html5up.net | @ajlkn Based on Stellar by HTML5 UP | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
--> -->
<html> <html>
<head> <head>
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="static/images/favicon.png">
<title>Spitfire Browser - Downloads</title> <title>Spitfire Browser - Downloads</title>
<meta content="🌐 Spitfire Browser" property="og:title" /> <meta content="🌐 Spitfire Browser" property="og:title" />
<meta content="Privacy respecting user friendly web browser." property="og:description" /> <meta content="Privacy respecting user friendly web browser." property="og:description" />
<meta content="https://spitfirebrowser.com/" property="og:url" /> <meta content="https://spitfirebrowser.com/" property="og:url" />
<meta content="https://spitfirebrowser.com/favicon.png" property="og:image" /> <meta content="https://spitfirebrowser.com/static/images/favicon.png" property="og:image" />
<meta content="#f1f1f1" data-react-helmet="true" name="theme-color" /> <meta content="#f1f1f1" data-react-helmet="true" name="theme-color" />
<meta name="darkreader-lock">
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
@ -30,7 +31,7 @@
</div> </div>
<!-- Top Floater Footer --> <!-- Top Floater Footer -->
<div style="background-color: red; color: white; text-align: center; padding: 10px 0; position: fixed; top: 0; width: 100%; z-index: 1000;"> <div style="background-color: red; color: white; text-align: center; padding: 10px 0; position: fixed; bottom: 0; width: 100%; z-index: 1000;">
🚧👷‍♂️ This site is under construction! Please check back later. 👷‍♀️🚧 🚧👷‍♂️ This site is under construction! Please check back later. 👷‍♀️🚧
</div> </div>

View file

@ -1,62 +1,63 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<!-- <!--
Stellar by HTML5 UP Spitfire Browser by Internet Addict (https://weforgecode.xyz/Spitfire/Website)
html5up.net | @ajlkn Based on Stellar by HTML5 UP | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
--> -->
<html> <html>
<head> <head>
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="static/images/favicon.png">
<title>Spitfire Browser - Downloads</title> <title>Spitfire Browser - Downloads</title>
<meta content="🌐 Spitfire Browser" property="og:title" /> <meta content="🌐 Spitfire Browser" property="og:title" />
<meta content="Privacy respecting user friendly web browser." property="og:description" /> <meta content="Privacy respecting user friendly web browser." property="og:description" />
<meta content="https://spitfirebrowser.com/" property="og:url" /> <meta content="https://spitfirebrowser.com/" property="og:url" />
<meta content="https://spitfirebrowser.com/favicon.png" property="og:image" /> <meta content="https://spitfirebrowser.com/static/images/favicon.png" property="og:image" />
<meta content="#f1f1f1" data-react-helmet="true" name="theme-color" /> <meta content="#f1f1f1" data-react-helmet="true" name="theme-color" />
<meta name="darkreader-lock">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> <meta charset="utf-8" />
<link rel="stylesheet" href="static/css/main.css" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="static/css/stars.css" /> <link rel="stylesheet" href="static/css/main.css" />
<noscript><link rel="stylesheet" href="static/css/noscript.css" /></noscript> <link rel="stylesheet" href="static/css/stars.css" />
<style> <noscript><link rel="stylesheet" href="static/css/noscript.css" /></noscript>
.download-section { <style>
text-align: center; .download-section {
padding: 2em 0; text-align: center;
} padding: 2em 0;
}
.download-buttons { .download-buttons {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
gap: 1em; gap: 1em;
} }
.download-button { .download-button {
border-radius: 0.5em; border-radius: 0.5em;
padding: 1em; padding: 1em;
width: 220px; width: 220px;
height: 220px; height: 220px;
text-align: center; text-align: center;
transition: background-color 0.3s ease; transition: background-color 0.3s ease;
} }
.download-button:hover { .download-button:hover {
background-color: #444; background-color: #444;
} }
.download-button img { .download-button img {
width: 48px; width: 48px;
height: 48px; height: 48px;
} }
.download-button span { .download-button span {
display: block; display: block;
margin-top: 0.5em; margin-top: 0.5em;
font-size: 1.2em; font-size: 1.2em;
} }
</style> </style>
</head> </head>
<body class="is-preload"> <body class="is-preload">
<!-- Star Background Divs --> <!-- Star Background Divs -->
@ -67,7 +68,7 @@
</div> </div>
<!-- Top Floater Footer --> <!-- Top Floater Footer -->
<div style="background-color: red; color: white; text-align: center; padding: 10px 0; position: fixed; top: 0; width: 100%; z-index: 1000;"> <div style="background-color: red; color: white; text-align: center; padding: 10px 0; position: fixed; bottom: 0; width: 100%; z-index: 1000;">
🚧👷‍♂️ This site is under construction! Please check back later. 👷‍♀️🚧 🚧👷‍♂️ This site is under construction! Please check back later. 👷‍♀️🚧
</div> </div>

View file

@ -1,18 +1,19 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<!-- <!--
Spitfire Browser by Internet Addict Spitfire Browser by Internet Addict (https://weforgecode.xyz/Spitfire/Website)
Based on Stellar by HTML5 UP Based on Stellar by HTML5 UP | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
--> -->
<html> <html>
<head> <head>
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="static/images/favicon.png">
<title>Spitfire Browser - Fast. Secure. Elegant.</title> <title>Spitfire Browser - Fast. Secure. Elegant.</title>
<meta content="🌐 Spitfire Browser" property="og:title" /> <meta content="🌐 Spitfire Browser" property="og:title" />
<meta content="Privacy respecting user friendly web browser." property="og:description" /> <meta content="Privacy respecting user friendly web browser." property="og:description" />
<meta content="https://spitfirebrowser.com/" property="og:url" /> <meta content="https://spitfirebrowser.com/" property="og:url" />
<meta content="https://spitfirebrowser.com/favicon.png" property="og:image" /> <meta content="https://spitfirebrowser.com/static/images/favicon.png" property="og:image" />
<meta content="#f1f1f1" data-react-helmet="true" name="theme-color" /> <meta content="#f1f1f1" data-react-helmet="true" name="theme-color" />
<meta name="darkreader-lock">
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
@ -20,31 +21,38 @@
<link rel="stylesheet" href="/static/css/stars.css" /> <link rel="stylesheet" href="/static/css/stars.css" />
<link rel="stylesheet" href="/static/css/fancy-gallery.css" /> <link rel="stylesheet" href="/static/css/fancy-gallery.css" />
<link rel="stylesheet" href="/static/css/extras.css" /> <link rel="stylesheet" href="/static/css/extras.css" />
<link rel="stylesheet" href="/static/css/slick.min.css" />
<noscript><link rel="stylesheet" href="/static/css/noscript.css" /></noscript> <noscript><link rel="stylesheet" href="/static/css/noscript.css" /></noscript>
</head> </head>
<body class="is-preload"> <body class="is-preload">
<!-- Star Background Divs --> <!-- Star Background Divs -->
<div id="star-background"> <div id="star-background">
<div id="stars"></div> <div id="particles-js"></div>
<div id="stars2"></div> <noscript>
<div id="stars3"></div> <div id="stars"></div>
<div id="stars2"></div>
<div id="stars3"></div>
</noscript>
</div> </div>
<!-- Top Floater Footer --> <!-- Top Floater Footer -->
<div style="background-color: red; color: white; text-align: center; padding: 10px 0; position: fixed; top: 0; width: 100%; z-index: 1000;"> <div style="background-color: red; color: white; text-align: center; padding: 10px 0; position: fixed; bottom: 0; width: 100%; z-index: 1000;">
🚧👷‍♂️ This site is under construction! Please check back later. 👷‍♀️🚧 🚧👷‍♂️ This site is under construction! Please check back later. 👷‍♀️🚧
</div> </div>
<!-- Wrapper --> <!-- Wrapper -->
<div id="wrapper"> <div id="wrapper">
<!-- Header --> <!-- Header -->
<header id="header" class="alt"> <header id="header" class="alt">
<span class="logo"><img src="/static/images/logo.svg" alt="Spitfire Logo" /></span> <span class="logo">
<a href="/"><img src="/static/images/logo.svg" alt="Spitfire Logo" /></a>
</span>
<h1>Spitfire Browser</h1> <h1>Spitfire Browser</h1>
<p>Fast. Secure. Elegant.</p> <p>Fast. Secure. Elegant.</p>
<a href="download" class="button">Download Now</a> <br>
<a href="/download" class="button">Download Now</a>
</header> </header>
<!-- Nav --> <!-- Nav -->
@ -52,8 +60,8 @@
<ul> <ul>
<li><a href="#intro" class="active">Introduction</a></li> <li><a href="#intro" class="active">Introduction</a></li>
<li><a href="#features">Features</a></li> <li><a href="#features">Features</a></li>
<li><a href="#search">Search</a></li>
<li><a href="#security">Security</a></li> <li><a href="#security">Security</a></li>
<li><a href="#cta">Get Started</a></li>
</ul> </ul>
</nav> </nav>
@ -65,18 +73,21 @@
<header class="major"> <header class="major">
<h2>Welcome to Spitfire Browser</h2> <h2>Welcome to Spitfire Browser</h2>
</header> </header>
<p>Spitfire Browser is your gateway to a fast, secure, and elegant browsing experience. Built on Firefox, Spitfire includes essential features like ad blocking, enhanced security, and anonymous browsing with Warp search engine.</p> <p>Spitfire Browser is your gateway to a fast, secure, and elegant browsing experience. Built on Firefox, Spitfire includes essential features like ad blocking, enhanced security, and anonymous browsing with Ocásek search engine.</p>
<div class="box alt"> <br> <!-- br? I call it super.fancy.tailor.r.css.react.native.way.to.add.super.padding.on.top.of.images.T3.js.express.lodash.moment.axios.jquery.vue.nft.d3.angular.bloat.typescript.webpack.web3.babel.parcel.T4 -->
<div class="fancy-gallery"> <div class="gallery-wrapper">
<div class="gallery-item"><img src="/static/images/screenshots/1.png" alt="Screenshot 1" /></div> <div class="the-slider"> <!-- Is this fucking centered? -->
<div class="gallery-item"><img src="/static/images/screenshots/1.png" alt="Screenshot 2" /></div> <div><img src="/static/images/screenshots/1.png" alt="Screenshot 1"></div>
<div><img src="/static/images/screenshots/1.png" alt="Screenshot 2"></div>
<div><img src="/static/images/screenshots/1.png" alt="Screenshot 3"></div>
</div> </div>
</div> </div>
<ul class="actions"> <!-- <ul class="actions js-disabled">
<li><a href="#features" class="button">More Screenshots</a></li> <li><a href="#intro" class="button">See More Screenshots</a></li>
</ul> </ul> -->
</div> </div>
</section> </section>
<!-- Features Section --> <!-- Features Section -->
<section id="features" class="main special"> <section id="features" class="main special">
<header class="major"> <header class="major">
@ -111,11 +122,20 @@
<li> <li>
<span class="icon solid major style6 fa-search"></span> <span class="icon solid major style6 fa-search"></span>
<h3>Anonymous Search</h3> <h3>Anonymous Search</h3>
<p><a herf="https://search.spitfirebrowser.com/">Warp search engine</a> allows you to browse Google results anonymously.</p> <p><a herf="#search">Ocásek search engine</a> allows you to browse Google results anonymously.</p>
</li> </li>
</ul> </ul>
</section> </section>
<!-- Try Search -->
<section id="search" class="main special">
<header class="major">
<h2>Try Searching</h2>
<p></p>
</header>
<iframe src="https://search.spitfirebrowser.com" width="100%" height="700px" style="border:none; border-radius: 10px; overflow:hidden;"></iframe>
</section>
<!-- Security Section --> <!-- Security Section -->
<section id="security" class="main special"> <section id="security" class="main special">
<header class="major"> <header class="major">
@ -189,13 +209,13 @@
</a> </a>
</li> </li>
<li> <li>
<a href="#" class="icon alt"> <a href="https://weforgecode.xyz/Spitfire" class="icon alt">
<img src="/static/images/icons/brands/git-alt.svg" alt="Forgejo"> <img src="/static/images/icons/brands/git-alt.svg" alt="Forgejo">
<span class="label">Forgejo</span> <span class="label">Forgejo</span>
</a> </a>
</li> </li>
<li> <li>
<a href="#" class="icon alt"> <a href="https://www.youtube.com/@Internet.Addict" class="icon alt">
<img src="/static/images/icons/brands/youtube.svg" alt="YouTube"> <img src="/static/images/icons/brands/youtube.svg" alt="YouTube">
<span class="label">YouTube</span> <span class="label">YouTube</span>
</a> </a>
@ -210,13 +230,23 @@
</div> </div>
<!-- Scripts --> <!-- Scripts -->
<script src="/static/js/jquery.min.js" defer></script> <script src="/static/js/jquery.min.js"></script>
<script src="/static/js/slick.min.js"></script>
<script src="/static/js/jquery.scrollex.min.js" defer></script> <script src="/static/js/jquery.scrollex.min.js" defer></script>
<script src="/static/js/jquery.scrolly.min.js" defer></script> <script src="/static/js/jquery.scrolly.min.js" defer></script>
<script src="/static/js/browser.min.js" defer></script> <script src="/static/js/browser.min.js" defer></script>
<script src="/static/js/breakpoints.min.js" defer></script> <script src="/static/js/breakpoints.min.js" defer></script>
<script src="/static/js/util.js" defer></script> <script src="/static/js/util.js" defer></script>
<script src="/static/js/main.js" defer></script> <script src="/static/js/main.js" defer></script>
<script src="/static/js/slick-conf.js" defer></script>
<script src="/static/js/particles.min.js"></script>
<script>
/* particlesJS.load(@dom-id, @path-json, @callback (optional)); */
particlesJS.load('particles-js', '/static/js/particlesjs-config.json', function() {
console.log('callback - particles.js config loaded');
});
</script>
</script>
</body> </body>
</html> </html>

View file

@ -1,113 +1,131 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<!-- <!--
Stellar by HTML5 UP Spitfire Browser by Internet Addict (https://weforgecode.xyz/Spitfire/Website)
html5up.net | @ajlkn Based on Stellar by HTML5 UP | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
--> -->
<html> <html>
<head> <head>
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="static/images/favicon.png">
<title>{{.Title}}</title> <title>{{.Title}}</title>
<meta content="🌐 {{.Title}}" property="og:title" /> <meta content="🌐 {{.Title}}" property="og:title" />
<meta content="Privacy respecting user friendly web browser." property="og:description" /> <meta content="Privacy respecting user friendly web browser." property="og:description" />
<meta content="https://spitfirebrowser.com/" property="og:url" /> <meta content="https://spitfirebrowser.com/" property="og:url" />
<meta content="https://spitfirebrowser.com/favicon.png" property="og:image" /> <meta content="https://spitfirebrowser.com/static/images/favicon.png" property="og:image" />
<meta content="#f1f1f1" data-react-helmet="true" name="theme-color" /> <meta content="#f1f1f1" data-react-helmet="true" name="theme-color" />
<meta name="darkreader-lock">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> <meta charset="utf-8" />
<link rel="stylesheet" href="/static/css/main.css" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="/static/css/stars.css" /> <link rel="stylesheet" href="/static/css/main.css" />
<link rel="stylesheet" href="/static/css/extras.css" /> <link rel="stylesheet" href="/static/css/stars.css" />
<noscript><link rel="stylesheet" href="/static/css/noscript.css" /></noscript> <link rel="stylesheet" href="/static/css/extras.css" />
</head> <link rel="stylesheet" href="/static/css/blog.css" />
<body class="is-preload"> <noscript><link rel="stylesheet" href="/static/css/noscript.css" /></noscript>
</head>
<!-- Star Background Divs --> <body class="is-preload">
<div id="star-background">
<div id="stars"></div> <!-- Star Background Divs -->
<div id="stars2"></div> <div id="star-background">
<div id="stars3"></div> <div id="particles-js"></div>
</div> <noscript>
<div id="stars"></div>
<!-- Top Floater Footer --> <div id="stars2"></div>
<div style="background-color: red; color: white; text-align: center; padding: 10px 0; position: fixed; top: 0; width: 100%; z-index: 1000;"> <div id="stars3"></div>
🚧👷‍♂️ This site is under construction! Please check back later. 👷‍♀️🚧 </noscript>
</div> </div>
<!-- Wrapper --> <!-- Top Floater Footer
<div id="wrapper"> <div style="background-color: red; color: white; text-align: center; padding: 10px 0; position: fixed; top: 0; width: 100%; z-index: 1000;">
🚧👷‍♂️ This site is under construction! Please check back later. 👷‍♀️🚧
<!-- Header --> </div> -->
<header id="header" class="alt">
<span class="logo"><img src="/static/images/logo.svg" alt="Spitfire Logo" /></span> <!-- Wrapper -->
<h1>Spitfire Browser</h1> <div id="wrapper">
<p>News</p>
</header> <!-- Header -->
<header id="header" class="alt">
<!-- Main --> <span class="logo">
<div id="main"> <a href="/"><img src="/static/images/logo.svg" alt="Spitfire Logo" /></a>
<!-- Stable Release Section --> </span>
<section id="cta" class="main special"> <h1>Spitfire Browser News</h1>
<div class="center-text"> </header>
<header class="major">
<h2>{{.Title}}</h2> <!-- Main -->
<p>{{.Content}}</p> <div id="main">
</header> <!-- Stable Release Section -->
<footer class="major"> <section id="cta" class="main">
<ul class="actions special"> <div class="center-text">
{{if .PrevLink}} <header class="major">
<li><a href="{{.PrevLink}}" class="button primary small">Previous</a></li> <div class="align-blog"> <p>{{.Content}}</p> </div>
{{end}} </header>
<li><a href="/" class="button primary small">Home</a></li> <footer class="major">
{{if .NextLink}} <ul class="actions special">
<li><a href="{{.NextLink}}" class="button primary small">Next</a></li> <li>
{{end}} <a href="{{if .PrevLink}}{{.PrevLink}}{{else}}#{{end}}"
</ul> class="button primary small {{if not .PrevLink}}disabled{{end}}">
</footer> Previous
</div> </a>
</section> </li>
</div> <li><a href="/" class="button primary small">Home</a></li>
<li>
<!-- Footer --> <a href="{{if .NextLink}}{{.NextLink}}{{else}}#{{end}}"
<footer id="footer"> class="button primary small {{if not .NextLink}}disabled{{end}}">
<section> Next
<h2>Support me</h2> </a>
<ul class="icons"> </li>
<li> </ul>
<a href="#" class="icon alt"> </footer>
<img src="/static/images/icons/regular/heart.svg" alt="LibrePay"> </div>
<span class="label">LibrePay</span> </section>
</a> </div>
</li>
<li> <!-- Footer -->
<a href="https://weforgecode.xyz/Spitfire/" class="icon alt"> <footer id="footer">
<img src="/static/images/icons/brands/git-alt.svg" alt="Forgejo"> <section>
<span class="label">Forgejo</span> <h2>Support me</h2>
</a> <ul class="icons">
</li> <li>
<li> <a href="#" class="icon alt">
<a href="#" class="icon alt"> <img src="/static/images/icons/regular/heart.svg" alt="LibrePay">
<img src="/static/images/icons/brands/youtube.svg" alt="YouTube"> <span class="label">LibrePay</span>
<span class="label">YouTube</span> </a>
</a> </li>
</li> <li>
</ul> <a href="https://weforgecode.xyz/Spitfire/" class="icon alt">
</section> <img src="/static/images/icons/brands/git-alt.svg" alt="Forgejo">
<section> <span class="label">Forgejo</span>
<p class="copyright">&copy; Spitfire Browser. Design based on <a href="https://html5up.net">HTML5 UP</a>.</p> </a>
</section> </li>
</footer> <li>
</div> <a href="#" class="icon alt">
<img src="/static/images/icons/brands/youtube.svg" alt="YouTube">
<!-- Scripts --> <span class="label">YouTube</span>
<script src="/static/js/jquery.min.js" defer></script> </a>
<script src="/static/js/jquery.scrollex.min.js" defer></script> </li>
<script src="/static/js/jquery.scrolly.min.js" defer></script> </ul>
<script src="/static/js/browser.min.js" defer></script> </section>
<script src="/static/js/breakpoints.min.js" defer></script> <section>
<script src="/static/js/util.js" defer></script> <p class="copyright">&copy; Spitfire Browser. Design based on <a href="https://html5up.net">HTML5 UP</a>.</p>
<script src="/static/js/main.js" defer></script> </section>
</footer>
</body> </div>
</html>
<!-- Scripts -->
<script src="/static/js/jquery.min.js" defer></script>
<script src="/static/js/jquery.scrollex.min.js" defer></script>
<script src="/static/js/jquery.scrolly.min.js" defer></script>
<script src="/static/js/browser.min.js" defer></script>
<script src="/static/js/breakpoints.min.js" defer></script>
<script src="/static/js/util.js" defer></script>
<script src="/static/js/main.js" defer></script>
<script src="/static/js/particles.min.js"></script>
<script>
/* particlesJS.load(@dom-id, @path-json, @callback (optional)); */
particlesJS.load('particles-js', '/static/js/particlesjs-config.json', function() {
console.log('callback - particles.js config loaded');
});
</script>
</body>
</html>