Files
obsidian-notes/.obsidian/plugins/customizable-menu/main.js
zzzisfunnyboy 3c69d0117d 1
2025-06-15 01:58:15 +08:00

270 lines
17 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository
*/
'use strict';
var obsidian = require('obsidian');
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
const ICON_LIST = ['activity', 'airplay', 'alarm-check', 'alarm-clock-off', 'alarm-clock', 'alarm-minus', 'alarm-plus', 'album', 'alert-circle', 'alert-octagon', 'alert-triangle', 'align-left', 'align-right', 'align-center', 'align-justify', 'anchor', 'aperture', 'archive', 'arrow-big-down', 'arrow-big-left', 'arrow-big-right', 'arrow-big-up', 'arrow-down-circle', 'arrow-down-left', 'arrow-down-right', 'arrow-down', 'arrow-left-circle', 'arrow-left-right', 'arrow-left', 'arrow-right-circle', 'arrow-right', 'arrow-up-circle', 'arrow-up-left', 'arrow-up-right', 'arrow-up', 'asterisk', 'at-sign', 'award', 'axe', 'banknote', 'bar-chart-2', 'bar-chart', 'battery-charging', 'battery-full', 'battery-low', 'battery-medium', 'battery', 'beaker', 'bell-minus', 'bell-off', 'bell-plus', 'bell-ring', 'bell', 'bike', 'binary', 'bitcoin', 'bluetooth-connected', 'bluetooth-off', 'bluetooth-searching', 'bluetooth', 'bold', 'book-open', 'book', 'bookmark-minus', 'bookmark-plus', 'bookmark', 'bot', 'box-select', 'box', 'briefcase', 'brush', 'bug', 'building', 'bus', 'calculator', 'calendar', 'camera-off', 'camera', 'car', 'carrot', 'cast', 'check-circle-2', 'check-circle', 'check-square', 'check', 'chevron-down', 'chevron-first', 'chevron-last', 'chevron-left', 'chevron-right', 'chevron-up', 'chevrons-down-up', 'chevrons-down', 'chevrons-left', 'chevrons-right', 'chevrons-up-down', 'chevrons-up', 'chrome', 'circle-slashed', 'circle', 'clipboard-check', 'clipboard-copy', 'clipboard-list', 'clipboard-x', 'clipboard', 'clock-1', 'clock-10', 'clock-11', 'clock-12', 'clock-2', 'clock-3', 'clock-4', 'clock-5', 'clock-6', 'clock-7', 'clock-8', 'clock-9', 'clock', 'cloud-drizzle', 'cloud-fog', 'cloud-hail', 'cloud-lightning', 'cloud-moon', 'cloud-off', 'cloud-rain-wind', 'cloud-rain', 'cloud-snow', 'cloud-sun', 'cloud', 'cloudy', 'clover', 'code-2', 'code', 'codepen', 'codesandbox', 'coffee', 'coins', 'columns', 'command', 'compass', 'contact', 'contrast', 'cookie', 'copy', 'copyleft', 'copyright', 'corner-down-left', 'corner-down-right', 'corner-left-down', 'corner-left-up', 'corner-right-down', 'corner-right-up', 'corner-up-left', 'corner-up-right', 'cpu', 'credit-card', 'crop', 'cross', 'crosshair', 'crown', 'currency', 'database', 'delete', 'dice', 'disc', 'divide-circle', 'divide-square', 'divide', 'dollar-sign', 'download-cloud', 'download', 'dribbble', 'droplet', 'droplets', 'drumstick', 'edit-2', 'edit-3', 'edit', 'egg', 'equal-not', 'equal', 'eraser', 'euro', 'expand', 'external-link', 'eye-off', 'eye', 'facebook', 'fast-forward', 'feather', 'figma', 'file-check-2', 'file-check', 'file-code', 'file-digit', 'file-input', 'file-minus-2', 'file-minus', 'file-output', 'file-plus-2', 'file-plus', 'file-search', 'file-text', 'file-x-2', 'file-x', 'file', 'files', 'film', 'filter', 'flag-triangle-left', 'flag-triangle-right', 'flag', 'flame', 'flashlight-off', 'flashlight', 'flask-conical', 'flask-round', 'folder-minus', 'folder-open', 'folder-plus', 'folder', 'form-input', 'forward', 'framer', 'frown', 'function-square', 'gamepad-2', 'gamepad', 'gauge', 'gavel', 'gem', 'ghost', 'gift', 'git-branch-plus', 'git-branch', 'git-commit', 'git-merge', 'git-pull-request', 'github', 'gitlab', 'glasses', 'globe-2', 'globe', 'grab', 'graduation-cap', 'grid', 'grip-horizontal', 'grip-vertical', 'hammer', 'hand-metal', 'hand', 'hard-drive', 'hard-hat', 'hash', 'haze', 'headphones', 'heart', 'help-circle', 'hexagon', 'highlighter', 'history', 'home', 'image-minus', 'image-off', 'image-plus', 'image', 'import', 'inbox', 'indent', 'indian-rupee', 'infinity', 'info', 'inspect', 'instagram', 'italic', 'japanese-yen', 'key', 'landmark', 'languages', 'laptop-2', 'laptop', 'lasso-select', 'lasso', 'layers', 'layout-dashboard', 'layout-grid', 'layout-list', 'layout-template', 'layout', 'library', 'life-buoy', 'lightbulb-off', 'lightbulb', 'link-2-off', 'link-2', 'link', 'linkedin', 'list-checks', 'list-minus', 'list-ordered', 'list-plus', 'list-x', 'list', 'loader-2', 'loader', 'locate-fixed', 'locate', 'lock', 'log-in', 'log-out', 'mail', 'map-pin', 'map', 'maximize-2', 'maximize', 'megaphone', 'meh', 'message-circle', 'message-square', 'mic-off', 'mic', 'minimize-2', 'minimize', 'minus-circle', 'minus-square', 'minus', 'monitor-off', 'monitor-speaker', 'monitor', 'moon', 'more-horizontal', 'more-vertical', 'mountain-snow', 'mountain', 'mouse-pointer-2', 'mouse-pointer-click', 'mouse-pointer', 'move-diagonal-2', 'move-diagonal', 'move-horizontal', 'move-vertical', 'move', 'music', 'navigation-2', 'navigation', 'network', 'octagon', 'option', 'outdent', 'package-check', 'package-minus', 'package-plus', 'package-search', 'package-x', 'package', 'palette', 'paperclip', 'paste', 'pause-circle', 'pause-octagon', 'pause', 'pen-tool', 'pencil', 'percent', 'person-standing', 'phone-call', 'phone-forwarded', 'phone-incoming', 'phone-missed', 'phone-off', 'phone-outgoing', 'phone', 'pie-chart', 'piggy-bank', 'pin', 'pipette', 'plane', 'play-circle', 'play', 'plug-zap', 'plus-circle', 'plus-square', 'plus', 'pocket', 'podcast', 'pointer', 'pound-sterling', 'power-off', 'power', 'printer', 'qr-code', 'quote', 'radio-receiver', 'radio', 'redo', 'refresh-ccw', 'refresh-cw', 'regex', 'repeat-1', 'repeat', 'reply-all', 'reply', 'rewind', 'rocking-chair', 'rotate-ccw', 'rotate-cw', 'rss', 'ruler', 'russian-ruble', 'save', 'scale', 'scan-line', 'scan', 'scissors', 'screen-share-off', 'screen-share', 'search', 'send', 'separator-horizontal', 'separator-vertical', 'server-crash', 'server-off', 'server', 'settings-2', 'settings', 'share-2', 'share', 'sheet', 'shield-alert', 'shield-check', 'shield-close', 'shield-off', 'shield', 'shirt', 'shopping-bag', 'shopping-cart', 'shovel', 'shrink', 'shuffle', 'sidebar-close', 'sidebar-open', 'sidebar', 'sigma', 'signal-high', 'signal-low', 'signal-medium', 'signal-zero', 'signal', 'skip-back', 'skip-forward', 'skull', 'slack', 'slash', 'sliders', 'smartphone-charging', 'smartphone', 'smile', 'snowflake', 'sort-asc', 'sort-desc', 'speaker', 'sprout', 'square', 'star-half', 'star', 'stop-circle', 'strikethrough', 'subscript', 'sun', 'sunrise', 'sunset', 'superscript', 'swiss-franc', 'switch-camera', 'table', 'tablet', 'target', 'tent', 'terminal-square', 'terminal', 'text-cursor-input', 'text-cursor', 'thermometer-snowflake', 'thermometer-sun', 'thermometer', 'thumbs-down', 'thumbs-up', 'ticket', 'timer-off', 'timer-reset', 'timer', 'toggle-left', 'toggle-right', 'tornado', 'trash-2', 'trash', 'trello', 'trending-down', 'trending-up', 'triangle', 'truck', 'tv-2', 'tv', 'twitch', 'twitter', 'type', 'umbrella', 'underline', 'undo', 'unlink-2', 'unlink', 'unlock', 'upload-cloud', 'upload', 'user-check', 'user-minus', 'user-plus', 'user-x', 'user', 'users', 'verified', 'vibrate', 'video-off', 'video', 'view', 'voicemail', 'volume-1', 'volume-2', 'volume-x', 'volume', 'wallet', 'wand', 'watch', 'webcam', 'wifi-off', 'wifi', 'wind', 'wrap-text', 'wrench', 'x-circle', 'x-octagon', 'x-square', 'x', 'youtube', 'zap-off', 'zap', 'zoom-in', 'zoom-out', 'lucide-clock', 'lucide-cloud', 'lucide-cross', 'lucide-folder', 'lucide-info', 'lucide-languages', 'lucide-link', 'lucide-pencil', 'lucide-pin', 'lucide-search', 'lucide-star', 'lucide-trash'];
class IconPicker extends obsidian.FuzzySuggestModal {
constructor(suggester, command, editMode = false) {
super(suggester.plugin.app);
this.plugin = suggester.plugin;
this.settingTab = suggester.settingTab;
this.command = command;
this.editMode = editMode;
this.setPlaceholder("Pick an icon");
}
cap(string) {
const words = string.split(" ");
return words.map((word) => {
return word[0].toUpperCase() + word.substring(1);
}).join(" ");
}
getItems() {
return ICON_LIST;
}
getItemText(item) {
return this.cap(item.replace(/-/ig, " "));
}
renderSuggestion(item, el) {
el.addClass("custom-menu-icon-container");
const div = createDiv({ cls: "custom-menu-icon" });
el.appendChild(div);
obsidian.setIcon(div, item.item);
super.renderSuggestion(item, el);
}
onChooseItem(item) {
return __awaiter(this, void 0, void 0, function* () {
if (this.editMode === false) {
const command = { name: this.command.name, id: this.command.id, icon: item };
yield this.plugin.addMenuItemSetting(command, this.settingTab);
}
else {
this.command.icon = item;
yield this.plugin.saveSettings();
this.settingTab.display();
}
});
}
}
class CommandSuggester extends obsidian.FuzzySuggestModal {
constructor(plugin, settingTab) {
super(plugin.app);
this.settingTab = settingTab;
this.plugin = plugin;
}
getItems() {
//@ts-ignore
return this.app.commands.listCommands();
}
getItemText(item) {
return item.name;
}
onChooseItem(item) {
if (item.icon) {
this.plugin.addMenuItemSetting(item, this.settingTab);
}
else {
new IconPicker(this, item).open();
}
}
}
const DEFAULT_SETTINGS = {
menuCommands: [],
hideTitles: [],
};
class CustomMenuSettingsTab extends obsidian.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
let { containerEl } = this;
containerEl.empty();
containerEl.createEl('h2', { text: 'Add commands' });
new obsidian.Setting(containerEl)
.setName("Add command to menu")
.setDesc("Add a new command to the right-click menu")
.addButton((button) => {
button.setButtonText("Add Command")
.onClick(() => {
new CommandSuggester(this.plugin, this).open();
});
});
this.plugin.settings.menuCommands.forEach(command => {
const iconDiv = createDiv({ cls: "custom-menu-settings-icon" });
obsidian.setIcon(iconDiv, command.icon, 20);
const setting = new obsidian.Setting(containerEl)
.setName(command.name)
.addExtraButton(button => {
button.setIcon("trash")
.setTooltip("Remove command")
.onClick(() => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.menuCommands.remove(command);
yield this.plugin.saveSettings();
this.display();
new obsidian.Notice("You will need to restart Obsidian for the command to disappear.");
}));
})
.addExtraButton(button => {
button.setIcon("gear")
.setTooltip("Edit icon")
.onClick(() => {
new IconPicker(new CommandSuggester(this.plugin, this), command, true).open(); //rewrite icon picker so it isn't taking a command suggester
});
});
setting.nameEl.prepend(iconDiv);
setting.nameEl.addClass("custom-menu-flex");
});
/* Hide commands */
containerEl.createEl('h2', { text: 'Hide commands' });
// https://github.com/ozntel/file-explorer-note-count/blob/main/src/settings.ts#L117=
new obsidian.Setting(containerEl)
.setDesc("Enter the names of the commands as a comma-separated list. Commands are case-sensitive. You will need to restart Obsidian for the changes to take effect.")
.addTextArea(text => {
const onChange = (value) => __awaiter(this, void 0, void 0, function* () {
const list = value.split(',').map((v) => v.trim());
this.plugin.settings.hideTitles = list;
yield this.plugin.saveSettings();
});
text.setPlaceholder('Enter commands to hide');
text.setValue(this.plugin.settings.hideTitles.join(', ')).onChange(obsidian.debounce(onChange, 500, true));
text.inputEl.rows = 5;
text.inputEl.cols = 30;
});
}
}
function around(obj, factories) {
const removers = Object.keys(factories).map(key => around1(obj, key, factories[key]));
return removers.length === 1 ? removers[0] : function () { removers.forEach(r => r()); };
}
function around1(obj, method, createWrapper) {
const original = obj[method], hadOwn = obj.hasOwnProperty(method);
let current = createWrapper(original);
// Let our wrapper inherit static props from the wrapping method,
// and the wrapping method, props from the original method
if (original)
Object.setPrototypeOf(current, original);
Object.setPrototypeOf(wrapper, current);
obj[method] = wrapper;
// Return a callback to allow safe removal
return remove;
function wrapper(...args) {
// If we have been deactivated and are no longer wrapped, remove ourselves
if (current === original && obj[method] === wrapper)
remove();
return current.apply(this, args);
}
function remove() {
// If no other patches, just do a direct removal
if (obj[method] === wrapper) {
if (hadOwn)
obj[method] = original;
else
delete obj[method];
}
if (current === original)
return;
// Else pass future calls through, and remove wrapper from the prototype chain
current = original;
Object.setPrototypeOf(wrapper, original || Function);
}
}
class CustomMenuPlugin extends obsidian.Plugin {
onload() {
return __awaiter(this, void 0, void 0, function* () {
console.log('Loading customizable menu');
yield this.loadSettings();
this.addSettingTab(new CustomMenuSettingsTab(this.app, this));
this.settings.menuCommands.forEach(command => {
this.addMenuItem(command);
});
/* moneky-around doesn't know about my this.settings, need to set it here */
let hideTitles = this.settings.hideTitles;
/* Hide menu items */
/* https://github.com/Panossa/mindful-obsidian/blob/master/main.ts */
this.register(around(obsidian.MenuItem.prototype, {
setTitle(old) {
return function (title) {
this.dom.dataset.stylizerTitle = String(title);
if (hideTitles.includes(String(title))) {
console.log(title);
this.dom.addClass('custom-menu-hide-item');
}
return old.call(this, title);
};
}
}));
});
}
//add command to right-click menu
addMenuItem(command) {
this.registerEvent(this.app.workspace.on("editor-menu", (menu) => {
menu.addItem((item) => {
item.setTitle(command.name)
.setIcon(command.icon)
.onClick(() => {
//@ts-ignore
this.app.commands.executeCommandById(command.id);
});
});
}));
}
//add command to the list of commands to be added to right-click menu (persistent, saved in settings)
addMenuItemSetting(command, settingTab) {
return __awaiter(this, void 0, void 0, function* () {
this.addMenuItem(command);
this.settings.menuCommands.push(command);
yield this.saveSettings();
settingTab.display(); //refresh settings tab
});
}
loadSettings() {
return __awaiter(this, void 0, void 0, function* () {
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
});
}
saveSettings() {
return __awaiter(this, void 0, void 0, function* () {
yield this.saveData(this.settings);
});
}
}
module.exports = CustomMenuPlugin;
/* nosourcemap */