Skip to content

Commit c7636de

Browse files
author
Allen Manning
authored
Merge pull request #4090 from quarto-dev/bug/link-resolve-create
Confluence: 2-Pass update for link resolution in Confluence
2 parents f819584 + 210bccb commit c7636de

File tree

3 files changed

+522
-87
lines changed

3 files changed

+522
-87
lines changed

src/publish/confluence/confluence-helper.ts

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ export const buildContentUpdate = (
260260
parent?: string,
261261
status: ContentStatusEnum = ContentStatusEnum.current,
262262
type: string = PAGE_TYPE,
263-
version: ContentVersion | null = null
263+
version: ContentVersion | null = null,
264+
ancestors: ContentAncestor[] | null = null
264265
): ContentUpdate => {
265266
return {
266267
contentChangeType: ContentChangeType.update,
@@ -269,7 +270,7 @@ export const buildContentUpdate = (
269270
title,
270271
type,
271272
status,
272-
ancestors: parent ? [{ id: parent }] : null,
273+
ancestors: parent ? [{ id: parent }] : ancestors,
273274
body,
274275
fileName,
275276
};
@@ -474,11 +475,20 @@ export const buildSpaceChanges = (
474475
return spaceChanges;
475476
};
476477

478+
export const replaceExtension = (
479+
fileName: string,
480+
oldExtension: string,
481+
newExtension: string
482+
) => {
483+
return fileName.replace(oldExtension, newExtension);
484+
};
485+
477486
export const getTitle = (
478487
fileName: string,
479488
metadataByInput: Record<string, InputMetadata>
480489
): string => {
481-
const qmdFileName = fileName.replace(".xml", ".qmd");
490+
const qmdFileName = replaceExtension(fileName, ".xml", ".qmd");
491+
482492
const metadataTitle = metadataByInput[qmdFileName]?.title;
483493

484494
const titleFromFilename = capitalizeWord(fileName.split(".")[0] ?? fileName);
@@ -540,12 +550,17 @@ export const updateLinks = (
540550
spaceChanges: ConfluenceSpaceChange[],
541551
server: string,
542552
parent: ConfluenceParent
543-
): ConfluenceSpaceChange[] => {
553+
): {
554+
pass1Changes: ConfluenceSpaceChange[];
555+
pass2Changes: ConfluenceSpaceChange[];
556+
} => {
544557
const root = `${server}`;
545558
const url = `${ensureTrailingSlash(server)}wiki/spaces/${
546559
parent.space
547560
}/pages/`;
548561

562+
let collectedPass2Changes: ConfluenceSpaceChange[] = [];
563+
549564
const changeMapper = (
550565
changeToProcess: ConfluenceSpaceChange
551566
): ConfluenceSpaceChange => {
@@ -597,7 +612,9 @@ export const updateLinks = (
597612

598613
updated = updated.replace(linkFullFileName, pagePath);
599614
} else {
600-
console.warn(`Link not found for ${siteFilePath}`);
615+
if (!collectedPass2Changes.includes(changeToProcess)) {
616+
collectedPass2Changes = [...collectedPass2Changes, changeToProcess];
617+
}
601618
}
602619

603620
return updated;
@@ -621,7 +638,66 @@ export const updateLinks = (
621638
const updatedChanges: ConfluenceSpaceChange[] =
622639
spaceChanges.map(changeMapper);
623640

624-
return updatedChanges;
641+
return { pass1Changes: updatedChanges, pass2Changes: collectedPass2Changes };
642+
};
643+
644+
export const convertForSecondPass = (
645+
fileMetadataTable: Record<string, SitePage>,
646+
spaceChanges: ConfluenceSpaceChange[],
647+
server: string,
648+
parent: ConfluenceParent
649+
): ConfluenceSpaceChange[] => {
650+
const toUpdatesReducer = (
651+
accumulator: ConfluenceSpaceChange[],
652+
change: ConfluenceSpaceChange
653+
) => {
654+
if (isContentUpdate(change)) {
655+
accumulator = [...accumulator, change];
656+
}
657+
658+
if (isContentCreate(change)) {
659+
console.log(
660+
"basename(change?.fileName?)",
661+
basename(change?.fileName ?? "")
662+
);
663+
const qmdFileName = replaceExtension(
664+
change.fileName ?? "",
665+
".xml",
666+
".qmd"
667+
);
668+
const updateId = fileMetadataTable[qmdFileName]?.id;
669+
670+
if (updateId) {
671+
const convertedUpdate = buildContentUpdate(
672+
updateId,
673+
change.title,
674+
change.body,
675+
change.fileName ?? "",
676+
"",
677+
ContentStatusEnum.current,
678+
PAGE_TYPE,
679+
null,
680+
change.ancestors
681+
);
682+
accumulator = [...accumulator, convertedUpdate];
683+
} else {
684+
console.warn("update ID not found for", change.fileName);
685+
}
686+
}
687+
688+
return accumulator;
689+
};
690+
691+
const changesAsUpdates = spaceChanges.reduce(toUpdatesReducer, []);
692+
693+
const updateLinkResults = updateLinks(
694+
fileMetadataTable,
695+
changesAsUpdates,
696+
server,
697+
parent
698+
);
699+
700+
return updateLinkResults.pass1Changes;
625701
};
626702

627703
export const updateImagePaths = (body: ContentBody): ContentBody => {

src/publish/confluence/confluence.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import {
5151
buildPublishRecordForContent,
5252
buildSpaceChanges,
5353
confluenceParentFromString,
54+
convertForSecondPass,
5455
doWithSpinner,
5556
filterFilesForUpdate,
5657
findAttachments,
@@ -349,7 +350,8 @@ async function publish(
349350
id: string,
350351
body: ContentBody,
351352
titleToUpdate: string = title,
352-
fileName: string = ""
353+
fileName: string = "",
354+
uploadFileAttachments: boolean = true
353355
): Promise<Content> => {
354356
const previousPage = await client.getContent(id);
355357

@@ -380,7 +382,7 @@ async function publish(
380382

381383
const updatedContent: Content = await client.updateContent(toUpdate);
382384

383-
if (toUpdate.id) {
385+
if (toUpdate.id && uploadFileAttachments) {
384386
const existingAttachments: AttachmentSummary[] =
385387
await client.getAttachments(toUpdate.id);
386388

@@ -571,7 +573,7 @@ async function publish(
571573
parent: parentId,
572574
};
573575

574-
const existingSite: SitePage[] = await fetchExistingSite(parentId);
576+
let existingSite: SitePage[] = await fetchExistingSite(parentId);
575577

576578
const publishFiles: PublishFiles = await renderSite(render);
577579
const metadataByInput: Record<string, InputMetadata> =
@@ -620,7 +622,7 @@ async function publish(
620622

621623
trace("fileMetadata", fileMetadata);
622624

623-
const metadataByFilename = buildFileToMetaTable(existingSite);
625+
let metadataByFilename = buildFileToMetaTable(existingSite);
624626

625627
trace("metadataByFilename", metadataByFilename);
626628

@@ -631,18 +633,23 @@ async function publish(
631633
existingSite
632634
);
633635

634-
changeList = updateLinks(
636+
const { pass1Changes, pass2Changes } = updateLinks(
635637
metadataByFilename,
636638
changeList,
637639
server,
638640
siteParent
639641
);
640642

641-
trace("changelist", changeList);
643+
changeList = pass1Changes;
644+
645+
trace("changelist Pass 1", changeList);
642646

643647
let pathsToId: Record<string, string> = {}; // build from existing site
644648

645-
const doChange = async (change: ConfluenceSpaceChange) => {
649+
const doChange = async (
650+
change: ConfluenceSpaceChange,
651+
uploadFileAttachments: boolean = true
652+
) => {
646653
if (isContentCreate(change)) {
647654
let ancestorId =
648655
(change?.ancestors && change?.ancestors[0]?.id) ?? null;
@@ -684,7 +691,8 @@ async function publish(
684691
update.id ?? "",
685692
update.body,
686693
update.title ?? "",
687-
update.fileName ?? ""
694+
update.fileName ?? "",
695+
uploadFileAttachments
688696
);
689697
} else if (isContentDelete(change)) {
690698
if (DELETE_DISABLED) {
@@ -704,8 +712,27 @@ async function publish(
704712
await doChange(currentChange);
705713
}
706714

707-
const parentPage: Content = await client.getContent(parentId);
715+
if (pass2Changes.length) {
716+
//PASS #2 to update links to newly created pages
717+
718+
trace("changelist Pass 2", pass2Changes);
719+
720+
existingSite = await fetchExistingSite(parentId);
721+
metadataByFilename = buildFileToMetaTable(existingSite);
722+
723+
const linkUpdateChanges: ConfluenceSpaceChange[] = convertForSecondPass(
724+
metadataByFilename,
725+
pass2Changes,
726+
server,
727+
parent
728+
);
708729

730+
for (let currentChange of linkUpdateChanges) {
731+
await doChange(currentChange, false);
732+
}
733+
}
734+
735+
const parentPage: Content = await client.getContent(parentId);
709736
return buildPublishRecordForContent(server, parentPage);
710737
};
711738

0 commit comments

Comments
 (0)