/*
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository
*/

'use strict';

var obsidian = require('obsidian');
var state = require('@codemirror/state');
var view = require('@codemirror/view');
var language = require('@codemirror/language');

/******************************************************************************
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.
***************************************************************************** */

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;
};

const matchTypes = {
    'exact': "Exact match",
    'contains': "Contains value",
    'whiteSpace': "Value within whitespace separated words",
    'startswith': "Starts with this value",
    'endswith': "Ends with this value"
};
const matchSign = {
    'exact': "",
    'contains': "*",
    'startswith': "^",
    'endswith': "$",
    'whiteSpace': "~"
};
const matchPreview = {
    'exact': "with value",
    'contains': "containing",
    'whiteSpace': "containing",
    'startswith': "starting with",
    'endswith': "ending with"
};
const matchPreviewPath = {
    'exact': "is",
    'contains': "contains",
    'whiteSpace': "contains",
    'startswith': "starts with",
    'endswith': "ends with"
};
const selectorType = {
    'attribute': 'Attribute value',
    'tag': 'Tag',
    'path': 'Note path'
};
class CSSLink {
    constructor() {
        this.type = 'attribute';
        this.name = "";
        this.value = "";
        this.matchCaseSensitive = false;
        this.match = "exact";
        let s4 = () => {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        };
        //return id of format 'aaaaaaaa'-'aaaa'-'aaaa'-'aaaa'-'aaaaaaaaaaaa'
        this.uid = s4() + "-" + s4();
        this.selectText = true;
        this.selectAppend = true;
        this.selectPrepend = true;
        this.selectBackground = true;
    }
}

function clearExtraAttributes(link) {
    Object.values(link.attributes).forEach(attr => {
        if (attr.name.includes("data-link")) {
            link.removeAttribute(attr.name);
        }
    });
}
function fetchTargetAttributesSync(app, settings, dest, addDataHref) {
    var _a;
    let new_props = { tags: "" };
    const cache = app.metadataCache.getFileCache(dest);
    if (!cache)
        return new_props;
    const frontmatter = cache.frontmatter;
    if (frontmatter) {
        settings.targetAttributes.forEach(attribute => {
            if (Object.keys(frontmatter).includes(attribute)) {
                if (attribute === 'tag' || attribute === 'tags') {
                    new_props['tags'] += frontmatter[attribute];
                }
                else {
                    new_props[attribute] = frontmatter[attribute];
                }
            }
        });
    }
    if (settings.targetTags) {
        new_props["tags"] += obsidian.getAllTags(cache).join(' ');
    }
    if (addDataHref) {
        new_props['data-href'] = dest.basename;
    }
    new_props['path'] = dest.path;
    //@ts-ignore
    const getResults = (api) => {
        const page = api.page(dest.path);
        if (!page) {
            return;
        }
        settings.targetAttributes.forEach((field) => {
            const value = page[field];
            if (value)
                new_props[field] = value;
        });
    };
    if (settings.getFromInlineField && app.plugins.enabledPlugins.has("dataview")) {
        const api = (_a = app.plugins.plugins.dataview) === null || _a === void 0 ? void 0 : _a.api;
        if (api) {
            getResults(api);
        }
        // This is crashing for some people. I think ignoring it will be ok. 
        // else
        //     this.plugin.registerEvent(
        //         app.metadataCache.on("dataview:api-ready", (api: any) =>
        //             getResults(api)
        //         )
        //     );
    }
    // Replace spaces with hyphens in the keys of new_props
    const hyphenated_props = {};
    for (const key in new_props) {
        const hyphenatedKey = key.replace(/ /g, '-');
        hyphenated_props[hyphenatedKey] = new_props[key];
    }
    new_props = hyphenated_props;
    return new_props;
}
function processKey(key) {
    // Replace spaces with hyphens (v0.13.4+)
    return key.replace(/ /g, '-');
}
function processValue(key, value) {
    // TODO: This is a hack specifically for Emile's setup. Should be commented in releases.
    if (key.contains("publishedIn") && (value === null || value === void 0 ? void 0 : value.length) && value.length === 1 && value[0].startsWith && value[0].startsWith("[[") && value[0].endsWith("]]")) {
        return value[0].slice(2, -2);
    }
    return value;
}
function setLinkNewProps(link, new_props) {
    // @ts-ignore
    for (const a of link.attributes) {
        if (a.name.includes("data-link") && !(a.name in new_props)) {
            link.removeAttribute(a.name);
        }
    }
    Object.keys(new_props).forEach(key => {
        const dom_key = processKey(key);
        const name = "data-link-" + dom_key;
        const curValue = link.getAttribute(name);
        const newValue = processValue(key, new_props[key]);
        // Only update if value is different
        if (!newValue || curValue != newValue) {
            link.setAttribute(name, newValue);
            if ((newValue === null || newValue === void 0 ? void 0 : newValue.startsWith) && (newValue.startsWith('http') || newValue.startsWith('data:'))) {
                link.style.setProperty(`--data-link-${dom_key}`, `url(${newValue})`);
            }
            else {
                link.style.setProperty(`--data-link-${dom_key}`, newValue);
            }
        }
    });
    if (!link.hasClass("data-link-icon")) {
        link.addClass("data-link-icon");
    }
    if (!link.hasClass("data-link-icon-after")) {
        link.addClass("data-link-icon-after");
    }
    if (!link.hasClass("data-link-text")) {
        link.addClass("data-link-text");
    }
}
function updateLinkExtraAttributes(app, settings, link, destName) {
    var _a, _b;
    const linkHref = (_b = (_a = link.getAttribute('href')) === null || _a === void 0 ? void 0 : _a.split('#')) === null || _b === void 0 ? void 0 : _b[0];
    if (linkHref) {
        const dest = app.metadataCache.getFirstLinkpathDest(linkHref, destName);
        if (dest) {
            const new_props = fetchTargetAttributesSync(app, settings, dest, false);
            setLinkNewProps(link, new_props);
        }
    }
}
function updateDivExtraAttributes(app, settings, link, destName, linkName, filter_collapsible = false) {
    if (filter_collapsible && link.parentElement.getAttribute("class").contains('mod-collapsible'))
        return; // Bookmarks Folder
    if (!linkName) {
        linkName = link.textContent;
    }
    // Sometimes textContent refers to the alias, missing the base name/path. Then we need to explicitly get the base name/path from attributes.
    // Check for file name in various attributes, in order of preference
    const parent = link.parentElement;
    const attributeSources = [
        () => parent === null || parent === void 0 ? void 0 : parent.getAttribute('data-path'), // File Browser
        () => parent === null || parent === void 0 ? void 0 : parent.getAttribute("data-href"), // Bases
        () => parent === null || parent === void 0 ? void 0 : parent.getAttribute("href"), // Bases 
        () => link.getAttribute("data-href"), // Bases (v1.10+)
        () => link.getAttribute("href"), // Bases
        () => (parent === null || parent === void 0 ? void 0 : parent.getAttribute("class")) === "suggestion-content" && link.nextElementSibling
            ? link.nextElementSibling.textContent + linkName : null // Auto complete
    ];
    for (const source of attributeSources) {
        const value = source();
        if (value) {
            linkName = value;
            break;
        }
    }
    const dest = app.metadataCache.getFirstLinkpathDest(obsidian.getLinkpath(linkName), destName);
    if (dest) {
        const new_props = fetchTargetAttributesSync(app, settings, dest, true);
        setLinkNewProps(link, new_props);
    }
}
function updateElLinks(app, plugin, el, ctx) {
    const settings = plugin.settings;
    const links = el.querySelectorAll('a.internal-link');
    const destName = ctx.sourcePath.replace(/(.*).md/, "$1");
    links.forEach((link) => {
        updateLinkExtraAttributes(app, settings, link, destName);
    });
}
function updatePropertiesPane(propertiesEl, file, app, plugin) {
    var _a;
    const frontmatter = (_a = app.metadataCache.getCache(file.path)) === null || _a === void 0 ? void 0 : _a.frontmatter;
    if (!!frontmatter) {
        const nodes = propertiesEl.querySelectorAll("div.multi-select-pill-content");
        for (let i = 0; i < nodes.length; ++i) {
            const el = nodes[i];
            const linkText = el.textContent;
            const keyEl = el.parentElement.parentElement.parentElement.parentElement.children[0].children[1];
            // @ts-ignore
            const key = keyEl.value;
            const listOfLinks = frontmatter[key];
            let foundS = null;
            if (!listOfLinks) {
                continue;
            }
            for (const s of listOfLinks) {
                if (s.length > 4 && s.startsWith("[[") && s.endsWith("]]")) {
                    const slicedS = s.slice(2, -2);
                    const split = slicedS.split("|");
                    if (split.length == 1 && split[0] == linkText) {
                        foundS = split[0];
                        break;
                    }
                    else if (split.length == 2 && split[1] == linkText) {
                        foundS = split[0];
                        break;
                    }
                }
            }
            if (!!foundS) {
                updateDivExtraAttributes(plugin.app, plugin.settings, el, "", foundS);
            }
        }
        const singleNodes = propertiesEl.querySelectorAll("div.metadata-link-inner");
        for (let i = 0; i < singleNodes.length; ++i) {
            const el = singleNodes[i];
            const linkText = el.textContent;
            const keyEl = el.parentElement.parentElement.parentElement.children[0].children[1];
            // @ts-ignore
            const key = keyEl.value;
            const link = frontmatter[key];
            if (!link) {
                continue;
            }
            let foundS = null;
            if ((link === null || link === void 0 ? void 0 : link.length) > 4 && link.startsWith("[[") && link.endsWith("]]")) {
                const slicedS = link.slice(2, -2);
                const split = slicedS.split("|");
                if (split.length == 1 && split[0] == linkText) {
                    foundS = split[0];
                }
                else if (split.length == 2 && split[1] == linkText) {
                    foundS = split[0];
                }
            }
            if (!!foundS) {
                updateDivExtraAttributes(plugin.app, plugin.settings, el, "", foundS);
            }
        }
    }
}
function updateVisibleLinks(app, plugin) {
    const settings = plugin.settings;
    app.workspace.iterateRootLeaves((leaf) => {
        var _a, _b;
        if (leaf.view instanceof obsidian.MarkdownView && leaf.view.file) {
            const file = leaf.view.file;
            const cachedFile = app.metadataCache.getFileCache(file);
            // @ts-ignore
            const metadata = (_b = (_a = leaf.view) === null || _a === void 0 ? void 0 : _a.metadataEditor) === null || _b === void 0 ? void 0 : _b.contentEl;
            if (!!metadata) {
                updatePropertiesPane(metadata, file, app, plugin);
            }
            //@ts-ignore
            const tabHeader = leaf.tabHeaderInnerTitleEl;
            if (settings.enableTabHeader) {
                // Supercharge tab headers
                updateDivExtraAttributes(app, settings, tabHeader, "", file.path);
            }
            else {
                clearExtraAttributes(tabHeader);
            }
            if (cachedFile === null || cachedFile === void 0 ? void 0 : cachedFile.links) {
                cachedFile.links.forEach((link) => {
                    const fileName = file.path.replace(/(.*).md/, "$1");
                    const dest = app.metadataCache.getFirstLinkpathDest(link.link, fileName);
                    if (dest) {
                        const new_props = fetchTargetAttributesSync(app, settings, dest, false);
                        const internalLinks = leaf.view.containerEl.querySelectorAll(`a.internal-link[href="${link.link}"]`);
                        internalLinks.forEach((internalLink) => setLinkNewProps(internalLink, new_props));
                    }
                });
            }
        }
    });
}

