mirror of
https://git.mills.io/prologic/zs.git
synced 2025-01-04 12:36:54 -05:00
Add zs init command to initialize new site
This commit is contained in:
parent
5e8f404eb5
commit
1e84d9a585
5
default/.gitignore
vendored
Normal file
5
default/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*~
|
||||
*.bak
|
||||
**/.DS_Store
|
||||
|
||||
/.pub
|
14
default/.zs/config.yml
Normal file
14
default/.zs/config.yml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Twtxt Docs
|
||||
description: Twtxt documentation for developers
|
||||
keywords: docs, twtxt, markdown, text, format, documentation
|
||||
|
||||
extensions:
|
||||
- anchor
|
||||
- definitionlist
|
||||
- linkify
|
||||
- footnote
|
||||
- strikethrough
|
||||
- table
|
||||
- typography
|
||||
- wikilink
|
9
default/.zs/editthispage
Executable file
9
default/.zs/editthispage
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
GITEA_BASE_URL="https://git.mills.io"
|
||||
REPO="yarnsocial/twtxt.dev"
|
||||
BRANCH="main"
|
||||
|
||||
url="${GITEA_BASE_URL}/${REPO}/_edit/${BRANCH}/${ZS_FILE}"
|
||||
|
||||
printf "<a href=\"%s\" rel=\"nofollow\" target=\"_blank\">✍️ Edit Page on Gitea</a>" "$url"
|
14
default/.zs/include
Executable file
14
default/.zs/include
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! $# = 1 ]; then
|
||||
printf "Usage: %s <file>\n" "$(basename "$0")"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -f "$1" ]; then
|
||||
cat "$1"
|
||||
else
|
||||
echo "error: file not found $1"
|
||||
fi
|
64
default/.zs/layout.html
Normal file
64
default/.zs/layout.html
Normal file
@ -0,0 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Meta Tags -->
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ title }}</title>
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
|
||||
<!-- Stylesheets -->
|
||||
{{ styles }}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Header with Navigation -->
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="header-top">
|
||||
<a href="/" class="logo">
|
||||
<img src="/logo.png" alt="{{ title }}" class="logo-img">
|
||||
{{ title }}
|
||||
</a>
|
||||
<button id="menu-toggle" aria-label="Toggle Navigation">☰</button>
|
||||
</div>
|
||||
<nav id="main-nav">
|
||||
<ul>
|
||||
{{ nav }}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="container">
|
||||
<article>{{ content }}</article>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer>
|
||||
<div class="container">
|
||||
<span class="edit-page-link">
|
||||
{{ editthispage }}
|
||||
</span>
|
||||
<p>
|
||||
Last modified <time datetime="{{ date -u +%Y-%m-%dT%H:%M:%SZ }}">{{ date -u }}</time>
|
||||
Built with <a href="https://git.mills.io/prologic/zs">zs</a>
|
||||
</p>
|
||||
<button id="theme-toggle" aria-label="Toggle Theme">🌓</button>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Scripts -->
|
||||
{{ scripts }}
|
||||
<script>
|
||||
hljs.highlightAll();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
90
default/.zs/list
Executable file
90
default/.zs/list
Executable file
@ -0,0 +1,90 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Define the directory to iterate over from the first argument
|
||||
dir="$1"
|
||||
|
||||
# Initialize the variable to hold the HTML list and date-file pairs
|
||||
html=""
|
||||
date_file_pairs=""
|
||||
|
||||
# Check if the directory exists
|
||||
if [ -d "$dir" ]; then
|
||||
# Find all Markdown files in the directory and store them in a variable
|
||||
md_files=$(find "$dir" -maxdepth 1 -type f -name "*.md")
|
||||
|
||||
# Process each Markdown file in a regular loop (not in a subshell)
|
||||
for md_file in $md_files; do
|
||||
# Extract front matter using sed, ensure the file is quoted
|
||||
front_matter=$(sed -n '/^---$/,/^---$/p' "$md_file")
|
||||
|
||||
# Extract date
|
||||
date=$(echo "$front_matter" | grep '^date:' | sed 's/^date:[[:space:]]*//')
|
||||
|
||||
# If no date is found, use a default date
|
||||
if [ -z "$date" ]; then
|
||||
date="1970-01-01" # Default date if none is found
|
||||
fi
|
||||
|
||||
# Add the date and file to the date_file_pairs variable, using printf to correctly append newlines
|
||||
date_file_pairs=$(printf "%s\n%s|%s" "$date_file_pairs" "$date" "$md_file")
|
||||
done
|
||||
|
||||
# Sort the date and file pairs by date
|
||||
sorted_date_file_pairs=$(printf "%s" "$date_file_pairs" | sort)
|
||||
|
||||
# Create a file descriptor to avoid subshell issues
|
||||
exec 3<<EOF
|
||||
$sorted_date_file_pairs
|
||||
EOF
|
||||
|
||||
# Generate the navigation list
|
||||
html="<ul class=\"list\">"
|
||||
while IFS= read -r pair <&3; do
|
||||
# Split the pair into date and filename using | as a delimiter
|
||||
date=$(printf "%s" "$pair" | cut -d'|' -f1)
|
||||
md_file=$(printf "%s" "$pair" | cut -d'|' -f2)
|
||||
|
||||
# Ensure md_file is not empty (safety check)
|
||||
[ -z "$md_file" ] && continue
|
||||
|
||||
# Extract front matter again using sed, ensure md_file is quoted
|
||||
front_matter=$(sed -n '/^---$/,/^---$/p' "$md_file")
|
||||
|
||||
# Extract title
|
||||
title=$(echo "$front_matter" | grep '^title:' | sed 's/^title:[[:space:]]*//')
|
||||
|
||||
# Use filename as a fallback if title is empty
|
||||
if [ -z "$title" ]; then
|
||||
# Get the base filename without extension, quote the argument
|
||||
base_name=$(basename "$md_file" .md)
|
||||
# Replace hyphens and underscores with spaces for display
|
||||
title=$(echo "$base_name" | sed 's/-/ /g' | sed 's/_/ /g')
|
||||
# Capitalize each word
|
||||
title=$(echo "$title" | awk '{ for (i=1; i<=NF; i++) $i=toupper(substr($i,1,1)) substr($i,2); print }')
|
||||
fi
|
||||
|
||||
# Format the date using POSIX-compliant date formatting
|
||||
if formatted_date=$(date -d "$date" '+%Y-%m-%d' 2>/dev/null); then
|
||||
: # formatted_date is valid
|
||||
else
|
||||
formatted_date="$date"
|
||||
fi
|
||||
|
||||
# Construct the link href, quote the argument
|
||||
href="/$dir/$(basename "${md_file%.md}.html")"
|
||||
|
||||
# Append to the HTML list
|
||||
html="$html<li><a href=\"$href\">$title</a> (published: $formatted_date)</li>"
|
||||
done
|
||||
html="$html</ul>"
|
||||
|
||||
# Close file descriptor
|
||||
exec 3<&-
|
||||
|
||||
else
|
||||
# If the directory doesn't exist, set a message
|
||||
html="<p>No pages found.</p>"
|
||||
fi
|
||||
|
||||
# Output the HTML list
|
||||
echo "$html"
|
57
default/.zs/nav
Executable file
57
default/.zs/nav
Executable file
@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Get the directory of the current page
|
||||
current_dir=$(dirname "$ZS_SOURCE_FILE")
|
||||
|
||||
# Remove leading './' if present
|
||||
case "$current_dir" in
|
||||
./*) current_dir="${current_dir#./}" ;;
|
||||
esac
|
||||
|
||||
# Initialize the navigation HTML with the 'Home' link
|
||||
if [ "$ZS_URL" = "index.html" ]; then
|
||||
nav_html="<li><a href=\"/index.html\" class=\"active\">Home</a></li>"
|
||||
else
|
||||
nav_html="<li><a href=\"/\">Home</a></li>"
|
||||
fi
|
||||
|
||||
# Create a temporary file to store filenames
|
||||
tmpfile=$(mktemp)
|
||||
|
||||
# Find all Markdown files in the current directory, excluding 'README.md' and 'index.md'
|
||||
find "$current_dir" -maxdepth 1 -type f -name "*.md" ! -name "README.md" ! -name "index.md" -print >"$tmpfile"
|
||||
|
||||
# Sort the files alphabetically
|
||||
sort "$tmpfile" >"${tmpfile}.sorted"
|
||||
|
||||
# Read each file and process
|
||||
while IFS= read -r md_file; do
|
||||
# Get the base filename without extension
|
||||
base_name=$(basename "$md_file" .md)
|
||||
|
||||
# Replace hyphens and underscores with spaces for display
|
||||
display_name=$(echo "$base_name" | tr '-' ' ' | tr '_' ' ')
|
||||
|
||||
# Capitalize the first letter of each word using awk
|
||||
display_name=$(echo "$display_name" | awk '{ for (i=1; i<=NF; i++) { $i = toupper(substr($i,1,1)) substr($i,2) } print }')
|
||||
|
||||
# Construct the link href relative to the site root
|
||||
if [ "$current_dir" = "." ]; then
|
||||
href="/${base_name}.html"
|
||||
else
|
||||
href="/${current_dir}/${base_name}.html"
|
||||
fi
|
||||
|
||||
# Append the navigation item
|
||||
if [ "$ZS_URL" = "$base_name.html" ]; then
|
||||
nav_html="${nav_html}<li><a href=\"${href}\" class=\"active\">${display_name}</a></li>"
|
||||
else
|
||||
nav_html="${nav_html}<li><a href=\"${href}\">${display_name}</a></li>"
|
||||
fi
|
||||
done <"${tmpfile}.sorted"
|
||||
|
||||
# Remove temporary files
|
||||
rm -f "$tmpfile" "${tmpfile}.sorted"
|
||||
|
||||
# Output the navigation HTML
|
||||
echo "$nav_html"
|
9
default/.zs/onthispage
Executable file
9
default/.zs/onthispage
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
{
|
||||
echo "**On this page**"
|
||||
echo
|
||||
toc -d 2 -s 1 "$ZS_FILE"
|
||||
} | zs gen
|
19
default/.zs/posthook
Executable file
19
default/.zs/posthook
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
minify_assets() {
|
||||
p="$1"
|
||||
t="$2"
|
||||
|
||||
find "$p" -type f -name "*.$t" | while read -r file; do
|
||||
name="${file#"$p"}"
|
||||
name="${name#"/"}"
|
||||
minify -o "${p}/${name}" "$file"
|
||||
done
|
||||
}
|
||||
|
||||
if command -v minify > /dev/null; then
|
||||
minify_assets "$ZS_OUTDIR" "css"
|
||||
minify_assets "$ZS_OUTDIR" "js"
|
||||
fi
|
3
default/.zs/prehook
Executable file
3
default/.zs/prehook
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
exit 0
|
14
default/.zs/scripts
Executable file
14
default/.zs/scripts
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
JS="highlight main"
|
||||
|
||||
# Load live.js for non-production builds for faster development
|
||||
if [ -z "$ZS_PRODUCTION" ]; then
|
||||
JS="$JS live"
|
||||
fi
|
||||
|
||||
for js in $JS; do
|
||||
printf "<script type=\"application/javascript\" src=\"/assets/js/%s.js\"></script>\n" "$js"
|
||||
done
|
9
default/.zs/styles
Executable file
9
default/.zs/styles
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
CSS="highlight site"
|
||||
|
||||
for css in $CSS; do
|
||||
printf "<link rel=\"stylesheet\" href=\"/assets/css/%s.css\">\n" "$css"
|
||||
done
|
6
default/.zsignore
Normal file
6
default/.zsignore
Normal file
@ -0,0 +1,6 @@
|
||||
*~
|
||||
*.bak
|
||||
|
||||
LICENSE
|
||||
Makefile
|
||||
README.md
|
13
default/LICENSE
Normal file
13
default/LICENSE
Normal file
@ -0,0 +1,13 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
29
default/Makefile
Normal file
29
default/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
.PHONY: deps dev build image clean
|
||||
|
||||
GOCMD=go
|
||||
IMAGE := r.mills.io/prologic/twtxt.dev
|
||||
TAG := latest
|
||||
|
||||
all: build
|
||||
|
||||
deps:
|
||||
@$(GOCMD) install go.mills.io/zs@latest
|
||||
@$(GOCMD) install github.com/tdewolff/minify/v2/cmd/minify@latest
|
||||
|
||||
dev : DEBUG=1
|
||||
dev : build
|
||||
@zs serve
|
||||
|
||||
build:
|
||||
@zs build
|
||||
|
||||
ifeq ($(PUBLISH), 1)
|
||||
image:
|
||||
@docker buildx build --platform linux/amd64,linux/arm64 --push -t $(IMAGE):$(TAG) .
|
||||
else
|
||||
image:
|
||||
@docker build -t $(IMAGE):$(TAG) .
|
||||
endif
|
||||
|
||||
clean:
|
||||
@git clean -f -d
|
BIN
default/apple-touch-icon.png
Normal file
BIN
default/apple-touch-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
9
default/assets/css/highlight.css
Normal file
9
default/assets/css/highlight.css
Normal file
@ -0,0 +1,9 @@
|
||||
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
|
||||
Theme: GitHub Dark Dimmed
|
||||
Description: Dark dimmed theme as seen on github.com
|
||||
Author: github.com
|
||||
Maintainer: @Hirse
|
||||
Updated: 2021-05-15
|
||||
|
||||
Colors taken from GitHub's CSS
|
||||
*/.hljs{color:#adbac7;background:#22272e}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#f47067}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#dcbdfb}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#6cb6ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#96d0ff}.hljs-built_in,.hljs-symbol{color:#f69d50}.hljs-code,.hljs-comment,.hljs-formula{color:#768390}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#8ddb8c}.hljs-subst{color:#adbac7}.hljs-section{color:#316dca;font-weight:700}.hljs-bullet{color:#eac55f}.hljs-emphasis{color:#adbac7;font-style:italic}.hljs-strong{color:#adbac7;font-weight:700}.hljs-addition{color:#b4f1b4;background-color:#1b4721}.hljs-deletion{color:#ffd8d3;background-color:#78191b}
|
48
default/assets/css/reset.css
Normal file
48
default/assets/css/reset.css
Normal file
@ -0,0 +1,48 @@
|
||||
/* http://meyerweb.com/eric/tools/css/reset/
|
||||
v2.0 | 20110126
|
||||
License: none (public domain)
|
||||
*/
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
447
default/assets/css/site.css
Normal file
447
default/assets/css/site.css
Normal file
@ -0,0 +1,447 @@
|
||||
/* site.css */
|
||||
|
||||
/* Default Light Theme Variables */
|
||||
:root {
|
||||
--background-color: #ffffff;
|
||||
--text-color: #333333;
|
||||
--link-color: #1d5ed0;
|
||||
--link-hover-color: #0a47ab;
|
||||
/* Improved hover contrast for light mode */
|
||||
--header-background: #f8f9fa;
|
||||
--footer-background: #f8f9fa;
|
||||
--button-background: transparent;
|
||||
--button-color: #333333;
|
||||
--nav-link-color: #333333;
|
||||
--nav-link-active: #ccc;
|
||||
--quote-border-color: #ccc;
|
||||
--quote-text-color: #555;
|
||||
--quote-background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
/* Dark Theme Variables */
|
||||
[data-theme="dark"] {
|
||||
--background-color: #121212;
|
||||
--text-color: #e0e0e0;
|
||||
--link-color: #64B5F6;
|
||||
/* Light blue with good contrast */
|
||||
--link-hover-color: #2196F3;
|
||||
/* Brighter blue for hover effect */
|
||||
--header-background: #1f1f1f;
|
||||
--footer-background: #1f1f1f;
|
||||
--button-background: transparent;
|
||||
--button-color: #e0e0e0;
|
||||
--nav-link-color: #e0e0e0;
|
||||
--nav-link-active: #333333;
|
||||
--quote-border-color: #555;
|
||||
--quote-text-color: #ccc;
|
||||
--quote-background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
/* Global Styles */
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
overflow-x: hidden;
|
||||
/* Prevent horizontal scrolling */
|
||||
}
|
||||
|
||||
/* Global Link Styles */
|
||||
a {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
color: var(--link-hover-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Adjusted Container */
|
||||
.container {
|
||||
width: 95%;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
/* Include padding and border in width */
|
||||
}
|
||||
|
||||
/* Adjust margins for child elements */
|
||||
.container h1,
|
||||
.container h2,
|
||||
.container h3,
|
||||
.container h4,
|
||||
.container h5,
|
||||
.container h6,
|
||||
.container p,
|
||||
.container ul,
|
||||
.container ol,
|
||||
.container pre,
|
||||
.container code,
|
||||
.container blockquote {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
header {
|
||||
background-color: var(--header-background);
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
header .container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.header-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
header .logo {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Theme Toggle Button */
|
||||
#theme-toggle {
|
||||
background: var(--button-background);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--button-color);
|
||||
font-size: 1.5em;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
/* Menu Toggle Button */
|
||||
#menu-toggle {
|
||||
background: var(--button-background);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--button-color);
|
||||
font-size: 1.5em;
|
||||
display: none;
|
||||
/* Hidden by default */
|
||||
}
|
||||
|
||||
/* Navigation Menu */
|
||||
nav#main-nav {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
display: block;
|
||||
color: var(--nav-link-color);
|
||||
text-decoration: none;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
nav ul li a.active {
|
||||
background-color: var(--nav-link-active);
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
background-color: var(--nav-link-active);
|
||||
text-decoration: none;
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
|
||||
/* Navigation Logo Styling */
|
||||
header .logo {
|
||||
display: flex;
|
||||
/* Make the logo a flex container */
|
||||
align-items: center;
|
||||
/* Vertically center the content */
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
header .logo img {
|
||||
height: 40px;
|
||||
/* Adjust logo size */
|
||||
width: auto;
|
||||
margin-right: 0.5em;
|
||||
/* Space between the logo and the text */
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
|
||||
/* Adjust header layout */
|
||||
.header-top {
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
/* Push the elements to the left and right ends */
|
||||
}
|
||||
|
||||
/* Show the menu toggle button */
|
||||
#menu-toggle {
|
||||
display: block;
|
||||
order: 2;
|
||||
/* Move the menu toggle to the right */
|
||||
}
|
||||
|
||||
/* Keep the logo on the left */
|
||||
header .logo {
|
||||
order: 1;
|
||||
margin-left: 0.5em;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* Adjust theme toggle button */
|
||||
#theme-toggle {
|
||||
order: 3;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Hide the navigation menu by default */
|
||||
nav#main-nav {
|
||||
display: none;
|
||||
order: 4;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Show the navigation menu when toggled */
|
||||
nav#main-nav.open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Stack the navigation links vertically */
|
||||
nav ul {
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
padding: 0.75em 0 0.75rem 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 801px) {
|
||||
|
||||
/* Hide the menu toggle button on large screens */
|
||||
#menu-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Ensure navigation is visible on large screens */
|
||||
nav#main-nav {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* Reset order and margins */
|
||||
.header-top {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
header .logo {
|
||||
order: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
#theme-toggle {
|
||||
order: 0;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
main {
|
||||
padding: 1em 0;
|
||||
}
|
||||
|
||||
article {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
article h2 {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
aside {
|
||||
width: 33%;
|
||||
padding-left: .5rem;
|
||||
margin-left: .5rem;
|
||||
float: right;
|
||||
border-left: 2px solid var(--button-color);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
aside>p {
|
||||
margin: .5rem;
|
||||
}
|
||||
|
||||
/* Inline Code */
|
||||
code {
|
||||
background-color: #f5f5f5;
|
||||
padding: 0.2em 0.4em;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
[data-theme="dark"] code {
|
||||
background-color: #1e1e1e;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
/* Code Blocks */
|
||||
pre {
|
||||
background-color: #f5f5f5;
|
||||
padding: 0.5em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
[data-theme="dark"] pre {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
pre code {
|
||||
background-color: inherit;
|
||||
/* Use the same background as pre */
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* Images and Media */
|
||||
img,
|
||||
iframe,
|
||||
video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
background-color: var(--footer-background);
|
||||
padding: 1em 0;
|
||||
}
|
||||
|
||||
footer .container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1em;
|
||||
/* Adds space between footer items */
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
/* Ensure there's no margin collapse and the text stays separated */
|
||||
}
|
||||
|
||||
footer .edit-page-link {
|
||||
margin-left: auto;
|
||||
/* Push the edit page link to the far right */
|
||||
}
|
||||
|
||||
footer .edit-page-link a {
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
footer .edit-page-link a:hover {
|
||||
text-decoration: underline;
|
||||
color: var(--link-hover-color);
|
||||
/* Improved hover color in footer */
|
||||
}
|
||||
|
||||
/* Responsive Footer */
|
||||
@media (max-width: 600px) {
|
||||
footer .container {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.5em;
|
||||
/* Adds vertical space between items */
|
||||
}
|
||||
|
||||
footer .edit-page-link {
|
||||
margin-left: 0;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Styles for Page Lists */
|
||||
.list {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.list li {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.list li::before {
|
||||
content: "• ";
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
/* Blockquote Styles */
|
||||
blockquote {
|
||||
border-left: 4px solid var(--quote-border-color);
|
||||
padding-left: 1em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
color: var(--quote-text-color);
|
||||
background-color: var(--quote-background-color);
|
||||
font-style: italic;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
/* Optional Inline Quote Styles */
|
||||
q {
|
||||
quotes: "“""”""‘""’";
|
||||
font-style: italic;
|
||||
color: var(--quote-text-color);
|
||||
}
|
||||
|
||||
/* Anchors */
|
||||
h1:hover .anchor:before,
|
||||
h2:hover .anchor:before,
|
||||
h3:hover .anchor:before,
|
||||
h4:hover .anchor:before,
|
||||
h5:hover .anchor:before,
|
||||
h6:hover .anchor:before {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
content: ' ';
|
||||
display: inline-block;
|
||||
background-color: currentColor;
|
||||
-webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
|
||||
mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
|
||||
}
|
1202
default/assets/js/highlight.js
Normal file
1202
default/assets/js/highlight.js
Normal file
File diff suppressed because one or more lines are too long
233
default/assets/js/live.js
Normal file
233
default/assets/js/live.js
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
Live.js - One script closer to Designing in the Browser
|
||||
Written for Handcraft.com by Martin Kool (@mrtnkl).
|
||||
|
||||
Version 4.
|
||||
Recent change: Made stylesheet and mimetype checks case insensitive.
|
||||
|
||||
http://livejs.com
|
||||
http://livejs.com/license (MIT)
|
||||
@livejs
|
||||
|
||||
Include live.js#css to monitor css changes only.
|
||||
Include live.js#js to monitor js changes only.
|
||||
Include live.js#html to monitor html changes only.
|
||||
Mix and match to monitor a preferred combination such as live.js#html,css
|
||||
|
||||
By default, just include live.js to monitor all css, js and html changes.
|
||||
|
||||
Live.js can also be loaded as a bookmarklet. It is best to only use it for CSS then,
|
||||
as a page reload due to a change in html or css would not re-include the bookmarklet.
|
||||
To monitor CSS and be notified that it has loaded, include it as: live.js#css,notify
|
||||
*/
|
||||
(function () {
|
||||
|
||||
var headers = { "Etag": 1, "Last-Modified": 1, "Content-Length": 1, "Content-Type": 1 },
|
||||
resources = {},
|
||||
pendingRequests = {},
|
||||
currentLinkElements = {},
|
||||
oldLinkElements = {},
|
||||
interval = 1000,
|
||||
loaded = false,
|
||||
active = { "html": 1, "css": 1, "js": 1 };
|
||||
|
||||
var Live = {
|
||||
|
||||
// performs a cycle per interval
|
||||
heartbeat: function () {
|
||||
if (document.body) {
|
||||
// make sure all resources are loaded on first activation
|
||||
if (!loaded) Live.loadresources();
|
||||
Live.checkForChanges();
|
||||
}
|
||||
setTimeout(Live.heartbeat, interval);
|
||||
},
|
||||
|
||||
// loads all local css and js resources upon first activation
|
||||
loadresources: function () {
|
||||
|
||||
// helper method to assert if a given url is local
|
||||
function isLocal(url) {
|
||||
var loc = document.location,
|
||||
reg = new RegExp("^\\.|^\/(?!\/)|^[\\w]((?!://).)*$|" + loc.protocol + "//" + loc.host);
|
||||
return url.match(reg);
|
||||
}
|
||||
|
||||
// gather all resources
|
||||
var scripts = document.getElementsByTagName("script"),
|
||||
links = document.getElementsByTagName("link"),
|
||||
uris = [];
|
||||
|
||||
// track local js urls
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
var script = scripts[i], src = script.getAttribute("src");
|
||||
if (src && isLocal(src))
|
||||
uris.push(src);
|
||||
if (src && src.match(/\blive.js#/)) {
|
||||
for (var type in active)
|
||||
active[type] = src.match("[#,|]" + type) != null
|
||||
if (src.match("notify"))
|
||||
alert("Live.js is loaded.");
|
||||
}
|
||||
}
|
||||
if (!active.js) uris = [];
|
||||
if (active.html) uris.push(document.location.href);
|
||||
|
||||
// track local css urls
|
||||
for (var i = 0; i < links.length && active.css; i++) {
|
||||
var link = links[i], rel = link.getAttribute("rel"), href = link.getAttribute("href", 2);
|
||||
if (href && rel && rel.match(new RegExp("stylesheet", "i")) && isLocal(href)) {
|
||||
uris.push(href);
|
||||
currentLinkElements[href] = link;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize the resources info
|
||||
for (var i = 0; i < uris.length; i++) {
|
||||
var url = uris[i];
|
||||
Live.getHead(url, function (url, info) {
|
||||
resources[url] = info;
|
||||
});
|
||||
}
|
||||
|
||||
// add rule for morphing between old and new css files
|
||||
var head = document.getElementsByTagName("head")[0],
|
||||
style = document.createElement("style"),
|
||||
rule = "transition: all .3s ease-out;"
|
||||
css = [".livejs-loading * { ", rule, " -webkit-", rule, "-moz-", rule, "-o-", rule, "}"].join('');
|
||||
style.setAttribute("type", "text/css");
|
||||
head.appendChild(style);
|
||||
style.styleSheet ? style.styleSheet.cssText = css : style.appendChild(document.createTextNode(css));
|
||||
|
||||
// yep
|
||||
loaded = true;
|
||||
},
|
||||
|
||||
// check all tracking resources for changes
|
||||
checkForChanges: function () {
|
||||
for (var url in resources) {
|
||||
if (pendingRequests[url])
|
||||
continue;
|
||||
|
||||
Live.getHead(url, function (url, newInfo) {
|
||||
var oldInfo = resources[url],
|
||||
hasChanged = false;
|
||||
resources[url] = newInfo;
|
||||
for (var header in oldInfo) {
|
||||
// do verification based on the header type
|
||||
var oldValue = oldInfo[header],
|
||||
newValue = newInfo[header],
|
||||
contentType = newInfo["Content-Type"];
|
||||
switch (header.toLowerCase()) {
|
||||
case "etag":
|
||||
if (!newValue) break;
|
||||
// fall through to default
|
||||
default:
|
||||
hasChanged = oldValue != newValue;
|
||||
break;
|
||||
}
|
||||
// if changed, act
|
||||
if (hasChanged) {
|
||||
Live.refreshResource(url, contentType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// act upon a changed url of certain content type
|
||||
refreshResource: function (url, type) {
|
||||
switch (type.toLowerCase()) {
|
||||
// css files can be reloaded dynamically by replacing the link element
|
||||
case "text/css":
|
||||
var link = currentLinkElements[url],
|
||||
html = document.body.parentNode,
|
||||
head = link.parentNode,
|
||||
next = link.nextSibling,
|
||||
newLink = document.createElement("link");
|
||||
|
||||
html.className = html.className.replace(/\s*livejs\-loading/gi, '') + ' livejs-loading';
|
||||
newLink.setAttribute("type", "text/css");
|
||||
newLink.setAttribute("rel", "stylesheet");
|
||||
newLink.setAttribute("href", url + "?now=" + new Date() * 1);
|
||||
next ? head.insertBefore(newLink, next) : head.appendChild(newLink);
|
||||
currentLinkElements[url] = newLink;
|
||||
oldLinkElements[url] = link;
|
||||
|
||||
// schedule removal of the old link
|
||||
Live.removeoldLinkElements();
|
||||
break;
|
||||
|
||||
// check if an html resource is our current url, then reload
|
||||
case "text/html":
|
||||
if (url != document.location.href)
|
||||
return;
|
||||
|
||||
// local javascript changes cause a reload as well
|
||||
case "text/javascript":
|
||||
case "application/javascript":
|
||||
case "application/x-javascript":
|
||||
document.location.reload();
|
||||
}
|
||||
},
|
||||
|
||||
// removes the old stylesheet rules only once the new one has finished loading
|
||||
removeoldLinkElements: function () {
|
||||
var pending = 0;
|
||||
for (var url in oldLinkElements) {
|
||||
// if this sheet has any cssRules, delete the old link
|
||||
try {
|
||||
var link = currentLinkElements[url],
|
||||
oldLink = oldLinkElements[url],
|
||||
html = document.body.parentNode,
|
||||
sheet = link.sheet || link.styleSheet,
|
||||
rules = sheet.rules || sheet.cssRules;
|
||||
if (rules.length >= 0) {
|
||||
oldLink.parentNode.removeChild(oldLink);
|
||||
delete oldLinkElements[url];
|
||||
setTimeout(function () {
|
||||
html.className = html.className.replace(/\s*livejs\-loading/gi, '');
|
||||
}, 100);
|
||||
}
|
||||
} catch (e) {
|
||||
pending++;
|
||||
}
|
||||
if (pending) setTimeout(Live.removeoldLinkElements, 50);
|
||||
}
|
||||
},
|
||||
|
||||
// performs a HEAD request and passes the header info to the given callback
|
||||
getHead: function (url, callback) {
|
||||
pendingRequests[url] = true;
|
||||
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XmlHttp");
|
||||
xhr.open("HEAD", url, true);
|
||||
xhr.onreadystatechange = function () {
|
||||
delete pendingRequests[url];
|
||||
if (xhr.readyState == 4 && xhr.status != 304) {
|
||||
xhr.getAllResponseHeaders();
|
||||
var info = {};
|
||||
for (var h in headers) {
|
||||
var value = xhr.getResponseHeader(h);
|
||||
// adjust the simple Etag variant to match on its significant part
|
||||
if (h.toLowerCase() == "etag" && value) value = value.replace(/^W\//, '');
|
||||
if (h.toLowerCase() == "content-type" && value) value = value.replace(/^(.*?);.*?$/i, "$1");
|
||||
info[h] = value;
|
||||
}
|
||||
callback(url, info);
|
||||
}
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
};
|
||||
|
||||
// start listening
|
||||
if (document.location.protocol != "file:") {
|
||||
if (!window.liveJsLoaded)
|
||||
Live.heartbeat();
|
||||
|
||||
window.liveJsLoaded = true;
|
||||
}
|
||||
else if (window.console)
|
||||
console.log("Live.js doesn't support the file protocol. It needs http.");
|
||||
})();
|
41
default/assets/js/main.js
Normal file
41
default/assets/js/main.js
Normal file
@ -0,0 +1,41 @@
|
||||
// Toggle the navigation menu and theme
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var menuToggle = document.getElementById('menu-toggle');
|
||||
var mainNav = document.getElementById('main-nav');
|
||||
var themeToggle = document.getElementById('theme-toggle');
|
||||
var body = document.body;
|
||||
|
||||
// Menu toggle functionality
|
||||
menuToggle.addEventListener('click', function() {
|
||||
mainNav.classList.toggle('open');
|
||||
});
|
||||
|
||||
// Theme toggle functionality
|
||||
themeToggle.addEventListener('click', function() {
|
||||
// Toggle between 'light' and 'dark' themes
|
||||
var currentTheme = body.getAttribute('data-theme') || 'light';
|
||||
var newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||
body.setAttribute('data-theme', newTheme);
|
||||
localStorage.setItem('theme', newTheme);
|
||||
});
|
||||
|
||||
// On page load, set the theme from localStorage or system preference
|
||||
var storedTheme = localStorage.getItem('theme');
|
||||
if (storedTheme) {
|
||||
body.setAttribute('data-theme', storedTheme);
|
||||
} else {
|
||||
// Detect system preference
|
||||
var prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
var defaultTheme = prefersDarkScheme ? 'dark' : 'light';
|
||||
body.setAttribute('data-theme', defaultTheme);
|
||||
}
|
||||
|
||||
// Listen for changes in the system color scheme
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
|
||||
var storedTheme = localStorage.getItem('theme');
|
||||
if (!storedTheme) {
|
||||
var newColorScheme = e.matches ? 'dark' : 'light';
|
||||
body.setAttribute('data-theme', newColorScheme);
|
||||
}
|
||||
});
|
||||
});
|
BIN
default/favicon-16x16.png
Normal file
BIN
default/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 347 B |
BIN
default/favicon-32x32.png
Normal file
BIN
default/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 675 B |
5
default/index.md
Normal file
5
default/index.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
title: my.zs.site
|
||||
---
|
||||
|
||||
👋 Hello World! 👋j
|
BIN
default/logo.png
Normal file
BIN
default/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 75 KiB |
13
go.mod
13
go.mod
@ -6,6 +6,7 @@ require (
|
||||
github.com/13rac1/goldmark-embed v0.0.0-20201220231550-e6806f2de66a
|
||||
github.com/FurqanSoftware/goldmark-d2 v0.0.0-20230207071629-ec535d32ca47
|
||||
github.com/alecthomas/chroma/v2 v2.7.0
|
||||
github.com/gabriel-vasile/mimetype v1.4.7
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
@ -16,7 +17,7 @@ require (
|
||||
go.abhg.dev/goldmark/anchor v0.1.1
|
||||
go.abhg.dev/goldmark/wikilink v0.5.0
|
||||
go.mills.io/static v0.0.0-20230401145044-4ee04f8d2f65
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sync v0.9.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
@ -55,13 +56,13 @@ require (
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/unrolled/logger v0.0.0-20201216141554-31a3694fe979 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||
golang.org/x/image v0.6.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/term v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/term v0.26.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
gonum.org/v1/plot v0.12.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec // indirect
|
||||
|
64
go.sum
64
go.sum
@ -1,5 +1,3 @@
|
||||
cdr.dev/slog v1.4.2-0.20221206192828-e4803b10ae17 h1:Jf+VOk2lif79HeTlnLaZ70zYTsuVSUEu/47U9VaG2Rw=
|
||||
cdr.dev/slog v1.4.2-0.20221206192828-e4803b10ae17/go.mod h1:YPVZsUbRMaLaPgme0RzlPWlC7fI7YmDj/j/kZLuvICs=
|
||||
cdr.dev/slog v1.4.2 h1:fIfiqASYQFJBZiASwL825atyzeA96NsqSxx2aL61P8I=
|
||||
cdr.dev/slog v1.4.2/go.mod h1:0EkH+GkFNxizNR+GAXUEdUHanxUH5t9zqPILmPM/Vn8=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
@ -55,18 +53,15 @@ github.com/FurqanSoftware/goldmark-d2 v0.0.0-20230207071629-ec535d32ca47 h1:TTYi
|
||||
github.com/FurqanSoftware/goldmark-d2 v0.0.0-20230207071629-ec535d32ca47/go.mod h1:re06sclYNSEKe8tBIZ7KweUIZECQewQSCaKKFyc1TpE=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
|
||||
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
|
||||
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
||||
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
||||
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw=
|
||||
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
|
||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.7.0 h1:hm1rY6c/Ob4eGclpQ7X/A3yhqBOZNUTk9q+yhyLIViI=
|
||||
github.com/alecthomas/chroma/v2 v2.7.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||
@ -93,13 +88,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.8.0 h1:rJD5HeGIT/2b5CDk63FVCwZA3qgYElfg+oQK7uH5pfE=
|
||||
github.com/dlclark/regexp2 v1.8.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0=
|
||||
github.com/dlclark/regexp2 v1.8.1/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||
github.com/dop251/goja v0.0.0-20230203172422-5460598cfa32 h1:audXtK7nV3y4W9ckAxRBE+eQV5Bljf5Non4NTa9kLVE=
|
||||
github.com/dop251/goja v0.0.0-20230203172422-5460598cfa32/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c h1:/utv6nmTctV6OVgfk5+O6lEMEWL+6KJy4h9NZ5fnkQQ=
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
||||
@ -111,13 +102,13 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA=
|
||||
github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU=
|
||||
github.com/go-fonts/liberation v0.2.0 h1:jAkAWJP4S+OsrPLZM4/eC9iW7CtHy+HBXrEwZXWo5VM=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -194,6 +185,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
@ -227,16 +219,12 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mazznoer/csscolorparser v0.1.3 h1:vug4zh6loQxAUxfU1DZEu70gTPufDPspamZlHAkKcxE=
|
||||
github.com/mazznoer/csscolorparser v0.1.3/go.mod h1:Aj22+L/rYN/Y6bj3bYqO3N6g1dtdHtGfQ32xZ5PJQic=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
|
||||
github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
|
||||
@ -249,16 +237,14 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
|
||||
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
||||
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
@ -304,8 +290,6 @@ go.abhg.dev/goldmark/anchor v0.1.1 h1:NUH3hAzhfeymRqZKOkSoFReZlEAmfXBZlbXEzpD2Qg
|
||||
go.abhg.dev/goldmark/anchor v0.1.1/go.mod h1:zYKiaHXTdugwVJRZqInVdmNGQRM3ZRJ6AGBC7xP7its=
|
||||
go.abhg.dev/goldmark/wikilink v0.5.0 h1:/Gndy7+PoXzOc3reVWtXAh7Cni7wSqSxiuXDfmoYlm4=
|
||||
go.abhg.dev/goldmark/wikilink v0.5.0/go.mod h1:W1NzvDIpo6uoayolBTCsIL6y/QRAHmLTKfUUDfR75DA=
|
||||
go.mills.io/static v0.0.0-20230316074605-51908d346ffc h1:BMeFNGUZAQCfgo8DxUKxgGNrXQa1KglS5gZ4Kn5fUsQ=
|
||||
go.mills.io/static v0.0.0-20230316074605-51908d346ffc/go.mod h1:TmaEDwM+IgrCRyMxtVWtmSdoxLP3N6ehBa7AiOZj2Mk=
|
||||
go.mills.io/static v0.0.0-20230401145044-4ee04f8d2f65 h1:1uqQoVNdJsKdNBLiUmO7nVj9vgfzTvlRnDEzZTt3ub8=
|
||||
go.mills.io/static v0.0.0-20230401145044-4ee04f8d2f65/go.mod h1:TmaEDwM+IgrCRyMxtVWtmSdoxLP3N6ehBa7AiOZj2Mk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
@ -316,7 +300,9 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@ -324,12 +310,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -340,15 +323,11 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg=
|
||||
golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.3.0 h1:HTDXbdK9bjfSWkPzDJIw89W8CAtfFGduujWs33NLLsg=
|
||||
golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A=
|
||||
golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4=
|
||||
golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -410,10 +389,9 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -434,8 +412,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -481,14 +460,14 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -498,11 +477,10 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@ -675,12 +653,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
oss.terrastruct.com/d2 v0.1.6 h1:TdNET4uzt3Djl66UriSR3sbItWYcCV9ugpHzF9w2eIY=
|
||||
oss.terrastruct.com/d2 v0.1.6/go.mod h1:7sIRmEj3QeXVB6erSPW6dOfFUX7orsQkO0twmTYILEA=
|
||||
oss.terrastruct.com/d2 v0.3.0 h1:hhrtD2P8mLbUDlxMzyu7sgJ3O7Y59EYpLozDdi+DT3g=
|
||||
oss.terrastruct.com/d2 v0.3.0/go.mod h1:7aLT1RP98WkuV6PQFtmCvdO83gOk2unuDiqYHFP2Ww8=
|
||||
oss.terrastruct.com/util-go v0.0.0-20230124232704-39c2226d2b5e h1:pCKxiUFOLQamCtmyMZsM3Hc8MuKVpDg/4VunhVOVW/4=
|
||||
oss.terrastruct.com/util-go v0.0.0-20230124232704-39c2226d2b5e/go.mod h1:Fwy72FDIOOM4K8F96ScXkxHHppR1CPfUyo9+x9c1PBU=
|
||||
oss.terrastruct.com/util-go v0.0.0-20230320053557-dcb5aac7d972 h1:HS7fg2GzGsqRLApsoh7ztaLMvXzxSln/Hfz4wy4tIDA=
|
||||
oss.terrastruct.com/util-go v0.0.0-20230320053557-dcb5aac7d972/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
|
145
main.go
145
main.go
@ -4,9 +4,11 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -17,16 +19,17 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
embed "github.com/13rac1/goldmark-embed"
|
||||
d2 "github.com/FurqanSoftware/goldmark-d2"
|
||||
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
|
||||
ignore "github.com/sabhiram/go-gitignore"
|
||||
embedExt "github.com/13rac1/goldmark-embed"
|
||||
d2Ext "github.com/FurqanSoftware/goldmark-d2"
|
||||
chromaHTMLExt "github.com/alecthomas/chroma/v2/formatters/html"
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
gitIgnore "github.com/sabhiram/go-gitignore"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
fences "github.com/stefanfritsch/goldmark-fences"
|
||||
fencesExt "github.com/stefanfritsch/goldmark-fences"
|
||||
"github.com/yuin/goldmark"
|
||||
highlighting "github.com/yuin/goldmark-highlighting/v2"
|
||||
highlightingExt "github.com/yuin/goldmark-highlighting/v2"
|
||||
"github.com/yuin/goldmark/extension"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/renderer/html"
|
||||
@ -62,7 +65,7 @@ README.md`
|
||||
)
|
||||
|
||||
// Ignore holds a set of patterns to ignore from parsing a .zsignore file
|
||||
var Ignore *ignore.GitIgnore
|
||||
var Ignore *gitIgnore.GitIgnore
|
||||
|
||||
// Parser holds a configured global instance of the goldmark markdown parser
|
||||
var Parser goldmark.Markdown
|
||||
@ -70,6 +73,9 @@ var Parser goldmark.Markdown
|
||||
var (
|
||||
configFile string
|
||||
enabledExtensions []string
|
||||
|
||||
//go:embed default default/.zs
|
||||
defaultFS embed.FS
|
||||
)
|
||||
|
||||
// Extensions is a mapping of name to extension and the default set of extensions enabled
|
||||
@ -84,16 +90,16 @@ var Extensions = map[string]goldmark.Extender{
|
||||
"footnote": extension.Footnote,
|
||||
"typography": extension.Typographer,
|
||||
"cjk": extension.CJK,
|
||||
"highlighting": highlighting.NewHighlighting(
|
||||
highlighting.WithStyle("github"),
|
||||
highlighting.WithFormatOptions(
|
||||
chromahtml.WithLineNumbers(true),
|
||||
"highlighting": highlightingExt.NewHighlighting(
|
||||
highlightingExt.WithStyle("github"),
|
||||
highlightingExt.WithFormatOptions(
|
||||
chromaHTMLExt.WithLineNumbers(true),
|
||||
),
|
||||
),
|
||||
"anchor": &anchor.Extender{Texter: anchor.Text(" ")},
|
||||
"d2": &d2.Extender{},
|
||||
"embed": embed.New(),
|
||||
"fences": &fences.Extender{},
|
||||
"d2": &d2Ext.Extender{},
|
||||
"embed": embedExt.New(),
|
||||
"fences": &fencesExt.Extender{},
|
||||
"wikilink": &wikilink.Extender{},
|
||||
}
|
||||
|
||||
@ -137,6 +143,8 @@ var RootCmd = &cobra.Command{
|
||||
- Use placeholders for variables and plugins in your markdown or html files, e.g. {{ title }} or {{ command arg1 arg2 }}.
|
||||
- Write extensions in any language you like and put them into the .zs sub-directory.
|
||||
- Everything the extensions prints to stdout becomes the value of the placeholder.
|
||||
|
||||
Quick Start: zs init
|
||||
`,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
debug, err := cmd.Flags().GetBool("debug")
|
||||
@ -214,6 +222,39 @@ var GenerateCmd = &cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
// InitCmd is the init sub-command that creates a new zs site
|
||||
var InitCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Aliases: []string{"new"},
|
||||
Short: "Initializes a new Zen Static site",
|
||||
Long: `The init command creates a new Zen Static site in the current directory`,
|
||||
Args: cobra.RangeArgs(0, 1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
dir string
|
||||
err error
|
||||
)
|
||||
|
||||
if len(args) > 0 || (len(args) == 1 && args[0] == ".") {
|
||||
dir = args[0]
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return fmt.Errorf("error creating directory %q: %w", dir, err)
|
||||
}
|
||||
} else {
|
||||
dir, err = os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting current directory: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := initSite(dir); err != nil {
|
||||
return fmt.Errorf("error initializing site: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// ServeCmd is the serve sub-command that performs whole builds or single builds
|
||||
var ServeCmd = &cobra.Command{
|
||||
Use: "serve [flags]",
|
||||
@ -683,6 +724,70 @@ func generate(r io.Reader, w io.Writer, v Vars) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// copyFile copies a file from the src fs.FS to the dst directory.
|
||||
//
|
||||
// This function assumes that the dst directory already exists.
|
||||
func copyFile(src fs.FS, dst string, path string) error {
|
||||
r, err := src.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := os.Create(filepath.Join(dst, path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err := io.Copy(f, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// initSite initializes the site
|
||||
func initSite(dir string) error {
|
||||
defaultFS, err := fs.Sub(defaultFS, "default")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get default fs: %w", err)
|
||||
}
|
||||
|
||||
// Copy files and directories from the default structure from defaultFS
|
||||
if err := fs.WalkDir(defaultFS, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if path == "." || path == ".." {
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.IsDir() {
|
||||
os.Mkdir(filepath.Join(dir, path), 0755)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := copyFile(defaultFS, dir, path); err != nil {
|
||||
return fmt.Errorf("failed to copy file: %w", err)
|
||||
}
|
||||
|
||||
fileType, err := mimetype.DetectFile(filepath.Join(dir, path))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to detect file type: %w", err)
|
||||
}
|
||||
|
||||
// If the fileType is an executable application or script, make it executable
|
||||
if fileType.Is("application/x-executable") {
|
||||
if err := os.Chmod(filepath.Join(dir, path), 0755); err != nil {
|
||||
return fmt.Errorf("failed to set executable permissions: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to walk default fs: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serve runs a static web server and builds and continuously watches for changes to rebuild
|
||||
func serve(ctx context.Context, bind, root string) error {
|
||||
os.Mkdir(root, 0755)
|
||||
@ -763,6 +868,7 @@ func init() {
|
||||
|
||||
RootCmd.AddCommand(BuildCmd)
|
||||
RootCmd.AddCommand(GenerateCmd)
|
||||
RootCmd.AddCommand(InitCmd)
|
||||
RootCmd.AddCommand(ServeCmd)
|
||||
RootCmd.AddCommand(VarCmd)
|
||||
RootCmd.AddCommand(WatchCmd)
|
||||
@ -770,6 +876,11 @@ func init() {
|
||||
// prepend .zs to $PATH, so plugins will be found before OS commands
|
||||
w, _ := os.Getwd()
|
||||
ensureFirstPath(filepath.Join(w, ZSDIR))
|
||||
|
||||
// Extend mimetype to support application/x-shellscript and text/x-shellscript
|
||||
mimetype.Extend(func(raw []byte, limit uint32) bool {
|
||||
return len(raw) >= 2 && raw[0] == '#' && raw[1] == '!'
|
||||
}, "application/x-executable", "")
|
||||
}
|
||||
|
||||
// initConfig reads in config file and ENV variables if set.
|
||||
@ -797,13 +908,13 @@ func initConfig() {
|
||||
}
|
||||
|
||||
// ParseIgnoreFile parsers a .zsignore file or uses the default if an error occurred
|
||||
func ParseIgnoreFile(fn string) *ignore.GitIgnore {
|
||||
obj, err := ignore.CompileIgnoreFile(ZSIGNORE)
|
||||
func ParseIgnoreFile(fn string) *gitIgnore.GitIgnore {
|
||||
obj, err := gitIgnore.CompileIgnoreFile(ZSIGNORE)
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
log.WithError(err).Warnf("error parsing .zsignore: %s (using defaults)s", fn)
|
||||
}
|
||||
return ignore.CompileIgnoreLines(DefaultIgnore)
|
||||
return gitIgnore.CompileIgnoreLines(DefaultIgnore)
|
||||
}
|
||||
|
||||
return obj
|
||||
|
Loading…
Reference in New Issue
Block a user