Skip to content

Instantly share code, notes, and snippets.

@dsebastien
Created November 19, 2025 10:05
Show Gist options
  • Select an option

  • Save dsebastien/68f7032eb646bd90e84b50e0769f3489 to your computer and use it in GitHub Desktop.

Select an option

Save dsebastien/68f7032eb646bd90e84b50e0769f3489 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// Configuration
const OUTPUT_DIR = '...'; // Relative path to the folder where landmark notes should be created
const FILE_PREFIX = 'Foo'; // Prefix for the landmark notes filenames
/**
* Get all KML files in the current directory
*/
function getKMLFiles() {
const files = fs.readdirSync('.');
return files.filter(file => file.toLowerCase().endsWith('.kml'));
}
/**
* Get the next available ID by checking existing files (not mandatory, but I just decided to give each landmark note a unique identifier)
*/
function getNextId() {
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
return 1;
}
const files = fs.readdirSync(OUTPUT_DIR);
const noteFiles = files.filter(file => file.startsWith(FILE_PREFIX) && file.endsWith('.md'));
if (noteFiles.length === 0) {
return 1;
}
// Extract IDs from filenames
const ids = noteFiles.map(file => {
const match = file.match(/(\d+)\.md$/);
return match ? parseInt(match[1], 10) : 0;
});
return Math.max(...ids) + 1;
}
/**
* Parse KML file and extract placemarks with PlacemarkStyle
*/
function parsePlacemarks(kmlFilePath) {
const content = fs.readFileSync(kmlFilePath, 'utf8');
const placemarks = [];
// Split content into individual placemark sections
const placemarkRegex = /<Placemark[^>]*>[\s\S]*?<\/Placemark>/gi;
const placemarkMatches = content.match(placemarkRegex) || [];
for (const placemarkText of placemarkMatches) {
// Check if it uses PlacemarkStyle
const styleUrlMatch = placemarkText.match(/<styleUrl>\s*#([^<]+)\s*<\/styleUrl>/i);
if (!styleUrlMatch || styleUrlMatch[1].trim() !== 'PlacemarkStyle') {
continue;
}
// Extract name
const nameMatch = placemarkText.match(/<name>\s*([^<]+)\s*<\/name>/i);
const name = nameMatch ? nameMatch[1].trim() : 'Cam';
// Extract coordinates
const coordinatesMatch = placemarkText.match(/<coordinates>\s*([^<]+)\s*<\/coordinates>/i);
if (!coordinatesMatch) {
continue;
}
const coordsText = coordinatesMatch[1].trim();
const [longitude, latitude, altitude] = coordsText.split(',').map(s => s.trim());
placemarks.push({
name,
latitude,
longitude,
altitude
});
}
return placemarks;
}
/**
* Format number with leading zeros
*/
function padId(id) {
return id.toString().padStart(4, '0');
}
/**
* Get current timestamp in ISO format
*/
function getTimestamp() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day}T${hours}:${minutes}`;
}
/**
* Create a note file for a placemark (note: you can customize the properties as needed)
*/
function createNote(placemark, id) {
const filename = `${FILE_PREFIX} - ${padId(id)}.md`;
const filepath = path.join(OUTPUT_DIR, filename);
const timestamp = getTimestamp();
const content = `---
created: ${timestamp}
updated: ${timestamp}
coordinates:
- "${placemark.latitude}"
- "${placemark.longitude}"
color: blue
icon: landmark
tags:
- cameras
---
`;
fs.writeFileSync(filepath, content, 'utf8');
console.log(`Created: ${filename} (Lat: ${placemark.latitude}, Lon: ${placemark.longitude})`);
}
/**
* Main function
*/
function main() {
console.log('Processing KML files...\n');
// Get all KML files
const kmlFiles = getKMLFiles();
if (kmlFiles.length === 0) {
console.log('No KML files found in the current directory.');
return;
}
console.log(`Found ${kmlFiles.length} KML file(s):\n${kmlFiles.map(f => ` - ${f}`).join('\n')}\n`);
// Get starting ID
let currentId = getNextId();
console.log(`Starting from ID: ${padId(currentId)}\n`);
// Process each KML file
let totalPlacemarks = 0;
const processedFiles = [];
for (const kmlFile of kmlFiles) {
console.log(`Processing: ${kmlFile}`);
const placemarks = parsePlacemarks(kmlFile);
console.log(` Found ${placemarks.length} placemark(s) with PlacemarkStyle`);
for (const placemark of placemarks) {
createNote(placemark, currentId);
currentId++;
totalPlacemarks++;
}
processedFiles.push(kmlFile);
console.log('');
}
console.log(`\nDone! Created ${totalPlacemarks} note(s).`);
// Delete processed KML files
if (processedFiles.length > 0) {
console.log('\nDeleting processed KML files...');
for (const kmlFile of processedFiles) {
try {
fs.unlinkSync(kmlFile);
console.log(` Deleted: ${kmlFile}`);
} catch (err) {
console.error(` Error deleting ${kmlFile}: ${err.message}`);
}
}
}
}
// Run the script
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment