add preadme.md; closes #105

This commit is contained in:
ed 2024-10-11 21:52:44 +00:00
parent 1e7697b551
commit 1d68acf8f0
5 changed files with 60 additions and 30 deletions

View file

@ -937,6 +937,8 @@ see [./srv/expand/](./srv/expand/) for usage and examples
* files named `README.md` / `readme.md` will be rendered after directory listings unless `--no-readme` (but `.epilogue.html` takes precedence) * files named `README.md` / `readme.md` will be rendered after directory listings unless `--no-readme` (but `.epilogue.html` takes precedence)
* and `PREADME.md` / `preadme.md` is shown above directory listings unless `--no-readme` or `.prologue.html`
* `README.md` and `*logue.html` can contain placeholder values which are replaced server-side before embedding into directory listings; see `--help-exp` * `README.md` and `*logue.html` can contain placeholder values which are replaced server-side before embedding into directory listings; see `--help-exp`
@ -2047,7 +2049,7 @@ other misc notes:
behavior that might be unexpected behavior that might be unexpected
* users without read-access to a folder can still see the `.prologue.html` / `.epilogue.html` / `README.md` contents, for the purpose of showing a description on how to use the uploader for example * users without read-access to a folder can still see the `.prologue.html` / `.epilogue.html` / `PREADME.md` / `README.md` contents, for the purpose of showing a description on how to use the uploader for example
* users can submit `<script>`s which autorun (in a sandbox) for other visitors in a few ways; * users can submit `<script>`s which autorun (in a sandbox) for other visitors in a few ways;
* uploading a `README.md` -- avoid with `--no-readme` * uploading a `README.md` -- avoid with `--no-readme`
* renaming `some.html` to `.epilogue.html` -- avoid with either `--no-logues` or `--no-dot-ren` * renaming `some.html` to `.epilogue.html` -- avoid with either `--no-logues` or `--no-dot-ren`

View file

