Bettern cmap handling. Lots of changes.

This commit is contained in:
2026-08-17 23:06:23 +02:00
parent 8997f7f94a
commit 12f1ed2764
27 changed files with 10351 additions and 217 deletions
+266 -15
View File
@@ -3,25 +3,27 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'">
<title>Racket Wiki</title>
<link rel="stylesheet" href="/vendor/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="/vendor/easymde.min.css">
<link rel="stylesheet" href="/vendor/highlight-github.min.css">
<link rel="stylesheet" href="/vendor/diff2html.min.css">
<link rel="stylesheet" href="/css/wiki.css">
<link rel="stylesheet" href="/css/wiki.css?id=__CMAP_CACHE_ID__">
<link rel="stylesheet" href="/cmap/cmap.css?id=__CMAP_CACHE_ID__">
</head>
<body>
<div id="connection-status" class="connection-status hidden" role="status"></div>
<div id="app">
<aside id="sidebar">
<a id="wiki-brand" class="brand" href="#">Racket Wiki</a>
<a id="recent-link" class="sidebar-primary-link" href="#">* <span data-tr="recent">Recent</span></a>
<a id="bookmarks-link" class="sidebar-primary-link" href="#">* <span data-tr="bookmarks">Bookmarks</span></a>
<a id="todo-link" class="sidebar-primary-link" href="#">* <span data-tr="todo-list">Todo list</span></a>
<a id="graph-link" class="sidebar-primary-link" href="#">* <span data-tr="graph">Graph</span></a>
<nav class="sidebar-icon-nav" aria-label="Wiki navigation">
<a id="bookmarks-link" class="sidebar-icon-link" href="#bookmarks" title="Bookmarks" data-tr-title="bookmarks" aria-label="Bookmarks" data-tr-aria-label="bookmarks"><i data-lucide="star"></i><span class="visually-hidden" data-tr="bookmarks">Bookmarks</span></a>
<a id="todo-link" class="sidebar-icon-link" href="#todos" title="Todo list" data-tr-title="todo-list" aria-label="Todo list" data-tr-aria-label="todo-list"><i data-lucide="list-checks"></i><span class="visually-hidden" data-tr="todo-list">Todo list</span></a>
<a id="recent-link" class="sidebar-icon-link" href="#recent" title="Recent" data-tr-title="recent" aria-label="Recent" data-tr-aria-label="recent"><i data-lucide="square-stack"></i><span class="visually-hidden" data-tr="recent">Recent</span></a>
<a id="graph-link" class="sidebar-icon-link" href="#graph" title="Navigation graph" data-tr-title="navigation-graph" aria-label="Navigation graph" data-tr-aria-label="navigation-graph"><i data-lucide="ship-wheel"></i><span class="visually-hidden" data-tr="navigation-graph">Navigation graph</span></a>
<a id="cmaps-link" class="sidebar-icon-link" href="#" title="CMaps" data-tr-title="cmaps" aria-label="CMaps" data-tr-aria-label="cmaps"><i data-lucide="share-2"></i><span class="visually-hidden" data-tr="cmaps">CMaps</span></a>
</nav>
<form id="search-form" class="wiki-search" role="search">
<input id="search-input" type="search" placeholder="Search wiki" data-tr-placeholder="search-wiki" autocomplete="off" aria-label="Search wiki">
<input id="search-input" type="search" placeholder="Search pages and concept maps" data-tr-placeholder="search-wiki" autocomplete="off" aria-label="Search pages and concept maps" data-tr-aria-label="search-wiki">
</form>
<section class="sidebar-section toc-section">
<div class="sidebar-heading"><span data-tr="contents">Contents</span> <a id="context-link" class="context-link hidden" href="#">(<span data-tr="context">context</span>)</a></div>
@@ -42,13 +44,14 @@
<span class="account-separator" aria-hidden="true">·</span>
<a id="logout-link" href="#" data-tr="sign-out">Sign out</a>
<span class="account-separator admin-only hidden" aria-hidden="true">·</span>
<a id="admin-link" class="admin-only hidden" href="#" data-tr="admin">Admin</a>
<a id="admin-link" class="admin-only hidden" href="#admin" data-tr="admin">Admin</a>
</div>
<div class="navigation-row">
<nav id="breadcrumbs" class="breadcrumbs hidden" aria-label="Breadcrumb"></nav>
<div id="page-action-links" class="page-action-links hidden">
<a id="bookmark-page" href="#" data-tr="bookmark">Bookmark</a>
<a id="edit-page" class="editor-only hidden" href="#" data-tr="edit">Edit</a>
<a id="rename-page" class="editor-only hidden" href="#" data-tr="rename">Rename</a>
<a id="history-page" href="#" data-tr="history">History</a>
<a id="delete-page" class="editor-only danger hidden" href="#" data-tr="delete">Delete</a>
</div>
@@ -62,7 +65,20 @@
<div id="page-meta" class="muted"></div>
</div>
</header>
<article id="markdown-preview" class="markdown-body"></article>
<div id="page-reading-layout" class="page-reading-layout">
<article id="markdown-preview" class="markdown-body"></article>
<aside id="context-dock" class="context-dock hidden" aria-label="Context graph">
<div class="context-dock-header">
<strong data-tr="context-graph">Context graph</strong>
<span class="context-graph-actions">
<a id="context-dock-popup" href="#" data-tr="popup">Popup</a>
<a id="context-dock-close" href="#" data-tr="close">Close</a>
</span>
</div>
<div id="context-dock-summary" class="muted"></div>
<svg id="context-dock-graph" class="wiki-graph context-graph-small" viewBox="0 0 1000 700" role="img" aria-label="Context graph"></svg>
</aside>
</div>
<footer id="page-details" class="page-details"></footer>
</section>
@@ -146,6 +162,93 @@
</div>
</section>
<section id="cmap-view" class="hidden">
<header class="cmap-page-header">
<div class="cmap-storage-controls">
<span id="cmap-map-navigation" class="cmap-map-navigation hidden"><button id="cmap-map-back" type="button" aria-label="Back to parent map"></button><strong id="cmap-active-map-title"></strong></span>
<div id="cmap-map-combobox" class="wiki-combobox">
<input id="cmap-map-select" type="search" role="combobox"
aria-label="Concept map" data-tr-placeholder="select-concept-map"
placeholder="Select a CMap">
<button type="button" class="wiki-combobox-toggle" tabindex="-1" aria-label="Show concept maps"></button>
<div id="cmap-map-options" class="wiki-combobox-list hidden" role="listbox"></div>
</div>
<span class="cmap-toolbar-separator" aria-hidden="true"></span>
<button id="cmap-tools-menu" class="editor-only" type="button" aria-label="Concept map tools" aria-haspopup="menu"></button>
<span id="cmap-save-status" class="muted" role="status"></span>
<span class="cmap-toolbar-spacer" aria-hidden="true"></span>
<div class="cmap-zoom-controls" aria-label="Zoom controls">
<button id="cmap-zoom-out" type="button" aria-label="Zoom out"></button>
<label><input id="cmap-zoom-percent" type="number" min="25" max="300" step="10" value="100" aria-label="Zoom percentage"><span>%</span></label>
<button id="cmap-zoom-in" type="button" aria-label="Zoom in">+</button>
<button id="cmap-zoom-reset" type="button">100%</button>
</div>
<span class="cmap-toolbar-separator" aria-hidden="true"></span>
<details class="cmap-help-menu">
<summary aria-label="Concept map help">?</summary>
<div class="cmap-help-popover muted">
<p data-tr="concept-map-help-context">Select with Ctrl/Cmd/Shift-click or by dragging over empty space. Drag a selected element to move the complete selection. Grouping creates a new sub-CMap around the selection. Double-click a page or sub-CMap to open it; right-click for editing tools.</p>
<dl class="cmap-shortcut-list">
<div><dt><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>/<kbd>Shift</kbd> + <span data-tr="click">click</span></dt><dd data-tr="cmap-help-add-selection">Add to or remove from the selection</dd></div>
<div><dt><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>A</kbd></dt><dd data-tr="select-all">Select all</dd></div>
<div><dt><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>G</kbd></dt><dd data-tr="group-selected">Group selection as sub-CMap</dd></div>
<div><dt><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>G</kbd></dt><dd data-tr="ungroup-selected">Detach from sub-CMap</dd></div>
<div><dt><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Z</kbd></dt><dd data-tr="undo">Undo</dd></div>
<div><dt><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Y</kbd> / <kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd></dt><dd data-tr="redo-action">Redo</dd></div>
<div><dt><kbd>F2</kbd></dt><dd data-tr="cmap-help-rename">Edit the selected concept</dd></div>
<div><dt><kbd>Delete</kbd>/<kbd>Backspace</kbd></dt><dd data-tr="delete-selected">Delete selection</dd></div>
<div><dt><kbd>Esc</kbd></dt><dd data-tr="cmap-help-clear-selection">Clear selection</dd></div>
<div><dt><kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>S</kbd></dt><dd data-tr="save-now">Save now</dd></div>
</dl>
</div>
</details>
</div>
</header>
<div class="cmap-workspace">
<div id="cmap-canvas" class="cmap-canvas" aria-label="Concept map"></div>
<nav id="cmap-context-menu" class="cmap-context-menu hidden" role="menu" aria-label="Concept map tools">
<button id="cmap-new-map" class="editor-only" type="button" role="menuitem" data-tr="new-concept-map">New CMap</button>
<button id="cmap-save-map" class="editor-only" type="button" role="menuitem" data-tr="save-now">Save now</button>
<div class="cmap-context-separator" role="separator"></div>
<button id="cmap-rename-map" type="button" role="menuitem" data-tr="rename-concept-map" disabled>Rename CMap</button>
<button id="cmap-delete-map" class="danger" type="button" role="menuitem" data-tr="delete-concept-map" disabled>Delete CMap</button>
<div class="cmap-context-separator" role="separator"></div>
<button id="cmap-add-concept" type="button" role="menuitem" data-tr="add-concept">Add concept</button>
<button id="cmap-add-page" type="button" role="menuitem" data-tr="add-page-node">Add current page</button>
<button id="cmap-add-submap" type="button" role="menuitem" data-tr="add-submap">Add sub-CMap</button>
<button id="cmap-promote-submap" type="button" role="menuitem" data-tr="promote-submap" disabled>Make separate CMap</button>
<button id="cmap-edit-selected" type="button" role="menuitem" data-tr="edit-selected-concept">Edit selected</button>
<div class="cmap-context-separator" role="separator"></div>
<button id="cmap-undo" type="button" role="menuitem" data-tr="undo" disabled>Undo</button>
<button id="cmap-redo" type="button" role="menuitem" data-tr="redo-action" disabled>Redo</button>
<div class="cmap-context-separator" role="separator"></div>
<button id="cmap-select-all" type="button" role="menuitem" data-tr="select-all">Select all</button>
<button id="cmap-group-selected" type="button" role="menuitem" data-tr="group-selected" disabled>Group selection as sub-CMap</button>
<button id="cmap-ungroup-selected" type="button" role="menuitem" data-tr="ungroup-selected" disabled>Detach from sub-CMap</button>
<button id="cmap-delete-selected" class="danger" type="button" role="menuitem" data-tr="delete-selected" disabled>Delete selection</button>
<div class="cmap-context-separator" role="separator"></div>
<button id="cmap-toggle-page-guides" type="button" role="menuitemcheckbox" aria-checked="true" data-tr="a4-page-boundaries">A4 page boundaries</button>
<button id="cmap-reset" type="button" role="menuitem" data-tr="reload-concept-map">Reload CMap</button>
</nav>
</div>
</section>
<section id="rename-view" class="hidden">
<div class="section-header">
<h1 data-tr="rename-page">Rename page</h1>
</div>
<div class="rename-form">
<label><span data-tr="page-title">Page title</span><input id="rename-title" type="text"></label>
<label><span data-tr="namespace">Namespace</span><input id="rename-namespace" type="text"></label>
<label><span data-tr="slug">Slug</span><input id="rename-slug" type="text"></label>
<div class="editor-buttons">
<button id="save-rename" type="button" data-tr="save">Save</button>
<button id="cancel-rename" type="button" data-tr="cancel">Cancel</button>
</div>
<p id="rename-status" class="muted"></p>
</div>
</section>
<section id="history-view" class="hidden">
<header class="page-header">
<h1 data-tr="page-history">Page history</h1>
@@ -159,25 +262,36 @@
<header class="page-header">
<h1 data-tr="admin">Admin</h1>
</header>
<p class="admin-version"><span data-tr="software-version">Software version</span>: <strong id="admin-software-version"></strong></p>
<nav class="admin-menu">
<a id="admin-users-link" href="#" data-tr="users">Users</a>
<a id="admin-users-link" href="#admin/users" data-tr="users">Users</a>
<a id="admin-aliases-link" href="#admin/aliases" data-tr="page-aliases">Page aliases</a>
<a id="admin-translations-link" href="#" data-tr="translations">Translations</a>
<a id="admin-orphaned-uploads-link" href="#" data-tr="orphaned-uploads">Orphaned uploads</a>
<a id="admin-orphaned-uploads-link" href="#admin/orphaned-uploads" data-tr="orphaned-uploads">Orphaned uploads</a>
</nav>
</section>
<section id="orphaned-uploads-view" class="hidden">
<header class="page-header">
<h1 data-tr="orphaned-uploads">Orphaned uploads</h1>
<a id="close-orphaned-uploads" href="#" data-tr="back">Back</a>
<a id="close-orphaned-uploads" href="#admin" data-tr="back">Back</a>
</header>
<div id="orphaned-uploads-list" class="orphaned-uploads-list"></div>
</section>
<section id="alias-admin-view" class="hidden">
<div class="section-header">
<h1 data-tr="page-aliases">Page aliases</h1>
<a id="close-alias-admin" href="#admin" data-tr="back">Back</a>
</div>
<p id="alias-admin-status" class="muted" role="status" aria-live="polite"></p>
<div id="alias-list"></div>
</section>
<section id="user-admin-view" class="hidden">
<header class="page-header">
<h1 data-tr="user-administration">User administration</h1>
<a id="close-user-admin" href="#" data-tr="back">Back</a>
<a id="close-user-admin" href="#admin" data-tr="back">Back</a>
</header>
<form id="new-user-form" class="user-form">
<input id="new-username" placeholder="Username" data-tr-placeholder="username" required>
@@ -195,11 +309,148 @@
</main>
</div>
<div id="context-overlay" class="context-overlay hidden" role="dialog" aria-modal="true" aria-labelledby="context-overlay-title">
<div class="context-overlay-panel">
<div class="context-overlay-header">
<div>
<h2 id="context-overlay-title" data-tr="context-graph">Context graph</h2>
<div id="context-overlay-summary" class="muted"></div>
</div>
<nav class="context-graph-actions">
<a id="context-dock-right" href="#" data-tr="dock-right">Dock right</a>
<a id="context-dock-top" href="#" data-tr="dock-above">Dock above</a>
<a id="context-open-full" href="#" data-tr="open-full-graph">Open full graph</a>
<a id="context-overlay-close" href="#" data-tr="close">Close</a>
</nav>
</div>
<div class="wiki-graph-shell context-overlay-graph-shell">
<svg id="context-overlay-graph" class="wiki-graph" viewBox="0 0 1000 700" role="img" aria-label="Context graph"></svg>
</div>
</div>
</div>
<dialog id="cmap-concept-dialog" class="cmap-concept-dialog" aria-labelledby="cmap-concept-dialog-title">
<form id="cmap-concept-form">
<h2 id="cmap-concept-dialog-title" data-tr="edit-concept">Edit concept</h2>
<label id="cmap-concept-page-row" class="cmap-concept-page-row">
<span data-tr="linked-page">Linked wiki page</span>
<div id="cmap-concept-page-combobox" class="wiki-combobox">
<input id="cmap-concept-page" type="search" role="combobox"
data-tr-placeholder="filter-pages" placeholder="Filter pages">
<button type="button" class="wiki-combobox-toggle" tabindex="-1" aria-label="Show wiki pages"></button>
<div id="cmap-concept-page-options" class="wiki-combobox-list hidden" role="listbox"></div>
</div>
</label>
<label id="cmap-concept-cmap-row" class="cmap-concept-page-row">
<span data-tr="linked-concept-map">Linked concept map</span>
<div id="cmap-concept-cmap-combobox" class="wiki-combobox">
<input id="cmap-concept-cmap" type="search" role="combobox"
data-tr-placeholder="filter-concept-maps" placeholder="Filter concept maps">
<button type="button" class="wiki-combobox-toggle" tabindex="-1" aria-label="Show concept maps"></button>
<div id="cmap-concept-cmap-options" class="wiki-combobox-list hidden" role="listbox"></div>
</div>
</label>
<label>
<span data-tr="label">Label</span>
<input id="cmap-concept-label" type="text" required>
</label>
<label>
<span data-tr="synopsis">Synopsis</span>
<textarea id="cmap-concept-synopsis" rows="4"></textarea>
</label>
<label>
<span id="cmap-concept-background-label" data-tr="background-color">Background color</span>
<input id="cmap-concept-background" type="color" value="#f3f6f8">
</label>
<fieldset id="cmap-submap-style-fields" class="cmap-submap-style-fields hidden">
<legend data-tr="submap-appearance">Sub-CMap appearance</legend>
<label>
<span data-tr="submap-background-color">Sub-CMap background color</span>
<input id="cmap-submap-background" type="color" value="#edf7e8">
</label>
<label>
<span data-tr="submap-border-color">Sub-CMap border color</span>
<input id="cmap-submap-border" type="color" value="#57834a">
</label>
</fieldset>
<label>
<span data-tr="text-color">Text color</span>
<input id="cmap-concept-text-color" type="color" value="#222222">
</label>
<fieldset class="cmap-concept-image-fields">
<legend data-tr="concept-image">Concept image</legend>
<input id="cmap-concept-image" type="file" accept="image/*">
<div id="cmap-concept-image-preview-row" class="cmap-concept-image-preview-row hidden">
<img id="cmap-concept-image-preview" alt="">
<button id="cmap-concept-image-remove" type="button" data-tr="remove-image">Remove image</button>
</div>
</fieldset>
<label>
<span data-tr="font-family">Font family</span>
<select id="cmap-concept-font-family">
<option value="Arial, Helvetica, sans-serif">Arial</option>
<option value="Verdana, Geneva, sans-serif">Verdana</option>
<option value="Tahoma, Geneva, sans-serif">Tahoma</option>
<option value="Trebuchet MS, Arial, sans-serif">Trebuchet MS</option>
<option value="Georgia, Times New Roman, serif">Georgia</option>
<option value="Times New Roman, Times, serif">Times New Roman</option>
<option value="Courier New, Courier, monospace">Courier New</option>
<option value="system-ui, sans-serif">System UI</option>
</select>
</label>
<label>
<span data-tr="font-size">Font size</span>
<span class="cmap-font-size-input"><input id="cmap-concept-font-size" type="number" min="6" max="54" step="1"><span>pt</span></span>
</label>
<div class="cmap-concept-dialog-actions">
<button id="cmap-concept-cancel" type="button" data-tr="cancel">Cancel</button>
<button type="submit" class="primary" data-tr="save">Save</button>
</div>
</form>
</dialog>
<dialog id="wiki-cmap-link-dialog" class="cmap-concept-dialog" aria-labelledby="wiki-cmap-link-title">
<form id="wiki-cmap-link-form">
<h2 id="wiki-cmap-link-title" data-tr="insert-concept-map-link">Insert CMap link</h2>
<label>
<span data-tr="linked-concept-map">Linked concept map</span>
<div id="wiki-cmap-link-combobox" class="wiki-combobox">
<input id="wiki-cmap-link" type="search" role="combobox"
data-tr-placeholder="filter-concept-maps" placeholder="Filter concept maps">
<button type="button" class="wiki-combobox-toggle" tabindex="-1" aria-label="Show concept maps"></button>
<div id="wiki-cmap-link-options" class="wiki-combobox-list hidden" role="listbox"></div>
</div>
</label>
<p class="muted" data-tr="concept-map-link-help">The selected CMap is inserted as a normal Markdown link.</p>
<div class="cmap-concept-dialog-actions">
<button id="wiki-cmap-link-cancel" type="button" data-tr="cancel">Cancel</button>
<button id="wiki-cmap-link-submit" type="submit" class="primary" data-tr="insert">Insert</button>
</div>
</form>
</dialog>
<dialog id="cmap-unsaved-dialog" class="cmap-unsaved-dialog" aria-labelledby="cmap-unsaved-title">
<form method="dialog">
<h2 id="cmap-unsaved-title" data-tr="unsaved-concept-map">Unsaved concept map</h2>
<p data-tr="save-concept-map-before-leaving">Save the changes to this concept map before leaving?</p>
<div class="cmap-concept-dialog-actions">
<button id="cmap-unsaved-cancel" type="button" data-tr="cancel">Cancel</button>
<button id="cmap-unsaved-discard" type="button" data-tr="dont-save">Don't save</button>
<button id="cmap-unsaved-save" type="button" class="primary editor-only" data-tr="save">Save</button>
</div>
</form>
</dialog>
<script src="/vendor/purify.min.js"></script>
<script src="/vendor/highlight.min.js"></script>
<script src="/vendor/highlight-scheme.min.js"></script>
<script src="/vendor/easymde.min.js"></script>
<script src="/vendor/lucide.min.js"></script>
<script src="/vendor/diff2html-ui-base.min.js"></script>
<script src="/js/wiki.js"></script>
<script src="/cmap/cmap.js?id=__CMAP_CACHE_ID__"></script>
<script src="/cmap/cmap-racket-wiki.js?id=__CMAP_CACHE_ID__"></script>
<script src="/js/combobox.js?id=__CMAP_CACHE_ID__"></script>
<script src="/js/wiki.js?id=__CMAP_CACHE_ID__"></script>
</body>
</html>