small changes

This commit is contained in:
2026-09-07 22:41:33 +02:00
parent 32c75f8ff1
commit d351b8e3c8
7 changed files with 250 additions and 11 deletions
+102 -8
View File
@@ -13,6 +13,7 @@ import {
expandNamespacedMarkdownLinks,
expandTodoMarkup,
expandWikiMentions,
normalizeMarkdownLinkDestinations,
protectCamelCaseWikiWords,
extractCmapEmbeds,
restoreCmapEmbeds
@@ -70,6 +71,8 @@ import { ComboBox } from "./widgets/combobox.js";
let easyMDE = null;
let pendingWikiCmapLinkLabel = "";
const sidebarPreferenceKey = "racket-wiki-sidebar-collapsed";
const editorSideBySidePreferenceKey = "racket-wiki-editor-side-by-side";
////////////////////////////////////////////////////////////////////////////////
// General UI and HTTP support
@@ -133,6 +136,50 @@ import { ComboBox } from "./widgets/combobox.js";
document.documentElement.lang = state.language || "en";
}
function setSidebarCollapsed(collapsed, remember = true) {
document.body.classList.toggle("sidebar-collapsed", collapsed);
const toggle = $("sidebar-toggle");
if (!toggle) return;
const translationKey = collapsed ? "expand-sidebar" : "collapse-sidebar";
toggle.dataset.trTitle = translationKey;
toggle.dataset.trAriaLabel = translationKey;
toggle.title = tr(translationKey, collapsed ? "Expand sidebar" : "Collapse sidebar");
toggle.setAttribute("aria-label", toggle.title);
toggle.setAttribute("aria-expanded", String(!collapsed));
const icon = document.createElement("i");
icon.dataset.lucide = collapsed ? "panel-left-open" : "panel-left-close";
icon.setAttribute("aria-hidden", "true");
const oldIcon = toggle.querySelector("[data-lucide], svg");
if (oldIcon) {
oldIcon.replaceWith(icon);
} else {
toggle.append(icon);
}
if (window.lucide && typeof window.lucide.createIcons === "function") {
window.lucide.createIcons();
}
if (remember) {
try {
window.sessionStorage.setItem(sidebarPreferenceKey, collapsed ? "true" : "false");
} catch (_error) {
// A blocked session storage should not prevent the toggle from working.
}
}
}
function initializeSidebarToggle() {
const toggle = $("sidebar-toggle");
if (!toggle) return;
let collapsed = false;
try {
collapsed = window.sessionStorage.getItem(sidebarPreferenceKey) === "true";
} catch (_error) {
collapsed = false;
}
setSidebarCollapsed(collapsed, false);
toggle.addEventListener("click", () => setSidebarCollapsed(!document.body.classList.contains("sidebar-collapsed")));
}
function navigateToHash(targetHash) {
const navigate = () => {
if (location.hash === targetHash) return route();
@@ -204,7 +251,8 @@ import { ComboBox } from "./widgets/combobox.js";
function renderMarkdown(markdown, pageSlug = null) {
const extracted = extractCmapEmbeds(markdown || "");
const withExplicitWikiLinks = expandNamespacedMarkdownLinks(extracted.markdown);
const normalizedLinks = normalizeMarkdownLinkDestinations(extracted.markdown);
const withExplicitWikiLinks = expandNamespacedMarkdownLinks(normalizedLinks);
const withWikiLinks = expandWikiMentions(
withExplicitWikiLinks,
state.pages,
@@ -436,6 +484,32 @@ import { ComboBox } from "./widgets/combobox.js";
easyMDE.codemirror.refresh();
}
function preferredEditorSideBySide() {
try {
const stored = window.sessionStorage.getItem(editorSideBySidePreferenceKey);
return stored === null ? true : stored === "true";
} catch (_error) {
return true;
}
}
function rememberEditorSideBySide() {
if (!easyMDE) return;
try {
window.sessionStorage.setItem(
editorSideBySidePreferenceKey,
String(easyMDE.isSideBySideActive())
);
} catch (_error) {
// A blocked session storage should not prevent the editor from working.
}
}
function toggleEditorSideBySide() {
easyMDE.toggleSideBySide();
rememberEditorSideBySide();
}
function protectCamelCaseInPage() {
if (!easyMDE) return;
const source = easyMDE.value();
@@ -523,9 +597,10 @@ import { ComboBox } from "./widgets/combobox.js";
"|",
toolbarButton("undo", EasyMDE.undo, "undo-2", tr("undo", "Undo")),
toolbarButton("redo", EasyMDE.redo, "redo-2", tr("redo", "Redo")),
toolbarButton("save", savePageFromFullscreen, "save", tr("save", "Save"), { noDisable: true }),
toolbarButton("raw-markdown", toggleRawMarkdown, "file-text", tr("raw-markdown", "Raw Markdown"), { noDisable: true }),
toolbarButton("preview", EasyMDE.togglePreview, "eye", tr("preview", "Preview"), { noDisable: true }),
toolbarButton("side-by-side", EasyMDE.toggleSideBySide, "columns-2", tr("side-by-side", "Side by side"), { noDisable: true, noMobile: true }),
toolbarButton("side-by-side", toggleEditorSideBySide, "columns-2", tr("side-by-side", "Side by side"), { noDisable: true, noMobile: true }),
toolbarButton("fullscreen", EasyMDE.toggleFullScreen, "maximize", tr("fullscreen", "Fullscreen"), { noDisable: true, noMobile: true })
]
});
@@ -575,7 +650,7 @@ import { ComboBox } from "./widgets/combobox.js";
requestAnimationFrame(() => {
easyMDE.codemirror.refresh();
const wideScreen = window.matchMedia("(min-width: 901px)").matches;
if (wideScreen && !easyMDE.isSideBySideActive()) {
if (wideScreen && easyMDE.isSideBySideActive() !== preferredEditorSideBySide()) {
easyMDE.toggleSideBySide();
}
updateEditorChromeMetrics();
@@ -1045,6 +1120,17 @@ import { ComboBox } from "./widgets/combobox.js";
* post : A successful save refreshes page metadata and opens the stored page.
*/
async function savePage() {
return savePageWithOptions();
}
function savePageFromFullscreen() {
savePageWithOptions({ keepEditing: true }).catch((error) => {
$("save-status").textContent = error.message;
});
}
/** Save the current Markdown and optionally keep the editor active. */
async function savePageWithOptions({ keepEditing = false } = {}) {
const title = $("editor-title").value.trim();
const namespace = $("editor-namespace").value.trim();
const currentSlug = state.editingNew ? state.newPageSlug : state.currentPage?.slug;
@@ -1096,8 +1182,14 @@ import { ComboBox } from "./widgets/combobox.js";
applyTranslations();
$("account-role").textContent = tr(`role-${state.session.user.role}`, state.session.user.role);
}
location.hash = `#/${encodeURIComponent(page.slug)}`;
await openPage(page.slug);
if (keepEditing) {
$("editor-namespace").disabled = true;
updateEditorSlugInfo();
$("edit-summary").value = "";
} else {
location.hash = `#/${encodeURIComponent(page.slug)}`;
await openPage(page.slug);
}
$("save-status").textContent = tr("saved", "Saved");
} catch (error) {
$("save-status").textContent = error.message;
@@ -1189,7 +1281,7 @@ import { ComboBox } from "./widgets/combobox.js";
}
const result = await uploadOneFile(file);
$("save-status").textContent = tr("image-upload-complete", "Image upload complete");
return result.url;
return encodeURI(result.url);
}
/**
@@ -1206,9 +1298,10 @@ import { ComboBox } from "./widgets/combobox.js";
for (const file of fileList) {
const result = await uploadOneFile(file);
const escapedName = file.name.replace(/[\[\]]/g, "\\$&");
const url = encodeURI(result.url);
const markdown = isInlineImage(file)
? `![${escapedName}](${result.url})`
: `[${escapedName}](${result.url})`;
? `![${escapedName}](${url})`
: `[${escapedName}](${url})`;
insertTextAtCursor(`\n${markdown}\n`);
}
$("save-status").textContent = tr("upload-complete", "Upload complete");
@@ -2023,6 +2116,7 @@ import { ComboBox } from "./widgets/combobox.js";
state.translationTemplate = translationData.template || "";
state.translations = translationData.translations || {};
applyTranslations();
initializeSidebarToggle();
await cmapWorkspace.initialize();
initializeEditor();
$("account-name").textContent = state.session.user.displayName;