Skip to content

Commit

Permalink
fix #1451: indicate current TOC section for UserCSS
Browse files Browse the repository at this point in the history
  • Loading branch information
tophf committed Jan 15, 2025
1 parent acade5d commit c303807
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/edit/codemirror-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const cmFactory = {
/**
* @param {HTMLElement | ((host: HTMLElement) => void)} place
* @param {CodeMirror.EditorConfiguration} [options]
* @return {CodeMirror.Editor}
* @return {CodeMirror.Editor & {doc: CodeMirror.Doc}}
*/
create(place, options) {
const cm = CodeMirror(place, options);
Expand Down
5 changes: 4 additions & 1 deletion src/edit/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const dirty = DirtyReporter();
/** @type {Set<HTMLInputElement>} */
const regexps = new Set();
const toc = [];
toc.cls = 'current';

let style;
let wasDirty = false;
Expand Down Expand Up @@ -37,6 +38,7 @@ const editor = self.editor = {
set style(val) {
style = val;
},
toc,

applyScrollInfo(cm, si = editor.scrollInfo.cms?.[0]) {
if (si && si.sel) {
Expand Down Expand Up @@ -174,7 +176,8 @@ const editor = self.editor = {
toc.length--;
}
if (added.focus) {
const cls = 'current';
toc.i = first;
const cls = toc.cls;
const old = toc.el.$('.' + cls);
const el = elFirst || toc.el.children[first];
if (old && old !== el) old.classList.remove(cls);
Expand Down
3 changes: 2 additions & 1 deletion src/edit/moz-section-finder.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ export default function MozSectionFinder(cm) {
}
if (op) {
sections.splice(cutAt, cutTo - cutAt, ...added);
listeners.forEach(fn => fn(added, removed, cutAt, cutTo));
for (const fn of listeners)
fn.call(cm, added, removed, cutAt, cutTo);
}
if (op === true) {
cm.endOperation();
Expand Down
56 changes: 48 additions & 8 deletions src/edit/source-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,21 @@ export default function SourceEditor() {
`.replace(/^\s+/gm, '');
let savedGeneration;
let prevMode = NaN;
let prevSel;
/** @type {MozSectionFinder} */
let sectionFinder;
let sectionWidget;
/** @type {MozSection[]} */
let mozSections;
let updateTocFocusPending;

$$remove('.sectioned-only');
$id('header').on('wheel', headerOnScroll);
$id('sections').textContent = '';
$id('sections').appendChild($create('.single-editor'));
$id('save-button').on('split-btn', saveTemplate);

const cmpPos = CodeMirror.cmpPos;
const cm = cmFactory.create($('.single-editor'), {
value: style.id ? style.sourceCode : setupNewStyle(editor.template),
finishInit(me) {
Expand All @@ -46,16 +51,17 @@ export default function SourceEditor() {
editor.viewTo = si.viewTo;
sectionFinder = MozSectionFinder(me);
sectionWidget = MozSectionWidget(me, sectionFinder);
editor.sections = sectionFinder.sections;
mozSections = editor.sections = sectionFinder.sections;
prevSel = me.doc.sel;
prefs.subscribe([kToc, kWidget], (k, val) => {
sectionFinder.onOff(editor.updateToc, prefs.__values[kToc] || prefs.__values[kWidget]);
sectionFinder.onOff(updateToc, prefs.__values[kToc] || prefs.__values[kWidget]);
if (k === kWidget) sectionWidget.toggle(val);
if (k === kToc) me[val ? 'on' : 'off']('cursorActivity', onCursorActivity);
}, true);
Object.assign(me.curOp, si.scroll);
editor.viewTo = 0;
},
});
const cmpPos = CodeMirror.cmpPos;
const metaCompiler = createMetaCompiler(meta => {
const {vars} = style[UCD] || {};
if (vars) {
Expand Down Expand Up @@ -294,16 +300,15 @@ export default function SourceEditor() {
// ensure the data is ready in case the user wants to jump around a lot in a large style
sectionFinder.keepAliveFor(nextPrevSection, 10e3);
sectionFinder.updatePositions();
const {sections} = sectionFinder;
const num = sections.length;
const num = mozSections.length;
if (!num) return;
dir = dir < 0 ? -1 : 0;
const pos = cm.getCursor();
let i = sections.findIndex(sec => CodeMirror.cmpPos(sec.start, pos) > Math.min(dir, 0));
if (i < 0 && (!dir || CodeMirror.cmpPos(sections[num - 1].start, pos) < 0)) {
let i = mozSections.findIndex(sec => CodeMirror.cmpPos(sec.start, pos) > Math.min(dir, 0));
if (i < 0 && (!dir || CodeMirror.cmpPos(mozSections[num - 1].start, pos) < 0)) {
i = 0;
}
cm.jumpToPos(sections[(i + dir + num) % num].start);
cm.jumpToPos(mozSections[(i + dir + num) % num].start);
}

function headerOnScroll({target, deltaY, deltaMode, shiftKey}) {
Expand Down Expand Up @@ -402,4 +407,39 @@ export default function SourceEditor() {
return prevRes;
}
}

function onCursorActivity() {
if (prevSel !== cm.doc.sel) {
prevSel = cm.doc.sel;
updateTocFocusPending ??= Promise.resolve().then(updateTocFocus);
}
}

function updateToc(...args) {
editor.updateToc(...args);
updateTocFocus();
}

function updateTocFocus() {
updateTocFocusPending = null;
const pos = prevSel.ranges[0].head;
const toc = editor.toc;
let end = mozSections.length;
let a = 0;
let b = end--;
let c = pos.line && Math.min(toc.i ?? (a + b) >> 1, end);
let c0, sec;
while (a < b && c0 !== c) {
sec = mozSections[c];
if (cmpPos(sec.start, pos) > 0)
b = c;
else if (c < end && cmpPos(mozSections[c + 1].start, pos) <= 0)
a = c;
else
return c !== toc.i && editor.updateToc({focus: true, 0: sec});
c0 = c;
c = (a + b) >> 1;
}
toc.el.$('.' + toc.cls)?.classList.remove(toc.cls);
}
}

0 comments on commit c303807

Please sign in to comment.