Skip to content

Commit f48d897

Browse files
committed
Changeset: Turn smartOpAssembler() into a real class
1 parent 27bd0aa commit f48d897

File tree

1 file changed

+92
-104
lines changed

1 file changed

+92
-104
lines changed

src/static/js/Changeset.js

Lines changed: 92 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -438,15 +438,92 @@ const opsFromText = function* (opcode, text, attribs = '', pool = null) {
438438
* - strips final "="
439439
* - ignores 0-length changes
440440
* - reorders consecutive + and - (which MergingOpAssembler doesn't do)
441-
*
442-
* @typedef {object} SmartOpAssembler
443-
* @property {Function} append -
444-
* @property {Function} appendOpWithText -
445-
* @property {Function} clear -
446-
* @property {Function} endDocument -
447-
* @property {Function} getLengthChange -
448-
* @property {Function} toString -
449441
*/
442+
class SmartOpAssembler {
443+
constructor() {
444+
this._minusAssem = new MergingOpAssembler();
445+
this._plusAssem = new MergingOpAssembler();
446+
this._keepAssem = new MergingOpAssembler();
447+
this._assem = exports.stringAssembler();
448+
this._lastOpcode = '';
449+
this._lengthChange = 0;
450+
}
451+
452+
_flushKeeps() {
453+
this._assem.append(this._keepAssem.toString());
454+
this._keepAssem.clear();
455+
}
456+
457+
_flushPlusMinus() {
458+
this._assem.append(this._minusAssem.toString());
459+
this._minusAssem.clear();
460+
this._assem.append(this._plusAssem.toString());
461+
this._plusAssem.clear();
462+
}
463+
464+
append(op) {
465+
if (!op.opcode) return;
466+
if (!op.chars) return;
467+
468+
if (op.opcode === '-') {
469+
if (this._lastOpcode === '=') {
470+
this._flushKeeps();
471+
}
472+
this._minusAssem.append(op);
473+
this._lengthChange -= op.chars;
474+
} else if (op.opcode === '+') {
475+
if (this._lastOpcode === '=') {
476+
this._flushKeeps();
477+
}
478+
this._plusAssem.append(op);
479+
this._lengthChange += op.chars;
480+
} else if (op.opcode === '=') {
481+
if (this._lastOpcode !== '=') {
482+
this._flushPlusMinus();
483+
}
484+
this._keepAssem.append(op);
485+
}
486+
this._lastOpcode = op.opcode;
487+
}
488+
489+
/**
490+
* Generates operations from the given text and attributes.
491+
*
492+
* @deprecated Use `opsFromText` instead.
493+
* @param {('-'|'+'|'=')} opcode - The operator to use.
494+
* @param {string} text - The text to remove/add/keep.
495+
* @param {(string|Attribute[])} attribs - The attributes to apply to the operations. See
496+
* `makeAttribsString`.
497+
* @param {?AttributePool} pool - See `makeAttribsString`.
498+
*/
499+
appendOpWithText(opcode, text, attribs, pool) {
500+
warnDeprecated('Changeset.SmartOpAssembler.prototype.appendOpWithText() is deprecated; ' +
501+
'use opsFromText() instead.');
502+
for (const op of opsFromText(opcode, text, attribs, pool)) this.append(op);
503+
}
504+
505+
toString() {
506+
this._flushPlusMinus();
507+
this._flushKeeps();
508+
return this._assem.toString();
509+
}
510+
511+
clear() {
512+
this._minusAssem.clear();
513+
this._plusAssem.clear();
514+
this._keepAssem.clear();
515+
this._assem.clear();
516+
this._lengthChange = 0;
517+
}
518+
519+
endDocument() {
520+
this._keepAssem.endDocument();
521+
}
522+
523+
getLengthChange() {
524+
return this._lengthChange;
525+
}
526+
}
450527

451528
/**
452529
* Used to check if a Changeset is valid. This function does not check things that require access to
@@ -462,7 +539,7 @@ exports.checkRep = (cs) => {
462539
const ops = unpacked.ops;
463540
let charBank = unpacked.charBank;
464541

465-
const assem = exports.smartOpAssembler();
542+
const assem = new SmartOpAssembler();
466543
let oldPos = 0;
467544
let calcNewLen = 0;
468545
let numInserted = 0;
@@ -503,96 +580,7 @@ exports.checkRep = (cs) => {
503580
/**
504581
* @returns {SmartOpAssembler}
505582
*/
506-
exports.smartOpAssembler = () => {
507-
const minusAssem = new MergingOpAssembler();
508-
const plusAssem = new MergingOpAssembler();
509-
const keepAssem = new MergingOpAssembler();
510-
const assem = exports.stringAssembler();
511-
let lastOpcode = '';
512-
let lengthChange = 0;
513-
514-
const flushKeeps = () => {
515-
assem.append(keepAssem.toString());
516-
keepAssem.clear();
517-
};
518-
519-
const flushPlusMinus = () => {
520-
assem.append(minusAssem.toString());
521-
minusAssem.clear();
522-
assem.append(plusAssem.toString());
523-
plusAssem.clear();
524-
};
525-
526-
const append = (op) => {
527-
if (!op.opcode) return;
528-
if (!op.chars) return;
529-
530-
if (op.opcode === '-') {
531-
if (lastOpcode === '=') {
532-
flushKeeps();
533-
}
534-
minusAssem.append(op);
535-
lengthChange -= op.chars;
536-
} else if (op.opcode === '+') {
537-
if (lastOpcode === '=') {
538-
flushKeeps();
539-
}
540-
plusAssem.append(op);
541-
lengthChange += op.chars;
542-
} else if (op.opcode === '=') {
543-
if (lastOpcode !== '=') {
544-
flushPlusMinus();
545-
}
546-
keepAssem.append(op);
547-
}
548-
lastOpcode = op.opcode;
549-
};
550-
551-
/**
552-
* Generates operations from the given text and attributes.
553-
*
554-
* @deprecated Use `opsFromText` instead.
555-
* @param {('-'|'+'|'=')} opcode - The operator to use.
556-
* @param {string} text - The text to remove/add/keep.
557-
* @param {(string|Attribute[])} attribs - The attributes to apply to the operations. See
558-
* `makeAttribsString`.
559-
* @param {?AttributePool} pool - See `makeAttribsString`.
560-
*/
561-
const appendOpWithText = (opcode, text, attribs, pool) => {
562-
warnDeprecated('Changeset.smartOpAssembler().appendOpWithText() is deprecated; ' +
563-
'use opsFromText() instead.');
564-
for (const op of opsFromText(opcode, text, attribs, pool)) append(op);
565-
};
566-
567-
const toString = () => {
568-
flushPlusMinus();
569-
flushKeeps();
570-
return assem.toString();
571-
};
572-
573-
const clear = () => {
574-
minusAssem.clear();
575-
plusAssem.clear();
576-
keepAssem.clear();
577-
assem.clear();
578-
lengthChange = 0;
579-
};
580-
581-
const endDocument = () => {
582-
keepAssem.endDocument();
583-
};
584-
585-
const getLengthChange = () => lengthChange;
586-
587-
return {
588-
append,
589-
toString,
590-
clear,
591-
endDocument,
592-
appendOpWithText,
593-
getLengthChange,
594-
};
595-
};
583+
exports.smartOpAssembler = () => new SmartOpAssembler();
596584

597585
/**
598586
* @returns {MergingOpAssembler}
@@ -1034,7 +1022,7 @@ const applyZip = (in1, in2, func) => {
10341022
const ops2 = exports.deserializeOps(in2);
10351023
let next1 = ops1.next();
10361024
let next2 = ops2.next();
1037-
const assem = exports.smartOpAssembler();
1025+
const assem = new SmartOpAssembler();
10381026
while (!next1.done || !next2.done) {
10391027
if (!next1.done && !next1.value.opcode) next1 = ops1.next();
10401028
if (!next2.done && !next2.value.opcode) next2 = ops2.next();
@@ -1526,7 +1514,7 @@ exports.makeSplice = (oldFullText, spliceStart, numRemoved, newText, optNewTextA
15261514
const oldText = oldFullText.substring(spliceStart, spliceStart + numRemoved);
15271515
const newLen = oldLen + newText.length - oldText.length;
15281516

1529-
const assem = exports.smartOpAssembler();
1517+
const assem = new SmartOpAssembler();
15301518
const ops = (function* () {
15311519
yield* opsFromText('=', oldFullText.substring(0, spliceStart));
15321520
yield* opsFromText('-', oldText);
@@ -1657,7 +1645,7 @@ exports.moveOpsToNewPool = (cs, oldPool, newPool) => {
16571645
* @returns {string}
16581646
*/
16591647
exports.makeAttribution = (text) => {
1660-
const assem = exports.smartOpAssembler();
1648+
const assem = new SmartOpAssembler();
16611649
for (const op of opsFromText('+', text)) assem.append(op);
16621650
return assem.toString();
16631651
};
@@ -1897,7 +1885,7 @@ exports.attribsAttributeValue = (attribs, key, pool) => {
18971885
* @returns {Builder}
18981886
*/
18991887
exports.builder = (oldLen) => {
1900-
const assem = exports.smartOpAssembler();
1888+
const assem = new SmartOpAssembler();
19011889
const o = new Op();
19021890
const charBank = exports.stringAssembler();
19031891

@@ -2000,7 +1988,7 @@ exports.makeAttribsString = (opcode, attribs, pool) => {
20001988
exports.subattribution = (astr, start, optEnd) => {
20011989
const attOps = exports.deserializeOps(astr);
20021990
let attOpsNext = attOps.next();
2003-
const assem = exports.smartOpAssembler();
1991+
const assem = new SmartOpAssembler();
20041992
let attOp = new Op();
20051993
const csOp = new Op();
20061994

0 commit comments

Comments
 (0)