Skip to content

Commit 1e0ecca

Browse files
authored
Use Google Maps Place data in templates (#294)
* Fill in templates with Google Maps places data * Fill in templates with Google Maps places data * simplify lookups * Updating docs * fixes * fixes * Small PR comments * Google maps result typing and empty string if undefined * fixes
1 parent c789885 commit 1e0ecca

File tree

6 files changed

+70
-9
lines changed

6 files changed

+70
-9
lines changed

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<!--ts-->
66

77
<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
8-
<!-- Added by: erez, at: Sun 03 Nov 2024 12:07:11 IST -->
8+
<!-- Added by: hal, at: Sun 22 Dec 12:58:47 GMT 2024 -->
99

1010
<!--te-->
1111

@@ -232,6 +232,19 @@ Map View adds an Obsidian command named "New geolocation note", which you can ma
232232
233233
This opens a dialog on which you can search (address or location based on your [configured geocoding provider](#changing-a-geocoding-provider)) or paste a URL using the built-in or custom [URL parsing rules](#url-parsing-rules).
234234
235+
When using Google Maps Places API, templates can extract additional result data.
236+
For instance, templates that match `googleMapsPlaceData.some.path` will be replaced with the value found at `some.path` in the [JSON serach result](https://developers.google.com/maps/documentation/places/web-service/place-data-fields).
237+
For instance, the following template would set a [place_id](https://developers.google.com/maps/documentation/places/web-service/place-id) property and tags the note with the [type](https://developers.google.com/maps/documentation/places/web-service/supported_types) of the place:
238+
239+
```
240+
---
241+
place_id: "{{googleMapsPlaceData.place_id}}"
242+
---
243+
#{{googleMapsPlaceData.types.0}}
244+
```
245+
246+
Currently only Google Maps Places API supports this advanced templating feature.
247+
235248
![](img/new-note-popup.gif)
236249

237250
### In an Existing Note

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@rollup/plugin-node-resolve": "^11.2.1",
2222
"@rollup/plugin-typescript": "^8.2.1",
2323
"@types/geojson": "^7946.0.7",
24+
"@types/google.maps": "^3.58.1",
2425
"@types/leaflet": "^1.9.3",
2526
"@types/leaflet.markercluster": "^1.4.5",
2627
"@types/node": "^14.14.37",

src/geosearch.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { PluginSettings } from 'src/settings';
77
import { UrlConvertor } from 'src/urlConvertor';
88
import { FileMarker } from 'src/markers';
99
import * as consts from 'src/consts';
10+
import * as utils from 'src/utils';
1011

1112
/**
1213
* A generic result of a geosearch
@@ -17,6 +18,7 @@ export class GeoSearchResult {
1718
location: leaflet.LatLng;
1819
resultType: 'searchResult' | 'url' | 'existingMarker';
1920
existingMarker?: FileMarker;
21+
extraLocationData?: utils.ExtraLocationData;
2022
}
2123

2224
export class GeoSearcher {
@@ -76,6 +78,7 @@ export class GeoSearcher {
7678
name: result.name,
7779
location: result.location,
7880
resultType: 'searchResult',
81+
extraLocationData: result.extraLocationData,
7982
});
8083
} catch (e) {
8184
console.log(
@@ -129,7 +132,7 @@ export async function googlePlacesSearch(
129132
'https://maps.googleapis.com/maps/api/place/textsearch/json?' +
130133
querystring.stringify(params);
131134
const googleContent = await request({ url: googleUrl });
132-
const jsonContent = JSON.parse(googleContent) as any;
135+
const jsonContent = JSON.parse(googleContent);
133136
let results: GeoSearchResult[] = [];
134137
if (
135138
jsonContent &&
@@ -147,6 +150,7 @@ export async function googlePlacesSearch(
147150
name: `${result?.name} (${result?.formatted_address})`,
148151
location: geolocation,
149152
resultType: 'searchResult',
153+
extraLocationData: { googleMapsPlaceData: result },
150154
} as GeoSearchResult);
151155
}
152156
}

src/locationSearchDialog.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ export class LocationSearchDialog extends SuggestModal<SuggestInfo> {
143143
this.plugin.newFrontMatterNote(
144144
value.location,
145145
evt,
146-
utils.sanitizePlaceNameForNoteName(value.name)
146+
utils.sanitizePlaceNameForNoteName(value.name),
147+
value.extraLocationData
147148
);
148149
else if (this.dialogAction == 'addToNote')
149150
this.addToNote(value.location, evt, value.name);

src/main.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export default class MapViewPlugin extends Plugin {
118118
)
119119
: null;
120120
if (location) {
121-
this.newFrontMatterNote(location, null, label);
121+
this.newFrontMatterNote(location, null, label, {});
122122
}
123123
} else if (params.mvaction === 'addtocurrentnotefm') {
124124
const location =
@@ -919,7 +919,8 @@ export default class MapViewPlugin extends Plugin {
919919
async newFrontMatterNote(
920920
location: leaflet.LatLng,
921921
ev: MouseEvent | KeyboardEvent | null,
922-
query: string
922+
query: string,
923+
extraLocationData: utils.ExtraLocationData
923924
) {
924925
const locationString = `${location.lat},${location.lng}`;
925926
const newFileName = utils.formatWithTemplates(
@@ -933,7 +934,8 @@ export default class MapViewPlugin extends Plugin {
933934
newFileName,
934935
locationString,
935936
this.settings.frontMatterKey,
936-
this.settings.newNoteTemplate
937+
this.settings.newNoteTemplate,
938+
extraLocationData
937939
);
938940
// If there is an open map view, use it to decide how and where to open the file.
939941
// Otherwise, open the file from the active leaf

src/utils.ts

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,48 @@ export function getLastUsedValidMarkdownLeaf() {
4141
return null;
4242
}
4343

44-
export function formatWithTemplates(s: string, query = '') {
44+
function resolveJsonPath(json: object, path: string): string | undefined {
45+
// Convert a string path like "some.path.to.data.0" to the value at that path in JSON
46+
// Remove leading/trailing curly braces and split the path into parts
47+
const pathParts = path.replace(/[{}]/g, '').split('.');
48+
// Use reduce with optional chaining to traverse the path
49+
return pathParts.reduce((current, part) => (current as any)?.[part], json);
50+
}
51+
52+
export type ExtraLocationData = {
53+
googleMapsPlaceData?: google.maps.places.PlaceResult;
54+
};
55+
56+
function replaceJsonPaths(content: string, json: ExtraLocationData) {
57+
// Use regex to find all patterns like {{some.path.to.data.0}}
58+
59+
// Find patterns to replace that start with an attribute of json
60+
for (const [key, data] of Object.entries(json)) {
61+
const regex = new RegExp(`{{${key}\\.(.*?)}}`, 'g');
62+
return content.replace(regex, (_, path: string) => {
63+
const result = resolveJsonPath(data, path);
64+
return result ? result : '';
65+
});
66+
}
67+
return content;
68+
}
69+
70+
export function formatWithTemplates(
71+
s: string,
72+
query = '',
73+
extraLocationData: ExtraLocationData = {}
74+
) {
4575
const datePattern = /{{date:([a-zA-Z\-\/\.\:]*)}}/g;
4676
const queryPattern = /{{query}}/g;
47-
const replaced = s
77+
let replaced = s
4878
.replace(datePattern, (_, pattern) => {
4979
// @ts-ignore
5080
return moment().format(pattern);
5181
})
5282
.replace(queryPattern, query);
5383

84+
replaced = replaceJsonPaths(replaced, extraLocationData);
85+
5486
return replaced;
5587
}
5688

@@ -101,11 +133,19 @@ export async function newNote(
101133
fileName: string,
102134
location: string,
103135
frontMatterKey: string,
104-
templatePath?: string
136+
templatePath: string,
137+
extraLocationData?: ExtraLocationData
105138
): Promise<[TFile, number]> {
106139
let templateContent = '';
107140
if (templatePath && templatePath.length > 0)
108141
templateContent = await app.vault.adapter.read(templatePath);
142+
143+
templateContent = formatWithTemplates(
144+
templateContent,
145+
'',
146+
extraLocationData
147+
);
148+
109149
const templateFrontMatterInfo = getFrontMatterInfo(templateContent);
110150

111151
let newFrontMatterContents;

0 commit comments

Comments
 (0)