From c5f4bcc1c5ff05579ab7283b61b056701d5eb773 Mon Sep 17 00:00:00 2001 From: luxick Date: Wed, 7 Jan 2026 11:42:40 +0100 Subject: [PATCH] Render open-location syntax as link --- _test/SyntaxTest.php | 6 +++--- images/folder.svg | 49 ++++++++++++++++++++++++++++++++++++++++++ images/open-folder.svg | 43 ++++++++++++++++++++++++++++++++++++ lang/en/settings.php | 2 +- script.js | 18 ++++++++++++++-- style.css | 20 +++++++++++++---- syntax/open.php | 34 +++++++++++++++++++++++------ 7 files changed, 156 insertions(+), 16 deletions(-) create mode 100644 images/folder.svg create mode 100644 images/open-folder.svg diff --git a/_test/SyntaxTest.php b/_test/SyntaxTest.php index 20d757b..1da276c 100644 --- a/_test/SyntaxTest.php +++ b/_test/SyntaxTest.php @@ -245,9 +245,9 @@ class plugin_luxtools_test extends DokuWikiTest } /** - * This function checks that the open syntax renders an inline button. + * This function checks that the open syntax renders an inline link. */ - public function test_open_button() + public function test_open_link() { $instructions = p_get_instructions('{{open>/tmp/somewhere|Open here}}'); $xhtml = p_render('xhtml', $instructions, $info); @@ -256,7 +256,7 @@ class plugin_luxtools_test extends DokuWikiTest $doc->html($xhtml); $structure = [ - 'button.luxtools-open' => 1, + 'a.luxtools-open' => 1, ]; $this->structureCheck($doc, $structure); diff --git a/images/folder.svg b/images/folder.svg new file mode 100644 index 0000000..7e38c50 --- /dev/null +++ b/images/folder.svg @@ -0,0 +1,49 @@ + + diff --git a/images/open-folder.svg b/images/open-folder.svg new file mode 100644 index 0000000..c867f84 --- /dev/null +++ b/images/open-folder.svg @@ -0,0 +1,43 @@ + + diff --git a/lang/en/settings.php b/lang/en/settings.php index 35f8575..a2ddd79 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -9,4 +9,4 @@ $lang['thumb_placeholder'] = 'MediaManager ID for the gallery thumbnail placehol $lang['gallery_thumb_scale'] = 'Gallery thumbnail scale factor. Use 2 for sharper thumbnails on HiDPI screens (still displayed as 150×150).'; -$lang['open_service_url'] = 'Local client service URL for the {{open>...}} button (e.g. http://127.0.0.1:8765).'; +$lang['open_service_url'] = 'Local client service URL for the {{open>...}} link (e.g. http://127.0.0.1:8765).'; diff --git a/script.js b/script.js index 5ed346b..acc5e59 100644 --- a/script.js +++ b/script.js @@ -119,9 +119,23 @@ return path; } + function findOpenElement(target) { + var el = target; + while (el && el !== document) { + if (el.classList && el.classList.contains('luxtools-open')) return el; + el = el.parentNode; + } + return null; + } + function onClick(event) { - var el = event.target; - if (!el || !el.classList || !el.classList.contains('luxtools-open')) return; + var el = findOpenElement(event.target); + if (!el) return; + + // {{open>...}} renders as a link; avoid jumping to '#'. + if (el.tagName && el.tagName.toLowerCase() === 'a') { + event.preventDefault(); + } var raw = el.getAttribute('data-path') || ''; if (!raw) return; diff --git a/style.css b/style.css index 9f148d5..637bfd8 100644 --- a/style.css +++ b/style.css @@ -21,13 +21,25 @@ div.luxtools-plugin table thead tr.luxtools-openlocation-row:hover td { /* Ensure directories use a dedicated folder icon. * DokuWiki's icon CSS is generated primarily for file extensions; a custom * mf_folder class may otherwise fall back to the generic file icon. - * - * The relative URL is resolved against the plugin directory by DokuWiki's CSS - * aggregator, resulting in lib/images/fileicons/svg/folder.svg. */ div.luxtools-plugin a.media.mediafile.mf_folder, div.luxtools-plugin a.mediafile.mf_folder { - background-image: url(../../images/fileicons/svg/folder.svg) !important; + background-image: url(images/folder.svg) !important; +} + +/* DokuWiki templates often style .media links with higher specificity. + * Ensure our custom color always wins. + */ +div.luxtools-plugin a.luxtools-open, +div.luxtools-plugin a.luxtools-open:visited, +a.luxtools-open, +a.luxtools-open:visited { + color: #b57d35 !important; +} + +/* Standalone {{open>...}} links are not wrapped in div.luxtools-plugin. */ +a.luxtools-open.media.mediafile.mf_folder { + background-image: url(images/open-folder.svg) !important; } /* Muted empty-state message when a listing has no results. */ diff --git a/syntax/open.php b/syntax/open.php index 46b3555..5d82051 100644 --- a/syntax/open.php +++ b/syntax/open.php @@ -5,7 +5,7 @@ use dokuwiki\Extension\SyntaxPlugin; /** * luxtools Plugin: Open local path syntax. * - * Renders an inline button. Clicking it triggers client-side JS that attempts + * Renders an inline link. Clicking it triggers client-side JS that attempts * to open the configured path in the default file manager (best-effort). */ class syntax_plugin_luxtools_open extends SyntaxPlugin @@ -74,14 +74,36 @@ class syntax_plugin_luxtools_open extends SyntaxPlugin } $serviceUrl = trim((string)$this->getConf('open_service_url')); + $serviceToken = trim((string)$this->getConf('open_service_token')); - $attrs = ' type="button" class="luxtools-open"' - . ' data-path="' . hsc($path) . '"'; - if ($serviceUrl !== '') { - $attrs .= ' data-service-url="' . hsc($serviceUrl) . '"'; + if (!($renderer instanceof \Doku_Renderer_xhtml)) { + $renderer->cdata($caption); + return true; } - $renderer->doc .= '' . hsc($caption) . ''; + global $conf; + /** @var \Doku_Renderer_xhtml $renderer */ + + // Render like a normal DokuWiki link with an icon in front. + // Use the same folder icon class as directory listings. + $link = [ + 'target' => $conf['target']['extern'], + 'style' => '', + 'pre' => '', + 'suf' => '', + 'name' => $caption, + 'url' => '#', + 'title' => $renderer->_xmlEntities($path), + 'more' => '', + 'class' => 'luxtools-open media mediafile mf_folder', + ]; + + $link['more'] .= ' data-path="' . hsc($path) . '"'; + if (!empty($conf['relnofollow'])) $link['more'] .= ' rel="nofollow"'; + if ($serviceUrl !== '') $link['more'] .= ' data-service-url="' . hsc($serviceUrl) . '"'; + if ($serviceToken !== '') $link['more'] .= ' data-service-token="' . hsc($serviceToken) . '"'; + + $renderer->doc .= $renderer->_formatLink($link); return true; } }