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');