You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
441 lines
35 KiB
441 lines
35 KiB
/*
|
|
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 = {
|
|
regex: /^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})$/i,
|
|
lineRegex: /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/gi,
|
|
linkRegex: /^\[([^\[\]]*)\]\((https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})\)$/i,
|
|
linkLineRegex: /\[([^\[\]]*)\]\((https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})\)/gi,
|
|
imageRegex: /\.(gif|jpe?g|tiff?|png|webp|bmp|tga|psd|ai)$/i,
|
|
shouldReplaceSelection: true,
|
|
enhanceDefaultPaste: true,
|
|
};
|
|
class AutoLinkTitleSettingTab extends obsidian.PluginSettingTab {
|
|
constructor(app, plugin) {
|
|
super(app, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
display() {
|
|
let { containerEl } = this;
|
|
containerEl.empty();
|
|
new obsidian.Setting(containerEl)
|
|
.setName("Enhance Default Paste")
|
|
.setDesc("Fetch the link title when pasting a link in the editor with the default paste command")
|
|
.addToggle((val) => val
|
|
.setValue(this.plugin.settings.enhanceDefaultPaste)
|
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
console.log(value);
|
|
this.plugin.settings.enhanceDefaultPaste = value;
|
|
yield this.plugin.saveSettings();
|
|
})));
|
|
new obsidian.Setting(containerEl)
|
|
.setName("Replace Selection")
|
|
.setDesc("Whether to replace a text selection with link and fetched title")
|
|
.addToggle((val) => val
|
|
.setValue(this.plugin.settings.shouldReplaceSelection)
|
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
console.log(value);
|
|
this.plugin.settings.shouldReplaceSelection = value;
|
|
yield this.plugin.saveSettings();
|
|
})));
|
|
}
|
|
}
|
|
|
|
class EditorExtensions {
|
|
static getSelectedText(editor) {
|
|
if (!editor.somethingSelected()) {
|
|
let wordBoundaries = this.getWordBoundaries(editor);
|
|
editor.setSelection(wordBoundaries.start, wordBoundaries.end);
|
|
}
|
|
return editor.getSelection();
|
|
}
|
|
static cursorWithinBoundaries(cursor, match) {
|
|
let startIndex = match.index;
|
|
let endIndex = match.index + match[0].length;
|
|
return startIndex <= cursor.ch && cursor.ch <= endIndex;
|
|
}
|
|
static getWordBoundaries(editor) {
|
|
let cursor = editor.getCursor();
|
|
// If its a normal URL token this is not a markdown link
|
|
// In this case we can simply overwrite the link boundaries as-is
|
|
let lineText = editor.getLine(cursor.line);
|
|
// First check if we're in a link
|
|
let linksInLine = lineText.matchAll(DEFAULT_SETTINGS.linkLineRegex);
|
|
for (let match of linksInLine) {
|
|
if (this.cursorWithinBoundaries(cursor, match)) {
|
|
return {
|
|
start: { line: cursor.line, ch: match.index },
|
|
end: { line: cursor.line, ch: match.index + match[0].length },
|
|
};
|
|
}
|
|
}
|
|
// If not, check if we're in just a standard ol' URL.
|
|
let urlsInLine = lineText.matchAll(DEFAULT_SETTINGS.lineRegex);
|
|
for (let match of urlsInLine) {
|
|
if (this.cursorWithinBoundaries(cursor, match)) {
|
|
return {
|
|
start: { line: cursor.line, ch: match.index },
|
|
end: { line: cursor.line, ch: match.index + match[0].length },
|
|
};
|
|
}
|
|
}
|
|
return {
|
|
start: cursor,
|
|
end: cursor,
|
|
};
|
|
}
|
|
static getEditorPositionFromIndex(content, index) {
|
|
let substr = content.substr(0, index);
|
|
let l = 0;
|
|
let offset = -1;
|
|
let r = -1;
|
|
for (; (r = substr.indexOf("\n", r + 1)) !== -1; l++, offset = r)
|
|
;
|
|
offset += 1;
|
|
let ch = content.substr(offset, index - offset).length;
|
|
return { line: l, ch: ch };
|
|
}
|
|
}
|
|
|
|
class CheckIf {
|
|
static isMarkdownLinkAlready(editor) {
|
|
let cursor = editor.getCursor();
|
|
// Check if the characters before the url are ]( to indicate a markdown link
|
|
var titleEnd = editor.getRange({ ch: cursor.ch - 2, line: cursor.line }, { ch: cursor.ch, line: cursor.line });
|
|
return titleEnd == "](";
|
|
}
|
|
static isAfterQuote(editor) {
|
|
let cursor = editor.getCursor();
|
|
// Check if the characters before the url are " or ' to indicate we want the url directly
|
|
// This is common in elements like <a href="linkhere"></a>
|
|
var beforeChar = editor.getRange({ ch: cursor.ch - 1, line: cursor.line }, { ch: cursor.ch, line: cursor.line });
|
|
return beforeChar == "\"" || beforeChar == "'";
|
|
}
|
|
static isUrl(text) {
|
|
let urlRegex = new RegExp(DEFAULT_SETTINGS.regex);
|
|
return urlRegex.test(text);
|
|
}
|
|
static isImage(text) {
|
|
let imageRegex = new RegExp(DEFAULT_SETTINGS.imageRegex);
|
|
return imageRegex.test(text);
|
|
}
|
|
static isLinkedUrl(text) {
|
|
let urlRegex = new RegExp(DEFAULT_SETTINGS.linkRegex);
|
|
return urlRegex.test(text);
|
|
}
|
|
}
|
|
|
|
const electronPkg = require("electron");
|
|
function blank(text) {
|
|
return text === undefined || text === null || text === "";
|
|
}
|
|
function notBlank(text) {
|
|
return !blank(text);
|
|
}
|
|
// async wrapper to load a url and settle on load finish or fail
|
|
function load(window, url) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
return new Promise((resolve, reject) => {
|
|
window.webContents.on("did-finish-load", (event) => resolve(event));
|
|
window.webContents.on("did-fail-load", (event) => reject(event));
|
|
window.loadURL(url);
|
|
});
|
|
});
|
|
}
|
|
function electronGetPageTitle(url) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const { remote } = electronPkg;
|
|
const { BrowserWindow } = remote;
|
|
try {
|
|
const window = new BrowserWindow({
|
|
width: 1000,
|
|
height: 600,
|
|
webPreferences: {
|
|
webSecurity: false,
|
|
nodeIntegration: true,
|
|
images: false,
|
|
},
|
|
show: false,
|
|
});
|
|
yield load(window, url);
|
|
try {
|
|
const title = window.webContents.getTitle();
|
|
window.destroy();
|
|
if (notBlank(title)) {
|
|
return title;
|
|
}
|
|
else {
|
|
return url;
|
|
}
|
|
}
|
|
catch (ex) {
|
|
return url;
|
|
}
|
|
}
|
|
catch (ex) {
|
|
console.error(ex);
|
|
return "Site Unreachable";
|
|
}
|
|
});
|
|
}
|
|
function nonElectronGetPageTitle(url) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
try {
|
|
const html = yield obsidian.request({ url });
|
|
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
const title = doc.querySelectorAll("title")[0];
|
|
if (title == null || blank(title === null || title === void 0 ? void 0 : title.innerText)) {
|
|
// If site is javascript based and has a no-title attribute when unloaded, use it.
|
|
var noTitle = title === null || title === void 0 ? void 0 : title.getAttr("no-title");
|
|
if (notBlank(noTitle)) {
|
|
return noTitle;
|
|
}
|
|
// Otherwise if the site has no title/requires javascript simply return Title Unknown
|
|
return url;
|
|
}
|
|
return title.innerText;
|
|
}
|
|
catch (ex) {
|
|
console.error(ex);
|
|
return "Site Unreachable";
|
|
}
|
|
});
|
|
}
|
|
function getPageTitle(url) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
// If we're on Desktop use the Electron scraper
|
|
if (electronPkg != null) {
|
|
return electronGetPageTitle(url);
|
|
}
|
|
else {
|
|
return nonElectronGetPageTitle(url);
|
|
}
|
|
});
|
|
}
|
|
|
|
class AutoLinkTitle extends obsidian.Plugin {
|
|
onload() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
console.log("loading obsidian-auto-link-title");
|
|
yield this.loadSettings();
|
|
// Listen to paste event
|
|
this.pasteFunction = this.pasteUrlWithTitle.bind(this);
|
|
this.addCommand({
|
|
id: "auto-link-title-paste",
|
|
name: "Paste URL and auto fetch title",
|
|
callback: () => {
|
|
this.manualPasteUrlWithTitle();
|
|
},
|
|
hotkeys: [],
|
|
});
|
|
this.registerEvent(this.app.workspace.on("editor-paste", this.pasteFunction));
|
|
this.addCommand({
|
|
id: "enhance-url-with-title",
|
|
name: "Enhance existing URL with link and title",
|
|
callback: () => this.addTitleToLink(),
|
|
hotkeys: [
|
|
{
|
|
modifiers: ["Mod", "Shift"],
|
|
key: "e",
|
|
},
|
|
],
|
|
});
|
|
this.addSettingTab(new AutoLinkTitleSettingTab(this.app, this));
|
|
});
|
|
}
|
|
addTitleToLink() {
|
|
// Only attempt fetch if online
|
|
if (!navigator.onLine)
|
|
return;
|
|
let editor = this.getEditor();
|
|
if (editor == null)
|
|
return;
|
|
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
|
// If the cursor is on a raw html link, convert to a markdown link and fetch title
|
|
if (CheckIf.isUrl(selectedText)) {
|
|
this.convertUrlToTitledLink(editor, selectedText);
|
|
}
|
|
// If the cursor is on the URL part of a markdown link, fetch title and replace existing link title
|
|
else if (CheckIf.isLinkedUrl(selectedText)) {
|
|
var link = this.getUrlFromLink(selectedText);
|
|
this.convertUrlToTitledLink(editor, link);
|
|
}
|
|
}
|
|
// Simulate standard paste but using editor.replaceSelection with clipboard text since we can't seem to dispatch a paste event.
|
|
manualPasteUrlWithTitle() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
let editor = this.getEditor();
|
|
// Only attempt fetch if online
|
|
if (!navigator.onLine) {
|
|
editor.replaceSelection(clipboardText);
|
|
return;
|
|
}
|
|
var clipboardText = yield navigator.clipboard.readText();
|
|
if (clipboardText == null || clipboardText == "")
|
|
return;
|
|
// If its not a URL, we return false to allow the default paste handler to take care of it.
|
|
// Similarly, image urls don't have a meaningful <title> attribute so downloading it
|
|
// to fetch the title is a waste of bandwidth.
|
|
if (!CheckIf.isUrl(clipboardText) || CheckIf.isImage(clipboardText)) {
|
|
editor.replaceSelection(clipboardText);
|
|
return;
|
|
}
|
|
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
|
if (selectedText && !this.settings.shouldReplaceSelection) {
|
|
// If there is selected text and shouldReplaceSelection is false, do not fetch title
|
|
editor.replaceSelection(clipboardText);
|
|
return;
|
|
}
|
|
// If it looks like we're pasting the url into a markdown link already, don't fetch title
|
|
// as the user has already probably put a meaningful title, also it would lead to the title
|
|
// being inside the link.
|
|
if (CheckIf.isMarkdownLinkAlready(editor) || CheckIf.isAfterQuote(editor)) {
|
|
editor.replaceSelection(clipboardText);
|
|
return;
|
|
}
|
|
// At this point we're just pasting a link in a normal fashion, fetch its title.
|
|
this.convertUrlToTitledLink(editor, clipboardText);
|
|
return;
|
|
});
|
|
}
|
|
pasteUrlWithTitle(clipboard) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!this.settings.enhanceDefaultPaste) {
|
|
return;
|
|
}
|
|
// Only attempt fetch if online
|
|
if (!navigator.onLine)
|
|
return;
|
|
let editor = this.getEditor();
|
|
let clipboardText = clipboard.clipboardData.getData("text/plain");
|
|
if (clipboardText == null || clipboardText == "")
|
|
return;
|
|
// If its not a URL, we return false to allow the default paste handler to take care of it.
|
|
// Similarly, image urls don't have a meaningful <title> attribute so downloading it
|
|
// to fetch the title is a waste of bandwidth.
|
|
if (!CheckIf.isUrl(clipboardText) || CheckIf.isImage(clipboardText)) {
|
|
return;
|
|
}
|
|
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
|
if (selectedText && !this.settings.shouldReplaceSelection) {
|
|
// If there is selected text and shouldReplaceSelection is false, do not fetch title
|
|
return;
|
|
}
|
|
// We've decided to handle the paste, stop propagation to the default handler.
|
|
clipboard.stopPropagation();
|
|
clipboard.preventDefault();
|
|
// If it looks like we're pasting the url into a markdown link already, don't fetch title
|
|
// as the user has already probably put a meaningful title, also it would lead to the title
|
|
// being inside the link.
|
|
if (CheckIf.isMarkdownLinkAlready(editor) || CheckIf.isAfterQuote(editor)) {
|
|
editor.replaceSelection(clipboardText);
|
|
return;
|
|
}
|
|
// At this point we're just pasting a link in a normal fashion, fetch its title.
|
|
this.convertUrlToTitledLink(editor, clipboardText);
|
|
return;
|
|
});
|
|
}
|
|
convertUrlToTitledLink(editor, url) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
// Generate a unique id for find/replace operations for the title.
|
|
const pasteId = `Fetching Title#${this.createBlockHash()}`;
|
|
// Instantly paste so you don't wonder if paste is broken
|
|
editor.replaceSelection(`[${pasteId}](${url})`);
|
|
// Fetch title from site, replace Fetching Title with actual title
|
|
const title = yield this.fetchUrlTitle(url);
|
|
const text = editor.getValue();
|
|
const start = text.indexOf(pasteId);
|
|
if (start < 0) {
|
|
console.log(`Unable to find text "${pasteId}" in current editor, bailing out; link ${url}`);
|
|
}
|
|
else {
|
|
const end = start + pasteId.length;
|
|
const startPos = EditorExtensions.getEditorPositionFromIndex(text, start);
|
|
const endPos = EditorExtensions.getEditorPositionFromIndex(text, end);
|
|
editor.replaceRange(title, startPos, endPos);
|
|
}
|
|
});
|
|
}
|
|
fetchUrlTitle(url) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
try {
|
|
const title = yield getPageTitle(url);
|
|
return title.replace(/(\r\n|\n|\r)/gm, "").trim();
|
|
}
|
|
catch (error) {
|
|
// console.error(error)
|
|
return "Site Unreachable";
|
|
}
|
|
});
|
|
}
|
|
getEditor() {
|
|
let activeLeaf = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
|
if (activeLeaf == null)
|
|
return;
|
|
return activeLeaf.editor;
|
|
}
|
|
getUrlFromLink(link) {
|
|
let urlRegex = new RegExp(DEFAULT_SETTINGS.linkRegex);
|
|
return urlRegex.exec(link)[2];
|
|
}
|
|
// Custom hashid by @shabegom
|
|
createBlockHash() {
|
|
let result = "";
|
|
var characters = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
var charactersLength = characters.length;
|
|
for (var i = 0; i < 4; i++) {
|
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
}
|
|
return result;
|
|
}
|
|
onunload() {
|
|
console.log("unloading obsidian-auto-link-title");
|
|
this.app.workspace.containerEl.removeEventListener("paste", this.pasteFunction, true);
|
|
}
|
|
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 = AutoLinkTitle;
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNldHRpbmdzLnRzIiwiZWRpdG9yLWVuaGFuY2VtZW50cy50cyIsImNoZWNraWYudHMiLCJzY3JhcGVyLnRzIiwibWFpbi50cyJdLCJzb3VyY2VzQ29udGVudCI6bnVsbCwibmFtZXMiOlsiUGx1Z2luU2V0dGluZ1RhYiIsIlNldHRpbmciLCJyZXF1ZXN0IiwiUGx1Z2luIiwiTWFya2Rvd25WaWV3Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBdURBO0FBQ08sU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFO0FBQzdELElBQUksU0FBUyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsT0FBTyxLQUFLLFlBQVksQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFO0FBQ2hILElBQUksT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFO0FBQy9ELFFBQVEsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUNuRyxRQUFRLFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FB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
|