style: normalize headers, overtype editor rounded corners, remove duplicate cover preview, thesis-add-header grid layout, subtitle below header with top gradient

This commit is contained in:
Pontoporeia committed 2026-05-19 00:08:05 +02:00
1 parent 7ccadbb224
commit 21c2b55bfb
23 files changed
+1855 -1531

No files matched your search

+2 -38
View File
@@ -1,47 +1,11 @@
<?php
/**
* HTMX handler: persist the new drag-and-drop sort order for form help blocks.
*
* Expects POST fields:
* csrf_token — standard admin CSRF token
* block[] — ordered list of block keys (one hidden input per block, submitted by
* Sortable+htmx via the form's `end` event trigger)
*
* Returns a 204 No Content on success (htmx will not swap anything).
* On error, returns a 400 with a plain-text message.
* Legacy endpoint — no longer used (blocks are now static, non-sortable).
* Returns 204 No Content for backwards compatibility.
*/
require_once __DIR__ . '/../../../bootstrap.php';
require_once __DIR__ . '/../../../src/AdminAuth.php';
AdminAuth::requireLogin();
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|| !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
http_response_code(403);
echo 'Token invalide.';
exit;
}
$keys = $_POST['block'] ?? [];
if (!is_array($keys) || empty($keys)) {
http_response_code(400);
echo 'Paramètre block[] manquant.';
exit;
}
// Sanitise: keep only scalar strings, deduplicate.
$keys = array_values(array_unique(array_filter($keys, 'is_string')));
require_once APP_ROOT . '/src/Database.php';
$db = new Database();
try {
$db->reorderFormHelpBlocks($keys);
} catch (Exception $e) {
error_log('form-help-reorder error: ' . $e->getMessage());
http_response_code(500);
echo 'Erreur lors de la sauvegarde.';
exit;
}
http_response_code(204);
exit;
+1 -1
View File
@@ -27,7 +27,7 @@ $autofocusField = App::consumeAutofocus();
$siteSettings = Database::getInstance()->getAllSettings();
// Form help blocks
$helpBlocks = Database::getInstance()->getAllFormHelpBlocks();
$helpFn = fn(string $key) => $helpBlocks[$key]['content'] ?? '';
$helpFn = fn(string $key) => empty($helpBlocks[$key]['enabled']) ? '' : ($helpBlocks[$key]['content'] ?? '');
function withAutofocus(string $fieldName, array $attrs = []): array {
global $autofocusField;
+1 -1
View File
@@ -50,7 +50,7 @@ try {
} elseif ($formHelpKey) {
$editType = "form_help";
$formHelpContent = $db->getFormHelpBlock($formHelpKey);
$editTitle = Database::FORM_HELP_LABELS[$formHelpKey] ?? $formHelpKey;
$editTitle = $formHelpKey;
} else {
$editType = "apropos";
$value = $db->getAproposContent($aproposKey);
+1 -1
View File
@@ -19,7 +19,7 @@ $autofocusField = App::consumeAutofocus();
// Form help blocks for editable généralités
$helpBlocks = Database::getInstance()->getAllFormHelpBlocks();
$helpFn = fn(string $key) => $helpBlocks[$key]['content'] ?? '';
$helpFn = fn(string $key) => empty($helpBlocks[$key]['enabled']) ? '' : ($helpBlocks[$key]['content'] ?? '');
function old($key, $default = "") {
global $formData;
@@ -0,0 +1,196 @@
<?php
/**
* HTMX fragment: expand/collapse/editor for a single form help block.
*
* GET ?key=xxx → render collapsed chip: 3/4 left (name + MD preview), 1/4 right (edit + toggle dot)
* GET ?key=xxx&edit=1 → render inline OverType editor + name field
* POST → save content + name, return collapsed view
* POST _action=toggle → toggle enabled, return collapsed view
*/
require_once __DIR__ . '/../../bootstrap.php';
require_once __DIR__ . '/../../src/AdminAuth.php';
AdminAuth::requireLogin();
require_once __DIR__ . '/../../src/Database.php';
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$key = $_GET['key'] ?? '';
if (!in_array($key, Database::FORM_HELP_KEYS, true)) {
http_response_code(400);
echo 'Clé invalide.';
exit;
}
// ── POST ─────────────────────────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['_action'] ?? 'save';
$db = new Database();
// Toggle doesn't need CSRF — low-risk action behind admin auth
if ($action === 'toggle') {
$db->toggleFormHelpBlock($key);
renderCollapsed($db, $key);
exit;
}
// Save requires CSRF
if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'])
|| !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
http_response_code(403);
echo 'Token invalide.';
exit;
}
// save
$content = $_POST['content'] ?? '';
$name = trim($_POST['name'] ?? '');
try {
$db->setFormHelpBlock($key, $content);
if ($name !== '') {
$db->setFormHelpBlockName($key, $name);
}
require_once __DIR__ . '/../../src/AdminLogger.php';
AdminLogger::make()->logFormStructureEdit($key);
} catch (Exception $e) {
error_log('form-help-inline save error: ' . $e->getMessage());
http_response_code(500);
echo 'Erreur lors de la sauvegarde.';
exit;
}
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
renderCollapsed($db, $key);
exit;
}
// ── GET ──────────────────────────────────────────────────────────────────────
$db = new Database();
$editMode = ($_GET['edit'] ?? '') === '1';
if ($editMode) {
renderEditor($db, $key);
} else {
renderCollapsed($db, $key);
}
// ═══════════════════════════════════════════════════════════════════════════════
// RENDER HELPERS
// ═══════════════════════════════════════════════════════════════════════════════
function renderCollapsed(Database $db, string $key): void
{
$blocks = $db->getAllFormHelpBlocks();
$b = $blocks[$key] ?? ['content' => '', 'name' => '', 'enabled' => 0];
$name = $b['name'] ?: $key;
$content = $b['content'] ?? '';
$enabled = (int)($b['enabled'] ?? 1);
$hasContent = trim($content) !== '';
$mdHtml = '';
if ($hasContent) {
require_once APP_ROOT . '/src/Parsedown.php';
$pd = new Parsedown();
$pd->setSafeMode(true);
$mdHtml = $pd->text($content);
}
?>
<div class="fhb-inline <?= $enabled ? '' : 'fhb-inline--disabled' ?>" data-key="<?= htmlspecialchars($key) ?>">
<!-- Left side: name + content (content hidden when disabled) -->
<div class="fhb-inline-body">
<div class="fhb-inline-name"><?= htmlspecialchars($name) ?></div>
<?php if ($enabled && $hasContent): ?>
<div class="fhb-md-preview"><?= $mdHtml ?></div>
<?php elseif ($enabled): ?>
<div class="fhb-inline-empty">— vide —</div>
<?php endif; ?>
</div>
<!-- Right side: dot above edit button (edit hidden when disabled) -->
<div class="fhb-inline-actions">
<form hx-post="/admin/form-help-inline-fragment.php?key=<?= urlencode($key) ?>"
hx-target="closest .fhb-inline"
hx-swap="outerHTML"
class="fhb-toggle-form">
<input type="hidden" name="_action" value="toggle">
<button type="submit"
class="fhb-dot <?= $enabled ? 'fhb-dot--on' : 'fhb-dot--off' ?>"
title="<?= $enabled ? 'Désactiver ce bloc' : 'Activer ce bloc' ?>"
aria-label="<?= $enabled ? 'Désactiver ce bloc' : 'Activer ce bloc' ?>"></button>
</form>
<?php if ($enabled): ?>
<button type="button" class="btn btn--primary btn--sm"
hx-get="/admin/form-help-inline-fragment.php?key=<?= urlencode($key) ?>&edit=1"
hx-target="closest .fhb-inline"
hx-swap="outerHTML">Éditer</button>
<?php endif; ?>
</div>
</div>
<?php
}
function renderEditor(Database $db, string $key): void
{
$blocks = $db->getAllFormHelpBlocks();
$b = $blocks[$key] ?? ['content' => '', 'name' => ''];
$name = $b['name'] ?: $key;
$content = $b['content'] ?? '';
?>
<div class="fhb-inline fhb-inline--editing" data-key="<?= htmlspecialchars($key) ?>">
<form hx-post="/admin/form-help-inline-fragment.php?key=<?= urlencode($key) ?>"
hx-swap="outerHTML"
hx-target="closest .fhb-inline"
class="fhb-inline-form">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<div class="fhb-edit-name-row">
<label for="fhb-name-<?= htmlspecialchars($key) ?>" class="fhb-edit-label">Nom du bloc :</label>
<input type="text" id="fhb-name-<?= htmlspecialchars($key) ?>" name="name"
value="<?= htmlspecialchars($name) ?>"
class="fhb-name-input"
placeholder="Nom du bloc d'aide">
</div>
<label for="fhb-ed-<?= htmlspecialchars($key) ?>" class="fhb-edit-label">Contenu (Markdown) :</label>
<input type="hidden" id="fhb-content-<?= htmlspecialchars($key) ?>" name="content"
value="<?= htmlspecialchars($content) ?>">
<div id="fhb-editor-<?= htmlspecialchars($key) ?>" class="fhb-overtype-editor"></div>
<div class="fhb-edit-buttons">
<button type="submit" class="btn btn--primary btn--sm">Enregistrer</button>
<button type="button" class="btn btn--secondary btn--sm"
hx-get="/admin/form-help-inline-fragment.php?key=<?= urlencode($key) ?>"
hx-target="closest .fhb-inline"
hx-swap="outerHTML">Annuler</button>
</div>
</form>
<script>
(function(){
var hidden = document.getElementById('fhb-content-<?= htmlspecialchars($key) ?>');
var ed = document.getElementById('fhb-editor-<?= htmlspecialchars($key) ?>');
if (hidden && ed && typeof OverType !== 'undefined') {
var OT = OverType.default || OverType;
new OT(ed, {
value: hidden.value,
minHeight: '400px',
spellcheck: false,
onChange: function(v) { hidden.value = v; }
});
} else {
ed.innerHTML = '<textarea name="content" style="width:100%;min-height:400px;font-family:monospace">'
+ hidden.value.replace(/</g,'&lt;').replace(/>/g,'&gt;') + '</textarea>';
var ta = ed.querySelector('textarea');
ta.addEventListener('input', function() {
hidden.value = this.value;
});
}
})();
</script>
</div>
<?php
}
+46
View File
@@ -0,0 +1,46 @@
<?php
/**
* HTMX fragment (admin): renders the licence section with conditional required states.
*
* POST: access_type_id, license_id, license_custom, cc2r, admin_mode
*
* Admin mode: never required.
*/
require_once __DIR__ . '/../../bootstrap.php';
require_once __DIR__ . '/../../src/AdminAuth.php';
AdminAuth::requireLogin();
$accessTypeId = $_POST['access_type_id'] ?? '2';
$licenseId = $_POST['license_id'] ?? '';
$licenseCustom = $_POST['license_custom'] ?? '';
$cc2r = !empty($_POST['cc2r']);
$adminMode = true;
require_once APP_ROOT . '/src/Database.php';
$db = Database::getInstance();
$licenseTypes = $db->getAllLicenseTypes();
?>
<div class="licence-license-choice">
<?php
$name = 'license_id'; $label = 'Licence :'; $options = $licenseTypes;
$selected = $licenseId; $placeholder = '— Sélectionner —'; $required = false;
include APP_ROOT . '/templates/partials/form/select-field.php';
?>
<?php
$name = 'license_custom'; $label = 'Ou précisez une autre licence :';
$value = htmlspecialchars($licenseCustom);
$hint = 'Ex: CC BY-NC 4.0, Tous droits réservés...';
include APP_ROOT . '/templates/partials/form/text-field.php';
?>
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="cc2r" value="1"
<?= $cc2r ? 'checked' : '' ?>>
J'accepte les Conditions Collectives de Réutilisation (CC2r)
</label>
<small><a href="https://cc2r.net/" target="_blank" rel="noopener">En savoir plus sur la CC2r ↗</a></small>
</div>
</div>
+213 -189
View File
@@ -16,7 +16,6 @@
white-space: nowrap;
scrollbar-width: thin;
}
.admin-body header nav .nav-left,
.admin-body header nav .nav-right-links {
flex-shrink: 0;
}
@@ -1480,7 +1479,7 @@
}
/* ═══════════════════════════════════════════════════════════════════════════
Form Help Blocks — drag-and-drop builder (contenus.php)
Form Help Blocks — static structure view (contenus.php)
═══════════════════════════════════════════════════════════════════════════ */
.fhb-hint {
@@ -1489,225 +1488,250 @@
margin-bottom: var(--space-m);
}
.fhb-layout {
/* ── Structure container ───────────────────────────────────────────────────── */
.fhb-structure {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-m);
align-items: start;
grid-template-columns: 1fr;
gap: var(--space-xs);
max-width: 100%;
margin-top: var(--space-m);
}
@media (max-width: 800px) {
.fhb-layout {
grid-template-columns: 1fr;
}
}
/* ── Fieldset cards (static reference) ─────────────────────────────────────── */
/* ── Panels ─────────────────────────────────────────────────────────────── */
.fhb-sortable-panel,
.fhb-form-preview-panel {
.fhb-fieldset-card {
border: 1px solid var(--border-primary);
border-radius: var(--radius);
padding: var(--space-s);
padding: var(--space-xs) var(--space-s);
background: var(--bg-secondary);
}
.fhb-panel-title {
.fhb-fieldset-card-legend {
font-size: var(--step-0);
font-weight: 600;
margin: 0 0 var(--space-3xs) 0;
letter-spacing: 0.03em;
}
.fhb-panel-desc {
font-size: var(--step--2);
color: var(--text-secondary);
margin: 0 0 var(--space-xs) 0;
}
/* ── Saving indicator ─────────────────────────────────────────────────────── */
.fhb-saving {
display: none;
align-items: center;
gap: var(--space-2xs);
font-size: var(--step--1);
color: var(--accent-primary);
padding: var(--space-2xs) 0;
}
.fhb-saving.htmx-request {
display: flex;
}
/* ── Draggable block cards ─────────────────────────────────────────────────── */
.fhb-sortable {
display: flex;
flex-direction: column;
gap: var(--space-2xs);
padding: 0;
margin: 0;
}
.fhb-block-card {
display: flex;
align-items: center;
gap: var(--space-xs);
background: var(--bg-primary);
border: 1px solid var(--border-primary);
border-left: 4px solid var(--accent-primary);
border-radius: var(--radius);
padding: var(--space-2xs) var(--space-xs);
cursor: default;
transition: box-shadow 0.15s, border-color 0.15s;
}
.fhb-block-card:hover {
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
border-color: var(--accent-primary);
}
.fhb-drag-handle {
font-size: 1.2em;
color: var(--text-tertiary);
cursor: grab;
flex-shrink: 0;
line-height: 1;
user-select: none;
padding: 2px 4px;
}
.fhb-drag-handle:active {
cursor: grabbing;
}
.fhb-block-info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.fhb-block-label {
font-size: var(--step--1);
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.fhb-block-preview {
font-size: var(--step--2);
color: var(--text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.fhb-block-empty {
font-size: var(--step--2);
color: var(--text-tertiary);
font-style: italic;
}
.fhb-edit-btn {
flex-shrink: 0;
font-size: var(--step--2) !important;
padding: 2px var(--space-xs) !important;
}
/* ── SortableJS state classes ─────────────────────────────────────────────── */
.fhb-ghost {
opacity: 0.35;
background: var(--accent-muted);
border-color: var(--accent-primary);
}
.fhb-chosen {
box-shadow: 0 4px 16px rgba(149, 87, 181, 0.25);
border-color: var(--accent-primary);
}
.fhb-dragging {
opacity: 0.9;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}
/* ── Form structure preview (right panel) ─────────────────────────────────── */
.fhb-form-preview {
display: flex;
flex-direction: column;
gap: var(--space-2xs);
}
.fhb-fieldset-preview {
border: 1px solid var(--border-secondary);
border-radius: var(--radius);
padding: var(--space-xs);
background: var(--bg-primary);
}
.fhb-fieldset-legend {
font-size: var(--step--1);
font-weight: 600;
color: var(--text-primary);
margin-bottom: var(--space-3xs);
padding-bottom: var(--space-3xs);
border-bottom: 1px solid var(--border-primary);
}
.fhb-fieldset-inputs {
.fhb-fieldset-card-inputs {
margin: 0;
padding: 0 0 0 var(--space-s);
list-style: disc;
list-style: none;
display: flex;
flex-wrap: wrap;
gap: var(--space-3xs) var(--space-m);
}
.fhb-fieldset-inputs li {
.fhb-fieldset-card-inputs li {
font-size: var(--step--2);
color: var(--text-secondary);
line-height: 1.6;
}
.fhb-anchor {
display: flex;
align-items: center;
gap: var(--space-2xs);
border-radius: var(--radius);
padding: var(--space-3xs) var(--space-xs);
font-size: var(--step--2);
border: 1px dashed var(--border-primary);
background: transparent;
}
.fhb-anchor--filled {
border-color: var(--accent-primary);
background: var(--accent-muted);
color: var(--accent-secondary);
}
.fhb-anchor--empty {
.fhb-fieldset-card-inputs li::before {
content: '· ';
color: var(--text-tertiary);
}
.fhb-anchor-icon {
flex-shrink: 0;
font-style: normal;
/* ── Help block wrapper ────────────────────────────────────────────────────── */
.fhb-block-wrapper {
/* container for the fhb-inline, one per help block */
}
.fhb-anchor-label {
flex: 1;
}
/* ── Inline help block (collapsed state) ───────────────────────────────────── */
.fhb-anchor-pos {
font-size: var(--step--2);
font-weight: 600;
color: var(--accent-primary);
background: var(--accent-muted);
.fhb-inline {
display: grid;
grid-template-columns: 1fr auto;
gap: var(--space-s);
align-items: center;
border: 1px solid var(--border-primary);
border-left: 4px solid var(--accent-primary);
border-radius: var(--radius);
padding: 0 4px;
padding: var(--space-xs) var(--space-s);
background: var(--bg-primary);
transition: opacity 0.15s;
}
.fhb-inline:hover {
opacity: 0.85;
}
/* Disabled state — one line only, content hidden */
.fhb-inline--disabled {
border-left-color: var(--text-tertiary);
opacity: 0.55;
}
.fhb-inline--disabled:hover {
opacity: 0.75;
}
.fhb-inline--disabled .fhb-md-preview,
.fhb-inline--disabled .fhb-inline-empty {
display: none;
}
/* Editing state */
.fhb-inline--editing {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr auto;
border-color: var(--accent-primary);
box-shadow: 0 4px 16px rgba(149, 87, 181, 0.15);
padding: var(--space-s);
min-height: 50vh;
}
.fhb-inline--editing .fhb-inline-form {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto auto 1fr auto;
height: 100%;
}
/* ── Left side: name + content ─────────────────────────────────────────────── */
.fhb-inline-body {
min-width: 0;
}
.fhb-inline-name {
font-size: var(--step--1);
font-weight: 600;
color: var(--accent-secondary);
margin-bottom: var(--space-3xs);
}
/* ── Small rendered Markdown preview ──────────────────────────────────────── */
.fhb-md-preview {
font-size: var(--step--2);
color: var(--text-secondary);
line-height: 1.45;
max-height: 6em;
overflow: hidden;
}
.fhb-md-preview p {
margin: 0;
}
.fhb-md-preview p + p {
margin-top: var(--space-3xs);
}
.fhb-md-preview ul,
.fhb-md-preview ol {
margin: var(--space-3xs) 0;
padding-left: var(--space-s);
}
.fhb-md-preview li {
margin-bottom: 0;
}
.fhb-md-preview strong { font-weight: 600; }
.fhb-md-preview em { font-style: italic; }
.fhb-md-preview code {
font-size: 0.9em;
background: var(--bg-secondary);
padding: 0 var(--space-4xs);
border-radius: 3px;
}
.fhb-inline-empty {
font-size: var(--step--2);
color: var(--text-tertiary);
font-style: italic;
}
/* ── Right side: edit button + live dot ───────────────────────────────────── */
.fhb-inline-actions {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: var(--space-2xs);
flex-shrink: 0;
}
.fhb-toggle-form {
margin: 0;
line-height: 0;
}
/* Live dot — green when on, red when off */
.fhb-dot {
display: block;
width: 18px;
height: 18px;
border-radius: 50%;
border: none;
cursor: pointer;
padding: 0;
transition: opacity 0.15s;
}
.fhb-dot:hover {
opacity: 0.7;
}
.fhb-dot--on {
background: #2d6a4f;
}
.fhb-dot--off {
background: #c0392b;
}
/* ── Editor form ──────────────────────────────────────────────────────────── */
.fhb-edit-name-row {
margin-bottom: var(--space-xs);
}
.fhb-edit-label {
display: block;
font-size: var(--step--2);
font-weight: 500;
color: var(--text-primary);
margin-bottom: var(--space-3xs);
}
.fhb-name-input {
width: 100%;
max-width: 400px;
padding: var(--space-2xs) var(--space-xs);
border: 1px solid var(--border-primary);
border-radius: var(--radius);
font-size: var(--step--1);
font-family: var(--font-body);
}
.fhb-name-input:focus {
outline: none;
border-color: var(--accent-primary);
box-shadow: 0 0 0 2px var(--accent-muted);
}
.fhb-overtype-editor .--type-container {
border-radius: var(--radius);
}
.fhb-edit-buttons {
display: grid;
grid-auto-flow: column;
grid-auto-columns: max-content;
gap: var(--space-xs);
margin-top: var(--space-xs);
}
.fhb-inline-form {
margin-top: var(--space-xs);
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+126
View File
@@ -0,0 +1,126 @@
/**
* OverType v2.3.10
* A lightweight markdown editor library with perfect WYSIWYG alignment
* @license MIT
* @author David Miranda
* https://github.com/panphora/overtype
*/
var OverTypeEditor=(()=>{var ke=Object.defineProperty;var xn=Object.getOwnPropertyDescriptor;var kn=Object.getOwnPropertyNames;var Ln=Object.prototype.hasOwnProperty;var Sn=(n,e,t)=>e in n?ke(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var lt=(n,e)=>{for(var t in e)ke(n,t,{get:e[t],enumerable:!0})},_n=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of kn(e))!Ln.call(n,o)&&o!==t&&ke(n,o,{get:()=>e[o],enumerable:!(i=xn(e,o))||i.enumerable});return n};var En=n=>_n(ke({},"__esModule",{value:!0}),n);var C=(n,e,t)=>(Sn(n,typeof e!="symbol"?e+"":e,t),t);var xi={};lt(xi,{default:()=>bi});var E=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};return e.replace(/[&<>"']/g,i=>t[i])}static preserveIndentation(e,t){let o=t.match(/^(\s*)/)[1].replace(/ /g,"&nbsp;");return e.replace(/^\s*/,o)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,i,o)=>{let r=i.length;return o=this.parseInlineElements(o),`<h${r}><span class="syntax-marker">${i} </span>${o}</h${r}>`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`<div><span class="hr-marker">${e}</span></div>`:null}static parseBlockquote(e){return e.replace(/^&gt; (.+)$/,(t,i)=>`<span class="blockquote"><span class="syntax-marker">&gt;</span> ${i}</span>`)}static parseBulletList(e){return e.replace(/^((?:&nbsp;)*)([-*+])\s(.+)$/,(t,i,o,r)=>(r=this.parseInlineElements(r),`${i}<li class="bullet-list"><span class="syntax-marker">${o} </span>${r}</li>`))}static parseTaskList(e,t=!1){return e.replace(/^((?:&nbsp;)*)-(\s+)\[([ xX])\](\s*)(.*)$/,(i,o,r,s,a,l)=>{if(l=this.parseInlineElements(l),t){let p=s.toLowerCase()==="x";return`${o}<li class="task-list"><input type="checkbox" ${p?"checked":""}> ${l}</li>`}else return`${o}<li class="task-list"><span class="syntax-marker">-${r}[${s}]${a}</span>${l}</li>`})}static parseNumberedList(e){return e.replace(/^((?:&nbsp;)*)(\d+\.)\s(.+)$/,(t,i,o,r)=>(r=this.parseInlineElements(r),`${i}<li class="ordered-list"><span class="syntax-marker">${o} </span>${r}</li>`))}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`<div><span class="code-fence">${e}</span></div>`:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'<strong><span class="syntax-marker">**</span>$1<span class="syntax-marker">**</span></strong>'),e=e.replace(/__(.+?)__/g,'<strong><span class="syntax-marker">__</span>$1<span class="syntax-marker">__</span></strong>'),e}static parseItalic(e){return e=e.replace(new RegExp("(?<![\\*>])\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)","g"),'<em><span class="syntax-marker">*</span>$1<span class="syntax-marker">*</span></em>'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?<!_)_(?!_)(?=\\s|$)","g"),'<em><span class="syntax-marker">_</span>$1<span class="syntax-marker">_</span></em>'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?<!~)~~(?!~)(.+?)(?<!~)~~(?!~)","g"),'<del><span class="syntax-marker">~~</span>$1<span class="syntax-marker">~~</span></del>'),e=e.replace(new RegExp("(?<!~)~(?!~)(.+?)(?<!~)~(?!~)","g"),'<del><span class="syntax-marker">~</span>$1<span class="syntax-marker">~</span></del>'),e}static parseInlineCode(e){return e.replace(new RegExp("(?<!`)(`+)(?!`)((?:(?!\\1).)+?)(\\1)(?!`)","g"),'<code><span class="syntax-marker">$1</span>$2<span class="syntax-marker">$3</span></code>')}static sanitizeUrl(e){let t=e.trim(),i=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>i.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,i,o)=>{let r=`--link-${this.linkIndex++}`;return`<a href="${this.sanitizeUrl(o)}" style="anchor-name: ${r}"><span class="syntax-marker">[</span>${i}<span class="syntax-marker url-part">](${o})</span></a>`})}static identifyAndProtectSanctuaries(e){let t=new Map,i=0,o=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,u=h+a[2].length;r.push({start:h,end:u})}let l=new RegExp("(?<!`)(`+)(?!`)((?:(?!\\1).)+?)(\\1)(?!`)","g"),p,c=[];for(;(p=l.exec(e))!==null;){let d=p.index,h=p.index+p[0].length;r.some(f=>d>=f.start&&h<=f.end)||c.push({match:p[0],index:p.index,openTicks:p[1],content:p[2],closeTicks:p[3]})}return c.sort((d,h)=>h.index-d.index),c.forEach(d=>{let h=`\uE000${i++}\uE001`;t.set(h,{type:"code",original:d.match,openTicks:d.openTicks,content:d.content,closeTicks:d.closeTicks}),o=o.substring(0,d.index)+h+o.substring(d.index+d.match.length)}),o=o.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(d,h,u)=>{let f=`\uE000${i++}\uE001`;return t.set(f,{type:"link",original:d,linkText:h,url:u}),f}),{protectedText:o,sanctuaries:t}}static restoreAndTransfLine truncated
`),a=!1,p=s.map((c,d)=>{if(i&&d===t)return`<div class="raw-line">${this.escapeHtml(c)||"&nbsp;"}</div>`;if(/^```[^`]*$/.test(c))return a=!a,this.applyCustomSyntax(this.parseLine(c,r));if(a){let u=this.escapeHtml(c);return`<div>${this.preserveIndentation(u,c)||"&nbsp;"}</div>`}return this.applyCustomSyntax(this.parseLine(c,r))}).join("");return this.postProcessHTML(p,o)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let i=document.createElement("div");i.innerHTML=e;let o=null,r=null,s=null,a=!1,l=Array.from(i.children);for(let p=0;p<l.length;p++){let c=l[p];if(!c.parentNode)continue;let d=c.querySelector(".code-fence");if(d){let u=d.textContent;if(u.startsWith("```"))if(a){let f=t||this.codeHighlighter;if(s&&f&&s._codeContent)try{let m=f(s._codeContent,s._language||"");m&&typeof m.then=="function"?console.warn("Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only."):m&&typeof m=="string"&&m.trim()&&(s._codeElement.innerHTML=m)}catch(m){console.warn("Code highlighting failed:",m)}a=!1,s=null;continue}else{a=!0,s=document.createElement("pre");let f=document.createElement("code");s.appendChild(f),s.className="code-block";let m=u.slice(3).trim();m&&(f.className=`language-${m}`),i.insertBefore(s,c.nextSibling),s._codeElement=f,s._language=m,s._codeContent="";continue}}if(a&&s&&c.tagName==="DIV"&&!c.querySelector(".code-fence")){let u=s._codeElement||s.querySelector("code");s._codeContent.length>0&&(s._codeContent+=`
`);let f=c.textContent.replace(/\u00A0/g," ");s._codeContent+=f,u.textContent.length>0&&(u.textContent+=`
`),u.textContent+=f,c.remove();continue}let h=null;if(c.tagName==="DIV"&&(h=c.querySelector("li")),h){let u=h.classList.contains("bullet-list"),f=h.classList.contains("ordered-list");if(!u&&!f){o=null,r=null;continue}let m=u?"ul":"ol";(!o||r!==m)&&(o=document.createElement(m),i.insertBefore(o,c),r=m);let g=[];for(let y of c.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))g.push(y.cloneNode(!0));else if(y===h)break;g.forEach(y=>{h.insertBefore(y,h.firstChild)}),o.appendChild(h),c.remove()}else o=null,r=null}return i.innerHTML}static postProcessHTMLManual(e,t){let i=e;i=i.replace(/((?:<div>(?:&nbsp;)*<li class="bullet-list">.*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/<div>(?:&nbsp;)*<li class="bullet-list">.*?<\/li><\/div>/gs)||[];return s.length>0?"<ul>"+s.map(l=>{let p=l.match(/<div>((?:&nbsp;)*)<li/),c=l.match(/<li class="bullet-list">.*?<\/li>/);if(p&&c){let d=p[1];return c[0].replace(/<li class="bullet-list">/,`<li class="bullet-list">${d}`)}return c?c[0]:""}).filter(Boolean).join("")+"</ul>":r}),i=i.replace(/((?:<div>(?:&nbsp;)*<li class="ordered-list">.*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/<div>(?:&nbsp;)*<li class="ordered-list">.*?<\/li><\/div>/gs)||[];return s.length>0?"<ol>"+s.map(l=>{let p=l.match(/<div>((?:&nbsp;)*)<li/),c=l.match(/<li class="ordered-list">.*?<\/li>/);if(p&&c){let d=p[1];return c[0].replace(/<li class="ordered-list">/,`<li class="ordered-list">${d}`)}return c?c[0]:""}).filter(Boolean).join("")+"</ol>":r});let o=/<div><span class="code-fence">(```[^<]*)<\/span><\/div>(.*?)<div><span class="code-fence">(```)<\/span><\/div>/gs;return i=i.replace(o,(r,s,a,l)=>{let c=(a.match(/<div>(.*?)<\/div>/gs)||[]).map(g=>g.replace(/<div>(.*?)<\/div>/s,"$1").replace(/&nbsp;/g," ")).join(`
`),d=s.slice(3).trim(),h=d?` class="language-${d}"`:"",u=c,f=t||this.codeHighlighter;if(f)try{let g=c.replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&"),y=f(g,d);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(u=y)}catch(g){console.warn("Code highlighting failed:",g)}let m=`<div><span class="code-fence">${s}</span></div>`;return m+=`<pre class="code-block"><code${h}>${u}</code></pre>`,m+=`<div><span class="code-fence">${l}</span></div>`,m}),i}static getListContext(e,t){let i=e.split(`
`),o=0,r=0,s=0;for(let h=0;h<i.length;h++){let u=i[h].length;if(o+u>=t){r=h,s=o;break}o+=u+1}let a=i[r],l=s+a.length,p=a.match(this.LIST_PATTERNS.checkbox);if(p)return{inList:!0,listType:"checkbox",indent:p[1],marker:"-",checked:p[2]==="x",content:p[3],lineStart:s,lineEnd:l,markerEndPos:s+p[1].length+p[2].length+5};let c=a.match(this.LIST_PATTERNS.bullet);if(c)return{inList:!0,listType:"bullet",indent:c[1],marker:c[2],content:c[3],lineStart:s,lineEnd:l,markerEndPos:s+c[1].length+c[2].length+1};let d=a.match(this.LIST_PATTERNS.numbered);return d?{inList:!0,listType:"numbered",indent:d[1],marker:parseInt(d[2]),content:d[3],lineStart:s,lineEnd:l,markerEndPos:s+d[1].length+d[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:l,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(`
`),i=new Map,o=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let l=a[1],p=l.length,c=a[3];o||i.clear();let d=(i.get(p)||0)+1;i.set(p,d);for(let[h]of i)h>p&&i.delete(h);return o=!0,`${l}${d}. ${c}`}else return(s.trim()===""||!s.match(/^\s/))&&(o=!1,i.clear()),s}).join(`
`)}};C(E,"linkIndex",0),C(E,"codeHighlighter",null),C(E,"customSyntax",null),C(E,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var re=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let o=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(o="toggleBold");break;case"i":e.shiftKey||(o="toggleItalic");break;case"k":e.shiftKey||(o="insertLink");break;case"7":e.shiftKey&&(o="toggleNumberedList");break;case"8":e.shiftKey&&(o="toggleBulletList");break}return o?(e.preventDefault(),this.editor.performAction(o,e),!0):!1}destroy(){}};var z={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca",placeholder:"#999999"},previewColors:{text:"#0d3b66",h1:"inherit",h2:"inherit",h3:"inherit",strong:"inherit",em:"inherit",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",bg:"transparent"}},ct={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52",placeholder:"#6a7a88"},previewColors:{text:"#c5dde8",h1:"inherit",h2:"inherit",h3:"inherit",strong:"inherit",em:"inherit",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",bg:"transparent"}},pt={solar:z,cave:ct,auto:z,light:z,dark:ct};function R(n){return typeof n=="string"?{...pt[n]||pt.solar,name:n}:n}function Ze(n){if(n!=="auto")return n;let e=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)");return e!=null&&e.matches?"cave":"solar"}function Q(n,e){let t=[];for(let[i,o]of Object.entries(n)){let r=i.replace(/([A-Z])/g,"-$1").toLowerCase();t.push(`--${r}: ${o};`)}if(e)for(let[i,o]of Object.entries(e)){let r=i.replace(/([A-Z])/g,"-$1").toLowerCase();t.push(`--preview-${r}-default: ${o};`)}return t.join(`
`)}function dt(n,e={},t={}){return{...n,colors:{...n.colors,...e},previewColors:{...n.previewColors,...t}}}function Le(n={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:i='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:o="20px",theme:r=null,mobile:s={}}=n,a=Object.keys(s).length>0?`
@media (max-width: 640px) {
.overtype-wrapper .overtype-input,
.overtype-wrapper .overtype-preview {
${Object.entries(s).map(([p,c])=>`${p.replace(/([A-Z])/g,"-$1").toLowerCase()}: ${c} !important;`).join(`
`)}
}
}
`:"",l=r&&r.colors?Q(r.colors,r.previewColors):"";return`.overtype-container *{margin: 0 !important;padding: 0 !important;border: 0 !important;float: none !important;clear: none !important;text-decoration: none !important;text-transform: none !important;letter-spacing: normal !important;box-shadow: none !important;text-shadow: none !important;box-sizing: border-box !important}.overtype-container{display: flex !important;flex-direction: column !important;width: 100% !important;height: 100% !important;position: relative !important;overflow: visible !important;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif !important;text-align: left !important;${l?`
/* Theme Variables */
${l}`:""}}.overtype-container .overtype-wrapper *{text-align: left !important}.overtype-container.overtype-auto-resize{height: auto !important}.overtype-container.overtype-auto-resize .overtype-wrapper{flex: 0 0 auto !important;height: auto !important;min-height: 60px !important;overflow: visible !important}.overtype-wrapper{position: relative !important;width: 100% !important;flex: 1 1 0 !important;min-height: 60px !important;overflow: hidden !important;background: var(--bg-secondary,#ffffff) !important;z-index: 1}.overtype-wrapper .overtype-input,.overtype-wrapper .overtype-preview{position: absolute !important;top: 0 !important;left: 0 !important;width: 100% !important;height: 100% !important;font-family: var(--instance-font-family,${i}) !important;
font-variant-ligatures: none !important; /* keep metrics stable for code */
font-size: var(--instance-font-size, ${e}) !important;
line-height: var(--instance-line-height, ${t}) !important;
font-weight: normal !important;
font-style: normal !important;
font-variant: normal !important;
font-stretch: normal !important;
font-kerning: none !important;
font-feature-settings: normal !important;
/* Box model - must match exactly */
padding: var(--instance-padding, ${o}) !important;margin: 0 !important;border: none !important;outline: none !important;box-sizing: border-box !important;white-space: pre-wrap !important;word-wrap: break-word !important;word-break: normal !important;overflow-wrap: break-word !important;tab-size: 2 !important;-moz-tab-size: 2 !important;text-align: left !important;text-indent: 0 !important;letter-spacing: normal !important;word-spacing: normal !important;text-transform: none !important;text-rendering: auto !important;-webkit-font-smoothing: auto !important;-webkit-text-size-adjust: 100% !important;direction: ltr !important;writing-mode: horizontal-tb !important;unicode-bidi: normal !important;text-orientation: mixed !important;text-shadow: none !important;filter: none !important;transform: none !important;zoom: 1 !important;vertical-align: baseline !important;min-width: 0 !important;min-height: 0 !important;max-width: none !important;max-height: none !important;overflow-y: auto !important;overflow-x: auto !important;scrollbar-width: auto !important;scrollbar-gutter: auto !important;animation: none !important;transition: none !important}.overtype-wrapper .overtype-input{z-index: 1 !important;color: transparent !important;caret-color: var(--cursor,#f95738) !important;background-color: transparent !important;resize: none !important;appearance: none !important;-webkit-appearance: none !important;-moz-appearance: none !important;touch-action: manipulation !important;autocomplete: off !important;autocorrect: off !important;autocapitalize: off !important}.overtype-wrapper .overtype-input::selection{background-color: var(--selection,rgba(244,211,94,0.4))}.overtype-wrapper .overtype-placeholder{position: absolute !important;top: 0 !important;left: 0 !important;width: 100% !important;z-index: 0 !important;pointer-events: none !important;user-select: none !important;font-family: var(--instance-font-family,${i}) !important;
font-size: var(--instance-font-size, ${e}) !important;
line-height: var(--instance-line-height, ${t}) !important;
padding: var(--instance-padding, ${o}) !important;box-sizing: border-box !important;color: var(--placeholder,#999) !important}.overtype-wrapper .overtype-preview{z-index: 0 !important;pointer-events: none !important;color: var(--text,#0d3b66) !important;background-color: transparent !important;user-select: none !important;-webkit-user-select: none !important;-moz-user-select: none !important;-ms-user-select: none !important}.overtype-wrapper .overtype-preview *{font-family: inherit !important;font-size: inherit !important;line-height: inherit !important}.overtype-wrapper .overtype-preview div{margin: 0 !important;padding: 0 !important;border: none !important;text-align: left !important;text-indent: 0 !important;display: block !important;position: static !important;transform: none !important;min-height: 0 !important;max-height: none !important;line-height: inherit !important;font-size: inherit !important;font-family: inherit !important}.overtype-wrapper .overtype-preview .header{font-weight: bold !important}.overtype-wrapper .overtype-preview .h1{color: var(--h1,#f95738) !important}.overtype-wrapper .overtype-preview .h2{color: var(--h2,#ee964b) !important}.overtype-wrapper .overtype-preview .h3{color: var(--h3,#3d8a51) !important}.overtype-wrapper .overtype-preview h1,.overtype-wrapper .overtype-preview h2,.overtype-wrapper .overtype-preview h3{font-size: inherit !important;font-weight: bold !important;margin: 0 !important;padding: 0 !important;display: inline !important;line-height: inherit !important}.overtype-wrapper .overtype-preview h1{color: var(--h1,#f95738) !important}.overtype-wrapper .overtype-preview h2{color: var(--h2,#ee964b) !important}.overtype-wrapper .overtype-preview h3{color: var(--h3,#3d8a51) !important}.overtype-wrapper .overtype-preview ul,.overtype-wrapper .overtype-preview ol{list-style: none !important;margin: 0 !important;padding: 0 !important;display: block !important}.overtype-wrapper .overtype-preview li{display: block !important;margin: 0 !important;padding: 0 !important}.overtype-wrapper .overtype-preview strong{color: var(--strong,#ee964b) !important;font-weight: bold !important}.overtype-wrapper .overtype-preview em{color: var(--em,#f95738) !important;text-decoration-color: var(--em,#f95738) !important;text-decoration-thickness: 1px !important;font-style: italic !important}.overtype-wrapper .overtype-preview del{color: var(--del,#ee964b) !important;text-decoration: line-through !important;text-decoration-color: var(--del,#ee964b) !important;text-decoration-thickness: 1px !important}.overtype-wrapper .overtype-preview code{background: var(--code-bg,rgba(244,211,94,0.4)) !important;color: var(--code,#0d3b66) !important;padding: 0 !important;border-radius: 2px !important;font-family: inherit !important;font-size: inherit !important;line-height: inherit !important;font-weight: normal !important}.overtype-wrapper .overtype-preview pre{padding: 0 !important;margin: 0 !important;border-radius: 4px !important;overflow-x: auto !important}.overtype-wrapper .overtype-preview pre.code-block{background: var(--code-bg,rgba(244,211,94,0.4)) !important;white-space: break-spaces !important}.overtype-wrapper .overtype-preview pre code{background: transparent !important;color: var(--code,#0d3b66) !important;font-family: var(--instance-font-family,${i}) !important}.overtype-wrapper .overtype-preview .blockquote{color: var(--blockquote,#5a7a9b) !important;padding: 0 !important;margin: 0 !important;border: none !important}.overtype-wrapper .overtype-preview a{color: var(--link,#0d3b66) !important;text-decoration: underline !important;font-weight: normal !important}.overtype-wrapper .overtype-preview a:hover{text-decoration: underline !important;color: var(--link,#0d3b66) !important}.overtype-wrapper .overtype-preview ul,.overtype-wrapper .overtype-preview ol{list-style: none !important;margin: 0 !important;padding: 0 !important}.overtype-wrapper .overtype-preview hr{border: none !important;color: var(--hr,#5a7a9b) !important;margin: 0 !important;padding: 0 !important}.overtype-wrapper .overtype-preview .hr-marker{color: var(--hr,#5a7a9b) !important;opacity: 0.6 !important}.overtype-wrapper .overtype-preview .code-fence{color: var(--code,#0d3b66) !important;background: var(--code-bg,rgba(244,211,94,0.4)) !important}.overtype-wrapper .overtype-preview .code-block-line{background: var(--code-bg,rgba(244,211,94,0.4)) !important}.overtype-wrapper .overtype-preview .code-block-line .code-fence{background: transparent !important}.overtype-wrapper .overtype-preview .raw-line{color: var(--raw-line,#5a7a9b) !important;font-style: normal !important;font-weight: normal !important}.overtype-wrapper .overtype-preview .syntax-marker{color: var(--syntax-marker,rgba(13,59,102,0.52)) !important;opacity: 0.7 !important}.overtype-wrapper .overtype-preview .list-marker{color: var(--list-marker,#ee964b) !important}.overtype-stats{height: 40px !important;padding: 0 20px !important;background: var(--bg-secondary,Line truncated
`}var pe={};lt(pe,{applyCustomFormat:()=>Et,default:()=>Fn,expandSelection:()=>_t,getActiveFormats:()=>Ie,getDebugMode:()=>Je,hasFormat:()=>St,insertHeader:()=>ce,insertLink:()=>Te,preserveSelection:()=>xt,setDebugMode:()=>vt,setUndoMethod:()=>wt,toggleBold:()=>Ee,toggleBulletList:()=>He,toggleCode:()=>Ae,toggleH1:()=>Pe,toggleH2:()=>$e,toggleH3:()=>Re,toggleItalic:()=>Ce,toggleNumberedList:()=>Me,toggleQuote:()=>Oe,toggleTaskList:()=>le});var Cn=Object.defineProperty,ht=Object.getOwnPropertySymbols,An=Object.prototype.hasOwnProperty,Tn=Object.prototype.propertyIsEnumerable,ut=(n,e,t)=>e in n?Cn(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,ft=(n,e)=>{for(var t in e||(e={}))An.call(e,t)&&ut(n,t,e[t]);if(ht)for(var t of ht(e))Tn.call(e,t)&&ut(n,t,e[t]);return n},I={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Hn(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function B(n){return ft(ft({},Hn()),n)}var ae=!1;function vt(n){ae=n}function Je(){return ae}function x(n,e,t){ae&&(console.group(`\u{1F50D} ${n}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function Se(n,e){if(!ae)return;let t=n.value.slice(n.selectionStart,n.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let i=n.value.slice(Math.max(0,n.selectionStart-10),n.selectionStart),o=n.value.slice(n.selectionEnd,Math.min(n.value.length,n.selectionEnd+10));console.log("Context:",JSON.stringify(i)+"[SELECTION]"+JSON.stringify(o)),console.groupEnd()}function yt(n){ae&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(n.text)),console.log("New selection:",`${n.selectionStart}-${n.selectionEnd}`),console.groupEnd())}var T=null;function N(n,{text:e,selectionStart:t,selectionEnd:i}){let o=Je();o&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",i)),n.focus();let r=n.selectionStart,s=n.selectionEnd,a=n.value.slice(0,r),l=n.value.slice(s);o&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(l.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(n.value.slice(r,s))));let p=n.value,c=r!==s;if(T===null||T===!0){n.contentEditable="true";try{T=document.execCommand("insertText",!1,e),o&&console.log("execCommand returned:",T,"for text with",e.split(`
`).length,"lines")}catch(d){T=!1,o&&console.log("execCommand threw error:",d)}n.contentEditable="false"}if(o&&(console.log("canInsertText before:",T),console.log("execCommand result:",T)),T){let d=a+e+l,h=n.value;o&&(console.log("Expected length:",d.length),console.log("Actual length:",h.length)),h!==d&&o&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(d.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!T)if(o&&console.log("Using manual insertion"),n.value===p){o&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(d){}n.value=a+e+l;try{document.execCommand("ms-endUndoUnit")}catch(d){}n.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else o&&console.log("Value was changed by execCommand, skipping manual insertion");o&&console.log("Setting selection range:",t,i),t!=null&&i!=null?n.setSelectionRange(t,i):n.setSelectionRange(r,n.selectionEnd),o&&(console.log("Final value length:",n.value.length),console.groupEnd())}function wt(n){switch(n){case"native":T=!0;break;case"manual":T=!1;break;case"auto":T=null;break}}function Qe(n){return n.trim().split(`
`).length>1}function Mn(n,e){let t=e;for(;n[t]&&n[t-1]!=null&&!n[t-1].match(/\s/);)t--;return t}function On(n,e,t){let i=e,o=t?/\n/:/\s/;for(;n[i]&&!n[i].match(o);)i++;return i}function bt(n){let e=n.value.split(`
`),t=0;for(let i=0;i<e.length;i++){let o=e[i].length+1;n.selectionStart>=t&&n.selectionStart<t+o&&(n.selectionStart=t),n.selectionEnd>=t&&n.selectionEnd<t+o&&(i===e.length-1?n.selectionEnd=Math.min(t+e[i].length,n.value.length):n.selectionEnd=t+o-1),t+=o}}function Pn(n,e,t,i=!1){if(n.selectionStart===n.selectionEnd)n.selectionStart=Mn(n.value,n.selectionStart),n.selectionEnd=On(n.value,n.selectionEnd,i);else{let o=n.selectionStart-e.length,r=n.selectionEnd+t.length,s=n.value.slice(o,n.selectionStart)===e,a=n.value.slice(n.selectionEnd,r)===t;s&&a&&(n.selectionStart=o,n.selectionEnd=r)}return n.value.slice(n.selectionStart,n.selectionEnd)}function Xe(n){let e=n.value.slice(0,n.selectionStart),t=n.value.slice(n.selectionEnd),i=e.match(/\n*$/),o=t.match(/^\n*/),r=i?i[0].length:0,s=o?o[0].length:0,a="",l="";return e.match(/\S/)&&r<2&&(a=`
`.repeat(2-r)),t.match(/\S/)&&s<2&&(l=`
`.repeat(2-s)),{newlinesToAppend:a,newlinesToPrepend:l}}function xt(n,e){let t=n.selectionStart,i=n.selectionEnd,o=n.scrollTop;e(),n.selectionStart=t,n.selectionEnd=i,n.scrollTop=o}function _e(n,e,t={}){let i=n.selectionStart,o=n.selectionEnd,r=i===o,s=n.value,a=i;for(;a>0&&s[a-1]!==`
`;)a--;if(r){let p=i;for(;p<s.length&&s[p]!==`
`;)p++;n.selectionStart=a,n.selectionEnd=p}else bt(n);let l=e(n);if(t.adjustSelection){let c=n.value.slice(n.selectionStart,n.selectionEnd).startsWith(t.prefix),d=t.adjustSelection(c,i,o,a);l.selectionStart=d.start,l.selectionEnd=d.end}else if(t.prefix){let c=n.value.slice(n.selectionStart,n.selectionEnd).startsWith(t.prefix);r?c?(l.selectionStart=Math.max(i-t.prefix.length,a),l.selectionEnd=l.selectionStart):(l.selectionStart=i+t.prefix.length,l.selectionEnd=l.selectionStart):c?(l.selectionStart=Math.max(i-t.prefix.length,a),l.selectionEnd=Math.max(o-t.prefix.length,a)):(l.selectionStart=i+t.prefix.length,l.selectionEnd=o+t.prefix.length)}return l}function te(n,e){let t,i,{prefix:o,suffix:r,blockPrefix:s,blockSuffix:a,replaceNext:l,prefixSpace:p,scanFor:c,surroundWithNewlines:d,trimFirst:h}=e,u=n.selectionStart,f=n.selectionEnd,m=n.value.slice(n.selectionStart,n.selectionEnd),g=Qe(m)&&s&&s.length>0?`${s}
`:o,y=Qe(m)&&a&&a.length>0?`
${a}`:r;if(p){let k=n.value[n.selectionStart-1];n.selectionStart!==0&&k!=null&&!k.match(/\s/)&&(g=` ${g}`)}m=Pn(n,g,y,e.multiline);let w=n.selectionStart,b=n.selectionEnd,L=l&&l.length>0&&y.indexOf(l)>-1&&m.length>0;if(d){let k=Xe(n);t=k.newlinesToAppend,i=k.newlinesToPrepend,g=t+o,y+=i}if(m.startsWith(g)&&m.endsWith(y)){let k=m.slice(g.length,m.length-y.length);if(u===f){let _=u-g.length;_=Math.max(_,w),_=Math.min(_,w+k.length),w=b=_}else b=w+k.length;return{text:k,selectionStart:w,selectionEnd:b}}else if(L)if(c&&c.length>0&&m.match(c)){y=y.replace(l,m);let k=g+y;return w=b=w+g.length,{text:k,selectionStart:w,selectionEnd:b}}else{let k=g+m+y;return w=w+g.length+m.length+y.indexOf(l),b=w+l.length,{text:k,selectionStart:w,selectionEnd:b}}else{let k=g+m+y;w=u+g.length,b=f+g.length;let _=m.match(/^\s*|\s*$/g);if(h&&_){let be=_[0]||"",Y=_[1]||"";k=be+g+m.trim()+y+Y,w+=be.length,b-=Y.length}return{text:k,selectionStart:w,selectionEnd:b}}}function Ge(n,e){let{prefix:t,suffix:i,surroundWithNewlines:o}=e,r=n.value.slice(n.selectionStart,n.selectionEnd),s=n.selectionStart,a=n.selectionEnd,l=r.split(`
`);if(l.every(c=>c.startsWith(t)&&(!i||c.endsWith(i))))r=l.map(c=>{let d=c.slice(t.length);return i&&(d=d.slice(0,d.length-i.length)),d}).join(`
`),a=s+r.length;else if(r=l.map(c=>t+c+(i||"")).join(`
`),o){let{newlinesToAppend:c,newlinesToPrepend:d}=Xe(n);s+=c.length,a=s+r.length,r=c+r+d}return{text:r,selectionStart:s,selectionEnd:a}}function mt(n){let e=n.split(`
`),t=/^\d+\.\s+/,i=e.every(r=>t.test(r)),o=e;return i&&(o=e.map(r=>r.replace(t,""))),{text:o.join(`
`),processed:i}}function gt(n){let e=n.split(`
`),t="- ",i=e.every(r=>r.startsWith(t)),o=e;return i&&(o=e.map(r=>r.slice(t.length))),{text:o.join(`
`),processed:i}}function se(n,e){return e?"- ":`${n+1}. `}function $n(n,e){let t,i,o;return n.orderedList?(t=mt(e),i=gt(t.text),o=i.text):(t=gt(e),i=mt(t.text),o=i.text),[t,i,o]}function Rn(n,e){let t=n.selectionStart===n.selectionEnd,i=n.selectionStart,o=n.selectionEnd;bt(n);let r=n.value.slice(n.selectionStart,n.selectionEnd),[s,a,l]=$n(e,r),p=l.split(`
`).map((m,g)=>`${se(g,e.unorderedList)}${m}`),c=p.reduce((m,g,y)=>m+se(y,e.unorderedList).length,0),d=p.reduce((m,g,y)=>m+se(y,!e.unorderedList).length,0);if(s.processed)return t?(i=Math.max(i-se(0,e.unorderedList).length,0),o=i):(i=n.selectionStart,o=n.selectionEnd-c),{text:l,selectionStart:i,selectionEnd:o};let{newlinesToAppend:h,newlinesToPrepend:u}=Xe(n),f=h+p.join(`
`)+u;return t?(i=Math.max(i+se(0,e.unorderedList).length+h.length,0),o=i):a.processed?(i=Math.max(n.selectionStart+h.length,0),o=n.selectionEnd+h.length+c-d):(i=Math.max(n.selectionStart+h.length,0),o=n.selectionEnd+h.length+c),{text:f,selectionStart:i,selectionEnd:o}}function kt(n,e){let t=_e(n,i=>Rn(i,e),{adjustSelection:(i,o,r,s)=>{let a=n.value.slice(s,n.selectionEnd),l=/^\d+\.\s+/,p=/^- /,c=l.test(a),d=p.test(a),h=e.orderedList&&c||e.unorderedList&&d;if(o===r)if(h){let u=a.match(e.orderedList?l:p),f=u?u[0].length:0;return{start:Math.max(o-f,s),end:Math.max(o-f,s)}}else if(c||d){let u=a.match(c?l:p),f=u?u[0].length:0,g=(e.unorderedList?2:3)-f;return{start:o+g,end:o+g}}else{let u=e.unorderedList?2:3;return{start:o+u,end:o+u}}else if(h){let u=a.match(e.orderedList?l:p),f=u?u[0].length:0;return{start:Math.max(o-f,s),end:Math.max(r-f,s)}}else if(c||d){let u=a.match(c?l:p),f=u?u[0].length:0,g=(e.unorderedList?2:3)-f;return{start:o+g,end:r+g}}else{let u=e.unorderedList?2:3;return{start:o+u,end:r+u}}}});N(n,t)}function Lt(n){if(!n)return[];let e=[],{selectionStart:t,selectionEnd:i,value:o}=n,r=o.split(`
`),s=0,a="";for(let d of r){if(t>=s&&t<=s+d.length){a=d;break}s+=d.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let l=Math.max(0,t-10),p=Math.min(o.length,i+10),c=o.slice(l,p);if(c.includes("**")){let d=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=d.lastIndexOf("**"),f=h.indexOf("**");u!==-1&&f!==-1&&e.push("bold")}if(c.includes("_")){let d=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=d.lastIndexOf("_"),f=h.indexOf("_");u!==-1&&f!==-1&&e.push("italic")}if(c.includes("`")){let d=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100));d.includes("`")&&h.includes("`")&&e.push("code")}if(c.includes("[")&&c.includes("]")){let d=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=d.lastIndexOf("["),f=h.indexOf("]");u!==-1&&f!==-1&&o.slice(i+f+1,i+f+10).startsWith("(")&&e.push("link")}return e}function In(n,e){return Lt(n).includes(e)}function Bn(n,e={}){if(!n)return;let{toWord:t,toLine:i,toFormat:o}=e,{selectionStart:r,selectionEnd:s,value:a}=n;if(i){let l=a.split(`
`),p=0,c=0,d=0;for(let h of l){if(r>=d&&r<=d+h.length){p=d,c=d+h.length;break}d+=h.length+1}n.selectionStart=p,n.selectionEnd=c}else if(t&&r===s){let l=r,p=s;for(;l>0&&!/\s/.test(a[l-1]);)l--;for(;p<a.length&&!/\s/.test(a[p]);)p++;n.selectionStart=l,n.selectionEnd=p}}function Ee(n){if(!n||n.disabled||n.readOnly)return;x("toggleBold","Starting"),Se(n,"Before");let e=B(I.bold),t=te(n,e);yt(t),N(n,t),Se(n,"After")}function Ce(n){if(!n||n.disabled||n.readOnly)return;let e=B(I.italic),t=te(n,e);N(n,t)}function Ae(n){if(!n||n.disabled||n.readOnly)return;let e=B(I.code),t=te(n,e);N(n,t)}function Te(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),i=B(I.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(i.suffix=`](${t})`,i.replaceNext=""):e.url&&(i.suffix=`](${e.url})`,i.replaceNext=""),e.text&&!t){let s=n.selectionStart;n.value=n.value.slice(0,s)+e.text+n.value.slice(s),n.selectionStart=s,n.selectionEnd=s+e.text.length}let r=te(n,i);N(n,r)}function He(n){if(!n||n.disabled||n.readOnly)return;let e=B(I.bulletList);kt(n,e)}function Me(n){if(!n||n.disabled||n.readOnly)return;let e=B(I.numberedList);kt(n,e)}function Oe(n){if(!n||n.disabled||n.readOnly)return;x("toggleQuote","Starting"),Se(n,"Initial");let e=B(I.quote),t=_e(n,i=>Ge(i,e),{prefix:e.prefix});yt(t),N(n,t),Se(n,"Final")}function le(n){if(!n||n.disabled||n.readOnly)return;let e=B(I.taskList),t=_e(n,i=>Ge(i,e),{prefix:e.prefix});N(n,t)}function ce(n,e=1,t=!1){if(!n||n.disabled||n.readOnly)return;(e<1||e>6)&&(e=1),x("insertHeader","============ START ============"),x("insertHeader",`Level: ${e}, Toggle: ${t}`),x("insertHeader",`Initial cursor: ${n.selectionStart}-${n.selectionEnd}`);let i=`header${e===1?"1":e}`,o=B(I[i]||I.header1);x("insertHeader",`Style prefix: "${o.prefix}"`);let r=n.value,s=n.selectionStart,a=n.selectionEnd,l=s;for(;l>0&&r[l-1]!==`
`;)l--;let p=a;for(;p<r.length&&r[p]!==`
`;)p++;let c=r.slice(l,p);x("insertHeader",`Current line (before): "${c}"`);let d=c.match(/^(#{1,6})\s*/),h=d?d[1].length:0,u=d?d[0].length:0;x("insertHeader","Existing header check:"),x("insertHeader",` - Match: ${d?`"${d[0]}"`:"none"}`),x("insertHeader",` - Existing level: ${h}`),x("insertHeader",` - Existing prefix length: ${u}`),x("insertHeader",` - Target level: ${e}`);let f=t&&h===e;x("insertHeader",`Should toggle OFF: ${f} (toggle=${t}, existingLevel=${h}, level=${e})`);let m=_e(n,g=>{let y=g.value.slice(g.selectionStart,g.selectionEnd);x("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");x("insertHeader",`Cleaned line: "${w}"`);let b;return f?(x("insertHeader","ACTION: Toggling OFF - removing header"),b=w):h>0?(x("insertHeader",`ACTION: Replacing H${h} with H${e}`),b=o.prefix+w):(x("insertHeader","ACTION: Adding new header"),b=o.prefix+w),x("insertHeader",`New line: "${b}"`),{text:b,selectionStart:g.selectionStart,selectionEnd:g.selectionEnd}},{prefix:o.prefix,adjustSelection:(g,y,w,b)=>{if(x("insertHeader","Adjusting selection:"),x("insertHeader",` - isRemoving param: ${g}`),x("insertHeader",` - shouldToggleOff: ${f}`),x("insertHeader",` - selStart: ${y}, selEnd: ${w}`),x("insertHeader",` - lineStartPos: ${b}`),f){let L=Math.max(y-u,b);return x("insertHeader",` - Removing header, adjusting by -${u}`),{start:L,end:y===w?L:Math.max(w-u,b)}}else if(u>0){let L=o.prefix.length-u;return x("insertHeader",` - Replacing header, adjusting by ${L}`),{start:y+L,end:w+L}}else return x("insertHeader",` - Adding header, adjusting by +${o.prefix.length}`),{start:y+o.prefix.length,end:w+o.prefix.length}}});x("insertHeader",`Final result: text="${m.text}", cursor=${m.selectionStart}-${m.selectionEnd}`),x("insertHeader","============ END ============"),N(n,m)}function Pe(n){ce(n,1,!0)}function $e(n){ce(n,2,!0)}function Re(n){ce(n,3,!0)}function Ie(n){return Lt(n)}function St(n,e){return In(n,e)}function _t(n,e={}){Bn(n,e)}function Et(n,e){if(!n||n.disabled||n.readOnly)return;let t=B(e),i;if(t.multiline){let o=n.value.slice(n.selectionStart,n.selectionEnd);Qe(o)?i=Ge(n,t):i=te(n,t)}else i=te(n,t);N(n,i)}var Fn={toggleBold:Ee,toggleItalic:Ce,toggleCode:Ae,insertLink:Te,toggleBulletList:He,toggleNumberedList:Me,toggleQuote:Oe,toggleTaskList:le,insertHeader:ce,toggleH1:Pe,toggleH2:$e,toggleH3:Re,getActiveFormats:Ie,hasFormat:St,expandSelection:_t,applyCustomFormat:Et,preserveSelection:xt,setUndoMethod:wt,setDebugMode:vt,getDebugMode:Je};var Be=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",i=>{i.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=i=>{i.preventDefault();let o=e.actionId||e.name;this.editor.performAction(o,i)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let i=this.createViewModeDropdown(e),o=e.getBoundingClientRect();i.style.position="absolute",i.style.top=`${o.bottom+5}px`,i.style.left=`${o.left}px`,document.body.appendChild(i),this.handleDocumentClick=r=>{!i.contains(r.target)&&!e.contains(r.target)&&(i.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("cl Line truncated
<span style="display: flex; align-items: center; gap: 6px;">
<svg width="12" height="12" viewBox="0 0 20 20" fill="currentColor" style="flex-shrink: 0;">
<path d="M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z"></path>
<path d="M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z"></path>
</svg>
<span class="overtype-link-tooltip-url"></span>
</span>
`,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,i=this.findLinkAtPosition(t,e);i?(!this.currentLink||this.currentLink.url!==i.url||this.currentLink.index!==i.index)&&this.show(i):this.scheduleHide()}findLinkAtPosition(e,t){let i=/\[([^\]]+)\]\(([^)]+)\)/g,o,r=0;for(;(o=i.exec(e))!==null;){let s=o.index,a=o.index+o[0].length;if(t>=s&&t<=a)return{text:o[1],url:o[2],index:r,start:s,end:a};r++}return null}async show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,await this.positionTooltip(e),this.currentLink===e&&this.tooltip.classList.add("visible")}async positionTooltip(e){let t=this.findAnchorElement(e.index);if(!t)return;let i=t.getBoundingClientRect();if(!(i.width===0||i.height===0))try{let{x:o,y:r}=await nn(t,this.tooltip,{strategy:"fixed",placement:"bottom",middleware:[Yt(8),en({padding:8}),tn()]});Object.assign(this.tooltip.style,{left:`${o}px`,top:`${r}px`,position:"fixed"})}catch(o){console.warn("Floating UI positioning failed:",o)}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.isTooltipHovered=!1}};var on='<svg viewBox="0 0 18 18"><path stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5,4H9.5A2.5,2.5,0,0,1,12,6.5v0A2.5,2.5,0,0,1,9.5,9H5A0,0,0,0,1,5,9V4A0,0,0,0,1,5,4Z"></path><path stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5,9h5.5A2.5,2.5,0,0,1,13,11.5v0A2.5,2.5,0,0,1,10.5,14H5a0,0,0,0,1,0,0V9A0,0,0,0,1,5,9Z"></path></svg>',rn='<svg viewBox="0 0 18 18"><line stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="7" x2="13" y1="4" y2="4"></line><line stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="5" x2="11" y1="14" y2="14"></line><line stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="8" x2="10" y1="14" y2="4"></line></svg>',sn='<svg viewBox="0 0 18 18"><path fill="currentColor" d="M10,4V14a1,1,0,0,1-2,0V10H3v4a1,1,0,0,1-2,0V4A1,1,0,0,1,3,4V8H8V4a1,1,0,0,1,2,0Zm6.06787,9.209H14.98975V7.59863a.54085.54085,0,0,0-.605-.60547h-.62744a1.01119,1.01119,0,0,0-.748.29688L11.645,8.56641a.5435.5435,0,0,0-.022.8584l.28613.30762a.53861.53861,0,0,0,.84717.0332l.09912-.08789a1.2137,1.2137,0,0,0,.2417-.35254h.02246s-.01123.30859-.01123.60547V13.209H12.041a.54085.54085,0,0,0-.605.60547v.43945a.54085.54085,0,0,0,.605.60547h4.02686a.54085.54085,0,0,0,.605-.60547v-.43945A.54085.54085,0,0,0,16.06787,13.209Z"></path></svg>',an='<svg viewBox="0 0 18 18"><path fill="currentColor" d="M16.73975,13.81445v.43945a.54085.54085,0,0,1-.605.60547H11.855a.58392.58392,0,0,1-.64893-.60547V14.0127c0-2.90527,3.39941-3.42187,3.39941-4.55469a.77675.77675,0,0,0-.84717-.78125,1.17684,1.17684,0,0,0-.83594.38477c-.2749.26367-.561.374-.85791.13184l-.4292-.34082c-.30811-.24219-.38525-.51758-.1543-.81445a2.97155,2.97155,0,0,1,2.45361-1.17676,2.45393,2.45393,0,0,1,2.68408,2.40918c0,2.45312-3.1792,2.92676-3.27832,3.93848h2.79443A.54085.54085,0,0,1,16.73975,13.81445ZM9,3A.99974.99974,0,0,0,8,4V8H3V4A1,1,0,0,0,1,4V14a1,1,0,0,0,2,0V10H8v4a1,1,0,0,0,2,0V4A.99974.99974,0,0,0,9,3Z"></path></svg>',ln='<svg viewBox="0 0 18 18"><path fill="currentColor" d="M16.65186,12.30664a2.6742,2.6742,0,0,1-2.915,2.68457,3.96592,3.96592,0,0,1-2.25537-.6709.56007.56007,0,0,1-.13232-.83594L11.64648,13c.209-.34082.48389-.36328.82471-.1543a2.32654,2.32654,0,0,0,1.12256.33008c.71484,0,1.12207-.35156,1.12207-.78125,0-.61523-.61621-.86816-1.46338-.86816H13.2085a.65159.65159,0,0,1-.68213-.41895l-.05518-.10937a.67114.67114,0,0,1,.14307-.78125l.71533-.86914a8.55289,8.55289,0,0,1,.68213-.7373V8.58887a3.93913,3.93913,0,0,1-.748.05469H11.9873a.54085.54085,0,0,1-.605-.60547V7.59863a.54085.54085,0,0,1,.605-.60547h3.75146a.53773.53773,0,0,1,.60547.59375v.17676a1.03723,1.03723,0,0,1-.27539.748L14.74854,10.0293A2.31132,2.31132,0,0,1,16.65186,12.30664ZM9,3A.99974.99974,0,0,0,8,4V8H3V4A1,1,0,0,0,1,4V14a1,1,0,0,0,2,0V10H8v4a1,1,0,0,0,2,0V4A.99974.99974,0,0,0,9,3Z"></path></svg>',cn='<svg viewBox="0 0 18 Line truncated
`),this.options.fileUpload.batch){t.push({file:i,placeholder:s});continue}this.options.fileUpload.onInsertFile(i).then(a=>{this.textarea.value=this.textarea.value.replace(s,a),this._trackInsertedUrls(a,i),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))},a=>{console.error("OverType: File upload failed",a),this.textarea.value=this.textarea.value.replace(s,"[Upload failed]()"),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))})}this.options.fileUpload.batch&&t.length>0&&this.options.fileUpload.onInsertFile(t.map(i=>i.file)).then(i=>{(Array.isArray(i)?i:[i]).forEach((r,s)=>{this.textarea.value=this.textarea.value.replace(t[s].placeholder,r),this._trackInsertedUrls(r,t[s].file)}),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))},i=>{console.error("OverType: File upload failed",i),t.forEach(({placeholder:o})=>{this.textarea.value=this.textarea.value.replace(o,"[Upload failed]()")}),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))})}_handleDragOver(e){e.preventDefault()}_destroyFileUpload(){this.textarea.removeEventListener("paste",this._boundHandleFilePaste),this.textarea.removeEventListener("drop",this._boundHandleFileDrop),this.textarea.removeEventListener("dragover",this._boundHandleDragOver),this._boundHandleFilePaste=null,this._boundHandleFileDrop=null,this._boundHandleDragOver=null,this._uploadedFiles=null,this.fileUploadInitialized=!1}insertAtCursor(e){let t=this.textarea.selectionStart,i=this.textarea.selectionEnd,o=!1;try{o=document.execCommand("insertText",!1,e)}catch(r){}if(!o){let r=this.textarea.value.slice(0,t),s=this.textarea.value.slice(i);this.textarea.value=r+e+s,this.textarea.setSelectionRange(t+e.length,t+e.length)}this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,i=this._getCurrentLine(e,t),o=this.container.dataset.mode==="preview",r=E.parse(e,i,this.options.showActiveLineRaw,this.options.codeHighlighter,o);this.preview.innerHTML=r,this.placeholderEl&&(this.placeholderEl.style.display=e?"none":""),this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onRender&&this.options.onRender(this.preview,o?"preview":"normal",this)}_notifyChange(){this.initialized&&(this._checkForRemovedUploads(),this.options.onChange&&this.options.onChange(this.textarea.value,this))}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;t<e.length-1;t+=2){let i=e[t],o=e[t+1],r=i.parentElement,s=o.parentElement;!r||!s||(i.style.display="block",o.style.display="block",r.classList.add("code-block-line"),s.classList.add("code-block-line"))}}_getCurrentLine(e,t){return e.substring(0,t).split(`
`).length-1}handleInput(e){this.updatePreview(),this._notifyChange()}handleFocus(e){this.options.onFocus&&this.options.onFocus(e,this)}handleBlur(e){this.options.onBlur&&this.options.onBlur(e,this)}handleKeydown(e){if(e.key==="Tab"){let i=this.textarea.selectionStart,o=this.textarea.selectionEnd,r=this.textarea.value;if(e.shiftKey&&i===o)return;if(e.preventDefault(),i!==o&&e.shiftKey){let s=r.substring(0,i),a=r.substring(i,o),l=r.substring(o),c=a.split(`
`).map(d=>d.replace(/^ /,"")).join(`
`);document.execCommand?(this.textarea.setSelectionRange(i,o),document.execCommand("insertText",!1,c)):(this.textarea.value=s+c+l,this.textarea.selectionStart=i,this.textarea.selectionEnd=i+c.length)}else if(i!==o){let s=r.substring(0,i),a=r.substring(i,o),l=r.substring(o),c=a.split(`
`).map(d=>" "+d).join(`
`);document.execCommand?(this.textarea.setSelectionRange(i,o),document.execCommand("insertText",!1,c)):(this.textarea.value=s+c+l,this.textarea.selectionStart=i,this.textarea.selectionEnd=i+c.length)}else document.execCommand?document.execCommand("insertText",!1," "):(this.textarea.value=r.substring(0,i)+" "+r.substring(o),this.textarea.selectionStart=this.textarea.selectionEnd=i+2);this.textarea.dispatchEvent(new Event("input",{bubbles:!0}));return}if(e.key==="Enter"&&!e.shiftKey&&!e.metaKey&&!e.ctrlKey&&this.options.smartLists&&this.handleSmartListContinuation()){e.preventDefault();return}!this.shortcuts.handleKeydown(e)&&this.options.onKeydown&&this.options.onKeydown(e,this)}handleSmartListContinuation(){let e=this.textarea,t=e.selectionStart,i=E.getListContext(e.value,t);return!i||!i.inList?!1:i.content.trim()===""&&t>=i.markerEndPos?(this.deleteListMarker(i),!0):(t>i.markerEndPos&&t<i.lineEnd?this.splitListItem(i,t):this.insertNewListItem(i),i.listType==="numbered"&&this.scheduleNumberedListUpdate(),!0)}deleteListMarker(e){this.textarea.setSelectionRange(e.lineStart,e.markerEndPos),document.execCommand("delete"),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}insertNewListItem(e){let t=E.createNewListItem(e);document.execCommand("insertText",!1,`
`+t),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}splitListItem(e,t){let i=e.content.substring(t-e.markerEndPos);this.textarea.setSelectionRange(t,e.lineEnd),document.execCommand("delete");let o=E.createNewListItem(e);document.execCommand("insertText",!1,`
`+o+i);let r=this.textarea.selectionStart-i.length;this.textarea.setSelectionRange(r,r),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}scheduleNumberedListUpdate(){this.numberUpdateTimeout&&clearTimeout(this.numberUpdateTimeout),this.numberUpdateTimeout=setTimeout(()=>{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,i=E.renumberLists(e);if(i!==e){let o=0,r=e.split(`
`),s=i.split(`
`),a=0;for(let p=0;p<r.length&&a<t;p++){if(r[p]!==s[p]){let c=s[p].length-r[p].length;a+r[p].length<t&&(o+=c)}a+=r[p].length+1}this.textarea.value=i;let l=t+o;this.textarea.setSelectionRange(l,l),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}}handleScroll(e){this.preview.scrollTop=this.textarea.scrollTop,this.preview.scrollLeft=this.textarea.scrollLeft}getValue(){return this.textarea.value}setValue(e){let t=this.textarea.value!==e;this.textarea.value=e,this.updatePreview(),this.options.autoResize&&this._updateAutoHeight(),t&&this._notifyChange()}async performAction(e,t=null){var r;let i=this.textarea;if(!i)return!1;let o=(r=this.actionsById)==null?void 0:r[e];if(!o)return console.warn(`OverType: Unknown action "${e}"`),!1;i.focus();try{return await o({editor:this,getValue:()=>this.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),i=E.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(i=i.replace(/<span class="syntax-marker[^"]*">.*?<\/span>/g,""),i=i.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),i=i.replace(/\sclass=""/g,"")),i}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var o;let t=(o=this.options)==null?void 0:o.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let i=this.toolbar&&this.options.toolbar&&vi(t,this.options.toolbarButtons);this._rebuildActionsMap(),i&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this.fileUploadInitialized&&this._destroyFileUpload(),this.options.fileUpload&&this._initFileUpload(),this._applyOptions(),this.updatePreview()}showToolbar(){this.toolbar?this.toolbar.show():this._createToolbar()}hideToolbar(){this.toolbar&&this.toolbar.hide()}setTheme(e){if(v._autoInstances.delete(this),this.instanceTheme=e,e==="auto")v._autoInstances.add(this),v._startAutoListener(),this._applyResolvedTheme(Ze("auto"));else{let t=typeof e=="string"?R(e):e,i=typeof t=="string"?t:t.name;if(i&&this.container.setAttribute("data-theme",i),t&&t.colors){let o=Q(t.colors,t.previewColors);this.container.style.cssText+=o}this.updatePreview()}return v._stopAutoListener(),this}_applyResolvedTheme(e){let t=R(e);this.container.setAttribute("data-theme",e),t&&t.colors&&(this.container.style.cssText=Q(t.colors,t.previewColors)),this.updatePreview()}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(`
`),i=e.length,o=e.split(/\s+/).filter(c=>c.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(`
`),l=a.length,p=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:i,words:o,lines:t.length,line:l,column:p}):this.statsBar.innerHTML=`
<div class="overtype-stat">
<span class="live-dot"></span>
<span>${i} chars, ${o} words, ${t.length} lines</span>
</div>
<div class="overtype-stat">Line ${l}, Col ${p}</div>
`}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper;if(this.container.dataset.mode==="preview"){i.style.removeProperty("height"),t.style.removeProperty("height"),t.style.removeProperty("overflow-y"),e.style.removeProperty("height"),e.style.removeProperty("overflow-y");return}let r=e.scrollTop;i.style.setProperty("height","auto","important"),e.style.setProperty("height","auto","important");let s=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);s=Math.max(s,p)}let a="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);s>p&&(s=p,a="auto")}let l=s+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",a,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",a,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=r,t.scrollTop=r,this.previousHeight!==s&&(this.previousHeight=s)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),this._updateAutoHeight(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this._updateAutoHeight(),this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this._updateAutoHeight(),this}destroy(){if(v._autoInstances.delete(this),v._stopAutoListener(),this.fileUploadInitialized&&this._destroyFileUpload(),this.element.overTypeInstance=null,v.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new v(e,t)}static initFromData(e,t={}){return v._resolveTargets(e).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let l=s.name.slice(8).replace(/-([a-z])/g,(p,c)=>c.toUpperCase());r[l]=v._parseDataValue(s.value)}return new v(o,r)[0]})}static _resolveTargets(e){if(e==null)throw new Error("Invalid target: must be selector string, Element, NodeList, or Array");if(typeof e=="string")return Array.from(document.querySelectorAll(e));if(e instanceof Element)return[e];if(e instanceof NodeList)return Array.from(e);if(Array.isArray(e))return e;if(typeof e.length=="number")return Array.from(e);throw new Error("Invalid target: must be selector string, Element, NodeList, or Array")}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){let t;return e instanceof Element?t=e:t=v._resolveTargets(e)[0],t&&(t.overTypeInstance||v.instances.get(t))||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=v.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(v.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=v.currentTheme||z,o=Le({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),v.stylesInjected=!0}static setTheme(e,t=null){if(v._globalAutoTheme=!1,v._globalAutoCustomColors=null,e==="auto"){v._globalAutoTheme=!0,v._globalAutoCustomColors=t,v._startAutoListener(),v._applyGlobalTheme(Ze("auto"),t);return}v._stopAutoListener(),v._applyGlobalTheme(e,t)}static _applyGlobalTheme(e,t=null){let i=typeof e=="string"?R(e):e;t&&(i=dt(i,t)),v.currentTheme=i,v.injectStyles(!0);let o=typeof i=="string"?i:i.name;document.querySelectorAll(".overtype-container").forEach(r=>{o&&r.setAttribute("data-theme",o)}),document.querySelectorAll(".overtype-wrapper").forEach(r=>{r.closest(".overtype-container")||o&&r.setAttribute("data-theme",o);let s=r._instance;s&&s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{o&&typeof r.setAttribute=="function"&&r.setAttribute("theme",o),typeof r.refreshTheme=="function"&&r.refreshTheme()})}static _startAutoListener(){v._autoMediaQuery||window.matchMedia&&(v._autoMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),v._autoMediaListener=e=>{let t=e.matches?"cave":"solar";v._globalAutoTheme&&v._applyGlobalTheme(t,v._globalAutoCustomColors),v._autoInstance Line truncated
`).replace(/\\t/g," ")}static get observedAttributes(){return wi}connectedCallback(){this._isConnected=!0,this._initializeEditor()}disconnectedCallback(){this._isConnected=!1,this._cleanup()}attributeChangedCallback(e,t,i){if(t!==i&&!this._silentUpdate){if(!this._initialized){this._pendingOptions[e]=i;return}this._updateOption(e,i)}}_initializeEditor(){if(!(this._initialized||!this._isConnected))try{let e=document.createElement("div");e.className=wn;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");t&&(e.style.height=t),i&&(e.style.minHeight=i),o&&(e.style.maxHeight=o),this._injectStyles(),this.shadowRoot.appendChild(e);let r=this._getOptionsFromAttributes(),s=new yn(e,r);this._editor=s[0],this._initialized=!0,this._editor&&this._editor.textarea&&(this._editor.textarea.addEventListener("scroll",()=>{this._editor&&this._editor.preview&&this._editor.textarea&&(this._editor.preview.scrollTop=this._editor.textarea.scrollTop,this._editor.preview.scrollLeft=this._editor.textarea.scrollLeft)}),this._editor.textarea.addEventListener("input",a=>{this._editor&&this._editor.handleInput&&this._editor.handleInput(a)}),this._editor.textarea.addEventListener("keydown",a=>{this._editor&&this._editor.handleKeydown&&this._editor.handleKeydown(a)}),this._selectionChangeHandler=()=>{if(document.activeElement===this){let a=this.shadowRoot.activeElement;a&&a===this._editor.textarea&&(this._editor.options.showStats&&this._editor.statsBar&&this._editor._updateStats(),this._editor.linkTooltip&&this._editor.linkTooltip.checkCursorPosition&&this._editor.linkTooltip.checkCursorPosition())}},document.addEventListener("selectionchange",this._selectionChangeHandler)),this._applyPendingOptions(),this._dispatchEvent("ready",{editor:this._editor})}catch(e){let t=e&&e.message?e.message:String(e);console.warn("OverType Web Component initialization failed:",t),this._dispatchEvent("error",{error:{message:t}})}}_injectStyles(){let e=document.createElement("style"),t=this.getAttribute("theme")||"solar",i=R(t),o=this._getOptionsFromAttributes(),r=Le({...o,theme:i}),s=`
/* Web Component Host Styles */
:host {
display: block;
position: relative;
width: 100%;
height: 100%;
contain: layout style;
}
.overtype-webcomponent-container {
width: 100%;
height: 100%;
position: relative;
}
/* Override container grid layout for web component */
.overtype-container {
height: 100% !important;
}
`;this._styleVersion+=1;let a=`
/* overtype-webcomponent styles v${this._styleVersion} */
`;e.textContent=a+r+s,this._baseStyleElement=e,this.shadowRoot.appendChild(e)}_getOptionsFromAttributes(){let e={value:this.getAttribute("value")!==null?this._decodeValue(this.getAttribute("value")):(this.textContent||"").trim(),placeholder:this.getAttribute("placeholder")||yi,toolbar:this.hasAttribute("toolbar"),autofocus:this.hasAttribute("autofocus"),autoResize:this.hasAttribute("auto-resize"),showStats:this.hasAttribute("show-stats"),smartLists:!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false",spellcheck:this.hasAttribute("spellcheck")&&this.getAttribute("spellcheck")!=="false",onChange:this._handleChange,onKeydown:this._handleKeydown,onRender:this._handleRender},t=this.getAttribute("font-size");t&&(e.fontSize=t);let i=this.getAttribute("line-height");i&&(e.lineHeight=parseFloat(i)||1.6);let o=this.getAttribute("padding");o&&(e.padding=o);let r=this.getAttribute("min-height");r&&(e.minHeight=r);let s=this.getAttribute("max-height");return s&&(e.maxHeight=s),e}_applyPendingOptions(){for(let[e,t]of Object.entries(this._pendingOptions))this._updateOption(e,t);this._pendingOptions={}}_updateOption(e,t){if(this._editor)switch(e){case"value":{let i=this._decodeValue(t);this._editor.getValue()!==i&&this._editor.setValue(i||"")}break;case"theme":this._reinjectStyles(),this._editor&&this._editor.setTheme&&this._editor.setTheme(t||"solar");break;case"placeholder":this._editor&&(this._editor.options.placeholder=t||"",this._editor.textarea&&(this._editor.textarea.placeholder=t||""),this._editor.placeholderEl&&(this._editor.placeholderEl.textContent=t||""));break;case"readonly":this._editor.textarea&&(this._editor.textarea.readOnly=this.hasAttribute("readonly"));break;case"height":case"min-height":case"max-height":this._updateContainerHeight();break;case"toolbar":if(!!this.hasAttribute("toolbar")==!!this._editor.options.toolbar)return;this._reinitializeEditor();break;case"auto-resize":if(!!this.hasAttribute("auto-resize")==!!this._editor.options.autoResize)return;this._reinitializeEditor();break;case"show-stats":if(!!this.hasAttribute("show-stats")==!!this._editor.options.showStats)return;this._reinitializeEditor();break;case"font-size":{this._updateFontSize(t)&&this._reinjectStyles();break}case"line-height":{this._updateLineHeight(t)&&this._reinjectStyles();break}case"padding":this._reinjectStyles();break;case"smart-lists":{let i=!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false";if(!!this._editor.options.smartLists==!!i)return;this._reinitializeEditor();break}case"spellcheck":if(this._editor){let i=this.hasAttribute("spellcheck")&&this.getAttribute("spellcheck")!=="false";this._editor.options.spellcheck=i,this._editor.textarea&&this._editor.textarea.setAttribute("spellcheck",String(i))}break}}_updateContainerHeight(){let e=this.shadowRoot.querySelector(`.${wn}`);if(!e)return;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");e.style.height=t||"",e.style.minHeight=i||"",e.style.maxHeight=o||""}_updateFontSize(e){return this._editor&&this._editor.wrapper?(this._editor.options.fontSize=e||"",this._editor.wrapper.style.setProperty("--instance-font-size",this._editor.options.fontSize),this._editor.updatePreview(),!0):!1}_updateLineHeight(e){if(this._editor&&this._editor.wrapper){let t=parseFloat(e),i=Number.isFinite(t)?t:this._editor.options.lineHeight;return this._editor.options.lineHeight=i,this._editor.wrapper.style.setProperty("--instance-line-height",String(i)),this._editor.updatePreview(),!0}return!1}_reinjectStyles(){this._baseStyleElement&&this._baseStyleElement.parentNode&&this._baseStyleElement.remove(),this._injectStyles()}_reinitializeEditor(){let e=this._editor?this._editor.getValue():"";this._cleanup(),this._initialized=!1,this.shadowRoot.innerHTML="",e&&!this.getAttribute("value")&&this.setAttribute("value",e),this._initializeEditor()}_handleChange(e){this._updateValueAttribute(e),!(!this._initialized||!this._editor)&&this._dispatchEvent("change",{value:e,editor:this._editor})}_handleKeydown(e){this._dispatchEvent("keydown",{event:e,editor:this._editor})}_handleRender(e,t){this._dispatchEvent("render",{preview:e,mode:t,editor:this._editor})}_updateValueAttribute(e){this.getAttribute("value")!==e&&(this._silentUpdate=!0,this.setAttribute("value",e),this._silentUpdate=!1)}_dispatchEvent(e,t={}){let i=new CustomEvent(e,{detail:t,bubbles:!0,composed:!0});this.dispatchEvent(i)}_cleanup(){this._selectionChangeHandler&&(document.removeEventListener("selectionchange",this._selectionChangeHandler),this._selectionChangeHandler=null),this._editor&&typeof this._editor.destroy=="function"&&this._editor.destroy(),this._editor=null,this._initialized=!1,this.shadowRoot&&(this.shadowRoot.innerHTML="")}refreshTheme(){this._initialized&&this._reinjectStyles()}getValue(){return this._editor?this._editor.getValue():this.getAttribute("value")||""}setValue(e){this._editor?this._editor.setValue(e):this.setAttribute("value" Line truncated
`),i=e.length,o=e.split(/\s+/).filter(c=>c.length>0).length,r=this._editor.textarea.selectionStart,a=e.substring(0,r).split(`
`),l=a.length,p=a[a.length-1].length+1;return{characters:i,words:o,lines:t.length,line:l,column:p}}isReady(){return this._initialized&&this._editor!==null}getEditor(){return this._editor}showToolbar(){this._editor&&this._editor.showToolbar()}hideToolbar(){this._editor&&this._editor.hideToolbar()}};customElements.get("overtype-editor")||customElements.define("overtype-editor",qe);var bi=qe;return En(xi);})();
/**
* OverType - A lightweight markdown editor library with perfect WYSIWYG alignment
* @version 1.0.0
* @license MIT
*/
/**
* OverType Web Component
* A custom element wrapper for the OverType markdown editor with Shadow DOM isolation
* @version 1.0.0
* @license MIT
*/
+21 -3
View File
@@ -50,6 +50,7 @@ $selectedFormats = isset($_POST['formats']) && is_array($_POST['formats'])
: [];
$adminMode = ($_POST['admin_mode'] ?? '0') === '1';
$editMode = ($_POST['edit_mode'] ?? '0') === '1';
$hasSiteWeb = $siteWebId && in_array($siteWebId, $selectedFormats, true);
$hasVideo = $videoId && in_array($videoId, $selectedFormats, true);
@@ -70,6 +71,10 @@ $hxPost = $adminMode ? '/admin/fichiers-fragment.php' : '/partage/fichiers-fragm
?>
<div id="format-fichiers-block">
<input type="hidden" name="admin_mode" value="<?= $adminMode ? '1' : '0' ?>">
<input type="hidden" name="edit_mode" value="<?= $editMode ? '1' : '0' ?>">
<?php if ($editMode && ($_POST['_cover'] ?? null)): ?>
<input type="hidden" name="_cover" value="<?= htmlspecialchars($_POST['_cover']) ?>">
<?php endif; ?>
<!-- ═══════════════════ Format(s) ═══════════════════ -->
<fieldset>
@@ -81,7 +86,7 @@ $hxPost = $adminMode ? '/admin/fichiers-fragment.php' : '/partage/fichiers-fragm
hx-post="<?= htmlspecialchars($hxPost) ?>"
hx-target="#format-fichiers-block"
hx-trigger="change"
hx-include="this, [name='website_url'], [name='website_label'], [name='admin_mode']"
hx-include="this, [name='website_url'], [name='website_label'], [name='admin_mode'], [name='edit_mode'], [name='_cover']"
hx-swap="outerHTML">
<legend class="sr-only">Format(s) du TFE</legend>
<ul>
@@ -108,13 +113,26 @@ $hxPost = $adminMode ? '/admin/fichiers-fragment.php' : '/partage/fichiers-fragm
<!-- ── 1. Couverture (always) ── -->
<div>
<?php
$_cover = $_POST['_cover'] ?? null;
if ($editMode && $_cover): ?>
<div class="admin-banner-preview">
<img src="/media?path=<?= urlencode($_cover) ?>"
alt="Couverture actuelle" style="max-height:180px;">
<label class="admin-checkbox-label">
<input type="checkbox" name="remove_cover" value="1"> Supprimer la couverture
</label>
</div>
<?php endif;
$name = 'couverture';
$label = 'Image de couverture (optionnel) :';
$accept = 'image/jpeg,image/png,image/webp';
$hint = 'JPG, PNG ou WEBP. Format 4:3 recommandé. Max 20 MB.';
$hint = ($editMode && $_cover)
? 'Laisser vide pour conserver la couverture actuelle. JPG, PNG ou WEBP. Max 20 MB.'
: 'JPG, PNG ou WEBP. Format 4:3 recommandé. Max 20 MB.';
$required = false;
$id = 'couverture';
include APP_ROOT . '/templates/partials/form/file-field.php';
unset($_cover);
?>
</div>
@@ -162,7 +180,7 @@ $hxPost = $adminMode ? '/admin/fichiers-fragment.php' : '/partage/fichiers-fragm
hx-post="<?= htmlspecialchars($hxPost) ?>"
hx-target="#format-fichiers-block"
hx-trigger="change"
hx-include="[name='formats[]'], [name='website_url'], [name='website_label'], [name='admin_mode'], [name='has_annexes']"
hx-include="[name='formats[]'], [name='website_url'], [name='website_label'], [name='admin_mode'], [name='edit_mode'], [name='_cover'], [name='has_annexes']"
hx-swap="outerHTML">
Ce TFE comporte des annexes
</label>
+9 -1
View File
@@ -42,6 +42,13 @@ if ($slug === 'fichiers-fragment' && $_SERVER['REQUEST_METHOD'] === 'POST') {
exit;
}
// Special route: /partage/licence-fragment (HTMX fragment — licence section with conditional required)
if ($slug === 'licence-fragment' && $_SERVER['REQUEST_METHOD'] === 'POST') {
App::boot();
require_once __DIR__ . '/licence-fragment.php';
exit;
}
// Special route: /partage/recapitulatif?id=N
if ($slug === 'recapitulatif' || $slug === 'recapitulatif.php') {
App::boot();
@@ -267,7 +274,7 @@ function renderShareLinkForm(string $slug, array $link): void
// Load all form help blocks in one query.
$helpBlocks = Database::getInstance()->getAllFormHelpBlocks();
$helpFn = fn(string $key) => $helpBlocks[$key]['content'] ?? '';
$helpFn = fn(string $key) => empty($helpBlocks[$key]['enabled']) ? '' : ($helpBlocks[$key]['content'] ?? '');
// ── Shared form variables ──────────────────────────────────────────────
$mode = 'partage';
@@ -356,6 +363,7 @@ function renderShareLinkForm(string $slug, array $link): void
<?php if ($isVerified): ?>
<span class="share-badge">🔓 Accès partagé</span>
<?php endif; ?>
<p class="thesis-add-subtitle">Formulaire pour <a href="/">XAMXAM</a></p>
</div>
<?php include APP_ROOT . '/templates/partials/form/form.php'; ?>
+47
View File
@@ -0,0 +1,47 @@
<?php
/**
* HTMX fragment: renders the licence section with conditional required states.
*
* POST: access_type_id, license_id, license_custom, cc2r, admin_mode
*
* When access_type_id=1 (Libre): licence fields are required.
* When access_type_id=2|3 (Interne/Interdit): licence fields are optional.
*/
require_once __DIR__ . '/../../bootstrap.php';
$accessTypeId = $_POST['access_type_id'] ?? '2';
$licenseId = $_POST['license_id'] ?? '';
$licenseCustom = $_POST['license_custom'] ?? '';
$cc2r = !empty($_POST['cc2r']);
$adminMode = ($_POST['admin_mode'] ?? '0') === '1';
$required = !$adminMode && $accessTypeId === '1';
require_once APP_ROOT . '/src/Database.php';
$db = Database::getInstance();
$licenseTypes = $db->getAllLicenseTypes();
?>
<div class="licence-license-choice">
<?php
$name = 'license_id'; $label = 'Licence :'; $options = $licenseTypes;
$selected = $licenseId; $placeholder = '— Sélectionner —';
include APP_ROOT . '/templates/partials/form/select-field.php';
?>
<?php
$name = 'license_custom'; $label = 'Ou précisez une autre licence :';
$value = htmlspecialchars($licenseCustom);
$hint = 'Ex: CC BY-NC 4.0, Tous droits réservés...';
include APP_ROOT . '/templates/partials/form/text-field.php';
?>
<div class="admin-form-group">
<label class="admin-checkbox-label">
<input type="checkbox" name="cc2r" value="1"
<?= $cc2r ? 'checked' : '' ?>>
J'accepte les Conditions Collectives de Réutilisation (CC2r)
</label>
<small><a href="https://cc2r.net/" target="_blank" rel="noopener">En savoir plus sur la CC2r ↗</a></small>
</div>
</div>