Skip to content

Commit

Permalink
Add fields markOpsBefore and markOpsAfter to TextNode in protobuf
Browse files Browse the repository at this point in the history
  • Loading branch information
chacha912 committed Sep 18, 2023
1 parent 7ab0076 commit ce14cb0
Show file tree
Hide file tree
Showing 7 changed files with 741 additions and 45 deletions.
100 changes: 78 additions & 22 deletions src/api/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {
RGATreeSplitNode,
RGATreeSplitNodeID,
RGATreeSplitPos,
StyleOperation as MarkOperation,
} from '@yorkie-js-sdk/src/document/crdt/rga_tree_split';
import { CRDTText, CRDTTextValue } from '@yorkie-js-sdk/src/document/crdt/text';
import {
Expand Down Expand Up @@ -83,6 +84,8 @@ import {
TreePos as PbTreePos,
TreeNodeID as PbTreeNodeID,
ValueType as PbValueType,
MarkOps as PbMarkOps,
MarkOp as PbMarkOp,
} from '@yorkie-js-sdk/src/api/yorkie/v1/resources_pb';
import { IncreaseOperation } from '@yorkie-js-sdk/src/document/operation/increase_operation';
import {
Expand Down Expand Up @@ -128,6 +131,33 @@ function toPresenceChange(
return pbPresenceChange;
}

/**
* `toMarkOps` converts the given model to Protobuf format.
*/
function toMarkOps(markOps: Set<MarkOperation>): PbMarkOps {
const pbMarkOps = new PbMarkOps();
const pbMarkOpsList: Array<PbMarkOp> = [];
for (const markOp of markOps) {
pbMarkOpsList.push(toMarkOp(markOp));
}
pbMarkOps.setOperationsList(pbMarkOpsList);
return pbMarkOps;
}

/**
* `toMarkOp` converts the given model to Protobuf format.
*/
function toMarkOp(markOp: MarkOperation): PbMarkOp {
const pbMarkOp = new PbMarkOp();
pbMarkOp.setFromboundary(toTextNodeBoundary(markOp.fromBoundary));
pbMarkOp.setToboundary(toTextNodeBoundary(markOp.toBoundary));
const pbAttributes = pbMarkOp.getAttributesMap();
for (const [key, value] of Object.entries(markOp.attributes)) {
pbAttributes.set(key, value);
}
return pbMarkOp;
}

/**
* `toCheckpoint` converts the given model to Protobuf format.
*/
Expand Down Expand Up @@ -539,7 +569,6 @@ function toTextNodes(
rgaTreeSplit: RGATreeSplit<CRDTTextValue>,
): Array<PbTextNode> {
const pbTextNodes = [];
let currentAttr = new Map<string, string>();

for (const textNode of rgaTreeSplit) {
const pbTextNode = new PbTextNode();
Expand All @@ -548,23 +577,6 @@ function toTextNodes(
pbTextNode.setRemovedAt(toTimeTicket(textNode.getRemovedAt()));

const pbNodeAttrsMap = pbTextNode.getAttributesMap();

const beforeAnchor = textNode.getStyleOpsBefore();
const afterAnchor = textNode.getStyleOpsAfter();
if (beforeAnchor) {
currentAttr = rgaTreeSplit.getAttrsFromAnchor(beforeAnchor);
}
if (!textNode.isRemoved()) {
for (const [key, value] of currentAttr.entries()) {
const pbNodeAttr = new PbNodeAttr();
pbNodeAttr.setValue(value);
pbNodeAttrsMap.set(key, pbNodeAttr);
}
}
if (afterAnchor) {
currentAttr = rgaTreeSplit.getAttrsFromAnchor(afterAnchor);
}

const attrs = textNode.getValue().getAttrs();
for (const attr of attrs) {
const pbNodeAttr = new PbNodeAttr();
Expand All @@ -573,6 +585,14 @@ function toTextNodes(
pbNodeAttrsMap.set(attr.getKey(), pbNodeAttr);
}

const styleOpsBefore = textNode.getStyleOpsBefore();
if (styleOpsBefore) {
pbTextNode.setMarkopsbefore(toMarkOps(styleOpsBefore));
}
const styleOpsAfter = textNode.getStyleOpsAfter();
if (styleOpsAfter) {
pbTextNode.setMarkopsafter(toMarkOps(styleOpsAfter));
}
pbTextNodes.push(pbTextNode);
}

Expand Down Expand Up @@ -985,6 +1005,22 @@ function fromTextNodeID(pbTextNodeID: PbTextNodeID): RGATreeSplitNodeID {
);
}

/**
* `fromMarkOp` converts the given Protobuf format to model format.
*/
function fromMarkOp(pbMarkOp: PbMarkOp): MarkOperation {
const attributes: Record<string, string> = {};
pbMarkOp.getAttributesMap().forEach((value, key) => {
attributes[key as string] = value;
});

return {
fromBoundary: fromTextNodeBoundary(pbMarkOp.getFromboundary()!),
toBoundary: fromTextNodeBoundary(pbMarkOp.getToboundary()!),
attributes,
};
}

/**
* `fromTextNode` converts the given Protobuf format to model format.
*/
Expand All @@ -998,10 +1034,30 @@ function fromTextNode(pbTextNode: PbTextNode): RGATreeSplitNode<CRDTTextValue> {
);
});

const textNode = RGATreeSplitNode.create(
fromTextNodeID(pbTextNode.getId()!),
textValue,
);
let styleOpsBefore: Set<MarkOperation> | undefined;
const markOpsBefore = pbTextNode.getMarkopsbefore()?.getOperationsList();
if (markOpsBefore) {
styleOpsBefore = new Set();
for (const op of markOpsBefore) {
styleOpsBefore.add(fromMarkOp(op));
}
}

let styleOpsAfter: Set<MarkOperation> | undefined;
const markOpsAfter = pbTextNode.getMarkopsafter()?.getOperationsList();
if (markOpsAfter) {
styleOpsAfter = new Set();
for (const op of markOpsAfter) {
styleOpsAfter.add(fromMarkOp(op));
}
}

const textNode = RGATreeSplitNode.create({
id: fromTextNodeID(pbTextNode.getId()!),
value: textValue,
styleOpsBefore,
styleOpsAfter,
});
textNode.remove(fromTimeTicket(pbTextNode.getRemovedAt()));
return textNode;
}
Expand Down
12 changes: 12 additions & 0 deletions src/api/yorkie/v1/resources.proto
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,25 @@ message TextNode {
TimeTicket removed_at = 3;
TextNodeID ins_prev_id = 4;
map<string, NodeAttr> attributes = 5;
MarkOps mark_ops_before = 6;
MarkOps mark_ops_After = 7;
}

message TextNodeID {
TimeTicket created_at = 1;
int32 offset = 2;
}

message MarkOps {
repeated MarkOp operations = 1;
}

message MarkOp {
TextNodeBoundary from_boundary = 1;
TextNodeBoundary to_boundary = 2;
map<string, string> attributes = 3;
}

message TreeNode {
TreeNodeID id = 1;
string type = 2;
Expand Down
62 changes: 62 additions & 0 deletions src/api/yorkie/v1/resources_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,16 @@ export class TextNode extends jspb.Message {
getAttributesMap(): jspb.Map<string, NodeAttr>;
clearAttributesMap(): TextNode;

getMarkopsbefore(): MarkOps | undefined;
setMarkopsbefore(value?: MarkOps): TextNode;
hasMarkopsbefore(): boolean;
clearMarkopsbefore(): TextNode;

getMarkopsafter(): MarkOps | undefined;
setMarkopsafter(value?: MarkOps): TextNode;
hasMarkopsafter(): boolean;
clearMarkopsafter(): TextNode;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): TextNode.AsObject;
static toObject(includeInstance: boolean, msg: TextNode): TextNode.AsObject;
Expand All @@ -1099,6 +1109,8 @@ export namespace TextNode {
removedAt?: TimeTicket.AsObject,
insPrevId?: TextNodeID.AsObject,
attributesMap: Array<[string, NodeAttr.AsObject]>,
markopsbefore?: MarkOps.AsObject,
markopsafter?: MarkOps.AsObject,
}
}

Expand Down Expand Up @@ -1126,6 +1138,56 @@ export namespace TextNodeID {
}
}

