diff --git a/src/main.ts b/src/main.ts index f8e1210..09ccc6a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ // noinspection JSUnusedGlobalSymbols -import { MarkdownPostProcessorContext, Plugin, TFile } from 'obsidian'; +import { MarkdownPostProcessorContext, Component, Plugin, TFile } from 'obsidian'; import { DEFAULT_SETTINGS, FantasyMapSettings, FantasyMapSettingTab } from "./settings"; import { parseFantasyMapParams, fantasyMapHelpMessage } from "./paramaters"; import { initMapInteractions } from "./mapInteractions"; @@ -43,7 +43,7 @@ export default class FantasyMap extends Plugin { async main(source: string, element: HTMLElement, ctx: MarkdownPostProcessorContext) { // get the user parameters set inside the defined code block in the note, and if the map parameter is not set or is empty, quit out of the function - const parameters = parseFantasyMapParams(source, element, ctx, this.settings); + const parameters = parseFantasyMapParams(source, element, ctx, this as Component, this.settings); if (parameters.map == null || parameters.map.trim() === "") return; //#region get the map file @@ -68,7 +68,7 @@ export default class FantasyMap extends Plugin { // if we can't find the map file, display an error message and quit if (mapFile == null || !mapFile) { - await fantasyMapHelpMessage(element, ctx, `Fantasy Map Error: Map file "${parameters.map}" not found in vault! Double-check the file name and path, and make sure the file is located somewhere in your vault.`); + await fantasyMapHelpMessage(element, ctx, this, `Fantasy Map Error: Map file "${parameters.map}" not found in vault! Double-check the file name and path, and make sure the file is located somewhere in your vault.`, false); return; } diff --git a/src/mapInteractions.ts b/src/mapInteractions.ts index c480d02..2617061 100644 --- a/src/mapInteractions.ts +++ b/src/mapInteractions.ts @@ -1,6 +1,7 @@ import { App } from "obsidian"; -import { React } from "react"; -import { updatePinPositions } from "pinInteractions"; +import { updatePinPositions } from "./pinInteractions"; +import { FantasyMapParams } from "./paramaters"; +import { FantasyMapSettings } from "./settings"; export interface PanZoomState { zoom: number; @@ -11,12 +12,11 @@ export interface PanZoomState { } let isPanning: boolean = false; -let wrapper: HTMLElement | null = null; let lastX: number = 0; let lastY: number = 0; export function initMapInteractions( - app: APP, + app: App, wrapper: HTMLElement, bgLayer: HTMLElement, tilesLayer: HTMLElement, @@ -32,7 +32,7 @@ export function initMapInteractions( maxZoom: 15 }; - this.wrapper = wrapper; + wrapper; function applyTransform() { // size of one world tile in screen space at current zoom @@ -143,7 +143,7 @@ export function initMapInteractions( wrapper.addEventListener("pointermove", (e) => { if (!isPanning) { - this.wrapper.releasePointerCapture(e.pointerId); + wrapper.releasePointerCapture(e.pointerId); return; } @@ -165,7 +165,8 @@ export function initMapInteractions( wrapper.addEventListener("wheel", (e) => { e.preventDefault(); const zoomStep = toolbar.querySelector(".fm-zoom-step") as HTMLInputElement; - const factor = e.deltaY < 0 ? (1 + zoomStep.value * 0.1) : 1 / (1 + zoomStep.value * 0.1); + const zoomValue = Number(zoomStep.value); + const factor = e.deltaY < 0 ? (1 + zoomValue * 0.1) : 1 / (1 + zoomValue * 0.1); zoomAt(e.clientX, e.clientY, factor); }, { passive: false }); @@ -182,14 +183,16 @@ export function initMapInteractions( zoomInBtn?.addEventListener("click", () => { const stepInput = toolbar.querySelector(".fm-zoom-step") as HTMLInputElement; - const step = Math.abs(Number(stepInput?.value)) || paramaters.defaultZoomIncrement || settings.defaultZoomIncrement; + const stepValue = Number(stepInput?.value); + const step = Math.abs(stepValue) || paramaters.defaultZoomIncrement || settings.defaultZoomIncrement; const factorBase = 1 + step * 0.1; zoomAtViewportCenter(factorBase); }); zoomOutBtn?.addEventListener("click", () => { const stepInput = toolbar.querySelector(".fm-zoom-step") as HTMLInputElement; - const step = Math.abs(Number(stepInput?.value)) || paramaters.defaultZoomIncrement || settings.defaultZoomIncrement; + const stepValue = Number(stepInput?.value); + const step = Math.abs(stepValue) || paramaters.defaultZoomIncrement || settings.defaultZoomIncrement; const factorBase = 1 + step * 0.1; zoomAtViewportCenter(1 / factorBase); }); diff --git a/src/paramaters.ts b/src/paramaters.ts index 6ad0aab..8568ffc 100644 --- a/src/paramaters.ts +++ b/src/paramaters.ts @@ -1,5 +1,5 @@ -import {App, MarkdownRenderer} from "obsidian"; -import {FantasyMapSettings} from "./settings"; +import { App, Component, MarkdownRenderer, MarkdownPostProcessorContext } from "obsidian"; +import { FantasyMapSettings } from "./settings"; // This interface defines the structure of the parameters that can be passed to the map renderer, including the required "map" parameter and various optional parameters with their corresponding types export interface FantasyMapParams { @@ -108,12 +108,12 @@ const helpKeywords = [ ]; // This function parses the parameters from the code block content and returns an object with the corresponding values, applying defaults where necessary -export function parseFantasyMapParams(source: string, element: HTMLElement, ctx: MarkdownPostProcessorContext, settings: FantasyMapSettings): FantasyMapParams { +export function parseFantasyMapParams(source: string, element: HTMLElement, ctx: MarkdownPostProcessorContext, component: Component, settings: FantasyMapSettings): FantasyMapParams { // split the code block content into lines, trim whitespace, and filter out any empty lines to prepare for parsing; this allows users to format their parameters with extra spaces or blank lines without affecting the parsing logic const lines = source.split("\n").map(l => l.trim()).filter(Boolean); const params: any = {}; - const helpMessages = []; + const helpMessages: string[] = []; // This function adds a help message to the helpMessages array if it hasn't already been added, and logs the added message to the console for debugging purposes; this ensures that each help message is only added once, even if multiple parameters contain help keywords function addHelpMessage(message: string) { @@ -121,7 +121,7 @@ export function parseFantasyMapParams(source: string, element: HTMLElement, ctx: } // if there are no lines of content in the code block, display a help message with usage instructions to guide users on how to use the plugin and what parameters are available; this provides a helpful starting point for users who may be new to the plugin or unsure of how to format their parameters - if (lines.length == 0) fantasyMapHelpMessage(element, ctx, compileHelpMessages(allHelpMessages(settings), "##### Available Fantasy Map Parameters:"), true); + if (lines.length == 0) fantasyMapHelpMessage(element, ctx, component, compileHelpMessages(allHelpMessages(settings), "##### Available Fantasy Map Parameters:"), true); // iterate through each line of the code block content, parsing the key and value for each parameter and applying the appropriate logic based on the parameter type and expected format; if a help keyword is detected in the value of any parameter, the corresponding help message will be added to the helpMessages array and displayed to the user without an error prefix else for (const line of lines) { @@ -307,17 +307,19 @@ export function parseFantasyMapParams(source: string, element: HTMLElement, ctx: if (params.unitOfMeasurement == null) params.unitOfMeasurement = settings.defaultUnitOfMeasurement; if (params.equatorialCircumference == null) params.equatorialCircumference = params.measurementUnits === "Metric" ? 40075 : 24901; - if (helpMessages.length > 0) fantasyMapHelpMessage(element, ctx, compileHelpMessages(helpMessages, "##### Fantasy Map Help Messages:"), true); + if (helpMessages.length > 0) fantasyMapHelpMessage(element, ctx, component, compileHelpMessages(helpMessages, "##### Fantasy Map Help Messages:"), true); return params as FantasyMapParams; } // Render a help message to markdown -export async function fantasyMapHelpMessage(element: HTMLElement, ctx: MarkdownPostProcessorContext, message: string, includeCopyLink: boolean = false) { +export async function fantasyMapHelpMessage(element: HTMLElement, ctx: MarkdownPostProcessorContext, component: Component, message: string | null, includeCopyLink: boolean = false) { + + if (message == null) return; // Render the markdown message in the code block container const container = element.createDiv(); - await MarkdownRenderer.renderMarkdown(message ?? "", container, ctx.sourcePath, this as any); + await MarkdownRenderer.renderMarkdown(message ?? "", container, ctx.sourcePath, component); if (includeCopyLink) appendCopyLink(container); } @@ -337,8 +339,8 @@ export function appendCopyLink(container: HTMLElement) { }); } -export function compileHelpMessages(messages: string[], title: string) : string { - if (messages == null || messages.length == 0) return null; +export function compileHelpMessages(messages: string[], title: string) : string | null { + if (messages.length == 0) return null; const message = [title?? null]; messages.forEach(m => {message.push("- {0}".replace("{0}", m))}); diff --git a/src/pinInteractions.ts b/src/pinInteractions.ts index 0e62c77..26742b5 100644 --- a/src/pinInteractions.ts +++ b/src/pinInteractions.ts @@ -1,7 +1,6 @@ import {App, CachedMetadata, MarkdownPostProcessorContext, MarkdownRenderer, Plugin, TFile, Component } from "obsidian"; import { FantasyMapSettings } from "./settings"; import { FantasyMapParams } from "./paramaters"; -import { updateMapInnerSize } from "./mapRenderer"; import { cancelMapPanning } from "./mapInteractions"; import { showCustomPreview, hideCustomPreview, destroyCustomPreview } from "./previewInteractions" @@ -40,6 +39,8 @@ export async function initPinInteractions( currentMap.width = wrapper.clientWidth; currentMap.height = wrapper.clientHeight; + if (paramaters.latitudeRange == null || paramaters.longitudeRange == null) return; + // define the map latitude and longitude bounds latBounds = { min: paramaters.latitudeRange[0], max: paramaters.latitudeRange[1] }; lngBounds = { min: paramaters.longitudeRange[0], max: paramaters.longitudeRange[1] }; @@ -71,7 +72,7 @@ export async function initPinInteractions( if (!location) return; // skip locations that are outside the map bounds - if (location.lat < latBounds.min || location.lat > latBounds.max || location.lng < lngBounds.min || location.lng > lngBounds.max) return``; + if (location.lat < latBounds.min || location.lat > latBounds.max || location.lng < lngBounds.min || location.lng > lngBounds.max) return; //#endregion @@ -112,7 +113,7 @@ export async function initPinInteractions( }); wrapper.addEventListener("pointerup", async (e) => { - if (!selectedPin) return; + if (!selectedPin || selectedPin == null) return; if (selectedPin.note) { if (enablePinDrag) { @@ -123,7 +124,8 @@ export async function initPinInteractions( selectedPin.location = pxToLocation(px); await app.fileManager.processFrontMatter(selectedPin.note, (frontmatter) => { - frontmatter["fantasy-map-location"] = formatLocation(selectedPin.location); + if (!selectedPin) return; + frontmatter["fantasy-map-location"] = formatLocation(selectedPin?.location); }); } else { diff --git a/src/types/assets.d.ts b/src/types/assets.d.ts new file mode 100644 index 0000000..dc59075 --- /dev/null +++ b/src/types/assets.d.ts @@ -0,0 +1,4 @@ +declare module "*.svg" { + const src: string; + export default src; +}