commit c12b67a2f49f8e27fa39d62c76a5886b5fc3bbc9 Author: jensmohr Date: Sun Aug 30 13:59:58 2026 +0200 Initial release of Link Heading Plugin diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ca10b3d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Jens Mohr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8ae6813 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Link Heading Plugin + +A simple plugin for DokuWiki that creates clickable headings linking to +internal DokuWiki pages. + +## Syntax + +By default, an H2 heading is created: + + {{linkheading>TARGET|HEADING}} + +Example: + + {{linkheading>oeffentlicheauslobung|Eine Überlegung zu Smart Glasses}} + +The heading level can be selected with a number from 1 to 6: + + {{linkheading>LEVEL|TARGET|HEADING}} + +Example using H4: + + {{linkheading>4|oeffentlicheauslobung|Eine Überlegung zu Smart Glasses}} + +Levels: + +- 1 = H1 +- 2 = H2 +- 3 = H3 +- 4 = H4 +- 5 = H5 +- 6 = H6 + +If no level is specified, H2 is used. + +## Namespaces + +The target is handled as an internal DokuWiki link. DokuWiki namespaces +can therefore be used as usual: + + {{linkheading>3|datenschutz:oeffentlicheauslobung|Öffentliche Auslobung}} + +## Author + +Jens Mohr + +## License + +MIT License + +Copyright (c) 2026 Jens Mohr + +See the `LICENSE` file for the full license text. diff --git a/plugin.info.txt b/plugin.info.txt new file mode 100644 index 0000000..521422b --- /dev/null +++ b/plugin.info.txt @@ -0,0 +1,5 @@ +base linkheading +author Jens Mohr +date 2026-08-30 +name Link Heading Plugin +desc Creates clickable headings linking to internal DokuWiki pages \ No newline at end of file diff --git a/syntax.php b/syntax.php new file mode 100644 index 0000000..54de135 --- /dev/null +++ b/syntax.php @@ -0,0 +1,120 @@ +Lexer->addSpecialPattern( + '\{\{linkheading>[^}]+\}\}', + $mode, + 'plugin_linkheading' + ); + } + + /** + * Parse plugin syntax. + * + * Supported forms: + * + * {{linkheading>target|Heading}} + * {{linkheading>4|target|Heading}} + * + * @inheritDoc + */ + public function handle($match, $state, $pos, Doku_Handler $handler) + { + $content = substr($match, 14, -2); + $parts = explode('|', $content); + + if ( + count($parts) >= 3 && + preg_match('/^[1-6]$/', trim($parts[0])) + ) { + $level = (int) trim(array_shift($parts)); + $target = trim(array_shift($parts)); + $title = trim(implode('|', $parts)); + } else { + $level = 2; + $target = trim(array_shift($parts)); + $title = trim(implode('|', $parts)); + } + + if ($title === '') { + $title = $target; + } + + return [ + 'level' => $level, + 'target' => $target, + 'title' => $title, + ]; + } + + /** + * Render linked heading. + * + * @inheritDoc + */ + public function render($mode, Doku_Renderer $renderer, $data) + { + $level = max(1, min(6, (int) $data['level'])); + $target = $data['target']; + $title = $data['title']; + + if ($mode === 'xhtml') { + $renderer->doc .= ''; + $renderer->internallink($target, $title); + $renderer->doc .= ''; + + return true; + } + + if ($mode === 'metadata') { + $renderer->internallink($target, $title); + + return true; + } + + return false; + } +}