export class MarkOps extends jspb.Message {
getOperationsList(): Array<MarkOp>;
setOperationsList(value: Array<MarkOp>): MarkOps;
clearOperationsList(): MarkOps;
addOperations(value?: MarkOp, index?: number): MarkOp;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): MarkOps.AsObject;
static toObject(includeInstance: boolean, msg: MarkOps): MarkOps.AsObject;
static serializeBinaryToWriter(message: MarkOps, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): MarkOps;
static deserializeBinaryFromReader(message: MarkOps, reader: jspb.BinaryReader): MarkOps;
}

export namespace MarkOps {
export type AsObject = {
operationsList: Array<MarkOp.AsObject>,
}
}

export class MarkOp extends jspb.Message {
getFromboundary(): TextNodeBoundary | undefined;
setFromboundary(value?: TextNodeBoundary): MarkOp;
hasFromboundary(): boolean;
clearFromboundary(): MarkOp;

getToboundary(): TextNodeBoundary | undefined;
setToboundary(value?: TextNodeBoundary): MarkOp;
hasToboundary(): boolean;
clearToboundary(): MarkOp;

getAttributesMap(): jspb.Map<string, string>;
clearAttributesMap(): MarkOp;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): MarkOp.AsObject;
static toObject(includeInstance: boolean, msg: MarkOp): MarkOp.AsObject;
static serializeBinaryToWriter(message: MarkOp, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): MarkOp;
static deserializeBinaryFromReader(message: MarkOp, reader: jspb.BinaryReader): MarkOp;
}

export namespace MarkOp {
export type AsObject = {
fromboundary?: TextNodeBoundary.AsObject,
toboundary?: TextNodeBoundary.AsObject,
attributesMap: Array<[string, string]>,
}
}

export class TreeNode extends jspb.Message {
getId(): TreeNodeID | undefined;
setId(value?: TreeNodeID): TreeNode;
Expand Down
Loading

0 comments on commit ce14cb0

Please sign in to comment.