Skip to content

Commit

Permalink
Add new model methods for inserting/removing data by index (#84)
Browse files Browse the repository at this point in the history
* fix tests

* use new method in the model

* add ci for collab manager

* lint fixes

* add getters for the index

* fix tests

* move methods to the document

* lint

* use helpers

* add tests

* Introduce DI & migrate tools builders (#80)

* Introduce DI & migrate tools builders

* Fixes after review

* 'Fix' lint

* Add unsaved files

* Fix comments

* Remove log & add docs

* Update packages/core/src/entities/UnifiedToolConfig.ts

Co-authored-by: Peter <[email protected]>

* Fixes after review

---------

Co-authored-by: Peter <[email protected]>

* Add BlockManager and EditorUI classes (#85)

* Add BlockManager and EditorUI classes

* Add JSDocs

* Add try catch for block.render() call

* feat(core): inputs content rendering (#86)

* passing formattingadapter to blocktooladapter

* lint

* Update BlockManager.ts

* Update BlockManager.ts

* Update App.vue

* Add Toolbox & ToolboxUI (#88)

* Add Toolbox & ToolboxUI

* Add comments

* Update tests for the model package

* Fix lint

* feat(dom-adapters): Inline tool adapter check for tool required data (#87)

* Implmenet global CaretAdapter

* Handle native inputs

* Pass input type to Input component props

* Use class to represent index

* Fix lint in dom-adapters

* fix linter

* added inline tool adapter

* implement model updates

* lint fix

* fix index

* adapter renders inline tools

* lint fix and clean up

* jsdoc

* clean up

* jsdoc

* jsdoc

* surround content replaced

* suggestions

* lint fix

* jsdoc

* added bold and italic inline tools into core package

* naming

* naming

* added inline toolbar and inlineToolAdapter init into core

* update packages and lock

* build fix

* implement inline tool adapter to core

- fully implement current realization of inline tool adapter to core
- remove from the playground

* clean up

* jsdoc and naming improvements

* naming

* naming

* renaming

* fix hardcoded

* tools are initialized inside of the inline toolbar initialization

* fixed inline tool attaching

* jsdoc

* naming fix

* fixed imports

* lint fix

* try build fix

* install dependencies

* add sdk package

* fix build for core

* change package name in actions

* add references

* typo

* fix build

* added inline tool data former

* fix lint

* rm unwanted changes

* lint fix

* fixed build

* docs improved

* fix build

* naming improved

* Update packages/core/src/ui/InlineToolbar/index.ts

Co-authored-by: Peter <[email protected]>

* Update packages/dom-adapters/src/FormattingAdapter/index.ts

Co-authored-by: Peter <[email protected]>

* rm unwanted change

* naming

* separated renderToolActions and apply method in formatting adapter

* naming

* moved surround to utils

* lint fix

* last naming fix 🤞

* made renderToolActions method private

---------

Co-authored-by: George Berezhnoy <[email protected]>
Co-authored-by: George Berezhnoy <[email protected]>
Co-authored-by: Peter <[email protected]>

* fix linter

---------

Co-authored-by: George Berezhnoy <[email protected]>
Co-authored-by: Peter <[email protected]>
Co-authored-by: e11sy <[email protected]>
Co-authored-by: George Berezhnoy <[email protected]>
  • Loading branch information
5 people authored Aug 30, 2024
1 parent 20f2ef7 commit efcfe22
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 2 deletions.
4 changes: 2 additions & 2 deletions packages/collaboration-manager/src/CollaborationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ export class CollaborationManager {

switch (operation.type) {
case OperationType.Insert:
this.#model.insertText(blockIndex, dataKey, operation.data.newValue, textRange[0]);
this.#model.insertData(operation.index, operation.data.newValue);
break;
case OperationType.Delete:
this.#model.removeText(blockIndex, dataKey, textRange[0], textRange[1]);
this.#model.removeData(operation.index);
break;
case OperationType.Modify:
console.log('modify operation is not implemented yet');

Check warning on line 95 in packages/collaboration-manager/src/CollaborationManager.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
Expand Down
2 changes: 2 additions & 0 deletions packages/model/src/EditorJSModel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ describe('EditorJSModel', () => {
'initializeDocument',
'setProperty',
'addBlock',
'insertData',
'removeData',
'updateTuneData',
'updateValue',
'removeBlock',
Expand Down
20 changes: 20 additions & 0 deletions packages/model/src/EditorJSModel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Stryker disable all -- we don't count mutation test coverage fot this file as it just proxy calls to EditorDocument
/* istanbul ignore file -- we don't count test coverage fot this file as it just proxy calls to EditorDocument */
import type { Index } from './entities/index.js';
import { type BlockNodeSerialized, EditorDocument } from './entities/index.js';
import { EventBus, EventType } from './EventBus/index.js';
import type { ModelEvents, CaretManagerCaretUpdatedEvent, CaretManagerEvents } from './EventBus/index.js';
Expand Down Expand Up @@ -188,6 +189,25 @@ export class EditorJSModel extends EventBus {
return this.#document.removeBlock(...parameters);

Check warning on line 189 in packages/model/src/EditorJSModel.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

/**
* Inserts data to the specified index
*
* @param index - index to insert data
* @param data - data to insert
*/
public insertData(index: Index, data: unknown): void {

Check warning on line 198 in packages/model/src/EditorJSModel.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
this.#document.insertData(index, data);

Check warning on line 199 in packages/model/src/EditorJSModel.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

/**
* Removes data from the specified index
*
* @param index - index to remove data from
*/
public removeData(index: Index): void {

Check warning on line 207 in packages/model/src/EditorJSModel.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
this.#document.removeData(index);

Check warning on line 208 in packages/model/src/EditorJSModel.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

/**
* Updates the ValueNode data associated with the BlockNode at the specified index.
*
Expand Down
92 changes: 92 additions & 0 deletions packages/model/src/entities/EditorDocument/EditorDocument.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,98 @@ describe('EditorDocument', () => {
});
});

describe('.insertData()', () => {
let document: EditorDocument;
const dataKey = 'text' as DataKey;
const text = 'Some text';
const blockIndex = 0;
let block: BlockNode;

beforeEach(() => {
const blockData = {
name: 'header' as BlockToolName,
data: {},
};

document = new EditorDocument();

document.initialize([ blockData ]);

block = document.getBlock(0);
});

it('should call .insertText() method if text index provided', () => {
const spy = jest.spyOn(document, 'insertText');
const index = new IndexBuilder().addBlockIndex(blockIndex)
.addDataKey(dataKey)
.addTextRange([0, 0])
.build();

document.insertData(index, text);

expect(spy)
.toHaveBeenCalledWith(blockIndex, dataKey, text, 0);
});

it('should call .addBlock() if block index is provided', () => {
const spy = jest.spyOn(document, 'addBlock');
const index = new IndexBuilder()
.addBlockIndex(blockIndex)
.build();


document.insertData(index, block);

expect(spy)
.toHaveBeenCalledWith(block, blockIndex);
});
});

describe('.removeData()', () => {
let document: EditorDocument;
const dataKey = 'text' as DataKey;
const blockIndex = 0;

beforeEach(() => {
const blockData = {
name: 'header' as BlockToolName,
data: {},
};

document = new EditorDocument();

document.initialize([ blockData ]);
});

it('should call .removeText() method if text index provided', () => {
const spy = jest.spyOn(document, 'removeText');
const rangeEnd = 5;
const index = new IndexBuilder()
.addBlockIndex(blockIndex)
.addDataKey(dataKey)
.addTextRange([0, rangeEnd])
.build();

document.removeData(index);

expect(spy)
.toHaveBeenCalledWith(blockIndex, dataKey, 0, rangeEnd);
});

it('should call .removeBlock() if block index is provided', () => {
const spy = jest.spyOn(document, 'removeBlock');
const index = new IndexBuilder()
.addBlockIndex(blockIndex)
.build();


document.removeData(index);

expect(spy)
.toHaveBeenCalledWith(blockIndex);
});
});

describe('.removeText()', () => {
let document: EditorDocument;
const dataKey = 'text' as DataKey;
Expand Down
41 changes: 41 additions & 0 deletions packages/model/src/entities/EditorDocument/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from '../../EventBus/events/index.js';
import type { Constructor } from '../../utils/types.js';
import { BaseDocumentEvent } from '../../EventBus/events/BaseEvent.js';
import type { Index } from '../Index/index.js';

/**
* EditorDocument class represents the top-level container for a tree-like structure of BlockNodes in an editor document.
Expand Down Expand Up @@ -323,6 +324,46 @@ export class EditorDocument extends EventBus {
return this.#children[blockIndex].getFragments(dataKey, start, end, tool);
}

/**
* Inserts data to the specified index
*
* @param index - index to insert data
* @param data - data to insert
*/
public insertData(index: Index, data: unknown): void {
switch (true) {
case index.isTextIndex:
this.insertText(index.blockIndex!, index.dataKey!, data as string, index.textRange![0]);
break;

case index.isBlockIndex:
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
this.addBlock(data as Parameters<EditorDocument['addBlock']>[0], index.blockIndex);
break;
default:
throw new Error('Unsupported index');

Check warning on line 344 in packages/model/src/entities/EditorDocument/index.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 344 in packages/model/src/entities/EditorDocument/index.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
}
}

/**
* Removes data from the specified index
*
* @param index - index to remove data from
*/
public removeData(index: Index): void {
switch (true) {
case index.isTextIndex:
this.removeText(index.blockIndex!, index.dataKey!, index.textRange![0], index.textRange![1]);
break;

case index.isBlockIndex:
this.removeBlock(index.blockIndex!);
break;
default:
throw new Error('Unsupported index');

Check warning on line 363 in packages/model/src/entities/EditorDocument/index.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 363 in packages/model/src/entities/EditorDocument/index.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
}
}

/**
* Listens to BlockNode events and bubbles them to the EditorDocument
*
Expand Down
62 changes: 62 additions & 0 deletions packages/model/src/entities/Index/Index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { DocumentIndex } from '../../EventBus/index.js';
import type { DataKey } from '../BlockNode/index.js';
import type { BlockTuneName } from '../BlockTune/index.js';
import { IndexBuilder } from '../index.js';
import { Index } from './index.js';

describe('Index', () => {
Expand Down Expand Up @@ -198,4 +199,65 @@ describe('Index', () => {
expect(index.validate()).toBe(true);
});
});

describe('.isBlockIndex', () => {
it('should return true if index points to the block', () => {
const index = new IndexBuilder().addBlockIndex(0)
.build();

expect(index.isBlockIndex).toBe(true);
});

it('should return false if index does not include block index', () => {
const index = new Index();

expect(index.isBlockIndex).toBe(false);
});

it('should return false if index points to the text range', () => {
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey('dataKey' as DataKey)
.addTextRange([0, 0])
.build();

expect(index.isBlockIndex).toBe(false);
});

it('should return false if index points to the tune data', () => {
const index = new IndexBuilder().addBlockIndex(0)
.addTuneName('tuneName' as BlockTuneName)
.addTuneKey('tuneKey')
.build();

expect(index.isBlockIndex).toBe(false);
});
});

describe('.isTextIndex', () => {
it('should return true if index points to the text', () => {
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey('dataKey' as DataKey)
.addTextRange([0, 0])
.build();

expect(index.isTextIndex).toBe(true);
});

it('should return false if index does not include text range', () => {
const index = new IndexBuilder().addBlockIndex(0)
.addDataKey('dataKey' as DataKey)
.build();

expect(index.isTextIndex).toBe(false);
});

it('should return false if index points to the tune data', () => {
const index = new IndexBuilder().addBlockIndex(0)
.addTuneName('tuneName' as BlockTuneName)
.addTuneKey('tuneKey')
.build();

expect(index.isTextIndex).toBe(false);
});
});
});
14 changes: 14 additions & 0 deletions packages/model/src/entities/Index/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,18 @@ export class Index {
return true;
}
}

/**
* Returns true if index points to the text data
*/
public get isTextIndex(): boolean {
return this.blockIndex !== undefined && this.dataKey !== undefined && this.textRange !== undefined;
}

/**
* Returns true if index points to the block node
*/
public get isBlockIndex(): boolean {
return this.blockIndex !== undefined && this.tuneName === undefined && this.dataKey === undefined && this.textRange === undefined;
}
}

2 comments on commit efcfe22

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for ./packages/model

St.
Category Percentage Covered / Total
🟢 Statements 96.95% 795/820
🟢 Branches 98.17% 214/218
🟢 Functions 88.79% 190/214
🟢 Lines 96.84% 767/792

Test suite run success

400 tests passing in 24 suites.

Report generated by 🧪jest coverage report action from efcfe22

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for ./packages/collaboration-manager

St.
Category Percentage Covered / Total
🟢 Statements 86.11% 62/72
🟡 Branches 62.5% 15/24
🟢 Functions 100% 10/10
🟢 Lines 86.11% 62/72

Test suite run success

6 tests passing in 1 suite.

Report generated by 🧪jest coverage report action from efcfe22

Please sign in to comment.