gr0grig_obsidian-virt-folder/main.js
2026-07-11 13:01:53 +04:00

7265 lines
202 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
*/
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// main.ts
var main_exports = {};
__export(main_exports, {
default: () => VirtFolderPlugin
});
module.exports = __toCommonJS(main_exports);
var import_obsidian9 = require("obsidian");
// node_modules/svelte/src/runtime/internal/utils.js
function noop() {
}
var identity = (x) => x;
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 get_store_value(store) {
let value;
subscribe(store, (_) => value = _)();
return value;
}
function component_subscribe(component, store, callback) {
component.$$.on_destroy.push(subscribe(store, callback));
}
function action_destroyer(action_result) {
return action_result && is_function(action_result.destroy) ? action_result.destroy : noop;
}
// node_modules/svelte/src/runtime/internal/environment.js
var is_client = typeof window !== "undefined";
var now = is_client ? () => window.performance.now() : () => Date.now();
var raf = is_client ? (cb) => requestAnimationFrame(cb) : noop;
// node_modules/svelte/src/runtime/internal/loop.js
var tasks = /* @__PURE__ */ new Set();
function run_tasks(now2) {
tasks.forEach((task) => {
if (!task.c(now2)) {
tasks.delete(task);
task.f();
}
});
if (tasks.size !== 0)
raf(run_tasks);
}
function loop(callback) {
let task;
if (tasks.size === 0)
raf(run_tasks);
return {
promise: new Promise((fulfill) => {
tasks.add(task = { c: callback, f: fulfill });
}),
abort() {
tasks.delete(task);
}
};
}
// 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 {
/** @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() {
var _a;
return (_a = this._observer) != null ? _a : this._observer = new ResizeObserver((entries) => {
var _a2;
for (const entry of entries) {
ResizeObserverSingleton.entries.set(entry.target, entry);
(_a2 = this._listeners.get(entry.target)) == null ? void 0 : _a2(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 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_empty_stylesheet(node) {
const style_element = element("style");
style_element.textContent = "/* empty */";
append_stylesheet(get_root_for_style(node), style_element);
return style_element.sheet;
}
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 element(name) {
return document.createElement(name);
}
function text(data2) {
return document.createTextNode(data2);
}
function space() {
return text(" ");
}
function empty() {
return text("");
}
function listen(node, event, handler, options) {
node.addEventListener(event, handler, options);
return () => node.removeEventListener(event, handler, options);
}
function prevent_default(fn) {
return function(event) {
event.preventDefault();
return fn.call(this, event);
};
}
function stop_propagation(fn) {
return function(event) {
event.stopPropagation();
return fn.call(this, event);
};
}
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, data2) {
data2 = "" + data2;
if (text2.data === data2)
return;
text2.data = /** @type {string} */
data2;
}
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/style_manager.js
var managed_styles = /* @__PURE__ */ new Map();
var active = 0;
function hash(str) {
let hash2 = 5381;
let i = str.length;
while (i--)
hash2 = (hash2 << 5) - hash2 ^ str.charCodeAt(i);
return hash2 >>> 0;
}
function create_style_information(doc, node) {
const info = { stylesheet: append_empty_stylesheet(node), rules: {} };
managed_styles.set(doc, info);
return info;
}
function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {
const step = 16.666 / duration;
let keyframes = "{\n";
for (let p = 0; p <= 1; p += step) {
const t = a + (b - a) * ease(p);
keyframes += p * 100 + `%{${fn(t, 1 - t)}}
`;
}
const rule = keyframes + `100% {${fn(b, 1 - b)}}
}`;
const name = `__svelte_${hash(rule)}_${uid}`;
const doc = get_root_for_style(node);
const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node);
if (!rules[name]) {
rules[name] = true;
stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
}
const animation = node.style.animation || "";
node.style.animation = `${animation ? `${animation}, ` : ""}${name} ${duration}ms linear ${delay}ms 1 both`;
active += 1;
return name;
}
function delete_rule(node, name) {
const previous = (node.style.animation || "").split(", ");
const next = previous.filter(
name ? (anim) => anim.indexOf(name) < 0 : (anim) => anim.indexOf("__svelte") === -1
// remove all Svelte animations
);
const deleted = previous.length - next.length;
if (deleted) {
node.style.animation = next.join(", ");
active -= deleted;
if (!active)
clear_rules();
}
}
function clear_rules() {
raf(() => {
if (active)
return;
managed_styles.forEach((info) => {
const { ownerNode } = info.stylesheet;
if (ownerNode)
detach(ownerNode);
});
managed_styles.clear();
});
}
// node_modules/svelte/src/runtime/internal/lifecycle.js
var current_component;
function set_current_component(component) {
current_component = component;
}
// 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 tick() {
schedule_update();
return resolved_promise;
}
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 promise;
function wait() {
if (!promise) {
promise = Promise.resolve();
promise.then(() => {
promise = null;
});
}
return promise;
}
function dispatch(node, direction, kind) {
node.dispatchEvent(custom_event(`${direction ? "intro" : "outro"}${kind}`));
}
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();
}
}
var null_transition = { duration: 0 };
function create_bidirectional_transition(node, fn, params, intro) {
const options = { direction: "both" };
let config = fn(node, params, options);
let t = intro ? 0 : 1;
let running_program = null;
let pending_program = null;
let animation_name = null;
let original_inert_value;
function clear_animation() {
if (animation_name)
delete_rule(node, animation_name);
}
function init2(program, duration) {
const d = (
/** @type {Program['d']} */
program.b - t
);
duration *= Math.abs(d);
return {
a: t,
b: program.b,
d,
duration,
start: program.start,
end: program.start + duration,
group: program.group
};
}
function go(b) {
const {
delay = 0,
duration = 300,
easing = identity,
tick: tick2 = noop,
css
} = config || null_transition;
const program = {
start: now() + delay,
b
};
if (!b) {
program.group = outros;
outros.r += 1;
}
if ("inert" in node) {
if (b) {
if (original_inert_value !== void 0) {
node.inert = original_inert_value;
}
} else {
original_inert_value = /** @type {HTMLElement} */
node.inert;
node.inert = true;
}
}
if (running_program || pending_program) {
pending_program = program;
} else {
if (css) {
clear_animation();
animation_name = create_rule(node, t, b, duration, delay, easing, css);
}
if (b)
tick2(0, 1);
running_program = init2(program, duration);
add_render_callback(() => dispatch(node, b, "start"));
loop((now2) => {
if (pending_program && now2 > pending_program.start) {
running_program = init2(pending_program, duration);
pending_program = null;
dispatch(node, running_program.b, "start");
if (css) {
clear_animation();
animation_name = create_rule(
node,
t,
running_program.b,
running_program.duration,
0,
easing,
config.css
);
}
}
if (running_program) {
if (now2 >= running_program.end) {
tick2(t = running_program.b, 1 - t);
dispatch(node, running_program.b, "end");
if (!pending_program) {
if (running_program.b) {
clear_animation();
} else {
if (!--running_program.group.r)
run_all(running_program.group.c);
}
}
running_program = null;
} else if (now2 >= running_program.start) {
const p = now2 - running_program.start;
t = running_program.a + running_program.d * easing(p / running_program.duration);
tick2(t, 1 - t);
}
}
return !!(running_program || pending_program);
});
}
}
return {
run(b) {
if (is_function(config)) {
wait().then(() => {
const opts = { direction: b ? "in" : "out" };
config = config(opts);
go(b);
});
} else {
go(b);
}
},
end() {
clear_animation();
running_program = pending_program = null;
}
};
}
// node_modules/svelte/src/runtime/internal/each.js
function ensure_array_like(array_like_or_iterator) {
return (array_like_or_iterator == null ? void 0 : array_like_or_iterator.length) !== void 0 ? array_like_or_iterator : Array.from(array_like_or_iterator);
}
function outro_and_destroy_block(block, lookup) {
transition_out(block, 1, 1, () => {
lookup.delete(block.key);
});
}
function update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list, lookup, node, destroy, create_each_block2, next, get_context) {
let o = old_blocks.length;
let n = list.length;
let i = o;
const old_indexes = {};
while (i--)
old_indexes[old_blocks[i].key] = i;
const new_blocks = [];
const new_lookup = /* @__PURE__ */ new Map();
const deltas = /* @__PURE__ */ new Map();
const updates = [];
i = n;
while (i--) {
const child_ctx = get_context(ctx, list, i);
const key = get_key(child_ctx);
let block = lookup.get(key);
if (!block) {
block = create_each_block2(key, child_ctx);
block.c();
} else if (dynamic) {
updates.push(() => block.p(child_ctx, dirty));
}
new_lookup.set(key, new_blocks[i] = block);
if (key in old_indexes)
deltas.set(key, Math.abs(i - old_indexes[key]));
}
const will_move = /* @__PURE__ */ new Set();
const did_move = /* @__PURE__ */ new Set();
function insert2(block) {
transition_in(block, 1);
block.m(node, next);
lookup.set(block.key, block);
next = block.first;
n--;
}
while (o && n) {
const new_block = new_blocks[n - 1];
const old_block = old_blocks[o - 1];
const new_key = new_block.key;
const old_key = old_block.key;
if (new_block === old_block) {
next = new_block.first;
o--;
n--;
} else if (!new_lookup.has(old_key)) {
destroy(old_block, lookup);
o--;
} else if (!lookup.has(new_key) || will_move.has(new_key)) {
insert2(new_block);
} else if (did_move.has(old_key)) {
o--;
} else if (deltas.get(new_key) > deltas.get(old_key)) {
did_move.add(new_key);
insert2(new_block);
} else {
will_move.add(old_key);
o--;
}
}
while (o--) {
const old_block = old_blocks[o];
if (!new_lookup.has(old_block.key))
destroy(old_block, lookup);
}
while (n)
insert2(new_blocks[n - 1]);
run_all(updates);
return new_blocks;
}
// 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, instance3, create_fragment3, not_equal, props, append_styles = 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_styles && append_styles($$.root);
let ready = false;
$$.ctx = instance3 ? instance3(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_fragment3 ? create_fragment3($$.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) {
var _a;
if (this.$$r)
return;
attr2 = this.$$g_p(attr2);
this.$$d[attr2] = get_custom_element_value(attr2, newValue, this.$$p_d, "toProp");
(_a = this.$$c) == null ? void 0 : _a.$set({ [attr2]: this.$$d[attr2] });
}
disconnectedCallback() {
this.$$cn = false;
Promise.resolve().then(() => {
if (!this.$$cn) {
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) {
var _a;
const type = (_a = props_definition[prop]) == null ? void 0 : _a.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/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 };
}
// components/stores.ts
var plugin = writable();
var getPlugin = () => get_store_value(plugin);
var data = writable();
var active_id = writable();
// data.ts
var NoteData = class {
constructor(base) {
this.base = base;
}
onStartApp() {
this.base.rescan();
}
onCreate(file) {
this.base.add_note(file);
}
onChange(file) {
this.base.update_note(file);
}
onRename(file, oldPath) {
this.base.rename_note(file, oldPath);
}
onDelete(file) {
this.base.remove_note(file.path);
}
};
// base_scanner.ts
var import_obsidian2 = require("obsidian");
// onenote.ts
var OneNote = class {
constructor(id, mtime, ctime, name, title) {
this.utime = 0;
// created or used as folder
this.parents = [];
this.children = [];
this.is_pinned = false;
this.icon = "";
this.highlight_color = "";
this.highlight_opacity = 0;
this.metadata = {};
this.id = id;
this.mtime = mtime;
this.name = name;
this.title = title;
this.utime = ctime;
}
clear() {
this.parents = [];
this.children = [];
this.is_pinned = false;
this.highlight_color = "";
this.highlight_opacity = 0;
this.metadata = {};
this.mtime = 0;
this.utime = 0;
}
is_no_parents() {
return this.parents.length == 0;
}
is_no_children() {
return this.children.length == 0;
}
has_children() {
return this.children.length > 0;
}
count_children() {
return this.children.length;
}
};
// settings.ts
var import_obsidian = require("obsidian");
var SortTypes = /* @__PURE__ */ ((SortTypes2) => {
SortTypes2["file_name"] = "file_name";
SortTypes2["note_title"] = "note_title";
SortTypes2["creation_time"] = "creation_time";
SortTypes2["modification_time"] = "modification_time";
SortTypes2["custom"] = "custom";
return SortTypes2;
})(SortTypes || {});
var DEFAULT_SETTINGS = {
ignorePath: "",
ignoreTags: "",
includePath: "",
includeTags: "",
propertyName: "Folders",
titleProp: "",
iconProp: "vf_icon",
cmdShowTitle: false,
sortTreeBy: "file_name" /* file_name */,
sortTreeRev: false,
hideOrphans: false,
expandOnClick: false,
UseWikiLinks: true,
folderAsString: false,
confirmDelete: true,
autoReveal: false,
autoCollapse: false,
lastSeenVersion: "",
tagHighlights: [],
exposeMetadata: false,
customOrder: {}
};
var VirtFolderSettingTab = class extends import_obsidian.PluginSettingTab {
constructor(app, plugin2) {
super(app, plugin2);
this.plugin = plugin2;
this.init_settings();
}
init_settings() {
this.update_filter(this.plugin.settings.ignorePath);
this.update_ignored_tags(this.plugin.settings.ignoreTags);
this.update_include_paths(this.plugin.settings.includePath);
this.update_include_tags(this.plugin.settings.includeTags);
this.update_prop_name(this.plugin.settings.propertyName);
this.update_title(this.plugin.settings.titleProp);
this.update_icon_prop(this.plugin.settings.iconProp);
this.update_tag_highlights();
this.plugin.base.settings.set_expose_metadata(this.plugin.settings.exposeMetadata);
this.update_hide_orphans(this.plugin.settings.hideOrphans);
}
display() {
let { containerEl } = this;
containerEl.empty();
new import_obsidian.Setting(containerEl).setName("YAML for note's folders").setDesc("The name can contain letters, numbers, minus sign, underscore and dots").addText((text2) => {
text2.setValue(this.plugin.settings.propertyName);
text2.setPlaceholder("Folders");
text2.onChange(async (value) => {
let style = text2.inputEl.style;
if (this.is_valid_prop_name(value)) {
style.borderColor = "";
this.plugin.settings.propertyName = value;
await this.plugin.saveSettings();
this.update_prop_name(value);
} else {
style.borderColor = this.get_css_var("--background-modifier-error");
}
});
});
new import_obsidian.Setting(containerEl).setName("YAML for note's title").setDesc("Leave the field blank to take the title from the file name. Case-sensitive").addText((text2) => {
text2.setValue(this.plugin.settings.titleProp);
text2.setPlaceholder("Title");
text2.onChange(async (value) => {
let style = text2.inputEl.style;
if (this.is_empty_str(value) || this.is_valid_prop_name(value)) {
style.borderColor = "";
this.plugin.settings.titleProp = value;
await this.plugin.saveSettings();
this.update_title(value);
} else {
style.borderColor = this.get_css_var("--background-modifier-error");
}
});
});
new import_obsidian.Setting(containerEl).setName("YAML for note's icon").setDesc("The name can contain letters, numbers, minus sign, underscore and dots").addText((text2) => {
text2.setValue(this.plugin.settings.iconProp);
text2.setPlaceholder("vf_icon");
text2.onChange(async (value) => {
let style = text2.inputEl.style;
if (this.is_valid_prop_name(value)) {
style.borderColor = "";
this.plugin.settings.iconProp = value;
await this.plugin.saveSettings();
this.update_icon_prop(value);
} else {
style.borderColor = this.get_css_var("--background-modifier-error");
}
});
});
new import_obsidian.Setting(containerEl).setName("Use title in commands").setDesc("Display note's title instead of file name when displaying command results").addToggle((tg) => {
tg.setValue(this.plugin.settings.cmdShowTitle);
tg.onChange(async (value) => {
this.plugin.settings.cmdShowTitle = value;
await this.plugin.saveSettings();
});
});
new import_obsidian.Setting(containerEl).setName("Sorting").setDesc("Note sorting criteria in the tree view").addDropdown((dc) => {
for (let key of Object.keys(SortTypes)) {
dc.addOption(key, key);
}
dc.setValue(this.plugin.settings.sortTreeBy);
dc.onChange(async (value) => {
this.plugin.settings.sortTreeBy = SortTypes[value];
await this.plugin.saveSettings();
this.update_note_list();
});
});
new import_obsidian.Setting(containerEl).setName("Reverse sort order").addToggle((tg) => {
tg.setValue(this.plugin.settings.sortTreeRev);
tg.onChange(async (value) => {
this.plugin.settings.sortTreeRev = value;
await this.plugin.saveSettings();
this.update_note_list();
});
});
new import_obsidian.Setting(containerEl).setName("Hide orphans").setDesc("Do not list orphan notes (notes with no parents and no children) in the tree").addToggle((tg) => {
tg.setValue(this.plugin.settings.hideOrphans);
tg.onChange(async (value) => {
this.plugin.settings.hideOrphans = value;
await this.plugin.saveSettings();
this.update_hide_orphans(value);
this.update_note_list();
});
});
new import_obsidian.Setting(containerEl).setName("Expand/collapse on title click").setDesc("When off, clicking a note's title only opens it; expanding or collapsing its children works via the arrow icon only").addToggle((tg) => {
tg.setValue(this.plugin.settings.expandOnClick);
tg.onChange(async (value) => {
this.plugin.settings.expandOnClick = value;
await this.plugin.saveSettings();
});
});
new import_obsidian.Setting(containerEl).setName("List of ignored paths").setDesc("Each line is interpreted as the start of an ignored path").addTextArea((textArea) => {
textArea.setValue(this.plugin.settings.ignorePath).setPlaceholder("Enter one or more paths relative to the archive root").onChange(async (value) => {
this.plugin.settings.ignorePath = value;
await this.plugin.saveSettings();
this.update_filter(value);
this.update_counter();
this.update_note_list();
});
textArea.inputEl.setAttr("rows", 6);
textArea.inputEl.setAttr("cols", 40);
});
new import_obsidian.Setting(containerEl).setName("List of ignored tags").setDesc("Notes with any of these tags will be hidden from the tree. One tag per line, # is optional").addTextArea((textArea) => {
textArea.setValue(this.plugin.settings.ignoreTags).setPlaceholder("fleeting\n#daily").onChange(async (value) => {
this.plugin.settings.ignoreTags = value;
await this.plugin.saveSettings();
this.update_ignored_tags(value);
this.update_counter();
this.update_note_list();
});
textArea.inputEl.setAttr("rows", 4);
textArea.inputEl.setAttr("cols", 40);
});
new import_obsidian.Setting(containerEl).setName("List of included paths").setDesc("If set, only notes whose path starts with one of these lines are shown. Leave empty to show all paths").addTextArea((textArea) => {
textArea.setValue(this.plugin.settings.includePath).setPlaceholder("Enter one or more paths relative to the archive root").onChange(async (value) => {
this.plugin.settings.includePath = value;
await this.plugin.saveSettings();
this.update_include_paths(value);
this.update_counter();
this.update_note_list();
});
textArea.inputEl.setAttr("rows", 6);
textArea.inputEl.setAttr("cols", 40);
});
new import_obsidian.Setting(containerEl).setName("List of included tags").setDesc("If set, only notes with one of these tags are shown. Combined with included paths (a note matching either is shown). One tag per line, # is optional").addTextArea((textArea) => {
textArea.setValue(this.plugin.settings.includeTags).setPlaceholder("project\n#area").onChange(async (value) => {
this.plugin.settings.includeTags = value;
await this.plugin.saveSettings();
this.update_include_tags(value);
this.update_counter();
this.update_note_list();
});
textArea.inputEl.setAttr("rows", 4);
textArea.inputEl.setAttr("cols", 40);
});
new import_obsidian.Setting(containerEl).setName("Hidden files").addText((text2) => {
text2.setValue("0").setDisabled(true);
this.counter = text2;
});
this.update_counter();
new import_obsidian.Setting(containerEl).setName("Use [[WikiLinks]] in YAML").addToggle((tg) => {
tg.setValue(this.plugin.settings.UseWikiLinks);
tg.onChange(async (value) => {
this.plugin.settings.UseWikiLinks = value;
await this.plugin.saveSettings();
this.update_note_list();
});
});
new import_obsidian.Setting(containerEl).setName("Use string for single folder link").setDesc("Write the folder property as a string instead of a list when a note has only one parent").addToggle((tg) => {
tg.setValue(this.plugin.settings.folderAsString);
tg.onChange(async (value) => {
this.plugin.settings.folderAsString = value;
await this.plugin.saveSettings();
});
});
new import_obsidian.Setting(containerEl).setName("Confirm before deleting").setDesc("Show confirmation dialog before deleting a note").addToggle((tg) => {
tg.setValue(this.plugin.settings.confirmDelete);
tg.onChange(async (value) => {
this.plugin.settings.confirmDelete = value;
await this.plugin.saveSettings();
});
});
new import_obsidian.Setting(containerEl).setName("Auto reveal active file").setDesc("Automatically reveal the active file in the tree when opening any file").addToggle((tg) => {
tg.setValue(this.plugin.settings.autoReveal);
tg.onChange(async (value) => {
this.plugin.settings.autoReveal = value;
await this.plugin.saveSettings();
});
});
new import_obsidian.Setting(containerEl).setName("Auto collapse other folders").setDesc("When revealing the active file, collapse the branches that are not on the path to it").addToggle((tg) => {
tg.setValue(this.plugin.settings.autoCollapse);
tg.onChange(async (value) => {
this.plugin.settings.autoCollapse = value;
await this.plugin.saveSettings();
});
});
new import_obsidian.Setting(containerEl).setName("Expose frontmatter as data attributes").setDesc("Add note properties as data-* attributes on tree items for CSS styling").addToggle((tg) => {
tg.setValue(this.plugin.settings.exposeMetadata);
tg.onChange(async (value) => {
this.plugin.settings.exposeMetadata = value;
await this.plugin.saveSettings();
this.plugin.base.settings.set_expose_metadata(value);
this.update_note_list();
});
});
containerEl.createEl("h3", { text: "Tag highlights" });
new import_obsidian.Setting(containerEl).setName("Add tag highlight").setDesc("Highlight notes in the tree based on their tags").addText((text2) => {
text2.setPlaceholder("#tag");
text2.inputEl.addEventListener("keydown", async (e) => {
if (e.key !== "Enter")
return;
let value = text2.getValue().trim();
if (!value)
return;
if (!value.startsWith("#"))
value = "#" + value;
if (this.plugin.settings.tagHighlights.some((h) => h.tag === value)) {
text2.inputEl.style.borderColor = this.get_css_var("--background-modifier-error");
return;
}
this.plugin.settings.tagHighlights.push({ tag: value, color: "#7f6df2", opacity: 0.3 });
await this.plugin.saveSettings();
this.update_tag_highlights();
this.update_note_list();
this.display();
});
});
for (let i = 0; i < this.plugin.settings.tagHighlights.length; i++) {
let hl = this.plugin.settings.tagHighlights[i];
new import_obsidian.Setting(containerEl).setName(hl.tag).addColorPicker((cp) => {
cp.setValue(hl.color);
cp.onChange(async (value) => {
hl.color = value;
await this.plugin.saveSettings();
this.update_tag_highlights();
this.update_note_list();
});
}).addSlider((sl) => {
sl.setLimits(5, 100, 5);
sl.setValue(hl.opacity * 100);
sl.setDynamicTooltip();
sl.onChange(async (value) => {
hl.opacity = value / 100;
await this.plugin.saveSettings();
this.update_tag_highlights();
this.update_note_list();
});
}).addExtraButton((btn) => {
btn.setIcon("trash");
btn.setTooltip("Remove");
btn.onClick(async () => {
this.plugin.settings.tagHighlights.splice(i, 1);
await this.plugin.saveSettings();
this.update_tag_highlights();
this.update_note_list();
this.display();
});
});
}
}
update_counter() {
let count = this.plugin.base.get_filtered_count();
this.counter.setValue(count.toString());
}
update_note_list() {
this.plugin.base.rescan();
this.plugin.update_data();
}
update_filter(value) {
let filter = this.parse_text_area(value);
this.plugin.base.settings.set_filter(filter);
}
update_ignored_tags(value) {
let tags = this.parse_text_area(value).map((t) => t.startsWith("#") ? t : "#" + t);
this.plugin.base.settings.set_ignored_tags(tags);
}
update_include_paths(value) {
let paths = this.parse_text_area(value);
this.plugin.base.settings.set_include_paths(paths);
}
update_include_tags(value) {
let tags = this.parse_text_area(value).map((t) => t.startsWith("#") ? t : "#" + t);
this.plugin.base.settings.set_include_tags(tags);
}
parse_text_area(value) {
return value.split(/\r|\n/).map((n) => n.trim()).filter((n) => n);
}
is_empty_str(name) {
return name === "";
}
is_valid_prop_name(name) {
let regexp = /^[\p{L}\p{N}_.-]+$/u;
return regexp.test(name);
}
update_prop_name(name) {
if (!this.is_valid_prop_name(name))
return;
this.plugin.base.settings.set_prop(name);
this.update_note_list();
}
update_title(value) {
if (this.is_empty_str(value) || this.is_valid_prop_name(value)) {
this.plugin.base.settings.set_title(value);
this.update_note_list();
}
}
update_icon_prop(value) {
if (this.is_valid_prop_name(value)) {
this.plugin.base.settings.set_icon_prop(value);
this.update_note_list();
}
}
update_tag_highlights() {
this.plugin.base.settings.set_tag_highlights(this.plugin.settings.tagHighlights);
}
update_hide_orphans(value) {
this.plugin.base.settings.set_hide_orphans(value);
}
get_css_var(variable) {
let el = document.querySelector("body");
if (!el)
return "";
let style = window.getComputedStyle(el);
if (!style)
return "";
return style.getPropertyValue(variable);
}
};
// base_scanner.ts
function _is_string(value) {
return typeof value === "string";
}
function _frontmatter_to_string(value) {
if (value === null || value === void 0)
return null;
if (typeof value === "string")
return value;
if (typeof value === "boolean" || typeof value === "number")
return String(value);
if (Array.isArray(value))
return value.filter((v) => typeof v !== "object").map((v) => String(v)).join(",");
return null;
}
var ScanSettings = class {
constructor() {
this.filter = [];
this.ignored_tags = [];
this.include_paths = [];
this.include_tags = [];
this.title = "";
this.icon_prop = "vf_icon";
this.tag_highlights = [];
this.expose_metadata = false;
this.hide_orphans = false;
this.prop_regexp = void 0;
}
set_filter(filter) {
this.filter = filter;
}
set_ignored_tags(tags) {
this.ignored_tags = tags;
}
set_include_paths(paths) {
this.include_paths = paths;
}
set_include_tags(tags) {
this.include_tags = tags;
}
set_title(title) {
this.title = title;
}
set_icon_prop(prop) {
this.icon_prop = prop;
}
set_tag_highlights(highlights) {
this.tag_highlights = highlights;
}
set_expose_metadata(value) {
this.expose_metadata = value;
}
set_hide_orphans(value) {
this.hide_orphans = value;
}
set_prop(prop) {
let regexp_str = `^${prop}(\\.\\d+){0,1}$`;
this.prop_regexp = new RegExp(regexp_str);
}
is_valid() {
return typeof this.prop_regexp !== "undefined";
}
};
var BaseScanner = class {
constructor(app, plugin2) {
this.app = app;
this.plugin = plugin2;
this.note_list = {};
this.top_list = [];
this.orphans_list = [];
this.last_active = ["1"];
this.settings = new ScanSettings();
}
test_prop_name(prop_name) {
if (!this.settings.prop_regexp)
return false;
return this.settings.prop_regexp.test(prop_name.trim());
}
restore_utime(old_list) {
for (let id in old_list) {
if (id in this.note_list) {
let new_ut = this.note_list[id].utime;
let old_ut = old_list[id].utime;
if (old_ut > new_ut) {
this.note_list[id].utime = old_ut;
}
}
}
}
rescan() {
if (!this.settings.is_valid())
return;
let old_list = this.note_list;
this.init_note_list();
this.build_links();
this.build_top();
this.sort_links();
this.restore_utime(old_list);
}
get_filtered_count() {
return this.app.vault.getMarkdownFiles().length - this.get_filtered_list().length;
}
get_filtered_list() {
return this.app.vault.getMarkdownFiles().filter((file) => {
for (let filter of this.settings.filter) {
if (file.path.startsWith(filter))
return false;
}
if (this.settings.ignored_tags.length > 0) {
let cache = this.app.metadataCache.getFileCache(file);
if (cache) {
let tags = (0, import_obsidian2.getAllTags)(cache);
if (tags) {
for (let tag of tags) {
if (this.settings.ignored_tags.includes(tag))
return false;
}
}
}
}
if (!this._is_included(file))
return false;
return true;
});
}
_is_included(file) {
let paths = this.settings.include_paths;
let tags = this.settings.include_tags;
if (paths.length === 0 && tags.length === 0)
return true;
for (let p of paths) {
if (file.path.startsWith(p))
return true;
}
if (tags.length > 0) {
let cache = this.app.metadataCache.getFileCache(file);
if (cache) {
let file_tags = (0, import_obsidian2.getAllTags)(cache);
if (file_tags) {
for (let tag of file_tags) {
if (tags.includes(tag))
return true;
}
}
}
}
return false;
}
get_meta_value(file, prop) {
let metadata = this.app.metadataCache.getFileCache(file);
if ((metadata == null ? void 0 : metadata.frontmatter) && prop in metadata.frontmatter) {
let value = metadata.frontmatter[prop];
if (typeof value === "string")
return value;
if (Array.isArray(value) && value.length > 0) {
let first = value[0];
if (typeof first === "string")
return first;
}
return null;
}
return null;
}
// can we get it from Note class?
get_note_title(file) {
let name = file.basename;
let title = this.get_meta_value(file, this.settings.title);
return title ? title : name;
}
link_to_title(value) {
let link_file = this.app.metadataCache.getFirstLinkpathDest(value, "");
if (!link_file)
return value;
return this.get_note_title(link_file);
}
link_to_ctime(value) {
let link_file = this.app.metadataCache.getFirstLinkpathDest(value, "");
if (!link_file)
return 0;
return link_file.stat.ctime;
}
link_to_mtime(value) {
let link_file = this.app.metadataCache.getFirstLinkpathDest(value, "");
if (!link_file)
return 0;
return link_file.stat.mtime;
}
init_note_list() {
this.note_list = {};
for (let file of this.get_filtered_list()) {
let file_id = file.path;
this.note_list[file_id] = new OneNote(
file_id,
file.stat.mtime,
file.stat.ctime,
file.basename,
this.get_note_title(file)
);
}
}
_build_note_links(file) {
let file_id = file.path;
if (!(file_id in this.note_list))
return;
let metadata = this.app.metadataCache.getFileCache(file);
if (!metadata)
return;
if (metadata.frontmatterLinks) {
for (let link of metadata.frontmatterLinks) {
if (!this.test_prop_name(link.key))
continue;
let link_file = this.app.metadataCache.getFirstLinkpathDest(link.link, "");
if (!link_file)
continue;
let link_id = link_file.path;
if (link_id === file_id)
continue;
if (!(link_id in this.note_list))
continue;
this.note_list[file_id].parents.push(link_id);
this.note_list[link_id].children.push(file_id);
}
}
if (metadata.frontmatter) {
if ("vf_pinned" in metadata.frontmatter) {
let value = metadata.frontmatter["vf_pinned"];
this.note_list[file_id].is_pinned = value != "0" && value != "false" && value != false;
}
if (this.settings.icon_prop in metadata.frontmatter) {
let value = metadata.frontmatter[this.settings.icon_prop];
if (_is_string(value))
this.note_list[file_id].icon = value;
}
}
this._apply_highlight(metadata, file_id);
this._extract_metadata(metadata, file_id);
}
_apply_highlight(metadata, file_id) {
if (this.settings.tag_highlights.length === 0)
return;
let tags = (0, import_obsidian2.getAllTags)(metadata);
if (!tags)
return;
for (let hl of this.settings.tag_highlights) {
if (tags.includes(hl.tag)) {
this.note_list[file_id].highlight_color = hl.color;
this.note_list[file_id].highlight_opacity = hl.opacity;
return;
}
}
}
_extract_metadata(metadata, file_id) {
if (!this.settings.expose_metadata)
return;
if (!(metadata == null ? void 0 : metadata.frontmatter))
return;
let result = {};
for (let key of Object.keys(metadata.frontmatter)) {
if (key === "position")
continue;
let str = _frontmatter_to_string(metadata.frontmatter[key]);
if (str === null)
continue;
result[key.toLowerCase()] = str;
}
this.note_list[file_id].metadata = result;
}
build_links() {
for (let file of this.get_filtered_list()) {
this._build_note_links(file);
}
}
is_orphan(note) {
return note.is_no_parents() && note.is_no_children();
}
is_top(note) {
return note.is_no_parents() && note.has_children();
}
is_orphan_or_top(note) {
return note.is_no_parents();
}
build_top() {
this.orphans_list = [];
this.top_list = [];
for (let i in this.note_list) {
let note = this.note_list[i];
if (this.is_orphan(note)) {
this.orphans_list.push(note.id);
continue;
}
if (this.is_top(note)) {
this.top_list.push(note.id);
}
}
}
l_sort(links, parentId) {
let links_copy = [...links];
let sortBy = this.plugin.settings.sortTreeBy;
let sortRev = this.plugin.settings.sortTreeRev;
if (sortBy == "custom" /* custom */ && parentId) {
let stored = this.plugin.settings.customOrder[parentId];
if (stored) {
let linkSet = new Set(links_copy);
let ordered = stored.filter((id) => linkSet.has(id));
let orderedSet = new Set(ordered);
let remaining = links_copy.filter((id) => !orderedSet.has(id));
remaining.sort((a, b) => a.split("/").pop().localeCompare(b.split("/").pop()));
links_copy = ordered.concat(remaining);
}
} else if (sortBy == "file_name" /* file_name */ || sortBy == "custom" /* custom */ && !parentId) {
links_copy.sort((a, b) => a.split("/").pop().localeCompare(b.split("/").pop()));
} else if (sortBy == "note_title" /* note_title */) {
links_copy.sort(
(a, b) => {
a = this.link_to_title(a);
b = this.link_to_title(b);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
);
} else if (sortBy == "creation_time" /* creation_time */) {
links_copy.sort(
(a, b) => {
return this.link_to_ctime(a) - this.link_to_ctime(b);
}
);
} else if (sortBy == "modification_time" /* modification_time */) {
links_copy.sort(
(a, b) => {
return this.link_to_mtime(a) - this.link_to_mtime(b);
}
);
}
if (sortBy != "custom" /* custom */ && sortRev)
links_copy.reverse();
let pinned = links_copy.filter((id) => {
var _a;
return (_a = this.note_list[id]) == null ? void 0 : _a.is_pinned;
});
let normal = links_copy.filter((id) => {
var _a;
return !((_a = this.note_list[id]) == null ? void 0 : _a.is_pinned);
});
return pinned.concat(normal);
}
sort_links() {
for (let id in this.note_list) {
let note = this.note_list[id];
note.children = this.l_sort(note.children, id);
}
this.orphans_list = this.l_sort(this.orphans_list, "orphan_dir");
this.top_list = this.l_sort(this.top_list, "top_dir");
}
note_by_id(id) {
if (id in this.note_list) {
return this.note_list[id];
}
}
get_all_descendants(id) {
let descendants = /* @__PURE__ */ new Set();
let stack = [id];
while (stack.length > 0) {
let currentId = stack.pop();
let current = this.note_by_id(currentId);
if (!current)
continue;
for (let childId of current.children) {
if (!descendants.has(childId)) {
descendants.add(childId);
stack.push(childId);
}
}
}
return descendants;
}
is_same_mtime(file) {
let id = file.path;
let note = this.note_by_id(id);
if (!note)
return false;
return note.mtime == file.stat.mtime;
}
_count_unique(arr) {
return new Set(arr).size;
}
_is_recursion(arr) {
return this._count_unique(arr) != arr.length;
}
_build_path(note, path, path_list) {
if (this._is_recursion(path))
return;
if (this.is_orphan(note)) {
let new_path = ["orphan_dir"].concat(path);
path_list.push(new_path);
return;
}
if (this.is_top(note)) {
let new_path = ["top_dir"].concat(path);
path_list.push(new_path);
return;
}
for (let parent of note.parents) {
let sub_note = this.note_by_id(parent);
if (!sub_note)
continue;
let new_path = [sub_note.id].concat(path);
this._build_path(sub_note, new_path, path_list);
}
}
build_path_list(id) {
let note = this.note_by_id(id);
if (!note)
return void 0;
let path_list = [];
this._build_path(note, [note.id], path_list);
return path_list;
}
_get_min_path(path_list) {
let min_path = [];
let min_count = Number.MAX_SAFE_INTEGER;
for (let path of path_list) {
let len = path.length;
if (len < min_count) {
min_count = len;
min_path = path;
}
}
return min_path.slice();
}
get_shortest_path(id) {
let path_list = this.build_path_list(id);
;
if (!path_list)
return void 0;
let path = this._get_min_path(path_list);
return path;
}
_array_index(path_list, old_path) {
for (let i in path_list) {
let path = path_list[i];
if (path.join("/") == old_path.join("/")) {
return parseInt(i);
}
}
}
_next_index(path_len, old_index) {
return path_len > old_index + 1 ? old_index + 1 : 0;
}
_split_into_parents(path_list) {
let parent_list = {};
for (let path of path_list) {
let parent = path[path.length - 2];
if (!(parent in parent_list))
parent_list[parent] = [];
parent_list[parent].push(path);
}
return parent_list;
}
_get_shortest_list(path_list) {
let parent_list = this._split_into_parents(path_list);
let shortest_list = [];
for (let parent in parent_list) {
let path_parent = parent_list[parent];
shortest_list.push(this._get_min_path(path_parent));
}
return shortest_list;
}
get_next_path(id) {
let path_list = this.build_path_list(id);
if (!path_list)
return void 0;
path_list = this._get_shortest_list(path_list);
let old_index = this._array_index(path_list, this.last_active);
let path = void 0;
if (old_index === void 0) {
if (this.last_active.length >= 2) {
let lastParent = this.last_active[this.last_active.length - 2];
let sameParent = path_list.find((p) => p.length >= 2 && p[p.length - 2] === lastParent);
if (sameParent)
path = sameParent;
}
if (!path)
path = this._get_min_path(path_list);
} else {
let next_index = this._next_index(path_list.length, old_index);
path = path_list[next_index];
}
this.last_active = path.slice();
return path;
}
// --- incremental updates ---
is_filtered(file) {
for (let filter of this.settings.filter) {
if (file.path.startsWith(filter))
return true;
}
if (this.settings.ignored_tags.length > 0) {
let cache = this.app.metadataCache.getFileCache(file);
if (cache) {
let tags = (0, import_obsidian2.getAllTags)(cache);
if (tags) {
for (let tag of tags) {
if (this.settings.ignored_tags.includes(tag))
return true;
}
}
}
}
if (!this._is_included(file))
return true;
return false;
}
rebuild_top_and_sort() {
this.build_top();
this.sort_links();
}
_detach_parents(file_id) {
let note = this.note_by_id(file_id);
if (!note)
return;
for (let parent_id of note.parents) {
let parent = this.note_by_id(parent_id);
if (parent) {
parent.children = parent.children.filter((id) => id !== file_id);
}
}
note.parents = [];
note.is_pinned = false;
}
_detach_children(file_id) {
let note = this.note_by_id(file_id);
if (!note)
return;
for (let child_id of note.children) {
let child = this.note_by_id(child_id);
if (child) {
child.parents = child.parents.filter((id) => id !== file_id);
}
}
note.children = [];
}
add_note(file) {
if (this.is_filtered(file))
return;
let file_id = file.path;
this.note_list[file_id] = new OneNote(
file_id,
file.stat.mtime,
file.stat.ctime,
file.basename,
this.get_note_title(file)
);
this._build_note_links(file);
this.rebuild_top_and_sort();
}
remove_note(file_id) {
let note = this.note_by_id(file_id);
if (!note)
return;
this._detach_parents(file_id);
this._detach_children(file_id);
delete this.note_list[file_id];
this.rebuild_top_and_sort();
}
rename_note(file, oldPath) {
let old_note = this.note_by_id(oldPath);
if (!old_note) {
this.add_note(file);
return;
}
let newPath = file.path;
for (let parent_id of old_note.parents) {
let parent = this.note_by_id(parent_id);
if (parent) {
let idx = parent.children.indexOf(oldPath);
if (idx !== -1)
parent.children[idx] = newPath;
}
}
for (let child_id of old_note.children) {
let child = this.note_by_id(child_id);
if (child) {
let idx = child.parents.indexOf(oldPath);
if (idx !== -1)
child.parents[idx] = newPath;
}
}
old_note.id = newPath;
old_note.name = file.basename;
old_note.title = this.get_note_title(file);
old_note.mtime = file.stat.mtime;
delete this.note_list[oldPath];
this.note_list[newPath] = old_note;
this.rebuild_top_and_sort();
}
_read_expected_parents(file) {
let parents = [];
let metadata = this.app.metadataCache.getFileCache(file);
if (!metadata || !metadata.frontmatterLinks)
return parents;
for (let link of metadata.frontmatterLinks) {
if (!this.test_prop_name(link.key))
continue;
let link_file = this.app.metadataCache.getFirstLinkpathDest(link.link, "");
if (!link_file)
continue;
let link_id = link_file.path;
if (link_id === file.path)
continue;
if (!(link_id in this.note_list))
continue;
parents.push(link_id);
}
return parents;
}
_read_expected_pinned(file) {
let metadata = this.app.metadataCache.getFileCache(file);
if (!metadata || !metadata.frontmatter)
return false;
if (!("vf_pinned" in metadata.frontmatter))
return false;
let value = metadata.frontmatter["vf_pinned"];
return value != "0" && value != "false" && value != false;
}
_read_expected_icon(file) {
let metadata = this.app.metadataCache.getFileCache(file);
if (!metadata || !metadata.frontmatter)
return "";
if (!(this.settings.icon_prop in metadata.frontmatter))
return "";
let value = metadata.frontmatter[this.settings.icon_prop];
return _is_string(value) ? value : "";
}
_read_expected_highlight(file) {
if (this.settings.tag_highlights.length === 0)
return { color: "", opacity: 0 };
let metadata = this.app.metadataCache.getFileCache(file);
if (!metadata)
return { color: "", opacity: 0 };
let tags = (0, import_obsidian2.getAllTags)(metadata);
if (!tags)
return { color: "", opacity: 0 };
for (let hl of this.settings.tag_highlights) {
if (tags.includes(hl.tag))
return { color: hl.color, opacity: hl.opacity };
}
return { color: "", opacity: 0 };
}
_read_expected_metadata(file) {
if (!this.settings.expose_metadata)
return {};
let metadata = this.app.metadataCache.getFileCache(file);
if (!(metadata == null ? void 0 : metadata.frontmatter))
return {};
let result = {};
for (let key of Object.keys(metadata.frontmatter)) {
if (key === "position")
continue;
let str = _frontmatter_to_string(metadata.frontmatter[key]);
if (str === null)
continue;
result[key.toLowerCase()] = str;
}
return result;
}
_arrays_equal(a, b) {
if (a.length !== b.length)
return false;
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i])
return false;
}
return true;
}
_records_equal(a, b) {
let keysA = Object.keys(a);
let keysB = Object.keys(b);
if (keysA.length !== keysB.length)
return false;
for (let key of keysA) {
if (a[key] !== b[key])
return false;
}
return true;
}
update_note(file) {
let file_id = file.path;
let note = this.note_by_id(file_id);
if (!note) {
if (!this.is_filtered(file)) {
this.add_note(file);
}
return;
}
if (this.is_filtered(file)) {
this.remove_note(file_id);
return;
}
let expected_parents = this._read_expected_parents(file);
let expected_pinned = this._read_expected_pinned(file);
let expected_title = this.get_note_title(file);
let expected_icon = this._read_expected_icon(file);
let expected_highlight = this._read_expected_highlight(file);
let expected_metadata = this._read_expected_metadata(file);
if (note.mtime == file.stat.mtime && note.title == expected_title && note.is_pinned == expected_pinned && note.icon == expected_icon && note.highlight_color == expected_highlight.color && note.highlight_opacity == expected_highlight.opacity && this._arrays_equal(note.parents, expected_parents) && this._records_equal(note.metadata, expected_metadata)) {
return;
}
let old_utime = note.utime;
this._detach_parents(file_id);
note.mtime = file.stat.mtime;
note.title = expected_title;
note.is_pinned = expected_pinned;
note.icon = expected_icon;
note.highlight_color = expected_highlight.color;
note.highlight_opacity = expected_highlight.opacity;
note.metadata = expected_metadata;
for (let parent_id of expected_parents) {
note.parents.push(parent_id);
this.note_list[parent_id].children.push(file_id);
}
note.utime = old_utime;
this.rebuild_top_and_sort();
}
};
// select_file_modal.ts
var import_obsidian3 = require("obsidian");
var VF_SelectFile = class extends import_obsidian3.FuzzySuggestModal {
constructor(plugin2, onSubmit, excludeIds) {
super(plugin2.app);
this.plugin = plugin2;
this.onSubmit = onSubmit;
this.excludeIds = excludeIds;
this.selected = "";
this.setPlaceholder("Type note's title");
}
getItemName(item) {
if (this.plugin.settings.cmdShowTitle)
return item.title;
return item.name;
}
getItemText(item) {
return this.getItemName(item);
}
getItems() {
let notes = [];
for (let id in this.plugin.base.note_list) {
if (this.excludeIds && this.excludeIds.has(id))
continue;
notes.push(this.plugin.base.note_list[id]);
}
notes.sort(function(a, b) {
return b.utime - a.utime;
});
return notes;
}
onChooseItem(item, evt) {
this.onSubmit(item.id);
}
_format_parents(parents) {
let links = [];
for (let id of parents) {
let note = this.plugin.base.note_by_id(id);
if (!note)
continue;
links.push(this.getItemName(note));
}
return links;
}
renderSuggestion(item, el) {
el.createEl("div", { text: this.getItemName(item.item) });
let small = el.createEl("small", { cls: "vf_search_parents" });
for (let parent of item.item.parents) {
let path = this.plugin.base.get_shortest_path(parent);
if (!path)
continue;
let links = this._format_parents(path);
let line = small.createEl("div", { cls: "vf_search_div" });
for (let id of links) {
line.createEl("span", { text: id, cls: "vf_search_link" });
}
}
}
};
// select_prop_modal.ts
var import_obsidian4 = require("obsidian");
function get_link_base(link) {
let regexp_1 = /(?:\[\[(.+?)\||\[\[(.+?)\]\]|\[.+?\]\((.+?)\))/;
let result = null;
let match = regexp_1.exec(link);
if (match) {
if (match[1])
result = match[1];
if (match[2])
result = match[2];
if (match[3])
result = match[3];
}
return result;
}
var VF_SelectPropModal = class extends import_obsidian4.SuggestModal {
constructor(plugin2, yamlProp, onSubmit) {
super(plugin2.app);
this.plugin = plugin2;
this.yamlProp = yamlProp;
this.onSubmit = onSubmit;
this.app = plugin2.app;
this.useMarkdownLinks = this.app.vault.getConfig("useMarkdownLinks");
this.setPlaceholder("Select one to remove");
}
open() {
this.plugin.yaml.get_links(this.yamlProp, (links) => {
if (links.length == 0) {
new import_obsidian4.Notice(`${this.yamlProp} is empty`);
return;
}
if (links.length == 1) {
this.onSubmit(links[0]);
return;
}
super.open();
});
}
async getSuggestions(query) {
let notes = [];
let file = this.app.workspace.getActiveFile();
if (file) {
await this.app.fileManager.processFrontMatter(file, (fm) => {
this._get_prop_list(fm, this.yamlProp);
});
for (let item of this.prop_list) {
let name = get_link_base(item);
if (!name)
continue;
notes.push({ name, full: item });
}
}
return notes;
}
getItemName(item) {
if (!this.plugin.settings.cmdShowTitle)
return item.name;
return this.plugin.base.link_to_title(item.name);
}
renderSuggestion(item, el) {
el.createEl("div", { text: this.getItemName(item) });
}
onChooseSuggestion(item, evt) {
this.onSubmit(item.full);
}
_get_prop_list(front, prop) {
if (prop in front && front[prop]) {
this.prop_list = front[prop];
} else {
this.prop_list = [];
}
}
};
// tree_view.ts
var import_obsidian7 = require("obsidian");
// 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);
// node_modules/tslib/tslib.es6.js
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
// node_modules/svelte/src/runtime/easing/index.js
function cubicOut(t) {
const f = t - 1;
return f * f * f + 1;
}
// node_modules/svelte/src/runtime/transition/index.js
function slide(node, { delay = 0, duration = 400, easing = cubicOut, axis = "y" } = {}) {
const style = getComputedStyle(node);
const opacity = +style.opacity;
const primary_property = axis === "y" ? "height" : "width";
const primary_property_value = parseFloat(style[primary_property]);
const secondary_properties = axis === "y" ? ["top", "bottom"] : ["left", "right"];
const capitalized_secondary_properties = secondary_properties.map(
(e) => `${e[0].toUpperCase()}${e.slice(1)}`
);
const padding_start_value = parseFloat(style[`padding${capitalized_secondary_properties[0]}`]);
const padding_end_value = parseFloat(style[`padding${capitalized_secondary_properties[1]}`]);
const margin_start_value = parseFloat(style[`margin${capitalized_secondary_properties[0]}`]);
const margin_end_value = parseFloat(style[`margin${capitalized_secondary_properties[1]}`]);
const border_width_start_value = parseFloat(
style[`border${capitalized_secondary_properties[0]}Width`]
);
const border_width_end_value = parseFloat(
style[`border${capitalized_secondary_properties[1]}Width`]
);
return {
delay,
duration,
easing,
css: (t) => `overflow: hidden;opacity: ${Math.min(t * 20, 1) * opacity};${primary_property}: ${t * primary_property_value}px;padding-${secondary_properties[0]}: ${t * padding_start_value}px;padding-${secondary_properties[1]}: ${t * padding_end_value}px;margin-${secondary_properties[0]}: ${t * margin_start_value}px;margin-${secondary_properties[1]}: ${t * margin_end_value}px;border-${secondary_properties[0]}-width: ${t * border_width_start_value}px;border-${secondary_properties[1]}-width: ${t * border_width_end_value}px;`
};
}
// components/Note.svelte
var import_obsidian6 = require("obsidian");
// icon_picker_modal.ts
var import_obsidian5 = require("obsidian");
// emoji_names.ts
var EMOJI_NAMES = {
"\u{1F600}": "grinning face",
"\u{1F603}": "smiley",
"\u{1F604}": "smile",
"\u{1F601}": "grin",
"\u{1F606}": "laughing",
"\u{1F605}": "sweat smile",
"\u{1F923}": "rofl",
"\u{1F602}": "joy",
"\u{1F642}": "slightly smiling",
"\u{1F609}": "wink",
"\u{1F60A}": "blush",
"\u{1F607}": "innocent halo",
"\u{1F970}": "smiling hearts love",
"\u{1F60D}": "heart eyes",
"\u{1F929}": "star struck",
"\u{1F60E}": "sunglasses cool",
"\u{1F913}": "nerd",
"\u{1F9D0}": "monocle",
"\u{1F60F}": "smirk",
"\u{1F914}": "thinking",
"\u{1F92B}": "shushing quiet",
"\u{1F634}": "sleeping zzz",
"\u{1F92F}": "exploding head mind blown",
"\u{1F631}": "scream fear",
"\u{1F973}": "party celebrate",
"\u{1F608}": "devil",
"\u{1F47B}": "ghost",
"\u{1F480}": "skull dead",
"\u{1F916}": "robot bot",
"\u{1F47D}": "alien ufo",
"\u{1F621}": "angry rage",
"\u{1F624}": "huffing steam",
"\u{1F62D}": "crying sob",
"\u{1F622}": "sad tear",
"\u{1F633}": "flushed embarrassed",
"\u{1F97A}": "pleading puppy",
"\u{1F62C}": "grimacing awkward",
"\u{1F92E}": "vomiting sick",
"\u{1F927}": "sneezing",
"\u{1F976}": "cold freezing",
"\u{1F975}": "hot sweating",
"\u{1F636}": "no mouth silent",
"\u{1F610}": "neutral",
"\u{1F611}": "expressionless",
"\u{1FAE0}": "melting",
"\u{1F911}": "money mouth rich",
"\u{1F917}": "hugging",
"\u{1F92D}": "giggling hand over mouth",
"\u{1FAE1}": "salute",
"\u{1FAE3}": "peeking",
"\u{1FAE2}": "open eyes hand over mouth",
"\u{1F62E}": "open mouth surprised",
"\u{1F62F}": "hushed",
"\u{1F632}": "astonished",
"\u{1F635}": "dizzy face",
"\u{1F974}": "woozy drunk",
"\u{1F637}": "mask medical",
"\u{1F912}": "thermometer sick",
"\u{1F915}": "bandage hurt",
"\u{1F910}": "zipper mouth secret",
"\u{1F636}\u200D\u{1F32B}\uFE0F": "face in clouds",
"\u{1FAE5}": "dotted line invisible",
"\u{1F925}": "lying pinocchio",
"\u{1F44D}": "thumbs up like",
"\u{1F44E}": "thumbs down dislike",
"\u{1F44B}": "wave hello",
"\u270B": "raised hand stop",
"\u{1F44F}": "clap applause",
"\u{1F91D}": "handshake deal",
"\u270C\uFE0F": "peace victory",
"\u{1F91E}": "crossed fingers luck",
"\u{1F4AA}": "muscle strong",
"\u270D\uFE0F": "writing hand",
"\u{1F64F}": "pray please thanks",
"\u{1F90C}": "pinched fingers italian",
"\u{1F90F}": "pinching small",
"\u{1F919}": "call me hang loose",
"\u{1F596}": "vulcan spock",
"\u{1FAF6}": "heart hands",
"\u{1F91F}": "love you gesture",
"\u{1F918}": "rock on horns",
"\u{1F44C}": "ok perfect",
"\u{1FAF0}": "hand with index finger and thumb crossed",
"\u2764\uFE0F": "red heart love",
"\u{1F9E1}": "orange heart",
"\u{1F49B}": "yellow heart",
"\u{1F49A}": "green heart",
"\u{1F499}": "blue heart",
"\u{1F49C}": "purple heart",
"\u{1F5A4}": "black heart",
"\u{1F90D}": "white heart",
"\u{1F494}": "broken heart",
"\u2764\uFE0F\u200D\u{1F525}": "heart on fire",
"\u2764\uFE0F\u200D\u{1FA79}": "mending heart",
"\u{1F4AF}": "hundred perfect score",
"\u{1F4A5}": "collision boom bang",
"\u{1F4AB}": "dizzy star",
"\u{1F4AC}": "speech bubble comment",
"\u{1F4AD}": "thought bubble think",
"\u{1F464}": "person silhouette user",
"\u{1F465}": "people group users",
"\u{1F476}": "baby child",
"\u{1F466}": "boy",
"\u{1F467}": "girl",
"\u{1F468}": "man",
"\u{1F469}": "woman",
"\u{1F474}": "old man elder",
"\u{1F475}": "old woman elder",
"\u{1F9D2}": "child",
"\u{1F9D3}": "older person",
"\u{1F9D4}": "bearded person",
"\u{1F9D1}\u200D\u{1F4BB}": "technologist programmer developer",
"\u{1F9D1}\u200D\u{1F393}": "student graduate",
"\u{1F9D1}\u200D\u{1F3EB}": "teacher professor",
"\u{1F9D1}\u200D\u{1F52C}": "scientist researcher",
"\u{1F9D1}\u200D\u{1F3A8}": "artist painter",
"\u{1F9D1}\u200D\u{1F680}": "astronaut space",
"\u{1F9D1}\u200D\u2695\uFE0F": "doctor health",
"\u{1F9D1}\u200D\u{1F373}": "cook chef",
"\u{1F9D1}\u200D\u{1F527}": "mechanic",
"\u{1F9D1}\u200D\u{1F3ED}": "factory worker",
"\u{1F9D1}\u200D\u{1F4BC}": "office worker",
"\u{1F9D1}\u200D\u{1F692}": "firefighter",
"\u{1F436}": "dog puppy",
"\u{1F431}": "cat kitten",
"\u{1F42D}": "mouse rat",
"\u{1F439}": "hamster",
"\u{1F430}": "rabbit bunny",
"\u{1F98A}": "fox",
"\u{1F43B}": "bear",
"\u{1F43C}": "panda",
"\u{1F428}": "koala",
"\u{1F981}": "lion king",
"\u{1F42F}": "tiger",
"\u{1F42E}": "cow",
"\u{1F437}": "pig",
"\u{1F438}": "frog",
"\u{1F435}": "monkey",
"\u{1F414}": "chicken",
"\u{1F427}": "penguin",
"\u{1F426}": "bird",
"\u{1F985}": "eagle",
"\u{1F989}": "owl wisdom",
"\u{1F98B}": "butterfly",
"\u{1F41B}": "bug insect",
"\u{1F41D}": "bee honeybee",
"\u{1F41E}": "ladybug",
"\u{1F422}": "turtle tortoise",
"\u{1F40D}": "snake",
"\u{1F98E}": "lizard",
"\u{1F419}": "octopus",
"\u{1F988}": "shark",
"\u{1F433}": "whale ocean",
"\u{1F42C}": "dolphin",
"\u{1F984}": "unicorn magic",
"\u{1F432}": "dragon",
"\u{1F434}": "horse",
"\u{1F43A}": "wolf",
"\u{1F417}": "boar",
"\u{1F43B}\u200D\u2744\uFE0F": "polar bear",
"\u{1F99D}": "raccoon",
"\u{1F9AB}": "beaver",
"\u{1F9A6}": "otter",
"\u{1F9A5}": "sloth",
"\u{1F9A8}": "skunk",
"\u{1F998}": "kangaroo",
"\u{1F9A1}": "badger",
"\u{1F43E}": "paw prints",
"\u{1F983}": "turkey",
"\u{1F413}": "rooster",
"\u{1F986}": "duck",
"\u{1F9A2}": "swan",
"\u{1F99C}": "parrot",
"\u{1FAB6}": "feather",
"\u{1F9A9}": "flamingo",
"\u{1F99A}": "peacock",
"\u{1F40A}": "crocodile",
"\u{1F409}": "dragon face",
"\u{1F995}": "sauropod dinosaur",
"\u{1F996}": "trex dinosaur",
"\u{1F40B}": "whale",
"\u{1F9AD}": "seal",
"\u{1F41F}": "fish",
"\u{1F420}": "tropical fish",
"\u{1F421}": "blowfish",
"\u{1F990}": "shrimp",
"\u{1F99E}": "lobster",
"\u{1F980}": "crab",
"\u{1F991}": "squid",
"\u{1F40C}": "snail",
"\u{1F997}": "cricket",
"\u{1FAB2}": "beetle",
"\u{1FAB3}": "cockroach",
"\u{1F577}\uFE0F": "spider",
"\u{1F578}\uFE0F": "spider web",
"\u{1F99F}": "mosquito",
"\u{1FAB0}": "fly",
"\u{1FAB1}": "worm",
"\u{1F9A0}": "microbe bacteria virus",
"\u{1F338}": "cherry blossom flower",
"\u{1F339}": "rose flower",
"\u{1F33B}": "sunflower",
"\u{1F33A}": "hibiscus flower",
"\u{1F337}": "tulip flower",
"\u{1F331}": "seedling sprout grow",
"\u{1F332}": "evergreen tree pine",
"\u{1F333}": "deciduous tree",
"\u{1F340}": "four leaf clover luck",
"\u{1F341}": "maple leaf autumn",
"\u{1F342}": "fallen leaf autumn",
"\u{1F33F}": "herb leaf green",
"\u{1F335}": "cactus desert",
"\u{1F344}": "mushroom",
"\u{1FAB4}": "potted plant",
"\u{1F33E}": "rice sheaf",
"\u{1FABB}": "hyacinth",
"\u{1FAB7}": "lotus",
"\u{1F34E}": "apple red fruit",
"\u{1F34A}": "orange tangerine fruit",
"\u{1F34B}": "lemon citrus",
"\u{1F347}": "grapes fruit",
"\u{1F353}": "strawberry fruit",
"\u{1F352}": "cherry fruit",
"\u{1F351}": "peach fruit",
"\u{1F34C}": "banana fruit",
"\u{1F349}": "watermelon fruit",
"\u{1F355}": "pizza food",
"\u{1F354}": "hamburger burger food",
"\u{1F35F}": "fries food",
"\u{1F32E}": "taco food",
"\u{1F370}": "cake dessert birthday",
"\u{1F369}": "donut doughnut dessert",
"\u{1F36A}": "cookie dessert",
"\u{1F36B}": "chocolate bar candy",
"\u{1F951}": "avocado",
"\u{1F955}": "carrot",
"\u{1F33D}": "corn",
"\u{1F966}": "broccoli",
"\u{1F9C4}": "garlic",
"\u{1F9C5}": "onion",
"\u{1F952}": "cucumber",
"\u{1FAD1}": "bell pepper",
"\u{1F950}": "croissant",
"\u{1F956}": "baguette bread",
"\u{1F968}": "pretzel",
"\u{1F9C0}": "cheese",
"\u{1F969}": "meat steak",
"\u{1F357}": "poultry chicken leg",
"\u{1F32D}": "hot dog",
"\u{1F96A}": "sandwich",
"\u{1F363}": "sushi",
"\u{1F35C}": "ramen noodles",
"\u{1F35D}": "pasta spaghetti",
"\u{1F35B}": "curry rice",
"\u{1F372}": "pot stew",
"\u{1F957}": "salad green",
"\u{1F37F}": "popcorn",
"\u{1F9C1}": "cupcake",
"\u{1F366}": "ice cream",
"\u{1F367}": "shaved ice",
"\u{1F368}": "ice cream sundae",
"\u{1F382}": "birthday cake",
"\u{1F36E}": "custard pudding",
"\u{1F36F}": "honey pot",
"\u2615": "coffee hot beverage",
"\u{1F375}": "tea green",
"\u{1F37A}": "beer mug drink",
"\u{1F377}": "wine glass drink",
"\u{1F964}": "cup straw beverage drink",
"\u{1F376}": "sake",
"\u{1F37E}": "champagne bottle",
"\u{1F942}": "clinking glasses cheers",
"\u{1F943}": "tumbler whiskey",
"\u{1FAD7}": "pouring liquid",
"\u{1F9CB}": "bubble tea boba",
"\u{1F9C3}": "juice box",
"\u{1F9CA}": "ice cube",
"\u{1F3E0}": "house home",
"\u{1F3E1}": "house garden home",
"\u{1F3E2}": "office building",
"\u{1F3EB}": "school building",
"\u{1F3E5}": "hospital building",
"\u{1F3F0}": "castle",
"\u{1F5FC}": "tower",
"\u{1F5FD}": "statue liberty",
"\u26EA": "church religion",
"\u{1F54C}": "mosque religion",
"\u26E9\uFE0F": "shinto shrine torii",
"\u{1F30D}": "earth globe world europe africa",
"\u{1F30E}": "earth globe world americas",
"\u{1F30F}": "earth globe world asia",
"\u{1F5FA}\uFE0F": "world map",
"\u{1F3D4}\uFE0F": "mountain snow",
"\u26F0\uFE0F": "mountain",
"\u{1F30B}": "volcano",
"\u{1F3DD}\uFE0F": "desert island",
"\u{1F3D6}\uFE0F": "beach umbrella",
"\u{1F697}": "car automobile",
"\u{1F695}": "taxi cab",
"\u{1F68C}": "bus",
"\u{1F680}": "rocket launch space",
"\u2708\uFE0F": "airplane plane flight travel",
"\u{1F681}": "helicopter",
"\u{1F6A2}": "ship boat",
"\u{1F682}": "train locomotive",
"\u{1F6B2}": "bicycle bike",
"\u26F5": "sailboat",
"\u{1F6F8}": "flying saucer ufo",
"\u{1F683}": "railway car",
"\u{1F684}": "high speed train",
"\u{1F685}": "bullet train",
"\u{1F686}": "train",
"\u{1F687}": "metro subway",
"\u{1F688}": "light rail",
"\u{1F689}": "station",
"\u{1F68A}": "tram",
"\u{1F69D}": "monorail",
"\u{1F69E}": "mountain railway",
"\u{1F68B}": "tram car",
"\u{1F68D}": "bus front",
"\u{1F68E}": "trolleybus",
"\u{1F690}": "minibus",
"\u{1F691}": "ambulance",
"\u{1F692}": "fire engine",
"\u{1F693}": "police car",
"\u{1F694}": "police car oncoming",
"\u{1F696}": "taxi oncoming",
"\u{1F698}": "automobile oncoming",
"\u{1F699}": "suv sport utility",
"\u{1F6FB}": "pickup truck",
"\u{1F69A}": "delivery truck",
"\u{1F69B}": "articulated lorry",
"\u{1F69C}": "tractor farm",
"\u{1F6F5}": "motor scooter",
"\u{1F3CD}\uFE0F": "motorcycle racing",
"\u{1F6FA}": "auto rickshaw",
"\u{1F6A0}": "mountain cableway",
"\u{1F6A1}": "aerial tramway",
"\u{1F6F6}": "canoe kayak",
"\u{1F6A4}": "speedboat",
"\u{1F6F3}\uFE0F": "passenger ship cruise",
"\u26F4\uFE0F": "ferry",
"\u{1F6E5}\uFE0F": "motor boat",
"\u{1F6E9}\uFE0F": "small airplane",
"\u{1FA82}": "parachute",
"\u{1F4BA}": "seat",
"\u{1F6F0}\uFE0F": "satellite",
"\u231A": "watch time clock",
"\u{1F4F1}": "phone mobile smartphone",
"\u{1F4BB}": "laptop computer",
"\u{1F5A5}\uFE0F": "desktop computer monitor",
"\u2328\uFE0F": "keyboard typing",
"\u{1F5B1}\uFE0F": "mouse computer",
"\u{1F5A8}\uFE0F": "printer",
"\u{1F4BE}": "floppy disk save",
"\u{1F4BF}": "cd optical disk",
"\u{1F4C0}": "dvd disk",
"\u{1F3AE}": "gamepad controller game",
"\u{1F579}\uFE0F": "joystick game",
"\u{1F50B}": "battery power",
"\u{1F4A1}": "light bulb idea",
"\u{1F526}": "flashlight torch",
"\u{1F4F7}": "camera photo",
"\u{1F3A5}": "movie camera video film",
"\u{1F4F9}": "video camera",
"\u{1F50D}": "magnifying glass search left",
"\u{1F50E}": "magnifying glass search right",
"\u{1F52C}": "microscope science research",
"\u{1F52D}": "telescope astronomy",
"\u{1F4E1}": "satellite antenna",
"\u{1F511}": "key password",
"\u{1F5DD}\uFE0F": "old key vintage",
"\u{1F512}": "lock locked security",
"\u{1F513}": "unlock unlocked open",
"\u{1F527}": "wrench tool fix",
"\u{1F528}": "hammer tool build",
"\u2699\uFE0F": "gear settings cog",
"\u{1F9F2}": "magnet",
"\u26A1": "lightning bolt zap electricity",
"\u{1F9EA}": "test tube experiment",
"\u{1F48A}": "pill medicine",
"\u{1FA7A}": "stethoscope medical doctor",
"\u{1F9EC}": "dna genetics",
"\u{1FA9B}": "screwdriver",
"\u{1FA9A}": "saw carpentry",
"\u{1FA9D}": "hook",
"\u{1F9F0}": "toolbox",
"\u{1FAA4}": "mousetrap",
"\u2697\uFE0F": "alembic chemistry",
"\u{1FA7B}": "x-ray",
"\u{1FA78}": "drop of blood",
"\u{1F4DD}": "memo note write pencil",
"\u{1F4CB}": "clipboard",
"\u{1F4CC}": "pushpin pin",
"\u{1F4CE}": "paperclip attach",
"\u270F\uFE0F": "pencil write edit",
"\u{1F58A}\uFE0F": "pen write",
"\u{1F58B}\uFE0F": "fountain pen write",
"\u{1F4D0}": "triangular ruler",
"\u{1F4CF}": "straight ruler",
"\u{1F4D5}": "book red closed",
"\u{1F4D7}": "book green",
"\u{1F4D8}": "book blue",
"\u{1F4D9}": "book orange",
"\u{1F4DA}": "books stack library",
"\u{1F4D6}": "open book read",
"\u{1F4D3}": "notebook",
"\u{1F4D2}": "ledger notebook",
"\u{1F4C4}": "page document file",
"\u{1F4C3}": "page curl document",
"\u{1F4D1}": "bookmark tabs",
"\u{1F5C2}\uFE0F": "card index dividers files",
"\u{1F4C1}": "folder file",
"\u{1F4C2}": "open folder file",
"\u{1F5C3}\uFE0F": "card file box archive",
"\u{1F5C4}\uFE0F": "file cabinet storage",
"\u{1F5D1}\uFE0F": "wastebasket trash delete",
"\u{1F4CA}": "bar chart graph statistics",
"\u{1F4C8}": "chart increasing up trend",
"\u{1F4C9}": "chart decreasing down trend",
"\u{1F4C6}": "calendar date",
"\u{1F4C5}": "calendar",
"\u{1F5D3}\uFE0F": "calendar spiral date",
"\u{1F4EC}": "mailbox mail",
"\u{1F4E7}": "email e-mail",
"\u{1F4E9}": "envelope arrow email incoming",
"\u{1F4E4}": "outbox tray upload",
"\u{1F4E5}": "inbox tray download",
"\u{1F4E6}": "package box",
"\u{1F4EA}": "mailbox closed",
"\u{1F4EB}": "mailbox raised flag",
"\u{1F4EE}": "postbox",
"\u{1F3F7}\uFE0F": "label tag price",
"\u2B50": "star favorite",
"\u{1F31F}": "glowing star shine",
"\u2728": "sparkles shine magic",
"\u{1F525}": "fire hot flame trending",
"\u{1F4A7}": "water droplet",
"\u{1F30A}": "wave ocean water",
"\u2600\uFE0F": "sun sunny bright",
"\u{1F319}": "moon crescent night",
"\u{1F308}": "rainbow",
"\u2601\uFE0F": "cloud",
"\u2744\uFE0F": "snowflake cold winter",
"\u{1F32A}\uFE0F": "tornado",
"\u{1F324}\uFE0F": "sun behind small cloud",
"\u26C8\uFE0F": "thunder cloud rain",
"\u{1F327}\uFE0F": "cloud rain",
"\u{1F328}\uFE0F": "cloud snow",
"\u2614": "umbrella rain",
"\u{1F3AF}": "target bullseye goal",
"\u{1F3C6}": "trophy award winner cup",
"\u{1F947}": "gold medal first",
"\u{1F948}": "silver medal second",
"\u{1F949}": "bronze medal third",
"\u{1F3C5}": "medal sports",
"\u{1F3AA}": "circus tent",
"\u{1F3A8}": "palette art paint color",
"\u{1F3AD}": "performing arts theater masks",
"\u{1F3AC}": "clapper board movie film",
"\u{1F3A4}": "microphone karaoke",
"\u{1F3A7}": "headphones music audio",
"\u{1F3B5}": "music note",
"\u{1F3B6}": "music notes",
"\u{1F3B9}": "piano musical keyboard",
"\u{1F3B8}": "guitar music",
"\u{1F3BA}": "trumpet music",
"\u{1F941}": "drum music",
"\u{1F3BB}": "violin",
"\u{1FA97}": "accordion",
"\u{1F3B7}": "saxophone",
"\u{1F3B2}": "dice game random",
"\u265F\uFE0F": "chess pawn strategy",
"\u{1F9E9}": "puzzle piece jigsaw",
"\u{1F381}": "gift present wrapped",
"\u{1F380}": "ribbon bow",
"\u{1F388}": "balloon party",
"\u{1F389}": "party popper celebrate tada",
"\u{1F38A}": "confetti ball celebrate",
"\u{1F397}\uFE0F": "reminder ribbon awareness",
"\u26BD": "soccer football",
"\u{1F3C0}": "basketball",
"\u{1F3C8}": "american football",
"\u26BE": "baseball",
"\u{1F3BE}": "tennis",
"\u{1F3D0}": "volleyball",
"\u{1F3C9}": "rugby",
"\u{1F3B1}": "billiards pool",
"\u{1F3D3}": "table tennis ping pong",
"\u{1F3F8}": "badminton",
"\u{1F94A}": "boxing glove",
"\u{1F94B}": "martial arts",
"\u{1F3CB}\uFE0F": "weight lifting",
"\u{1F938}": "cartwheeling gymnastics",
"\u26F7\uFE0F": "skier",
"\u{1F3C2}": "snowboarder",
"\u{1F3C4}": "surfer",
"\u{1F6A3}": "rowing",
"\u{1F3CA}": "swimming",
"\u{1F9D7}": "climbing",
"\u{1F6B4}": "cycling bicyclist",
"\u{1F9D8}": "yoga meditation",
"\u{1F3A3}": "fishing",
"\u{1FA81}": "kite",
"\u2705": "check mark done complete",
"\u274C": "cross mark error wrong",
"\u26A0\uFE0F": "warning alert caution",
"\u{1F6AB}": "prohibited forbidden no",
"\u2753": "question mark",
"\u2757": "exclamation mark important",
"\u203C\uFE0F": "double exclamation",
"\u2049\uFE0F": "exclamation question",
"\u{1F534}": "red circle dot",
"\u{1F7E0}": "orange circle dot",
"\u{1F7E1}": "yellow circle dot",
"\u{1F7E2}": "green circle dot",
"\u{1F535}": "blue circle dot",
"\u{1F7E3}": "purple circle dot",
"\u26AB": "black circle dot",
"\u26AA": "white circle dot",
"\u{1F7E4}": "brown circle dot",
"\u{1F7E5}": "red square",
"\u{1F7E7}": "orange square",
"\u{1F7E8}": "yellow square",
"\u{1F7E9}": "green square",
"\u{1F7E6}": "blue square",
"\u{1F7EA}": "purple square",
"\u2B1B": "black large square",
"\u2B1C": "white large square",
"\u{1F7EB}": "brown square",
"\u2B06\uFE0F": "arrow up",
"\u2B07\uFE0F": "arrow down",
"\u2B05\uFE0F": "arrow left",
"\u27A1\uFE0F": "arrow right",
"\u21A9\uFE0F": "arrow return back",
"\u{1F504}": "arrows counterclockwise refresh",
"\u{1F500}": "shuffle twisted arrows",
"\u{1F501}": "repeat loop",
"\u25B6\uFE0F": "play button",
"\u23F8\uFE0F": "pause button",
"\u23F9\uFE0F": "stop button",
"\u23E9": "fast forward",
"\u23EA": "rewind",
"\u{1F3F3}\uFE0F": "white flag surrender",
"\u{1F3F4}": "black flag",
"\u{1F6A9}": "triangular flag red",
"\u{1F3C1}": "checkered flag race finish",
"\u267B\uFE0F": "recycling recycle",
"\u{1F517}": "link chain",
"\u{1F4E2}": "loudspeaker announce",
"\u{1F514}": "bell notification",
"\u{1F515}": "bell slash no notification mute",
"\u{1F6E1}\uFE0F": "shield protect security",
"\u2694\uFE0F": "crossed swords fight",
"\u{1F3F9}": "bow arrow archery",
"\u{1F48E}": "gem diamond jewel",
"\u{1F451}": "crown king queen royal",
"\u{1F393}": "graduation cap education",
"\u{1F9E0}": "brain mind think intelligence",
"\u{1F441}\uFE0F": "eye see look vision",
"\u{1F440}": "eyes see look",
"\u{1FAC0}": "anatomical heart organ",
"\u{1F9B7}": "tooth dental",
"\u{1F9B4}": "bone skeleton",
"\u{1F48D}": "ring wedding diamond",
"\u{1F453}": "glasses eyeglasses",
"\u{1F576}\uFE0F": "sunglasses dark",
"\u{1F9F3}": "luggage suitcase travel",
"\u{1F392}": "backpack school bag",
"\u{1F6D2}": "shopping cart",
"\u23F0": "alarm clock time",
"\u23F3": "hourglass time sand",
"\u{1F9ED}": "compass navigation direction",
"\u{1F4CD}": "pin location map",
"\u{1F510}": "locked key secure",
"\u{1F56F}\uFE0F": "candle light",
"\u{1F4B0}": "money bag",
"\u{1F4B5}": "dollar banknote",
"\u{1F4B3}": "credit card",
"\u{1F9FE}": "receipt",
"\u{1F4B8}": "money with wings flying",
"\u{1FA99}": "coin",
"\u{1F3B0}": "slot machine jackpot",
"\u{1FA84}": "magic wand",
"\u{1F52E}": "crystal ball fortune",
"\u{1F9FF}": "nazar amulet evil eye",
"\u{1FAAC}": "hamsa",
"\u267E\uFE0F": "infinity",
"\u{1F3B4}": "flower playing cards",
"\u{1F004}": "mahjong",
"\u{1F0CF}": "joker card",
"\u{1F6C1}": "bathtub",
"\u{1F6BF}": "shower",
"\u{1FAA5}": "toothbrush",
"\u{1F9F4}": "lotion bottle",
"\u{1F9F7}": "safety pin",
"\u{1F9F9}": "broom",
"\u{1FAA3}": "bucket",
"\u{1F9FA}": "basket",
"\u{1F9FB}": "toilet paper roll",
"\u{1F6BD}": "toilet",
"\u{1FA9E}": "mirror",
"\u{1FA9F}": "window",
"\u{1F6CF}\uFE0F": "bed",
"\u{1F6CB}\uFE0F": "couch lamp",
"\u{1FA91}": "chair",
"\u{1F6AA}": "door",
"\u{1F9EF}": "fire extinguisher",
"\u{1F488}": "barber pole",
"\u{1F3FA}": "amphora vase",
// Additional smileys and faces
"\u{1F972}": "smiling tear happy sad",
"\u{1FAE4}": "face diagonal mouth",
"\u{1FAE8}": "shaking face",
"\u{1FAE9}": "face with bags under eyes tired",
"\u{1F60B}": "yum delicious savoring",
"\u{1F61C}": "winking tongue playful",
"\u{1F92A}": "zany crazy",
"\u{1F61D}": "squinting tongue",
"\u{1F61B}": "tongue out",
"\u{1F978}": "disguised face",
"\u{1F612}": "unamused",
"\u{1F61E}": "disappointed sad",
"\u{1F614}": "pensive sad",
"\u{1F61F}": "worried",
"\u{1F615}": "confused",
"\u{1F641}": "slightly frowning",
"\u{1F623}": "persevering",
"\u{1F616}": "confounded",
"\u{1F62B}": "tired weary",
"\u{1F629}": "weary exhausted",
"\u{1F971}": "yawning bored",
"\u{1F92C}": "cursing swearing angry",
"\u{1F620}": "angry",
"\u{1FAE7}": "bubbles soap",
"\u{1F4A8}": "dashing away wind fast",
"\u{1F4A6}": "sweat droplets splashing",
"\u{1F4A4}": "zzz sleeping",
"\u{1F573}\uFE0F": "hole",
"\u{1F4A3}": "bomb explosive",
"\u{1F5E8}\uFE0F": "left speech bubble",
"\u{1F5EF}\uFE0F": "right anger bubble",
"\u{1F4A2}": "anger symbol",
// More hand gestures
"\u{1F590}\uFE0F": "hand with fingers splayed",
"\u{1F91A}": "raised back of hand",
"\u{1F44A}": "fist bump punch",
"\u270A": "raised fist power",
"\u{1FAF3}": "palm down hand",
"\u{1FAF4}": "palm up hand",
"\u{1FAF2}": "leftwards hand",
"\u{1FAF1}": "rightwards hand",
"\u{1F448}": "pointing left",
"\u{1F449}": "pointing right",
"\u{1F446}": "pointing up",
"\u{1F447}": "pointing down",
"\u261D\uFE0F": "index pointing up",
"\u{1F595}": "middle finger",
"\u{1FAF5}": "index pointing at viewer",
"\u{1F932}": "palms up together",
"\u{1F64C}": "raising hands hooray",
"\u{1F933}": "selfie",
// Body and people
"\u{1F9B6}": "foot",
"\u{1F9B5}": "leg",
"\u{1FAC1}": "lungs breathing",
"\u{1F9BB}": "ear hearing",
"\u{1F442}": "ear",
"\u{1F443}": "nose smell",
"\u{1F9BF}": "mechanical leg prosthetic",
"\u{1F9BE}": "mechanical arm prosthetic",
"\u{1F485}": "nail polish",
"\u{1F937}": "shrug",
"\u{1F926}": "facepalm",
"\u{1F646}": "ok gesture person",
"\u{1F645}": "no good person",
"\u{1F487}": "haircut",
"\u{1F486}": "massage",
"\u{1F9D6}": "person in steamy room sauna",
"\u{1F6C0}": "person taking bath",
"\u{1F9D1}\u200D\u{1F9AF}": "person with white cane blind",
"\u{1F9D1}\u200D\u{1F9BC}": "person in motorized wheelchair",
"\u{1F9D1}\u200D\u{1F9BD}": "person in manual wheelchair",
"\u{1F9D9}": "mage wizard",
"\u{1F9DA}": "fairy",
"\u{1F9DB}": "vampire",
"\u{1F9DC}": "merperson",
"\u{1F9DD}": "elf",
"\u{1F9DE}": "genie",
"\u{1F9DF}": "zombie",
"\u{1F9D1}\u200D\u{1F91D}\u200D\u{1F9D1}": "people holding hands",
"\u{1F46B}": "man woman holding hands couple",
"\u{1F46C}": "men holding hands",
"\u{1F46D}": "women holding hands",
"\u{1F48F}": "kiss couple",
"\u{1F491}": "couple with heart love",
"\u{1F46A}": "family",
"\u{1F9D1}\u200D\u{1F9D1}\u200D\u{1F9D2}": "family parents child",
"\u{1FAC2}": "people hugging embrace",
// More animals
"\u{1F400}": "rat",
"\u{1F401}": "mouse small",
"\u{1F402}": "ox",
"\u{1F403}": "water buffalo",
"\u{1F404}": "cow dairy",
"\u{1F405}": "tiger full",
"\u{1F406}": "leopard",
"\u{1F407}": "rabbit full",
"\u{1F408}": "cat full",
"\u{1F408}\u200D\u2B1B": "black cat",
"\u{1F429}": "poodle dog",
"\u{1F9AE}": "guide dog",
"\u{1F415}\u200D\u{1F9BA}": "service dog",
"\u{1F415}": "dog full",
"\u{1F40E}": "horse racing",
"\u{1FACE}": "moose elk",
"\u{1FACF}": "donkey",
"\u{1F98C}": "deer",
"\u{1F9AC}": "bison buffalo",
"\u{1F9A3}": "mammoth woolly",
"\u{1F98F}": "rhinoceros",
"\u{1F99B}": "hippopotamus hippo",
"\u{1F42A}": "camel one hump",
"\u{1F42B}": "two hump camel",
"\u{1F992}": "giraffe",
"\u{1F418}": "elephant",
"\u{1F40F}": "ram sheep",
"\u{1F411}": "ewe sheep",
"\u{1F410}": "goat",
"\u{1F999}": "llama alpaca",
"\u{1F994}": "hedgehog",
"\u{1F43F}\uFE0F": "chipmunk",
"\u{1F426}\u200D\u2B1B": "black bird crow raven",
"\u{1F9A4}": "dodo extinct",
"\u{1FABF}": "goose",
"\u{1F9A7}": "orangutan",
"\u{1F412}": "monkey full",
"\u{1F98D}": "gorilla ape",
"\u{1F416}": "pig full",
"\u{1FAB8}": "coral reef",
"\u{1FABC}": "jellyfish",
"\u{1F41A}": "shell seashell",
"\u{1F41C}": "ant",
"\u{1F982}": "scorpion",
// More plants and nature
"\u{1F33C}": "blossom flower",
"\u{1F490}": "bouquet flowers",
"\u{1F330}": "chestnut nut",
"\u{1FAD8}": "beans",
"\u{1FAB9}": "empty nest",
"\u{1FABA}": "nest with eggs",
"\u{1F311}": "new moon dark",
"\u{1F312}": "waxing crescent moon",
"\u{1F313}": "first quarter moon",
"\u{1F314}": "waxing gibbous moon",
"\u{1F315}": "full moon",
"\u{1F316}": "waning gibbous moon",
"\u{1F317}": "last quarter moon",
"\u{1F318}": "waning crescent moon",
"\u{1F31A}": "new moon face",
"\u{1F31B}": "first quarter moon face",
"\u{1F31C}": "last quarter moon face",
"\u{1F31D}": "full moon face",
"\u{1F31E}": "sun with face",
"\u{1FA90}": "ringed planet saturn",
"\u{1F320}": "shooting star",
"\u{1F30C}": "milky way galaxy night sky",
"\u{1F32B}\uFE0F": "fog",
"\u{1F32C}\uFE0F": "wind face blowing",
"\u{1F300}": "cyclone hurricane typhoon spiral",
"\u{1F301}": "foggy",
// More food and drink
"\u{1F360}": "sweet potato roasted",
"\u{1F954}": "potato",
"\u{1F95A}": "egg",
"\u{1F373}": "cooking egg fried",
"\u{1F953}": "bacon",
"\u{1F95E}": "pancakes",
"\u{1F9C7}": "waffle",
"\u{1F96F}": "bagel",
"\u{1FAD3}": "flatbread",
"\u{1FAD4}": "tamale",
"\u{1F959}": "stuffed flatbread pita",
"\u{1F9C6}": "falafel",
"\u{1F958}": "shallow pan paella",
"\u{1FAD5}": "fondue",
"\u{1F96B}": "canned food",
"\u{1F371}": "bento box japanese lunch",
"\u{1F358}": "rice cracker",
"\u{1F359}": "rice ball onigiri",
"\u{1F35A}": "cooked rice",
"\u{1F362}": "oden skewer",
"\u{1F361}": "dango",
"\u{1F95F}": "dumpling",
"\u{1F960}": "fortune cookie",
"\u{1F961}": "takeout box",
"\u{1F967}": "pie",
"\u{1F36C}": "candy sweet",
"\u{1F36D}": "lollipop candy",
"\u{1FAD6}": "teapot",
"\u{1F37C}": "baby bottle milk",
"\u{1F95B}": "glass of milk",
"\u{1FAD9}": "jar container",
"\u{1F37D}\uFE0F": "plate cutlery fork knife",
"\u{1F962}": "chopsticks",
"\u{1F944}": "spoon",
"\u{1F52A}": "kitchen knife hocho",
// More buildings and places
"\u{1F3D7}\uFE0F": "construction building crane",
"\u{1F3D8}\uFE0F": "houses neighborhood",
"\u{1F3DA}\uFE0F": "derelict house abandoned",
"\u{1F3DB}\uFE0F": "classical building columns",
"\u{1F3D9}\uFE0F": "cityscape skyline",
"\u{1F303}": "night with stars city",
"\u{1F306}": "cityscape at dusk sunset",
"\u{1F307}": "sunset city",
"\u{1F305}": "sunrise morning",
"\u{1F304}": "sunrise over mountains",
"\u{1F3DC}\uFE0F": "desert",
"\u{1F3DE}\uFE0F": "national park nature",
"\u{1F3A0}": "carousel horse merry go round",
"\u{1F3A1}": "ferris wheel",
"\u{1F3A2}": "roller coaster",
"\u{1F3DF}\uFE0F": "stadium",
"\u{1F54D}": "synagogue jewish",
"\u{1F6D5}": "hindu temple",
"\u{1F54B}": "kaaba mecca",
"\u26F2": "fountain water",
"\u26FA": "tent camping",
"\u{1F3D5}\uFE0F": "camping tent nature",
// More objects
"\u{1FA94}": "diya lamp oil",
"\u{1F4FA}": "television tv monitor",
"\u{1F4FB}": "radio",
"\u{1F4E0}": "fax machine",
"\u{1F50A}": "speaker loud volume high",
"\u{1F509}": "speaker medium volume",
"\u{1F508}": "speaker low volume",
"\u{1F507}": "muted speaker volume off",
"\u{1F4E3}": "megaphone cheering",
"\u{1F399}\uFE0F": "studio microphone podcast",
"\u{1F39A}\uFE0F": "level slider",
"\u{1F39B}\uFE0F": "control knobs",
"\u{1F9EE}": "abacus math calculate",
"\u{1F5A9}": "calculator",
"\u{1F4F8}": "camera flash photo",
"\u{1F4FD}\uFE0F": "film projector",
"\u{1F39E}\uFE0F": "film frames",
"\u{1F4FC}": "videocassette vhs tape",
"\u{1F50C}": "electric plug power",
"\u{1FAAB}": "low battery",
"\u{1F4B6}": "euro banknote",
"\u{1F4B7}": "pound banknote",
"\u{1F4B4}": "yen banknote",
"\u{1FAAA}": "identification card id",
"\u{1F9EB}": "petri dish biology",
"\u{1F6D7}": "elevator lift",
"\u{1FA9C}": "ladder steps",
"\u2696\uFE0F": "balance scale justice",
"\u26D3\uFE0F": "chains linked",
"\u2693": "anchor nautical ship",
"\u{1F5FF}": "moai easter island statue",
// Zodiac and symbols
"\u2648": "aries zodiac",
"\u2649": "taurus zodiac",
"\u264A": "gemini zodiac",
"\u264B": "cancer zodiac",
"\u264C": "leo zodiac",
"\u264D": "virgo zodiac",
"\u264E": "libra zodiac",
"\u264F": "scorpio zodiac",
"\u2650": "sagittarius zodiac",
"\u2651": "capricorn zodiac",
"\u2652": "aquarius zodiac",
"\u2653": "pisces zodiac",
"\u26CE": "ophiuchus zodiac",
// Country flags
"\u{1F1FA}\u{1F1F8}": "flag usa america united states",
"\u{1F1EC}\u{1F1E7}": "flag uk britain england",
"\u{1F1EB}\u{1F1F7}": "flag france french",
"\u{1F1E9}\u{1F1EA}": "flag germany german",
"\u{1F1EE}\u{1F1F9}": "flag italy italian",
"\u{1F1EA}\u{1F1F8}": "flag spain spanish",
"\u{1F1F7}\u{1F1FA}": "flag russia russian",
"\u{1F1E8}\u{1F1F3}": "flag china chinese",
"\u{1F1EF}\u{1F1F5}": "flag japan japanese",
"\u{1F1F0}\u{1F1F7}": "flag korea south korean",
"\u{1F1E7}\u{1F1F7}": "flag brazil brazilian",
"\u{1F1EE}\u{1F1F3}": "flag india indian",
"\u{1F1E8}\u{1F1E6}": "flag canada canadian",
"\u{1F1E6}\u{1F1FA}": "flag australia australian",
"\u{1F1F2}\u{1F1FD}": "flag mexico mexican",
"\u{1F1E6}\u{1F1F7}": "flag argentina",
"\u{1F1F9}\u{1F1F7}": "flag turkey turkish",
"\u{1F1F8}\u{1F1E6}": "flag saudi arabia",
"\u{1F1F3}\u{1F1F1}": "flag netherlands dutch",
"\u{1F1F8}\u{1F1EA}": "flag sweden swedish",
"\u{1F1F3}\u{1F1F4}": "flag norway norwegian",
"\u{1F1E9}\u{1F1F0}": "flag denmark danish",
"\u{1F1EB}\u{1F1EE}": "flag finland finnish",
"\u{1F1F5}\u{1F1F1}": "flag poland polish",
"\u{1F1FA}\u{1F1E6}": "flag ukraine ukrainian",
"\u{1F1E8}\u{1F1ED}": "flag switzerland swiss",
"\u{1F1E6}\u{1F1F9}": "flag austria",
"\u{1F1E7}\u{1F1EA}": "flag belgium",
"\u{1F1F5}\u{1F1F9}": "flag portugal portuguese",
"\u{1F1EC}\u{1F1F7}": "flag greece greek",
"\u{1F1EE}\u{1F1EA}": "flag ireland irish",
"\u{1F1EE}\u{1F1F1}": "flag israel",
"\u{1F1EA}\u{1F1EC}": "flag egypt",
"\u{1F1FF}\u{1F1E6}": "flag south africa",
"\u{1F1F9}\u{1F1ED}": "flag thailand thai",
"\u{1F1FB}\u{1F1F3}": "flag vietnam vietnamese",
"\u{1F1EE}\u{1F1E9}": "flag indonesia",
"\u{1F1F5}\u{1F1ED}": "flag philippines",
"\u{1F1F3}\u{1F1FF}": "flag new zealand",
"\u{1F1F8}\u{1F1EC}": "flag singapore",
"\u{1F1F2}\u{1F1FE}": "flag malaysia",
"\u{1F1E8}\u{1F1F4}": "flag colombia",
"\u{1F1E8}\u{1F1F1}": "flag chile",
"\u{1F1F5}\u{1F1EA}": "flag peru",
"\u{1F1F0}\u{1F1FF}": "flag kazakhstan",
"\u{1F1EC}\u{1F1EA}": "flag georgia",
"\u{1F3F4}\u200D\u2620\uFE0F": "pirate flag jolly roger",
"\u{1F3F3}\uFE0F\u200D\u{1F308}": "rainbow flag pride lgbtq",
"\u{1F3F3}\uFE0F\u200D\u26A7\uFE0F": "transgender flag",
// More misc symbols
"\u262E\uFE0F": "peace symbol",
"\u271D\uFE0F": "latin cross christian",
"\u262A\uFE0F": "star and crescent islam",
"\u{1F549}\uFE0F": "om hindu buddhist",
"\u262F\uFE0F": "yin yang balance",
"\u2721\uFE0F": "star of david jewish",
"\u{1F52F}": "six pointed star",
"\u2638\uFE0F": "wheel of dharma buddhism",
"\u{1F6D0}": "place of worship",
"\u269B\uFE0F": "atom symbol science",
"\u2622\uFE0F": "radioactive nuclear",
"\u2623\uFE0F": "biohazard",
"\u{1F194}": "id identity",
"\u2695\uFE0F": "medical symbol caduceus",
"\u24C2\uFE0F": "circled m metro",
"\u{1F170}\uFE0F": "a button blood type",
"\u{1F171}\uFE0F": "b button blood type",
"\u{1F18E}": "ab button blood type",
"\u{1F17E}\uFE0F": "o button blood type",
"\u{1F198}": "sos emergency help",
"\u{1F19A}": "vs versus",
"\u{1F197}": "ok button",
"\u{1F195}": "new button",
"\u{1F193}": "free button",
"\u{1F201}": "japanese here",
"\u{1F202}\uFE0F": "japanese service charge",
"\u{1F530}": "japanese symbol beginner",
"\u2640\uFE0F": "female sign woman",
"\u2642\uFE0F": "male sign man",
"\u26A7\uFE0F": "transgender symbol",
"\u2716\uFE0F": "multiply cross",
"\u2795": "plus add",
"\u2796": "minus subtract",
"\u2797": "divide",
"\u{1F7F0}": "equals sign",
"#\uFE0F\u20E3": "hash number sign",
"*\uFE0F\u20E3": "asterisk keycap",
"0\uFE0F\u20E3": "zero keycap",
"1\uFE0F\u20E3": "one keycap",
"2\uFE0F\u20E3": "two keycap",
"3\uFE0F\u20E3": "three keycap",
"4\uFE0F\u20E3": "four keycap",
"5\uFE0F\u20E3": "five keycap",
"6\uFE0F\u20E3": "six keycap",
"7\uFE0F\u20E3": "seven keycap",
"8\uFE0F\u20E3": "eight keycap",
"9\uFE0F\u20E3": "nine keycap",
"\u{1F51F}": "ten keycap",
"\u{1F17F}\uFE0F": "parking button",
"\u{1F233}": "japanese vacancy",
"\u{1F234}": "japanese passing grade",
"\u{1F235}": "japanese no vacancy",
"\u{1F239}": "japanese discount",
"\u{1F232}": "japanese prohibited",
"\u{1F250}": "japanese bargain",
"\u{1F236}": "japanese not free of charge",
"\u{1F21A}": "japanese free of charge",
"\u{1F51D}": "top arrow",
"\u{1F519}": "back arrow",
"\u{1F51B}": "on arrow",
"\u{1F51C}": "soon arrow",
"\u{1F51A}": "end arrow",
"\u2195\uFE0F": "up down arrow",
"\u2194\uFE0F": "left right arrow",
"\u2197\uFE0F": "northeast arrow",
"\u2198\uFE0F": "southeast arrow",
"\u2199\uFE0F": "southwest arrow",
"\u2196\uFE0F": "northwest arrow",
"\u2934\uFE0F": "right arrow curving up",
"\u2935\uFE0F": "right arrow curving down",
"\u{1F502}": "repeat single loop one",
"\u{1F503}": "clockwise arrows",
"\u25C0\uFE0F": "reverse button rewind",
"\u23ED\uFE0F": "next track",
"\u23EE\uFE0F": "previous track",
"\u23EF\uFE0F": "play pause toggle",
"\u{1F505}": "dim button brightness low",
"\u{1F506}": "bright button brightness high",
"\u{1F4F6}": "signal bars antenna",
"\u{1F4F3}": "vibration mode",
"\u{1F4F4}": "mobile phone off",
"\u{1F518}": "radio button",
"\u{1F532}": "black square button",
"\u{1F533}": "white square button",
"\u{1F53A}": "red triangle up",
"\u{1F53B}": "red triangle down",
"\u{1F538}": "small orange diamond",
"\u{1F539}": "small blue diamond",
"\u{1F536}": "large orange diamond",
"\u{1F537}": "large blue diamond",
"\u25FB\uFE0F": "white medium square",
"\u25FC\uFE0F": "black medium square",
"\u25FD": "white medium small square",
"\u25FE": "black medium small square",
"\u25AA\uFE0F": "black small square",
"\u25AB\uFE0F": "white small square",
"\u{1F4A0}": "diamond shape with dot inside blue",
"\xA9\uFE0F": "copyright",
"\xAE\uFE0F": "registered trademark",
"\u2122\uFE0F": "trademark"
};
// icon_picker_modal.ts
var GROUPS = [
{
label: "Smileys",
icon: "\u{1F600}",
emojis: [
"\u{1F600}",
"\u{1F603}",
"\u{1F604}",
"\u{1F601}",
"\u{1F606}",
"\u{1F605}",
"\u{1F923}",
"\u{1F602}",
"\u{1F642}",
"\u{1F643}",
"\u{1FAE0}",
"\u{1F609}",
"\u{1F60A}",
"\u{1F607}",
"\u{1F970}",
"\u{1F60D}",
"\u{1F929}",
"\u{1F618}",
"\u{1F617}",
"\u263A\uFE0F",
"\u{1F61A}",
"\u{1F619}",
"\u{1F972}",
"\u{1F60B}",
"\u{1F61B}",
"\u{1F61C}",
"\u{1F92A}",
"\u{1F61D}",
"\u{1F911}",
"\u{1F917}",
"\u{1F92D}",
"\u{1FAE2}",
"\u{1FAE3}",
"\u{1F92B}",
"\u{1F914}",
"\u{1FAE1}",
"\u{1F910}",
"\u{1F928}",
"\u{1F610}",
"\u{1F611}",
"\u{1F636}",
"\u{1FAE5}",
"\u{1F636}\u200D\u{1F32B}\uFE0F",
"\u{1F60F}",
"\u{1F612}",
"\u{1F644}",
"\u{1F62C}",
"\u{1F62E}\u200D\u{1F4A8}",
"\u{1F925}",
"\u{1FAE8}",
"\u{1F60C}",
"\u{1F614}",
"\u{1F62A}",
"\u{1F924}",
"\u{1F634}",
"\u{1FAE9}",
"\u{1F637}",
"\u{1F912}",
"\u{1F915}",
"\u{1F922}",
"\u{1F92E}",
"\u{1F927}",
"\u{1F975}",
"\u{1F976}",
"\u{1F974}",
"\u{1F635}",
"\u{1F635}\u200D\u{1F4AB}",
"\u{1F92F}",
"\u{1F920}",
"\u{1F973}",
"\u{1F978}",
"\u{1F60E}",
"\u{1F913}",
"\u{1F9D0}",
"\u{1F615}",
"\u{1FAE4}",
"\u{1F61F}",
"\u{1F641}",
"\u2639\uFE0F",
"\u{1F62E}",
"\u{1F62F}",
"\u{1F632}",
"\u{1F633}",
"\u{1F97A}",
"\u{1F979}",
"\u{1F626}",
"\u{1F627}",
"\u{1F628}",
"\u{1F630}",
"\u{1F625}",
"\u{1F622}",
"\u{1F62D}",
"\u{1F631}",
"\u{1F616}",
"\u{1F623}",
"\u{1F61E}",
"\u{1F613}",
"\u{1F629}",
"\u{1F62B}",
"\u{1F971}",
"\u{1F624}",
"\u{1F621}",
"\u{1F620}",
"\u{1F92C}",
"\u{1F608}",
"\u{1F47F}",
"\u{1F480}",
"\u2620\uFE0F",
"\u{1F4A9}",
"\u{1F921}",
"\u{1F479}",
"\u{1F47A}",
"\u{1F47B}",
"\u{1F47D}",
"\u{1F47E}",
"\u{1F916}",
"\u{1F63A}",
"\u{1F638}",
"\u{1F639}",
"\u{1F63B}",
"\u{1F63C}",
"\u{1F63D}",
"\u{1F640}",
"\u{1F63F}",
"\u{1F63E}",
"\u{1F648}",
"\u{1F649}",
"\u{1F64A}",
"\u{1F48C}",
"\u{1F498}",
"\u{1F49D}",
"\u{1F496}",
"\u{1F497}",
"\u{1F493}",
"\u{1F49E}",
"\u{1F495}",
"\u{1F49F}",
"\u2763\uFE0F",
"\u{1F494}",
"\u2764\uFE0F\u200D\u{1F525}",
"\u2764\uFE0F\u200D\u{1FA79}",
"\u2764\uFE0F",
"\u{1FA77}",
"\u{1F9E1}",
"\u{1F49B}",
"\u{1F49A}",
"\u{1F499}",
"\u{1FA75}",
"\u{1F49C}",
"\u{1F90E}",
"\u{1F5A4}",
"\u{1FA76}",
"\u{1F90D}",
"\u{1F48B}",
"\u{1F4AF}",
"\u{1F4A2}",
"\u{1F4A5}",
"\u{1F4AB}",
"\u{1F4A6}",
"\u{1F4A8}",
"\u{1F573}\uFE0F",
"\u{1F4AC}",
"\u{1F441}\uFE0F\u200D\u{1F5E8}\uFE0F",
"\u{1F5E8}\uFE0F",
"\u{1F5EF}\uFE0F",
"\u{1F4AD}",
"\u{1F4A4}"
]
},
{
label: "People",
icon: "\u{1F44B}",
emojis: [
"\u{1F44B}",
"\u{1F91A}",
"\u{1F590}\uFE0F",
"\u270B",
"\u{1F596}",
"\u{1FAF1}",
"\u{1FAF2}",
"\u{1FAF3}",
"\u{1FAF4}",
"\u{1FAF7}",
"\u{1FAF8}",
"\u{1F44C}",
"\u{1F90C}",
"\u{1F90F}",
"\u270C\uFE0F",
"\u{1F91E}",
"\u{1FAF0}",
"\u{1F91F}",
"\u{1F918}",
"\u{1F919}",
"\u{1F448}",
"\u{1F449}",
"\u{1F446}",
"\u{1F595}",
"\u{1F447}",
"\u261D\uFE0F",
"\u{1FAF5}",
"\u{1F44D}",
"\u{1F44E}",
"\u270A",
"\u{1F44A}",
"\u{1F91B}",
"\u{1F91C}",
"\u{1F44F}",
"\u{1F64C}",
"\u{1FAF6}",
"\u{1F450}",
"\u{1F932}",
"\u{1F91D}",
"\u{1F64F}",
"\u270D\uFE0F",
"\u{1F485}",
"\u{1F933}",
"\u{1F4AA}",
"\u{1F9BE}",
"\u{1F9BF}",
"\u{1F9B5}",
"\u{1F9B6}",
"\u{1F442}",
"\u{1F9BB}",
"\u{1F443}",
"\u{1F9E0}",
"\u{1FAC0}",
"\u{1FAC1}",
"\u{1F9B7}",
"\u{1F9B4}",
"\u{1F440}",
"\u{1F441}\uFE0F",
"\u{1F445}",
"\u{1F444}",
"\u{1FAE6}",
"\u{1F476}",
"\u{1F9D2}",
"\u{1F466}",
"\u{1F467}",
"\u{1F9D1}",
"\u{1F471}",
"\u{1F468}",
"\u{1F469}",
"\u{1F9D3}",
"\u{1F474}",
"\u{1F475}",
"\u{1F645}",
"\u{1F646}",
"\u{1F481}",
"\u{1F64B}",
"\u{1F9CF}",
"\u{1F647}",
"\u{1F926}",
"\u{1F937}",
"\u{1F9D1}\u200D\u2695\uFE0F",
"\u{1F9D1}\u200D\u{1F393}",
"\u{1F9D1}\u200D\u{1F3EB}",
"\u{1F9D1}\u200D\u2696\uFE0F",
"\u{1F9D1}\u200D\u{1F33E}",
"\u{1F9D1}\u200D\u{1F373}",
"\u{1F9D1}\u200D\u{1F527}",
"\u{1F9D1}\u200D\u{1F3ED}",
"\u{1F9D1}\u200D\u{1F4BC}",
"\u{1F9D1}\u200D\u{1F52C}",
"\u{1F9D1}\u200D\u{1F4BB}",
"\u{1F9D1}\u200D\u{1F3A4}",
"\u{1F9D1}\u200D\u{1F3A8}",
"\u{1F9D1}\u200D\u2708\uFE0F",
"\u{1F9D1}\u200D\u{1F680}",
"\u{1F9D1}\u200D\u{1F692}",
"\u{1F46E}",
"\u{1F575}\uFE0F",
"\u{1F482}",
"\u{1F977}",
"\u{1F477}",
"\u{1FAC5}",
"\u{1F934}",
"\u{1F478}",
"\u{1F473}",
"\u{1F472}",
"\u{1F9D5}",
"\u{1F935}",
"\u{1F470}",
"\u{1F930}",
"\u{1F931}",
"\u{1F47C}",
"\u{1F385}",
"\u{1F936}",
"\u{1F9D1}\u200D\u{1F384}",
"\u{1F9B8}",
"\u{1F9B9}",
"\u{1F9D9}",
"\u{1F9DA}",
"\u{1F9DB}",
"\u{1F9DC}",
"\u{1F9DD}",
"\u{1F9DE}",
"\u{1F9DF}",
"\u{1F9CC}",
"\u{1F486}",
"\u{1F487}",
"\u{1F6B6}",
"\u{1F9CD}",
"\u{1F9CE}",
"\u{1F9D1}\u200D\u{1F9AF}",
"\u{1F9D1}\u200D\u{1F9BC}",
"\u{1F9D1}\u200D\u{1F9BD}",
"\u{1F3C3}",
"\u{1F483}",
"\u{1F57A}",
"\u{1F574}\uFE0F",
"\u{1F46F}",
"\u{1F9D6}",
"\u{1F9D7}",
"\u{1F93A}",
"\u{1F3C7}",
"\u26F7\uFE0F",
"\u{1F3C2}",
"\u{1F3CC}\uFE0F",
"\u{1F3C4}",
"\u{1F6A3}",
"\u{1F3CA}",
"\u26F9\uFE0F",
"\u{1F3CB}\uFE0F",
"\u{1F6B4}",
"\u{1F6B5}",
"\u{1F938}",
"\u{1F93C}",
"\u{1F93D}",
"\u{1F93E}",
"\u{1F939}",
"\u{1F9D8}",
"\u{1F6C0}",
"\u{1F6CC}",
"\u{1F9D1}\u200D\u{1F91D}\u200D\u{1F9D1}",
"\u{1F46D}",
"\u{1F46B}",
"\u{1F46C}",
"\u{1F48F}",
"\u{1F491}",
"\u{1F46A}",
"\u{1F5E3}\uFE0F",
"\u{1F464}",
"\u{1F465}",
"\u{1FAC2}",
"\u{1F463}"
]
},
{
label: "Animals",
icon: "\u{1F436}",
emojis: [
"\u{1F435}",
"\u{1F412}",
"\u{1F98D}",
"\u{1F9A7}",
"\u{1F436}",
"\u{1F415}",
"\u{1F9AE}",
"\u{1F415}\u200D\u{1F9BA}",
"\u{1F429}",
"\u{1F43A}",
"\u{1F98A}",
"\u{1F99D}",
"\u{1F431}",
"\u{1F408}",
"\u{1F408}\u200D\u2B1B",
"\u{1F981}",
"\u{1F42F}",
"\u{1F405}",
"\u{1F406}",
"\u{1F434}",
"\u{1FACE}",
"\u{1FACF}",
"\u{1F40E}",
"\u{1F984}",
"\u{1F993}",
"\u{1F98C}",
"\u{1F9AC}",
"\u{1F42E}",
"\u{1F402}",
"\u{1F403}",
"\u{1F404}",
"\u{1F437}",
"\u{1F416}",
"\u{1F417}",
"\u{1F43D}",
"\u{1F40F}",
"\u{1F411}",
"\u{1F410}",
"\u{1F42A}",
"\u{1F42B}",
"\u{1F999}",
"\u{1F992}",
"\u{1F418}",
"\u{1F9A3}",
"\u{1F98F}",
"\u{1F99B}",
"\u{1F42D}",
"\u{1F401}",
"\u{1F400}",
"\u{1F439}",
"\u{1F430}",
"\u{1F407}",
"\u{1F43F}\uFE0F",
"\u{1F9AB}",
"\u{1F994}",
"\u{1F987}",
"\u{1F43B}",
"\u{1F43B}\u200D\u2744\uFE0F",
"\u{1F428}",
"\u{1F43C}",
"\u{1F9A5}",
"\u{1F9A6}",
"\u{1F9A8}",
"\u{1F998}",
"\u{1F9A1}",
"\u{1F43E}",
"\u{1F983}",
"\u{1F414}",
"\u{1F413}",
"\u{1F423}",
"\u{1F424}",
"\u{1F425}",
"\u{1F426}",
"\u{1F427}",
"\u{1F54A}\uFE0F",
"\u{1F985}",
"\u{1F986}",
"\u{1F9A2}",
"\u{1F989}",
"\u{1F9A4}",
"\u{1FAB6}",
"\u{1F9A9}",
"\u{1F99A}",
"\u{1F99C}",
"\u{1FABD}",
"\u{1F426}\u200D\u2B1B",
"\u{1FABF}",
"\u{1F426}\u200D\u{1F525}",
"\u{1F438}",
"\u{1F40A}",
"\u{1F422}",
"\u{1F98E}",
"\u{1F40D}",
"\u{1F432}",
"\u{1F409}",
"\u{1F995}",
"\u{1F996}",
"\u{1F433}",
"\u{1F40B}",
"\u{1F42C}",
"\u{1F9AD}",
"\u{1F41F}",
"\u{1F420}",
"\u{1F421}",
"\u{1F988}",
"\u{1F419}",
"\u{1F41A}",
"\u{1FAB8}",
"\u{1FABC}",
"\u{1F980}",
"\u{1F99E}",
"\u{1F990}",
"\u{1F991}",
"\u{1F9AA}",
"\u{1F40C}",
"\u{1F98B}",
"\u{1F41B}",
"\u{1F41C}",
"\u{1F41D}",
"\u{1FAB2}",
"\u{1F41E}",
"\u{1F997}",
"\u{1FAB3}",
"\u{1F577}\uFE0F",
"\u{1F578}\uFE0F",
"\u{1F982}",
"\u{1F99F}",
"\u{1FAB0}",
"\u{1FAB1}",
"\u{1F9A0}",
"\u{1F490}",
"\u{1F338}",
"\u{1F4AE}",
"\u{1FAB7}",
"\u{1F3F5}\uFE0F",
"\u{1F339}",
"\u{1F940}",
"\u{1F33A}",
"\u{1F33B}",
"\u{1F33C}",
"\u{1F337}",
"\u{1FABB}",
"\u{1F331}",
"\u{1FAB4}",
"\u{1F332}",
"\u{1F333}",
"\u{1F334}",
"\u{1F335}",
"\u{1F33E}",
"\u{1F33F}",
"\u2618\uFE0F",
"\u{1F340}",
"\u{1F341}",
"\u{1F342}",
"\u{1F343}",
"\u{1FAB9}",
"\u{1FABA}",
"\u{1F344}"
]
},
{
label: "Food",
icon: "\u{1F354}",
emojis: [
"\u{1F347}",
"\u{1F348}",
"\u{1F349}",
"\u{1F34A}",
"\u{1F34B}",
"\u{1F34B}\u200D\u{1F7E9}",
"\u{1F34C}",
"\u{1F34D}",
"\u{1F96D}",
"\u{1F34E}",
"\u{1F34F}",
"\u{1F350}",
"\u{1F351}",
"\u{1F352}",
"\u{1F353}",
"\u{1FAD0}",
"\u{1F95D}",
"\u{1F345}",
"\u{1FAD2}",
"\u{1F965}",
"\u{1F951}",
"\u{1F346}",
"\u{1F954}",
"\u{1F955}",
"\u{1F33D}",
"\u{1F336}\uFE0F",
"\u{1FAD1}",
"\u{1F952}",
"\u{1F96C}",
"\u{1F966}",
"\u{1F9C4}",
"\u{1F9C5}",
"\u{1F95C}",
"\u{1FAD8}",
"\u{1F330}",
"\u{1FADA}",
"\u{1FADB}",
"\u{1F35E}",
"\u{1F950}",
"\u{1F956}",
"\u{1FAD3}",
"\u{1F968}",
"\u{1F96F}",
"\u{1F95E}",
"\u{1F9C7}",
"\u{1F9C0}",
"\u{1F356}",
"\u{1F357}",
"\u{1F969}",
"\u{1F953}",
"\u{1F354}",
"\u{1F35F}",
"\u{1F355}",
"\u{1F32D}",
"\u{1F96A}",
"\u{1F32E}",
"\u{1F32F}",
"\u{1FAD4}",
"\u{1F959}",
"\u{1F9C6}",
"\u{1F95A}",
"\u{1F373}",
"\u{1F958}",
"\u{1F372}",
"\u{1FAD5}",
"\u{1F963}",
"\u{1F957}",
"\u{1F37F}",
"\u{1F9C8}",
"\u{1F9C2}",
"\u{1F96B}",
"\u{1F371}",
"\u{1F358}",
"\u{1F359}",
"\u{1F35A}",
"\u{1F35B}",
"\u{1F35C}",
"\u{1F35D}",
"\u{1F360}",
"\u{1F362}",
"\u{1F363}",
"\u{1F364}",
"\u{1F365}",
"\u{1F96E}",
"\u{1F361}",
"\u{1F95F}",
"\u{1F960}",
"\u{1F961}",
"\u{1F366}",
"\u{1F367}",
"\u{1F368}",
"\u{1F369}",
"\u{1F36A}",
"\u{1F382}",
"\u{1F370}",
"\u{1F9C1}",
"\u{1F967}",
"\u{1F36B}",
"\u{1F36C}",
"\u{1F36D}",
"\u{1F36E}",
"\u{1F36F}",
"\u{1F37C}",
"\u{1F95B}",
"\u2615",
"\u{1FAD6}",
"\u{1F375}",
"\u{1F376}",
"\u{1F37E}",
"\u{1F377}",
"\u{1F378}",
"\u{1F379}",
"\u{1F37A}",
"\u{1F37B}",
"\u{1F942}",
"\u{1F943}",
"\u{1FAD7}",
"\u{1F964}",
"\u{1F9CB}",
"\u{1F9C3}",
"\u{1F9C9}",
"\u{1F9CA}",
"\u{1F962}",
"\u{1F37D}\uFE0F",
"\u{1F374}",
"\u{1F944}",
"\u{1F52A}",
"\u{1FAD9}",
"\u{1F3FA}"
]
},
{
label: "Travel",
icon: "\u{1F697}",
emojis: [
"\u{1F30D}",
"\u{1F30E}",
"\u{1F30F}",
"\u{1F310}",
"\u{1F5FA}\uFE0F",
"\u{1F5FE}",
"\u{1F9ED}",
"\u{1F3D4}\uFE0F",
"\u26F0\uFE0F",
"\u{1F30B}",
"\u{1F5FB}",
"\u{1F3D5}\uFE0F",
"\u{1F3D6}\uFE0F",
"\u{1F3DC}\uFE0F",
"\u{1F3DD}\uFE0F",
"\u{1F3DE}\uFE0F",
"\u{1F3DF}\uFE0F",
"\u{1F3DB}\uFE0F",
"\u{1F3D7}\uFE0F",
"\u{1F9F1}",
"\u{1FAA8}",
"\u{1FAB5}",
"\u{1F6D6}",
"\u{1F3D8}\uFE0F",
"\u{1F3DA}\uFE0F",
"\u{1F3E0}",
"\u{1F3E1}",
"\u{1F3E2}",
"\u{1F3E3}",
"\u{1F3E4}",
"\u{1F3E5}",
"\u{1F3E6}",
"\u{1F3E8}",
"\u{1F3E9}",
"\u{1F3EA}",
"\u{1F3EB}",
"\u{1F3EC}",
"\u{1F3ED}",
"\u{1F3EF}",
"\u{1F3F0}",
"\u{1F492}",
"\u{1F5FC}",
"\u{1F5FD}",
"\u26EA",
"\u{1F54C}",
"\u{1F6D5}",
"\u{1F54D}",
"\u26E9\uFE0F",
"\u{1F54B}",
"\u26F2",
"\u26FA",
"\u{1F301}",
"\u{1F303}",
"\u{1F3D9}\uFE0F",
"\u{1F304}",
"\u{1F305}",
"\u{1F306}",
"\u{1F307}",
"\u{1F309}",
"\u2668\uFE0F",
"\u{1F3A0}",
"\u{1F6DD}",
"\u{1F3A1}",
"\u{1F3A2}",
"\u{1F488}",
"\u{1F3AA}",
"\u{1F682}",
"\u{1F683}",
"\u{1F684}",
"\u{1F685}",
"\u{1F686}",
"\u{1F687}",
"\u{1F688}",
"\u{1F689}",
"\u{1F68A}",
"\u{1F69D}",
"\u{1F69E}",
"\u{1F68B}",
"\u{1F68C}",
"\u{1F68D}",
"\u{1F68E}",
"\u{1F690}",
"\u{1F691}",
"\u{1F692}",
"\u{1F693}",
"\u{1F694}",
"\u{1F695}",
"\u{1F696}",
"\u{1F697}",
"\u{1F698}",
"\u{1F699}",
"\u{1F6FB}",
"\u{1F69A}",
"\u{1F69B}",
"\u{1F69C}",
"\u{1F3CE}\uFE0F",
"\u{1F3CD}\uFE0F",
"\u{1F6F5}",
"\u{1F9BD}",
"\u{1F9BC}",
"\u{1F6FA}",
"\u{1F6B2}",
"\u{1F6F4}",
"\u{1F6F9}",
"\u{1F6FC}",
"\u{1F68F}",
"\u{1F6E3}\uFE0F",
"\u{1F6E4}\uFE0F",
"\u{1F6E2}\uFE0F",
"\u26FD",
"\u{1F6DE}",
"\u{1F6A8}",
"\u{1F6A5}",
"\u{1F6A6}",
"\u{1F6D1}",
"\u{1F6A7}",
"\u2693",
"\u{1F6DF}",
"\u26F5",
"\u{1F6F6}",
"\u{1F6A4}",
"\u{1F6F3}\uFE0F",
"\u26F4\uFE0F",
"\u{1F6E5}\uFE0F",
"\u{1F6A2}",
"\u2708\uFE0F",
"\u{1F6E9}\uFE0F",
"\u{1F6EB}",
"\u{1F6EC}",
"\u{1FA82}",
"\u{1F4BA}",
"\u{1F681}",
"\u{1F69F}",
"\u{1F6A0}",
"\u{1F6A1}",
"\u{1F6F0}\uFE0F",
"\u{1F680}",
"\u{1F6F8}",
"\u{1F6CE}\uFE0F",
"\u{1F9F3}",
"\u231B",
"\u23F3",
"\u231A",
"\u23F0",
"\u23F1\uFE0F",
"\u23F2\uFE0F",
"\u{1F570}\uFE0F",
"\u{1F311}",
"\u{1F312}",
"\u{1F313}",
"\u{1F314}",
"\u{1F315}",
"\u{1F316}",
"\u{1F317}",
"\u{1F318}",
"\u{1F319}",
"\u{1F31A}",
"\u{1F31B}",
"\u{1F31C}",
"\u{1F321}\uFE0F",
"\u2600\uFE0F",
"\u{1F31D}",
"\u{1F31E}",
"\u{1FA90}",
"\u2B50",
"\u{1F31F}",
"\u{1F320}",
"\u{1F30C}",
"\u2601\uFE0F",
"\u26C5",
"\u26C8\uFE0F",
"\u{1F324}\uFE0F",
"\u{1F325}\uFE0F",
"\u{1F326}\uFE0F",
"\u{1F327}\uFE0F",
"\u{1F328}\uFE0F",
"\u{1F329}\uFE0F",
"\u{1F32A}\uFE0F",
"\u{1F32B}\uFE0F",
"\u{1F32C}\uFE0F",
"\u{1F300}",
"\u{1F308}",
"\u{1F302}",
"\u2602\uFE0F",
"\u2614",
"\u26F1\uFE0F",
"\u26A1",
"\u2744\uFE0F",
"\u2603\uFE0F",
"\u26C4",
"\u2604\uFE0F",
"\u{1F525}",
"\u{1F4A7}",
"\u{1F30A}"
]
},
{
label: "Activities",
icon: "\u{1F3AF}",
emojis: [
"\u{1F383}",
"\u{1F384}",
"\u{1F386}",
"\u{1F387}",
"\u{1F9E8}",
"\u2728",
"\u{1F388}",
"\u{1F389}",
"\u{1F38A}",
"\u{1F38B}",
"\u{1F38D}",
"\u{1F38E}",
"\u{1F38F}",
"\u{1F390}",
"\u{1F391}",
"\u{1F9E7}",
"\u{1F380}",
"\u{1F381}",
"\u{1F397}\uFE0F",
"\u{1F39F}\uFE0F",
"\u{1F3AB}",
"\u{1F396}\uFE0F",
"\u{1F3C6}",
"\u{1F3C5}",
"\u{1F947}",
"\u{1F948}",
"\u{1F949}",
"\u26BD",
"\u26BE",
"\u{1F94E}",
"\u{1F3C0}",
"\u{1F3D0}",
"\u{1F3C8}",
"\u{1F3C9}",
"\u{1F3BE}",
"\u{1F94F}",
"\u{1F3B3}",
"\u{1F3CF}",
"\u{1F3D1}",
"\u{1F3D2}",
"\u{1F94D}",
"\u{1F3D3}",
"\u{1F3F8}",
"\u{1F94A}",
"\u{1F94B}",
"\u{1F945}",
"\u26F3",
"\u26F8\uFE0F",
"\u{1F3A3}",
"\u{1F93F}",
"\u{1F3BD}",
"\u{1F3BF}",
"\u{1F6F7}",
"\u{1F94C}",
"\u{1F3AF}",
"\u{1FA80}",
"\u{1FA81}",
"\u{1F52B}",
"\u{1F3B1}",
"\u{1F52E}",
"\u{1FA84}",
"\u{1F3AE}",
"\u{1F579}\uFE0F",
"\u{1F3B0}",
"\u{1F3B2}",
"\u{1F9E9}",
"\u{1F9F8}",
"\u{1FA85}",
"\u{1FAA9}",
"\u{1FA86}",
"\u2660\uFE0F",
"\u2665\uFE0F",
"\u2666\uFE0F",
"\u2663\uFE0F",
"\u265F\uFE0F",
"\u{1F0CF}",
"\u{1F004}",
"\u{1F3B4}",
"\u{1F3AD}",
"\u{1F5BC}\uFE0F",
"\u{1F3A8}",
"\u{1F9F5}",
"\u{1FAA1}",
"\u{1F9F6}",
"\u{1FAA2}"
]
},
{
label: "Objects",
icon: "\u{1F4A1}",
emojis: [
"\u{1F453}",
"\u{1F576}\uFE0F",
"\u{1F97D}",
"\u{1F97C}",
"\u{1F9BA}",
"\u{1F454}",
"\u{1F455}",
"\u{1F456}",
"\u{1F9E3}",
"\u{1F9E4}",
"\u{1F9E5}",
"\u{1F9E6}",
"\u{1F457}",
"\u{1F458}",
"\u{1F97B}",
"\u{1FA71}",
"\u{1FA72}",
"\u{1FA73}",
"\u{1F459}",
"\u{1F45A}",
"\u{1FAAD}",
"\u{1F45B}",
"\u{1F45C}",
"\u{1F45D}",
"\u{1F6CD}\uFE0F",
"\u{1F392}",
"\u{1FA74}",
"\u{1F45E}",
"\u{1F45F}",
"\u{1F97E}",
"\u{1F97F}",
"\u{1F460}",
"\u{1F461}",
"\u{1FA70}",
"\u{1F462}",
"\u{1FAAE}",
"\u{1F451}",
"\u{1F452}",
"\u{1F3A9}",
"\u{1F393}",
"\u{1F9E2}",
"\u{1FA96}",
"\u26D1\uFE0F",
"\u{1F4FF}",
"\u{1F484}",
"\u{1F48D}",
"\u{1F48E}",
"\u{1F507}",
"\u{1F508}",
"\u{1F509}",
"\u{1F50A}",
"\u{1F4E2}",
"\u{1F4E3}",
"\u{1F4EF}",
"\u{1F514}",
"\u{1F515}",
"\u{1F3BC}",
"\u{1F3B5}",
"\u{1F3B6}",
"\u{1F399}\uFE0F",
"\u{1F39A}\uFE0F",
"\u{1F39B}\uFE0F",
"\u{1F3A4}",
"\u{1F3A7}",
"\u{1F4FB}",
"\u{1F3B7}",
"\u{1FA97}",
"\u{1F3B8}",
"\u{1F3B9}",
"\u{1F3BA}",
"\u{1F3BB}",
"\u{1FA95}",
"\u{1F941}",
"\u{1FA98}",
"\u{1FA87}",
"\u{1FA88}",
"\u{1FA89}",
"\u{1F4F1}",
"\u{1F4F2}",
"\u260E\uFE0F",
"\u{1F4DE}",
"\u{1F4DF}",
"\u{1F4E0}",
"\u{1F50B}",
"\u{1FAAB}",
"\u{1F50C}",
"\u{1F4BB}",
"\u{1F5A5}\uFE0F",
"\u{1F5A8}\uFE0F",
"\u2328\uFE0F",
"\u{1F5B1}\uFE0F",
"\u{1F5B2}\uFE0F",
"\u{1F4BD}",
"\u{1F4BE}",
"\u{1F4BF}",
"\u{1F4C0}",
"\u{1F9EE}",
"\u{1F3A5}",
"\u{1F39E}\uFE0F",
"\u{1F4FD}\uFE0F",
"\u{1F3AC}",
"\u{1F4FA}",
"\u{1F4F7}",
"\u{1F4F8}",
"\u{1F4F9}",
"\u{1F4FC}",
"\u{1F50D}",
"\u{1F50E}",
"\u{1F56F}\uFE0F",
"\u{1F4A1}",
"\u{1F526}",
"\u{1F3EE}",
"\u{1FA94}",
"\u{1F4D4}",
"\u{1F4D5}",
"\u{1F4D6}",
"\u{1F4D7}",
"\u{1F4D8}",
"\u{1F4D9}",
"\u{1F4DA}",
"\u{1F4D3}",
"\u{1F4D2}",
"\u{1F4C3}",
"\u{1F4DC}",
"\u{1F4C4}",
"\u{1F4F0}",
"\u{1F5DE}\uFE0F",
"\u{1F4D1}",
"\u{1F516}",
"\u{1F3F7}\uFE0F",
"\u{1F4B0}",
"\u{1FA99}",
"\u{1F4B4}",
"\u{1F4B5}",
"\u{1F4B6}",
"\u{1F4B7}",
"\u{1F4B8}",
"\u{1F4B3}",
"\u{1F9FE}",
"\u{1F4B9}",
"\u2709\uFE0F",
"\u{1F4E7}",
"\u{1F4E8}",
"\u{1F4E9}",
"\u{1F4E4}",
"\u{1F4E5}",
"\u{1F4E6}",
"\u{1F4EB}",
"\u{1F4EA}",
"\u{1F4EC}",
"\u{1F4ED}",
"\u{1F4EE}",
"\u{1F5F3}\uFE0F",
"\u270F\uFE0F",
"\u2712\uFE0F",
"\u{1F58B}\uFE0F",
"\u{1F58A}\uFE0F",
"\u{1F58C}\uFE0F",
"\u{1F58D}\uFE0F",
"\u{1F4DD}",
"\u{1F4BC}",
"\u{1F4C1}",
"\u{1F4C2}",
"\u{1F5C2}\uFE0F",
"\u{1F4C5}",
"\u{1F4C6}",
"\u{1F5D2}\uFE0F",
"\u{1F5D3}\uFE0F",
"\u{1F4C7}",
"\u{1F4C8}",
"\u{1F4C9}",
"\u{1F4CA}",
"\u{1F4CB}",
"\u{1F4CC}",
"\u{1F4CD}",
"\u{1F4CE}",
"\u{1F587}\uFE0F",
"\u{1F4CF}",
"\u{1F4D0}",
"\u2702\uFE0F",
"\u{1F5C3}\uFE0F",
"\u{1F5C4}\uFE0F",
"\u{1F5D1}\uFE0F",
"\u{1F512}",
"\u{1F513}",
"\u{1F50F}",
"\u{1F510}",
"\u{1F511}",
"\u{1F5DD}\uFE0F",
"\u{1F528}",
"\u{1FA93}",
"\u26CF\uFE0F",
"\u2692\uFE0F",
"\u{1F6E0}\uFE0F",
"\u{1F5E1}\uFE0F",
"\u2694\uFE0F",
"\u{1F4A3}",
"\u{1FA83}",
"\u{1F3F9}",
"\u{1F6E1}\uFE0F",
"\u{1FA9A}",
"\u{1F527}",
"\u{1FA9B}",
"\u{1F529}",
"\u2699\uFE0F",
"\u{1F5DC}\uFE0F",
"\u2696\uFE0F",
"\u{1F9AF}",
"\u{1F517}",
"\u26D3\uFE0F",
"\u{1FA9D}",
"\u{1F9F0}",
"\u{1F9F2}",
"\u{1FA9C}",
"\u2697\uFE0F",
"\u{1F9EA}",
"\u{1F9EB}",
"\u{1F9EC}",
"\u{1F52C}",
"\u{1F52D}",
"\u{1F4E1}",
"\u{1F489}",
"\u{1FA78}",
"\u{1F48A}",
"\u{1FA79}",
"\u{1FA7C}",
"\u{1FA7A}",
"\u{1FA7B}",
"\u{1F6AA}",
"\u{1F6D7}",
"\u{1FA9E}",
"\u{1FA9F}",
"\u{1F6CF}\uFE0F",
"\u{1F6CB}\uFE0F",
"\u{1FA91}",
"\u{1F6BD}",
"\u{1FAA0}",
"\u{1F6BF}",
"\u{1F6C1}",
"\u{1FAA4}",
"\u{1FA92}",
"\u{1F9F4}",
"\u{1F9F7}",
"\u{1F9F9}",
"\u{1F9FA}",
"\u{1F9FB}",
"\u{1FAA3}",
"\u{1F9FC}",
"\u{1FAE7}",
"\u{1FAA5}",
"\u{1F9FD}",
"\u{1F9EF}",
"\u{1F6D2}",
"\u{1F6AC}",
"\u26B0\uFE0F",
"\u{1FAA6}",
"\u26B1\uFE0F",
"\u{1F9FF}",
"\u{1FAAC}",
"\u{1F5FF}",
"\u{1FAA7}",
"\u{1FAAA}"
]
},
{
label: "Symbols",
icon: "\u{1F523}",
emojis: [
"\u{1F3E7}",
"\u{1F6AE}",
"\u{1F6B0}",
"\u267F",
"\u{1F6B9}",
"\u{1F6BA}",
"\u{1F6BB}",
"\u{1F6BC}",
"\u{1F6BE}",
"\u{1F6C2}",
"\u{1F6C3}",
"\u{1F6C4}",
"\u{1F6C5}",
"\u26A0\uFE0F",
"\u{1F6B8}",
"\u26D4",
"\u{1F6AB}",
"\u{1F6B3}",
"\u{1F6AD}",
"\u{1F6AF}",
"\u{1F6B1}",
"\u{1F6B7}",
"\u{1F4F5}",
"\u{1F51E}",
"\u2622\uFE0F",
"\u2623\uFE0F",
"\u2B06\uFE0F",
"\u2197\uFE0F",
"\u27A1\uFE0F",
"\u2198\uFE0F",
"\u2B07\uFE0F",
"\u2199\uFE0F",
"\u2B05\uFE0F",
"\u2196\uFE0F",
"\u2195\uFE0F",
"\u2194\uFE0F",
"\u21A9\uFE0F",
"\u21AA\uFE0F",
"\u2934\uFE0F",
"\u2935\uFE0F",
"\u{1F503}",
"\u{1F504}",
"\u{1F519}",
"\u{1F51A}",
"\u{1F51B}",
"\u{1F51C}",
"\u{1F51D}",
"\u{1F6D0}",
"\u269B\uFE0F",
"\u{1F549}\uFE0F",
"\u2721\uFE0F",
"\u2638\uFE0F",
"\u262F\uFE0F",
"\u271D\uFE0F",
"\u2626\uFE0F",
"\u262A\uFE0F",
"\u262E\uFE0F",
"\u{1F54E}",
"\u{1F52F}",
"\u{1FAAF}",
"\u2648",
"\u2649",
"\u264A",
"\u264B",
"\u264C",
"\u264D",
"\u264E",
"\u264F",
"\u2650",
"\u2651",
"\u2652",
"\u2653",
"\u26CE",
"\u{1F500}",
"\u{1F501}",
"\u{1F502}",
"\u25B6\uFE0F",
"\u23E9",
"\u23ED\uFE0F",
"\u23EF\uFE0F",
"\u25C0\uFE0F",
"\u23EA",
"\u23EE\uFE0F",
"\u{1F53C}",
"\u23EB",
"\u{1F53D}",
"\u23EC",
"\u23F8\uFE0F",
"\u23F9\uFE0F",
"\u23FA\uFE0F",
"\u23CF\uFE0F",
"\u{1F3A6}",
"\u{1F505}",
"\u{1F506}",
"\u{1F4F6}",
"\u{1F6DC}",
"\u{1F4F3}",
"\u{1F4F4}",
"\u2640\uFE0F",
"\u2642\uFE0F",
"\u26A7\uFE0F",
"\u2716\uFE0F",
"\u2795",
"\u2796",
"\u2797",
"\u{1F7F0}",
"\u267E\uFE0F",
"\u203C\uFE0F",
"\u2049\uFE0F",
"\u2753",
"\u2754",
"\u2755",
"\u2757",
"\u3030\uFE0F",
"\u{1F4B1}",
"\u{1F4B2}",
"\u2695\uFE0F",
"\u267B\uFE0F",
"\u269C\uFE0F",
"\u{1F531}",
"\u{1F4DB}",
"\u{1F530}",
"\u2B55",
"\u2705",
"\u2611\uFE0F",
"\u2714\uFE0F",
"\u274C",
"\u274E",
"\u27B0",
"\u27BF",
"\u303D\uFE0F",
"\u2733\uFE0F",
"\u2734\uFE0F",
"\u2747\uFE0F",
"\xA9\uFE0F",
"\xAE\uFE0F",
"\u2122\uFE0F",
"#\uFE0F\u20E3",
"*\uFE0F\u20E3",
"0\uFE0F\u20E3",
"1\uFE0F\u20E3",
"2\uFE0F\u20E3",
"3\uFE0F\u20E3",
"4\uFE0F\u20E3",
"5\uFE0F\u20E3",
"6\uFE0F\u20E3",
"7\uFE0F\u20E3",
"8\uFE0F\u20E3",
"9\uFE0F\u20E3",
"\u{1F51F}",
"\u{1F520}",
"\u{1F521}",
"\u{1F522}",
"\u{1F523}",
"\u{1F524}",
"\u{1F170}\uFE0F",
"\u{1F18E}",
"\u{1F171}\uFE0F",
"\u{1F191}",
"\u{1F192}",
"\u{1F193}",
"\u2139\uFE0F",
"\u{1F194}",
"\u24C2\uFE0F",
"\u{1F195}",
"\u{1F196}",
"\u{1F17E}\uFE0F",
"\u{1F197}",
"\u{1F17F}\uFE0F",
"\u{1F198}",
"\u{1F199}",
"\u{1F19A}",
"\u{1F201}",
"\u{1F202}\uFE0F",
"\u{1F237}\uFE0F",
"\u{1F236}",
"\u{1F22F}",
"\u{1F250}",
"\u{1F239}",
"\u{1F21A}",
"\u{1F232}",
"\u{1F251}",
"\u{1F238}",
"\u{1F234}",
"\u{1F233}",
"\u3297\uFE0F",
"\u3299\uFE0F",
"\u{1F23A}",
"\u{1F235}",
"\u{1F534}",
"\u{1F7E0}",
"\u{1F7E1}",
"\u{1F7E2}",
"\u{1F535}",
"\u{1F7E3}",
"\u{1F7E4}",
"\u26AB",
"\u26AA",
"\u{1F7E5}",
"\u{1F7E7}",
"\u{1F7E8}",
"\u{1F7E9}",
"\u{1F7E6}",
"\u{1F7EA}",
"\u{1F7EB}",
"\u2B1B",
"\u2B1C",
"\u25FC\uFE0F",
"\u25FB\uFE0F",
"\u25FE",
"\u25FD",
"\u25AA\uFE0F",
"\u25AB\uFE0F",
"\u{1F536}",
"\u{1F537}",
"\u{1F538}",
"\u{1F539}",
"\u{1F53A}",
"\u{1F53B}",
"\u{1F4A0}",
"\u{1F518}",
"\u{1F533}",
"\u{1F532}"
]
}
];
function getAllItems() {
let items = [];
for (let g of GROUPS)
for (let e of g.emojis)
items.push({ emoji: e, name: EMOJI_NAMES[e] || "" });
return items;
}
var VF_IconPickerModal = class extends import_obsidian5.Modal {
constructor(plugin2, onSubmit) {
super(plugin2.app);
this.plugin = plugin2;
this.onSubmit = onSubmit;
this.query = "";
this.activeGroup = 0;
}
onOpen() {
this.titleEl.setText("Manage icon");
this.modalEl.addClass("vf-icon-modal");
let searchInput = this.contentEl.createEl("input", {
type: "text",
placeholder: "Search...",
cls: "vf-icon-search"
});
let searchTimer = 0;
searchInput.addEventListener("input", () => {
if (searchTimer)
clearTimeout(searchTimer);
searchTimer = window.setTimeout(() => {
this.query = searchInput.value.toLowerCase();
this.renderGrid();
}, 120);
});
this.tabsEl = this.contentEl.createDiv({ cls: "vf-icon-tabs" });
this.gridEl = this.contentEl.createDiv({ cls: "vf-icon-grid" });
this.gridEl.addEventListener("click", (e) => {
let target = e.target.closest(".vf-icon-cell");
if (!target || !target.dataset.emoji)
return;
this.close();
this.onSubmit(target.dataset.emoji);
});
this.buildTabs();
this.renderGrid();
let removeBtn = this.contentEl.createEl("button", {
text: "Remove icon",
cls: "vf-icon-remove-btn"
});
removeBtn.addEventListener("click", () => {
this.close();
this.onSubmit("");
});
searchInput.focus();
}
buildTabs() {
for (let i = 0; i < GROUPS.length; i++) {
let tab = this.tabsEl.createDiv({ cls: "vf-icon-tab" });
tab.textContent = GROUPS[i].icon;
tab.title = GROUPS[i].label;
tab.addEventListener("click", () => {
this.activeGroup = i;
this.query = "";
let input = this.contentEl.querySelector(".vf-icon-search");
if (input)
input.value = "";
this.updateTabHighlight();
this.renderGrid();
});
}
this.updateTabHighlight();
}
updateTabHighlight() {
let tabs = this.tabsEl.children;
for (let i = 0; i < tabs.length; i++)
tabs[i].toggleClass("is-active", !this.query && i === this.activeGroup);
}
renderGrid() {
this.gridEl.empty();
this.updateTabHighlight();
let items;
if (this.query) {
let terms = this.query.split(/\s+/);
items = getAllItems().filter((item) => {
let text2 = (item.name + " " + item.emoji).toLowerCase();
return terms.every((t) => text2.includes(t));
});
} else {
let group = GROUPS[this.activeGroup];
items = group.emojis.map((e) => ({ emoji: e, name: EMOJI_NAMES[e] || "" }));
}
if (items.length === 0) {
this.gridEl.createDiv({ cls: "vf-icon-empty", text: "Nothing found" });
return;
}
let fragment = document.createDocumentFragment();
for (let item of items) {
let cell = document.createElement("div");
cell.className = "vf-icon-cell";
cell.textContent = item.emoji;
cell.dataset.emoji = item.emoji;
if (item.name)
cell.title = item.name;
fragment.appendChild(cell);
}
this.gridEl.appendChild(fragment);
}
};
// components/Note.svelte
function get_each_context(ctx, list, i) {
const child_ctx = ctx.slice();
child_ctx[43] = list[i];
child_ctx[44] = list;
child_ctx[45] = i;
return child_ctx;
}
function create_if_block_4(ctx) {
let div;
let collapsedIcon_action;
let mounted;
let dispose;
return {
c() {
div = element("div");
attr(div, "class", "tree-item-icon collapse-icon");
toggle_class(
div,
"is-collapsed",
/*isCollapsed*/
ctx[6]
);
},
m(target, anchor) {
insert(target, div, anchor);
if (!mounted) {
dispose = [
listen(div, "click", stop_propagation(
/*click_handler*/
ctx[34]
)),
action_destroyer(collapsedIcon_action = /*collapsedIcon*/
ctx[17].call(null, div))
];
mounted = true;
}
},
p(ctx2, dirty) {
if (dirty[0] & /*isCollapsed*/
64) {
toggle_class(
div,
"is-collapsed",
/*isCollapsed*/
ctx2[6]
);
}
},
d(detaching) {
if (detaching) {
detach(div);
}
mounted = false;
run_all(dispose);
}
};
}
function create_if_block_3(ctx) {
let span;
let t;
return {
c() {
span = element("span");
t = text(
/*noteIcon*/
ctx[4]
);
attr(span, "class", "vf-note-icon");
},
m(target, anchor) {
insert(target, span, anchor);
append(span, t);
},
p(ctx2, dirty) {
if (dirty[0] & /*noteIcon*/
16)
set_data(
t,
/*noteIcon*/
ctx2[4]
);
},
d(detaching) {
if (detaching) {
detach(span);
}
}
};
}
function create_if_block_2(ctx) {
let span;
return {
c() {
span = element("span");
span.textContent = "\u{1F4CC}";
attr(span, "class", "vf-pin-icon");
},
m(target, anchor) {
insert(target, span, anchor);
},
d(detaching) {
if (detaching) {
detach(span);
}
}
};
}
function create_if_block_1(ctx) {
let span;
let t;
return {
c() {
span = element("span");
t = text(
/*childCounter*/
ctx[8]
);
attr(span, "class", "vf-counter");
},
m(target, anchor) {
insert(target, span, anchor);
append(span, t);
},
p(ctx2, dirty) {
if (dirty[0] & /*childCounter*/
256)
set_data(
t,
/*childCounter*/
ctx2[8]
);
},
d(detaching) {
if (detaching) {
detach(span);
}
}
};
}
function create_if_block(ctx) {
let div;
let each_blocks = [];
let each_1_lookup = /* @__PURE__ */ new Map();
let div_transition;
let current;
let mounted;
let dispose;
let each_value = ensure_array_like(
/*childList*/
ctx[9]
);
const get_key = (ctx2) => (
/*child*/
ctx2[43]
);
for (let i = 0; i < each_value.length; i += 1) {
let child_ctx = get_each_context(ctx, each_value, i);
let key = get_key(child_ctx);
each_1_lookup.set(key, each_blocks[i] = create_each_block(key, child_ctx));
}
return {
c() {
div = element("div");
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].c();
}
attr(div, "class", "tree-item-children");
},
m(target, anchor) {
insert(target, div, anchor);
for (let i = 0; i < each_blocks.length; i += 1) {
if (each_blocks[i]) {
each_blocks[i].m(div, null);
}
}
current = true;
if (!mounted) {
dispose = [
listen(
div,
"introstart",
/*expandTransitionStart*/
ctx[18]
),
listen(
div,
"introend",
/*introend_handler*/
ctx[37]
)
];
mounted = true;
}
},
p(ctx2, dirty) {
if (dirty[0] & /*childList, build_path, children*/
526848) {
each_value = ensure_array_like(
/*childList*/
ctx2[9]
);
group_outros();
each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx2, each_value, each_1_lookup, div, outro_and_destroy_block, create_each_block, null, get_each_context);
check_outros();
}
},
i(local) {
if (current)
return;
for (let i = 0; i < each_value.length; i += 1) {
transition_in(each_blocks[i]);
}
if (local) {
add_render_callback(() => {
if (!current)
return;
if (!div_transition)
div_transition = create_bidirectional_transition(div, slide, { duration: 100 }, true);
div_transition.run(1);
});
}
current = true;
},
o(local) {
for (let i = 0; i < each_blocks.length; i += 1) {
transition_out(each_blocks[i]);
}
if (local) {
if (!div_transition)
div_transition = create_bidirectional_transition(div, slide, { duration: 100 }, false);
div_transition.run(0);
}
current = false;
},
d(detaching) {
if (detaching) {
detach(div);
}
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].d();
}
if (detaching && div_transition)
div_transition.end();
mounted = false;
run_all(dispose);
}
};
}
function create_each_block(key_1, ctx) {
let first;
let note_1;
let child = (
/*child*/
ctx[43]
);
let current;
const assign_note_1 = () => (
/*note_1_binding*/
ctx[36](note_1, child)
);
const unassign_note_1 = () => (
/*note_1_binding*/
ctx[36](null, child)
);
let note_1_props = {
id: (
/*child*/
ctx[43]
),
node_path: (
/*build_path*/
ctx[19](
/*child*/
ctx[43]
)
)
};
note_1 = new Note({ props: note_1_props });
assign_note_1();
return {
key: key_1,
first: null,
c() {
first = empty();
create_component(note_1.$$.fragment);
this.first = first;
},
m(target, anchor) {
insert(target, first, anchor);
mount_component(note_1, target, anchor);
current = true;
},
p(new_ctx, dirty) {
ctx = new_ctx;
if (child !== /*child*/
ctx[43]) {
unassign_note_1();
child = /*child*/
ctx[43];
assign_note_1();
}
const note_1_changes = {};
if (dirty[0] & /*childList*/
512)
note_1_changes.id = /*child*/
ctx[43];
if (dirty[0] & /*childList*/
512)
note_1_changes.node_path = /*build_path*/
ctx[19](
/*child*/
ctx[43]
);
note_1.$set(note_1_changes);
},
i(local) {
if (current)
return;
transition_in(note_1.$$.fragment, local);
current = true;
},
o(local) {
transition_out(note_1.$$.fragment, local);
current = false;
},
d(detaching) {
if (detaching) {
detach(first);
}
unassign_note_1();
destroy_component(note_1, detaching);
}
};
}
function create_fragment(ctx) {
let div2;
let div1;
let t0;
let div0;
let t1;
let t2;
let t3;
let t4;
let div1_class_value;
let div1_draggable_value;
let applyDataAttrs_action;
let t5;
let current;
let mounted;
let dispose;
let if_block0 = (
/*childCounter*/
ctx[8] > 0 && create_if_block_4(ctx)
);
let if_block1 = (
/*noteIcon*/
ctx[4] && create_if_block_3(ctx)
);
let if_block2 = (
/*isPinned*/
ctx[5] && create_if_block_2(ctx)
);
let if_block3 = (
/*childCounter*/
ctx[8] > 0 && create_if_block_1(ctx)
);
let if_block4 = (
/*childCounter*/
ctx[8] > 0 && !/*isCollapsed*/
ctx[6] && create_if_block(ctx)
);
return {
c() {
div2 = element("div");
div1 = element("div");
if (if_block0)
if_block0.c();
t0 = space();
div0 = element("div");
if (if_block1)
if_block1.c();
t1 = space();
t2 = text(
/*title*/
ctx[3]
);
t3 = space();
if (if_block2)
if_block2.c();
t4 = space();
if (if_block3)
if_block3.c();
t5 = space();
if (if_block4)
if_block4.c();
attr(div0, "class", "tree-item-inner");
attr(div1, "class", div1_class_value = "tree-item-self is-clickable mod-collapsible " + /*IsOpened*/
(ctx[2] ? "vf-current-note" : ""));
attr(
div1,
"style",
/*tagHighlightStyle*/
ctx[14]
);
attr(div1, "draggable", div1_draggable_value = /*type*/
ctx[1] === "sub_note");
toggle_class(
div1,
"vf-tag-highlight",
/*tagHighlightStyle*/
ctx[14] !== ""
);
toggle_class(
div1,
"vf-drop-target",
/*dropMode*/
ctx[13] === "target"
);
toggle_class(
div1,
"vf-drop-before",
/*dropMode*/
ctx[13] === "before"
);
toggle_class(
div1,
"vf-drop-after",
/*dropMode*/
ctx[13] === "after"
);
attr(div2, "class", "tree-item is-clickable");
},
m(target, anchor) {
insert(target, div2, anchor);
append(div2, div1);
if (if_block0)
if_block0.m(div1, null);
append(div1, t0);
append(div1, div0);
if (if_block1)
if_block1.m(div0, null);
append(div0, t1);
append(div0, t2);
append(div0, t3);
if (if_block2)
if_block2.m(div0, null);
append(div1, t4);
if (if_block3)
if_block3.m(div1, null);
append(div2, t5);
if (if_block4)
if_block4.m(div2, null);
ctx[38](div2);
current = true;
if (!mounted) {
dispose = [
action_destroyer(applyDataAttrs_action = /*applyDataAttrs*/
ctx[16].call(
null,
div1,
/*dataAttrs*/
ctx[7]
)),
listen(
div1,
"dragstart",
/*handleDragStart*/
ctx[21]
),
listen(div1, "dragover", prevent_default(
/*handleDragOver*/
ctx[22]
)),
listen(
div1,
"dragleave",
/*handleDragLeave*/
ctx[23]
),
listen(
div1,
"drop",
/*handleDrop*/
ctx[24]
),
listen(
div1,
"contextmenu",
/*handleContextMenu*/
ctx[25]
),
listen(
div1,
"click",
/*click_handler_1*/
ctx[35]
)
];
mounted = true;
}
},
p(ctx2, dirty) {
if (
/*childCounter*/
ctx2[8] > 0
) {
if (if_block0) {
if_block0.p(ctx2, dirty);
} else {
if_block0 = create_if_block_4(ctx2);
if_block0.c();
if_block0.m(div1, t0);
}
} else if (if_block0) {
if_block0.d(1);
if_block0 = null;
}
if (
/*noteIcon*/
ctx2[4]
) {
if (if_block1) {
if_block1.p(ctx2, dirty);
} else {
if_block1 = create_if_block_3(ctx2);
if_block1.c();
if_block1.m(div0, t1);
}
} else if (if_block1) {
if_block1.d(1);
if_block1 = null;
}
if (!current || dirty[0] & /*title*/
8)
set_data(
t2,
/*title*/
ctx2[3]
);
if (
/*isPinned*/
ctx2[5]
) {
if (if_block2) {
} else {
if_block2 = create_if_block_2(ctx2);
if_block2.c();
if_block2.m(div0, null);
}
} else if (if_block2) {
if_block2.d(1);
if_block2 = null;
}
if (
/*childCounter*/
ctx2[8] > 0
) {
if (if_block3) {
if_block3.p(ctx2, dirty);
} else {
if_block3 = create_if_block_1(ctx2);
if_block3.c();
if_block3.m(div1, null);
}
} else if (if_block3) {
if_block3.d(1);
if_block3 = null;
}
if (!current || dirty[0] & /*IsOpened*/
4 && div1_class_value !== (div1_class_value = "tree-item-self is-clickable mod-collapsible " + /*IsOpened*/
(ctx2[2] ? "vf-current-note" : ""))) {
attr(div1, "class", div1_class_value);
}
if (!current || dirty[0] & /*tagHighlightStyle*/
16384) {
attr(
div1,
"style",
/*tagHighlightStyle*/
ctx2[14]
);
}
if (!current || dirty[0] & /*type*/
2 && div1_draggable_value !== (div1_draggable_value = /*type*/
ctx2[1] === "sub_note")) {
attr(div1, "draggable", div1_draggable_value);
}
if (applyDataAttrs_action && is_function(applyDataAttrs_action.update) && dirty[0] & /*dataAttrs*/
128)
applyDataAttrs_action.update.call(
null,
/*dataAttrs*/
ctx2[7]
);
if (!current || dirty[0] & /*IsOpened, tagHighlightStyle*/
16388) {
toggle_class(
div1,
"vf-tag-highlight",
/*tagHighlightStyle*/
ctx2[14] !== ""
);
}
if (!current || dirty[0] & /*IsOpened, dropMode*/
8196) {
toggle_class(
div1,
"vf-drop-target",
/*dropMode*/
ctx2[13] === "target"
);
}
if (!current || dirty[0] & /*IsOpened, dropMode*/
8196) {
toggle_class(
div1,
"vf-drop-before",
/*dropMode*/
ctx2[13] === "before"
);
}
if (!current || dirty[0] & /*IsOpened, dropMode*/
8196) {
toggle_class(
div1,
"vf-drop-after",
/*dropMode*/
ctx2[13] === "after"
);
}
if (
/*childCounter*/
ctx2[8] > 0 && !/*isCollapsed*/
ctx2[6]
) {
if (if_block4) {
if_block4.p(ctx2, dirty);
if (dirty[0] & /*childCounter, isCollapsed*/
320) {
transition_in(if_block4, 1);
}
} else {
if_block4 = create_if_block(ctx2);
if_block4.c();
transition_in(if_block4, 1);
if_block4.m(div2, null);
}
} else if (if_block4) {
group_outros();
transition_out(if_block4, 1, 1, () => {
if_block4 = null;
});
check_outros();
}
},
i(local) {
if (current)
return;
transition_in(if_block4);
current = true;
},
o(local) {
transition_out(if_block4);
current = false;
},
d(detaching) {
if (detaching) {
detach(div2);
}
if (if_block0)
if_block0.d();
if (if_block1)
if_block1.d();
if (if_block2)
if_block2.d();
if (if_block3)
if_block3.d();
if (if_block4)
if_block4.d();
ctx[38](null);
mounted = false;
run_all(dispose);
}
};
}
function instance($$self, $$props, $$invalidate) {
let tagHighlightStyle;
let $data;
let $active_id;
component_subscribe($$self, data, ($$value) => $$invalidate(32, $data = $$value));
component_subscribe($$self, active_id, ($$value) => $$invalidate(33, $active_id = $$value));
let { id = "unknown-link-id" } = $$props;
let { type = "sub_note" } = $$props;
let { node_path = [] } = $$props;
let plugin2 = getPlugin();
let note;
let title = id;
let noteIcon = "";
let isPinned = false;
let isCollapsed = true;
let IsOpened = false;
let highlightColor = "";
let highlightOpacity = 0;
let dataAttrs = {};
let childCounter = 0;
let childList = [];
let myElement;
const children2 = {};
const applyDataAttrs = function(node, attrs) {
let prev = [];
function update2(newAttrs) {
for (let key of prev)
node.removeAttribute(key);
prev = Object.keys(newAttrs);
for (let key of prev)
node.setAttribute(key, newAttrs[key]);
}
update2(attrs);
return { update: update2 };
};
const collapsedIcon = function(node) {
node.appendChild((0, import_obsidian6.getIcon)("right-triangle"));
};
let expandTransitionWaiter = Promise.resolve();
let expandTransitionEnd;
function expandTransitionStart() {
expandTransitionWaiter = new Promise((resolve) => {
$$invalidate(12, expandTransitionEnd = resolve);
});
}
function build_path(id2) {
return node_path.concat([id2]);
}
function openNote(id2, new_tab = false) {
if (type == "top_dir" || type == "orphan_dir") {
return;
}
plugin2.app.workspace.openLinkText(id2, id2, new_tab);
}
function scrollIntoMiddle() {
let scrollable = myElement.closest(".view-content");
if (!scrollable)
return;
let elementRect = myElement.getBoundingClientRect();
let containerRect = scrollable.getBoundingClientRect();
let elementTopRelative = elementRect.top - containerRect.top + scrollable.scrollTop;
let elementHeight = elementRect.height;
let containerHeight = containerRect.height;
if (elementHeight <= containerHeight) {
let targetTop = elementTopRelative - containerHeight / 2 + elementHeight / 2;
scrollable.scrollTop = targetTop;
} else {
scrollable.scrollTop = elementTopRelative;
}
}
let dropMode = "none";
function getDragParentId() {
let parentId = node_path[node_path.length - 2];
if (parentId === "top_dir" || parentId === "orphan_dir")
return null;
return parentId;
}
function getRawParentId() {
return node_path.length >= 2 ? node_path[node_path.length - 2] : null;
}
function handleDragStart(event) {
if (type !== "sub_note" || !event.dataTransfer)
return;
event.dataTransfer.setData("text/plain", JSON.stringify({
id,
parentId: getDragParentId(),
rawParentId: getRawParentId()
}));
event.dataTransfer.effectAllowed = "move";
}
function handleDragOver(event) {
event.preventDefault();
if (event.dataTransfer)
event.dataTransfer.dropEffect = "move";
if (plugin2.settings.sortTreeBy === "custom" /* custom */ && type === "sub_note") {
let rect = event.currentTarget.getBoundingClientRect();
$$invalidate(13, dropMode = event.clientY < rect.top + rect.height / 2 ? "before" : "after");
} else {
$$invalidate(13, dropMode = "target");
}
}
function handleDragLeave() {
$$invalidate(13, dropMode = "none");
}
function handleDrop(event) {
event.preventDefault();
$$invalidate(13, dropMode = "none");
if (!event.dataTransfer)
return;
let dragData;
try {
dragData = JSON.parse(event.dataTransfer.getData("text/plain"));
} catch (_a) {
return;
}
let draggedId = dragData.id;
let oldParentId = dragData.parentId;
let draggedRawParent = dragData.rawParentId;
if (draggedId === id || node_path.includes(draggedId)) {
new import_obsidian6.Notice("Can't move a folder into itself");
return;
}
let myRawParent = getRawParentId();
if (draggedRawParent && draggedRawParent === myRawParent && plugin2.settings.sortTreeBy === "custom" /* custom */ && type === "sub_note") {
let rect = event.currentTarget.getBoundingClientRect();
let insertBefore = event.clientY < rect.top + rect.height / 2;
plugin2.reorderNote(draggedId, id, draggedRawParent, insertBefore);
return;
}
let newParentId = null;
if (type === "sub_note")
newParentId = id;
if (oldParentId === newParentId)
return;
plugin2.moveNoteToFolder(draggedId, oldParentId, newParentId);
}
function handleContextMenu(event) {
var _a, _b;
if (type !== "sub_note" && type !== "top_dir")
return;
event.preventDefault();
const menu = new import_obsidian6.Menu();
let folderId = type === "top_dir" ? null : id;
menu.addItem((item) => {
item.setTitle("Create note").setIcon("plus").onClick(() => {
plugin2.createNoteInFolder(folderId);
});
});
if ((_b = (_a = plugin2.app.internalPlugins) === null || _a === void 0 ? void 0 : _a.getPluginById("zk-prefixer")) === null || _b === void 0 ? void 0 : _b.enabled) {
menu.addItem((item) => {
item.setTitle("Create unique note").setIcon("fingerprint").onClick(() => {
plugin2.createNoteInFolder(folderId, true);
});
});
}
if (type === "sub_note") {
let file = plugin2.app.vault.getFileByPath(id);
if (file) {
menu.addItem((item) => {
item.setTitle("Manage icon").setIcon("image").onClick(() => {
new VF_IconPickerModal(
plugin2,
(icon) => {
let f = plugin2.app.vault.getFileByPath(id);
if (!f)
return;
plugin2.yaml.set_icon(f, icon);
plugin2.update_data();
}
).open();
});
});
let isPinned2 = note ? note.is_pinned : false;
menu.addItem((item) => {
item.setTitle(isPinned2 ? "Unpin note" : "Pin note").setIcon("pin").onClick(() => {
let f = plugin2.app.vault.getFileByPath(id);
if (!f)
return;
plugin2.yaml.toggle_pin(f, !isPinned2);
plugin2.update_data();
});
});
}
menu.addSeparator();
menu.addItem((item) => {
item.setTitle("Delete note").setIcon("trash-2").onClick(() => {
plugin2.deleteNote(id);
});
});
if (note && note.has_children()) {
menu.addItem((item) => {
item.setTitle("Delete with children").setIcon("trash-2").onClick(() => {
plugin2.deleteNoteRecursive(id);
});
});
}
}
menu.showAtMouseEvent(event);
}
const collapse = () => {
$$invalidate(6, isCollapsed = true);
};
const focusNotes = (pathNotes) => __awaiter(void 0, void 0, void 0, function* () {
$$invalidate(6, isCollapsed = false);
yield tick();
let next = pathNotes.shift();
if (next && plugin2.settings.autoCollapse) {
for (let key in children2) {
if (key !== next)
children2[key].collapse();
}
}
if (pathNotes.length === 0)
yield expandTransitionWaiter;
if (!next) {
if (myElement) {
scrollIntoMiddle();
}
return;
}
if (next in children2) {
children2[next].focusNotes(pathNotes);
}
});
const click_handler = () => {
$$invalidate(6, isCollapsed = !isCollapsed);
};
const click_handler_1 = (event) => {
if (event.shiftKey) {
openNote(id, false);
return;
}
if (event.ctrlKey) {
openNote(id, true);
return;
}
if (plugin2.settings.expandOnClick)
$$invalidate(6, isCollapsed = !isCollapsed);
openNote(id);
};
function note_1_binding($$value, child) {
binding_callbacks[$$value ? "unshift" : "push"](() => {
children2[child] = $$value;
$$invalidate(11, children2);
});
}
const introend_handler = () => {
expandTransitionEnd();
};
function div2_binding($$value) {
binding_callbacks[$$value ? "unshift" : "push"](() => {
myElement = $$value;
$$invalidate(10, myElement);
});
}
$$self.$$set = ($$props2) => {
if ("id" in $$props2)
$$invalidate(0, id = $$props2.id);
if ("type" in $$props2)
$$invalidate(1, type = $$props2.type);
if ("node_path" in $$props2)
$$invalidate(26, node_path = $$props2.node_path);
};
$$self.$$.update = () => {
if ($$self.$$.dirty[0] & /*id, type, note*/
536870915 | $$self.$$.dirty[1] & /*$active_id, $data*/
6) {
$: {
$$invalidate(2, IsOpened = id == $active_id);
if (type == "top_dir") {
$$invalidate(3, title = "ROOT");
$$invalidate(8, childCounter = $data.top_list.length);
$$invalidate(9, childList = $data.top_list);
$$invalidate(7, dataAttrs = {});
}
if (type == "orphan_dir") {
$$invalidate(3, title = "Orphans");
$$invalidate(8, childCounter = $data.orphans_list.length);
$$invalidate(9, childList = $data.orphans_list);
$$invalidate(7, dataAttrs = {});
}
if (type == "sub_note") {
$$invalidate(29, note = $data.note_list[id]);
if (note) {
$$invalidate(3, title = note.title);
$$invalidate(4, noteIcon = note.icon || "");
$$invalidate(5, isPinned = note.is_pinned);
$$invalidate(30, highlightColor = note.highlight_color || "");
$$invalidate(31, highlightOpacity = note.highlight_opacity || 0);
$$invalidate(8, childCounter = note.count_children());
$$invalidate(9, childList = note.children);
let attrs = {};
for (let key in note.metadata) {
attrs["data-" + key] = note.metadata[key];
}
$$invalidate(7, dataAttrs = attrs);
}
}
}
}
if ($$self.$$.dirty[0] & /*highlightColor, IsOpened*/
1073741828 | $$self.$$.dirty[1] & /*highlightOpacity*/
1) {
$:
$$invalidate(14, tagHighlightStyle = highlightColor && highlightOpacity > 0 && !IsOpened ? `background-color: color-mix(in srgb, ${highlightColor} ${highlightOpacity * 100}%, transparent)` : "");
}
};
return [
id,
type,
IsOpened,
title,
noteIcon,
isPinned,
isCollapsed,
dataAttrs,
childCounter,
childList,
myElement,
children2,
expandTransitionEnd,
dropMode,
tagHighlightStyle,
plugin2,
applyDataAttrs,
collapsedIcon,
expandTransitionStart,
build_path,
openNote,
handleDragStart,
handleDragOver,
handleDragLeave,
handleDrop,
handleContextMenu,
node_path,
collapse,
focusNotes,
note,
highlightColor,
highlightOpacity,
$data,
$active_id,
click_handler,
click_handler_1,
note_1_binding,
introend_handler,
div2_binding
];
}
var Note = class extends SvelteComponent {
constructor(options) {
super();
init(
this,
options,
instance,
create_fragment,
safe_not_equal,
{
id: 0,
type: 1,
node_path: 26,
collapse: 27,
focusNotes: 28
},
null,
[-1, -1]
);
}
get collapse() {
return this.$$.ctx[27];
}
get focusNotes() {
return this.$$.ctx[28];
}
};
var Note_default = Note;
// components/Component.svelte
function create_if_block2(ctx) {
let note;
let t;
let if_block_anchor;
let current;
let note_props = { type: "top_dir", node_path: ["top_dir"] };
note = new Note_default({ props: note_props });
ctx[3](note);
let if_block = (
/*$data*/
ctx[1].orphans_list.length && !/*$data*/
ctx[1].settings.hide_orphans && create_if_block_12(ctx)
);
return {
c() {
create_component(note.$$.fragment);
t = space();
if (if_block)
if_block.c();
if_block_anchor = empty();
},
m(target, anchor) {
mount_component(note, target, anchor);
insert(target, t, anchor);
if (if_block)
if_block.m(target, anchor);
insert(target, if_block_anchor, anchor);
current = true;
},
p(ctx2, dirty) {
const note_changes = {};
note.$set(note_changes);
if (
/*$data*/
ctx2[1].orphans_list.length && !/*$data*/
ctx2[1].settings.hide_orphans
) {
if (if_block) {
if_block.p(ctx2, dirty);
if (dirty & /*$data*/
2) {
transition_in(if_block, 1);
}
} else {
if_block = create_if_block_12(ctx2);
if_block.c();
transition_in(if_block, 1);
if_block.m(if_block_anchor.parentNode, if_block_anchor);
}
} else if (if_block) {
group_outros();
transition_out(if_block, 1, 1, () => {
if_block = null;
});
check_outros();
}
},
i(local) {
if (current)
return;
transition_in(note.$$.fragment, local);
transition_in(if_block);
current = true;
},
o(local) {
transition_out(note.$$.fragment, local);
transition_out(if_block);
current = false;
},
d(detaching) {
if (detaching) {
detach(t);
detach(if_block_anchor);
}
ctx[3](null);
destroy_component(note, detaching);
if (if_block)
if_block.d(detaching);
}
};
}
function create_if_block_12(ctx) {
let note;
let current;
let note_props = {
type: "orphan_dir",
node_path: ["orphan_dir"]
};
note = new Note_default({ props: note_props });
ctx[4](note);
return {
c() {
create_component(note.$$.fragment);
},
m(target, anchor) {
mount_component(note, target, anchor);
current = true;
},
p(ctx2, dirty) {
const note_changes = {};
note.$set(note_changes);
},
i(local) {
if (current)
return;
transition_in(note.$$.fragment, local);
current = true;
},
o(local) {
transition_out(note.$$.fragment, local);
current = false;
},
d(detaching) {
ctx[4](null);
destroy_component(note, detaching);
}
};
}
function create_fragment2(ctx) {
let if_block_anchor;
let current;
let if_block = (
/*$data*/
ctx[1] !== void 0 && create_if_block2(ctx)
);
return {
c() {
if (if_block)
if_block.c();
if_block_anchor = empty();
},
m(target, anchor) {
if (if_block)
if_block.m(target, anchor);
insert(target, if_block_anchor, anchor);
current = true;
},
p(ctx2, [dirty]) {
if (
/*$data*/
ctx2[1] !== void 0
) {
if (if_block) {
if_block.p(ctx2, dirty);
if (dirty & /*$data*/
2) {
transition_in(if_block, 1);
}
} else {
if_block = create_if_block2(ctx2);
if_block.c();
transition_in(if_block, 1);
if_block.m(if_block_anchor.parentNode, if_block_anchor);
}
} else if (if_block) {
group_outros();
transition_out(if_block, 1, 1, () => {
if_block = null;
});
check_outros();
}
},
i(local) {
if (current)
return;
transition_in(if_block);
current = true;
},
o(local) {
transition_out(if_block);
current = false;
},
d(detaching) {
if (detaching) {
detach(if_block_anchor);
}
if (if_block)
if_block.d(detaching);
}
};
}
function instance2($$self, $$props, $$invalidate) {
let $data;
component_subscribe($$self, data, ($$value) => $$invalidate(1, $data = $$value));
const children2 = {};
function focusTo(pathNotes) {
let first = pathNotes.shift();
if (!first || !(first in children2))
return;
children2[first].focusNotes(pathNotes);
}
function note_binding($$value) {
binding_callbacks[$$value ? "unshift" : "push"](() => {
children2["top_dir"] = $$value;
$$invalidate(0, children2);
});
}
function note_binding_1($$value) {
binding_callbacks[$$value ? "unshift" : "push"](() => {
children2["orphan_dir"] = $$value;
$$invalidate(0, children2);
});
}
return [children2, $data, focusTo, note_binding, note_binding_1];
}
var Component = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance2, create_fragment2, safe_not_equal, { focusTo: 2 });
}
get focusTo() {
return this.$$.ctx[2];
}
};
var Component_default = Component;
// tree_view.ts
var TREE_ICON = "folder-tree";
var VIEW_TYPE_VF = "virt-folder-view";
var VirtFolderView = class extends import_obsidian7.ItemView {
constructor(leaf, plugin2) {
super(leaf);
this.plugin = plugin2;
this.icon = TREE_ICON;
}
getViewType() {
return VIEW_TYPE_VF;
}
getDisplayText() {
return "VirtFolder";
}
async onOpen() {
plugin.set(this.plugin);
this.component = new Component_default({
target: this.contentEl
});
}
async onClose() {
this.component.$destroy();
}
getComponent() {
return this.component;
}
};
// yaml_parser.ts
var import_obsidian8 = require("obsidian");
var YamlParser = class {
constructor(app, plugin2) {
this.app = app;
this.plugin = plugin2;
}
showMessage(msg) {
new import_obsidian8.Notice(msg);
}
_ensure_array(front, prop) {
if (prop in front && front[prop] && !Array.isArray(front[prop])) {
front[prop] = [front[prop]];
}
}
_normalize_prop(front, prop) {
if (!this.plugin.settings.folderAsString)
return;
if (!(prop in front) || !front[prop])
return;
if (Array.isArray(front[prop]) && front[prop].length === 1) {
front[prop] = front[prop][0];
}
}
_fm_add_link(front, selected, prop) {
let file = this.app.vault.getFileByPath(selected);
if (!file)
return;
let link = this.app.metadataCache.fileToLinktext(file, "");
let formated_link = `[[${link}]]`;
if (!this.plugin.settings.UseWikiLinks) {
formated_link = `[${link}](${link})`;
}
this._ensure_array(front, prop);
if (prop in front && front[prop]) {
if (front[prop].contains(formated_link)) {
this.showMessage(`${prop}'s link already exist`);
return;
}
} else {
front[prop] = [];
}
front[prop].push(formated_link);
this._normalize_prop(front, prop);
this.showMessage(`Set ${prop}: ${link}`);
}
add_link(yamlProp, file_id) {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
this.app.fileManager.processFrontMatter(file, (fm) => {
this._fm_add_link(fm, file_id, yamlProp);
});
}
add_link_to_file(file, yamlProp, file_id) {
this.app.fileManager.processFrontMatter(file, (fm) => {
this._fm_add_link(fm, file_id, yamlProp);
});
}
_fm_replace_link(front, selected, prop, old_link) {
let file = this.app.vault.getFileByPath(selected);
if (!file)
return;
let link = this.app.metadataCache.fileToLinktext(file, "");
let formated_link = `[[${link}]]`;
if (!this.plugin.settings.UseWikiLinks) {
formated_link = `[${link}](${link})`;
}
this._ensure_array(front, prop);
if (prop in front && front[prop]) {
if (front[prop].contains(formated_link)) {
this.showMessage(`${prop}'s link already exist`);
return;
}
if (!front[prop].contains(old_link)) {
this.showMessage(`Can't find ${old_link} in ${prop}`);
return;
}
let i = front[prop].indexOf(old_link);
front[prop][i] = formated_link;
this._normalize_prop(front, prop);
this.showMessage(`Set ${prop}: ${link}`);
} else {
front[prop] = [formated_link];
this._normalize_prop(front, prop);
this.showMessage(`Set ${prop}: ${link}`);
}
}
replace_link(yamlProp, old_link, file_id) {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
this.app.fileManager.processFrontMatter(file, (fm) => {
this._fm_replace_link(fm, file_id, yamlProp, old_link);
});
}
_fm_get_links(front, prop) {
if (prop in front && front[prop]) {
if (Array.isArray(front[prop]))
return front[prop];
return [front[prop]];
} else {
return [];
}
}
get_links(yamlProp, callback) {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
this.app.fileManager.processFrontMatter(file, (fm) => {
callback(this._fm_get_links(fm, yamlProp));
});
}
_fm_remove_link(front, prop, old_link) {
this._ensure_array(front, prop);
if (prop in front && front[prop]) {
if (front[prop].contains(old_link)) {
front[prop].remove(old_link);
this._normalize_prop(front, prop);
this.showMessage(`${prop}'s link removed`);
} else {
this.showMessage(`${prop}'s link not exist`);
}
}
}
remove_link(yamlProp, old_link) {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
this.app.fileManager.processFrontMatter(file, (fm) => {
this._fm_remove_link(fm, yamlProp, old_link);
});
}
_extract_link_base(link) {
let regexp = /(?:\[\[(.+?)\||\[\[(.+?)\]\]|\[.+?\]\((.+?)\))/;
let match = regexp.exec(link);
if (!match)
return null;
return match[1] || match[2] || match[3] || null;
}
_find_link_for_path(front, prop, targetPath) {
if (!(prop in front) || !front[prop])
return null;
let links = Array.isArray(front[prop]) ? front[prop] : [front[prop]];
for (let rawLink of links) {
let linkBase = this._extract_link_base(rawLink);
if (!linkBase)
continue;
let resolved = this.app.metadataCache.getFirstLinkpathDest(linkBase, "");
if (resolved && resolved.path === targetPath)
return rawLink;
}
return null;
}
set_icon(file, icon) {
this.app.fileManager.processFrontMatter(file, (fm) => {
if (icon) {
fm[this.plugin.settings.iconProp] = icon;
this.showMessage(`Icon set: ${icon}`);
} else {
delete fm[this.plugin.settings.iconProp];
this.showMessage("Icon removed");
}
});
}
toggle_pin(file, pin) {
this.app.fileManager.processFrontMatter(file, (fm) => {
if (pin) {
fm["vf_pinned"] = true;
this.showMessage("Note pinned");
} else {
delete fm["vf_pinned"];
this.showMessage("Note unpinned");
}
});
}
move_to_folder(noteFile, yamlProp, oldParentPath, newParentPath) {
this.app.fileManager.processFrontMatter(noteFile, (fm) => {
this._ensure_array(fm, yamlProp);
if (oldParentPath) {
let rawLink = this._find_link_for_path(fm, yamlProp, oldParentPath);
if (rawLink) {
fm[yamlProp].remove(rawLink);
}
}
if (newParentPath) {
this._fm_add_link(fm, newParentPath, yamlProp);
} else if (oldParentPath) {
this._normalize_prop(fm, yamlProp);
this.showMessage(`${yamlProp}'s link removed`);
}
});
}
};
// main.ts
var VirtFolderPlugin = class extends import_obsidian9.Plugin {
constructor() {
super(...arguments);
this.isFirstRun = false;
this.onOpenFile = (file) => {
this.setActiveFile(file);
if (this.settings.autoReveal && file) {
let path = this.base.get_next_path(file.path);
if (path)
this.revealFile(path);
}
};
this.onCreateFile = (file) => {
if (file instanceof import_obsidian9.TFile && file.extension === "md") {
this.data.onCreate(file);
this.update_data();
}
};
this.onDeleteFile = (file) => {
if (file instanceof import_obsidian9.TFile && file.extension === "md") {
this.data.onDelete(file);
this.update_data();
}
};
this.onRenameFile = (file, oldPath) => {
if (file instanceof import_obsidian9.TFile && file.extension === "md") {
for (let key in this.settings.customOrder) {
let order = this.settings.customOrder[key];
let idx = order.indexOf(oldPath);
if (idx !== -1)
order[idx] = file.path;
}
if (oldPath in this.settings.customOrder) {
this.settings.customOrder[file.path] = this.settings.customOrder[oldPath];
delete this.settings.customOrder[oldPath];
}
this.saveSettings();
this.data.onRename(file, oldPath);
this.update_data();
}
};
this.onResolveMetadata = (file) => {
let activeFile = this.app.workspace.getActiveFile();
let isActive = !!activeFile && activeFile.path === file.path;
let oldPath = isActive ? this.base.get_shortest_path(file.path) : void 0;
this.data.onChange(file);
this.update_data();
if (isActive) {
let newPath = this.base.get_shortest_path(file.path);
let relocated = (oldPath ? oldPath.join("/") : "") !== (newPath ? newPath.join("/") : "");
if (relocated && newPath) {
let path = this.base.get_next_path(file.path);
if (path)
this.revealFile(path);
}
}
};
}
async onload() {
await this.loadSettings();
this.base = new BaseScanner(this.app, this);
this.data = new NoteData(this.base);
this.yaml = new YamlParser(this.app, this);
this.addSettingTab(new VirtFolderSettingTab(this.app, this));
this.registerView(
VIEW_TYPE_VF,
(leaf) => new VirtFolderView(leaf, this)
);
this.addCommand({
id: "open_tree_view",
name: "Show tree",
icon: "folder-tree",
callback: () => {
this.VF_OpenTreeView();
}
});
this.addCommand({
id: "add_folder",
name: "Add folder",
icon: "folder-plus",
callback: () => {
this.VF_AddFolder();
}
});
this.addCommand({
id: "replace_folder",
name: "Move folder",
icon: "folder-output",
callback: () => {
this.VF_MoveFolder();
}
});
this.addCommand({
id: "remove_folder",
name: "Delete folder",
icon: "folder-minus",
callback: () => {
this.VF_RemoveFolder();
}
});
this.addCommand({
id: "reveal_active_file",
name: "Reveal file",
icon: "folder-search-2",
callback: () => {
this.VF_RevealActiveFile();
}
});
this.addCommand({
id: "add_selected_to_folder",
name: "Add selected files to virtual folder",
icon: "folder-plus",
callback: () => {
var _a;
let files = [];
let leaves = this.app.workspace.getLeavesOfType("file-explorer");
if (leaves.length > 0) {
let view = leaves[0].view;
if ((_a = view.tree) == null ? void 0 : _a.selectedDoms) {
for (let dom of view.tree.selectedDoms.values()) {
if (dom.file instanceof import_obsidian9.TFile)
files.push(dom.file);
}
}
}
if (files.length === 0) {
let file = this.app.workspace.getActiveFile();
if (file)
files.push(file);
}
if (files.length === 0)
return;
this.VF_AddFilesToFolder(files);
}
});
this.addCommand({
id: "manage_icon",
name: "Manage icon",
icon: "image",
callback: () => {
this.VF_SetIcon();
}
});
this.addCommand({
id: "pin_note",
name: "Pin note",
icon: "pin",
callback: () => {
this.VF_TogglePin();
}
});
this.addCommand({
id: "navigate_parent",
name: "Navigate to parent folder",
icon: "arrow-up",
callback: () => {
this.VF_NavigateToParent();
}
});
this.addCommand({
id: "navigate_next",
name: "Navigate to next sibling",
icon: "arrow-down",
callback: () => {
this.VF_NavigateToSibling(1);
}
});
this.addCommand({
id: "navigate_prev",
name: "Navigate to previous sibling",
icon: "arrow-up",
callback: () => {
this.VF_NavigateToSibling(-1);
}
});
this.addCommand({
id: "navigate_child",
name: "Navigate to first child",
icon: "arrow-down",
callback: () => {
this.VF_NavigateToChild();
}
});
this.registerView(VIEW_TYPE_VF_WHATSNEW, (leaf) => new VF_WhatsNewView(leaf, this.manifest.version));
this.addCommand({
id: "whatsnew",
name: "What's new",
icon: "info",
callback: () => {
this.app.workspace.getLeaf("tab").setViewState({
type: VIEW_TYPE_VF_WHATSNEW,
active: true
});
}
});
this.app.workspace.onLayoutReady(async () => {
this.data.onStartApp();
this.update_data();
let activeFile = this.app.workspace.getActiveFile();
if (activeFile) {
this.setActiveFile(activeFile);
let path = this.base.get_next_path(activeFile.path);
if (path)
this.revealFile(path);
}
if (this.isFirstRun) {
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_VF);
if (leaves.length === 0)
this.activateView();
}
this.registerEvent(this.app.metadataCache.on("resolve", this.onResolveMetadata));
this.registerEvent(this.app.workspace.on("file-open", this.onOpenFile, this));
this.registerEvent(this.app.vault.on("create", this.onCreateFile));
this.registerEvent(this.app.vault.on("delete", this.onDeleteFile));
this.registerEvent(this.app.vault.on("rename", this.onRenameFile));
this.registerEvent(this.app.workspace.on("file-menu", (menu, file, source) => {
if (!(file instanceof import_obsidian9.TFile))
return;
menu.addItem((item) => {
item.setTitle("Add to virtual folder").setIcon("folder-plus").onClick(() => {
this.VF_AddFilesToFolder([file]);
});
});
menu.addItem((item) => {
item.setTitle("Manage icon").setIcon("image").onClick(() => {
new VF_IconPickerModal(this, (icon) => {
this.yaml.set_icon(file, icon);
this.update_data();
}).open();
});
});
let note = this.base.note_by_id(file.path);
let isPinned = note ? note.is_pinned : false;
menu.addItem((item) => {
item.setTitle(isPinned ? "Unpin note" : "Pin note").setIcon("pin").onClick(() => {
this.yaml.toggle_pin(file, !isPinned);
this.update_data();
});
});
}));
this.registerEvent(this.app.workspace.on("files-menu", (menu, files, source) => {
let tfiles = files.filter((f) => f instanceof import_obsidian9.TFile);
if (tfiles.length === 0)
return;
menu.addItem((item) => {
item.setTitle("Add to virtual folder").setIcon("folder-plus").onClick(() => {
this.VF_AddFilesToFolder(tfiles);
});
});
}));
});
}
async loadSettings() {
let saved = await this.loadData();
this.isFirstRun = !saved;
this.settings = Object.assign({}, DEFAULT_SETTINGS, saved);
}
async saveSettings() {
await this.saveData(this.settings);
}
updateActiveFile() {
let file = this.app.workspace.getActiveFile();
if (file)
active_id.set(file.path);
else
active_id.set("");
}
setActiveFile(file) {
if (file instanceof import_obsidian9.TFile) {
active_id.set(file.path);
} else {
active_id.set("");
}
}
update_data() {
data.set(this.base);
this.updateActiveFile();
}
revealFile(path) {
for (const leaf of this.app.workspace.getLeavesOfType(VIEW_TYPE_VF)) {
if (!(leaf.view instanceof VirtFolderView))
continue;
leaf.view.component.focusTo(path);
}
}
async activateView() {
const { workspace } = this.app;
let leaf = null;
const leaves = workspace.getLeavesOfType(VIEW_TYPE_VF);
if (leaves.length > 0) {
leaf = leaves[0];
} else {
leaf = workspace.getLeftLeaf(false);
if (leaf)
await leaf.setViewState({ type: VIEW_TYPE_VF, active: true });
}
if (leaf)
workspace.revealLeaf(leaf);
}
VF_OpenTreeView() {
this.activateView();
}
async VF_RevealActiveFile() {
await this.activateView();
let file = this.app.workspace.getActiveFile();
if (!file)
return;
let path = this.base.get_next_path(file.path);
if (path)
this.revealFile(path);
}
updateUsedTime(file_id) {
this.base.note_list[file_id].utime = Date.now();
}
VF_TogglePin() {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
let note = this.base.note_by_id(file.path);
let isPinned = note ? note.is_pinned : false;
this.yaml.toggle_pin(file, !isPinned);
this.update_data();
}
VF_NavigateToChild() {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
let note = this.base.note_by_id(file.path);
if (!note || note.children.length === 0)
return;
this.app.workspace.openLinkText(note.children[0], note.children[0], false);
}
VF_NavigateToParent() {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
let note = this.base.note_by_id(file.path);
if (!note || note.parents.length === 0)
return;
this.app.workspace.openLinkText(note.parents[0], note.parents[0], false);
}
VF_GetSiblingList(noteId) {
let note = this.base.note_by_id(noteId);
if (!note)
return null;
if (note.parents.length > 0) {
let parentId = note.parents[0];
let lastActive = this.base.last_active;
if (lastActive.length >= 2) {
let lastParent = lastActive[lastActive.length - 2];
if (note.parents.includes(lastParent))
parentId = lastParent;
}
let parent = this.base.note_by_id(parentId);
if (!parent)
return null;
return parent.children;
}
if (note.has_children())
return this.base.top_list;
return this.base.orphans_list;
}
VF_NavigateToSibling(direction) {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
let list = this.VF_GetSiblingList(file.path);
if (!list || list.length < 2)
return;
let index = list.indexOf(file.path);
if (index === -1)
return;
let next = (index + direction + list.length) % list.length;
this.app.workspace.openLinkText(list[next], list[next], false);
}
VF_SetIcon() {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
new VF_IconPickerModal(this, (icon) => {
let activeFile = this.app.workspace.getActiveFile();
if (!activeFile)
return;
this.yaml.set_icon(activeFile, icon);
this.update_data();
}).open();
}
VF_AddFolder() {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
let excludeIds = this.base.get_all_descendants(file.path);
excludeIds.add(file.path);
new VF_SelectFile(
this,
(file_id) => {
this.yaml.add_link(this.settings.propertyName, file_id);
this.updateUsedTime(file_id);
this.update_data();
},
excludeIds
).open();
}
VF_AddFilesToFolder(files) {
let excludeIds = /* @__PURE__ */ new Set();
for (let file of files) {
excludeIds.add(file.path);
let descendants = this.base.get_all_descendants(file.path);
for (let d of descendants)
excludeIds.add(d);
}
new VF_SelectFile(
this,
(folder_id) => {
for (let file of files) {
this.yaml.add_link_to_file(file, this.settings.propertyName, folder_id);
}
this.updateUsedTime(folder_id);
this.update_data();
},
excludeIds
).open();
}
VF_MoveFolder() {
let file = this.app.workspace.getActiveFile();
if (!file)
return;
let excludeIds = this.base.get_all_descendants(file.path);
excludeIds.add(file.path);
new VF_SelectPropModal(
this,
this.settings.propertyName,
(old_link) => {
new VF_SelectFile(
this,
(file_id) => {
this.yaml.replace_link(this.settings.propertyName, old_link, file_id);
this.updateUsedTime(file_id);
this.update_data();
},
excludeIds
).open();
}
).open();
}
VF_RemoveFolder() {
new VF_SelectPropModal(
this,
this.settings.propertyName,
(old_link) => {
this.yaml.remove_link(this.settings.propertyName, old_link);
this.update_data();
}
).open();
}
async createNoteInFolder(parentId, unique = false) {
if (unique) {
let commands = this.app.commands;
if (!commands || !commands.executeCommandById) {
this.yaml.showMessage("Commands API is not available");
return;
}
let ref = this.app.vault.on("create", async (file2) => {
if (!(file2 instanceof import_obsidian9.TFile))
return;
this.app.vault.offref(ref);
if (parentId)
await this.app.fileManager.processFrontMatter(file2, (fm) => {
this.yaml._fm_add_link(fm, parentId, this.settings.propertyName);
});
let metaRef2 = this.app.metadataCache.on("resolve", (resolved) => {
if (resolved.path !== file2.path)
return;
this.app.metadataCache.offref(metaRef2);
this.update_data();
this.VF_RevealActiveFile();
});
});
let executed = commands.executeCommandById("zk-prefixer");
if (!executed) {
this.app.vault.offref(ref);
this.yaml.showMessage('Enable "Unique note creator" core plugin');
}
return;
}
let folder = this.app.fileManager.getNewFileParent("");
let prefix = folder.path === "/" ? "" : folder.path + "/";
let name = "Untitled";
let counter = 0;
let path = `${prefix}${name}.md`;
while (this.app.vault.getAbstractFileByPath(path)) {
counter++;
path = `${prefix}${name} ${counter}.md`;
}
let file = await this.app.vault.create(path, "");
if (parentId)
await this.app.fileManager.processFrontMatter(file, (fm) => {
this.yaml._fm_add_link(fm, parentId, this.settings.propertyName);
});
let metaRef = this.app.metadataCache.on("resolve", (resolved) => {
if (resolved.path !== path)
return;
this.app.metadataCache.offref(metaRef);
this.update_data();
this.VF_RevealActiveFile();
});
await this.app.workspace.openLinkText(path, path);
}
async deleteNote(noteId) {
let file = this.app.vault.getFileByPath(noteId);
if (!file)
return;
let doDelete = async () => {
await this.app.vault.trash(file, true);
new import_obsidian9.Notice("Note deleted");
this.update_data();
};
if (this.settings.confirmDelete) {
let note = this.base.note_by_id(noteId);
let displayName = note && this.settings.cmdShowTitle ? note.title : file.basename;
new VF_ConfirmModal(this.app, doDelete, "Delete note", `Delete "${displayName}"?`).open();
} else {
await doDelete();
}
}
async deleteNoteRecursive(noteId) {
let file = this.app.vault.getFileByPath(noteId);
if (!file)
return;
let descendants = this.base.get_all_descendants(noteId);
let allIds = [noteId, ...descendants];
let note = this.base.note_by_id(noteId);
let displayName = note && this.settings.cmdShowTitle ? note.title : file.basename;
let title = "Delete notes";
let message = `Delete "${displayName}" and ${descendants.size} nested notes?`;
if (descendants.size === 0) {
title = "Delete note";
message = `Delete "${displayName}"?`;
}
let doDelete = async () => {
for (let id of allIds) {
let f = this.app.vault.getFileByPath(id);
if (f)
await this.app.vault.trash(f, true);
}
new import_obsidian9.Notice(`${allIds.length} note(s) deleted`);
this.update_data();
};
new VF_ConfirmModal(this.app, doDelete, title, message).open();
}
moveNoteToFolder(noteId, oldParentId, newParentId) {
let noteFile = this.app.vault.getFileByPath(noteId);
if (!noteFile)
return;
this.yaml.move_to_folder(noteFile, this.settings.propertyName, oldParentId, newParentId);
if (newParentId) {
let note = this.base.note_by_id(newParentId);
if (note)
note.utime = Date.now();
}
this.update_data();
}
reorderNote(noteId, targetId, parentKey, insertBefore) {
let children2;
if (parentKey === "top_dir")
children2 = this.base.top_list;
else if (parentKey === "orphan_dir")
children2 = this.base.orphans_list;
else {
let parent = this.base.note_by_id(parentKey);
if (!parent)
return;
children2 = parent.children;
}
if (!this.settings.customOrder[parentKey]) {
this.settings.customOrder[parentKey] = [...children2];
}
let order = this.settings.customOrder[parentKey].filter((id) => id !== noteId);
let targetIdx = order.indexOf(targetId);
if (targetIdx === -1)
targetIdx = order.length - 1;
let insertIdx = insertBefore ? targetIdx : targetIdx + 1;
order.splice(insertIdx, 0, noteId);
this.settings.customOrder[parentKey] = order;
this.saveSettings();
this.base.sort_links();
this.update_data();
}
};
var VF_ConfirmModal = class extends import_obsidian9.Modal {
constructor(app, onConfirm, title = "Delete note", message = "") {
super(app);
this.onConfirm = onConfirm;
this.title = title;
this.message = message;
}
onOpen() {
this.titleEl.setText(this.title);
this.contentEl.createEl("p", { text: this.message });
new import_obsidian9.Setting(this.contentEl).addButton((btn) => {
btn.setButtonText("Delete").setWarning().onClick(() => {
this.close();
this.onConfirm();
});
}).addButton((btn) => {
btn.setButtonText("Cancel").onClick(() => {
this.close();
});
});
}
};
var VIEW_TYPE_VF_WHATSNEW = "virt-folder-whatsnew";
var WHATSNEW_MD = `
Thank you for using VirtFolder! \u2764\uFE0F This is an independent project, and every share helps new users discover it. If the plugin is useful to you, consider telling a friend or [starring the repo on GitHub](https://github.com/gr0grig/obsidian-virt-folder) \u2014 it really makes a difference!
---
## July 2026
- **Open without expanding** \u2014 clicking a note's title now opens it without toggling its children. Expand/collapse is done via the arrow icon. A setting (\`Expand/collapse on title click\`) restores the old click-to-toggle behavior.
- **Hide orphans** \u2014 optional setting to keep orphan notes (no parents, no children) out of the tree, useful for large vaults and keyboard navigation.
- **Reveal on folder change fix** \u2014 changing a note's folder property no longer hides it inside a collapsed branch; the active note is re-revealed at its new location.
## May 2026
- **Custom sort order** \u2014 manual note ordering via drag-and-drop in \`custom\` sort mode. Drag onto a sibling's top/bottom half to reorder. Order persists across sessions and survives renames.
- **Frontmatter as data attributes** \u2014 optional setting to expose all frontmatter as \`data-*\` HTML attributes on tree items, enabling CSS snippet styling based on any YAML property.
## April 2026
- **Tag-based highlighting** \u2014 color-coded note backgrounds based on tags. Configurable color and opacity per tag in settings.
- **Sibling navigation improvements** \u2014 Navigate next/previous sibling now stays within the current parent context for multi-parent notes.
- **Self-reference protection** \u2014 notes linking to themselves in the Folders property are now ignored, preventing them from disappearing from the tree.
- **Folder link as string** \u2014 optional setting to write single-parent folder links as a YAML string instead of a list. Auto-converts between string and list when parents change.
- **Click to collapse** \u2014 clicking a tree node now toggles expand/collapse (previously only expanded).
- **Array title support** \u2014 when the title YAML property is an array, the first element is used (PR #25).
## March 2026
- **Hide notes by tag** \u2014 filter notes from the tree by tag (Settings > Ignored tags).
- **Auto-reveal scroll fix** \u2014 notes taller than the viewport align to top instead of centering (PR #22).
- **Array property safety** \u2014 check if property is array before moving, preventing data corruption (PR #24).
- **Navigation commands** \u2014 navigate to parent, next/previous sibling, first child. Reveal active file in tree.
- **Configurable icon property** \u2014 YAML property name for emoji icons is now configurable in settings.
## February 2026
- **File explorer integration** \u2014 add files to virtual folders from Obsidian's file explorer context menu. Pin/unpin and manage icons from file explorer.
- **Delete with children** \u2014 recursive delete option in tree context menu.
- **Drag and drop** \u2014 move notes between folders by dragging in the tree. Safety: can't drop onto self or descendants.
- **Create notes from tree** \u2014 create note / create unique note via tree context menu. Works at ROOT level and under any note.
- **Database optimization** \u2014 incremental updates instead of full rescans.
- **Unicode YAML support** \u2014 folder property names now support any language characters.
- **Unique note creator** \u2014 integration with the Unique Note Creator plugin for auto-generated note names.
- **Auto-open tree on first run** \u2014 the tree view opens automatically when the plugin is installed for the first time.
## August 2024
- **Link format settings** \u2014 choose between \`[[WikiLinks]]\` and \`[Markdown](links)\` format for folder links in YAML.
- **Sorting options** \u2014 sort tree children by filename, title, creation time, or modification time. Reverse sort order toggle.
## July 2024
- **Initial release** \u2014 tree view sidebar with collapsible hierarchy built from YAML frontmatter links.
- **YAML-based structure** \u2014 notes define parent-child relationships via a configurable frontmatter property.
- **Custom display title** \u2014 use a YAML property as the display title instead of the filename.
- **Mobile support** \u2014 full compatibility with Obsidian Mobile.
- **Emoji icons** \u2014 set custom emoji icons on notes via an icon picker with categorized groups and search.
- **Pinned notes** \u2014 pin notes to the top of their sibling list.
- **Orphans section** \u2014 notes with no parents and no children are collected in a collapsible Orphans section.
- **Child counter** \u2014 badge showing the number of direct children on each note.
- **Active note highlight** \u2014 the currently open note is visually highlighted in the tree.
- **Auto-reveal** \u2014 optionally auto-scroll the tree to the active file when switching notes.
- **Confirm before deleting** \u2014 optional confirmation dialog for delete actions.
- **Ignored paths** \u2014 exclude notes by path prefix from the tree.
`;
var VF_WhatsNewView = class extends import_obsidian9.ItemView {
constructor(leaf, version) {
super(leaf);
this.version = version;
}
getViewType() {
return VIEW_TYPE_VF_WHATSNEW;
}
getDisplayText() {
return "What's new in VirtFolder";
}
getIcon() {
return "info";
}
async onOpen() {
let container = this.contentEl;
container.empty();
container.addClass("markdown-rendered");
let md = `# VirtFolder v${this.version}
` + WHATSNEW_MD;
await import_obsidian9.MarkdownRenderer.render(this.app, md, container, "", this);
}
};