diff --git a/package.json b/package.json index 20590fcbe..775f3508d 100644 --- a/package.json +++ b/package.json @@ -42,12 +42,14 @@ "@primeng/themes": "^19.0.9", "ace-builds": "^1.42.0", "chart.js": "^4.4.9", + "diff": "^8.0.2", "ngx-markdown-editor": "^5.3.4", "primeflex": "^4.0.0", "primeicons": "^7.0.0", "primeng": "^19.0.9", "rxjs": "~7.8.0", "tslib": "^2.3.0", + "turndown": "^7.2.0", "zone.js": "~0.15.0" }, "devDependencies": { @@ -58,6 +60,7 @@ "@commitlint/config-conventional": "^19.7.1", "@types/jasmine": "~5.1.0", "@types/jest": "^29.5.14", + "@types/turndown": "^5.0.5", "angular-eslint": "19.1.0", "angularx-qrcode": "^19.0.0", "eslint": "^9.20.0", diff --git a/src/app/features/project/wiki/components/compare-section/compare-section.component.html b/src/app/features/project/wiki/components/compare-section/compare-section.component.html index 9351a9279..6a425c080 100644 --- a/src/app/features/project/wiki/components/compare-section/compare-section.component.html +++ b/src/app/features/project/wiki/components/compare-section/compare-section.component.html @@ -19,10 +19,8 @@

{{ 'project.wiki.compare' | translate }}

styleClass="select-version" /> - -

- {{ versionContent() }} -

+ +
} diff --git a/src/app/features/project/wiki/components/compare-section/compare-section.component.ts b/src/app/features/project/wiki/components/compare-section/compare-section.component.ts index b0677e0ed..b11bc130d 100644 --- a/src/app/features/project/wiki/components/compare-section/compare-section.component.ts +++ b/src/app/features/project/wiki/components/compare-section/compare-section.component.ts @@ -9,6 +9,9 @@ import { FormsModule } from '@angular/forms'; import { WikiVersion } from '../../models'; +import * as Diff from 'diff'; +import TurndownService from 'turndown'; + @Component({ selector: 'osf-compare-section', imports: [PanelModule, Select, FormsModule, TranslatePipe, Skeleton], @@ -19,6 +22,7 @@ import { WikiVersion } from '../../models'; export class CompareSectionComponent { versions = input.required(); versionContent = input.required(); + previewContent = input.required(); isLoading = input.required(); selectVersion = output(); @@ -26,7 +30,7 @@ export class CompareSectionComponent { mappedVersions = computed(() => [ ...this.versions().map((version, index) => { - const labelPrefix = index === 0 ? '(Current)' : `(${index})`; + const labelPrefix = index === 0 ? '(Current)' : `(${this.versions().length - index})`; return { label: `${labelPrefix} ${version.createdBy}: (${new Date(version.createdAt).toLocaleString()})`, value: version.id, @@ -34,13 +38,41 @@ export class CompareSectionComponent { }), ]); + content = computed(() => { + const changes = Diff.diffWords( + this.convertHtmlToMarkdown(this.versionContent()), + this.convertHtmlToMarkdown(this.previewContent()) + ); + return changes + .map((change) => { + if (change.added) { + return `${change.value}`; + } else if (change.removed) { + return `${change.value}`; + } + return change.value; + }) + .join(''); + }); + constructor() { effect(() => { - this.versions(); - this.selectedVersion = null; + this.selectedVersion = this.versions()[0].id; + this.selectVersion.emit(this.selectedVersion); }); } - + convertHtmlToMarkdown(html: string): string { + const turndownService = new TurndownService({ + headingStyle: 'atx', + emDelimiter: '*', + strongDelimiter: '**', + hr: '---', + linkStyle: 'inlined', + bulletListMarker: '-', + codeBlockStyle: 'indented', + }); + return turndownService.turndown(html); + } onVersionChange(versionId: string): void { this.selectedVersion = versionId; this.selectVersion.emit(versionId); diff --git a/src/app/features/project/wiki/components/view-section/view-section.component.ts b/src/app/features/project/wiki/components/view-section/view-section.component.ts index d7bafcb95..73f813414 100644 --- a/src/app/features/project/wiki/components/view-section/view-section.component.ts +++ b/src/app/features/project/wiki/components/view-section/view-section.component.ts @@ -38,7 +38,7 @@ export class ViewSectionComponent { mappedVersions = computed(() => [ this.previewOption, ...this.versions().map((version, index) => { - const labelPrefix = index === 0 ? '(Current)' : `(${index})`; + const labelPrefix = index === 0 ? '(Current)' : `(${this.versions().length - index})`; return { label: `${labelPrefix} ${version.createdBy}: (${new Date(version.createdAt).toLocaleString()})`, value: version.id, diff --git a/src/app/features/project/wiki/wiki.component.html b/src/app/features/project/wiki/wiki.component.html index a74076e23..a7ada9fbd 100644 --- a/src/app/features/project/wiki/wiki.component.html +++ b/src/app/features/project/wiki/wiki.component.html @@ -48,6 +48,7 @@ @if (wikiModes().compare) {