Skip to content

misohena/org-geolink

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Geo Location Link Type in Org-mode

This emacs lisp code adds geo location (latitude / longitude) link type to org-mode.

Geo location links can be opened with any web service or osm.el.

Also, you can freely customize the results when exporting geo location links.

Example of export results:

https://misohena.github.io/org-geolink/example-js.html

Setup

(with-eval-after-load "org"
  (require 'org-geolink))

Customize default map service as you like:

Link Notation Examples

- [​[geo:36.2893,137.64785]]
- [​[geo:36.2893,137.64785;z=18]]
- [​[geo:36.2893,137.64785][Oku-hotaka-dake]]

When exporting as HTML, the output is as follows:

<ul class="org-ul">
<li><a href="https://www.openstreetmap.org/#map=15/36.2893/137.64785" target="_blank" rel="noopener" data-geolink="36.2893,137.64785">36.2893,137.64785</a></li>
<li><a href="https://www.openstreetmap.org/#map=18/36.2893/137.64785" target="_blank" rel="noopener" data-geolink="36.2893,137.64785;z=18">36.2893,137.64785</a></li>
<li><a href="https://www.openstreetmap.org/#map=15/36.2893/137.64785" target="_blank" rel="noopener" data-geolink="36.2893,137.64785">Oku-hotaka-dake</a></li>
</ul>

The syntax of the path part is the same as the geo URI Scheme (rfc5870, Wikipedia). However, CRS conversion is not supported.

More Examples:

https://raw.githubusercontent.com/misohena/org-geolink/master/example.org

Open Link by Browser

Type C-c C-o on geo link.

The variable org-geolink-follow-function allows you to customize how locations are opened. In addition to the web browser, you can also open a location using the browse-url geo protocol handler or osm.el.

If you are using osm.el, you can open the location currently displayed in the osm buffer with a map service registered with org-geolink.

(with-eval-after-load 'osm
  (define-key osm-mode-map (kbd \"O\")
    #'org-geolink-open-osm-el-location-by-selected-web-service))

Customize HTML Export

Template Notation

{{{PATH}}}
Original path string.
{{{CONTENTS}}}
Description of link or result of expanding org-geolink-contents-template.
{{{URL}}}
Result of expanding org-geolink-url-template.
{{{1}}}
First coordinate number (Latitude).
{{{2}}}
Second coordinate number (Longitude).
{{{3}}}
Third coordinate number (Optional).
{{{ pname }}}
Value of link parameter ( ; pname = pvalue ).
{{{ pname : fmt }}}
(if pvalue (format fmt pvalue) "").

Variable: org-geolink-html-template

Template to use when creating a link HTML.

Default
<a href="{{{URL}}}" target="_blank" rel="noopener" data-geolink="{{{PATH}}}">{{{CONTENTS}}}</a>
In-Buffer Setting
#+GEOLINK_HTML_TEMPLATE: string

Variable: org-geolink-contents-template

Link text to use if no description is specified.

Default
~”{{{1}}},{{{2}}}”~
In-Buffer Setting
#+GEOLINK_CONTENTS_TEMPLATE: string

Variable: org-geolink-url-template

Template to use when creating a URL.

Specify in a format like ~”https://www.openstreetmap.org/#map={{{z}}}/{{{1}}}/{{{2}}}”~ .

nil means to use the default map service.

Default
nil (Use org-geolink-map-service-default )

Variable: org-geolink-map-service-default

Default map service. Specify ID symbol defined in org-geolink-map-services-user and org-geolink-map-services

Default
osm
In-Buffer Setting
#+GEOLINK_MAP: map-id
Predefined map services
ID
osmOpen Street Map
appleApple Maps
googleGoole Maps
jgsiThe Geospatial Information Authority of Japan

Variable: org-geolink-map-services-user

Alist of user defined map services.

Default
nil
Example
(setq org-geolink-map-services-user
      '((ex-map-1
         (name . "Example Map 1")
         (url . "https://www.example.com/type1/#map={{{z}}}/{{{1}}}/{{{2}}}"))
        (ex-map-2
         (name . "Example Map 2")
         (url . "https://www.example.com/type2/lat={{{1}}}&lng={{{2}}}&z={{{z}}}"))))
    

Variable: org-geolink-default-params

Default path parameters alist.

Default
’((“z” . “15”))
In-Buffer Setting
#+GEOLINK_DEFAULT_PARAMS: key=value;key=value=;…

CSS Examples

The following CSS inserts an earth emoji right after the geolink:

a[data-geolink]::after {
    content: "\1f310";
}

JavaScript Examples

See demo page: https://misohena.github.io/org-geolink/example-js.html

Org-mode source code: https://raw.githubusercontent.com/misohena/org-geolink/master/example-js.org

Embedded Map Example

The following example replaces a geolink with an embedded map. Replaces only the links with ;style=map with the Leaflet map. You can also specify ;map-width= and ;map-height=.

Settings:

(require 'org-geolink)

(defconst my-geolink-html-template-default
  "<a href=\"{{{URL}}}\" target=\"_blank\" rel=\"noopener\" data-geolink=\"{{{PATH}}}\">{{{CONTENTS}}}</a>")

(defconst my-geolink-html-template-for-map
  "<script>
(function(){
const div=document.createElement('div');
div.style.width = '{{{map-width}}}px';
div.style.height = '{{{map-height}}}px';
div.style.display = 'inline-block';
document.currentScript.parentNode.insertBefore(div, document.currentScript);
const map = L.map(div).setView([{{{1}}},{{{2}}}],{{{z}}});
const tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
      attribution: '© <a href=\"http://osm.org/copyright\">OpenStreetMap</a> contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>',
      maxZoom: 19
    });
tileLayer.addTo(map);
})();
</script>
")
(setf (alist-get "map-width" org-geolink-default-params nil nil #'equal) "200")
(setf (alist-get "map-height" org-geolink-default-params nil nil #'equal) "200")

(defun my-geolink-html-template (params)
  (if (equal (cdr (assoc "style" params)) "map")
      (org-geolink-expand-template my-geolink-html-template-for-map params)
    (org-geolink-expand-template my-geolink-html-template-default params)))

(setq org-geolink-html-template #'my-geolink-html-template)

Org-mode source:

#+HTML_HEAD: <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
#+HTML_HEAD: <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>

Normal Link: [​[geo:36.2893,137.64785][Oku-hotaka-dake]]

Map [​[geo:36.2893,137.64785;style=map]] or [​[geo:36.2893,137.64785;z=18;style=map]]

[​[geo:36.2893,137.64785;z=18;style=map;map-width=400;map-height=300]]

Header-free HTML template:

(defconst my-geolink-html-template-for-map
  "<script>
(function(){
  const currentScript = document.currentScript;
  function createMap(){
    const div=document.createElement('div');
    div.style.width = '{{{map-width}}}px';
    div.style.height = '{{{map-height}}}px';
    div.style.display = 'inline-block';
    currentScript.parentNode.insertBefore(div, currentScript);
    const map = L.map(div).setView([{{{1}}},{{{2}}}],{{{z}}});
    const tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{attribution: '© <a href=\"http://osm.org/copyright\">OpenStreetMap</a> contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>', maxZoom: 19});
    tileLayer.addTo(map);
  }
  if(window.L){
    createMap();
  }
  else{
    let scr = Array.prototype.find.call(document.head.querySelectorAll('script[src]'), (scr)=>scr.src.includes('leaflet.js'));
    if(scr){
      const onloadOld = scr.onload;
      scr.onload = ()=>{if(onloadOld){onloadOld();} createMap();};
    }
    else{
      const ls = document.createElement('link');
      ls.rel='stylesheet';
      ls.href='https://unpkg.com/leaflet@1.7.1/dist/leaflet.css';
      ls.crossOrigin='';
      ls.integrity='sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==';
      document.head.appendChild(ls);
      scr = document.createElement('script');
      scr.src = 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.js';
      scr.crossOrigin='';
      scr.integrity='sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==';
      scr.onload = createMap;
      document.head.appendChild(scr);
    }
  }
})();
</script>
")

Releases

No releases published

Packages

No packages published