feat(web): polish the WASM site - UX, help, parsing, assets

- About panel (collapsible, closed by default with a pulsing "Help" badge)
  explaining the tool; the `help` command now prints a full command reference
  instead of "HELP" (benefits the CLI too).
- Live generation as you type; Store button; masked output that stays mono-width
  (gen masks only the password column, never the header); command history with
  Up/Down (persisted); console auto-scroll; Export fixed (uses `dump`); Import.
- Name field normalizes to its canonical parsed form on blur; quick-gen and Store
  resolve the real entry name, so a leading prefix like `*P0 test1` is handled
  correctly (new hel_parse / hel_parse_name wasm helpers).
- Parser: prefix-only forms now parse with defaults - `*P0 test1` ->
  `*P0 test1 R 99 <today>`, `*P0 test1 R`, `*P0 test1 20R` - via new qpname/npname
  rules mirroring qname/nname; the fully-qualified form is unchanged.
- Favicons + web app manifest + enso asset; pkg rebuilt.
This commit is contained in:
Oleksandr Kozachuk
2026-06-08 20:11:24 +02:00
parent 03c5dadccb
commit 3031105000
17 changed files with 503 additions and 98 deletions
+7 -1
View File
@@ -37,13 +37,19 @@ peg::parser! {
{ Password::new(None, pn, pl, pm, ps, pd, pc) }
rule mname() -> Password = &(word() _ word() _ num()? mode() _ date()) pr:word() _ pn:word() _ pl:num()? pm:mode() _ pd:date() pc:comment()?
{ Password::new(Some(pr), pn, pl, pm, 99, pd, pc) }
// prefix + name + [len]mode (no seq/date) -> defaults seq 99, date now
rule npname() -> Password = &(word() _ word() _ num()? mode()) pr:word() _ pn:word() _ pl:num()? pm:mode()
{ Password::new(Some(pr), pn, pl, pm, 99, Date::now(), None) }
rule sname() -> Password = &(word() _ num()? mode() _ date()) pn:word() _ pl:num()? pm:mode() _ pd:date() pc:comment()?
{ Password::new(None, pn, pl, pm, 99, pd, pc) }
rule nname() -> Password = &(word() _ num()? mode()) pn:word() _ pl:num()? pm:mode()
{ Password::new(None, pn, pl, pm, 99, Date::now(), None) }
// prefix + name only -> defaults mode R, seq 99, date now
rule qpname() -> Password = &(word() _ word()) pr:word() _ pn:word()
{ Password::new(Some(pr), pn, None, Mode::Regular, 99, Date::now(), None) }
rule qname() -> Password = &(word()) pn:word()
{ Password::new(None, pn, None, Mode::NoSpaceCamel, 99, Date::now(), None) }
pub rule name() -> Password = name:(jname() / pname() / mname() / sname() / nname() / qname())? {?
pub rule name() -> Password = name:(jname() / pname() / mname() / npname() / sname() / nname() / qpname() / qname())? {?
match name { Some(n) => Ok(n), None => Err("failed to parse password description") }
}