@bestend/confluence-cli 1.15.3 → 1.15.4

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.
@@ -19,11 +19,15 @@ jobs:
19
19
  node-version: '24.x'
20
20
  registry-url: 'https://registry.npmjs.org'
21
21
 
22
- - name: Set package version from tag
22
+ - name: Ensure package version matches tag
23
23
  run: |
24
24
  TAG="${GITHUB_REF_NAME#v}"
25
- echo "Setting package version to ${TAG}"
26
- npm version "$TAG" --no-git-tag-version
25
+ PKG_VERSION=$(node -p "require('./package.json').version")
26
+ echo "Tag: $TAG / package.json: $PKG_VERSION"
27
+ if [ "$TAG" != "$PKG_VERSION" ]; then
28
+ echo "package.json version mismatch: $PKG_VERSION (expected $TAG)" >&2
29
+ exit 1
30
+ fi
27
31
 
28
32
  - name: Install dependencies
29
33
  run: npm ci
@@ -61,6 +61,12 @@ class ConfluenceClient {
61
61
  if (pageIdMatch) {
62
62
  return pageIdMatch[1];
63
63
  }
64
+
65
+ // Handle /spaces/SPACEKEY/pages/PAGEID/Title format
66
+ const spacesMatch = pageIdOrUrl.match(/\/spaces\/[^/]+\/pages\/(\d+)/);
67
+ if (spacesMatch) {
68
+ return spacesMatch[1];
69
+ }
64
70
 
65
71
  // Handle display URLs - search by space and title
66
72
  const displayMatch = pageIdOrUrl.match(/\/display\/([^/]+)\/(.+)/);
@@ -842,9 +848,18 @@ class ConfluenceClient {
842
848
  // Convert code blocks to Confluence code macro
843
849
  storage = storage.replace(/<pre><code(?:\s+class="language-(\w+)")?>(.*?)<\/code><\/pre>/gs, (_, lang, code) => {
844
850
  const language = lang || 'text';
851
+ // Decode HTML entities inside code blocks before wrapping in CDATA
852
+ let decoded = code
853
+ .replace(/&amp;/g, '&')
854
+ .replace(/&lt;/g, '<')
855
+ .replace(/&gt;/g, '>')
856
+ .replace(/&quot;/g, '"')
857
+ .replace(/&#39;/g, "'");
858
+ decoded = decoded.replace(/\]\]>/g, ']]]]><![CDATA[>');
859
+
845
860
  return `<ac:structured-macro ac:name="code">
846
861
  <ac:parameter ac:name="language">${language}</ac:parameter>
847
- <ac:plain-text-body><![CDATA[${code}]]></ac:plain-text-body>
862
+ <ac:plain-text-body><![CDATA[${decoded}]]></ac:plain-text-body>
848
863
  </ac:structured-macro>`;
849
864
  });
850
865
 
@@ -885,8 +900,7 @@ class ConfluenceClient {
885
900
  storage = storage.replace(/<th>(.*?)<\/th>/g, '<th><p>$1</p></th>');
886
901
  storage = storage.replace(/<td>(.*?)<\/td>/g, '<td><p>$1</p></td>');
887
902
 
888
- // Convert links
889
- storage = storage.replace(/<a href="(.*?)">(.*?)<\/a>/g, '<ac:link><ri:url ri:value="$1" /><ac:plain-text-link-body><![CDATA[$2]]></ac:plain-text-link-body></ac:link>');
903
+ // Links: keep <a href> as-is (compatible with both Cloud and Server/Data Center)
890
904
 
891
905
  // Convert horizontal rules
892
906
  storage = storage.replace(/<hr\s*\/?>/g, '<hr />');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bestend/confluence-cli",
3
- "version": "1.15.3",
3
+ "version": "1.15.4",
4
4
  "description": "A command-line interface for Atlassian Confluence with page creation and editing capabilities",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -141,7 +141,7 @@ describe('ConfluenceClient', () => {
141
141
 
142
142
  expect(result).toContain('<ac:structured-macro ac:name="code">');
143
143
  expect(result).toContain('<ac:parameter ac:name="language">javascript</ac:parameter>');
144
- expect(result).toContain('console.log(&quot;Hello World&quot;);');
144
+ expect(result).toContain('console.log("Hello World");');
145
145
  });
146
146
 
147
147
  test('should convert lists to native Confluence format', () => {
@@ -171,12 +171,11 @@ describe('ConfluenceClient', () => {
171
171
  expect(result).toContain('<td><p>Cell 1</p></td>');
172
172
  });
173
173
 
174
- test('should convert links to Confluence link format', () => {
174
+ test('should keep links as standard HTML anchors', () => {
175
175
  const markdown = '[Example Link](https://example.com)';
176
176
  const result = client.markdownToStorage(markdown);
177
177
 
178
- expect(result).toContain('<ac:link>');
179
- expect(result).toContain('ri:value="https://example.com"');
178
+ expect(result).toContain('<a href="https://example.com">');
180
179
  expect(result).toContain('Example Link');
181
180
  });
182
181
  });