making simplewebpage html compliant

This commit is contained in:
Q
2025-08-27 10:13:13 +03:00
parent e5c8026bab
commit d378c2d1e9

View File

@@ -1,18 +1,17 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding=utf-8 # coding=utf-8
""" A script that creates an index for a folder. """A script that creates an index for a folder."""
"""
import base64
import json
import os import os
import random
import re
import string
import sys import sys
import time import time
import string
import json
import re
import urllib.parse import urllib.parse
from glob import fnmatch from glob import fnmatch
import base64
import random
from pprint import pprint from pprint import pprint
try: try:
@@ -22,7 +21,7 @@ try:
except ImportError: except ImportError:
MARKDOWN_AVAILABLE = False MARKDOWN_AVAILABLE = False
VERSION = "20240819" VERSION = "20250827"
IMAGE_EXTENSIONS = ["png", "gif", "jpg", "jpeg", "tif", "tiff"] IMAGE_EXTENSIONS = ["png", "gif", "jpg", "jpeg", "tif", "tiff"]
AUDIO_EXTENSIONS = ["wav", "mp3", "ogg"] AUDIO_EXTENSIONS = ["wav", "mp3", "ogg"]
VIDEO_EXTENSIONS = ["mp4", "ogg", "webm"] VIDEO_EXTENSIONS = ["mp4", "ogg", "webm"]
@@ -247,20 +246,18 @@ def generate_index(opts):
if opts.filename in files: if opts.filename in files:
opts, existing_config = HTML2setup(opts, opts.overwrite) opts, existing_config = HTML2setup(opts, opts.overwrite)
if not existing_config and not opts.overwrite: if not existing_config and not opts.overwrite:
print( print(opts.filename + " exists, and not generated with SimpleWebPage. Exiting.")
opts.filename
+ " exists, and not generated with SimpleWebPage. Exiting."
)
sys.exit(1) sys.exit(1)
# Re-read files, with probably changed opts # Re-read files, with probably changed opts
dirs, files, path = get_files_and_folders(opts) dirs, files, path = get_files_and_folders(opts)
print_setup(opts) print_setup(opts)
files = [f for f in files if f != opts.filename] files = [f for f in files if f != opts.filename]
files = [f for f in files if f != opts.password_filename] files = [f for f in files if f != opts.password_filename]
natsort = lambda s: [int(t) if t.isdigit() else t for t in re.split(r"(\d+)", s)]
files = match_files(files, opts.includes, opts.excludes) files = match_files(files, opts.includes, opts.excludes)
dirs = match_files(dirs, opts.includes, opts.excludes) dirs = match_files(dirs, opts.includes, opts.excludes)
dirs.sort(reverse=opts.reverse) dirs.sort(reverse=opts.reverse, key=natsort)
files.sort(reverse=opts.reverse) files.sort(reverse=opts.reverse, key=natsort)
files.sort(key=lambda x: x.find("/") > 0) files.sort(key=lambda x: x.find("/") > 0)
readme = get_readme(path, opts.no_readme) readme = get_readme(path, opts.no_readme)
with open(os.path.join(path, opts.filename), "wt") as f: with open(os.path.join(path, opts.filename), "wt") as f:
@@ -271,9 +268,7 @@ def generate_index(opts):
f.write(get_pathlink(path, di)) f.write(get_pathlink(path, di))
for fi in files: for fi in files:
f.write(get_filelink(path, fi, opts.images, opts.media)) f.write(get_filelink(path, fi, opts.images, opts.media))
f.write(get_footer(readme, show_wget=not opts.no_wget)) f.write(get_footer(readme, show_wget=not opts.no_wget, recursive=opts.recursive, files=files))
if not opts.no_wget:
f.write(get_download_lines(files, recursive=opts.recursive))
f.close() f.close()
return return
@@ -314,9 +309,7 @@ def generate_password_page(path, password_file, password):
def get_filelink(path, fname, images=False, media=False): def get_filelink(path, fname, images=False, media=False):
if os.path.islink(os.path.join(path, fname)) and not os.path.exists( if os.path.islink(os.path.join(path, fname)) and not os.path.exists(os.path.join(path, fname)):
os.path.join(path, fname)
):
(fsize, fsstr, fsstrb, fdstr) = (0, "NA", "NA", "NA") (fsize, fsstr, fsstrb, fdstr) = (0, "NA", "NA", "NA")
else: else:
fsize = os.path.getsize(os.path.join(path, fname)) fsize = os.path.getsize(os.path.join(path, fname))
@@ -361,15 +354,11 @@ def get_imagestr(fname):
def get_audiostr(fname): def get_audiostr(fname):
return '<audio src="%s" controls class=audio></audio>' % ( return '<audio src="%s" controls class=audio></audio>' % (urllib.parse.quote(fname),)
urllib.parse.quote(fname),
)
def get_videostr(fname): def get_videostr(fname):
return '<video class=video controls><source src="%s"></video>' % ( return '<video class=video controls><source src="%s"></video>' % (urllib.parse.quote(fname),)
urllib.parse.quote(fname),
)
def get_pathlink(path, dname): def get_pathlink(path, dname):
@@ -383,7 +372,7 @@ def get_pathlink(path, dname):
def get_password_page(secret, target_base, target_ext): def get_password_page(secret, target_base, target_ext):
return ( return (
"""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
@@ -459,7 +448,7 @@ function newPass(password, target) {
} }
//console.log("Use newPass('pass','page.html'); to get a new hash"); //console.log("Use newPass('pass','page.html'); to get a new hash");
</script> </script>
<style> <style type="text/css">
iframe { iframe {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
@@ -507,9 +496,7 @@ def get_readme(path, no_read):
return "" return ""
with open(os.path.join(path, "README.md"), "rt") as fp: with open(os.path.join(path, "README.md"), "rt") as fp:
if MARKDOWN_AVAILABLE: if MARKDOWN_AVAILABLE:
return "<div class=readme>{}</div>".format( return "<div class=readme>{}</div>".format(markdown.markdown(fp.read().strip(), extensions=["extra"]))
markdown.markdown(fp.read().strip(), extensions=["extra"])
)
else: else:
sys.stderr.write("import markdown failed, using simple regex\n") sys.stderr.write("import markdown failed, using simple regex\n")
@@ -574,11 +561,12 @@ function ts_makeSortable(t) {
if (!firstRow) return; if (!firstRow) return;
// We have a first row: assume it's the header, and make its contents clickable links // We have a first row: assume it's the header, and make its contents clickable links
var untag = '</';
for (var i=0;i<firstRow.cells.length;i++) { for (var i=0;i<firstRow.cells.length;i++) {
var cell = firstRow.cells[i]; var cell = firstRow.cells[i];
var txt = ts_getInnerText(cell); var txt = ts_getInnerText(cell);
if (cell.className != "unsortable" && cell.className.indexOf("unsortable") == -1) { if (cell.className != "unsortable" && cell.className.indexOf("unsortable") == -1) {
cell.innerHTML = '<span class="sortheader" onclick="ts_resortTable(this, '+i+');return false;">'+txt+'<span class="sortarrow">&nbsp;&nbsp;&varr;</span></span>'; cell.innerHTML = '<span class="sortheader" onclick="ts_resortTable(this, '+i+');return false;">'+txt+'<span class="sortarrow">&nbsp;&nbsp;&varr;' + untag + 'span>' + untag + 'span>';
} }
} }
if (alternate_row_colors) { if (alternate_row_colors) {
@@ -632,7 +620,7 @@ function ts_resortTable(lnk, clid) {
sortfn = ts_sort_caseinsensitive; sortfn = ts_sort_caseinsensitive;
if (itm.match(/^\d\d[\/\.-][a-zA-z][a-zA-Z][a-zA-Z][\/\.-]\d\d\d\d$/)) sortfn = ts_sort_date; if (itm.match(/^\d\d[\/\.-][a-zA-z][a-zA-Z][a-zA-Z][\/\.-]\d\d\d\d$/)) sortfn = ts_sort_date;
if (itm.match(/^\d\d[\/\.-]\d\d[\/\.-]\d\d\d{2}?$/)) sortfn = ts_sort_date; if (itm.match(/^\d\d[\/\.-]\d\d[\/\.-]\d\d\d{2}?$/)) sortfn = ts_sort_date;
if (itm.match(/^-?[£$€Û¢´]\d/)) sortfn = ts_sort_numeric; if (itm.match(/^-?[£$¢´]\d/)) sortfn = ts_sort_numeric;
if (itm.match(/^-?(\d+[,\.]?)+(E[-+][\d]+)?%?$/)) sortfn = ts_sort_numeric; if (itm.match(/^-?(\d+[,\.]?)+(E[-+][\d]+)?%?$/)) sortfn = ts_sort_numeric;
SORT_COLUMN_INDEX = column; SORT_COLUMN_INDEX = column;
var firstRow = new Array(); var firstRow = new Array();
@@ -861,7 +849,7 @@ function show_wget_magic() {
""" """
) )
css_style = """ css_style = """
<style> <style type="text/css">
/* Style modified from: https://css-tricks.com/snippets/php/display-styled-directory-contents/ */ /* Style modified from: https://css-tricks.com/snippets/php/display-styled-directory-contents/ */
body { body {
color: #222; color: #222;
@@ -962,8 +950,8 @@ function show_wget_magic() {
padding-left: 5px; padding-left: 5px;
} }
.video { .video {
width: 320; width: 320px;
height: 240; height: 240px;
} }
.container pre { .container pre {
margin: 10px 10px 10px 10px; margin: 10px 10px 10px 10px;
@@ -983,7 +971,7 @@ function show_wget_magic() {
} }
table { table {
margin: 0; margin: 0;
width: 800px;monilla yrityksi width: 800px;
} }
td { td {
padding-top: 10px; padding-top: 10px;
@@ -1023,14 +1011,14 @@ function show_wget_magic() {
</style> </style>
""" """
header = ( header = (
"""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, height=device-height, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1, height=device-height, viewport-fit=cover">
<meta name="generator" content="{program}"/> <meta name="generator" content="{program}">
<meta name="SimpleWebPageVersion" content="{version}"/> <meta name="SimpleWebPageVersion" content="{version}">
<meta name="SimpleWebPageSetup" content='{config}'/> <meta name="SimpleWebPageSetup" content='{config}'>
<title>{title}</title> <title>{title}</title>
{css_style} {css_style}
@@ -1052,21 +1040,22 @@ function show_wget_magic() {
return header return header
def get_footer(readme, show_wget=True): def get_footer(readme, show_wget=True, recursive=False, files=[]):
if show_wget: if show_wget:
wget_str = """ wget_str = """
<div id=wget_container> <div id=wget_container>
<div id=wget_toggle onclick="show_wget_magic()">wget?</div> <div id=wget_toggle onclick="show_wget_magic()">wget?</div>
<pre id=wget_magic class=hidden></pre> <pre id=wget_magic class=hidden></pre>
</div> </div>"""
""" file_lines = get_download_lines(files, recursive=recursive)
else: else:
wget_str = "" wget_str = ""
file_lines = ""
return """</tbody></table>{README} return """</tbody></table>{README}
</div>{WGET_STR} </div>{WGET_STR}
{FILE_LINES}
</body></html>""".format( </body></html>""".format(
README=readme, WGET_STR=wget_str README=readme, WGET_STR=wget_str, FILE_LINES=file_lines
) )