Commit Graph

89 Commits

Author SHA1 Message Date
ef1c8ff09a feat(i18n): offer every ISO 639-1 language
The table was thirty languages typed by hand. It is now generated:
utils/generate_languages.py takes the 184 alpha-2 codes from pycountry,
the display names from CLDR through babel, and the writing direction from
CLDR character order. 159 languages carry their endonym; the remaining 25
have no CLDR entry and carry their English ISO name.

That corrects the right-to-left set, which had four entries and needs ten
— dv, ks, ps, sd, ug and yi were simply missed.

Only 29 languages ship an interface catalogue, so the other 155 render in
English until one is filled. make i18n-ui fills app/i18n/ui/ for them, and
make i18n now covers the interface strings as well; neither asks for a
string a shipped catalogue already answers, so hand-written entries stay.

184 entries do not fit on a screen, so the language menu scrolls inside
itself. overscroll-behavior keeps the page behind it from moving once the
list reaches its end.

babel and pycountry are dev dependencies: the generator needs them, the
application does not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 01:18:30 +02:00
efabbd3b2e fix(modal): stop untrusted content reaching innerHTML and the iframe
Every one of these paths checked a string that the browser reinterprets
afterwards. isSafeUrl now hangs the value on an <a> and reads back
probe.protocol, so the check sees what the browser will see: a pre-parse
test reads "&#106;avascript:" as a relative path and passes it, and the
HTML parser then decodes it to "javascript:".

marked passes raw HTML through and emits hrefs unescaped. renderMarkdown
escapes the angle brackets before parsing, parses into an inert DOMParser
document where no script runs and no image loads, and drops anchors and
images whose scheme is not http, https or mailto. Blockquotes and
<autolinks> stop working as a result; neither appears in the configuration.

modalTitle and the alternatives list interpolated subitem.name and
icon.class into innerHTML. Both are built as nodes now. name is a
translatable key, so it arrives from the machine-written catalogues.

The link kept its click handler and its class across popups, because one
anchor serves all of them: a later, unrelated click opened whatever an
earlier popup pointed at, and addEventListener stacked one handler per
open. Both are reset per popup and the handler is assigned, not added.

openIframe guards its own argument. Removing the href alone left the
handler passing the raw URL on, and ?iframe= in the query string reaches
the same sink with no configuration involved at all.

Verified in headless Chromium: decimal and hex character references,
&Tab;- and &NewLine;-split schemes, reference-style links, raw HTML as a
link's text, and the two name sinks all executed before these changes.
injection.spec.js keeps all fifteen payloads.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 01:18:29 +02:00
a42930a699 build(make): run e2e without act, lint yaml, js and shell
test-e2e drove Cypress through act, which fails to start where it cannot
resolve a host address for its artifact server. It now starts Flask and
Cypress in one shell via scripts/run-e2e.sh, so both share a network
namespace; the act path stays available as test-e2e-act.

The script guards the cases that made the old target lie: it aborts when
something already serves the port instead of testing that server, checks
that its own Flask is alive before trusting a response, pins Cypress to
the same origin Flask binds, and drops ELECTRON_RUN_AS_NODE, which VS Code
exports and which makes Cypress' bundled Electron reject its own flags.

30 YAML and 18 JavaScript files had no linter. yamllint runs correctness
rules only, because the repository predates it and its cosmetic findings
would be noise; key-duplicates is the one that earns its keep, since
PyYAML keeps the last of two identical keys without complaining. eslint
runs the recommended set and already found a dead getBoundingClientRect()
call in navigation.js. Both get a CI job so make lint and the workflows
stop diverging.

flask>=3.1 because app.config["TRUSTED_HOSTS"] arrived in 3.1 and an older
Flask accepts the key and ignores it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 01:18:27 +02:00
f3c15e3e1c fix(navigation): unclip dropdowns and flip toward the side with more space
- Move <header> overflow:hidden into body.fullscreen scope and drop the
  implicit-vertical-clip overflow-x:auto from .navbar-nav so dropdown
  menus can escape the navbar.
- Drive top-level dropdowns through bootstrap.Dropdown (popperConfig
  strategy:'fixed'), and add a chooseDirection() helper that toggles
  .dropup/.dropdown on the .nav-item based on space above vs below
  before each show. Split the navigation.css rules to position the menu
  with top:100% or bottom:100% accordingly.
- Mark the dropdown toggle with data-bs-toggle="dropdown" in the
  template; cover that with a Jinja-rendered unit test and add Cypress
  specs for the header (opens downward) and footer (flips to .dropup)
  cases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 02:26:02 +02:00