function displayText(link, settings) {
    if (link.type === 'tag') {
        if (!link.value) {
            return "<b>Please choose a tag</b>";
        }
        return `<span class="data-link-icon data-link-text data-link-icon-after" data-link-tags="${link.value}">Note</span> has tag <a class="tag">#${link.value}</a>`;
    }
    else if (link.type === 'attribute') {
        if (settings.targetAttributes.length === 0) {
            return `<b>No attributes added to "Target attributes". Go to plugin settings to add them.</b>`;
        }
        if (!link.name) {
            return "<b>Please choose an attribute name.</b>";
        }
        if (!link.value) {
            return "<b>Please choose an attribute value.</b>";
        }
        return `<span class="data-link-icon data-link-text data-link-icon-after" data-link-${link.name}="${link.value}">Note</span> has attribute <b>${link.name.replace(/-/g, ' ')}</b> ${matchPreview[link.match]} <b>${link.value}</b>.`;
    }
    if (!link.value) {
        return "<b>Please choose a path.</b>";
    }
    return `The path of the <span class="data-link-icon data-link-text data-link-icon-after" data-link-path="${link.value}">note</span> ${matchPreviewPath[link.match]} <b>${link.value}</b>`;
}
function updateDisplay(textArea, link, settings) {
    let toDisplay = displayText(link, settings);
    let disabled = false;
    if (link.type === 'tag') {
        if (!link.value) {
            disabled = true;
        }
    }
    else if (link.type === 'attribute') {
        if (settings.targetAttributes.length === 0) {
            disabled = true;
        }
        else if (!link.name) {
            disabled = true;
        }
        else if (!link.value) {
            disabled = true;
        }
    }
    else {
        if (!link.value) {
            disabled = true;
        }
    }
    textArea.innerHTML = toDisplay;
    return disabled;
}
class CSSBuilderModal extends obsidian.Modal {
    constructor(plugin, saveCallback, cssLink = null) {
        super(plugin.app);
        this.cssLink = cssLink;
        if (!cssLink) {
            this.cssLink = new CSSLink();
        }
        this.plugin = plugin;
        this.saveCallback = saveCallback;
    }
    onOpen() {
        this.titleEl.setText(`Select what links to style!`);
        // is tag
        const matchAttrPlaceholder = "Attribute value to match.";
        const matchTagPlaceholder = "Note tag to match (without #).";
        const matchPathPlaceholder = "File path to match.";
        const matchAttrTxt = "Attribute value";
        const matchTagTxt = "Tag";
        const matchPathTxt = "Path";
        const cssLink = this.cssLink;
        const plugin = this.plugin;
        this.contentEl.addClass("supercharged-modal");
        // Type
        new obsidian.Setting(this.contentEl)
            .setName("Type of selector")
            .setDesc("Attributes selects YAML and DataView attributes" +
            ", tags chooses the tags of a note, and path considers the name of the note including in what folder it is.")
            .addDropdown(dc => {
            Object.keys(selectorType).forEach((type) => {
                dc.addOption(type, selectorType[type]);
                if (type === this.cssLink.type) {
                    dc.setValue(type);
                }
            });
            dc.onChange((type) => {
                cssLink.type = type;
                updateContainer(cssLink.type);
                saveButton.setDisabled(updateDisplay(preview, this.cssLink, this.plugin.settings));
            });
        });
        // attribute name
        const attrName = new obsidian.Setting(this.contentEl)
            .setName("Attribute name")
            .setDesc("What attribute to target? Make sure to first add target attributes to the settings at the top!")
            .addDropdown(dc => {
            plugin.settings.targetAttributes.forEach((attribute) => {
                const dom_attribute = processKey(attribute);
                dc.addOption(dom_attribute, attribute);
                if (dom_attribute === cssLink.name) {
                    dc.setValue(dom_attribute);
                }
            });
            dc.onChange(name => {
                cssLink.name = name;
                saveButton.setDisabled(updateDisplay(preview, cssLink, plugin.settings));
            });
        });
        // attribute value
        const attrValue = new obsidian.Setting(this.contentEl)
            .setName("Value to match")
            .setDesc("TODO")
            .addText(t => {
            t.setValue(cssLink.value);
            t.onChange(value => {
                cssLink.value = value;
                saveButton.setDisabled(updateDisplay(preview, cssLink, plugin.settings));
            });
        });
        this.contentEl.createEl('h4', { text: 'Advanced' });
        // matching type
        const matchingType = new obsidian.Setting(this.contentEl)
            .setName("Matching type")
            .setDesc("How to compare the attribute or path with the given value.")
            .addDropdown(dc => {
            Object.keys(matchTypes).forEach((key) => {
                dc.addOption(key, matchTypes[key]);
                if (key == cssLink.match) {
                    dc.setValue(key);
                }
            });
            dc.onChange((value) => {
                cssLink.match = value;
                saveButton.setDisabled(updateDisplay(preview, cssLink, plugin.settings));
            });
        });
        // case sensitive
        const caseSensitiveTogglerContainer = new obsidian.Setting(this.contentEl)
            .setName("Case sensitive matching")
            .setDesc("Should the matching of the value be case sensitive?")
            .addToggle(b => {
            b.setValue(cssLink.matchCaseSensitive);
            b.onChange(value => {
                cssLink.matchCaseSensitive = value;
                b.setDisabled(updateDisplay(preview, cssLink, plugin.settings));
            });
        });
        if (!this.cssLink.name && this.plugin.settings.targetAttributes.length > 0) {
            this.cssLink.name = this.plugin.settings.targetAttributes[0];
        }
        const updateContainer = function (type) {
            if (type === 'attribute') {
                attrName.settingEl.show();
                attrValue.nameEl.setText(matchAttrTxt);
                attrValue.descEl.setText(matchAttrPlaceholder);
                matchingType.settingEl.show();
                caseSensitiveTogglerContainer.settingEl.show();
            }
            else if (type === 'tag') {
                attrName.settingEl.hide();
                attrValue.nameEl.setText(matchTagTxt);
                attrValue.descEl.setText(matchTagPlaceholder);
                matchingType.settingEl.hide();
                caseSensitiveTogglerContainer.settingEl.hide();
            }
            else {
                attrName.settingEl.hide();
                attrValue.nameEl.setText(matchPathTxt);
                attrValue.descEl.setText(matchPathPlaceholder);
                matchingType.settingEl.show();
                caseSensitiveTogglerContainer.settingEl.show();
            }
        };
        new obsidian.Setting(this.contentEl)
            .setName("Style options")
            .setDesc("What styling options are active? " +
            "Disabling options you won't use can improve performance slightly.")
            .addToggle(t => {
            t.onChange(value => {
                cssLink.selectText = value;
            });
            t.setValue(cssLink.selectText);
            t.setTooltip("Style link text");
        })
            .addToggle(t => {
            t.onChange(value => {
                cssLink.selectPrepend = value;
            });
            t.setValue(cssLink.selectPrepend);
            t.setTooltip("Add content before link");
        })
            .addToggle(t => {
            t.onChange(value => {
                cssLink.selectAppend = value;
            });
            t.setValue(cssLink.selectAppend);
            t.setTooltip("Add content after link");
        })
            .addToggle(t => {
            t.onChange(value => {
                cssLink.selectBackground = value;
            });
            t.setValue(cssLink.selectBackground);
            t.setTooltip("Add optional background or underline to link");
        });
        this.contentEl.createEl('h4', { text: 'Result' });
        const modal = this;
        const saveButton = new obsidian.Setting(this.contentEl)
            .setName("Preview")
            .setDesc("")
            .addButton(b => {
            b.setButtonText("Save");
            b.onClick(() => {
                modal.saveCallback(cssLink);
                modal.close();
            });
        });
        // generate button
        const preview = saveButton.nameEl;
        updateContainer(cssLink.type);
        saveButton.setDisabled(updateDisplay(preview, this.cssLink, this.plugin.settings));
    }
}

