chore(web): further PR cleanup

This commit is contained in:
Joshua A. Horton 2024-02-08 13:12:26 +07:00
parent f36aba7bad
commit aefef2181d
5 changed files with 55 additions and 23 deletions

View file

@ -1,7 +1,7 @@
///<reference types="@keymanapp/models-types" />
import { extendString } from "@keymanapp/web-utils";
import { searchStringDivergence } from "./stringDivergence.js";
import { findCommonSubstringEndIndex } from "./stringDivergence.js";
extendString();
@ -124,14 +124,14 @@ export default abstract class OutputTarget {
const toLeft = this.getTextBeforeCaret();
const fromLeft = original.getTextBeforeCaret();
const leftDivergenceIndex = searchStringDivergence(fromLeft, toLeft, false);
const leftDivergenceIndex = findCommonSubstringEndIndex(fromLeft, toLeft, false);
const deletedLeft = fromLeft.substring(leftDivergenceIndex)._kmwLength();
// No need for our specialized variant here.
const insertedText = toLeft.substring(leftDivergenceIndex);
const toRight = this.getTextAfterCaret();
const fromRight = original.getTextAfterCaret();
const rightDivergenceIndex = searchStringDivergence(fromRight, toRight, true);
const rightDivergenceIndex = findCommonSubstringEndIndex(fromRight, toRight, true);
// Right insertions aren't supported, but right deletions will matter in some scenarios.
// In particular, once we allow right-deletion for pred-text suggestions applied with the

View file

@ -1,11 +1,15 @@
// Future TODO: import from @keymanapp/common-types... once we no longer need to support ES5.
import { Uni_IsSurrogate1, Uni_IsSurrogate2 } from '@keymanapp/web-utils';
/**
* Returns the index for the code point divergence point in code unit coordinates.
* Returns the index for the code point divergence point between two strings, as measured in code
* unit coordinates.
* @param str1
* @param str2
* @param commonSuffix If false, asserts a common prefix to the strings. If true, asserts a common suffix.
* @returns The code unit index within `str1` for the start of the code point not common to both.
*/
export function searchStringDivergence(str1: string, str2: string, commonSuffix: boolean): number {
export function findCommonSubstringEndIndex(str1: string, str2: string, commonSuffix: boolean): number {
/**
* The maximum number of iterations to consider; exceeding this would go past a string boundary.
*/
@ -67,16 +71,15 @@ export function searchStringDivergence(str1: string, str2: string, commonSuffix:
const divergentChar1 = str1.charCodeAt(index);
const divergentChar2 = str2.charCodeAt(index + offset);
const isHigh = (charCode: number) => charCode >= 0xD800 && charCode <= 0xDBFF;
const isLow = (charCode: number) => charCode >= 0xDC00 && charCode <= 0xDFFF;
const commonChecker = commonSuffix ? isLow : isHigh;
const divergentChecker = commonSuffix ? isHigh : isLow;
const commonSurrogateChecker = commonSuffix ? Uni_IsSurrogate2 : Uni_IsSurrogate1;
const divergentSurrogateChecker = commonSuffix ? Uni_IsSurrogate1 : Uni_IsSurrogate2;
// If the last common char qualifies as a direction-appropriate SMP surrogate...
if(commonChecker(commonPotentialSurrogate)) {
// If the last common character if of the direction-appropriate surrogate type (for
// comprising a potential split surrogate pair representing a non-BMP char)...
if(commonSurrogateChecker(commonPotentialSurrogate)) {
// And one of the two divergent chars is a qualifying match - a surrogate
// of the opposite type...
if(divergentChecker(divergentChar1) || divergentChecker(divergentChar2)) {
if(divergentSurrogateChecker(divergentChar1) || divergentSurrogateChecker(divergentChar2)) {
// Our current index would split a surrogate pair; decrement the index to
// preserve the pair.
return index - inc;

View file

@ -7,11 +7,11 @@ extendString(); // Ensure KMW's string-extension functionality is available.
String.kmwEnableSupplementaryPlane(false);
// A unicode-coding like alias for use in constructing SMP strings.
// A unicode-coding like alias for use in constructing non-BMP strings.
const u = String.fromCodePoint;
/**
* Returns the "Mathematical Sans-Serif Small" SMP encoding for
* Returns the "Mathematical Sans-Serif Small" non-BMP encoding for
* a passed-in lowercase char between 'a' and 'z', inclusive.
* @param {*} char
* @returns
@ -39,7 +39,7 @@ describe("String divergence calculations", function() {
assert.equal(result2, 0);
});
it("SMP text", () => {
it("non-BMP text", () => {
const smp_ify = (str) => str.split('').map(ss).join('');
const result1 = searchStringDivergence(
@ -48,7 +48,7 @@ describe("String divergence calculations", function() {
false
);
// 2 per SMP char; is in code-unit... units.
// 2 per non-BMP char; is in code-unit... units.
// Will avoid splitting code points, though.
assert.equal(result1, 8);
@ -61,7 +61,7 @@ describe("String divergence calculations", function() {
assert.equal(result2, 8);
});
it("SMP edge cases", () => {
it("non-BMP edge cases", () => {
const smp_ify = (str) => str.split('').map(ss).join('');
const result1 = searchStringDivergence(
@ -106,7 +106,7 @@ describe("String divergence calculations", function() {
assert.equal(result2, "post-caret text".length-1);
})
it("SMP text", () => {
it("non-BMP text", () => {
const smp_ify = (str) => str.split('').map(ss).join('');
// att|endance
@ -117,7 +117,7 @@ describe("String divergence calculations", function() {
true
);
// 2 per SMP char; is in code-unit... units.
// 2 per non-BMP char; is in code-unit... units.
// Will avoid splitting code points; is odd b/c we get the index of the LAST char of the pair.
assert.equal(result1, 5);
@ -132,7 +132,7 @@ describe("String divergence calculations", function() {
});
it("SMP edge cases", () => {
it("non-BMP edge cases", () => {
const smp_ify = (str) => str.split('').map(ss).join('');
// If the two are equal...
@ -155,7 +155,7 @@ describe("String divergence calculations", function() {
});
describe("Transcriptions and Transforms", function() {
// Built in-line via function. Looks functionally equivalent to "apple", but with SMP characters.
// Built in-line via function. Looks functionally equivalent to "apple", but with non-BMP characters.
let smpApple = u(0x1d5ba)+u(0x1d5c9)+u(0x1d5c9)+u(0x1d5c5)+u(0x1d5be);
it("does not store an alias for related OutputTargets", function() {
@ -263,7 +263,7 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels.
assert.equal(transcription.transform.deleteRight, 1, "Incorrect count for right-of-caret deletions");
});
it("handles deletions around the caret without text insertion (SMP text)", function() {
it("handles deletions around the caret without text insertion (non-BMP text)", function() {
try {
String.kmwEnableSupplementaryPlane(true);
var target = new Mock(smpApple, 2);
@ -355,7 +355,7 @@ but not himself.`; // Sheev Palpatine, in the Star Wars prequels.
assert.equal(transcription.transform.deleteRight, 3, "Incorrect count for right-of-caret deletions");
});
it("handles deletions around the caret with text insertion (SMP text)", function() {
it("handles deletions around the caret with text insertion (non-BMP text)", function() {
try {
String.kmwEnableSupplementaryPlane(true);

View file

@ -21,6 +21,8 @@ export { default as extendString } from "./kmwstring.js";
export { default as ManagedPromise } from "./managedPromise.js";
export { default as TimeoutPromise, timedPromise } from "./timeoutPromise.js";
export { Uni_IsSurrogate1, Uni_IsSurrogate2 } from "./surrogates.js";
// // Uncomment the following line and run the bundled output to verify successful
// // esbuild bundling of this submodule:
// console.log(Version.CURRENT.toString());

View file

@ -0,0 +1,27 @@
/*
* The definitions below are duplicated from common/web/types/util/util.ts;
* we can't downcompile the originals to ES5 when bundling with esbuild.
* `import type` stuff is fine, but not non-type `import` statements.
*
* TODO: Use those instead, once we're no longer building ES5 versions of Web.
*/
export const Uni_LEAD_SURROGATE_START = 0xD800;
export const Uni_LEAD_SURROGATE_END = 0xDBFF;
export const Uni_TRAIL_SURROGATE_START = 0xDC00;
export const Uni_TRAIL_SURROGATE_END = 0xDFFF;
/**
* @brief True if a lead surrogate
* \def Uni_IsSurrogate1
*/
export function Uni_IsSurrogate1(ch : number) {
return ((ch) >= Uni_LEAD_SURROGATE_START && (ch) <= Uni_LEAD_SURROGATE_END);
}
/**
* @brief True if a trail surrogate
* \def Uni_IsSurrogate2
*/
export function Uni_IsSurrogate2(ch : number) {
return ((ch) >= Uni_TRAIL_SURROGATE_START && (ch) <= Uni_TRAIL_SURROGATE_END);
}