735 lines
103 KiB
JavaScript
735 lines
103 KiB
JavaScript
|
'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.
|
||
|
***************************************************************************** */
|
||
|
/* global Reflect, Promise */
|
||
|
|
||
|
var extendStatics = function(d, b) {
|
||
|
extendStatics = Object.setPrototypeOf ||
|
||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||
|
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||
|
return extendStatics(d, b);
|
||
|
};
|
||
|
|
||
|
function __extends(d, b) {
|
||
|
if (typeof b !== "function" && b !== null)
|
||
|
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
||
|
extendStatics(d, b);
|
||
|
function __() { this.constructor = d; }
|
||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||
|
}
|
||
|
|
||
|
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());
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function __generator(thisArg, body) {
|
||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||
|
function step(op) {
|
||
|
if (f) throw new TypeError("Generator is already executing.");
|
||
|
while (_) try {
|
||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||
|
switch (op[0]) {
|
||
|
case 0: case 1: t = op; break;
|
||
|
case 4: _.label++; return { value: op[1], done: false };
|
||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||
|
default:
|
||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||
|
if (t[2]) _.ops.pop();
|
||
|
_.trys.pop(); continue;
|
||
|
}
|
||
|
op = body.call(thisArg, _);
|
||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function isExcalidraw(app, f) {
|
||
|
if (f.extension === 'excalidraw' || /.*\.excalidraw\.md$/g.test(f.path)) {
|
||
|
return true;
|
||
|
}
|
||
|
var fileCache = app.metadataCache.getFileCache(f);
|
||
|
return (!!(fileCache === null || fileCache === void 0 ? void 0 : fileCache.frontmatter) && !!fileCache.frontmatter['excalidraw-plugin']);
|
||
|
}
|
||
|
function isExcluded(app, f) {
|
||
|
if (isExcalidraw(app, f)) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var stockIllegalSymbols = /[\\/:|#^[\]]/g;
|
||
|
var DEFAULT_SETTINGS = {
|
||
|
userIllegalSymbols: [],
|
||
|
ignoredFiles: {},
|
||
|
ignoreRegex: '',
|
||
|
useFileOpenHook: true,
|
||
|
useFileSaveHook: true,
|
||
|
newHeadingStyle: "Prefix" /* Prefix */,
|
||
|
replaceStyle: false,
|
||
|
underlineString: '===',
|
||
|
};
|
||
|
var FilenameHeadingSyncPlugin = /** @class */ (function (_super) {
|
||
|
__extends(FilenameHeadingSyncPlugin, _super);
|
||
|
function FilenameHeadingSyncPlugin() {
|
||
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||
|
_this.isRenameInProgress = false;
|
||
|
return _this;
|
||
|
}
|
||
|
FilenameHeadingSyncPlugin.prototype.onload = function () {
|
||
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
var _this = this;
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0: return [4 /*yield*/, this.loadSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
this.registerEvent(this.app.vault.on('rename', function (file, oldPath) {
|
||
|
if (_this.settings.useFileSaveHook) {
|
||
|
return _this.handleSyncFilenameToHeading(file, oldPath);
|
||
|
}
|
||
|
}));
|
||
|
this.registerEvent(this.app.vault.on('modify', function (file) {
|
||
|
if (_this.settings.useFileSaveHook) {
|
||
|
return _this.handleSyncHeadingToFile(file);
|
||
|
}
|
||
|
}));
|
||
|
this.registerEvent(this.app.workspace.on('file-open', function (file) {
|
||
|
if (_this.settings.useFileOpenHook && file !== null) {
|
||
|
return _this.handleSyncFilenameToHeading(file, file.path);
|
||
|
}
|
||
|
}));
|
||
|
this.addSettingTab(new FilenameHeadingSyncSettingTab(this.app, this));
|
||
|
this.addCommand({
|
||
|
id: 'page-heading-sync-ignore-file',
|
||
|
name: 'Ignore current file',
|
||
|
checkCallback: function (checking) {
|
||
|
var leaf = _this.app.workspace.activeLeaf;
|
||
|
if (leaf) {
|
||
|
if (!checking) {
|
||
|
_this.settings.ignoredFiles[_this.app.workspace.getActiveFile().path] = null;
|
||
|
_this.saveSettings();
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
},
|
||
|
});
|
||
|
this.addCommand({
|
||
|
id: 'sync-filename-to-heading',
|
||
|
name: 'Sync Filename to Heading',
|
||
|
editorCallback: function (editor, view) {
|
||
|
return _this.forceSyncFilenameToHeading(view.file);
|
||
|
},
|
||
|
});
|
||
|
this.addCommand({
|
||
|
id: 'sync-heading-to-filename',
|
||
|
name: 'Sync Heading to Filename',
|
||
|
editorCallback: function (editor, view) {
|
||
|
return _this.forceSyncHeadingToFilename(view.file);
|
||
|
},
|
||
|
});
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
FilenameHeadingSyncPlugin.prototype.fileIsIgnored = function (activeFile, path) {
|
||
|
// check exclusions
|
||
|
if (isExcluded(this.app, activeFile)) {
|
||
|
return true;
|
||
|
}
|
||
|
// check manual ignore
|
||
|
if (this.settings.ignoredFiles[path] !== undefined) {
|
||
|
return true;
|
||
|
}
|
||
|
// check regex
|
||
|
try {
|
||
|
if (this.settings.ignoreRegex === '') {
|
||
|
return;
|
||
|
}
|
||
|
var reg = new RegExp(this.settings.ignoreRegex);
|
||
|
return reg.exec(path) !== null;
|
||
|
}
|
||
|
catch (_a) { }
|
||
|
return false;
|
||
|
};
|
||
|
/**
|
||
|
* Renames the file with the first heading found
|
||
|
*
|
||
|
* @param {TAbstractFile} file The file
|
||
|
*/
|
||
|
FilenameHeadingSyncPlugin.prototype.handleSyncHeadingToFile = function (file) {
|
||
|
if (!(file instanceof obsidian.TFile)) {
|
||
|
return;
|
||
|
}
|
||
|
if (file.extension !== 'md') {
|
||
|
// just bail
|
||
|
return;
|
||
|
}
|
||
|
// if currently opened file is not the same as the one that fired the event, skip
|
||
|
// this is to make sure other events don't trigger this plugin
|
||
|
if (this.app.workspace.getActiveFile() !== file) {
|
||
|
return;
|
||
|
}
|
||
|
// if ignored, just bail
|
||
|
if (this.fileIsIgnored(file, file.path)) {
|
||
|
return;
|
||
|
}
|
||
|
this.forceSyncHeadingToFilename(file);
|
||
|
};
|
||
|
FilenameHeadingSyncPlugin.prototype.forceSyncHeadingToFilename = function (file) {
|
||
|
var _this = this;
|
||
|
this.app.vault.read(file).then(function (data) { return __awaiter(_this, void 0, void 0, function () {
|
||
|
var lines, start, heading, sanitizedHeading, newPath;
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
lines = data.split('\n');
|
||
|
start = this.findNoteStart(lines);
|
||
|
heading = this.findHeading(lines, start);
|
||
|
if (heading === null)
|
||
|
return [2 /*return*/]; // no heading found, nothing to do here
|
||
|
sanitizedHeading = this.sanitizeHeading(heading.text);
|
||
|
if (!(sanitizedHeading.length > 0 &&
|
||
|
this.sanitizeHeading(file.basename) !== sanitizedHeading)) return [3 /*break*/, 2];
|
||
|
newPath = file.parent.path + "/" + sanitizedHeading + ".md";
|
||
|
this.isRenameInProgress = true;
|
||
|
return [4 /*yield*/, this.app.fileManager.renameFile(file, newPath)];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
this.isRenameInProgress = false;
|
||
|
_a.label = 2;
|
||
|
case 2: return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
};
|
||
|
/**
|
||
|
* Syncs the current filename to the first heading
|
||
|
* Finds the first heading of the file, then replaces it with the filename
|
||
|
*
|
||
|
* @param {TAbstractFile} file The file that fired the event
|
||
|
* @param {string} oldPath The old path
|
||
|
*/
|
||
|
FilenameHeadingSyncPlugin.prototype.handleSyncFilenameToHeading = function (file, oldPath) {
|
||
|
if (this.isRenameInProgress) {
|
||
|
return;
|
||
|
}
|
||
|
if (!(file instanceof obsidian.TFile)) {
|
||
|
return;
|
||
|
}
|
||
|
if (file.extension !== 'md') {
|
||
|
// just bail
|
||
|
return;
|
||
|
}
|
||
|
// if oldpath is ignored, hook in and update the new filepath to be ignored instead
|
||
|
if (this.fileIsIgnored(file, oldPath.trim())) {
|
||
|
// if filename didn't change, just bail, nothing to do here
|
||
|
if (file.path === oldPath) {
|
||
|
return;
|
||
|
}
|
||
|
// If filepath changed and the file was in the ignore list before,
|
||
|
// remove it from the list and add the new one instead
|
||
|
if (this.settings.ignoredFiles[oldPath]) {
|
||
|
delete this.settings.ignoredFiles[oldPath];
|
||
|
this.settings.ignoredFiles[file.path] = null;
|
||
|
this.saveSettings();
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
this.forceSyncFilenameToHeading(file);
|
||
|
};
|
||
|
FilenameHeadingSyncPlugin.prototype.forceSyncFilenameToHeading = function (file) {
|
||
|
var _this = this;
|
||
|
var sanitizedHeading = this.sanitizeHeading(file.basename);
|
||
|
this.app.vault.read(file).then(function (data) {
|
||
|
var lines = data.split('\n');
|
||
|
var start = _this.findNoteStart(lines);
|
||
|
var heading = _this.findHeading(lines, start);
|
||
|
if (heading !== null) {
|
||
|
if (_this.sanitizeHeading(heading.text) !== sanitizedHeading) {
|
||
|
_this.replaceHeading(file, lines, heading.lineNumber, heading.style, sanitizedHeading);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
_this.insertHeading(file, lines, start, sanitizedHeading);
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* Finds the start of the note file, excluding frontmatter
|
||
|
*
|
||
|
* @param {string[]} fileLines array of the file's contents, line by line
|
||
|
* @returns {number} zero-based index of the starting line of the note
|
||
|
*/
|
||
|
FilenameHeadingSyncPlugin.prototype.findNoteStart = function (fileLines) {
|
||
|
// check for frontmatter by checking if first line is a divider ('---')
|
||
|
if (fileLines[0] === '---') {
|
||
|
// find end of frontmatter
|
||
|
// if no end is found, then it isn't really frontmatter and function will end up returning 0
|
||
|
for (var i = 1; i < fileLines.length; i++) {
|
||
|
if (fileLines[i] === '---') {
|
||
|
// end of frontmatter found, next line is start of note
|
||
|
return i + 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
};
|
||
|
/**
|
||
|
* Finds the first heading of the note file
|
||
|
*
|
||
|
* @param {string[]} fileLines array of the file's contents, line by line
|
||
|
* @param {number} startLine zero-based index of the starting line of the note
|
||
|
* @returns {LinePointer | null} LinePointer to heading or null if no heading found
|
||
|
*/
|
||
|
FilenameHeadingSyncPlugin.prototype.findHeading = function (fileLines, startLine) {
|
||
|
for (var i = startLine; i < fileLines.length; i++) {
|
||
|
if (fileLines[i].startsWith('# ')) {
|
||
|
return {
|
||
|
lineNumber: i,
|
||
|
text: fileLines[i].substring(2),
|
||
|
style: "Prefix" /* Prefix */,
|
||
|
};
|
||
|
}
|
||
|
else {
|
||
|
if (fileLines[i + 1] !== undefined &&
|
||
|
fileLines[i + 1].match(/^=+$/) !== null) {
|
||
|
return {
|
||
|
lineNumber: i,
|
||
|
text: fileLines[i],
|
||
|
style: "Underline" /* Underline */,
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return null; // no heading found
|
||
|
};
|
||
|
FilenameHeadingSyncPlugin.prototype.regExpEscape = function (str) {
|
||
|
return String(str).replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
|
||
|
};
|
||
|
FilenameHeadingSyncPlugin.prototype.sanitizeHeading = function (text) {
|
||
|
var _this = this;
|
||
|
// stockIllegalSymbols is a regExp object, but userIllegalSymbols is a list of strings and therefore they are handled separately.
|
||
|
text = text.replace(stockIllegalSymbols, '');
|
||
|
var userIllegalSymbolsEscaped = this.settings.userIllegalSymbols.map(function (str) { return _this.regExpEscape(str); });
|
||
|
var userIllegalSymbolsRegExp = new RegExp(userIllegalSymbolsEscaped.join('|'), 'g');
|
||
|
text = text.replace(userIllegalSymbolsRegExp, '');
|
||
|
return text.trim();
|
||
|
};
|
||
|
/**
|
||
|
* Insert the `heading` at `lineNumber` in `file`.
|
||
|
*
|
||
|
* @param {TFile} file the file to modify
|
||
|
* @param {string[]} fileLines array of the file's contents, line by line
|
||
|
* @param {number} lineNumber zero-based index of the line to replace
|
||
|
* @param {string} text the new text
|
||
|
*/
|
||
|
FilenameHeadingSyncPlugin.prototype.insertHeading = function (file, fileLines, lineNumber, heading) {
|
||
|
var newStyle = this.settings.newHeadingStyle;
|
||
|
switch (newStyle) {
|
||
|
case "Underline" /* Underline */: {
|
||
|
this.insertLineInFile(file, fileLines, lineNumber, "" + heading);
|
||
|
this.insertLineInFile(file, fileLines, lineNumber + 1, this.settings.underlineString);
|
||
|
break;
|
||
|
}
|
||
|
case "Prefix" /* Prefix */: {
|
||
|
this.insertLineInFile(file, fileLines, lineNumber, "# " + heading);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
/**
|
||
|
* Modified `file` by replacing the heading at `lineNumber` with `newHeading`,
|
||
|
* updating the heading style according the user settings.
|
||
|
*
|
||
|
* @param {TFile} file the file to modify
|
||
|
* @param {string[]} fileLines array of the file's contents, line by line
|
||
|
* @param {number} lineNumber zero-based index of the line to replace
|
||
|
* @param {HeadingStyle} oldStyle the style of the original heading
|
||
|
* @param {string} text the new text
|
||
|
*/
|
||
|
FilenameHeadingSyncPlugin.prototype.replaceHeading = function (file, fileLines, lineNumber, oldStyle, newHeading) {
|
||
|
var newStyle = this.settings.newHeadingStyle;
|
||
|
var replaceStyle = this.settings.replaceStyle;
|
||
|
// If replacing the style
|
||
|
if (replaceStyle) {
|
||
|
switch (newStyle) {
|
||
|
// For underline style, replace heading line...
|
||
|
case "Underline" /* Underline */: {
|
||
|
this.replaceLineInFile(file, fileLines, lineNumber, "" + newHeading);
|
||
|
//..., then add or replace underline.
|
||
|
switch (oldStyle) {
|
||
|
case "Prefix" /* Prefix */: {
|
||
|
this.insertLineInFile(file, fileLines, lineNumber + 1, this.settings.underlineString);
|
||
|
break;
|
||
|
}
|
||
|
case "Underline" /* Underline */: {
|
||
|
// Update underline with setting.
|
||
|
this.replaceLineInFile(file, fileLines, lineNumber + 1, this.settings.underlineString);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
// For prefix style, replace heading line, and possibly delete underline
|
||
|
case "Prefix" /* Prefix */: {
|
||
|
this.replaceLineInFile(file, fileLines, lineNumber, "# " + newHeading);
|
||
|
switch (oldStyle) {
|
||
|
case "Prefix" /* Prefix */: {
|
||
|
// nop
|
||
|
break;
|
||
|
}
|
||
|
case "Underline" /* Underline */: {
|
||
|
this.replaceLineInFile(file, fileLines, lineNumber + 1, '');
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
// If not replacing style, match
|
||
|
switch (oldStyle) {
|
||
|
case "Underline" /* Underline */: {
|
||
|
this.replaceLineInFile(file, fileLines, lineNumber, "" + newHeading);
|
||
|
break;
|
||
|
}
|
||
|
case "Prefix" /* Prefix */: {
|
||
|
this.replaceLineInFile(file, fileLines, lineNumber, "# " + newHeading);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
/**
|
||
|
* Modifies the file by replacing a particular line with new text.
|
||
|
*
|
||
|
* The function will add a newline character at the end of the replaced line.
|
||
|
*
|
||
|
* If the `lineNumber` parameter is higher than the index of the last line of the file
|
||
|
* the function will add a newline character to the current last line and append a new
|
||
|
* line at the end of the file with the new text (essentially a new last line).
|
||
|
*
|
||
|
* @param {TFile} file the file to modify
|
||
|
* @param {string[]} fileLines array of the file's contents, line by line
|
||
|
* @param {number} lineNumber zero-based index of the line to replace
|
||
|
* @param {string} text the new text
|
||
|
*/
|
||
|
FilenameHeadingSyncPlugin.prototype.replaceLineInFile = function (file, fileLines, lineNumber, text) {
|
||
|
if (lineNumber >= fileLines.length) {
|
||
|
fileLines.push(text + '\n');
|
||
|
}
|
||
|
else {
|
||
|
fileLines[lineNumber] = text;
|
||
|
}
|
||
|
var data = fileLines.join('\n');
|
||
|
this.app.vault.modify(file, data);
|
||
|
};
|
||
|
/**
|
||
|
* Modifies the file by inserting a line with specified text.
|
||
|
*
|
||
|
* The function will add a newline character at the end of the inserted line.
|
||
|
*
|
||
|
* @param {TFile} file the file to modify
|
||
|
* @param {string[]} fileLines array of the file's contents, line by line
|
||
|
* @param {number} lineNumber zero-based index of where the line should be inserted
|
||
|
* @param {string} text the text that the line shall contain
|
||
|
*/
|
||
|
FilenameHeadingSyncPlugin.prototype.insertLineInFile = function (file, fileLines, lineNumber, text) {
|
||
|
if (lineNumber >= fileLines.length) {
|
||
|
fileLines.push(text + '\n');
|
||
|
}
|
||
|
else {
|
||
|
fileLines.splice(lineNumber, 0, text);
|
||
|
}
|
||
|
var data = fileLines.join('\n');
|
||
|
this.app.vault.modify(file, data);
|
||
|
};
|
||
|
FilenameHeadingSyncPlugin.prototype.loadSettings = function () {
|
||
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
var _a, _b, _c, _d;
|
||
|
return __generator(this, function (_e) {
|
||
|
switch (_e.label) {
|
||
|
case 0:
|
||
|
_a = this;
|
||
|
_c = (_b = Object).assign;
|
||
|
_d = [{}, DEFAULT_SETTINGS];
|
||
|
return [4 /*yield*/, this.loadData()];
|
||
|
case 1:
|
||
|
_a.settings = _c.apply(_b, _d.concat([_e.sent()]));
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
FilenameHeadingSyncPlugin.prototype.saveSettings = function () {
|
||
|
return __awaiter(this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0: return [4 /*yield*/, this.saveData(this.settings)];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
return FilenameHeadingSyncPlugin;
|
||
|
}(obsidian.Plugin));
|
||
|
var FilenameHeadingSyncSettingTab = /** @class */ (function (_super) {
|
||
|
__extends(FilenameHeadingSyncSettingTab, _super);
|
||
|
function FilenameHeadingSyncSettingTab(app, plugin) {
|
||
|
var _this = _super.call(this, app, plugin) || this;
|
||
|
_this.plugin = plugin;
|
||
|
_this.app = app;
|
||
|
return _this;
|
||
|
}
|
||
|
FilenameHeadingSyncSettingTab.prototype.display = function () {
|
||
|
var _this = this;
|
||
|
var containerEl = this.containerEl;
|
||
|
var regexIgnoredFilesDiv;
|
||
|
var renderRegexIgnoredFiles = function (div) {
|
||
|
// empty existing div
|
||
|
div.innerHTML = '';
|
||
|
if (_this.plugin.settings.ignoreRegex === '') {
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
var files = _this.app.vault.getFiles();
|
||
|
var reg_1 = new RegExp(_this.plugin.settings.ignoreRegex);
|
||
|
files
|
||
|
.filter(function (file) { return reg_1.exec(file.path) !== null; })
|
||
|
.forEach(function (el) {
|
||
|
new obsidian.Setting(div).setDesc(el.path);
|
||
|
});
|
||
|
}
|
||
|
catch (e) {
|
||
|
return;
|
||
|
}
|
||
|
};
|
||
|
containerEl.empty();
|
||
|
containerEl.createEl('h2', { text: 'Filename Heading Sync' });
|
||
|
containerEl.createEl('p', {
|
||
|
text: 'This plugin will overwrite the first heading found in a file with the filename.',
|
||
|
});
|
||
|
containerEl.createEl('p', {
|
||
|
text: 'If no header is found, will insert a new one at the first line (after frontmatter).',
|
||
|
});
|
||
|
new obsidian.Setting(containerEl)
|
||
|
.setName('Custom Illegal Characters/Strings')
|
||
|
.setDesc('Type characters/strings separated by a comma. This input is space sensitive.')
|
||
|
.addText(function (text) {
|
||
|
return text
|
||
|
.setPlaceholder('[],#,...')
|
||
|
.setValue(_this.plugin.settings.userIllegalSymbols.join())
|
||
|
.onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
this.plugin.settings.userIllegalSymbols = value.split(',');
|
||
|
return [4 /*yield*/, this.plugin.saveSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
});
|
||
|
new obsidian.Setting(containerEl)
|
||
|
.setName('Ignore Regex Rule')
|
||
|
.setDesc('Ignore rule in RegEx format. All files listed below will get ignored by this plugin.')
|
||
|
.addText(function (text) {
|
||
|
return text
|
||
|
.setPlaceholder('MyFolder/.*')
|
||
|
.setValue(_this.plugin.settings.ignoreRegex)
|
||
|
.onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
try {
|
||
|
new RegExp(value);
|
||
|
this.plugin.settings.ignoreRegex = value;
|
||
|
}
|
||
|
catch (_b) {
|
||
|
this.plugin.settings.ignoreRegex = '';
|
||
|
}
|
||
|
return [4 /*yield*/, this.plugin.saveSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
renderRegexIgnoredFiles(regexIgnoredFilesDiv);
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
});
|
||
|
new obsidian.Setting(containerEl)
|
||
|
.setName('Use File Open Hook')
|
||
|
.setDesc('Whether this plugin should trigger when a file is opened, and not just on save. Disable this when you notice conflicts with other plugins that also act on file open.')
|
||
|
.addToggle(function (toggle) {
|
||
|
return toggle
|
||
|
.setValue(_this.plugin.settings.useFileOpenHook)
|
||
|
.onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
this.plugin.settings.useFileOpenHook = value;
|
||
|
return [4 /*yield*/, this.plugin.saveSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
});
|
||
|
new obsidian.Setting(containerEl)
|
||
|
.setName('Use File Save Hook')
|
||
|
.setDesc('Whether this plugin should trigger when a file is saved. Disable this when you want to trigger sync only manually.')
|
||
|
.addToggle(function (toggle) {
|
||
|
return toggle
|
||
|
.setValue(_this.plugin.settings.useFileSaveHook)
|
||
|
.onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
this.plugin.settings.useFileSaveHook = value;
|
||
|
return [4 /*yield*/, this.plugin.saveSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
});
|
||
|
new obsidian.Setting(containerEl)
|
||
|
.setName('New Heading Style')
|
||
|
.setDesc('Which Markdown heading style to use when creating new headings: Prefix ("# Heading") or Underline ("Heading\\n===").')
|
||
|
.addDropdown(function (cb) {
|
||
|
return cb
|
||
|
.addOption("Prefix" /* Prefix */, 'Prefix')
|
||
|
.addOption("Underline" /* Underline */, 'Underline')
|
||
|
.setValue(_this.plugin.settings.newHeadingStyle)
|
||
|
.onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
if (value === 'Prefix') {
|
||
|
this.plugin.settings.newHeadingStyle = "Prefix" /* Prefix */;
|
||
|
}
|
||
|
if (value === 'Underline') {
|
||
|
this.plugin.settings.newHeadingStyle = "Underline" /* Underline */;
|
||
|
}
|
||
|
return [4 /*yield*/, this.plugin.saveSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
});
|
||
|
new obsidian.Setting(containerEl)
|
||
|
.setName('Replace Heading Style')
|
||
|
.setDesc('Whether this plugin should replace existing heading styles when updating headings.')
|
||
|
.addToggle(function (toggle) {
|
||
|
return toggle
|
||
|
.setValue(_this.plugin.settings.replaceStyle)
|
||
|
.onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
this.plugin.settings.replaceStyle = value;
|
||
|
return [4 /*yield*/, this.plugin.saveSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
});
|
||
|
new obsidian.Setting(containerEl)
|
||
|
.setName('Underline String')
|
||
|
.setDesc('The string to use when insert Underline-style headings; should be some number of "="s.')
|
||
|
.addText(function (text) {
|
||
|
return text
|
||
|
.setPlaceholder('===')
|
||
|
.setValue(_this.plugin.settings.underlineString)
|
||
|
.onChange(function (value) { return __awaiter(_this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
this.plugin.settings.underlineString = value;
|
||
|
return [4 /*yield*/, this.plugin.saveSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
});
|
||
|
containerEl.createEl('h2', { text: 'Ignored Files By Regex' });
|
||
|
containerEl.createEl('p', {
|
||
|
text: 'All files matching the above RegEx will get listed here',
|
||
|
});
|
||
|
regexIgnoredFilesDiv = containerEl.createDiv('test');
|
||
|
renderRegexIgnoredFiles(regexIgnoredFilesDiv);
|
||
|
containerEl.createEl('h2', { text: 'Manually Ignored Files' });
|
||
|
containerEl.createEl('p', {
|
||
|
text: 'You can ignore files from this plugin by using the "ignore this file" command',
|
||
|
});
|
||
|
var _loop_1 = function (key) {
|
||
|
var ignoredFilesSettingsObj = new obsidian.Setting(containerEl).setDesc(key);
|
||
|
ignoredFilesSettingsObj.addButton(function (button) {
|
||
|
button.setButtonText('Delete').onClick(function () { return __awaiter(_this, void 0, void 0, function () {
|
||
|
return __generator(this, function (_a) {
|
||
|
switch (_a.label) {
|
||
|
case 0:
|
||
|
delete this.plugin.settings.ignoredFiles[key];
|
||
|
return [4 /*yield*/, this.plugin.saveSettings()];
|
||
|
case 1:
|
||
|
_a.sent();
|
||
|
this.display();
|
||
|
return [2 /*return*/];
|
||
|
}
|
||
|
});
|
||
|
}); });
|
||
|
});
|
||
|
};
|
||
|
// go over all ignored files and add them
|
||
|
for (var key in this.plugin.settings.ignoredFiles) {
|
||
|
_loop_1(key);
|
||
|
}
|
||
|
};
|
||
|
return FilenameHeadingSyncSettingTab;
|
||
|
}(obsidian.PluginSettingTab));
|
||
|
|
||
|
module.exports = FilenameHeadingSyncPlugin;
|
||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsImV4Y2x1c2lvbnMudHMiLCJtYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSB
|