@ -780,7 +780,7 @@ def get_sects():
dedent( dedent(
""" """
specify --exp or the "exp" volflag to enable placeholder expansions specify --exp or the "exp" volflag to enable placeholder expansions
in README.md / .prologue.html / .epilogue.html in README.md / PREADME.md / .prologue.html / .epilogue.html
--exp-md (volflag exp_md) holds the list of placeholders which can be --exp-md (volflag exp_md) holds the list of placeholders which can be
expanded in READMEs, and --exp-lg (volflag exp_lg) likewise for logues; expanded in READMEs, and --exp-lg (volflag exp_lg) likewise for logues;
@ -1255,7 +1255,7 @@ def add_safety(ap):
ap2.add_argument("--no-dot-mv", action="store_true", help="disallow moving dotfiles; makes it impossible to move folders containing dotfiles") ap2.add_argument("--no-dot-mv", action="store_true", help="disallow moving dotfiles; makes it impossible to move folders containing dotfiles")
ap2.add_argument("--no-dot-ren", action="store_true", help="disallow renaming dotfiles; makes it impossible to turn something into a dotfile") ap2.add_argument("--no-dot-ren", action="store_true", help="disallow renaming dotfiles; makes it impossible to turn something into a dotfile")
ap2.add_argument("--no-logues", action="store_true", help="disable rendering .prologue/.epilogue.html into directory listings") ap2.add_argument("--no-logues", action="store_true", help="disable rendering .prologue/.epilogue.html into directory listings")
ap2.add_argument("--no-readme", action="store_true", help="disable rendering readme.md into directory listings") ap2.add_argument("--no-readme", action="store_true", help="disable rendering readme/preadme.md into directory listings")
ap2.add_argument("--vague-403", action="store_true", help="send 404 instead of 403 (security through ambiguity, very enterprise)") ap2.add_argument("--vague-403", action="store_true", help="send 404 instead of 403 (security through ambiguity, very enterprise)")
ap2.add_argument("--force-js", action="store_true", help="don't send folder listings as HTML, force clients to use the embedded json instead -- slight protection against misbehaving search engines which ignore \033[33m--no-robots\033[0m") ap2.add_argument("--force-js", action="store_true", help="don't send folder listings as HTML, force clients to use the embedded json instead -- slight protection against misbehaving search engines which ignore \033[33m--no-robots\033[0m")
ap2.add_argument("--no-robots", action="store_true", help="adds http and html headers asking search engines to not index anything (volflag=norobots)") ap2.add_argument("--no-robots", action="store_true", help="adds http and html headers asking search engines to not index anything (volflag=norobots)")
@ -1453,7 +1453,7 @@ def add_ui(ap, retry):
ap2.add_argument("--k304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable k304 on the controlpanel (workaround for buggy reverse-proxies); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on") ap2.add_argument("--k304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable k304 on the controlpanel (workaround for buggy reverse-proxies); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on")
ap2.add_argument("--md-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for README.md docs (volflag=md_sbf); see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox") ap2.add_argument("--md-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for README.md docs (volflag=md_sbf); see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox")
ap2.add_argument("--lg-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for prologue/epilogue docs (volflag=lg_sbf)") ap2.add_argument("--lg-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for prologue/epilogue docs (volflag=lg_sbf)")
ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README.md documents (volflags: no_sb_md | sb_md)") ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README/PREADME.md documents (volflags: no_sb_md | sb_md)")
ap2.add_argument("--no-sb-lg", action="store_true", help="don't sandbox prologue/epilogue docs (volflags: no_sb_lg | sb_lg); enables non-js support") ap2.add_argument("--no-sb-lg", action="store_true", help="don't sandbox prologue/epilogue docs (volflags: no_sb_lg | sb_lg); enables non-js support")

View file

@ -127,6 +127,10 @@ _ = (argparse, threading)
NO_CACHE = {"Cache-Control": "no-cache"} NO_CACHE = {"Cache-Control": "no-cache"}
LOGUES = [[0, ".prologue.html"], [1, ".epilogue.html"]]
READMES = [[0, ["preadme.md", "PREADME.md"]], [1, ["readme.md", "README.md"]]]
class HttpCli(object): class HttpCli(object):
""" """
@ -3255,10 +3259,10 @@ class HttpCli(object):
def _add_logues( def _add_logues(
self, vn: VFS, abspath: str, lnames: Optional[dict[str, str]] self, vn: VFS, abspath: str, lnames: Optional[dict[str, str]]
) -> tuple[list[str], str]: ) -> tuple[list[str], list[str]]:
logues = ["", ""] logues = ["", ""]
if not self.args.no_logues: if not self.args.no_logues:
for n, fn in enumerate([".prologue.html", ".epilogue.html"]): for n, fn in LOGUES:
if lnames is not None and fn not in lnames: if lnames is not None and fn not in lnames:
continue continue
fn = "%s/%s" % (abspath, fn) fn = "%s/%s" % (abspath, fn)
@ -3270,25 +3274,31 @@ class HttpCli(object):
logues[n], vn.flags.get("exp_lg") or [] logues[n], vn.flags.get("exp_lg") or []
) )
readme = "" readmes = ["", ""]
if not self.args.no_readme and not logues[1]: for n, fns in [] if self.args.no_readme else READMES:
if lnames is None: if logues[n]:
fns = ["README.md", "readme.md"] continue
elif "readme.md" in lnames: elif lnames is None:
fns = [lnames["readme.md"]] pass
elif fns[0] in lnames:
fns = [lnames[fns[0]]]
else: else:
fns = [] fns = []
txt = ""
for fn in fns: for fn in fns:
fn = "%s/%s" % (abspath, fn) fn = "%s/%s" % (abspath, fn)
if bos.path.isfile(fn): if bos.path.isfile(fn):
with open(fsenc(fn), "rb") as f: with open(fsenc(fn), "rb") as f:
readme = f.read().decode("utf-8") txt = f.read().decode("utf-8")
break break
if readme and "exp" in vn.flags:
readme = self._expand(readme, vn.flags.get("exp_md") or [])
return logues, readme if txt and "exp" in vn.flags:
txt = self._expand(txt, vn.flags.get("exp_md") or [])
readmes[n] = txt
return logues, readmes
def _expand(self, txt: str, phs: list[str]) -> str: def _expand(self, txt: str, phs: list[str]) -> str:
for ph in phs: for ph in phs:
@ -5142,9 +5152,9 @@ class HttpCli(object):
j2a["no_prism"] = True j2a["no_prism"] = True
if not self.can_read and not is_dk: if not self.can_read and not is_dk:
logues, readme = self._add_logues(vn, abspath, None) logues, readmes = self._add_logues(vn, abspath, None)
ls_ret["logues"] = j2a["logues"] = logues ls_ret["logues"] = j2a["logues"] = logues
ls_ret["readme"] = cgv["readme"] = readme ls_ret["readmes"] = cgv["readmes"] = readmes
if is_ls: if is_ls:
return self.tx_ls(ls_ret) return self.tx_ls(ls_ret)
@ -5401,11 +5411,18 @@ class HttpCli(object):
else: else:
taglist = list(tagset) taglist = list(tagset)
logues, readme = self._add_logues(vn, abspath, lnames) logues, readmes = self._add_logues(vn, abspath, lnames)
ls_ret["logues"] = j2a["logues"] = logues ls_ret["logues"] = j2a["logues"] = logues
ls_ret["readme"] = cgv["readme"] = readme ls_ret["readmes"] = cgv["readmes"] = readmes
if not files and not dirs and not readme and not logues[0] and not logues[1]: if (
not files
and not dirs
and not readmes[0]
and not readmes[1]
and not logues[0]
and not logues[1]
):
logues[1] = "this folder is empty" logues[1] = "this folder is empty"
if "descript.ion" in lnames and os.path.isfile( if "descript.ion" in lnames and os.path.isfile(

View file

@ -896,7 +896,7 @@ html.y #path a:hover {
max-width: 52em; max-width: 52em;
} }
.mdo.sb, .mdo.sb,
#epi.logue.mdo>iframe { .logue.mdo>iframe {
max-width: 54em; max-width: 54em;
} }
.mdo, .mdo,

