@ -58,8 +58,8 @@ function __awaiter(thisArg, _arguments, P, generator) {
const MAP _VIEW _NAME = 'map' ;
// SVG editor used: https://svgedit.netlify.app/editor/index.html
const RIBBON _ICON = '<path fill="currentColor" stroke="currentColor" d="m50.06001,1.76c-26.54347,0 -48.06001,21.74039 -48.06001,48.56c0,26.81961 21.51654,48.56 48.06001,48.56c26.54347,0 48.06001,-21.74039 48.06001,-48.56c0,-26.81961 -21.51654,-48.56 -48.06001,-48.56zm15.94701,70.02039c-0.75578,0.75973 -1.54838,1.55666 -2.19177,2.2087c-0.57943,0.58742 -0.98833,1.3119 -1.19569,2.09709c-0.29262,1.10826 -0.52905,2.22828 -0.92438,3.30325l-3.37001,9.17353c-2.66656,0.58742 -5.42613,0.91833 -8.26516,0.91833l0,-5.36118c0.32751,-2.47108 -1.48056,-7.09994 -4.38548,-10.03508c-1.16274,-1.17484 -1.81582,-2.7687 -1.81582,-4.4311l0,-6.26776c0,-2.27919 -1.21507,-4.37432 -3.18979,-5.47671c-2.78477,-1.55666 -6.74584,-3.73207 -9.45891,-5.11251c-2.22471,-1.13176 -4.28277,-2.5729 -6.13346,-4.25879l-0.15503,-0.14098c-1.32339,-1.20715 -2.49854,-2.57055 -3.49985,-4.06103c-1.81775,-2.69625 -4.77887,-7.13127 -6.70321,-10.01354c3.96689,-8.90919 11.11582,-16.06396 19.99917,-19.95072l4.65291,2.35164c2.06193,1.04169 4.48818,-0.47189 4.48818,-2.80199l0,-2.21261c1.54838,-0.25259 3.1239,-0.41315 4.72655,-0.47385l5.48427,5.54132c1.21119,1.22379 1.21119,3.20731 0,4.4311l-0.90888,0.91637l-2.00379,2.02464c-0.60463,0.61092 -0.60463,1.60365 0,2.21457l0.90888,0.91833c0.60463,0.61092 0.60463,1.60365 0,2.21457l-1.55032,1.56645c-0.29107,0.29351 -0.68563,0.45838 -1.09685,0.45819l-1.74218,0c-0.40308,0 -0.79066,0.1586 -1.08135,0.44448l-1.9224,1.88953c-0.48351,0.47581 -0.60734,1.21263 -0.30619,1.82296l3.02119,6.1072c0.51548,1.04169 -0.23449,2.26744 -1.3856,2.26744l-1.09298,0c-0.37402,0 -0.73447,-0.13706 -1.01546,-0.38378l-1.79837,-1.5782c-0.82787,-0.72566 -1.97337,-0.95651 -3.01344,-0.607l-6.04045,2.03443c-0.9457,0.31858 -1.58365,1.21302 -1.58327,2.22045c0,0.887 0.4961,1.69568 1.28095,2.09317l2.1472,1.08477c1.82357,0.92225 3.83511,1.40197 5.87379,1.40197c2.03867,0 4.37772,5.34356 6.20129,6.26581l12.93551,0c1.64528,0 3.2208,0.65987 4.38548,1.83471l2.65299,2.68059c1.10829,1.12021 1.73074,2.63947 1.73055,4.22355c-0.00078,2.42428 -0.95771,4.74811 -2.6588,6.4577zm16.80356,-17.88692c-1.12205,-0.28392 -2.10069,-0.97903 -2.74213,-1.95219l-3.48435,-5.2809c-1.04259,-1.57781 -1.04259,-3.63456 0,-5.21237l3.79635,-5.75279c0.44959,-0.67945 1.06585,-1.23162 1.79062,-1.59582l2.5154,-1.27078c2.62005,5.27111 4.13161,11.20013 4.13161,17.49139c0,1.69764 -0.1434,3.36004 -0.3527,5.0009l-5.6548,-1.42743z" fill="#000000" id="shape0" stroke="#000000" stroke-linecap="square" stroke-linejoin="bevel" stroke-opacity="0" stroke-width="0"/>' ;
const TILES _URL _OPENSTREETMAP = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png' ;
const SEARCH _RESULT _MARKER = { prefix : 'fas' , icon : 'fa-search' , markerColor : 'blue' } ;
const MAX _CLUSTER _PREVIEW _ICONS = 4 ;
const LAT _LIMITS = [ - 90 , 90 ] ;
const LNG _LIMITS = [ - 180 , 180 ] ;
@ -14145,9 +14145,18 @@ function formatWithTemplates(s, query = '') {
}
const CURSOR = '$CURSOR$' ;
function sanitizeFileName ( s ) {
const illegalChars = /[\ /\ ?<>\\:\*\|":]/g;
const illegalChars = /[\ ?<>\\:\*\|":]/g;
return s . replace ( illegalChars , '-' ) ;
}
/ * *
* Create a new markdown note and populate with the location
* @ param app The Obsidian App instance
* @ param newNoteType The location format to encode as
* @ param directory The directory path to put the file in
* @ param fileName The name of the file
* @ param location The geolocation
* @ param templatePath Optional path to a template to use for constructing the new file
* /
function newNote ( app , newNoteType , directory , fileName , location , templatePath ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
// `$CURSOR$` is used to set the cursor
@ -14168,6 +14177,12 @@ function newNote(app, newNoteType, directory, fileName, location, templatePath)
}
} ) ;
}
/ * *
* Go to a character index in the note
* @ param editor The Obsidian Editor instance
* @ param fileLocation The character index in the file to go to
* @ param highlight If true will select the whole line
* /
function goToEditorLocation ( editor , fileLocation , highlight ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
if ( fileLocation ) {
@ -14219,6 +14234,12 @@ function verifyOrAddFrontMatter(editor, fieldName, fieldValue) {
}
return false ;
}
/ * *
* Populate a context menu from the user configurable URLs
* @ param menu The menu to attach
* @ param location The geolocation to use in the menu item
* @ param settings Plugin settings
* /
function populateOpenInItems ( menu , location , settings ) {
for ( let setting of settings . openIn ) {
if ( ! setting . name || ! setting . urlPattern )
@ -14341,15 +14362,26 @@ class LocationSuggest extends obsidian.EditorSuggest {
}
}
/** A class to convert a string (usually a URL) into geolocation format */
class UrlConvertor {
constructor ( app , settings ) {
this . settings = settings ;
}
/ * *
* Parse the current editor line using the user defined URL parsers .
* Returns leaflet . LatLng on success and null on failure .
* @ param editor The Obsidian Editor instance to use
* /
findMatchInLine ( editor ) {
const cursor = editor . getCursor ( ) ;
const result = this . parseLocationFromUrl ( editor . getLine ( cursor . line ) ) ;
return result === null || result === void 0 ? void 0 : result . location ;
}
/ * *
* Get geolocation from an encoded string ( usually a URL ) .
* Will try each url parsing rule until one succeeds .
* @ param line The string to decode
* /
parseLocationFromUrl ( line ) {
for ( const rule of this . settings . urlParsingRules ) {
const regexp = RegExp ( rule . regExp , 'g' ) ;
@ -14368,6 +14400,13 @@ class UrlConvertor {
}
return null ;
}
/ * *
* Insert a geo link into the editor at the cursor position
* @ param location The geolocation to convert to text and insert
* @ param editor The Obsidian Editor instance
* @ param replaceStart The EditorPosition to start the replacement at . If null will replace any text selected
* @ param replaceLength The EditorPosition to stop the replacement at . If null will replace any text selected
* /
insertLocationToEditor ( location , editor , replaceStart , replaceLength ) {
const locationString = ` [](geo: ${ location . lat } , ${ location . lng } ) ` ;
const cursor = editor . getCursor ( ) ;
@ -14381,6 +14420,10 @@ class UrlConvertor {
editor . setCursor ( { line : cursor . line , ch : newCursorPos } ) ;
verifyOrAddFrontMatter ( editor , 'locations' , '' ) ;
}
/ * *
* Replace the text at the cursor location with a geo link
* @ param editor The Obsidian Editor instance
* /
convertUrlAtCursorToGeolocation ( editor ) {
const cursor = editor . getCursor ( ) ;
const result = this . parseLocationFromUrl ( editor . getLine ( cursor . line ) ) ;
@ -17347,21 +17390,22 @@ const DEFAULT_SETTINGS = {
{ ruleName : "#dogs" , preset : false , iconDetails : { "prefix" : "fas" , "icon" : "fa-paw" } } ,
] ,
zoomOnGoFromNote : 15 ,
tilesUrl : TILES _URL _OPENSTREETMAP ,
autoZoom : true ,
markerClickBehavior : 'samePane' ,
newNoteNameFormat : 'Location added on {{date:YYYY-MM-DD}}T{{date:HH-mm}}' ,
snippetLines : 3 ,
showNotePreview : true ,
showClusterPreview : false ,
debug : false ,
openIn : [ { name : 'Google Maps' , urlPattern : 'https://maps.google.com/?q={x},{y}' } ] ,
urlParsingRules : [
{ name : ' Google Maps', regExp : /https:\/\/\S*\@([0-9\.\-]+),( [0-9\.\-]+)\S*/. source , order : 'latFirst' , preset : true } ,
{ name : ' OpenStreetMap Show Address', regExp : /https:\/\/www.openstreetmap.org\S*query=([0-9\.\-]+%2C[0-9\.\-]+)\S* /. source , order : 'latFirst' , preset : true }
{ name : ' OpenStreetMap Show Address', regExp : /https:\/\/www.openstreetmap.org\S*query=([0-9\.\-]+%2C [0-9\.\-]+)\S*/. source , order : 'latFirst' , preset : true } ,
{ name : ' Generic Lat,Lng', regExp : /([0-9\.\-]+), ([0-9\.\-]+) /. source , order : 'latFirst' , preset : true }
] ,
mapControls : { filtersDisplayed : true , viewDisplayed : true , presetsDisplayed : false } ,
maxClusterRadiusPixels : 20 ,
searchProvider : 'osm' ,
mapSources : [ { name : 'OpenStreetMap' , urlLight : TILES _URL _OPENSTREETMAP } ] ,
mapSources : [ { name : 'CartoDB' , urlLight : 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png' , preset : true } ] ,
// mapSources: [{name: 'OpenStreetMap', urlLight: consts.TILES_URL_OPENSTREETMAP}],
chosenMapMode : 'auto'
} ;
function convertLegacyMarkerIcons ( settings ) {
@ -17399,6 +17443,18 @@ function convertLegacyDefaultState(settings) {
}
return false ;
}
function removeLegacyPresets1 ( settings ) {
const googleMapsParsingRule = settings . urlParsingRules . findIndex ( rule => rule . name == 'Google Maps' && rule . preset ) ;
if ( googleMapsParsingRule > - 1 ) {
settings . urlParsingRules . splice ( googleMapsParsingRule , 1 ) ;
return true ;
}
if ( settings . mapSources . findIndex ( item => item . name == DEFAULT _SETTINGS . mapSources [ 0 ] . name ) === - 1 ) {
settings . mapSources . unshift ( DEFAULT _SETTINGS . mapSources [ 0 ] ) ;
return true ;
}
return false ;
}
/* jshint node: true */
@ -17681,8 +17737,15 @@ styleInject(css_248z);
// Ugly hack for obsidian-leaflet compatability, see https://github.com/esm7/obsidian-map-view/issues/6
// @ts-ignore
let localL = L ;
/** An object that represents a single marker in a file, which is either a complete note with a geolocation, or an inline geolocation inside a note */
class FileMarker {
/ * *
* Construct a new FileMarker object
* @ param file The file the pin comes from
* @ param location The geolocation
* /
constructor ( file , location ) {
/** Tags that this marker includes */
this . tags = [ ] ;
this . file = file ;
this . location = location ;
@ -17708,6 +17771,14 @@ class FileMarker {
return this . file . name + this . location . lat . toString ( ) + this . location . lng . toString ( ) ;
}
}
/ * *
* Create a FileMarker for every front matter and inline geolocation in the given file .
* @ param mapToAppendTo The list of file markers to append to
* @ param file The file object to parse
* @ param settings The plugin settings
* @ param app The Obsidian App instance
* @ param skipMetadata If true will not find markers in the front matter
* /
function buildAndAppendFileMarkers ( mapToAppendTo , file , settings , app , skipMetadata ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
const fileCache = app . metadataCache . getFileCache ( file ) ;
@ -17729,6 +17800,12 @@ function buildAndAppendFileMarkers(mapToAppendTo, file, settings, app, skipMetad
}
} ) ;
}
/ * *
* Create FileMarker instances for all the files in the given list
* @ param files The list of file objects to find geolocations in .
* @ param settings The plugin settings
* @ param app The Obsidian App instance
* /
function buildMarkers ( files , settings , app ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
if ( settings . debug )
@ -17746,6 +17823,12 @@ function checkTagPatternMatch(tagPattern, tags) {
let match = wildcard ( tagPattern , tags ) ;
return match && match . length > 0 ;
}
/ * *
* Create a leaflet icon for the marker
* @ param marker The FileMarker to create the icon for
* @ param settings The plugin settings
* @ param app The Obsidian App instance
* /
function getIconForMarker ( marker , settings , app ) {
const fileCache = app . metadataCache . getFileCache ( marker . file ) ;
// Combine the file tags with the marker-specific tags
@ -17776,12 +17859,21 @@ function getIconFromOptions(iconSpec) {
L = backupL ;
}
}
/ * *
* Make sure that the coordinates are valid world coordinates
* - 90 <= longitude <= 90 and - 180 <= latitude <= 180
* @ param location
* /
function verifyLocation ( location ) {
if ( location . lng < LNG _LIMITS [ 0 ] || location . lng > LNG _LIMITS [ 1 ] )
throw Error ( ` Lng ${ location . lng } is outside the allowed limits ` ) ;
if ( location . lat < LAT _LIMITS [ 0 ] || location . lat > LAT _LIMITS [ 1 ] )
throw Error ( ` Lat ${ location . lat } is outside the allowed limits ` ) ;
}
/ * *
* Find all inline geolocations in a string
* @ param content The file contents to find the coordinates in
* /
function matchInlineLocation ( content ) {
// Old syntax of ` `location: ... ` `. This syntax doesn't support a name so we leave an empty capture group
const locationRegex1 = /\`()location:\s*\[?([0-9.\-]+)\s*,\s*([0-9.\-]+)\]?\`/g ;
@ -17791,6 +17883,12 @@ function matchInlineLocation(content) {
const matches2 = content . matchAll ( locationRegex2 ) ;
return Array . from ( matches1 ) . concat ( Array . from ( matches2 ) ) ;
}
/ * *
* Build markers from inline locations in the file body
* @ param file The file object to load
* @ param settings The plugin settings
* @ param app The Obsidian App instance
* /
function getMarkersFromFileContent ( file , settings , app ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
let markers = [ ] ;
@ -17812,6 +17910,7 @@ function getMarkersFromFileContent(file, settings, app) {
marker . tags . push ( '#' + tag [ 1 ] ) ;
}
marker . fileLocation = match . index ;
marker . fileLine = content . substring ( 0 , marker . fileLocation ) . split ( '\n' ) . length - 1 ;
marker . icon = getIconForMarker ( marker , settings , app ) ;
marker . snippet = yield makeTextSnippet ( file , content , marker . fileLocation , settings ) ;
markers . push ( marker ) ;
@ -17864,6 +17963,11 @@ function makeTextSnippet(file, fileContent, fileLocation, settings) {
return snippet ;
} ) ;
}
/ * *
* Get the geolocation stored in the front matter of a file
* @ param file The file to load the front matter from
* @ param app The Obsidian App instance
* /
function getFrontMatterLocation ( file , app ) {
const fileCache = app . metadataCache . getFileCache ( file ) ;
const frontMatter = fileCache === null || fileCache === void 0 ? void 0 : fileCache . frontmatter ;
@ -18205,13 +18309,22 @@ class ViewControls {
}
class MapView extends obsidian . ItemView {
/ * *
* Construct a new map instance
* @ param leaf The leaf the map should be put in
* @ param settings The plugin settings
* @ param plugin The plugin instance
* /
constructor ( leaf , settings , plugin ) {
super ( leaf ) ;
/** The map data */
this . display = new class {
constructor ( ) {
/** The markers currently on the map */
this . markers = new Map ( ) ;
}
} ;
/** Is the view currently open */
this . isOpen = false ;
this . navigation = true ;
this . settings = settings ;
@ -18226,6 +18339,7 @@ class MapView extends obsidian.ItemView {
this . getState = ( ) => {
return this . state ;
} ;
// Listen to file changes so we can update markers accordingly
this . app . vault . on ( 'delete' , file => this . updateMarkersWithRelationToFile ( file . path , null , true ) ) ;
this . app . vault . on ( 'rename' , ( file , oldPath ) => this . updateMarkersWithRelationToFile ( oldPath , file , true ) ) ;
this . app . metadataCache . on ( 'changed' , file => this . updateMarkersWithRelationToFile ( file . path , file , false ) ) ;
@ -18317,6 +18431,16 @@ class MapView extends obsidian.ItemView {
className : neededClassName
} ) ;
this . display . map . addLayer ( this . display . tileLayer ) ;
if ( ! ( chosenMapSource === null || chosenMapSource === void 0 ? void 0 : chosenMapSource . ignoreErrors ) ) {
let recentTileError = false ;
this . display . tileLayer . on ( 'tileerror' , ( event ) => {
if ( ! recentTileError ) {
new obsidian . Notice ( ` Map view: unable to load map tiles. Try switching the map source using the View controls. ` , 20000 ) ;
recentTileError = true ;
setTimeout ( ( ) => { recentTileError = false ; } , 5000 ) ;
}
} ) ;
}
}
}
refreshMap ( ) {
@ -18372,24 +18496,26 @@ class MapView extends obsidian.ItemView {
this . state . mapCenter = this . display . map . getCenter ( ) ;
( _b = ( _a = this . display ) === null || _a === void 0 ? void 0 : _a . controls ) === null || _b === void 0 ? void 0 : _b . invalidateActivePreset ( ) ;
} ) ;
// --- Work in progress ---
// this.display.clusterGroup.on('clustermouseover', cluster => {
// console.log(cluster.propagatedFrom.getAllChildMarkers());
// let content = this.contentEl.createDiv();
// for (const marker of cluster.propagatedFrom.getAllChildMarkers()) {
// console.log(marker);
// const iconElement = marker.options.icon.createIcon();
// let style = iconElement.style;
// style.marginLeft = style.marginTop = '0';
// style.position = 'relative';
// content.appendChild(iconElement);
// }
// cluster.propagatedFrom.bindPopup(content, {closeButton: false, autoPan: false}).openPopup();
// cluster.propagatedFrom.activePopup = content;
// });
// this.display.clusterGroup.on('clustermouseout', cluster => {
// // cluster.propagatedFrom.closePopup();
// });
if ( this . settings . showClusterPreview ) {
this . display . clusterGroup . on ( 'clustermouseover' , cluster => {
let content = this . contentEl . createDiv ( ) ;
content . classList . add ( 'clusterPreviewContainer' ) ;
for ( const m of cluster . propagatedFrom . getAllChildMarkers ( ) ) {
const marker = m ;
const iconElement = marker . options . icon . createIcon ( ) ;
iconElement . classList . add ( 'clusterPreviewIcon' ) ;
content . appendChild ( iconElement ) ;
if ( content . children . length >= MAX _CLUSTER _PREVIEW _ICONS )
break ;
}
cluster . propagatedFrom . bindPopup ( content , { closeButton : true , autoPan : false } ) . openPopup ( ) ;
cluster . propagatedFrom . activePopup = content ;
} ) ;
this . display . clusterGroup . on ( 'clustermouseout' , cluster => {
cluster . propagatedFrom . closePopup ( ) ;
} ) ;
}
// Build the map marker right-click context menu
this . display . map . on ( 'contextmenu' , ( event ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) {
let mapPopup = new obsidian . Menu ( this . app ) ;
mapPopup . setNoIcon ( ) ;
@ -18436,13 +18562,18 @@ class MapView extends obsidian.ItemView {
} ) ) ;
} ) ;
}
// Updates the map to the given state and then sets the state accordingly, but only if the given state version
// is not lower than the current state version (so concurrent async updates always keep the latest one)
/ * *
* Set the map state
* @ param state The map state to set
* @ param force Force setting the state . Will ignore if the state is old
* /
updateMarkersToState ( state , force = false ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
if ( this . settings . debug )
console . time ( 'updateMarkersToState' ) ;
// Get a list of all files matching the tags
const files = this . getFileListByQuery ( state . tags ) ;
// Build the markers for all files matching the tag
let newMarkers = yield buildMarkers ( files , this . settings , this . app ) ;
// --- BEYOND THIS POINT NOTHING SHOULD BE ASYNC ---
// Saying it again: do not use 'await' below this line!
@ -18454,6 +18585,10 @@ class MapView extends obsidian.ItemView {
console . timeEnd ( 'updateMarkersToState' ) ;
} ) ;
}
/ * *
* Get a list of files containing at least one of the tags
* @ param tags A list of string tags to match
* /
getFileListByQuery ( tags ) {
let results = [ ] ;
const allFiles = this . app . vault . getFiles ( ) ;
@ -18474,6 +18609,11 @@ class MapView extends obsidian.ItemView {
}
return results ;
}
/ * *
* Update the actual Leaflet markers of the map according to a new list of logical markers .
* Unchanged markers are not touched , new markers are created and old markers that are not in the updated list are removed .
* @ param newMarkers The new array of FileMarkers
* /
updateMapMarkers ( newMarkers ) {
let newMarkersMap = new Map ( ) ;
let markersToAdd = [ ] ;
@ -18506,11 +18646,18 @@ class MapView extends obsidian.ItemView {
this . goToMarker ( marker , event . originalEvent . ctrlKey , true ) ;
} ) ;
newMarker . on ( 'mouseover' , ( event ) => {
if ( this . settings . showNotePreview ) {
const previewDetails = {
scroll : marker . fileLine ,
line : marker . fileLine ,
startLoc : { line : marker . fileLine , col : 0 , offset : marker . fileLocation } ,
endLoc : { line : marker . fileLine , col : 0 , offset : marker . fileLocation }
} ;
this . app . workspace . trigger ( 'link-hover' , newMarker . getElement ( ) , newMarker . getElement ( ) , marker . file . path , '' , previewDetails ) ;
}
let content = ` <p class="map-view-marker-name"> ${ marker . file . name } </p> ` ;
if ( marker . extraName )
content += ` <p class="map-view-extra-name"> ${ marker . extraName } </p> ` ;
if ( marker . snippet )
content += ` <p class="map-view-marker-snippet"> ${ marker . snippet } </p> ` ;
newMarker . bindPopup ( content , { closeButton : true , autoPan : false } ) . openPopup ( ) ;
} ) ;
newMarker . on ( 'mouseout' , ( event ) => {
@ -18537,6 +18684,7 @@ class MapView extends obsidian.ItemView {
} ) ;
return newMarker ;
}
/** Zoom the map to fit all markers on the screen */
autoFitMapToMarkers ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
if ( this . display . markers . size > 0 ) {
@ -18545,6 +18693,12 @@ class MapView extends obsidian.ItemView {
}
} ) ;
}
/ * *
* Open a file in an editor window
* @ param file The file object to open
* @ param useCtrlKeyBehavior If true will use the alternative behaviour , as set in the settings
* @ param editorAction Optional callback to run when the file is opened
* /
goToFile ( file , useCtrlKeyBehavior , editorAction ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
let leafToUse = this . app . workspace . activeLeaf ;
@ -18585,21 +18739,36 @@ class MapView extends obsidian.ItemView {
yield editorAction ( editor ) ;
} ) ;
}
/ * *
* Open and go to the editor location represented by the marker
* @ param marker The FileMarker to open
* @ param useCtrlKeyBehavior If true will use the alternative behaviour , as set in the settings
* @ param highlight If true will highlight the line
* /
goToMarker ( marker , useCtrlKeyBehavior , highlight ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
return this . goToFile ( marker . file , useCtrlKeyBehavior , ( editor ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) { yield goToEditorLocation ( editor , marker . fileLocation , highlight ) ; } ) ) ;
} ) ;
}
/ * *
* Update the map markers with a list of markers not from the removed file plus the markers from the new file .
* Run when a file is deleted , renamed or changed .
* @ param fileRemoved The old file path
* @ param fileAddedOrChanged The new file data
* /
updateMarkersWithRelationToFile ( fileRemoved , fileAddedOrChanged , skipMetadata ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
if ( ! this . display . map || ! this . isOpen )
// If the map has not been set up yet then do nothing
return ;
let newMarkers = [ ] ;
// Create an array of all file markers not in the removed file
for ( let [ markerId , fileMarker ] of this . display . markers ) {
if ( fileMarker . file . path !== fileRemoved )
newMarkers . push ( fileMarker ) ;
}
if ( fileAddedOrChanged && fileAddedOrChanged instanceof obsidian . TFile )
// Add file markers from the added file
yield buildAndAppendFileMarkers ( newMarkers , fileAddedOrChanged , this . settings , this . app ) ;
this . updateMapMarkers ( newMarkers ) ;
} ) ;
@ -18732,17 +18901,25 @@ class SettingsTab extends obsidian.PluginSettingTab {
} ) ) ;
} ) ;
new obsidian . Setting ( containerEl )
. setName ( 'Note lines to show on map marker popup' )
. setDesc ( 'Number of total lines to show in the snippet displayed for inline geolocation notes.' )
. addSlider ( slider => {
var _a ;
slider
. setLimits ( 0 , 12 , 1 )
. setDynamicTooltip ( )
. setValue ( ( _a = this . plugin . settings . snippetLines ) !== null && _a !== void 0 ? _a : DEFAULT _SETTINGS . snippetLines )
. setName ( 'Show note preview on map marker hover' )
. setDesc ( 'In addition to the note and internal link name, show the native Obsidian note preview.' )
. addToggle ( component => {
component
. setValue ( this . plugin . settings . showNotePreview )
. onChange ( ( value ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) {
this . plugin . settings . snippetLines = value ;
this . plugin . saveSettings ( ) ;
this . plugin . settings . showNotePreview = value ;
yield this . plugin . saveSettings ( ) ;
} ) ) ;
} ) ;
new obsidian . Setting ( containerEl )
. setName ( 'Show preview for marker clusters' )
. setDesc ( 'Show a hover popup summarizing the icons inside a marker cluster. Changes are applied after restart.' )
. addToggle ( component => {
component
. setValue ( this . plugin . settings . showClusterPreview )
. onChange ( ( value ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) {
this . plugin . settings . showClusterPreview = value ;
yield this . plugin . saveSettings ( ) ;
} ) ) ;
} ) ;
new obsidian . Setting ( containerEl )
@ -18871,15 +19048,16 @@ class SettingsTab extends obsidian.PluginSettingTab {
this . refreshPluginOnHide = true ;
yield this . plugin . saveSettings ( ) ;
} ) ) ;
} )
. addButton ( component => component
. setButtonText ( 'Delete' )
. onClick ( ( ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) {
this . plugin . settings . mapSources . remove ( setting ) ;
this . refreshPluginOnHide = true ;
yield this . plugin . saveSettings ( ) ;
this . refreshMapSourceSettings ( containerEl ) ;
} ) ) ) ;
} ) ;
if ( ! setting . preset )
controls . addButton ( component => component
. setButtonText ( 'Delete' )
. onClick ( ( ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) {
this . plugin . settings . mapSources . remove ( setting ) ;
this . refreshPluginOnHide = true ;
yield this . plugin . saveSettings ( ) ;
this . refreshMapSourceSettings ( containerEl ) ;
} ) ) ) ;
controls . settingEl . style . padding = '5px' ;
controls . settingEl . style . borderTop = 'none' ;
}
@ -19252,7 +19430,9 @@ class MapViewPlugin extends obsidian.Plugin {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
obsidian . addIcon ( 'globe' , RIBBON _ICON ) ;
yield this . loadSettings ( ) ;
// Add a new ribbon entry to the left bar
this . addRibbonIcon ( 'globe' , 'Open map view' , ( ) => {
// When clicked change the active view to the map
this . app . workspace . getLeaf ( ) . setViewState ( { type : MAP _VIEW _NAME } ) ;
} ) ;
this . registerView ( MAP _VIEW _NAME , ( leaf ) => {
@ -19261,6 +19441,7 @@ class MapViewPlugin extends obsidian.Plugin {
this . suggestor = new LocationSuggest ( this . app , this . settings ) ;
this . urlConvertor = new UrlConvertor ( this . app , this . settings ) ;
this . registerEditorSuggest ( this . suggestor ) ;
// Convert old settings formats that are no longer supported
if ( convertLegacyMarkerIcons ( this . settings ) ) {
yield this . saveSettings ( ) ;
new obsidian . Notice ( "Map View: legacy marker icons were converted to the new format" ) ;
@ -19273,6 +19454,12 @@ class MapViewPlugin extends obsidian.Plugin {
yield this . saveSettings ( ) ;
new obsidian . Notice ( "Map View: legacy default state was converted to the new format" ) ;
}
if ( removeLegacyPresets1 ( this . settings ) ) {
yield this . saveSettings ( ) ;
new obsidian . Notice ( "Map View: legacy URL parsing rules and/or map sources were converted. See the release notes" ) ;
}
// Register commands to the command palette
// Command that opens the map view (same as clicking the map icon)
this . addCommand ( {
id : 'open-map-view' ,
name : 'Open Map View' ,
@ -19280,6 +19467,7 @@ class MapViewPlugin extends obsidian.Plugin {
this . app . workspace . getLeaf ( ) . setViewState ( { type : MAP _VIEW _NAME } ) ;
} ,
} ) ;
// Command that looks up the selected text to find the location
this . addCommand ( {
id : 'convert-selection-to-location' ,
name : 'Convert Selection to Geolocation' ,
@ -19289,6 +19477,7 @@ class MapViewPlugin extends obsidian.Plugin {
this . suggestor . selectionToLink ( editor ) ;
}
} ) ;
// Command that adds a blank inline location at the cursor location
this . addCommand ( {
id : 'insert-geolink' ,
name : 'Add inline geolocation link' ,
@ -19298,6 +19487,7 @@ class MapViewPlugin extends obsidian.Plugin {
editor . setCursor ( { line : positionBeforeInsert . line , ch : positionBeforeInsert . ch + 1 } ) ;
}
} ) ;
// Command that opens the location search dialog and creates a new note from this location
this . addCommand ( {
id : 'new-geolocation-note' ,
name : 'New geolocation note' ,
@ -19306,6 +19496,7 @@ class MapViewPlugin extends obsidian.Plugin {
dialog . open ( ) ;
}
} ) ;
// Command that opens the location search dialog and adds the location to the current note
this . addCommand ( {
id : 'add-frontmatter-geolocation' ,
name : 'Add geolocation (front matter) to current note' ,
@ -19315,25 +19506,32 @@ class MapViewPlugin extends obsidian.Plugin {
}
} ) ;
this . addSettingTab ( new SettingsTab ( this . app , this ) ) ;
// Add items to the file context menu (run when the context menu is built)
// This is the context menu in the File Explorer and clicking "More options" (three dots) from within a file.
this . app . workspace . on ( 'file-menu' , ( menu , file , _source , leaf ) => {
if ( file instanceof obsidian . TFile ) {
const location = getFrontMatterLocation ( file , this . app ) ;
if ( location ) {
// If there is a geolocation in the front matter of the file
// Add an option to open it in the map
menu . addItem ( ( item ) => {
item . setTitle ( 'Show on map' ) ;
item . setIcon ( 'globe' ) ;
item . onClick ( ( evt ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) { return yield this . openMapWithLocation ( location , evt . ctrlKey ) ; } ) ) ;
} ) ;
// Add an option to open it in the default app
menu . addItem ( ( item ) => {
item . setTitle ( 'Open with default app' ) ;
item . onClick ( _ev => {
open ( ` geo: ${ location . lat } , ${ location . lng } ` ) ;
} ) ;
} ) ;
// Populate menu items from user defined "Open In" strings
populateOpenInItems ( menu , location , this . settings ) ;
}
else {
if ( leaf && leaf . view instanceof obsidian . MarkdownView ) {
// If there is no valid geolocation in the front matter, add a menu item to populate it.
const editor = leaf . view . editor ;
menu . addItem ( ( item ) => {
item . setTitle ( 'Add geolocation (front matter)' ) ;
@ -19347,31 +19545,39 @@ class MapViewPlugin extends obsidian.Plugin {
}
}
} ) ;
// Add items to the editor context menu (run when the context menu is built)
// This is the context menu when right clicking within an editor view.
this . app . workspace . on ( 'editor-menu' , ( menu , editor , view ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) {
var _a ;
if ( view instanceof obsidian . FileView ) {
const location = this . getLocationOnEditorLine ( editor , view ) ;
if ( location ) {
// If there is a geolocation on the line
// Add an option to open it in the map
menu . addItem ( ( item ) => {
item . setTitle ( 'Show on map' ) ;
item . setIcon ( 'globe' ) ;
item . onClick ( ( evt ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) { return yield this . openMapWithLocation ( location , evt . ctrlKey ) ; } ) ) ;
} ) ;
// Add an option to open it in the default app
menu . addItem ( ( item ) => {
item . setTitle ( 'Open with default app' ) ;
item . onClick ( _ev => {
open ( ` geo: ${ location . lat } , ${ location . lng } ` ) ;
} ) ;
} ) ;
// Populate menu items from user defined "Open In" strings
populateOpenInItems ( menu , location , this . settings ) ;
}
if ( editor . getSelection ( ) ) {
// If there is text selected, add a menu item to convert it to coordinates using geosearch
menu . addItem ( ( item ) => {
item . setTitle ( 'Convert to geolocation (geosearch)' ) ;
item . onClick ( ( ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) { return yield this . suggestor . selectionToLink ( editor ) ; } ) ) ;
} ) ;
}
if ( this . urlConvertor . findMatchInLine ( editor ) )
// If the line contains a recognized geolocation that can be converted from a URL parsing rule
menu . addItem ( ( item ) => {
item . setTitle ( 'Convert to geolocation' ) ;
item . onClick ( ( ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) {
@ -19381,6 +19587,7 @@ class MapViewPlugin extends obsidian.Plugin {
const clipboard = yield navigator . clipboard . readText ( ) ;
const clipboardLocation = ( _a = this . urlConvertor . parseLocationFromUrl ( clipboard ) ) === null || _a === void 0 ? void 0 : _a . location ;
if ( clipboardLocation ) {
// If the clipboard contains a recognized geolocation that can be converted from a URL parsing rule
menu . addItem ( ( item ) => {
item . setTitle ( 'Paste as geolocation' ) ;
item . onClick ( ( ) => _ _awaiter ( this , void 0 , void 0 , function * ( ) {
@ -19392,6 +19599,11 @@ class MapViewPlugin extends obsidian.Plugin {
} ) ) ;
} ) ;
}
/ * *
* Open an instance of the map at the given geolocation
* @ param location The geolocation to open the map at
* @ param ctrlKey Was the control key pressed
* /
openMapWithLocation ( location , ctrlKey ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
yield this . openMapWithState ( { mapCenter : location , mapZoom : this . settings . zoomOnGoFromNote } , ctrlKey ) ;
@ -19413,6 +19625,12 @@ class MapViewPlugin extends obsidian.Plugin {
yield chosenLeaf . setViewState ( { type : MAP _VIEW _NAME , state : state } ) ;
} ) ;
}
/ * *
* Get the geolocation on the current editor line
* @ param editor obsidian Editor instance
* @ param view obsidian FileView instance
* @ private
* /
getLocationOnEditorLine ( editor , view ) {
const line = editor . getLine ( editor . getCursor ( ) . line ) ;
const match = matchInlineLocation ( line ) [ 0 ] ;
@ -19432,11 +19650,13 @@ class MapViewPlugin extends obsidian.Plugin {
}
onunload ( ) {
}
/** Initialise the plugin settings from Obsidian's cache */
loadSettings ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
this . settings = Object . assign ( { } , DEFAULT _SETTINGS , yield this . loadData ( ) ) ;
} ) ;
}
/** Save the plugin settings to Obsidian's cache so it can be reused later. */
saveSettings ( ) {
return _ _awaiter ( this , void 0 , void 0 , function * ( ) {
yield this . saveData ( this . settings ) ;