6861b2c0eb fix(nav): prevent navbar items from wrapping to second line
- Set flex-wrap: nowrap on navbar-nav to keep all items in one row
- Add hidden overflow-x scroll (no visible scrollbar) as fallback
- Fix #navbar_logo taking up space when invisible via max-width transition

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 10:10:55 +02:00
46b0b744ca Added logo to navbar when in fullscreen 2025-07-21 11:39:59 +02:00
7bc0f32145 Added cypress tests 2025-07-08 17:16:57 +02:00
6ed3e60dd0 Solved 2tap fullscreen hight bug 2025-07-08 14:39:13 +02:00
ab8ea0dbd6 Added iframe observer 2025-07-07 23:40:35 +02:00
b0446dcd29 Added include svgs 2025-07-07 19:14:29 +02:00
55d309b2d7 Changed fade between html iframe animation 2025-07-07 15:37:24 +02:00
d99a8c8452 Added restore functionality to small logo 2025-07-07 15:06:36 +02:00
3f6a195ecb Optimizid hover 2025-07-07 13:37:02 +02:00
430ea4a120 Solved loading bug 2025-07-07 13:19:49 +02:00
9ada9acb3a Implemented SVG handling 2025-07-07 12:40:25 +02:00
6572a39d48 Added hover effects to cards 2025-07-06 22:25:22 +02:00
a80262c0d4 Solved container height bug 2025-07-06 22:18:28 +02:00
531c2295bd Added header/footer animation 2025-07-06 18:14:42 +02:00
0640ec6439 Added animation for fullscreen log 2025-07-06 17:46:51 +02:00
a7eb14046f Added fullwidth animation 2025-07-06 17:35:40 +02:00
539580ad09 Added missing enterfullscreen function 2025-07-06 17:13:15 +02:00
faf5bd1e8c Solved iframe margin bug 2025-07-06 10:55:12 +02:00
97378422bd Solved more CSS bugs 2025-07-05 21:07:31 +02:00
2632c21de3 Removed unnecessary log messages 2025-07-05 20:33:08 +02:00
64db9a4e6a Implemented Nasa Picture of the day 2025-07-05 20:08:00 +02:00
d0f8d7d172 Added logo for small screen 2025-07-05 18:54:18 +02:00
20b6c731b8 Added onclick functionality for menu items 2025-07-05 18:32:26 +02:00
2f63009c31 Implemented full width function 2025-07-05 18:00:23 +02:00
f0d4206731 Finished resize implementation for iframe 2025-07-05 16:53:25 +02:00
b8aad8b695 Removed non functional resize code 2025-07-05 14:39:18 +02:00
697696347f finished fullscreen base implementation 2025-07-05 14:20:52 +02:00
d6389157ec Added fullscreen mode 2025-07-05 13:30:25 +02:00
25dbc3f331 Added correct iframe size loading 2025-07-05 13:17:38 +02:00
bb8799eb8a Added functionality for iframe url 2025-07-05 11:54:20 +02:00
8e280de139 Added header h1 pointer 2025-03-19 17:20:08 +01:00
19f47a82fa Implemented iframe logic for modals 2025-03-19 17:16:44 +01:00
3b4dc298f8 Rafactored iframe.js 2025-03-19 16:53:49 +01:00
79e10e97b7 Marked header h1 as clickable 2025-03-19 16:16:27 +01:00
f5a9838474 Added logic for reload via header 2025-03-19 16:14:06 +01:00
6a0db00f24 Modified scrollbars for iframes 2025-03-18 15:03:03 +01:00
3529749df5 Added iframe draft 2025-03-18 14:59:54 +01:00
ae775916b0 Replaced German by English comments 2025-03-18 14:27:07 +01:00
464d307ee8 Optimized nav corners 2025-03-18 14:03:19 +01:00
4aceb2ed62 Solved main shadow bug 2025-03-18 13:56:42 +01:00
a8a2efd091 Solved scrollbar issues 2025-03-18 13:49:35 +01:00
3284684282 Solved main size bug 2025-03-18 13:30:38 +01:00
20c4a4809b Refactored css 2025-03-18 13:10:35 +01:00
898f7479c9 Added scrollbar draft 2025-03-18 12:50:14 +01:00
94b4e1f883 Added support for css logos 2025-02-19 20:53:05 +01:00
0f8113974f Refactored warning and info js 2025-01-17 01:07:48 +01:00