confluence-cli 2.3.1 → 2.5.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 +11 -1
- package/bin/confluence.js +147 -4
- package/lib/confluence-client.js +190 -10
- package/lib/html-to-storage.js +3 -2
- package/npm-shrinkwrap.json +6 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -466,7 +466,14 @@ confluence export 123456789 --skip-attachments
|
|
|
466
466
|
|
|
467
467
|
### List Spaces
|
|
468
468
|
```bash
|
|
469
|
+
# Default: up to 500 spaces (paginated automatically across requests)
|
|
469
470
|
confluence spaces
|
|
471
|
+
|
|
472
|
+
# Increase the cap when your tenant has more than 500 spaces
|
|
473
|
+
confluence spaces --limit 2000
|
|
474
|
+
|
|
475
|
+
# Fetch every space, regardless of how many pages it takes
|
|
476
|
+
confluence spaces --all
|
|
470
477
|
```
|
|
471
478
|
|
|
472
479
|
### List Child Pages
|
|
@@ -691,7 +698,7 @@ confluence stats
|
|
|
691
698
|
| `read <pageId_or_url>` | Read page content | `--format <html\|text\|storage\|markdown>` |
|
|
692
699
|
| `info <pageId_or_url>` | Get page information | `--format <text\|json>` |
|
|
693
700
|
| `search <query>` | Search for pages | `--limit <number>` |
|
|
694
|
-
| `spaces` | List available spaces | `--limit <number
|
|
701
|
+
| `spaces` | List available spaces | `--limit <number>`, `--all` |
|
|
695
702
|
| `find <title>` | Find a page by its title | `--space <spaceKey>` |
|
|
696
703
|
| `children <pageId>` | List child pages of a page | `--recursive`, `--max-depth <number>`, `--format <list\|tree\|json>`, `--show-url`, `--show-id` |
|
|
697
704
|
| `create <title> <spaceKey>` | Create a new page or folder | `--content <string>`, `--file <path>`, `--format <storage\|html\|markdown>`, `--type <page\|folder>` |
|
|
@@ -700,6 +707,9 @@ confluence stats
|
|
|
700
707
|
| `update <pageId>` | Update a page's title or content | `--title <string>`, `--content <string>`, `--file <path>`, `--format <storage\|html\|markdown>` |
|
|
701
708
|
| `move <pageId_or_url> <newParentId_or_url>` | Move a page to a new parent location | `--title <string>` |
|
|
702
709
|
| `delete <pageId_or_url>` | Delete a page by ID or URL | `--yes` |
|
|
710
|
+
| `versions <pageId_or_url>` | List historical versions of a page | `--format <text\|json>` |
|
|
711
|
+
| `version-delete <pageId_or_url> <versionNumber>` | Delete a single non-current version of a page | `--yes` |
|
|
712
|
+
| `versions-purge <pageId_or_url>` | Delete every non-current historical version of a page | `--yes`, `--throttle <seconds>` |
|
|
703
713
|
| `edit <pageId>` | Export page content for editing | `--output <file>` |
|
|
704
714
|
| `attachments <pageId_or_url>` | List or download attachments for a page | `--limit <number>`, `--pattern <glob>`, `--download`, `--dest <directory>` |
|
|
705
715
|
| `attachment-upload <pageId_or_url>` | Upload attachments to a page | `--file <path>`, `--comment <text>`, `--replace`, `--minor-edit` |
|
package/bin/confluence.js
CHANGED
|
@@ -154,15 +154,17 @@ program
|
|
|
154
154
|
program
|
|
155
155
|
.command('spaces')
|
|
156
156
|
.description('List Confluence spaces')
|
|
157
|
-
.option('-l, --limit <limit>', '
|
|
157
|
+
.option('-l, --limit <limit>', 'Maximum total spaces to return across paginated requests', '500')
|
|
158
|
+
.option('--all', 'Fetch every space, paginating through all results (overrides --limit)')
|
|
158
159
|
.action(async (options) => {
|
|
159
160
|
const analytics = new Analytics();
|
|
160
161
|
try {
|
|
161
162
|
const config = getConfig(getProfileName());
|
|
162
163
|
const client = new ConfluenceClient(config);
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
const maxResults = options.all ? null : parseInt(options.limit);
|
|
165
|
+
const spaces = await client.getSpaces(maxResults);
|
|
166
|
+
|
|
167
|
+
console.log(chalk.blue(`Available spaces (${spaces.length}):`));
|
|
166
168
|
spaces.forEach(space => {
|
|
167
169
|
console.log(`${chalk.green(space.key)} - ${space.name}`);
|
|
168
170
|
});
|
|
@@ -451,6 +453,147 @@ program
|
|
|
451
453
|
}
|
|
452
454
|
});
|
|
453
455
|
|
|
456
|
+
// List historical versions of a page
|
|
457
|
+
program
|
|
458
|
+
.command('versions <pageId>')
|
|
459
|
+
.description('List historical versions of a Confluence page')
|
|
460
|
+
.option('--format <format>', 'Output format: text or json (default: text)', 'text')
|
|
461
|
+
.action(async (pageId, options) => {
|
|
462
|
+
const analytics = new Analytics();
|
|
463
|
+
try {
|
|
464
|
+
const config = getConfig(getProfileName());
|
|
465
|
+
const client = new ConfluenceClient(config);
|
|
466
|
+
const resolvedId = String(await client.extractPageId(pageId));
|
|
467
|
+
const versions = await client.listVersions(resolvedId);
|
|
468
|
+
|
|
469
|
+
if (options.format === 'json') {
|
|
470
|
+
console.log(JSON.stringify({ pageId: resolvedId, versions }, null, 2));
|
|
471
|
+
} else {
|
|
472
|
+
const max = versions.length ? Math.max(...versions.map(v => v.number)) : 0;
|
|
473
|
+
console.log(chalk.blue(`Versions for page ${resolvedId} (${versions.length} total):`));
|
|
474
|
+
if (versions.length === 0) {
|
|
475
|
+
console.log(chalk.yellow(' (no versions returned)'));
|
|
476
|
+
}
|
|
477
|
+
for (const v of versions) {
|
|
478
|
+
const tag = v.number === max ? chalk.green(' [current]') : '';
|
|
479
|
+
const author = v.by || 'unknown';
|
|
480
|
+
const note = v.message ? ` — ${v.message}` : '';
|
|
481
|
+
console.log(` v${v.number}${tag} ${v.when} ${author}${note}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
analytics.track('versions', true);
|
|
485
|
+
} catch (error) {
|
|
486
|
+
handleCommandError(analytics, 'versions', error);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
// Delete a single historical version of a page
|
|
491
|
+
program
|
|
492
|
+
.command('version-delete <pageId> <versionNumber>')
|
|
493
|
+
.description('Delete a single historical version of a page (cannot delete the current version)')
|
|
494
|
+
.option('-y, --yes', 'Skip confirmation prompt')
|
|
495
|
+
.action(async (pageId, versionNumber, options) => {
|
|
496
|
+
const analytics = new Analytics();
|
|
497
|
+
try {
|
|
498
|
+
const config = getConfig(getProfileName());
|
|
499
|
+
assertWritable(config);
|
|
500
|
+
const client = new ConfluenceClient(config);
|
|
501
|
+
const resolvedId = String(await client.extractPageId(pageId));
|
|
502
|
+
const n = Number(versionNumber);
|
|
503
|
+
|
|
504
|
+
if (!options.yes) {
|
|
505
|
+
const { confirmed } = await inquirer.prompt([{
|
|
506
|
+
type: 'confirm',
|
|
507
|
+
name: 'confirmed',
|
|
508
|
+
default: false,
|
|
509
|
+
message: `Delete v${n} of page ${resolvedId}? This cannot be undone.`
|
|
510
|
+
}]);
|
|
511
|
+
if (!confirmed) {
|
|
512
|
+
console.log(chalk.yellow('Cancelled.'));
|
|
513
|
+
analytics.track('version_delete_cancel', true);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const result = await client.deleteVersion(resolvedId, n);
|
|
519
|
+
const note = result.viaExperimental ? chalk.yellow(' (via experimental endpoint)') : '';
|
|
520
|
+
console.log(chalk.green(`✅ Deleted v${result.versionNumber} of page ${result.id}${note}`));
|
|
521
|
+
analytics.track('version_delete', true);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
handleCommandError(analytics, 'version_delete', error);
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
// Convenience: delete every non-current historical version of a page,
|
|
528
|
+
// keeping only the current one.
|
|
529
|
+
program
|
|
530
|
+
.command('versions-purge <pageId>')
|
|
531
|
+
.description('Delete every non-current historical version of a page (keeps only current)')
|
|
532
|
+
.option('-y, --yes', 'Skip confirmation prompt')
|
|
533
|
+
.option('--throttle <seconds>', 'Sleep between version-delete calls', '0')
|
|
534
|
+
.action(async (pageId, options) => {
|
|
535
|
+
const analytics = new Analytics();
|
|
536
|
+
try {
|
|
537
|
+
const config = getConfig(getProfileName());
|
|
538
|
+
assertWritable(config);
|
|
539
|
+
const client = new ConfluenceClient(config);
|
|
540
|
+
const resolvedId = String(await client.extractPageId(pageId));
|
|
541
|
+
const versions = await client.listVersions(resolvedId);
|
|
542
|
+
|
|
543
|
+
if (versions.length === 0) {
|
|
544
|
+
console.log(chalk.yellow(`No versions returned for page ${resolvedId}.`));
|
|
545
|
+
analytics.track('versions_purge', true);
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
const max = Math.max(...versions.map(v => v.number));
|
|
549
|
+
const historicalCount = versions.filter(v => v.number !== max).length;
|
|
550
|
+
if (historicalCount === 0) {
|
|
551
|
+
console.log(chalk.yellow(`Only current version v${max} exists for page ${resolvedId}; nothing to purge.`));
|
|
552
|
+
analytics.track('versions_purge', true);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (!options.yes) {
|
|
557
|
+
const { confirmed } = await inquirer.prompt([{
|
|
558
|
+
type: 'confirm',
|
|
559
|
+
name: 'confirmed',
|
|
560
|
+
default: false,
|
|
561
|
+
message: `Delete ${historicalCount} historical version(s) of page ${resolvedId}? Current version (v${max}) will be kept.`
|
|
562
|
+
}]);
|
|
563
|
+
if (!confirmed) {
|
|
564
|
+
console.log(chalk.yellow('Cancelled.'));
|
|
565
|
+
analytics.track('versions_purge_cancel', true);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const throttleMs = Math.max(0, parseFloat(options.throttle || '0')) * 1000;
|
|
571
|
+
const result = await client.purgeNonCurrentVersions(resolvedId, {
|
|
572
|
+
onProgress: async (event) => {
|
|
573
|
+
if (event.kind === 'deleted') {
|
|
574
|
+
const note = event.viaExperimental ? chalk.yellow(' (experimental)') : '';
|
|
575
|
+
console.log(chalk.green(` ✓ deleted v${event.versionNumber}${note}`));
|
|
576
|
+
} else if (event.kind === 'failed') {
|
|
577
|
+
console.log(chalk.red(` ✗ v${event.versionNumber}: ${event.message}`));
|
|
578
|
+
}
|
|
579
|
+
if (throttleMs > 0) {
|
|
580
|
+
await new Promise(r => setTimeout(r, throttleMs));
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
console.log('');
|
|
586
|
+
console.log(chalk.green(`✅ Purge complete for page ${result.id}: ` +
|
|
587
|
+
`${result.deleted} deleted, ${result.failed} failed, kept v${result.kept}.`));
|
|
588
|
+
analytics.track('versions_purge', result.failed === 0);
|
|
589
|
+
if (result.failed > 0) {
|
|
590
|
+
process.exitCode = 1;
|
|
591
|
+
}
|
|
592
|
+
} catch (error) {
|
|
593
|
+
handleCommandError(analytics, 'versions_purge', error);
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
|
|
454
597
|
// Edit command - opens page content for editing
|
|
455
598
|
program
|
|
456
599
|
.command('edit <pageId>')
|
package/lib/confluence-client.js
CHANGED
|
@@ -437,20 +437,58 @@ class ConfluenceClient {
|
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
/**
|
|
440
|
-
*
|
|
440
|
+
* List a single page of spaces with pagination metadata
|
|
441
441
|
*/
|
|
442
|
-
async
|
|
442
|
+
async listSpaces(options = {}) {
|
|
443
|
+
const limit = this.parsePositiveInt(options.limit, 500);
|
|
444
|
+
const start = this.parsePositiveInt(options.start, 0);
|
|
445
|
+
|
|
443
446
|
const response = await this.client.get('/space', {
|
|
444
|
-
params: {
|
|
445
|
-
limit
|
|
446
|
-
}
|
|
447
|
+
params: { limit, start }
|
|
447
448
|
});
|
|
448
449
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
450
|
+
const results = Array.isArray(response.data?.results)
|
|
451
|
+
? response.data.results.map(space => ({
|
|
452
|
+
key: space.key,
|
|
453
|
+
name: space.name,
|
|
454
|
+
type: space.type
|
|
455
|
+
}))
|
|
456
|
+
: [];
|
|
457
|
+
|
|
458
|
+
return {
|
|
459
|
+
results,
|
|
460
|
+
nextStart: this.parseNextStart(response.data?._links?.next)
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Get spaces, paginating through results until maxResults is reached or
|
|
466
|
+
* the server stops returning a `_links.next`. Pass `null` to fetch every space.
|
|
467
|
+
*/
|
|
468
|
+
async getSpaces(maxResults = 500, options = {}) {
|
|
469
|
+
const cap = maxResults === null || maxResults === undefined
|
|
470
|
+
? null
|
|
471
|
+
: this.parsePositiveInt(maxResults, 500);
|
|
472
|
+
const pageSize = this.parsePositiveInt(options.pageSize, 500);
|
|
473
|
+
let start = this.parsePositiveInt(options.start, 0);
|
|
474
|
+
const spaces = [];
|
|
475
|
+
|
|
476
|
+
let hasNext = true;
|
|
477
|
+
while (hasNext) {
|
|
478
|
+
if (cap !== null && spaces.length >= cap) break;
|
|
479
|
+
const requestLimit = cap === null
|
|
480
|
+
? pageSize
|
|
481
|
+
: Math.min(pageSize, cap - spaces.length);
|
|
482
|
+
const page = await this.listSpaces({ limit: requestLimit, start });
|
|
483
|
+
spaces.push(...page.results);
|
|
484
|
+
|
|
485
|
+
hasNext = page.nextStart !== null && page.nextStart !== undefined;
|
|
486
|
+
if (hasNext) {
|
|
487
|
+
start = page.nextStart;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return cap !== null ? spaces.slice(0, cap) : spaces;
|
|
454
492
|
}
|
|
455
493
|
|
|
456
494
|
/**
|
|
@@ -1405,6 +1443,148 @@ class ConfluenceClient {
|
|
|
1405
1443
|
return { id: String(pageId) };
|
|
1406
1444
|
}
|
|
1407
1445
|
|
|
1446
|
+
/**
|
|
1447
|
+
* Build the absolute URL for the experimental version endpoint.
|
|
1448
|
+
* Confluence Server/Data Center exposes content versions only at
|
|
1449
|
+
* /rest/experimental/ (the modern /rest/api/.../version path 404s
|
|
1450
|
+
* there). Cloud accepts both. We use this as a fallback when the
|
|
1451
|
+
* configured apiPath returns 404/405.
|
|
1452
|
+
*/
|
|
1453
|
+
experimentalVersionUrl(pageId, versionNumber = null) {
|
|
1454
|
+
const base = `${this.protocol}://${this.domain}${this.webUrlPrefix}/rest/experimental/content/${pageId}/version`;
|
|
1455
|
+
return versionNumber == null ? base : `${base}/${versionNumber}`;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* List historical versions of a page. Returns an array sorted by
|
|
1460
|
+
* version number ascending. Each entry has: number, when, by,
|
|
1461
|
+
* minorEdit, message.
|
|
1462
|
+
*
|
|
1463
|
+
* Pages with many versions (e.g. heavily edited or repeatedly
|
|
1464
|
+
* uploaded) may exceed a single page of results, so this paginates
|
|
1465
|
+
* via start/limit until all versions are collected.
|
|
1466
|
+
*
|
|
1467
|
+
* Path strategy: try the configured /rest/api/ path first; on 404
|
|
1468
|
+
* or 405 (typical of Server/DC where the version endpoints live
|
|
1469
|
+
* under /rest/experimental/), fall back transparently. Subsequent
|
|
1470
|
+
* pages use whichever path succeeded so we don't double the
|
|
1471
|
+
* round-trip count on long histories.
|
|
1472
|
+
*/
|
|
1473
|
+
async listVersions(pageIdOrUrl) {
|
|
1474
|
+
const pageId = await this.extractPageId(pageIdOrUrl);
|
|
1475
|
+
const limit = 200;
|
|
1476
|
+
let start = 0;
|
|
1477
|
+
let useExperimental = false;
|
|
1478
|
+
const all = [];
|
|
1479
|
+
while (true) {
|
|
1480
|
+
let response;
|
|
1481
|
+
try {
|
|
1482
|
+
const url = useExperimental
|
|
1483
|
+
? this.experimentalVersionUrl(pageId)
|
|
1484
|
+
: `/content/${pageId}/version`;
|
|
1485
|
+
response = await this.client.get(url, { params: { start, limit } });
|
|
1486
|
+
} catch (error) {
|
|
1487
|
+
const status = error.response && error.response.status;
|
|
1488
|
+
if (!useExperimental && (status === 404 || status === 405)) {
|
|
1489
|
+
useExperimental = true;
|
|
1490
|
+
continue;
|
|
1491
|
+
}
|
|
1492
|
+
throw error;
|
|
1493
|
+
}
|
|
1494
|
+
const results = response.data.results || [];
|
|
1495
|
+
all.push(...results);
|
|
1496
|
+
if (results.length < limit) {
|
|
1497
|
+
break;
|
|
1498
|
+
}
|
|
1499
|
+
start += limit;
|
|
1500
|
+
}
|
|
1501
|
+
return all.map(v => ({
|
|
1502
|
+
number: v.number,
|
|
1503
|
+
when: v.when,
|
|
1504
|
+
by: v.by ? (v.by.displayName || v.by.publicName || v.by.email || null) : null,
|
|
1505
|
+
minorEdit: v.minorEdit === true,
|
|
1506
|
+
message: v.message || ''
|
|
1507
|
+
})).sort((a, b) => a.number - b.number);
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Delete a single historical version of a page.
|
|
1512
|
+
*
|
|
1513
|
+
* Confluence refuses to delete the current version (returns 400).
|
|
1514
|
+
* The "rolled up into the next version" wording in Atlassian's
|
|
1515
|
+
* docs refers to the diff representation; the deleted version's
|
|
1516
|
+
* snapshot is removed from page history.
|
|
1517
|
+
*
|
|
1518
|
+
* Server/DC instances expose this only at /rest/experimental/, so
|
|
1519
|
+
* a 404 or 405 on the configured /rest/api/ path triggers a
|
|
1520
|
+
* one-shot retry against the experimental URL.
|
|
1521
|
+
*/
|
|
1522
|
+
async deleteVersion(pageIdOrUrl, versionNumber) {
|
|
1523
|
+
const pageId = await this.extractPageId(pageIdOrUrl);
|
|
1524
|
+
const n = Number(versionNumber);
|
|
1525
|
+
if (!Number.isInteger(n) || n < 1) {
|
|
1526
|
+
throw new Error(`versionNumber must be a positive integer, got: ${versionNumber}`);
|
|
1527
|
+
}
|
|
1528
|
+
try {
|
|
1529
|
+
await this.client.delete(`/content/${pageId}/version/${n}`);
|
|
1530
|
+
return { id: String(pageId), versionNumber: n, viaExperimental: false };
|
|
1531
|
+
} catch (error) {
|
|
1532
|
+
const status = error.response && error.response.status;
|
|
1533
|
+
if (status !== 404 && status !== 405) {
|
|
1534
|
+
throw error;
|
|
1535
|
+
}
|
|
1536
|
+
await this.client.delete(this.experimentalVersionUrl(pageId, n));
|
|
1537
|
+
return { id: String(pageId), versionNumber: n, viaExperimental: true };
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
/**
|
|
1542
|
+
* Delete every non-current version of a page. Used to purge the
|
|
1543
|
+
* historical content snapshots that may still hold a leaked secret
|
|
1544
|
+
* even after the current version has been overwritten with a
|
|
1545
|
+
* redacted copy.
|
|
1546
|
+
*
|
|
1547
|
+
* Returns { id, kept, deleted, failed } where `kept` is the version
|
|
1548
|
+
* number that survived (the current one) and `deleted`/`failed` are
|
|
1549
|
+
* the counts of historical versions removed/errored.
|
|
1550
|
+
*/
|
|
1551
|
+
async purgeNonCurrentVersions(pageIdOrUrl, options = {}) {
|
|
1552
|
+
const onProgress = typeof options.onProgress === 'function' ? options.onProgress : () => {};
|
|
1553
|
+
const pageId = String(await this.extractPageId(pageIdOrUrl));
|
|
1554
|
+
const versions = await this.listVersions(pageId);
|
|
1555
|
+
|
|
1556
|
+
if (versions.length === 0) {
|
|
1557
|
+
return { id: pageId, kept: null, deleted: 0, failed: 0, errors: [] };
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
const max = Math.max(...versions.map(v => v.number));
|
|
1561
|
+
// Delete in descending order. Some Confluence builds renumber
|
|
1562
|
+
// historical versions when an earlier one is removed; deleting
|
|
1563
|
+
// newest-first sidesteps the resulting off-by-one drift.
|
|
1564
|
+
const toDelete = versions
|
|
1565
|
+
.filter(v => v.number !== max)
|
|
1566
|
+
.map(v => v.number)
|
|
1567
|
+
.sort((a, b) => b - a);
|
|
1568
|
+
|
|
1569
|
+
let deleted = 0;
|
|
1570
|
+
const errors = [];
|
|
1571
|
+
for (const n of toDelete) {
|
|
1572
|
+
try {
|
|
1573
|
+
const res = await this.deleteVersion(pageId, n);
|
|
1574
|
+
deleted += 1;
|
|
1575
|
+
onProgress({ kind: 'deleted', versionNumber: n, viaExperimental: res.viaExperimental });
|
|
1576
|
+
} catch (error) {
|
|
1577
|
+
const detail = error.response
|
|
1578
|
+
? `HTTP ${error.response.status} ${error.response.statusText || ''}`.trim()
|
|
1579
|
+
: error.message;
|
|
1580
|
+
errors.push({ versionNumber: n, message: detail });
|
|
1581
|
+
onProgress({ kind: 'failed', versionNumber: n, message: detail });
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
return { id: pageId, kept: max, deleted, failed: errors.length, errors };
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1408
1588
|
/**
|
|
1409
1589
|
* Search for a page by title and space
|
|
1410
1590
|
*/
|
package/lib/html-to-storage.js
CHANGED
|
@@ -344,10 +344,11 @@ function dispatchTag(node, ctx) {
|
|
|
344
344
|
return `<img${renderAttrs(node.attribs)}>`;
|
|
345
345
|
case 'ul':
|
|
346
346
|
case 'ol':
|
|
347
|
-
return `<${node.name}>${walkChildren(node, ctx)}</${node.name}>`;
|
|
347
|
+
return `<${node.name}${renderAttrs(node.attribs)}>${walkChildren(node, ctx)}</${node.name}>`;
|
|
348
348
|
case 'li': {
|
|
349
349
|
const inner = walkChildren(node, ctx);
|
|
350
|
-
|
|
350
|
+
const open = `<li${renderAttrs(node.attribs)}>`;
|
|
351
|
+
return shouldWrapInP(node) ? `${open}<p>${inner}</p></li>` : `${open}${inner}</li>`;
|
|
351
352
|
}
|
|
352
353
|
case 'pre':
|
|
353
354
|
return convertCodeBlock(node, ctx);
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "confluence-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "confluence-cli",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.5.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"axios": "
|
|
12
|
+
"axios": "~1.15.2",
|
|
13
13
|
"chalk": "^4.1.2",
|
|
14
14
|
"commander": "^11.1.0",
|
|
15
15
|
"entities": "^4.5.0",
|
|
@@ -129,9 +129,9 @@
|
|
|
129
129
|
"license": "MIT"
|
|
130
130
|
},
|
|
131
131
|
"node_modules/axios": {
|
|
132
|
-
"version": "1.15.
|
|
133
|
-
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.
|
|
134
|
-
"integrity": "sha512-
|
|
132
|
+
"version": "1.15.2",
|
|
133
|
+
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz",
|
|
134
|
+
"integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==",
|
|
135
135
|
"license": "MIT",
|
|
136
136
|
"dependencies": {
|
|
137
137
|
"follow-redirects": "^1.15.11",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "confluence-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.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": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"author": "pchuri",
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"axios": "
|
|
26
|
+
"axios": "~1.15.2",
|
|
27
27
|
"chalk": "^4.1.2",
|
|
28
28
|
"commander": "^11.1.0",
|
|
29
29
|
"entities": "^4.5.0",
|