const colorSet = [[
        '#0089BA',
        '#2C73D2',
        '#008E9B',
        '#0081CF',
        '#008F7A',
        '#008E9B',
    ], [
        '#D65DB1',
        '#0082C1',
        '#9270D3',
        '#007F93',
        '#007ED9',
        '#007660',
    ], [
        '#FF9671',
        '#A36AAA',
        '#F27D88',
        '#6967A9',
        '#D26F9D',
        '#1b6299',
    ], [
        '#FFC75F',
        '#4C9A52',
        '#C3BB4E',
        '#00855B',
        '#88AC4B',
        '#006F61',
    ], [
        '#FF6F91',
        '#6F7F22',
        '#E07250',
        '#257A3E',
        '#AC7C26',
        '#006F5F',
    ], [
        '#d9d867',
        '#2FAB63',
        '#B8E067',
        '#008E63',
        '#78C664',
        '#007160',
    ]];
const colors = [];
for (const i of Array(6).keys()) {
    for (const j of Array(6).keys()) {
        colors.push(colorSet[j][i]);
    }
}
function hash(uid) {
    let hash = 0;
    for (let i = 0; i < uid.length; i++) {
        const char = uid.charCodeAt(i);
        hash = ((hash << 5) - hash) + char;
        hash = hash & hash; // Convert to 32bit integer
    }
    hash = Math.abs(hash);
    return hash;
}
function buildCSS(selectors, plugin) {
    return __awaiter(this, void 0, void 0, function* () {
        var _a;
        const instructions = [
            "/* WARNING: This file will be overwritten by the plugin.",
            "Do not edit this file directly! First copy this file and rename it if you want to edit things. */",
            "",
            ":root {"
        ];
        selectors.forEach((selector, i) => {
            if (selector.selectText) {
                instructions.push(`    --${selector.uid}-color: ${colors[hash(selector.uid) % 36]};`);
                instructions.push(`    --${selector.uid}-weight: initial;`);
            }
            if (selector.selectPrepend) {
                instructions.push(`    --${selector.uid}-before: '';`);
            }
            if (selector.selectAppend) {
                instructions.push(`    --${selector.uid}-after: '';`);
            }
            if (selector.selectBackground) {
                instructions.push(`    --${selector.uid}-background-color: #ffffff;`);
                instructions.push(`    --${selector.uid}-decoration: initial;`);
            }
        });
        instructions.push("}");
        selectors.forEach(selector => {
            let cssSelector;
            if (selector.type === 'attribute') {
                cssSelector = `[data-link-${selector.name}${matchSign[selector.match]}="${selector.value}" ${selector.matchCaseSensitive ? "" : " i"}]`;
            }
            else if (selector.type === 'tag') {
                cssSelector = `[data-link-tags*="${selector.value}" i]`;
            }
            else {
                cssSelector = `[data-link-path${matchSign[selector.match]}="${selector.value}" ${selector.matchCaseSensitive ? "" : "i"}]`;
            }
            if (selector.selectText) {
                instructions.push(...[
                    "",
                    `div[data-id="${selector.uid}"] div.setting-item-description,`,
                    cssSelector + " {",
                    `    color: var(--${selector.uid}-color) !important;`,
                    `    font-weight: var(--${selector.uid}-weight);`,
                    "}"
                ]);
            }
            if (selector.selectBackground) {
                instructions.push(...["",
                    `.c-${selector.uid}-use-background div[data-id="${selector.uid}"] div.setting-item-description,`,
                    `.c-${selector.uid}-use-background .data-link-text${cssSelector} {`,
                    `    background-color: var(--${selector.uid}-background-color) !important;`,
                    `    border-radius: 5px;`,
                    `    padding-left: 2px;`,
                    `    padding-right: 2px;`,
                    `    text-decoration: var(--${selector.uid}-decoration) !important;`,
                    "}"]);
            }
            if (selector.selectPrepend) {
                instructions.push(...["",
                    `div[data-id="${selector.uid}"] div.setting-item-description::before,`,
                    `.data-link-icon${cssSelector}::before {`,
                    `    content: var(--${selector.uid}-before);`,
                    "}"]);
            }
            if (selector.selectAppend) {
                instructions.push(...["",
                    `div[data-id="${selector.uid}"] div.setting-item-description::after,`,
                    `.data-link-icon-after${cssSelector}::after {`,
                    `    content: var(--${selector.uid}-after);`,
                    "}"]);
            }
        });
        instructions.push(...[
            "/* @settings",
            "name: Supercharged Links",
            "id: supercharged-links",
            "settings:",
        ]);
        selectors.forEach((selector, i) => {
            let name = selector.name;
            let value = selector.value;
            if (selector.type === 'tag') {
                name = 'tag';
                // value = "\#" + value;
            }
            else if (selector.type === 'path') {
                name = 'path';
            }
            instructions.push(...[
                "    - ",
                `        id: ${selector.uid}`,
                `        title: ${name} is ${value}`,
                `        description: Example note`,
                "        type: heading",
                "        collapsed: true",
                "        level: 3"
            ]);
            if (selector.selectText) {
                instructions.push(...[
                    "    - ",
                    `        id: ${selector.uid}-color`,
                    `        title: Link color`,
                    "        type: variable-color",
                    "        format: hex",
                    `        default: '${colors[hash(selector.uid) % 36]}'`,
                    "    - ",
                    `        id: ${selector.uid}-weight`,
                    `        title: Font weight`,
                    "        type: variable-select",
                    `        default: initial`,
                    `        options:`,
                    `            - initial`,
                    `            - lighter`,
                    `            - normal`,
                    `            - bold`,
                    `            - bolder`,
                    "    - ",
                    `        id: ${selector.uid}-decoration`,
                    `        title: Font decoration`,
                    "        type: variable-select",
                    `        default: initial`,
                    `        options:`,
                    `            - initial`,
                    `            - underline`,
                    `            - overline`,
                    `            - line-through`
                ]);
            }
            if (selector.selectPrepend) {
                instructions.push(...["    - ",
                    `        id: ${selector.uid}-before`,
                    `        title: Prepend text`,
                    `        description: Add some text, such as an emoji, before the links.`,
                    "        type: variable-text",
                    `        default: ''`,
                    `        quotes: true`]);
            }
            if (selector.selectAppend) {
                instructions.push(...["    - ",
                    `        id: ${selector.uid}-after`,
                    `        title: Append text`,
                    `        description: Add some text, such as an emoji, after the links.`,
                    "        type: variable-text",
                    `        default: ''`,
                    `        quotes: true`]);
            }
            if (selector.selectBackground) {
                instructions.push(...["    - ",
                    `        id: c-${selector.uid}-use-background`,
                    `        title: Use background color`,
                    `        description: Adds a background color to the link. This can look buggy in live preview.`,
                    "        type: class-toggle",
                    "    - ",
                    `        id: ${selector.uid}-background-color`,
                    `        title: Background color`,
                    "        type: variable-color",
                    "        format: hex",
                    `        default: '#ffffff'`]);
            }
        });
        instructions.push("*/");
        const vault = plugin.app.vault;
        const configDir = (_a = vault.configDir) !== null && _a !== void 0 ? _a : ".obsidian";
        const pathDir = configDir + "/snippets";
        yield vault.adapter.mkdir(pathDir);
        const path = pathDir + "/supercharged-links-gen.css";
        if (yield vault.adapter.exists(path)) {
            yield vault.adapter.remove(path);
        }
        yield plugin.app.vault.create(path, instructions.join('\n'));
        // Activate snippet
        if (plugin.settings.activateSnippet) {
            // @ts-ignore
            const customCss = plugin.app.customCss;
            customCss.enabledSnippets.add('supercharged-links-gen');
            customCss.requestLoadSnippets();
        }
        // Ensure Style Settings reads changes
        plugin.app.workspace.trigger("parse-style-settings");
    });
}

