confluence-cli 1.34.0 → 2.0.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 CHANGED
@@ -770,6 +770,55 @@ echo "# Hello" | confluence convert --input-format markdown --output-format stor
770
770
  confluence convert -i page.xml -o page.md --input-format storage --output-format markdown
771
771
  ```
772
772
 
773
+ ## Markdown Marker Conventions
774
+
775
+ When converting markdown to Confluence storage format (via `confluence convert`, `create`, or `update`), the following paragraph-level markers produce native Confluence macros. Each marker round-trips back to its markdown form when going storage → markdown.
776
+
777
+ ### Callout macros — `INFO`, `WARNING`, `NOTE`
778
+
779
+ A blockquote whose first line is `**INFO**`, `**WARNING**`, or `**NOTE**` becomes the corresponding Confluence macro:
780
+
781
+ ```markdown
782
+ > **INFO**
783
+ > Heads up — this is an info box.
784
+
785
+ > **WARNING**
786
+ > Watch out for this.
787
+
788
+ > **NOTE**
789
+ > Side note for the reader.
790
+ ```
791
+
792
+ The reverse direction emits the equivalent shorthand (`[!info]` / `[!warning]` / `[!note]` followed by the body), which markdown→storage then re-expands.
793
+
794
+ A blockquote without one of these markers stays a **plain blockquote** (`<blockquote>…</blockquote>`) — `> …` is treated as a quotation, not an alert. Use the markers above when you want a callout.
795
+
796
+ ### `**TOC**` — Table of Contents
797
+
798
+ A paragraph containing only `**TOC**` becomes a Confluence Table of Contents macro using the macro's default heading levels:
799
+
800
+ ```markdown
801
+ **TOC**
802
+ ```
803
+
804
+ ### `**ANCHOR: id**` — anchor
805
+
806
+ A paragraph containing only `**ANCHOR: my-section**` becomes a Confluence anchor macro with the given id:
807
+
808
+ ```markdown
809
+ **ANCHOR: my-section**
810
+ ```
811
+
812
+ ### `[text](#id)` — same-page anchor link
813
+
814
+ A standard markdown link whose href starts with `#` becomes an `ac:link` with `ac:anchor`, rendering as an in-page jump in Confluence:
815
+
816
+ ```markdown
817
+ See [the anchor](#my-section) above.
818
+ ```
819
+
820
+ This works under all three `linkStyle` modes (`smart`, `wiki`, `plain`) — the anchor-link conversion runs before the general `<a href>` handling.
821
+
773
822
  ## Development
774
823
 
775
824
  ```bash
@@ -105,9 +105,10 @@ class MacroConverter {
105
105
  <ac:rich-text-body>${cleanContent}</ac:rich-text-body>
106
106
  </ac:structured-macro>`;
107
107
  } else {
108
- return `<ac:structured-macro ac:name="info">
109
- <ac:rich-text-body>${content}</ac:rich-text-body>
110
- </ac:structured-macro>`;
108
+ // Plain blockquote — `> …` is a quotation, not an alert. Use the
109
+ // `> **INFO**` / `> **WARNING**` / `> **NOTE**` markers above to
110
+ // produce a Confluence info / warning / note macro instead.
111
+ return `<blockquote>${content}</blockquote>`;
111
112
  }
112
113
  });
113
114
 
@@ -261,6 +262,14 @@ class MacroConverter {
261
262
  return `[!note]\n${cleanContent}`;
262
263
  });
263
264
 
265
+ // anchor macro → **ANCHOR: id** marker (round-trip with markdownToStorage).
266
+ // Must run before the generic <ac:structured-macro> catch-all below, which
267
+ // would otherwise drop the anchor entirely.
268
+ markdown = markdown.replace(
269
+ /<ac:structured-macro ac:name="anchor"[^>]*>[\s\S]*?<ac:parameter ac:name="">([\s\S]*?)<\/ac:parameter>[\s\S]*?<\/ac:structured-macro>/g,
270
+ '\n**ANCHOR: $1**\n'
271
+ );
272
+
264
273
  markdown = markdown.replace(/<ac:task-list>([\s\S]*?)<\/ac:task-list>/g, (_, content) => {
265
274
  const tasks = [];
266
275
  const taskRegex = /<ac:task>[\s\S]*?<ac:task-status>([^<]*)<\/ac:task-status>[\s\S]*?<ac:task-body>([\s\S]*?)<\/ac:task-body>[\s\S]*?<\/ac:task>/g;
@@ -317,6 +326,14 @@ class MacroConverter {
317
326
 
318
327
  markdown = markdown.replace(/<ac:structured-macro[^>]*>[\s\S]*?<\/ac:structured-macro>/g, '');
319
328
 
329
+ // ac:link with ac:anchor → [text](#id) (round-trip with markdownToStorage).
330
+ // Must run before the <ac:link[^>]*>…</ac:link> catch-all below, which
331
+ // would otherwise drop the anchor link entirely.
332
+ markdown = markdown.replace(
333
+ /<ac:link ac:anchor="([^"]*)">\s*<ac:plain-text-link-body><!\[CDATA\[([\s\S]*?)\]\]><\/ac:plain-text-link-body>\s*<\/ac:link>/g,
334
+ '[$2](#$1)'
335
+ );
336
+
320
337
  markdown = markdown.replace(/<ac:link><ri:url ri:value="([^"]*)" \/><ac:plain-text-link-body><!\[CDATA\[([^\]]*)\]\]><\/ac:plain-text-link-body><\/ac:link>/g, '[$2]($1)');
321
338
 
322
339
  markdown = markdown.replace(/<ac:link>\s*<ri:page[^>]*ri:content-title="([^"]*)"[^>]*\/>\s*<\/ac:link>/g, '[$1]');
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "confluence-cli",
3
- "version": "1.34.0",
3
+ "version": "2.0.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "confluence-cli",
9
- "version": "1.34.0",
9
+ "version": "2.0.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "axios": "^1.15.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "confluence-cli",
3
- "version": "1.34.0",
3
+ "version": "2.0.0",
4
4
  "description": "A command-line interface for Atlassian Confluence with page creation and editing capabilities",
5
5
  "main": "index.js",
6
6
  "bin": {