Add asset pipeline and professionalize theme
CI / build (push) Failing after 6m2s

Introduce a Node build system for minified CSS/JS with content hashes,
add PWA support, i18n helpers, accessibility improvements, and more
translatable strings. Move theme configuration from bookmarks to
localStorage, add Playwright tests, and set up CI workflows.
This commit is contained in:
2026-08-09 09:25:03 -04:00
parent 10af62dd6c
commit f753b27542
68 changed files with 4743 additions and 1989 deletions
+95
View File
@@ -0,0 +1,95 @@
// =====================================================================
// Navigation helpers for Shaarli Pro:
// - Add note/todo shortcut buttons in the sidebar.
// - Mobile sidebar toggle.
// =====================================================================
document.addEventListener('DOMContentLoaded', () => {
'use strict';
// ===== Add Note Button Handler (Android convention) =====
const addNoteBtn = document.querySelector('.sidebar-add-note');
if (addNoteBtn) {
addNoteBtn.addEventListener('click', (e) => {
e.preventDefault();
if (!window.ShaarItRules) {
// eslint-disable-next-line no-console
console.warn('[shaarit] ShaarItRules not available, cannot generate note URL');
return;
}
const basePath = addNoteBtn.getAttribute('data-base-path') || '';
const noteUrl = window.ShaarItRules.generateNoteUrl();
const redirectUrl = `${basePath}/admin/shaare?post=${encodeURIComponent(noteUrl)}&tags=note`;
window.location.href = redirectUrl;
});
}
// ===== Add Todo Button Handler (Android convention) =====
const addTodoBtn = document.querySelector('.sidebar-add-todo');
if (addTodoBtn) {
addTodoBtn.addEventListener('click', (e) => {
e.preventDefault();
if (!window.ShaarItRules) {
// eslint-disable-next-line no-console
console.warn('[shaarit] ShaarItRules not available, cannot generate todo URL');
return;
}
const basePath = addTodoBtn.getAttribute('data-base-path') || '';
const todoUrl = window.ShaarItRules.generateTodoUrl();
const redirectUrl = `${basePath}/admin/shaare?post=${encodeURIComponent(todoUrl)}&tags=todo&title=%E2%9C%85%20`;
window.location.href = redirectUrl;
});
}
// ===== Mobile Sidebar Toggle =====
const sidebar = document.getElementById('sidebar');
const sidebarOverlay = document.getElementById('sidebar-overlay');
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
function isMobileViewport() {
return window.matchMedia('(max-width: 1100px)').matches;
}
function openSidebar() {
if (!sidebar || !sidebarOverlay) return;
sidebar.classList.add('show');
sidebarOverlay.classList.add('show');
mobileMenuBtn?.setAttribute('aria-expanded', 'true');
sidebarOverlay.setAttribute('aria-hidden', 'false');
if (isMobileViewport()) {
document.body.style.overflow = 'hidden';
}
}
function closeSidebar() {
if (!sidebar || !sidebarOverlay) return;
sidebar.classList.remove('show');
sidebarOverlay.classList.remove('show');
mobileMenuBtn?.setAttribute('aria-expanded', 'false');
sidebarOverlay.setAttribute('aria-hidden', 'true');
document.body.style.overflow = '';
}
function toggleSidebar() {
if (sidebar?.classList.contains('show')) {
closeSidebar();
return;
}
openSidebar();
}
mobileMenuBtn?.addEventListener('click', toggleSidebar);
sidebarOverlay?.addEventListener('click', closeSidebar);
sidebar?.querySelectorAll('a').forEach((link) => {
link.addEventListener('click', () => {
if (isMobileViewport()) {
closeSidebar();
}
});
});
window.addEventListener('resize', () => {
if (!isMobileViewport()) {
closeSidebar();
}
});
});