class SuperchargedLinksSettingTab extends obsidian.PluginSettingTab {
    constructor(app, plugin) {
        super(app, plugin);
        this.plugin = plugin;
        this.debouncedGenerate = obsidian.debounce(this._generateSnippet, 1000, true);
        // Generate CSS immediately rather than 1 second - feels laggy
        this._generateSnippet();
    }
    display() {
        let { containerEl } = this;
        containerEl.empty();
        /* Managing extra attirbutes for a.internal-link */
        new obsidian.Setting(containerEl)
            .setName('Target Attributes for styling')
            .setDesc('Frontmatter attributes to target, comma separated')
            .addTextArea((text) => {
            text
                .setPlaceholder('Enter attributes as string, comma separated')
                .setValue(this.plugin.settings.targetAttributes.join(', '))
                .onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.targetAttributes = value.split(',').map(attr => attr.trim());
                if (this.plugin.settings.targetAttributes.length === 1 && !this.plugin.settings.targetAttributes[0]) {
                    this.plugin.settings.targetAttributes = [];
                }
                yield this.plugin.saveSettings();
            }));
            text.inputEl.rows = 6;
            text.inputEl.cols = 25;
        });
        containerEl.createEl('h4', { text: 'Styling' });
        const styleSettingDescription = containerEl.createDiv();
        styleSettingDescription.innerHTML = `
Styling can be done using the Style Settings plugin. 
 <ol>
 <li>Create selectors down below.</li>
 <li>Go to the Style Settings tab and style your links!</li>
</ol>`;
        const selectorDiv = containerEl.createDiv();
        this.drawSelectors(selectorDiv);
        containerEl.createEl('h4', { text: 'Settings' });
        new obsidian.Setting(containerEl)
            .setName('Enable in Editor')
            .setDesc('If true, this will also supercharge internal links in the editor view of a note.')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.enableEditor);
            toggle.onChange(value => {
                this.plugin.settings.enableEditor = value;
                this.plugin.saveSettings();
                updateVisibleLinks(this.app, this.plugin);
            });
        });
        new obsidian.Setting(containerEl)
            .setName('Enable in tab headers')
            .setDesc('If true, this will also supercharge the headers of a tab.')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.enableTabHeader);
            toggle.onChange(value => {
                this.plugin.settings.enableTabHeader = value;
                this.plugin.saveSettings();
                updateVisibleLinks(this.app, this.plugin);
            });
        });
        new obsidian.Setting(containerEl)
            .setName('Enable in File Browser')
            .setDesc('If true, this will also supercharge the file browser.')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.enableFileList);
            toggle.onChange(value => {
                this.plugin.settings.enableFileList = value;
                this.plugin.saveSettings();
            });
        });
        new obsidian.Setting(containerEl)
            .setName('Enable in Bases')
            .setDesc('If true, this will also supercharge Obsidian Bases.')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.enableBases);
            toggle.onChange(value => {
                this.plugin.settings.enableBases = value;
                this.plugin.saveSettings();
            });
        });
        new obsidian.Setting(containerEl)
            .setName('Enable in Plugins')
            .setDesc('If true, this will also supercharge plugins like the backlinks and forward links panels.')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.enableBacklinks);
            toggle.onChange(value => {
                this.plugin.settings.enableBacklinks = value;
                this.plugin.saveSettings();
            });
        });
        new obsidian.Setting(containerEl)
            .setName('Enable in Quick Switcher')
            .setDesc('If true, this will also supercharge the quick switcher.')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.enableQuickSwitcher);
            toggle.onChange(value => {
                this.plugin.settings.enableQuickSwitcher = value;
                this.plugin.saveSettings();
            });
        });
        new obsidian.Setting(containerEl)
            .setName('Enable in Link Autocompleter')
            .setDesc('If true, this will also supercharge the link autocompleter.')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.enableSuggestor);
            toggle.onChange(value => {
                this.plugin.settings.enableSuggestor = value;
                this.plugin.saveSettings();
            });
        });
        containerEl.createEl('h4', { text: 'Advanced' });
        // Managing choice wether you want to parse tags both from normal tags and in the frontmatter
        new obsidian.Setting(containerEl)
            .setName('Parse all tags in the file')
            .setDesc('Sets the `data-link-tags`-attribute to look for tags both in the frontmatter and in the file as #tag-name')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.targetTags);
            toggle.onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.targetTags = value;
                yield this.plugin.saveSettings();
            }));
        });
        // Managing choice wether you get attributes from inline fields and frontmatter or only frontmater
        new obsidian.Setting(containerEl)
            .setName('Search for attribute in Inline fields like <field::>')
            .setDesc('Sets the `data-link-<field>`-attribute to the value of inline fields')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.getFromInlineField);
            toggle.onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.getFromInlineField = value;
                yield this.plugin.saveSettings();
            }));
        });
        // Automatically activate snippet
        new obsidian.Setting(containerEl)
            .setName('Automatically activate snippet')
            .setDesc('If true, this will automatically activate the generated CSS snippet "supercharged-links-gen.css". ' +
            'Turn this off if you don\'t want this to happen.')
            .addToggle(toggle => {
            toggle.setValue(this.plugin.settings.activateSnippet);
            toggle.onChange((value) => __awaiter(this, void 0, void 0, function* () {
                this.plugin.settings.activateSnippet = value;
                yield this.plugin.saveSettings();
            }));
        });
        /* Managing predefined values for properties */
        /* Manage menu options display*/
        new obsidian.Setting(containerEl)
            .setName("Display field options in context menu")
            .setDesc("This feature has been migrated to metadata-menu plugin https://github.com/mdelobelle/metadatamenu");
    }
    generateSnippet() {
        this.debouncedGenerate();
    }
    _generateSnippet() {
        return __awaiter(this, void 0, void 0, function* () {
            yield buildCSS(this.plugin.settings.selectors, this.plugin);
            // new Notice("Generated supercharged-links-gen.css");
        });
    }
    drawSelectors(div) {
        div.empty();
        this.generateSnippet();
        const selectors = this.plugin.settings.selectors;
        selectors.forEach((selector, i) => {
            const s = new obsidian.Setting(div)
                .addButton(button => {
                button.onClick(() => {
                    const oldSelector = selectors[i + 1];
                    selectors[i + 1] = selector;
                    selectors[i] = oldSelector;
                    this.drawSelectors(div);
                });
                button.setIcon("down-arrow-with-tail");
                button.setTooltip("Move selector down");
                if (i === selectors.length - 1) {
                    button.setDisabled(true);
                }
            })
                .addButton(button => {
                button.onClick(() => {
                    const oldSelector = selectors[i - 1];
                    selectors[i - 1] = selector;
                    selectors[i] = oldSelector;
                    this.drawSelectors(div);
                });
                button.setIcon("up-arrow-with-tail");
                button.setTooltip("Move selector up");
                if (i === 0) {
                    button.setDisabled(true);
                }
            })
                .addButton(button => {
                button.onClick(() => {
                    const formModal = new CSSBuilderModal(this.plugin, (newSelector) => {
                        this.plugin.settings.selectors[i] = newSelector;
                        this.plugin.saveSettings();
                        updateDisplay(s.nameEl, selector, this.plugin.settings);
                        this.generateSnippet();
                    }, selector);
                    formModal.open();
                });
                button.setIcon("pencil");
                button.setTooltip("Edit selector");
            })
                .addButton(button => {
                button.onClick(() => {
                    this.plugin.settings.selectors.remove(selector);
                    this.plugin.saveSettings();
                    this.drawSelectors(div);
                });
                button.setIcon("cross");
                button.setTooltip("Remove selector");
            });
            updateDisplay(s.nameEl, selector, this.plugin.settings);
        });
        new obsidian.Setting(div)
            .setName("New selector")
            .setDesc("Create a new selector to style with Style Settings.")
            .addButton(button => {
            button.onClick(() => {
                const formModal = new CSSBuilderModal(this.plugin, (newSelector) => {
                    this.plugin.settings.selectors.push(newSelector);
                    this.plugin.saveSettings();
                    this.drawSelectors(div);
                    // TODO: Force redraw somehow?
                });
                formModal.open();
            });
            button.setButtonText("New");
        });
    }
}

