3418 lines
		
	
	
		
			119 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			3418 lines
		
	
	
		
			119 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
var obsidian = require('obsidian');
 | 
						|
var view = require('@codemirror/view');
 | 
						|
var language = require('@codemirror/language');
 | 
						|
var state = require('@codemirror/state');
 | 
						|
 | 
						|
/******************************************************************************
 | 
						|
Copyright (c) Microsoft Corporation.
 | 
						|
 | 
						|
Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
purpose with or without fee is hereby granted.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 | 
						|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 | 
						|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
 | 
						|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 | 
						|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 | 
						|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
						|
PERFORMANCE OF THIS SOFTWARE.
 | 
						|
***************************************************************************** */
 | 
						|
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
 | 
						|
 | 
						|
 | 
						|
function __awaiter(thisArg, _arguments, P, generator) {
 | 
						|
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
 | 
						|
    return new (P || (P = Promise))(function (resolve, reject) {
 | 
						|
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
 | 
						|
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
 | 
						|
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
 | 
						|
        step((generator = generator.apply(thisArg, _arguments || [])).next());
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
 | 
						|
    var e = new Error(message);
 | 
						|
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
 | 
						|
};
 | 
						|
 | 
						|
class MoveCursorToPreviousUnfoldedLine {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const list = this.root.getListUnderCursor();
 | 
						|
        const cursor = this.root.getCursor();
 | 
						|
        const lines = list.getLinesInfo();
 | 
						|
        const lineNo = lines.findIndex((l) => {
 | 
						|
            return (cursor.ch === l.from.ch + list.getCheckboxLength() &&
 | 
						|
                cursor.line === l.from.line);
 | 
						|
        });
 | 
						|
        if (lineNo === 0) {
 | 
						|
            this.moveCursorToPreviousUnfoldedItem(root, cursor);
 | 
						|
        }
 | 
						|
        else if (lineNo > 0) {
 | 
						|
            this.moveCursorToPreviousNoteLine(root, lines, lineNo);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    moveCursorToPreviousNoteLine(root, lines, lineNo) {
 | 
						|
        this.stopPropagation = true;
 | 
						|
        this.updated = true;
 | 
						|
        root.replaceCursor(lines[lineNo - 1].to);
 | 
						|
    }
 | 
						|
    moveCursorToPreviousUnfoldedItem(root, cursor) {
 | 
						|
        const prev = root.getListUnderLine(cursor.line - 1);
 | 
						|
        if (!prev) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        this.updated = true;
 | 
						|
        if (prev.isFolded()) {
 | 
						|
            const foldRoot = prev.getTopFoldRoot();
 | 
						|
            const firstLineEnd = foldRoot.getLinesInfo()[0].to;
 | 
						|
            root.replaceCursor(firstLineEnd);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            root.replaceCursor(prev.getLastLineContentEnd());
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function getEditorFromState(state) {
 | 
						|
    const { editor } = state.field(obsidian.editorInfoField);
 | 
						|
    if (!editor) {
 | 
						|
        return null;
 | 
						|
    }
 | 
						|
    return new MyEditor(editor);
 | 
						|
}
 | 
						|
function foldInside(view, from, to) {
 | 
						|
    let found = null;
 | 
						|
    language.foldedRanges(view.state).between(from, to, (from, to) => {
 | 
						|
        if (!found || found.from > from)
 | 
						|
            found = { from, to };
 | 
						|
    });
 | 
						|
    return found;
 | 
						|
}
 | 
						|
class MyEditor {
 | 
						|
    constructor(e) {
 | 
						|
        this.e = e;
 | 
						|
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
						|
        this.view = this.e.cm;
 | 
						|
    }
 | 
						|
    getCursor() {
 | 
						|
        return this.e.getCursor();
 | 
						|
    }
 | 
						|
    getLine(n) {
 | 
						|
        return this.e.getLine(n);
 | 
						|
    }
 | 
						|
    lastLine() {
 | 
						|
        return this.e.lastLine();
 | 
						|
    }
 | 
						|
    listSelections() {
 | 
						|
        return this.e.listSelections();
 | 
						|
    }
 | 
						|
    getRange(from, to) {
 | 
						|
        return this.e.getRange(from, to);
 | 
						|
    }
 | 
						|
    replaceRange(replacement, from, to) {
 | 
						|
        return this.e.replaceRange(replacement, from, to);
 | 
						|
    }
 | 
						|
    setSelections(selections) {
 | 
						|
        this.e.setSelections(selections);
 | 
						|
    }
 | 
						|
    setValue(text) {
 | 
						|
        this.e.setValue(text);
 | 
						|
    }
 | 
						|
    getValue() {
 | 
						|
        return this.e.getValue();
 | 
						|
    }
 | 
						|
    offsetToPos(offset) {
 | 
						|
        return this.e.offsetToPos(offset);
 | 
						|
    }
 | 
						|
    posToOffset(pos) {
 | 
						|
        return this.e.posToOffset(pos);
 | 
						|
    }
 | 
						|
    fold(n) {
 | 
						|
        const { view } = this;
 | 
						|
        const l = view.lineBlockAt(view.state.doc.line(n + 1).from);
 | 
						|
        const range = language.foldable(view.state, l.from, l.to);
 | 
						|
        if (!range || range.from === range.to) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        view.dispatch({ effects: [language.foldEffect.of(range)] });
 | 
						|
    }
 | 
						|
    unfold(n) {
 | 
						|
        const { view } = this;
 | 
						|
        const l = view.lineBlockAt(view.state.doc.line(n + 1).from);
 | 
						|
        const range = foldInside(view, l.from, l.to);
 | 
						|
        if (!range) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        view.dispatch({ effects: [language.unfoldEffect.of(range)] });
 | 
						|
    }
 | 
						|
    getAllFoldedLines() {
 | 
						|
        const c = language.foldedRanges(this.view.state).iter();
 | 
						|
        const res = [];
 | 
						|
        while (c.value) {
 | 
						|
            res.push(this.offsetToPos(c.from).line);
 | 
						|
            c.next();
 | 
						|
        }
 | 
						|
        return res;
 | 
						|
    }
 | 
						|
    triggerOnKeyDown(e) {
 | 
						|
        view.runScopeHandlers(this.view, e, "editor");
 | 
						|
    }
 | 
						|
    getZoomRange() {
 | 
						|
        if (!window.ObsidianZoomPlugin) {
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
        return window.ObsidianZoomPlugin.getZoomRange(this.e);
 | 
						|
    }
 | 
						|
    zoomOut() {
 | 
						|
        if (!window.ObsidianZoomPlugin) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        window.ObsidianZoomPlugin.zoomOut(this.e);
 | 
						|
    }
 | 
						|
    zoomIn(line) {
 | 
						|
        if (!window.ObsidianZoomPlugin) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        window.ObsidianZoomPlugin.zoomIn(this.e, line);
 | 
						|
    }
 | 
						|
    tryRefreshZoom(line) {
 | 
						|
        if (!window.ObsidianZoomPlugin) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        if (window.ObsidianZoomPlugin.refreshZoom) {
 | 
						|
            window.ObsidianZoomPlugin.refreshZoom(this.e);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            window.ObsidianZoomPlugin.zoomIn(this.e, line);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function createKeymapRunCallback(config) {
 | 
						|
    const check = config.check || (() => true);
 | 
						|
    const { run } = config;
 | 
						|
    return (view) => {
 | 
						|
        const editor = getEditorFromState(view.state);
 | 
						|
        if (!check(editor)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        const { shouldUpdate, shouldStopPropagation } = run(editor);
 | 
						|
        return shouldUpdate || shouldStopPropagation;
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
class ArrowLeftAndCtrlArrowLeftBehaviourOverride {
 | 
						|
    constructor(plugin, settings, imeDetector, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.imeDetector = imeDetector;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.check = () => {
 | 
						|
            return (this.settings.keepCursorWithinContent !== "never" &&
 | 
						|
                !this.imeDetector.isOpened());
 | 
						|
        };
 | 
						|
        this.run = (editor) => {
 | 
						|
            return this.operationPerformer.perform((root) => new MoveCursorToPreviousUnfoldedLine(root), editor);
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(view.keymap.of([
 | 
						|
                {
 | 
						|
                    key: "ArrowLeft",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
                {
 | 
						|
                    win: "c-ArrowLeft",
 | 
						|
                    linux: "c-ArrowLeft",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
            ]));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function cmpPos(a, b) {
 | 
						|
    return a.line - b.line || a.ch - b.ch;
 | 
						|
}
 | 
						|
function maxPos(a, b) {
 | 
						|
    return cmpPos(a, b) < 0 ? b : a;
 | 
						|
}
 | 
						|
function minPos(a, b) {
 | 
						|
    return cmpPos(a, b) < 0 ? a : b;
 | 
						|
}
 | 
						|
function isRangesIntersects(a, b) {
 | 
						|
    return cmpPos(a[1], b[0]) >= 0 && cmpPos(a[0], b[1]) <= 0;
 | 
						|
}
 | 
						|
function recalculateNumericBullets(root) {
 | 
						|
    function visit(parent) {
 | 
						|
        let index = 1;
 | 
						|
        for (const child of parent.getChildren()) {
 | 
						|
            if (/\d+\./.test(child.getBullet())) {
 | 
						|
                child.replateBullet(`${index++}.`);
 | 
						|
            }
 | 
						|
            visit(child);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    visit(root);
 | 
						|
}
 | 
						|
let idSeq = 0;
 | 
						|
class List {
 | 
						|
    constructor(root, indent, bullet, optionalCheckbox, spaceAfterBullet, firstLine, foldRoot) {
 | 
						|
        this.root = root;
 | 
						|
        this.indent = indent;
 | 
						|
        this.bullet = bullet;
 | 
						|
        this.optionalCheckbox = optionalCheckbox;
 | 
						|
        this.spaceAfterBullet = spaceAfterBullet;
 | 
						|
        this.foldRoot = foldRoot;
 | 
						|
        this.parent = null;
 | 
						|
        this.children = [];
 | 
						|
        this.notesIndent = null;
 | 
						|
        this.lines = [];
 | 
						|
        this.id = idSeq++;
 | 
						|
        this.lines.push(firstLine);
 | 
						|
    }
 | 
						|
    getID() {
 | 
						|
        return this.id;
 | 
						|
    }
 | 
						|
    getNotesIndent() {
 | 
						|
        return this.notesIndent;
 | 
						|
    }
 | 
						|
    setNotesIndent(notesIndent) {
 | 
						|
        if (this.notesIndent !== null) {
 | 
						|
            throw new Error(`Notes indent already provided`);
 | 
						|
        }
 | 
						|
        this.notesIndent = notesIndent;
 | 
						|
    }
 | 
						|
    addLine(text) {
 | 
						|
        if (this.notesIndent === null) {
 | 
						|
            throw new Error(`Unable to add line, notes indent should be provided first`);
 | 
						|
        }
 | 
						|
        this.lines.push(text);
 | 
						|
    }
 | 
						|
    replaceLines(lines) {
 | 
						|
        if (lines.length > 1 && this.notesIndent === null) {
 | 
						|
            throw new Error(`Unable to add line, notes indent should be provided first`);
 | 
						|
        }
 | 
						|
        this.lines = lines;
 | 
						|
    }
 | 
						|
    getLineCount() {
 | 
						|
        return this.lines.length;
 | 
						|
    }
 | 
						|
    getRoot() {
 | 
						|
        return this.root;
 | 
						|
    }
 | 
						|
    getChildren() {
 | 
						|
        return this.children.concat();
 | 
						|
    }
 | 
						|
    getLinesInfo() {
 | 
						|
        const startLine = this.root.getContentLinesRangeOf(this)[0];
 | 
						|
        return this.lines.map((row, i) => {
 | 
						|
            const line = startLine + i;
 | 
						|
            const startCh = i === 0 ? this.getContentStartCh() : this.notesIndent.length;
 | 
						|
            const endCh = startCh + row.length;
 | 
						|
            return {
 | 
						|
                text: row,
 | 
						|
                from: { line, ch: startCh },
 | 
						|
                to: { line, ch: endCh },
 | 
						|
            };
 | 
						|
        });
 | 
						|
    }
 | 
						|
    getLines() {
 | 
						|
        return this.lines.concat();
 | 
						|
    }
 | 
						|
    getFirstLineContentStart() {
 | 
						|
        const startLine = this.root.getContentLinesRangeOf(this)[0];
 | 
						|
        return {
 | 
						|
            line: startLine,
 | 
						|
            ch: this.getContentStartCh(),
 | 
						|
        };
 | 
						|
    }
 | 
						|
    getFirstLineContentStartAfterCheckbox() {
 | 
						|
        const startLine = this.root.getContentLinesRangeOf(this)[0];
 | 
						|
        return {
 | 
						|
            line: startLine,
 | 
						|
            ch: this.getContentStartCh() + this.getCheckboxLength(),
 | 
						|
        };
 | 
						|
    }
 | 
						|
    getLastLineContentEnd() {
 | 
						|
        const endLine = this.root.getContentLinesRangeOf(this)[1];
 | 
						|
        const endCh = this.lines.length === 1
 | 
						|
            ? this.getContentStartCh() + this.lines[0].length
 | 
						|
            : this.notesIndent.length + this.lines[this.lines.length - 1].length;
 | 
						|
        return {
 | 
						|
            line: endLine,
 | 
						|
            ch: endCh,
 | 
						|
        };
 | 
						|
    }
 | 
						|
    getContentEndIncludingChildren() {
 | 
						|
        return this.getLastChild().getLastLineContentEnd();
 | 
						|
    }
 | 
						|
    getLastChild() {
 | 
						|
        let lastChild = this;
 | 
						|
        while (!lastChild.isEmpty()) {
 | 
						|
            lastChild = lastChild.getChildren().last();
 | 
						|
        }
 | 
						|
        return lastChild;
 | 
						|
    }
 | 
						|
    getContentStartCh() {
 | 
						|
        return this.indent.length + this.bullet.length + 1;
 | 
						|
    }
 | 
						|
    isFolded() {
 | 
						|
        if (this.foldRoot) {
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        if (this.parent) {
 | 
						|
            return this.parent.isFolded();
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    isFoldRoot() {
 | 
						|
        return this.foldRoot;
 | 
						|
    }
 | 
						|
    getTopFoldRoot() {
 | 
						|
        let tmp = this;
 | 
						|
        let foldRoot = null;
 | 
						|
        while (tmp) {
 | 
						|
            if (tmp.isFoldRoot()) {
 | 
						|
                foldRoot = tmp;
 | 
						|
            }
 | 
						|
            tmp = tmp.parent;
 | 
						|
        }
 | 
						|
        return foldRoot;
 | 
						|
    }
 | 
						|
    getLevel() {
 | 
						|
        if (!this.parent) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
        return this.parent.getLevel() + 1;
 | 
						|
    }
 | 
						|
    unindentContent(from, till) {
 | 
						|
        this.indent = this.indent.slice(0, from) + this.indent.slice(till);
 | 
						|
        if (this.notesIndent !== null) {
 | 
						|
            this.notesIndent =
 | 
						|
                this.notesIndent.slice(0, from) + this.notesIndent.slice(till);
 | 
						|
        }
 | 
						|
        for (const child of this.children) {
 | 
						|
            child.unindentContent(from, till);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    indentContent(indentPos, indentChars) {
 | 
						|
        this.indent =
 | 
						|
            this.indent.slice(0, indentPos) +
 | 
						|
                indentChars +
 | 
						|
                this.indent.slice(indentPos);
 | 
						|
        if (this.notesIndent !== null) {
 | 
						|
            this.notesIndent =
 | 
						|
                this.notesIndent.slice(0, indentPos) +
 | 
						|
                    indentChars +
 | 
						|
                    this.notesIndent.slice(indentPos);
 | 
						|
        }
 | 
						|
        for (const child of this.children) {
 | 
						|
            child.indentContent(indentPos, indentChars);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    getFirstLineIndent() {
 | 
						|
        return this.indent;
 | 
						|
    }
 | 
						|
    getBullet() {
 | 
						|
        return this.bullet;
 | 
						|
    }
 | 
						|
    getSpaceAfterBullet() {
 | 
						|
        return this.spaceAfterBullet;
 | 
						|
    }
 | 
						|
    getCheckboxLength() {
 | 
						|
        return this.optionalCheckbox.length;
 | 
						|
    }
 | 
						|
    replateBullet(bullet) {
 | 
						|
        this.bullet = bullet;
 | 
						|
    }
 | 
						|
    getParent() {
 | 
						|
        return this.parent;
 | 
						|
    }
 | 
						|
    addBeforeAll(list) {
 | 
						|
        this.children.unshift(list);
 | 
						|
        list.parent = this;
 | 
						|
    }
 | 
						|
    addAfterAll(list) {
 | 
						|
        this.children.push(list);
 | 
						|
        list.parent = this;
 | 
						|
    }
 | 
						|
    removeChild(list) {
 | 
						|
        const i = this.children.indexOf(list);
 | 
						|
        this.children.splice(i, 1);
 | 
						|
        list.parent = null;
 | 
						|
    }
 | 
						|
    addBefore(before, list) {
 | 
						|
        const i = this.children.indexOf(before);
 | 
						|
        this.children.splice(i, 0, list);
 | 
						|
        list.parent = this;
 | 
						|
    }
 | 
						|
    addAfter(before, list) {
 | 
						|
        const i = this.children.indexOf(before);
 | 
						|
        this.children.splice(i + 1, 0, list);
 | 
						|
        list.parent = this;
 | 
						|
    }
 | 
						|
    getPrevSiblingOf(list) {
 | 
						|
        const i = this.children.indexOf(list);
 | 
						|
        return i > 0 ? this.children[i - 1] : null;
 | 
						|
    }
 | 
						|
    getNextSiblingOf(list) {
 | 
						|
        const i = this.children.indexOf(list);
 | 
						|
        return i >= 0 && i < this.children.length ? this.children[i + 1] : null;
 | 
						|
    }
 | 
						|
    isEmpty() {
 | 
						|
        return this.children.length === 0;
 | 
						|
    }
 | 
						|
    print() {
 | 
						|
        let res = "";
 | 
						|
        for (let i = 0; i < this.lines.length; i++) {
 | 
						|
            res +=
 | 
						|
                i === 0
 | 
						|
                    ? this.indent + this.bullet + this.spaceAfterBullet
 | 
						|
                    : this.notesIndent;
 | 
						|
            res += this.lines[i];
 | 
						|
            res += "\n";
 | 
						|
        }
 | 
						|
        for (const child of this.children) {
 | 
						|
            res += child.print();
 | 
						|
        }
 | 
						|
        return res;
 | 
						|
    }
 | 
						|
    clone(newRoot) {
 | 
						|
        const clone = new List(newRoot, this.indent, this.bullet, this.optionalCheckbox, this.spaceAfterBullet, "", this.foldRoot);
 | 
						|
        clone.id = this.id;
 | 
						|
        clone.lines = this.lines.concat();
 | 
						|
        clone.notesIndent = this.notesIndent;
 | 
						|
        for (const child of this.children) {
 | 
						|
            clone.addAfterAll(child.clone(newRoot));
 | 
						|
        }
 | 
						|
        return clone;
 | 
						|
    }
 | 
						|
}
 | 
						|
class Root {
 | 
						|
    constructor(start, end, selections) {
 | 
						|
        this.start = start;
 | 
						|
        this.end = end;
 | 
						|
        this.rootList = new List(this, "", "", "", "", "", false);
 | 
						|
        this.selections = [];
 | 
						|
        this.replaceSelections(selections);
 | 
						|
    }
 | 
						|
    getRootList() {
 | 
						|
        return this.rootList;
 | 
						|
    }
 | 
						|
    getContentRange() {
 | 
						|
        return [this.getContentStart(), this.getContentEnd()];
 | 
						|
    }
 | 
						|
    getContentStart() {
 | 
						|
        return Object.assign({}, this.start);
 | 
						|
    }
 | 
						|
    getContentEnd() {
 | 
						|
        return Object.assign({}, this.end);
 | 
						|
    }
 | 
						|
    getSelections() {
 | 
						|
        return this.selections.map((s) => ({
 | 
						|
            anchor: Object.assign({}, s.anchor),
 | 
						|
            head: Object.assign({}, s.head),
 | 
						|
        }));
 | 
						|
    }
 | 
						|
    hasSingleCursor() {
 | 
						|
        if (!this.hasSingleSelection()) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        const selection = this.selections[0];
 | 
						|
        return (selection.anchor.line === selection.head.line &&
 | 
						|
            selection.anchor.ch === selection.head.ch);
 | 
						|
    }
 | 
						|
    hasSingleSelection() {
 | 
						|
        return this.selections.length === 1;
 | 
						|
    }
 | 
						|
    getSelection() {
 | 
						|
        const selection = this.selections[this.selections.length - 1];
 | 
						|
        const from = selection.anchor.ch > selection.head.ch
 | 
						|
            ? selection.head.ch
 | 
						|
            : selection.anchor.ch;
 | 
						|
        const to = selection.anchor.ch > selection.head.ch
 | 
						|
            ? selection.anchor.ch
 | 
						|
            : selection.head.ch;
 | 
						|
        return Object.assign(Object.assign({}, selection), { from,
 | 
						|
            to });
 | 
						|
    }
 | 
						|
    getCursor() {
 | 
						|
        return Object.assign({}, this.selections[this.selections.length - 1].head);
 | 
						|
    }
 | 
						|
    replaceCursor(cursor) {
 | 
						|
        this.selections = [{ anchor: cursor, head: cursor }];
 | 
						|
    }
 | 
						|
    replaceSelections(selections) {
 | 
						|
        if (selections.length < 1) {
 | 
						|
            throw new Error(`Unable to create Root without selections`);
 | 
						|
        }
 | 
						|
        this.selections = selections;
 | 
						|
    }
 | 
						|
    getListUnderCursor() {
 | 
						|
        return this.getListUnderLine(this.getCursor().line);
 | 
						|
    }
 | 
						|
    getListUnderLine(line) {
 | 
						|
        if (line < this.start.line || line > this.end.line) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        let result = null;
 | 
						|
        let index = this.start.line;
 | 
						|
        const visitArr = (ll) => {
 | 
						|
            for (const l of ll) {
 | 
						|
                const listFromLine = index;
 | 
						|
                const listTillLine = listFromLine + l.getLineCount() - 1;
 | 
						|
                if (line >= listFromLine && line <= listTillLine) {
 | 
						|
                    result = l;
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    index = listTillLine + 1;
 | 
						|
                    visitArr(l.getChildren());
 | 
						|
                }
 | 
						|
                if (result !== null) {
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        };
 | 
						|
        visitArr(this.rootList.getChildren());
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
    getContentLinesRangeOf(list) {
 | 
						|
        let result = null;
 | 
						|
        let line = this.start.line;
 | 
						|
        const visitArr = (ll) => {
 | 
						|
            for (const l of ll) {
 | 
						|
                const listFromLine = line;
 | 
						|
                const listTillLine = listFromLine + l.getLineCount() - 1;
 | 
						|
                if (l === list) {
 | 
						|
                    result = [listFromLine, listTillLine];
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    line = listTillLine + 1;
 | 
						|
                    visitArr(l.getChildren());
 | 
						|
                }
 | 
						|
                if (result !== null) {
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        };
 | 
						|
        visitArr(this.rootList.getChildren());
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
    getChildren() {
 | 
						|
        return this.rootList.getChildren();
 | 
						|
    }
 | 
						|
    print() {
 | 
						|
        let res = "";
 | 
						|
        for (const child of this.rootList.getChildren()) {
 | 
						|
            res += child.print();
 | 
						|
        }
 | 
						|
        return res.replace(/\n$/, "");
 | 
						|
    }
 | 
						|
    clone() {
 | 
						|
        const clone = new Root(Object.assign({}, this.start), Object.assign({}, this.end), this.getSelections());
 | 
						|
        clone.rootList = this.rootList.clone(clone);
 | 
						|
        return clone;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class DeleteTillPreviousLineContentEnd {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        const lines = list.getLinesInfo();
 | 
						|
        const lineNo = lines.findIndex((l) => cursor.ch === l.from.ch && cursor.line === l.from.line);
 | 
						|
        if (lineNo === 0) {
 | 
						|
            this.mergeWithPreviousItem(root, cursor, list);
 | 
						|
        }
 | 
						|
        else if (lineNo > 0) {
 | 
						|
            this.mergeNotes(root, cursor, list, lines, lineNo);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    mergeNotes(root, cursor, list, lines, lineNo) {
 | 
						|
        this.stopPropagation = true;
 | 
						|
        this.updated = true;
 | 
						|
        const prevLineNo = lineNo - 1;
 | 
						|
        root.replaceCursor({
 | 
						|
            line: cursor.line - 1,
 | 
						|
            ch: lines[prevLineNo].text.length + lines[prevLineNo].from.ch,
 | 
						|
        });
 | 
						|
        lines[prevLineNo].text += lines[lineNo].text;
 | 
						|
        lines.splice(lineNo, 1);
 | 
						|
        list.replaceLines(lines.map((l) => l.text));
 | 
						|
    }
 | 
						|
    mergeWithPreviousItem(root, cursor, list) {
 | 
						|
        if (root.getChildren()[0] === list && list.isEmpty()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        const prev = root.getListUnderLine(cursor.line - 1);
 | 
						|
        if (!prev) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const bothAreEmpty = prev.isEmpty() && list.isEmpty();
 | 
						|
        const prevIsEmptyAndSameLevel = prev.isEmpty() && !list.isEmpty() && prev.getLevel() === list.getLevel();
 | 
						|
        const listIsEmptyAndPrevIsParent = list.isEmpty() && prev.getLevel() === list.getLevel() - 1;
 | 
						|
        if (bothAreEmpty || prevIsEmptyAndSameLevel || listIsEmptyAndPrevIsParent) {
 | 
						|
            this.updated = true;
 | 
						|
            const parent = list.getParent();
 | 
						|
            const prevEnd = prev.getLastLineContentEnd();
 | 
						|
            if (!prev.getNotesIndent() && list.getNotesIndent()) {
 | 
						|
                prev.setNotesIndent(prev.getFirstLineIndent() +
 | 
						|
                    list.getNotesIndent().slice(list.getFirstLineIndent().length));
 | 
						|
            }
 | 
						|
            const oldLines = prev.getLines();
 | 
						|
            const newLines = list.getLines();
 | 
						|
            oldLines[oldLines.length - 1] += newLines[0];
 | 
						|
            const resultLines = oldLines.concat(newLines.slice(1));
 | 
						|
            prev.replaceLines(resultLines);
 | 
						|
            parent.removeChild(list);
 | 
						|
            for (const c of list.getChildren()) {
 | 
						|
                list.removeChild(c);
 | 
						|
                prev.addAfterAll(c);
 | 
						|
            }
 | 
						|
            root.replaceCursor(prevEnd);
 | 
						|
            recalculateNumericBullets(root);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class BackspaceBehaviourOverride {
 | 
						|
    constructor(plugin, settings, imeDetector, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.imeDetector = imeDetector;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.check = () => {
 | 
						|
            return (this.settings.keepCursorWithinContent !== "never" &&
 | 
						|
                !this.imeDetector.isOpened());
 | 
						|
        };
 | 
						|
        this.run = (editor) => {
 | 
						|
            return this.operationPerformer.perform((root) => new DeleteTillPreviousLineContentEnd(root), editor);
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(view.keymap.of([
 | 
						|
                {
 | 
						|
                    key: "Backspace",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
            ]));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const BETTER_LISTS_BODY_CLASS = "outliner-plugin-better-lists";
 | 
						|
class BetterListsStyles {
 | 
						|
    constructor(settings, obsidianSettings) {
 | 
						|
        this.settings = settings;
 | 
						|
        this.obsidianSettings = obsidianSettings;
 | 
						|
        this.updateBodyClass = () => {
 | 
						|
            const shouldExists = this.obsidianSettings.isDefaultThemeEnabled() &&
 | 
						|
                this.settings.betterListsStyles;
 | 
						|
            const exists = document.body.classList.contains(BETTER_LISTS_BODY_CLASS);
 | 
						|
            if (shouldExists && !exists) {
 | 
						|
                document.body.classList.add(BETTER_LISTS_BODY_CLASS);
 | 
						|
            }
 | 
						|
            if (!shouldExists && exists) {
 | 
						|
                document.body.classList.remove(BETTER_LISTS_BODY_CLASS);
 | 
						|
            }
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.updateBodyClass();
 | 
						|
            this.updateBodyClassInterval = window.setInterval(() => {
 | 
						|
                this.updateBodyClass();
 | 
						|
            }, 1000);
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            clearInterval(this.updateBodyClassInterval);
 | 
						|
            document.body.classList.remove(BETTER_LISTS_BODY_CLASS);
 | 
						|
        });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class SelectAllContent {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleSelection()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const selection = root.getSelections()[0];
 | 
						|
        const [rootStart, rootEnd] = root.getContentRange();
 | 
						|
        const selectionFrom = minPos(selection.anchor, selection.head);
 | 
						|
        const selectionTo = maxPos(selection.anchor, selection.head);
 | 
						|
        if (selectionFrom.line < rootStart.line ||
 | 
						|
            selectionTo.line > rootEnd.line) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        if (selectionFrom.line === rootStart.line &&
 | 
						|
            selectionFrom.ch === rootStart.ch &&
 | 
						|
            selectionTo.line === rootEnd.line &&
 | 
						|
            selectionTo.ch === rootEnd.ch) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const contentStart = list.getFirstLineContentStartAfterCheckbox();
 | 
						|
        const contentEnd = list.getLastLineContentEnd();
 | 
						|
        const listUnderSelectionFrom = root.getListUnderLine(selectionFrom.line);
 | 
						|
        const listStart = listUnderSelectionFrom.getFirstLineContentStartAfterCheckbox();
 | 
						|
        const listEnd = listUnderSelectionFrom.getContentEndIncludingChildren();
 | 
						|
        this.stopPropagation = true;
 | 
						|
        this.updated = true;
 | 
						|
        if (selectionFrom.line === contentStart.line &&
 | 
						|
            selectionFrom.ch === contentStart.ch &&
 | 
						|
            selectionTo.line === contentEnd.line &&
 | 
						|
            selectionTo.ch === contentEnd.ch) {
 | 
						|
            if (list.getChildren().length) {
 | 
						|
                // select sub lists
 | 
						|
                root.replaceSelections([
 | 
						|
                    { anchor: contentStart, head: list.getContentEndIncludingChildren() },
 | 
						|
                ]);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                // select whole list
 | 
						|
                root.replaceSelections([{ anchor: rootStart, head: rootEnd }]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else if (listStart.ch == selectionFrom.ch &&
 | 
						|
            listEnd.line == selectionTo.line &&
 | 
						|
            listEnd.ch == selectionTo.ch) {
 | 
						|
            // select whole list
 | 
						|
            root.replaceSelections([{ anchor: rootStart, head: rootEnd }]);
 | 
						|
        }
 | 
						|
        else if ((selectionFrom.line > contentStart.line ||
 | 
						|
            (selectionFrom.line == contentStart.line &&
 | 
						|
                selectionFrom.ch >= contentStart.ch)) &&
 | 
						|
            (selectionTo.line < contentEnd.line ||
 | 
						|
                (selectionTo.line == contentEnd.line &&
 | 
						|
                    selectionTo.ch <= contentEnd.ch))) {
 | 
						|
            // select whole line
 | 
						|
            root.replaceSelections([{ anchor: contentStart, head: contentEnd }]);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            this.stopPropagation = false;
 | 
						|
            this.updated = false;
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class CtrlAAndCmdABehaviourOverride {
 | 
						|
    constructor(plugin, settings, imeDetector, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.imeDetector = imeDetector;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.check = () => {
 | 
						|
            return (this.settings.overrideSelectAllBehaviour && !this.imeDetector.isOpened());
 | 
						|
        };
 | 
						|
        this.run = (editor) => {
 | 
						|
            return this.operationPerformer.perform((root) => new SelectAllContent(root), editor);
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(view.keymap.of([
 | 
						|
                {
 | 
						|
                    key: "c-a",
 | 
						|
                    mac: "m-a",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
            ]));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class DeleteTillNextLineContentStart {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.deleteTillPreviousLineContentEnd =
 | 
						|
            new DeleteTillPreviousLineContentEnd(root);
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.deleteTillPreviousLineContentEnd.shouldStopPropagation();
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.deleteTillPreviousLineContentEnd.shouldUpdate();
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        const lines = list.getLinesInfo();
 | 
						|
        const lineNo = lines.findIndex((l) => cursor.ch === l.to.ch && cursor.line === l.to.line);
 | 
						|
        if (lineNo === lines.length - 1) {
 | 
						|
            const nextLine = lines[lineNo].to.line + 1;
 | 
						|
            const nextList = root.getListUnderLine(nextLine);
 | 
						|
            if (!nextList) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            root.replaceCursor(nextList.getFirstLineContentStart());
 | 
						|
            this.deleteTillPreviousLineContentEnd.perform();
 | 
						|
        }
 | 
						|
        else if (lineNo >= 0) {
 | 
						|
            root.replaceCursor(lines[lineNo + 1].from);
 | 
						|
            this.deleteTillPreviousLineContentEnd.perform();
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class DeleteBehaviourOverride {
 | 
						|
    constructor(plugin, settings, imeDetector, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.imeDetector = imeDetector;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.check = () => {
 | 
						|
            return (this.settings.keepCursorWithinContent !== "never" &&
 | 
						|
                !this.imeDetector.isOpened());
 | 
						|
        };
 | 
						|
        this.run = (editor) => {
 | 
						|
            return this.operationPerformer.perform((root) => new DeleteTillNextLineContentStart(root), editor);
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(view.keymap.of([
 | 
						|
                {
 | 
						|
                    key: "Delete",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
            ]));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class MoveListToDifferentPosition {
 | 
						|
    constructor(root, listToMove, placeToMove, whereToMove, defaultIndentChars) {
 | 
						|
        this.root = root;
 | 
						|
        this.listToMove = listToMove;
 | 
						|
        this.placeToMove = placeToMove;
 | 
						|
        this.whereToMove = whereToMove;
 | 
						|
        this.defaultIndentChars = defaultIndentChars;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        if (this.listToMove === this.placeToMove) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        this.updated = true;
 | 
						|
        const cursorAnchor = this.calculateCursorAnchor();
 | 
						|
        this.moveList();
 | 
						|
        this.changeIndent();
 | 
						|
        this.restoreCursor(cursorAnchor);
 | 
						|
        recalculateNumericBullets(this.root);
 | 
						|
    }
 | 
						|
    calculateCursorAnchor() {
 | 
						|
        const cursorLine = this.root.getCursor().line;
 | 
						|
        const lines = [
 | 
						|
            this.listToMove.getFirstLineContentStart().line,
 | 
						|
            this.listToMove.getLastLineContentEnd().line,
 | 
						|
            this.placeToMove.getFirstLineContentStart().line,
 | 
						|
            this.placeToMove.getLastLineContentEnd().line,
 | 
						|
        ];
 | 
						|
        const listStartLine = Math.min(...lines);
 | 
						|
        const listEndLine = Math.max(...lines);
 | 
						|
        if (cursorLine < listStartLine || cursorLine > listEndLine) {
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
        const cursor = this.root.getCursor();
 | 
						|
        const cursorList = this.root.getListUnderLine(cursor.line);
 | 
						|
        const cursorListStart = cursorList.getFirstLineContentStart();
 | 
						|
        const lineDiff = cursor.line - cursorListStart.line;
 | 
						|
        const chDiff = cursor.ch - cursorListStart.ch;
 | 
						|
        return { cursorList, lineDiff, chDiff };
 | 
						|
    }
 | 
						|
    moveList() {
 | 
						|
        this.listToMove.getParent().removeChild(this.listToMove);
 | 
						|
        switch (this.whereToMove) {
 | 
						|
            case "before":
 | 
						|
                this.placeToMove
 | 
						|
                    .getParent()
 | 
						|
                    .addBefore(this.placeToMove, this.listToMove);
 | 
						|
                break;
 | 
						|
            case "after":
 | 
						|
                this.placeToMove
 | 
						|
                    .getParent()
 | 
						|
                    .addAfter(this.placeToMove, this.listToMove);
 | 
						|
                break;
 | 
						|
            case "inside":
 | 
						|
                this.placeToMove.addBeforeAll(this.listToMove);
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    changeIndent() {
 | 
						|
        const oldIndent = this.listToMove.getFirstLineIndent();
 | 
						|
        const newIndent = this.whereToMove === "inside"
 | 
						|
            ? this.placeToMove.getFirstLineIndent() + this.defaultIndentChars
 | 
						|
            : this.placeToMove.getFirstLineIndent();
 | 
						|
        this.listToMove.unindentContent(0, oldIndent.length);
 | 
						|
        this.listToMove.indentContent(0, newIndent);
 | 
						|
    }
 | 
						|
    restoreCursor(cursorAnchor) {
 | 
						|
        if (cursorAnchor) {
 | 
						|
            const cursorListStart = cursorAnchor.cursorList.getFirstLineContentStart();
 | 
						|
            this.root.replaceCursor({
 | 
						|
                line: cursorListStart.line + cursorAnchor.lineDiff,
 | 
						|
                ch: cursorListStart.ch + cursorAnchor.chDiff,
 | 
						|
            });
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            // When you move a list, the screen scrolls to the cursor.
 | 
						|
            // It is better to move the cursor into the viewport than let the screen scroll.
 | 
						|
            this.root.replaceCursor(this.listToMove.getLastLineContentEnd());
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const BODY_CLASS = "outliner-plugin-dnd";
 | 
						|
class DragAndDrop {
 | 
						|
    constructor(plugin, settings, obisidian, parser, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.obisidian = obisidian;
 | 
						|
        this.parser = parser;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.preStart = null;
 | 
						|
        this.state = null;
 | 
						|
        this.handleSettingsChange = () => {
 | 
						|
            if (!isFeatureSupported()) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            if (this.settings.dragAndDrop) {
 | 
						|
                document.body.classList.add(BODY_CLASS);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                document.body.classList.remove(BODY_CLASS);
 | 
						|
            }
 | 
						|
        };
 | 
						|
        this.handleMouseDown = (e) => {
 | 
						|
            if (!isFeatureSupported() ||
 | 
						|
                !this.settings.dragAndDrop ||
 | 
						|
                !isClickOnBullet(e)) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            const view = getEditorViewFromHTMLElement(e.target);
 | 
						|
            if (!view) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            e.preventDefault();
 | 
						|
            e.stopPropagation();
 | 
						|
            this.preStart = {
 | 
						|
                x: e.x,
 | 
						|
                y: e.y,
 | 
						|
                view,
 | 
						|
            };
 | 
						|
        };
 | 
						|
        this.handleMouseMove = (e) => {
 | 
						|
            if (this.preStart) {
 | 
						|
                this.startDragging();
 | 
						|
            }
 | 
						|
            if (this.state) {
 | 
						|
                this.detectAndDrawDropZone(e.x, e.y);
 | 
						|
            }
 | 
						|
        };
 | 
						|
        this.handleMouseUp = () => {
 | 
						|
            if (this.preStart) {
 | 
						|
                this.preStart = null;
 | 
						|
            }
 | 
						|
            if (this.state) {
 | 
						|
                this.stopDragging();
 | 
						|
            }
 | 
						|
        };
 | 
						|
        this.handleKeyDown = (e) => {
 | 
						|
            if (this.state && e.code === "Escape") {
 | 
						|
                this.cancelDragging();
 | 
						|
            }
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension([
 | 
						|
                draggingLinesStateField,
 | 
						|
                droppingLinesStateField,
 | 
						|
            ]);
 | 
						|
            this.enableFeatureToggle();
 | 
						|
            this.createDropZone();
 | 
						|
            this.addEventListeners();
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.removeEventListeners();
 | 
						|
            this.removeDropZone();
 | 
						|
            this.disableFeatureToggle();
 | 
						|
        });
 | 
						|
    }
 | 
						|
    enableFeatureToggle() {
 | 
						|
        this.settings.onChange(this.handleSettingsChange);
 | 
						|
        this.handleSettingsChange();
 | 
						|
    }
 | 
						|
    disableFeatureToggle() {
 | 
						|
        this.settings.removeCallback(this.handleSettingsChange);
 | 
						|
        document.body.classList.remove(BODY_CLASS);
 | 
						|
    }
 | 
						|
    createDropZone() {
 | 
						|
        this.dropZonePadding = document.createElement("div");
 | 
						|
        this.dropZonePadding.classList.add("outliner-plugin-drop-zone-padding");
 | 
						|
        this.dropZone = document.createElement("div");
 | 
						|
        this.dropZone.classList.add("outliner-plugin-drop-zone");
 | 
						|
        this.dropZone.style.display = "none";
 | 
						|
        this.dropZone.appendChild(this.dropZonePadding);
 | 
						|
        document.body.appendChild(this.dropZone);
 | 
						|
    }
 | 
						|
    removeDropZone() {
 | 
						|
        document.body.removeChild(this.dropZone);
 | 
						|
        this.dropZonePadding = null;
 | 
						|
        this.dropZone = null;
 | 
						|
    }
 | 
						|
    addEventListeners() {
 | 
						|
        document.addEventListener("mousedown", this.handleMouseDown, {
 | 
						|
            capture: true,
 | 
						|
        });
 | 
						|
        document.addEventListener("mousemove", this.handleMouseMove);
 | 
						|
        document.addEventListener("mouseup", this.handleMouseUp);
 | 
						|
        document.addEventListener("keydown", this.handleKeyDown);
 | 
						|
    }
 | 
						|
    removeEventListeners() {
 | 
						|
        document.removeEventListener("mousedown", this.handleMouseDown, {
 | 
						|
            capture: true,
 | 
						|
        });
 | 
						|
        document.removeEventListener("mousemove", this.handleMouseMove);
 | 
						|
        document.removeEventListener("mouseup", this.handleMouseUp);
 | 
						|
        document.removeEventListener("keydown", this.handleKeyDown);
 | 
						|
    }
 | 
						|
    startDragging() {
 | 
						|
        const { x, y, view } = this.preStart;
 | 
						|
        this.preStart = null;
 | 
						|
        const editor = getEditorFromState(view.state);
 | 
						|
        const pos = editor.offsetToPos(view.posAtCoords({ x, y }));
 | 
						|
        const root = this.parser.parse(editor, pos);
 | 
						|
        const list = root.getListUnderLine(pos.line);
 | 
						|
        const state = new DragAndDropState(view, editor, root, list);
 | 
						|
        if (!state.hasDropVariants()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.state = state;
 | 
						|
        this.highlightDraggingLines();
 | 
						|
    }
 | 
						|
    detectAndDrawDropZone(x, y) {
 | 
						|
        this.state.calculateNearestDropVariant(x, y);
 | 
						|
        this.drawDropZone();
 | 
						|
    }
 | 
						|
    cancelDragging() {
 | 
						|
        this.state.dropVariant = null;
 | 
						|
        this.stopDragging();
 | 
						|
    }
 | 
						|
    stopDragging() {
 | 
						|
        this.unhightlightDraggingLines();
 | 
						|
        this.hideDropZone();
 | 
						|
        this.applyChanges();
 | 
						|
        this.state = null;
 | 
						|
    }
 | 
						|
    applyChanges() {
 | 
						|
        if (!this.state.dropVariant) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const { state } = this;
 | 
						|
        const { dropVariant, editor, root, list } = state;
 | 
						|
        const newRoot = this.parser.parse(editor, root.getContentStart());
 | 
						|
        if (!isSameRoots(root, newRoot)) {
 | 
						|
            new obsidian.Notice(`The item cannot be moved. The page content changed during the move.`, 5000);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.operationPerformer.eval(root, new MoveListToDifferentPosition(root, list, dropVariant.placeToMove, dropVariant.whereToMove, this.obisidian.getDefaultIndentChars()), editor);
 | 
						|
    }
 | 
						|
    highlightDraggingLines() {
 | 
						|
        const { state } = this;
 | 
						|
        const { list, editor, view } = state;
 | 
						|
        const lines = [];
 | 
						|
        const fromLine = list.getFirstLineContentStart().line;
 | 
						|
        const tillLine = list.getContentEndIncludingChildren().line;
 | 
						|
        for (let i = fromLine; i <= tillLine; i++) {
 | 
						|
            lines.push(editor.posToOffset({ line: i, ch: 0 }));
 | 
						|
        }
 | 
						|
        view.dispatch({
 | 
						|
            effects: [dndStarted.of(lines)],
 | 
						|
        });
 | 
						|
        document.body.classList.add("outliner-plugin-dragging");
 | 
						|
    }
 | 
						|
    unhightlightDraggingLines() {
 | 
						|
        document.body.classList.remove("outliner-plugin-dragging");
 | 
						|
        this.state.view.dispatch({
 | 
						|
            effects: [dndEnded.of()],
 | 
						|
        });
 | 
						|
    }
 | 
						|
    drawDropZone() {
 | 
						|
        const { state } = this;
 | 
						|
        const { view, editor, dropVariant } = state;
 | 
						|
        const newParent = dropVariant.whereToMove === "inside"
 | 
						|
            ? dropVariant.placeToMove
 | 
						|
            : dropVariant.placeToMove.getParent();
 | 
						|
        const newParentIsRootList = !newParent.getParent();
 | 
						|
        {
 | 
						|
            const width = Math.round(view.contentDOM.offsetWidth -
 | 
						|
                (dropVariant.left - this.state.leftPadding));
 | 
						|
            this.dropZone.style.display = "block";
 | 
						|
            this.dropZone.style.top = dropVariant.top + "px";
 | 
						|
            this.dropZone.style.left = dropVariant.left + "px";
 | 
						|
            this.dropZone.style.width = width + "px";
 | 
						|
        }
 | 
						|
        {
 | 
						|
            const level = newParent.getLevel();
 | 
						|
            const indentWidth = this.state.tabWidth;
 | 
						|
            const width = indentWidth * level;
 | 
						|
            const dashPadding = 3;
 | 
						|
            const dashWidth = indentWidth - dashPadding;
 | 
						|
            const color = getComputedStyle(document.body).getPropertyValue("--color-accent");
 | 
						|
            this.dropZonePadding.style.width = `${width}px`;
 | 
						|
            this.dropZonePadding.style.marginLeft = `-${width}px`;
 | 
						|
            this.dropZonePadding.style.backgroundImage = `url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%20${width}%204%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cline%20x1%3D%220%22%20y1%3D%220%22%20x2%3D%22${width}%22%20y2%3D%220%22%20stroke%3D%22${color}%22%20stroke-width%3D%228%22%20stroke-dasharray%3D%22${dashWidth}%20${dashPadding}%22%2F%3E%3C%2Fsvg%3E')`;
 | 
						|
        }
 | 
						|
        this.state.view.dispatch({
 | 
						|
            effects: [
 | 
						|
                dndMoved.of(newParentIsRootList
 | 
						|
                    ? null
 | 
						|
                    : editor.posToOffset({
 | 
						|
                        line: newParent.getFirstLineContentStart().line,
 | 
						|
                        ch: 0,
 | 
						|
                    })),
 | 
						|
            ],
 | 
						|
        });
 | 
						|
    }
 | 
						|
    hideDropZone() {
 | 
						|
        this.dropZone.style.display = "none";
 | 
						|
    }
 | 
						|
}
 | 
						|
class DragAndDropState {
 | 
						|
    constructor(view, editor, root, list) {
 | 
						|
        this.view = view;
 | 
						|
        this.editor = editor;
 | 
						|
        this.root = root;
 | 
						|
        this.list = list;
 | 
						|
        this.dropVariants = new Map();
 | 
						|
        this.dropVariant = null;
 | 
						|
        this.leftPadding = 0;
 | 
						|
        this.tabWidth = 0;
 | 
						|
        this.collectDropVariants();
 | 
						|
        this.calculateLeftPadding();
 | 
						|
        this.calculateTabWidth();
 | 
						|
    }
 | 
						|
    getDropVariants() {
 | 
						|
        return Array.from(this.dropVariants.values());
 | 
						|
    }
 | 
						|
    hasDropVariants() {
 | 
						|
        return this.dropVariants.size > 0;
 | 
						|
    }
 | 
						|
    calculateNearestDropVariant(x, y) {
 | 
						|
        const { view, editor } = this;
 | 
						|
        const dropVariants = this.getDropVariants();
 | 
						|
        const possibleDropVariants = [];
 | 
						|
        for (const v of dropVariants) {
 | 
						|
            const { placeToMove } = v;
 | 
						|
            const positionAfterList = v.whereToMove === "after" || v.whereToMove === "inside";
 | 
						|
            const line = positionAfterList
 | 
						|
                ? placeToMove.getContentEndIncludingChildren().line
 | 
						|
                : placeToMove.getFirstLineContentStart().line;
 | 
						|
            const linePos = editor.posToOffset({
 | 
						|
                line,
 | 
						|
                ch: 0,
 | 
						|
            });
 | 
						|
            const coords = view.coordsAtPos(linePos, -1);
 | 
						|
            if (!coords) {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            v.left = this.leftPadding + (v.level - 1) * this.tabWidth;
 | 
						|
            v.top = coords.top;
 | 
						|
            if (positionAfterList) {
 | 
						|
                v.top += view.lineBlockAt(linePos).height;
 | 
						|
            }
 | 
						|
            // Better vertical alignment
 | 
						|
            v.top -= 8;
 | 
						|
            possibleDropVariants.push(v);
 | 
						|
        }
 | 
						|
        const nearestLineTop = possibleDropVariants
 | 
						|
            .sort((a, b) => Math.abs(y - a.top) - Math.abs(y - b.top))
 | 
						|
            .first().top;
 | 
						|
        const variansOnNearestLine = possibleDropVariants.filter((v) => Math.abs(v.top - nearestLineTop) <= 4);
 | 
						|
        this.dropVariant = variansOnNearestLine
 | 
						|
            .sort((a, b) => Math.abs(x - a.left) - Math.abs(x - b.left))
 | 
						|
            .first();
 | 
						|
    }
 | 
						|
    addDropVariant(v) {
 | 
						|
        this.dropVariants.set(`${v.line} ${v.level}`, v);
 | 
						|
    }
 | 
						|
    collectDropVariants() {
 | 
						|
        const visit = (lists) => {
 | 
						|
            for (const placeToMove of lists) {
 | 
						|
                const lineBefore = placeToMove.getFirstLineContentStart().line;
 | 
						|
                const lineAfter = placeToMove.getContentEndIncludingChildren().line + 1;
 | 
						|
                const level = placeToMove.getLevel();
 | 
						|
                this.addDropVariant({
 | 
						|
                    line: lineBefore,
 | 
						|
                    level,
 | 
						|
                    left: 0,
 | 
						|
                    top: 0,
 | 
						|
                    placeToMove,
 | 
						|
                    whereToMove: "before",
 | 
						|
                });
 | 
						|
                this.addDropVariant({
 | 
						|
                    line: lineAfter,
 | 
						|
                    level,
 | 
						|
                    left: 0,
 | 
						|
                    top: 0,
 | 
						|
                    placeToMove,
 | 
						|
                    whereToMove: "after",
 | 
						|
                });
 | 
						|
                if (placeToMove === this.list) {
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
                if (placeToMove.isEmpty()) {
 | 
						|
                    this.addDropVariant({
 | 
						|
                        line: lineAfter,
 | 
						|
                        level: level + 1,
 | 
						|
                        left: 0,
 | 
						|
                        top: 0,
 | 
						|
                        placeToMove,
 | 
						|
                        whereToMove: "inside",
 | 
						|
                    });
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    visit(placeToMove.getChildren());
 | 
						|
                }
 | 
						|
            }
 | 
						|
        };
 | 
						|
        visit(this.root.getChildren());
 | 
						|
    }
 | 
						|
    calculateLeftPadding() {
 | 
						|
        const cmLine = this.view.dom.querySelector("div.cm-line");
 | 
						|
        this.leftPadding = cmLine.getBoundingClientRect().left;
 | 
						|
    }
 | 
						|
    calculateTabWidth() {
 | 
						|
        const { view } = this;
 | 
						|
        const indentDom = view.dom.querySelector(".cm-indent");
 | 
						|
        if (indentDom) {
 | 
						|
            this.tabWidth = indentDom.offsetWidth;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const singleIndent = language.indentString(view.state, language.getIndentUnit(view.state));
 | 
						|
        for (let i = 1; i <= view.state.doc.lines; i++) {
 | 
						|
            const line = view.state.doc.line(i);
 | 
						|
            if (line.text.startsWith(singleIndent)) {
 | 
						|
                const a = view.coordsAtPos(line.from, -1);
 | 
						|
                if (!a) {
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
                const b = view.coordsAtPos(line.from + singleIndent.length, -1);
 | 
						|
                if (!b) {
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
                this.tabWidth = b.left - a.left;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        this.tabWidth = view.defaultCharacterWidth * language.getIndentUnit(view.state);
 | 
						|
    }
 | 
						|
}
 | 
						|
const dndStarted = state.StateEffect.define({
 | 
						|
    map: (lines, change) => lines.map((l) => change.mapPos(l)),
 | 
						|
});
 | 
						|
const dndMoved = state.StateEffect.define({
 | 
						|
    map: (line, change) => (line !== null ? change.mapPos(line) : line),
 | 
						|
});
 | 
						|
const dndEnded = state.StateEffect.define();
 | 
						|
const draggingLineDecoration = view.Decoration.line({
 | 
						|
    class: "outliner-plugin-dragging-line",
 | 
						|
});
 | 
						|
const droppingLineDecoration = view.Decoration.line({
 | 
						|
    class: "outliner-plugin-dropping-line",
 | 
						|
});
 | 
						|
const draggingLinesStateField = state.StateField.define({
 | 
						|
    create: () => view.Decoration.none,
 | 
						|
    update: (dndState, tr) => {
 | 
						|
        dndState = dndState.map(tr.changes);
 | 
						|
        for (const e of tr.effects) {
 | 
						|
            if (e.is(dndStarted)) {
 | 
						|
                dndState = dndState.update({
 | 
						|
                    add: e.value.map((l) => draggingLineDecoration.range(l, l)),
 | 
						|
                });
 | 
						|
            }
 | 
						|
            if (e.is(dndEnded)) {
 | 
						|
                dndState = view.Decoration.none;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return dndState;
 | 
						|
    },
 | 
						|
    provide: (f) => view.EditorView.decorations.from(f),
 | 
						|
});
 | 
						|
const droppingLinesStateField = state.StateField.define({
 | 
						|
    create: () => view.Decoration.none,
 | 
						|
    update: (dndDroppingState, tr) => {
 | 
						|
        dndDroppingState = dndDroppingState.map(tr.changes);
 | 
						|
        for (const e of tr.effects) {
 | 
						|
            if (e.is(dndMoved)) {
 | 
						|
                dndDroppingState =
 | 
						|
                    e.value === null
 | 
						|
                        ? view.Decoration.none
 | 
						|
                        : view.Decoration.set(droppingLineDecoration.range(e.value, e.value));
 | 
						|
            }
 | 
						|
            if (e.is(dndEnded)) {
 | 
						|
                dndDroppingState = view.Decoration.none;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return dndDroppingState;
 | 
						|
    },
 | 
						|
    provide: (f) => view.EditorView.decorations.from(f),
 | 
						|
});
 | 
						|
function getEditorViewFromHTMLElement(e) {
 | 
						|
    while (e && !e.classList.contains("cm-editor")) {
 | 
						|
        e = e.parentElement;
 | 
						|
    }
 | 
						|
    if (!e) {
 | 
						|
        return null;
 | 
						|
    }
 | 
						|
    return view.EditorView.findFromDOM(e);
 | 
						|
}
 | 
						|
function isClickOnBullet(e) {
 | 
						|
    let el = e.target;
 | 
						|
    while (el) {
 | 
						|
        if (el.classList.contains("cm-formatting-list") ||
 | 
						|
            el.classList.contains("cm-fold-indicator") ||
 | 
						|
            el.classList.contains("task-list-item-checkbox")) {
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        el = el.parentElement;
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
}
 | 
						|
function isSameRoots(a, b) {
 | 
						|
    const [aStart, aEnd] = a.getContentRange();
 | 
						|
    const [bStart, bEnd] = b.getContentRange();
 | 
						|
    if (cmpPos(aStart, bStart) !== 0 || cmpPos(aEnd, bEnd) !== 0) {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    return a.print() === b.print();
 | 
						|
}
 | 
						|
function isFeatureSupported() {
 | 
						|
    return obsidian.Platform.isDesktop;
 | 
						|
}
 | 
						|
 | 
						|
class KeepCursorOutsideFoldedLines {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        if (!list.isFolded()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const foldRoot = list.getTopFoldRoot();
 | 
						|
        const firstLineEnd = foldRoot.getLinesInfo()[0].to;
 | 
						|
        if (cursor.line > firstLineEnd.line) {
 | 
						|
            this.updated = true;
 | 
						|
            this.stopPropagation = true;
 | 
						|
            root.replaceCursor(firstLineEnd);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class KeepCursorWithinListContent {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const contentStart = list.getFirstLineContentStartAfterCheckbox();
 | 
						|
        const linePrefix = contentStart.line === cursor.line
 | 
						|
            ? contentStart.ch
 | 
						|
            : list.getNotesIndent().length;
 | 
						|
        if (cursor.ch < linePrefix) {
 | 
						|
            this.updated = true;
 | 
						|
            this.stopPropagation = true;
 | 
						|
            root.replaceCursor({
 | 
						|
                line: cursor.line,
 | 
						|
                ch: linePrefix,
 | 
						|
            });
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class EditorSelectionsBehaviourOverride {
 | 
						|
    constructor(plugin, settings, parser, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.parser = parser;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.transactionExtender = (tr) => {
 | 
						|
            if (this.settings.keepCursorWithinContent === "never" || !tr.selection) {
 | 
						|
                return null;
 | 
						|
            }
 | 
						|
            const editor = getEditorFromState(tr.startState);
 | 
						|
            setTimeout(() => {
 | 
						|
                this.handleSelectionsChanges(editor);
 | 
						|
            }, 0);
 | 
						|
            return null;
 | 
						|
        };
 | 
						|
        this.handleSelectionsChanges = (editor) => {
 | 
						|
            const root = this.parser.parse(editor);
 | 
						|
            if (!root) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            {
 | 
						|
                const { shouldStopPropagation } = this.operationPerformer.eval(root, new KeepCursorOutsideFoldedLines(root), editor);
 | 
						|
                if (shouldStopPropagation) {
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            this.operationPerformer.eval(root, new KeepCursorWithinListContent(root), editor);
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(state.EditorState.transactionExtender.of(this.transactionExtender));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const checkboxRe = `\\[[^\\[\\]]\\][ \t]`;
 | 
						|
 | 
						|
function isEmptyLineOrEmptyCheckbox(line) {
 | 
						|
    return line === "" || line === "[ ] ";
 | 
						|
}
 | 
						|
 | 
						|
class CreateNewItem {
 | 
						|
    constructor(root, defaultIndentChars, getZoomRange, after = true) {
 | 
						|
        this.root = root;
 | 
						|
        this.defaultIndentChars = defaultIndentChars;
 | 
						|
        this.getZoomRange = getZoomRange;
 | 
						|
        this.after = after;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleSelection()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const selection = root.getSelection();
 | 
						|
        if (!selection || selection.anchor.line !== selection.head.line) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const lines = list.getLinesInfo();
 | 
						|
        if (lines.length === 1 && isEmptyLineOrEmptyCheckbox(lines[0].text)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        const lineUnderCursor = lines.find((l) => l.from.line === cursor.line);
 | 
						|
        if (cursor.ch < lineUnderCursor.from.ch) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const { oldLines, newLines } = lines.reduce((acc, line) => {
 | 
						|
            if (cursor.line > line.from.line) {
 | 
						|
                acc.oldLines.push(line.text);
 | 
						|
            }
 | 
						|
            else if (cursor.line === line.from.line) {
 | 
						|
                const left = line.text.slice(0, selection.from - line.from.ch);
 | 
						|
                const right = line.text.slice(selection.to - line.from.ch);
 | 
						|
                acc.oldLines.push(left);
 | 
						|
                acc.newLines.push(right);
 | 
						|
            }
 | 
						|
            else if (cursor.line < line.from.line) {
 | 
						|
                acc.newLines.push(line.text);
 | 
						|
            }
 | 
						|
            return acc;
 | 
						|
        }, {
 | 
						|
            oldLines: [],
 | 
						|
            newLines: [],
 | 
						|
        });
 | 
						|
        const codeBlockBacticks = oldLines.join("\n").split("```").length - 1;
 | 
						|
        const isInsideCodeblock = codeBlockBacticks > 0 && codeBlockBacticks % 2 !== 0;
 | 
						|
        if (isInsideCodeblock) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        this.updated = true;
 | 
						|
        const zoomRange = this.getZoomRange.getZoomRange();
 | 
						|
        const listIsZoomingRoot = Boolean(zoomRange &&
 | 
						|
            list.getFirstLineContentStart().line >= zoomRange.from.line &&
 | 
						|
            list.getLastLineContentEnd().line <= zoomRange.from.line);
 | 
						|
        const hasChildren = !list.isEmpty();
 | 
						|
        const childIsFolded = list.isFoldRoot();
 | 
						|
        const endPos = list.getLastLineContentEnd();
 | 
						|
        const endOfLine = cursor.line === endPos.line && cursor.ch === endPos.ch;
 | 
						|
        const onChildLevel = listIsZoomingRoot || (hasChildren && !childIsFolded && endOfLine);
 | 
						|
        const indent = onChildLevel
 | 
						|
            ? hasChildren
 | 
						|
                ? list.getChildren()[0].getFirstLineIndent()
 | 
						|
                : list.getFirstLineIndent() + this.defaultIndentChars
 | 
						|
            : list.getFirstLineIndent();
 | 
						|
        const bullet = onChildLevel && hasChildren
 | 
						|
            ? list.getChildren()[0].getBullet()
 | 
						|
            : list.getBullet();
 | 
						|
        const spaceAfterBullet = onChildLevel && hasChildren
 | 
						|
            ? list.getChildren()[0].getSpaceAfterBullet()
 | 
						|
            : list.getSpaceAfterBullet();
 | 
						|
        const prefix = oldLines[0].match(checkboxRe) ? "[ ] " : "";
 | 
						|
        const newList = new List(list.getRoot(), indent, bullet, prefix, spaceAfterBullet, prefix + newLines.shift(), false);
 | 
						|
        if (newLines.length > 0) {
 | 
						|
            newList.setNotesIndent(list.getNotesIndent());
 | 
						|
            for (const line of newLines) {
 | 
						|
                newList.addLine(line);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (onChildLevel) {
 | 
						|
            list.addBeforeAll(newList);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            if (!childIsFolded || !endOfLine) {
 | 
						|
                const children = list.getChildren();
 | 
						|
                for (const child of children) {
 | 
						|
                    list.removeChild(child);
 | 
						|
                    newList.addAfterAll(child);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (this.after) {
 | 
						|
                list.getParent().addAfter(list, newList);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                list.getParent().addBefore(list, newList);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        list.replaceLines(oldLines);
 | 
						|
        const newListStart = newList.getFirstLineContentStart();
 | 
						|
        root.replaceCursor({
 | 
						|
            line: newListStart.line,
 | 
						|
            ch: newListStart.ch + prefix.length,
 | 
						|
        });
 | 
						|
        recalculateNumericBullets(root);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class OutdentList {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const parent = list.getParent();
 | 
						|
        const grandParent = parent.getParent();
 | 
						|
        if (!grandParent) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.updated = true;
 | 
						|
        const listStartLineBefore = root.getContentLinesRangeOf(list)[0];
 | 
						|
        const indentRmFrom = parent.getFirstLineIndent().length;
 | 
						|
        const indentRmTill = list.getFirstLineIndent().length;
 | 
						|
        parent.removeChild(list);
 | 
						|
        grandParent.addAfter(parent, list);
 | 
						|
        list.unindentContent(indentRmFrom, indentRmTill);
 | 
						|
        const listStartLineAfter = root.getContentLinesRangeOf(list)[0];
 | 
						|
        const lineDiff = listStartLineAfter - listStartLineBefore;
 | 
						|
        const chDiff = indentRmTill - indentRmFrom;
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        root.replaceCursor({
 | 
						|
            line: cursor.line + lineDiff,
 | 
						|
            ch: cursor.ch - chDiff,
 | 
						|
        });
 | 
						|
        recalculateNumericBullets(root);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class OutdentListIfItsEmpty {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.outdentList = new OutdentList(root);
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.outdentList.shouldStopPropagation();
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.outdentList.shouldUpdate();
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const lines = list.getLines();
 | 
						|
        if (lines.length > 1 ||
 | 
						|
            !isEmptyLineOrEmptyCheckbox(lines[0]) ||
 | 
						|
            list.getLevel() === 1) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.outdentList.perform();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class EnterBehaviourOverride {
 | 
						|
    constructor(plugin, settings, imeDetector, obsidianSettings, parser, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.imeDetector = imeDetector;
 | 
						|
        this.obsidianSettings = obsidianSettings;
 | 
						|
        this.parser = parser;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.check = () => {
 | 
						|
            return this.settings.overrideEnterBehaviour && !this.imeDetector.isOpened();
 | 
						|
        };
 | 
						|
        this.run = (editor) => {
 | 
						|
            const root = this.parser.parse(editor);
 | 
						|
            if (!root) {
 | 
						|
                return {
 | 
						|
                    shouldUpdate: false,
 | 
						|
                    shouldStopPropagation: false,
 | 
						|
                };
 | 
						|
            }
 | 
						|
            {
 | 
						|
                const res = this.operationPerformer.eval(root, new OutdentListIfItsEmpty(root), editor);
 | 
						|
                if (res.shouldStopPropagation) {
 | 
						|
                    return res;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            {
 | 
						|
                const defaultIndentChars = this.obsidianSettings.getDefaultIndentChars();
 | 
						|
                const zoomRange = editor.getZoomRange();
 | 
						|
                const getZoomRange = {
 | 
						|
                    getZoomRange: () => zoomRange,
 | 
						|
                };
 | 
						|
                const res = this.operationPerformer.eval(root, new CreateNewItem(root, defaultIndentChars, getZoomRange), editor);
 | 
						|
                if (res.shouldUpdate && zoomRange) {
 | 
						|
                    editor.tryRefreshZoom(zoomRange.from.line);
 | 
						|
                }
 | 
						|
                return res;
 | 
						|
            }
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(state.Prec.highest(view.keymap.of([
 | 
						|
                {
 | 
						|
                    key: "Enter",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
            ])));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function createEditorCallback(cb) {
 | 
						|
    return (editor) => {
 | 
						|
        const myEditor = new MyEditor(editor);
 | 
						|
        const shouldStopPropagation = cb(myEditor);
 | 
						|
        if (!shouldStopPropagation &&
 | 
						|
            window.event &&
 | 
						|
            window.event.type === "keydown") {
 | 
						|
            myEditor.triggerOnKeyDown(window.event);
 | 
						|
        }
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
class ListsFoldingCommands {
 | 
						|
    constructor(plugin, obsidianSettings) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.obsidianSettings = obsidianSettings;
 | 
						|
        this.fold = (editor) => {
 | 
						|
            return this.setFold(editor, "fold");
 | 
						|
        };
 | 
						|
        this.unfold = (editor) => {
 | 
						|
            return this.setFold(editor, "unfold");
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.addCommand({
 | 
						|
                id: "fold",
 | 
						|
                icon: "chevrons-down-up",
 | 
						|
                name: "Fold the list",
 | 
						|
                editorCallback: createEditorCallback(this.fold),
 | 
						|
                hotkeys: [
 | 
						|
                    {
 | 
						|
                        modifiers: ["Mod"],
 | 
						|
                        key: "ArrowUp",
 | 
						|
                    },
 | 
						|
                ],
 | 
						|
            });
 | 
						|
            this.plugin.addCommand({
 | 
						|
                id: "unfold",
 | 
						|
                icon: "chevrons-up-down",
 | 
						|
                name: "Unfold the list",
 | 
						|
                editorCallback: createEditorCallback(this.unfold),
 | 
						|
                hotkeys: [
 | 
						|
                    {
 | 
						|
                        modifiers: ["Mod"],
 | 
						|
                        key: "ArrowDown",
 | 
						|
                    },
 | 
						|
                ],
 | 
						|
            });
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
    setFold(editor, type) {
 | 
						|
        if (!this.obsidianSettings.getFoldSettings().foldIndent) {
 | 
						|
            new obsidian.Notice(`Unable to ${type} because folding is disabled. Please enable "Fold indent" in Obsidian settings.`, 5000);
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        const cursor = editor.getCursor();
 | 
						|
        if (type === "fold") {
 | 
						|
            editor.fold(cursor.line);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            editor.unfold(cursor.line);
 | 
						|
        }
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class IndentList {
 | 
						|
    constructor(root, defaultIndentChars) {
 | 
						|
        this.root = root;
 | 
						|
        this.defaultIndentChars = defaultIndentChars;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const parent = list.getParent();
 | 
						|
        const prev = parent.getPrevSiblingOf(list);
 | 
						|
        if (!prev) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.updated = true;
 | 
						|
        const listStartLineBefore = root.getContentLinesRangeOf(list)[0];
 | 
						|
        const indentPos = list.getFirstLineIndent().length;
 | 
						|
        let indentChars = "";
 | 
						|
        if (indentChars === "" && !prev.isEmpty()) {
 | 
						|
            indentChars = prev
 | 
						|
                .getChildren()[0]
 | 
						|
                .getFirstLineIndent()
 | 
						|
                .slice(prev.getFirstLineIndent().length);
 | 
						|
        }
 | 
						|
        if (indentChars === "") {
 | 
						|
            indentChars = list
 | 
						|
                .getFirstLineIndent()
 | 
						|
                .slice(parent.getFirstLineIndent().length);
 | 
						|
        }
 | 
						|
        if (indentChars === "" && !list.isEmpty()) {
 | 
						|
            indentChars = list.getChildren()[0].getFirstLineIndent();
 | 
						|
        }
 | 
						|
        if (indentChars === "") {
 | 
						|
            indentChars = this.defaultIndentChars;
 | 
						|
        }
 | 
						|
        parent.removeChild(list);
 | 
						|
        prev.addAfterAll(list);
 | 
						|
        list.indentContent(indentPos, indentChars);
 | 
						|
        const listStartLineAfter = root.getContentLinesRangeOf(list)[0];
 | 
						|
        const lineDiff = listStartLineAfter - listStartLineBefore;
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        root.replaceCursor({
 | 
						|
            line: cursor.line + lineDiff,
 | 
						|
            ch: cursor.ch + indentChars.length,
 | 
						|
        });
 | 
						|
        recalculateNumericBullets(root);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class MoveListDown {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const parent = list.getParent();
 | 
						|
        const grandParent = parent.getParent();
 | 
						|
        const next = parent.getNextSiblingOf(list);
 | 
						|
        const listStartLineBefore = root.getContentLinesRangeOf(list)[0];
 | 
						|
        if (!next && grandParent) {
 | 
						|
            const newParent = grandParent.getNextSiblingOf(parent);
 | 
						|
            if (newParent) {
 | 
						|
                this.updated = true;
 | 
						|
                parent.removeChild(list);
 | 
						|
                newParent.addBeforeAll(list);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else if (next) {
 | 
						|
            this.updated = true;
 | 
						|
            parent.removeChild(list);
 | 
						|
            parent.addAfter(next, list);
 | 
						|
        }
 | 
						|
        if (!this.updated) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const listStartLineAfter = root.getContentLinesRangeOf(list)[0];
 | 
						|
        const lineDiff = listStartLineAfter - listStartLineBefore;
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        root.replaceCursor({
 | 
						|
            line: cursor.line + lineDiff,
 | 
						|
            ch: cursor.ch,
 | 
						|
        });
 | 
						|
        recalculateNumericBullets(root);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class MoveListUp {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const parent = list.getParent();
 | 
						|
        const grandParent = parent.getParent();
 | 
						|
        const prev = parent.getPrevSiblingOf(list);
 | 
						|
        const listStartLineBefore = root.getContentLinesRangeOf(list)[0];
 | 
						|
        if (!prev && grandParent) {
 | 
						|
            const newParent = grandParent.getPrevSiblingOf(parent);
 | 
						|
            if (newParent) {
 | 
						|
                this.updated = true;
 | 
						|
                parent.removeChild(list);
 | 
						|
                newParent.addAfterAll(list);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else if (prev) {
 | 
						|
            this.updated = true;
 | 
						|
            parent.removeChild(list);
 | 
						|
            parent.addBefore(prev, list);
 | 
						|
        }
 | 
						|
        if (!this.updated) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const listStartLineAfter = root.getContentLinesRangeOf(list)[0];
 | 
						|
        const lineDiff = listStartLineAfter - listStartLineBefore;
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        root.replaceCursor({
 | 
						|
            line: cursor.line + lineDiff,
 | 
						|
            ch: cursor.ch,
 | 
						|
        });
 | 
						|
        recalculateNumericBullets(root);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class ListsMovementCommands {
 | 
						|
    constructor(plugin, obsidianSettings, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.obsidianSettings = obsidianSettings;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.moveListDown = (editor) => {
 | 
						|
            const { shouldStopPropagation } = this.operationPerformer.perform((root) => new MoveListDown(root), editor);
 | 
						|
            return shouldStopPropagation;
 | 
						|
        };
 | 
						|
        this.moveListUp = (editor) => {
 | 
						|
            const { shouldStopPropagation } = this.operationPerformer.perform((root) => new MoveListUp(root), editor);
 | 
						|
            return shouldStopPropagation;
 | 
						|
        };
 | 
						|
        this.indentList = (editor) => {
 | 
						|
            const { shouldStopPropagation } = this.operationPerformer.perform((root) => new IndentList(root, this.obsidianSettings.getDefaultIndentChars()), editor);
 | 
						|
            return shouldStopPropagation;
 | 
						|
        };
 | 
						|
        this.outdentList = (editor) => {
 | 
						|
            const { shouldStopPropagation } = this.operationPerformer.perform((root) => new OutdentList(root), editor);
 | 
						|
            return shouldStopPropagation;
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.addCommand({
 | 
						|
                id: "move-list-item-up",
 | 
						|
                icon: "arrow-up",
 | 
						|
                name: "Move list and sublists up",
 | 
						|
                editorCallback: createEditorCallback(this.moveListUp),
 | 
						|
                hotkeys: [
 | 
						|
                    {
 | 
						|
                        modifiers: ["Mod", "Shift"],
 | 
						|
                        key: "ArrowUp",
 | 
						|
                    },
 | 
						|
                ],
 | 
						|
            });
 | 
						|
            this.plugin.addCommand({
 | 
						|
                id: "move-list-item-down",
 | 
						|
                icon: "arrow-down",
 | 
						|
                name: "Move list and sublists down",
 | 
						|
                editorCallback: createEditorCallback(this.moveListDown),
 | 
						|
                hotkeys: [
 | 
						|
                    {
 | 
						|
                        modifiers: ["Mod", "Shift"],
 | 
						|
                        key: "ArrowDown",
 | 
						|
                    },
 | 
						|
                ],
 | 
						|
            });
 | 
						|
            this.plugin.addCommand({
 | 
						|
                id: "indent-list",
 | 
						|
                icon: "indent",
 | 
						|
                name: "Indent the list and sublists",
 | 
						|
                editorCallback: createEditorCallback(this.indentList),
 | 
						|
                hotkeys: [],
 | 
						|
            });
 | 
						|
            this.plugin.addCommand({
 | 
						|
                id: "outdent-list",
 | 
						|
                icon: "outdent",
 | 
						|
                name: "Outdent the list and sublists",
 | 
						|
                editorCallback: createEditorCallback(this.outdentList),
 | 
						|
                hotkeys: [],
 | 
						|
            });
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class DeleteTillCurrentLineContentStart {
 | 
						|
    constructor(root) {
 | 
						|
        this.root = root;
 | 
						|
        this.stopPropagation = false;
 | 
						|
        this.updated = false;
 | 
						|
    }
 | 
						|
    shouldStopPropagation() {
 | 
						|
        return this.stopPropagation;
 | 
						|
    }
 | 
						|
    shouldUpdate() {
 | 
						|
        return this.updated;
 | 
						|
    }
 | 
						|
    perform() {
 | 
						|
        const { root } = this;
 | 
						|
        if (!root.hasSingleCursor()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        this.stopPropagation = true;
 | 
						|
        this.updated = true;
 | 
						|
        const cursor = root.getCursor();
 | 
						|
        const list = root.getListUnderCursor();
 | 
						|
        const lines = list.getLinesInfo();
 | 
						|
        const lineNo = lines.findIndex((l) => l.from.line === cursor.line);
 | 
						|
        lines[lineNo].text = lines[lineNo].text.slice(cursor.ch - lines[lineNo].from.ch);
 | 
						|
        list.replaceLines(lines.map((l) => l.text));
 | 
						|
        root.replaceCursor(lines[lineNo].from);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class MetaBackspaceBehaviourOverride {
 | 
						|
    constructor(plugin, settings, imeDetector, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.imeDetector = imeDetector;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.check = () => {
 | 
						|
            return (this.settings.keepCursorWithinContent !== "never" &&
 | 
						|
                !this.imeDetector.isOpened());
 | 
						|
        };
 | 
						|
        this.run = (editor) => {
 | 
						|
            return this.operationPerformer.perform((root) => new DeleteTillCurrentLineContentStart(root), editor);
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(view.keymap.of([
 | 
						|
                {
 | 
						|
                    mac: "m-Backspace",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
            ]));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class ObsidianOutlinerPluginSettingTab extends obsidian.PluginSettingTab {
 | 
						|
    constructor(app, plugin, settings) {
 | 
						|
        super(app, plugin);
 | 
						|
        this.settings = settings;
 | 
						|
    }
 | 
						|
    display() {
 | 
						|
        const { containerEl } = this;
 | 
						|
        containerEl.empty();
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Stick the cursor to the content")
 | 
						|
            .setDesc("Don't let the cursor move to the bullet position.")
 | 
						|
            .addDropdown((dropdown) => {
 | 
						|
            dropdown
 | 
						|
                .addOptions({
 | 
						|
                never: "Never",
 | 
						|
                "bullet-only": "Stick cursor out of bullets",
 | 
						|
                "bullet-and-checkbox": "Stick cursor out of bullets and checkboxes",
 | 
						|
            })
 | 
						|
                .setValue(this.settings.keepCursorWithinContent)
 | 
						|
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.keepCursorWithinContent = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Enhance the Tab key")
 | 
						|
            .setDesc("Make Tab and Shift-Tab behave the same as other outliners.")
 | 
						|
            .addToggle((toggle) => {
 | 
						|
            toggle
 | 
						|
                .setValue(this.settings.overrideTabBehaviour)
 | 
						|
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.overrideTabBehaviour = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Enhance the Enter key")
 | 
						|
            .setDesc("Make the Enter key behave the same as other outliners.")
 | 
						|
            .addToggle((toggle) => {
 | 
						|
            toggle
 | 
						|
                .setValue(this.settings.overrideEnterBehaviour)
 | 
						|
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.overrideEnterBehaviour = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Vim-mode o/O inserts bullets")
 | 
						|
            .setDesc("Create a bullet when pressing o or O in Vim mode.")
 | 
						|
            .addToggle((toggle) => {
 | 
						|
            toggle
 | 
						|
                .setValue(this.settings.overrideVimOBehaviour)
 | 
						|
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.overrideVimOBehaviour = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Enhance the Ctrl+A or Cmd+A behavior")
 | 
						|
            .setDesc("Press the hotkey once to select the current list item. Press the hotkey twice to select the entire list.")
 | 
						|
            .addToggle((toggle) => {
 | 
						|
            toggle
 | 
						|
                .setValue(this.settings.overrideSelectAllBehaviour)
 | 
						|
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.overrideSelectAllBehaviour = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Improve the style of your lists")
 | 
						|
            .setDesc("Styles are only compatible with built-in Obsidian themes and may not be compatible with other themes.")
 | 
						|
            .addToggle((toggle) => {
 | 
						|
            toggle
 | 
						|
                .setValue(this.settings.betterListsStyles)
 | 
						|
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.betterListsStyles = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Draw vertical indentation lines")
 | 
						|
            .addToggle((toggle) => {
 | 
						|
            toggle.setValue(this.settings.verticalLines).onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.verticalLines = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Vertical indentation line click action")
 | 
						|
            .addDropdown((dropdown) => {
 | 
						|
            dropdown
 | 
						|
                .addOptions({
 | 
						|
                none: "None",
 | 
						|
                "zoom-in": "Zoom In",
 | 
						|
                "toggle-folding": "Toggle Folding",
 | 
						|
            })
 | 
						|
                .setValue(this.settings.verticalLinesAction)
 | 
						|
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.verticalLinesAction = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl).setName("Drag-and-Drop").addToggle((toggle) => {
 | 
						|
            toggle.setValue(this.settings.dragAndDrop).onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.dragAndDrop = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
        new obsidian.Setting(containerEl)
 | 
						|
            .setName("Debug mode")
 | 
						|
            .setDesc("Open DevTools (Command+Option+I or Control+Shift+I) to copy the debug logs.")
 | 
						|
            .addToggle((toggle) => {
 | 
						|
            toggle.setValue(this.settings.debug).onChange((value) => __awaiter(this, void 0, void 0, function* () {
 | 
						|
                this.settings.debug = value;
 | 
						|
                yield this.settings.save();
 | 
						|
            }));
 | 
						|
        });
 | 
						|
    }
 | 
						|
}
 | 
						|
class SettingsTab {
 | 
						|
    constructor(plugin, settings) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.addSettingTab(new ObsidianOutlinerPluginSettingTab(this.plugin.app, this.plugin, this.settings));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class ShiftTabBehaviourOverride {
 | 
						|
    constructor(plugin, imeDetector, settings, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.imeDetector = imeDetector;
 | 
						|
        this.settings = settings;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.check = () => {
 | 
						|
            return this.settings.overrideTabBehaviour && !this.imeDetector.isOpened();
 | 
						|
        };
 | 
						|
        this.run = (editor) => {
 | 
						|
            return this.operationPerformer.perform((root) => new OutdentList(root), editor);
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(state.Prec.highest(view.keymap.of([
 | 
						|
                {
 | 
						|
                    key: "s-Tab",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
            ])));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class SystemInfoModal extends obsidian.Modal {
 | 
						|
    constructor(app, settings) {
 | 
						|
        super(app);
 | 
						|
        this.settings = settings;
 | 
						|
    }
 | 
						|
    onOpen() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.titleEl.setText("System Information");
 | 
						|
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
						|
            const app = this.app;
 | 
						|
            const data = {
 | 
						|
                process: {
 | 
						|
                    arch: process.arch,
 | 
						|
                    platform: process.platform,
 | 
						|
                },
 | 
						|
                app: {
 | 
						|
                    internalPlugins: {
 | 
						|
                        config: app.internalPlugins.config,
 | 
						|
                    },
 | 
						|
                    isMobile: app.isMobile,
 | 
						|
                    plugins: {
 | 
						|
                        enabledPlugins: Array.from(app.plugins.enabledPlugins),
 | 
						|
                        manifests: Object.keys(app.plugins.manifests).reduce((acc, key) => {
 | 
						|
                            acc[key] = {
 | 
						|
                                version: app.plugins.manifests[key].version,
 | 
						|
                            };
 | 
						|
                            return acc;
 | 
						|
                        }, {}),
 | 
						|
                    },
 | 
						|
                    vault: {
 | 
						|
                        config: app.vault.config,
 | 
						|
                    },
 | 
						|
                },
 | 
						|
                plugin: {
 | 
						|
                    settings: { values: this.settings.getValues() },
 | 
						|
                },
 | 
						|
            };
 | 
						|
            const text = JSON.stringify(data, null, 2);
 | 
						|
            const pre = this.contentEl.createEl("pre");
 | 
						|
            pre.setText(text);
 | 
						|
            pre.setCssStyles({
 | 
						|
                overflow: "scroll",
 | 
						|
                maxHeight: "300px",
 | 
						|
            });
 | 
						|
            const button = this.contentEl.createEl("button");
 | 
						|
            button.setText("Copy and Close");
 | 
						|
            button.onClickEvent(() => {
 | 
						|
                navigator.clipboard.writeText("```json\n" + text + "\n```");
 | 
						|
                this.close();
 | 
						|
            });
 | 
						|
        });
 | 
						|
    }
 | 
						|
}
 | 
						|
class SystemInfo {
 | 
						|
    constructor(plugin, settings) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.callback = () => {
 | 
						|
            const modal = new SystemInfoModal(this.plugin.app, this.settings);
 | 
						|
            modal.open();
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.addCommand({
 | 
						|
                id: "system-info",
 | 
						|
                name: "Show System Info",
 | 
						|
                callback: this.callback,
 | 
						|
                hotkeys: [
 | 
						|
                    {
 | 
						|
                        modifiers: ["Mod", "Shift", "Alt"],
 | 
						|
                        key: "I",
 | 
						|
                    },
 | 
						|
                ],
 | 
						|
            });
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class TabBehaviourOverride {
 | 
						|
    constructor(plugin, imeDetector, obsidianSettings, settings, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.imeDetector = imeDetector;
 | 
						|
        this.obsidianSettings = obsidianSettings;
 | 
						|
        this.settings = settings;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.check = () => {
 | 
						|
            return this.settings.overrideTabBehaviour && !this.imeDetector.isOpened();
 | 
						|
        };
 | 
						|
        this.run = (editor) => {
 | 
						|
            return this.operationPerformer.perform((root) => new IndentList(root, this.obsidianSettings.getDefaultIndentChars()), editor);
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.plugin.registerEditorExtension(state.Prec.highest(view.keymap.of([
 | 
						|
                {
 | 
						|
                    key: "Tab",
 | 
						|
                    run: createKeymapRunCallback({
 | 
						|
                        check: this.check,
 | 
						|
                        run: this.run,
 | 
						|
                    }),
 | 
						|
                },
 | 
						|
            ])));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () { });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const VERTICAL_LINES_BODY_CLASS = "outliner-plugin-vertical-lines";
 | 
						|
class VerticalLinesPluginValue {
 | 
						|
    constructor(settings, obsidianSettings, parser, view) {
 | 
						|
        this.settings = settings;
 | 
						|
        this.obsidianSettings = obsidianSettings;
 | 
						|
        this.parser = parser;
 | 
						|
        this.view = view;
 | 
						|
        this.lineElements = [];
 | 
						|
        this.waitForEditor = () => {
 | 
						|
            const editor = getEditorFromState(this.view.state);
 | 
						|
            if (!editor) {
 | 
						|
                setTimeout(this.waitForEditor, 0);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            this.editor = editor;
 | 
						|
            this.scheduleRecalculate();
 | 
						|
        };
 | 
						|
        this.onScroll = (e) => {
 | 
						|
            const { scrollLeft, scrollTop } = e.target;
 | 
						|
            this.scroller.scrollTo(scrollLeft, scrollTop);
 | 
						|
        };
 | 
						|
        this.scheduleRecalculate = () => {
 | 
						|
            clearTimeout(this.scheduled);
 | 
						|
            this.scheduled = setTimeout(this.calculate, 0);
 | 
						|
        };
 | 
						|
        this.calculate = () => {
 | 
						|
            this.lines = [];
 | 
						|
            if (this.settings.verticalLines &&
 | 
						|
                this.obsidianSettings.isDefaultThemeEnabled() &&
 | 
						|
                this.view.viewportLineBlocks.length > 0 &&
 | 
						|
                this.view.visibleRanges.length > 0) {
 | 
						|
                const fromLine = this.editor.offsetToPos(this.view.viewport.from).line;
 | 
						|
                const toLine = this.editor.offsetToPos(this.view.viewport.to).line;
 | 
						|
                const lists = this.parser.parseRange(this.editor, fromLine, toLine);
 | 
						|
                for (const list of lists) {
 | 
						|
                    this.lastLine = list.getContentEnd().line;
 | 
						|
                    for (const c of list.getChildren()) {
 | 
						|
                        this.recursive(c);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                this.lines.sort((a, b) => a.top === b.top ? a.left - b.left : a.top - b.top);
 | 
						|
            }
 | 
						|
            this.updateDom();
 | 
						|
        };
 | 
						|
        this.onClick = (e) => {
 | 
						|
            e.preventDefault();
 | 
						|
            const line = this.lines[Number(e.target.dataset.index)];
 | 
						|
            switch (this.settings.verticalLinesAction) {
 | 
						|
                case "zoom-in":
 | 
						|
                    this.zoomIn(line);
 | 
						|
                    break;
 | 
						|
                case "toggle-folding":
 | 
						|
                    this.toggleFolding(line);
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
        };
 | 
						|
        this.view.scrollDOM.addEventListener("scroll", this.onScroll);
 | 
						|
        this.settings.onChange(this.scheduleRecalculate);
 | 
						|
        this.prepareDom();
 | 
						|
        this.waitForEditor();
 | 
						|
    }
 | 
						|
    prepareDom() {
 | 
						|
        this.contentContainer = document.createElement("div");
 | 
						|
        this.contentContainer.classList.add("outliner-plugin-list-lines-content-container");
 | 
						|
        this.scroller = document.createElement("div");
 | 
						|
        this.scroller.classList.add("outliner-plugin-list-lines-scroller");
 | 
						|
        this.scroller.appendChild(this.contentContainer);
 | 
						|
        this.view.dom.appendChild(this.scroller);
 | 
						|
    }
 | 
						|
    update(update) {
 | 
						|
        if (update.docChanged ||
 | 
						|
            update.viewportChanged ||
 | 
						|
            update.geometryChanged ||
 | 
						|
            update.transactions.some((tr) => tr.reconfigured)) {
 | 
						|
            this.scheduleRecalculate();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    getNextSibling(list) {
 | 
						|
        let listTmp = list;
 | 
						|
        let p = listTmp.getParent();
 | 
						|
        while (p) {
 | 
						|
            const nextSibling = p.getNextSiblingOf(listTmp);
 | 
						|
            if (nextSibling) {
 | 
						|
                return nextSibling;
 | 
						|
            }
 | 
						|
            listTmp = p;
 | 
						|
            p = listTmp.getParent();
 | 
						|
        }
 | 
						|
        return null;
 | 
						|
    }
 | 
						|
    recursive(list, parentCtx = {}) {
 | 
						|
        const children = list.getChildren();
 | 
						|
        if (children.length === 0) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const fromOffset = this.editor.posToOffset({
 | 
						|
            line: list.getFirstLineContentStart().line,
 | 
						|
            ch: list.getFirstLineIndent().length,
 | 
						|
        });
 | 
						|
        const nextSibling = this.getNextSibling(list);
 | 
						|
        const tillOffset = this.editor.posToOffset({
 | 
						|
            line: nextSibling
 | 
						|
                ? nextSibling.getFirstLineContentStart().line - 1
 | 
						|
                : this.lastLine,
 | 
						|
            ch: 0,
 | 
						|
        });
 | 
						|
        let visibleFrom = this.view.visibleRanges[0].from;
 | 
						|
        let visibleTo = this.view.visibleRanges[this.view.visibleRanges.length - 1].to;
 | 
						|
        const zoomRange = this.editor.getZoomRange();
 | 
						|
        if (zoomRange) {
 | 
						|
            visibleFrom = Math.max(visibleFrom, this.editor.posToOffset(zoomRange.from));
 | 
						|
            visibleTo = Math.min(visibleTo, this.editor.posToOffset(zoomRange.to));
 | 
						|
        }
 | 
						|
        if (fromOffset > visibleTo || tillOffset < visibleFrom) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        const coords = this.view.coordsAtPos(fromOffset, 1);
 | 
						|
        if (parentCtx.rootLeft === undefined) {
 | 
						|
            parentCtx.rootLeft = coords.left;
 | 
						|
        }
 | 
						|
        const left = Math.floor(coords.right - parentCtx.rootLeft);
 | 
						|
        const top = visibleFrom > 0 && fromOffset < visibleFrom
 | 
						|
            ? -20
 | 
						|
            : this.view.lineBlockAt(fromOffset).top;
 | 
						|
        const bottom = tillOffset > visibleTo
 | 
						|
            ? this.view.lineBlockAt(visibleTo - 1).bottom
 | 
						|
            : this.view.lineBlockAt(tillOffset).bottom;
 | 
						|
        const height = bottom - top;
 | 
						|
        if (height > 0 && !list.isFolded()) {
 | 
						|
            const nextSibling = list.getParent().getNextSiblingOf(list);
 | 
						|
            const hasNextSibling = !!nextSibling &&
 | 
						|
                this.editor.posToOffset(nextSibling.getFirstLineContentStart()) <=
 | 
						|
                    visibleTo;
 | 
						|
            this.lines.push({
 | 
						|
                top,
 | 
						|
                left,
 | 
						|
                height: `calc(${height}px ${hasNextSibling ? "- 1.5em" : "- 2em"})`,
 | 
						|
                list,
 | 
						|
            });
 | 
						|
        }
 | 
						|
        for (const child of children) {
 | 
						|
            if (!child.isEmpty()) {
 | 
						|
                this.recursive(child, parentCtx);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    zoomIn(line) {
 | 
						|
        const editor = getEditorFromState(this.view.state);
 | 
						|
        editor.zoomIn(line.list.getFirstLineContentStart().line);
 | 
						|
    }
 | 
						|
    toggleFolding(line) {
 | 
						|
        const { list } = line;
 | 
						|
        if (list.isEmpty()) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        let needToUnfold = true;
 | 
						|
        const linesToToggle = [];
 | 
						|
        for (const c of list.getChildren()) {
 | 
						|
            if (c.isEmpty()) {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            if (!c.isFolded()) {
 | 
						|
                needToUnfold = false;
 | 
						|
            }
 | 
						|
            linesToToggle.push(c.getFirstLineContentStart().line);
 | 
						|
        }
 | 
						|
        const editor = getEditorFromState(this.view.state);
 | 
						|
        for (const l of linesToToggle) {
 | 
						|
            if (needToUnfold) {
 | 
						|
                editor.unfold(l);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                editor.fold(l);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    updateDom() {
 | 
						|
        const cmScroll = this.view.scrollDOM;
 | 
						|
        const cmContent = this.view.contentDOM;
 | 
						|
        const cmContentContainer = cmContent.parentElement;
 | 
						|
        const cmSizer = cmContentContainer.parentElement;
 | 
						|
        /**
 | 
						|
         * Obsidian can add additional elements into Content Manager.
 | 
						|
         * The most obvious case is the 'embedded-backlinks' core plugin that adds a menu inside a Content Manager.
 | 
						|
         * We must take heights of all of these elements into account
 | 
						|
         * to be able to calculate the correct size of lines' container.
 | 
						|
         */
 | 
						|
        let cmSizerChildrenSumHeight = 0;
 | 
						|
        for (let i = 0; i < cmSizer.children.length; i++) {
 | 
						|
            cmSizerChildrenSumHeight += cmSizer.children[i].clientHeight;
 | 
						|
        }
 | 
						|
        this.scroller.style.top = cmScroll.offsetTop + "px";
 | 
						|
        this.contentContainer.style.height = cmSizerChildrenSumHeight + "px";
 | 
						|
        this.contentContainer.style.marginLeft =
 | 
						|
            cmContentContainer.offsetLeft + "px";
 | 
						|
        this.contentContainer.style.marginTop =
 | 
						|
            cmContent.firstElementChild.offsetTop - 24 + "px";
 | 
						|
        for (let i = 0; i < this.lines.length; i++) {
 | 
						|
            if (this.lineElements.length === i) {
 | 
						|
                const e = document.createElement("div");
 | 
						|
                e.classList.add("outliner-plugin-list-line");
 | 
						|
                e.dataset.index = String(i);
 | 
						|
                e.addEventListener("mousedown", this.onClick);
 | 
						|
                this.contentContainer.appendChild(e);
 | 
						|
                this.lineElements.push(e);
 | 
						|
            }
 | 
						|
            const l = this.lines[i];
 | 
						|
            const e = this.lineElements[i];
 | 
						|
            e.style.top = l.top + "px";
 | 
						|
            e.style.left = l.left + "px";
 | 
						|
            e.style.height = l.height;
 | 
						|
            e.style.display = "block";
 | 
						|
        }
 | 
						|
        for (let i = this.lines.length; i < this.lineElements.length; i++) {
 | 
						|
            const e = this.lineElements[i];
 | 
						|
            e.style.top = "0px";
 | 
						|
            e.style.left = "0px";
 | 
						|
            e.style.height = "0px";
 | 
						|
            e.style.display = "none";
 | 
						|
        }
 | 
						|
    }
 | 
						|
    destroy() {
 | 
						|
        this.settings.removeCallback(this.scheduleRecalculate);
 | 
						|
        this.view.scrollDOM.removeEventListener("scroll", this.onScroll);
 | 
						|
        this.view.dom.removeChild(this.scroller);
 | 
						|
        clearTimeout(this.scheduled);
 | 
						|
    }
 | 
						|
}
 | 
						|
class VerticalLines {
 | 
						|
    constructor(plugin, settings, obsidianSettings, parser) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.obsidianSettings = obsidianSettings;
 | 
						|
        this.parser = parser;
 | 
						|
        this.updateBodyClass = () => {
 | 
						|
            const shouldExists = this.obsidianSettings.isDefaultThemeEnabled() &&
 | 
						|
                this.settings.verticalLines;
 | 
						|
            const exists = document.body.classList.contains(VERTICAL_LINES_BODY_CLASS);
 | 
						|
            if (shouldExists && !exists) {
 | 
						|
                document.body.classList.add(VERTICAL_LINES_BODY_CLASS);
 | 
						|
            }
 | 
						|
            if (!shouldExists && exists) {
 | 
						|
                document.body.classList.remove(VERTICAL_LINES_BODY_CLASS);
 | 
						|
            }
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.updateBodyClass();
 | 
						|
            this.updateBodyClassInterval = window.setInterval(() => {
 | 
						|
                this.updateBodyClass();
 | 
						|
            }, 1000);
 | 
						|
            this.plugin.registerEditorExtension(view.ViewPlugin.define((view) => new VerticalLinesPluginValue(this.settings, this.obsidianSettings, this.parser, view)));
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            clearInterval(this.updateBodyClassInterval);
 | 
						|
            document.body.classList.remove(VERTICAL_LINES_BODY_CLASS);
 | 
						|
        });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class VimOBehaviourOverride {
 | 
						|
    constructor(plugin, settings, obsidianSettings, parser, operationPerformer) {
 | 
						|
        this.plugin = plugin;
 | 
						|
        this.settings = settings;
 | 
						|
        this.obsidianSettings = obsidianSettings;
 | 
						|
        this.parser = parser;
 | 
						|
        this.operationPerformer = operationPerformer;
 | 
						|
        this.inited = false;
 | 
						|
        this.handleSettingsChange = () => {
 | 
						|
            if (!this.settings.overrideVimOBehaviour) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            if (!window.CodeMirrorAdapter || !window.CodeMirrorAdapter.Vim) {
 | 
						|
                console.error("Vim adapter not found");
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            const vim = window.CodeMirrorAdapter.Vim;
 | 
						|
            const plugin = this.plugin;
 | 
						|
            const parser = this.parser;
 | 
						|
            const obsidianSettings = this.obsidianSettings;
 | 
						|
            const operationPerformer = this.operationPerformer;
 | 
						|
            const settings = this.settings;
 | 
						|
            vim.defineAction("insertLineAfterBullet", (cm, operatorArgs) => {
 | 
						|
                // Move the cursor to the end of the line
 | 
						|
                vim.handleEx(cm, "normal! A");
 | 
						|
                if (!settings.overrideVimOBehaviour) {
 | 
						|
                    if (operatorArgs.after) {
 | 
						|
                        vim.handleEx(cm, "normal! o");
 | 
						|
                    }
 | 
						|
                    else {
 | 
						|
                        vim.handleEx(cm, "normal! O");
 | 
						|
                    }
 | 
						|
                    vim.enterInsertMode(cm);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                const view = plugin.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
 | 
						|
                const editor = new MyEditor(view.editor);
 | 
						|
                const root = parser.parse(editor);
 | 
						|
                if (!root) {
 | 
						|
                    if (operatorArgs.after) {
 | 
						|
                        vim.handleEx(cm, "normal! o");
 | 
						|
                    }
 | 
						|
                    else {
 | 
						|
                        vim.handleEx(cm, "normal! O");
 | 
						|
                    }
 | 
						|
                    vim.enterInsertMode(cm);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                const defaultIndentChars = obsidianSettings.getDefaultIndentChars();
 | 
						|
                const zoomRange = editor.getZoomRange();
 | 
						|
                const getZoomRange = {
 | 
						|
                    getZoomRange: () => zoomRange,
 | 
						|
                };
 | 
						|
                const res = operationPerformer.eval(root, new CreateNewItem(root, defaultIndentChars, getZoomRange, operatorArgs.after), editor);
 | 
						|
                if (res.shouldUpdate && zoomRange) {
 | 
						|
                    editor.tryRefreshZoom(zoomRange.from.line);
 | 
						|
                }
 | 
						|
                // Ensure the editor is always left in insert mode
 | 
						|
                vim.enterInsertMode(cm);
 | 
						|
            });
 | 
						|
            vim.mapCommand("o", "action", "insertLineAfterBullet", {}, {
 | 
						|
                isEdit: true,
 | 
						|
                context: "normal",
 | 
						|
                interlaceInsertRepeat: true,
 | 
						|
                actionArgs: { after: true },
 | 
						|
            });
 | 
						|
            vim.mapCommand("O", "action", "insertLineAfterBullet", {}, {
 | 
						|
                isEdit: true,
 | 
						|
                context: "normal",
 | 
						|
                interlaceInsertRepeat: true,
 | 
						|
                actionArgs: { after: false },
 | 
						|
            });
 | 
						|
            this.inited = true;
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.settings.onChange(this.handleSettingsChange);
 | 
						|
            this.handleSettingsChange();
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            if (!this.inited) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            new obsidian.Notice(`To fully unload obsidian-outliner plugin, please restart the app`, 5000);
 | 
						|
        });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class ChangesApplicator {
 | 
						|
    apply(editor, prevRoot, newRoot) {
 | 
						|
        const changes = this.calculateChanges(editor, prevRoot, newRoot);
 | 
						|
        if (changes) {
 | 
						|
            const { replacement, changeFrom, changeTo } = changes;
 | 
						|
            const { unfold, fold } = this.calculateFoldingOprations(prevRoot, newRoot, changeFrom, changeTo);
 | 
						|
            for (const line of unfold) {
 | 
						|
                editor.unfold(line);
 | 
						|
            }
 | 
						|
            editor.replaceRange(replacement, changeFrom, changeTo);
 | 
						|
            for (const line of fold) {
 | 
						|
                editor.fold(line);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        editor.setSelections(newRoot.getSelections());
 | 
						|
    }
 | 
						|
    calculateChanges(editor, prevRoot, newRoot) {
 | 
						|
        const rootRange = prevRoot.getContentRange();
 | 
						|
        const oldString = editor.getRange(rootRange[0], rootRange[1]);
 | 
						|
        const newString = newRoot.print();
 | 
						|
        const changeFrom = Object.assign({}, rootRange[0]);
 | 
						|
        const changeTo = Object.assign({}, rootRange[1]);
 | 
						|
        let oldTmp = oldString;
 | 
						|
        let newTmp = newString;
 | 
						|
        while (true) {
 | 
						|
            const nlIndex = oldTmp.lastIndexOf("\n");
 | 
						|
            if (nlIndex < 0) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            const oldLine = oldTmp.slice(nlIndex);
 | 
						|
            const newLine = newTmp.slice(-oldLine.length);
 | 
						|
            if (oldLine !== newLine) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            oldTmp = oldTmp.slice(0, -oldLine.length);
 | 
						|
            newTmp = newTmp.slice(0, -oldLine.length);
 | 
						|
            const nlIndex2 = oldTmp.lastIndexOf("\n");
 | 
						|
            changeTo.ch =
 | 
						|
                nlIndex2 >= 0 ? oldTmp.length - nlIndex2 - 1 : oldTmp.length;
 | 
						|
            changeTo.line--;
 | 
						|
        }
 | 
						|
        while (true) {
 | 
						|
            const nlIndex = oldTmp.indexOf("\n");
 | 
						|
            if (nlIndex < 0) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            const oldLine = oldTmp.slice(0, nlIndex + 1);
 | 
						|
            const newLine = newTmp.slice(0, oldLine.length);
 | 
						|
            if (oldLine !== newLine) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            changeFrom.line++;
 | 
						|
            oldTmp = oldTmp.slice(oldLine.length);
 | 
						|
            newTmp = newTmp.slice(oldLine.length);
 | 
						|
        }
 | 
						|
        if (oldTmp === newTmp) {
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
        return {
 | 
						|
            replacement: newTmp,
 | 
						|
            changeFrom,
 | 
						|
            changeTo,
 | 
						|
        };
 | 
						|
    }
 | 
						|
    calculateFoldingOprations(prevRoot, newRoot, changeFrom, changeTo) {
 | 
						|
        const changedRange = [changeFrom, changeTo];
 | 
						|
        const prevLists = getAllChildren(prevRoot);
 | 
						|
        const newLists = getAllChildren(newRoot);
 | 
						|
        const unfold = [];
 | 
						|
        const fold = [];
 | 
						|
        for (const prevList of prevLists.values()) {
 | 
						|
            if (!prevList.isFoldRoot()) {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            const newList = newLists.get(prevList.getID());
 | 
						|
            if (!newList) {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            const prevListRange = [
 | 
						|
                prevList.getFirstLineContentStart(),
 | 
						|
                prevList.getContentEndIncludingChildren(),
 | 
						|
            ];
 | 
						|
            if (isRangesIntersects(prevListRange, changedRange)) {
 | 
						|
                unfold.push(prevList.getFirstLineContentStart().line);
 | 
						|
                fold.push(newList.getFirstLineContentStart().line);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unfold.sort((a, b) => b - a);
 | 
						|
        fold.sort((a, b) => b - a);
 | 
						|
        return { unfold, fold };
 | 
						|
    }
 | 
						|
}
 | 
						|
function getAllChildrenReduceFn(acc, child) {
 | 
						|
    acc.set(child.getID(), child);
 | 
						|
    child.getChildren().reduce(getAllChildrenReduceFn, acc);
 | 
						|
    return acc;
 | 
						|
}
 | 
						|
function getAllChildren(root) {
 | 
						|
    return root.getChildren().reduce(getAllChildrenReduceFn, new Map());
 | 
						|
}
 | 
						|
 | 
						|
class IMEDetector {
 | 
						|
    constructor() {
 | 
						|
        this.composition = false;
 | 
						|
        this.onCompositionStart = () => {
 | 
						|
            this.composition = true;
 | 
						|
        };
 | 
						|
        this.onCompositionEnd = () => {
 | 
						|
            this.composition = false;
 | 
						|
        };
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            document.addEventListener("compositionstart", this.onCompositionStart);
 | 
						|
            document.addEventListener("compositionend", this.onCompositionEnd);
 | 
						|
        });
 | 
						|
    }
 | 
						|
    unload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            document.removeEventListener("compositionend", this.onCompositionEnd);
 | 
						|
            document.removeEventListener("compositionstart", this.onCompositionStart);
 | 
						|
        });
 | 
						|
    }
 | 
						|
    isOpened() {
 | 
						|
        return this.composition && obsidian.Platform.isDesktop;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class Logger {
 | 
						|
    constructor(settings) {
 | 
						|
        this.settings = settings;
 | 
						|
    }
 | 
						|
    log(method, ...args) {
 | 
						|
        if (!this.settings.debug) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        console.info(method, ...args);
 | 
						|
    }
 | 
						|
    bind(method) {
 | 
						|
        return (...args) => this.log(method, ...args);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function getHiddenObsidianConfig(app) {
 | 
						|
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
						|
    return app.vault.config;
 | 
						|
}
 | 
						|
class ObsidianSettings {
 | 
						|
    constructor(app) {
 | 
						|
        this.app = app;
 | 
						|
    }
 | 
						|
    isLegacyEditorEnabled() {
 | 
						|
        const config = Object.assign({ legacyEditor: false }, getHiddenObsidianConfig(this.app));
 | 
						|
        return config.legacyEditor;
 | 
						|
    }
 | 
						|
    isDefaultThemeEnabled() {
 | 
						|
        const config = Object.assign({ cssTheme: "" }, getHiddenObsidianConfig(this.app));
 | 
						|
        return config.cssTheme === "";
 | 
						|
    }
 | 
						|
    getTabsSettings() {
 | 
						|
        return Object.assign({ useTab: true, tabSize: 4 }, getHiddenObsidianConfig(this.app));
 | 
						|
    }
 | 
						|
    getFoldSettings() {
 | 
						|
        return Object.assign({ foldIndent: true }, getHiddenObsidianConfig(this.app));
 | 
						|
    }
 | 
						|
    getDefaultIndentChars() {
 | 
						|
        const { useTab, tabSize } = this.getTabsSettings();
 | 
						|
        return useTab ? "\t" : new Array(tabSize).fill(" ").join("");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class OperationPerformer {
 | 
						|
    constructor(parser, changesApplicator) {
 | 
						|
        this.parser = parser;
 | 
						|
        this.changesApplicator = changesApplicator;
 | 
						|
    }
 | 
						|
    eval(root, op, editor) {
 | 
						|
        const prevRoot = root.clone();
 | 
						|
        op.perform();
 | 
						|
        if (op.shouldUpdate()) {
 | 
						|
            this.changesApplicator.apply(editor, prevRoot, root);
 | 
						|
        }
 | 
						|
        return {
 | 
						|
            shouldUpdate: op.shouldUpdate(),
 | 
						|
            shouldStopPropagation: op.shouldStopPropagation(),
 | 
						|
        };
 | 
						|
    }
 | 
						|
    perform(cb, editor, cursor = editor.getCursor()) {
 | 
						|
        const root = this.parser.parse(editor, cursor);
 | 
						|
        if (!root) {
 | 
						|
            return { shouldUpdate: false, shouldStopPropagation: false };
 | 
						|
        }
 | 
						|
        const op = cb(root);
 | 
						|
        return this.eval(root, op, editor);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const bulletSignRe = `(?:[-*+]|\\d+\\.)`;
 | 
						|
const optionalCheckboxRe = `(?:${checkboxRe})?`;
 | 
						|
const listItemWithoutSpacesRe = new RegExp(`^${bulletSignRe}( |\t)`);
 | 
						|
const listItemRe = new RegExp(`^[ \t]*${bulletSignRe}( |\t)`);
 | 
						|
const stringWithSpacesRe = new RegExp(`^[ \t]+`);
 | 
						|
const parseListItemRe = new RegExp(`^([ \t]*)(${bulletSignRe})( |\t)(${optionalCheckboxRe})(.*)$`);
 | 
						|
class Parser {
 | 
						|
    constructor(logger, settings) {
 | 
						|
        this.logger = logger;
 | 
						|
        this.settings = settings;
 | 
						|
    }
 | 
						|
    parseRange(editor, fromLine = 0, toLine = editor.lastLine()) {
 | 
						|
        const lists = [];
 | 
						|
        for (let i = fromLine; i <= toLine; i++) {
 | 
						|
            const line = editor.getLine(i);
 | 
						|
            if (i === fromLine || this.isListItem(line)) {
 | 
						|
                const list = this.parseWithLimits(editor, i, fromLine, toLine);
 | 
						|
                if (list) {
 | 
						|
                    lists.push(list);
 | 
						|
                    i = list.getContentEnd().line;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return lists;
 | 
						|
    }
 | 
						|
    parse(editor, cursor = editor.getCursor()) {
 | 
						|
        return this.parseWithLimits(editor, cursor.line, 0, editor.lastLine());
 | 
						|
    }
 | 
						|
    parseWithLimits(editor, parsingStartLine, limitFrom, limitTo) {
 | 
						|
        const d = this.logger.bind("parseList");
 | 
						|
        const error = (msg) => {
 | 
						|
            d(msg);
 | 
						|
            return null;
 | 
						|
        };
 | 
						|
        const line = editor.getLine(parsingStartLine);
 | 
						|
        let listLookingPos = null;
 | 
						|
        if (this.isListItem(line)) {
 | 
						|
            listLookingPos = parsingStartLine;
 | 
						|
        }
 | 
						|
        else if (this.isLineWithIndent(line)) {
 | 
						|
            let listLookingPosSearch = parsingStartLine - 1;
 | 
						|
            while (listLookingPosSearch >= 0) {
 | 
						|
                const line = editor.getLine(listLookingPosSearch);
 | 
						|
                if (this.isListItem(line)) {
 | 
						|
                    listLookingPos = listLookingPosSearch;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                else if (this.isLineWithIndent(line)) {
 | 
						|
                    listLookingPosSearch--;
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (listLookingPos === null) {
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
        let listStartLine = null;
 | 
						|
        let listStartLineLookup = listLookingPos;
 | 
						|
        while (listStartLineLookup >= 0) {
 | 
						|
            const line = editor.getLine(listStartLineLookup);
 | 
						|
            if (!this.isListItem(line) && !this.isLineWithIndent(line)) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            if (this.isListItemWithoutSpaces(line)) {
 | 
						|
                listStartLine = listStartLineLookup;
 | 
						|
                if (listStartLineLookup <= limitFrom) {
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            listStartLineLookup--;
 | 
						|
        }
 | 
						|
        if (listStartLine === null) {
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
        let listEndLine = listLookingPos;
 | 
						|
        let listEndLineLookup = listLookingPos;
 | 
						|
        while (listEndLineLookup <= editor.lastLine()) {
 | 
						|
            const line = editor.getLine(listEndLineLookup);
 | 
						|
            if (!this.isListItem(line) && !this.isLineWithIndent(line)) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            if (!this.isEmptyLine(line)) {
 | 
						|
                listEndLine = listEndLineLookup;
 | 
						|
            }
 | 
						|
            if (listEndLineLookup >= limitTo) {
 | 
						|
                listEndLine = limitTo;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            listEndLineLookup++;
 | 
						|
        }
 | 
						|
        if (listStartLine > parsingStartLine || listEndLine < parsingStartLine) {
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
        // if the last line contains only spaces and that's incorrect indent, then ignore the last line
 | 
						|
        // https://github.com/vslinko/obsidian-outliner/issues/368
 | 
						|
        if (listEndLine > listStartLine) {
 | 
						|
            const lastLine = editor.getLine(listEndLine);
 | 
						|
            if (lastLine.trim().length === 0) {
 | 
						|
                const prevLine = editor.getLine(listEndLine - 1);
 | 
						|
                const [, prevLineIndent] = /^(\s*)/.exec(prevLine);
 | 
						|
                if (!lastLine.startsWith(prevLineIndent)) {
 | 
						|
                    listEndLine--;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        const root = new Root({ line: listStartLine, ch: 0 }, { line: listEndLine, ch: editor.getLine(listEndLine).length }, editor.listSelections().map((r) => ({
 | 
						|
            anchor: { line: r.anchor.line, ch: r.anchor.ch },
 | 
						|
            head: { line: r.head.line, ch: r.head.ch },
 | 
						|
        })));
 | 
						|
        let currentParent = root.getRootList();
 | 
						|
        let currentList = null;
 | 
						|
        let currentIndent = "";
 | 
						|
        const foldedLines = editor.getAllFoldedLines();
 | 
						|
        for (let l = listStartLine; l <= listEndLine; l++) {
 | 
						|
            const line = editor.getLine(l);
 | 
						|
            const matches = parseListItemRe.exec(line);
 | 
						|
            if (matches) {
 | 
						|
                const [, indent, bullet, spaceAfterBullet] = matches;
 | 
						|
                let [, , , , optionalCheckbox, content] = matches;
 | 
						|
                content = optionalCheckbox + content;
 | 
						|
                if (this.settings.keepCursorWithinContent !== "bullet-and-checkbox") {
 | 
						|
                    optionalCheckbox = "";
 | 
						|
                }
 | 
						|
                const compareLength = Math.min(currentIndent.length, indent.length);
 | 
						|
                const indentSlice = indent.slice(0, compareLength);
 | 
						|
                const currentIndentSlice = currentIndent.slice(0, compareLength);
 | 
						|
                if (indentSlice !== currentIndentSlice) {
 | 
						|
                    const expected = currentIndentSlice
 | 
						|
                        .replace(/ /g, "S")
 | 
						|
                        .replace(/\t/g, "T");
 | 
						|
                    const got = indentSlice.replace(/ /g, "S").replace(/\t/g, "T");
 | 
						|
                    return error(`Unable to parse list: expected indent "${expected}", got "${got}"`);
 | 
						|
                }
 | 
						|
                if (indent.length > currentIndent.length) {
 | 
						|
                    currentParent = currentList;
 | 
						|
                    currentIndent = indent;
 | 
						|
                }
 | 
						|
                else if (indent.length < currentIndent.length) {
 | 
						|
                    while (currentParent.getFirstLineIndent().length >= indent.length &&
 | 
						|
                        currentParent.getParent()) {
 | 
						|
                        currentParent = currentParent.getParent();
 | 
						|
                    }
 | 
						|
                    currentIndent = indent;
 | 
						|
                }
 | 
						|
                const foldRoot = foldedLines.includes(l);
 | 
						|
                currentList = new List(root, indent, bullet, optionalCheckbox, spaceAfterBullet, content, foldRoot);
 | 
						|
                currentParent.addAfterAll(currentList);
 | 
						|
            }
 | 
						|
            else if (this.isLineWithIndent(line)) {
 | 
						|
                if (!currentList) {
 | 
						|
                    return error(`Unable to parse list: expected list item, got empty line`);
 | 
						|
                }
 | 
						|
                const indentToCheck = currentList.getNotesIndent() || currentIndent;
 | 
						|
                if (line.indexOf(indentToCheck) !== 0) {
 | 
						|
                    const expected = indentToCheck.replace(/ /g, "S").replace(/\t/g, "T");
 | 
						|
                    const got = line
 | 
						|
                        .match(/^[ \t]*/)[0]
 | 
						|
                        .replace(/ /g, "S")
 | 
						|
                        .replace(/\t/g, "T");
 | 
						|
                    return error(`Unable to parse list: expected indent "${expected}", got "${got}"`);
 | 
						|
                }
 | 
						|
                if (!currentList.getNotesIndent()) {
 | 
						|
                    const matches = line.match(/^[ \t]+/);
 | 
						|
                    if (!matches || matches[0].length <= currentIndent.length) {
 | 
						|
                        if (/^\s+$/.test(line)) {
 | 
						|
                            continue;
 | 
						|
                        }
 | 
						|
                        return error(`Unable to parse list: expected some indent, got no indent`);
 | 
						|
                    }
 | 
						|
                    currentList.setNotesIndent(matches[0]);
 | 
						|
                }
 | 
						|
                currentList.addLine(line.slice(currentList.getNotesIndent().length));
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                return error(`Unable to parse list: expected list item or note, got "${line}"`);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return root;
 | 
						|
    }
 | 
						|
    isEmptyLine(line) {
 | 
						|
        return line.length === 0;
 | 
						|
    }
 | 
						|
    isLineWithIndent(line) {
 | 
						|
        return stringWithSpacesRe.test(line);
 | 
						|
    }
 | 
						|
    isListItem(line) {
 | 
						|
        return listItemRe.test(line);
 | 
						|
    }
 | 
						|
    isListItemWithoutSpaces(line) {
 | 
						|
        return listItemWithoutSpacesRe.test(line);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const DEFAULT_SETTINGS = {
 | 
						|
    styleLists: true,
 | 
						|
    debug: false,
 | 
						|
    stickCursor: "bullet-and-checkbox",
 | 
						|
    betterEnter: true,
 | 
						|
    betterVimO: true,
 | 
						|
    betterTab: true,
 | 
						|
    selectAll: true,
 | 
						|
    listLines: false,
 | 
						|
    listLineAction: "toggle-folding",
 | 
						|
    dnd: true,
 | 
						|
    previousRelease: null,
 | 
						|
};
 | 
						|
class Settings {
 | 
						|
    constructor(storage) {
 | 
						|
        this.storage = storage;
 | 
						|
        this.callbacks = new Set();
 | 
						|
    }
 | 
						|
    get keepCursorWithinContent() {
 | 
						|
        // Adaptor for users migrating from older version of the plugin.
 | 
						|
        if (this.values.stickCursor === true) {
 | 
						|
            return "bullet-and-checkbox";
 | 
						|
        }
 | 
						|
        else if (this.values.stickCursor === false) {
 | 
						|
            return "never";
 | 
						|
        }
 | 
						|
        return this.values.stickCursor;
 | 
						|
    }
 | 
						|
    set keepCursorWithinContent(value) {
 | 
						|
        this.set("stickCursor", value);
 | 
						|
    }
 | 
						|
    get overrideTabBehaviour() {
 | 
						|
        return this.values.betterTab;
 | 
						|
    }
 | 
						|
    set overrideTabBehaviour(value) {
 | 
						|
        this.set("betterTab", value);
 | 
						|
    }
 | 
						|
    get overrideEnterBehaviour() {
 | 
						|
        return this.values.betterEnter;
 | 
						|
    }
 | 
						|
    set overrideEnterBehaviour(value) {
 | 
						|
        this.set("betterEnter", value);
 | 
						|
    }
 | 
						|
    get overrideVimOBehaviour() {
 | 
						|
        return this.values.betterVimO;
 | 
						|
    }
 | 
						|
    set overrideVimOBehaviour(value) {
 | 
						|
        this.set("betterVimO", value);
 | 
						|
    }
 | 
						|
    get overrideSelectAllBehaviour() {
 | 
						|
        return this.values.selectAll;
 | 
						|
    }
 | 
						|
    set overrideSelectAllBehaviour(value) {
 | 
						|
        this.set("selectAll", value);
 | 
						|
    }
 | 
						|
    get betterListsStyles() {
 | 
						|
        return this.values.styleLists;
 | 
						|
    }
 | 
						|
    set betterListsStyles(value) {
 | 
						|
        this.set("styleLists", value);
 | 
						|
    }
 | 
						|
    get verticalLines() {
 | 
						|
        return this.values.listLines;
 | 
						|
    }
 | 
						|
    set verticalLines(value) {
 | 
						|
        this.set("listLines", value);
 | 
						|
    }
 | 
						|
    get verticalLinesAction() {
 | 
						|
        return this.values.listLineAction;
 | 
						|
    }
 | 
						|
    set verticalLinesAction(value) {
 | 
						|
        this.set("listLineAction", value);
 | 
						|
    }
 | 
						|
    get dragAndDrop() {
 | 
						|
        return this.values.dnd;
 | 
						|
    }
 | 
						|
    set dragAndDrop(value) {
 | 
						|
        this.set("dnd", value);
 | 
						|
    }
 | 
						|
    get debug() {
 | 
						|
        return this.values.debug;
 | 
						|
    }
 | 
						|
    set debug(value) {
 | 
						|
        this.set("debug", value);
 | 
						|
    }
 | 
						|
    get previousRelease() {
 | 
						|
        return this.values.previousRelease;
 | 
						|
    }
 | 
						|
    set previousRelease(value) {
 | 
						|
        this.set("previousRelease", value);
 | 
						|
    }
 | 
						|
    onChange(cb) {
 | 
						|
        this.callbacks.add(cb);
 | 
						|
    }
 | 
						|
    removeCallback(cb) {
 | 
						|
        this.callbacks.delete(cb);
 | 
						|
    }
 | 
						|
    reset() {
 | 
						|
        for (const [k, v] of Object.entries(DEFAULT_SETTINGS)) {
 | 
						|
            this.set(k, v);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    load() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.values = Object.assign({}, DEFAULT_SETTINGS, yield this.storage.loadData());
 | 
						|
        });
 | 
						|
    }
 | 
						|
    save() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            yield this.storage.saveData(this.values);
 | 
						|
        });
 | 
						|
    }
 | 
						|
    getValues() {
 | 
						|
        return Object.assign({}, this.values);
 | 
						|
    }
 | 
						|
    set(key, value) {
 | 
						|
        this.values[key] = value;
 | 
						|
        for (const cb of this.callbacks) {
 | 
						|
            cb();
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class ObsidianOutlinerPlugin extends obsidian.Plugin {
 | 
						|
    onload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            console.log(`Loading obsidian-outliner`);
 | 
						|
            yield this.prepareSettings();
 | 
						|
            this.obsidianSettings = new ObsidianSettings(this.app);
 | 
						|
            this.logger = new Logger(this.settings);
 | 
						|
            this.parser = new Parser(this.logger, this.settings);
 | 
						|
            this.changesApplicator = new ChangesApplicator();
 | 
						|
            this.operationPerformer = new OperationPerformer(this.parser, this.changesApplicator);
 | 
						|
            this.imeDetector = new IMEDetector();
 | 
						|
            yield this.imeDetector.load();
 | 
						|
            this.features = [
 | 
						|
                // service features
 | 
						|
                // new ReleaseNotesAnnouncement(this, this.settings),
 | 
						|
                new SettingsTab(this, this.settings),
 | 
						|
                new SystemInfo(this, this.settings),
 | 
						|
                // general features
 | 
						|
                new ListsMovementCommands(this, this.obsidianSettings, this.operationPerformer),
 | 
						|
                new ListsFoldingCommands(this, this.obsidianSettings),
 | 
						|
                // features based on settings.keepCursorWithinContent
 | 
						|
                new EditorSelectionsBehaviourOverride(this, this.settings, this.parser, this.operationPerformer),
 | 
						|
                new ArrowLeftAndCtrlArrowLeftBehaviourOverride(this, this.settings, this.imeDetector, this.operationPerformer),
 | 
						|
                new BackspaceBehaviourOverride(this, this.settings, this.imeDetector, this.operationPerformer),
 | 
						|
                new MetaBackspaceBehaviourOverride(this, this.settings, this.imeDetector, this.operationPerformer),
 | 
						|
                new DeleteBehaviourOverride(this, this.settings, this.imeDetector, this.operationPerformer),
 | 
						|
                // features based on settings.overrideTabBehaviour
 | 
						|
                new TabBehaviourOverride(this, this.imeDetector, this.obsidianSettings, this.settings, this.operationPerformer),
 | 
						|
                new ShiftTabBehaviourOverride(this, this.imeDetector, this.settings, this.operationPerformer),
 | 
						|
                // features based on settings.overrideEnterBehaviour
 | 
						|
                new EnterBehaviourOverride(this, this.settings, this.imeDetector, this.obsidianSettings, this.parser, this.operationPerformer),
 | 
						|
                // features based on settings.overrideVimOBehaviour
 | 
						|
                new VimOBehaviourOverride(this, this.settings, this.obsidianSettings, this.parser, this.operationPerformer),
 | 
						|
                // features based on settings.overrideSelectAllBehaviour
 | 
						|
                new CtrlAAndCmdABehaviourOverride(this, this.settings, this.imeDetector, this.operationPerformer),
 | 
						|
                // features based on settings.betterListsStyles
 | 
						|
                new BetterListsStyles(this.settings, this.obsidianSettings),
 | 
						|
                // features based on settings.verticalLines
 | 
						|
                new VerticalLines(this, this.settings, this.obsidianSettings, this.parser),
 | 
						|
                // features based on settings.dragAndDrop
 | 
						|
                new DragAndDrop(this, this.settings, this.obsidianSettings, this.parser, this.operationPerformer),
 | 
						|
            ];
 | 
						|
            for (const feature of this.features) {
 | 
						|
                yield feature.load();
 | 
						|
            }
 | 
						|
        });
 | 
						|
    }
 | 
						|
    onunload() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            console.log(`Unloading obsidian-outliner`);
 | 
						|
            yield this.imeDetector.unload();
 | 
						|
            for (const feature of this.features) {
 | 
						|
                yield feature.unload();
 | 
						|
            }
 | 
						|
        });
 | 
						|
    }
 | 
						|
    prepareSettings() {
 | 
						|
        return __awaiter(this, void 0, void 0, function* () {
 | 
						|
            this.settings = new Settings(this);
 | 
						|
            yield this.settings.load();
 | 
						|
        });
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
module.exports = ObsidianOutlinerPlugin;
 | 
						|
 | 
						|
 | 
						|
/* nosourcemap */ |