parent
4c354023b1
commit
e324422d1a
@ -1,674 +0,0 @@
|
||||
/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
https://github.com/joethei/obisidian-link-favicon
|
||||
*/
|
||||
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var __export = (target, all) => {
|
||||
__markAsModule(target);
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __reExport = (target, module2, desc) => {
|
||||
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
||||
for (let key of __getOwnPropNames(module2))
|
||||
if (!__hasOwnProp.call(target, key) && key !== "default")
|
||||
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
||||
}
|
||||
return target;
|
||||
};
|
||||
var __toModule = (module2) => {
|
||||
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
||||
};
|
||||
var __async = (__this, __arguments, generator) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
var fulfilled = (value) => {
|
||||
try {
|
||||
step(generator.next(value));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
};
|
||||
var rejected = (value) => {
|
||||
try {
|
||||
step(generator.throw(value));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
};
|
||||
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
||||
step((generator = generator.apply(__this, __arguments)).next());
|
||||
});
|
||||
};
|
||||
|
||||
// node_modules/@aidenlx/obsidian-icon-shortcodes/lib/index.js
|
||||
var require_lib = __commonJS({
|
||||
"node_modules/@aidenlx/obsidian-icon-shortcodes/lib/index.js"(exports) {
|
||||
var a = Object.create;
|
||||
var t = Object.defineProperty;
|
||||
var d = Object.getOwnPropertyDescriptor;
|
||||
var p = Object.getOwnPropertyNames;
|
||||
var f = Object.getPrototypeOf;
|
||||
var g = Object.prototype.hasOwnProperty;
|
||||
var o = (n) => t(n, "__esModule", { value: true });
|
||||
var l = (n, e) => {
|
||||
o(n);
|
||||
for (var i in e)
|
||||
t(n, i, { get: e[i], enumerable: true });
|
||||
};
|
||||
var c = (n, e, i) => {
|
||||
if (e && typeof e == "object" || typeof e == "function")
|
||||
for (let r of p(e))
|
||||
!g.call(n, r) && r !== "default" && t(n, r, { get: () => e[r], enumerable: !(i = d(e, r)) || i.enumerable });
|
||||
return n;
|
||||
};
|
||||
var u = (n) => c(o(t(n != null ? a(f(n)) : {}, "default", n && n.__esModule && "default" in n ? { get: () => n.default, enumerable: true } : { value: n, enumerable: true })), n);
|
||||
l(exports, { getApi: () => s, isPluginEnabled: () => P });
|
||||
var v = u(require("obsidian"));
|
||||
var s = (n) => {
|
||||
var e;
|
||||
return n ? (e = n.app.plugins.plugins["obsidian-icon-shortcodes"]) == null ? void 0 : e.api : window.IconSCAPIv0;
|
||||
};
|
||||
var P = (n) => s(n) !== void 0;
|
||||
}
|
||||
});
|
||||
|
||||
// src/main.ts
|
||||
__export(exports, {
|
||||
default: () => FaviconPlugin
|
||||
});
|
||||
var import_obsidian5 = __toModule(require("obsidian"));
|
||||
|
||||
// src/settings.ts
|
||||
var import_obsidian3 = __toModule(require("obsidian"));
|
||||
|
||||
// src/provider.ts
|
||||
var import_obsidian = __toModule(require("obsidian"));
|
||||
var providers = {
|
||||
"google": { name: "Google", url: (domain) => Promise.resolve("https://www.google.com/s2/favicons?domain=" + domain) },
|
||||
"duckduckgo": { name: "DuckDuckGo", url: (domain) => Promise.resolve("https://icons.duckduckgo.com/ip3/" + domain + ".ico") },
|
||||
"iconhorse": { name: "Icon Horse", url: (domain) => Promise.resolve("https://icon.horse/icon/" + domain) },
|
||||
"splitbee": { name: "Splitbee", url: (domain) => Promise.resolve("https://favicon.splitbee.io/?url=" + domain) },
|
||||
"besticon": { name: "The Favicon Finder", url: (domain, settings) => {
|
||||
const host = settings.provider === "besticon" ? settings.providerDomain : settings.fallbackProviderDomain;
|
||||
return Promise.resolve(host + "/icon?url=" + domain + "&size=32..64..256");
|
||||
} },
|
||||
"favicongrabber": { name: "Favicon Grabber", url: (domain) => __async(void 0, null, function* () {
|
||||
const icons = JSON.parse(yield (0, import_obsidian.request)({
|
||||
method: "GET",
|
||||
url: "https://favicongrabber.com/api/grab/" + domain
|
||||
}));
|
||||
if (icons.length === 0)
|
||||
return Promise.resolve("http://invalid.stuff");
|
||||
return Promise.resolve(icons.icons[0].src);
|
||||
}) }
|
||||
};
|
||||
|
||||
// src/OverwrittenIconModal.ts
|
||||
var import_obsidian2 = __toModule(require("obsidian"));
|
||||
var import_obsidian_icon_shortcodes = __toModule(require_lib());
|
||||
var OverwrittenIconModal = class extends import_obsidian2.Modal {
|
||||
constructor(plugin, map, name) {
|
||||
super(plugin.app);
|
||||
this.name = "Domain";
|
||||
this.plugin = plugin;
|
||||
if (name) {
|
||||
this.name = name;
|
||||
}
|
||||
if (map) {
|
||||
this.domain = map.domain;
|
||||
this.icon = map.icon;
|
||||
}
|
||||
}
|
||||
displayPreview(contentEl) {
|
||||
return __async(this, null, function* () {
|
||||
if ((0, import_obsidian_icon_shortcodes.isPluginEnabled)(this.plugin) && this.icon) {
|
||||
contentEl.empty();
|
||||
const iconPreview = contentEl.createDiv("preview");
|
||||
iconPreview.addClass("link-favicon-preview");
|
||||
const iconApi = (0, import_obsidian_icon_shortcodes.getApi)(this.plugin);
|
||||
const icon = iconApi.getIcon(this.icon, false);
|
||||
if (icon !== null)
|
||||
iconPreview.append(icon);
|
||||
}
|
||||
});
|
||||
}
|
||||
display() {
|
||||
return __async(this, null, function* () {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
let previewEL;
|
||||
new import_obsidian2.Setting(contentEl).setName(this.name).addText((text) => {
|
||||
text.setValue(this.domain).onChange((value) => {
|
||||
this.domain = value;
|
||||
});
|
||||
});
|
||||
const api = (0, import_obsidian_icon_shortcodes.getApi)(this.plugin);
|
||||
if (api) {
|
||||
if (api.version.compare(">=", "0.6.1")) {
|
||||
new import_obsidian2.Setting(contentEl).setName("Icon").addButton((button) => {
|
||||
button.setButtonText("Choose").onClick(() => __async(this, null, function* () {
|
||||
const icon = yield api.getIconFromUser();
|
||||
console.log(icon);
|
||||
if (icon) {
|
||||
this.icon = icon.id;
|
||||
if (previewEL) {
|
||||
yield this.displayPreview(previewEL);
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
new import_obsidian2.Setting(contentEl).setName("Icon").addText((text) => {
|
||||
text.setValue(this.icon).onChange((value) => __async(this, null, function* () {
|
||||
this.icon = value;
|
||||
if (previewEL) {
|
||||
yield this.displayPreview(previewEL);
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
previewEL = contentEl.createDiv("preview");
|
||||
yield this.displayPreview(previewEL);
|
||||
const footerEl = contentEl.createDiv();
|
||||
const footerButtons = new import_obsidian2.Setting(footerEl);
|
||||
footerButtons.addButton((b) => {
|
||||
b.setTooltip("Save").setIcon("checkmark").onClick(() => __async(this, null, function* () {
|
||||
this.saved = true;
|
||||
this.close();
|
||||
}));
|
||||
return b;
|
||||
});
|
||||
footerButtons.addExtraButton((b) => {
|
||||
b.setIcon("cross").setTooltip("Cancel").onClick(() => {
|
||||
this.saved = false;
|
||||
this.close();
|
||||
});
|
||||
return b;
|
||||
});
|
||||
});
|
||||
}
|
||||
onOpen() {
|
||||
return __async(this, null, function* () {
|
||||
yield this.display();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// src/settings.ts
|
||||
var import_obsidian_icon_shortcodes2 = __toModule(require_lib());
|
||||
var DEFAULT_SETTINGS = {
|
||||
provider: "duckduckgo",
|
||||
fallbackProvider: "google",
|
||||
providerDomain: "",
|
||||
fallbackProviderDomain: "",
|
||||
ignored: "",
|
||||
overwritten: [],
|
||||
protocol: []
|
||||
};
|
||||
var FaviconSettings = class extends import_obsidian3.PluginSettingTab {
|
||||
constructor(app, plugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
display() {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
containerEl.createEl("h2", { text: "Link Favicons" });
|
||||
new import_obsidian3.Setting(containerEl).setName("Icon Provider").addDropdown((dropdown) => {
|
||||
for (const id in providers) {
|
||||
if (providers.hasOwnProperty(id)) {
|
||||
dropdown.addOption(id, providers[id].name);
|
||||
}
|
||||
}
|
||||
dropdown.setValue(this.plugin.settings.provider).onChange((value) => __async(this, null, function* () {
|
||||
this.plugin.settings.provider = value;
|
||||
yield this.plugin.saveSettings();
|
||||
this.display();
|
||||
}));
|
||||
});
|
||||
if (Array.of("besticon").includes(this.plugin.settings.provider)) {
|
||||
new import_obsidian3.Setting(containerEl).setName("Provider Domain").setDesc("This Provider is selfhosted, please specify your deployment url. Refer to the readme of the provider for deployment instructions.").addText((text) => text.setValue(this.plugin.settings.providerDomain).onChange((value) => __async(this, null, function* () {
|
||||
this.plugin.settings.providerDomain = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
}
|
||||
new import_obsidian3.Setting(containerEl).setName("Fallback Icon Provider").addDropdown((dropdown) => {
|
||||
for (const id in providers) {
|
||||
if (providers.hasOwnProperty(id)) {
|
||||
dropdown.addOption(id, providers[id].name);
|
||||
}
|
||||
}
|
||||
dropdown.setValue(this.plugin.settings.fallbackProvider).onChange((value) => __async(this, null, function* () {
|
||||
this.plugin.settings.fallbackProvider = value;
|
||||
yield this.plugin.saveSettings();
|
||||
this.display();
|
||||
}));
|
||||
});
|
||||
if (Array.of("besticon").includes(this.plugin.settings.fallbackProvider)) {
|
||||
new import_obsidian3.Setting(containerEl).setName("Fallback Provider Domain").setDesc("This Provider is be selfhosted, please specify your deployment url. Refer to the readme of the provider for deployment instructions.").addText((text) => text.setValue(this.plugin.settings.fallbackProviderDomain).onChange((value) => __async(this, null, function* () {
|
||||
this.plugin.settings.fallbackProviderDomain = value;
|
||||
yield this.plugin.saveSettings();
|
||||
})));
|
||||
}
|
||||
new import_obsidian3.Setting(containerEl).setName("Ignored Domains").setDesc("Don't show an favicon for these domains(one per line)").addTextArea((text) => {
|
||||
text.setValue(this.plugin.settings.ignored).onChange((value) => __async(this, null, function* () {
|
||||
this.plugin.settings.ignored = value;
|
||||
yield this.plugin.saveSettings();
|
||||
}));
|
||||
text.inputEl.setAttr("rows", 8);
|
||||
});
|
||||
if ((0, import_obsidian_icon_shortcodes2.isPluginEnabled)(this.plugin)) {
|
||||
containerEl.createEl("h2", { text: "Custom icons" });
|
||||
containerEl.createEl("h3", { text: "for Domains" });
|
||||
new import_obsidian3.Setting(containerEl).setName("Add New").setDesc("Add custom icon").addButton((button) => {
|
||||
return button.setTooltip("add custom icon").setIcon("plus-with-circle").onClick(() => __async(this, null, function* () {
|
||||
const modal = new OverwrittenIconModal(this.plugin);
|
||||
modal.onClose = () => __async(this, null, function* () {
|
||||
if (modal.saved) {
|
||||
this.plugin.settings.overwritten.push({
|
||||
domain: modal.domain,
|
||||
icon: modal.icon
|
||||
});
|
||||
yield this.plugin.saveSettings();
|
||||
this.display();
|
||||
}
|
||||
});
|
||||
modal.open();
|
||||
}));
|
||||
});
|
||||
const overwrittenContainer = containerEl.createDiv("overwritten");
|
||||
const overwrittenDiv = overwrittenContainer.createDiv("overwritten");
|
||||
for (const overwritten of this.plugin.settings.overwritten) {
|
||||
const setting = new import_obsidian3.Setting(overwrittenDiv);
|
||||
const iconAPI = (0, import_obsidian_icon_shortcodes2.getApi)(this.plugin);
|
||||
const desc = new DocumentFragment();
|
||||
desc.createEl("p", { text: " " + overwritten.icon }).prepend(iconAPI.getIcon(overwritten.icon));
|
||||
setting.setName(overwritten.domain).setDesc(desc).addExtraButton((b) => {
|
||||
b.setIcon("pencil").setTooltip("Edit").onClick(() => {
|
||||
const modal = new OverwrittenIconModal(this.plugin, overwritten);
|
||||
modal.onClose = () => __async(this, null, function* () {
|
||||
if (modal.saved) {
|
||||
const setting2 = this.plugin.settings.overwritten.filter((overwritten2) => {
|
||||
return overwritten2.domain !== modal.domain;
|
||||
});
|
||||
setting2.push({ domain: modal.domain, icon: modal.icon });
|
||||
this.plugin.settings.overwritten = setting2;
|
||||
yield this.plugin.saveSettings();
|
||||
this.display();
|
||||
}
|
||||
});
|
||||
modal.open();
|
||||
});
|
||||
}).addExtraButton((b) => {
|
||||
b.setIcon("trash").setTooltip("Delete").onClick(() => __async(this, null, function* () {
|
||||
this.plugin.settings.overwritten = this.plugin.settings.overwritten.filter((tmp) => {
|
||||
return overwritten.domain !== tmp.domain;
|
||||
});
|
||||
yield this.plugin.saveSettings();
|
||||
this.display();
|
||||
}));
|
||||
});
|
||||
}
|
||||
containerEl.createEl("h3", { text: "for URI Schemas" });
|
||||
new import_obsidian3.Setting(containerEl).setName("Add New").setDesc("Add custom icon").addButton((button) => {
|
||||
return button.setTooltip("add custom icon").setIcon("plus-with-circle").onClick(() => __async(this, null, function* () {
|
||||
const modal = new OverwrittenIconModal(this.plugin, null, "URI Schema");
|
||||
modal.onClose = () => __async(this, null, function* () {
|
||||
if (modal.saved) {
|
||||
this.plugin.settings.protocol.push({
|
||||
domain: modal.domain,
|
||||
icon: modal.icon
|
||||
});
|
||||
yield this.plugin.saveSettings();
|
||||
this.display();
|
||||
}
|
||||
});
|
||||
modal.open();
|
||||
}));
|
||||
});
|
||||
const protocolContainer = containerEl.createDiv("overwritten");
|
||||
const voicesDiv = protocolContainer.createDiv("overwritten");
|
||||
for (const protocol of this.plugin.settings.protocol) {
|
||||
const setting = new import_obsidian3.Setting(voicesDiv);
|
||||
const iconAPI = (0, import_obsidian_icon_shortcodes2.getApi)(this.plugin);
|
||||
const desc = new DocumentFragment();
|
||||
desc.createEl("p", { text: " " + protocol.icon }).prepend(iconAPI.getIcon(protocol.icon));
|
||||
setting.setName(protocol.domain).setDesc(desc).addExtraButton((b) => {
|
||||
b.setIcon("pencil").setTooltip("Edit").onClick(() => {
|
||||
const modal = new OverwrittenIconModal(this.plugin, protocol, "URI Schema");
|
||||
modal.onClose = () => __async(this, null, function* () {
|
||||
if (modal.saved) {
|
||||
const setting2 = this.plugin.settings.protocol.filter((overwritten) => {
|
||||
return overwritten.domain !== modal.domain;
|
||||
});
|
||||
setting2.push({ domain: modal.domain, icon: modal.icon });
|
||||
this.plugin.settings.protocol = setting2;
|
||||
yield this.plugin.saveSettings();
|
||||
this.display();
|
||||
}
|
||||
});
|
||||
modal.open();
|
||||
});
|
||||
}).addExtraButton((b) => {
|
||||
b.setIcon("trash").setTooltip("Delete").onClick(() => __async(this, null, function* () {
|
||||
this.plugin.settings.protocol = this.plugin.settings.protocol.filter((overwritten) => {
|
||||
return overwritten.domain !== protocol.domain;
|
||||
});
|
||||
yield this.plugin.saveSettings();
|
||||
this.display();
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// src/main.ts
|
||||
var import_obsidian_icon_shortcodes3 = __toModule(require_lib());
|
||||
var import_state2 = __toModule(require("@codemirror/state"));
|
||||
|
||||
// src/Decorations.ts
|
||||
var import_obsidian4 = __toModule(require("obsidian"));
|
||||
var import_view = __toModule(require("@codemirror/view"));
|
||||
var import_state = __toModule(require("@codemirror/state"));
|
||||
var import_language = __toModule(require("@codemirror/language"));
|
||||
var import_stream_parser = __toModule(require("@codemirror/stream-parser"));
|
||||
var statefulDecorations = defineStatefulDecoration();
|
||||
var StatefulDecorationSet = class {
|
||||
constructor(editor, plugin) {
|
||||
this.decoCache = Object.create(null);
|
||||
this.debouncedUpdate = (0, import_obsidian4.debounce)(this.updateAsyncDecorations, 100, true);
|
||||
this.editor = editor;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
computeAsyncDecorations(tokens) {
|
||||
return __async(this, null, function* () {
|
||||
const decorations = [];
|
||||
for (let token of tokens) {
|
||||
let deco = this.decoCache[token.value];
|
||||
if (!deco) {
|
||||
const provider = providers[this.plugin.settings.provider];
|
||||
const fallbackProvider = providers[this.plugin.settings.fallbackProvider];
|
||||
let url;
|
||||
try {
|
||||
url = new URL(token.value);
|
||||
} catch (e) {
|
||||
console.error("Invalid url: " + token.value);
|
||||
console.error(e);
|
||||
}
|
||||
const icon = yield this.plugin.getIcon(url, provider);
|
||||
const fallbackIcon = yield this.plugin.getIcon(url, fallbackProvider);
|
||||
const domain = url.protocol.contains("http") ? url.hostname : url.protocol;
|
||||
deco = this.decoCache[token.value] = import_view.Decoration.widget({ widget: new IconWidget(this.plugin, icon, fallbackIcon, domain) });
|
||||
}
|
||||
decorations.push(deco.range(token.from, token.from));
|
||||
}
|
||||
return import_view.Decoration.set(decorations, true);
|
||||
});
|
||||
}
|
||||
updateAsyncDecorations(tokens) {
|
||||
return __async(this, null, function* () {
|
||||
const decorations = yield this.computeAsyncDecorations(tokens);
|
||||
if (decorations || this.editor.state.field(statefulDecorations.field).size) {
|
||||
this.editor.dispatch({ effects: statefulDecorations.update.of(decorations || import_view.Decoration.none) });
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
function buildViewPlugin(plugin) {
|
||||
return import_view.ViewPlugin.fromClass(class {
|
||||
constructor(view) {
|
||||
this.decoManager = new StatefulDecorationSet(view, plugin);
|
||||
this.buildAsyncDecorations(view);
|
||||
}
|
||||
update(update) {
|
||||
if (update.docChanged || update.viewportChanged) {
|
||||
this.buildAsyncDecorations(update.view);
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
}
|
||||
buildAsyncDecorations(view) {
|
||||
const targetElements = [];
|
||||
for (let { from, to } of view.visibleRanges) {
|
||||
const tree = (0, import_language.syntaxTree)(view.state);
|
||||
tree.iterate({
|
||||
from,
|
||||
to,
|
||||
enter: (type, from2, to2) => {
|
||||
const tokenProps = type.prop(import_stream_parser.tokenClassNodeProp);
|
||||
if (tokenProps) {
|
||||
const props = new Set(tokenProps.split(" "));
|
||||
const isExternalLink = props.has("url");
|
||||
const linkText = view.state.doc.sliceString(from2, to2);
|
||||
if (isExternalLink && linkText.contains("://")) {
|
||||
const line = view.state.doc.lineAt(from2);
|
||||
const toLine = line.to - to2;
|
||||
const toLineT = line.length - toLine;
|
||||
const fromIndex = line.text.lastIndexOf("[", toLineT);
|
||||
if (fromIndex === -1) {
|
||||
return;
|
||||
}
|
||||
const fromTarget = line.from + fromIndex;
|
||||
targetElements.push({ from: fromTarget, to: to2, value: linkText });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
this.decoManager.debouncedUpdate(targetElements);
|
||||
}
|
||||
});
|
||||
}
|
||||
function asyncDecoBuilderExt(plugin) {
|
||||
return [statefulDecorations.field, buildViewPlugin(plugin)];
|
||||
}
|
||||
function defineStatefulDecoration() {
|
||||
const update = import_state.StateEffect.define();
|
||||
const field = import_state.StateField.define({
|
||||
create() {
|
||||
return import_view.Decoration.none;
|
||||
},
|
||||
update(deco, tr) {
|
||||
return tr.effects.reduce((deco2, effect) => effect.is(update) ? effect.value : deco2, deco.map(tr.changes));
|
||||
},
|
||||
provide: (field2) => import_view.EditorView.decorations.from(field2)
|
||||
});
|
||||
return { update, field };
|
||||
}
|
||||
var IconWidget = class extends import_view.WidgetType {
|
||||
constructor(plugin, icon, fallbackIcon, domain) {
|
||||
super();
|
||||
this.plugin = plugin;
|
||||
this.icon = icon;
|
||||
this.fallbackIcon = fallbackIcon;
|
||||
this.domain = domain;
|
||||
}
|
||||
eq(other) {
|
||||
return other == this;
|
||||
}
|
||||
toDOM() {
|
||||
if (!this.icon || this.icon === "") {
|
||||
return document.createElement("span");
|
||||
}
|
||||
if (typeof this.icon === "string") {
|
||||
if (!this.icon.startsWith("http")) {
|
||||
const span = document.createElement("span");
|
||||
span.textContent = this.icon;
|
||||
span.className = "link-favicon";
|
||||
return span;
|
||||
}
|
||||
const el = document.createElement("object");
|
||||
el.addClass("link-favicon");
|
||||
el.dataset.host = this.domain;
|
||||
el.data = this.icon;
|
||||
el.data.contains(".ico") ? el.type = "image/x-icon" : el.type = "image/png";
|
||||
el.style.height = "0.8em";
|
||||
el.style.display = "inline-block";
|
||||
if (typeof this.fallbackIcon === "string") {
|
||||
const img = el.createEl("img");
|
||||
img.src = this.fallbackIcon;
|
||||
img.addClass("link-favicon");
|
||||
img.style.height = "0.8em";
|
||||
img.style.display = "block";
|
||||
el.append(img);
|
||||
}
|
||||
return el;
|
||||
} else {
|
||||
return this.icon;
|
||||
}
|
||||
}
|
||||
ignoreEvent() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// src/main.ts
|
||||
var FaviconPlugin = class extends import_obsidian5.Plugin {
|
||||
isDisabled(el) {
|
||||
if (el.getAttribute("data-no-favicon"))
|
||||
return true;
|
||||
if (el.getAttribute("data-favicon"))
|
||||
return true;
|
||||
}
|
||||
getCustomDomainIcon(domain) {
|
||||
if ((0, import_obsidian_icon_shortcodes3.isPluginEnabled)(this)) {
|
||||
const icons = this.settings.overwritten.filter((value) => value.domain === domain);
|
||||
if (icons.length > 0) {
|
||||
const iconApi = (0, import_obsidian_icon_shortcodes3.getApi)(this);
|
||||
const icon = icons[0].icon;
|
||||
return iconApi.getIcon(icon, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
getCustomSchemeIcon(scheme) {
|
||||
if ((0, import_obsidian_icon_shortcodes3.isPluginEnabled)(this)) {
|
||||
const icons = this.settings.protocol.filter((value) => value.domain === scheme.substr(0, scheme.length - 1));
|
||||
if (icons.length > 0) {
|
||||
const iconApi = (0, import_obsidian_icon_shortcodes3.getApi)(this);
|
||||
const icon = icons[0].icon;
|
||||
return iconApi.getIcon(icon, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
getIcon(domain, provider) {
|
||||
return __async(this, null, function* () {
|
||||
if (!domain.protocol.startsWith("http")) {
|
||||
const customSchemeIcon = this.getCustomSchemeIcon(domain.protocol);
|
||||
if (customSchemeIcon) {
|
||||
if (typeof customSchemeIcon !== "string") {
|
||||
customSchemeIcon.addClass("link-favicon");
|
||||
customSchemeIcon.dataset.host = domain.hostname;
|
||||
}
|
||||
return customSchemeIcon;
|
||||
}
|
||||
}
|
||||
if (this.settings.ignored.split("\n").contains(domain.hostname)) {
|
||||
return "";
|
||||
}
|
||||
const customDomainIcon = this.getCustomDomainIcon(domain.hostname);
|
||||
if (customDomainIcon) {
|
||||
if (typeof customDomainIcon !== "string") {
|
||||
customDomainIcon.addClass("link-favicon");
|
||||
customDomainIcon.dataset.host = domain.hostname;
|
||||
}
|
||||
return customDomainIcon;
|
||||
}
|
||||
return provider.url(domain.hostname, this.settings);
|
||||
});
|
||||
}
|
||||
onload() {
|
||||
return __async(this, null, function* () {
|
||||
console.log("enabling plugin: link favicons");
|
||||
yield this.loadSettings();
|
||||
this.addSettingTab(new FaviconSettings(this.app, this));
|
||||
this.registerEditorExtension(import_state2.Prec.lowest(asyncDecoBuilderExt(this)));
|
||||
this.registerMarkdownPostProcessor((element, ctx) => __async(this, null, function* () {
|
||||
if (ctx.sourcePath.contains("no-favicon")) {
|
||||
return;
|
||||
}
|
||||
const provider = providers[this.settings.provider];
|
||||
const fallbackProvider = providers[this.settings.fallbackProvider];
|
||||
if (!provider || !fallbackProvider) {
|
||||
console.error("Link Favicons: misconfigured providers");
|
||||
return;
|
||||
}
|
||||
const links = element.querySelectorAll("a.external-link:not([data-favicon])");
|
||||
for (let index = 0; index < links.length; index++) {
|
||||
const link = links.item(index);
|
||||
if (!this.isDisabled(link)) {
|
||||
link.dataset.favicon = "true";
|
||||
let domain;
|
||||
try {
|
||||
domain = new URL(link.href);
|
||||
} catch (e) {
|
||||
console.error("Invalid url: " + link.href);
|
||||
console.error(e);
|
||||
}
|
||||
if (!domain)
|
||||
continue;
|
||||
const icon = yield this.getIcon(domain, provider);
|
||||
const fallbackIcon = yield this.getIcon(domain, fallbackProvider);
|
||||
let el;
|
||||
if (!icon || icon === "") {
|
||||
continue;
|
||||
}
|
||||
if (typeof icon === "string") {
|
||||
if (!icon.startsWith("http")) {
|
||||
el = icon;
|
||||
} else {
|
||||
el = document.createElement("object");
|
||||
el.addClass("link-favicon");
|
||||
el.dataset.host = domain.hostname;
|
||||
el.data = icon;
|
||||
el.data.contains(".ico") ? el.type = "image/x-icon" : el.type = "image/png";
|
||||
el.style.height = "0.8em";
|
||||
el.style.display = "inline-block";
|
||||
}
|
||||
} else {
|
||||
el = icon;
|
||||
}
|
||||
if (!el)
|
||||
continue;
|
||||
if (typeof el !== "string" && typeof fallbackIcon === "string") {
|
||||
const img = el.createEl("img");
|
||||
img.src = fallbackIcon;
|
||||
img.addClass("link-favicon");
|
||||
img.style.height = "0.8em";
|
||||
img.style.display = "block";
|
||||
el.append(img);
|
||||
}
|
||||
if (el) {
|
||||
link.prepend(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
onunload() {
|
||||
console.log("disabling plugin: link favicons");
|
||||
}
|
||||
loadSettings() {
|
||||
return __async(this, null, function* () {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
|
||||
});
|
||||
}
|
||||
saveSettings() {
|
||||
return __async(this, null, function* () {
|
||||
yield this.saveData(this.settings);
|
||||
});
|
||||
}
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"id": "link-favicon",
|
||||
"name": "Link Favicons",
|
||||
"version": "1.4.1",
|
||||
"minAppVersion": "0.13.14",
|
||||
"description": "See the favicon for a linked website. ",
|
||||
"author": "Johannes Theiner",
|
||||
"authorUrl": "https://github.com/joethei",
|
||||
"isDesktopOnly": false
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
.link-favicon{
|
||||
vertical-align: bottom;
|
||||
margin-bottom: 0.3em;
|
||||
margin-left: 0.1em;
|
||||
margin-right: 0.1em;
|
||||
cursor: pointer !important;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
}
|
||||
|
||||
.link-favicon-preview {
|
||||
font-size: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.link-favicon-preview img{
|
||||
height: 50px;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "obsidian-sortable",
|
||||
"name": "Sortable",
|
||||
"version": "0.2.0",
|
||||
"minAppVersion": "0.12.0",
|
||||
"description": "Wiki-like table sorting.",
|
||||
"author": "Alexandru Dinu",
|
||||
"authorUrl": "https://github.com/alexandru-dinu",
|
||||
"isDesktopOnly": false
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
.theme-light {
|
||||
--arrows-up: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='4' viewBox='0 0 21 4'%3E%3Cpath d='M6.5 4l4-4 4 4z'/%3E%3C/svg%3E");
|
||||
--arrows-down: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='4' viewBox='0 0 21 4'%3E%3Cpath d='M14.5 0l-4 4-4-4z'/%3E%3C/svg%3E");
|
||||
--arrows-up-down: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='9' viewBox='0 0 21 9'%3E%3Cpath d='M14.5 5l-4 4-4-4zm0-1l-4-4-4 4z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.theme-dark {
|
||||
--arrows-up: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='4' viewBox='0 0 21 4'%3E%3Cpath fill='grey' d='M6.5 4l4-4 4 4z'/%3E%3C/svg%3E");
|
||||
--arrows-down: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='4' viewBox='0 0 21 4'%3E%3Cpath fill='grey' d='M14.5 0l-4 4-4-4z'/%3E%3C/svg%3E");
|
||||
--arrows-up-down: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='9' viewBox='0 0 21 9'%3E%3Cpath fill='grey' d='M14.5 5l-4 4-4-4zm0-1l-4-4-4 4z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.markdown-preview-view th {
|
||||
background-image: var(--arrows-up-down);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center right;
|
||||
padding-right: 21px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
th[sortable-style="sortable-asc"] {
|
||||
background-image: var(--arrows-up);
|
||||
}
|
||||
|
||||
th[sortable-style="sortable-desc"] {
|
||||
background-image: var(--arrows-down);
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,229 @@
|
||||
/* READ ME */
|
||||
/*
|
||||
This css has been built to be used with dataview tables, and assumes you are not using dataviewjs. But this can easily be adapted to list view. Because this css is not supported by a js backend, text and backgrounds will not autosize (i think so anyway, i haven't found a way. if you do share on discord @yungbananapeel#2624)
|
||||
|
||||
I'm not that great as using css, so there is probably a lot of redundancies in the file. The Main thing to understand about using the css to manipulate the tables is the structure of a DV table.
|
||||
|
||||
Any content about a page you want returned is delivered as a child element of a span, that is nested inside of a TD.The TD's are the individual containers that make up the columns of a row. if you want to change the structure of a table on top of this file, its important to remember all the relationships between the TR>TD>SPAN>CONTENT.
|
||||
|
||||
An an example images and links are returned as <a> & <img> tags as children of a div, but strings are returned as the content of the span, not as content of a child element.like so:
|
||||
<span>
|
||||
<a href="mylink"> cool link </a>
|
||||
<img src="prettyPic"> picture </img>
|
||||
</span>
|
||||
<span>YOUR TEXT HERE</span>
|
||||
|
||||
TABLE STRUCTURE
|
||||
<div>
|
||||
<table>
|
||||
<thead>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
EACH TR CORRESPONDS TO A SINGLE PAGE RETURNED FROM YOUR QUERY.
|
||||
<td>
|
||||
EACH TD CORRESPONDS TO A COLUMN
|
||||
THEY ARE ORDERED TOP TO BOTTOM, IN ORDER FROM LEFT TO RIGHT
|
||||
<span>
|
||||
THIS SPAN IS WHERE YOUR RETURNS INFO IS (links, images, text)
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
*/
|
||||
/* COLORS */
|
||||
.CardView {
|
||||
--Name-bg: red;
|
||||
--
|
||||
}
|
||||
/* Hide Table Head */
|
||||
.CardView thead{
|
||||
display: none;
|
||||
line-height: 0;
|
||||
height: 0px;
|
||||
}
|
||||
CardView table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
/* Table wide Changes */
|
||||
/* .CardView tbody {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
} */
|
||||
/* Turn all spans into flex boxes*/
|
||||
.CardView span {
|
||||
display: flex;
|
||||
float: left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-width: 350px;
|
||||
}
|
||||
/* Create a card Shape from the Table Row */
|
||||
.CardView tr {
|
||||
display: block;
|
||||
text-align: justify;
|
||||
float: left;
|
||||
padding: 0;
|
||||
margin-right: 60px;
|
||||
height: 475px;
|
||||
width: 310px;
|
||||
background-color: rgb(36, 32, 32) !important;
|
||||
border: 5px solid rgb(0, 0, 0) !important;
|
||||
box-shadow: 10px 11px 19px -1px #070202;
|
||||
}
|
||||
|
||||
.CardView td {
|
||||
display: block;
|
||||
min-height: 50px;
|
||||
padding: 15px;
|
||||
}
|
||||
/* First Column Box*/
|
||||
.CardView td:first-child {
|
||||
min-height: 75px !important ;
|
||||
padding: auto;
|
||||
background-color: rgba(255, 255, 255, 0.863);
|
||||
border: 5px solid rgb(255, 255, 255);
|
||||
}
|
||||
/* First Column link */
|
||||
.CardView td:first-child span a {
|
||||
text-overflow: ellipsis !important;
|
||||
word-wrap: break-word !important;
|
||||
text-overflow: ellipsis !important;
|
||||
display: block;
|
||||
line-height: 1em;
|
||||
max-height: 2em;
|
||||
font-size: 23px;
|
||||
font-weight: bold !important;
|
||||
color: rgb(207, 17, 17) !important;
|
||||
}
|
||||
|
||||
/* Second Column */
|
||||
/* column bg */
|
||||
.CardView td:nth-child(2) {
|
||||
z-index: 2;
|
||||
background-color: rgb(226, 75, 75);
|
||||
width: 175px;
|
||||
display: block;
|
||||
float: left;
|
||||
line-height: 1em;
|
||||
max-height: 2em;
|
||||
}
|
||||
/* column link */
|
||||
.CardView td:nth-child(2) a {
|
||||
color: rgb(206, 211, 189) !important;
|
||||
font-weight: bold !important;
|
||||
width: 60px;
|
||||
word-wrap: break-word;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
|
||||
/* third column */
|
||||
.CardView td:nth-child(3) {
|
||||
max-height: 50px !important;
|
||||
color: rgb(255, 81, 81) !important;
|
||||
z-index: -1;
|
||||
width: 125px;
|
||||
line-height: 1em;
|
||||
max-height: 2em;
|
||||
display: block;
|
||||
float: right;
|
||||
background-color: rgb(250, 246, 0);
|
||||
}
|
||||
/* third column links */
|
||||
.CardView td:nth-child(3) span a {
|
||||
color: rgb(255, 81, 81) !important;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
float: right;
|
||||
font-weight: bold !important;
|
||||
word-wrap: break-word;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
/* third column strings */
|
||||
.CardView td:nth-child(3) span{
|
||||
color: rgb(255, 81, 81) !important;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
float: right;
|
||||
font-weight: bold !important;
|
||||
word-wrap: break-word;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
|
||||
.CardView td:nth-child(4) {
|
||||
z-index: 2;
|
||||
background-color: rgb(226, 75, 75);
|
||||
width: 175px;
|
||||
display: block;
|
||||
float: left;
|
||||
line-height: 1em;
|
||||
max-height: 2em;
|
||||
}
|
||||
/* column link */
|
||||
.CardView td:nth-child(4) a {
|
||||
color: rgb(206, 211, 189) !important;
|
||||
font-weight: bold !important;
|
||||
width: 60px;
|
||||
word-wrap: break-word;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
|
||||
/* third column */
|
||||
.CardView td:nth-child(5) {
|
||||
max-height: 50px !important;
|
||||
color: rgb(255, 81, 81) !important;
|
||||
z-index: -1;
|
||||
width: 125px;
|
||||
line-height: 1em;
|
||||
max-height: 2em;
|
||||
display: block;
|
||||
float: right;
|
||||
background-color: rgb(250, 246, 0);
|
||||
}
|
||||
/* third column links */
|
||||
.CardView td:nth-child(5) span a {
|
||||
color: rgb(255, 81, 81) !important;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
float: right;
|
||||
font-weight: bold !important;
|
||||
word-wrap: break-word;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
/* third column strings */
|
||||
.CardView td:nth-child(5) span{
|
||||
color: rgb(255, 81, 81) !important;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
float: right;
|
||||
font-weight: bold !important;
|
||||
word-wrap: break-word;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
|
||||
/* Last Column Image */
|
||||
.CardView td span img {
|
||||
display: block;
|
||||
width: 300px;
|
||||
height: 250px;
|
||||
object-fit: contain;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
Loading…
Reference in new issue