After #166 a repeated `[^a]` is one footnote (reuse): one number, one definition, N forward links. But the definition's ↩ only returned to the FIRST reference. Now a definition with N references shows ↩ a b c …, each backlink scrolling to its own occurrence (Pandoc/Wikipedia convention); a single-reference footnote keeps the plain ↩ unchanged. - editor-ext: `computeFootnoteRefCounts(doc)` (id -> occurrence count) cached alongside the number map in the numbering plugin state; `getFootnoteRefCount` getter (O(1), no per-render doc walk). `scrollToReference(id, index?)` picks the index-th `sup[data-footnote-ref][data-id]` occurrence (document order), falling back to the first. - client: FootnoteDefinitionView renders one lettered link (a, b, c, … aa …) per occurrence when refCount > 1; the chrome stays after the contentDOM so the #146 caret invariant holds. i18n keys (ru) added. Tests: computeFootnoteRefCounts + getFootnoteRefCount (reuse counts, unknown id => 0); structure test gains 3 cases (N lettered links render, click jumps to the n-th occorrence, single ref => one ↩). NOTE: the visual layout of the backlink row needs a real browser to verify (jsdom can't); the structural and behavioral contract is covered headless. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
133 lines
3.2 KiB
CSS
133 lines
3.2 KiB
CSS
/* Superscript reference marker. The visible number comes from the numbering
|
|
plugin decoration which sets the --footnote-number CSS variable. */
|
|
.reference {
|
|
cursor: pointer;
|
|
color: var(--mantine-color-blue-6);
|
|
font-weight: 500;
|
|
vertical-align: super;
|
|
font-size: 0.75em;
|
|
line-height: 0;
|
|
user-select: none;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.reference::after {
|
|
content: var(--footnote-number, "");
|
|
}
|
|
|
|
.reference:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.reference.selected {
|
|
background-color: var(--mantine-color-blue-1);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
/* Read-only popover shown on hover/click of a reference. */
|
|
.popover {
|
|
position: absolute;
|
|
z-index: 1000;
|
|
max-width: 360px;
|
|
padding: var(--mantine-spacing-sm);
|
|
background: var(--mantine-color-body);
|
|
color: var(--mantine-color-default-color);
|
|
border: 1px solid var(--mantine-color-default-border);
|
|
border-radius: var(--mantine-radius-md);
|
|
box-shadow: var(--mantine-shadow-md);
|
|
font-size: var(--mantine-font-size-sm);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.popoverHeader {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--mantine-spacing-xs);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.popoverNumber {
|
|
font-weight: 600;
|
|
color: var(--mantine-color-dimmed);
|
|
}
|
|
|
|
.popoverBody {
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
|
|
/* Bottom footnotes container. Flex column so the heading (rendered AFTER the
|
|
editable NodeViewContent in the DOM for #146) is lifted back above the list
|
|
visually via `order`, instead of sitting in-flow before the contentDOM. */
|
|
.list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
margin-top: var(--mantine-spacing-lg);
|
|
padding-top: var(--mantine-spacing-md);
|
|
border-top: 1px solid var(--mantine-color-default-border);
|
|
}
|
|
|
|
.listHeading {
|
|
order: -1; /* visually above the list, though it follows it in the DOM (#146) */
|
|
font-weight: 600;
|
|
font-size: var(--mantine-font-size-sm);
|
|
color: var(--mantine-color-dimmed);
|
|
margin-bottom: var(--mantine-spacing-xs);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.03em;
|
|
}
|
|
|
|
.definition {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
/* Tight number→text spacing (~one space) so it reads like "1. text"
|
|
instead of leaving a wide gap after the period. */
|
|
gap: 0.4em;
|
|
padding: 2px 0;
|
|
}
|
|
|
|
.definitionMarker {
|
|
order: -1; /* keep the "N." marker on the LEFT though it follows content in DOM (#146) */
|
|
flex: 0 0 auto;
|
|
min-width: 1.5em;
|
|
/* Right-align within the narrow column so the period sits next to the text
|
|
and multi-digit numbers (10, 11, …) stay aligned on their right edge. */
|
|
text-align: right;
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--mantine-color-dimmed);
|
|
user-select: none;
|
|
}
|
|
|
|
.definitionContent {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.backLink {
|
|
flex: 0 0 auto;
|
|
cursor: pointer;
|
|
color: var(--mantine-color-blue-6);
|
|
user-select: none;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.backLink:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* Multi-backlink row (#168): ↩ a b c — one lettered link per reference
|
|
occurrence. Sits on the right, after the content, like the single ↩. */
|
|
.backLinks {
|
|
flex: 0 0 auto;
|
|
display: inline-flex;
|
|
align-items: baseline;
|
|
gap: 0.3em;
|
|
user-select: none;
|
|
}
|
|
|
|
.backLinkArrow {
|
|
color: var(--mantine-color-dimmed);
|
|
font-size: 0.9em;
|
|
}
|