View file

@ -7345,6 +7345,9 @@ var treectl = (function () {
var lg0 = res.logues ? res.logues[0] || "" : "", var lg0 = res.logues ? res.logues[0] || "" : "",
lg1 = res.logues ? res.logues[1] || "" : "", lg1 = res.logues ? res.logues[1] || "" : "",
mds = res.readmes && treectl.ireadme,
md0 = mds ? res.readmes[0] || "" : "",
md1 = mds ? res.readmes[1] || "" : "",
dirchg = get_evpath() != cdir; dirchg = get_evpath() != cdir;
if (lg1 === Ls.eng.f_empty) if (lg1 === Ls.eng.f_empty)
@ -7354,9 +7357,14 @@ var treectl = (function () {
if (dirchg) if (dirchg)
sandbox(ebi('epi'), sb_lg, '', lg1); sandbox(ebi('epi'), sb_lg, '', lg1);
clmod(ebi('pro'), 'mdo');
clmod(ebi('epi'), 'mdo'); clmod(ebi('epi'), 'mdo');
if (res.readme && treectl.ireadme)
show_readme(res.readme); if (md0)
show_readme(md0, 0);
if (md1)
show_readme(md1, 1);
else if (!dirchg) else if (!dirchg)
sandbox(ebi('epi'), sb_lg, '', lg1); sandbox(ebi('epi'), sb_lg, '', lg1);
@ -8877,14 +8885,17 @@ function set_tabindex() {
} }
function show_readme(md) { function show_readme(md, n) {
if (!treectl.ireadme) var tgt = ebi(n ? 'epi' : 'pro');
return sandbox(ebi('epi'), '', '', 'a');
show_md(md, 'README.md', ebi('epi')); if (!treectl.ireadme)
return sandbox(tgt, '', '', 'a');
show_md(md, n ? 'README.md' : 'PREADME.md', tgt);
} }
if (readme) for (var a = 0; a < readmes.length; a++)
show_readme(readme); if (readmes[a])
show_readme(readmes[a], a);
function sandbox(tgt, rules, cls, html) { function sandbox(tgt, rules, cls, html) {