const DEFAULT_SETTINGS = {
    targetAttributes: [],
    targetTags: true,
    getFromInlineField: false,
    enableTabHeader: true,
    activateSnippet: true,
    enableEditor: true,
    enableFileList: true,
    enableBacklinks: true,
    enableQuickSwitcher: true,
    enableSuggestor: true,
    enableBases: true,
    selectors: []
};

function buildCMViewPlugin(app, _settings) {
    // Implements the live preview supercharging
    // Code structure based on https://github.com/nothingislost/obsidian-cm6-attributes/blob/743d71b0aa616407149a0b6ea5ffea28e2154158/src/main.ts
    // Code help credits to @NothingIsLost! They have been a great help getting this to work properly.
    class HeaderWidget extends view.WidgetType {
        constructor(attributes, after) {
            super();
            this.attributes = attributes;
            this.after = after;
        }
        toDOM() {
            var _a;
            let headerEl = document.createElement("span");
            headerEl.setAttrs(this.attributes);
            for (let key in this.attributes) {
                // CSS doesn't allow interpolation of variables for URLs, so do it beforehand to be nice.
                if (((_a = this.attributes[key]) === null || _a === void 0 ? void 0 : _a.startsWith) && (this.attributes[key].startsWith('http') || this.attributes[key].startsWith('data:'))) {
                    headerEl.style.setProperty(`--${key}`, `url(${this.attributes[key]})`);
                }
                else {
                    headerEl.style.setProperty(`--${key}`, processValue(key, this.attributes[key]));
                }
            }
            if (this.after) {
                headerEl.addClass('data-link-icon-after');
            }
            else {
                headerEl.addClass('data-link-icon');
            }
            // create a naive bread crumb
            return headerEl;
        }
        ignoreEvent() {
            return true;
        }
    }
    const settings = _settings;
    const viewPlugin = view.ViewPlugin.fromClass(class {
        constructor(view) {
            this.decorations = this.buildDecorations(view);
        }
        update(update) {
            if (update.docChanged) {
                this.decorations = this.decorations.map(update.changes);
                update.changes.iterChanges((fromA, toA, fromB, toB, t) => {
                    // Update all 'line blocks' between the range changed. Prevents weird graphical bugs
                    const minFrom = update.view.lineBlockAt(fromB).from;
                    const maxTo = update.view.lineBlockAt(toB).to;
                    // remove things within bounds
                    this.decorations = this.decorations.update({
                        filter: (from, to) => to < minFrom || from > maxTo
                    });
                    // Update decorations within bounds
                    this.decorations = state.RangeSet.join([this.decorations,
                        this.buildDecorations(update.view, minFrom, maxTo)]);
                });
            }
            else if (update.viewportChanged) {
                this.decorations = this.buildDecorations(update.view);
            }
        }
        destroy() {
        }
        buildDecorations(view$1, updateFrom = -1, updateTo = -1) {
            let builder = new state.RangeSetBuilder();
            if (!settings.enableEditor) {
                return builder.finish();
            }
            const mdView = view$1.state.field(obsidian.editorViewField);
            let lastAttributes = {};
            let iconDecoAfter = null;
            let iconDecoAfterWhere = null;
            let mdAliasFrom = null;
            let mdAliasTo = null;
            for (let { from, to } of view$1.visibleRanges) {
                // When updating, only changes the range given.
                if (updateFrom !== -1 && (to < updateFrom || from > updateTo))
                    continue;
                language.syntaxTree(view$1.state).iterate({
                    from,
                    to,
                    enter: (node) => {
                        if (updateFrom !== -1 && (node.to < updateFrom || node.from > updateTo))
                            return;
                        const tokenProps = node.type.prop(language.tokenClassNodeProp);
                        if (tokenProps) {
                            const props = new Set(tokenProps.split(" "));
                            // Square Brackets of links both internal (`[[`, `]]`) and md link (`[`, `]`)
                            const isMDFormatting = props.has('formatting-link') || props.has('formatting-link-string');
                            if (isMDFormatting)
                                return;
                            // Parts of internal links
                            const isLink = props.has("hmd-internal-link"); // [[`Note` or `|` or `Alias`]]
                            const isAlias = props.has("link-alias"); // [[Note| `Alias`]]
                            const isPipe = props.has("link-alias-pipe"); // [[Note `|` Alias]]
                            // The 'alias' of the md link (or its brackets)
                            const isMDLink = props.has('link'); // `[` or `Alias` or `]`(URL)
                            // The 'internal link' of the md link (or its brackets)
                            const isMDUrl = props.has('url'); // [Alias]`(` or `URL` or `)`
                            if (isMDLink) {
                                // This catches the alias of md links i.e. [ `Alias` ](URL)
                                // We'll apply the styling in the next iteration when we analyze the `URL`
                                mdAliasFrom = node.from;
                                mdAliasTo = node.to;
                            }
                            if (!isPipe && !isAlias) {
                                if (iconDecoAfter) {
                                    builder.add(iconDecoAfterWhere, iconDecoAfterWhere, iconDecoAfter);
                                    iconDecoAfter = null;
                                    iconDecoAfterWhere = null;
                                }
                            }
                            if (isLink && !isAlias && !isPipe || isMDUrl) {
                                let linkText = view$1.state.doc.sliceString(node.from, node.to);
                                linkText = linkText.split("#")[0];
                                let file = app.metadataCache.getFirstLinkpathDest(linkText, mdView.file.basename);
                                if (isMDUrl && !file) {
                                    try {
                                        file = app.vault.getAbstractFileByPath(decodeURIComponent(linkText));
                                    }
                                    catch (e) { }
                                }
                                if (file) {
                                    let _attributes = fetchTargetAttributesSync(app, settings, file, true);
                                    let attributes = {};
                                    for (let key in _attributes) {
                                        attributes["data-link-" + key] = _attributes[key];
                                    }
                                    let deco = view.Decoration.mark({
                                        attributes,
                                        class: "data-link-text"
                                    });
                                    let iconDecoBefore = view.Decoration.widget({
                                        widget: new HeaderWidget(attributes, false),
                                    });
                                    iconDecoAfter = view.Decoration.widget({
                                        widget: new HeaderWidget(attributes, true),
                                    });
                                    if (isMDUrl) {
                                        // Apply retroactively to the alias found before
                                        let deco = view.Decoration.mark({
                                            attributes: attributes,
                                            class: "data-link-text"
                                        });
                                        builder.add(mdAliasFrom, mdAliasFrom, iconDecoBefore);
                                        builder.add(mdAliasFrom, mdAliasTo, deco);
                                        if (iconDecoAfter) {
                                            builder.add(mdAliasTo, mdAliasTo, iconDecoAfter);
                                            iconDecoAfter = null;
                                            iconDecoAfterWhere = null;
                                            mdAliasFrom = null;
                                            mdAliasTo = null;
                                        }
                                    }
                                    else {
                                        builder.add(node.from, node.from, iconDecoBefore);
                                    }
                                    builder.add(node.from, node.to, deco);
                                    lastAttributes = attributes;
                                    iconDecoAfterWhere = node.to;
                                }
                            }
                            else if (isLink && isAlias) {
                                let deco = view.Decoration.mark({
                                    attributes: lastAttributes,
                                    class: "data-link-text"
                                });
                                builder.add(node.from, node.to, deco);
                                if (iconDecoAfter) {
                                    builder.add(node.to, node.to, iconDecoAfter);
                                    iconDecoAfter = null;
                                    iconDecoAfterWhere = null;
                                }
                            }
                        }
                    }
                });
            }
            return builder.finish();
        }
    }, {
        decorations: v => v.decorations
    });
    return viewPlugin;
}

