diff --git a/README.md b/README.md index 9be1f25..03ad5be 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Article content here... | Field | Description | |---|---| -| Personal Access Token | A GitHub token with `repo` scope. [Generate one here](https://github.com/settings/tokens/new). | +| Personal Access Token | A GitHub token with `public_repo` scope (or `repo` if the repository is private). [Generate one here](https://github.com/settings/tokens/new). | | Repository Owner | Your GitHub username or organization name. | | Repository Name | The target repository (e.g. `my-blog`). | | Branch | Branch to push to (default: `main`). | diff --git a/plugin.php b/plugin.php index ef9615c..b2d7758 100644 --- a/plugin.php +++ b/plugin.php @@ -27,7 +27,7 @@ class pluginBluditGithub extends Plugin $html = '
'; $html .= ''; $html .= ''; - $html .= 'Requires repo scope. Generate token'; + $html .= 'Requires public_repo scope (or repo for private repositories). Generate token'; $html .= '
'; $html .= '
'; @@ -115,14 +115,22 @@ class pluginBluditGithub extends Plugin if (empty($key) || !$this->isConfigured()) { return; } - $filePath = $this->getFilePath($key); - $sha = $this->getFileSha($filePath); - if ($sha) { - $this->githubRequest('DELETE', '/contents/' . $filePath, [ - 'message' => 'Delete: ' . $key, - 'sha' => $sha, - 'branch' => $this->getValue('branch'), - ]); + // List all files in the article's folder and delete them + $prefix = trim($this->getValue('path'), '/'); + $dirPath = ($prefix ? $prefix . '/' : '') . $key; + $items = $this->githubRequest('GET', '/contents/' . $dirPath); + + if (!is_array($items)) { + return; + } + foreach ($items as $item) { + if ($item['type'] === 'file') { + $this->githubRequest('DELETE', '/contents/' . $item['path'], [ + 'message' => 'Delete: ' . $key . '/' . $item['name'], + 'sha' => $item['sha'], + 'branch' => $this->getValue('branch'), + ]); + } } } catch (Throwable $e) { $this->setStatus('Error (afterPageDelete): ' . $e->getMessage()); @@ -154,8 +162,45 @@ class pluginBluditGithub extends Plugin $result = $this->githubRequest('PUT', '/contents/' . $filePath, $data); - if ($result !== false && $saveStatus) { - $this->setStatus(date('Y-m-d H:i:s') . ' — Exported: ' . $page->title()); + if ($result !== false) { + $this->exportImages($key); + if ($saveStatus) { + $this->setStatus(date('Y-m-d H:i:s') . ' — Exported: ' . $page->title()); + } + } + } + + private function exportImages($key) + { + if (!defined('PATH_UPLOADS_PAGES')) { + return; + } + + $dir = PATH_UPLOADS_PAGES . $key; + if (!is_dir($dir)) { + return; + } + + $prefix = trim($this->getValue('path'), '/'); + + foreach (glob($dir . DS . '*') as $file) { + if (!is_file($file)) { + continue; + } + $filename = basename($file); + $repoPath = ($prefix ? $prefix . '/' : '') . $key . '/' . $filename; + $sha = $this->getFileSha($repoPath); + + $data = [ + 'message' => ($sha ? 'Update' : 'Add') . ' image: ' . $key . '/' . $filename, + 'content' => base64_encode(file_get_contents($file)), + 'branch' => $this->getValue('branch'), + ]; + if ($sha) { + $data['sha'] = $sha; + } + + $this->githubRequest('PUT', '/contents/' . $repoPath, $data); } } @@ -189,10 +234,17 @@ class pluginBluditGithub extends Plugin private function buildMarkdown($page, $key) { - // TinyMCE stores HTML — content() returns the full rendered content $content = $page->content(); - // Tags: getValue returns an array in Bludit + // Rewrite absolute Bludit upload URLs to relative filenames + // e.g. https://domain/bl-content/uploads/pages/UUID/image.png → image.png + $content = preg_replace( + '/https?:\/\/[^\/]+\/bl-content\/uploads\/pages\/[^\/]+\/([^"\')\s]+)/', + '$1', + $content + ); + + // Tags $rawTags = $page->getValue('tags'); $tagLines = ''; if (!empty($rawTags)) { @@ -304,7 +356,6 @@ class pluginBluditGithub extends Plugin return $decoded; } - private function isConfigured() { return $this->getValue('token') && $this->getValue('owner') && $this->getValue('repo');