Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
f8994cb
feat: add function for mapping doc paragraphs by id
Dec 16, 2025
f605dc4
feat: add function for flattening paragraph text but keep track of po…
Dec 16, 2025
6e1ddaf
feat: add function for calculating text diffs using LCS
Dec 16, 2025
32d4be8
feat: add function for calculating paragraph-level diffing
Dec 16, 2025
0cba4d3
feat: add diffing extension
Dec 17, 2025
60e68fb
test: add diffing tests
Dec 17, 2025
58de494
refactor: switch LCS algorith to Myers for performance
Dec 18, 2025
67016b6
refactor: code structure
Dec 18, 2025
022463f
feat: compute text similarity using Levenshtein distance
Dec 19, 2025
46236f7
feat: identify contiguous text changes as single operation
Dec 22, 2025
89f0e7a
feat: implement logic for diffing paragraph attributes
Dec 23, 2025
30f6d8f
refactor: extract generic sequence diffing helper
Dec 23, 2025
f1cde92
refactor: modify paragraph diffing to reuse generic helper
Dec 23, 2025
ea3e98a
refactor: extract operation reordering function
Dec 23, 2025
c918f10
fix: standardize positions for text diffing
Dec 23, 2025
f71179f
refactor: change text diffing logic to account for formatting
Dec 26, 2025
867f868
refactor: change from "type" to "action"
Dec 26, 2025
74f0fab
feat: support diffing non-textual inline nodes
Dec 26, 2025
58e2aa8
feat: include previous element when building add diff
Dec 29, 2025
ee95c82
docs: add JSDoc to inline diffing
Dec 29, 2025
7ed8605
fix: handle arrays in attributes diff
Dec 29, 2025
370400d
feat: implement generic diffing for all nodes
Dec 29, 2025
cc3c300
refactor: move paragraph utility functions
Dec 29, 2025
cbb747d
feat: use generic diffing for diff computation command
Dec 29, 2025
02adeed
refactor: simplify grouping logic during inline diffing
Dec 29, 2025
57d314a
refactor: convert modules to typescript and improve documentation
Dec 29, 2025
2c34b26
fix: diffing of inline node attributes
Dec 29, 2025
bd11e93
fix: diff positions for modified non-paragraph nodes
Dec 29, 2025
b8a80ba
feat: improve diff comparison for table rows
Dec 29, 2025
77216ba
fix: emit single diff when container node is deleted
Dec 30, 2025
531b22a
fix: compute correct insertion position for first child node
Dec 30, 2025
d7c86c6
fix: remove unused position resolver for inline diffing
Dec 30, 2025
4ae29e8
refactor: remove serialization/deserialization of run attrs during diff
Dec 30, 2025
1021cdc
fix: include node type when extracting content from paragraph
Dec 30, 2025
acb62e4
refactor: include JSON nodes instead of PM nodes in diffs
Dec 30, 2025
174e897
refactor: simplify typescript interfaces
Dec 30, 2025
d3acd76
refactor: extract insertion position calculation logic into helper
Dec 30, 2025
0772fb7
refactor: simplify resolution of inline node positions
Dec 30, 2025
aeb5a18
refactor: remove unecessary exports
Dec 30, 2025
2a247e6
refactor: standardize diff attribute names for modifications
Dec 30, 2025
209769c
docs: add JSDoc to compareDocuments command
Dec 30, 2025
b7fe2ef
feat: add function for diffing marks
Dec 31, 2025
9aa8270
feat: take marks into account during diff computation
Dec 31, 2025
9ab2bb7
refactor: modify computeDiff signature to account for comments diffing
Dec 31, 2025
50aee80
feat: add generic inline content tokenization function
Dec 31, 2025
a8115e9
refactor: use inline content tokenization function for paragraphs
Dec 31, 2025
2132421
feat: implement tokenization of comment data
Dec 31, 2025
b28ca39
refactor: change diffNodes signature to facilitate reuse
Dec 31, 2025
ee1f0d9
feat: allow specifying keys to be ignored when diffing attributes
Dec 31, 2025
761bc95
feat: implement comments diffing hooks
Dec 31, 2025
f5e454e
feat: update compareDocuments command to support diffing comments
Dec 31, 2025
ad9e731
test: move test files to separate directory
Dec 31, 2025
d629191
docs: improve TSDoc comments for interfaces
Dec 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { describe, it, expect } from 'vitest';
import { getAttributesDiff } from './attributes-diffing.ts';

describe('getAttributesDiff', () => {
it('detects nested additions, deletions, and modifications', () => {
const objectA = {
id: 1,
name: 'Alice',
age: 30,
config: {
theme: 'dark',
notifications: true,
additional: {
layout: 'grid',
itemsPerPage: 10,
},
},
};

const objectB = {
id: 1,
name: 'Alice Smith',
config: {
theme: 'light',
additional: {
layout: 'list',
itemsPerPage: 10,
showSidebar: true,
},
},
isActive: true,
};

const diff = getAttributesDiff(objectA, objectB);

expect(diff).toEqual({
added: {
isActive: true,
'config.additional.showSidebar': true,
},
deleted: {
age: 30,
'config.notifications': true,
},
modified: {
name: { from: 'Alice', to: 'Alice Smith' },
'config.theme': { from: 'dark', to: 'light' },
'config.additional.layout': { from: 'grid', to: 'list' },
},
});
});

it('returns empty diff when objects are identical', () => {
const objectA = {
name: 'Same',
config: {
theme: 'dark',
},
};

const diff = getAttributesDiff(objectA, { ...objectA });

expect(diff).toBeNull();
});

it('handles whole-object additions, removals, and non-object replacements', () => {
const objectA = {
profile: {
preferences: {
email: true,
},
},
options: {
advanced: {
mode: 'auto',
},
},
};

const objectB = {
profile: {},
options: {
advanced: 'manual',
},
flags: ['a'],
};

const diff = getAttributesDiff(objectA, objectB);

expect(diff.added).toEqual({
flags: ['a'],
});
expect(diff.deleted).toEqual({
'profile.preferences.email': true,
});
expect(diff.modified).toEqual({
'options.advanced': { from: { mode: 'auto' }, to: 'manual' },
});
});

it('ignores keys defined in the ignored attribute list', () => {
const objectA = {
sdBlockId: '123',
nested: {
sdBlockId: '456',
value: 1,
},
};

const objectB = {
nested: {
sdBlockId: '789',
value: 2,
},
};

const diff = getAttributesDiff(objectA, objectB);

expect(diff.added).toEqual({});
expect(diff.deleted).toEqual({});
expect(diff.modified).toEqual({
'nested.value': { from: 1, to: 2 },
});
});

it('handles array equality and modifications', () => {
const objectA = {
tags: ['alpha', 'beta'],
nested: {
metrics: [
{ name: 'views', value: 10 },
{ name: 'likes', value: 5 },
],
},
};

const objectB = {
tags: ['alpha', 'beta'],
nested: {
metrics: [
{ name: 'views', value: 12 },
{ name: 'likes', value: 5 },
],
},
};

let diff = getAttributesDiff(objectA, objectB);
expect(diff.added).toEqual({});
expect(diff.deleted).toEqual({});
expect(diff.modified).toEqual({
'nested.metrics': {
from: [
{ name: 'views', value: 10 },
{ name: 'likes', value: 5 },
],
to: [
{ name: 'views', value: 12 },
{ name: 'likes', value: 5 },
],
},
});

diff = getAttributesDiff(objectA, { ...objectA });
expect(diff).toBeNull();
});
});
Loading