This commit is contained in:
torsten 2026-03-06 16:34:59 +01:00
parent 1e4127f89e
commit ff05109422
52 changed files with 388 additions and 131 deletions

View file

@ -9,5 +9,6 @@
"landscape": false,
"margin": "1",
"downscalePercent": 100
}
},
"newFileLocation": "current"
}

View file

@ -1,10 +1,11 @@
[
"obsidian-style-settings",
"fantasy-name",
"fantasy-content-generator",
"obsidian-excalidraw-plugin",
"oz-clear-unused-images",
"editing-toolbar",
"obsidian-excalidraw-plugin",
"obsidian-style-settings",
"mousewheel-image-zoom",
"manual-sorting",
"editing-toolbar"
"obsidian-leaflet-plugin",
"fantasy-name",
"fantasy-content-generator"
]

View file

@ -2,12 +2,6 @@
"customOrder": {
"/": {
"children": [
"Pasted image 20260305221102.png",
"Pasted image 20260305221419.png",
"Pasted image 20260305221556.png",
"Pasted image 20260305221755.png",
"Pasted image 20260305222825.png",
"wohnung_silbergasse.jpg",
"1-Sessions",
"2-Spieler",
"3-Welt",
@ -15,7 +9,6 @@
"5-Regeln",
"6-Dokumente",
"7-Prep",
"Excalidraw",
"zz_archiv"
],
"sortOrder": "custom"
@ -31,7 +24,7 @@
"1-Sessions/Sitzung 005, 18.07.2025.md",
"1-Sessions/Sitzung 006, 03.10.2025.md",
"1-Sessions/Sitzung 007, 09.01.2026.md",
"1-Sessions/Sitzung 008 prep.md"
"1-Sessions/Sitzung 008 Prep 06.03.2026"
],
"sortOrder": "custom"
},
@ -77,6 +70,14 @@
],
"sortOrder": "custom"
},
"1-Sessions/Sitzung 008 Prep 06.03.2026": {
"children": [
"1-Sessions/Sitzung 008 Prep 06.03.2026/Garana Events.md",
"1-Sessions/Sitzung 008 Prep 06.03.2026/Übersicht Prep 08.md",
"1-Sessions/Sitzung 008 Prep 06.03.2026/Hooks.md"
],
"sortOrder": "custom"
},
"1-Sessions/Sitzungsarchiv": {
"children": [
"1-Sessions/Sitzungsarchiv/Sitzung 001, 29.11.2024.md"
@ -486,14 +487,9 @@
],
"sortOrder": "custom"
},
"Excalidraw": {
"children": [
"Excalidraw/Drawing 2026-01-03 21.06.39.excalidraw.md"
],
"sortOrder": "custom"
},
"zz_archiv": {
"children": [
"zz_archiv/Garana_Umgebung.png",
"zz_archiv/images",
"zz_archiv/prep_Notizen",
"zz_archiv/Youtube Prep Notes",
@ -503,6 +499,14 @@
},
"zz_archiv/images": {
"children": [
"zz_archiv/images/das_koenligliche_magie_kollegium.jpg",
"zz_archiv/images/zoctaban_der_rote 1.jpg",
"zz_archiv/images/Pasted image 20260305221102.png",
"zz_archiv/images/Pasted image 20260305221419.png",
"zz_archiv/images/Pasted image 20260305221556.png",
"zz_archiv/images/Pasted image 20260305221755.png",
"zz_archiv/images/Pasted image 20260305222825.png",
"zz_archiv/images/wohnung_silbergasse.jpg",
"zz_archiv/images/der_unsichtbare_turm__die_silberschmiede.jpg",
"zz_archiv/images/heiltrank.jpg",
"zz_archiv/images/Pasted image 20260304215813.png",

View file

@ -57,7 +57,7 @@ class Util {
* @private
*/
static isInTable(searchString, fileValue) {
return fileValue.search(new RegExp(`^\\|.+${searchString}.+\\|$`, "m")) !== -1;
return fileValue.search(new RegExp(`^\\|.+${escapeRegex(searchString)}.+\\|$`, "m")) !== -1;
}
/**
* Get the image name from a given src uri of a local image
@ -90,12 +90,12 @@ class Util {
const sizeSeparator = isInTable ? "\\|" : "|";
// Separator to use for the regex: isInTable ? \\\| : \|
const regexSeparator = isInTable ? "\\\\\\|" : "\\|";
const imageAttributes = this.getImageAttributes(imageName, fileText);
imageName = `${imageName}${imageAttributes}`;
// check character before the imageName to check if markdown link or obsidian link
const imageNamePosition = fileText.indexOf(imageName);
const isObsidianLink = fileText.charAt(imageNamePosition - 1) === "[";
if (isObsidianLink) {
const imageAttributes = this.getImageAttributes(imageName, fileText);
imageName = `${imageName}${imageAttributes}`;
return Util.generateReplaceTermForObsidianSyntax(imageName, regexSeparator, sizeSeparator);
}
else {
@ -243,8 +243,10 @@ var ModifierKey;
const DEFAULT_SETTINGS = {
modifierKey: ModifierKey.ALT,
stepSize: 25,
initialSize: 500
initialSize: 500,
resizeInCanvas: true,
};
const CtrlCanvasConflictWarning = "Warning: Using Ctrl as the modifier key conflicts with default canvas zooming behavior when 'Resize in canvas' is enabled. Consider using another modifier key or disabling 'Resize in canvas'.";
class MouseWheelZoomPlugin extends obsidian.Plugin {
constructor() {
super(...arguments);
@ -259,8 +261,40 @@ class MouseWheelZoomPlugin extends obsidian.Plugin {
this.registerEvents(window);
this.addSettingTab(new MouseWheelZoomSettingsTab(this.app, this));
console.log("Loaded: Mousewheel image zoom");
this.checkExistingUserConflict();
});
}
checkExistingUserConflict() {
const noticeShownKey = 'mousewheel-zoom-ctrl-warning-shown'; // Key for localStorage flag
const isCtrl = this.settings.modifierKey === ModifierKey.CTRL || this.settings.modifierKey === ModifierKey.CTRL_RIGHT;
// Only show the notice if the conflict exists AND the user hasn't dismissed it before (using localStorage flag)
if (isCtrl && this.settings.resizeInCanvas && !localStorage.getItem(noticeShownKey)) {
const fragment = document.createDocumentFragment();
const titleEl = document.createElement('strong');
titleEl.textContent = "Mousewheel Image Zoom";
fragment.appendChild(titleEl);
fragment.appendChild(document.createElement('br'));
const messageEl = document.createElement('span');
messageEl.textContent = CtrlCanvasConflictWarning;
fragment.appendChild(messageEl);
fragment.appendChild(document.createElement('br'));
const settingsButton = document.createElement('button');
settingsButton.textContent = "Open Settings";
settingsButton.style.marginTop = "5px";
settingsButton.onclick = () => {
// settings is a private property of the app object, so we need to cast it to any to access it
// See https://forum.obsidian.md/t/open-settings-for-my-plugin-community-plugin-settings-deeplink/61563/4
const setting = this.app.setting;
setting.open();
setting.openTabById(this.manifest.id);
};
fragment.appendChild(settingsButton);
new obsidian.Notice(fragment, 0);
// Set the flag in localStorage so the notice doesn't appear again
// unless the user clears their localStorage or the key changes.
localStorage.setItem(noticeShownKey, 'true');
}
}
/**
* When the config key is released, we enable the scroll again and reset the key held down flag.
*/
@ -280,7 +314,13 @@ class MouseWheelZoomPlugin extends obsidian.Plugin {
registerEvents(currentWindow) {
const doc = currentWindow.document;
this.registerDomEvent(doc, "keydown", (evt) => {
var _a;
if (evt.code === this.settings.modifierKey.toString()) {
// When canvas mode is enabled we just ignore the keydown event if the canvas is active
const isActiveViewCanvas = ((_a = this.app.workspace.getActiveViewOfType(obsidian.View)) === null || _a === void 0 ? void 0 : _a.getViewType()) === "canvas";
if (isActiveViewCanvas && !this.settings.resizeInCanvas) {
return;
}
this.isKeyHeldDown = true;
if (this.settings.modifierKey !== ModifierKey.SHIFT && this.settings.modifierKey !== ModifierKey.SHIFT_RIGHT) { // Ignore shift to allow horizontal scrolling
// Disable the normal scrolling behavior when the key is held down
@ -309,7 +349,7 @@ class MouseWheelZoomPlugin extends obsidian.Plugin {
if (targetIsCanvas || targetIsCanvasNode || targetIsImage) {
this.disableScroll(currentWindow);
}
if (targetIsCanvas) {
if (targetIsCanvas && this.settings.resizeInCanvas) {
// seems we're trying to zoom on some canvas node.
this.handleZoomForCanvas(evt, eventTarget);
}
@ -320,6 +360,12 @@ class MouseWheelZoomPlugin extends obsidian.Plugin {
}
}
});
this.registerDomEvent(currentWindow, "blur", () => {
// When the window loses focus, ensure scrolling is re-enabled for this window
// and reset the key held state defensively, although the keyup should ideally handle it.
this.isKeyHeldDown = false;
this.enableScroll(currentWindow);
});
}
/**
* Handles zooming with the mousewheel on canvas node
@ -357,36 +403,44 @@ class MouseWheelZoomPlugin extends obsidian.Plugin {
return __awaiter(this, void 0, void 0, function* () {
const imageUri = eventTarget.attributes.getNamedItem("src").textContent;
const activeFile = yield this.getActivePaneWithImage(eventTarget);
let fileText = yield this.app.vault.read(activeFile);
const originalFileText = fileText;
// Get parameters like the regex or the replacement terms based on the fact if the image is locally stored or not.
const zoomParams = this.getZoomParams(imageUri, fileText, eventTarget);
// Check if there is already a size parameter for this image.
const sizeMatches = fileText.match(zoomParams.sizeMatchRegExp);
// Element already has a size entry
if (sizeMatches !== null) {
const oldSize = parseInt(sizeMatches[1]);
let newSize = oldSize;
if (evt.deltaY < 0) {
newSize += this.settings.stepSize;
yield this.app.vault.process(activeFile, (fileText) => {
let frontmatter = "";
let body = fileText;
const frontmatterRegex = /^---\s*([\s\S]*?)\s*---\n*/;
const match = fileText.match(frontmatterRegex);
if (match) {
frontmatter = match[0]; // Keep the full matched frontmatter block including delimiters and trailing newline
body = fileText.slice(frontmatter.length); // The rest is the body
}
else if (evt.deltaY > 0 && newSize > this.settings.stepSize) {
newSize -= this.settings.stepSize;
const zoomParams = this.getZoomParams(imageUri, body, eventTarget);
// Perform replacements ONLY on the body
let modifiedBody = body;
const sizeMatches = body.match(zoomParams.sizeMatchRegExp);
// Element already has a size entry in the body
if (sizeMatches !== null) {
const oldSize = parseInt(sizeMatches[1]);
let newSize = oldSize;
if (evt.deltaY < 0) {
newSize += this.settings.stepSize;
}
else if (evt.deltaY > 0 && newSize > this.settings.stepSize) {
newSize -= this.settings.stepSize;
}
// Replace within the body
modifiedBody = body.replace(zoomParams.replaceSizeExist.getReplaceFromString(oldSize), zoomParams.replaceSizeExist.getReplaceWithString(newSize));
}
fileText = fileText.replace(zoomParams.replaceSizeExist.getReplaceFromString(oldSize), zoomParams.replaceSizeExist.getReplaceWithString(newSize));
}
else { // Element has no size entry -> give it an initial size
const initialSize = this.settings.initialSize;
var image = new Image();
image.src = imageUri;
var width = image.naturalWidth;
var minWidth = Math.min(width, initialSize);
fileText = fileText.replace(zoomParams.replaceSizeNotExist.getReplaceFromString(0), zoomParams.replaceSizeNotExist.getReplaceWithString(minWidth));
}
// Save changed size
if (fileText !== originalFileText) {
yield this.app.vault.modify(activeFile, fileText);
}
else { // Element has no size entry in the body -> give it an initial size
const initialSize = this.settings.initialSize;
const image = new Image();
image.src = imageUri;
const width = image.naturalWidth || initialSize;
const minWidth = Math.min(width, initialSize);
// Replace within the body
modifiedBody = body.replace(zoomParams.replaceSizeNotExist.getReplaceFromString(0), zoomParams.replaceSizeNotExist.getReplaceWithString(minWidth));
}
// Combine original frontmatter with the modified body
return frontmatter + modifiedBody;
});
});
}
/**
@ -422,6 +476,11 @@ class MouseWheelZoomPlugin extends obsidian.Plugin {
const imageName = Util.getLocalImageNameFromUri(imageUri);
return Util.getLocalImageZoomParams(imageName, fileText);
}
else if (imageUri.contains("data:image/")) { // for image generated by PDF++ extension
// example: data:image/png;base64,iVB...
const imageName = Util.getLocalImageNameFromUri(target.parentElement.getAttribute("src"));
return Util.getLocalImageZoomParams(imageName, fileText);
}
throw new Error("Image is not zoomable");
}
loadSettings() {
@ -469,6 +528,23 @@ class MouseWheelZoomSettingsTab extends obsidian.PluginSettingTab {
super(app, plugin);
this.plugin = plugin;
}
// Helper function to update the warning message
updateWarningMessage(modifierKey, resizeInCanvas) {
if (!this.warningEl)
return;
const isCtrl = modifierKey === ModifierKey.CTRL || modifierKey === ModifierKey.CTRL_RIGHT;
const conflict = isCtrl && resizeInCanvas;
if (conflict) {
this.warningEl.setText(CtrlCanvasConflictWarning);
this.warningEl.style.display = 'block';
this.warningEl.style.color = 'var(--text-warning)';
this.warningEl.style.marginTop = '10px';
}
else {
this.warningEl.setText("");
this.warningEl.style.display = 'none';
}
}
display() {
let { containerEl } = this;
containerEl.empty();
@ -486,6 +562,7 @@ class MouseWheelZoomSettingsTab extends obsidian.PluginSettingTab {
.setValue(this.plugin.settings.modifierKey)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.modifierKey = value;
this.updateWarningMessage(this.plugin.settings.modifierKey, this.plugin.settings.resizeInCanvas);
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
@ -516,6 +593,20 @@ class MouseWheelZoomSettingsTab extends obsidian.PluginSettingTab {
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName('Resize in canvas')
.setDesc('When enabled, all nodes on the Obsidian canvas can also be resized using the Modifier key')
.addToggle((toggle) => {
toggle.setValue(this.plugin.settings.resizeInCanvas)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.resizeInCanvas = value;
this.updateWarningMessage(this.plugin.settings.modifierKey, value);
yield this.plugin.saveSettings();
}));
});
this.warningEl = containerEl.createDiv({ cls: 'mousewheel-zoom-warning' });
this.warningEl.style.display = 'none';
this.updateWarningMessage(this.plugin.settings.modifierKey, this.plugin.settings.resizeInCanvas);
}
}

View file

@ -1,7 +1,7 @@
{
"id": "mousewheel-image-zoom",
"name": "Mousewheel Image zoom",
"version": "1.0.22",
"version": "1.0.24",
"minAppVersion": "0.9.12",
"description": "This plugin enables you to increase/decrease the size of an image by scrolling",
"author": "Nico Jeske",

View file

@ -1,4 +1,7 @@
{
"copyLinkToElemenetAnchorTo100": false,
"copyFrameLinkByName": false,
"disableDoubleClickTextEditing": false,
"folder": "Excalidraw",
"cropFolder": "",
"annotateFolder": "",
@ -21,7 +24,9 @@
"drawingFilnameEmbedPostfix": " ",
"drawingFilenameDateTime": "YYYY-MM-DD HH.mm.ss",
"useExcalidrawExtension": true,
"cropSuffix": "",
"cropPrefix": "cropped_",
"annotateSuffix": "",
"annotatePrefix": "annotated_",
"annotatePreserveSize": false,
"previewImageType": "SVGIMG",
@ -35,6 +40,9 @@
"overrideObsidianFontSize": false,
"dynamicStyling": "colorful",
"isLeftHanded": false,
"desktopUIMode": "tray",
"tabletUIMode": "compact",
"phoneUIMode": "mobile",
"iframeMatchExcalidrawTheme": true,
"matchTheme": false,
"matchThemeAlways": false,
@ -44,6 +52,7 @@
"penModeDoubleTapEraser": true,
"penModeSingleFingerPanning": true,
"penModeCrosshairVisible": true,
"panWithRightMouseButton": false,
"renderImageInMarkdownReadingMode": false,
"renderImageInHoverPreviewForMDNotes": false,
"renderImageInMarkdownToPDF": false,
@ -52,6 +61,9 @@
"zoomToFitOnOpen": true,
"zoomToFitOnResize": true,
"zoomToFitMaxLevel": 2,
"zoomStep": 0.05,
"zoomMin": 0.1,
"zoomMax": 30,
"linkPrefix": "📍",
"urlPrefix": "🌐",
"parseTODO": false,
@ -64,6 +76,7 @@
"focusOnFileTab": true,
"openInMainWorkspace": true,
"showLinkBrackets": true,
"syncElementLinkWithText": false,
"allowCtrlClick": true,
"forceWrap": false,
"pageTransclusionCharLimit": 200,
@ -100,7 +113,7 @@
"library2": {
"type": "excalidrawlib",
"version": 2,
"source": "https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/2.8.3",
"source": "https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/2.20.6",
"libraryItems": []
},
"imageElementNotice": true,
@ -111,15 +124,16 @@
"mdBorderColor": "Black",
"mdCSS": "",
"scriptEngineSettings": {},
"defaultTrayMode": true,
"previousRelease": "2.8.3",
"previousRelease": "2.20.6",
"showReleaseNotes": true,
"compareManifestToPluginVersion": true,
"showNewVersionNotification": true,
"latexBoilerplate": "\\color{blue}",
"latexPreambleLocation": "preamble.sty",
"taskboneEnabled": false,
"taskboneAPIkey": "",
"pinnedScripts": [],
"sidepanelTabs": [],
"customPens": [
{
"type": "default",
@ -467,8 +481,10 @@
"markdownNodeOneClickEditing": false,
"canvasImmersiveEmbed": true,
"startupScriptPath": "",
"aiEnabled": true,
"openAIAPIToken": "",
"openAIDefaultTextModel": "gpt-3.5-turbo-1106",
"openAIDefaultTextModelMaxTokens": 4096,
"openAIDefaultVisionModel": "gpt-4o",
"openAIDefaultImageGenerationModel": "dall-e-3",
"openAIURL": "https://api.openai.com/v1/chat/completions",
@ -795,5 +811,7 @@
"customPaperColor": "#ffffff",
"alignment": "center",
"margin": "normal"
}
},
"disableContextMenu": false,
"defaultTrayMode": true
}

File diff suppressed because one or more lines are too long

View file

@ -1,12 +1,12 @@
{
"id": "obsidian-excalidraw-plugin",
"name": "Excalidraw",
"version": "2.8.3",
"minAppVersion": "1.1.6",
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
"version": "2.20.6",
"minAppVersion": "1.5.7",
"description": "Sketch Your Mind. An Obsidian plugin to edit and view Excalidraw drawings. Enter the world of 4D Visual PKM.",
"author": "Zsolt Viczian",
"authorUrl": "https://www.zsolt.blog",
"authorUrl": "https://excalidraw-obsidian.online",
"fundingUrl": "https://ko-fi.com/zsolt",
"helpUrl": "https://github.com/zsviczian/obsidian-excalidraw-plugin#readme",
"isDesktopOnly": false
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,38 @@
{
"mapMarkers": [],
"defaultMarker": {
"type": "default",
"iconName": "map-marker",
"color": "#dddddd",
"transform": {
"size": 6,
"x": 0,
"y": -2
}
},
"markerIcons": [],
"color": "#dddddd",
"lat": 39.983334,
"long": -82.98333,
"notePreview": false,
"layerMarkers": true,
"previousVersion": "6.0.5",
"version": {
"major": 6,
"minor": 0,
"patch": 5
},
"warnedAboutMapMarker": false,
"copyOnClick": false,
"displayMarkerTooltips": "hover",
"displayOverlayTooltips": true,
"configDirectory": null,
"mapViewEnabled": true,
"mapViewParameters": {},
"enableDraw": true,
"defaultUnitType": "imperial",
"defaultTile": "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png",
"defaultTileDark": "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png",
"defaultAttribution": "&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors &copy; <a href=\"https://carto.com/attributions\">CARTO</a>",
"defaultTileSubdomains": "a,b,c,d"
}

View file

@ -22,6 +22,8 @@
"excalidraw-css": "text",
"excalidraw-autoexport": "text",
"excalidraw-embeddable-theme": "text",
"excalidraw-open-md": "checkbox"
"excalidraw-open-md": "checkbox",
"excalidraw-export-internal-links": "checkbox",
"excalidraw-embed-md": "checkbox"
}
}