class SuperchargedLinks extends obsidian.Plugin {
    constructor() {
        super(...arguments);
        this.modalObservers = [];
    }
    onload() {
        return __awaiter(this, void 0, void 0, function* () {
            console.log('Supercharged links loaded');
            yield this.loadSettings();
            this.addSettingTab(new SuperchargedLinksSettingTab(this.app, this));
            this.registerMarkdownPostProcessor((el, ctx) => {
                updateElLinks(this.app, this, el, ctx);
            });
            const plugin = this;
            const updateLinks = function (_file) {
                updateVisibleLinks(plugin.app, plugin);
                plugin.observers.forEach(([observer, type, own_class]) => {
                    const leaves = plugin.app.workspace.getLeavesOfType(type);
                    leaves.forEach(leaf => {
                        plugin.updateContainer(leaf.view.containerEl, plugin, own_class);
                    });
                });
            };
            // Live preview
            const ext = state.Prec.lowest(buildCMViewPlugin(this.app, this.settings));
            this.registerEditorExtension(ext);
            this.observers = [];
            this.app.workspace.onLayoutReady(() => {
                this.initViewObservers(this);
                this.initModalObservers(this, document);
                updateVisibleLinks(this.app, this);
            });
            // Initialization
            this.registerEvent(this.app.workspace.on("window-open", (window, win) => this.initModalObservers(this, window.getContainer().doc)));
            // Update when 
            // Debounced to prevent lag when writing
            this.registerEvent(this.app.metadataCache.on('changed', obsidian.debounce(updateLinks, 500, true)));
            // Update when layout changes
            // @ts-ignore
            this.registerEvent(this.app.workspace.on("layout-change", obsidian.debounce(updateLinks, 10, true)));
            // Update plugin views when layout changes
            // TODO: This is an expensive operation that seems like it is called fairly frequently. Maybe we can do this more efficiently?
            this.registerEvent(this.app.workspace.on("layout-change", () => this.initViewObservers(this)));
            // DEBUG: When adding a new view, to get the proper id of that view, uncomment this and reload the plugin
            // this.app.workspace.iterateAllLeaves(leaf => {
            // 	console.log(leaf.view.getViewType());
            // });
        });
    }
    initViewObservers(plugin) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
        // Reset observers
        plugin.observers.forEach(([observer, type]) => {
            observer.disconnect();
        });
        plugin.observers = [];
        // Register new observers for particular file panes
        plugin.registerViewType('backlink', plugin, ".tree-item-inner", true);
        plugin.registerViewType('outgoing-link', plugin, ".tree-item-inner", true);
        plugin.registerViewType('search', plugin, ".tree-item-inner");
        if ((_c = (_b = (_a = plugin.app) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.plugins) === null || _c === void 0 ? void 0 : _c.breadcrumbs) {
            // console.log('Supercharged links: Enabling breadcrumbs support');
            plugin.registerViewType('bc-matrix-view', plugin, 'span.internal-link');
            plugin.registerViewType('BC-ducks', plugin, '.internal-link');
            plugin.registerViewType('bc-tree-view', plugin, 'span.internal-link');
            // Breadcrumbs codeblock support as suggested by https://github.com/mdelobelle/obsidian_supercharged_links/issues/248#issuecomment-3231706063
            plugin.registerViewType('markdown', plugin, '.BC-page-views span.internal-link, .BC-codeblock-tree span.internal-link, .nodes a.internal-link');
        }
        plugin.registerViewType('graph-analysis', plugin, '.internal-link');
        plugin.registerViewType('starred', plugin, '.nav-file-title-content');
        plugin.registerViewType('file-explorer', plugin, '.nav-file-title-content');
        if ((_f = (_e = (_d = plugin.app) === null || _d === void 0 ? void 0 : _d.plugins) === null || _e === void 0 ? void 0 : _e.plugins) === null || _f === void 0 ? void 0 : _f['folder-notes']) {
            // console.log('Supercharged links: Enabling folder notes support');
            plugin.registerViewType('file-explorer', plugin, '.has-folder-note .tree-item-inner');
        }
        plugin.registerViewType('recent-files', plugin, '.nav-file-title-content');
        plugin.registerViewType('bookmarks', plugin, '.tree-item-inner', false, true);
        // @ts-ignore
        if (((_k = (_j = (_h = (_g = plugin.app) === null || _g === void 0 ? void 0 : _g.internalPlugins) === null || _h === void 0 ? void 0 : _h.plugins) === null || _j === void 0 ? void 0 : _j.bases) === null || _k === void 0 ? void 0 : _k.enabled) && plugin.settings.enableBases) {
            // console.log('Supercharged links: Enabling bases support');
            plugin.registerViewType('bases', plugin, 'span.internal-link');
            plugin.registerViewType('bases', plugin, '.multi-select-pill-content');
            // For embedded bases
            plugin.registerViewType('markdown', plugin, 'div.bases-table-cell > span.internal-link');
            plugin.registerViewType('markdown', plugin, 'div.bases-table-cell div.multi-select-pill-content');
            plugin.registerViewType('markdown', plugin, 'div.bases-cards-line');
        }
        if ((_o = (_m = (_l = plugin.app) === null || _l === void 0 ? void 0 : _l.plugins) === null || _m === void 0 ? void 0 : _m.plugins) === null || _o === void 0 ? void 0 : _o['similar-notes']) {
            plugin.registerViewType('markdown', plugin, '.similar-notes-pane .tree-item-inner', true);
        }
        // If backlinks in editor is on
        // @ts-ignore
        if (((_s = (_r = (_q = (_p = plugin.app) === null || _p === void 0 ? void 0 : _p.internalPlugins) === null || _q === void 0 ? void 0 : _q.plugins) === null || _r === void 0 ? void 0 : _r.backlink) === null || _s === void 0 ? void 0 : _s.enabled) && ((_y = (_x = (_w = (_v = (_u = (_t = plugin.app) === null || _t === void 0 ? void 0 : _t.internalPlugins) === null || _u === void 0 ? void 0 : _u.plugins) === null || _v === void 0 ? void 0 : _v.backlink) === null || _w === void 0 ? void 0 : _w.instance) === null || _x === void 0 ? void 0 : _x.options) === null || _y === void 0 ? void 0 : _y.backlinkInDocument)) {
            // console.log("Supercharged links: Enabling backlinks in document support");
            plugin.registerViewType('markdown', plugin, '.embedded-backlinks .tree-item-inner', true);
        }
        const propertyLeaves = this.app.workspace.getLeavesOfType("file-properties");
        for (let i = 0; i < propertyLeaves.length; i++) {
            const container = propertyLeaves[i].view.containerEl;
            let observer = new MutationObserver((records, _) => {
                const file = this.app.workspace.getActiveFile();
                if (!!file) {
                    updatePropertiesPane(container, this.app.workspace.getActiveFile(), this.app, plugin);
                }
            });
            observer.observe(container, { subtree: true, childList: true, attributes: false });
            plugin.observers.push([observer, "file-properties" + i, ""]);
            // TODO: No proper unloading!
        }
        plugin.registerViewType('file-properties', plugin, 'div.internal-link > .multi-select-pill-content');
        if ((_1 = (_0 = (_z = plugin.app) === null || _z === void 0 ? void 0 : _z.plugins) === null || _0 === void 0 ? void 0 : _0.plugins) === null || _1 === void 0 ? void 0 : _1['notebook-navigator']) {
            plugin.registerViewType('notebook-navigator', plugin, 'span.nn-shortcut-label');
            plugin.registerViewType('notebook-navigator', plugin, 'div.nn-file-name');
        }
    }
    initModalObservers(plugin, doc) {
        const config = {
            subtree: false,
            childList: true,
            attributes: false
        };
        this.modalObservers.push(new MutationObserver(records => {
            records.forEach((mutation) => {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(n => {
                        if ('className' in n &&
                            // @ts-ignore
                            (n.className.includes('modal-container') && plugin.settings.enableQuickSwitcher
                                // @ts-ignore
                                || n.className.includes('suggestion-container') && plugin.settings.enableSuggestor)) {
                            let selector = ".suggestion-title, .suggestion-note, .another-quick-switcher__item__title, .omnisearch-result__title > span";
                            // @ts-ignore
                            if (n.className.includes('suggestion-container')) {
                                selector = ".suggestion-title, .suggestion-note";
                            }
                            plugin.updateContainer(n, plugin, selector);
                            plugin._watchContainer(null, n, plugin, selector);
                        }
                    });
                }
            });
        }));
        this.modalObservers.last().observe(doc.body, config);
    }
    registerViewType(viewTypeName, plugin, selector, updateDynamic = false, filter_collapsible = false) {
        const leaves = this.app.workspace.getLeavesOfType(viewTypeName);
        // if (leaves.length > 1) {
        for (let i = 0; i < leaves.length; i++) {
            const container = leaves[i].view.containerEl;
            if (updateDynamic) {
                plugin._watchContainerDynamic(viewTypeName + i, container, plugin, selector);
            }
            else {
                plugin._watchContainer(viewTypeName + i, container, plugin, selector, filter_collapsible);
            }
        }
        // }
        // else if (leaves.length < 1) return;
        // else {
        // 	const container = leaves[0].view.containerEl;
        // 	this.updateContainer(container, plugin, selector);
        // 	if (updateDynamic) {
        // 		plugin._watchContainerDynamic(viewTypeName, container, plugin, selector)
        // 	}
        // 	else {
        // 		plugin._watchContainer(viewTypeName, container, plugin, selector);
        // 	}
        // }
    }
    updateContainer(container, plugin, selector, filter_collapsible = false) {
        if (!plugin.settings.enableBacklinks && container.getAttribute("data-type") !== "file-explorer")
            return;
        if (!plugin.settings.enableFileList && container.getAttribute("data-type") === "file-explorer")
            return;
        const nodes = container.findAll(selector);
        for (let i = 0; i < nodes.length; ++i) {
            const el = nodes[i];
            updateDivExtraAttributes(plugin.app, plugin.settings, el, "", undefined, filter_collapsible);
        }
    }
    removeFromContainer(container, selector) {
        const nodes = container.findAll(selector);
        for (let i = 0; i < nodes.length; ++i) {
            const el = nodes[i];
            clearExtraAttributes(el);
        }
    }
    _watchContainer(viewType, container, plugin, selector, filter_collapsible = false) {
        let observer = new MutationObserver((records, _) => {
            plugin.updateContainer(container, plugin, selector, filter_collapsible);
        });
        observer.observe(container, { subtree: true, childList: true, attributes: false });
        if (viewType) {
            plugin.observers.push([observer, viewType, selector]);
        }
    }
    _watchContainerDynamic(viewType, container, plugin, selector, parent_class = 'tree-item') {
        // Used for efficient updating of the backlinks panel
        // Only loops through newly added DOM nodes instead of changing all of them
        if (!plugin.settings.enableBacklinks)
            return;
        let observer = new MutationObserver((records, _) => {
            records.forEach((mutation) => {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach((n) => {
                        if ('className' in n) {
                            // @ts-ignore
                            if (n.className.includes && typeof n.className.includes === 'function' && n.className.includes(parent_class)) {
                                const fileDivs = n.findAll(selector);
                                for (let i = 0; i < fileDivs.length; ++i) {
                                    const link = fileDivs[i];
                                    updateDivExtraAttributes(plugin.app, plugin.settings, link, "");
                                }
                            }
                        }
                    });
                }
            });
        });
        observer.observe(container, { subtree: true, childList: true, attributes: false });
        plugin.observers.push([observer, viewType, selector]);
    }
    onunload() {
        this.observers.forEach(([observer, type, own_class]) => {
            observer.disconnect();
            const leaves = this.app.workspace.getLeavesOfType(type);
            leaves.forEach(leaf => {
                this.removeFromContainer(leaf.view.containerEl, own_class);
            });
        });
        for (const observer of this.modalObservers) {
            observer.disconnect();
        }
        console.log('Supercharged links unloaded');
    }
    loadSettings() {
        return __awaiter(this, void 0, void 0, function* () {
            this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
        });
    }
    saveSettings() {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.saveData(this.settings);
        });
    }
}

module.exports = SuperchargedLinks;


/* nosourcemap */