>/g,(function(){return"(?:"+a+"|"+d+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("false|true","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism);
+!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var e=[],t={},n=function(){};Prism.plugins.toolbar={};var a=Prism.plugins.toolbar.registerButton=function(n,a){var r;r="function"==typeof a?a:function(e){var t;return"function"==typeof a.onClick?((t=document.createElement("button")).type="button",t.addEventListener("click",(function(){a.onClick.call(this,e)}))):"string"==typeof a.url?(t=document.createElement("a")).href=a.url:t=document.createElement("span"),a.className&&t.classList.add(a.className),t.textContent=a.text,t},n in t?console.warn('There is a button with the key "'+n+'" registered already.'):e.push(t[n]=r)},r=Prism.plugins.toolbar.hook=function(a){var r=a.element.parentNode;if(r&&/pre/i.test(r.nodeName)&&!r.parentNode.classList.contains("code-toolbar")){var o=document.createElement("div");o.classList.add("code-toolbar"),r.parentNode.insertBefore(o,r),o.appendChild(r);var i=document.createElement("div");i.classList.add("toolbar");var l=e,d=function(e){for(;e;){var t=e.getAttribute("data-toolbar-order");if(null!=t)return(t=t.trim()).length?t.split(/\s*,\s*/g):[];e=e.parentElement}}(a.element);d&&(l=d.map((function(e){return t[e]||n}))),l.forEach((function(e){var t=e(a);if(t){var n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(t),i.appendChild(n)}})),o.appendChild(i)}};a("label",(function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-label")){var n,a,r=t.getAttribute("data-label");try{a=document.querySelector("template#"+r)}catch(e){}return a?n=a.content:(t.hasAttribute("data-url")?(n=document.createElement("a")).href=t.getAttribute("data-url"):n=document.createElement("span"),n.textContent=r),n}})),Prism.hooks.add("complete",r)}}();
+!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document)if(Prism.plugins.toolbar){var e={none:"Plain text",plain:"Plain text",plaintext:"Plain text",text:"Plain text",txt:"Plain text",html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",rss:"RSS",css:"CSS",clike:"C-like",js:"JavaScript",abap:"ABAP",abnf:"ABNF",al:"AL",antlr4:"ANTLR4",g4:"ANTLR4",apacheconf:"Apache Configuration",apl:"APL",aql:"AQL",ino:"Arduino",arff:"ARFF",armasm:"ARM Assembly","arm-asm":"ARM Assembly",art:"Arturo",asciidoc:"AsciiDoc",adoc:"AsciiDoc",aspnet:"ASP.NET (C#)",asm6502:"6502 Assembly",asmatmel:"Atmel AVR Assembly",autohotkey:"AutoHotkey",autoit:"AutoIt",avisynth:"AviSynth",avs:"AviSynth","avro-idl":"Avro IDL",avdl:"Avro IDL",awk:"AWK",gawk:"GAWK",sh:"Shell",basic:"BASIC",bbcode:"BBcode",bbj:"BBj",bnf:"BNF",rbnf:"RBNF",bqn:"BQN",bsl:"BSL (1C:Enterprise)",oscript:"OneScript",csharp:"C#",cs:"C#",dotnet:"C#",cpp:"C++",cfscript:"CFScript",cfc:"CFScript",cil:"CIL",cilkc:"Cilk/C","cilk-c":"Cilk/C",cilkcpp:"Cilk/C++","cilk-cpp":"Cilk/C++",cilk:"Cilk/C++",cmake:"CMake",cobol:"COBOL",coffee:"CoffeeScript",conc:"Concurnas",csp:"Content-Security-Policy","css-extras":"CSS Extras",csv:"CSV",cue:"CUE",dataweave:"DataWeave",dax:"DAX",django:"Django/Jinja2",jinja2:"Django/Jinja2","dns-zone-file":"DNS zone file","dns-zone":"DNS zone file",dockerfile:"Docker",dot:"DOT (Graphviz)",gv:"DOT (Graphviz)",ebnf:"EBNF",editorconfig:"EditorConfig",ejs:"EJS",etlua:"Embedded Lua templating",erb:"ERB","excel-formula":"Excel Formula",xlsx:"Excel Formula",xls:"Excel Formula",fsharp:"F#","firestore-security-rules":"Firestore security rules",ftl:"FreeMarker Template Language",gml:"GameMaker Language",gamemakerlanguage:"GameMaker Language",gap:"GAP (CAS)",gcode:"G-code",gdscript:"GDScript",gedcom:"GEDCOM",gettext:"gettext",po:"gettext",glsl:"GLSL",gn:"GN",gni:"GN","linker-script":"GNU Linker Script",ld:"GNU Linker Script","go-module":"Go module","go-mod":"Go module",graphql:"GraphQL",hbs:"Handlebars",hs:"Haskell",hcl:"HCL",hlsl:"HLSL",http:"HTTP",hpkp:"HTTP Public-Key-Pins",hsts:"HTTP Strict-Transport-Security",ichigojam:"IchigoJam","icu-message-format":"ICU Message Format",idr:"Idris",ignore:".ignore",gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore",inform7:"Inform 7",javadoc:"JavaDoc",javadoclike:"JavaDoc-like",javastacktrace:"Java stack trace",jq:"JQ",jsdoc:"JSDoc","js-extras":"JS Extras",json:"JSON",webmanifest:"Web App Manifest",json5:"JSON5",jsonp:"JSONP",jsstacktrace:"JS stack trace","js-templates":"JS Templates",keepalived:"Keepalived Configure",kts:"Kotlin Script",kt:"Kotlin",kumir:"KuMir (КуМир)",kum:"KuMir (КуМир)",latex:"LaTeX",tex:"TeX",context:"ConTeXt",lilypond:"LilyPond",ly:"LilyPond",emacs:"Lisp",elisp:"Lisp","emacs-lisp":"Lisp",llvm:"LLVM IR",log:"Log file",lolcode:"LOLCODE",magma:"Magma (CAS)",md:"Markdown","markup-templating":"Markup templating",matlab:"MATLAB",maxscript:"MAXScript",mel:"MEL",metafont:"METAFONT",mongodb:"MongoDB",moon:"MoonScript",n1ql:"N1QL",n4js:"N4JS",n4jsd:"N4JS","nand2tetris-hdl":"Nand To Tetris HDL",naniscript:"Naninovel Script",nani:"Naninovel Script",nasm:"NASM",neon:"NEON",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",objc:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",openqasm:"OpenQasm",qasm:"OpenQasm",parigp:"PARI/GP",objectpascal:"Object Pascal",psl:"PATROL Scripting Language",pcaxis:"PC-Axis",px:"PC-Axis",peoplecode:"PeopleCode",pcode:"PeopleCode",php:"PHP",phpdoc:"PHPDoc","php-extras":"PHP Extras","plant-uml":"PlantUML",plantuml:"PlantUML",plsql:"PL/SQL",powerquery:"PowerQuery",pq:"PowerQuery",mscript:"PowerQuery",powershell:"PowerShell",promql:"PromQL",properties:".properties",protobuf:"Protocol Buffers",purebasic:"PureBasic",pbfasm:"PureBasic",purs:"PureScript",py:"Python",qsharp:"Q#",qs:"Q#",q:"Q (kdb+ database)",qml:"QML",rkt:"Racket",cshtml:"Razor C#",razor:"Razor C#",jsx:"React JSX",tsx:"React TSX",renpy:"Ren'py",rpy:"Ren'py",res:"ReScript",rest:"reST (reStructuredText)",robotframework:"Robot Framework",robot:"Robot Framework",rb:"Ruby",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (SCSS)","shell-session":"Shell session","sh-session":"Shell session",shellsession:"Shell session",sml:"SML",smlnj:"SML/NJ",solidity:"Solidity (Ethereum)",sol:"Solidity (Ethereum)","solution-file":"Solution file",sln:"Solution file",soy:"Soy (Closure Template)",sparql:"SPARQL",rq:"SPARQL","splunk-spl":"Splunk SPL",sqf:"SQF: Status Quo Function (Arma 3)",sql:"SQL",stata:"Stata Ado",iecst:"Structured Text (IEC 61131-3)",supercollider:"SuperCollider",sclang:"SuperCollider",systemd:"Systemd configuration file","t4-templating":"T4 templating","t4-cs":"T4 Text Templates (C#)",t4:"T4 Text Templates (C#)","t4-vb":"T4 Text Templates (VB)",tap:"TAP",tt2:"Template Toolkit 2",toml:"TOML",trickle:"trickle",troy:"troy",trig:"TriG",ts:"TypeScript",tsconfig:"TSConfig",uscript:"UnrealScript",uc:"UnrealScript",uorazor:"UO Razor Script",uri:"URI",url:"URL",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim","visual-basic":"Visual Basic",vba:"VBA",vb:"Visual Basic",wasm:"WebAssembly","web-idl":"Web IDL",webidl:"Web IDL",wgsl:"WGSL",wiki:"Wiki markup",wolfram:"Wolfram language",nb:"Mathematica Notebook",wl:"Wolfram language",xeoracube:"XeoraCube","xml-doc":"XML doc (.net)",xojo:"Xojo (REALbasic)",xquery:"XQuery",yaml:"YAML",yml:"YAML",yang:"YANG"};Prism.plugins.toolbar.registerButton("show-language",(function(a){var t=a.element.parentNode;if(t&&/pre/i.test(t.nodeName)){var o,i=t.getAttribute("data-language")||e[a.language]||((o=a.language)?(o.substring(0,1).toUpperCase()+o.substring(1)).replace(/s(?=cript)/,"S"):o);if(i){var s=document.createElement("span");return s.textContent=i,s}}}))}else console.warn("Show Languages plugin loaded before Toolbar plugin.")}();
+!function(){function t(t){var e=document.createElement("textarea");e.value=t.getText(),e.style.top="0",e.style.left="0",e.style.position="fixed",document.body.appendChild(e),e.focus(),e.select();try{var o=document.execCommand("copy");setTimeout((function(){o?t.success():t.error()}),1)}catch(e){setTimeout((function(){t.error(e)}),1)}document.body.removeChild(e)}"undefined"!=typeof Prism&&"undefined"!=typeof document&&(Prism.plugins.toolbar?Prism.plugins.toolbar.registerButton("copy-to-clipboard",(function(e){var o=e.element,n=function(t){var e={copy:"Copy","copy-error":"Press Ctrl+C to copy","copy-success":"Copied!","copy-timeout":5e3};for(var o in e){for(var n="data-prismjs-"+o,c=t;c&&!c.hasAttribute(n);)c=c.parentElement;c&&(e[o]=c.getAttribute(n))}return e}(o),c=document.createElement("button");c.className="copy-to-clipboard-button",c.setAttribute("type","button");var r=document.createElement("span");return c.appendChild(r),u("copy"),function(e,o){e.addEventListener("click",(function(){!function(e){navigator.clipboard?navigator.clipboard.writeText(e.getText()).then(e.success,(function(){t(e)})):t(e)}(o)}))}(c,{getText:function(){return o.textContent},success:function(){u("copy-success"),i()},error:function(){u("copy-error"),setTimeout((function(){!function(t){window.getSelection().selectAllChildren(t)}(o)}),1),i()}}),c;function i(){setTimeout((function(){u("copy")}),n["copy-timeout"])}function u(t){r.textContent=n[t],c.setAttribute("data-copy-state",t)}})):console.warn("Copy to Clipboard plugin loaded before Toolbar plugin."))}();
diff --git a/docs/README.manual.md b/docs/README.manual.md
new file mode 100644
index 0000000..de58b6a
--- /dev/null
+++ b/docs/README.manual.md
@@ -0,0 +1,73 @@
+# Hinweise zum Umgang mit dem Handbuch
+
+Die Handbuchseiten sind in der package.yml definiert.
+
+- Der Einstiegspunkt ist auf der obersten Menü-Ebene des Addons (`page=geolocation/manual`);
+- Es gibt zwei Menü-Ebenen im Handbuch
+ - Ebene 1 wird im Addon-Menü als zweite Ebene angezeigt.
+ - Ebene 2 (nur Entwickler und Installation), also Admin-relevant, haben eine weitere Ebene.
+ Diese Seiten werden direkt über dem Text als Tab-Menü angezeigt.
+- Alle Handbuch-Seiten werden mit `pages/manual.php` angezeigt. Die Einträge haben daher alle
+ `subpath: pages/manual.php`.
+- Die Zuordnung der Handbuch-Texte zu den Seiten im Addon erfolgt über den Namen des Eintrags.
+ Z.B. ergibt sich aus dem Seitennamen `geolocation/manual/install/install` die Datei `docs/install.md`.
+
+## Vorgegebene Dateistruktur
+
+```
+geolocation/docs Hier liegen die Textdateien
+geolocation/docs/assets Hier liegen alle Assets, insb. die eingebundenen Grafiken
+```
+
+
+## Was muss man beim Schreiben beachten
+
+Es gilt: "GitHub first", Alle Seiten sind so geschrieben und platziert, dass die Referenzen auf Assets
+und andere Seiten auf Github korrekt angezeigt werden.
+
+### Links zu anderen Seiten des Handbuchs
+
+Links werden Markdown-konform als `[name](seite.md)` geschrieben. Da alle Seiten im selben Verzeichnis liegen,
+lösen sich die Referenzen korrekt auf. Innerhalb der REDAXO-Instanz werden diese Links in Page-Links
+der Redaxo-Instanz umgewandelt (`index-php?page=geolocation/manual/seite`).
+
+Anker sind zulässig (`[name](seite.md#anker)`).
+
+### Links zu Assets
+
+Assets meint Bilder! Links werden Markdown-konform als `![name](assets/grafik.jpg)` geschrieben.
+Innerhalb der REDAXO-Instanz werden die Bilder-Links in Page-Links mit angehängtem Ressourcen-Namen
+umgewandelt (`index-php?page=geolocation/manual/seite&res=grafik.jpg`).
+
+### URI-Links und andere
+
+Links, die klassisch als URI ausgelegt sind (`irgendwas://der.rest?der=url`) bleiben unverändert. Das
+gilt auch für jeden anderen Link.
+
+### Code-Blöcke
+
+Damit der Link-Umbau in der Instanz funktioniert, müssen Code-Blöcke ausgenommen werden.
+Als Code-Blöcke werden hierbei nur die Code-Blöcke in Backticks (\`...\` bzw. \`\`\`...\`\`\`)
+berücksichtigt. Keine Codeblöcke durch Einrückung!!!
+
+### Hauptmenü für die GitHub Darstellung
+
+Das mehrseitige Handbuch hat auf jeder Seite eine Linkliste auf die anderen Seiten.
+Die Zeilen beginnen alle mit `>` und müssen ab der ersten Zeile der Datei lückenlos
+sein. Dieser Block (alle fortlaufenden Zeilen am Anfang der Datei, die mit `>` beginnen)
+wird in der Redaxo-Instanz entfernt, denn dort gibt es ja ein Menü im Addon.
+
+### Codeblock-Beautifier
+
+Code-Blöcke werden optisch verschönert. Da REDAXO sowas intern nur für PHP unterstützt,
+greifen wir auf PrismJS zurück. Damit können verschiedene Sprachen bearbeitet werden.
+
+Sprachcode nur in Kleinbuchstaben!
+
+- \`\`\`php
+- \`\`\`js
+- \`\`\`htm
+- \`\`\`css
+- \`\`\`scss
+- \`\`\`svg
+- \`\`\`sql
\ No newline at end of file
diff --git a/docs/devgeojson.md b/docs/devgeojson.md
index c0276e5..8b29e46 100644
--- a/docs/devgeojson.md
+++ b/docs/devgeojson.md
@@ -1,4 +1,5 @@
-> - Installation und Einstellungen
+> **Hauptmenü**
+> - [Installation und Einstellungen](install.md)
> - [Installation](install.md)
> - [Einstellungen](settings.md)
> - [Kartensätze verwalten](mapset.md)
@@ -8,7 +9,7 @@
> - [PHP](devphp.md)
> - [Javascript](devjs.md)
> - [JS-Tools](devtools.md)
-> - geoJSON
+> - __geoJSON__
> - [Rechnen (PHP)](devmath.md)
# Für Entwickler ‐ geoJSON und Kartentools
diff --git a/docs/devjs.md b/docs/devjs.md
index 29c0383..f450485 100644
--- a/docs/devjs.md
+++ b/docs/devjs.md
@@ -1,4 +1,5 @@
-> - Installation und Einstellungen
+> **Hauptmenü**
+> - [Installation und Einstellungen](install.md)
> - [Installation](install.md)
> - [Einstellungen](settings.md)
> - [Kartensätze verwalten](mapset.md)
@@ -6,7 +7,7 @@
> - [Karten-Proxy und -Cache](proxy_cache.md)
> - [Für Entwickler](devphp.md)
> - [PHP](devphp.md)
-> - Javascript
+> - __Javascript__
> - [JS-Tools](devtools.md)
> - [geoJSON](devgeojson.md)
> - [Rechnen (PHP)](devmath.md)
diff --git a/docs/devmath.md b/docs/devmath.md
index 5ff68e7..70c504a 100644
--- a/docs/devmath.md
+++ b/docs/devmath.md
@@ -1,4 +1,5 @@
-> - Installation und Einstellungen
+> **Hauptmenü**
+> - [Installation und Einstellungen](install.md)
> - [Installation](install.md)
> - [Einstellungen](settings.md)
> - [Kartensätze verwalten](mapset.md)
@@ -9,7 +10,7 @@
> - [Javascript](devjs.md)
> - [JS-Tools](devtools.md)
> - [geoJSON](devgeojson.md)
-> - Rechnen (PHP)
+> - __Rechnen (PHP)__
# Für Entwickler ‐ Rechnen mit Koordinaten (PHP)
@@ -22,8 +23,8 @@ der kugeligen Realität etwas komplizierter.
In **Geolocation** ist die PHP-Bibliothek [**phpGeo**](https://github.com/mjaschen/phpgeo) von
[Markus Jaschen](https://github.com/mjaschen) enthalten. Sie stellt eine Reihe von Klassen zur
Verwaltung von und Rechnen mit Koordinaten (`Coordinate`), Rechtecken (`Bounds`) etc. im Namespace
-`\Location` zur Verfügung. **Geolocation** baut darauf auf und stellt drei eigene Klassen bereit,
-die erweiterte Funktionen im Namespace `\Geolocation` bereitstellen.
+`Location` zur Verfügung. **Geolocation** baut darauf auf und stellt drei eigene Klassen bereit,
+die erweiterte Funktionen im Namespace `FriendsOfRedaxo\Geolocation` bereitstellen.
- `class Point`: Verwaltet einen geografischen Punkt
- Factory-Methoden für verschiedene Quelldaten-Formate inkl. Zeichenketten
@@ -383,7 +384,7 @@ Die Funktion ermittelt die kürzeste Distanz in Meter zwischen `$point` und dem
Zielpunkt. Die Distanz wird auf dem [Großkreis](https://de.wikipedia.org/wiki/Gro%C3%9Fkreis)
ermittelt.
-```PHP
+```php
use FriendsOfRedaxo\Geolocation\Calc\Point;
$northWest = [39.753838434606,-105.00341892242];
@@ -429,7 +430,7 @@ Die Funktion ermittelt die Kompassrichtung der kürzesten Distanz zum Zielpunkt
Die Funktion ermittelt die Kompassrichtung der kürzesten Distanz zum Zielpunkt `$point` bei der
"Ankunft" (am Zielpunkt) auf dem Großkreis (0°...360°).
-```PHP
+```php
use FriendsOfRedaxo\Geolocation\Calc\Point;
$northWest = [39.753838434606,-105.00341892242];
@@ -470,7 +471,7 @@ dump(get_defined_vars());
Aus den Parametern Distanz (in Meter) und Kompasskurs (0°...360°) am Ausgangspunkt wird der
Zielpunkt über den Großkreis berechnet.
-```PHP
+```php
use FriendsOfRedaxo\Geolocation\Calc\Point;
$northWest = [39.753838434606,-105.00341892242];
@@ -507,7 +508,7 @@ Die Funktion ermittelt, ob der Abstand zum Referenzpunkt nicht größer ist als
angegeben in Meter. Der Vorgabewert ist 10 cm. Je nach Zoom-Faktor können so zu vernachlässigende
Punkte ermittelt werden.
-```PHP
+```php
use FriendsOfRedaxo\Geolocation\Calc\Point;
$NW = Point::byLatLng( [39.753838434606,-105.00341892242] );
diff --git a/docs/devphp.md b/docs/devphp.md
index eb787f0..81560ea 100644
--- a/docs/devphp.md
+++ b/docs/devphp.md
@@ -1,11 +1,11 @@
-> - Installation und Einstellungen
+> - [Installation und Einstellungen](install.md)
> - [Installation](install.md)
> - [Einstellungen](settings.md)
> - [Kartensätze verwalten](mapset.md)
> - [Karten/Layer verwalten](layer.md)
> - [Karten-Proxy und -Cache](proxy_cache.md)
> - Für Entwickler
-> - PHP
+> - __PHP_
> - [Javascript](devjs.md)
> - [JS-Tools](devtools.md)
> - [geoJSON](devgeojson.md)
@@ -14,9 +14,9 @@
# Für Entwickler ‐ PHP
-## Namespace **Geolocation**
+## Namespace **FriendsOfRedaxo\Geolocation**
-Alle PHP-Komponenten der serverseitigen Verarbeitung liegen im Namespace `Geolocation`. Das betrifft
+Alle PHP-Komponenten der serverseitigen Verarbeitung liegen im Namespace `FriendsOfRedaxo\Geolocation`. Das betrifft
die Klassen und globalen Konstanten. Hier die wichtigsten:
| Objekt | Anmerkung |
@@ -46,7 +46,7 @@ die Klassen und globalen Konstanten. Hier die wichtigsten:
Hier ein Beispiel:
-```PHP
+```php
$id = \rex_request( FriendsOfRedaxo\Geolocation\KEY_MAPSET, 'integer', 1 );
$mapset = FriendsOfRedaxo\Geolocation\Mapset::take( $id );
@@ -82,7 +82,7 @@ erforderlich sind, kann der Name durch ein Suffix eindeutig gemacht werden. Das
`|` angehängt (`position|eins`).
Die Methoden können verkettet werden:
-```PHP
+```php
echo FriendsOfRedaxo\Geolocation\Mapset::take( $mapsetId )
->attributes( 'id', 'my-map-id' )
->attributes( 'class', 'mymapclass' )
@@ -102,7 +102,7 @@ Das Resultat ist ein HTML-Tag mit fünf Attributen:
```
Alternatives Vorgehen:
-```PHP
+```php
$mapset = FriendsOfRedaxo\Geolocation\Mapset::take( $mapsetId );
$fragment = new \rex_fragment();
@@ -128,7 +128,7 @@ zur Verfügung.
Der Rückgabewert `TRUE` signalisiert, dass der Kartensatz-Datensatz gelöscht werden darf.
-```PHP
+```php
$delete = \rex_extension::registerPoint(new \rex_extension_point(
'GEOLOCATION_MAPSET_DELETE',
true,
@@ -139,8 +139,8 @@ $delete = \rex_extension::registerPoint(new \rex_extension_point(
Das Anwendungsbeispiel referenziert auf das weiter unten beschriebene Modul, bei dem in `value2`
die Auswahl des Kartensatzes gespeichert ist.
-```PHP
-\rex_extension::register('GEOLOCATION_MAPSET_DELETE', function( \rex_extension_point $ep ){
+```php
+\rex_extension::register('GEOLOCATION_MAPSET_DELETE', static function( \rex_extension_point $ep ){
$id = $ep->getParam('id');
$sql = rex_sql::factory();
$sql->setQuery( 'SELECT id FROM '.rex::getTable('article_slice').' WHERE value2 = ? LIMIT 1', [$id] );
@@ -280,7 +280,7 @@ Die Kartenausgabe beinhaltet
Wie das Bounds-Rechteck sichtbar gemacht wird, ist [hier beschrieben](devtools.md#boundsvisible).
-```PHP
+```php
- Installation und Einstellungen
+> **Hauptmenü**
+> - [Installation und Einstellungen](install.md)
> - [Installation](install.md)
> - [Einstellungen](settings.md)
> - [Kartensätze verwalten](mapset.md)
@@ -7,7 +8,7 @@
> - [Für Entwickler](devphp.md)
> - [PHP](devphp.md)
> - [Javascript](devjs.md)
-> - JS-Tools
+> - __JS-Tools__
> - [geoJSON](devgeojson.md)
> - [Rechnen (PHP)](devmath.md)
@@ -136,7 +137,7 @@ geändert werden.
Der Beispiel-Code ergänzt das im PHP-Kapitel beschriebene [Modul](devphp.md#output).
-```PHP
+```php
if( rex::isBackend() ){
echo '';
- }
- $path = $this->context->getAssetsPath('help.min.css');
- if( file_exists($path) ){
- $file = $this->context->getAssetsUrl('help.min.css');
- $url = \rex_url::backendController(['asset' => $file, 'buster' => filemtime($path)]);
- $HTML .= '';
- }
- return $HTML;
- }
-
- }
-}
-
-// Here we go ....
-
-$publish = new help_documentation( $this );
-
-if( $publish->isAsset() ) {
- $publish->sendAsset();
-}
-
-if( $path = $publish->getFilePath() ) {
-
- $text = \rex_file::get( $path );
-
- $text = $publish->stripGithubNavigation( $text );
- $text = $publish->replaceLinks( $text );
-
-} else {
-
- $key = $this->getName() . '_helpphp_not_found';
- if( !\rex_i18n::hasMsg($key) ) {
- \rex_i18n::addMsg($key, '#Sorry, die angeforderte Seite existiert nicht oder ist gesperrt!');
- }
- $text = \rex_i18n::msg($key);
-}
-
-$text = $publish->getDocument( $text );
-
-?>
-=$publish->getJsCss()?>
-
- =$publish->getNavigation( )?>
- =$text?>
-
diff --git a/help.yml b/help.yml
deleted file mode 100644
index c5e050e..0000000
--- a/help.yml
+++ /dev/null
@@ -1,65 +0,0 @@
-default:
-# initial: i.d.R. docs/mapset.md
- permissions:
- # sperrt das verlinkte Bild in docs/layer.md für Berechtigung geolocation[mapset]
- docs/assets/tiles_list.jpg: 'geolocation[layer]'
- docs/assets/tiles_edit.jpg: 'geolocation[layer]'
- # sperrt weitere Assets für alle Berechtigungen außer Admin[]
- docs/assets/config.jpg: 'admin[]'
- docs/assets/cronjob.jpg: 'admin[]'
-
- 0:
- title: ''
- icon: fa fa-info
- perm: 'admin[]'
- path: README.md
- 1:
- title: translate:geolocation_manpage_install
- icon: fa fa-book
- perm: 'admin[]'
- path: docs/install.md
- subnav:
- 0:
- title: Installation
- path: docs/install.md
- 1:
- title: Einstellungen
- path: docs/settings.md
-
- 2:
- title: translate:geolocation_manpage_mapset
- icon: fa fa-book
- perm: 'geolocation[mapset]'
- active: true
- path: docs/mapset.md
- 3:
- title: translate:geolocation_manpage_layer
- icon: fa fa-book
- perm: 'geolocation[layer]'
- path: docs/layer.md
- 4:
- title: translate:geolocation_manpage_proxy
- icon: fa fa-book
- perm: 'admin[]'
- path: docs/proxy_cache.md
- 5:
- title: translate:geolocation_manpage_developer
- icon: fa fa-book
- perm: 'admin[]'
- path: docs/devphp.md
- subnav:
- 0:
- title: translate:geolocation_manpage_devphp
- path: docs/devphp.md
- 1:
- title: translate:geolocation_manpage_devjs
- path: docs/devjs.md
- 2:
- title: translate:geolocation_manpage_devtools
- path: docs/devtools.md
- 3:
- title: translate:geolocation_manpage_devgeojson
- path: docs/devgeojson.md
- 4:
- title: translate:geolocation_manpage_devmath
- path: docs/devmath.md
diff --git a/package.yml b/package.yml
index c230505..a7a2b7d 100644
--- a/package.yml
+++ b/package.yml
@@ -9,10 +9,6 @@ page:
icon: rex-icon fa-globe
perm: geolocation[]
subpages:
- config:
- title: translate:geolocation_config
- icon: fa fa-wrench
- perm: 'admin[]'
mapset:
title: translate:geolocation_mapset
perm: 'geolocation[mapset]'
@@ -23,10 +19,62 @@ page:
perm: 'geolocation[layer]'
icon: fa fa-cloud-download
subPath: pages/yform.php
- docs:
+ config:
+ title: translate:geolocation_config
+ icon: fa fa-cog
+ perm: 'admin[]'
+ manual:
title: translate:geolocation_manpage
icon: fa fa-book
- subPath: help.php
+ subpages:
+ mapset:
+ title: translate:geolocation_manpage_mapset
+ icon: fa fa-earth-europe
+ perm: 'geolocation[mapset]'
+ subpath: pages/manual.php
+ layer:
+ title: translate:geolocation_manpage_layer
+ icon: fa fa-map
+ perm: 'geolocation[layer]'
+ subpath: pages/manual.php
+ proxy_cache:
+ title: translate:geolocation_manpage_proxy
+ icon: fa fa-route
+ perm: 'admin[]'
+ subpath: pages/manual.php
+ developer:
+ title: translate:geolocation_manpage_developer
+ icon: fa fa-user-gear
+ perm: 'admin[]'
+ subpages:
+ devphp:
+ title: translate:geolocation_manpage_devphp
+ subpath: pages/manual.php
+ devjs:
+ title: translate:geolocation_manpage_devjs
+ subpath: pages/manual.php
+ devtools:
+ title: translate:geolocation_manpage_devtools
+ subpath: pages/manual.php
+ devgeojson:
+ title: translate:geolocation_manpage_devgeojson
+ subpath: pages/manual.php
+ devmath:
+ title: translate:geolocation_manpage_devmath
+ subpath: pages/manual.php
+ install:
+ title: translate:geolocation_manpage_install
+ icon: fa fa-wrench
+ perm: 'admin[]'
+ subpages:
+ install:
+ title: Installation
+ icon: fa fa-wrench
+ subpath: pages/manual.php
+ settings:
+ title: Einstellungen
+ icon: fa fa-cog
+ subpath: pages/manual.php
clear_cache:
title: 'translate:geolocation_clear_cache'
perm: 'geolocation[clearcache]'
diff --git a/pages/manual.php b/pages/manual.php
new file mode 100644
index 0000000..ac97564
--- /dev/null
+++ b/pages/manual.php
@@ -0,0 +1,226 @@
+getPath('docs/' . $page->getKey() . '.md');
+if (!is_readable($path)) {
+ throw new rex_functional_exception($addon->getName() . '-Manual: file «' . basename($path) . '»not found');
+}
+
+/**
+ * PassThru für Bilder.
+ */
+$res = $context->getParam('res', '');
+if ('' < $res) {
+ $filePath = $addon->getPath('docs/assets/' . $res);
+ rex_response::cleanOutputBuffers();
+ if (is_readable($filePath)) {
+ $mime = mime_content_type($filePath);
+ $disposition = str_starts_with($mime, 'image/') ? 'inline' : 'attachment';
+ rex_response::sendFile($filePath, $mime, $disposition, basename($path));
+ } else {
+ rex_response::setStatus(rex_response::HTTP_NOT_FOUND);
+ rex_response::sendContent(rex_response::HTTP_NOT_FOUND);
+ }
+}
+
+/**
+ * Ggf vorhandene Language-Version benutzen.
+ */
+$languagePath = substr($path, 0, -3) . '.' . rex_i18n::getLanguage() . '.md';
+if (is_readable($languagePath)) {
+ $path = $languagePath;
+}
+$document = rex_file::require($path);
+
+/**
+ * Das für die Github-Darstellung eingebaute GitHub-Menü entfernen.
+ */
+$document = preg_replace('/^(\>\s+\-\s?.*?\\n)*\s*\\n/', '', $document);
+
+/**
+ * Für den Link-Austausch zuerst Code-Blöcke durch Platzhalter ersetzen
+ * Es werden nur Code-Blöcke in Backticks aufgestöbert!
+ */
+$codeBlock = [];
+$document = preg_replace_callback('/(```.*?```|`.*?`)/s', static function ($matches) use (&$codeBlock) {
+ $marker = '';
+ $codeBlock["/$marker/"] = $matches[0];
+ return $marker;
+}, $document);
+
+/**
+ * Für die Link-Korrektur wird eine Zuordnungsliste "page => MD-Datei"
+ * benötigt. Die wird aus der Handbuchstruktur ermittelt.
+ */
+$treeBuilderFunc = static function ($page, $key, $xref, $callback) {
+ $key = $key . '/' . $page->getKey();
+ if (0 === count($page->getSubpages())) {
+ $xref[$key] = $page->getKey() . '.md';
+ } else {
+ foreach ($page->getSubpages() as $subPage) {
+ $xref = $callback($subPage, $key, $xref, $callback);
+ }
+ }
+ return $xref;
+};
+$manual = $treeBuilderFunc(rex_be_controller::getPageObject('geolocation/manual'), 'geolocation', [], $treeBuilderFunc);
+
+/**
+ * Links korrigieren.
+ *
+ * Die Liste aller Links aus dem Text heraussuchen,
+ * Je nach Typ ('!' oder nicht) den Grafik-Link oder den Page-Link erzeugen
+ *
+ * - leere Links ignorieren
+ * - Dokument-interne Referenzen (#) ignorieren
+ * - REDAXO-Interne Aufrufe (?...) ignorieren
+ * - Dokumente mit kompletter URL ignorieren (irgendwas://sonstnochwas)
+ */
+$document = preg_replace_callback(
+ '/((!?)\[(.*?)\]\()\s*([^#^\?](.*?))\s*(\))/',
+ static function ($matches) use ($manual, $context) {
+ $link = $matches[4];
+ // komplette Url lassen wie sie ist
+ if (preg_match('/^.*?\:\/\/.*?$/', $link)) {
+ return $matches[0];
+ }
+
+ // Grafik-Links mit MM-Type anzeigen
+ if ('!' === $matches[2]) {
+ $context->setParam('res', basename($link));
+ return $matches[1] . $context->getUrl([], false) . $matches[6];
+ }
+
+ /**
+ * interne Seitenlinks in eine BE-Url umwandeln.
+ */
+ $name = explode('#', $matches[4]);
+ $pageKey = array_search($name[0], $manual);
+ if (is_string($pageKey)) {
+ return $matches[1] . rex_url::backendPage($pageKey) . substr($matches[4], strlen($name[0])) . $matches[6];
+ }
+
+ /**
+ * Unbekannte Seite, lassen wie es ist.
+ */
+ return $matches[0];
+ },
+ $document);
+
+/**
+ * Code-Blöcke wieder einbauen.
+ */
+if (0 < count($codeBlock)) {
+ $document = preg_replace(array_keys($codeBlock), $codeBlock, $document);
+}
+
+/**
+ * Bei Dokumenten der Ebene vier (außerhalb des normalen Page-Menüs) wird
+ * über dem Text ein weiteres Tab-Menü erstellt.
+ */
+$navigation = [];
+if (4 === count(explode('/', $page->getFullKey())) && 1 < count($page->getParent()->getSubpages())) {
+ foreach ($page->getParent()->getSubpages() as $key => $subPage) {
+ $navigation[] = [
+ 'linkAttr' => $page->getLinkAttr(null),
+ 'itemAttr' => $page->getItemAttr(null),
+ 'href' => rex_url::backendPage($subPage->getFullKey()),
+ 'icon' => $subPage->getIcon(),
+ 'title' => $subPage->getTitle(),
+ 'active' => $key === $page->getKey(),
+ ];
+ }
+}
+
+/**
+ * Dokument formatieren.
+ *
+ * Eingebautes PHP-Highlighting nur wenn das Tool PrismJS nicht verfügbar ist.
+ */
+$phpHighlight = !is_readable($addon->getAssetsPath('help.min.js')) || !is_readable($addon->getAssetsPath('help.min.css'));
+
+[$toc, $content] = rex_markdown::factory()->parseWithToc($document, 2, 3, [
+ rex_markdown::SOFT_LINE_BREAKS => false,
+ rex_markdown::HIGHLIGHT_PHP => $phpHighlight,
+]);
+
+if (!$phpHighlight) {
+ $url = rex_url::backendController([
+ 'asset' => $addon->getAssetsUrl('help.min.js'),
+ 'buster' => filemtime($addon->getAssetsPath('help.min.js')),
+ ]);
+ echo '';
+ $url = rex_url::backendController([
+ 'asset' => $addon->getAssetsUrl('help.min.css'),
+ 'buster' => filemtime($addon->getAssetsPath('help.min.css')),
+ ]);
+ echo '';
+}
+
+// Hotel
+
+/**
+ * Ausgabe.
+ */
+$navi = '';
+if (0 < count($navigation)) {
+ // nötiges HTML direckt ausgeben
+ echo '';
+ $fragment = new rex_fragment();
+ $fragment->setVar('id', 'EB3HA4EL99');
+ $fragment->setVar('left', $navigation);
+ $navi = $fragment->parse('core/navigations/content.php');
+}
+
+$fragment = new rex_fragment();
+$fragment->setVar('content', $content, false);
+$fragment->setVar('toc', $toc, false);
+$content = $fragment->parse('core/page/docs.php');
+
+$fragment = new rex_fragment();
+$fragment->setVar('class', 'manual');
+$fragment->setVar('body', $content, false);
+echo $navi,$fragment->parse('core/page/section.php');
+
+echo '';