@repo-toolkit/confluence 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/cli.js +26 -3
- package/index.js +26 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -73,7 +73,8 @@ Flags:
|
|
|
73
73
|
- `--parent-page-id <id>` — numeric Confluence page id (required)
|
|
74
74
|
- `--version-message <text>` — version-message suffix appended to every PUT
|
|
75
75
|
- `--repository-url <url>` — repository URL appended to synced pages as an
|
|
76
|
-
italic source notice.
|
|
76
|
+
italic source notice. The `--folder` path is added to the notice link when it
|
|
77
|
+
is relative to `--cwd`. When omitted, GitHub Actions runs infer this from
|
|
77
78
|
`GITHUB_SERVER_URL` and `GITHUB_REPOSITORY`.
|
|
78
79
|
- `--skip-unchanged` / `--no-skip-unchanged` — skip pages whose body is unchanged (default: `skip`)
|
|
79
80
|
- `--dry-run` — walk the doc tree and validate every markdown file and local
|
package/cli.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
|
|
15
15
|
// src/index.ts
|
|
16
16
|
import { readFileSync as readFileSync2 } from "fs";
|
|
17
|
-
import { dirname, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
|
|
17
|
+
import { dirname, isAbsolute as isAbsolute2, relative as relative3, resolve as resolve2 } from "path";
|
|
18
18
|
|
|
19
19
|
// src/confluence-client.ts
|
|
20
20
|
import { Buffer } from "buffer";
|
|
@@ -1688,7 +1688,8 @@ function resolveConfluenceSyncPlan(options = {}) {
|
|
|
1688
1688
|
throw new Error(`parentPageId must be numeric, got: ${options.parentPageId}`);
|
|
1689
1689
|
}
|
|
1690
1690
|
}
|
|
1691
|
-
|
|
1691
|
+
const repositoryUrl = options.repositoryUrl ? repositoryNoticeUrl(options.repositoryUrl, cwd, options.folder ?? "") : "";
|
|
1692
|
+
if (repositoryUrl && !isAllowedUrl(repositoryUrl)) {
|
|
1692
1693
|
throw new Error(
|
|
1693
1694
|
"repositoryUrl must be an http(s), protocol-relative, server-relative, mailto, tel, or relative URL"
|
|
1694
1695
|
);
|
|
@@ -1705,7 +1706,7 @@ function resolveConfluenceSyncPlan(options = {}) {
|
|
|
1705
1706
|
skipUnchanged: options.skipUnchanged ?? true,
|
|
1706
1707
|
dryRun: options.dryRun ?? false,
|
|
1707
1708
|
renderHtmlBlocks: options.renderHtmlBlocks === true,
|
|
1708
|
-
repositoryUrl
|
|
1709
|
+
repositoryUrl
|
|
1709
1710
|
};
|
|
1710
1711
|
}
|
|
1711
1712
|
async function syncConfluenceToDocs(options = {}) {
|
|
@@ -1909,6 +1910,28 @@ function appendRepositoryNotice(html, repositoryUrl) {
|
|
|
1909
1910
|
const text = escapeHtml(repositoryUrl);
|
|
1910
1911
|
return html + '\n<p><em>This document is synced from repository <a href="' + url + '">' + text + "</a>.</em></p>";
|
|
1911
1912
|
}
|
|
1913
|
+
function repositoryNoticeUrl(repositoryUrl, cwd, folder) {
|
|
1914
|
+
const folderPath = repositoryFolderPath(cwd, folder);
|
|
1915
|
+
if (folderPath.length === 0) {
|
|
1916
|
+
return repositoryUrl;
|
|
1917
|
+
}
|
|
1918
|
+
const trimmedUrl = repositoryUrl.replace(/\/+$/, "").replace(/\.git$/, "");
|
|
1919
|
+
const encodedFolder = folderPath.split("/").map(encodeURIComponent).join("/");
|
|
1920
|
+
if (/^https?:\/\/github\.com\//i.test(trimmedUrl) && !/\/tree\/|\/blob\//.test(trimmedUrl)) {
|
|
1921
|
+
return trimmedUrl + "/tree/HEAD/" + encodedFolder;
|
|
1922
|
+
}
|
|
1923
|
+
return trimmedUrl + "/" + encodedFolder;
|
|
1924
|
+
}
|
|
1925
|
+
function repositoryFolderPath(cwd, folder) {
|
|
1926
|
+
if (folder.length === 0) {
|
|
1927
|
+
return "";
|
|
1928
|
+
}
|
|
1929
|
+
const relativePath = relative3(cwd, resolveInputPath(cwd, folder));
|
|
1930
|
+
if (relativePath === "" || relativePath.startsWith("..") || isAbsolute2(relativePath)) {
|
|
1931
|
+
return "";
|
|
1932
|
+
}
|
|
1933
|
+
return relativePath.split(/[\\/]+/).filter((part) => part !== "" && part !== ".").join("/");
|
|
1934
|
+
}
|
|
1912
1935
|
async function predictBody(html, mermaidBlocks, pageId, client, ctx) {
|
|
1913
1936
|
let predicted = html;
|
|
1914
1937
|
if (ctx.hasMermaidBlocks) {
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { readFileSync as readFileSync2 } from "fs";
|
|
3
|
-
import { dirname, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
|
|
3
|
+
import { dirname, isAbsolute as isAbsolute2, relative as relative3, resolve as resolve2 } from "path";
|
|
4
4
|
|
|
5
5
|
// src/confluence-client.ts
|
|
6
6
|
import { Buffer } from "buffer";
|
|
@@ -1675,7 +1675,8 @@ function resolveConfluenceSyncPlan(options = {}) {
|
|
|
1675
1675
|
throw new Error(`parentPageId must be numeric, got: ${options.parentPageId}`);
|
|
1676
1676
|
}
|
|
1677
1677
|
}
|
|
1678
|
-
|
|
1678
|
+
const repositoryUrl = options.repositoryUrl ? repositoryNoticeUrl(options.repositoryUrl, cwd, options.folder ?? "") : "";
|
|
1679
|
+
if (repositoryUrl && !isAllowedUrl(repositoryUrl)) {
|
|
1679
1680
|
throw new Error(
|
|
1680
1681
|
"repositoryUrl must be an http(s), protocol-relative, server-relative, mailto, tel, or relative URL"
|
|
1681
1682
|
);
|
|
@@ -1692,7 +1693,7 @@ function resolveConfluenceSyncPlan(options = {}) {
|
|
|
1692
1693
|
skipUnchanged: options.skipUnchanged ?? true,
|
|
1693
1694
|
dryRun: options.dryRun ?? false,
|
|
1694
1695
|
renderHtmlBlocks: options.renderHtmlBlocks === true,
|
|
1695
|
-
repositoryUrl
|
|
1696
|
+
repositoryUrl
|
|
1696
1697
|
};
|
|
1697
1698
|
}
|
|
1698
1699
|
async function syncConfluenceToDocs(options = {}) {
|
|
@@ -1896,6 +1897,28 @@ function appendRepositoryNotice(html, repositoryUrl) {
|
|
|
1896
1897
|
const text = escapeHtml(repositoryUrl);
|
|
1897
1898
|
return html + '\n<p><em>This document is synced from repository <a href="' + url + '">' + text + "</a>.</em></p>";
|
|
1898
1899
|
}
|
|
1900
|
+
function repositoryNoticeUrl(repositoryUrl, cwd, folder) {
|
|
1901
|
+
const folderPath = repositoryFolderPath(cwd, folder);
|
|
1902
|
+
if (folderPath.length === 0) {
|
|
1903
|
+
return repositoryUrl;
|
|
1904
|
+
}
|
|
1905
|
+
const trimmedUrl = repositoryUrl.replace(/\/+$/, "").replace(/\.git$/, "");
|
|
1906
|
+
const encodedFolder = folderPath.split("/").map(encodeURIComponent).join("/");
|
|
1907
|
+
if (/^https?:\/\/github\.com\//i.test(trimmedUrl) && !/\/tree\/|\/blob\//.test(trimmedUrl)) {
|
|
1908
|
+
return trimmedUrl + "/tree/HEAD/" + encodedFolder;
|
|
1909
|
+
}
|
|
1910
|
+
return trimmedUrl + "/" + encodedFolder;
|
|
1911
|
+
}
|
|
1912
|
+
function repositoryFolderPath(cwd, folder) {
|
|
1913
|
+
if (folder.length === 0) {
|
|
1914
|
+
return "";
|
|
1915
|
+
}
|
|
1916
|
+
const relativePath = relative3(cwd, resolveInputPath(cwd, folder));
|
|
1917
|
+
if (relativePath === "" || relativePath.startsWith("..") || isAbsolute2(relativePath)) {
|
|
1918
|
+
return "";
|
|
1919
|
+
}
|
|
1920
|
+
return relativePath.split(/[\\/]+/).filter((part) => part !== "" && part !== ".").join("/");
|
|
1921
|
+
}
|
|
1899
1922
|
async function predictBody(html, mermaidBlocks, pageId, client, ctx) {
|
|
1900
1923
|
let predicted = html;
|
|
1901
1924
|
if (ctx.hasMermaidBlocks) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@repo-toolkit/confluence",
|
|
3
3
|
"description": "Sync a folder of markdown docs to Confluence pages and attachments (GitHub Action compatible)",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.17.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"keywords": [
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"node": ">=20"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@repo-toolkit/publish-package": "0.
|
|
30
|
+
"@repo-toolkit/publish-package": "0.17.0"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"**/*",
|