FanficNotes/.obsidian/plugins/obsidian-regex-replace/main.js

321 lines
62 KiB
JavaScript
Raw Normal View History

2024-06-08 04:55:36 +00:00
/*
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 DEFAULT_SETTINGS = {
findText: '',
replaceText: '',
useRegEx: true,
selOnly: false,
caseInsensitive: false,
processLineBreak: false,
processTab: false,
prefillFind: false
};
// logThreshold: 0 ... only error messages
// 9 ... verbose output
const logThreshold = 9;
const logger = (logString, logLevel = 0) => { if (logLevel <= logThreshold)
console.log('RegexFiRe: ' + logString); };
class RegexFindReplacePlugin extends obsidian.Plugin {
onload() {
return __awaiter(this, void 0, void 0, function* () {
logger('Loading Plugin...', 9);
yield this.loadSettings();
this.addSettingTab(new RegexFindReplaceSettingTab(this.app, this));
this.addCommand({
id: 'obsidian-regex-replace',
name: 'Find and Replace using regular expressions',
editorCallback: (editor) => {
new FindAndReplaceModal(this.app, editor, this.settings, this).open();
},
});
});
}
onunload() {
logger('Bye!', 9);
}
loadSettings() {
return __awaiter(this, void 0, void 0, function* () {
logger('Loading Settings...', 6);
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
logger(' findVal: ' + this.settings.findText, 6);
logger(' replaceText: ' + this.settings.replaceText, 6);
logger(' caseInsensitive: ' + this.settings.caseInsensitive, 6);
logger(' processLineBreak: ' + this.settings.processLineBreak, 6);
});
}
saveSettings() {
return __awaiter(this, void 0, void 0, function* () {
yield this.saveData(this.settings);
});
}
}
class FindAndReplaceModal extends obsidian.Modal {
constructor(app, editor, settings, plugin) {
super(app);
this.editor = editor;
this.settings = settings;
this.plugin = plugin;
}
onOpen() {
const { contentEl, titleEl, editor, modalEl } = this;
modalEl.addClass('find-replace-modal');
titleEl.setText('Regex Find/Replace');
const rowClass = 'row';
const divClass = 'div';
const noSelection = editor.getSelection() === '';
let regexFlags = 'gm';
if (this.settings.caseInsensitive)
regexFlags = regexFlags.concat('i');
logger('No text selected?: ' + noSelection, 9);
const addTextComponent = (label, placeholder, postfix = '') => {
const containerEl = document.createElement(divClass);
containerEl.addClass(rowClass);
const targetEl = document.createElement(divClass);
targetEl.addClass('input-wrapper');
const labelEl = document.createElement(divClass);
labelEl.addClass('input-label');
labelEl.setText(label);
const labelEl2 = document.createElement(divClass);
labelEl2.addClass('postfix-label');
labelEl2.setText(postfix);
containerEl.appendChild(labelEl);
containerEl.appendChild(targetEl);
containerEl.appendChild(labelEl2);
const component = new obsidian.TextComponent(targetEl);
component.setPlaceholder(placeholder);
contentEl.append(containerEl);
return [component, labelEl2];
};
const addToggleComponent = (label, tooltip, hide = false) => {
const containerEl = document.createElement(divClass);
containerEl.addClass(rowClass);
const targetEl = document.createElement(divClass);
targetEl.addClass(rowClass);
const component = new obsidian.ToggleComponent(targetEl);
component.setTooltip(tooltip);
const labelEl = document.createElement(divClass);
labelEl.addClass('check-label');
labelEl.setText(label);
containerEl.appendChild(labelEl);
containerEl.appendChild(targetEl);
if (!hide)
contentEl.appendChild(containerEl);
return component;
};
// Create input fields
const findRow = addTextComponent('Find:', 'e.g. (.*)', '/' + regexFlags);
const findInputComponent = findRow[0];
const findRegexFlags = findRow[1];
const replaceRow = addTextComponent('Replace:', 'e.g. $1', this.settings.processLineBreak ? '\\n=LF' : '');
const replaceWithInputComponent = replaceRow[0];
// Create and show regular expression toggle switch
const regToggleComponent = addToggleComponent('Use regular expressions', 'If enabled, regular expressions in the find field are processed as such, and regex groups might be addressed in the replace field');
// Update regex-flags label if regular expressions are enabled or disabled
regToggleComponent.onChange(regNew => {
if (regNew) {
findRegexFlags.setText('/' + regexFlags);
}
else {
findRegexFlags.setText('');
}
});
// Create and show selection toggle switch only if any text is selected
const selToggleComponent = addToggleComponent('Replace only in selection', 'If enabled, replaces only occurances in the currently selected text', noSelection);
// Create Buttons
const buttonContainerEl = document.createElement(divClass);
buttonContainerEl.addClass(rowClass);
const submitButtonTarget = document.createElement(divClass);
submitButtonTarget.addClass('button-wrapper');
submitButtonTarget.addClass(rowClass);
const cancelButtonTarget = document.createElement(divClass);
cancelButtonTarget.addClass('button-wrapper');
cancelButtonTarget.addClass(rowClass);
const submitButtonComponent = new obsidian.ButtonComponent(submitButtonTarget);
const cancelButtonComponent = new obsidian.ButtonComponent(cancelButtonTarget);
cancelButtonComponent.setButtonText('Cancel');
cancelButtonComponent.onClick(() => {
logger('Action cancelled.', 8);
this.close();
});
submitButtonComponent.setButtonText('Replace All');
submitButtonComponent.setCta();
submitButtonComponent.onClick(() => {
let resultString = 'No match';
let scope = '';
const searchString = findInputComponent.getValue();
let replaceString = replaceWithInputComponent.getValue();
const selectedText = editor.getSelection();
if (searchString === '') {
new obsidian.Notice('Nothing to search for!');
return;
}
// Replace line breaks in find-field if option is enabled
if (this.settings.processLineBreak) {
logger('Replacing linebreaks in replace-field', 9);
logger(' old: ' + replaceString, 9);
replaceString = replaceString.replace(/\\n/gm, '\n');
logger(' new: ' + replaceString, 9);
}
// Replace line breaks in find-field if option is enabled
if (this.settings.processTab) {
logger('Replacing tabs in replace-field', 9);
logger(' old: ' + replaceString, 9);
replaceString = replaceString.replace(/\\t/gm, '\t');
logger(' new: ' + replaceString, 9);
}
// Check if regular expressions should be used
if (regToggleComponent.getValue()) {
logger('USING regex with flags: ' + regexFlags, 8);
const searchRegex = new RegExp(searchString, regexFlags);
if (!selToggleComponent.getValue()) {
logger(' SCOPE: Full document', 9);
const documentText = editor.getValue();
const rresult = documentText.match(searchRegex);
if (rresult) {
editor.setValue(documentText.replace(searchRegex, replaceString));
resultString = `Made ${rresult.length} replacement(s) in document`;
}
}
else {
logger(' SCOPE: Selection', 9);
const rresult = selectedText.match(searchRegex);
if (rresult) {
editor.replaceSelection(selectedText.replace(searchRegex, replaceString));
resultString = `Made ${rresult.length} replacement(s) in selection`;
}
}
}
else {
logger('NOT using regex', 8);
let nrOfHits = 0;
if (!selToggleComponent.getValue()) {
logger(' SCOPE: Full document', 9);
scope = 'selection';
const documentText = editor.getValue();
const documentSplit = documentText.split(searchString);
nrOfHits = documentSplit.length - 1;
editor.setValue(documentSplit.join(replaceString));
}
else {
logger(' SCOPE: Selection', 9);
scope = 'document';
const selectedSplit = selectedText.split(searchString);
nrOfHits = selectedSplit.length - 1;
editor.replaceSelection(selectedSplit.join(replaceString));
}
resultString = `Made ${nrOfHits} replacement(s) in ${scope}`;
}
// Saving settings (find/replace text and toggle switch states)
this.settings.findText = searchString;
this.settings.replaceText = replaceString;
this.settings.useRegEx = regToggleComponent.getValue();
this.settings.selOnly = selToggleComponent.getValue();
this.plugin.saveData(this.settings);
this.close();
new obsidian.Notice(resultString);
});
// Apply settings
regToggleComponent.setValue(this.settings.useRegEx);
selToggleComponent.setValue(this.settings.selOnly);
replaceWithInputComponent.setValue(this.settings.replaceText);
// Check if the prefill find option is enabled and the selection does not contain linebreaks
if (this.settings.prefillFind && editor.getSelection().indexOf('\n') < 0 && !noSelection) {
logger('Found selection without linebreaks and option is enabled -> fill', 9);
findInputComponent.setValue(editor.getSelection());
selToggleComponent.setValue(false);
}
else {
logger('Restore find text', 9);
findInputComponent.setValue(this.settings.findText);
}
// Add button row to dialog
buttonContainerEl.appendChild(submitButtonTarget);
buttonContainerEl.appendChild(cancelButtonTarget);
contentEl.appendChild(buttonContainerEl);
// If no text is selected, disable selection-toggle-switch
if (noSelection)
selToggleComponent.setValue(false);
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
}
class RegexFindReplaceSettingTab extends obsidian.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl('h4', { text: 'Regular Expression Settings' });
new obsidian.Setting(containerEl)
.setName('Case Insensitive')
.setDesc('When using regular expressions, apply the \'/i\' modifier for case insensitive search)')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.caseInsensitive)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
logger('Settings update: caseInsensitive: ' + value);
this.plugin.settings.caseInsensitive = value;
yield this.plugin.saveSettings();
})));
containerEl.createEl('h4', { text: 'General Settings' });
new obsidian.Setting(containerEl)
.setName('Process \\n as line break')
.setDesc('When \'\\n\' is used in the replace field, a \'line break\' will be inserted accordingly')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.processLineBreak)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
logger('Settings update: processLineBreak: ' + value);
this.plugin.settings.processLineBreak = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName('Prefill Find Field')
.setDesc('Copy the currently selected text (if any) into the \'Find\' text field. This setting is only applied if the selection does not contain linebreaks')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.prefillFind)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
logger('Settings update: prefillFind: ' + value);
this.plugin.settings.prefillFind = value;
yield this.plugin.saveSettings();
})));
}
}
module.exports = RegexFindReplacePlugin;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNyYy9tYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8