4425 lines
128 KiB
JavaScript
4425 lines
128 KiB
JavaScript
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
if you want to view the source, please visit the github repository of this plugin
|
|
*/
|
|
|
|
"use strict";
|
|
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
// file that has been converted to a CommonJS file using a Babel-
|
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
mod
|
|
));
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var __publicField = (obj, key, value) => {
|
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
return value;
|
|
};
|
|
|
|
// src/main.ts
|
|
var main_exports = {};
|
|
__export(main_exports, {
|
|
default: () => CoreSearchAssistantPlugin
|
|
});
|
|
module.exports = __toCommonJS(main_exports);
|
|
|
|
// src/Events.ts
|
|
var import_obsidian = require("obsidian");
|
|
var EVENT_SEARCH_RESULT_ITEM_DETECTED = "search-result-item-detected";
|
|
var EVENT_SORT_ORDER_CHANGED = "sort-order-changed";
|
|
var CoreSearchAssistantEvents = class extends import_obsidian.Events {
|
|
trigger(name, ...data) {
|
|
super.trigger(name, ...data);
|
|
}
|
|
on(name, callback, ctx) {
|
|
return super.on(name, callback, ctx);
|
|
}
|
|
};
|
|
|
|
// src/ModeScope.ts
|
|
var ModeScope = class {
|
|
constructor() {
|
|
this._depth = 0;
|
|
}
|
|
get inSearchMode() {
|
|
return this._depth > 0;
|
|
}
|
|
get depth() {
|
|
return this._depth;
|
|
}
|
|
push() {
|
|
this._depth++;
|
|
}
|
|
pop() {
|
|
this._depth--;
|
|
if (this.depth < 0) {
|
|
throw "[ERROR in Core Search Assistant] ModeScope.depth < 0";
|
|
}
|
|
}
|
|
reset() {
|
|
this._depth = 0;
|
|
}
|
|
};
|
|
|
|
// src/Setting.ts
|
|
var import_obsidian6 = require("obsidian");
|
|
|
|
// src/ui/HotkeySetter.ts
|
|
var import_obsidian5 = require("obsidian");
|
|
|
|
// node_modules/svelte/src/runtime/internal/utils.js
|
|
function noop() {
|
|
}
|
|
function run(fn) {
|
|
return fn();
|
|
}
|
|
function blank_object() {
|
|
return /* @__PURE__ */ Object.create(null);
|
|
}
|
|
function run_all(fns) {
|
|
fns.forEach(run);
|
|
}
|
|
function is_function(thing) {
|
|
return typeof thing === "function";
|
|
}
|
|
function safe_not_equal(a, b) {
|
|
return a != a ? b == b : a !== b || a && typeof a === "object" || typeof a === "function";
|
|
}
|
|
function is_empty(obj) {
|
|
return Object.keys(obj).length === 0;
|
|
}
|
|
function subscribe(store, ...callbacks) {
|
|
if (store == null) {
|
|
for (const callback of callbacks) {
|
|
callback(void 0);
|
|
}
|
|
return noop;
|
|
}
|
|
const unsub = store.subscribe(...callbacks);
|
|
return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
|
|
}
|
|
function component_subscribe(component, store, callback) {
|
|
component.$$.on_destroy.push(subscribe(store, callback));
|
|
}
|
|
|
|
// node_modules/svelte/src/runtime/internal/globals.js
|
|
var globals = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : (
|
|
// @ts-ignore Node typings have this
|
|
global
|
|
);
|
|
|
|
// node_modules/svelte/src/runtime/internal/ResizeObserverSingleton.js
|
|
var ResizeObserverSingleton = class _ResizeObserverSingleton {
|
|
/** @param {ResizeObserverOptions} options */
|
|
constructor(options) {
|
|
/**
|
|
* @private
|
|
* @readonly
|
|
* @type {WeakMap<Element, import('./private.js').Listener>}
|
|
*/
|
|
__publicField(this, "_listeners", "WeakMap" in globals ? /* @__PURE__ */ new WeakMap() : void 0);
|
|
/**
|
|
* @private
|
|
* @type {ResizeObserver}
|
|
*/
|
|
__publicField(this, "_observer");
|
|
/** @type {ResizeObserverOptions} */
|
|
__publicField(this, "options");
|
|
this.options = options;
|
|
}
|
|
/**
|
|
* @param {Element} element
|
|
* @param {import('./private.js').Listener} listener
|
|
* @returns {() => void}
|
|
*/
|
|
observe(element2, listener) {
|
|
this._listeners.set(element2, listener);
|
|
this._getObserver().observe(element2, this.options);
|
|
return () => {
|
|
this._listeners.delete(element2);
|
|
this._observer.unobserve(element2);
|
|
};
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
_getObserver() {
|
|
return this._observer ?? (this._observer = new ResizeObserver((entries) => {
|
|
for (const entry of entries) {
|
|
_ResizeObserverSingleton.entries.set(entry.target, entry);
|
|
this._listeners.get(entry.target)?.(entry);
|
|
}
|
|
}));
|
|
}
|
|
};
|
|
ResizeObserverSingleton.entries = "WeakMap" in globals ? /* @__PURE__ */ new WeakMap() : void 0;
|
|
|
|
// node_modules/svelte/src/runtime/internal/dom.js
|
|
var is_hydrating = false;
|
|
function start_hydrating() {
|
|
is_hydrating = true;
|
|
}
|
|
function end_hydrating() {
|
|
is_hydrating = false;
|
|
}
|
|
function append(target, node) {
|
|
target.appendChild(node);
|
|
}
|
|
function append_styles(target, style_sheet_id, styles) {
|
|
const append_styles_to = get_root_for_style(target);
|
|
if (!append_styles_to.getElementById(style_sheet_id)) {
|
|
const style = element("style");
|
|
style.id = style_sheet_id;
|
|
style.textContent = styles;
|
|
append_stylesheet(append_styles_to, style);
|
|
}
|
|
}
|
|
function get_root_for_style(node) {
|
|
if (!node)
|
|
return document;
|
|
const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
|
|
if (root && /** @type {ShadowRoot} */
|
|
root.host) {
|
|
return (
|
|
/** @type {ShadowRoot} */
|
|
root
|
|
);
|
|
}
|
|
return node.ownerDocument;
|
|
}
|
|
function append_stylesheet(node, style) {
|
|
append(
|
|
/** @type {Document} */
|
|
node.head || node,
|
|
style
|
|
);
|
|
return style.sheet;
|
|
}
|
|
function insert(target, node, anchor) {
|
|
target.insertBefore(node, anchor || null);
|
|
}
|
|
function detach(node) {
|
|
if (node.parentNode) {
|
|
node.parentNode.removeChild(node);
|
|
}
|
|
}
|
|
function destroy_each(iterations, detaching) {
|
|
for (let i = 0; i < iterations.length; i += 1) {
|
|
if (iterations[i])
|
|
iterations[i].d(detaching);
|
|
}
|
|
}
|
|
function element(name) {
|
|
return document.createElement(name);
|
|
}
|
|
function text(data) {
|
|
return document.createTextNode(data);
|
|
}
|
|
function space() {
|
|
return text(" ");
|
|
}
|
|
function listen(node, event, handler, options) {
|
|
node.addEventListener(event, handler, options);
|
|
return () => node.removeEventListener(event, handler, options);
|
|
}
|
|
function attr(node, attribute, value) {
|
|
if (value == null)
|
|
node.removeAttribute(attribute);
|
|
else if (node.getAttribute(attribute) !== value)
|
|
node.setAttribute(attribute, value);
|
|
}
|
|
function children(element2) {
|
|
return Array.from(element2.childNodes);
|
|
}
|
|
function set_data(text2, data) {
|
|
data = "" + data;
|
|
if (text2.data === data)
|
|
return;
|
|
text2.data = /** @type {string} */
|
|
data;
|
|
}
|
|
function toggle_class(element2, name, toggle) {
|
|
element2.classList.toggle(name, !!toggle);
|
|
}
|
|
function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
|
|
return new CustomEvent(type, { detail, bubbles, cancelable });
|
|
}
|
|
function get_custom_elements_slots(element2) {
|
|
const result = {};
|
|
element2.childNodes.forEach(
|
|
/** @param {Element} node */
|
|
(node) => {
|
|
result[node.slot || "default"] = true;
|
|
}
|
|
);
|
|
return result;
|
|
}
|
|
|
|
// node_modules/svelte/src/runtime/internal/lifecycle.js
|
|
var current_component;
|
|
function set_current_component(component) {
|
|
current_component = component;
|
|
}
|
|
function get_current_component() {
|
|
if (!current_component)
|
|
throw new Error("Function called outside component initialization");
|
|
return current_component;
|
|
}
|
|
function onMount(fn) {
|
|
get_current_component().$$.on_mount.push(fn);
|
|
}
|
|
function onDestroy(fn) {
|
|
get_current_component().$$.on_destroy.push(fn);
|
|
}
|
|
function createEventDispatcher() {
|
|
const component = get_current_component();
|
|
return (type, detail, { cancelable = false } = {}) => {
|
|
const callbacks = component.$$.callbacks[type];
|
|
if (callbacks) {
|
|
const event = custom_event(
|
|
/** @type {string} */
|
|
type,
|
|
detail,
|
|
{ cancelable }
|
|
);
|
|
callbacks.slice().forEach((fn) => {
|
|
fn.call(component, event);
|
|
});
|
|
return !event.defaultPrevented;
|
|
}
|
|
return true;
|
|
};
|
|
}
|
|
|
|
// node_modules/svelte/src/runtime/internal/scheduler.js
|
|
var dirty_components = [];
|
|
var binding_callbacks = [];
|
|
var render_callbacks = [];
|
|
var flush_callbacks = [];
|
|
var resolved_promise = /* @__PURE__ */ Promise.resolve();
|
|
var update_scheduled = false;
|
|
function schedule_update() {
|
|
if (!update_scheduled) {
|
|
update_scheduled = true;
|
|
resolved_promise.then(flush);
|
|
}
|
|
}
|
|
function add_render_callback(fn) {
|
|
render_callbacks.push(fn);
|
|
}
|
|
var seen_callbacks = /* @__PURE__ */ new Set();
|
|
var flushidx = 0;
|
|
function flush() {
|
|
if (flushidx !== 0) {
|
|
return;
|
|
}
|
|
const saved_component = current_component;
|
|
do {
|
|
try {
|
|
while (flushidx < dirty_components.length) {
|
|
const component = dirty_components[flushidx];
|
|
flushidx++;
|
|
set_current_component(component);
|
|
update(component.$$);
|
|
}
|
|
} catch (e) {
|
|
dirty_components.length = 0;
|
|
flushidx = 0;
|
|
throw e;
|
|
}
|
|
set_current_component(null);
|
|
dirty_components.length = 0;
|
|
flushidx = 0;
|
|
while (binding_callbacks.length)
|
|
binding_callbacks.pop()();
|
|
for (let i = 0; i < render_callbacks.length; i += 1) {
|
|
const callback = render_callbacks[i];
|
|
if (!seen_callbacks.has(callback)) {
|
|
seen_callbacks.add(callback);
|
|
callback();
|
|
}
|
|
}
|
|
render_callbacks.length = 0;
|
|
} while (dirty_components.length);
|
|
while (flush_callbacks.length) {
|
|
flush_callbacks.pop()();
|
|
}
|
|
update_scheduled = false;
|
|
seen_callbacks.clear();
|
|
set_current_component(saved_component);
|
|
}
|
|
function update($$) {
|
|
if ($$.fragment !== null) {
|
|
$$.update();
|
|
run_all($$.before_update);
|
|
const dirty = $$.dirty;
|
|
$$.dirty = [-1];
|
|
$$.fragment && $$.fragment.p($$.ctx, dirty);
|
|
$$.after_update.forEach(add_render_callback);
|
|
}
|
|
}
|
|
function flush_render_callbacks(fns) {
|
|
const filtered = [];
|
|
const targets = [];
|
|
render_callbacks.forEach((c) => fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c));
|
|
targets.forEach((c) => c());
|
|
render_callbacks = filtered;
|
|
}
|
|
|
|
// node_modules/svelte/src/runtime/internal/transitions.js
|
|
var outroing = /* @__PURE__ */ new Set();
|
|
var outros;
|
|
function group_outros() {
|
|
outros = {
|
|
r: 0,
|
|
c: [],
|
|
p: outros
|
|
// parent group
|
|
};
|
|
}
|
|
function check_outros() {
|
|
if (!outros.r) {
|
|
run_all(outros.c);
|
|
}
|
|
outros = outros.p;
|
|
}
|
|
function transition_in(block, local) {
|
|
if (block && block.i) {
|
|
outroing.delete(block);
|
|
block.i(local);
|
|
}
|
|
}
|
|
function transition_out(block, local, detach2, callback) {
|
|
if (block && block.o) {
|
|
if (outroing.has(block))
|
|
return;
|
|
outroing.add(block);
|
|
outros.c.push(() => {
|
|
outroing.delete(block);
|
|
if (callback) {
|
|
if (detach2)
|
|
block.d(1);
|
|
callback();
|
|
}
|
|
});
|
|
block.o(local);
|
|
} else if (callback) {
|
|
callback();
|
|
}
|
|
}
|
|
|
|
// node_modules/svelte/src/runtime/internal/each.js
|
|
function ensure_array_like(array_like_or_iterator) {
|
|
return array_like_or_iterator?.length !== void 0 ? array_like_or_iterator : Array.from(array_like_or_iterator);
|
|
}
|
|
|
|
// node_modules/svelte/src/shared/boolean_attributes.js
|
|
var _boolean_attributes = (
|
|
/** @type {const} */
|
|
[
|
|
"allowfullscreen",
|
|
"allowpaymentrequest",
|
|
"async",
|
|
"autofocus",
|
|
"autoplay",
|
|
"checked",
|
|
"controls",
|
|
"default",
|
|
"defer",
|
|
"disabled",
|
|
"formnovalidate",
|
|
"hidden",
|
|
"inert",
|
|
"ismap",
|
|
"loop",
|
|
"multiple",
|
|
"muted",
|
|
"nomodule",
|
|
"novalidate",
|
|
"open",
|
|
"playsinline",
|
|
"readonly",
|
|
"required",
|
|
"reversed",
|
|
"selected"
|
|
]
|
|
);
|
|
var boolean_attributes = /* @__PURE__ */ new Set([..._boolean_attributes]);
|
|
|
|
// node_modules/svelte/src/runtime/internal/Component.js
|
|
function create_component(block) {
|
|
block && block.c();
|
|
}
|
|
function mount_component(component, target, anchor) {
|
|
const { fragment, after_update } = component.$$;
|
|
fragment && fragment.m(target, anchor);
|
|
add_render_callback(() => {
|
|
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
|
|
if (component.$$.on_destroy) {
|
|
component.$$.on_destroy.push(...new_on_destroy);
|
|
} else {
|
|
run_all(new_on_destroy);
|
|
}
|
|
component.$$.on_mount = [];
|
|
});
|
|
after_update.forEach(add_render_callback);
|
|
}
|
|
function destroy_component(component, detaching) {
|
|
const $$ = component.$$;
|
|
if ($$.fragment !== null) {
|
|
flush_render_callbacks($$.after_update);
|
|
run_all($$.on_destroy);
|
|
$$.fragment && $$.fragment.d(detaching);
|
|
$$.on_destroy = $$.fragment = null;
|
|
$$.ctx = [];
|
|
}
|
|
}
|
|
function make_dirty(component, i) {
|
|
if (component.$$.dirty[0] === -1) {
|
|
dirty_components.push(component);
|
|
schedule_update();
|
|
component.$$.dirty.fill(0);
|
|
}
|
|
component.$$.dirty[i / 31 | 0] |= 1 << i % 31;
|
|
}
|
|
function init(component, options, instance8, create_fragment8, not_equal, props, append_styles2 = null, dirty = [-1]) {
|
|
const parent_component = current_component;
|
|
set_current_component(component);
|
|
const $$ = component.$$ = {
|
|
fragment: null,
|
|
ctx: [],
|
|
// state
|
|
props,
|
|
update: noop,
|
|
not_equal,
|
|
bound: blank_object(),
|
|
// lifecycle
|
|
on_mount: [],
|
|
on_destroy: [],
|
|
on_disconnect: [],
|
|
before_update: [],
|
|
after_update: [],
|
|
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
|
|
// everything else
|
|
callbacks: blank_object(),
|
|
dirty,
|
|
skip_bound: false,
|
|
root: options.target || parent_component.$$.root
|
|
};
|
|
append_styles2 && append_styles2($$.root);
|
|
let ready = false;
|
|
$$.ctx = instance8 ? instance8(component, options.props || {}, (i, ret, ...rest) => {
|
|
const value = rest.length ? rest[0] : ret;
|
|
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
|
|
if (!$$.skip_bound && $$.bound[i])
|
|
$$.bound[i](value);
|
|
if (ready)
|
|
make_dirty(component, i);
|
|
}
|
|
return ret;
|
|
}) : [];
|
|
$$.update();
|
|
ready = true;
|
|
run_all($$.before_update);
|
|
$$.fragment = create_fragment8 ? create_fragment8($$.ctx) : false;
|
|
if (options.target) {
|
|
if (options.hydrate) {
|
|
start_hydrating();
|
|
const nodes = children(options.target);
|
|
$$.fragment && $$.fragment.l(nodes);
|
|
nodes.forEach(detach);
|
|
} else {
|
|
$$.fragment && $$.fragment.c();
|
|
}
|
|
if (options.intro)
|
|
transition_in(component.$$.fragment);
|
|
mount_component(component, options.target, options.anchor);
|
|
end_hydrating();
|
|
flush();
|
|
}
|
|
set_current_component(parent_component);
|
|
}
|
|
var SvelteElement;
|
|
if (typeof HTMLElement === "function") {
|
|
SvelteElement = class extends HTMLElement {
|
|
constructor($$componentCtor, $$slots, use_shadow_dom) {
|
|
super();
|
|
/** The Svelte component constructor */
|
|
__publicField(this, "$$ctor");
|
|
/** Slots */
|
|
__publicField(this, "$$s");
|
|
/** The Svelte component instance */
|
|
__publicField(this, "$$c");
|
|
/** Whether or not the custom element is connected */
|
|
__publicField(this, "$$cn", false);
|
|
/** Component props data */
|
|
__publicField(this, "$$d", {});
|
|
/** `true` if currently in the process of reflecting component props back to attributes */
|
|
__publicField(this, "$$r", false);
|
|
/** @type {Record<string, CustomElementPropDefinition>} Props definition (name, reflected, type etc) */
|
|
__publicField(this, "$$p_d", {});
|
|
/** @type {Record<string, Function[]>} Event listeners */
|
|
__publicField(this, "$$l", {});
|
|
/** @type {Map<Function, Function>} Event listener unsubscribe functions */
|
|
__publicField(this, "$$l_u", /* @__PURE__ */ new Map());
|
|
this.$$ctor = $$componentCtor;
|
|
this.$$s = $$slots;
|
|
if (use_shadow_dom) {
|
|
this.attachShadow({ mode: "open" });
|
|
}
|
|
}
|
|
addEventListener(type, listener, options) {
|
|
this.$$l[type] = this.$$l[type] || [];
|
|
this.$$l[type].push(listener);
|
|
if (this.$$c) {
|
|
const unsub = this.$$c.$on(type, listener);
|
|
this.$$l_u.set(listener, unsub);
|
|
}
|
|
super.addEventListener(type, listener, options);
|
|
}
|
|
removeEventListener(type, listener, options) {
|
|
super.removeEventListener(type, listener, options);
|
|
if (this.$$c) {
|
|
const unsub = this.$$l_u.get(listener);
|
|
if (unsub) {
|
|
unsub();
|
|
this.$$l_u.delete(listener);
|
|
}
|
|
}
|
|
}
|
|
async connectedCallback() {
|
|
this.$$cn = true;
|
|
if (!this.$$c) {
|
|
let create_slot = function(name) {
|
|
return () => {
|
|
let node;
|
|
const obj = {
|
|
c: function create() {
|
|
node = element("slot");
|
|
if (name !== "default") {
|
|
attr(node, "name", name);
|
|
}
|
|
},
|
|
/**
|
|
* @param {HTMLElement} target
|
|
* @param {HTMLElement} [anchor]
|
|
*/
|
|
m: function mount(target, anchor) {
|
|
insert(target, node, anchor);
|
|
},
|
|
d: function destroy(detaching) {
|
|
if (detaching) {
|
|
detach(node);
|
|
}
|
|
}
|
|
};
|
|
return obj;
|
|
};
|
|
};
|
|
await Promise.resolve();
|
|
if (!this.$$cn || this.$$c) {
|
|
return;
|
|
}
|
|
const $$slots = {};
|
|
const existing_slots = get_custom_elements_slots(this);
|
|
for (const name of this.$$s) {
|
|
if (name in existing_slots) {
|
|
$$slots[name] = [create_slot(name)];
|
|
}
|
|
}
|
|
for (const attribute of this.attributes) {
|
|
const name = this.$$g_p(attribute.name);
|
|
if (!(name in this.$$d)) {
|
|
this.$$d[name] = get_custom_element_value(name, attribute.value, this.$$p_d, "toProp");
|
|
}
|
|
}
|
|
for (const key in this.$$p_d) {
|
|
if (!(key in this.$$d) && this[key] !== void 0) {
|
|
this.$$d[key] = this[key];
|
|
delete this[key];
|
|
}
|
|
}
|
|
this.$$c = new this.$$ctor({
|
|
target: this.shadowRoot || this,
|
|
props: {
|
|
...this.$$d,
|
|
$$slots,
|
|
$$scope: {
|
|
ctx: []
|
|
}
|
|
}
|
|
});
|
|
const reflect_attributes = () => {
|
|
this.$$r = true;
|
|
for (const key in this.$$p_d) {
|
|
this.$$d[key] = this.$$c.$$.ctx[this.$$c.$$.props[key]];
|
|
if (this.$$p_d[key].reflect) {
|
|
const attribute_value = get_custom_element_value(
|
|
key,
|
|
this.$$d[key],
|
|
this.$$p_d,
|
|
"toAttribute"
|
|
);
|
|
if (attribute_value == null) {
|
|
this.removeAttribute(this.$$p_d[key].attribute || key);
|
|
} else {
|
|
this.setAttribute(this.$$p_d[key].attribute || key, attribute_value);
|
|
}
|
|
}
|
|
}
|
|
this.$$r = false;
|
|
};
|
|
this.$$c.$$.after_update.push(reflect_attributes);
|
|
reflect_attributes();
|
|
for (const type in this.$$l) {
|
|
for (const listener of this.$$l[type]) {
|
|
const unsub = this.$$c.$on(type, listener);
|
|
this.$$l_u.set(listener, unsub);
|
|
}
|
|
}
|
|
this.$$l = {};
|
|
}
|
|
}
|
|
// We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte
|
|
// and setting attributes through setAttribute etc, this is helpful
|
|
attributeChangedCallback(attr2, _oldValue, newValue) {
|
|
if (this.$$r)
|
|
return;
|
|
attr2 = this.$$g_p(attr2);
|
|
this.$$d[attr2] = get_custom_element_value(attr2, newValue, this.$$p_d, "toProp");
|
|
this.$$c?.$set({ [attr2]: this.$$d[attr2] });
|
|
}
|
|
disconnectedCallback() {
|
|
this.$$cn = false;
|
|
Promise.resolve().then(() => {
|
|
if (!this.$$cn && this.$$c) {
|
|
this.$$c.$destroy();
|
|
this.$$c = void 0;
|
|
}
|
|
});
|
|
}
|
|
$$g_p(attribute_name) {
|
|
return Object.keys(this.$$p_d).find(
|
|
(key) => this.$$p_d[key].attribute === attribute_name || !this.$$p_d[key].attribute && key.toLowerCase() === attribute_name
|
|
) || attribute_name;
|
|
}
|
|
};
|
|
}
|
|
function get_custom_element_value(prop, value, props_definition, transform) {
|
|
const type = props_definition[prop]?.type;
|
|
value = type === "Boolean" && typeof value !== "boolean" ? value != null : value;
|
|
if (!transform || !props_definition[prop]) {
|
|
return value;
|
|
} else if (transform === "toAttribute") {
|
|
switch (type) {
|
|
case "Object":
|
|
case "Array":
|
|
return value == null ? null : JSON.stringify(value);
|
|
case "Boolean":
|
|
return value ? "" : null;
|
|
case "Number":
|
|
return value == null ? null : value;
|
|
default:
|
|
return value;
|
|
}
|
|
} else {
|
|
switch (type) {
|
|
case "Object":
|
|
case "Array":
|
|
return value && JSON.parse(value);
|
|
case "Boolean":
|
|
return value;
|
|
case "Number":
|
|
return value != null ? +value : value;
|
|
default:
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
var SvelteComponent = class {
|
|
constructor() {
|
|
/**
|
|
* ### PRIVATE API
|
|
*
|
|
* Do not use, may change at any time
|
|
*
|
|
* @type {any}
|
|
*/
|
|
__publicField(this, "$$");
|
|
/**
|
|
* ### PRIVATE API
|
|
*
|
|
* Do not use, may change at any time
|
|
*
|
|
* @type {any}
|
|
*/
|
|
__publicField(this, "$$set");
|
|
}
|
|
/** @returns {void} */
|
|
$destroy() {
|
|
destroy_component(this, 1);
|
|
this.$destroy = noop;
|
|
}
|
|
/**
|
|
* @template {Extract<keyof Events, string>} K
|
|
* @param {K} type
|
|
* @param {((e: Events[K]) => void) | null | undefined} callback
|
|
* @returns {() => void}
|
|
*/
|
|
$on(type, callback) {
|
|
if (!is_function(callback)) {
|
|
return noop;
|
|
}
|
|
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
|
|
callbacks.push(callback);
|
|
return () => {
|
|
const index = callbacks.indexOf(callback);
|
|
if (index !== -1)
|
|
callbacks.splice(index, 1);
|
|
};
|
|
}
|
|
/**
|
|
* @param {Partial<Props>} props
|
|
* @returns {void}
|
|
*/
|
|
$set(props) {
|
|
if (this.$$set && !is_empty(props)) {
|
|
this.$$.skip_bound = true;
|
|
this.$$set(props);
|
|
this.$$.skip_bound = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
// node_modules/svelte/src/shared/version.js
|
|
var PUBLIC_VERSION = "4";
|
|
|
|
// node_modules/svelte/src/runtime/internal/disclose-version/index.js
|
|
if (typeof window !== "undefined")
|
|
(window.__svelte || (window.__svelte = { v: /* @__PURE__ */ new Set() })).v.add(PUBLIC_VERSION);
|
|
|
|
// src/ui/HotKeyEntry.svelte
|
|
var import_obsidian4 = require("obsidian");
|
|
|
|
// src/ui/HotkeySetting.svelte
|
|
var import_obsidian3 = require("obsidian");
|
|
|
|
// src/utils/Keymap.ts
|
|
var import_obsidian2 = require("obsidian");
|
|
var CODE_KEY_MAP = {
|
|
Semicolon: ";",
|
|
Quote: "'",
|
|
Comma: ",",
|
|
Period: ".",
|
|
Slash: "/",
|
|
BracketLeft: "[",
|
|
BracketRight: "]",
|
|
BackSlash: "\\",
|
|
Backquote: "`",
|
|
Space: " ",
|
|
Minus: "-",
|
|
Equal: "="
|
|
};
|
|
for (let i = 0; i < 10; i++) {
|
|
CODE_KEY_MAP[`Digit${i}`] = i.toString();
|
|
}
|
|
for (let i = 65; i < 91; i++) {
|
|
const char = String.fromCharCode(i);
|
|
const upChar = char.toUpperCase();
|
|
CODE_KEY_MAP[`Key${upChar}`] = char;
|
|
}
|
|
function convertCodeToKey(code) {
|
|
return CODE_KEY_MAP[code] ?? code;
|
|
}
|
|
function convertKeyToText(key) {
|
|
switch (key) {
|
|
case "ArrowLeft":
|
|
return "\u2190";
|
|
case "ArrowRight":
|
|
return "\u2192";
|
|
case "ArrowUp":
|
|
return "\u2191";
|
|
case "ArrowDown":
|
|
return "\u2193";
|
|
case "Mod":
|
|
return import_obsidian2.Platform.isMacOS ? "\u2318" : "Ctrl";
|
|
case "Ctrl":
|
|
return import_obsidian2.Platform.isMacOS ? "\u2303" : "Ctrl";
|
|
case "Meta":
|
|
return import_obsidian2.Platform.isMacOS ? "\u2318" : "Win";
|
|
case "Alt":
|
|
return import_obsidian2.Platform.isMacOS ? "\u2325" : "Alt";
|
|
case "Shift":
|
|
return import_obsidian2.Platform.isMacOS ? "\u21E7" : "Shift";
|
|
case " ":
|
|
return "Space";
|
|
case "Enter":
|
|
return "\u21B5";
|
|
default:
|
|
return key.charAt(0).toUpperCase() + key.slice(1);
|
|
}
|
|
}
|
|
function convertHotkeyToText(hotkey) {
|
|
const parts = [];
|
|
hotkey.modifiers.forEach((mod) => {
|
|
parts.push(convertKeyToText(mod));
|
|
});
|
|
const modifierPart = parts.join(" ");
|
|
const keyPart = convertKeyToText(hotkey.key);
|
|
return ` ${modifierPart} ${keyPart} `;
|
|
}
|
|
function compileModifiers(modifiers) {
|
|
return modifiers.map((modifier) => {
|
|
return "Mod" === modifier ? import_obsidian2.Platform.isMacOS ? "Meta" : "Ctrl" : modifier;
|
|
}).sort().join(",");
|
|
}
|
|
function decompileModifiers(modifiersId) {
|
|
const modifiers = [];
|
|
const parts = modifiersId.split(",");
|
|
parts.forEach((s) => {
|
|
if (import_obsidian2.Platform.isMacOS && s === "Meta" || !import_obsidian2.Platform.isMacOS && s === "Ctrl") {
|
|
modifiers.push("Mod");
|
|
return;
|
|
}
|
|
if (s === "Alt" || s === "Shift" || s === "Meta" || s === "Ctrl") {
|
|
modifiers.push(s);
|
|
return;
|
|
}
|
|
});
|
|
return modifiers;
|
|
}
|
|
function getModifiers(evt) {
|
|
const modifiers = [];
|
|
evt.ctrlKey && modifiers.push("Ctrl");
|
|
evt.metaKey && modifiers.push("Meta");
|
|
evt.altKey && modifiers.push("Alt");
|
|
evt.shiftKey && modifiers.push("Shift");
|
|
return compileModifiers(modifiers);
|
|
}
|
|
function getHotkey(evt) {
|
|
const modifiers = decompileModifiers(getModifiers(evt));
|
|
const key = convertCodeToKey(evt.code);
|
|
return {
|
|
modifiers,
|
|
key
|
|
};
|
|
}
|
|
function contain(hotkeys, hotkey) {
|
|
const hotkeyId = convertHotkeyToText(hotkey);
|
|
return hotkeys.some((key) => {
|
|
return hotkeyId === convertHotkeyToText(key);
|
|
});
|
|
}
|
|
|
|
// src/ui/HotkeySetting.svelte
|
|
function add_css(target) {
|
|
append_styles(target, "svelte-2wacg2", ".icon-container.svelte-2wacg2{display:inline-block;cursor:pointer;width:16px;height:16px;border-radius:10px;line-height:16px;text-align:center}.icon-container.svelte-2wacg2:hover{background-color:var(--background-modifier-error);color:var(--text-on-accent)}.setting-hotkey.svelte-2wacg2{font-size:12px;background-color:var(--background-secondary-alt);border-radius:4px;padding:0 10px;min-height:24px;align-self:flex-end;position:relative}");
|
|
}
|
|
function create_fragment(ctx) {
|
|
let span1;
|
|
let t0_value = convertHotkeyToText(
|
|
/*hotkey*/
|
|
ctx[0]
|
|
) + "";
|
|
let t0;
|
|
let t1;
|
|
let span0;
|
|
let mounted;
|
|
let dispose;
|
|
return {
|
|
c() {
|
|
span1 = element("span");
|
|
t0 = text(t0_value);
|
|
t1 = space();
|
|
span0 = element("span");
|
|
attr(span0, "class", "icon-container svelte-2wacg2");
|
|
attr(span1, "class", "setting-hotkey svelte-2wacg2");
|
|
},
|
|
m(target, anchor) {
|
|
insert(target, span1, anchor);
|
|
append(span1, t0);
|
|
append(span1, t1);
|
|
append(span1, span0);
|
|
ctx[3](span0);
|
|
if (!mounted) {
|
|
dispose = listen(
|
|
span0,
|
|
"click",
|
|
/*onIconClicked*/
|
|
ctx[2]
|
|
);
|
|
mounted = true;
|
|
}
|
|
},
|
|
p(ctx2, [dirty]) {
|
|
if (dirty & /*hotkey*/
|
|
1 && t0_value !== (t0_value = convertHotkeyToText(
|
|
/*hotkey*/
|
|
ctx2[0]
|
|
) + ""))
|
|
set_data(t0, t0_value);
|
|
},
|
|
i: noop,
|
|
o: noop,
|
|
d(detaching) {
|
|
if (detaching) {
|
|
detach(span1);
|
|
}
|
|
ctx[3](null);
|
|
mounted = false;
|
|
dispose();
|
|
}
|
|
};
|
|
}
|
|
function instance($$self, $$props, $$invalidate) {
|
|
let { hotkey } = $$props;
|
|
let iconContainerEl;
|
|
const dispatcher = createEventDispatcher();
|
|
onMount(() => {
|
|
if (iconContainerEl instanceof HTMLSpanElement) {
|
|
(0, import_obsidian3.setIcon)(iconContainerEl, "cross", 8);
|
|
}
|
|
});
|
|
function onIconClicked() {
|
|
dispatcher("removed");
|
|
}
|
|
function span0_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
iconContainerEl = $$value;
|
|
$$invalidate(1, iconContainerEl);
|
|
});
|
|
}
|
|
$$self.$$set = ($$props2) => {
|
|
if ("hotkey" in $$props2)
|
|
$$invalidate(0, hotkey = $$props2.hotkey);
|
|
};
|
|
return [hotkey, iconContainerEl, onIconClicked, span0_binding];
|
|
}
|
|
var HotkeySetting = class extends SvelteComponent {
|
|
constructor(options) {
|
|
super();
|
|
init(this, options, instance, create_fragment, safe_not_equal, { hotkey: 0 }, add_css);
|
|
}
|
|
};
|
|
var HotkeySetting_default = HotkeySetting;
|
|
|
|
// src/ui/HotKeyEntry.svelte
|
|
function add_css2(target) {
|
|
append_styles(target, "svelte-1my40ui", ".item-container.svelte-1my40ui{display:flex;align-items:center;padding:18px 0 18px 0;border-top:1px solid var(--background-modifier-border)}.info-container.svelte-1my40ui{flex:1 1 auto;flex-grow:1;margin-right:20px}.control-container.svelte-1my40ui{flex:1 1 auto;text-align:right;display:flex;justify-content:flex-end;align-items:center}.hotkeys-container.svelte-1my40ui{display:flex;flex-direction:column;margin-right:6px}.setting-hotkey.svelte-1my40ui{font-size:12px;background-color:var(--interactive-accent);border-radius:4px;padding:0 10px;min-height:24px;align-self:flex-end;position:relative;color:var(--text-on-accent)}.icon-container.svelte-1my40ui{padding:4px 6px;border-radius:4px;color:var(--text-faint);cursor:pointer;height:26px}.icon-container.svelte-1my40ui:hover{background-color:var(--background-secondary-alt);color:var(--text-normal)}.icon-container.svelte-1my40ui .clickable-icon{color:unset;cursor:unset;margin:unset}.icon-container.svelte-1my40ui .setting-editor-extra-setting-button{line-height:0}.icon-container.svelte-1my40ui .clickable-icon svg{position:relative;bottom:2px}");
|
|
}
|
|
function get_each_context(ctx, list, i) {
|
|
const child_ctx = ctx.slice();
|
|
child_ctx[13] = list[i];
|
|
return child_ctx;
|
|
}
|
|
function create_each_block(ctx) {
|
|
let hotkeysetting;
|
|
let current;
|
|
function removed_handler() {
|
|
return (
|
|
/*removed_handler*/
|
|
ctx[8](
|
|
/*hotkey*/
|
|
ctx[13]
|
|
)
|
|
);
|
|
}
|
|
hotkeysetting = new HotkeySetting_default({ props: { hotkey: (
|
|
/*hotkey*/
|
|
ctx[13]
|
|
) } });
|
|
hotkeysetting.$on("removed", removed_handler);
|
|
return {
|
|
c() {
|
|
create_component(hotkeysetting.$$.fragment);
|
|
},
|
|
m(target, anchor) {
|
|
mount_component(hotkeysetting, target, anchor);
|
|
current = true;
|
|
},
|
|
p(new_ctx, dirty) {
|
|
ctx = new_ctx;
|
|
const hotkeysetting_changes = {};
|
|
if (dirty & /*_hotkeys*/
|
|
16)
|
|
hotkeysetting_changes.hotkey = /*hotkey*/
|
|
ctx[13];
|
|
hotkeysetting.$set(hotkeysetting_changes);
|
|
},
|
|
i(local) {
|
|
if (current)
|
|
return;
|
|
transition_in(hotkeysetting.$$.fragment, local);
|
|
current = true;
|
|
},
|
|
o(local) {
|
|
transition_out(hotkeysetting.$$.fragment, local);
|
|
current = false;
|
|
},
|
|
d(detaching) {
|
|
destroy_component(hotkeysetting, detaching);
|
|
}
|
|
};
|
|
}
|
|
function create_if_block(ctx) {
|
|
let div;
|
|
return {
|
|
c() {
|
|
div = element("div");
|
|
div.textContent = "Press hotkey...";
|
|
attr(div, "class", "setting-hotkey svelte-1my40ui");
|
|
},
|
|
m(target, anchor) {
|
|
insert(target, div, anchor);
|
|
},
|
|
d(detaching) {
|
|
if (detaching) {
|
|
detach(div);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
function create_fragment2(ctx) {
|
|
let div3;
|
|
let div0;
|
|
let t0;
|
|
let t1;
|
|
let div2;
|
|
let div1;
|
|
let t2;
|
|
let t3;
|
|
let span0;
|
|
let t4;
|
|
let span1;
|
|
let current;
|
|
let mounted;
|
|
let dispose;
|
|
let each_value = ensure_array_like(
|
|
/*_hotkeys*/
|
|
ctx[4] ?? []
|
|
);
|
|
let each_blocks = [];
|
|
for (let i = 0; i < each_value.length; i += 1) {
|
|
each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
|
|
}
|
|
const out = (i) => transition_out(each_blocks[i], 1, 1, () => {
|
|
each_blocks[i] = null;
|
|
});
|
|
let if_block = (
|
|
/*_listening*/
|
|
ctx[3] && create_if_block(ctx)
|
|
);
|
|
return {
|
|
c() {
|
|
div3 = element("div");
|
|
div0 = element("div");
|
|
t0 = text(
|
|
/*actionName*/
|
|
ctx[0]
|
|
);
|
|
t1 = space();
|
|
div2 = element("div");
|
|
div1 = element("div");
|
|
for (let i = 0; i < each_blocks.length; i += 1) {
|
|
each_blocks[i].c();
|
|
}
|
|
t2 = space();
|
|
if (if_block)
|
|
if_block.c();
|
|
t3 = space();
|
|
span0 = element("span");
|
|
t4 = space();
|
|
span1 = element("span");
|
|
attr(div0, "class", "info-container svelte-1my40ui");
|
|
attr(div1, "class", "hotkeys-container svelte-1my40ui");
|
|
attr(span0, "class", "icon-container svelte-1my40ui");
|
|
attr(span1, "class", "icon-container svelte-1my40ui");
|
|
attr(div2, "class", "control-container svelte-1my40ui");
|
|
attr(div3, "class", "item-container svelte-1my40ui");
|
|
},
|
|
m(target, anchor) {
|
|
insert(target, div3, anchor);
|
|
append(div3, div0);
|
|
append(div0, t0);
|
|
append(div3, t1);
|
|
append(div3, div2);
|
|
append(div2, div1);
|
|
for (let i = 0; i < each_blocks.length; i += 1) {
|
|
if (each_blocks[i]) {
|
|
each_blocks[i].m(div1, null);
|
|
}
|
|
}
|
|
append(div1, t2);
|
|
if (if_block)
|
|
if_block.m(div1, null);
|
|
append(div2, t3);
|
|
append(div2, span0);
|
|
ctx[9](span0);
|
|
append(div2, t4);
|
|
append(div2, span1);
|
|
ctx[11](span1);
|
|
current = true;
|
|
if (!mounted) {
|
|
dispose = [
|
|
listen(
|
|
span0,
|
|
"click",
|
|
/*click_handler*/
|
|
ctx[10]
|
|
),
|
|
listen(
|
|
span1,
|
|
"click",
|
|
/*click_handler_1*/
|
|
ctx[12]
|
|
)
|
|
];
|
|
mounted = true;
|
|
}
|
|
},
|
|
p(ctx2, [dirty]) {
|
|
if (!current || dirty & /*actionName*/
|
|
1)
|
|
set_data(
|
|
t0,
|
|
/*actionName*/
|
|
ctx2[0]
|
|
);
|
|
if (dirty & /*_hotkeys, dispatcher*/
|
|
48) {
|
|
each_value = ensure_array_like(
|
|
/*_hotkeys*/
|
|
ctx2[4] ?? []
|
|
);
|
|
let i;
|
|
for (i = 0; i < each_value.length; i += 1) {
|
|
const child_ctx = get_each_context(ctx2, each_value, i);
|
|
if (each_blocks[i]) {
|
|
each_blocks[i].p(child_ctx, dirty);
|
|
transition_in(each_blocks[i], 1);
|
|
} else {
|
|
each_blocks[i] = create_each_block(child_ctx);
|
|
each_blocks[i].c();
|
|
transition_in(each_blocks[i], 1);
|
|
each_blocks[i].m(div1, t2);
|
|
}
|
|
}
|
|
group_outros();
|
|
for (i = each_value.length; i < each_blocks.length; i += 1) {
|
|
out(i);
|
|
}
|
|
check_outros();
|
|
}
|
|
if (
|
|
/*_listening*/
|
|
ctx2[3]
|
|
) {
|
|
if (if_block) {
|
|
} else {
|
|
if_block = create_if_block(ctx2);
|
|
if_block.c();
|
|
if_block.m(div1, null);
|
|
}
|
|
} else if (if_block) {
|
|
if_block.d(1);
|
|
if_block = null;
|
|
}
|
|
},
|
|
i(local) {
|
|
if (current)
|
|
return;
|
|
for (let i = 0; i < each_value.length; i += 1) {
|
|
transition_in(each_blocks[i]);
|
|
}
|
|
current = true;
|
|
},
|
|
o(local) {
|
|
each_blocks = each_blocks.filter(Boolean);
|
|
for (let i = 0; i < each_blocks.length; i += 1) {
|
|
transition_out(each_blocks[i]);
|
|
}
|
|
current = false;
|
|
},
|
|
d(detaching) {
|
|
if (detaching) {
|
|
detach(div3);
|
|
}
|
|
destroy_each(each_blocks, detaching);
|
|
if (if_block)
|
|
if_block.d();
|
|
ctx[9](null);
|
|
ctx[11](null);
|
|
mounted = false;
|
|
run_all(dispose);
|
|
}
|
|
};
|
|
}
|
|
var ICON_SIZE = 22;
|
|
function instance2($$self, $$props, $$invalidate) {
|
|
let _hotkeys;
|
|
let _listening;
|
|
let { actionName } = $$props;
|
|
let { hotkeys } = $$props;
|
|
const listening = false;
|
|
let restoreButtonEl;
|
|
let addHotkeyButtonEl;
|
|
const dispatcher = createEventDispatcher();
|
|
onMount(() => {
|
|
if (restoreButtonEl) {
|
|
const component = new import_obsidian4.ExtraButtonComponent(restoreButtonEl).setTooltip("Restore default");
|
|
(0, import_obsidian4.setIcon)(component.extraSettingsEl, "reset", ICON_SIZE);
|
|
}
|
|
if (addHotkeyButtonEl) {
|
|
const component = new import_obsidian4.ExtraButtonComponent(addHotkeyButtonEl).setTooltip("Customize this action");
|
|
(0, import_obsidian4.setIcon)(component.extraSettingsEl, "any-key", ICON_SIZE);
|
|
}
|
|
});
|
|
const removed_handler = (hotkey) => {
|
|
dispatcher("removed", { removed: hotkey });
|
|
};
|
|
function span0_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
restoreButtonEl = $$value;
|
|
$$invalidate(1, restoreButtonEl);
|
|
});
|
|
}
|
|
const click_handler = () => {
|
|
dispatcher("restored");
|
|
};
|
|
function span1_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
addHotkeyButtonEl = $$value;
|
|
$$invalidate(2, addHotkeyButtonEl);
|
|
});
|
|
}
|
|
const click_handler_1 = () => {
|
|
dispatcher("start-listening-keys");
|
|
};
|
|
$$self.$$set = ($$props2) => {
|
|
if ("actionName" in $$props2)
|
|
$$invalidate(0, actionName = $$props2.actionName);
|
|
if ("hotkeys" in $$props2)
|
|
$$invalidate(6, hotkeys = $$props2.hotkeys);
|
|
};
|
|
$$self.$$.update = () => {
|
|
if ($$self.$$.dirty & /*hotkeys*/
|
|
64) {
|
|
$:
|
|
$$invalidate(4, _hotkeys = [...hotkeys ?? []]);
|
|
}
|
|
};
|
|
$:
|
|
$$invalidate(3, _listening = listening);
|
|
return [
|
|
actionName,
|
|
restoreButtonEl,
|
|
addHotkeyButtonEl,
|
|
_listening,
|
|
_hotkeys,
|
|
dispatcher,
|
|
hotkeys,
|
|
listening,
|
|
removed_handler,
|
|
span0_binding,
|
|
click_handler,
|
|
span1_binding,
|
|
click_handler_1
|
|
];
|
|
}
|
|
var HotKeyEntry = class extends SvelteComponent {
|
|
constructor(options) {
|
|
super();
|
|
init(this, options, instance2, create_fragment2, safe_not_equal, { actionName: 0, hotkeys: 6, listening: 7 }, add_css2);
|
|
}
|
|
get listening() {
|
|
return this.$$.ctx[7];
|
|
}
|
|
};
|
|
var HotKeyEntry_default = HotKeyEntry;
|
|
|
|
// src/ui/HotkeySetter.ts
|
|
var HotkeySetter = class {
|
|
constructor(app2, containerEl, text2, currentHotkeys, defaultHotkeys) {
|
|
this.shouldReflect = (_) => true;
|
|
this.onRestored = () => {
|
|
const { component } = this;
|
|
if (!component)
|
|
return;
|
|
const renewed = [...this.defaultHotkeys];
|
|
if (this.shouldReflect(renewed)) {
|
|
this.currentHotkeys = renewed;
|
|
component.$set({
|
|
hotkeys: renewed
|
|
});
|
|
}
|
|
};
|
|
this.onRemoved = (evt) => {
|
|
const { component } = this;
|
|
if (!component)
|
|
return;
|
|
if (!(evt instanceof CustomEvent))
|
|
return;
|
|
const removed = evt.detail.removed;
|
|
const renewed = [...this.currentHotkeys];
|
|
renewed.remove(removed);
|
|
if (this.shouldReflect(renewed)) {
|
|
this.currentHotkeys = renewed;
|
|
component.$set({
|
|
hotkeys: renewed
|
|
});
|
|
}
|
|
};
|
|
this.onStartListening = () => {
|
|
const { component } = this;
|
|
if (!component)
|
|
return;
|
|
component.$set({
|
|
listening: true
|
|
});
|
|
this.scope = new import_obsidian5.Scope();
|
|
this.app.keymap.pushScope(this.scope);
|
|
this.scope.register(null, null, (evt) => {
|
|
evt.preventDefault();
|
|
if (evt.key === "Escape") {
|
|
component.$set({
|
|
listening: false
|
|
});
|
|
if (this.scope)
|
|
this.app.keymap.popScope(this.scope);
|
|
return;
|
|
}
|
|
const hotkey = getHotkey(evt);
|
|
const collision = contain(this.currentHotkeys, hotkey);
|
|
if (collision)
|
|
return;
|
|
const renewed = [...this.currentHotkeys];
|
|
renewed.push(hotkey);
|
|
if (!this.shouldReflect(renewed, hotkey))
|
|
return;
|
|
this.currentHotkeys = renewed;
|
|
component.$set({
|
|
hotkeys: renewed
|
|
});
|
|
component.$set({
|
|
listening: false
|
|
});
|
|
if (this.scope)
|
|
this.app.keymap.popScope(this.scope);
|
|
});
|
|
};
|
|
this.app = app2;
|
|
this.containerEl = containerEl;
|
|
this.text = text2;
|
|
this.currentHotkeys = [...currentHotkeys];
|
|
this.defaultHotkeys = [...defaultHotkeys];
|
|
this.component = this.attachComponent();
|
|
}
|
|
unload() {
|
|
this.onunload();
|
|
}
|
|
/**
|
|
* @param cb : should return true if you want to adopt the current change
|
|
*/
|
|
onChanged(cb) {
|
|
this.shouldReflect = cb;
|
|
return this;
|
|
}
|
|
attachComponent() {
|
|
const component = new HotKeyEntry_default({
|
|
target: this.containerEl,
|
|
props: {
|
|
actionName: this.text,
|
|
hotkeys: this.currentHotkeys
|
|
}
|
|
});
|
|
component.$on("removed", this.onRemoved);
|
|
component.$on("restored", this.onRestored);
|
|
component.$on("start-listening-keys", this.onStartListening);
|
|
return component;
|
|
}
|
|
onunload() {
|
|
this.component?.$destroy();
|
|
if (this.scope) {
|
|
this.app.keymap.popScope(this.scope);
|
|
}
|
|
}
|
|
};
|
|
|
|
// src/Setting.ts
|
|
var AVAILABLE_OUTLINE_WIDTHS = [0, 3, 5, 7, 10];
|
|
var AUTO_PREVIEW_MODE_IDS = ["none", "singleView", "cardView"];
|
|
var autoPreviewModeInfos = {
|
|
none: "none",
|
|
singleView: "single view",
|
|
cardView: "card view"
|
|
};
|
|
var AVAILABLE_CARD_LAYOUT = ["2x2", "2x3", "3x2", "3x3"];
|
|
var DEFAULT_SETTINGS = {
|
|
keepSelectedItemsCentered: false,
|
|
outlineWidth: 5,
|
|
autoPreviewMode: "cardView",
|
|
cardViewLayout: "2x3",
|
|
splitDirection: "horizontal",
|
|
autoToggleSidebar: false,
|
|
renderCardsManually: false,
|
|
// hideIframe: false,
|
|
searchModeHotkeys: {
|
|
selectNext: [
|
|
{ modifiers: ["Ctrl"], key: "n" },
|
|
{ modifiers: [], key: "ArrowDown" }
|
|
],
|
|
selectPrevious: [
|
|
{ modifiers: ["Ctrl"], key: "p" },
|
|
{ modifiers: [], key: "ArrowUp" }
|
|
],
|
|
previewModal: [{ modifiers: ["Ctrl"], key: " " }],
|
|
open: [{ modifiers: ["Ctrl"], key: "Enter" }],
|
|
openInNewPane: [{ modifiers: ["Ctrl", "Shift"], key: "Enter" }],
|
|
showOptions: [{ modifiers: ["Shift"], key: " " }],
|
|
nextPage: [{ modifiers: ["Ctrl"], key: "]" }],
|
|
previousPage: [{ modifiers: ["Ctrl"], key: "[" }],
|
|
copyLink: [{ modifiers: ["Ctrl"], key: "i" }]
|
|
},
|
|
previewModalHotkeys: {
|
|
scrollDown: [
|
|
{ modifiers: ["Ctrl"], key: "n" },
|
|
{ modifiers: [], key: "ArrowDown" }
|
|
],
|
|
scrollUp: [
|
|
{ modifiers: ["Ctrl"], key: "p" },
|
|
{ modifiers: [], key: "ArrowUp" }
|
|
],
|
|
bigScrollDown: [{ modifiers: [], key: " " }],
|
|
bigScrollUp: [{ modifiers: ["Shift"], key: " " }],
|
|
open: [{ modifiers: ["Ctrl"], key: "Enter" }],
|
|
openInNewPage: [{ modifiers: ["Ctrl", "Shift"], key: "Enter" }],
|
|
closeModal: [{ modifiers: ["Ctrl"], key: " " }],
|
|
focusNext: [{ modifiers: [], key: "Tab" }],
|
|
focusPrevious: [{ modifiers: ["Shift"], key: "Tab" }],
|
|
togglePreviewMode: [{ modifiers: ["Ctrl"], key: "e" }],
|
|
copyLink: [{ modifiers: ["Ctrl"], key: "i" }]
|
|
}
|
|
};
|
|
var CoreSearchAssistantSettingTab = class extends import_obsidian6.PluginSettingTab {
|
|
constructor(app2, plugin2) {
|
|
super(app2, plugin2);
|
|
this.plugin = plugin2;
|
|
this.hotkeySetters = [];
|
|
}
|
|
display() {
|
|
this.hide();
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
new import_obsidian6.Setting(containerEl).setName("Keep selected item centered").addToggle((component) => {
|
|
component.setValue(
|
|
this.plugin.settings?.keepSelectedItemsCentered ?? DEFAULT_SETTINGS.keepSelectedItemsCentered
|
|
).onChange((value) => {
|
|
if (!this.plugin.settings) {
|
|
return;
|
|
}
|
|
this.plugin.settings.keepSelectedItemsCentered = value;
|
|
this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian6.Setting(containerEl).setName("Outline width (px)").setDesc("An outline appears when you enter search mode.").addDropdown((component) => {
|
|
AVAILABLE_OUTLINE_WIDTHS.forEach((width) => {
|
|
const text2 = width.toString();
|
|
component.addOption(text2, text2);
|
|
});
|
|
component.setValue(
|
|
validOutlineWidth(this.plugin.settings?.outlineWidth).toString()
|
|
).onChange((value) => {
|
|
const width = Number.parseInt(value);
|
|
if (!this.plugin.settings) {
|
|
return;
|
|
}
|
|
if (!AVAILABLE_OUTLINE_WIDTHS.includes(width)) {
|
|
return;
|
|
}
|
|
this.plugin.settings.outlineWidth = width;
|
|
this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian6.Setting(containerEl).setName("Auto preview mode").addDropdown((component) => {
|
|
component.addOptions(autoPreviewModeInfos).setValue(this.plugin.settings?.autoPreviewMode ?? "cardView").onChange((id) => {
|
|
if (!this.plugin.settings) {
|
|
return;
|
|
}
|
|
if (!AUTO_PREVIEW_MODE_IDS.includes(id)) {
|
|
return;
|
|
}
|
|
this.plugin.settings.autoPreviewMode = id;
|
|
this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian6.Setting(containerEl).setName("Default layout of card view").addDropdown((component) => {
|
|
AVAILABLE_CARD_LAYOUT.forEach((layout) => {
|
|
component.addOption(layout, layout);
|
|
});
|
|
component.setValue(
|
|
this.plugin.settings?.cardViewLayout ?? DEFAULT_SETTINGS.cardViewLayout
|
|
).onChange((value) => {
|
|
if (!this.plugin.settings) {
|
|
return;
|
|
}
|
|
if (!AVAILABLE_CARD_LAYOUT.includes(value)) {
|
|
return;
|
|
}
|
|
this.plugin.settings.cardViewLayout = value;
|
|
this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian6.Setting(containerEl).setName("Default split direction").setDesc("This applies when you open a file in a new pane").addDropdown((component) => {
|
|
if (!this.plugin.settings) {
|
|
return;
|
|
}
|
|
component.addOptions({
|
|
horizontal: "horizontal",
|
|
vertical: "vertical"
|
|
}).setValue(this.plugin.settings.splitDirection).onChange(async (direction) => {
|
|
if (!this.plugin.settings) {
|
|
return;
|
|
}
|
|
if (direction === "horizontal" || direction === "vertical") {
|
|
this.plugin.settings.splitDirection = direction;
|
|
await this.plugin.saveSettings();
|
|
}
|
|
});
|
|
});
|
|
new import_obsidian6.Setting(containerEl).setName("Toggle sidebars automatically").setDesc(
|
|
"Automatically collapse the other sidebar when entering the search mode and the search panel when exiting the search mode"
|
|
).addToggle((component) => {
|
|
if (!this.plugin.settings) {
|
|
return;
|
|
}
|
|
component.setValue(this.plugin.settings.autoToggleSidebar).onChange((value) => {
|
|
if (!this.plugin.settings) {
|
|
return;
|
|
}
|
|
this.plugin.settings.autoToggleSidebar = value;
|
|
this.plugin.saveSettings();
|
|
});
|
|
});
|
|
new import_obsidian6.Setting(containerEl).setName("Render cards manually").setDesc("If enabled, you must hit the enter key to render cards.").addToggle((component) => {
|
|
if (!this.plugin.settings)
|
|
return;
|
|
component.setValue(this.plugin.settings.renderCardsManually).onChange((value) => {
|
|
if (!this.plugin.settings)
|
|
return;
|
|
this.plugin.settings.renderCardsManually = value;
|
|
this.plugin.saveSettings();
|
|
});
|
|
});
|
|
containerEl.createEl("h2", { text: "Hotkeys" });
|
|
const { settings } = this.plugin;
|
|
containerEl.createEl("h3", { text: "Search mode" });
|
|
if (!settings)
|
|
return;
|
|
SEARCH_MODE_HOTKEY_ACTION_IDS.forEach((actionId) => {
|
|
const hotkeys = settings.searchModeHotkeys[actionId];
|
|
const defaultHotkeys = DEFAULT_SETTINGS.searchModeHotkeys[actionId];
|
|
const description = SEARCH_MODE_HOTKEY_ACTION_INFO[actionId];
|
|
const hotkeySetter = new HotkeySetter(
|
|
this.app,
|
|
containerEl,
|
|
description,
|
|
hotkeys,
|
|
defaultHotkeys
|
|
).onChanged((renewed, added) => {
|
|
if (added) {
|
|
if (added.modifiers.length === 0)
|
|
return false;
|
|
const collision = SEARCH_MODE_HOTKEY_ACTION_IDS.some((actionId2) => {
|
|
const hotkeys2 = settings.searchModeHotkeys[actionId2];
|
|
return contain(hotkeys2, added);
|
|
});
|
|
if (collision) {
|
|
new import_obsidian6.Notice("Hotkeys are conflicting!");
|
|
return false;
|
|
}
|
|
}
|
|
settings.searchModeHotkeys[actionId] = renewed;
|
|
this.plugin.saveSettings();
|
|
return true;
|
|
});
|
|
this.hotkeySetters.push(hotkeySetter);
|
|
});
|
|
containerEl.createEl("h3", { text: "Preview Modal" });
|
|
PREVIEW_MODAL_HOTKEY_ACTION_IDS.forEach((actionId) => {
|
|
const hotkeys = settings.previewModalHotkeys[actionId];
|
|
const defaultHotkeys = DEFAULT_SETTINGS.previewModalHotkeys[actionId];
|
|
const description = PREVIEW_MODAL_HOTKEY_ACTION_INFO[actionId];
|
|
DEFAULT_SETTINGS.previewModalHotkeys[actionId];
|
|
const hotkeySetter = new HotkeySetter(
|
|
this.app,
|
|
containerEl,
|
|
description,
|
|
hotkeys,
|
|
defaultHotkeys
|
|
).onChanged((renewed, added) => {
|
|
if (added) {
|
|
const collision = PREVIEW_MODAL_HOTKEY_ACTION_IDS.some((actionId2) => {
|
|
const hotkeys2 = settings.previewModalHotkeys[actionId2];
|
|
return contain(hotkeys2, added);
|
|
});
|
|
if (collision) {
|
|
new import_obsidian6.Notice("Hotkeys are conflicting!");
|
|
return false;
|
|
}
|
|
}
|
|
settings.previewModalHotkeys[actionId] = renewed;
|
|
this.plugin.saveSettings();
|
|
return true;
|
|
});
|
|
this.hotkeySetters.push(hotkeySetter);
|
|
});
|
|
}
|
|
hide() {
|
|
super.hide();
|
|
this.hotkeySetters.forEach((s) => s.unload());
|
|
this.hotkeySetters = [];
|
|
}
|
|
};
|
|
function validOutlineWidth(width) {
|
|
if (typeof width !== "number") {
|
|
return DEFAULT_SETTINGS.outlineWidth;
|
|
}
|
|
if (!Number.isInteger(width)) {
|
|
return DEFAULT_SETTINGS.outlineWidth;
|
|
}
|
|
if (!AVAILABLE_OUTLINE_WIDTHS.includes(width)) {
|
|
return DEFAULT_SETTINGS.outlineWidth;
|
|
}
|
|
return width;
|
|
}
|
|
function parseCardLayout(layout) {
|
|
const [row, column] = layout.split("x");
|
|
return [Number.parseInt(row ?? "0"), Number.parseInt(column ?? "0")];
|
|
}
|
|
var SEARCH_MODE_HOTKEY_ACTION_IDS = [
|
|
"selectNext",
|
|
"selectPrevious",
|
|
"previewModal",
|
|
"open",
|
|
"openInNewPane",
|
|
"showOptions",
|
|
"nextPage",
|
|
"previousPage",
|
|
"copyLink"
|
|
];
|
|
var SEARCH_MODE_HOTKEY_ACTION_INFO = {
|
|
selectNext: "Select the next item",
|
|
selectPrevious: "Select the previous item",
|
|
previewModal: "Preview the selected item",
|
|
open: "Open the selected item",
|
|
openInNewPane: "Open the selected item in a new pane",
|
|
showOptions: "Set search options",
|
|
nextPage: "Move to the next set of cards",
|
|
previousPage: "Move to the previous set of cards",
|
|
copyLink: "Copy wiki link of the selected item"
|
|
};
|
|
var PREVIEW_MODAL_HOTKEY_ACTION_IDS = [
|
|
"scrollDown",
|
|
"scrollUp",
|
|
"bigScrollDown",
|
|
"bigScrollUp",
|
|
"open",
|
|
"openInNewPage",
|
|
"closeModal",
|
|
"focusNext",
|
|
"focusPrevious",
|
|
"togglePreviewMode",
|
|
"copyLink"
|
|
];
|
|
var PREVIEW_MODAL_HOTKEY_ACTION_INFO = {
|
|
scrollDown: "Scroll down a bit",
|
|
scrollUp: "Scroll up a bit",
|
|
bigScrollDown: "Scroll down a lot",
|
|
bigScrollUp: "Scroll up a lot",
|
|
open: "Open the selected item",
|
|
openInNewPage: "Open the selected item in a new pane",
|
|
closeModal: "Close the modal",
|
|
focusNext: "Focus on the next match",
|
|
focusPrevious: "Focus on the previous match",
|
|
togglePreviewMode: "Toggle preview mode",
|
|
copyLink: "Copy wiki link of the selected item"
|
|
};
|
|
|
|
// src/components/OptionModal.ts
|
|
var import_obsidian7 = require("obsidian");
|
|
|
|
// src/types/Option.ts
|
|
var searchOptions = {
|
|
matchingCase: {
|
|
iconId: "uppercase-lowercase-a",
|
|
description: "Toggle matching case"
|
|
},
|
|
explainSearch: {
|
|
iconId: "info",
|
|
description: "Toggle explanation of search term"
|
|
},
|
|
collapseAll: {
|
|
iconId: "bullet-list",
|
|
description: "Toggle collapsing results"
|
|
},
|
|
extraContext: {
|
|
iconId: "expand-vertically",
|
|
description: "Toggle showing more context"
|
|
},
|
|
alphabetical: {
|
|
iconId: "down-arrow-with-tail",
|
|
description: "Sort by file name (A \u2192 Z)"
|
|
},
|
|
alphabeticalReverse: {
|
|
iconId: "up-arrow-with-tail",
|
|
description: "Sort by file name (Z \u2192 A)"
|
|
},
|
|
byModifiedTime: {
|
|
iconId: "down-arrow-with-tail",
|
|
description: "Sort by modified time (new \u2192 old)"
|
|
},
|
|
byModifiedTimeReverse: {
|
|
iconId: "up-arrow-with-tail",
|
|
description: "Sort by modified time (old \u2192 new)"
|
|
},
|
|
byCreatedTime: {
|
|
iconId: "down-arrow-with-tail",
|
|
description: "Sort by created time (new \u2192 old)"
|
|
},
|
|
byCreatedTimeReverse: {
|
|
iconId: "up-arrow-with-tail",
|
|
description: "Sort by created time (old \u2192 new)"
|
|
}
|
|
};
|
|
|
|
// src/components/OptionModal.ts
|
|
var OptionModal = class extends import_obsidian7.Modal {
|
|
constructor(app2, plugin2, modeScope) {
|
|
super(app2);
|
|
this.plugin = plugin2;
|
|
this.modeScope = modeScope;
|
|
this.items = [
|
|
{
|
|
id: "matchingCase",
|
|
key: "a",
|
|
onChoose: () => {
|
|
this.plugin.searchInterface?.toggleMatchingCase();
|
|
this.plugin.searchInterface?.renewSortOrderInfo();
|
|
this.plugin.controller?.reset();
|
|
}
|
|
},
|
|
{
|
|
id: "explainSearch",
|
|
key: "s",
|
|
onChoose: () => {
|
|
this.plugin.searchInterface?.toggleExplainSearch();
|
|
}
|
|
},
|
|
{
|
|
id: "collapseAll",
|
|
key: "d",
|
|
onChoose: () => {
|
|
this.plugin.searchInterface?.toggleCollapseAll();
|
|
}
|
|
},
|
|
{
|
|
id: "extraContext",
|
|
key: "f",
|
|
onChoose: () => {
|
|
this.plugin.searchInterface?.toggleExtraContext();
|
|
}
|
|
},
|
|
{
|
|
id: "alphabetical",
|
|
key: "g",
|
|
onChoose: () => {
|
|
const changed = this.plugin.searchInterface?.setSortOrder("alphabetical");
|
|
if (changed) {
|
|
this.plugin.searchInterface?.renewSortOrderInfo();
|
|
this.plugin.controller?.reset();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: "alphabeticalReverse",
|
|
key: "h",
|
|
onChoose: () => {
|
|
const changed = this.plugin.searchInterface?.setSortOrder(
|
|
"alphabeticalReverse"
|
|
);
|
|
if (changed) {
|
|
this.plugin.searchInterface?.renewSortOrderInfo();
|
|
this.plugin.controller?.reset();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: "byModifiedTime",
|
|
key: "j",
|
|
onChoose: () => {
|
|
const changed = this.plugin.searchInterface?.setSortOrder("byModifiedTime");
|
|
if (changed) {
|
|
this.plugin.searchInterface?.renewSortOrderInfo();
|
|
this.plugin.controller?.reset();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: "byModifiedTimeReverse",
|
|
key: "k",
|
|
onChoose: () => {
|
|
const changed = this.plugin.searchInterface?.setSortOrder(
|
|
"byModifiedTimeReverse"
|
|
);
|
|
if (changed) {
|
|
this.plugin.searchInterface?.renewSortOrderInfo();
|
|
this.plugin.controller?.reset();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: "byCreatedTime",
|
|
key: "l",
|
|
onChoose: () => {
|
|
const changed = this.plugin.searchInterface?.setSortOrder("byCreatedTime");
|
|
if (changed) {
|
|
this.plugin.searchInterface?.renewSortOrderInfo();
|
|
this.plugin.controller?.reset();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: "byCreatedTimeReverse",
|
|
key: ";",
|
|
onChoose: () => {
|
|
const changed = this.plugin.searchInterface?.setSortOrder(
|
|
"byCreatedTimeReverse"
|
|
);
|
|
if (changed) {
|
|
this.plugin.searchInterface?.renewSortOrderInfo();
|
|
this.plugin.controller?.reset();
|
|
}
|
|
}
|
|
}
|
|
];
|
|
}
|
|
onOpen() {
|
|
this.modeScope.push();
|
|
this.items.forEach((item) => {
|
|
this.scope.register([], item.key, item.onChoose);
|
|
});
|
|
this.renderOptions();
|
|
}
|
|
onClose() {
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
setTimeout(() => this.modeScope.pop(), 100);
|
|
}
|
|
renderOptions() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
this.containerEl.addClass("core-search-assistant_option-modal");
|
|
this.items.forEach((item) => {
|
|
const entryEl = contentEl.createEl("div", {
|
|
cls: "suggestion-item"
|
|
});
|
|
const iconEl = entryEl.createEl("span", {
|
|
cls: "suggestion-icon"
|
|
});
|
|
(0, import_obsidian7.setIcon)(iconEl, searchOptions[item.id].iconId);
|
|
entryEl.createEl("span", {
|
|
text: searchOptions[item.id].description,
|
|
cls: "suggestion-content"
|
|
});
|
|
entryEl.createEl("kbd", {
|
|
text: item.key.toUpperCase(),
|
|
cls: "suggestion-hotkey"
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
// src/components/PreviewModal.ts
|
|
var import_obsidian13 = require("obsidian");
|
|
|
|
// src/interfaces/ViewGenerator.ts
|
|
var import_obsidian8 = require("obsidian");
|
|
|
|
// src/utils/Util.ts
|
|
async function delay(millisecond) {
|
|
await new Promise((resolve) => setTimeout(resolve, millisecond));
|
|
}
|
|
function scrollIteration(editor) {
|
|
const line = lineCount(editor);
|
|
if (line === void 0) {
|
|
return void 0;
|
|
}
|
|
return Math.max(Math.floor(line / 1e3), 1);
|
|
}
|
|
function lineCount(editor) {
|
|
const line = editor?.cm?.state?.doc?.length;
|
|
return typeof line === "number" ? line : void 0;
|
|
}
|
|
async function retry(cb, interval, trials, check = (got) => got !== void 0) {
|
|
for (let i = 0; i < trials; i++) {
|
|
const got = cb();
|
|
if (check(got)) {
|
|
return got;
|
|
}
|
|
await delay(interval);
|
|
}
|
|
return void 0;
|
|
}
|
|
function shallowClone(obj) {
|
|
return Object.assign({}, obj);
|
|
}
|
|
function deepClone(obj) {
|
|
if (obj === null)
|
|
return obj;
|
|
if (typeof obj !== "object")
|
|
return obj;
|
|
if (Array.isArray(obj)) {
|
|
const clone2 = new Array(obj.length);
|
|
obj.forEach((value, id) => {
|
|
clone2[id] = deepClone(value);
|
|
});
|
|
return clone2;
|
|
}
|
|
const clone = shallowClone(obj);
|
|
for (const key in clone) {
|
|
const value = clone[key];
|
|
clone[key] = deepClone(value);
|
|
}
|
|
return clone;
|
|
}
|
|
function deepMerge(a, b) {
|
|
if (b === void 0) {
|
|
return deepClone(a);
|
|
}
|
|
if (a === void 0) {
|
|
return deepClone(b);
|
|
}
|
|
if (typeof a !== typeof b) {
|
|
throw new Error(`failed to deepMerge ${a} and ${b}`);
|
|
}
|
|
if (typeof b !== "object")
|
|
return deepClone(b);
|
|
if (b === null) {
|
|
return deepClone(a);
|
|
}
|
|
if (a === null) {
|
|
return deepClone(b);
|
|
}
|
|
if (Array.isArray(b)) {
|
|
if (Array.isArray(a)) {
|
|
return deepClone(b);
|
|
}
|
|
throw new Error(`failed to deepMerge ${a} and ${b}`);
|
|
}
|
|
if (Array.isArray(a)) {
|
|
throw new Error(`failed to deepMerge ${a} and ${b}`);
|
|
}
|
|
const clone = shallowClone(a);
|
|
for (const key in a) {
|
|
clone[key] = deepMerge(a[key], b[key]);
|
|
}
|
|
for (const key in b) {
|
|
clone[key] = deepMerge(a[key], b[key]);
|
|
}
|
|
return clone;
|
|
}
|
|
|
|
// src/interfaces/ViewGenerator.ts
|
|
var ViewGenerator = class {
|
|
constructor(app2, containerEl, file) {
|
|
this.extensions = [];
|
|
this.app = app2;
|
|
this.containerEl = containerEl;
|
|
this.leaf = new import_obsidian8.WorkspaceLeaf(this.app);
|
|
this.file = file;
|
|
}
|
|
async load(mode) {
|
|
await this.onload(mode);
|
|
return this;
|
|
}
|
|
async unload() {
|
|
this.onunload();
|
|
}
|
|
async toggleViewMode() {
|
|
for (const ext of this.extensions) {
|
|
if (!await ext.isMine(this.leaf))
|
|
continue;
|
|
await ext.toggleViewMode(this.leaf);
|
|
return;
|
|
}
|
|
}
|
|
async onload(mode) {
|
|
const fileType = fileTypeMap[this.file.extension];
|
|
if (!fileType)
|
|
return;
|
|
this.containerEl.appendChild(this.leaf.containerEl);
|
|
await this.openFile();
|
|
for (const ext of this.extensions) {
|
|
if (!await ext.isMine(this.leaf))
|
|
continue;
|
|
await ext.setViewMode(this.leaf, mode ?? "preview");
|
|
return;
|
|
}
|
|
}
|
|
onunload() {
|
|
this.leaf.detach();
|
|
}
|
|
async openFile() {
|
|
const { leaf, file } = this;
|
|
await leaf.openFile(file);
|
|
}
|
|
// it should be called once because is is not idempotent
|
|
// it can be called even when view mode = 'preview'
|
|
highlightMatches(matches, cls) {
|
|
const view = this.leaf.view;
|
|
if (!(view instanceof import_obsidian8.MarkdownView)) {
|
|
return;
|
|
}
|
|
const editor = view.editor;
|
|
const ranges = [];
|
|
matches.forEach((match) => {
|
|
const range = {
|
|
from: editor.offsetToPos(match[0]),
|
|
to: editor.offsetToPos(match[1])
|
|
};
|
|
ranges.push(range);
|
|
});
|
|
editor.addHighlights(ranges, cls);
|
|
}
|
|
async scrollIntoView(match, center) {
|
|
const view = this.leaf.view;
|
|
if (!(view instanceof import_obsidian8.MarkdownView)) {
|
|
return;
|
|
}
|
|
if (view.getMode() !== "source") {
|
|
return;
|
|
}
|
|
const editor = view.editor;
|
|
const range = {
|
|
from: editor.offsetToPos(match[0]),
|
|
to: editor.offsetToPos(match[1])
|
|
};
|
|
const iter = scrollIteration(editor);
|
|
if (iter === void 0) {
|
|
return;
|
|
}
|
|
for (let i = 0; i < iter; i++) {
|
|
editor.scrollIntoView(range, center);
|
|
await delay(1);
|
|
}
|
|
}
|
|
async focusOn(match, cls, center) {
|
|
const view = this.leaf.view;
|
|
if (!(view instanceof import_obsidian8.MarkdownView)) {
|
|
return;
|
|
}
|
|
if (view.getMode() !== "source") {
|
|
return;
|
|
}
|
|
await this.scrollIntoView(match, center);
|
|
const { editor } = view;
|
|
editor.removeHighlights(cls);
|
|
const range = {
|
|
from: editor.offsetToPos(match[0]),
|
|
to: editor.offsetToPos(match[1])
|
|
};
|
|
editor.addHighlights([range], cls);
|
|
}
|
|
registerExtension(ext) {
|
|
this.extensions.push(ext);
|
|
return this;
|
|
}
|
|
};
|
|
var fileTypeMap = {
|
|
md: "md",
|
|
png: "image",
|
|
jpg: "image",
|
|
jpeg: "image",
|
|
gif: "image",
|
|
bmp: "image",
|
|
svg: "image",
|
|
webp: "image",
|
|
mp3: "audio",
|
|
webm: "audio",
|
|
wav: "audio",
|
|
m4a: "audio",
|
|
ogg: "audio",
|
|
"3gp": "audio",
|
|
flac: "audio",
|
|
mp4: "movie",
|
|
ogv: "movie",
|
|
pdf: "pdf"
|
|
};
|
|
|
|
// src/interfaces/viewGeneratorExtensions/Excalidraw.ts
|
|
var import_obsidian9 = require("obsidian");
|
|
var excalidrawPluginId = "obsidian-excalidraw-plugin";
|
|
var excalidrawViewType = "excalidraw";
|
|
var ExcalidrawViewGeneratorExtension = class {
|
|
constructor(app2) {
|
|
this.app = app2;
|
|
const excalidraw = this.app.plugins.plugins[excalidrawPluginId];
|
|
if (!isExcalidrawPlugin(excalidraw)) {
|
|
this.excalidraw = void 0;
|
|
} else {
|
|
this.excalidraw = excalidraw;
|
|
}
|
|
}
|
|
isMine(leaf) {
|
|
return leaf.view.getViewType() === excalidrawViewType;
|
|
}
|
|
// https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/109fe05302bde0e8fe4e97c3bad6ca3f51f6b6b1/src/main.ts#L953-L986
|
|
async setViewMode(leaf, mode) {
|
|
const { excalidraw } = this;
|
|
if (!excalidraw)
|
|
return;
|
|
excalidraw.excalidrawFileModes[leaf.id] = "markdown";
|
|
await excalidraw.setMarkdownView(leaf);
|
|
if (!(leaf.view instanceof import_obsidian9.MarkdownView))
|
|
return;
|
|
await leaf.view.setState(
|
|
{
|
|
...leaf.view.getState(),
|
|
mode
|
|
},
|
|
{}
|
|
);
|
|
leaf.view.editor.blur();
|
|
}
|
|
async toggleViewMode(leaf) {
|
|
const { excalidraw } = this;
|
|
if (!excalidraw)
|
|
return;
|
|
excalidraw.excalidrawFileModes[leaf.id] = "markdown";
|
|
await excalidraw.setMarkdownView(leaf);
|
|
if (!(leaf.view instanceof import_obsidian9.MarkdownView))
|
|
return;
|
|
const mode = leaf.view.getMode();
|
|
await leaf.view.setState(
|
|
{
|
|
...leaf.view.getState(),
|
|
mode: mode === "preview" ? "source" : "preview"
|
|
},
|
|
{}
|
|
);
|
|
leaf.view.editor.blur();
|
|
}
|
|
};
|
|
function isExcalidrawPlugin(plugin2) {
|
|
if (!(plugin2 instanceof import_obsidian9.Plugin))
|
|
return false;
|
|
const { excalidrawFileModes, setMarkdownView } = plugin2;
|
|
if (typeof excalidrawFileModes !== "object")
|
|
return false;
|
|
if (typeof setMarkdownView !== "function")
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// src/interfaces/viewGeneratorExtensions/Kanban.ts
|
|
var import_obsidian10 = require("obsidian");
|
|
var kanbanPluginId = "obsidian-kanban";
|
|
var frontMatterKey = "kanban-plugin";
|
|
var kanbanViewType = "kanban";
|
|
var KanbanViewGeneratorExtension = class {
|
|
constructor(app2) {
|
|
this.app = app2;
|
|
const kanban = this.app.plugins.plugins[kanbanPluginId];
|
|
if (IsKanbanPlugin(kanban)) {
|
|
this.kanban = kanban;
|
|
}
|
|
if (kanban === void 0) {
|
|
this.kanban = void 0;
|
|
}
|
|
}
|
|
isMine(leaf) {
|
|
const { view } = leaf;
|
|
if (view.getViewType() === kanbanViewType)
|
|
return true;
|
|
if (!(view instanceof import_obsidian10.TextFileView))
|
|
return false;
|
|
const fileCache = this.app.metadataCache.getFileCache(view.file);
|
|
const fileIsKanban = !!fileCache?.frontmatter && !!fileCache.frontmatter[frontMatterKey];
|
|
return fileIsKanban;
|
|
}
|
|
// https://github.com/mgmeyers/obsidian-kanban/blob/350fc891a8489f70551d288ae914534424c8c095/src/main.ts#L317-L345
|
|
async setViewMode(leaf, mode) {
|
|
const { kanban } = this;
|
|
if (!kanban)
|
|
return;
|
|
if (mode === "source") {
|
|
kanban.kanbanFileModes[leaf.id] = "markdown";
|
|
await kanban.setMarkdownView(leaf);
|
|
await leaf.view.setState(
|
|
{
|
|
...leaf.view.getState(),
|
|
mode: "source"
|
|
},
|
|
{}
|
|
);
|
|
if (leaf.view instanceof import_obsidian10.MarkdownView) {
|
|
leaf.view.editor.blur();
|
|
}
|
|
} else {
|
|
kanban.kanbanFileModes[leaf.id] = kanbanViewType;
|
|
await kanban.setKanbanView(leaf);
|
|
}
|
|
}
|
|
async toggleViewMode(leaf) {
|
|
const { kanban } = this;
|
|
if (!kanban)
|
|
return;
|
|
const mode = kanban.kanbanFileModes[leaf.id];
|
|
await this.setViewMode(leaf, mode === "markdown" ? "preview" : "source");
|
|
}
|
|
};
|
|
function IsKanbanPlugin(plugin2) {
|
|
if (!(plugin2 instanceof import_obsidian10.Plugin))
|
|
return false;
|
|
const { kanbanFileModes, setKanbanView, setMarkdownView } = plugin2;
|
|
if (typeof kanbanFileModes !== "object")
|
|
return false;
|
|
if (typeof setMarkdownView !== "function")
|
|
return false;
|
|
if (typeof setKanbanView !== "function")
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// src/interfaces/viewGeneratorExtensions/Markdown.ts
|
|
var import_obsidian11 = require("obsidian");
|
|
var MarkdownViewGeneratorExtension = class {
|
|
isMine(leaf) {
|
|
return leaf.view instanceof import_obsidian11.MarkdownView;
|
|
}
|
|
async setViewMode(leaf, mode) {
|
|
await leaf.view.setState(
|
|
{
|
|
...leaf.view.getState(),
|
|
mode
|
|
},
|
|
{}
|
|
);
|
|
}
|
|
async toggleViewMode(leaf) {
|
|
if (!(leaf.view instanceof import_obsidian11.MarkdownView))
|
|
return;
|
|
await this.setViewMode(
|
|
leaf,
|
|
leaf.view.getMode() === "preview" ? "source" : "preview"
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/interfaces/viewGeneratorExtensions/NonMarkdown.ts
|
|
var import_obsidian12 = require("obsidian");
|
|
var NON_MARKDOWN_FILE_TYPES = ["image", "audio", "pdf", "video"];
|
|
var NonMarkdownViewGeneratorExtension = class {
|
|
isMine(leaf) {
|
|
if (!(leaf.view instanceof import_obsidian12.FileView))
|
|
return false;
|
|
return NON_MARKDOWN_FILE_TYPES.includes(
|
|
leaf.view.getViewType()
|
|
);
|
|
}
|
|
setViewMode(_leaf, _mode) {
|
|
return;
|
|
}
|
|
toggleViewMode(_) {
|
|
return;
|
|
}
|
|
};
|
|
|
|
// node_modules/svelte/src/runtime/store/index.js
|
|
var subscriber_queue = [];
|
|
function writable(value, start = noop) {
|
|
let stop;
|
|
const subscribers = /* @__PURE__ */ new Set();
|
|
function set(new_value) {
|
|
if (safe_not_equal(value, new_value)) {
|
|
value = new_value;
|
|
if (stop) {
|
|
const run_queue = !subscriber_queue.length;
|
|
for (const subscriber of subscribers) {
|
|
subscriber[1]();
|
|
subscriber_queue.push(subscriber, value);
|
|
}
|
|
if (run_queue) {
|
|
for (let i = 0; i < subscriber_queue.length; i += 2) {
|
|
subscriber_queue[i][0](subscriber_queue[i + 1]);
|
|
}
|
|
subscriber_queue.length = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function update2(fn) {
|
|
set(fn(value));
|
|
}
|
|
function subscribe2(run2, invalidate = noop) {
|
|
const subscriber = [run2, invalidate];
|
|
subscribers.add(subscriber);
|
|
if (subscribers.size === 1) {
|
|
stop = start(set, update2) || noop;
|
|
}
|
|
run2(value);
|
|
return () => {
|
|
subscribers.delete(subscriber);
|
|
if (subscribers.size === 0 && stop) {
|
|
stop();
|
|
stop = null;
|
|
}
|
|
};
|
|
}
|
|
return { set, update: update2, subscribe: subscribe2 };
|
|
}
|
|
|
|
// src/ui/store.ts
|
|
var app = writable();
|
|
var plugin = writable();
|
|
|
|
// src/ui/PreviewModalContent.svelte
|
|
function add_css3(target) {
|
|
append_styles(target, "svelte-6cqu2r", ".core-search-assistant_preview-modal_view-container.svelte-6cqu2r{min-width:700px}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .highlight-search-match{color:var(--highlight-search-match);background-color:var(--highlight-search-match-bg)}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .focus-search-match{background-color:var(--focus-search-match-bg)}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .workspace-leaf{contain:initial !important}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .view-content{overflow:unset}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .markdown-preview-view{overflow:unset}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .workspace-leaf-content{overflow:unset}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .workspace-leaf-resize-handle{display:none}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .view-header{display:none}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .markdown-preview-view{padding:0}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .markdown-source-view{pointer-events:none}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .workspace-leaf-content[data-type='pdf']{height:990px}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .markdown-source-view.mod-cm6 .cm-editor{flex:initial;display:initial}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .markdown-source-view.mod-cm6{display:initial}.core-search-assistant_preview-modal_view-container.svelte-6cqu2r .markdown-source-view.mod-cm6 .cm-scroller{padding:0}");
|
|
}
|
|
function create_fragment3(ctx) {
|
|
let div;
|
|
return {
|
|
c() {
|
|
div = element("div");
|
|
attr(div, "class", "core-search-assistant_preview-modal_view-container svelte-6cqu2r");
|
|
},
|
|
m(target, anchor) {
|
|
insert(target, div, anchor);
|
|
ctx[5](div);
|
|
},
|
|
p: noop,
|
|
i: noop,
|
|
o: noop,
|
|
d(detaching) {
|
|
if (detaching) {
|
|
detach(div);
|
|
}
|
|
ctx[5](null);
|
|
}
|
|
};
|
|
}
|
|
function instance3($$self, $$props, $$invalidate) {
|
|
let $app;
|
|
component_subscribe($$self, app, ($$value) => $$invalidate(7, $app = $$value));
|
|
let { file } = $$props;
|
|
let { matches } = $$props;
|
|
let contentContainerEl;
|
|
let renderer;
|
|
onMount(async () => {
|
|
if (!file) {
|
|
return;
|
|
}
|
|
if (!contentContainerEl) {
|
|
return;
|
|
}
|
|
const fileType = fileTypeMap[file.extension];
|
|
if (fileType !== void 0) {
|
|
contentContainerEl.empty();
|
|
renderer = await new ViewGenerator($app, contentContainerEl, file).registerExtension(new ExcalidrawViewGeneratorExtension($app)).registerExtension(new KanbanViewGeneratorExtension($app)).registerExtension(new MarkdownViewGeneratorExtension()).registerExtension(new NonMarkdownViewGeneratorExtension()).load("source");
|
|
highlightMatches();
|
|
}
|
|
});
|
|
onDestroy(() => {
|
|
setTimeout(() => renderer?.unload(), 1e3);
|
|
});
|
|
async function toggleViewMode() {
|
|
await renderer?.toggleViewMode();
|
|
}
|
|
function focusOn(matchId, center) {
|
|
if (!matches)
|
|
return;
|
|
const match = matches[matchId];
|
|
if (match === void 0) {
|
|
return;
|
|
}
|
|
renderer?.focusOn(match, "focus-search-match", center);
|
|
}
|
|
function highlightMatches() {
|
|
renderer?.highlightMatches(matches ?? [], "highlight-search-match");
|
|
}
|
|
function div_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
contentContainerEl = $$value;
|
|
$$invalidate(0, contentContainerEl);
|
|
});
|
|
}
|
|
$$self.$$set = ($$props2) => {
|
|
if ("file" in $$props2)
|
|
$$invalidate(1, file = $$props2.file);
|
|
if ("matches" in $$props2)
|
|
$$invalidate(2, matches = $$props2.matches);
|
|
};
|
|
return [contentContainerEl, file, matches, toggleViewMode, focusOn, div_binding];
|
|
}
|
|
var PreviewModalContent = class extends SvelteComponent {
|
|
constructor(options) {
|
|
super();
|
|
init(
|
|
this,
|
|
options,
|
|
instance3,
|
|
create_fragment3,
|
|
safe_not_equal,
|
|
{
|
|
file: 1,
|
|
matches: 2,
|
|
toggleViewMode: 3,
|
|
focusOn: 4
|
|
},
|
|
add_css3
|
|
);
|
|
}
|
|
get toggleViewMode() {
|
|
return this.$$.ctx[3];
|
|
}
|
|
get focusOn() {
|
|
return this.$$.ctx[4];
|
|
}
|
|
};
|
|
var PreviewModalContent_default = PreviewModalContent;
|
|
|
|
// src/utils/Link.ts
|
|
function generateInternalLinkFrom(app2, file) {
|
|
const text2 = getDisplayText(app2.metadataCache, file);
|
|
return app2.fileManager.generateMarkdownLink(file, "", void 0, text2);
|
|
}
|
|
function getDisplayText(metadataCache, file) {
|
|
const cache = metadataCache.getFileCache(file);
|
|
if (!cache)
|
|
return void 0;
|
|
const title = getTitle(cache.frontmatter);
|
|
if (title !== void 0) {
|
|
return title;
|
|
}
|
|
const h1 = getFirstH1(cache.headings);
|
|
if (h1 !== void 0) {
|
|
return h1;
|
|
}
|
|
return void 0;
|
|
}
|
|
function getTitle(frontmatter) {
|
|
return frontmatter?.title;
|
|
}
|
|
function getFirstH1(headings) {
|
|
if (!headings)
|
|
return void 0;
|
|
for (const heading of headings) {
|
|
if (heading.level !== 1)
|
|
continue;
|
|
return heading.heading;
|
|
}
|
|
return void 0;
|
|
}
|
|
|
|
// src/components/PreviewModal.ts
|
|
var SCROLL_AMOUNT = 70;
|
|
var PreviewModal = class extends import_obsidian13.Modal {
|
|
constructor(app2, plugin2, modeScope, item) {
|
|
super(app2);
|
|
this.plugin = plugin2;
|
|
this.modeScope = modeScope;
|
|
this.item = item;
|
|
this.currentFocus = -1;
|
|
}
|
|
async onOpen() {
|
|
await this.renderView();
|
|
this.modeScope.push();
|
|
const hotkeyMap = this.plugin.settings?.previewModalHotkeys;
|
|
if (!hotkeyMap)
|
|
return;
|
|
hotkeyMap.closeModal.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
this.shouldRestoreSelection = true;
|
|
this.close();
|
|
});
|
|
});
|
|
hotkeyMap.open.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
this.openAndFocus(this.currentFocus);
|
|
this.plugin.controller?.exit();
|
|
this.shouldRestoreSelection = false;
|
|
this.close();
|
|
});
|
|
});
|
|
hotkeyMap.openInNewPage.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
this.openAndFocus(
|
|
this.currentFocus,
|
|
this.plugin.settings?.splitDirection
|
|
);
|
|
this.plugin.controller?.exit();
|
|
this.shouldRestoreSelection = false;
|
|
this.close();
|
|
});
|
|
});
|
|
hotkeyMap.bigScrollDown.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
this.scroll("down");
|
|
});
|
|
});
|
|
hotkeyMap.bigScrollUp.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
this.scroll("up");
|
|
});
|
|
});
|
|
hotkeyMap.scrollDown.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
this.scroll("down", SCROLL_AMOUNT);
|
|
});
|
|
});
|
|
hotkeyMap.scrollUp.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
this.scroll("up", SCROLL_AMOUNT);
|
|
});
|
|
});
|
|
hotkeyMap.focusNext.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, (evt) => {
|
|
evt.preventDefault();
|
|
const numMatches = this.countMatches();
|
|
if (numMatches === void 0 || numMatches === 0) {
|
|
return;
|
|
}
|
|
this.currentFocus = cyclicId(++this.currentFocus, numMatches);
|
|
this.previewContent?.focusOn(this.currentFocus, true);
|
|
});
|
|
});
|
|
hotkeyMap.focusPrevious.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, (evt) => {
|
|
evt.preventDefault();
|
|
const numMatches = this.countMatches();
|
|
if (numMatches === void 0 || numMatches === 0) {
|
|
return;
|
|
}
|
|
this.currentFocus = cyclicId(--this.currentFocus, numMatches);
|
|
this.previewContent?.focusOn(this.currentFocus, true);
|
|
});
|
|
});
|
|
hotkeyMap.togglePreviewMode.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, (evt) => {
|
|
(async () => {
|
|
evt.preventDefault();
|
|
await this.previewContent?.toggleViewMode();
|
|
})();
|
|
});
|
|
});
|
|
hotkeyMap.copyLink.forEach((hotkey) => {
|
|
this.scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
const { file } = this.item;
|
|
const internalLink = generateInternalLinkFrom(this.app, file);
|
|
navigator.clipboard.writeText(internalLink);
|
|
new import_obsidian13.Notice("Copy wiki link!");
|
|
});
|
|
});
|
|
}
|
|
onClose() {
|
|
this.previewContent?.$destroy();
|
|
setTimeout(() => {
|
|
if (this.modeScope.depth > 1) {
|
|
this.modeScope.pop();
|
|
}
|
|
}, 100);
|
|
}
|
|
async renderView() {
|
|
const { contentEl } = this;
|
|
contentEl.empty();
|
|
contentEl.hide();
|
|
this.previewContent = new PreviewModalContent_default({
|
|
target: contentEl,
|
|
props: {
|
|
file: this.item.file,
|
|
matches: this.item.result.content
|
|
}
|
|
});
|
|
contentEl.show();
|
|
}
|
|
countMatches() {
|
|
return this.item.result.content?.length;
|
|
}
|
|
scroll(direction, px) {
|
|
const { containerEl, contentEl } = this;
|
|
const move = (px ?? containerEl.clientHeight / 2) * (direction === "up" ? -1 : 1);
|
|
contentEl.scrollBy({
|
|
top: move,
|
|
behavior: "smooth"
|
|
});
|
|
}
|
|
async openAndFocus(matchId, direction) {
|
|
const { item } = this;
|
|
const leaf = direction === void 0 ? this.app.workspace.getMostRecentLeaf() : this.app.workspace.splitActiveLeaf(direction);
|
|
await leaf.openFile(item.file);
|
|
this.app.workspace.setActiveLeaf(leaf, true, true);
|
|
const match = item?.result?.content?.[matchId];
|
|
if (!match) {
|
|
return;
|
|
}
|
|
const { view } = leaf;
|
|
if (!(view instanceof import_obsidian13.MarkdownView)) {
|
|
return;
|
|
}
|
|
const editor = view.editor;
|
|
const range = {
|
|
from: editor.offsetToPos(match[0]),
|
|
to: editor.offsetToPos(match[1])
|
|
};
|
|
editor.addHighlights([range], "obsidian-search-match-highlight");
|
|
const iter = scrollIteration(editor);
|
|
if (iter === void 0) {
|
|
return;
|
|
}
|
|
for (let i = 0; i < iter; i++) {
|
|
editor.scrollIntoView(range, true);
|
|
}
|
|
editor.setCursor(range.from);
|
|
}
|
|
};
|
|
function cyclicId(id, total) {
|
|
return (id % total + total) % total;
|
|
}
|
|
|
|
// src/Controller.ts
|
|
var obsidian = __toESM(require("obsidian"), 1);
|
|
var import_obsidian14 = require("obsidian");
|
|
|
|
// src/ui/CardContainer.svelte
|
|
function add_css4(target) {
|
|
append_styles(target, "svelte-1g7kfgn", ".core-search-assistant_card-container.svelte-1g7kfgn.svelte-1g7kfgn{overflow:hidden;display:flex;flex-direction:column;height:100%;position:relative;box-shadow:0 2px 5px rgba(0, 0, 0, 0.2);border-radius:10px;cursor:pointer;background-color:var(--background-primary);box-sizing:content-box}.core-search-assistant_card-container.svelte-1g7kfgn.svelte-1g7kfgn:hover{border:5px solid var(--interactive-accent);margin:-5px}.core-search-assistant_card-container.is-selected.svelte-1g7kfgn.svelte-1g7kfgn{border:5px solid var(--interactive-accent);margin:-5px}.card-container-header.svelte-1g7kfgn.svelte-1g7kfgn{padding:5px 10px;background-color:var(--background-secondary);display:flex;color:var(--text-muted)}.file-name-container.svelte-1g7kfgn.svelte-1g7kfgn{font-size:1rem;line-height:1.2rem;overflow-wrap:break-word;min-width:0;flex:1}.file-name-container.svelte-1g7kfgn span.matched-in-path{color:var(--text-normal);font-weight:bold}.content-container-wrapper.svelte-1g7kfgn.svelte-1g7kfgn{padding:5px;flex:1;height:100%;min-height:0}.content-container.svelte-1g7kfgn.svelte-1g7kfgn{overflow:hidden;height:100%;font-size:0.8rem;line-height:1.2}.content-container.svelte-1g7kfgn div.content-not-supported-file-format.svelte-1g7kfgn{font-size:1rem;color:var(--text-muted)}.content-container.svelte-1g7kfgn p{font-size:0.8rem;line-height:1.2}.content-container.svelte-1g7kfgn code{font-size:0.8rem;line-height:1.2}.content-container.svelte-1g7kfgn div{font-size:0.8rem}.content-container.svelte-1g7kfgn li{font-size:0.8rem;line-height:1.2}.content-container.svelte-1g7kfgn h1{font-size:1rem;line-height:1.2;margin:5px}.content-container.svelte-1g7kfgn h2{font-size:1rem;line-height:1.2;margin:5px}.content-container.svelte-1g7kfgn h3{font-size:1rem;line-height:1.2;margin:5px}.content-container.svelte-1g7kfgn h4{font-size:1rem;line-height:1.2;margin:5px}.content-container.svelte-1g7kfgn h5{font-size:1rem;line-height:1.2;margin:5px}.content-container.svelte-1g7kfgn h6{font-size:1rem;line-height:1.2;margin:5px}.content-container.svelte-1g7kfgn a{pointer-events:none}.content-container.svelte-1g7kfgn .workspace-leaf{contain:initial !important;height:100%}.content-container.svelte-1g7kfgn .workspace-leaf-resize-handle{display:none}.content-container.svelte-1g7kfgn .view-header{display:none}.content-container.svelte-1g7kfgn .view-content{flex:1;overflow:hidden}.content-container.svelte-1g7kfgn .markdown-preview-view{padding:0;overflow:hidden}.content-container.svelte-1g7kfgn .modal-content{margin:0}");
|
|
}
|
|
function create_fragment4(ctx) {
|
|
let div5;
|
|
let div1;
|
|
let div0;
|
|
let t0;
|
|
let div4;
|
|
let div3;
|
|
let div2;
|
|
let t1_value = `${/*file*/
|
|
ctx[1].extension.toUpperCase()} file`;
|
|
let t1;
|
|
let div5_data_path_value;
|
|
let mounted;
|
|
let dispose;
|
|
return {
|
|
c() {
|
|
div5 = element("div");
|
|
div1 = element("div");
|
|
div0 = element("div");
|
|
t0 = space();
|
|
div4 = element("div");
|
|
div3 = element("div");
|
|
div2 = element("div");
|
|
t1 = text(t1_value);
|
|
attr(div0, "class", "file-name-container svelte-1g7kfgn");
|
|
attr(div1, "class", "card-container-header svelte-1g7kfgn");
|
|
attr(div2, "class", "content-not-supported-file-format svelte-1g7kfgn");
|
|
attr(div3, "class", "content-container svelte-1g7kfgn");
|
|
attr(div4, "class", "content-container-wrapper svelte-1g7kfgn");
|
|
attr(div5, "class", "core-search-assistant_card-container svelte-1g7kfgn");
|
|
attr(
|
|
div5,
|
|
"data-id",
|
|
/*id*/
|
|
ctx[0]
|
|
);
|
|
attr(div5, "data-path", div5_data_path_value = /*file*/
|
|
ctx[1].path);
|
|
attr(div5, "role", "button");
|
|
toggle_class(
|
|
div5,
|
|
"is-selected",
|
|
/*selected*/
|
|
ctx[2]
|
|
);
|
|
},
|
|
m(target, anchor) {
|
|
insert(target, div5, anchor);
|
|
append(div5, div1);
|
|
append(div1, div0);
|
|
ctx[8](div0);
|
|
append(div5, t0);
|
|
append(div5, div4);
|
|
append(div4, div3);
|
|
append(div3, div2);
|
|
append(div2, t1);
|
|
ctx[9](div3);
|
|
if (!mounted) {
|
|
dispose = listen(
|
|
div5,
|
|
"click",
|
|
/*onClicked*/
|
|
ctx[5]
|
|
);
|
|
mounted = true;
|
|
}
|
|
},
|
|
p(ctx2, [dirty]) {
|
|
if (dirty & /*file*/
|
|
2 && t1_value !== (t1_value = `${/*file*/
|
|
ctx2[1].extension.toUpperCase()} file`))
|
|
set_data(t1, t1_value);
|
|
if (dirty & /*id*/
|
|
1) {
|
|
attr(
|
|
div5,
|
|
"data-id",
|
|
/*id*/
|
|
ctx2[0]
|
|
);
|
|
}
|
|
if (dirty & /*file*/
|
|
2 && div5_data_path_value !== (div5_data_path_value = /*file*/
|
|
ctx2[1].path)) {
|
|
attr(div5, "data-path", div5_data_path_value);
|
|
}
|
|
if (dirty & /*selected*/
|
|
4) {
|
|
toggle_class(
|
|
div5,
|
|
"is-selected",
|
|
/*selected*/
|
|
ctx2[2]
|
|
);
|
|
}
|
|
},
|
|
i: noop,
|
|
o: noop,
|
|
d(detaching) {
|
|
if (detaching) {
|
|
detach(div5);
|
|
}
|
|
ctx[8](null);
|
|
ctx[9](null);
|
|
mounted = false;
|
|
dispose();
|
|
}
|
|
};
|
|
}
|
|
function renderFileName(fileName, containerEl) {
|
|
containerEl.appendText(fileName);
|
|
}
|
|
function instance4($$self, $$props, $$invalidate) {
|
|
let $app;
|
|
component_subscribe($$self, app, ($$value) => $$invalidate(11, $app = $$value));
|
|
let { id } = $$props;
|
|
let { file } = $$props;
|
|
let { selected } = $$props;
|
|
let { focusEl } = $$props;
|
|
let contentContainerEl;
|
|
let fileNameContainerEl;
|
|
let renderer;
|
|
const dispatch = createEventDispatcher();
|
|
function path() {
|
|
return file.path;
|
|
}
|
|
onMount(async () => {
|
|
if (!fileNameContainerEl) {
|
|
return;
|
|
}
|
|
renderFileName(file.name, fileNameContainerEl);
|
|
if (!contentContainerEl) {
|
|
return;
|
|
}
|
|
const fileType = fileTypeMap[file.extension];
|
|
if (fileType !== void 0) {
|
|
contentContainerEl.empty();
|
|
renderer = await new ViewGenerator($app, contentContainerEl, file).registerExtension(new ExcalidrawViewGeneratorExtension($app)).registerExtension(new KanbanViewGeneratorExtension($app)).registerExtension(new MarkdownViewGeneratorExtension()).registerExtension(new NonMarkdownViewGeneratorExtension()).load("preview");
|
|
}
|
|
focusEl?.focus();
|
|
});
|
|
onDestroy(() => {
|
|
setTimeout(() => renderer?.unload(), 1e3);
|
|
});
|
|
async function onClicked() {
|
|
await openFile();
|
|
dispatch("click");
|
|
}
|
|
async function openFile() {
|
|
const leaf = $app.workspace.getMostRecentLeaf();
|
|
await leaf.openFile(file);
|
|
$app.workspace.setActiveLeaf(leaf, true, true);
|
|
}
|
|
function div0_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
fileNameContainerEl = $$value;
|
|
$$invalidate(4, fileNameContainerEl);
|
|
});
|
|
}
|
|
function div3_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
contentContainerEl = $$value;
|
|
$$invalidate(3, contentContainerEl);
|
|
});
|
|
}
|
|
$$self.$$set = ($$props2) => {
|
|
if ("id" in $$props2)
|
|
$$invalidate(0, id = $$props2.id);
|
|
if ("file" in $$props2)
|
|
$$invalidate(1, file = $$props2.file);
|
|
if ("selected" in $$props2)
|
|
$$invalidate(2, selected = $$props2.selected);
|
|
if ("focusEl" in $$props2)
|
|
$$invalidate(6, focusEl = $$props2.focusEl);
|
|
};
|
|
return [
|
|
id,
|
|
file,
|
|
selected,
|
|
contentContainerEl,
|
|
fileNameContainerEl,
|
|
onClicked,
|
|
focusEl,
|
|
path,
|
|
div0_binding,
|
|
div3_binding
|
|
];
|
|
}
|
|
var CardContainer = class extends SvelteComponent {
|
|
constructor(options) {
|
|
super();
|
|
init(
|
|
this,
|
|
options,
|
|
instance4,
|
|
create_fragment4,
|
|
safe_not_equal,
|
|
{
|
|
id: 0,
|
|
file: 1,
|
|
selected: 2,
|
|
focusEl: 6,
|
|
path: 7
|
|
},
|
|
add_css4
|
|
);
|
|
}
|
|
get path() {
|
|
return this.$$.ctx[7];
|
|
}
|
|
};
|
|
var CardContainer_default = CardContainer;
|
|
|
|
// src/ui/CardViewComponent.svelte
|
|
function add_css5(target) {
|
|
append_styles(target, "svelte-pwex1j", ".card-view-container.svelte-pwex1j{position:absolute;top:0;left:0;width:100%;height:100%;z-index:var(--layer-modal);padding:20px 30px;display:flex;justify-content:center}.card-view-background.svelte-pwex1j{position:absolute;top:0;left:0;width:100%;height:100%;background-color:var(--background-modifier-cover)}.cards-container.svelte-pwex1j{display:grid;grid-gap:20px;height:100%;width:100%;min-height:0}");
|
|
}
|
|
function create_fragment5(ctx) {
|
|
let div2;
|
|
let div0;
|
|
let t;
|
|
let div1;
|
|
let mounted;
|
|
let dispose;
|
|
return {
|
|
c() {
|
|
div2 = element("div");
|
|
div0 = element("div");
|
|
t = space();
|
|
div1 = element("div");
|
|
attr(div0, "class", "card-view-background svelte-pwex1j");
|
|
attr(div1, "class", "cards-container svelte-pwex1j");
|
|
attr(div2, "class", "card-view-container svelte-pwex1j");
|
|
},
|
|
m(target, anchor) {
|
|
insert(target, div2, anchor);
|
|
append(div2, div0);
|
|
append(div2, t);
|
|
append(div2, div1);
|
|
ctx[10](div1);
|
|
if (!mounted) {
|
|
dispose = listen(
|
|
div0,
|
|
"click",
|
|
/*click_handler*/
|
|
ctx[9]
|
|
);
|
|
mounted = true;
|
|
}
|
|
},
|
|
p: noop,
|
|
i: noop,
|
|
o: noop,
|
|
d(detaching) {
|
|
if (detaching) {
|
|
detach(div2);
|
|
}
|
|
ctx[10](null);
|
|
mounted = false;
|
|
dispose();
|
|
}
|
|
};
|
|
}
|
|
function cardsPerPage(layout) {
|
|
if (!checkLayout(layout))
|
|
return 0;
|
|
return layout[0] * layout[1];
|
|
}
|
|
function setLayout(contentEl, layout) {
|
|
if (!contentEl)
|
|
return;
|
|
if (!checkLayout(layout))
|
|
return;
|
|
contentEl.style.gridTemplateColumns = `repeat(${layout[1]}, minmax(0, 1fr))`;
|
|
contentEl.style.gridTemplateRows = `repeat(${layout[0]}, 1fr)`;
|
|
}
|
|
function checkLayout(layout) {
|
|
const check = (x) => Number.isInteger(x) && x > 0;
|
|
return check(layout[0]) && check(layout[1]);
|
|
}
|
|
function instance5($$self, $$props, $$invalidate) {
|
|
let { layout } = $$props;
|
|
let { focusEl } = $$props;
|
|
let contentEl;
|
|
let cards = [];
|
|
const dispatcher = createEventDispatcher();
|
|
function addCard(file) {
|
|
if (!contentEl)
|
|
return;
|
|
if (!focusEl)
|
|
return;
|
|
if (cards.length >= cardsPerPage(layout))
|
|
return;
|
|
const card = new CardContainer_default({
|
|
target: contentEl,
|
|
props: {
|
|
file,
|
|
id: cards.length,
|
|
selected: false,
|
|
focusEl
|
|
}
|
|
});
|
|
cards.push(card);
|
|
}
|
|
function renderPage(files) {
|
|
files.forEach((file) => {
|
|
addCard(file);
|
|
});
|
|
}
|
|
function focusOn(id) {
|
|
const pos = id % cardsPerPage(layout);
|
|
[-1, 0, 1].forEach((i) => {
|
|
const card = cards[pos + i];
|
|
if (!card)
|
|
return;
|
|
if (i === 0) {
|
|
card.$set({ selected: true });
|
|
} else {
|
|
card.$set({ selected: false });
|
|
}
|
|
});
|
|
}
|
|
function detachCards() {
|
|
cards.forEach((card) => {
|
|
card.$destroy();
|
|
});
|
|
cards = [];
|
|
}
|
|
function checkCardsRenderedCorrectly(files) {
|
|
if (!checkLayout(layout))
|
|
return false;
|
|
for (let i = 0; i < cardsPerPage(layout); i++) {
|
|
const file = files[i];
|
|
const card = cards[i];
|
|
if (file?.path !== card?.path()) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
onMount(() => {
|
|
setLayout(contentEl, layout);
|
|
});
|
|
onDestroy(() => {
|
|
detachCards();
|
|
});
|
|
const click_handler = () => {
|
|
dispatcher("should-destroy");
|
|
};
|
|
function div1_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
contentEl = $$value;
|
|
$$invalidate(0, contentEl);
|
|
});
|
|
}
|
|
$$self.$$set = ($$props2) => {
|
|
if ("layout" in $$props2)
|
|
$$invalidate(2, layout = $$props2.layout);
|
|
if ("focusEl" in $$props2)
|
|
$$invalidate(3, focusEl = $$props2.focusEl);
|
|
};
|
|
return [
|
|
contentEl,
|
|
dispatcher,
|
|
layout,
|
|
focusEl,
|
|
addCard,
|
|
renderPage,
|
|
focusOn,
|
|
detachCards,
|
|
checkCardsRenderedCorrectly,
|
|
click_handler,
|
|
div1_binding
|
|
];
|
|
}
|
|
var CardViewComponent = class extends SvelteComponent {
|
|
constructor(options) {
|
|
super();
|
|
init(
|
|
this,
|
|
options,
|
|
instance5,
|
|
create_fragment5,
|
|
safe_not_equal,
|
|
{
|
|
layout: 2,
|
|
focusEl: 3,
|
|
addCard: 4,
|
|
renderPage: 5,
|
|
focusOn: 6,
|
|
detachCards: 7,
|
|
checkCardsRenderedCorrectly: 8
|
|
},
|
|
add_css5
|
|
);
|
|
}
|
|
get addCard() {
|
|
return this.$$.ctx[4];
|
|
}
|
|
get renderPage() {
|
|
return this.$$.ctx[5];
|
|
}
|
|
get focusOn() {
|
|
return this.$$.ctx[6];
|
|
}
|
|
get detachCards() {
|
|
return this.$$.ctx[7];
|
|
}
|
|
get checkCardsRenderedCorrectly() {
|
|
return this.$$.ctx[8];
|
|
}
|
|
};
|
|
var CardViewComponent_default = CardViewComponent;
|
|
|
|
// src/ui/Outline.svelte
|
|
function add_css6(target) {
|
|
append_styles(target, "svelte-f5i2qg", ".outline-container.svelte-f5i2qg{position:absolute;top:0;left:0;width:100%;height:100%;z-index:var(--layer-modal);pointer-events:none}");
|
|
}
|
|
function create_fragment6(ctx) {
|
|
let div;
|
|
return {
|
|
c() {
|
|
div = element("div");
|
|
attr(div, "class", "outline-container svelte-f5i2qg");
|
|
},
|
|
m(target, anchor) {
|
|
insert(target, div, anchor);
|
|
ctx[2](div);
|
|
},
|
|
p: noop,
|
|
i: noop,
|
|
o: noop,
|
|
d(detaching) {
|
|
if (detaching) {
|
|
detach(div);
|
|
}
|
|
ctx[2](null);
|
|
}
|
|
};
|
|
}
|
|
var STYLE_VAR_COLOR_SEARCH_MODE_OUTLINE = "--search-mode-outline";
|
|
function instance6($$self, $$props, $$invalidate) {
|
|
let { lineWidth } = $$props;
|
|
let el;
|
|
onMount(() => {
|
|
if (!el)
|
|
return;
|
|
$$invalidate(0, el.style.outline = `${lineWidth}px solid var(${STYLE_VAR_COLOR_SEARCH_MODE_OUTLINE})`, el);
|
|
$$invalidate(0, el.style.outlineOffset = `-${lineWidth}px`, el);
|
|
});
|
|
function div_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
el = $$value;
|
|
$$invalidate(0, el);
|
|
});
|
|
}
|
|
$$self.$$set = ($$props2) => {
|
|
if ("lineWidth" in $$props2)
|
|
$$invalidate(1, lineWidth = $$props2.lineWidth);
|
|
};
|
|
return [el, lineWidth, div_binding];
|
|
}
|
|
var Outline = class extends SvelteComponent {
|
|
constructor(options) {
|
|
super();
|
|
init(this, options, instance6, create_fragment6, safe_not_equal, { lineWidth: 1 }, add_css6);
|
|
}
|
|
};
|
|
var Outline_default = Outline;
|
|
|
|
// src/ui/WorkspacePreview.svelte
|
|
function add_css7(target) {
|
|
append_styles(target, "svelte-1fata0e", ".core-search-assistant_workspace-preview_container.svelte-1fata0e{position:absolute;top:0;left:0;width:100%;height:100%;z-index:var(--layer-modal);background-color:var(--background-primary);padding:20px 30px;overflow:auto}.core-search-assistant_workspace-preview_container.svelte-1fata0e .highlight-search-match{color:var(--highlight-search-match);background-color:var(--highlight-search-match-bg)}.core-search-assistant_workspace-preview_container.svelte-1fata0e .focus-search-match{background-color:var(--focus-search-match-bg)}.core-search-assistant_workspace-preview_container.svelte-1fata0e .workspace-leaf{contain:initial !important;height:100%}.core-search-assistant_workspace-preview_container.svelte-1fata0e .workspace-leaf-resize-handle{display:none}.core-search-assistant_workspace-preview_container.svelte-1fata0e .view-header{display:none}.core-search-assistant_workspace-preview_container.svelte-1fata0e .view-content{overflow:hidden}.core-search-assistant_workspace-preview_container.svelte-1fata0e .markdown-preview-view{padding:0}.core-search-assistant_workspace-preview_container.svelte-1fata0e .modal-content{margin:0}.core-search-assistant_workspace-preview_container.svelte-1fata0e .markdown-source-view.mod-cm6 .cm-editor{flex:initial;display:initial}.core-search-assistant_workspace-preview_container.svelte-1fata0e .markdown-source-view.mod-cm6{display:initial}.core-search-assistant_workspace-preview_container.svelte-1fata0e .markdown-source-view{pointer-events:none}.core-search-assistant_workspace-preview_container.svelte-1fata0e .markdown-source-view.mod-cm6 .cm-scroller{padding:0}");
|
|
}
|
|
function create_fragment7(ctx) {
|
|
let div1;
|
|
let div0;
|
|
let t_value = `${/*file*/
|
|
ctx[0].extension.toUpperCase()} file`;
|
|
let t;
|
|
return {
|
|
c() {
|
|
div1 = element("div");
|
|
div0 = element("div");
|
|
t = text(t_value);
|
|
attr(div0, "class", "content-not-supported-file-format");
|
|
attr(div1, "class", "core-search-assistant_workspace-preview_container svelte-1fata0e");
|
|
},
|
|
m(target, anchor) {
|
|
insert(target, div1, anchor);
|
|
append(div1, div0);
|
|
append(div0, t);
|
|
ctx[4](div1);
|
|
},
|
|
p(ctx2, [dirty]) {
|
|
if (dirty & /*file*/
|
|
1 && t_value !== (t_value = `${/*file*/
|
|
ctx2[0].extension.toUpperCase()} file`))
|
|
set_data(t, t_value);
|
|
},
|
|
i: noop,
|
|
o: noop,
|
|
d(detaching) {
|
|
if (detaching) {
|
|
detach(div1);
|
|
}
|
|
ctx[4](null);
|
|
}
|
|
};
|
|
}
|
|
function instance7($$self, $$props, $$invalidate) {
|
|
let $app;
|
|
component_subscribe($$self, app, ($$value) => $$invalidate(6, $app = $$value));
|
|
let { file } = $$props;
|
|
let { matches } = $$props;
|
|
let { focusEl } = $$props;
|
|
let containerEl;
|
|
let renderer;
|
|
onMount(async () => {
|
|
if (!containerEl)
|
|
return;
|
|
const fileType = fileTypeMap[file.extension];
|
|
if (fileType !== void 0) {
|
|
containerEl.empty();
|
|
renderer = await new ViewGenerator($app, containerEl, file).registerExtension(new ExcalidrawViewGeneratorExtension($app)).registerExtension(new KanbanViewGeneratorExtension($app)).registerExtension(new MarkdownViewGeneratorExtension()).registerExtension(new NonMarkdownViewGeneratorExtension()).load("source");
|
|
highlightMatches();
|
|
}
|
|
focusEl?.focus();
|
|
});
|
|
onDestroy(() => {
|
|
setTimeout(() => renderer?.unload(), 1e3);
|
|
});
|
|
function highlightMatches() {
|
|
renderer?.highlightMatches(matches ?? [], "highlight-search-match");
|
|
}
|
|
function div1_binding($$value) {
|
|
binding_callbacks[$$value ? "unshift" : "push"](() => {
|
|
containerEl = $$value;
|
|
$$invalidate(1, containerEl);
|
|
});
|
|
}
|
|
$$self.$$set = ($$props2) => {
|
|
if ("file" in $$props2)
|
|
$$invalidate(0, file = $$props2.file);
|
|
if ("matches" in $$props2)
|
|
$$invalidate(2, matches = $$props2.matches);
|
|
if ("focusEl" in $$props2)
|
|
$$invalidate(3, focusEl = $$props2.focusEl);
|
|
};
|
|
return [file, containerEl, matches, focusEl, div1_binding];
|
|
}
|
|
var WorkspacePreview = class extends SvelteComponent {
|
|
constructor(options) {
|
|
super();
|
|
init(this, options, instance7, create_fragment7, safe_not_equal, { file: 0, matches: 2, focusEl: 3 }, add_css7);
|
|
}
|
|
};
|
|
var WorkspacePreview_default = WorkspacePreview;
|
|
|
|
// src/Controller.ts
|
|
var DELAY_TO_RELOAD_IN_MILLISECOND = 1e3;
|
|
var RETRY_INTERVAL = 1;
|
|
var RETRY_TRIALS = 1e3;
|
|
var DELAY_TO_RENDER_CARD_VIEW_ON_ENTRY_IN_MILLISECOND = 100;
|
|
var Controller = class extends obsidian.Component {
|
|
constructor(app2, plugin2, events, searchInterface) {
|
|
super();
|
|
this.app = app2;
|
|
this.plugin = plugin2;
|
|
this.events = events;
|
|
this.searchInterface = searchInterface;
|
|
this.modeScope = new ModeScope();
|
|
this.cardViewCheckDebouncer = (0, import_obsidian14.debounce)(
|
|
this.onCheckCardView,
|
|
DELAY_TO_RELOAD_IN_MILLISECOND,
|
|
true
|
|
);
|
|
this.countSearchItemDetected = 0;
|
|
}
|
|
onunload() {
|
|
this.exit();
|
|
}
|
|
onload() {
|
|
this.saveLayout();
|
|
this.setSearchModeTriggers();
|
|
}
|
|
async enter() {
|
|
if (this.modeScope.inSearchMode) {
|
|
return;
|
|
}
|
|
this.setHotkeys();
|
|
this.addChildren();
|
|
if (this.plugin.settings?.autoToggleSidebar) {
|
|
this.collapseOppositeSidedock();
|
|
}
|
|
const shouldDetectSearchItems = this.plugin.settings?.autoPreviewMode === "cardView" && this.plugin.settings.renderCardsManually === false;
|
|
if (shouldDetectSearchItems) {
|
|
this.searchInterface.startWatching(this.events);
|
|
await delay(DELAY_TO_RENDER_CARD_VIEW_ON_ENTRY_IN_MILLISECOND);
|
|
this.renewCardViewPage();
|
|
this.cardViewCheckDebouncer();
|
|
}
|
|
this.modeScope.push();
|
|
}
|
|
reset() {
|
|
if (!this.modeScope.inSearchMode) {
|
|
return;
|
|
}
|
|
this.forget();
|
|
this.unfocus();
|
|
this.cardViewComponent?.detachCards();
|
|
this.countSearchItemDetected = 0;
|
|
}
|
|
exit(reason) {
|
|
if (!this.modeScope.inSearchMode) {
|
|
return;
|
|
}
|
|
this.reset();
|
|
this.detachHotkeys();
|
|
this.removeChildren();
|
|
if (this.shouldCollapseSidedock(reason)) {
|
|
this.collapseSidedock();
|
|
}
|
|
if (this.plugin.settings?.autoToggleSidebar) {
|
|
this.restoreOppositeSidedock();
|
|
}
|
|
this.countSearchItemDetected = 0;
|
|
this.searchInterface.stopWatching();
|
|
this.unfocus();
|
|
this.modeScope.reset();
|
|
}
|
|
focus() {
|
|
if (this.currentFocusId === void 0) {
|
|
return;
|
|
}
|
|
this.searchInterface.focusOn(this.currentFocusId);
|
|
this.cardViewComponent?.focusOn(this.currentFocusId);
|
|
}
|
|
open(direction) {
|
|
if (this.currentFocusId === void 0) {
|
|
return;
|
|
}
|
|
this.searchInterface.open(this.currentFocusId, direction);
|
|
}
|
|
async renewCardViewPage() {
|
|
if (this.plugin.settings?.autoPreviewMode !== "cardView")
|
|
return;
|
|
this.cardViewComponent?.detachCards();
|
|
this.cardViewComponent?.renderPage(this.filesToBeRendered());
|
|
if (this.currentFocusId !== void 0) {
|
|
this.cardViewComponent?.focusOn(this.currentFocusId ?? 0);
|
|
}
|
|
}
|
|
filesToBeRendered() {
|
|
const cardsPerPage2 = this.cardsPerPage();
|
|
if (cardsPerPage2 === void 0) {
|
|
return [];
|
|
}
|
|
const pageId = Math.floor((this.currentFocusId ?? 0) / cardsPerPage2);
|
|
const items = this.plugin.searchInterface?.resultItems;
|
|
if (!items)
|
|
return [];
|
|
return items.slice(pageId * cardsPerPage2).map((item) => item.file);
|
|
}
|
|
collapseSidedock() {
|
|
this.searchInterface.collapseSidedock();
|
|
}
|
|
collapseOppositeSidedock() {
|
|
const collapsed = this.searchInterface.oppositeSidedock?.collapsed;
|
|
this.searchInterface.collapseOppositeSidedock();
|
|
this._restoreOppositeSidedock = () => {
|
|
if (collapsed === false) {
|
|
this.searchInterface.expandOppositeSidedock();
|
|
}
|
|
};
|
|
}
|
|
restoreOppositeSidedock() {
|
|
const restoreOppositeSidedock = this._restoreOppositeSidedock;
|
|
if (restoreOppositeSidedock === void 0) {
|
|
return void 0;
|
|
}
|
|
return restoreOppositeSidedock();
|
|
}
|
|
addChildren() {
|
|
this.removeChildren();
|
|
const { settings } = this.plugin;
|
|
if (settings === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to addChildren: failed to read setting";
|
|
}
|
|
this.outline = new Outline_default({
|
|
target: document.body,
|
|
props: {
|
|
lineWidth: settings.outlineWidth
|
|
}
|
|
});
|
|
if (settings.autoPreviewMode === "cardView") {
|
|
this.renewCardViewComponent();
|
|
}
|
|
}
|
|
removeChildren() {
|
|
this.outline?.$destroy();
|
|
this.outline = void 0;
|
|
this.cardViewComponent?.$destroy();
|
|
this.cardViewComponent = void 0;
|
|
this.workspacePreviewComponent?.$destroy();
|
|
this.workspacePreviewComponent = void 0;
|
|
}
|
|
forget() {
|
|
this.currentFocusId = void 0;
|
|
this.countSearchItemDetected = 0;
|
|
}
|
|
navigateForward() {
|
|
let updated = true;
|
|
const numResults = this.searchInterface.count() ?? 0;
|
|
if (this.currentFocusId === void 0) {
|
|
this.currentFocusId = 0;
|
|
} else {
|
|
this.currentFocusId++;
|
|
if (this.currentFocusId >= numResults) {
|
|
this.currentFocusId = numResults - 1;
|
|
updated = false;
|
|
}
|
|
}
|
|
if (!updated)
|
|
return;
|
|
const { settings } = this.plugin;
|
|
if (!settings)
|
|
return;
|
|
if (settings.autoPreviewMode === "cardView" && this.shouldTransitNextPageInCardView()) {
|
|
this.renewCardViewPage();
|
|
} else if (settings.autoPreviewMode === "singleView") {
|
|
this.renewWorkspacePreviewComponent();
|
|
}
|
|
this.focus();
|
|
}
|
|
navigateBack() {
|
|
if (this.currentFocusId === void 0) {
|
|
return;
|
|
}
|
|
let updated = true;
|
|
this.currentFocusId--;
|
|
if (this.currentFocusId < 0) {
|
|
this.currentFocusId = 0;
|
|
updated = false;
|
|
}
|
|
if (!updated)
|
|
return;
|
|
const { settings } = this.plugin;
|
|
if (!settings)
|
|
return;
|
|
if (settings.autoPreviewMode === "cardView" && this.shouldTransitPreviousPageInCardView()) {
|
|
this.renewCardViewPage();
|
|
} else if (settings.autoPreviewMode === "singleView") {
|
|
this.renewWorkspacePreviewComponent();
|
|
}
|
|
this.focus();
|
|
}
|
|
moveToNextPage() {
|
|
const pageId = this.pageId;
|
|
if (pageId === void 0)
|
|
return;
|
|
const pageCount = this.pageCount;
|
|
if (pageCount === void 0)
|
|
return;
|
|
if (pageId >= pageCount - 1)
|
|
return;
|
|
const cardsPerPage2 = this.cardsPerPage();
|
|
if (cardsPerPage2 === void 0)
|
|
return;
|
|
this.currentFocusId = cardsPerPage2 * (pageId + 1);
|
|
this.renewCardViewPage();
|
|
this.focus();
|
|
}
|
|
moveToPreviousPage() {
|
|
const pageId = this.pageId;
|
|
if (pageId === void 0)
|
|
return;
|
|
const pageCount = this.pageCount;
|
|
if (pageCount === void 0)
|
|
return;
|
|
if (pageId <= 0)
|
|
return;
|
|
const cardsPerPage2 = this.cardsPerPage();
|
|
if (cardsPerPage2 === void 0)
|
|
return;
|
|
this.currentFocusId = cardsPerPage2 * (pageId - 1);
|
|
this.renewCardViewPage();
|
|
this.focus();
|
|
}
|
|
unfocus() {
|
|
this.searchInterface.unfocus();
|
|
}
|
|
openPreviewModal() {
|
|
const { currentFocusId } = this;
|
|
if (currentFocusId === void 0) {
|
|
return;
|
|
}
|
|
const item = this.searchInterface.getResultItemAt(currentFocusId);
|
|
if (!item) {
|
|
return;
|
|
}
|
|
new PreviewModal(this.app, this.plugin, this.modeScope, item).open();
|
|
}
|
|
shouldTransitNextPageInCardView() {
|
|
if (this.currentFocusId === void 0 || this.currentFocusId === 0) {
|
|
return false;
|
|
}
|
|
if (!this.plugin.settings) {
|
|
return false;
|
|
}
|
|
const [row, column] = parseCardLayout(this.plugin.settings.cardViewLayout);
|
|
const cardsPerPage2 = row * column;
|
|
return this.currentFocusId % cardsPerPage2 === 0;
|
|
}
|
|
shouldTransitPreviousPageInCardView() {
|
|
if (!this.plugin.settings) {
|
|
return false;
|
|
}
|
|
const [row, column] = parseCardLayout(this.plugin.settings.cardViewLayout);
|
|
const cardsPerPage2 = row * column;
|
|
if (this.currentFocusId === void 0) {
|
|
return false;
|
|
}
|
|
return (this.currentFocusId + 1) % cardsPerPage2 === 0;
|
|
}
|
|
get pageId() {
|
|
if (this.currentFocusId === void 0)
|
|
return void 0;
|
|
const cardsPerPage2 = this.cardsPerPage();
|
|
if (cardsPerPage2 === void 0)
|
|
return void 0;
|
|
const pageId = Math.floor(this.currentFocusId / cardsPerPage2);
|
|
return pageId;
|
|
}
|
|
get pageCount() {
|
|
const numResults = this.plugin.searchInterface?.count();
|
|
const cardsPerPage2 = this.cardsPerPage();
|
|
if (cardsPerPage2 === void 0)
|
|
return void 0;
|
|
const pageCount = Math.ceil((numResults ?? 0) / cardsPerPage2);
|
|
return pageCount;
|
|
}
|
|
cardsPerPage() {
|
|
if (!this.plugin.settings) {
|
|
return void 0;
|
|
}
|
|
const [row, column] = parseCardLayout(this.plugin.settings.cardViewLayout);
|
|
return row * column;
|
|
}
|
|
/**
|
|
* check layout change
|
|
* use for detecting whether layout-change really occurs
|
|
* @returns callback which returns
|
|
*/
|
|
saveLayout() {
|
|
this.app.workspace.onLayoutReady(async () => {
|
|
const inputEl = await retry(
|
|
() => this.searchInterface.searchInputEl,
|
|
RETRY_INTERVAL,
|
|
RETRY_TRIALS
|
|
);
|
|
this._layoutChanged = async () => inputEl !== await retry(
|
|
() => this.searchInterface.searchInputEl,
|
|
RETRY_INTERVAL,
|
|
RETRY_TRIALS
|
|
);
|
|
});
|
|
}
|
|
async layoutChanged() {
|
|
const shouldRenewController = await this._layoutChanged?.();
|
|
if (shouldRenewController === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to renewRequired: saveLayout was not called.";
|
|
}
|
|
return shouldRenewController;
|
|
}
|
|
setSearchModeTriggers() {
|
|
this.registerEvent(
|
|
this.events.on(
|
|
EVENT_SEARCH_RESULT_ITEM_DETECTED,
|
|
this.onSearchResultItemDetected
|
|
)
|
|
);
|
|
this.registerEvent(
|
|
this.events.on(EVENT_SORT_ORDER_CHANGED, this.onSortOrderChanged)
|
|
);
|
|
this.app.workspace.onLayoutReady(async () => {
|
|
const appContainerEl = await retry(
|
|
() => this.app.dom.appContainerEl,
|
|
RETRY_INTERVAL,
|
|
RETRY_TRIALS
|
|
);
|
|
if (appContainerEl === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to find the app container element";
|
|
}
|
|
const inputEl = await retry(
|
|
() => this.plugin.searchInterface?.searchInputEl,
|
|
RETRY_INTERVAL,
|
|
RETRY_TRIALS
|
|
);
|
|
if (inputEl === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to find the search input form.";
|
|
}
|
|
const matchingCaseButtonEl = await retry(
|
|
() => this.plugin.searchInterface?.matchingCaseButtonEl,
|
|
RETRY_INTERVAL,
|
|
RETRY_TRIALS
|
|
);
|
|
if (matchingCaseButtonEl === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to find the matching case button.";
|
|
}
|
|
this.registerDomEvent(appContainerEl, "click", (evt) => {
|
|
const targetEl = evt.target;
|
|
if (!(targetEl instanceof HTMLElement)) {
|
|
return;
|
|
}
|
|
if (this.plugin.searchInterface?.searchLeaf?.containerEl.contains(
|
|
targetEl
|
|
)) {
|
|
if (!this.plugin.searchInterface.isBuiltInElementToOpenFile(targetEl))
|
|
return;
|
|
}
|
|
if (this.plugin.searchInterface?.tabHeaderEl?.contains(targetEl)) {
|
|
return;
|
|
}
|
|
if (this.plugin.searchInterface?.isShowMoreContextButton(targetEl)) {
|
|
return;
|
|
}
|
|
if (this.modeScope.depth === 1) {
|
|
this.exit({ id: "mouse", event: evt });
|
|
}
|
|
});
|
|
this.registerDomEvent(matchingCaseButtonEl, "click", () => {
|
|
if (this.modeScope.inSearchMode) {
|
|
this.reset();
|
|
}
|
|
});
|
|
this.registerDomEvent(inputEl, "input", () => {
|
|
if (!this.modeScope.inSearchMode) {
|
|
this.enter();
|
|
}
|
|
this.reset();
|
|
});
|
|
this.registerDomEvent(inputEl, "keypress", (evt) => {
|
|
if (evt.key !== "Enter") {
|
|
return;
|
|
}
|
|
if (!this.modeScope.inSearchMode) {
|
|
this.enter();
|
|
}
|
|
this.reset();
|
|
});
|
|
this.registerDomEvent(inputEl, "focus", () => {
|
|
if (!this.modeScope.inSearchMode) {
|
|
this.enter();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
setHotkeys() {
|
|
const hotkeyMap = this.plugin.settings?.searchModeHotkeys;
|
|
if (!hotkeyMap)
|
|
return;
|
|
const scope = new obsidian.Scope();
|
|
this.app.keymap.pushScope(scope);
|
|
hotkeyMap.selectNext.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, (evt) => {
|
|
evt.preventDefault();
|
|
this.navigateForward();
|
|
});
|
|
});
|
|
hotkeyMap.selectPrevious.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, (evt) => {
|
|
evt.preventDefault();
|
|
this.navigateBack();
|
|
});
|
|
});
|
|
hotkeyMap.open.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, (evt) => {
|
|
evt.preventDefault();
|
|
this.open();
|
|
this.exit();
|
|
});
|
|
});
|
|
hotkeyMap.openInNewPane.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, (evt) => {
|
|
evt.preventDefault();
|
|
this.open(this.plugin.settings?.splitDirection);
|
|
this.exit();
|
|
});
|
|
});
|
|
hotkeyMap.previewModal.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
if (this.app.vault.config.legacyEditor) {
|
|
return;
|
|
}
|
|
this.openPreviewModal();
|
|
});
|
|
});
|
|
hotkeyMap.showOptions.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
new OptionModal(this.app, this.plugin, this.modeScope).open();
|
|
});
|
|
});
|
|
hotkeyMap.nextPage.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
if (this.plugin.settings?.autoPreviewMode === "cardView") {
|
|
this.moveToNextPage();
|
|
}
|
|
});
|
|
});
|
|
hotkeyMap.previousPage.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
if (this.plugin.settings?.autoPreviewMode === "cardView") {
|
|
this.moveToPreviousPage();
|
|
}
|
|
});
|
|
});
|
|
hotkeyMap.copyLink.forEach((hotkey) => {
|
|
scope.register(hotkey.modifiers, hotkey.key, () => {
|
|
const item = this.searchInterface.getResultItemAt(
|
|
this.currentFocusId ?? 0
|
|
);
|
|
if (!item)
|
|
return;
|
|
const { file } = item;
|
|
const internalLink = generateInternalLinkFrom(this.app, file);
|
|
navigator.clipboard.writeText(internalLink);
|
|
new import_obsidian14.Notice("Copy wiki link!");
|
|
});
|
|
});
|
|
scope.register([], "Escape", (evt) => {
|
|
evt.preventDefault();
|
|
this.exit();
|
|
});
|
|
scope.register([], "Enter", (evt) => {
|
|
setTimeout(this.focusOnInput, 100);
|
|
const shouldRenderCardsManually = this.plugin.settings?.autoPreviewMode === "cardView" && this.plugin.settings.renderCardsManually;
|
|
if (shouldRenderCardsManually) {
|
|
evt.preventDefault();
|
|
this.reset();
|
|
this.renewCardViewPage();
|
|
}
|
|
});
|
|
this._detachHotkeys = () => {
|
|
this.app.keymap.popScope(scope);
|
|
};
|
|
}
|
|
detachHotkeys() {
|
|
const detachHotkeys = this._detachHotkeys;
|
|
if (detachHotkeys === void 0) {
|
|
return;
|
|
}
|
|
detachHotkeys();
|
|
}
|
|
get onSearchResultItemDetected() {
|
|
return () => {
|
|
if (this.plugin.settings?.autoPreviewMode !== "cardView") {
|
|
return;
|
|
}
|
|
if (this.currentFocusId !== void 0) {
|
|
return;
|
|
}
|
|
if (this.countSearchItemDetected === 0) {
|
|
this.cardViewComponent?.detachCards();
|
|
}
|
|
const item = this.searchInterface.getResultItemAt(
|
|
this.countSearchItemDetected
|
|
);
|
|
if (!item)
|
|
return;
|
|
this.cardViewComponent?.addCard(item.file);
|
|
this.cardViewCheckDebouncer();
|
|
this.countSearchItemDetected++;
|
|
};
|
|
}
|
|
renewCardViewComponent() {
|
|
this.cardViewComponent?.$destroy();
|
|
const { settings } = this.plugin;
|
|
if (!settings)
|
|
return;
|
|
const focusEl = this.searchInterface.searchInputEl;
|
|
if (!focusEl)
|
|
return;
|
|
const layout = parseCardLayout(settings.cardViewLayout);
|
|
this.app.workspace.onLayoutReady(() => {
|
|
const containerEl = this.app.workspace.rootSplit.containerEl;
|
|
const cardViewComponent = new CardViewComponent_default({
|
|
target: containerEl,
|
|
props: {
|
|
layout,
|
|
focusEl
|
|
}
|
|
});
|
|
this.cardViewComponent = cardViewComponent;
|
|
});
|
|
}
|
|
renewWorkspacePreviewComponent() {
|
|
this.workspacePreviewComponent?.$destroy();
|
|
if (this.currentFocusId === void 0)
|
|
return;
|
|
const focusEl = this.searchInterface.searchInputEl;
|
|
if (!focusEl)
|
|
return;
|
|
const item = this.searchInterface.getResultItemAt(this.currentFocusId);
|
|
if (!item)
|
|
return;
|
|
this.app.workspace.onLayoutReady(() => {
|
|
const containerEl = this.app.workspace.rootSplit.containerEl;
|
|
const workspacePreviewComponent = new WorkspacePreview_default({
|
|
target: containerEl,
|
|
props: {
|
|
file: item.file,
|
|
matches: item.result.content ?? [],
|
|
focusEl
|
|
}
|
|
});
|
|
this.workspacePreviewComponent = workspacePreviewComponent;
|
|
});
|
|
}
|
|
get focusOnInput() {
|
|
return async () => {
|
|
const inputEl = await retry(
|
|
() => this.plugin.searchInterface?.searchInputEl,
|
|
RETRY_INTERVAL,
|
|
RETRY_TRIALS
|
|
);
|
|
if (inputEl === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to find the search input form.";
|
|
}
|
|
inputEl.focus();
|
|
};
|
|
}
|
|
get onSortOrderChanged() {
|
|
return () => {
|
|
this.reset();
|
|
if (this.plugin.settings?.autoPreviewMode === "cardView") {
|
|
this.renewCardViewPage();
|
|
}
|
|
};
|
|
}
|
|
shouldCollapseSidedock(reason) {
|
|
if (!this.plugin.settings?.autoToggleSidebar) {
|
|
return false;
|
|
}
|
|
if (reason === void 0) {
|
|
return true;
|
|
}
|
|
if (reason.id !== "mouse") {
|
|
return true;
|
|
}
|
|
const targetEl = reason.event.target;
|
|
if (!(targetEl instanceof HTMLElement)) {
|
|
return true;
|
|
}
|
|
return !this.searchInterface.sideDock?.containerEl.contains(targetEl);
|
|
}
|
|
get onCheckCardView() {
|
|
return () => {
|
|
const { cardViewComponent } = this;
|
|
if (!cardViewComponent)
|
|
return;
|
|
const ok = cardViewComponent.checkCardsRenderedCorrectly(
|
|
this.filesToBeRendered()
|
|
);
|
|
if (!ok) {
|
|
this.reset();
|
|
this.renewCardViewPage();
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
// src/interfaces/SearchComponentInterface.ts
|
|
var import_obsidian16 = require("obsidian");
|
|
|
|
// src/types/Guards.ts
|
|
var import_obsidian15 = require("obsidian");
|
|
var SORT_ORDER_IN_SEARCH = [
|
|
"alphabeticalReverse",
|
|
"alphabetical",
|
|
"byModifiedTime",
|
|
"byModifiedTimeReverse",
|
|
"byCreatedTime",
|
|
"byCreatedTimeReverse"
|
|
];
|
|
function isSearchView(view) {
|
|
if (typeof view !== "object") {
|
|
return false;
|
|
}
|
|
if (view === null) {
|
|
return false;
|
|
}
|
|
const {
|
|
matchingCase,
|
|
explainSearch,
|
|
dom,
|
|
setCollapseAll,
|
|
setExplainSearch,
|
|
setExtraContext,
|
|
setMatchingCase,
|
|
setSortOrder,
|
|
searchInfoEl,
|
|
searchComponent
|
|
} = view;
|
|
if (typeof matchingCase !== "boolean") {
|
|
return false;
|
|
}
|
|
if (typeof explainSearch !== "boolean") {
|
|
return false;
|
|
}
|
|
if (!isSearchDom(dom)) {
|
|
return false;
|
|
}
|
|
if (typeof searchComponent !== "object") {
|
|
return false;
|
|
}
|
|
if (typeof searchInfoEl !== "object") {
|
|
return false;
|
|
}
|
|
if (!(searchInfoEl instanceof HTMLDivElement)) {
|
|
return false;
|
|
}
|
|
if (!(setCollapseAll instanceof Function)) {
|
|
return false;
|
|
}
|
|
if (!(setExplainSearch instanceof Function)) {
|
|
return false;
|
|
}
|
|
if (!(setExtraContext instanceof Function)) {
|
|
return false;
|
|
}
|
|
if (!(setMatchingCase instanceof Function)) {
|
|
return false;
|
|
}
|
|
if (!(setSortOrder instanceof Function)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
function isSearchDom(obj) {
|
|
if (typeof obj !== "object") {
|
|
return false;
|
|
}
|
|
if (obj === null) {
|
|
return false;
|
|
}
|
|
const { extraContext, collapseAll, sortOrder, vChildren, childrenEl } = obj;
|
|
if (typeof extraContext !== "boolean") {
|
|
return false;
|
|
}
|
|
if (typeof collapseAll !== "boolean") {
|
|
return false;
|
|
}
|
|
if (typeof sortOrder !== "string") {
|
|
return false;
|
|
}
|
|
if (!SORT_ORDER_IN_SEARCH.includes(sortOrder)) {
|
|
return false;
|
|
}
|
|
if (!isSearchResultItemGroup(vChildren)) {
|
|
return false;
|
|
}
|
|
if (typeof childrenEl !== "object") {
|
|
return false;
|
|
}
|
|
if (!(childrenEl instanceof HTMLElement)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
function isSearchResultItemGroup(obj) {
|
|
if (typeof obj !== "object" || obj === null) {
|
|
return false;
|
|
}
|
|
const { _children: children2 } = obj;
|
|
if (typeof children2 !== "object") {
|
|
return false;
|
|
}
|
|
if (!Array.isArray(children2)) {
|
|
return false;
|
|
}
|
|
for (const child of children2) {
|
|
if (!isSearchResultItem(child)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
function isSearchResultItem(obj) {
|
|
if (typeof obj !== "object" || obj === null) {
|
|
return false;
|
|
}
|
|
const { file, containerEl } = obj;
|
|
if (!(file instanceof import_obsidian15.TFile)) {
|
|
return false;
|
|
}
|
|
if (!(containerEl instanceof HTMLElement)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// src/utils/LinkedList.ts
|
|
var LinkedList = class {
|
|
constructor(events, eventId) {
|
|
this.unlinkedPool = /* @__PURE__ */ new Map();
|
|
this.events = events;
|
|
this.eventId = eventId;
|
|
}
|
|
// attach nodes recursively
|
|
structure(cur, pre) {
|
|
let linked = false;
|
|
if (pre === void 0) {
|
|
this.setRoot(cur);
|
|
linked = true;
|
|
this.signal();
|
|
} else if (this.tail !== void 0 && pre === this.tail.entity) {
|
|
this.link(cur);
|
|
linked = true;
|
|
this.unlinkedPool.delete(cur);
|
|
this.signal();
|
|
}
|
|
if (linked) {
|
|
if (!this.unlinkedPool.has(cur)) {
|
|
return;
|
|
}
|
|
const next = this.unlinkedPool.get(cur);
|
|
if (next === void 0) {
|
|
return;
|
|
}
|
|
this.structure(next, cur);
|
|
} else {
|
|
if (pre) {
|
|
this.unlinkedPool.set(pre, cur);
|
|
}
|
|
}
|
|
}
|
|
setRoot(entity) {
|
|
const rootNode = {
|
|
entity,
|
|
pre: void 0,
|
|
next: void 0
|
|
};
|
|
this.head = rootNode;
|
|
this.tail = rootNode;
|
|
}
|
|
link(cur) {
|
|
if (!this.tail) {
|
|
return;
|
|
}
|
|
const currentTail = this.tail;
|
|
currentTail.next = {
|
|
entity: cur,
|
|
pre: currentTail,
|
|
next: void 0
|
|
};
|
|
this.tail = currentTail.next;
|
|
}
|
|
clean() {
|
|
this.head = void 0;
|
|
this.tail = void 0;
|
|
this.unlinkedPool = /* @__PURE__ */ new Map();
|
|
}
|
|
// let outside know a node is attached
|
|
signal() {
|
|
this.events.trigger(this.eventId);
|
|
}
|
|
};
|
|
|
|
// src/interfaces/SearchComponentInterface.ts
|
|
var SearchComponentInterface = class extends import_obsidian16.Component {
|
|
constructor(app2, plugin2, events) {
|
|
super();
|
|
this.observationConfig = {
|
|
childList: true
|
|
};
|
|
this.onObservedCallback = async (mutations, _observer) => {
|
|
for (const mutation of mutations) {
|
|
if (mutation.addedNodes.length === 0) {
|
|
continue;
|
|
}
|
|
const pre = mutation.previousSibling;
|
|
if (!(pre instanceof HTMLElement)) {
|
|
continue;
|
|
}
|
|
for (const node of Array.from(mutation.addedNodes)) {
|
|
if (!(node instanceof HTMLElement)) {
|
|
continue;
|
|
}
|
|
const isSearchResultItem2 = node.tagName === "DIV" && node.hasClass("tree-item") && node.hasClass("search-result");
|
|
if (!isSearchResultItem2) {
|
|
continue;
|
|
}
|
|
if (!this.linkedList) {
|
|
return;
|
|
}
|
|
this.linkedList.structure(
|
|
node,
|
|
this.isRootSearchResult(pre) ? void 0 : pre
|
|
);
|
|
}
|
|
}
|
|
};
|
|
this.app = app2;
|
|
this.plugin = plugin2;
|
|
this.events = events;
|
|
this.observer = new MutationObserver(
|
|
this.onObservedCallback.bind(this)
|
|
);
|
|
}
|
|
onload() {
|
|
this.app.workspace.onLayoutReady(() => {
|
|
this.renewSortOrderInfo();
|
|
this.registerDomEvent(document, "click", () => {
|
|
this.renewSortOrderInfo(this.events);
|
|
});
|
|
});
|
|
}
|
|
onunload() {
|
|
this.sortOrderContainerEl?.empty();
|
|
this.sortOrderContainerEl?.remove();
|
|
this.observer.disconnect();
|
|
}
|
|
toggleMatchingCase() {
|
|
const view = this.searchView;
|
|
view?.setMatchingCase(!view.matchingCase);
|
|
}
|
|
toggleExplainSearch() {
|
|
const view = this.searchView;
|
|
view?.setExplainSearch(!view.explainSearch);
|
|
}
|
|
toggleCollapseAll() {
|
|
const view = this.searchView;
|
|
view?.setCollapseAll(!view.dom.collapseAll);
|
|
}
|
|
toggleExtraContext() {
|
|
const view = this.searchView;
|
|
view?.setExtraContext(!view.dom.extraContext);
|
|
}
|
|
setSortOrder(sortOrder) {
|
|
const view = this.searchView;
|
|
const originalOrder = view?.dom.sortOrder;
|
|
view?.setSortOrder(sortOrder);
|
|
return sortOrder !== originalOrder;
|
|
}
|
|
focusOn(pos) {
|
|
this.unfocus();
|
|
const item = this.getResultItemAt(pos);
|
|
if (!item) {
|
|
return;
|
|
}
|
|
item.containerEl.addClass(
|
|
"core-search-assistant_search-result-items-focus"
|
|
);
|
|
item.containerEl.scrollIntoView(
|
|
this.plugin.settings?.keepSelectedItemsCentered ? { block: "center" } : { block: "nearest" }
|
|
);
|
|
}
|
|
unfocus() {
|
|
const items = this.resultItems;
|
|
items.forEach((item) => {
|
|
item.containerEl.removeClass(
|
|
"core-search-assistant_search-result-items-focus"
|
|
);
|
|
});
|
|
}
|
|
async open(pos, direction) {
|
|
const item = this.getResultItemAt(pos);
|
|
if (!item) {
|
|
return;
|
|
}
|
|
const { file } = item;
|
|
const leaf = direction === void 0 ? this.app.workspace.getMostRecentLeaf() : this.app.workspace.splitActiveLeaf(direction);
|
|
await leaf.openFile(file);
|
|
this.app.workspace.setActiveLeaf(leaf, true, true);
|
|
}
|
|
renewSortOrderInfo(events) {
|
|
if (!this.sortOrderContainerEl) {
|
|
this.createSortOrderEls();
|
|
}
|
|
const view = this.searchView;
|
|
if (!view) {
|
|
return;
|
|
}
|
|
const sortOrder = view.dom.sortOrder;
|
|
if (!this.sortOrderContentEl) {
|
|
return;
|
|
}
|
|
const originalContent = this.sortOrderContentEl.textContent;
|
|
this.sortOrderContentEl.textContent = searchOptions[sortOrder].description;
|
|
if (events !== void 0 && originalContent !== this.sortOrderContentEl.textContent) {
|
|
events.trigger(EVENT_SORT_ORDER_CHANGED);
|
|
}
|
|
}
|
|
count() {
|
|
const results = this.searchView?.dom.vChildren._children;
|
|
if (!results) {
|
|
return 0;
|
|
}
|
|
return results.length;
|
|
}
|
|
get resultItems() {
|
|
return this.searchView?.dom.vChildren._children ?? [];
|
|
}
|
|
getResultItemAt(pos) {
|
|
return this.searchView?.dom.vChildren._children[pos];
|
|
}
|
|
get searchInputEl() {
|
|
return this.searchView?.searchComponent.inputEl;
|
|
}
|
|
startWatching(events) {
|
|
this.linkedList = new LinkedList(
|
|
events,
|
|
EVENT_SEARCH_RESULT_ITEM_DETECTED
|
|
);
|
|
const childrenContainerEl = this.searchView?.dom.childrenEl;
|
|
if (!(childrenContainerEl instanceof HTMLElement)) {
|
|
throw "[ERROR in Core Search Assistant] failed to SearchComponentInterface#startWatching: childrenContainerEl is not an instance of HTMLElement";
|
|
}
|
|
this.observer.observe(childrenContainerEl, this.observationConfig);
|
|
}
|
|
stopWatching() {
|
|
this.observer.disconnect();
|
|
}
|
|
collapseOppositeSidedock() {
|
|
const sideDock = this.oppositeSidedock;
|
|
if (sideDock === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to collapseOppositeSidedock: failed to fetch the opposite sidedock";
|
|
}
|
|
sideDock.collapse();
|
|
}
|
|
expandOppositeSidedock() {
|
|
const sideDock = this.oppositeSidedock;
|
|
if (sideDock === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to expandOppositeSidedock: failed to fetch the opposite sidedock";
|
|
}
|
|
sideDock.expand();
|
|
}
|
|
collapseSidedock() {
|
|
const sideDock = this.sideDock;
|
|
if (sideDock === void 0) {
|
|
throw "[ERROR in Core Search Assistant] failed to collapseSidedock: failed to fetch the sidedock";
|
|
}
|
|
sideDock.collapse();
|
|
}
|
|
get sideDock() {
|
|
const leaf = this.searchLeaf;
|
|
if (leaf === void 0) {
|
|
return void 0;
|
|
}
|
|
const parent = leaf.getRoot();
|
|
if (parent instanceof import_obsidian16.WorkspaceSidedock) {
|
|
return parent;
|
|
}
|
|
return void 0;
|
|
}
|
|
get oppositeSidedock() {
|
|
const leaf = this.searchLeaf;
|
|
if (leaf === void 0) {
|
|
return void 0;
|
|
}
|
|
const parent = leaf.getRoot();
|
|
if (parent === this.app.workspace.leftSplit) {
|
|
const opposite = this.app.workspace.rightSplit;
|
|
return opposite instanceof import_obsidian16.WorkspaceSidedock ? opposite : void 0;
|
|
}
|
|
if (parent === this.app.workspace.rightSplit) {
|
|
const opposite = this.app.workspace.leftSplit;
|
|
return opposite instanceof import_obsidian16.WorkspaceSidedock ? opposite : void 0;
|
|
}
|
|
return void 0;
|
|
}
|
|
createSortOrderEls() {
|
|
this.sortOrderContainerEl = createEl("div", {
|
|
cls: "search-info-container"
|
|
});
|
|
this.sortOrderContentEl = this.sortOrderContainerEl.createEl("div");
|
|
const view = this.searchView;
|
|
if (!view) {
|
|
return;
|
|
}
|
|
this.sortOrderContainerEl.insertAfter(view.searchInfoEl);
|
|
}
|
|
get matchingCaseButtonEl() {
|
|
return this.searchView?.matchingCaseButtonEl;
|
|
}
|
|
get tabHeaderEl() {
|
|
return this.searchLeaf?.tabHeaderEl;
|
|
}
|
|
isBuiltInElementToOpenFile(el) {
|
|
const isFileNameContainerEl = el.tagName === "DIV" && el.hasClass("tree-item-inner");
|
|
const isMatchCountContainerEl = el.tagName === "DIV" && el.hasClass("tree-item-flair-outer");
|
|
const isMatchContainerEl = el.tagName === "DIV" && el.hasClass("search-result-file-match");
|
|
if (isFileNameContainerEl || isMatchContainerEl || isMatchCountContainerEl) {
|
|
return true;
|
|
}
|
|
const parentEl = el.parentElement;
|
|
if (parentEl === null) {
|
|
return false;
|
|
}
|
|
return this.isBuiltInElementToOpenFile(parentEl);
|
|
}
|
|
isShowMoreContextButton(el) {
|
|
return el.tagName === "DIV" && el.hasClass("search-result-hover-button");
|
|
}
|
|
// get changeSortOrderButtonEl(): HTMLElement | undefined {
|
|
// const changeSortOrderButtonEl =
|
|
// this.searchView?.headerDom.navButtonsEl.querySelector(
|
|
// 'div.nav-action-button[aria-label="Change sort order"]'
|
|
// );
|
|
// return changeSortOrderButtonEl instanceof HTMLElement
|
|
// ? changeSortOrderButtonEl
|
|
// : undefined;
|
|
// }
|
|
get searchView() {
|
|
const leaf = this.searchLeaf;
|
|
if (!leaf) {
|
|
return void 0;
|
|
}
|
|
const view = leaf.view;
|
|
return isSearchView(view) ? view : void 0;
|
|
}
|
|
get searchLeaf() {
|
|
return this.app.workspace.getLeavesOfType("search")[0];
|
|
}
|
|
isRootSearchResult(el) {
|
|
return el.tagName === "DIV" && !el.hasClass("tree-item") && !el.hasClass("search-result");
|
|
}
|
|
// async watchSortOrderChangeByClick() {
|
|
// const callback = async (evt: Event) => {
|
|
// this.renewSortOrderInfo();
|
|
// if (evt.currentTarget === null) {
|
|
// return;
|
|
// }
|
|
// evt.currentTarget.removeEventListener('click', callback);
|
|
// };
|
|
// await new Promise((resolve) => setTimeout(resolve, 1)); // prevent callback from being called immediately
|
|
// document.addEventListener('click', callback);
|
|
// }
|
|
// getSortOrderSettingButton(): HTMLElement | undefined {
|
|
// const view = this.getSearchView();
|
|
// const buttonsEl = view?.headerDom.navButtonsEl;
|
|
// if (!buttonsEl) {
|
|
// return undefined;
|
|
// }
|
|
// const sortOrderSettingButtonEl = buttonsEl.querySelector(
|
|
// 'div.nav-action-button[aria-label="Change sort order"]'
|
|
// );
|
|
// return sortOrderSettingButtonEl
|
|
// ? (sortOrderSettingButtonEl as HTMLElement)
|
|
// : undefined;
|
|
// }
|
|
};
|
|
|
|
// src/main.ts
|
|
var import_obsidian17 = require("obsidian");
|
|
var CoreSearchAssistantPlugin = class extends import_obsidian17.Plugin {
|
|
async onload() {
|
|
await this.loadSettings();
|
|
this.events = new CoreSearchAssistantEvents();
|
|
this.searchInterface = this.addChild(
|
|
new SearchComponentInterface(this.app, this, this.events)
|
|
);
|
|
this.controller = this.addChild(
|
|
new Controller(this.app, this, this.events, this.searchInterface)
|
|
);
|
|
this.watchLayoutChange();
|
|
this.setSvelteStoreValues();
|
|
this.addSettingTab(new CoreSearchAssistantSettingTab(this.app, this));
|
|
}
|
|
// override onunload() {}
|
|
async loadSettings() {
|
|
this.settings = deepMerge(DEFAULT_SETTINGS, await this.loadData());
|
|
}
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
renewController() {
|
|
if (this.controller) {
|
|
this.removeChild(this.controller);
|
|
}
|
|
if (this.events === void 0) {
|
|
throw "[ERROR in Core Search Interface] failed to renewController: plugin.events = undefined";
|
|
}
|
|
if (this.searchInterface === void 0) {
|
|
throw "[ERROR in Core Search Interface] failed to renewController: plugin.searchInterface = undefined";
|
|
}
|
|
this.controller = this.addChild(
|
|
new Controller(this.app, this, this.events, this.searchInterface)
|
|
);
|
|
}
|
|
watchLayoutChange() {
|
|
this.app.workspace.onLayoutReady(() => {
|
|
this.app.workspace.on("layout-change", async () => {
|
|
if (await this.controller?.layoutChanged()) {
|
|
this.renewController();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
setSvelteStoreValues() {
|
|
plugin.set(this);
|
|
app.set(this.app);
|
|
}
|
|
};
|
|
|
|
/* nosourcemap */ |