diff --git a/README.md b/README.md index f1ee3c4..a33db50 100644 --- a/README.md +++ b/README.md @@ -98,15 +98,20 @@ Key settings: - **paths** Allowed base filesystem roots (one per line). Each root can be followed by: - - `A> /Alias/` (optional) alias used in wiki syntax and open links + - `A> Alias` (optional) alias used in wiki syntax and open links Example: ``` /srv/share/Datascape/ - A> /Scape/ + A> Scape ``` + Notes: + - Wiki syntax accepts aliases in path form (for example `Scape/sub/folder`). + - Open links sent to the local client service are emitted as `Alias>relative/path` + (for example `Scape>sub/folder`) so each client can resolve its own local root. + luxtools links use the plugin endpoint: `lib/plugins/luxtools/file.php?root=...&file=...` diff --git a/_test/PathTest.php b/_test/PathTest.php index 5a6fe36..e8dc194 100644 --- a/_test/PathTest.php +++ b/_test/PathTest.php @@ -115,9 +115,20 @@ EOT public function testMapToAliasPath() { $mapped = $this->path->mapToAliasPath('/linux/another/path/some/folder'); - $this->assertEquals('alias/some/folder', $mapped); + $this->assertEquals('alias>some/folder', $mapped); + + $mappedRoot = $this->path->mapToAliasPath('/linux/another/path/'); + $this->assertEquals('alias>', $mappedRoot); $unmapped = $this->path->mapToAliasPath('/linux/file/path/example.txt'); $this->assertEquals('/linux/file/path/example.txt', $unmapped); } + + public function testMapToAliasPathLegacyAliasStyle() + { + $path = new Path("/srv/share/Datascape/\nA> /Scape/\n"); + + $mapped = $path->mapToAliasPath('/srv/share/Datascape/projects/demo'); + $this->assertEquals('Scape>projects/demo', $mapped); + } } diff --git a/src/Path.php b/src/Path.php index 0d4e510..bdcd4fa 100644 --- a/src/Path.php +++ b/src/Path.php @@ -99,10 +99,10 @@ class Path } /** - * Map a real filesystem path back to a configured alias, if available. + * Map a real filesystem path back to an open-service alias, if available. * * Example: root "/share/Datascape/" with alias "/Scape/" maps - * "/share/Datascape/some/folder" -> "/Scape/some/folder". + * "/share/Datascape/some/folder" -> "Scape>some/folder". * * If no alias matches, the input path is returned unchanged (except for * normalization of slashes and dot-segments). @@ -117,12 +117,17 @@ class Path // normalize input for matching, but do not force a trailing slash $normalized = static::cleanPath($path, false); - // collect root->alias mappings (avoid alias keys that reference the same config) + // collect root->alias mappings for open-service links + // (avoid alias keys that reference the same config) $mappings = []; foreach ($this->paths as $key => $info) { if (!isset($info['root']) || $key !== $info['root']) continue; if (empty($info['alias'])) continue; - $mappings[$info['root']] = $info['alias']; + + $alias = $this->normalizeOpenAlias((string)$info['alias']); + if ($alias === '') continue; + + $mappings[$info['root']] = $alias; } if ($mappings === []) return $normalized; @@ -131,16 +136,34 @@ class Path uksort($mappings, static fn($a, $b) => strlen($b) - strlen($a)); foreach ($mappings as $root => $alias) { + $rootNoTrailingSlash = rtrim($root, '/'); + if (!str_starts_with($normalized, $root) && $normalized !== $rootNoTrailingSlash) continue; + + $suffix = ''; if (str_starts_with($normalized, $root)) { - $suffix = substr($normalized, strlen($root)); - $alias = static::cleanPath($alias, true); - return rtrim($alias, '/') . '/' . $suffix; + $suffix = (string)substr($normalized, strlen($root)); } + $suffix = ltrim($suffix, '/'); + + return $alias . '>' . $suffix; } return $normalized; } + /** + * Convert legacy path-like aliases (e.g. /Scape/) to open aliases (Scape). + * + * @param string $alias + * @return string + */ + protected function normalizeOpenAlias($alias) + { + $alias = trim($alias); + $alias = trim($alias, '/\\'); + return $alias; + } + /** * Clean a path for better comparison * diff --git a/syntax/open.php b/syntax/open.php index 900f885..1fed2ab 100644 --- a/syntax/open.php +++ b/syntax/open.php @@ -105,7 +105,21 @@ class syntax_plugin_luxtools_open extends SyntaxPlugin if (!preg_match('/^[a-zA-Z][a-zA-Z0-9+.-]*:/', $path)) { try { $pathHelper = $this->createPathHelper(); - $path = $pathHelper->mapToAliasPath($path); + + // If the input itself uses a configured path alias (legacy syntax + // like "alias/sub/path"), resolve it first so the emitted open + // path uses the new client-side alias format "ALIAS>relative". + $resolvedPath = $path; + try { + $pathInfo = $pathHelper->getPathInfo($path, false); + if (isset($pathInfo['path']) && is_string($pathInfo['path']) && $pathInfo['path'] !== '') { + $resolvedPath = $pathInfo['path']; + } + } catch (\Exception $e) { + // keep original path as-is when it is not in configured roots + } + + $path = $pathHelper->mapToAliasPath($resolvedPath); } catch (\Exception $e) { // ignore mapping failures }