From 9093c0719b27d0d6fa126f6bf2586e0f7fb87d99 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 12 Feb 2024 08:47:47 +0700 Subject: [PATCH 01/89] change(web): preps for wordbreaker child projects --- common/models/wordbreakers/build.sh | 2 +- .../wordbreakers/src/{ => main}/ascii.ts | 0 .../src/{ => main}/default/data.ts | 0 .../src/{ => main}/default/index.ts | 0 .../wordbreakers/src/{ => main}/index.ts | 0 .../src/{ => main}/placeholder.ts | 0 .../wordbreakers/src/main/tsconfig.json | 19 +++++++++++++++++++ common/models/wordbreakers/tsconfig.json | 15 ++++----------- 8 files changed, 24 insertions(+), 12 deletions(-) rename common/models/wordbreakers/src/{ => main}/ascii.ts (100%) rename common/models/wordbreakers/src/{ => main}/default/data.ts (100%) rename common/models/wordbreakers/src/{ => main}/default/index.ts (100%) rename common/models/wordbreakers/src/{ => main}/index.ts (100%) rename common/models/wordbreakers/src/{ => main}/placeholder.ts (100%) create mode 100644 common/models/wordbreakers/src/main/tsconfig.json diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index fadd350118..a2ff0d14dd 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -34,7 +34,7 @@ function do_build() { tsc -b # Declaration bundling. - tsc --emitDeclarationOnly --outFile ./build/lib/index.d.ts + tsc -p src/main/tsconfig.json --emitDeclarationOnly --outFile ./build/lib/index.d.ts } function do_test() { diff --git a/common/models/wordbreakers/src/ascii.ts b/common/models/wordbreakers/src/main/ascii.ts similarity index 100% rename from common/models/wordbreakers/src/ascii.ts rename to common/models/wordbreakers/src/main/ascii.ts diff --git a/common/models/wordbreakers/src/default/data.ts b/common/models/wordbreakers/src/main/default/data.ts similarity index 100% rename from common/models/wordbreakers/src/default/data.ts rename to common/models/wordbreakers/src/main/default/data.ts diff --git a/common/models/wordbreakers/src/default/index.ts b/common/models/wordbreakers/src/main/default/index.ts similarity index 100% rename from common/models/wordbreakers/src/default/index.ts rename to common/models/wordbreakers/src/main/default/index.ts diff --git a/common/models/wordbreakers/src/index.ts b/common/models/wordbreakers/src/main/index.ts similarity index 100% rename from common/models/wordbreakers/src/index.ts rename to common/models/wordbreakers/src/main/index.ts diff --git a/common/models/wordbreakers/src/placeholder.ts b/common/models/wordbreakers/src/main/placeholder.ts similarity index 100% rename from common/models/wordbreakers/src/placeholder.ts rename to common/models/wordbreakers/src/main/placeholder.ts diff --git a/common/models/wordbreakers/src/main/tsconfig.json b/common/models/wordbreakers/src/main/tsconfig.json new file mode 100644 index 0000000000..ce66f0bbfc --- /dev/null +++ b/common/models/wordbreakers/src/main/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.kmw-worker-base.json", + + "compilerOptions": { + "baseUrl": "./", + "outDir": "../../build/obj", + "tsBuildInfoFile": "../../build/obj/tsconfig.tsbuildinfo", + "rootDir": "./" + }, + "references": [ + { "path": "../../../types" } + ], + "include": [ + "./**/*" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/common/models/wordbreakers/tsconfig.json b/common/models/wordbreakers/tsconfig.json index 54d12d5d8c..57df26333b 100644 --- a/common/models/wordbreakers/tsconfig.json +++ b/common/models/wordbreakers/tsconfig.json @@ -4,17 +4,10 @@ "compilerOptions": { "baseUrl": "./", "outDir": "build/obj", - "tsBuildInfoFile": "build/obj/tsconfig.tsbuildinfo", - "rootDir": "./src" + "tsBuildInfoFile": "build/tsconfig.tsbuildinfo", + "rootDir": "./" }, "references": [ - { "path": "../types" } - ], - "include": [ - "src/**/*" - ], - "exclude": [ - "node_modules", - "test/**/*.ts" + { "path": "./src/main" } ] -} +} \ No newline at end of file From 901861a75d22cf51bf2fb2f56753b079789bfa6f Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 12 Feb 2024 09:39:31 +0700 Subject: [PATCH 02/89] feat(web): implements string-encoded prop-array search --- common/models/wordbreakers/package.json | 5 ++- .../src/data-compiler/tsconfig.json | 19 ++++++++ .../src/main/default/searchForProperty.ts | 44 +++++++++++++++++++ .../wordbreakers/src/main/test-index.ts | 6 +++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 common/models/wordbreakers/src/data-compiler/tsconfig.json create mode 100644 common/models/wordbreakers/src/main/default/searchForProperty.ts create mode 100644 common/models/wordbreakers/src/main/test-index.ts diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index 6fe09dea62..ee9de24237 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -24,7 +24,10 @@ "./lib": { "types": "./build/lib/index.d.ts" }, - "./obj/*.js": "./build/obj/*.js" + "./obj/*.js": "./build/obj/*.js", + "./test-index": { + "default": "./build/obj/test-index.js" + } }, "directories": { "lib": "lib", diff --git a/common/models/wordbreakers/src/data-compiler/tsconfig.json b/common/models/wordbreakers/src/data-compiler/tsconfig.json new file mode 100644 index 0000000000..ce66f0bbfc --- /dev/null +++ b/common/models/wordbreakers/src/data-compiler/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.kmw-worker-base.json", + + "compilerOptions": { + "baseUrl": "./", + "outDir": "../../build/obj", + "tsBuildInfoFile": "../../build/obj/tsconfig.tsbuildinfo", + "rootDir": "./" + }, + "references": [ + { "path": "../../../types" } + ], + "include": [ + "./**/*" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/common/models/wordbreakers/src/main/default/searchForProperty.ts b/common/models/wordbreakers/src/main/default/searchForProperty.ts new file mode 100644 index 0000000000..45a1641bd9 --- /dev/null +++ b/common/models/wordbreakers/src/main/default/searchForProperty.ts @@ -0,0 +1,44 @@ +import { WordBreakProperty } from "./data.js"; + +export function searchForProperty(codePoint: number): WordBreakProperty { + const bucketSize = codePoint <= 0xFFFF ? 2 : 3; + + // SMP chars take a bit more space to encode. + // TODO: encode the strings & import them here. + const encodedArray = bucketSize == 2 ? "" /* BMP string */ : "" /* non-BMP string */; + + return _searchForProperty(encodedArray, codePoint, bucketSize, 0, encodedArray.length / bucketSize - 1); +} + +/** + * Binary search for the word break property of a given CODE POINT. + * + * The auto-generated data.ts master array defines a **character range** + * lookup table. If a character's codepoint is equal to or greater than + * the start-of-range value for an entry and exclusively less than the next + * entry's start-of-range, it falls within the first entry's range bucket + * and is classified accordingly by this method. + */ +function _searchForProperty(encodedArray: string, codePoint: number, bucketSize: number, left: number, right: number): WordBreakProperty { + // All items that are not found in the array are assigned the 'Other' property. + if (right < left) { // May need special handling at end of BMP / start of non-BMP. + return WordBreakProperty.Other; + } + + let midpoint = left + ~~((right - left) / 2); + let candidate = encodedArray.codePointAt(bucketSize * midpoint); + + // If out-of-bounds, gives NaN. + let nextRange = encodedArray.codePointAt(bucketSize * (midpoint + 1)); + let startOfNextRange = isNaN(nextRange) ? Infinity : nextRange; + + if (codePoint < candidate) { + return _searchForProperty(encodedArray, codePoint, bucketSize, left, midpoint - 1); + } else if (codePoint >= startOfNextRange) { + return _searchForProperty(encodedArray, codePoint, bucketSize, midpoint + 1, right); + } + + // We found it! + const propertyCode = encodedArray.charCodeAt(bucketSize * (midpoint + 1) - 1); + return propertyCode as WordBreakProperty; +} \ No newline at end of file diff --git a/common/models/wordbreakers/src/main/test-index.ts b/common/models/wordbreakers/src/main/test-index.ts new file mode 100644 index 0000000000..a69cc42ae3 --- /dev/null +++ b/common/models/wordbreakers/src/main/test-index.ts @@ -0,0 +1,6 @@ +// Include all standard exports. +export * from './index.js'; + +// Exposes some internal properties for unit-test accessibility +export { WordBreakProperty } from './default/data.js'; +export { searchForProperty } from './default/searchForProperty.js'; From 58c7575d4bc73e1514a840b9bd00030be29afbf1 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 13 Feb 2024 08:21:40 +0700 Subject: [PATCH 03/89] feat(web): full property data-table generation functionality; data is exact match --- common/models/wordbreakers/UNICODE_VERSION.md | 1 + common/models/wordbreakers/package.json | 6 +- .../wordbreakers/src/data-compiler/index.ts | 323 ++++++++++++++++++ .../src/data-compiler/tsconfig.json | 8 +- .../imports/WordBreakProperty-13.0.0.txt.gz | Bin 0 -> 23663 bytes .../src/imports/emoji-data-13.0.0.txt.gz | Bin 0 -> 23400 bytes common/models/wordbreakers/tsconfig.json | 7 +- package-lock.json | 13 +- 8 files changed, 351 insertions(+), 7 deletions(-) create mode 100644 common/models/wordbreakers/UNICODE_VERSION.md create mode 100644 common/models/wordbreakers/src/data-compiler/index.ts create mode 100644 common/models/wordbreakers/src/imports/WordBreakProperty-13.0.0.txt.gz create mode 100644 common/models/wordbreakers/src/imports/emoji-data-13.0.0.txt.gz diff --git a/common/models/wordbreakers/UNICODE_VERSION.md b/common/models/wordbreakers/UNICODE_VERSION.md new file mode 100644 index 0000000000..70045d3c9a --- /dev/null +++ b/common/models/wordbreakers/UNICODE_VERSION.md @@ -0,0 +1 @@ +13.0.0 \ No newline at end of file diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index ee9de24237..bd530aaeab 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -27,6 +27,9 @@ "./obj/*.js": "./build/obj/*.js", "./test-index": { "default": "./build/obj/test-index.js" + }, + "./UNICODE_VERSION.md": { + "default": "./UNICODE_VERSION.md" } }, "directories": { @@ -60,7 +63,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "ts-node": "^10.9.1", - "typescript": "^4.9.5" + "typescript": "^4.9.5", + "zlib": "^1.0.5" }, "type": "module", "dependencies": { diff --git a/common/models/wordbreakers/src/data-compiler/index.ts b/common/models/wordbreakers/src/data-compiler/index.ts new file mode 100644 index 0000000000..e217bc51f1 --- /dev/null +++ b/common/models/wordbreakers/src/data-compiler/index.ts @@ -0,0 +1,323 @@ +#!/usr/bin/env node + +// Original version found at: https://github.com/eddieantonio/unicode-default-word-boundary/blob/master/libexec/compile-word-break.js + +// TODO: Adapt to produce two string-encoded arrays - one for BMP chars, one for non-BMP chars. + +import zlib from 'zlib'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +import { createRequire } from 'module'; +const require = createRequire(import.meta.url); + +/* + * Generates the TypeScript file for data required for the word boundary + * function: + * + * - a sorted array to facilitate binary search of the Word_Break property. + * - a regular expression that matches characters that have Extended_Pictographic=Yes. + * + * For internal use only. Please keep away from children. + * + * The generated file is saved to ../src/gen/WordBreakProperty.ts + */ + +const MAX_CODE_POINT = 0x10FFFF; + +// Where to get the data: +// - http://www.unicode.org/reports/tr51/#emoji_data +// - https://www.unicode.org/reports/tr41/tr41-26.html#Props0 + +//////////////////////////////////// Main //////////////////////////////////// + +const projectDir = path.dirname(require.resolve("@keymanapp/models-wordbreakers/UNICODE_VERSION.md")); +const generatedFilename = path.join(projectDir, 'src', 'main', 'default', 'data_test.ts'); + +// Ensure this package's major version number is in sync with the Unicode +// major version. + +const packageVersion = new String(fs.readFileSync(`${projectDir}/UNICODE_VERSION.md`)); +const UNICODE_VERSION = packageVersion.split('.')[0] + '.0.0'; + +// The data files should be in this repository, with names matching the +// Unicode version. +let wordBoundaryFilename = path.join(projectDir, `./src/imports/WordBreakProperty-${UNICODE_VERSION}.txt.gz`); +let emojiDataFilename = path.join(projectDir, `./src/imports/emoji-data-${UNICODE_VERSION}.txt.gz`); + +///////////////////////////// Word_Boundary file ///////////////////////////// + +// Extract the ranges IN ASCENDING ORDER from the file. +// This will be the big binary search table. +let ranges = readZippedCharacterPropertyFile(wordBoundaryFilename) + .sort((a, b) => { + return a.start - b.start; + }); + +// The list of ranges are initially sparse — having gaps between assigned +// ranges. Fill in those gaps: +ranges = makeDense(ranges); +ensureDense(ranges); + +// The possible Word_Break property assignments. +let categories = new Set(); +for (let {property} of ranges) { + categories.add(property); +} +// Also add pseudo-categories of start-of-text and end-of-text: +categories.add('sot'); +categories.add('eot'); + +///////////////////////// Extended_Pictographic=Yes ////////////////////////// + +let extendedPictographicCodePoints = readZippedCharacterPropertyFile(emojiDataFilename) + .filter(({property}) => property === 'Extended_Pictographic'); + +// Try generating the regular expression both in a way that is +// backwards-compatbile and one that only works in ES6+. +let extendedPictographicRegExp; +let compatibleRegexp = utf16AlternativesStrategy(); +let es6Regexp = unicodeRangeStrategy(); + +// Choose the shortest regular expression. +// In my experience, the ES6 regexp is an order of magnitude smaller! +if (es6Regexp.length < compatibleRegexp.length) { + extendedPictographicRegExp = es6Regexp; + console.warn(`Using ES6 regexp [${es6Regexp.length} chars]`); +} else { + extendedPictographicRegExp = compatibleRegexp; + console.warn(`Using compatibility regexp [${compatibleRegexp.length} chars]`); +} + +let catIndexSeed = 0; +const categoryMap = new Map(); + +for(let cat of categories) { + categoryMap.set(cat, catIndexSeed++); +} + +//////////////////////// Creating the generated file ///////////////////////// + +// Save the output in the gen/ directory. +let stream = fs.createWriteStream(generatedFilename); + +// // Former entry in the original version by Eddie that was never included in our repo: +// export const extendedPictographic = ${extendedPictographicRegExp}; + +// Generate the file! +stream.write(`// Automatically generated file. DO NOT MODIFY. + +/** + * Valid values for a word break property. + */ +export const enum WordBreakProperty { +${ /* Create enum values for each word break property */ + Array.from(categories) + .map(x => ` ${x}`) + .join(',\n') +} +}; + +export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ +${ + // TODO: Two versions: one that's BMP-encoded, one that's non-BMP encoded. + ranges.map(({start, property}) => (` [` + + `/*start*/ 0x${start.toString(16).toUpperCase()}, ` + + `WordBreakProperty.${property}],` + )).join('\n') +} +]; +`); + +/** + * Reads a Unicode character property file. + * + * Character property files are composed of comment lines, empty lines, and + * property lines. Comments lines begin with '#' and should be ignored, as + * well as empty lines. + * + * Property lines have a code point or a code point range, followed by a + * semi-colon, followed by the property text. e.g., + * + * 1F600 ; Emoji # 6.1 [1] (😀) grinning face + * 26C4..26C5 ; Emoji_Presentation # 5.2 [2] (⛄..⛅) snowman without snow..sun behind butt + * + * This will read the file at the given filename, and return an ordered array + * or property lines, with attributes: + * + * {start: number, end: number, property: string} + * + * If the property specifies a single code point (i.e., not a range of code + * points), then end === start. + */ +function readZippedCharacterPropertyFile(filename) { + let textContents = zlib.gunzipSync( + fs.readFileSync(filename) + ).toString('utf8'); + + return textContents.split('\n') + .filter(line => !line.startsWith('#') && line.trim()) + .map(line => { + let [_, startText, endText, property] = line.match( + // Parse lines that look like this: + // 0000 .. 0000 ; CategoryName + /^([0-9A-F]{4,6})(?:..([0-9A-F]{4,6}))?\s+;\s+([A-Za-z_]+)/ + ); + + let start = parseCodepoint(startText); + let end = endText !== undefined ? parseCodepoint(endText) : start; + + return { start, end, property }; + }); +} + +/** + * Parses a code point, expressed as a 4 or 6 digit hexadecimal string. + * Does some bounds checking in order to determine if the string is in fact a + * valid code point. + */ +function parseCodepoint(hexString) { + let number = parseInt(hexString, 16); + if (Number.isNaN(number)) { + throw new SyntaxError(`Cannot parse codepoint: ${hexString}`); + } + + if (number < 0 || number > MAX_CODE_POINT) { + throw new RangeError(`Codepoint out of range: ${number}`); + } + + return number; +} + +function toUnicodeEscape(codePoint) { + let isBMP = codePoint <= 0xFFFF; + let simpleConversion = codePoint.toString(16).toUpperCase(); + + let padding = (isBMP ? 4 : 6) - simpleConversion.length; + let digits = '0'.repeat(padding) + simpleConversion; + + if (isBMP) { + return '\\u' + digits; + } else { + return `\\u{${digits}}`; + } +} + +function utf16AlternativesStrategy() { + let codePoints = []; + for (let {start, end} of extendedPictographicCodePoints) { + for (let current = start; current <= end; current ++) { + codePoints.push(current); + } + } + + let alternatives = codePoints.map(codePointToUTF16Escape); + return `/^(?:${alternatives.join('|')})/`; +} + +function codePointToUTF16Escape(codePoint) { + // Scalar values remain the same + if (codePoint <= 0xFFFF) { + return toUnicodeEscape(codePoint); + } + + const LOWEST_TEN_BITS_MASK = 0x03FF; + let astralBits = codePoint - 0x10000; + + let highSurrogate = 0xD800 + (astralBits >>> 10); + let lowSurrogate = 0xDC00 + (astralBits & LOWEST_TEN_BITS_MASK); + + console.assert(highSurrogate <= 0xDBFF); + console.assert(lowSurrogate <= 0xDFFF); + console.assert(String.fromCharCode(highSurrogate) + String.fromCharCode(lowSurrogate) === + String.fromCodePoint(codePoint)); + return codePointToUTF16Escape(highSurrogate) + codePointToUTF16Escape(lowSurrogate); +} + +function unicodeRangeStrategy() { + let regexp = ''; + for (let {start, end} of extendedPictographicCodePoints) { + if (start === end) { + regexp += toUnicodeEscape(start); + } else { + regexp += toUnicodeEscape(start) + '-' + toUnicodeEscape(end); + } + } + return `/^[${regexp}]/u`; +} + +function makeDense(ranges) { + return joinSameAdjacentProperties(fillInGaps(ranges)); +} + +function ensureDense(ranges) { + let lastEnd = -1; + let lastProperty = 'sot'; + for (let range of ranges) { + let {start, end, property} = range + + if (lastEnd + 1 !== start) { + throw new Error(`Non-adjacent range: ${JSON.stringify(range)}`); + } + + if (lastProperty === property) { + throw new Error(`adjacent ranges have same property: ${JSON.stringify(range)}`); + } + + lastEnd = end; + lastProperty = property; + } +} + + +function joinSameAdjacentProperties(ranges) { + console.assert(ranges.length > 1); + + let conjoinedRanges = []; + conjoinedRanges.push(ranges.shift()); + + for (let range of ranges) { + let lastRange = conjoinedRanges[conjoinedRanges.length - 1]; + if (range.property === lastRange.property) { + lastRange.end = range.end; + } else { + conjoinedRanges.push(range); + } + } + + return conjoinedRanges; +} + +function fillInGaps(ranges) { + console.assert(ranges.length > 1); + + let denseRanges = []; + let nextUnaccountedCodepoint = 0x0000; + + for (let range of ranges) { + if (range.start > nextUnaccountedCodepoint) { + // Need to create a range BEFORE the next start of ranges + denseRanges.push({ + start: nextUnaccountedCodepoint, + end: range.start - 1, + // If it's unassigned in the file, it should be 'Other'. + property: 'Other', + }); + } + + denseRanges.push(range); + nextUnaccountedCodepoint = range.end + 1; + } + + // Create the last range (till the end) + if (nextUnaccountedCodepoint < MAX_CODE_POINT) { + denseRanges.push({ + start: nextUnaccountedCodepoint, + end: MAX_CODE_POINT, + property: 'Other', + }) + } + + return denseRanges; +} \ No newline at end of file diff --git a/common/models/wordbreakers/src/data-compiler/tsconfig.json b/common/models/wordbreakers/src/data-compiler/tsconfig.json index ce66f0bbfc..19f5dfbab0 100644 --- a/common/models/wordbreakers/src/data-compiler/tsconfig.json +++ b/common/models/wordbreakers/src/data-compiler/tsconfig.json @@ -3,9 +3,11 @@ "compilerOptions": { "baseUrl": "./", - "outDir": "../../build/obj", - "tsBuildInfoFile": "../../build/obj/tsconfig.tsbuildinfo", - "rootDir": "./" + "outDir": "../../build/obj/data-compiler", + "tsBuildInfoFile": "../../build/obj/data-compiler/tsconfig.tsbuildinfo", + "rootDir": "./", + "module": "node16", + "moduleResolution": "node16" }, "references": [ { "path": "../../../types" } diff --git a/common/models/wordbreakers/src/imports/WordBreakProperty-13.0.0.txt.gz b/common/models/wordbreakers/src/imports/WordBreakProperty-13.0.0.txt.gz new file mode 100644 index 0000000000000000000000000000000000000000..d3d188ae8249794dfe489b2dabaab286bf7f4725 GIT binary patch literal 23663 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 SwySxQKmGqYUQY-}lK}wuYX*M+ literal 0 HcmV?d00001 diff --git a/common/models/wordbreakers/src/imports/emoji-data-13.0.0.txt.gz b/common/models/wordbreakers/src/imports/emoji-data-13.0.0.txt.gz new file mode 100644 index 0000000000000000000000000000000000000000..bf2d917698e8109106f2ae2da8f778c222ce7f4c GIT binary patch literal 23400 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%0DIL-cBHi5~rE~}k z9TL)wbl2v&@4esmIQFOg2d*Em)^#q|BY`Tj3(9?`G^PU)7G35$btEg~-88iHh8iI{rURU4{LNb!eP+6x^o}7vWm2cCABp|~a2|*v z%w`*~doKVz!+HCkq$#`zQokJ184s)>*=;-1H|Rzi!+oq>0=t8I(M9((>=tArp-_h~Q;t@svl!IC{Hsk9(yCjlb`*F8*ngJNGqUn@>Vp^x;8s+; zpUqa7Od+4YLx?o(GHz{PX^dv@X#TwUg}cqSb(fT1>~Qw-=ML!YoB{2J6okT(d2Ci4 zvE$QL^6~T`TYlR^>bP|6%zZWbs0>D#kMbG-uN1LekLBAqq3u8zgZ!$hIC=vL~k1qj;F7Au8=&s+|d0N7G%+h{GGUR8^E9Z4UqejW8XAkIsKQ@wYFg^-+uHi*;* zb+CKv=4$_sLXn*~A0=$p1X|R^RkPJUE-0=SEgxL8QOwIR<+tM51ENtXIBZo6n3=_T z?H|GH#NRE@G6R%($(=P1FY6OfCo@m`eMsZhWJWhOn9cZEn+lt93f9T2?HJ>i1 zTv}{Nx1W+VDRC#4JWdffv)il^?sPWlJ(3Fl!jG(w*1E6O`dEkx%|ncCD^X+B?09=S z9w3wZ`Sz;0UE{Fm51)5Uh^T#!d)giXC${jL@G5p^`_D}6)dc@blRWp{>(u?({c20$ zRb%|~okB;Azm`UqzUKzcY1(d+2ox>8`(Jzb|uQxA= zEloA%Oa(^ow5?)i{bZ3U9^s1p^?Q$gaui2mvD;Ngx#S0;03Q72IBf*Gc%#d zY{Ve7Y`D5{yzE-vx8BhNI+ohV+>>PuHYcIo1zGqNG6~CwHky_Z#zJ2tG}VT7^`S3j zXncCMwtIW1kJ4zp&qp<|yg>SBouTud;9ATsm%mu~Roo8NOqcIknug1unJHKlc#bU? z*6yO}7&CHE?t*b~C!ASDeqQdPeTNPl|M<%APOanIZ~ppkkOupAs<+u*i<&)+W?gZT z{vI`Jzo~f5gx=Si%I;iq*55fv5hfAHAIo>w)!ht>&qjD&_K85%P=tq}tS?4|vqCIw zz%`5)>%_~)&y9xR)gpFAiVNW86)8Uj~iF#(#DYm=ScHRgvJS}_)t|1l#%?=h$h~0D;k)?&-EjsR4V-ky<_#@ICpL__$ z=)Jlzt2?Il<_z3L?bJG>1UTkuYTxe!c>twEA`)GYD7p_d9g(IoxsY)3lqWRyM$){= zBALlC(k!tULOD5j01FVRzZJQu$@if`@S{IsA;%GE{%V@H+u zoTK0|#zCvA=hiwth$@$)64aYU-GC%$Xjm_>C)~Y);-hqJ-|O^>Ic*F?kWgMv-(q!e zX8uS1=MfCgNH?ozy|;#RkH1=`?gpO&n;3)K2F}vwa(ng7wWuM`)qaoqZu81Lb|$&# zn@0f!U5T3@#}x-7)AprKE-m09p9?M%Tc~qtH6Ru|Y*4{UB^yb8*ZalGNOa8;$Jfj| z8-4E2N0z;thZC-nmX=6f2kstz1Tm~IeKdt z{g`6{e$-?Vkm35}VCA}bI1x?I2R9u~%~1wIGHtscAxkjk^*Y!mv@)LD$s9Je4sWws zK8lTRpRel358>BRskY-G)!q6Ixb!12w0*umV_m5@TZpJHd@|w%x4D6#i@NVFR++2 zd~e*LvRD4o`?tm#L522)vCh<9@(h6eX9brWtob9e_tEi}PZb<4zL|pp&Sl{KW%WE+ zN*9$DRm?5O`La527#%YGm}W=>>!N6&i>kYL{rMVKSJ5m}{-*9}Us<`DyONu5{{~GD zNjN-;9UlGOAZhDHOXMQungT0Ik_Zd`Ae2_OI3*wt^22-NJx>`)I(IcFr+{!}N%SM* z10AKJNVx0uuhZ1S96!|QM4d+FByU&;whKt^p9o4Oo(=Z`%v zY}oyaloHhJ;5_Q@j1-($wt6Yi{*h7-^F>&hJ$%DT^+C+^En^pnEpPaR`Cmcr_t#a#()!Pd19v#%kLa@p(YDJ5kq7vIx&nn}vCGBqkfRz-fN2&(>%mD(Oe z$nM7)Bs}yORimLZZLuDKTph82qpA*9sg@$z{QtF5YQHECBTR532-lL%`A{^`zGCeo zQb1XDtg!P8%$Gv2p0@ktKL&%`xBtJDg1T^jiy5Pw@-_`s=(1 zEUFJ#Tl2F-PEq*Lv^3Q;IcQRE4IK&uuxrEC7wn}z7EeV5cOEtOomzfs|Kb|u;vch# z2+*BPBQ-t{^8p7OMT`$0%lwO_w7lv5!BS_OFI1!cwNnb7d{7bRGp@P6W=2;kSJYp- z_@1LDRPVht9Tu+a2{CCR=M$_yyw!^*?^J~EGKe?1sze6*HOCaGUL%?%pL(*sK4;;X26eli)~>%?;C%{%5oWeY|6wcQ0- zvg<)_1*$dTunmv$zc#DGDSX)NM*q=LoIhT)6l>&vYbnhI-wW--So(o#eZTRrS+3F$ zfZ*4IhMGb#28CqHWS5Oloecw(!AKyX*{H4B-3Vs9K#!0o1=WCkYX?Gmd(5J%7-vJX z+&^Hdg4#?KV`ZwB&(3Npn5ef`WT3WYw00R_yJaX$XyhOK*23bcgGA^WRh&d7=>sTq zZoLI#zJyy-Udyjt!pFE|B*fwrL4m1BXLF9=95FPhmD0qS`(Y^CB+0UT*wv6^k^oOu zgvSy_x34h&BBqQPo!KpV%wQj24?R~C;P3)l1lBKGNvcCUMO%cv^xyZ&h zO%6p&(Z$+_l76B{C>!1$>w4Hlw7y}C^<^?w1}v!XJUq?+UF6S1jRsf0JMN>%I}?4N zE%Q;Lmwj;|+!bvXj%JE)1 zsd8_v{zh7kTp$OOtUVD_K9EMP5nN!Jpsi83SfiKZcjM`A&Eims%q{by%T+7fO!)EA zZ8!e4zj?Hd+n(bt;`TC?53c*r42couJ&=RT$f(2=mFk|oV2W#u176)b(W2Fu=aoU} z!`vC{^kS?eyZrqrky!OtQRZTK$kmXG(v!*r)&Yj1V3=dj0QyFikS&46P;e;P&=X~A zQ3XLCm7`Zo1diZOeS#G-!s5Onfe2l4*D-7jk#z|hY3&Vs_Pk~#U5Y~Th)g{h(Qlsq zuXA7n>B%qUhNwakiH+#G(k;kE(}q8kFm<4@tE_``*qZNjA5?s*K8c zRCuu4ZzJ}@8JJCqy;Ss|VFwXjM0fU>M0y4Lq`ho-8I2{FQb}Qe z#_A0ERW&&03hQ(KZZNh;Nuu_M3Ze$}$yo39v(N1(s8T;)ozPkaNcsqCDTz*hjlq(= z2BiOuJR8Enb~5cr7w>&LB8LuXp*HvI%@pbaP|UWWKrq#kEm-Z(Q^#;lLk4@$e0XE# zK55P!rd8EC(MiR#vCUW$Z(r)Y4gk4 zVb7^xoNh|Qb=*F=d-*VkWajh+2sD~0EI@9q3R)l0^Fgw%)VYRHH2dm zV&bXYT?S}Ik|xUnnS_PvHX*#UI`nZv=T5 z|AIG=jhxsm5zP)#F|k`(el-kE>te?i(g-YO{7d_|Rk1HAc?WHA)!!~k(=APQDHGb5 zn42O%KrVAHn_!c!G)P!|#i9pf=8Wn5Olx~mPc(3xQ8o1it>|1cD_IaNX8cKHy~?2N z{%Zt_N?aTit>tT(-Dg5w>Ac}Ce~qm;uUcU*~zkQ zsxd)Q0}y^gW>=$m^j4c$UU8D(!r&c^ z9P|KBbcfov`;U&toGLtoa#gkUhnpz7my8!s>W&a`FF=3b(A8kj-}*ZT$!T~G)%@ZmIscC*Hz|MpI%Hu2Xm>XWIX3$*2JY;VsA3nIi=j*xV*Fy@tRxLVH#G5C zeKB^w@0ELD`inTv7f%zlcXfe+4EPW*Mpi!A`R4Gu8u5(bLHZ+jFfG5yeIN@*_ zyfo|>hbmoCyeniF_>Va`S|}+M22oB~9mdnCcCH6&QpQq)9;v_tGkLzY3qJ50sMBYwN`CPJjTvx zn3E_doZK!mCjaV4w6jD!Ni_NgLo8Vz?eL1Pec8~nByL0zJc zKR>C$ZBtl$pEs6zSjgP5oSJQcFJ!5G#-;V$T2nrp7Gr%Zi3 z`)+d~m<-f!Db1$D8juxN#yqylVxLw_AJSxCc^B0EH+@vFLvD^mNmJ^(C9*N#H>J8J zu7s};yApC^&Z>rcZY}2(x*O%v+j@(@DitY8zb{v_Q%+1IJ)&dy&dz(}wVRv!r*t}l zAH?rp1YX_6vKx#ObAr-6f`8;c1kcP-buQ6ut;T%oLzLKm2%g(b)0Qj3e7+g2s08|) z+pQm1{q%Bm>XaGpu2Br5eyu{j;LN_=Tv%8&%1Xd!HuD8x;^ZFMiW z(vVDl0DZ!M;VS_rM3d+av-!%(;jF^>Wn>d}AGRWOX54UpaIlFxu{SnTekQRk*;Dzn z5c~*{Sb@fLt&8t+PTHKcKVx2RSb4Wc+x@YIoGA2!1-`e$`6IP2podgil}>LX)nkp9 ztqKYJJ&zy9)~r0I*^vc0$Y$|u7oE{*c?I_)rwBHsq6qGK+V2iAE&v-Ua@13nL*0;{ aQ%ik#j4iV%A}=wXX`((eecZ`JMEEab8)bz6 literal 0 HcmV?d00001 diff --git a/common/models/wordbreakers/tsconfig.json b/common/models/wordbreakers/tsconfig.json index 57df26333b..1cebab27c4 100644 --- a/common/models/wordbreakers/tsconfig.json +++ b/common/models/wordbreakers/tsconfig.json @@ -5,9 +5,12 @@ "baseUrl": "./", "outDir": "build/obj", "tsBuildInfoFile": "build/tsconfig.tsbuildinfo", - "rootDir": "./" + "rootDir": "./", + "module": "Node16", + "moduleResolution": "Node16" }, "references": [ - { "path": "./src/main" } + { "path": "./src/main" }, + { "path": "./src/data-compiler" } ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index f6a9e8a692..9b20b0299c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -109,7 +109,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "ts-node": "^10.9.1", - "typescript": "^4.9.5" + "typescript": "^4.9.5", + "zlib": "^1.0.5" } }, "common/models/wordbreakers/node_modules/@types/node": { @@ -12343,6 +12344,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zlib": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz", + "integrity": "sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w==", + "dev": true, + "hasInstallScript": true, + "engines": { + "node": ">=0.2.0" + } + }, "resources/build/version": { "name": "@keymanapp/auto-history-action", "license": "MIT", From 0b79b86197a2ce335e01b299b634c6a25a2e971f Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 13 Feb 2024 08:26:27 +0700 Subject: [PATCH 04/89] feat(common/models): initial pass for encoded-string wordbreaker data tables --- .../wordbreakers/src/data-compiler/index.ts | 65 +++++++++++++++---- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/common/models/wordbreakers/src/data-compiler/index.ts b/common/models/wordbreakers/src/data-compiler/index.ts index e217bc51f1..f639f670a8 100644 --- a/common/models/wordbreakers/src/data-compiler/index.ts +++ b/common/models/wordbreakers/src/data-compiler/index.ts @@ -95,6 +95,37 @@ const categoryMap = new Map(); for(let cat of categories) { categoryMap.set(cat, catIndexSeed++); + if(catIndexSeed == '`'.charCodeAt(0)) { + catIndexSeed++; // Skip the back-tick as an encoding symbol. + // Reduces complications, as it's the encoding string start/end char. + } +} + +const bmpRanges: typeof ranges = []; +const nonBmpRanges: typeof ranges = []; + +// { start: number, property: number}[] +for(let range of ranges) { // already sorted + if(range.start <= 0xFFFF) { + bmpRanges.push(range); + } else { + if(nonBmpRanges.length == 0) { + const finalBmpRange = bmpRanges[bmpRanges.length - 1]; + bmpRanges.push({ + start: 0xFFFF, + property: range.property, + end: undefined + }); + + nonBmpRanges.push({ + start: 0x10000, + property: finalBmpRange.property, + end: undefined + }); + } + + nonBmpRanges.push(range); + } } //////////////////////// Creating the generated file ///////////////////////// @@ -107,28 +138,40 @@ let stream = fs.createWriteStream(generatedFilename); // Generate the file! stream.write(`// Automatically generated file. DO NOT MODIFY. - /** * Valid values for a word break property. */ export const enum WordBreakProperty { ${ /* Create enum values for each word break property */ Array.from(categories) - .map(x => ` ${x}`) + .map(x => ` ${x} = ${categoryMap.get(x)}`) .join(',\n') } }; -export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ -${ - // TODO: Two versions: one that's BMP-encoded, one that's non-BMP encoded. - ranges.map(({start, property}) => (` [` + - `/*start*/ 0x${start.toString(16).toUpperCase()}, ` + - `WordBreakProperty.${property}],` - )).join('\n') +export const WORD_BREAK_PROPERTY_BMP: string = \`${ + // To consider: emit `\uxxxx` codes instead of the raw char? + bmpRanges.map(({start, property}) => { + let codedStart = String.fromCodePoint(start); + if(codedStart == '`') { + // Prevents accidental unescaped use of the string start/end char. + // The backslash gets removed on file-load. + codedStart = '\\`'; + } + const codedProp = String.fromCharCode(categoryMap.get(property)); + return `${codedStart}${codedProp}`; + }).join('') +}\` + +export const WORD_BREAK_PROPERTY_NON_BMP: string = \`${ + // To consider: emit `\uxxxx` codes instead of the raw char? + nonBmpRanges.map(({start, property}) => { + const codedStart = String.fromCodePoint(start); + const codedProp = String.fromCharCode(categoryMap.get(property)); + return `${codedStart}${codedProp}`; + }).join('') } -]; -`); +\``); /** * Reads a Unicode character property file. From 47d945f30934bd12b0c16af8a104308521ed6cef Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Fri, 16 Feb 2024 11:56:44 +0700 Subject: [PATCH 05/89] fix(web): conditional import path --- common/models/wordbreakers/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index bd530aaeab..774ceee042 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -18,7 +18,7 @@ "types": "build/obj/index.d.ts", "exports": { ".": { - "es6-bundling": "./src/index.ts", + "es6-bundling": "./src/main/index.ts", "default": "./build/obj/index.js" }, "./lib": { From 346556b74f75766d98156724e869ad9218d5d415 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Fri, 16 Feb 2024 11:56:44 +0700 Subject: [PATCH 06/89] fix(web): conditional import path --- common/models/wordbreakers/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index bd530aaeab..774ceee042 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -18,7 +18,7 @@ "types": "build/obj/index.d.ts", "exports": { ".": { - "es6-bundling": "./src/index.ts", + "es6-bundling": "./src/main/index.ts", "default": "./build/obj/index.js" }, "./lib": { From 39ae61a8358cd7988c1d4c3b6c5d6ed323affbe7 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Thu, 6 Jun 2024 16:31:11 +0700 Subject: [PATCH 07/89] fix(mac): add unit tests to confirm first calls to compliance check Also makes public the description method used for logging. A private description method may have been an issue with the older logging code. To build successfully with Xcode, it was necessary to change runOnlyForDeploymentPostprocessing=1. This was apparently needed because of the upgrade to Xcode 15 --- .../Keyman4MacIM.xcodeproj/project.pbxproj | 4 +- .../Keyman4MacIM/TextApiCompliance.h | 1 + .../Keyman4MacIM/TextApiCompliance.m | 2 +- .../KeymanTests/InputMethodTests.m | 53 +++++++++++++++++-- 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj index 35a362f261..8e0b973442 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj +++ b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj @@ -114,13 +114,13 @@ }; E211CCF420B5FE7A00505C36 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; + buildActionMask = 8; dstPath = ""; dstSubfolderSpec = 16; files = ( E211CCF620B600A500505C36 /* KeymanEngine4Mac.framework.dSYM in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 0; + runOnlyForDeploymentPostprocessing = 1; }; E27BA9CF202036BA00D273E7 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.h b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.h index 6c80417faf..81cc4c3b34 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.h +++ b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.h @@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN @property (readonly) NSString *clientApplicationId; -(instancetype)initWithClient:(id) client applicationId:(NSString *)appId; +-(NSString *)description; -(void)checkCompliance:(id) client; -(void) checkComplianceAfterInsert:(id) client delete:(NSString *)textToDelete insert:(NSString *)textToInsert; -(BOOL)isComplianceUncertain; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m index 0f62fa61a8..e83439794b 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m @@ -73,7 +73,7 @@ NSString *const kKMLegacyApps = @"KMLegacyApps"; -(NSString *)description { - return [NSString stringWithFormat:@"complianceUncertain: %d, hasCompliantSelectionApi: %d, canReadText: %d, canReplaceText: %d, mustBackspaceUsingEvents: %d, clientAppId: %@, client: %@", self.complianceUncertain, self.hasCompliantSelectionApi, [self canReadText], [self canReplaceText], [self mustBackspaceUsingEvents], _clientApplicationId, _client]; + return [NSString stringWithFormat:@"complianceUncertain: %d, hasCompliantSelectionApi: %d, canReadText: %d, canReplaceText: %d, mustBackspaceUsingEvents: %d, clientApplicationId: %@, client: %@", self.complianceUncertain, self.hasCompliantSelectionApi, [self canReadText], [self canReplaceText], [self mustBackspaceUsingEvents], _clientApplicationId, _client]; } /** test to see if the API selectedRange functions properly for the text input client */ diff --git a/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m b/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m index 8eb9d974ce..a2953c44cf 100644 --- a/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m +++ b/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m @@ -15,23 +15,27 @@ #import "TextApiCompliance.h" KMInputMethodEventHandler *testEventHandler = nil; +id testClient = nil; @interface InputMethodTests : XCTestCase @end @interface KMInputMethodEventHandler (Testing) - +@property (nonatomic, retain) TextApiCompliance* apiCompliance; +@property (nonatomic, retain) NSString* clientApplicationId; +@property BOOL contextChanged; - (instancetype)initWithClient:(NSString *)clientAppId client:(id) sender; - (NSRange) calculateInsertRangeForDeletedText:(NSString*)textToDelete selectionRange:(NSRange) selection; +- (void)checkTextApiCompliance:(id)client; @end @implementation InputMethodTests - (void)setUp { - id client = [[AppleCompliantTestClient alloc] init]; + testClient = [[AppleCompliantTestClient alloc] init]; NSString *clientAppId = @"com.compliant.app"; - testEventHandler = [[KMInputMethodEventHandler alloc]initWithClient:clientAppId client:client]; + testEventHandler = [[KMInputMethodEventHandler alloc]initWithClient:clientAppId client:testClient]; } - (void)tearDown { @@ -85,4 +89,47 @@ KMInputMethodEventHandler *testEventHandler = nil; XCTAssertTrue(correctResult, @"insert or replacement range expected to be {1,2}"); } +/** + * test compliance check of a KMInputMethodEventHandler with a nil client application ID + * not sure if this can ever happen, but the lifecycle of the input method is not 100% clear, + * and we would like this scenario, if it can occur, to not result in a crash + */ +- (void)testCheckCompliance_withUnknownApplicationId_createsComplianceObject { + id client = [[AppleCompliantTestClient alloc] init]; + //NSString *clientAppId = @"com.compliant.app"; + KMInputMethodEventHandler *eventHandler = [[KMInputMethodEventHandler alloc]initWithClient:nil client:client]; + [eventHandler checkTextApiCompliance:client]; + XCTAssertNotNil(eventHandler.apiCompliance, @"apiCompliance object was not created"); +} + +- (void)testCheckCompliance_withNilComplianceObject_createsComplianceObject { + [testEventHandler checkTextApiCompliance:testClient]; + XCTAssertNotNil(testEventHandler.apiCompliance, @"apiCompliance object was not created"); +} + +- (void)testCheckCompliance_withChangedClientApplicationId_createsNewComplianceObject { + // first call causes textApiCompliance object to be created + [testEventHandler checkTextApiCompliance:testClient]; + TextApiCompliance *originalComplianceObject = testEventHandler.apiCompliance; + + testEventHandler.clientApplicationId = @"com.different.app"; + // second call causes new textApiCompliance object to be created due to stale application ID + [testEventHandler checkTextApiCompliance:testClient]; + XCTAssertNotEqualObjects(originalComplianceObject, testEventHandler.apiCompliance, @"New TextApiCompliance object not created for new client application ID"); +} + +- (void)testCheckCompliance_withContextChanged_createsNewComplianceObject { + // first call causes textApiCompliance object to be created + [testEventHandler checkTextApiCompliance:testClient]; + TextApiCompliance *originalComplianceObject = testEventHandler.apiCompliance; + + testEventHandler.contextChanged = YES; + // second call causes new textApiCompliance object to be created due to setting contextChanged flag + [testEventHandler checkTextApiCompliance:testClient]; + XCTAssertNotEqualObjects(originalComplianceObject, testEventHandler.apiCompliance, @"New TextApiCompliance object not created after contextChanged flag set"); +} + + + + @end From 83c06299ba1bf1996511d762c6f0d093d4e36eb7 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Fri, 7 Jun 2024 09:35:02 +0700 Subject: [PATCH 08/89] fix(mac): rollback runOnlyForDeploymentPostprocessing change break into separate PR --- mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj index 8e0b973442..f0af727d56 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj +++ b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj @@ -114,13 +114,13 @@ }; E211CCF420B5FE7A00505C36 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; + buildActionMask = 12; dstPath = ""; dstSubfolderSpec = 16; files = ( E211CCF620B600A500505C36 /* KeymanEngine4Mac.framework.dSYM in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; }; E27BA9CF202036BA00D273E7 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; From e1f4be9a3ef48b406d478bed7606dd5333932a0b Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:41:34 +1000 Subject: [PATCH 09/89] fix(windows): check IM window will be in a visible location The IM display call back is used to show the IM window. With this change deadcode is removed and a check is made to ensure the IM window is completley visible coordinates for the monitor that has focus. If not it will be position close to where the caret in the application that has focus. --- windows/src/engine/keyman32/calldll.cpp | 64 +++++++++++++++++++------ 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/windows/src/engine/keyman32/calldll.cpp b/windows/src/engine/keyman32/calldll.cpp index c91fab64a9..adab1b7cac 100644 --- a/windows/src/engine/keyman32/calldll.cpp +++ b/windows/src/engine/keyman32/calldll.cpp @@ -438,25 +438,61 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMDisplayIM(HWND hwnd, BOOL FShowAlw *Globals::hwndIM() = hwnd; *Globals::hwndIMAlways() = FShowAlways; - POINT pt; - RECT r; + POINT IMTop, Caret; + RECT RectIM, RectApp; + HWND hFocus; + int n = 0; - GetCaretPos(&pt); + HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + if (hMonitor == NULL) { + return FALSE; + } - int n; - //if(pt.x == 0 && pt.y == 0) - n = SWP_NOMOVE; - //else n = 0; + MONITORINFO monitor_info; + monitor_info.cbSize = sizeof(monitor_info); + if (!GetMonitorInfo(hMonitor, &monitor_info)) { + return FALSE; + } - ClientToScreen(hwndFocus, &pt); - GetWindowRect(hwnd, &r); - if(pt.x + r.right - r.left >= GetSystemMetrics(SM_CXSCREEN)) - pt.x = GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left); + if (!GetWindowRect(hwnd, &RectIM)) { + return FALSE; + } - if(pt.y - (r.bottom-r.top) > 0) pt.y -= (r.bottom-r.top); - else pt.y += 32; // guessing... + // Only adjust the IM window coordinates if it is not going to be visible on the + // monitor it is currently showing on. Otherwise leave it to the 3rd paryt app + // to control the location of the IM Window. + // If changing the coordinates place the IM window use the caret postion of the + // application that has focus. + if ((RectIM.left < monitor_info.rcMonitor.left) || (RectIM.right > monitor_info.rcMonitor.right) || + (RectIM.top < monitor_info.rcMonitor.top) || (RectIM.bottom > monitor_info.rcMonitor.bottom)) { - SetWindowPos(hwnd, HWND_TOPMOST, pt.x,pt.y,0,0, n|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + if (!GetCaretPos(&Caret)) { + return FALSE; + } + + hFocus = GetFocus(); + if (!GetWindowRect(hFocus, &RectApp)) { + return FALSE; + } + + IMTop.x = Caret.x + RectApp.left; + IMTop.y = Caret.y + RectApp.top + 24; + + if (IMTop.x + RectIM.right - RectIM.left > RectApp.right) { + IMTop.x = RectApp.right - (RectIM.right - RectIM.left); + } + + if (IMTop.y + RectIM.bottom - RectIM.top > RectApp.bottom) { + IMTop.y = RectApp.top + Caret.y - (RectIM.bottom - RectIM.top); + } + n = 0; // Move to tracked postion + } else { + IMTop.x = 0; // will be ignored by SWP_NOMOVE; + IMTop.y = 0; + n = SWP_NOMOVE; + } + + SetWindowPos(hwnd, HWND_TOPMOST, IMTop.x, IMTop.y, 0, 0, n|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); //SendDebugMessageFormat(0, sdmKeyboard, 0, "KMDisplayIM: Exit"); return TRUE; } From 13fdfe9f5480d2350999828ad7dae7161f9fe2bb Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:33:38 +1000 Subject: [PATCH 10/89] fix(windows): review comment suggestions Co-authored-by: Eberhard Beilharz --- windows/src/engine/keyman32/calldll.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/windows/src/engine/keyman32/calldll.cpp b/windows/src/engine/keyman32/calldll.cpp index adab1b7cac..59ce4d057e 100644 --- a/windows/src/engine/keyman32/calldll.cpp +++ b/windows/src/engine/keyman32/calldll.cpp @@ -439,11 +439,11 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMDisplayIM(HWND hwnd, BOOL FShowAlw *Globals::hwndIMAlways() = FShowAlways; POINT IMTop, Caret; - RECT RectIM, RectApp; - HWND hFocus; - int n = 0; + RECT RectIM, RectApp; + HWND hFocus; + int n = 0; - HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); if (hMonitor == NULL) { return FALSE; } @@ -459,9 +459,9 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMDisplayIM(HWND hwnd, BOOL FShowAlw } // Only adjust the IM window coordinates if it is not going to be visible on the - // monitor it is currently showing on. Otherwise leave it to the 3rd paryt app + // monitor it is currently showing on. Otherwise leave it to the 3rd party app // to control the location of the IM Window. - // If changing the coordinates place the IM window use the caret postion of the + // If changing the coordinates to place the IM window use the caret postion of the // application that has focus. if ((RectIM.left < monitor_info.rcMonitor.left) || (RectIM.right > monitor_info.rcMonitor.right) || (RectIM.top < monitor_info.rcMonitor.top) || (RectIM.bottom > monitor_info.rcMonitor.bottom)) { From 336db7b5c5d4af80c6dc22a86dcc90a481c3a206 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Fri, 2 Aug 2024 11:15:33 +1000 Subject: [PATCH 11/89] fix(windows): handle IM bigger than app window --- windows/src/engine/keyman32/calldll.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/windows/src/engine/keyman32/calldll.cpp b/windows/src/engine/keyman32/calldll.cpp index 59ce4d057e..2c93b0584b 100644 --- a/windows/src/engine/keyman32/calldll.cpp +++ b/windows/src/engine/keyman32/calldll.cpp @@ -477,9 +477,16 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMDisplayIM(HWND hwnd, BOOL FShowAlw IMTop.x = Caret.x + RectApp.left; IMTop.y = Caret.y + RectApp.top + 24; + LONG IMWidth = RectIM.right - RectIM.left; - if (IMTop.x + RectIM.right - RectIM.left > RectApp.right) { - IMTop.x = RectApp.right - (RectIM.right - RectIM.left); + if (IMTop.x + IMWidth > RectApp.right) { + // align IM right edge with App right edge + if (IMWidth < (RectApp.right - RectApp.left)) { + IMTop.x = RectApp.right - IMWidth; + } + else { // align IM left edge with App left edge + IMTop.x = RectApp.left; + } } if (IMTop.y + RectIM.bottom - RectIM.top > RectApp.bottom) { From cc023dd5af8ad9b196bbad5b0281929209f33570 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 6 Aug 2024 13:36:30 +0700 Subject: [PATCH 12/89] chore(common/models): reverts unneeded addition of zlib --- common/models/wordbreakers/package.json | 3 +- .../wordbreakers/src/data-compiler/index.ts | 71 +++++++++++++------ package-lock.json | 13 +--- 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index 0ca47c6f21..c2b295ec42 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -60,8 +60,7 @@ "c8": "^7.12.0", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "typescript": "^5.4.5", - "zlib": "^1.0.5" + "typescript": "^5.4.5" }, "type": "module" } diff --git a/common/models/wordbreakers/src/data-compiler/index.ts b/common/models/wordbreakers/src/data-compiler/index.ts index e217bc51f1..3ef1dc1fc7 100644 --- a/common/models/wordbreakers/src/data-compiler/index.ts +++ b/common/models/wordbreakers/src/data-compiler/index.ts @@ -4,10 +4,8 @@ // TODO: Adapt to produce two string-encoded arrays - one for BMP chars, one for non-BMP chars. -import zlib from 'zlib'; import fs from 'fs'; import path from 'path'; -import { fileURLToPath } from 'url'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); @@ -27,13 +25,13 @@ const require = createRequire(import.meta.url); const MAX_CODE_POINT = 0x10FFFF; // Where to get the data: -// - http://www.unicode.org/reports/tr51/#emoji_data -// - https://www.unicode.org/reports/tr41/tr41-26.html#Props0 +// - https://www.unicode.org/reports/tr51/#emoji_data +// - https://www.unicode.org/reports/tr41/#Props0 //////////////////////////////////// Main //////////////////////////////////// const projectDir = path.dirname(require.resolve("@keymanapp/models-wordbreakers/UNICODE_VERSION.md")); -const generatedFilename = path.join(projectDir, 'src', 'main', 'default', 'data_test.ts'); +const generatedFilename = path.join(projectDir, 'src', 'main', 'default', 'data.ts'); // Ensure this package's major version number is in sync with the Unicode // major version. @@ -43,14 +41,20 @@ const UNICODE_VERSION = packageVersion.split('.')[0] + '.0.0'; // The data files should be in this repository, with names matching the // Unicode version. -let wordBoundaryFilename = path.join(projectDir, `./src/imports/WordBreakProperty-${UNICODE_VERSION}.txt.gz`); -let emojiDataFilename = path.join(projectDir, `./src/imports/emoji-data-${UNICODE_VERSION}.txt.gz`); +let wordBoundaryFilename = path.join(projectDir, `./src/imports/WordBreakProperty-${UNICODE_VERSION}.txt`); +let emojiDataFilename = path.join(projectDir, `./src/imports/emoji-data-${UNICODE_VERSION}.txt`); ///////////////////////////// Word_Boundary file ///////////////////////////// +interface DataRange { + start: number; + end: number; + property: string; +} + // Extract the ranges IN ASCENDING ORDER from the file. // This will be the big binary search table. -let ranges = readZippedCharacterPropertyFile(wordBoundaryFilename) +let ranges = readCharacterPropertyFile(wordBoundaryFilename) .sort((a, b) => { return a.start - b.start; }); @@ -71,22 +75,22 @@ categories.add('eot'); ///////////////////////// Extended_Pictographic=Yes ////////////////////////// -let extendedPictographicCodePoints = readZippedCharacterPropertyFile(emojiDataFilename) +let extendedPictographicCodePoints = readCharacterPropertyFile(emojiDataFilename) .filter(({property}) => property === 'Extended_Pictographic'); // Try generating the regular expression both in a way that is // backwards-compatbile and one that only works in ES6+. -let extendedPictographicRegExp; +// let extendedPictographicRegExp; let compatibleRegexp = utf16AlternativesStrategy(); let es6Regexp = unicodeRangeStrategy(); // Choose the shortest regular expression. // In my experience, the ES6 regexp is an order of magnitude smaller! if (es6Regexp.length < compatibleRegexp.length) { - extendedPictographicRegExp = es6Regexp; + // extendedPictographicRegExp = es6Regexp; console.warn(`Using ES6 regexp [${es6Regexp.length} chars]`); } else { - extendedPictographicRegExp = compatibleRegexp; + // extendedPictographicRegExp = compatibleRegexp; console.warn(`Using compatibility regexp [${compatibleRegexp.length} chars]`); } @@ -110,6 +114,9 @@ stream.write(`// Automatically generated file. DO NOT MODIFY. /** * Valid values for a word break property. + * + * Is optimized away at compile-time; use \`propertyMap\` to find the mapped + * value at runtime for a property name if needed. */ export const enum WordBreakProperty { ${ /* Create enum values for each word break property */ @@ -119,6 +126,26 @@ ${ /* Create enum values for each word break property */ } }; +/** + * Contains property names per associated index, as this is compiled away + * by TypeScript for \`const enum\` cases like \`WordBreakProperty\`. + */ +export const propertyMap = [ +${ /* Enumerate the plain-text names for ease of lookup at runtime */ + Array.from(categories) + .map(x => ` "${x}"`) + .join(',\n') +} +]; + +/** + * Constants for indexing values in WORD_BREAK_PROPERTY. + */ +export const enum I { + Start = 0, + Value = 1 +} + export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ ${ // TODO: Two versions: one that's BMP-encoded, one that's non-BMP encoded. @@ -151,10 +178,8 @@ ${ * If the property specifies a single code point (i.e., not a range of code * points), then end === start. */ -function readZippedCharacterPropertyFile(filename) { - let textContents = zlib.gunzipSync( - fs.readFileSync(filename) - ).toString('utf8'); +function readCharacterPropertyFile(filename: string) { + let textContents = fs.readFileSync(filename, { encoding: 'utf8'}); return textContents.split('\n') .filter(line => !line.startsWith('#') && line.trim()) @@ -177,7 +202,7 @@ function readZippedCharacterPropertyFile(filename) { * Does some bounds checking in order to determine if the string is in fact a * valid code point. */ -function parseCodepoint(hexString) { +function parseCodepoint(hexString: string) { let number = parseInt(hexString, 16); if (Number.isNaN(number)) { throw new SyntaxError(`Cannot parse codepoint: ${hexString}`); @@ -190,7 +215,7 @@ function parseCodepoint(hexString) { return number; } -function toUnicodeEscape(codePoint) { +function toUnicodeEscape(codePoint: number) { let isBMP = codePoint <= 0xFFFF; let simpleConversion = codePoint.toString(16).toUpperCase(); @@ -216,7 +241,7 @@ function utf16AlternativesStrategy() { return `/^(?:${alternatives.join('|')})/`; } -function codePointToUTF16Escape(codePoint) { +function codePointToUTF16Escape(codePoint: number): string { // Scalar values remain the same if (codePoint <= 0xFFFF) { return toUnicodeEscape(codePoint); @@ -247,11 +272,11 @@ function unicodeRangeStrategy() { return `/^[${regexp}]/u`; } -function makeDense(ranges) { +function makeDense(ranges: DataRange[]) { return joinSameAdjacentProperties(fillInGaps(ranges)); } -function ensureDense(ranges) { +function ensureDense(ranges: DataRange[]) { let lastEnd = -1; let lastProperty = 'sot'; for (let range of ranges) { @@ -271,7 +296,7 @@ function ensureDense(ranges) { } -function joinSameAdjacentProperties(ranges) { +function joinSameAdjacentProperties(ranges: DataRange[]) { console.assert(ranges.length > 1); let conjoinedRanges = []; @@ -289,7 +314,7 @@ function joinSameAdjacentProperties(ranges) { return conjoinedRanges; } -function fillInGaps(ranges) { +function fillInGaps(ranges: DataRange[]) { console.assert(ranges.length > 1); let denseRanges = []; diff --git a/package-lock.json b/package-lock.json index 995617cfb1..2f2ca04142 100644 --- a/package-lock.json +++ b/package-lock.json @@ -105,8 +105,7 @@ "c8": "^7.12.0", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "typescript": "^5.4.5", - "zlib": "^1.0.5" + "typescript": "^5.4.5" } }, "common/predictive-text": { @@ -14431,16 +14430,6 @@ "node": "^12.20.0 || >=14" } }, - "node_modules/zlib": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz", - "integrity": "sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w==", - "dev": true, - "hasInstallScript": true, - "engines": { - "node": ">=0.2.0" - } - }, "node_modules/zod": { "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", From fd8b260865fad11155271d548cefa91513c8e9d9 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 6 Aug 2024 14:46:13 +0700 Subject: [PATCH 13/89] change(common/models): adds unicode-data downloader --- .../WordBreakProperty.txt | 1468 +++++++++++++++++ .../unicode-character-database/build.sh | 66 + .../unicode-character-database/emoji-data.txt | 1320 +++++++++++++++ .../unicode-copyright.txt | 56 - 4 files changed, 2854 insertions(+), 56 deletions(-) create mode 100644 resources/standards-data/unicode-character-database/WordBreakProperty.txt create mode 100755 resources/standards-data/unicode-character-database/build.sh create mode 100644 resources/standards-data/unicode-character-database/emoji-data.txt delete mode 100644 resources/standards-data/unicode-character-database/unicode-copyright.txt diff --git a/resources/standards-data/unicode-character-database/WordBreakProperty.txt b/resources/standards-data/unicode-character-database/WordBreakProperty.txt new file mode 100644 index 0000000000..302a2769b3 --- /dev/null +++ b/resources/standards-data/unicode-character-database/WordBreakProperty.txt @@ -0,0 +1,1468 @@ +# WordBreakProperty-15.1.0.txt +# Date: 2023-03-31, 03:19:05 GMT +# © 2023 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see https://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see https://www.unicode.org/reports/tr44/ + +# ================================================ + +# Property: Word_Break + +# All code points not explicitly listed for Word_Break +# have the value Other (XX). + +# @missing: 0000..10FFFF; Other + +# ================================================ + +0022 ; Double_Quote # Po QUOTATION MARK + +# Total code points: 1 + +# ================================================ + +0027 ; Single_Quote # Po APOSTROPHE + +# Total code points: 1 + +# ================================================ + +05D0..05EA ; Hebrew_Letter # Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV +05EF..05F2 ; Hebrew_Letter # Lo [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD +FB1D ; Hebrew_Letter # Lo HEBREW LETTER YOD WITH HIRIQ +FB1F..FB28 ; Hebrew_Letter # Lo [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV +FB2A..FB36 ; Hebrew_Letter # Lo [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH +FB38..FB3C ; Hebrew_Letter # Lo [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH +FB3E ; Hebrew_Letter # Lo HEBREW LETTER MEM WITH DAGESH +FB40..FB41 ; Hebrew_Letter # Lo [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH +FB43..FB44 ; Hebrew_Letter # Lo [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH +FB46..FB4F ; Hebrew_Letter # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED + +# Total code points: 75 + +# ================================================ + +000D ; CR # Cc + +# Total code points: 1 + +# ================================================ + +000A ; LF # Cc + +# Total code points: 1 + +# ================================================ + +000B..000C ; Newline # Cc [2] .. +0085 ; Newline # Cc +2028 ; Newline # Zl LINE SEPARATOR +2029 ; Newline # Zp PARAGRAPH SEPARATOR + +# Total code points: 5 + +# ================================================ + +0300..036F ; Extend # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X +0483..0487 ; Extend # Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE +0488..0489 ; Extend # Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN +0591..05BD ; Extend # Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG +05BF ; Extend # Mn HEBREW POINT RAFE +05C1..05C2 ; Extend # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT +05C4..05C5 ; Extend # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT +05C7 ; Extend # Mn HEBREW POINT QAMATS QATAN +0610..061A ; Extend # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA +064B..065F ; Extend # Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW +0670 ; Extend # Mn ARABIC LETTER SUPERSCRIPT ALEF +06D6..06DC ; Extend # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN +06DF..06E4 ; Extend # Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA +06E7..06E8 ; Extend # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON +06EA..06ED ; Extend # Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM +0711 ; Extend # Mn SYRIAC LETTER SUPERSCRIPT ALAPH +0730..074A ; Extend # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH +07A6..07B0 ; Extend # Mn [11] THAANA ABAFILI..THAANA SUKUN +07EB..07F3 ; Extend # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE +07FD ; Extend # Mn NKO DANTAYALAN +0816..0819 ; Extend # Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH +081B..0823 ; Extend # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A +0825..0827 ; Extend # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U +0829..082D ; Extend # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA +0859..085B ; Extend # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK +0898..089F ; Extend # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA +08CA..08E1 ; Extend # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA +08E3..0902 ; Extend # Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA +0903 ; Extend # Mc DEVANAGARI SIGN VISARGA +093A ; Extend # Mn DEVANAGARI VOWEL SIGN OE +093B ; Extend # Mc DEVANAGARI VOWEL SIGN OOE +093C ; Extend # Mn DEVANAGARI SIGN NUKTA +093E..0940 ; Extend # Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II +0941..0948 ; Extend # Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI +0949..094C ; Extend # Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU +094D ; Extend # Mn DEVANAGARI SIGN VIRAMA +094E..094F ; Extend # Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW +0951..0957 ; Extend # Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE +0962..0963 ; Extend # Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL +0981 ; Extend # Mn BENGALI SIGN CANDRABINDU +0982..0983 ; Extend # Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA +09BC ; Extend # Mn BENGALI SIGN NUKTA +09BE..09C0 ; Extend # Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II +09C1..09C4 ; Extend # Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR +09C7..09C8 ; Extend # Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI +09CB..09CC ; Extend # Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU +09CD ; Extend # Mn BENGALI SIGN VIRAMA +09D7 ; Extend # Mc BENGALI AU LENGTH MARK +09E2..09E3 ; Extend # Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL +09FE ; Extend # Mn BENGALI SANDHI MARK +0A01..0A02 ; Extend # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI +0A03 ; Extend # Mc GURMUKHI SIGN VISARGA +0A3C ; Extend # Mn GURMUKHI SIGN NUKTA +0A3E..0A40 ; Extend # Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II +0A41..0A42 ; Extend # Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU +0A47..0A48 ; Extend # Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI +0A4B..0A4D ; Extend # Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA +0A51 ; Extend # Mn GURMUKHI SIGN UDAAT +0A70..0A71 ; Extend # Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK +0A75 ; Extend # Mn GURMUKHI SIGN YAKASH +0A81..0A82 ; Extend # Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA +0A83 ; Extend # Mc GUJARATI SIGN VISARGA +0ABC ; Extend # Mn GUJARATI SIGN NUKTA +0ABE..0AC0 ; Extend # Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II +0AC1..0AC5 ; Extend # Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E +0AC7..0AC8 ; Extend # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI +0AC9 ; Extend # Mc GUJARATI VOWEL SIGN CANDRA O +0ACB..0ACC ; Extend # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU +0ACD ; Extend # Mn GUJARATI SIGN VIRAMA +0AE2..0AE3 ; Extend # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL +0AFA..0AFF ; Extend # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE +0B01 ; Extend # Mn ORIYA SIGN CANDRABINDU +0B02..0B03 ; Extend # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA +0B3C ; Extend # Mn ORIYA SIGN NUKTA +0B3E ; Extend # Mc ORIYA VOWEL SIGN AA +0B3F ; Extend # Mn ORIYA VOWEL SIGN I +0B40 ; Extend # Mc ORIYA VOWEL SIGN II +0B41..0B44 ; Extend # Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR +0B47..0B48 ; Extend # Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI +0B4B..0B4C ; Extend # Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU +0B4D ; Extend # Mn ORIYA SIGN VIRAMA +0B55..0B56 ; Extend # Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK +0B57 ; Extend # Mc ORIYA AU LENGTH MARK +0B62..0B63 ; Extend # Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL +0B82 ; Extend # Mn TAMIL SIGN ANUSVARA +0BBE..0BBF ; Extend # Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I +0BC0 ; Extend # Mn TAMIL VOWEL SIGN II +0BC1..0BC2 ; Extend # Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU +0BC6..0BC8 ; Extend # Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI +0BCA..0BCC ; Extend # Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU +0BCD ; Extend # Mn TAMIL SIGN VIRAMA +0BD7 ; Extend # Mc TAMIL AU LENGTH MARK +0C00 ; Extend # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE +0C01..0C03 ; Extend # Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA +0C04 ; Extend # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE +0C3C ; Extend # Mn TELUGU SIGN NUKTA +0C3E..0C40 ; Extend # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II +0C41..0C44 ; Extend # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR +0C46..0C48 ; Extend # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI +0C4A..0C4D ; Extend # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA +0C55..0C56 ; Extend # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK +0C62..0C63 ; Extend # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL +0C81 ; Extend # Mn KANNADA SIGN CANDRABINDU +0C82..0C83 ; Extend # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA +0CBC ; Extend # Mn KANNADA SIGN NUKTA +0CBE ; Extend # Mc KANNADA VOWEL SIGN AA +0CBF ; Extend # Mn KANNADA VOWEL SIGN I +0CC0..0CC4 ; Extend # Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR +0CC6 ; Extend # Mn KANNADA VOWEL SIGN E +0CC7..0CC8 ; Extend # Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI +0CCA..0CCB ; Extend # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO +0CCC..0CCD ; Extend # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA +0CD5..0CD6 ; Extend # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK +0CE2..0CE3 ; Extend # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL +0CF3 ; Extend # Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT +0D00..0D01 ; Extend # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU +0D02..0D03 ; Extend # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA +0D3B..0D3C ; Extend # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA +0D3E..0D40 ; Extend # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II +0D41..0D44 ; Extend # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR +0D46..0D48 ; Extend # Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI +0D4A..0D4C ; Extend # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU +0D4D ; Extend # Mn MALAYALAM SIGN VIRAMA +0D57 ; Extend # Mc MALAYALAM AU LENGTH MARK +0D62..0D63 ; Extend # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL +0D81 ; Extend # Mn SINHALA SIGN CANDRABINDU +0D82..0D83 ; Extend # Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA +0DCA ; Extend # Mn SINHALA SIGN AL-LAKUNA +0DCF..0DD1 ; Extend # Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA +0DD2..0DD4 ; Extend # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA +0DD6 ; Extend # Mn SINHALA VOWEL SIGN DIGA PAA-PILLA +0DD8..0DDF ; Extend # Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA +0DF2..0DF3 ; Extend # Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA +0E31 ; Extend # Mn THAI CHARACTER MAI HAN-AKAT +0E34..0E3A ; Extend # Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU +0E47..0E4E ; Extend # Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN +0EB1 ; Extend # Mn LAO VOWEL SIGN MAI KAN +0EB4..0EBC ; Extend # Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO +0EC8..0ECE ; Extend # Mn [7] LAO TONE MAI EK..LAO YAMAKKAN +0F18..0F19 ; Extend # Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS +0F35 ; Extend # Mn TIBETAN MARK NGAS BZUNG NYI ZLA +0F37 ; Extend # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS +0F39 ; Extend # Mn TIBETAN MARK TSA -PHRU +0F3E..0F3F ; Extend # Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES +0F71..0F7E ; Extend # Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO +0F7F ; Extend # Mc TIBETAN SIGN RNAM BCAD +0F80..0F84 ; Extend # Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA +0F86..0F87 ; Extend # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS +0F8D..0F97 ; Extend # Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA +0F99..0FBC ; Extend # Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA +0FC6 ; Extend # Mn TIBETAN SYMBOL PADMA GDAN +102B..102C ; Extend # Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA +102D..1030 ; Extend # Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU +1031 ; Extend # Mc MYANMAR VOWEL SIGN E +1032..1037 ; Extend # Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW +1038 ; Extend # Mc MYANMAR SIGN VISARGA +1039..103A ; Extend # Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT +103B..103C ; Extend # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA +103D..103E ; Extend # Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA +1056..1057 ; Extend # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR +1058..1059 ; Extend # Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL +105E..1060 ; Extend # Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA +1062..1064 ; Extend # Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO +1067..106D ; Extend # Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5 +1071..1074 ; Extend # Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE +1082 ; Extend # Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA +1083..1084 ; Extend # Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E +1085..1086 ; Extend # Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y +1087..108C ; Extend # Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3 +108D ; Extend # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE +108F ; Extend # Mc MYANMAR SIGN RUMAI PALAUNG TONE-5 +109A..109C ; Extend # Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A +109D ; Extend # Mn MYANMAR VOWEL SIGN AITON AI +135D..135F ; Extend # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK +1712..1714 ; Extend # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA +1715 ; Extend # Mc TAGALOG SIGN PAMUDPOD +1732..1733 ; Extend # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U +1734 ; Extend # Mc HANUNOO SIGN PAMUDPOD +1752..1753 ; Extend # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U +1772..1773 ; Extend # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U +17B4..17B5 ; Extend # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA +17B6 ; Extend # Mc KHMER VOWEL SIGN AA +17B7..17BD ; Extend # Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA +17BE..17C5 ; Extend # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU +17C6 ; Extend # Mn KHMER SIGN NIKAHIT +17C7..17C8 ; Extend # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU +17C9..17D3 ; Extend # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT +17DD ; Extend # Mn KHMER SIGN ATTHACAN +180B..180D ; Extend # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE +180F ; Extend # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR +1885..1886 ; Extend # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA +18A9 ; Extend # Mn MONGOLIAN LETTER ALI GALI DAGALGA +1920..1922 ; Extend # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U +1923..1926 ; Extend # Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU +1927..1928 ; Extend # Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O +1929..192B ; Extend # Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA +1930..1931 ; Extend # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA +1932 ; Extend # Mn LIMBU SMALL LETTER ANUSVARA +1933..1938 ; Extend # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA +1939..193B ; Extend # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I +1A17..1A18 ; Extend # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U +1A19..1A1A ; Extend # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O +1A1B ; Extend # Mn BUGINESE VOWEL SIGN AE +1A55 ; Extend # Mc TAI THAM CONSONANT SIGN MEDIAL RA +1A56 ; Extend # Mn TAI THAM CONSONANT SIGN MEDIAL LA +1A57 ; Extend # Mc TAI THAM CONSONANT SIGN LA TANG LAI +1A58..1A5E ; Extend # Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA +1A60 ; Extend # Mn TAI THAM SIGN SAKOT +1A61 ; Extend # Mc TAI THAM VOWEL SIGN A +1A62 ; Extend # Mn TAI THAM VOWEL SIGN MAI SAT +1A63..1A64 ; Extend # Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA +1A65..1A6C ; Extend # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW +1A6D..1A72 ; Extend # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI +1A73..1A7C ; Extend # Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN +1A7F ; Extend # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT +1AB0..1ABD ; Extend # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW +1ABE ; Extend # Me COMBINING PARENTHESES OVERLAY +1ABF..1ACE ; Extend # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T +1B00..1B03 ; Extend # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG +1B04 ; Extend # Mc BALINESE SIGN BISAH +1B34 ; Extend # Mn BALINESE SIGN REREKAN +1B35 ; Extend # Mc BALINESE VOWEL SIGN TEDUNG +1B36..1B3A ; Extend # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA +1B3B ; Extend # Mc BALINESE VOWEL SIGN RA REPA TEDUNG +1B3C ; Extend # Mn BALINESE VOWEL SIGN LA LENGA +1B3D..1B41 ; Extend # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG +1B42 ; Extend # Mn BALINESE VOWEL SIGN PEPET +1B43..1B44 ; Extend # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG +1B6B..1B73 ; Extend # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG +1B80..1B81 ; Extend # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR +1B82 ; Extend # Mc SUNDANESE SIGN PANGWISAD +1BA1 ; Extend # Mc SUNDANESE CONSONANT SIGN PAMINGKAL +1BA2..1BA5 ; Extend # Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU +1BA6..1BA7 ; Extend # Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG +1BA8..1BA9 ; Extend # Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG +1BAA ; Extend # Mc SUNDANESE SIGN PAMAAEH +1BAB..1BAD ; Extend # Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA +1BE6 ; Extend # Mn BATAK SIGN TOMPI +1BE7 ; Extend # Mc BATAK VOWEL SIGN E +1BE8..1BE9 ; Extend # Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE +1BEA..1BEC ; Extend # Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O +1BED ; Extend # Mn BATAK VOWEL SIGN KARO O +1BEE ; Extend # Mc BATAK VOWEL SIGN U +1BEF..1BF1 ; Extend # Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H +1BF2..1BF3 ; Extend # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN +1C24..1C2B ; Extend # Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU +1C2C..1C33 ; Extend # Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T +1C34..1C35 ; Extend # Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG +1C36..1C37 ; Extend # Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA +1CD0..1CD2 ; Extend # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA +1CD4..1CE0 ; Extend # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA +1CE1 ; Extend # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA +1CE2..1CE8 ; Extend # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL +1CED ; Extend # Mn VEDIC SIGN TIRYAK +1CF4 ; Extend # Mn VEDIC TONE CANDRA ABOVE +1CF7 ; Extend # Mc VEDIC SIGN ATIKRAMA +1CF8..1CF9 ; Extend # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE +1DC0..1DFF ; Extend # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +200C ; Extend # Cf ZERO WIDTH NON-JOINER +20D0..20DC ; Extend # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE +20DD..20E0 ; Extend # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH +20E1 ; Extend # Mn COMBINING LEFT RIGHT ARROW ABOVE +20E2..20E4 ; Extend # Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE +20E5..20F0 ; Extend # Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE +2CEF..2CF1 ; Extend # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS +2D7F ; Extend # Mn TIFINAGH CONSONANT JOINER +2DE0..2DFF ; Extend # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS +302A..302D ; Extend # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK +302E..302F ; Extend # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK +3099..309A ; Extend # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK +A66F ; Extend # Mn COMBINING CYRILLIC VZMET +A670..A672 ; Extend # Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN +A674..A67D ; Extend # Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK +A69E..A69F ; Extend # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E +A6F0..A6F1 ; Extend # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS +A802 ; Extend # Mn SYLOTI NAGRI SIGN DVISVARA +A806 ; Extend # Mn SYLOTI NAGRI SIGN HASANTA +A80B ; Extend # Mn SYLOTI NAGRI SIGN ANUSVARA +A823..A824 ; Extend # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I +A825..A826 ; Extend # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E +A827 ; Extend # Mc SYLOTI NAGRI VOWEL SIGN OO +A82C ; Extend # Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA +A880..A881 ; Extend # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA +A8B4..A8C3 ; Extend # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU +A8C4..A8C5 ; Extend # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU +A8E0..A8F1 ; Extend # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA +A8FF ; Extend # Mn DEVANAGARI VOWEL SIGN AY +A926..A92D ; Extend # Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU +A947..A951 ; Extend # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R +A952..A953 ; Extend # Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA +A980..A982 ; Extend # Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR +A983 ; Extend # Mc JAVANESE SIGN WIGNYAN +A9B3 ; Extend # Mn JAVANESE SIGN CECAK TELU +A9B4..A9B5 ; Extend # Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG +A9B6..A9B9 ; Extend # Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT +A9BA..A9BB ; Extend # Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE +A9BC..A9BD ; Extend # Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET +A9BE..A9C0 ; Extend # Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON +A9E5 ; Extend # Mn MYANMAR SIGN SHAN SAW +AA29..AA2E ; Extend # Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE +AA2F..AA30 ; Extend # Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI +AA31..AA32 ; Extend # Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE +AA33..AA34 ; Extend # Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA +AA35..AA36 ; Extend # Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA +AA43 ; Extend # Mn CHAM CONSONANT SIGN FINAL NG +AA4C ; Extend # Mn CHAM CONSONANT SIGN FINAL M +AA4D ; Extend # Mc CHAM CONSONANT SIGN FINAL H +AA7B ; Extend # Mc MYANMAR SIGN PAO KAREN TONE +AA7C ; Extend # Mn MYANMAR SIGN TAI LAING TONE-2 +AA7D ; Extend # Mc MYANMAR SIGN TAI LAING TONE-5 +AAB0 ; Extend # Mn TAI VIET MAI KANG +AAB2..AAB4 ; Extend # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U +AAB7..AAB8 ; Extend # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA +AABE..AABF ; Extend # Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK +AAC1 ; Extend # Mn TAI VIET TONE MAI THO +AAEB ; Extend # Mc MEETEI MAYEK VOWEL SIGN II +AAEC..AAED ; Extend # Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI +AAEE..AAEF ; Extend # Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU +AAF5 ; Extend # Mc MEETEI MAYEK VOWEL SIGN VISARGA +AAF6 ; Extend # Mn MEETEI MAYEK VIRAMA +ABE3..ABE4 ; Extend # Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP +ABE5 ; Extend # Mn MEETEI MAYEK VOWEL SIGN ANAP +ABE6..ABE7 ; Extend # Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP +ABE8 ; Extend # Mn MEETEI MAYEK VOWEL SIGN UNAP +ABE9..ABEA ; Extend # Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG +ABEC ; Extend # Mc MEETEI MAYEK LUM IYEK +ABED ; Extend # Mn MEETEI MAYEK APUN IYEK +FB1E ; Extend # Mn HEBREW POINT JUDEO-SPANISH VARIKA +FE00..FE0F ; Extend # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 +FE20..FE2F ; Extend # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF +FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK +101FD ; Extend # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE +102E0 ; Extend # Mn COPTIC EPACT THOUSANDS MARK +10376..1037A ; Extend # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII +10A01..10A03 ; Extend # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R +10A05..10A06 ; Extend # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O +10A0C..10A0F ; Extend # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA +10A38..10A3A ; Extend # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW +10A3F ; Extend # Mn KHAROSHTHI VIRAMA +10AE5..10AE6 ; Extend # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW +10D24..10D27 ; Extend # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI +10EAB..10EAC ; Extend # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK +10EFD..10EFF ; Extend # Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA +10F46..10F50 ; Extend # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW +10F82..10F85 ; Extend # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW +11000 ; Extend # Mc BRAHMI SIGN CANDRABINDU +11001 ; Extend # Mn BRAHMI SIGN ANUSVARA +11002 ; Extend # Mc BRAHMI SIGN VISARGA +11038..11046 ; Extend # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA +11070 ; Extend # Mn BRAHMI SIGN OLD TAMIL VIRAMA +11073..11074 ; Extend # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O +1107F..11081 ; Extend # Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA +11082 ; Extend # Mc KAITHI SIGN VISARGA +110B0..110B2 ; Extend # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II +110B3..110B6 ; Extend # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI +110B7..110B8 ; Extend # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU +110B9..110BA ; Extend # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA +110C2 ; Extend # Mn KAITHI VOWEL SIGN VOCALIC R +11100..11102 ; Extend # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA +11127..1112B ; Extend # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU +1112C ; Extend # Mc CHAKMA VOWEL SIGN E +1112D..11134 ; Extend # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA +11145..11146 ; Extend # Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI +11173 ; Extend # Mn MAHAJANI SIGN NUKTA +11180..11181 ; Extend # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA +11182 ; Extend # Mc SHARADA SIGN VISARGA +111B3..111B5 ; Extend # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II +111B6..111BE ; Extend # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O +111BF..111C0 ; Extend # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA +111C9..111CC ; Extend # Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK +111CE ; Extend # Mc SHARADA VOWEL SIGN PRISHTHAMATRA E +111CF ; Extend # Mn SHARADA SIGN INVERTED CANDRABINDU +1122C..1122E ; Extend # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II +1122F..11231 ; Extend # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI +11232..11233 ; Extend # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU +11234 ; Extend # Mn KHOJKI SIGN ANUSVARA +11235 ; Extend # Mc KHOJKI SIGN VIRAMA +11236..11237 ; Extend # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA +1123E ; Extend # Mn KHOJKI SIGN SUKUN +11241 ; Extend # Mn KHOJKI VOWEL SIGN VOCALIC R +112DF ; Extend # Mn KHUDAWADI SIGN ANUSVARA +112E0..112E2 ; Extend # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II +112E3..112EA ; Extend # Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA +11300..11301 ; Extend # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU +11302..11303 ; Extend # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA +1133B..1133C ; Extend # Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA +1133E..1133F ; Extend # Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I +11340 ; Extend # Mn GRANTHA VOWEL SIGN II +11341..11344 ; Extend # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR +11347..11348 ; Extend # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI +1134B..1134D ; Extend # Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA +11357 ; Extend # Mc GRANTHA AU LENGTH MARK +11362..11363 ; Extend # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL +11366..1136C ; Extend # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX +11370..11374 ; Extend # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA +11435..11437 ; Extend # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II +11438..1143F ; Extend # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI +11440..11441 ; Extend # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU +11442..11444 ; Extend # Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA +11445 ; Extend # Mc NEWA SIGN VISARGA +11446 ; Extend # Mn NEWA SIGN NUKTA +1145E ; Extend # Mn NEWA SANDHI MARK +114B0..114B2 ; Extend # Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II +114B3..114B8 ; Extend # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL +114B9 ; Extend # Mc TIRHUTA VOWEL SIGN E +114BA ; Extend # Mn TIRHUTA VOWEL SIGN SHORT E +114BB..114BE ; Extend # Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU +114BF..114C0 ; Extend # Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA +114C1 ; Extend # Mc TIRHUTA SIGN VISARGA +114C2..114C3 ; Extend # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA +115AF..115B1 ; Extend # Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II +115B2..115B5 ; Extend # Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR +115B8..115BB ; Extend # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU +115BC..115BD ; Extend # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA +115BE ; Extend # Mc SIDDHAM SIGN VISARGA +115BF..115C0 ; Extend # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA +115DC..115DD ; Extend # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU +11630..11632 ; Extend # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II +11633..1163A ; Extend # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI +1163B..1163C ; Extend # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU +1163D ; Extend # Mn MODI SIGN ANUSVARA +1163E ; Extend # Mc MODI SIGN VISARGA +1163F..11640 ; Extend # Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA +116AB ; Extend # Mn TAKRI SIGN ANUSVARA +116AC ; Extend # Mc TAKRI SIGN VISARGA +116AD ; Extend # Mn TAKRI VOWEL SIGN AA +116AE..116AF ; Extend # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II +116B0..116B5 ; Extend # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU +116B6 ; Extend # Mc TAKRI SIGN VIRAMA +116B7 ; Extend # Mn TAKRI SIGN NUKTA +1171D..1171F ; Extend # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA +11720..11721 ; Extend # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA +11722..11725 ; Extend # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU +11726 ; Extend # Mc AHOM VOWEL SIGN E +11727..1172B ; Extend # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER +1182C..1182E ; Extend # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II +1182F..11837 ; Extend # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA +11838 ; Extend # Mc DOGRA SIGN VISARGA +11839..1183A ; Extend # Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA +11930..11935 ; Extend # Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E +11937..11938 ; Extend # Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O +1193B..1193C ; Extend # Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU +1193D ; Extend # Mc DIVES AKURU SIGN HALANTA +1193E ; Extend # Mn DIVES AKURU VIRAMA +11940 ; Extend # Mc DIVES AKURU MEDIAL YA +11942 ; Extend # Mc DIVES AKURU MEDIAL RA +11943 ; Extend # Mn DIVES AKURU SIGN NUKTA +119D1..119D3 ; Extend # Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II +119D4..119D7 ; Extend # Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR +119DA..119DB ; Extend # Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI +119DC..119DF ; Extend # Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA +119E0 ; Extend # Mn NANDINAGARI SIGN VIRAMA +119E4 ; Extend # Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E +11A01..11A0A ; Extend # Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK +11A33..11A38 ; Extend # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA +11A39 ; Extend # Mc ZANABAZAR SQUARE SIGN VISARGA +11A3B..11A3E ; Extend # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA +11A47 ; Extend # Mn ZANABAZAR SQUARE SUBJOINER +11A51..11A56 ; Extend # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE +11A57..11A58 ; Extend # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU +11A59..11A5B ; Extend # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK +11A8A..11A96 ; Extend # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA +11A97 ; Extend # Mc SOYOMBO SIGN VISARGA +11A98..11A99 ; Extend # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER +11C2F ; Extend # Mc BHAIKSUKI VOWEL SIGN AA +11C30..11C36 ; Extend # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L +11C38..11C3D ; Extend # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA +11C3E ; Extend # Mc BHAIKSUKI SIGN VISARGA +11C3F ; Extend # Mn BHAIKSUKI SIGN VIRAMA +11C92..11CA7 ; Extend # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA +11CA9 ; Extend # Mc MARCHEN SUBJOINED LETTER YA +11CAA..11CB0 ; Extend # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA +11CB1 ; Extend # Mc MARCHEN VOWEL SIGN I +11CB2..11CB3 ; Extend # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E +11CB4 ; Extend # Mc MARCHEN VOWEL SIGN O +11CB5..11CB6 ; Extend # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU +11D31..11D36 ; Extend # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R +11D3A ; Extend # Mn MASARAM GONDI VOWEL SIGN E +11D3C..11D3D ; Extend # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O +11D3F..11D45 ; Extend # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA +11D47 ; Extend # Mn MASARAM GONDI RA-KARA +11D8A..11D8E ; Extend # Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU +11D90..11D91 ; Extend # Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI +11D93..11D94 ; Extend # Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU +11D95 ; Extend # Mn GUNJALA GONDI SIGN ANUSVARA +11D96 ; Extend # Mc GUNJALA GONDI SIGN VISARGA +11D97 ; Extend # Mn GUNJALA GONDI VIRAMA +11EF3..11EF4 ; Extend # Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U +11EF5..11EF6 ; Extend # Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O +11F00..11F01 ; Extend # Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA +11F03 ; Extend # Mc KAWI SIGN VISARGA +11F34..11F35 ; Extend # Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA +11F36..11F3A ; Extend # Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R +11F3E..11F3F ; Extend # Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI +11F40 ; Extend # Mn KAWI VOWEL SIGN EU +11F41 ; Extend # Mc KAWI SIGN KILLER +11F42 ; Extend # Mn KAWI CONJOINER +13440 ; Extend # Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY +13447..13455 ; Extend # Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED +16AF0..16AF4 ; Extend # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE +16B30..16B36 ; Extend # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM +16F4F ; Extend # Mn MIAO SIGN CONSONANT MODIFIER BAR +16F51..16F87 ; Extend # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI +16F8F..16F92 ; Extend # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW +16FE4 ; Extend # Mn KHITAN SMALL SCRIPT FILLER +16FF0..16FF1 ; Extend # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY +1BC9D..1BC9E ; Extend # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK +1CF00..1CF2D ; Extend # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT +1CF30..1CF46 ; Extend # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG +1D165..1D166 ; Extend # Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM +1D167..1D169 ; Extend # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 +1D16D..1D172 ; Extend # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 +1D17B..1D182 ; Extend # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE +1D185..1D18B ; Extend # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE +1D1AA..1D1AD ; Extend # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO +1D242..1D244 ; Extend # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME +1DA00..1DA36 ; Extend # Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN +1DA3B..1DA6C ; Extend # Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT +1DA75 ; Extend # Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS +1DA84 ; Extend # Mn SIGNWRITING LOCATION HEAD NECK +1DA9B..1DA9F ; Extend # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 +1DAA1..1DAAF ; Extend # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 +1E000..1E006 ; Extend # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE +1E008..1E018 ; Extend # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU +1E01B..1E021 ; Extend # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI +1E023..1E024 ; Extend # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS +1E026..1E02A ; Extend # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA +1E08F ; Extend # Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I +1E130..1E136 ; Extend # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D +1E2AE ; Extend # Mn TOTO SIGN RISING TONE +1E2EC..1E2EF ; Extend # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI +1E4EC..1E4EF ; Extend # Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH +1E8D0..1E8D6 ; Extend # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS +1E944..1E94A ; Extend # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA +1F3FB..1F3FF ; Extend # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 +E0020..E007F ; Extend # Cf [96] TAG SPACE..CANCEL TAG +E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 + +# Total code points: 2554 + +# ================================================ + +1F1E6..1F1FF ; Regional_Indicator # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + +# Total code points: 26 + +# ================================================ + +00AD ; Format # Cf SOFT HYPHEN +061C ; Format # Cf ARABIC LETTER MARK +180E ; Format # Cf MONGOLIAN VOWEL SEPARATOR +200E..200F ; Format # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK +202A..202E ; Format # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE +2060..2064 ; Format # Cf [5] WORD JOINER..INVISIBLE PLUS +2066..206F ; Format # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES +FEFF ; Format # Cf ZERO WIDTH NO-BREAK SPACE +FFF9..FFFB ; Format # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR +13430..1343F ; Format # Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE +1BCA0..1BCA3 ; Format # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP +1D173..1D17A ; Format # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE +E0001 ; Format # Cf LANGUAGE TAG + +# Total code points: 58 + +# ================================================ + +3031..3035 ; Katakana # Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF +309B..309C ; Katakana # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK +30A0 ; Katakana # Pd KATAKANA-HIRAGANA DOUBLE HYPHEN +30A1..30FA ; Katakana # Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO +30FC..30FE ; Katakana # Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK +30FF ; Katakana # Lo KATAKANA DIGRAPH KOTO +31F0..31FF ; Katakana # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO +32D0..32FE ; Katakana # So [47] CIRCLED KATAKANA A..CIRCLED KATAKANA WO +3300..3357 ; Katakana # So [88] SQUARE APAATO..SQUARE WATTO +FF66..FF6F ; Katakana # Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU +FF70 ; Katakana # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK +FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N +1AFF0..1AFF3 ; Katakana # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; Katakana # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; Katakana # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 +1B000 ; Katakana # Lo KATAKANA LETTER ARCHAIC E +1B120..1B122 ; Katakana # Lo [3] KATAKANA LETTER ARCHAIC YI..KATAKANA LETTER ARCHAIC WU +1B155 ; Katakana # Lo KATAKANA LETTER SMALL KO +1B164..1B167 ; Katakana # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N + +# Total code points: 331 + +# ================================================ + +0041..005A ; ALetter # L& [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z +0061..007A ; ALetter # L& [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z +00AA ; ALetter # Lo FEMININE ORDINAL INDICATOR +00B5 ; ALetter # L& MICRO SIGN +00BA ; ALetter # Lo MASCULINE ORDINAL INDICATOR +00C0..00D6 ; ALetter # L& [23] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER O WITH DIAERESIS +00D8..00F6 ; ALetter # L& [31] LATIN CAPITAL LETTER O WITH STROKE..LATIN SMALL LETTER O WITH DIAERESIS +00F8..01BA ; ALetter # L& [195] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL +01BB ; ALetter # Lo LATIN LETTER TWO WITH STROKE +01BC..01BF ; ALetter # L& [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN +01C0..01C3 ; ALetter # Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK +01C4..0293 ; ALetter # L& [208] LATIN CAPITAL LETTER DZ WITH CARON..LATIN SMALL LETTER EZH WITH CURL +0294 ; ALetter # Lo LATIN LETTER GLOTTAL STOP +0295..02AF ; ALetter # L& [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL +02B0..02C1 ; ALetter # Lm [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP +02C2..02C5 ; ALetter # Sk [4] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD +02C6..02D1 ; ALetter # Lm [12] MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON +02D2..02D7 ; ALetter # Sk [6] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER MINUS SIGN +02DE..02DF ; ALetter # Sk [2] MODIFIER LETTER RHOTIC HOOK..MODIFIER LETTER CROSS ACCENT +02E0..02E4 ; ALetter # Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP +02E5..02EB ; ALetter # Sk [7] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER YANG DEPARTING TONE MARK +02EC ; ALetter # Lm MODIFIER LETTER VOICING +02ED ; ALetter # Sk MODIFIER LETTER UNASPIRATED +02EE ; ALetter # Lm MODIFIER LETTER DOUBLE APOSTROPHE +02EF..02FF ; ALetter # Sk [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW +0370..0373 ; ALetter # L& [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI +0374 ; ALetter # Lm GREEK NUMERAL SIGN +0376..0377 ; ALetter # L& [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA +037A ; ALetter # Lm GREEK YPOGEGRAMMENI +037B..037D ; ALetter # L& [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL +037F ; ALetter # L& GREEK CAPITAL LETTER YOT +0386 ; ALetter # L& GREEK CAPITAL LETTER ALPHA WITH TONOS +0388..038A ; ALetter # L& [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS +038C ; ALetter # L& GREEK CAPITAL LETTER OMICRON WITH TONOS +038E..03A1 ; ALetter # L& [20] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK CAPITAL LETTER RHO +03A3..03F5 ; ALetter # L& [83] GREEK CAPITAL LETTER SIGMA..GREEK LUNATE EPSILON SYMBOL +03F7..0481 ; ALetter # L& [139] GREEK CAPITAL LETTER SHO..CYRILLIC SMALL LETTER KOPPA +048A..052F ; ALetter # L& [166] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER EL WITH DESCENDER +0531..0556 ; ALetter # L& [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH +0559 ; ALetter # Lm ARMENIAN MODIFIER LETTER LEFT HALF RING +055A..055C ; ALetter # Po [3] ARMENIAN APOSTROPHE..ARMENIAN EXCLAMATION MARK +055E ; ALetter # Po ARMENIAN QUESTION MARK +0560..0588 ; ALetter # L& [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE +058A ; ALetter # Pd ARMENIAN HYPHEN +05F3 ; ALetter # Po HEBREW PUNCTUATION GERESH +0620..063F ; ALetter # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE +0640 ; ALetter # Lm ARABIC TATWEEL +0641..064A ; ALetter # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH +066E..066F ; ALetter # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF +0671..06D3 ; ALetter # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE +06D5 ; ALetter # Lo ARABIC LETTER AE +06E5..06E6 ; ALetter # Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH +06EE..06EF ; ALetter # Lo [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V +06FA..06FC ; ALetter # Lo [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW +06FF ; ALetter # Lo ARABIC LETTER HEH WITH INVERTED V +070F ; ALetter # Cf SYRIAC ABBREVIATION MARK +0710 ; ALetter # Lo SYRIAC LETTER ALAPH +0712..072F ; ALetter # Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH +074D..07A5 ; ALetter # Lo [89] SYRIAC LETTER SOGDIAN ZHAIN..THAANA LETTER WAAVU +07B1 ; ALetter # Lo THAANA LETTER NAA +07CA..07EA ; ALetter # Lo [33] NKO LETTER A..NKO LETTER JONA RA +07F4..07F5 ; ALetter # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE +07FA ; ALetter # Lm NKO LAJANYALAN +0800..0815 ; ALetter # Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF +081A ; ALetter # Lm SAMARITAN MODIFIER LETTER EPENTHETIC YUT +0824 ; ALetter # Lm SAMARITAN MODIFIER LETTER SHORT A +0828 ; ALetter # Lm SAMARITAN MODIFIER LETTER I +0840..0858 ; ALetter # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN +0860..086A ; ALetter # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA +0870..0887 ; ALetter # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT +0889..088E ; ALetter # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL +08A0..08C8 ; ALetter # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF +08C9 ; ALetter # Lm ARABIC SMALL FARSI YEH +0904..0939 ; ALetter # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA +093D ; ALetter # Lo DEVANAGARI SIGN AVAGRAHA +0950 ; ALetter # Lo DEVANAGARI OM +0958..0961 ; ALetter # Lo [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL +0971 ; ALetter # Lm DEVANAGARI SIGN HIGH SPACING DOT +0972..0980 ; ALetter # Lo [15] DEVANAGARI LETTER CANDRA A..BENGALI ANJI +0985..098C ; ALetter # Lo [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L +098F..0990 ; ALetter # Lo [2] BENGALI LETTER E..BENGALI LETTER AI +0993..09A8 ; ALetter # Lo [22] BENGALI LETTER O..BENGALI LETTER NA +09AA..09B0 ; ALetter # Lo [7] BENGALI LETTER PA..BENGALI LETTER RA +09B2 ; ALetter # Lo BENGALI LETTER LA +09B6..09B9 ; ALetter # Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA +09BD ; ALetter # Lo BENGALI SIGN AVAGRAHA +09CE ; ALetter # Lo BENGALI LETTER KHANDA TA +09DC..09DD ; ALetter # Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA +09DF..09E1 ; ALetter # Lo [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL +09F0..09F1 ; ALetter # Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL +09FC ; ALetter # Lo BENGALI LETTER VEDIC ANUSVARA +0A05..0A0A ; ALetter # Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU +0A0F..0A10 ; ALetter # Lo [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI +0A13..0A28 ; ALetter # Lo [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA +0A2A..0A30 ; ALetter # Lo [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA +0A32..0A33 ; ALetter # Lo [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA +0A35..0A36 ; ALetter # Lo [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA +0A38..0A39 ; ALetter # Lo [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA +0A59..0A5C ; ALetter # Lo [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA +0A5E ; ALetter # Lo GURMUKHI LETTER FA +0A72..0A74 ; ALetter # Lo [3] GURMUKHI IRI..GURMUKHI EK ONKAR +0A85..0A8D ; ALetter # Lo [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E +0A8F..0A91 ; ALetter # Lo [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O +0A93..0AA8 ; ALetter # Lo [22] GUJARATI LETTER O..GUJARATI LETTER NA +0AAA..0AB0 ; ALetter # Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA +0AB2..0AB3 ; ALetter # Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA +0AB5..0AB9 ; ALetter # Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA +0ABD ; ALetter # Lo GUJARATI SIGN AVAGRAHA +0AD0 ; ALetter # Lo GUJARATI OM +0AE0..0AE1 ; ALetter # Lo [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL +0AF9 ; ALetter # Lo GUJARATI LETTER ZHA +0B05..0B0C ; ALetter # Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L +0B0F..0B10 ; ALetter # Lo [2] ORIYA LETTER E..ORIYA LETTER AI +0B13..0B28 ; ALetter # Lo [22] ORIYA LETTER O..ORIYA LETTER NA +0B2A..0B30 ; ALetter # Lo [7] ORIYA LETTER PA..ORIYA LETTER RA +0B32..0B33 ; ALetter # Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA +0B35..0B39 ; ALetter # Lo [5] ORIYA LETTER VA..ORIYA LETTER HA +0B3D ; ALetter # Lo ORIYA SIGN AVAGRAHA +0B5C..0B5D ; ALetter # Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA +0B5F..0B61 ; ALetter # Lo [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL +0B71 ; ALetter # Lo ORIYA LETTER WA +0B83 ; ALetter # Lo TAMIL SIGN VISARGA +0B85..0B8A ; ALetter # Lo [6] TAMIL LETTER A..TAMIL LETTER UU +0B8E..0B90 ; ALetter # Lo [3] TAMIL LETTER E..TAMIL LETTER AI +0B92..0B95 ; ALetter # Lo [4] TAMIL LETTER O..TAMIL LETTER KA +0B99..0B9A ; ALetter # Lo [2] TAMIL LETTER NGA..TAMIL LETTER CA +0B9C ; ALetter # Lo TAMIL LETTER JA +0B9E..0B9F ; ALetter # Lo [2] TAMIL LETTER NYA..TAMIL LETTER TTA +0BA3..0BA4 ; ALetter # Lo [2] TAMIL LETTER NNA..TAMIL LETTER TA +0BA8..0BAA ; ALetter # Lo [3] TAMIL LETTER NA..TAMIL LETTER PA +0BAE..0BB9 ; ALetter # Lo [12] TAMIL LETTER MA..TAMIL LETTER HA +0BD0 ; ALetter # Lo TAMIL OM +0C05..0C0C ; ALetter # Lo [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L +0C0E..0C10 ; ALetter # Lo [3] TELUGU LETTER E..TELUGU LETTER AI +0C12..0C28 ; ALetter # Lo [23] TELUGU LETTER O..TELUGU LETTER NA +0C2A..0C39 ; ALetter # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA +0C3D ; ALetter # Lo TELUGU SIGN AVAGRAHA +0C58..0C5A ; ALetter # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA +0C5D ; ALetter # Lo TELUGU LETTER NAKAARA POLLU +0C60..0C61 ; ALetter # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL +0C80 ; ALetter # Lo KANNADA SIGN SPACING CANDRABINDU +0C85..0C8C ; ALetter # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L +0C8E..0C90 ; ALetter # Lo [3] KANNADA LETTER E..KANNADA LETTER AI +0C92..0CA8 ; ALetter # Lo [23] KANNADA LETTER O..KANNADA LETTER NA +0CAA..0CB3 ; ALetter # Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA +0CB5..0CB9 ; ALetter # Lo [5] KANNADA LETTER VA..KANNADA LETTER HA +0CBD ; ALetter # Lo KANNADA SIGN AVAGRAHA +0CDD..0CDE ; ALetter # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA +0CE0..0CE1 ; ALetter # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL +0CF1..0CF2 ; ALetter # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA +0D04..0D0C ; ALetter # Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L +0D0E..0D10 ; ALetter # Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI +0D12..0D3A ; ALetter # Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA +0D3D ; ALetter # Lo MALAYALAM SIGN AVAGRAHA +0D4E ; ALetter # Lo MALAYALAM LETTER DOT REPH +0D54..0D56 ; ALetter # Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL +0D5F..0D61 ; ALetter # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL +0D7A..0D7F ; ALetter # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K +0D85..0D96 ; ALetter # Lo [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA +0D9A..0DB1 ; ALetter # Lo [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA +0DB3..0DBB ; ALetter # Lo [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA +0DBD ; ALetter # Lo SINHALA LETTER DANTAJA LAYANNA +0DC0..0DC6 ; ALetter # Lo [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA +0F00 ; ALetter # Lo TIBETAN SYLLABLE OM +0F40..0F47 ; ALetter # Lo [8] TIBETAN LETTER KA..TIBETAN LETTER JA +0F49..0F6C ; ALetter # Lo [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA +0F88..0F8C ; ALetter # Lo [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN +10A0..10C5 ; ALetter # L& [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE +10C7 ; ALetter # L& GEORGIAN CAPITAL LETTER YN +10CD ; ALetter # L& GEORGIAN CAPITAL LETTER AEN +10D0..10FA ; ALetter # L& [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN +10FC ; ALetter # Lm MODIFIER LETTER GEORGIAN NAR +10FD..10FF ; ALetter # L& [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN +1100..1248 ; ALetter # Lo [329] HANGUL CHOSEONG KIYEOK..ETHIOPIC SYLLABLE QWA +124A..124D ; ALetter # Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE +1250..1256 ; ALetter # Lo [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO +1258 ; ALetter # Lo ETHIOPIC SYLLABLE QHWA +125A..125D ; ALetter # Lo [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE +1260..1288 ; ALetter # Lo [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA +128A..128D ; ALetter # Lo [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE +1290..12B0 ; ALetter # Lo [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA +12B2..12B5 ; ALetter # Lo [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE +12B8..12BE ; ALetter # Lo [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO +12C0 ; ALetter # Lo ETHIOPIC SYLLABLE KXWA +12C2..12C5 ; ALetter # Lo [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE +12C8..12D6 ; ALetter # Lo [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O +12D8..1310 ; ALetter # Lo [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA +1312..1315 ; ALetter # Lo [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE +1318..135A ; ALetter # Lo [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA +1380..138F ; ALetter # Lo [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE +13A0..13F5 ; ALetter # L& [86] CHEROKEE LETTER A..CHEROKEE LETTER MV +13F8..13FD ; ALetter # L& [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV +1401..166C ; ALetter # Lo [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA +166F..167F ; ALetter # Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W +1681..169A ; ALetter # Lo [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH +16A0..16EA ; ALetter # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X +16EE..16F0 ; ALetter # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL +16F1..16F8 ; ALetter # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC +1700..1711 ; ALetter # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA +171F..1731 ; ALetter # Lo [19] TAGALOG LETTER ARCHAIC RA..HANUNOO LETTER HA +1740..1751 ; ALetter # Lo [18] BUHID LETTER A..BUHID LETTER HA +1760..176C ; ALetter # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA +176E..1770 ; ALetter # Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA +1820..1842 ; ALetter # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI +1843 ; ALetter # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN +1844..1878 ; ALetter # Lo [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS +1880..1884 ; ALetter # Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA +1887..18A8 ; ALetter # Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA +18AA ; ALetter # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA +18B0..18F5 ; ALetter # Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S +1900..191E ; ALetter # Lo [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA +1A00..1A16 ; ALetter # Lo [23] BUGINESE LETTER KA..BUGINESE LETTER HA +1B05..1B33 ; ALetter # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA +1B45..1B4C ; ALetter # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA +1B83..1BA0 ; ALetter # Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA +1BAE..1BAF ; ALetter # Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA +1BBA..1BE5 ; ALetter # Lo [44] SUNDANESE AVAGRAHA..BATAK LETTER U +1C00..1C23 ; ALetter # Lo [36] LEPCHA LETTER KA..LEPCHA LETTER A +1C4D..1C4F ; ALetter # Lo [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA +1C5A..1C77 ; ALetter # Lo [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH +1C78..1C7D ; ALetter # Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD +1C80..1C88 ; ALetter # L& [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK +1C90..1CBA ; ALetter # L& [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN +1CBD..1CBF ; ALetter # L& [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN +1CE9..1CEC ; ALetter # Lo [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL +1CEE..1CF3 ; ALetter # Lo [6] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ROTATED ARDHAVISARGA +1CF5..1CF6 ; ALetter # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA +1CFA ; ALetter # Lo VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA +1D00..1D2B ; ALetter # L& [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL +1D2C..1D6A ; ALetter # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI +1D6B..1D77 ; ALetter # L& [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G +1D78 ; ALetter # Lm MODIFIER LETTER CYRILLIC EN +1D79..1D9A ; ALetter # L& [34] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK +1D9B..1DBF ; ALetter # Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA +1E00..1F15 ; ALetter # L& [278] LATIN CAPITAL LETTER A WITH RING BELOW..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA +1F18..1F1D ; ALetter # L& [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA +1F20..1F45 ; ALetter # L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA +1F48..1F4D ; ALetter # L& [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA +1F50..1F57 ; ALetter # L& [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI +1F59 ; ALetter # L& GREEK CAPITAL LETTER UPSILON WITH DASIA +1F5B ; ALetter # L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA +1F5D ; ALetter # L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA +1F5F..1F7D ; ALetter # L& [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA +1F80..1FB4 ; ALetter # L& [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI +1FB6..1FBC ; ALetter # L& [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI +1FBE ; ALetter # L& GREEK PROSGEGRAMMENI +1FC2..1FC4 ; ALetter # L& [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI +1FC6..1FCC ; ALetter # L& [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI +1FD0..1FD3 ; ALetter # L& [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA +1FD6..1FDB ; ALetter # L& [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA +1FE0..1FEC ; ALetter # L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA +1FF2..1FF4 ; ALetter # L& [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI +1FF6..1FFC ; ALetter # L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI +2071 ; ALetter # Lm SUPERSCRIPT LATIN SMALL LETTER I +207F ; ALetter # Lm SUPERSCRIPT LATIN SMALL LETTER N +2090..209C ; ALetter # Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T +2102 ; ALetter # L& DOUBLE-STRUCK CAPITAL C +2107 ; ALetter # L& EULER CONSTANT +210A..2113 ; ALetter # L& [10] SCRIPT SMALL G..SCRIPT SMALL L +2115 ; ALetter # L& DOUBLE-STRUCK CAPITAL N +2119..211D ; ALetter # L& [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R +2124 ; ALetter # L& DOUBLE-STRUCK CAPITAL Z +2126 ; ALetter # L& OHM SIGN +2128 ; ALetter # L& BLACK-LETTER CAPITAL Z +212A..212D ; ALetter # L& [4] KELVIN SIGN..BLACK-LETTER CAPITAL C +212F..2134 ; ALetter # L& [6] SCRIPT SMALL E..SCRIPT SMALL O +2135..2138 ; ALetter # Lo [4] ALEF SYMBOL..DALET SYMBOL +2139 ; ALetter # L& INFORMATION SOURCE +213C..213F ; ALetter # L& [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI +2145..2149 ; ALetter # L& [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J +214E ; ALetter # L& TURNED SMALL F +2160..2182 ; ALetter # Nl [35] ROMAN NUMERAL ONE..ROMAN NUMERAL TEN THOUSAND +2183..2184 ; ALetter # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C +2185..2188 ; ALetter # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND +24B6..24E9 ; ALetter # So [52] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN SMALL LETTER Z +2C00..2C7B ; ALetter # L& [124] GLAGOLITIC CAPITAL LETTER AZU..LATIN LETTER SMALL CAPITAL TURNED E +2C7C..2C7D ; ALetter # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V +2C7E..2CE4 ; ALetter # L& [103] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SYMBOL KAI +2CEB..2CEE ; ALetter # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA +2CF2..2CF3 ; ALetter # L& [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI +2D00..2D25 ; ALetter # L& [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE +2D27 ; ALetter # L& GEORGIAN SMALL LETTER YN +2D2D ; ALetter # L& GEORGIAN SMALL LETTER AEN +2D30..2D67 ; ALetter # Lo [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO +2D6F ; ALetter # Lm TIFINAGH MODIFIER LETTER LABIALIZATION MARK +2D80..2D96 ; ALetter # Lo [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE +2DA0..2DA6 ; ALetter # Lo [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO +2DA8..2DAE ; ALetter # Lo [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO +2DB0..2DB6 ; ALetter # Lo [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO +2DB8..2DBE ; ALetter # Lo [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO +2DC0..2DC6 ; ALetter # Lo [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO +2DC8..2DCE ; ALetter # Lo [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO +2DD0..2DD6 ; ALetter # Lo [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO +2DD8..2DDE ; ALetter # Lo [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO +2E2F ; ALetter # Lm VERTICAL TILDE +3005 ; ALetter # Lm IDEOGRAPHIC ITERATION MARK +303B ; ALetter # Lm VERTICAL IDEOGRAPHIC ITERATION MARK +303C ; ALetter # Lo MASU MARK +3105..312F ; ALetter # Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN +3131..318E ; ALetter # Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE +31A0..31BF ; ALetter # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH +A000..A014 ; ALetter # Lo [21] YI SYLLABLE IT..YI SYLLABLE E +A015 ; ALetter # Lm YI SYLLABLE WU +A016..A48C ; ALetter # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR +A4D0..A4F7 ; ALetter # Lo [40] LISU LETTER BA..LISU LETTER OE +A4F8..A4FD ; ALetter # Lm [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU +A500..A60B ; ALetter # Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG +A60C ; ALetter # Lm VAI SYLLABLE LENGTHENER +A610..A61F ; ALetter # Lo [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG +A62A..A62B ; ALetter # Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO +A640..A66D ; ALetter # L& [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O +A66E ; ALetter # Lo CYRILLIC LETTER MULTIOCULAR O +A67F ; ALetter # Lm CYRILLIC PAYEROK +A680..A69B ; ALetter # L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O +A69C..A69D ; ALetter # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN +A6A0..A6E5 ; ALetter # Lo [70] BAMUM LETTER A..BAMUM LETTER KI +A6E6..A6EF ; ALetter # Nl [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM +A708..A716 ; ALetter # Sk [15] MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR +A717..A71F ; ALetter # Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK +A720..A721 ; ALetter # Sk [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE +A722..A76F ; ALetter # L& [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON +A770 ; ALetter # Lm MODIFIER LETTER US +A771..A787 ; ALetter # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T +A788 ; ALetter # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT +A789..A78A ; ALetter # Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN +A78B..A78E ; ALetter # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT +A78F ; ALetter # Lo LATIN LETTER SINOLOGICAL DOT +A790..A7CA ; ALetter # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +A7D0..A7D1 ; ALetter # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G +A7D3 ; ALetter # L& LATIN SMALL LETTER DOUBLE THORN +A7D5..A7D9 ; ALetter # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S +A7F2..A7F4 ; ALetter # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q +A7F5..A7F6 ; ALetter # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H +A7F7 ; ALetter # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I +A7F8..A7F9 ; ALetter # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE +A7FA ; ALetter # L& LATIN LETTER SMALL CAPITAL TURNED M +A7FB..A801 ; ALetter # Lo [7] LATIN EPIGRAPHIC LETTER REVERSED F..SYLOTI NAGRI LETTER I +A803..A805 ; ALetter # Lo [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O +A807..A80A ; ALetter # Lo [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO +A80C..A822 ; ALetter # Lo [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO +A840..A873 ; ALetter # Lo [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU +A882..A8B3 ; ALetter # Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA +A8F2..A8F7 ; ALetter # Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA +A8FB ; ALetter # Lo DEVANAGARI HEADSTROKE +A8FD..A8FE ; ALetter # Lo [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY +A90A..A925 ; ALetter # Lo [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO +A930..A946 ; ALetter # Lo [23] REJANG LETTER KA..REJANG LETTER A +A960..A97C ; ALetter # Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH +A984..A9B2 ; ALetter # Lo [47] JAVANESE LETTER A..JAVANESE LETTER HA +A9CF ; ALetter # Lm JAVANESE PANGRANGKEP +AA00..AA28 ; ALetter # Lo [41] CHAM LETTER A..CHAM LETTER HA +AA40..AA42 ; ALetter # Lo [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG +AA44..AA4B ; ALetter # Lo [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS +AAE0..AAEA ; ALetter # Lo [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA +AAF2 ; ALetter # Lo MEETEI MAYEK ANJI +AAF3..AAF4 ; ALetter # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK +AB01..AB06 ; ALetter # Lo [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO +AB09..AB0E ; ALetter # Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO +AB11..AB16 ; ALetter # Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO +AB20..AB26 ; ALetter # Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO +AB28..AB2E ; ALetter # Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO +AB30..AB5A ; ALetter # L& [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG +AB5B ; ALetter # Sk MODIFIER BREVE WITH INVERTED BREVE +AB5C..AB5F ; ALetter # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK +AB60..AB68 ; ALetter # L& [9] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE +AB69 ; ALetter # Lm MODIFIER LETTER SMALL TURNED W +AB70..ABBF ; ALetter # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA +ABC0..ABE2 ; ALetter # Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM +AC00..D7A3 ; ALetter # Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH +D7B0..D7C6 ; ALetter # Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E +D7CB..D7FB ; ALetter # Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH +FB00..FB06 ; ALetter # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST +FB13..FB17 ; ALetter # L& [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH +FB50..FBB1 ; ALetter # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM +FBD3..FD3D ; ALetter # Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM +FD50..FD8F ; ALetter # Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM +FD92..FDC7 ; ALetter # Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM +FDF0..FDFB ; ALetter # Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU +FE70..FE74 ; ALetter # Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM +FE76..FEFC ; ALetter # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM +FF21..FF3A ; ALetter # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z +FF41..FF5A ; ALetter # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z +FFA0..FFBE ; ALetter # Lo [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH +FFC2..FFC7 ; ALetter # Lo [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E +FFCA..FFCF ; ALetter # Lo [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE +FFD2..FFD7 ; ALetter # Lo [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU +FFDA..FFDC ; ALetter # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I +10000..1000B ; ALetter # Lo [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE +1000D..10026 ; ALetter # Lo [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO +10028..1003A ; ALetter # Lo [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO +1003C..1003D ; ALetter # Lo [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE +1003F..1004D ; ALetter # Lo [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO +10050..1005D ; ALetter # Lo [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089 +10080..100FA ; ALetter # Lo [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305 +10140..10174 ; ALetter # Nl [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS +10280..1029C ; ALetter # Lo [29] LYCIAN LETTER A..LYCIAN LETTER X +102A0..102D0 ; ALetter # Lo [49] CARIAN LETTER A..CARIAN LETTER UUU3 +10300..1031F ; ALetter # Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS +1032D..10340 ; ALetter # Lo [20] OLD ITALIC LETTER YE..GOTHIC LETTER PAIRTHRA +10341 ; ALetter # Nl GOTHIC LETTER NINETY +10342..10349 ; ALetter # Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL +1034A ; ALetter # Nl GOTHIC LETTER NINE HUNDRED +10350..10375 ; ALetter # Lo [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA +10380..1039D ; ALetter # Lo [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU +103A0..103C3 ; ALetter # Lo [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA +103C8..103CF ; ALetter # Lo [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH +103D1..103D5 ; ALetter # Nl [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED +10400..1044F ; ALetter # L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW +10450..1049D ; ALetter # Lo [78] SHAVIAN LETTER PEEP..OSMANYA LETTER OO +104B0..104D3 ; ALetter # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA +104D8..104FB ; ALetter # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA +10500..10527 ; ALetter # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE +10530..10563 ; ALetter # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW +10570..1057A ; ALetter # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA +1057C..1058A ; ALetter # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE +1058C..10592 ; ALetter # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE +10594..10595 ; ALetter # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE +10597..105A1 ; ALetter # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA +105A3..105B1 ; ALetter # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE +105B3..105B9 ; ALetter # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE +105BB..105BC ; ALetter # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE +10600..10736 ; ALetter # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 +10740..10755 ; ALetter # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE +10760..10767 ; ALetter # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 +10780..10785 ; ALetter # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; ALetter # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; ALetter # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL +10800..10805 ; ALetter # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA +10808 ; ALetter # Lo CYPRIOT SYLLABLE JO +1080A..10835 ; ALetter # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO +10837..10838 ; ALetter # Lo [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE +1083C ; ALetter # Lo CYPRIOT SYLLABLE ZA +1083F..10855 ; ALetter # Lo [23] CYPRIOT SYLLABLE ZO..IMPERIAL ARAMAIC LETTER TAW +10860..10876 ; ALetter # Lo [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW +10880..1089E ; ALetter # Lo [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW +108E0..108F2 ; ALetter # Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH +108F4..108F5 ; ALetter # Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW +10900..10915 ; ALetter # Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU +10920..10939 ; ALetter # Lo [26] LYDIAN LETTER A..LYDIAN LETTER C +10980..109B7 ; ALetter # Lo [56] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC CURSIVE LETTER DA +109BE..109BF ; ALetter # Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN +10A00 ; ALetter # Lo KHAROSHTHI LETTER A +10A10..10A13 ; ALetter # Lo [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA +10A15..10A17 ; ALetter # Lo [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA +10A19..10A35 ; ALetter # Lo [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA +10A60..10A7C ; ALetter # Lo [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH +10A80..10A9C ; ALetter # Lo [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH +10AC0..10AC7 ; ALetter # Lo [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW +10AC9..10AE4 ; ALetter # Lo [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW +10B00..10B35 ; ALetter # Lo [54] AVESTAN LETTER A..AVESTAN LETTER HE +10B40..10B55 ; ALetter # Lo [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW +10B60..10B72 ; ALetter # Lo [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW +10B80..10B91 ; ALetter # Lo [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW +10C00..10C48 ; ALetter # Lo [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH +10C80..10CB2 ; ALetter # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US +10CC0..10CF2 ; ALetter # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US +10D00..10D23 ; ALetter # Lo [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA +10E80..10EA9 ; ALetter # Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET +10EB0..10EB1 ; ALetter # Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE +10F00..10F1C ; ALetter # Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL +10F27 ; ALetter # Lo OLD SOGDIAN LIGATURE AYIN-DALETH +10F30..10F45 ; ALetter # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN +10F70..10F81 ; ALetter # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH +10FB0..10FC4 ; ALetter # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW +10FE0..10FF6 ; ALetter # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH +11003..11037 ; ALetter # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA +11071..11072 ; ALetter # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O +11075 ; ALetter # Lo BRAHMI LETTER OLD TAMIL LLA +11083..110AF ; ALetter # Lo [45] KAITHI LETTER A..KAITHI LETTER HA +110D0..110E8 ; ALetter # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE +11103..11126 ; ALetter # Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA +11144 ; ALetter # Lo CHAKMA LETTER LHAA +11147 ; ALetter # Lo CHAKMA LETTER VAA +11150..11172 ; ALetter # Lo [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA +11176 ; ALetter # Lo MAHAJANI LIGATURE SHRI +11183..111B2 ; ALetter # Lo [48] SHARADA LETTER A..SHARADA LETTER HA +111C1..111C4 ; ALetter # Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM +111DA ; ALetter # Lo SHARADA EKAM +111DC ; ALetter # Lo SHARADA HEADSTROKE +11200..11211 ; ALetter # Lo [18] KHOJKI LETTER A..KHOJKI LETTER JJA +11213..1122B ; ALetter # Lo [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA +1123F..11240 ; ALetter # Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I +11280..11286 ; ALetter # Lo [7] MULTANI LETTER A..MULTANI LETTER GA +11288 ; ALetter # Lo MULTANI LETTER GHA +1128A..1128D ; ALetter # Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA +1128F..1129D ; ALetter # Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA +1129F..112A8 ; ALetter # Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA +112B0..112DE ; ALetter # Lo [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA +11305..1130C ; ALetter # Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L +1130F..11310 ; ALetter # Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI +11313..11328 ; ALetter # Lo [22] GRANTHA LETTER OO..GRANTHA LETTER NA +1132A..11330 ; ALetter # Lo [7] GRANTHA LETTER PA..GRANTHA LETTER RA +11332..11333 ; ALetter # Lo [2] GRANTHA LETTER LA..GRANTHA LETTER LLA +11335..11339 ; ALetter # Lo [5] GRANTHA LETTER VA..GRANTHA LETTER HA +1133D ; ALetter # Lo GRANTHA SIGN AVAGRAHA +11350 ; ALetter # Lo GRANTHA OM +1135D..11361 ; ALetter # Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL +11400..11434 ; ALetter # Lo [53] NEWA LETTER A..NEWA LETTER HA +11447..1144A ; ALetter # Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI +1145F..11461 ; ALetter # Lo [3] NEWA LETTER VEDIC ANUSVARA..NEWA SIGN UPADHMANIYA +11480..114AF ; ALetter # Lo [48] TIRHUTA ANJI..TIRHUTA LETTER HA +114C4..114C5 ; ALetter # Lo [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG +114C7 ; ALetter # Lo TIRHUTA OM +11580..115AE ; ALetter # Lo [47] SIDDHAM LETTER A..SIDDHAM LETTER HA +115D8..115DB ; ALetter # Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U +11600..1162F ; ALetter # Lo [48] MODI LETTER A..MODI LETTER LLA +11644 ; ALetter # Lo MODI SIGN HUVA +11680..116AA ; ALetter # Lo [43] TAKRI LETTER A..TAKRI LETTER RRA +116B8 ; ALetter # Lo TAKRI LETTER ARCHAIC KHA +11800..1182B ; ALetter # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA +118A0..118DF ; ALetter # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO +118FF..11906 ; ALetter # Lo [8] WARANG CITI OM..DIVES AKURU LETTER E +11909 ; ALetter # Lo DIVES AKURU LETTER O +1190C..11913 ; ALetter # Lo [8] DIVES AKURU LETTER KA..DIVES AKURU LETTER JA +11915..11916 ; ALetter # Lo [2] DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA +11918..1192F ; ALetter # Lo [24] DIVES AKURU LETTER DDA..DIVES AKURU LETTER ZA +1193F ; ALetter # Lo DIVES AKURU PREFIXED NASAL SIGN +11941 ; ALetter # Lo DIVES AKURU INITIAL RA +119A0..119A7 ; ALetter # Lo [8] NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR +119AA..119D0 ; ALetter # Lo [39] NANDINAGARI LETTER E..NANDINAGARI LETTER RRA +119E1 ; ALetter # Lo NANDINAGARI SIGN AVAGRAHA +119E3 ; ALetter # Lo NANDINAGARI HEADSTROKE +11A00 ; ALetter # Lo ZANABAZAR SQUARE LETTER A +11A0B..11A32 ; ALetter # Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA +11A3A ; ALetter # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA +11A50 ; ALetter # Lo SOYOMBO LETTER A +11A5C..11A89 ; ALetter # Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA +11A9D ; ALetter # Lo SOYOMBO MARK PLUTA +11AB0..11AF8 ; ALetter # Lo [73] CANADIAN SYLLABICS NATTILIK HI..PAU CIN HAU GLOTTAL STOP FINAL +11C00..11C08 ; ALetter # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L +11C0A..11C2E ; ALetter # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA +11C40 ; ALetter # Lo BHAIKSUKI SIGN AVAGRAHA +11C72..11C8F ; ALetter # Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A +11D00..11D06 ; ALetter # Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E +11D08..11D09 ; ALetter # Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O +11D0B..11D30 ; ALetter # Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA +11D46 ; ALetter # Lo MASARAM GONDI REPHA +11D60..11D65 ; ALetter # Lo [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU +11D67..11D68 ; ALetter # Lo [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI +11D6A..11D89 ; ALetter # Lo [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA +11D98 ; ALetter # Lo GUNJALA GONDI OM +11EE0..11EF2 ; ALetter # Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA +11F02 ; ALetter # Lo KAWI SIGN REPHA +11F04..11F10 ; ALetter # Lo [13] KAWI LETTER A..KAWI LETTER O +11F12..11F33 ; ALetter # Lo [34] KAWI LETTER KA..KAWI LETTER JNYA +11FB0 ; ALetter # Lo LISU LETTER YHA +12000..12399 ; ALetter # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U +12400..1246E ; ALetter # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM +12480..12543 ; ALetter # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU +12F90..12FF0 ; ALetter # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 +13000..1342F ; ALetter # Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D +13441..13446 ; ALetter # Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN +14400..14646 ; ALetter # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 +16800..16A38 ; ALetter # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ +16A40..16A5E ; ALetter # Lo [31] MRO LETTER TA..MRO LETTER TEK +16A70..16ABE ; ALetter # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA +16AD0..16AED ; ALetter # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I +16B00..16B2F ; ALetter # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU +16B40..16B43 ; ALetter # Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM +16B63..16B77 ; ALetter # Lo [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS +16B7D..16B8F ; ALetter # Lo [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ +16E40..16E7F ; ALetter # L& [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y +16F00..16F4A ; ALetter # Lo [75] MIAO LETTER PA..MIAO LETTER RTE +16F50 ; ALetter # Lo MIAO LETTER NASALIZATION +16F93..16F9F ; ALetter # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 +16FE0..16FE1 ; ALetter # Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK +16FE3 ; ALetter # Lm OLD CHINESE ITERATION MARK +1BC00..1BC6A ; ALetter # Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M +1BC70..1BC7C ; ALetter # Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK +1BC80..1BC88 ; ALetter # Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL +1BC90..1BC99 ; ALetter # Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW +1D400..1D454 ; ALetter # L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G +1D456..1D49C ; ALetter # L& [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A +1D49E..1D49F ; ALetter # L& [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D +1D4A2 ; ALetter # L& MATHEMATICAL SCRIPT CAPITAL G +1D4A5..1D4A6 ; ALetter # L& [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K +1D4A9..1D4AC ; ALetter # L& [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q +1D4AE..1D4B9 ; ALetter # L& [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D +1D4BB ; ALetter # L& MATHEMATICAL SCRIPT SMALL F +1D4BD..1D4C3 ; ALetter # L& [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N +1D4C5..1D505 ; ALetter # L& [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B +1D507..1D50A ; ALetter # L& [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G +1D50D..1D514 ; ALetter # L& [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q +1D516..1D51C ; ALetter # L& [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y +1D51E..1D539 ; ALetter # L& [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B +1D53B..1D53E ; ALetter # L& [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G +1D540..1D544 ; ALetter # L& [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M +1D546 ; ALetter # L& MATHEMATICAL DOUBLE-STRUCK CAPITAL O +1D54A..1D550 ; ALetter # L& [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y +1D552..1D6A5 ; ALetter # L& [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J +1D6A8..1D6C0 ; ALetter # L& [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA +1D6C2..1D6DA ; ALetter # L& [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA +1D6DC..1D6FA ; ALetter # L& [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA +1D6FC..1D714 ; ALetter # L& [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA +1D716..1D734 ; ALetter # L& [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA +1D736..1D74E ; ALetter # L& [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA +1D750..1D76E ; ALetter # L& [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA +1D770..1D788 ; ALetter # L& [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA +1D78A..1D7A8 ; ALetter # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA +1D7AA..1D7C2 ; ALetter # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA +1D7C4..1D7CB ; ALetter # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA +1DF00..1DF09 ; ALetter # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK +1DF0A ; ALetter # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK +1DF0B..1DF1E ; ALetter # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL +1DF25..1DF2A ; ALetter # L& [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK +1E030..1E06D ; ALetter # Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE +1E100..1E12C ; ALetter # Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W +1E137..1E13D ; ALetter # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER +1E14E ; ALetter # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ +1E290..1E2AD ; ALetter # Lo [30] TOTO LETTER PA..TOTO LETTER A +1E2C0..1E2EB ; ALetter # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH +1E4D0..1E4EA ; ALetter # Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL +1E4EB ; ALetter # Lm NAG MUNDARI SIGN OJOD +1E7E0..1E7E6 ; ALetter # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO +1E7E8..1E7EB ; ALetter # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE +1E7ED..1E7EE ; ALetter # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE +1E7F0..1E7FE ; ALetter # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE +1E800..1E8C4 ; ALetter # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON +1E900..1E943 ; ALetter # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA +1E94B ; ALetter # Lm ADLAM NASALIZATION MARK +1EE00..1EE03 ; ALetter # Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL +1EE05..1EE1F ; ALetter # Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF +1EE21..1EE22 ; ALetter # Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM +1EE24 ; ALetter # Lo ARABIC MATHEMATICAL INITIAL HEH +1EE27 ; ALetter # Lo ARABIC MATHEMATICAL INITIAL HAH +1EE29..1EE32 ; ALetter # Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF +1EE34..1EE37 ; ALetter # Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH +1EE39 ; ALetter # Lo ARABIC MATHEMATICAL INITIAL DAD +1EE3B ; ALetter # Lo ARABIC MATHEMATICAL INITIAL GHAIN +1EE42 ; ALetter # Lo ARABIC MATHEMATICAL TAILED JEEM +1EE47 ; ALetter # Lo ARABIC MATHEMATICAL TAILED HAH +1EE49 ; ALetter # Lo ARABIC MATHEMATICAL TAILED YEH +1EE4B ; ALetter # Lo ARABIC MATHEMATICAL TAILED LAM +1EE4D..1EE4F ; ALetter # Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN +1EE51..1EE52 ; ALetter # Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF +1EE54 ; ALetter # Lo ARABIC MATHEMATICAL TAILED SHEEN +1EE57 ; ALetter # Lo ARABIC MATHEMATICAL TAILED KHAH +1EE59 ; ALetter # Lo ARABIC MATHEMATICAL TAILED DAD +1EE5B ; ALetter # Lo ARABIC MATHEMATICAL TAILED GHAIN +1EE5D ; ALetter # Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON +1EE5F ; ALetter # Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF +1EE61..1EE62 ; ALetter # Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM +1EE64 ; ALetter # Lo ARABIC MATHEMATICAL STRETCHED HEH +1EE67..1EE6A ; ALetter # Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF +1EE6C..1EE72 ; ALetter # Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF +1EE74..1EE77 ; ALetter # Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH +1EE79..1EE7C ; ALetter # Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH +1EE7E ; ALetter # Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH +1EE80..1EE89 ; ALetter # Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH +1EE8B..1EE9B ; ALetter # Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN +1EEA1..1EEA3 ; ALetter # Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL +1EEA5..1EEA9 ; ALetter # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH +1EEAB..1EEBB ; ALetter # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN +1F130..1F149 ; ALetter # So [26] SQUARED LATIN CAPITAL LETTER A..SQUARED LATIN CAPITAL LETTER Z +1F150..1F169 ; ALetter # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z +1F170..1F189 ; ALetter # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z + +# Total code points: 29490 + +# ================================================ + +003A ; MidLetter # Po COLON +00B7 ; MidLetter # Po MIDDLE DOT +0387 ; MidLetter # Po GREEK ANO TELEIA +055F ; MidLetter # Po ARMENIAN ABBREVIATION MARK +05F4 ; MidLetter # Po HEBREW PUNCTUATION GERSHAYIM +2027 ; MidLetter # Po HYPHENATION POINT +FE13 ; MidLetter # Po PRESENTATION FORM FOR VERTICAL COLON +FE55 ; MidLetter # Po SMALL COLON +FF1A ; MidLetter # Po FULLWIDTH COLON + +# Total code points: 9 + +# ================================================ + +002C ; MidNum # Po COMMA +003B ; MidNum # Po SEMICOLON +037E ; MidNum # Po GREEK QUESTION MARK +0589 ; MidNum # Po ARMENIAN FULL STOP +060C..060D ; MidNum # Po [2] ARABIC COMMA..ARABIC DATE SEPARATOR +066C ; MidNum # Po ARABIC THOUSANDS SEPARATOR +07F8 ; MidNum # Po NKO COMMA +2044 ; MidNum # Sm FRACTION SLASH +FE10 ; MidNum # Po PRESENTATION FORM FOR VERTICAL COMMA +FE14 ; MidNum # Po PRESENTATION FORM FOR VERTICAL SEMICOLON +FE50 ; MidNum # Po SMALL COMMA +FE54 ; MidNum # Po SMALL SEMICOLON +FF0C ; MidNum # Po FULLWIDTH COMMA +FF1B ; MidNum # Po FULLWIDTH SEMICOLON + +# Total code points: 15 + +# ================================================ + +002E ; MidNumLet # Po FULL STOP +2018 ; MidNumLet # Pi LEFT SINGLE QUOTATION MARK +2019 ; MidNumLet # Pf RIGHT SINGLE QUOTATION MARK +2024 ; MidNumLet # Po ONE DOT LEADER +FE52 ; MidNumLet # Po SMALL FULL STOP +FF07 ; MidNumLet # Po FULLWIDTH APOSTROPHE +FF0E ; MidNumLet # Po FULLWIDTH FULL STOP + +# Total code points: 7 + +# ================================================ + +0030..0039 ; Numeric # Nd [10] DIGIT ZERO..DIGIT NINE +0600..0605 ; Numeric # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE +0660..0669 ; Numeric # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE +066B ; Numeric # Po ARABIC DECIMAL SEPARATOR +06DD ; Numeric # Cf ARABIC END OF AYAH +06F0..06F9 ; Numeric # Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE +07C0..07C9 ; Numeric # Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE +0890..0891 ; Numeric # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE +08E2 ; Numeric # Cf ARABIC DISPUTED END OF AYAH +0966..096F ; Numeric # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE +09E6..09EF ; Numeric # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE +0A66..0A6F ; Numeric # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE +0AE6..0AEF ; Numeric # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE +0B66..0B6F ; Numeric # Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE +0BE6..0BEF ; Numeric # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE +0C66..0C6F ; Numeric # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE +0CE6..0CEF ; Numeric # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE +0D66..0D6F ; Numeric # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE +0DE6..0DEF ; Numeric # Nd [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE +0E50..0E59 ; Numeric # Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE +0ED0..0ED9 ; Numeric # Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE +0F20..0F29 ; Numeric # Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE +1040..1049 ; Numeric # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE +1090..1099 ; Numeric # Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE +17E0..17E9 ; Numeric # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE +1810..1819 ; Numeric # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE +1946..194F ; Numeric # Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE +19D0..19D9 ; Numeric # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE +1A80..1A89 ; Numeric # Nd [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE +1A90..1A99 ; Numeric # Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE +1B50..1B59 ; Numeric # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE +1BB0..1BB9 ; Numeric # Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE +1C40..1C49 ; Numeric # Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE +1C50..1C59 ; Numeric # Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE +A620..A629 ; Numeric # Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE +A8D0..A8D9 ; Numeric # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE +A900..A909 ; Numeric # Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE +A9D0..A9D9 ; Numeric # Nd [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE +A9F0..A9F9 ; Numeric # Nd [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE +AA50..AA59 ; Numeric # Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE +ABF0..ABF9 ; Numeric # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE +FF10..FF19 ; Numeric # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE +104A0..104A9 ; Numeric # Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE +10D30..10D39 ; Numeric # Nd [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE +11066..1106F ; Numeric # Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE +110BD ; Numeric # Cf KAITHI NUMBER SIGN +110CD ; Numeric # Cf KAITHI NUMBER SIGN ABOVE +110F0..110F9 ; Numeric # Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE +11136..1113F ; Numeric # Nd [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE +111D0..111D9 ; Numeric # Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE +112F0..112F9 ; Numeric # Nd [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE +11450..11459 ; Numeric # Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE +114D0..114D9 ; Numeric # Nd [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE +11650..11659 ; Numeric # Nd [10] MODI DIGIT ZERO..MODI DIGIT NINE +116C0..116C9 ; Numeric # Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE +11730..11739 ; Numeric # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE +118E0..118E9 ; Numeric # Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE +11950..11959 ; Numeric # Nd [10] DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE +11C50..11C59 ; Numeric # Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE +11D50..11D59 ; Numeric # Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE +11DA0..11DA9 ; Numeric # Nd [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE +11F50..11F59 ; Numeric # Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE +16A60..16A69 ; Numeric # Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE +16AC0..16AC9 ; Numeric # Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE +16B50..16B59 ; Numeric # Nd [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE +1D7CE..1D7FF ; Numeric # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE +1E140..1E149 ; Numeric # Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE +1E2F0..1E2F9 ; Numeric # Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE +1E4F0..1E4F9 ; Numeric # Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE +1E950..1E959 ; Numeric # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE +1FBF0..1FBF9 ; Numeric # Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE + +# Total code points: 693 + +# ================================================ + +005F ; ExtendNumLet # Pc LOW LINE +202F ; ExtendNumLet # Zs NARROW NO-BREAK SPACE +203F..2040 ; ExtendNumLet # Pc [2] UNDERTIE..CHARACTER TIE +2054 ; ExtendNumLet # Pc INVERTED UNDERTIE +FE33..FE34 ; ExtendNumLet # Pc [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE +FE4D..FE4F ; ExtendNumLet # Pc [3] DASHED LOW LINE..WAVY LOW LINE +FF3F ; ExtendNumLet # Pc FULLWIDTH LOW LINE + +# Total code points: 11 + +# ================================================ + +200D ; ZWJ # Cf ZERO WIDTH JOINER + +# Total code points: 1 + +# ================================================ + +0020 ; WSegSpace # Zs SPACE +1680 ; WSegSpace # Zs OGHAM SPACE MARK +2000..2006 ; WSegSpace # Zs [7] EN QUAD..SIX-PER-EM SPACE +2008..200A ; WSegSpace # Zs [3] PUNCTUATION SPACE..HAIR SPACE +205F ; WSegSpace # Zs MEDIUM MATHEMATICAL SPACE +3000 ; WSegSpace # Zs IDEOGRAPHIC SPACE + +# Total code points: 14 + +# EOF diff --git a/resources/standards-data/unicode-character-database/build.sh b/resources/standards-data/unicode-character-database/build.sh new file mode 100755 index 0000000000..a1be097be6 --- /dev/null +++ b/resources/standards-data/unicode-character-database/build.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# +# Compile our sourcemap-path remapping module for use by Web builds, releases, etc. +# +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../resources/build/builder.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +. "$KEYMAN_ROOT/resources/build/minimum-versions.inc.sh" + +################################ Main script ################################ + +builder_describe \ + "Downloads Unicode data consumed by various Keyman platforms." \ + clean configure build + +builder_describe_outputs \ + configure /resources/standards-data/unicode-character-database/UnicodeData.txt \ + build /resources/standards-data/unicode-character-database/UnicodeData.txt + +builder_parse "$@" + +# Used by Developer +BLOCKS_SRC_HREF="https://www.unicode.org/Public/$KEYMAN_VERSION_UNICODE/ucd/Blocks.txt" +BLOCKS_SRC_LOCAL="./Blocks.txt" + +UNICODE_DATA_SRC_HREF="https://www.unicode.org/Public/$KEYMAN_VERSION_UNICODE/ucd/UnicodeData.txt" +UNICODE_DATA_SRC_LOCAL="./UnicodeData.txt" + +# Used by common/models/wordbreakers for the default Unicode wordbreaker. +WORDBREAK_PROP_SRC_HREF="https://www.unicode.org/Public/$KEYMAN_VERSION_UNICODE/ucd/auxiliary/WordBreakProperty.txt" +WORDBREAK_PROP_SRC_LOCAL="./WordBreakProperty.txt" + +EMOJI_DATA_SRC_HREF="https://www.unicode.org/Public/$KEYMAN_VERSION_UNICODE/ucd/emoji/emoji-data.txt" +EMOJI_DATA_SRC_LOCAL="./emoji-data.txt" + +function downloadPropertyFile() { + local SRC="$1" + local DEST="$2" + + local RETRY=5 # Curl retries this number of times before giving up + local RETRY_DELAY=5 # Make curl sleep this amount of time before each retry when a transfer has failed + + echo "Downloading ${SRC} - ${RETRY} attempts" + # local URL_DOWNLOAD_FILE=`curl --retry "$RETRY" --retry-delay "$RETRY_DELAY" --silent "${SRC}" | "$JQ" -r .txt` + curl --fail --retry "$RETRY" --retry-delay "$RETRY_DELAY" --silent "$SRC" --output "$DEST" || { + builder_die "Downloading $SRC failed with error $?" + } +} + +do_clean() { + rm -rf **/*.txt +} + +do_configure() { + downloadPropertyFile "${BLOCKS_SRC_HREF}" "${BLOCKS_SRC_LOCAL}" + downloadPropertyFile "${UNICODE_DATA_SRC_HREF}" "${UNICODE_DATA_SRC_LOCAL}" + + downloadPropertyFile "${WORDBREAK_PROP_SRC_HREF}" "${WORDBREAK_PROP_SRC_LOCAL}" + downloadPropertyFile "${EMOJI_DATA_SRC_HREF}" "${EMOJI_DATA_SRC_LOCAL}" +} + +builder_run_action clean do_clean +builder_run_action configure do_configure \ No newline at end of file diff --git a/resources/standards-data/unicode-character-database/emoji-data.txt b/resources/standards-data/unicode-character-database/emoji-data.txt new file mode 100644 index 0000000000..0ba10e9ce4 --- /dev/null +++ b/resources/standards-data/unicode-character-database/emoji-data.txt @@ -0,0 +1,1320 @@ +# emoji-data.txt +# Date: 2023-02-01, 02:22:54 GMT +# © 2023 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see https://www.unicode.org/terms_of_use.html +# +# Emoji Data for UTS #51 +# Used with Emoji Version 15.1 and subsequent minor revisions (if any) +# +# For documentation and usage, see https://www.unicode.org/reports/tr51 +# +# Format: +# ; # +# Note: there is no guarantee as to the structure of whitespace or comments +# +# Characters and sequences are listed in code point order. Users should be shown a more natural order. +# See the CLDR collation order for Emoji. + + +# ================================================ + +# All omitted code points have Emoji=No + +0023 ; Emoji # E0.0 [1] (#️) hash sign +002A ; Emoji # E0.0 [1] (*️) asterisk +0030..0039 ; Emoji # E0.0 [10] (0️..9️) digit zero..digit nine +00A9 ; Emoji # E0.6 [1] (©️) copyright +00AE ; Emoji # E0.6 [1] (®️) registered +203C ; Emoji # E0.6 [1] (‼️) double exclamation mark +2049 ; Emoji # E0.6 [1] (⁉️) exclamation question mark +2122 ; Emoji # E0.6 [1] (™️) trade mark +2139 ; Emoji # E0.6 [1] (ℹ️) information +2194..2199 ; Emoji # E0.6 [6] (↔️..↙️) left-right arrow..down-left arrow +21A9..21AA ; Emoji # E0.6 [2] (↩️..↪️) right arrow curving left..left arrow curving right +231A..231B ; Emoji # E0.6 [2] (⌚..⌛) watch..hourglass done +2328 ; Emoji # E1.0 [1] (⌨️) keyboard +23CF ; Emoji # E1.0 [1] (⏏️) eject button +23E9..23EC ; Emoji # E0.6 [4] (⏩..⏬) fast-forward button..fast down button +23ED..23EE ; Emoji # E0.7 [2] (⏭️..⏮️) next track button..last track button +23EF ; Emoji # E1.0 [1] (⏯️) play or pause button +23F0 ; Emoji # E0.6 [1] (⏰) alarm clock +23F1..23F2 ; Emoji # E1.0 [2] (⏱️..⏲️) stopwatch..timer clock +23F3 ; Emoji # E0.6 [1] (⏳) hourglass not done +23F8..23FA ; Emoji # E0.7 [3] (⏸️..⏺️) pause button..record button +24C2 ; Emoji # E0.6 [1] (Ⓜ️) circled M +25AA..25AB ; Emoji # E0.6 [2] (▪️..▫️) black small square..white small square +25B6 ; Emoji # E0.6 [1] (▶️) play button +25C0 ; Emoji # E0.6 [1] (◀️) reverse button +25FB..25FE ; Emoji # E0.6 [4] (◻️..◾) white medium square..black medium-small square +2600..2601 ; Emoji # E0.6 [2] (☀️..☁️) sun..cloud +2602..2603 ; Emoji # E0.7 [2] (☂️..☃️) umbrella..snowman +2604 ; Emoji # E1.0 [1] (☄️) comet +260E ; Emoji # E0.6 [1] (☎️) telephone +2611 ; Emoji # E0.6 [1] (☑️) check box with check +2614..2615 ; Emoji # E0.6 [2] (☔..☕) umbrella with rain drops..hot beverage +2618 ; Emoji # E1.0 [1] (☘️) shamrock +261D ; Emoji # E0.6 [1] (☝️) index pointing up +2620 ; Emoji # E1.0 [1] (☠️) skull and crossbones +2622..2623 ; Emoji # E1.0 [2] (☢️..☣️) radioactive..biohazard +2626 ; Emoji # E1.0 [1] (☦️) orthodox cross +262A ; Emoji # E0.7 [1] (☪️) star and crescent +262E ; Emoji # E1.0 [1] (☮️) peace symbol +262F ; Emoji # E0.7 [1] (☯️) yin yang +2638..2639 ; Emoji # E0.7 [2] (☸️..☹️) wheel of dharma..frowning face +263A ; Emoji # E0.6 [1] (☺️) smiling face +2640 ; Emoji # E4.0 [1] (♀️) female sign +2642 ; Emoji # E4.0 [1] (♂️) male sign +2648..2653 ; Emoji # E0.6 [12] (♈..♓) Aries..Pisces +265F ; Emoji # E11.0 [1] (♟️) chess pawn +2660 ; Emoji # E0.6 [1] (♠️) spade suit +2663 ; Emoji # E0.6 [1] (♣️) club suit +2665..2666 ; Emoji # E0.6 [2] (♥️..♦️) heart suit..diamond suit +2668 ; Emoji # E0.6 [1] (♨️) hot springs +267B ; Emoji # E0.6 [1] (♻️) recycling symbol +267E ; Emoji # E11.0 [1] (♾️) infinity +267F ; Emoji # E0.6 [1] (♿) wheelchair symbol +2692 ; Emoji # E1.0 [1] (⚒️) hammer and pick +2693 ; Emoji # E0.6 [1] (⚓) anchor +2694 ; Emoji # E1.0 [1] (⚔️) crossed swords +2695 ; Emoji # E4.0 [1] (⚕️) medical symbol +2696..2697 ; Emoji # E1.0 [2] (⚖️..⚗️) balance scale..alembic +2699 ; Emoji # E1.0 [1] (⚙️) gear +269B..269C ; Emoji # E1.0 [2] (⚛️..⚜️) atom symbol..fleur-de-lis +26A0..26A1 ; Emoji # E0.6 [2] (⚠️..⚡) warning..high voltage +26A7 ; Emoji # E13.0 [1] (⚧️) transgender symbol +26AA..26AB ; Emoji # E0.6 [2] (⚪..⚫) white circle..black circle +26B0..26B1 ; Emoji # E1.0 [2] (⚰️..⚱️) coffin..funeral urn +26BD..26BE ; Emoji # E0.6 [2] (⚽..⚾) soccer ball..baseball +26C4..26C5 ; Emoji # E0.6 [2] (⛄..⛅) snowman without snow..sun behind cloud +26C8 ; Emoji # E0.7 [1] (⛈️) cloud with lightning and rain +26CE ; Emoji # E0.6 [1] (⛎) Ophiuchus +26CF ; Emoji # E0.7 [1] (⛏️) pick +26D1 ; Emoji # E0.7 [1] (⛑️) rescue worker’s helmet +26D3 ; Emoji # E0.7 [1] (⛓️) chains +26D4 ; Emoji # E0.6 [1] (⛔) no entry +26E9 ; Emoji # E0.7 [1] (⛩️) shinto shrine +26EA ; Emoji # E0.6 [1] (⛪) church +26F0..26F1 ; Emoji # E0.7 [2] (⛰️..⛱️) mountain..umbrella on ground +26F2..26F3 ; Emoji # E0.6 [2] (⛲..⛳) fountain..flag in hole +26F4 ; Emoji # E0.7 [1] (⛴️) ferry +26F5 ; Emoji # E0.6 [1] (⛵) sailboat +26F7..26F9 ; Emoji # E0.7 [3] (⛷️..⛹️) skier..person bouncing ball +26FA ; Emoji # E0.6 [1] (⛺) tent +26FD ; Emoji # E0.6 [1] (⛽) fuel pump +2702 ; Emoji # E0.6 [1] (✂️) scissors +2705 ; Emoji # E0.6 [1] (✅) check mark button +2708..270C ; Emoji # E0.6 [5] (✈️..✌️) airplane..victory hand +270D ; Emoji # E0.7 [1] (✍️) writing hand +270F ; Emoji # E0.6 [1] (✏️) pencil +2712 ; Emoji # E0.6 [1] (✒️) black nib +2714 ; Emoji # E0.6 [1] (✔️) check mark +2716 ; Emoji # E0.6 [1] (✖️) multiply +271D ; Emoji # E0.7 [1] (✝️) latin cross +2721 ; Emoji # E0.7 [1] (✡️) star of David +2728 ; Emoji # E0.6 [1] (✨) sparkles +2733..2734 ; Emoji # E0.6 [2] (✳️..✴️) eight-spoked asterisk..eight-pointed star +2744 ; Emoji # E0.6 [1] (❄️) snowflake +2747 ; Emoji # E0.6 [1] (❇️) sparkle +274C ; Emoji # E0.6 [1] (❌) cross mark +274E ; Emoji # E0.6 [1] (❎) cross mark button +2753..2755 ; Emoji # E0.6 [3] (❓..❕) red question mark..white exclamation mark +2757 ; Emoji # E0.6 [1] (❗) red exclamation mark +2763 ; Emoji # E1.0 [1] (❣️) heart exclamation +2764 ; Emoji # E0.6 [1] (❤️) red heart +2795..2797 ; Emoji # E0.6 [3] (➕..➗) plus..divide +27A1 ; Emoji # E0.6 [1] (➡️) right arrow +27B0 ; Emoji # E0.6 [1] (➰) curly loop +27BF ; Emoji # E1.0 [1] (➿) double curly loop +2934..2935 ; Emoji # E0.6 [2] (⤴️..⤵️) right arrow curving up..right arrow curving down +2B05..2B07 ; Emoji # E0.6 [3] (⬅️..⬇️) left arrow..down arrow +2B1B..2B1C ; Emoji # E0.6 [2] (⬛..⬜) black large square..white large square +2B50 ; Emoji # E0.6 [1] (⭐) star +2B55 ; Emoji # E0.6 [1] (⭕) hollow red circle +3030 ; Emoji # E0.6 [1] (〰️) wavy dash +303D ; Emoji # E0.6 [1] (〽️) part alternation mark +3297 ; Emoji # E0.6 [1] (㊗️) Japanese “congratulations” button +3299 ; Emoji # E0.6 [1] (㊙️) Japanese “secret” button +1F004 ; Emoji # E0.6 [1] (🀄) mahjong red dragon +1F0CF ; Emoji # E0.6 [1] (🃏) joker +1F170..1F171 ; Emoji # E0.6 [2] (🅰️..🅱️) A button (blood type)..B button (blood type) +1F17E..1F17F ; Emoji # E0.6 [2] (🅾️..🅿️) O button (blood type)..P button +1F18E ; Emoji # E0.6 [1] (🆎) AB button (blood type) +1F191..1F19A ; Emoji # E0.6 [10] (🆑..🆚) CL button..VS button +1F1E6..1F1FF ; Emoji # E0.0 [26] (🇦..🇿) regional indicator symbol letter a..regional indicator symbol letter z +1F201..1F202 ; Emoji # E0.6 [2] (🈁..🈂️) Japanese “here” button..Japanese “service charge” button +1F21A ; Emoji # E0.6 [1] (🈚) Japanese “free of charge” button +1F22F ; Emoji # E0.6 [1] (🈯) Japanese “reserved” button +1F232..1F23A ; Emoji # E0.6 [9] (🈲..🈺) Japanese “prohibited” button..Japanese “open for business” button +1F250..1F251 ; Emoji # E0.6 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button +1F300..1F30C ; Emoji # E0.6 [13] (🌀..🌌) cyclone..milky way +1F30D..1F30E ; Emoji # E0.7 [2] (🌍..🌎) globe showing Europe-Africa..globe showing Americas +1F30F ; Emoji # E0.6 [1] (🌏) globe showing Asia-Australia +1F310 ; Emoji # E1.0 [1] (🌐) globe with meridians +1F311 ; Emoji # E0.6 [1] (🌑) new moon +1F312 ; Emoji # E1.0 [1] (🌒) waxing crescent moon +1F313..1F315 ; Emoji # E0.6 [3] (🌓..🌕) first quarter moon..full moon +1F316..1F318 ; Emoji # E1.0 [3] (🌖..🌘) waning gibbous moon..waning crescent moon +1F319 ; Emoji # E0.6 [1] (🌙) crescent moon +1F31A ; Emoji # E1.0 [1] (🌚) new moon face +1F31B ; Emoji # E0.6 [1] (🌛) first quarter moon face +1F31C ; Emoji # E0.7 [1] (🌜) last quarter moon face +1F31D..1F31E ; Emoji # E1.0 [2] (🌝..🌞) full moon face..sun with face +1F31F..1F320 ; Emoji # E0.6 [2] (🌟..🌠) glowing star..shooting star +1F321 ; Emoji # E0.7 [1] (🌡️) thermometer +1F324..1F32C ; Emoji # E0.7 [9] (🌤️..🌬️) sun behind small cloud..wind face +1F32D..1F32F ; Emoji # E1.0 [3] (🌭..🌯) hot dog..burrito +1F330..1F331 ; Emoji # E0.6 [2] (🌰..🌱) chestnut..seedling +1F332..1F333 ; Emoji # E1.0 [2] (🌲..🌳) evergreen tree..deciduous tree +1F334..1F335 ; Emoji # E0.6 [2] (🌴..🌵) palm tree..cactus +1F336 ; Emoji # E0.7 [1] (🌶️) hot pepper +1F337..1F34A ; Emoji # E0.6 [20] (🌷..🍊) tulip..tangerine +1F34B ; Emoji # E1.0 [1] (🍋) lemon +1F34C..1F34F ; Emoji # E0.6 [4] (🍌..🍏) banana..green apple +1F350 ; Emoji # E1.0 [1] (🍐) pear +1F351..1F37B ; Emoji # E0.6 [43] (🍑..🍻) peach..clinking beer mugs +1F37C ; Emoji # E1.0 [1] (🍼) baby bottle +1F37D ; Emoji # E0.7 [1] (🍽️) fork and knife with plate +1F37E..1F37F ; Emoji # E1.0 [2] (🍾..🍿) bottle with popping cork..popcorn +1F380..1F393 ; Emoji # E0.6 [20] (🎀..🎓) ribbon..graduation cap +1F396..1F397 ; Emoji # E0.7 [2] (🎖️..🎗️) military medal..reminder ribbon +1F399..1F39B ; Emoji # E0.7 [3] (🎙️..🎛️) studio microphone..control knobs +1F39E..1F39F ; Emoji # E0.7 [2] (🎞️..🎟️) film frames..admission tickets +1F3A0..1F3C4 ; Emoji # E0.6 [37] (🎠..🏄) carousel horse..person surfing +1F3C5 ; Emoji # E1.0 [1] (🏅) sports medal +1F3C6 ; Emoji # E0.6 [1] (🏆) trophy +1F3C7 ; Emoji # E1.0 [1] (🏇) horse racing +1F3C8 ; Emoji # E0.6 [1] (🏈) american football +1F3C9 ; Emoji # E1.0 [1] (🏉) rugby football +1F3CA ; Emoji # E0.6 [1] (🏊) person swimming +1F3CB..1F3CE ; Emoji # E0.7 [4] (🏋️..🏎️) person lifting weights..racing car +1F3CF..1F3D3 ; Emoji # E1.0 [5] (🏏..🏓) cricket game..ping pong +1F3D4..1F3DF ; Emoji # E0.7 [12] (🏔️..🏟️) snow-capped mountain..stadium +1F3E0..1F3E3 ; Emoji # E0.6 [4] (🏠..🏣) house..Japanese post office +1F3E4 ; Emoji # E1.0 [1] (🏤) post office +1F3E5..1F3F0 ; Emoji # E0.6 [12] (🏥..🏰) hospital..castle +1F3F3 ; Emoji # E0.7 [1] (🏳️) white flag +1F3F4 ; Emoji # E1.0 [1] (🏴) black flag +1F3F5 ; Emoji # E0.7 [1] (🏵️) rosette +1F3F7 ; Emoji # E0.7 [1] (🏷️) label +1F3F8..1F407 ; Emoji # E1.0 [16] (🏸..🐇) badminton..rabbit +1F408 ; Emoji # E0.7 [1] (🐈) cat +1F409..1F40B ; Emoji # E1.0 [3] (🐉..🐋) dragon..whale +1F40C..1F40E ; Emoji # E0.6 [3] (🐌..🐎) snail..horse +1F40F..1F410 ; Emoji # E1.0 [2] (🐏..🐐) ram..goat +1F411..1F412 ; Emoji # E0.6 [2] (🐑..🐒) ewe..monkey +1F413 ; Emoji # E1.0 [1] (🐓) rooster +1F414 ; Emoji # E0.6 [1] (🐔) chicken +1F415 ; Emoji # E0.7 [1] (🐕) dog +1F416 ; Emoji # E1.0 [1] (🐖) pig +1F417..1F429 ; Emoji # E0.6 [19] (🐗..🐩) boar..poodle +1F42A ; Emoji # E1.0 [1] (🐪) camel +1F42B..1F43E ; Emoji # E0.6 [20] (🐫..🐾) two-hump camel..paw prints +1F43F ; Emoji # E0.7 [1] (🐿️) chipmunk +1F440 ; Emoji # E0.6 [1] (👀) eyes +1F441 ; Emoji # E0.7 [1] (👁️) eye +1F442..1F464 ; Emoji # E0.6 [35] (👂..👤) ear..bust in silhouette +1F465 ; Emoji # E1.0 [1] (👥) busts in silhouette +1F466..1F46B ; Emoji # E0.6 [6] (👦..👫) boy..woman and man holding hands +1F46C..1F46D ; Emoji # E1.0 [2] (👬..👭) men holding hands..women holding hands +1F46E..1F4AC ; Emoji # E0.6 [63] (👮..💬) police officer..speech balloon +1F4AD ; Emoji # E1.0 [1] (💭) thought balloon +1F4AE..1F4B5 ; Emoji # E0.6 [8] (💮..💵) white flower..dollar banknote +1F4B6..1F4B7 ; Emoji # E1.0 [2] (💶..💷) euro banknote..pound banknote +1F4B8..1F4EB ; Emoji # E0.6 [52] (💸..📫) money with wings..closed mailbox with raised flag +1F4EC..1F4ED ; Emoji # E0.7 [2] (📬..📭) open mailbox with raised flag..open mailbox with lowered flag +1F4EE ; Emoji # E0.6 [1] (📮) postbox +1F4EF ; Emoji # E1.0 [1] (📯) postal horn +1F4F0..1F4F4 ; Emoji # E0.6 [5] (📰..📴) newspaper..mobile phone off +1F4F5 ; Emoji # E1.0 [1] (📵) no mobile phones +1F4F6..1F4F7 ; Emoji # E0.6 [2] (📶..📷) antenna bars..camera +1F4F8 ; Emoji # E1.0 [1] (📸) camera with flash +1F4F9..1F4FC ; Emoji # E0.6 [4] (📹..📼) video camera..videocassette +1F4FD ; Emoji # E0.7 [1] (📽️) film projector +1F4FF..1F502 ; Emoji # E1.0 [4] (📿..🔂) prayer beads..repeat single button +1F503 ; Emoji # E0.6 [1] (🔃) clockwise vertical arrows +1F504..1F507 ; Emoji # E1.0 [4] (🔄..🔇) counterclockwise arrows button..muted speaker +1F508 ; Emoji # E0.7 [1] (🔈) speaker low volume +1F509 ; Emoji # E1.0 [1] (🔉) speaker medium volume +1F50A..1F514 ; Emoji # E0.6 [11] (🔊..🔔) speaker high volume..bell +1F515 ; Emoji # E1.0 [1] (🔕) bell with slash +1F516..1F52B ; Emoji # E0.6 [22] (🔖..🔫) bookmark..water pistol +1F52C..1F52D ; Emoji # E1.0 [2] (🔬..🔭) microscope..telescope +1F52E..1F53D ; Emoji # E0.6 [16] (🔮..🔽) crystal ball..downwards button +1F549..1F54A ; Emoji # E0.7 [2] (🕉️..🕊️) om..dove +1F54B..1F54E ; Emoji # E1.0 [4] (🕋..🕎) kaaba..menorah +1F550..1F55B ; Emoji # E0.6 [12] (🕐..🕛) one o’clock..twelve o’clock +1F55C..1F567 ; Emoji # E0.7 [12] (🕜..🕧) one-thirty..twelve-thirty +1F56F..1F570 ; Emoji # E0.7 [2] (🕯️..🕰️) candle..mantelpiece clock +1F573..1F579 ; Emoji # E0.7 [7] (🕳️..🕹️) hole..joystick +1F57A ; Emoji # E3.0 [1] (🕺) man dancing +1F587 ; Emoji # E0.7 [1] (🖇️) linked paperclips +1F58A..1F58D ; Emoji # E0.7 [4] (🖊️..🖍️) pen..crayon +1F590 ; Emoji # E0.7 [1] (🖐️) hand with fingers splayed +1F595..1F596 ; Emoji # E1.0 [2] (🖕..🖖) middle finger..vulcan salute +1F5A4 ; Emoji # E3.0 [1] (🖤) black heart +1F5A5 ; Emoji # E0.7 [1] (🖥️) desktop computer +1F5A8 ; Emoji # E0.7 [1] (🖨️) printer +1F5B1..1F5B2 ; Emoji # E0.7 [2] (🖱️..🖲️) computer mouse..trackball +1F5BC ; Emoji # E0.7 [1] (🖼️) framed picture +1F5C2..1F5C4 ; Emoji # E0.7 [3] (🗂️..🗄️) card index dividers..file cabinet +1F5D1..1F5D3 ; Emoji # E0.7 [3] (🗑️..🗓️) wastebasket..spiral calendar +1F5DC..1F5DE ; Emoji # E0.7 [3] (🗜️..🗞️) clamp..rolled-up newspaper +1F5E1 ; Emoji # E0.7 [1] (🗡️) dagger +1F5E3 ; Emoji # E0.7 [1] (🗣️) speaking head +1F5E8 ; Emoji # E2.0 [1] (🗨️) left speech bubble +1F5EF ; Emoji # E0.7 [1] (🗯️) right anger bubble +1F5F3 ; Emoji # E0.7 [1] (🗳️) ballot box with ballot +1F5FA ; Emoji # E0.7 [1] (🗺️) world map +1F5FB..1F5FF ; Emoji # E0.6 [5] (🗻..🗿) mount fuji..moai +1F600 ; Emoji # E1.0 [1] (😀) grinning face +1F601..1F606 ; Emoji # E0.6 [6] (😁..😆) beaming face with smiling eyes..grinning squinting face +1F607..1F608 ; Emoji # E1.0 [2] (😇..😈) smiling face with halo..smiling face with horns +1F609..1F60D ; Emoji # E0.6 [5] (😉..😍) winking face..smiling face with heart-eyes +1F60E ; Emoji # E1.0 [1] (😎) smiling face with sunglasses +1F60F ; Emoji # E0.6 [1] (😏) smirking face +1F610 ; Emoji # E0.7 [1] (😐) neutral face +1F611 ; Emoji # E1.0 [1] (😑) expressionless face +1F612..1F614 ; Emoji # E0.6 [3] (😒..😔) unamused face..pensive face +1F615 ; Emoji # E1.0 [1] (😕) confused face +1F616 ; Emoji # E0.6 [1] (😖) confounded face +1F617 ; Emoji # E1.0 [1] (😗) kissing face +1F618 ; Emoji # E0.6 [1] (😘) face blowing a kiss +1F619 ; Emoji # E1.0 [1] (😙) kissing face with smiling eyes +1F61A ; Emoji # E0.6 [1] (😚) kissing face with closed eyes +1F61B ; Emoji # E1.0 [1] (😛) face with tongue +1F61C..1F61E ; Emoji # E0.6 [3] (😜..😞) winking face with tongue..disappointed face +1F61F ; Emoji # E1.0 [1] (😟) worried face +1F620..1F625 ; Emoji # E0.6 [6] (😠..😥) angry face..sad but relieved face +1F626..1F627 ; Emoji # E1.0 [2] (😦..😧) frowning face with open mouth..anguished face +1F628..1F62B ; Emoji # E0.6 [4] (😨..😫) fearful face..tired face +1F62C ; Emoji # E1.0 [1] (😬) grimacing face +1F62D ; Emoji # E0.6 [1] (😭) loudly crying face +1F62E..1F62F ; Emoji # E1.0 [2] (😮..😯) face with open mouth..hushed face +1F630..1F633 ; Emoji # E0.6 [4] (😰..😳) anxious face with sweat..flushed face +1F634 ; Emoji # E1.0 [1] (😴) sleeping face +1F635 ; Emoji # E0.6 [1] (😵) face with crossed-out eyes +1F636 ; Emoji # E1.0 [1] (😶) face without mouth +1F637..1F640 ; Emoji # E0.6 [10] (😷..🙀) face with medical mask..weary cat +1F641..1F644 ; Emoji # E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes +1F645..1F64F ; Emoji # E0.6 [11] (🙅..🙏) person gesturing NO..folded hands +1F680 ; Emoji # E0.6 [1] (🚀) rocket +1F681..1F682 ; Emoji # E1.0 [2] (🚁..🚂) helicopter..locomotive +1F683..1F685 ; Emoji # E0.6 [3] (🚃..🚅) railway car..bullet train +1F686 ; Emoji # E1.0 [1] (🚆) train +1F687 ; Emoji # E0.6 [1] (🚇) metro +1F688 ; Emoji # E1.0 [1] (🚈) light rail +1F689 ; Emoji # E0.6 [1] (🚉) station +1F68A..1F68B ; Emoji # E1.0 [2] (🚊..🚋) tram..tram car +1F68C ; Emoji # E0.6 [1] (🚌) bus +1F68D ; Emoji # E0.7 [1] (🚍) oncoming bus +1F68E ; Emoji # E1.0 [1] (🚎) trolleybus +1F68F ; Emoji # E0.6 [1] (🚏) bus stop +1F690 ; Emoji # E1.0 [1] (🚐) minibus +1F691..1F693 ; Emoji # E0.6 [3] (🚑..🚓) ambulance..police car +1F694 ; Emoji # E0.7 [1] (🚔) oncoming police car +1F695 ; Emoji # E0.6 [1] (🚕) taxi +1F696 ; Emoji # E1.0 [1] (🚖) oncoming taxi +1F697 ; Emoji # E0.6 [1] (🚗) automobile +1F698 ; Emoji # E0.7 [1] (🚘) oncoming automobile +1F699..1F69A ; Emoji # E0.6 [2] (🚙..🚚) sport utility vehicle..delivery truck +1F69B..1F6A1 ; Emoji # E1.0 [7] (🚛..🚡) articulated lorry..aerial tramway +1F6A2 ; Emoji # E0.6 [1] (🚢) ship +1F6A3 ; Emoji # E1.0 [1] (🚣) person rowing boat +1F6A4..1F6A5 ; Emoji # E0.6 [2] (🚤..🚥) speedboat..horizontal traffic light +1F6A6 ; Emoji # E1.0 [1] (🚦) vertical traffic light +1F6A7..1F6AD ; Emoji # E0.6 [7] (🚧..🚭) construction..no smoking +1F6AE..1F6B1 ; Emoji # E1.0 [4] (🚮..🚱) litter in bin sign..non-potable water +1F6B2 ; Emoji # E0.6 [1] (🚲) bicycle +1F6B3..1F6B5 ; Emoji # E1.0 [3] (🚳..🚵) no bicycles..person mountain biking +1F6B6 ; Emoji # E0.6 [1] (🚶) person walking +1F6B7..1F6B8 ; Emoji # E1.0 [2] (🚷..🚸) no pedestrians..children crossing +1F6B9..1F6BE ; Emoji # E0.6 [6] (🚹..🚾) men’s room..water closet +1F6BF ; Emoji # E1.0 [1] (🚿) shower +1F6C0 ; Emoji # E0.6 [1] (🛀) person taking bath +1F6C1..1F6C5 ; Emoji # E1.0 [5] (🛁..🛅) bathtub..left luggage +1F6CB ; Emoji # E0.7 [1] (🛋️) couch and lamp +1F6CC ; Emoji # E1.0 [1] (🛌) person in bed +1F6CD..1F6CF ; Emoji # E0.7 [3] (🛍️..🛏️) shopping bags..bed +1F6D0 ; Emoji # E1.0 [1] (🛐) place of worship +1F6D1..1F6D2 ; Emoji # E3.0 [2] (🛑..🛒) stop sign..shopping cart +1F6D5 ; Emoji # E12.0 [1] (🛕) hindu temple +1F6D6..1F6D7 ; Emoji # E13.0 [2] (🛖..🛗) hut..elevator +1F6DC ; Emoji # E15.0 [1] (🛜) wireless +1F6DD..1F6DF ; Emoji # E14.0 [3] (🛝..🛟) playground slide..ring buoy +1F6E0..1F6E5 ; Emoji # E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat +1F6E9 ; Emoji # E0.7 [1] (🛩️) small airplane +1F6EB..1F6EC ; Emoji # E1.0 [2] (🛫..🛬) airplane departure..airplane arrival +1F6F0 ; Emoji # E0.7 [1] (🛰️) satellite +1F6F3 ; Emoji # E0.7 [1] (🛳️) passenger ship +1F6F4..1F6F6 ; Emoji # E3.0 [3] (🛴..🛶) kick scooter..canoe +1F6F7..1F6F8 ; Emoji # E5.0 [2] (🛷..🛸) sled..flying saucer +1F6F9 ; Emoji # E11.0 [1] (🛹) skateboard +1F6FA ; Emoji # E12.0 [1] (🛺) auto rickshaw +1F6FB..1F6FC ; Emoji # E13.0 [2] (🛻..🛼) pickup truck..roller skate +1F7E0..1F7EB ; Emoji # E12.0 [12] (🟠..🟫) orange circle..brown square +1F7F0 ; Emoji # E14.0 [1] (🟰) heavy equals sign +1F90C ; Emoji # E13.0 [1] (🤌) pinched fingers +1F90D..1F90F ; Emoji # E12.0 [3] (🤍..🤏) white heart..pinching hand +1F910..1F918 ; Emoji # E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns +1F919..1F91E ; Emoji # E3.0 [6] (🤙..🤞) call me hand..crossed fingers +1F91F ; Emoji # E5.0 [1] (🤟) love-you gesture +1F920..1F927 ; Emoji # E3.0 [8] (🤠..🤧) cowboy hat face..sneezing face +1F928..1F92F ; Emoji # E5.0 [8] (🤨..🤯) face with raised eyebrow..exploding head +1F930 ; Emoji # E3.0 [1] (🤰) pregnant woman +1F931..1F932 ; Emoji # E5.0 [2] (🤱..🤲) breast-feeding..palms up together +1F933..1F93A ; Emoji # E3.0 [8] (🤳..🤺) selfie..person fencing +1F93C..1F93E ; Emoji # E3.0 [3] (🤼..🤾) people wrestling..person playing handball +1F93F ; Emoji # E12.0 [1] (🤿) diving mask +1F940..1F945 ; Emoji # E3.0 [6] (🥀..🥅) wilted flower..goal net +1F947..1F94B ; Emoji # E3.0 [5] (🥇..🥋) 1st place medal..martial arts uniform +1F94C ; Emoji # E5.0 [1] (🥌) curling stone +1F94D..1F94F ; Emoji # E11.0 [3] (🥍..🥏) lacrosse..flying disc +1F950..1F95E ; Emoji # E3.0 [15] (🥐..🥞) croissant..pancakes +1F95F..1F96B ; Emoji # E5.0 [13] (🥟..🥫) dumpling..canned food +1F96C..1F970 ; Emoji # E11.0 [5] (🥬..🥰) leafy green..smiling face with hearts +1F971 ; Emoji # E12.0 [1] (🥱) yawning face +1F972 ; Emoji # E13.0 [1] (🥲) smiling face with tear +1F973..1F976 ; Emoji # E11.0 [4] (🥳..🥶) partying face..cold face +1F977..1F978 ; Emoji # E13.0 [2] (🥷..🥸) ninja..disguised face +1F979 ; Emoji # E14.0 [1] (🥹) face holding back tears +1F97A ; Emoji # E11.0 [1] (🥺) pleading face +1F97B ; Emoji # E12.0 [1] (🥻) sari +1F97C..1F97F ; Emoji # E11.0 [4] (🥼..🥿) lab coat..flat shoe +1F980..1F984 ; Emoji # E1.0 [5] (🦀..🦄) crab..unicorn +1F985..1F991 ; Emoji # E3.0 [13] (🦅..🦑) eagle..squid +1F992..1F997 ; Emoji # E5.0 [6] (🦒..🦗) giraffe..cricket +1F998..1F9A2 ; Emoji # E11.0 [11] (🦘..🦢) kangaroo..swan +1F9A3..1F9A4 ; Emoji # E13.0 [2] (🦣..🦤) mammoth..dodo +1F9A5..1F9AA ; Emoji # E12.0 [6] (🦥..🦪) sloth..oyster +1F9AB..1F9AD ; Emoji # E13.0 [3] (🦫..🦭) beaver..seal +1F9AE..1F9AF ; Emoji # E12.0 [2] (🦮..🦯) guide dog..white cane +1F9B0..1F9B9 ; Emoji # E11.0 [10] (🦰..🦹) red hair..supervillain +1F9BA..1F9BF ; Emoji # E12.0 [6] (🦺..🦿) safety vest..mechanical leg +1F9C0 ; Emoji # E1.0 [1] (🧀) cheese wedge +1F9C1..1F9C2 ; Emoji # E11.0 [2] (🧁..🧂) cupcake..salt +1F9C3..1F9CA ; Emoji # E12.0 [8] (🧃..🧊) beverage box..ice +1F9CB ; Emoji # E13.0 [1] (🧋) bubble tea +1F9CC ; Emoji # E14.0 [1] (🧌) troll +1F9CD..1F9CF ; Emoji # E12.0 [3] (🧍..🧏) person standing..deaf person +1F9D0..1F9E6 ; Emoji # E5.0 [23] (🧐..🧦) face with monocle..socks +1F9E7..1F9FF ; Emoji # E11.0 [25] (🧧..🧿) red envelope..nazar amulet +1FA70..1FA73 ; Emoji # E12.0 [4] (🩰..🩳) ballet shoes..shorts +1FA74 ; Emoji # E13.0 [1] (🩴) thong sandal +1FA75..1FA77 ; Emoji # E15.0 [3] (🩵..🩷) light blue heart..pink heart +1FA78..1FA7A ; Emoji # E12.0 [3] (🩸..🩺) drop of blood..stethoscope +1FA7B..1FA7C ; Emoji # E14.0 [2] (🩻..🩼) x-ray..crutch +1FA80..1FA82 ; Emoji # E12.0 [3] (🪀..🪂) yo-yo..parachute +1FA83..1FA86 ; Emoji # E13.0 [4] (🪃..🪆) boomerang..nesting dolls +1FA87..1FA88 ; Emoji # E15.0 [2] (🪇..🪈) maracas..flute +1FA90..1FA95 ; Emoji # E12.0 [6] (🪐..🪕) ringed planet..banjo +1FA96..1FAA8 ; Emoji # E13.0 [19] (🪖..🪨) military helmet..rock +1FAA9..1FAAC ; Emoji # E14.0 [4] (🪩..🪬) mirror ball..hamsa +1FAAD..1FAAF ; Emoji # E15.0 [3] (🪭..🪯) folding hand fan..khanda +1FAB0..1FAB6 ; Emoji # E13.0 [7] (🪰..🪶) fly..feather +1FAB7..1FABA ; Emoji # E14.0 [4] (🪷..🪺) lotus..nest with eggs +1FABB..1FABD ; Emoji # E15.0 [3] (🪻..🪽) hyacinth..wing +1FABF ; Emoji # E15.0 [1] (🪿) goose +1FAC0..1FAC2 ; Emoji # E13.0 [3] (🫀..🫂) anatomical heart..people hugging +1FAC3..1FAC5 ; Emoji # E14.0 [3] (🫃..🫅) pregnant man..person with crown +1FACE..1FACF ; Emoji # E15.0 [2] (🫎..🫏) moose..donkey +1FAD0..1FAD6 ; Emoji # E13.0 [7] (🫐..🫖) blueberries..teapot +1FAD7..1FAD9 ; Emoji # E14.0 [3] (🫗..🫙) pouring liquid..jar +1FADA..1FADB ; Emoji # E15.0 [2] (🫚..🫛) ginger root..pea pod +1FAE0..1FAE7 ; Emoji # E14.0 [8] (🫠..🫧) melting face..bubbles +1FAE8 ; Emoji # E15.0 [1] (🫨) shaking face +1FAF0..1FAF6 ; Emoji # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands +1FAF7..1FAF8 ; Emoji # E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand + +# Total elements: 1424 + +# ================================================ + +# All omitted code points have Emoji_Presentation=No + +231A..231B ; Emoji_Presentation # E0.6 [2] (⌚..⌛) watch..hourglass done +23E9..23EC ; Emoji_Presentation # E0.6 [4] (⏩..⏬) fast-forward button..fast down button +23F0 ; Emoji_Presentation # E0.6 [1] (⏰) alarm clock +23F3 ; Emoji_Presentation # E0.6 [1] (⏳) hourglass not done +25FD..25FE ; Emoji_Presentation # E0.6 [2] (◽..◾) white medium-small square..black medium-small square +2614..2615 ; Emoji_Presentation # E0.6 [2] (☔..☕) umbrella with rain drops..hot beverage +2648..2653 ; Emoji_Presentation # E0.6 [12] (♈..♓) Aries..Pisces +267F ; Emoji_Presentation # E0.6 [1] (♿) wheelchair symbol +2693 ; Emoji_Presentation # E0.6 [1] (⚓) anchor +26A1 ; Emoji_Presentation # E0.6 [1] (⚡) high voltage +26AA..26AB ; Emoji_Presentation # E0.6 [2] (⚪..⚫) white circle..black circle +26BD..26BE ; Emoji_Presentation # E0.6 [2] (⚽..⚾) soccer ball..baseball +26C4..26C5 ; Emoji_Presentation # E0.6 [2] (⛄..⛅) snowman without snow..sun behind cloud +26CE ; Emoji_Presentation # E0.6 [1] (⛎) Ophiuchus +26D4 ; Emoji_Presentation # E0.6 [1] (⛔) no entry +26EA ; Emoji_Presentation # E0.6 [1] (⛪) church +26F2..26F3 ; Emoji_Presentation # E0.6 [2] (⛲..⛳) fountain..flag in hole +26F5 ; Emoji_Presentation # E0.6 [1] (⛵) sailboat +26FA ; Emoji_Presentation # E0.6 [1] (⛺) tent +26FD ; Emoji_Presentation # E0.6 [1] (⛽) fuel pump +2705 ; Emoji_Presentation # E0.6 [1] (✅) check mark button +270A..270B ; Emoji_Presentation # E0.6 [2] (✊..✋) raised fist..raised hand +2728 ; Emoji_Presentation # E0.6 [1] (✨) sparkles +274C ; Emoji_Presentation # E0.6 [1] (❌) cross mark +274E ; Emoji_Presentation # E0.6 [1] (❎) cross mark button +2753..2755 ; Emoji_Presentation # E0.6 [3] (❓..❕) red question mark..white exclamation mark +2757 ; Emoji_Presentation # E0.6 [1] (❗) red exclamation mark +2795..2797 ; Emoji_Presentation # E0.6 [3] (➕..➗) plus..divide +27B0 ; Emoji_Presentation # E0.6 [1] (➰) curly loop +27BF ; Emoji_Presentation # E1.0 [1] (➿) double curly loop +2B1B..2B1C ; Emoji_Presentation # E0.6 [2] (⬛..⬜) black large square..white large square +2B50 ; Emoji_Presentation # E0.6 [1] (⭐) star +2B55 ; Emoji_Presentation # E0.6 [1] (⭕) hollow red circle +1F004 ; Emoji_Presentation # E0.6 [1] (🀄) mahjong red dragon +1F0CF ; Emoji_Presentation # E0.6 [1] (🃏) joker +1F18E ; Emoji_Presentation # E0.6 [1] (🆎) AB button (blood type) +1F191..1F19A ; Emoji_Presentation # E0.6 [10] (🆑..🆚) CL button..VS button +1F1E6..1F1FF ; Emoji_Presentation # E0.0 [26] (🇦..🇿) regional indicator symbol letter a..regional indicator symbol letter z +1F201 ; Emoji_Presentation # E0.6 [1] (🈁) Japanese “here” button +1F21A ; Emoji_Presentation # E0.6 [1] (🈚) Japanese “free of charge” button +1F22F ; Emoji_Presentation # E0.6 [1] (🈯) Japanese “reserved” button +1F232..1F236 ; Emoji_Presentation # E0.6 [5] (🈲..🈶) Japanese “prohibited” button..Japanese “not free of charge” button +1F238..1F23A ; Emoji_Presentation # E0.6 [3] (🈸..🈺) Japanese “application” button..Japanese “open for business” button +1F250..1F251 ; Emoji_Presentation # E0.6 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button +1F300..1F30C ; Emoji_Presentation # E0.6 [13] (🌀..🌌) cyclone..milky way +1F30D..1F30E ; Emoji_Presentation # E0.7 [2] (🌍..🌎) globe showing Europe-Africa..globe showing Americas +1F30F ; Emoji_Presentation # E0.6 [1] (🌏) globe showing Asia-Australia +1F310 ; Emoji_Presentation # E1.0 [1] (🌐) globe with meridians +1F311 ; Emoji_Presentation # E0.6 [1] (🌑) new moon +1F312 ; Emoji_Presentation # E1.0 [1] (🌒) waxing crescent moon +1F313..1F315 ; Emoji_Presentation # E0.6 [3] (🌓..🌕) first quarter moon..full moon +1F316..1F318 ; Emoji_Presentation # E1.0 [3] (🌖..🌘) waning gibbous moon..waning crescent moon +1F319 ; Emoji_Presentation # E0.6 [1] (🌙) crescent moon +1F31A ; Emoji_Presentation # E1.0 [1] (🌚) new moon face +1F31B ; Emoji_Presentation # E0.6 [1] (🌛) first quarter moon face +1F31C ; Emoji_Presentation # E0.7 [1] (🌜) last quarter moon face +1F31D..1F31E ; Emoji_Presentation # E1.0 [2] (🌝..🌞) full moon face..sun with face +1F31F..1F320 ; Emoji_Presentation # E0.6 [2] (🌟..🌠) glowing star..shooting star +1F32D..1F32F ; Emoji_Presentation # E1.0 [3] (🌭..🌯) hot dog..burrito +1F330..1F331 ; Emoji_Presentation # E0.6 [2] (🌰..🌱) chestnut..seedling +1F332..1F333 ; Emoji_Presentation # E1.0 [2] (🌲..🌳) evergreen tree..deciduous tree +1F334..1F335 ; Emoji_Presentation # E0.6 [2] (🌴..🌵) palm tree..cactus +1F337..1F34A ; Emoji_Presentation # E0.6 [20] (🌷..🍊) tulip..tangerine +1F34B ; Emoji_Presentation # E1.0 [1] (🍋) lemon +1F34C..1F34F ; Emoji_Presentation # E0.6 [4] (🍌..🍏) banana..green apple +1F350 ; Emoji_Presentation # E1.0 [1] (🍐) pear +1F351..1F37B ; Emoji_Presentation # E0.6 [43] (🍑..🍻) peach..clinking beer mugs +1F37C ; Emoji_Presentation # E1.0 [1] (🍼) baby bottle +1F37E..1F37F ; Emoji_Presentation # E1.0 [2] (🍾..🍿) bottle with popping cork..popcorn +1F380..1F393 ; Emoji_Presentation # E0.6 [20] (🎀..🎓) ribbon..graduation cap +1F3A0..1F3C4 ; Emoji_Presentation # E0.6 [37] (🎠..🏄) carousel horse..person surfing +1F3C5 ; Emoji_Presentation # E1.0 [1] (🏅) sports medal +1F3C6 ; Emoji_Presentation # E0.6 [1] (🏆) trophy +1F3C7 ; Emoji_Presentation # E1.0 [1] (🏇) horse racing +1F3C8 ; Emoji_Presentation # E0.6 [1] (🏈) american football +1F3C9 ; Emoji_Presentation # E1.0 [1] (🏉) rugby football +1F3CA ; Emoji_Presentation # E0.6 [1] (🏊) person swimming +1F3CF..1F3D3 ; Emoji_Presentation # E1.0 [5] (🏏..🏓) cricket game..ping pong +1F3E0..1F3E3 ; Emoji_Presentation # E0.6 [4] (🏠..🏣) house..Japanese post office +1F3E4 ; Emoji_Presentation # E1.0 [1] (🏤) post office +1F3E5..1F3F0 ; Emoji_Presentation # E0.6 [12] (🏥..🏰) hospital..castle +1F3F4 ; Emoji_Presentation # E1.0 [1] (🏴) black flag +1F3F8..1F407 ; Emoji_Presentation # E1.0 [16] (🏸..🐇) badminton..rabbit +1F408 ; Emoji_Presentation # E0.7 [1] (🐈) cat +1F409..1F40B ; Emoji_Presentation # E1.0 [3] (🐉..🐋) dragon..whale +1F40C..1F40E ; Emoji_Presentation # E0.6 [3] (🐌..🐎) snail..horse +1F40F..1F410 ; Emoji_Presentation # E1.0 [2] (🐏..🐐) ram..goat +1F411..1F412 ; Emoji_Presentation # E0.6 [2] (🐑..🐒) ewe..monkey +1F413 ; Emoji_Presentation # E1.0 [1] (🐓) rooster +1F414 ; Emoji_Presentation # E0.6 [1] (🐔) chicken +1F415 ; Emoji_Presentation # E0.7 [1] (🐕) dog +1F416 ; Emoji_Presentation # E1.0 [1] (🐖) pig +1F417..1F429 ; Emoji_Presentation # E0.6 [19] (🐗..🐩) boar..poodle +1F42A ; Emoji_Presentation # E1.0 [1] (🐪) camel +1F42B..1F43E ; Emoji_Presentation # E0.6 [20] (🐫..🐾) two-hump camel..paw prints +1F440 ; Emoji_Presentation # E0.6 [1] (👀) eyes +1F442..1F464 ; Emoji_Presentation # E0.6 [35] (👂..👤) ear..bust in silhouette +1F465 ; Emoji_Presentation # E1.0 [1] (👥) busts in silhouette +1F466..1F46B ; Emoji_Presentation # E0.6 [6] (👦..👫) boy..woman and man holding hands +1F46C..1F46D ; Emoji_Presentation # E1.0 [2] (👬..👭) men holding hands..women holding hands +1F46E..1F4AC ; Emoji_Presentation # E0.6 [63] (👮..💬) police officer..speech balloon +1F4AD ; Emoji_Presentation # E1.0 [1] (💭) thought balloon +1F4AE..1F4B5 ; Emoji_Presentation # E0.6 [8] (💮..💵) white flower..dollar banknote +1F4B6..1F4B7 ; Emoji_Presentation # E1.0 [2] (💶..💷) euro banknote..pound banknote +1F4B8..1F4EB ; Emoji_Presentation # E0.6 [52] (💸..📫) money with wings..closed mailbox with raised flag +1F4EC..1F4ED ; Emoji_Presentation # E0.7 [2] (📬..📭) open mailbox with raised flag..open mailbox with lowered flag +1F4EE ; Emoji_Presentation # E0.6 [1] (📮) postbox +1F4EF ; Emoji_Presentation # E1.0 [1] (📯) postal horn +1F4F0..1F4F4 ; Emoji_Presentation # E0.6 [5] (📰..📴) newspaper..mobile phone off +1F4F5 ; Emoji_Presentation # E1.0 [1] (📵) no mobile phones +1F4F6..1F4F7 ; Emoji_Presentation # E0.6 [2] (📶..📷) antenna bars..camera +1F4F8 ; Emoji_Presentation # E1.0 [1] (📸) camera with flash +1F4F9..1F4FC ; Emoji_Presentation # E0.6 [4] (📹..📼) video camera..videocassette +1F4FF..1F502 ; Emoji_Presentation # E1.0 [4] (📿..🔂) prayer beads..repeat single button +1F503 ; Emoji_Presentation # E0.6 [1] (🔃) clockwise vertical arrows +1F504..1F507 ; Emoji_Presentation # E1.0 [4] (🔄..🔇) counterclockwise arrows button..muted speaker +1F508 ; Emoji_Presentation # E0.7 [1] (🔈) speaker low volume +1F509 ; Emoji_Presentation # E1.0 [1] (🔉) speaker medium volume +1F50A..1F514 ; Emoji_Presentation # E0.6 [11] (🔊..🔔) speaker high volume..bell +1F515 ; Emoji_Presentation # E1.0 [1] (🔕) bell with slash +1F516..1F52B ; Emoji_Presentation # E0.6 [22] (🔖..🔫) bookmark..water pistol +1F52C..1F52D ; Emoji_Presentation # E1.0 [2] (🔬..🔭) microscope..telescope +1F52E..1F53D ; Emoji_Presentation # E0.6 [16] (🔮..🔽) crystal ball..downwards button +1F54B..1F54E ; Emoji_Presentation # E1.0 [4] (🕋..🕎) kaaba..menorah +1F550..1F55B ; Emoji_Presentation # E0.6 [12] (🕐..🕛) one o’clock..twelve o’clock +1F55C..1F567 ; Emoji_Presentation # E0.7 [12] (🕜..🕧) one-thirty..twelve-thirty +1F57A ; Emoji_Presentation # E3.0 [1] (🕺) man dancing +1F595..1F596 ; Emoji_Presentation # E1.0 [2] (🖕..🖖) middle finger..vulcan salute +1F5A4 ; Emoji_Presentation # E3.0 [1] (🖤) black heart +1F5FB..1F5FF ; Emoji_Presentation # E0.6 [5] (🗻..🗿) mount fuji..moai +1F600 ; Emoji_Presentation # E1.0 [1] (😀) grinning face +1F601..1F606 ; Emoji_Presentation # E0.6 [6] (😁..😆) beaming face with smiling eyes..grinning squinting face +1F607..1F608 ; Emoji_Presentation # E1.0 [2] (😇..😈) smiling face with halo..smiling face with horns +1F609..1F60D ; Emoji_Presentation # E0.6 [5] (😉..😍) winking face..smiling face with heart-eyes +1F60E ; Emoji_Presentation # E1.0 [1] (😎) smiling face with sunglasses +1F60F ; Emoji_Presentation # E0.6 [1] (😏) smirking face +1F610 ; Emoji_Presentation # E0.7 [1] (😐) neutral face +1F611 ; Emoji_Presentation # E1.0 [1] (😑) expressionless face +1F612..1F614 ; Emoji_Presentation # E0.6 [3] (😒..😔) unamused face..pensive face +1F615 ; Emoji_Presentation # E1.0 [1] (😕) confused face +1F616 ; Emoji_Presentation # E0.6 [1] (😖) confounded face +1F617 ; Emoji_Presentation # E1.0 [1] (😗) kissing face +1F618 ; Emoji_Presentation # E0.6 [1] (😘) face blowing a kiss +1F619 ; Emoji_Presentation # E1.0 [1] (😙) kissing face with smiling eyes +1F61A ; Emoji_Presentation # E0.6 [1] (😚) kissing face with closed eyes +1F61B ; Emoji_Presentation # E1.0 [1] (😛) face with tongue +1F61C..1F61E ; Emoji_Presentation # E0.6 [3] (😜..😞) winking face with tongue..disappointed face +1F61F ; Emoji_Presentation # E1.0 [1] (😟) worried face +1F620..1F625 ; Emoji_Presentation # E0.6 [6] (😠..😥) angry face..sad but relieved face +1F626..1F627 ; Emoji_Presentation # E1.0 [2] (😦..😧) frowning face with open mouth..anguished face +1F628..1F62B ; Emoji_Presentation # E0.6 [4] (😨..😫) fearful face..tired face +1F62C ; Emoji_Presentation # E1.0 [1] (😬) grimacing face +1F62D ; Emoji_Presentation # E0.6 [1] (😭) loudly crying face +1F62E..1F62F ; Emoji_Presentation # E1.0 [2] (😮..😯) face with open mouth..hushed face +1F630..1F633 ; Emoji_Presentation # E0.6 [4] (😰..😳) anxious face with sweat..flushed face +1F634 ; Emoji_Presentation # E1.0 [1] (😴) sleeping face +1F635 ; Emoji_Presentation # E0.6 [1] (😵) face with crossed-out eyes +1F636 ; Emoji_Presentation # E1.0 [1] (😶) face without mouth +1F637..1F640 ; Emoji_Presentation # E0.6 [10] (😷..🙀) face with medical mask..weary cat +1F641..1F644 ; Emoji_Presentation # E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes +1F645..1F64F ; Emoji_Presentation # E0.6 [11] (🙅..🙏) person gesturing NO..folded hands +1F680 ; Emoji_Presentation # E0.6 [1] (🚀) rocket +1F681..1F682 ; Emoji_Presentation # E1.0 [2] (🚁..🚂) helicopter..locomotive +1F683..1F685 ; Emoji_Presentation # E0.6 [3] (🚃..🚅) railway car..bullet train +1F686 ; Emoji_Presentation # E1.0 [1] (🚆) train +1F687 ; Emoji_Presentation # E0.6 [1] (🚇) metro +1F688 ; Emoji_Presentation # E1.0 [1] (🚈) light rail +1F689 ; Emoji_Presentation # E0.6 [1] (🚉) station +1F68A..1F68B ; Emoji_Presentation # E1.0 [2] (🚊..🚋) tram..tram car +1F68C ; Emoji_Presentation # E0.6 [1] (🚌) bus +1F68D ; Emoji_Presentation # E0.7 [1] (🚍) oncoming bus +1F68E ; Emoji_Presentation # E1.0 [1] (🚎) trolleybus +1F68F ; Emoji_Presentation # E0.6 [1] (🚏) bus stop +1F690 ; Emoji_Presentation # E1.0 [1] (🚐) minibus +1F691..1F693 ; Emoji_Presentation # E0.6 [3] (🚑..🚓) ambulance..police car +1F694 ; Emoji_Presentation # E0.7 [1] (🚔) oncoming police car +1F695 ; Emoji_Presentation # E0.6 [1] (🚕) taxi +1F696 ; Emoji_Presentation # E1.0 [1] (🚖) oncoming taxi +1F697 ; Emoji_Presentation # E0.6 [1] (🚗) automobile +1F698 ; Emoji_Presentation # E0.7 [1] (🚘) oncoming automobile +1F699..1F69A ; Emoji_Presentation # E0.6 [2] (🚙..🚚) sport utility vehicle..delivery truck +1F69B..1F6A1 ; Emoji_Presentation # E1.0 [7] (🚛..🚡) articulated lorry..aerial tramway +1F6A2 ; Emoji_Presentation # E0.6 [1] (🚢) ship +1F6A3 ; Emoji_Presentation # E1.0 [1] (🚣) person rowing boat +1F6A4..1F6A5 ; Emoji_Presentation # E0.6 [2] (🚤..🚥) speedboat..horizontal traffic light +1F6A6 ; Emoji_Presentation # E1.0 [1] (🚦) vertical traffic light +1F6A7..1F6AD ; Emoji_Presentation # E0.6 [7] (🚧..🚭) construction..no smoking +1F6AE..1F6B1 ; Emoji_Presentation # E1.0 [4] (🚮..🚱) litter in bin sign..non-potable water +1F6B2 ; Emoji_Presentation # E0.6 [1] (🚲) bicycle +1F6B3..1F6B5 ; Emoji_Presentation # E1.0 [3] (🚳..🚵) no bicycles..person mountain biking +1F6B6 ; Emoji_Presentation # E0.6 [1] (🚶) person walking +1F6B7..1F6B8 ; Emoji_Presentation # E1.0 [2] (🚷..🚸) no pedestrians..children crossing +1F6B9..1F6BE ; Emoji_Presentation # E0.6 [6] (🚹..🚾) men’s room..water closet +1F6BF ; Emoji_Presentation # E1.0 [1] (🚿) shower +1F6C0 ; Emoji_Presentation # E0.6 [1] (🛀) person taking bath +1F6C1..1F6C5 ; Emoji_Presentation # E1.0 [5] (🛁..🛅) bathtub..left luggage +1F6CC ; Emoji_Presentation # E1.0 [1] (🛌) person in bed +1F6D0 ; Emoji_Presentation # E1.0 [1] (🛐) place of worship +1F6D1..1F6D2 ; Emoji_Presentation # E3.0 [2] (🛑..🛒) stop sign..shopping cart +1F6D5 ; Emoji_Presentation # E12.0 [1] (🛕) hindu temple +1F6D6..1F6D7 ; Emoji_Presentation # E13.0 [2] (🛖..🛗) hut..elevator +1F6DC ; Emoji_Presentation # E15.0 [1] (🛜) wireless +1F6DD..1F6DF ; Emoji_Presentation # E14.0 [3] (🛝..🛟) playground slide..ring buoy +1F6EB..1F6EC ; Emoji_Presentation # E1.0 [2] (🛫..🛬) airplane departure..airplane arrival +1F6F4..1F6F6 ; Emoji_Presentation # E3.0 [3] (🛴..🛶) kick scooter..canoe +1F6F7..1F6F8 ; Emoji_Presentation # E5.0 [2] (🛷..🛸) sled..flying saucer +1F6F9 ; Emoji_Presentation # E11.0 [1] (🛹) skateboard +1F6FA ; Emoji_Presentation # E12.0 [1] (🛺) auto rickshaw +1F6FB..1F6FC ; Emoji_Presentation # E13.0 [2] (🛻..🛼) pickup truck..roller skate +1F7E0..1F7EB ; Emoji_Presentation # E12.0 [12] (🟠..🟫) orange circle..brown square +1F7F0 ; Emoji_Presentation # E14.0 [1] (🟰) heavy equals sign +1F90C ; Emoji_Presentation # E13.0 [1] (🤌) pinched fingers +1F90D..1F90F ; Emoji_Presentation # E12.0 [3] (🤍..🤏) white heart..pinching hand +1F910..1F918 ; Emoji_Presentation # E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns +1F919..1F91E ; Emoji_Presentation # E3.0 [6] (🤙..🤞) call me hand..crossed fingers +1F91F ; Emoji_Presentation # E5.0 [1] (🤟) love-you gesture +1F920..1F927 ; Emoji_Presentation # E3.0 [8] (🤠..🤧) cowboy hat face..sneezing face +1F928..1F92F ; Emoji_Presentation # E5.0 [8] (🤨..🤯) face with raised eyebrow..exploding head +1F930 ; Emoji_Presentation # E3.0 [1] (🤰) pregnant woman +1F931..1F932 ; Emoji_Presentation # E5.0 [2] (🤱..🤲) breast-feeding..palms up together +1F933..1F93A ; Emoji_Presentation # E3.0 [8] (🤳..🤺) selfie..person fencing +1F93C..1F93E ; Emoji_Presentation # E3.0 [3] (🤼..🤾) people wrestling..person playing handball +1F93F ; Emoji_Presentation # E12.0 [1] (🤿) diving mask +1F940..1F945 ; Emoji_Presentation # E3.0 [6] (🥀..🥅) wilted flower..goal net +1F947..1F94B ; Emoji_Presentation # E3.0 [5] (🥇..🥋) 1st place medal..martial arts uniform +1F94C ; Emoji_Presentation # E5.0 [1] (🥌) curling stone +1F94D..1F94F ; Emoji_Presentation # E11.0 [3] (🥍..🥏) lacrosse..flying disc +1F950..1F95E ; Emoji_Presentation # E3.0 [15] (🥐..🥞) croissant..pancakes +1F95F..1F96B ; Emoji_Presentation # E5.0 [13] (🥟..🥫) dumpling..canned food +1F96C..1F970 ; Emoji_Presentation # E11.0 [5] (🥬..🥰) leafy green..smiling face with hearts +1F971 ; Emoji_Presentation # E12.0 [1] (🥱) yawning face +1F972 ; Emoji_Presentation # E13.0 [1] (🥲) smiling face with tear +1F973..1F976 ; Emoji_Presentation # E11.0 [4] (🥳..🥶) partying face..cold face +1F977..1F978 ; Emoji_Presentation # E13.0 [2] (🥷..🥸) ninja..disguised face +1F979 ; Emoji_Presentation # E14.0 [1] (🥹) face holding back tears +1F97A ; Emoji_Presentation # E11.0 [1] (🥺) pleading face +1F97B ; Emoji_Presentation # E12.0 [1] (🥻) sari +1F97C..1F97F ; Emoji_Presentation # E11.0 [4] (🥼..🥿) lab coat..flat shoe +1F980..1F984 ; Emoji_Presentation # E1.0 [5] (🦀..🦄) crab..unicorn +1F985..1F991 ; Emoji_Presentation # E3.0 [13] (🦅..🦑) eagle..squid +1F992..1F997 ; Emoji_Presentation # E5.0 [6] (🦒..🦗) giraffe..cricket +1F998..1F9A2 ; Emoji_Presentation # E11.0 [11] (🦘..🦢) kangaroo..swan +1F9A3..1F9A4 ; Emoji_Presentation # E13.0 [2] (🦣..🦤) mammoth..dodo +1F9A5..1F9AA ; Emoji_Presentation # E12.0 [6] (🦥..🦪) sloth..oyster +1F9AB..1F9AD ; Emoji_Presentation # E13.0 [3] (🦫..🦭) beaver..seal +1F9AE..1F9AF ; Emoji_Presentation # E12.0 [2] (🦮..🦯) guide dog..white cane +1F9B0..1F9B9 ; Emoji_Presentation # E11.0 [10] (🦰..🦹) red hair..supervillain +1F9BA..1F9BF ; Emoji_Presentation # E12.0 [6] (🦺..🦿) safety vest..mechanical leg +1F9C0 ; Emoji_Presentation # E1.0 [1] (🧀) cheese wedge +1F9C1..1F9C2 ; Emoji_Presentation # E11.0 [2] (🧁..🧂) cupcake..salt +1F9C3..1F9CA ; Emoji_Presentation # E12.0 [8] (🧃..🧊) beverage box..ice +1F9CB ; Emoji_Presentation # E13.0 [1] (🧋) bubble tea +1F9CC ; Emoji_Presentation # E14.0 [1] (🧌) troll +1F9CD..1F9CF ; Emoji_Presentation # E12.0 [3] (🧍..🧏) person standing..deaf person +1F9D0..1F9E6 ; Emoji_Presentation # E5.0 [23] (🧐..🧦) face with monocle..socks +1F9E7..1F9FF ; Emoji_Presentation # E11.0 [25] (🧧..🧿) red envelope..nazar amulet +1FA70..1FA73 ; Emoji_Presentation # E12.0 [4] (🩰..🩳) ballet shoes..shorts +1FA74 ; Emoji_Presentation # E13.0 [1] (🩴) thong sandal +1FA75..1FA77 ; Emoji_Presentation # E15.0 [3] (🩵..🩷) light blue heart..pink heart +1FA78..1FA7A ; Emoji_Presentation # E12.0 [3] (🩸..🩺) drop of blood..stethoscope +1FA7B..1FA7C ; Emoji_Presentation # E14.0 [2] (🩻..🩼) x-ray..crutch +1FA80..1FA82 ; Emoji_Presentation # E12.0 [3] (🪀..🪂) yo-yo..parachute +1FA83..1FA86 ; Emoji_Presentation # E13.0 [4] (🪃..🪆) boomerang..nesting dolls +1FA87..1FA88 ; Emoji_Presentation # E15.0 [2] (🪇..🪈) maracas..flute +1FA90..1FA95 ; Emoji_Presentation # E12.0 [6] (🪐..🪕) ringed planet..banjo +1FA96..1FAA8 ; Emoji_Presentation # E13.0 [19] (🪖..🪨) military helmet..rock +1FAA9..1FAAC ; Emoji_Presentation # E14.0 [4] (🪩..🪬) mirror ball..hamsa +1FAAD..1FAAF ; Emoji_Presentation # E15.0 [3] (🪭..🪯) folding hand fan..khanda +1FAB0..1FAB6 ; Emoji_Presentation # E13.0 [7] (🪰..🪶) fly..feather +1FAB7..1FABA ; Emoji_Presentation # E14.0 [4] (🪷..🪺) lotus..nest with eggs +1FABB..1FABD ; Emoji_Presentation # E15.0 [3] (🪻..🪽) hyacinth..wing +1FABF ; Emoji_Presentation # E15.0 [1] (🪿) goose +1FAC0..1FAC2 ; Emoji_Presentation # E13.0 [3] (🫀..🫂) anatomical heart..people hugging +1FAC3..1FAC5 ; Emoji_Presentation # E14.0 [3] (🫃..🫅) pregnant man..person with crown +1FACE..1FACF ; Emoji_Presentation # E15.0 [2] (🫎..🫏) moose..donkey +1FAD0..1FAD6 ; Emoji_Presentation # E13.0 [7] (🫐..🫖) blueberries..teapot +1FAD7..1FAD9 ; Emoji_Presentation # E14.0 [3] (🫗..🫙) pouring liquid..jar +1FADA..1FADB ; Emoji_Presentation # E15.0 [2] (🫚..🫛) ginger root..pea pod +1FAE0..1FAE7 ; Emoji_Presentation # E14.0 [8] (🫠..🫧) melting face..bubbles +1FAE8 ; Emoji_Presentation # E15.0 [1] (🫨) shaking face +1FAF0..1FAF6 ; Emoji_Presentation # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands +1FAF7..1FAF8 ; Emoji_Presentation # E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand + +# Total elements: 1205 + +# ================================================ + +# All omitted code points have Emoji_Modifier=No + +1F3FB..1F3FF ; Emoji_Modifier # E1.0 [5] (🏻..🏿) light skin tone..dark skin tone + +# Total elements: 5 + +# ================================================ + +# All omitted code points have Emoji_Modifier_Base=No + +261D ; Emoji_Modifier_Base # E0.6 [1] (☝️) index pointing up +26F9 ; Emoji_Modifier_Base # E0.7 [1] (⛹️) person bouncing ball +270A..270C ; Emoji_Modifier_Base # E0.6 [3] (✊..✌️) raised fist..victory hand +270D ; Emoji_Modifier_Base # E0.7 [1] (✍️) writing hand +1F385 ; Emoji_Modifier_Base # E0.6 [1] (🎅) Santa Claus +1F3C2..1F3C4 ; Emoji_Modifier_Base # E0.6 [3] (🏂..🏄) snowboarder..person surfing +1F3C7 ; Emoji_Modifier_Base # E1.0 [1] (🏇) horse racing +1F3CA ; Emoji_Modifier_Base # E0.6 [1] (🏊) person swimming +1F3CB..1F3CC ; Emoji_Modifier_Base # E0.7 [2] (🏋️..🏌️) person lifting weights..person golfing +1F442..1F443 ; Emoji_Modifier_Base # E0.6 [2] (👂..👃) ear..nose +1F446..1F450 ; Emoji_Modifier_Base # E0.6 [11] (👆..👐) backhand index pointing up..open hands +1F466..1F46B ; Emoji_Modifier_Base # E0.6 [6] (👦..👫) boy..woman and man holding hands +1F46C..1F46D ; Emoji_Modifier_Base # E1.0 [2] (👬..👭) men holding hands..women holding hands +1F46E..1F478 ; Emoji_Modifier_Base # E0.6 [11] (👮..👸) police officer..princess +1F47C ; Emoji_Modifier_Base # E0.6 [1] (👼) baby angel +1F481..1F483 ; Emoji_Modifier_Base # E0.6 [3] (💁..💃) person tipping hand..woman dancing +1F485..1F487 ; Emoji_Modifier_Base # E0.6 [3] (💅..💇) nail polish..person getting haircut +1F48F ; Emoji_Modifier_Base # E0.6 [1] (💏) kiss +1F491 ; Emoji_Modifier_Base # E0.6 [1] (💑) couple with heart +1F4AA ; Emoji_Modifier_Base # E0.6 [1] (💪) flexed biceps +1F574..1F575 ; Emoji_Modifier_Base # E0.7 [2] (🕴️..🕵️) person in suit levitating..detective +1F57A ; Emoji_Modifier_Base # E3.0 [1] (🕺) man dancing +1F590 ; Emoji_Modifier_Base # E0.7 [1] (🖐️) hand with fingers splayed +1F595..1F596 ; Emoji_Modifier_Base # E1.0 [2] (🖕..🖖) middle finger..vulcan salute +1F645..1F647 ; Emoji_Modifier_Base # E0.6 [3] (🙅..🙇) person gesturing NO..person bowing +1F64B..1F64F ; Emoji_Modifier_Base # E0.6 [5] (🙋..🙏) person raising hand..folded hands +1F6A3 ; Emoji_Modifier_Base # E1.0 [1] (🚣) person rowing boat +1F6B4..1F6B5 ; Emoji_Modifier_Base # E1.0 [2] (🚴..🚵) person biking..person mountain biking +1F6B6 ; Emoji_Modifier_Base # E0.6 [1] (🚶) person walking +1F6C0 ; Emoji_Modifier_Base # E0.6 [1] (🛀) person taking bath +1F6CC ; Emoji_Modifier_Base # E1.0 [1] (🛌) person in bed +1F90C ; Emoji_Modifier_Base # E13.0 [1] (🤌) pinched fingers +1F90F ; Emoji_Modifier_Base # E12.0 [1] (🤏) pinching hand +1F918 ; Emoji_Modifier_Base # E1.0 [1] (🤘) sign of the horns +1F919..1F91E ; Emoji_Modifier_Base # E3.0 [6] (🤙..🤞) call me hand..crossed fingers +1F91F ; Emoji_Modifier_Base # E5.0 [1] (🤟) love-you gesture +1F926 ; Emoji_Modifier_Base # E3.0 [1] (🤦) person facepalming +1F930 ; Emoji_Modifier_Base # E3.0 [1] (🤰) pregnant woman +1F931..1F932 ; Emoji_Modifier_Base # E5.0 [2] (🤱..🤲) breast-feeding..palms up together +1F933..1F939 ; Emoji_Modifier_Base # E3.0 [7] (🤳..🤹) selfie..person juggling +1F93C..1F93E ; Emoji_Modifier_Base # E3.0 [3] (🤼..🤾) people wrestling..person playing handball +1F977 ; Emoji_Modifier_Base # E13.0 [1] (🥷) ninja +1F9B5..1F9B6 ; Emoji_Modifier_Base # E11.0 [2] (🦵..🦶) leg..foot +1F9B8..1F9B9 ; Emoji_Modifier_Base # E11.0 [2] (🦸..🦹) superhero..supervillain +1F9BB ; Emoji_Modifier_Base # E12.0 [1] (🦻) ear with hearing aid +1F9CD..1F9CF ; Emoji_Modifier_Base # E12.0 [3] (🧍..🧏) person standing..deaf person +1F9D1..1F9DD ; Emoji_Modifier_Base # E5.0 [13] (🧑..🧝) person..elf +1FAC3..1FAC5 ; Emoji_Modifier_Base # E14.0 [3] (🫃..🫅) pregnant man..person with crown +1FAF0..1FAF6 ; Emoji_Modifier_Base # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands +1FAF7..1FAF8 ; Emoji_Modifier_Base # E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand + +# Total elements: 134 + +# ================================================ + +# All omitted code points have Emoji_Component=No + +0023 ; Emoji_Component # E0.0 [1] (#️) hash sign +002A ; Emoji_Component # E0.0 [1] (*️) asterisk +0030..0039 ; Emoji_Component # E0.0 [10] (0️..9️) digit zero..digit nine +200D ; Emoji_Component # E0.0 [1] (‍) zero width joiner +20E3 ; Emoji_Component # E0.0 [1] (⃣) combining enclosing keycap +FE0F ; Emoji_Component # E0.0 [1] () VARIATION SELECTOR-16 +1F1E6..1F1FF ; Emoji_Component # E0.0 [26] (🇦..🇿) regional indicator symbol letter a..regional indicator symbol letter z +1F3FB..1F3FF ; Emoji_Component # E1.0 [5] (🏻..🏿) light skin tone..dark skin tone +1F9B0..1F9B3 ; Emoji_Component # E11.0 [4] (🦰..🦳) red hair..white hair +E0020..E007F ; Emoji_Component # E0.0 [96] (󠀠..󠁿) tag space..cancel tag + +# Total elements: 146 + +# ================================================ + +# All omitted code points have Extended_Pictographic=No + +00A9 ; Extended_Pictographic# E0.6 [1] (©️) copyright +00AE ; Extended_Pictographic# E0.6 [1] (®️) registered +203C ; Extended_Pictographic# E0.6 [1] (‼️) double exclamation mark +2049 ; Extended_Pictographic# E0.6 [1] (⁉️) exclamation question mark +2122 ; Extended_Pictographic# E0.6 [1] (™️) trade mark +2139 ; Extended_Pictographic# E0.6 [1] (ℹ️) information +2194..2199 ; Extended_Pictographic# E0.6 [6] (↔️..↙️) left-right arrow..down-left arrow +21A9..21AA ; Extended_Pictographic# E0.6 [2] (↩️..↪️) right arrow curving left..left arrow curving right +231A..231B ; Extended_Pictographic# E0.6 [2] (⌚..⌛) watch..hourglass done +2328 ; Extended_Pictographic# E1.0 [1] (⌨️) keyboard +2388 ; Extended_Pictographic# E0.0 [1] (⎈) HELM SYMBOL +23CF ; Extended_Pictographic# E1.0 [1] (⏏️) eject button +23E9..23EC ; Extended_Pictographic# E0.6 [4] (⏩..⏬) fast-forward button..fast down button +23ED..23EE ; Extended_Pictographic# E0.7 [2] (⏭️..⏮️) next track button..last track button +23EF ; Extended_Pictographic# E1.0 [1] (⏯️) play or pause button +23F0 ; Extended_Pictographic# E0.6 [1] (⏰) alarm clock +23F1..23F2 ; Extended_Pictographic# E1.0 [2] (⏱️..⏲️) stopwatch..timer clock +23F3 ; Extended_Pictographic# E0.6 [1] (⏳) hourglass not done +23F8..23FA ; Extended_Pictographic# E0.7 [3] (⏸️..⏺️) pause button..record button +24C2 ; Extended_Pictographic# E0.6 [1] (Ⓜ️) circled M +25AA..25AB ; Extended_Pictographic# E0.6 [2] (▪️..▫️) black small square..white small square +25B6 ; Extended_Pictographic# E0.6 [1] (▶️) play button +25C0 ; Extended_Pictographic# E0.6 [1] (◀️) reverse button +25FB..25FE ; Extended_Pictographic# E0.6 [4] (◻️..◾) white medium square..black medium-small square +2600..2601 ; Extended_Pictographic# E0.6 [2] (☀️..☁️) sun..cloud +2602..2603 ; Extended_Pictographic# E0.7 [2] (☂️..☃️) umbrella..snowman +2604 ; Extended_Pictographic# E1.0 [1] (☄️) comet +2605 ; Extended_Pictographic# E0.0 [1] (★) BLACK STAR +2607..260D ; Extended_Pictographic# E0.0 [7] (☇..☍) LIGHTNING..OPPOSITION +260E ; Extended_Pictographic# E0.6 [1] (☎️) telephone +260F..2610 ; Extended_Pictographic# E0.0 [2] (☏..☐) WHITE TELEPHONE..BALLOT BOX +2611 ; Extended_Pictographic# E0.6 [1] (☑️) check box with check +2612 ; Extended_Pictographic# E0.0 [1] (☒) BALLOT BOX WITH X +2614..2615 ; Extended_Pictographic# E0.6 [2] (☔..☕) umbrella with rain drops..hot beverage +2616..2617 ; Extended_Pictographic# E0.0 [2] (☖..☗) WHITE SHOGI PIECE..BLACK SHOGI PIECE +2618 ; Extended_Pictographic# E1.0 [1] (☘️) shamrock +2619..261C ; Extended_Pictographic# E0.0 [4] (☙..☜) REVERSED ROTATED FLORAL HEART BULLET..WHITE LEFT POINTING INDEX +261D ; Extended_Pictographic# E0.6 [1] (☝️) index pointing up +261E..261F ; Extended_Pictographic# E0.0 [2] (☞..☟) WHITE RIGHT POINTING INDEX..WHITE DOWN POINTING INDEX +2620 ; Extended_Pictographic# E1.0 [1] (☠️) skull and crossbones +2621 ; Extended_Pictographic# E0.0 [1] (☡) CAUTION SIGN +2622..2623 ; Extended_Pictographic# E1.0 [2] (☢️..☣️) radioactive..biohazard +2624..2625 ; Extended_Pictographic# E0.0 [2] (☤..☥) CADUCEUS..ANKH +2626 ; Extended_Pictographic# E1.0 [1] (☦️) orthodox cross +2627..2629 ; Extended_Pictographic# E0.0 [3] (☧..☩) CHI RHO..CROSS OF JERUSALEM +262A ; Extended_Pictographic# E0.7 [1] (☪️) star and crescent +262B..262D ; Extended_Pictographic# E0.0 [3] (☫..☭) FARSI SYMBOL..HAMMER AND SICKLE +262E ; Extended_Pictographic# E1.0 [1] (☮️) peace symbol +262F ; Extended_Pictographic# E0.7 [1] (☯️) yin yang +2630..2637 ; Extended_Pictographic# E0.0 [8] (☰..☷) TRIGRAM FOR HEAVEN..TRIGRAM FOR EARTH +2638..2639 ; Extended_Pictographic# E0.7 [2] (☸️..☹️) wheel of dharma..frowning face +263A ; Extended_Pictographic# E0.6 [1] (☺️) smiling face +263B..263F ; Extended_Pictographic# E0.0 [5] (☻..☿) BLACK SMILING FACE..MERCURY +2640 ; Extended_Pictographic# E4.0 [1] (♀️) female sign +2641 ; Extended_Pictographic# E0.0 [1] (♁) EARTH +2642 ; Extended_Pictographic# E4.0 [1] (♂️) male sign +2643..2647 ; Extended_Pictographic# E0.0 [5] (♃..♇) JUPITER..PLUTO +2648..2653 ; Extended_Pictographic# E0.6 [12] (♈..♓) Aries..Pisces +2654..265E ; Extended_Pictographic# E0.0 [11] (♔..♞) WHITE CHESS KING..BLACK CHESS KNIGHT +265F ; Extended_Pictographic# E11.0 [1] (♟️) chess pawn +2660 ; Extended_Pictographic# E0.6 [1] (♠️) spade suit +2661..2662 ; Extended_Pictographic# E0.0 [2] (♡..♢) WHITE HEART SUIT..WHITE DIAMOND SUIT +2663 ; Extended_Pictographic# E0.6 [1] (♣️) club suit +2664 ; Extended_Pictographic# E0.0 [1] (♤) WHITE SPADE SUIT +2665..2666 ; Extended_Pictographic# E0.6 [2] (♥️..♦️) heart suit..diamond suit +2667 ; Extended_Pictographic# E0.0 [1] (♧) WHITE CLUB SUIT +2668 ; Extended_Pictographic# E0.6 [1] (♨️) hot springs +2669..267A ; Extended_Pictographic# E0.0 [18] (♩..♺) QUARTER NOTE..RECYCLING SYMBOL FOR GENERIC MATERIALS +267B ; Extended_Pictographic# E0.6 [1] (♻️) recycling symbol +267C..267D ; Extended_Pictographic# E0.0 [2] (♼..♽) RECYCLED PAPER SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL +267E ; Extended_Pictographic# E11.0 [1] (♾️) infinity +267F ; Extended_Pictographic# E0.6 [1] (♿) wheelchair symbol +2680..2685 ; Extended_Pictographic# E0.0 [6] (⚀..⚅) DIE FACE-1..DIE FACE-6 +2690..2691 ; Extended_Pictographic# E0.0 [2] (⚐..⚑) WHITE FLAG..BLACK FLAG +2692 ; Extended_Pictographic# E1.0 [1] (⚒️) hammer and pick +2693 ; Extended_Pictographic# E0.6 [1] (⚓) anchor +2694 ; Extended_Pictographic# E1.0 [1] (⚔️) crossed swords +2695 ; Extended_Pictographic# E4.0 [1] (⚕️) medical symbol +2696..2697 ; Extended_Pictographic# E1.0 [2] (⚖️..⚗️) balance scale..alembic +2698 ; Extended_Pictographic# E0.0 [1] (⚘) FLOWER +2699 ; Extended_Pictographic# E1.0 [1] (⚙️) gear +269A ; Extended_Pictographic# E0.0 [1] (⚚) STAFF OF HERMES +269B..269C ; Extended_Pictographic# E1.0 [2] (⚛️..⚜️) atom symbol..fleur-de-lis +269D..269F ; Extended_Pictographic# E0.0 [3] (⚝..⚟) OUTLINED WHITE STAR..THREE LINES CONVERGING LEFT +26A0..26A1 ; Extended_Pictographic# E0.6 [2] (⚠️..⚡) warning..high voltage +26A2..26A6 ; Extended_Pictographic# E0.0 [5] (⚢..⚦) DOUBLED FEMALE SIGN..MALE WITH STROKE SIGN +26A7 ; Extended_Pictographic# E13.0 [1] (⚧️) transgender symbol +26A8..26A9 ; Extended_Pictographic# E0.0 [2] (⚨..⚩) VERTICAL MALE WITH STROKE SIGN..HORIZONTAL MALE WITH STROKE SIGN +26AA..26AB ; Extended_Pictographic# E0.6 [2] (⚪..⚫) white circle..black circle +26AC..26AF ; Extended_Pictographic# E0.0 [4] (⚬..⚯) MEDIUM SMALL WHITE CIRCLE..UNMARRIED PARTNERSHIP SYMBOL +26B0..26B1 ; Extended_Pictographic# E1.0 [2] (⚰️..⚱️) coffin..funeral urn +26B2..26BC ; Extended_Pictographic# E0.0 [11] (⚲..⚼) NEUTER..SESQUIQUADRATE +26BD..26BE ; Extended_Pictographic# E0.6 [2] (⚽..⚾) soccer ball..baseball +26BF..26C3 ; Extended_Pictographic# E0.0 [5] (⚿..⛃) SQUARED KEY..BLACK DRAUGHTS KING +26C4..26C5 ; Extended_Pictographic# E0.6 [2] (⛄..⛅) snowman without snow..sun behind cloud +26C6..26C7 ; Extended_Pictographic# E0.0 [2] (⛆..⛇) RAIN..BLACK SNOWMAN +26C8 ; Extended_Pictographic# E0.7 [1] (⛈️) cloud with lightning and rain +26C9..26CD ; Extended_Pictographic# E0.0 [5] (⛉..⛍) TURNED WHITE SHOGI PIECE..DISABLED CAR +26CE ; Extended_Pictographic# E0.6 [1] (⛎) Ophiuchus +26CF ; Extended_Pictographic# E0.7 [1] (⛏️) pick +26D0 ; Extended_Pictographic# E0.0 [1] (⛐) CAR SLIDING +26D1 ; Extended_Pictographic# E0.7 [1] (⛑️) rescue worker’s helmet +26D2 ; Extended_Pictographic# E0.0 [1] (⛒) CIRCLED CROSSING LANES +26D3 ; Extended_Pictographic# E0.7 [1] (⛓️) chains +26D4 ; Extended_Pictographic# E0.6 [1] (⛔) no entry +26D5..26E8 ; Extended_Pictographic# E0.0 [20] (⛕..⛨) ALTERNATE ONE-WAY LEFT WAY TRAFFIC..BLACK CROSS ON SHIELD +26E9 ; Extended_Pictographic# E0.7 [1] (⛩️) shinto shrine +26EA ; Extended_Pictographic# E0.6 [1] (⛪) church +26EB..26EF ; Extended_Pictographic# E0.0 [5] (⛫..⛯) CASTLE..MAP SYMBOL FOR LIGHTHOUSE +26F0..26F1 ; Extended_Pictographic# E0.7 [2] (⛰️..⛱️) mountain..umbrella on ground +26F2..26F3 ; Extended_Pictographic# E0.6 [2] (⛲..⛳) fountain..flag in hole +26F4 ; Extended_Pictographic# E0.7 [1] (⛴️) ferry +26F5 ; Extended_Pictographic# E0.6 [1] (⛵) sailboat +26F6 ; Extended_Pictographic# E0.0 [1] (⛶) SQUARE FOUR CORNERS +26F7..26F9 ; Extended_Pictographic# E0.7 [3] (⛷️..⛹️) skier..person bouncing ball +26FA ; Extended_Pictographic# E0.6 [1] (⛺) tent +26FB..26FC ; Extended_Pictographic# E0.0 [2] (⛻..⛼) JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL +26FD ; Extended_Pictographic# E0.6 [1] (⛽) fuel pump +26FE..2701 ; Extended_Pictographic# E0.0 [4] (⛾..✁) CUP ON BLACK SQUARE..UPPER BLADE SCISSORS +2702 ; Extended_Pictographic# E0.6 [1] (✂️) scissors +2703..2704 ; Extended_Pictographic# E0.0 [2] (✃..✄) LOWER BLADE SCISSORS..WHITE SCISSORS +2705 ; Extended_Pictographic# E0.6 [1] (✅) check mark button +2708..270C ; Extended_Pictographic# E0.6 [5] (✈️..✌️) airplane..victory hand +270D ; Extended_Pictographic# E0.7 [1] (✍️) writing hand +270E ; Extended_Pictographic# E0.0 [1] (✎) LOWER RIGHT PENCIL +270F ; Extended_Pictographic# E0.6 [1] (✏️) pencil +2710..2711 ; Extended_Pictographic# E0.0 [2] (✐..✑) UPPER RIGHT PENCIL..WHITE NIB +2712 ; Extended_Pictographic# E0.6 [1] (✒️) black nib +2714 ; Extended_Pictographic# E0.6 [1] (✔️) check mark +2716 ; Extended_Pictographic# E0.6 [1] (✖️) multiply +271D ; Extended_Pictographic# E0.7 [1] (✝️) latin cross +2721 ; Extended_Pictographic# E0.7 [1] (✡️) star of David +2728 ; Extended_Pictographic# E0.6 [1] (✨) sparkles +2733..2734 ; Extended_Pictographic# E0.6 [2] (✳️..✴️) eight-spoked asterisk..eight-pointed star +2744 ; Extended_Pictographic# E0.6 [1] (❄️) snowflake +2747 ; Extended_Pictographic# E0.6 [1] (❇️) sparkle +274C ; Extended_Pictographic# E0.6 [1] (❌) cross mark +274E ; Extended_Pictographic# E0.6 [1] (❎) cross mark button +2753..2755 ; Extended_Pictographic# E0.6 [3] (❓..❕) red question mark..white exclamation mark +2757 ; Extended_Pictographic# E0.6 [1] (❗) red exclamation mark +2763 ; Extended_Pictographic# E1.0 [1] (❣️) heart exclamation +2764 ; Extended_Pictographic# E0.6 [1] (❤️) red heart +2765..2767 ; Extended_Pictographic# E0.0 [3] (❥..❧) ROTATED HEAVY BLACK HEART BULLET..ROTATED FLORAL HEART BULLET +2795..2797 ; Extended_Pictographic# E0.6 [3] (➕..➗) plus..divide +27A1 ; Extended_Pictographic# E0.6 [1] (➡️) right arrow +27B0 ; Extended_Pictographic# E0.6 [1] (➰) curly loop +27BF ; Extended_Pictographic# E1.0 [1] (➿) double curly loop +2934..2935 ; Extended_Pictographic# E0.6 [2] (⤴️..⤵️) right arrow curving up..right arrow curving down +2B05..2B07 ; Extended_Pictographic# E0.6 [3] (⬅️..⬇️) left arrow..down arrow +2B1B..2B1C ; Extended_Pictographic# E0.6 [2] (⬛..⬜) black large square..white large square +2B50 ; Extended_Pictographic# E0.6 [1] (⭐) star +2B55 ; Extended_Pictographic# E0.6 [1] (⭕) hollow red circle +3030 ; Extended_Pictographic# E0.6 [1] (〰️) wavy dash +303D ; Extended_Pictographic# E0.6 [1] (〽️) part alternation mark +3297 ; Extended_Pictographic# E0.6 [1] (㊗️) Japanese “congratulations” button +3299 ; Extended_Pictographic# E0.6 [1] (㊙️) Japanese “secret” button +1F000..1F003 ; Extended_Pictographic# E0.0 [4] (🀀..🀃) MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND +1F004 ; Extended_Pictographic# E0.6 [1] (🀄) mahjong red dragon +1F005..1F0CE ; Extended_Pictographic# E0.0 [202] (🀅..🃎) MAHJONG TILE GREEN DRAGON..PLAYING CARD KING OF DIAMONDS +1F0CF ; Extended_Pictographic# E0.6 [1] (🃏) joker +1F0D0..1F0FF ; Extended_Pictographic# E0.0 [48] (🃐..🃿) .. +1F10D..1F10F ; Extended_Pictographic# E0.0 [3] (🄍..🄏) CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH +1F12F ; Extended_Pictographic# E0.0 [1] (🄯) COPYLEFT SYMBOL +1F16C..1F16F ; Extended_Pictographic# E0.0 [4] (🅬..🅯) RAISED MR SIGN..CIRCLED HUMAN FIGURE +1F170..1F171 ; Extended_Pictographic# E0.6 [2] (🅰️..🅱️) A button (blood type)..B button (blood type) +1F17E..1F17F ; Extended_Pictographic# E0.6 [2] (🅾️..🅿️) O button (blood type)..P button +1F18E ; Extended_Pictographic# E0.6 [1] (🆎) AB button (blood type) +1F191..1F19A ; Extended_Pictographic# E0.6 [10] (🆑..🆚) CL button..VS button +1F1AD..1F1E5 ; Extended_Pictographic# E0.0 [57] (🆭..🇥) MASK WORK SYMBOL.. +1F201..1F202 ; Extended_Pictographic# E0.6 [2] (🈁..🈂️) Japanese “here” button..Japanese “service charge” button +1F203..1F20F ; Extended_Pictographic# E0.0 [13] (🈃..🈏) .. +1F21A ; Extended_Pictographic# E0.6 [1] (🈚) Japanese “free of charge” button +1F22F ; Extended_Pictographic# E0.6 [1] (🈯) Japanese “reserved” button +1F232..1F23A ; Extended_Pictographic# E0.6 [9] (🈲..🈺) Japanese “prohibited” button..Japanese “open for business” button +1F23C..1F23F ; Extended_Pictographic# E0.0 [4] (🈼..🈿) .. +1F249..1F24F ; Extended_Pictographic# E0.0 [7] (🉉..🉏) .. +1F250..1F251 ; Extended_Pictographic# E0.6 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button +1F252..1F2FF ; Extended_Pictographic# E0.0 [174] (🉒..🋿) .. +1F300..1F30C ; Extended_Pictographic# E0.6 [13] (🌀..🌌) cyclone..milky way +1F30D..1F30E ; Extended_Pictographic# E0.7 [2] (🌍..🌎) globe showing Europe-Africa..globe showing Americas +1F30F ; Extended_Pictographic# E0.6 [1] (🌏) globe showing Asia-Australia +1F310 ; Extended_Pictographic# E1.0 [1] (🌐) globe with meridians +1F311 ; Extended_Pictographic# E0.6 [1] (🌑) new moon +1F312 ; Extended_Pictographic# E1.0 [1] (🌒) waxing crescent moon +1F313..1F315 ; Extended_Pictographic# E0.6 [3] (🌓..🌕) first quarter moon..full moon +1F316..1F318 ; Extended_Pictographic# E1.0 [3] (🌖..🌘) waning gibbous moon..waning crescent moon +1F319 ; Extended_Pictographic# E0.6 [1] (🌙) crescent moon +1F31A ; Extended_Pictographic# E1.0 [1] (🌚) new moon face +1F31B ; Extended_Pictographic# E0.6 [1] (🌛) first quarter moon face +1F31C ; Extended_Pictographic# E0.7 [1] (🌜) last quarter moon face +1F31D..1F31E ; Extended_Pictographic# E1.0 [2] (🌝..🌞) full moon face..sun with face +1F31F..1F320 ; Extended_Pictographic# E0.6 [2] (🌟..🌠) glowing star..shooting star +1F321 ; Extended_Pictographic# E0.7 [1] (🌡️) thermometer +1F322..1F323 ; Extended_Pictographic# E0.0 [2] (🌢..🌣) BLACK DROPLET..WHITE SUN +1F324..1F32C ; Extended_Pictographic# E0.7 [9] (🌤️..🌬️) sun behind small cloud..wind face +1F32D..1F32F ; Extended_Pictographic# E1.0 [3] (🌭..🌯) hot dog..burrito +1F330..1F331 ; Extended_Pictographic# E0.6 [2] (🌰..🌱) chestnut..seedling +1F332..1F333 ; Extended_Pictographic# E1.0 [2] (🌲..🌳) evergreen tree..deciduous tree +1F334..1F335 ; Extended_Pictographic# E0.6 [2] (🌴..🌵) palm tree..cactus +1F336 ; Extended_Pictographic# E0.7 [1] (🌶️) hot pepper +1F337..1F34A ; Extended_Pictographic# E0.6 [20] (🌷..🍊) tulip..tangerine +1F34B ; Extended_Pictographic# E1.0 [1] (🍋) lemon +1F34C..1F34F ; Extended_Pictographic# E0.6 [4] (🍌..🍏) banana..green apple +1F350 ; Extended_Pictographic# E1.0 [1] (🍐) pear +1F351..1F37B ; Extended_Pictographic# E0.6 [43] (🍑..🍻) peach..clinking beer mugs +1F37C ; Extended_Pictographic# E1.0 [1] (🍼) baby bottle +1F37D ; Extended_Pictographic# E0.7 [1] (🍽️) fork and knife with plate +1F37E..1F37F ; Extended_Pictographic# E1.0 [2] (🍾..🍿) bottle with popping cork..popcorn +1F380..1F393 ; Extended_Pictographic# E0.6 [20] (🎀..🎓) ribbon..graduation cap +1F394..1F395 ; Extended_Pictographic# E0.0 [2] (🎔..🎕) HEART WITH TIP ON THE LEFT..BOUQUET OF FLOWERS +1F396..1F397 ; Extended_Pictographic# E0.7 [2] (🎖️..🎗️) military medal..reminder ribbon +1F398 ; Extended_Pictographic# E0.0 [1] (🎘) MUSICAL KEYBOARD WITH JACKS +1F399..1F39B ; Extended_Pictographic# E0.7 [3] (🎙️..🎛️) studio microphone..control knobs +1F39C..1F39D ; Extended_Pictographic# E0.0 [2] (🎜..🎝) BEAMED ASCENDING MUSICAL NOTES..BEAMED DESCENDING MUSICAL NOTES +1F39E..1F39F ; Extended_Pictographic# E0.7 [2] (🎞️..🎟️) film frames..admission tickets +1F3A0..1F3C4 ; Extended_Pictographic# E0.6 [37] (🎠..🏄) carousel horse..person surfing +1F3C5 ; Extended_Pictographic# E1.0 [1] (🏅) sports medal +1F3C6 ; Extended_Pictographic# E0.6 [1] (🏆) trophy +1F3C7 ; Extended_Pictographic# E1.0 [1] (🏇) horse racing +1F3C8 ; Extended_Pictographic# E0.6 [1] (🏈) american football +1F3C9 ; Extended_Pictographic# E1.0 [1] (🏉) rugby football +1F3CA ; Extended_Pictographic# E0.6 [1] (🏊) person swimming +1F3CB..1F3CE ; Extended_Pictographic# E0.7 [4] (🏋️..🏎️) person lifting weights..racing car +1F3CF..1F3D3 ; Extended_Pictographic# E1.0 [5] (🏏..🏓) cricket game..ping pong +1F3D4..1F3DF ; Extended_Pictographic# E0.7 [12] (🏔️..🏟️) snow-capped mountain..stadium +1F3E0..1F3E3 ; Extended_Pictographic# E0.6 [4] (🏠..🏣) house..Japanese post office +1F3E4 ; Extended_Pictographic# E1.0 [1] (🏤) post office +1F3E5..1F3F0 ; Extended_Pictographic# E0.6 [12] (🏥..🏰) hospital..castle +1F3F1..1F3F2 ; Extended_Pictographic# E0.0 [2] (🏱..🏲) WHITE PENNANT..BLACK PENNANT +1F3F3 ; Extended_Pictographic# E0.7 [1] (🏳️) white flag +1F3F4 ; Extended_Pictographic# E1.0 [1] (🏴) black flag +1F3F5 ; Extended_Pictographic# E0.7 [1] (🏵️) rosette +1F3F6 ; Extended_Pictographic# E0.0 [1] (🏶) BLACK ROSETTE +1F3F7 ; Extended_Pictographic# E0.7 [1] (🏷️) label +1F3F8..1F3FA ; Extended_Pictographic# E1.0 [3] (🏸..🏺) badminton..amphora +1F400..1F407 ; Extended_Pictographic# E1.0 [8] (🐀..🐇) rat..rabbit +1F408 ; Extended_Pictographic# E0.7 [1] (🐈) cat +1F409..1F40B ; Extended_Pictographic# E1.0 [3] (🐉..🐋) dragon..whale +1F40C..1F40E ; Extended_Pictographic# E0.6 [3] (🐌..🐎) snail..horse +1F40F..1F410 ; Extended_Pictographic# E1.0 [2] (🐏..🐐) ram..goat +1F411..1F412 ; Extended_Pictographic# E0.6 [2] (🐑..🐒) ewe..monkey +1F413 ; Extended_Pictographic# E1.0 [1] (🐓) rooster +1F414 ; Extended_Pictographic# E0.6 [1] (🐔) chicken +1F415 ; Extended_Pictographic# E0.7 [1] (🐕) dog +1F416 ; Extended_Pictographic# E1.0 [1] (🐖) pig +1F417..1F429 ; Extended_Pictographic# E0.6 [19] (🐗..🐩) boar..poodle +1F42A ; Extended_Pictographic# E1.0 [1] (🐪) camel +1F42B..1F43E ; Extended_Pictographic# E0.6 [20] (🐫..🐾) two-hump camel..paw prints +1F43F ; Extended_Pictographic# E0.7 [1] (🐿️) chipmunk +1F440 ; Extended_Pictographic# E0.6 [1] (👀) eyes +1F441 ; Extended_Pictographic# E0.7 [1] (👁️) eye +1F442..1F464 ; Extended_Pictographic# E0.6 [35] (👂..👤) ear..bust in silhouette +1F465 ; Extended_Pictographic# E1.0 [1] (👥) busts in silhouette +1F466..1F46B ; Extended_Pictographic# E0.6 [6] (👦..👫) boy..woman and man holding hands +1F46C..1F46D ; Extended_Pictographic# E1.0 [2] (👬..👭) men holding hands..women holding hands +1F46E..1F4AC ; Extended_Pictographic# E0.6 [63] (👮..💬) police officer..speech balloon +1F4AD ; Extended_Pictographic# E1.0 [1] (💭) thought balloon +1F4AE..1F4B5 ; Extended_Pictographic# E0.6 [8] (💮..💵) white flower..dollar banknote +1F4B6..1F4B7 ; Extended_Pictographic# E1.0 [2] (💶..💷) euro banknote..pound banknote +1F4B8..1F4EB ; Extended_Pictographic# E0.6 [52] (💸..📫) money with wings..closed mailbox with raised flag +1F4EC..1F4ED ; Extended_Pictographic# E0.7 [2] (📬..📭) open mailbox with raised flag..open mailbox with lowered flag +1F4EE ; Extended_Pictographic# E0.6 [1] (📮) postbox +1F4EF ; Extended_Pictographic# E1.0 [1] (📯) postal horn +1F4F0..1F4F4 ; Extended_Pictographic# E0.6 [5] (📰..📴) newspaper..mobile phone off +1F4F5 ; Extended_Pictographic# E1.0 [1] (📵) no mobile phones +1F4F6..1F4F7 ; Extended_Pictographic# E0.6 [2] (📶..📷) antenna bars..camera +1F4F8 ; Extended_Pictographic# E1.0 [1] (📸) camera with flash +1F4F9..1F4FC ; Extended_Pictographic# E0.6 [4] (📹..📼) video camera..videocassette +1F4FD ; Extended_Pictographic# E0.7 [1] (📽️) film projector +1F4FE ; Extended_Pictographic# E0.0 [1] (📾) PORTABLE STEREO +1F4FF..1F502 ; Extended_Pictographic# E1.0 [4] (📿..🔂) prayer beads..repeat single button +1F503 ; Extended_Pictographic# E0.6 [1] (🔃) clockwise vertical arrows +1F504..1F507 ; Extended_Pictographic# E1.0 [4] (🔄..🔇) counterclockwise arrows button..muted speaker +1F508 ; Extended_Pictographic# E0.7 [1] (🔈) speaker low volume +1F509 ; Extended_Pictographic# E1.0 [1] (🔉) speaker medium volume +1F50A..1F514 ; Extended_Pictographic# E0.6 [11] (🔊..🔔) speaker high volume..bell +1F515 ; Extended_Pictographic# E1.0 [1] (🔕) bell with slash +1F516..1F52B ; Extended_Pictographic# E0.6 [22] (🔖..🔫) bookmark..water pistol +1F52C..1F52D ; Extended_Pictographic# E1.0 [2] (🔬..🔭) microscope..telescope +1F52E..1F53D ; Extended_Pictographic# E0.6 [16] (🔮..🔽) crystal ball..downwards button +1F546..1F548 ; Extended_Pictographic# E0.0 [3] (🕆..🕈) WHITE LATIN CROSS..CELTIC CROSS +1F549..1F54A ; Extended_Pictographic# E0.7 [2] (🕉️..🕊️) om..dove +1F54B..1F54E ; Extended_Pictographic# E1.0 [4] (🕋..🕎) kaaba..menorah +1F54F ; Extended_Pictographic# E0.0 [1] (🕏) BOWL OF HYGIEIA +1F550..1F55B ; Extended_Pictographic# E0.6 [12] (🕐..🕛) one o’clock..twelve o’clock +1F55C..1F567 ; Extended_Pictographic# E0.7 [12] (🕜..🕧) one-thirty..twelve-thirty +1F568..1F56E ; Extended_Pictographic# E0.0 [7] (🕨..🕮) RIGHT SPEAKER..BOOK +1F56F..1F570 ; Extended_Pictographic# E0.7 [2] (🕯️..🕰️) candle..mantelpiece clock +1F571..1F572 ; Extended_Pictographic# E0.0 [2] (🕱..🕲) BLACK SKULL AND CROSSBONES..NO PIRACY +1F573..1F579 ; Extended_Pictographic# E0.7 [7] (🕳️..🕹️) hole..joystick +1F57A ; Extended_Pictographic# E3.0 [1] (🕺) man dancing +1F57B..1F586 ; Extended_Pictographic# E0.0 [12] (🕻..🖆) LEFT HAND TELEPHONE RECEIVER..PEN OVER STAMPED ENVELOPE +1F587 ; Extended_Pictographic# E0.7 [1] (🖇️) linked paperclips +1F588..1F589 ; Extended_Pictographic# E0.0 [2] (🖈..🖉) BLACK PUSHPIN..LOWER LEFT PENCIL +1F58A..1F58D ; Extended_Pictographic# E0.7 [4] (🖊️..🖍️) pen..crayon +1F58E..1F58F ; Extended_Pictographic# E0.0 [2] (🖎..🖏) LEFT WRITING HAND..TURNED OK HAND SIGN +1F590 ; Extended_Pictographic# E0.7 [1] (🖐️) hand with fingers splayed +1F591..1F594 ; Extended_Pictographic# E0.0 [4] (🖑..🖔) REVERSED RAISED HAND WITH FINGERS SPLAYED..REVERSED VICTORY HAND +1F595..1F596 ; Extended_Pictographic# E1.0 [2] (🖕..🖖) middle finger..vulcan salute +1F597..1F5A3 ; Extended_Pictographic# E0.0 [13] (🖗..🖣) WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX +1F5A4 ; Extended_Pictographic# E3.0 [1] (🖤) black heart +1F5A5 ; Extended_Pictographic# E0.7 [1] (🖥️) desktop computer +1F5A6..1F5A7 ; Extended_Pictographic# E0.0 [2] (🖦..🖧) KEYBOARD AND MOUSE..THREE NETWORKED COMPUTERS +1F5A8 ; Extended_Pictographic# E0.7 [1] (🖨️) printer +1F5A9..1F5B0 ; Extended_Pictographic# E0.0 [8] (🖩..🖰) POCKET CALCULATOR..TWO BUTTON MOUSE +1F5B1..1F5B2 ; Extended_Pictographic# E0.7 [2] (🖱️..🖲️) computer mouse..trackball +1F5B3..1F5BB ; Extended_Pictographic# E0.0 [9] (🖳..🖻) OLD PERSONAL COMPUTER..DOCUMENT WITH PICTURE +1F5BC ; Extended_Pictographic# E0.7 [1] (🖼️) framed picture +1F5BD..1F5C1 ; Extended_Pictographic# E0.0 [5] (🖽..🗁) FRAME WITH TILES..OPEN FOLDER +1F5C2..1F5C4 ; Extended_Pictographic# E0.7 [3] (🗂️..🗄️) card index dividers..file cabinet +1F5C5..1F5D0 ; Extended_Pictographic# E0.0 [12] (🗅..🗐) EMPTY NOTE..PAGES +1F5D1..1F5D3 ; Extended_Pictographic# E0.7 [3] (🗑️..🗓️) wastebasket..spiral calendar +1F5D4..1F5DB ; Extended_Pictographic# E0.0 [8] (🗔..🗛) DESKTOP WINDOW..DECREASE FONT SIZE SYMBOL +1F5DC..1F5DE ; Extended_Pictographic# E0.7 [3] (🗜️..🗞️) clamp..rolled-up newspaper +1F5DF..1F5E0 ; Extended_Pictographic# E0.0 [2] (🗟..🗠) PAGE WITH CIRCLED TEXT..STOCK CHART +1F5E1 ; Extended_Pictographic# E0.7 [1] (🗡️) dagger +1F5E2 ; Extended_Pictographic# E0.0 [1] (🗢) LIPS +1F5E3 ; Extended_Pictographic# E0.7 [1] (🗣️) speaking head +1F5E4..1F5E7 ; Extended_Pictographic# E0.0 [4] (🗤..🗧) THREE RAYS ABOVE..THREE RAYS RIGHT +1F5E8 ; Extended_Pictographic# E2.0 [1] (🗨️) left speech bubble +1F5E9..1F5EE ; Extended_Pictographic# E0.0 [6] (🗩..🗮) RIGHT SPEECH BUBBLE..LEFT ANGER BUBBLE +1F5EF ; Extended_Pictographic# E0.7 [1] (🗯️) right anger bubble +1F5F0..1F5F2 ; Extended_Pictographic# E0.0 [3] (🗰..🗲) MOOD BUBBLE..LIGHTNING MOOD +1F5F3 ; Extended_Pictographic# E0.7 [1] (🗳️) ballot box with ballot +1F5F4..1F5F9 ; Extended_Pictographic# E0.0 [6] (🗴..🗹) BALLOT SCRIPT X..BALLOT BOX WITH BOLD CHECK +1F5FA ; Extended_Pictographic# E0.7 [1] (🗺️) world map +1F5FB..1F5FF ; Extended_Pictographic# E0.6 [5] (🗻..🗿) mount fuji..moai +1F600 ; Extended_Pictographic# E1.0 [1] (😀) grinning face +1F601..1F606 ; Extended_Pictographic# E0.6 [6] (😁..😆) beaming face with smiling eyes..grinning squinting face +1F607..1F608 ; Extended_Pictographic# E1.0 [2] (😇..😈) smiling face with halo..smiling face with horns +1F609..1F60D ; Extended_Pictographic# E0.6 [5] (😉..😍) winking face..smiling face with heart-eyes +1F60E ; Extended_Pictographic# E1.0 [1] (😎) smiling face with sunglasses +1F60F ; Extended_Pictographic# E0.6 [1] (😏) smirking face +1F610 ; Extended_Pictographic# E0.7 [1] (😐) neutral face +1F611 ; Extended_Pictographic# E1.0 [1] (😑) expressionless face +1F612..1F614 ; Extended_Pictographic# E0.6 [3] (😒..😔) unamused face..pensive face +1F615 ; Extended_Pictographic# E1.0 [1] (😕) confused face +1F616 ; Extended_Pictographic# E0.6 [1] (😖) confounded face +1F617 ; Extended_Pictographic# E1.0 [1] (😗) kissing face +1F618 ; Extended_Pictographic# E0.6 [1] (😘) face blowing a kiss +1F619 ; Extended_Pictographic# E1.0 [1] (😙) kissing face with smiling eyes +1F61A ; Extended_Pictographic# E0.6 [1] (😚) kissing face with closed eyes +1F61B ; Extended_Pictographic# E1.0 [1] (😛) face with tongue +1F61C..1F61E ; Extended_Pictographic# E0.6 [3] (😜..😞) winking face with tongue..disappointed face +1F61F ; Extended_Pictographic# E1.0 [1] (😟) worried face +1F620..1F625 ; Extended_Pictographic# E0.6 [6] (😠..😥) angry face..sad but relieved face +1F626..1F627 ; Extended_Pictographic# E1.0 [2] (😦..😧) frowning face with open mouth..anguished face +1F628..1F62B ; Extended_Pictographic# E0.6 [4] (😨..😫) fearful face..tired face +1F62C ; Extended_Pictographic# E1.0 [1] (😬) grimacing face +1F62D ; Extended_Pictographic# E0.6 [1] (😭) loudly crying face +1F62E..1F62F ; Extended_Pictographic# E1.0 [2] (😮..😯) face with open mouth..hushed face +1F630..1F633 ; Extended_Pictographic# E0.6 [4] (😰..😳) anxious face with sweat..flushed face +1F634 ; Extended_Pictographic# E1.0 [1] (😴) sleeping face +1F635 ; Extended_Pictographic# E0.6 [1] (😵) face with crossed-out eyes +1F636 ; Extended_Pictographic# E1.0 [1] (😶) face without mouth +1F637..1F640 ; Extended_Pictographic# E0.6 [10] (😷..🙀) face with medical mask..weary cat +1F641..1F644 ; Extended_Pictographic# E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes +1F645..1F64F ; Extended_Pictographic# E0.6 [11] (🙅..🙏) person gesturing NO..folded hands +1F680 ; Extended_Pictographic# E0.6 [1] (🚀) rocket +1F681..1F682 ; Extended_Pictographic# E1.0 [2] (🚁..🚂) helicopter..locomotive +1F683..1F685 ; Extended_Pictographic# E0.6 [3] (🚃..🚅) railway car..bullet train +1F686 ; Extended_Pictographic# E1.0 [1] (🚆) train +1F687 ; Extended_Pictographic# E0.6 [1] (🚇) metro +1F688 ; Extended_Pictographic# E1.0 [1] (🚈) light rail +1F689 ; Extended_Pictographic# E0.6 [1] (🚉) station +1F68A..1F68B ; Extended_Pictographic# E1.0 [2] (🚊..🚋) tram..tram car +1F68C ; Extended_Pictographic# E0.6 [1] (🚌) bus +1F68D ; Extended_Pictographic# E0.7 [1] (🚍) oncoming bus +1F68E ; Extended_Pictographic# E1.0 [1] (🚎) trolleybus +1F68F ; Extended_Pictographic# E0.6 [1] (🚏) bus stop +1F690 ; Extended_Pictographic# E1.0 [1] (🚐) minibus +1F691..1F693 ; Extended_Pictographic# E0.6 [3] (🚑..🚓) ambulance..police car +1F694 ; Extended_Pictographic# E0.7 [1] (🚔) oncoming police car +1F695 ; Extended_Pictographic# E0.6 [1] (🚕) taxi +1F696 ; Extended_Pictographic# E1.0 [1] (🚖) oncoming taxi +1F697 ; Extended_Pictographic# E0.6 [1] (🚗) automobile +1F698 ; Extended_Pictographic# E0.7 [1] (🚘) oncoming automobile +1F699..1F69A ; Extended_Pictographic# E0.6 [2] (🚙..🚚) sport utility vehicle..delivery truck +1F69B..1F6A1 ; Extended_Pictographic# E1.0 [7] (🚛..🚡) articulated lorry..aerial tramway +1F6A2 ; Extended_Pictographic# E0.6 [1] (🚢) ship +1F6A3 ; Extended_Pictographic# E1.0 [1] (🚣) person rowing boat +1F6A4..1F6A5 ; Extended_Pictographic# E0.6 [2] (🚤..🚥) speedboat..horizontal traffic light +1F6A6 ; Extended_Pictographic# E1.0 [1] (🚦) vertical traffic light +1F6A7..1F6AD ; Extended_Pictographic# E0.6 [7] (🚧..🚭) construction..no smoking +1F6AE..1F6B1 ; Extended_Pictographic# E1.0 [4] (🚮..🚱) litter in bin sign..non-potable water +1F6B2 ; Extended_Pictographic# E0.6 [1] (🚲) bicycle +1F6B3..1F6B5 ; Extended_Pictographic# E1.0 [3] (🚳..🚵) no bicycles..person mountain biking +1F6B6 ; Extended_Pictographic# E0.6 [1] (🚶) person walking +1F6B7..1F6B8 ; Extended_Pictographic# E1.0 [2] (🚷..🚸) no pedestrians..children crossing +1F6B9..1F6BE ; Extended_Pictographic# E0.6 [6] (🚹..🚾) men’s room..water closet +1F6BF ; Extended_Pictographic# E1.0 [1] (🚿) shower +1F6C0 ; Extended_Pictographic# E0.6 [1] (🛀) person taking bath +1F6C1..1F6C5 ; Extended_Pictographic# E1.0 [5] (🛁..🛅) bathtub..left luggage +1F6C6..1F6CA ; Extended_Pictographic# E0.0 [5] (🛆..🛊) TRIANGLE WITH ROUNDED CORNERS..GIRLS SYMBOL +1F6CB ; Extended_Pictographic# E0.7 [1] (🛋️) couch and lamp +1F6CC ; Extended_Pictographic# E1.0 [1] (🛌) person in bed +1F6CD..1F6CF ; Extended_Pictographic# E0.7 [3] (🛍️..🛏️) shopping bags..bed +1F6D0 ; Extended_Pictographic# E1.0 [1] (🛐) place of worship +1F6D1..1F6D2 ; Extended_Pictographic# E3.0 [2] (🛑..🛒) stop sign..shopping cart +1F6D3..1F6D4 ; Extended_Pictographic# E0.0 [2] (🛓..🛔) STUPA..PAGODA +1F6D5 ; Extended_Pictographic# E12.0 [1] (🛕) hindu temple +1F6D6..1F6D7 ; Extended_Pictographic# E13.0 [2] (🛖..🛗) hut..elevator +1F6D8..1F6DB ; Extended_Pictographic# E0.0 [4] (🛘..🛛) .. +1F6DC ; Extended_Pictographic# E15.0 [1] (🛜) wireless +1F6DD..1F6DF ; Extended_Pictographic# E14.0 [3] (🛝..🛟) playground slide..ring buoy +1F6E0..1F6E5 ; Extended_Pictographic# E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat +1F6E6..1F6E8 ; Extended_Pictographic# E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE +1F6E9 ; Extended_Pictographic# E0.7 [1] (🛩️) small airplane +1F6EA ; Extended_Pictographic# E0.0 [1] (🛪) NORTHEAST-POINTING AIRPLANE +1F6EB..1F6EC ; Extended_Pictographic# E1.0 [2] (🛫..🛬) airplane departure..airplane arrival +1F6ED..1F6EF ; Extended_Pictographic# E0.0 [3] (🛭..🛯) .. +1F6F0 ; Extended_Pictographic# E0.7 [1] (🛰️) satellite +1F6F1..1F6F2 ; Extended_Pictographic# E0.0 [2] (🛱..🛲) ONCOMING FIRE ENGINE..DIESEL LOCOMOTIVE +1F6F3 ; Extended_Pictographic# E0.7 [1] (🛳️) passenger ship +1F6F4..1F6F6 ; Extended_Pictographic# E3.0 [3] (🛴..🛶) kick scooter..canoe +1F6F7..1F6F8 ; Extended_Pictographic# E5.0 [2] (🛷..🛸) sled..flying saucer +1F6F9 ; Extended_Pictographic# E11.0 [1] (🛹) skateboard +1F6FA ; Extended_Pictographic# E12.0 [1] (🛺) auto rickshaw +1F6FB..1F6FC ; Extended_Pictographic# E13.0 [2] (🛻..🛼) pickup truck..roller skate +1F6FD..1F6FF ; Extended_Pictographic# E0.0 [3] (🛽..🛿) .. +1F774..1F77F ; Extended_Pictographic# E0.0 [12] (🝴..🝿) LOT OF FORTUNE..ORCUS +1F7D5..1F7DF ; Extended_Pictographic# E0.0 [11] (🟕..🟟) CIRCLED TRIANGLE.. +1F7E0..1F7EB ; Extended_Pictographic# E12.0 [12] (🟠..🟫) orange circle..brown square +1F7EC..1F7EF ; Extended_Pictographic# E0.0 [4] (🟬..🟯) .. +1F7F0 ; Extended_Pictographic# E14.0 [1] (🟰) heavy equals sign +1F7F1..1F7FF ; Extended_Pictographic# E0.0 [15] (🟱..🟿) .. +1F80C..1F80F ; Extended_Pictographic# E0.0 [4] (🠌..🠏) .. +1F848..1F84F ; Extended_Pictographic# E0.0 [8] (🡈..🡏) .. +1F85A..1F85F ; Extended_Pictographic# E0.0 [6] (🡚..🡟) .. +1F888..1F88F ; Extended_Pictographic# E0.0 [8] (🢈..🢏) .. +1F8AE..1F8FF ; Extended_Pictographic# E0.0 [82] (🢮..🣿) .. +1F90C ; Extended_Pictographic# E13.0 [1] (🤌) pinched fingers +1F90D..1F90F ; Extended_Pictographic# E12.0 [3] (🤍..🤏) white heart..pinching hand +1F910..1F918 ; Extended_Pictographic# E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns +1F919..1F91E ; Extended_Pictographic# E3.0 [6] (🤙..🤞) call me hand..crossed fingers +1F91F ; Extended_Pictographic# E5.0 [1] (🤟) love-you gesture +1F920..1F927 ; Extended_Pictographic# E3.0 [8] (🤠..🤧) cowboy hat face..sneezing face +1F928..1F92F ; Extended_Pictographic# E5.0 [8] (🤨..🤯) face with raised eyebrow..exploding head +1F930 ; Extended_Pictographic# E3.0 [1] (🤰) pregnant woman +1F931..1F932 ; Extended_Pictographic# E5.0 [2] (🤱..🤲) breast-feeding..palms up together +1F933..1F93A ; Extended_Pictographic# E3.0 [8] (🤳..🤺) selfie..person fencing +1F93C..1F93E ; Extended_Pictographic# E3.0 [3] (🤼..🤾) people wrestling..person playing handball +1F93F ; Extended_Pictographic# E12.0 [1] (🤿) diving mask +1F940..1F945 ; Extended_Pictographic# E3.0 [6] (🥀..🥅) wilted flower..goal net +1F947..1F94B ; Extended_Pictographic# E3.0 [5] (🥇..🥋) 1st place medal..martial arts uniform +1F94C ; Extended_Pictographic# E5.0 [1] (🥌) curling stone +1F94D..1F94F ; Extended_Pictographic# E11.0 [3] (🥍..🥏) lacrosse..flying disc +1F950..1F95E ; Extended_Pictographic# E3.0 [15] (🥐..🥞) croissant..pancakes +1F95F..1F96B ; Extended_Pictographic# E5.0 [13] (🥟..🥫) dumpling..canned food +1F96C..1F970 ; Extended_Pictographic# E11.0 [5] (🥬..🥰) leafy green..smiling face with hearts +1F971 ; Extended_Pictographic# E12.0 [1] (🥱) yawning face +1F972 ; Extended_Pictographic# E13.0 [1] (🥲) smiling face with tear +1F973..1F976 ; Extended_Pictographic# E11.0 [4] (🥳..🥶) partying face..cold face +1F977..1F978 ; Extended_Pictographic# E13.0 [2] (🥷..🥸) ninja..disguised face +1F979 ; Extended_Pictographic# E14.0 [1] (🥹) face holding back tears +1F97A ; Extended_Pictographic# E11.0 [1] (🥺) pleading face +1F97B ; Extended_Pictographic# E12.0 [1] (🥻) sari +1F97C..1F97F ; Extended_Pictographic# E11.0 [4] (🥼..🥿) lab coat..flat shoe +1F980..1F984 ; Extended_Pictographic# E1.0 [5] (🦀..🦄) crab..unicorn +1F985..1F991 ; Extended_Pictographic# E3.0 [13] (🦅..🦑) eagle..squid +1F992..1F997 ; Extended_Pictographic# E5.0 [6] (🦒..🦗) giraffe..cricket +1F998..1F9A2 ; Extended_Pictographic# E11.0 [11] (🦘..🦢) kangaroo..swan +1F9A3..1F9A4 ; Extended_Pictographic# E13.0 [2] (🦣..🦤) mammoth..dodo +1F9A5..1F9AA ; Extended_Pictographic# E12.0 [6] (🦥..🦪) sloth..oyster +1F9AB..1F9AD ; Extended_Pictographic# E13.0 [3] (🦫..🦭) beaver..seal +1F9AE..1F9AF ; Extended_Pictographic# E12.0 [2] (🦮..🦯) guide dog..white cane +1F9B0..1F9B9 ; Extended_Pictographic# E11.0 [10] (🦰..🦹) red hair..supervillain +1F9BA..1F9BF ; Extended_Pictographic# E12.0 [6] (🦺..🦿) safety vest..mechanical leg +1F9C0 ; Extended_Pictographic# E1.0 [1] (🧀) cheese wedge +1F9C1..1F9C2 ; Extended_Pictographic# E11.0 [2] (🧁..🧂) cupcake..salt +1F9C3..1F9CA ; Extended_Pictographic# E12.0 [8] (🧃..🧊) beverage box..ice +1F9CB ; Extended_Pictographic# E13.0 [1] (🧋) bubble tea +1F9CC ; Extended_Pictographic# E14.0 [1] (🧌) troll +1F9CD..1F9CF ; Extended_Pictographic# E12.0 [3] (🧍..🧏) person standing..deaf person +1F9D0..1F9E6 ; Extended_Pictographic# E5.0 [23] (🧐..🧦) face with monocle..socks +1F9E7..1F9FF ; Extended_Pictographic# E11.0 [25] (🧧..🧿) red envelope..nazar amulet +1FA00..1FA6F ; Extended_Pictographic# E0.0 [112] (🨀..🩯) NEUTRAL CHESS KING.. +1FA70..1FA73 ; Extended_Pictographic# E12.0 [4] (🩰..🩳) ballet shoes..shorts +1FA74 ; Extended_Pictographic# E13.0 [1] (🩴) thong sandal +1FA75..1FA77 ; Extended_Pictographic# E15.0 [3] (🩵..🩷) light blue heart..pink heart +1FA78..1FA7A ; Extended_Pictographic# E12.0 [3] (🩸..🩺) drop of blood..stethoscope +1FA7B..1FA7C ; Extended_Pictographic# E14.0 [2] (🩻..🩼) x-ray..crutch +1FA7D..1FA7F ; Extended_Pictographic# E0.0 [3] (🩽..🩿) .. +1FA80..1FA82 ; Extended_Pictographic# E12.0 [3] (🪀..🪂) yo-yo..parachute +1FA83..1FA86 ; Extended_Pictographic# E13.0 [4] (🪃..🪆) boomerang..nesting dolls +1FA87..1FA88 ; Extended_Pictographic# E15.0 [2] (🪇..🪈) maracas..flute +1FA89..1FA8F ; Extended_Pictographic# E0.0 [7] (🪉..🪏) .. +1FA90..1FA95 ; Extended_Pictographic# E12.0 [6] (🪐..🪕) ringed planet..banjo +1FA96..1FAA8 ; Extended_Pictographic# E13.0 [19] (🪖..🪨) military helmet..rock +1FAA9..1FAAC ; Extended_Pictographic# E14.0 [4] (🪩..🪬) mirror ball..hamsa +1FAAD..1FAAF ; Extended_Pictographic# E15.0 [3] (🪭..🪯) folding hand fan..khanda +1FAB0..1FAB6 ; Extended_Pictographic# E13.0 [7] (🪰..🪶) fly..feather +1FAB7..1FABA ; Extended_Pictographic# E14.0 [4] (🪷..🪺) lotus..nest with eggs +1FABB..1FABD ; Extended_Pictographic# E15.0 [3] (🪻..🪽) hyacinth..wing +1FABE ; Extended_Pictographic# E0.0 [1] (🪾) +1FABF ; Extended_Pictographic# E15.0 [1] (🪿) goose +1FAC0..1FAC2 ; Extended_Pictographic# E13.0 [3] (🫀..🫂) anatomical heart..people hugging +1FAC3..1FAC5 ; Extended_Pictographic# E14.0 [3] (🫃..🫅) pregnant man..person with crown +1FAC6..1FACD ; Extended_Pictographic# E0.0 [8] (🫆..🫍) .. +1FACE..1FACF ; Extended_Pictographic# E15.0 [2] (🫎..🫏) moose..donkey +1FAD0..1FAD6 ; Extended_Pictographic# E13.0 [7] (🫐..🫖) blueberries..teapot +1FAD7..1FAD9 ; Extended_Pictographic# E14.0 [3] (🫗..🫙) pouring liquid..jar +1FADA..1FADB ; Extended_Pictographic# E15.0 [2] (🫚..🫛) ginger root..pea pod +1FADC..1FADF ; Extended_Pictographic# E0.0 [4] (🫜..🫟) .. +1FAE0..1FAE7 ; Extended_Pictographic# E14.0 [8] (🫠..🫧) melting face..bubbles +1FAE8 ; Extended_Pictographic# E15.0 [1] (🫨) shaking face +1FAE9..1FAEF ; Extended_Pictographic# E0.0 [7] (🫩..🫯) .. +1FAF0..1FAF6 ; Extended_Pictographic# E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands +1FAF7..1FAF8 ; Extended_Pictographic# E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand +1FAF9..1FAFF ; Extended_Pictographic# E0.0 [7] (🫹..🫿) .. +1FC00..1FFFD ; Extended_Pictographic# E0.0[1022] (🰀..🿽) .. + +# Total elements: 3537 + +#EOF diff --git a/resources/standards-data/unicode-character-database/unicode-copyright.txt b/resources/standards-data/unicode-character-database/unicode-copyright.txt deleted file mode 100644 index 812c525e15..0000000000 --- a/resources/standards-data/unicode-character-database/unicode-copyright.txt +++ /dev/null @@ -1,56 +0,0 @@ -Unicode Data Files ("DATA FILES") include all data files under the directories: -http://www.unicode.org/Public/ -http://www.unicode.org/reports/ -https://www.unicode.org/ivd/data/ - -Unicode Data Files do not include PDF online code charts under the -directory: -http://www.unicode.org/Public/ - -Unicode Software ("SOFTWARE") includes any source code published in the Unicode Standard -or any source code or compiled code under the directories: -https://www.unicode.org/Public/PROGRAMS/ -https://www.unicode.org/Public/cldr/ -https://site.icu-project.org/download/ - -NOTICE TO USER: Carefully read the following legal agreement. -BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S -DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), -YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE -TERMS AND CONDITIONS OF THIS AGREEMENT. -IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE -THE DATA FILES OR SOFTWARE. - -COPYRIGHT AND PERMISSION NOTICE - -Copyright © 1991-2023 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in https://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that either -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, or -(b) this copyright and permission notice appear in associated -Documentation. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. From 77b94bf559f1cae8ec84c2c257aa39db499942f2 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 6 Aug 2024 14:47:04 +0700 Subject: [PATCH 14/89] feat(common/models): integrates wordbreaking-data processor into wordbreaker toolchain --- common/models/wordbreakers/UNICODE_VERSION.md | 1 - common/models/wordbreakers/build.sh | 4 +++- .../wordbreakers/src/data-compiler/index.ts | 10 ++-------- .../src/imports/WordBreakProperty-13.0.0.txt.gz | Bin 23663 -> 0 bytes .../src/imports/emoji-data-13.0.0.txt.gz | Bin 23400 -> 0 bytes .../wordbreakers/src/main/default/data.ts | 11 ++++++++--- common/models/wordbreakers/tsconfig.json | 16 ---------------- 7 files changed, 13 insertions(+), 29 deletions(-) delete mode 100644 common/models/wordbreakers/UNICODE_VERSION.md delete mode 100644 common/models/wordbreakers/src/imports/WordBreakProperty-13.0.0.txt.gz delete mode 100644 common/models/wordbreakers/src/imports/emoji-data-13.0.0.txt.gz delete mode 100644 common/models/wordbreakers/tsconfig.json diff --git a/common/models/wordbreakers/UNICODE_VERSION.md b/common/models/wordbreakers/UNICODE_VERSION.md deleted file mode 100644 index 70045d3c9a..0000000000 --- a/common/models/wordbreakers/UNICODE_VERSION.md +++ /dev/null @@ -1 +0,0 @@ -13.0.0 \ No newline at end of file diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index bd28c11acf..561bc5a115 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -13,6 +13,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ################################ Main script ################################ builder_describe "Builds the predictive-text wordbreaker implementation module" \ + "@/resources/standards-data/unicode-character-database" \ "clean" \ "configure" \ "build" \ @@ -26,7 +27,8 @@ builder_describe_outputs \ builder_parse "$@" function do_build() { - tsc -b + tsc -b src/data-compiler/tsconfig.json + tsc -b src/main/tsconfig.json # Declaration bundling. tsc -p src/main/tsconfig.json --emitDeclarationOnly --outFile ./build/lib/index.d.ts diff --git a/common/models/wordbreakers/src/data-compiler/index.ts b/common/models/wordbreakers/src/data-compiler/index.ts index 3ef1dc1fc7..4e3a6db337 100644 --- a/common/models/wordbreakers/src/data-compiler/index.ts +++ b/common/models/wordbreakers/src/data-compiler/index.ts @@ -33,16 +33,10 @@ const MAX_CODE_POINT = 0x10FFFF; const projectDir = path.dirname(require.resolve("@keymanapp/models-wordbreakers/UNICODE_VERSION.md")); const generatedFilename = path.join(projectDir, 'src', 'main', 'default', 'data.ts'); -// Ensure this package's major version number is in sync with the Unicode -// major version. - -const packageVersion = new String(fs.readFileSync(`${projectDir}/UNICODE_VERSION.md`)); -const UNICODE_VERSION = packageVersion.split('.')[0] + '.0.0'; - // The data files should be in this repository, with names matching the // Unicode version. -let wordBoundaryFilename = path.join(projectDir, `./src/imports/WordBreakProperty-${UNICODE_VERSION}.txt`); -let emojiDataFilename = path.join(projectDir, `./src/imports/emoji-data-${UNICODE_VERSION}.txt`); +const wordBoundaryFilename = path.join(projectDir, `./resources/standards-data/unicode-character-database/WordBreakProperty.txt`); +const emojiDataFilename = path.join(projectDir, `./resources/standards-data/unicode-character-database/emoji-data.txt`); ///////////////////////////// Word_Boundary file ///////////////////////////// diff --git a/common/models/wordbreakers/src/imports/WordBreakProperty-13.0.0.txt.gz b/common/models/wordbreakers/src/imports/WordBreakProperty-13.0.0.txt.gz deleted file mode 100644 index d3d188ae8249794dfe489b2dabaab286bf7f4725..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23663 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 SwySxQKmGqYUQY-}lK}wuYX*M+ diff --git a/common/models/wordbreakers/src/imports/emoji-data-13.0.0.txt.gz b/common/models/wordbreakers/src/imports/emoji-data-13.0.0.txt.gz deleted file mode 100644 index bf2d917698e8109106f2ae2da8f778c222ce7f4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23400 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%0DIL-cBHi5~rE~}k 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 aQ%ik#j4iV%A}=wXX`((eecZ`JMEEab8)bz6 diff --git a/common/models/wordbreakers/src/main/default/data.ts b/common/models/wordbreakers/src/main/default/data.ts index abd128f020..0b3bc14942 100644 --- a/common/models/wordbreakers/src/main/default/data.ts +++ b/common/models/wordbreakers/src/main/default/data.ts @@ -2,8 +2,11 @@ /** * Valid values for a word break property. + * + * Is optimized away at compile-time; use `propertyMap` to find the mapped + * value at runtime for a property name if needed. */ -export const enum WordBreakProperty { // Scary bit: this does not exist as an object at run-time! +export const enum WordBreakProperty { Other, LF, Newline, @@ -27,8 +30,10 @@ export const enum WordBreakProperty { // Scary bit: this does not exist as an o eot }; -// Not currently built by the auto-generator tool, but it easily could be. -// If and when we import the data.ts rebuilder, we can add this in. +/** + * Contains property names per associated index, as this is compiled away + * by TypeScript for `const enum` cases like `WordBreakProperty`. + */ export const propertyMap = [ "Other", "LF", diff --git a/common/models/wordbreakers/tsconfig.json b/common/models/wordbreakers/tsconfig.json deleted file mode 100644 index 1cebab27c4..0000000000 --- a/common/models/wordbreakers/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "../tsconfig.kmw-worker-base.json", - - "compilerOptions": { - "baseUrl": "./", - "outDir": "build/obj", - "tsBuildInfoFile": "build/tsconfig.tsbuildinfo", - "rootDir": "./", - "module": "Node16", - "moduleResolution": "Node16" - }, - "references": [ - { "path": "./src/main" }, - { "path": "./src/data-compiler" } - ] -} \ No newline at end of file From 242eb6c0ad38414a5af03e129a3acaa30b289a87 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 6 Aug 2024 14:55:30 +0700 Subject: [PATCH 15/89] fix(common): restore, preserve unicode-copyright.txt --- .../unicode-character-database/build.sh | 4 +- .../unicode-copyright.txt | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 resources/standards-data/unicode-character-database/unicode-copyright.txt diff --git a/resources/standards-data/unicode-character-database/build.sh b/resources/standards-data/unicode-character-database/build.sh index a1be097be6..edb3c1e6ba 100755 --- a/resources/standards-data/unicode-character-database/build.sh +++ b/resources/standards-data/unicode-character-database/build.sh @@ -51,7 +51,9 @@ function downloadPropertyFile() { } do_clean() { - rm -rf **/*.txt + mv unicode-copyright.txt unicode-copyright.txt.bak + rm -rf *.txt + mv unicode-copyright.txt.bak unicode-copyright.txt } do_configure() { diff --git a/resources/standards-data/unicode-character-database/unicode-copyright.txt b/resources/standards-data/unicode-character-database/unicode-copyright.txt new file mode 100644 index 0000000000..812c525e15 --- /dev/null +++ b/resources/standards-data/unicode-character-database/unicode-copyright.txt @@ -0,0 +1,56 @@ +Unicode Data Files ("DATA FILES") include all data files under the directories: +http://www.unicode.org/Public/ +http://www.unicode.org/reports/ +https://www.unicode.org/ivd/data/ + +Unicode Data Files do not include PDF online code charts under the +directory: +http://www.unicode.org/Public/ + +Unicode Software ("SOFTWARE") includes any source code published in the Unicode Standard +or any source code or compiled code under the directories: +https://www.unicode.org/Public/PROGRAMS/ +https://www.unicode.org/Public/cldr/ +https://site.icu-project.org/download/ + +NOTICE TO USER: Carefully read the following legal agreement. +BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. +IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +THE DATA FILES OR SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2023 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in https://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. From c7f4631fea307c9d02859a765bab62b53e4ba1bd Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 08:34:57 +0700 Subject: [PATCH 16/89] fix(common/models): fix tsconfig issue from this PR's changes --- .../wordbreakers/src/main/tsconfig.json | 19 ------------------- common/models/wordbreakers/tsconfig.json | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 common/models/wordbreakers/src/main/tsconfig.json create mode 100644 common/models/wordbreakers/tsconfig.json diff --git a/common/models/wordbreakers/src/main/tsconfig.json b/common/models/wordbreakers/src/main/tsconfig.json deleted file mode 100644 index ce66f0bbfc..0000000000 --- a/common/models/wordbreakers/src/main/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../../tsconfig.kmw-worker-base.json", - - "compilerOptions": { - "baseUrl": "./", - "outDir": "../../build/obj", - "tsBuildInfoFile": "../../build/obj/tsconfig.tsbuildinfo", - "rootDir": "./" - }, - "references": [ - { "path": "../../../types" } - ], - "include": [ - "./**/*" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/common/models/wordbreakers/tsconfig.json b/common/models/wordbreakers/tsconfig.json new file mode 100644 index 0000000000..64d193242d --- /dev/null +++ b/common/models/wordbreakers/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../tsconfig.kmw-worker-base.json", + + "compilerOptions": { + "baseUrl": "./", + "outDir": "./build/obj", + "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", + "rootDir": "./src/main" + }, + "references": [ + { "path": "../types" } + ], + "include": [ + "./src/main/**/*" + ], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file From e2dffff68d0653c4f6d4961f8479550e438b1470 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 08:36:17 +0700 Subject: [PATCH 17/89] fix(common): fix data-compiler path references --- common/models/wordbreakers/package.json | 4 ++-- .../wordbreakers/src/data-compiler/index.ts | 22 ++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index c2b295ec42..d433bcdff4 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -28,8 +28,8 @@ "./test-index": { "default": "./build/obj/test-index.js" }, - "./UNICODE_VERSION.md": { - "default": "./UNICODE_VERSION.md" + "./README.md": { + "default": "./README.md" } }, "directories": { diff --git a/common/models/wordbreakers/src/data-compiler/index.ts b/common/models/wordbreakers/src/data-compiler/index.ts index 4e3a6db337..c986d13281 100644 --- a/common/models/wordbreakers/src/data-compiler/index.ts +++ b/common/models/wordbreakers/src/data-compiler/index.ts @@ -30,13 +30,13 @@ const MAX_CODE_POINT = 0x10FFFF; //////////////////////////////////// Main //////////////////////////////////// -const projectDir = path.dirname(require.resolve("@keymanapp/models-wordbreakers/UNICODE_VERSION.md")); +const projectDir = path.dirname(require.resolve("@keymanapp/models-wordbreakers/README.md")); const generatedFilename = path.join(projectDir, 'src', 'main', 'default', 'data.ts'); // The data files should be in this repository, with names matching the // Unicode version. -const wordBoundaryFilename = path.join(projectDir, `./resources/standards-data/unicode-character-database/WordBreakProperty.txt`); -const emojiDataFilename = path.join(projectDir, `./resources/standards-data/unicode-character-database/emoji-data.txt`); +const wordBoundaryFilename = path.join(projectDir, `../../../resources/standards-data/unicode-character-database/WordBreakProperty.txt`); +const emojiDataFilename = path.join(projectDir, `../../../resources/standards-data/unicode-character-database/emoji-data.txt`); ///////////////////////////// Word_Boundary file ///////////////////////////// @@ -105,6 +105,7 @@ let stream = fs.createWriteStream(generatedFilename); // Generate the file! stream.write(`// Automatically generated file. DO NOT MODIFY. +// The generator script is defined at /common/models/wordbreakers/src/data-compiler/index.ts. /** * Valid values for a word break property. @@ -140,6 +141,21 @@ export const enum I { Value = 1 } +/** + * Defines a mapping of all characters to their assigned word-breaking + * property type. + * + * There are implicit buckets starting at the char with specified code \`number\` + * of an entry up to, but not including, the value in the next entry. All + * entries in each bucket share the same property value. + * + * Consider the following two consecutive buckets: + * - [0x0041, WordBreakProperty.ALetter] + * - [0x005B, WordBreakProperty.Other] + * + * For this example, all characters from 0x0041 to 0x005B (that is, 'A'-'Z') + * have the wordbreaking property \`ALetter\`. + */ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ ${ // TODO: Two versions: one that's BMP-encoded, one that's non-BMP encoded. From 217ad29a5ba6e8e344d4fa791327334907eb32a6 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 08:36:25 +0700 Subject: [PATCH 18/89] fix(common/models): actually run the data-compiler --- common/models/wordbreakers/build.sh | 6 +- .../wordbreakers/src/main/default/data.ts | 180 ++++++++++++++---- 2 files changed, 149 insertions(+), 37 deletions(-) diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index 561bc5a115..8dfa0f7cb6 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -28,10 +28,12 @@ builder_parse "$@" function do_build() { tsc -b src/data-compiler/tsconfig.json - tsc -b src/main/tsconfig.json + node ./build/obj/data-compiler/index.js + + tsc -b ./tsconfig.json # Declaration bundling. - tsc -p src/main/tsconfig.json --emitDeclarationOnly --outFile ./build/lib/index.d.ts + tsc -p ./tsconfig.json --emitDeclarationOnly --outFile ./build/lib/index.d.ts } function do_test() { diff --git a/common/models/wordbreakers/src/main/default/data.ts b/common/models/wordbreakers/src/main/default/data.ts index 0b3bc14942..e1cd8aeb88 100644 --- a/common/models/wordbreakers/src/main/default/data.ts +++ b/common/models/wordbreakers/src/main/default/data.ts @@ -1,4 +1,5 @@ // Automatically generated file. DO NOT MODIFY. +// The generator script is defined at /common/models/wordbreakers/src/data-compiler/index.ts. /** * Valid values for a word break property. @@ -66,6 +67,21 @@ export const enum I { Value = 1 } +/** + * Defines a mapping of all characters to their assigned word-breaking + * property type. + * + * There are implicit buckets starting at the char with specified code `number` + * of an entry up to, but not including, the value in the next entry. All + * entries in each bucket share the same property value. + * + * Consider the following two consecutive buckets: + * - [0x0041, WordBreakProperty.ALetter] + * - [0x005B, WordBreakProperty.Other] + * + * For this example, all characters from 0x0041 to 0x005B (that is, 'A'-'Z') + * have the wordbreaking property `ALetter`. + */ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x0, WordBreakProperty.Other], [/*start*/ 0xA, WordBreakProperty.LF], @@ -161,7 +177,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x5F3, WordBreakProperty.ALetter], [/*start*/ 0x5F4, WordBreakProperty.MidLetter], [/*start*/ 0x5F5, WordBreakProperty.Other], - [/*start*/ 0x600, WordBreakProperty.Format], + [/*start*/ 0x600, WordBreakProperty.Numeric], [/*start*/ 0x606, WordBreakProperty.Other], [/*start*/ 0x60C, WordBreakProperty.MidNum], [/*start*/ 0x60E, WordBreakProperty.Other], @@ -182,7 +198,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x6D4, WordBreakProperty.Other], [/*start*/ 0x6D5, WordBreakProperty.ALetter], [/*start*/ 0x6D6, WordBreakProperty.Extend], - [/*start*/ 0x6DD, WordBreakProperty.Format], + [/*start*/ 0x6DD, WordBreakProperty.Numeric], [/*start*/ 0x6DE, WordBreakProperty.Other], [/*start*/ 0x6DF, WordBreakProperty.Extend], [/*start*/ 0x6E5, WordBreakProperty.ALetter], @@ -195,8 +211,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x6FD, WordBreakProperty.Other], [/*start*/ 0x6FF, WordBreakProperty.ALetter], [/*start*/ 0x700, WordBreakProperty.Other], - [/*start*/ 0x70F, WordBreakProperty.Format], - [/*start*/ 0x710, WordBreakProperty.ALetter], + [/*start*/ 0x70F, WordBreakProperty.ALetter], [/*start*/ 0x711, WordBreakProperty.Extend], [/*start*/ 0x712, WordBreakProperty.ALetter], [/*start*/ 0x730, WordBreakProperty.Extend], @@ -230,12 +245,16 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x85C, WordBreakProperty.Other], [/*start*/ 0x860, WordBreakProperty.ALetter], [/*start*/ 0x86B, WordBreakProperty.Other], + [/*start*/ 0x870, WordBreakProperty.ALetter], + [/*start*/ 0x888, WordBreakProperty.Other], + [/*start*/ 0x889, WordBreakProperty.ALetter], + [/*start*/ 0x88F, WordBreakProperty.Other], + [/*start*/ 0x890, WordBreakProperty.Numeric], + [/*start*/ 0x892, WordBreakProperty.Other], + [/*start*/ 0x898, WordBreakProperty.Extend], [/*start*/ 0x8A0, WordBreakProperty.ALetter], - [/*start*/ 0x8B5, WordBreakProperty.Other], - [/*start*/ 0x8B6, WordBreakProperty.ALetter], - [/*start*/ 0x8C8, WordBreakProperty.Other], - [/*start*/ 0x8D3, WordBreakProperty.Extend], - [/*start*/ 0x8E2, WordBreakProperty.Format], + [/*start*/ 0x8CA, WordBreakProperty.Extend], + [/*start*/ 0x8E2, WordBreakProperty.Numeric], [/*start*/ 0x8E3, WordBreakProperty.Extend], [/*start*/ 0x904, WordBreakProperty.ALetter], [/*start*/ 0x93A, WordBreakProperty.Extend], @@ -428,6 +447,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0xC29, WordBreakProperty.Other], [/*start*/ 0xC2A, WordBreakProperty.ALetter], [/*start*/ 0xC3A, WordBreakProperty.Other], + [/*start*/ 0xC3C, WordBreakProperty.Extend], [/*start*/ 0xC3D, WordBreakProperty.ALetter], [/*start*/ 0xC3E, WordBreakProperty.Extend], [/*start*/ 0xC45, WordBreakProperty.Other], @@ -439,6 +459,8 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0xC57, WordBreakProperty.Other], [/*start*/ 0xC58, WordBreakProperty.ALetter], [/*start*/ 0xC5B, WordBreakProperty.Other], + [/*start*/ 0xC5D, WordBreakProperty.ALetter], + [/*start*/ 0xC5E, WordBreakProperty.Other], [/*start*/ 0xC60, WordBreakProperty.ALetter], [/*start*/ 0xC62, WordBreakProperty.Extend], [/*start*/ 0xC64, WordBreakProperty.Other], @@ -467,7 +489,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0xCCE, WordBreakProperty.Other], [/*start*/ 0xCD5, WordBreakProperty.Extend], [/*start*/ 0xCD7, WordBreakProperty.Other], - [/*start*/ 0xCDE, WordBreakProperty.ALetter], + [/*start*/ 0xCDD, WordBreakProperty.ALetter], [/*start*/ 0xCDF, WordBreakProperty.Other], [/*start*/ 0xCE0, WordBreakProperty.ALetter], [/*start*/ 0xCE2, WordBreakProperty.Extend], @@ -475,7 +497,8 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0xCE6, WordBreakProperty.Numeric], [/*start*/ 0xCF0, WordBreakProperty.Other], [/*start*/ 0xCF1, WordBreakProperty.ALetter], - [/*start*/ 0xCF3, WordBreakProperty.Other], + [/*start*/ 0xCF3, WordBreakProperty.Extend], + [/*start*/ 0xCF4, WordBreakProperty.Other], [/*start*/ 0xD00, WordBreakProperty.Extend], [/*start*/ 0xD04, WordBreakProperty.ALetter], [/*start*/ 0xD0D, WordBreakProperty.Other], @@ -538,7 +561,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0xEB4, WordBreakProperty.Extend], [/*start*/ 0xEBD, WordBreakProperty.Other], [/*start*/ 0xEC8, WordBreakProperty.Extend], - [/*start*/ 0xECE, WordBreakProperty.Other], + [/*start*/ 0xECF, WordBreakProperty.Other], [/*start*/ 0xED0, WordBreakProperty.Numeric], [/*start*/ 0xEDA, WordBreakProperty.Other], [/*start*/ 0xF00, WordBreakProperty.ALetter], @@ -647,11 +670,9 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x16EE, WordBreakProperty.ALetter], [/*start*/ 0x16F9, WordBreakProperty.Other], [/*start*/ 0x1700, WordBreakProperty.ALetter], - [/*start*/ 0x170D, WordBreakProperty.Other], - [/*start*/ 0x170E, WordBreakProperty.ALetter], [/*start*/ 0x1712, WordBreakProperty.Extend], - [/*start*/ 0x1715, WordBreakProperty.Other], - [/*start*/ 0x1720, WordBreakProperty.ALetter], + [/*start*/ 0x1716, WordBreakProperty.Other], + [/*start*/ 0x171F, WordBreakProperty.ALetter], [/*start*/ 0x1732, WordBreakProperty.Extend], [/*start*/ 0x1735, WordBreakProperty.Other], [/*start*/ 0x1740, WordBreakProperty.ALetter], @@ -671,7 +692,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x17EA, WordBreakProperty.Other], [/*start*/ 0x180B, WordBreakProperty.Extend], [/*start*/ 0x180E, WordBreakProperty.Format], - [/*start*/ 0x180F, WordBreakProperty.Other], + [/*start*/ 0x180F, WordBreakProperty.Extend], [/*start*/ 0x1810, WordBreakProperty.Numeric], [/*start*/ 0x181A, WordBreakProperty.Other], [/*start*/ 0x1820, WordBreakProperty.ALetter], @@ -707,12 +728,12 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x1A90, WordBreakProperty.Numeric], [/*start*/ 0x1A9A, WordBreakProperty.Other], [/*start*/ 0x1AB0, WordBreakProperty.Extend], - [/*start*/ 0x1AC1, WordBreakProperty.Other], + [/*start*/ 0x1ACF, WordBreakProperty.Other], [/*start*/ 0x1B00, WordBreakProperty.Extend], [/*start*/ 0x1B05, WordBreakProperty.ALetter], [/*start*/ 0x1B34, WordBreakProperty.Extend], [/*start*/ 0x1B45, WordBreakProperty.ALetter], - [/*start*/ 0x1B4C, WordBreakProperty.Other], + [/*start*/ 0x1B4D, WordBreakProperty.Other], [/*start*/ 0x1B50, WordBreakProperty.Numeric], [/*start*/ 0x1B5A, WordBreakProperty.Other], [/*start*/ 0x1B6B, WordBreakProperty.Extend], @@ -753,8 +774,6 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x1CFB, WordBreakProperty.Other], [/*start*/ 0x1D00, WordBreakProperty.ALetter], [/*start*/ 0x1DC0, WordBreakProperty.Extend], - [/*start*/ 0x1DFA, WordBreakProperty.Other], - [/*start*/ 0x1DFB, WordBreakProperty.Extend], [/*start*/ 0x1E00, WordBreakProperty.ALetter], [/*start*/ 0x1F16, WordBreakProperty.Other], [/*start*/ 0x1F18, WordBreakProperty.ALetter], @@ -860,10 +879,6 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x24B6, WordBreakProperty.ALetter], [/*start*/ 0x24EA, WordBreakProperty.Other], [/*start*/ 0x2C00, WordBreakProperty.ALetter], - [/*start*/ 0x2C2F, WordBreakProperty.Other], - [/*start*/ 0x2C30, WordBreakProperty.ALetter], - [/*start*/ 0x2C5F, WordBreakProperty.Other], - [/*start*/ 0x2C60, WordBreakProperty.ALetter], [/*start*/ 0x2CE5, WordBreakProperty.Other], [/*start*/ 0x2CEB, WordBreakProperty.ALetter], [/*start*/ 0x2CEF, WordBreakProperty.Extend], @@ -952,10 +967,14 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0xA6F0, WordBreakProperty.Extend], [/*start*/ 0xA6F2, WordBreakProperty.Other], [/*start*/ 0xA708, WordBreakProperty.ALetter], - [/*start*/ 0xA7C0, WordBreakProperty.Other], - [/*start*/ 0xA7C2, WordBreakProperty.ALetter], [/*start*/ 0xA7CB, WordBreakProperty.Other], - [/*start*/ 0xA7F5, WordBreakProperty.ALetter], + [/*start*/ 0xA7D0, WordBreakProperty.ALetter], + [/*start*/ 0xA7D2, WordBreakProperty.Other], + [/*start*/ 0xA7D3, WordBreakProperty.ALetter], + [/*start*/ 0xA7D4, WordBreakProperty.Other], + [/*start*/ 0xA7D5, WordBreakProperty.ALetter], + [/*start*/ 0xA7DA, WordBreakProperty.Other], + [/*start*/ 0xA7F2, WordBreakProperty.ALetter], [/*start*/ 0xA802, WordBreakProperty.Extend], [/*start*/ 0xA803, WordBreakProperty.ALetter], [/*start*/ 0xA806, WordBreakProperty.Extend], @@ -1188,12 +1207,34 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x10528, WordBreakProperty.Other], [/*start*/ 0x10530, WordBreakProperty.ALetter], [/*start*/ 0x10564, WordBreakProperty.Other], + [/*start*/ 0x10570, WordBreakProperty.ALetter], + [/*start*/ 0x1057B, WordBreakProperty.Other], + [/*start*/ 0x1057C, WordBreakProperty.ALetter], + [/*start*/ 0x1058B, WordBreakProperty.Other], + [/*start*/ 0x1058C, WordBreakProperty.ALetter], + [/*start*/ 0x10593, WordBreakProperty.Other], + [/*start*/ 0x10594, WordBreakProperty.ALetter], + [/*start*/ 0x10596, WordBreakProperty.Other], + [/*start*/ 0x10597, WordBreakProperty.ALetter], + [/*start*/ 0x105A2, WordBreakProperty.Other], + [/*start*/ 0x105A3, WordBreakProperty.ALetter], + [/*start*/ 0x105B2, WordBreakProperty.Other], + [/*start*/ 0x105B3, WordBreakProperty.ALetter], + [/*start*/ 0x105BA, WordBreakProperty.Other], + [/*start*/ 0x105BB, WordBreakProperty.ALetter], + [/*start*/ 0x105BD, WordBreakProperty.Other], [/*start*/ 0x10600, WordBreakProperty.ALetter], [/*start*/ 0x10737, WordBreakProperty.Other], [/*start*/ 0x10740, WordBreakProperty.ALetter], [/*start*/ 0x10756, WordBreakProperty.Other], [/*start*/ 0x10760, WordBreakProperty.ALetter], [/*start*/ 0x10768, WordBreakProperty.Other], + [/*start*/ 0x10780, WordBreakProperty.ALetter], + [/*start*/ 0x10786, WordBreakProperty.Other], + [/*start*/ 0x10787, WordBreakProperty.ALetter], + [/*start*/ 0x107B1, WordBreakProperty.Other], + [/*start*/ 0x107B2, WordBreakProperty.ALetter], + [/*start*/ 0x107BB, WordBreakProperty.Other], [/*start*/ 0x10800, WordBreakProperty.ALetter], [/*start*/ 0x10806, WordBreakProperty.Other], [/*start*/ 0x10808, WordBreakProperty.ALetter], @@ -1272,6 +1313,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x10EAD, WordBreakProperty.Other], [/*start*/ 0x10EB0, WordBreakProperty.ALetter], [/*start*/ 0x10EB2, WordBreakProperty.Other], + [/*start*/ 0x10EFD, WordBreakProperty.Extend], [/*start*/ 0x10F00, WordBreakProperty.ALetter], [/*start*/ 0x10F1D, WordBreakProperty.Other], [/*start*/ 0x10F27, WordBreakProperty.ALetter], @@ -1279,6 +1321,9 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x10F30, WordBreakProperty.ALetter], [/*start*/ 0x10F46, WordBreakProperty.Extend], [/*start*/ 0x10F51, WordBreakProperty.Other], + [/*start*/ 0x10F70, WordBreakProperty.ALetter], + [/*start*/ 0x10F82, WordBreakProperty.Extend], + [/*start*/ 0x10F86, WordBreakProperty.Other], [/*start*/ 0x10FB0, WordBreakProperty.ALetter], [/*start*/ 0x10FC5, WordBreakProperty.Other], [/*start*/ 0x10FE0, WordBreakProperty.ALetter], @@ -1288,14 +1333,20 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x11038, WordBreakProperty.Extend], [/*start*/ 0x11047, WordBreakProperty.Other], [/*start*/ 0x11066, WordBreakProperty.Numeric], - [/*start*/ 0x11070, WordBreakProperty.Other], + [/*start*/ 0x11070, WordBreakProperty.Extend], + [/*start*/ 0x11071, WordBreakProperty.ALetter], + [/*start*/ 0x11073, WordBreakProperty.Extend], + [/*start*/ 0x11075, WordBreakProperty.ALetter], + [/*start*/ 0x11076, WordBreakProperty.Other], [/*start*/ 0x1107F, WordBreakProperty.Extend], [/*start*/ 0x11083, WordBreakProperty.ALetter], [/*start*/ 0x110B0, WordBreakProperty.Extend], [/*start*/ 0x110BB, WordBreakProperty.Other], - [/*start*/ 0x110BD, WordBreakProperty.Format], + [/*start*/ 0x110BD, WordBreakProperty.Numeric], [/*start*/ 0x110BE, WordBreakProperty.Other], - [/*start*/ 0x110CD, WordBreakProperty.Format], + [/*start*/ 0x110C2, WordBreakProperty.Extend], + [/*start*/ 0x110C3, WordBreakProperty.Other], + [/*start*/ 0x110CD, WordBreakProperty.Numeric], [/*start*/ 0x110CE, WordBreakProperty.Other], [/*start*/ 0x110D0, WordBreakProperty.ALetter], [/*start*/ 0x110E9, WordBreakProperty.Other], @@ -1335,7 +1386,9 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x1122C, WordBreakProperty.Extend], [/*start*/ 0x11238, WordBreakProperty.Other], [/*start*/ 0x1123E, WordBreakProperty.Extend], - [/*start*/ 0x1123F, WordBreakProperty.Other], + [/*start*/ 0x1123F, WordBreakProperty.ALetter], + [/*start*/ 0x11241, WordBreakProperty.Extend], + [/*start*/ 0x11242, WordBreakProperty.Other], [/*start*/ 0x11280, WordBreakProperty.ALetter], [/*start*/ 0x11287, WordBreakProperty.Other], [/*start*/ 0x11288, WordBreakProperty.ALetter], @@ -1480,7 +1533,7 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x11A9A, WordBreakProperty.Other], [/*start*/ 0x11A9D, WordBreakProperty.ALetter], [/*start*/ 0x11A9E, WordBreakProperty.Other], - [/*start*/ 0x11AC0, WordBreakProperty.ALetter], + [/*start*/ 0x11AB0, WordBreakProperty.ALetter], [/*start*/ 0x11AF9, WordBreakProperty.Other], [/*start*/ 0x11C00, WordBreakProperty.ALetter], [/*start*/ 0x11C09, WordBreakProperty.Other], @@ -1532,6 +1585,18 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x11EE0, WordBreakProperty.ALetter], [/*start*/ 0x11EF3, WordBreakProperty.Extend], [/*start*/ 0x11EF7, WordBreakProperty.Other], + [/*start*/ 0x11F00, WordBreakProperty.Extend], + [/*start*/ 0x11F02, WordBreakProperty.ALetter], + [/*start*/ 0x11F03, WordBreakProperty.Extend], + [/*start*/ 0x11F04, WordBreakProperty.ALetter], + [/*start*/ 0x11F11, WordBreakProperty.Other], + [/*start*/ 0x11F12, WordBreakProperty.ALetter], + [/*start*/ 0x11F34, WordBreakProperty.Extend], + [/*start*/ 0x11F3B, WordBreakProperty.Other], + [/*start*/ 0x11F3E, WordBreakProperty.Extend], + [/*start*/ 0x11F43, WordBreakProperty.Other], + [/*start*/ 0x11F50, WordBreakProperty.Numeric], + [/*start*/ 0x11F5A, WordBreakProperty.Other], [/*start*/ 0x11FB0, WordBreakProperty.ALetter], [/*start*/ 0x11FB1, WordBreakProperty.Other], [/*start*/ 0x12000, WordBreakProperty.ALetter], @@ -1540,10 +1605,14 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x1246F, WordBreakProperty.Other], [/*start*/ 0x12480, WordBreakProperty.ALetter], [/*start*/ 0x12544, WordBreakProperty.Other], + [/*start*/ 0x12F90, WordBreakProperty.ALetter], + [/*start*/ 0x12FF1, WordBreakProperty.Other], [/*start*/ 0x13000, WordBreakProperty.ALetter], - [/*start*/ 0x1342F, WordBreakProperty.Other], [/*start*/ 0x13430, WordBreakProperty.Format], - [/*start*/ 0x13439, WordBreakProperty.Other], + [/*start*/ 0x13440, WordBreakProperty.Extend], + [/*start*/ 0x13441, WordBreakProperty.ALetter], + [/*start*/ 0x13447, WordBreakProperty.Extend], + [/*start*/ 0x13456, WordBreakProperty.Other], [/*start*/ 0x14400, WordBreakProperty.ALetter], [/*start*/ 0x14647, WordBreakProperty.Other], [/*start*/ 0x16800, WordBreakProperty.ALetter], @@ -1552,6 +1621,10 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x16A5F, WordBreakProperty.Other], [/*start*/ 0x16A60, WordBreakProperty.Numeric], [/*start*/ 0x16A6A, WordBreakProperty.Other], + [/*start*/ 0x16A70, WordBreakProperty.ALetter], + [/*start*/ 0x16ABF, WordBreakProperty.Other], + [/*start*/ 0x16AC0, WordBreakProperty.Numeric], + [/*start*/ 0x16ACA, WordBreakProperty.Other], [/*start*/ 0x16AD0, WordBreakProperty.ALetter], [/*start*/ 0x16AEE, WordBreakProperty.Other], [/*start*/ 0x16AF0, WordBreakProperty.Extend], @@ -1585,8 +1658,18 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x16FE5, WordBreakProperty.Other], [/*start*/ 0x16FF0, WordBreakProperty.Extend], [/*start*/ 0x16FF2, WordBreakProperty.Other], + [/*start*/ 0x1AFF0, WordBreakProperty.Katakana], + [/*start*/ 0x1AFF4, WordBreakProperty.Other], + [/*start*/ 0x1AFF5, WordBreakProperty.Katakana], + [/*start*/ 0x1AFFC, WordBreakProperty.Other], + [/*start*/ 0x1AFFD, WordBreakProperty.Katakana], + [/*start*/ 0x1AFFF, WordBreakProperty.Other], [/*start*/ 0x1B000, WordBreakProperty.Katakana], [/*start*/ 0x1B001, WordBreakProperty.Other], + [/*start*/ 0x1B120, WordBreakProperty.Katakana], + [/*start*/ 0x1B123, WordBreakProperty.Other], + [/*start*/ 0x1B155, WordBreakProperty.Katakana], + [/*start*/ 0x1B156, WordBreakProperty.Other], [/*start*/ 0x1B164, WordBreakProperty.Katakana], [/*start*/ 0x1B168, WordBreakProperty.Other], [/*start*/ 0x1BC00, WordBreakProperty.ALetter], @@ -1601,6 +1684,10 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x1BC9F, WordBreakProperty.Other], [/*start*/ 0x1BCA0, WordBreakProperty.Format], [/*start*/ 0x1BCA4, WordBreakProperty.Other], + [/*start*/ 0x1CF00, WordBreakProperty.Extend], + [/*start*/ 0x1CF2E, WordBreakProperty.Other], + [/*start*/ 0x1CF30, WordBreakProperty.Extend], + [/*start*/ 0x1CF47, WordBreakProperty.Other], [/*start*/ 0x1D165, WordBreakProperty.Extend], [/*start*/ 0x1D16A, WordBreakProperty.Other], [/*start*/ 0x1D16D, WordBreakProperty.Extend], @@ -1687,6 +1774,10 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x1DAA0, WordBreakProperty.Other], [/*start*/ 0x1DAA1, WordBreakProperty.Extend], [/*start*/ 0x1DAB0, WordBreakProperty.Other], + [/*start*/ 0x1DF00, WordBreakProperty.ALetter], + [/*start*/ 0x1DF1F, WordBreakProperty.Other], + [/*start*/ 0x1DF25, WordBreakProperty.ALetter], + [/*start*/ 0x1DF2B, WordBreakProperty.Other], [/*start*/ 0x1E000, WordBreakProperty.Extend], [/*start*/ 0x1E007, WordBreakProperty.Other], [/*start*/ 0x1E008, WordBreakProperty.Extend], @@ -1697,6 +1788,10 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x1E025, WordBreakProperty.Other], [/*start*/ 0x1E026, WordBreakProperty.Extend], [/*start*/ 0x1E02B, WordBreakProperty.Other], + [/*start*/ 0x1E030, WordBreakProperty.ALetter], + [/*start*/ 0x1E06E, WordBreakProperty.Other], + [/*start*/ 0x1E08F, WordBreakProperty.Extend], + [/*start*/ 0x1E090, WordBreakProperty.Other], [/*start*/ 0x1E100, WordBreakProperty.ALetter], [/*start*/ 0x1E12D, WordBreakProperty.Other], [/*start*/ 0x1E130, WordBreakProperty.Extend], @@ -1706,10 +1801,25 @@ export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ [/*start*/ 0x1E14A, WordBreakProperty.Other], [/*start*/ 0x1E14E, WordBreakProperty.ALetter], [/*start*/ 0x1E14F, WordBreakProperty.Other], + [/*start*/ 0x1E290, WordBreakProperty.ALetter], + [/*start*/ 0x1E2AE, WordBreakProperty.Extend], + [/*start*/ 0x1E2AF, WordBreakProperty.Other], [/*start*/ 0x1E2C0, WordBreakProperty.ALetter], [/*start*/ 0x1E2EC, WordBreakProperty.Extend], [/*start*/ 0x1E2F0, WordBreakProperty.Numeric], [/*start*/ 0x1E2FA, WordBreakProperty.Other], + [/*start*/ 0x1E4D0, WordBreakProperty.ALetter], + [/*start*/ 0x1E4EC, WordBreakProperty.Extend], + [/*start*/ 0x1E4F0, WordBreakProperty.Numeric], + [/*start*/ 0x1E4FA, WordBreakProperty.Other], + [/*start*/ 0x1E7E0, WordBreakProperty.ALetter], + [/*start*/ 0x1E7E7, WordBreakProperty.Other], + [/*start*/ 0x1E7E8, WordBreakProperty.ALetter], + [/*start*/ 0x1E7EC, WordBreakProperty.Other], + [/*start*/ 0x1E7ED, WordBreakProperty.ALetter], + [/*start*/ 0x1E7EF, WordBreakProperty.Other], + [/*start*/ 0x1E7F0, WordBreakProperty.ALetter], + [/*start*/ 0x1E7FF, WordBreakProperty.Other], [/*start*/ 0x1E800, WordBreakProperty.ALetter], [/*start*/ 0x1E8C5, WordBreakProperty.Other], [/*start*/ 0x1E8D0, WordBreakProperty.Extend], From c2da9cdbf641dc5f899211bd418696c642a821f0 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 08:38:21 +0700 Subject: [PATCH 19/89] change(common/models): data table compilation as configure, not build --- common/models/wordbreakers/build.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index 8dfa0f7cb6..41c45f533a 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -26,10 +26,14 @@ builder_describe_outputs \ builder_parse "$@" -function do_build() { +function do_configure() { + verify_npm_setup + tsc -b src/data-compiler/tsconfig.json node ./build/obj/data-compiler/index.js +} +function do_build() { tsc -b ./tsconfig.json # Declaration bundling. @@ -44,7 +48,7 @@ function do_test() { fi } -builder_run_action configure verify_npm_setup +builder_run_action configure do_configure builder_run_action clean rm -rf build/ builder_run_action build do_build builder_run_action test do_test \ No newline at end of file From 1ff33a329a6a8957b7f97a95591586dd11793c45 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 08:39:24 +0700 Subject: [PATCH 20/89] change(common/models): set unicode-data dep for configure step --- common/models/wordbreakers/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index 41c45f533a..e6b503be17 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -13,7 +13,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ################################ Main script ################################ builder_describe "Builds the predictive-text wordbreaker implementation module" \ - "@/resources/standards-data/unicode-character-database" \ + "@/resources/standards-data/unicode-character-database configure" \ "clean" \ "configure" \ "build" \ From 5045df13dbf5b14b699e9cf7898984f5d05cc2ae Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 09:37:07 +0700 Subject: [PATCH 21/89] change(common/models): improve encoding format --- .../wordbreakers/src/data-compiler/index.ts | 55 +++++++++--------- .../wordbreakers/src/main/default/data.ts | Bin 90011 -> 9188 bytes .../wordbreakers/src/main/default/index.ts | 39 ++----------- 3 files changed, 33 insertions(+), 61 deletions(-) diff --git a/common/models/wordbreakers/src/data-compiler/index.ts b/common/models/wordbreakers/src/data-compiler/index.ts index 71ac214768..e4b5d72357 100644 --- a/common/models/wordbreakers/src/data-compiler/index.ts +++ b/common/models/wordbreakers/src/data-compiler/index.ts @@ -2,8 +2,6 @@ // Original version found at: https://github.com/eddieantonio/unicode-default-word-boundary/blob/master/libexec/compile-word-break.js -// TODO: Adapt to produce two string-encoded arrays - one for BMP chars, one for non-BMP chars. - import fs from 'fs'; import path from 'path'; @@ -115,11 +113,13 @@ for(let range of ranges) { // already sorted end: undefined }); - nonBmpRanges.push({ - start: 0x10000, - property: finalBmpRange.property, - end: undefined - }); + if(range.start != 0x10000) { + nonBmpRanges.push({ + start: 0x10000, + property: finalBmpRange.property, + end: undefined + }); + } } nonBmpRanges.push(range); @@ -131,6 +131,14 @@ for(let range of ranges) { // already sorted // Save the output in the gen/ directory. let stream = fs.createWriteStream(generatedFilename); +function escape(codedChar: string) { + if(codedChar == '`' || codedChar == '\\') { + return '\\' + codedChar; + } else { + return codedChar; + } +} + // // Former entry in the original version by Eddie that was never included in our repo: // export const extendedPictographic = ${extendedPictographicRegExp}; @@ -164,37 +172,30 @@ ${ /* Enumerate the plain-text names for ease of lookup at runtime */ } ]; -/** - * Constants for indexing values in WORD_BREAK_PROPERTY. - */ -export const enum I { - Start = 0, - Value = 1 -} - export const WORD_BREAK_PROPERTY_BMP: string = \`${ // To consider: emit `\uxxxx` codes instead of the raw char? bmpRanges.map(({start, property}) => { - let codedStart = String.fromCodePoint(start); - if(codedStart == '`') { - // Prevents accidental unescaped use of the string start/end char. - // The backslash gets removed on file-load. - codedStart = '\\`'; - } - const codedProp = String.fromCharCode(categoryMap.get(property)); + let codedStart = escape(String.fromCodePoint(start)); + + // Offset the encoded property value to lie within a friendlier range, + // with characters that render naturally within code editors. + const codedProp = escape(String.fromCharCode(categoryMap.get(property) + 0x20)); return `${codedStart}${codedProp}`; }).join('') -}\` +}\`; export const WORD_BREAK_PROPERTY_NON_BMP: string = \`${ // To consider: emit `\uxxxx` codes instead of the raw char? nonBmpRanges.map(({start, property}) => { - const codedStart = String.fromCodePoint(start); - const codedProp = String.fromCharCode(categoryMap.get(property)); + const codedStart = escape(String.fromCodePoint(start)); + + // Offset the encoded property value to lie within a friendlier range, + // with characters that render naturally within code editors. + const codedProp = escape(String.fromCharCode(categoryMap.get(property) + 0x20)); return `${codedStart}${codedProp}`; }).join('') -} -\``); +}\`; +`); /** * Reads a Unicode character property file. diff --git a/common/models/wordbreakers/src/main/default/data.ts b/common/models/wordbreakers/src/main/default/data.ts index e1cd8aeb88c6d059e7c0f5e4fa04c9ea76e19404..8713fad43c0a0abfae8ca05a9d42141aa230afb2 100644 GIT binary patch literal 9188 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 literal 90011 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 diff --git a/common/models/wordbreakers/src/main/default/index.ts b/common/models/wordbreakers/src/main/default/index.ts index ef50ab4b31..e606a3fbfb 100644 --- a/common/models/wordbreakers/src/main/default/index.ts +++ b/common/models/wordbreakers/src/main/default/index.ts @@ -1,4 +1,6 @@ -import { WordBreakProperty, WORD_BREAK_PROPERTY, I, propertyMap } from "./data.js"; +import { WordBreakProperty, propertyMap } from "./data.js"; + +import { searchForProperty } from "./searchForProperty.js"; /** * A set of options used to customize and extend the behavior of the default @@ -566,7 +568,7 @@ function property(character: string, options?: DefaultWordBreakerOptions): WordB // TODO: remove dependence on character.codepointAt()? let codepoint = character.codePointAt(0) as number; - return searchForProperty(codepoint, 0, WORD_BREAK_PROPERTY.length - 1); + return searchForProperty(codepoint); } function propertyVal(propName: string, options?: DefaultWordBreakerOptions) { @@ -574,35 +576,4 @@ function propertyVal(propName: string, options?: DefaultWordBreakerOptions) { const customIndex = options?.customProperties?.findIndex(matcher) ?? -1; return customIndex != -1 ? -customIndex - 1 : propertyMap.findIndex(matcher); -} - -/** - * Binary search for the word break property of a given CODE POINT. - * - * The auto-generated data.ts master array defines a **character range** - * lookup table. If a character's codepoint is equal to or greater than - * the I.Start value for an entry and exclusively less than the next entry, - * it falls in the first entry's range bucket and is classified accordingly - * by this method. - */ -function searchForProperty(codePoint: number, left: number, right: number): WordBreakProperty { - // All items that are not found in the array are assigned the 'Other' property. - if (right < left) { - return WordBreakProperty.Other; - } - - let midpoint = left + ~~((right - left) / 2); - let candidate = WORD_BREAK_PROPERTY[midpoint]; - - let nextRange = WORD_BREAK_PROPERTY[midpoint + 1]; - let startOfNextRange = nextRange ? nextRange[I.Start] : Infinity; - - if (codePoint < candidate[I.Start]) { - return searchForProperty(codePoint, left, midpoint - 1); - } else if (codePoint >= startOfNextRange) { - return searchForProperty(codePoint, midpoint + 1, right); - } - - // We found it! - return candidate[I.Value]; -} +} \ No newline at end of file From fdecc602d336069ba809bdf7143c7804bbafaaff Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 09:37:22 +0700 Subject: [PATCH 22/89] feat(common/models): connect encoded lookup table --- .../src/main/default/searchForProperty.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/common/models/wordbreakers/src/main/default/searchForProperty.ts b/common/models/wordbreakers/src/main/default/searchForProperty.ts index 45a1641bd9..9fa8f96596 100644 --- a/common/models/wordbreakers/src/main/default/searchForProperty.ts +++ b/common/models/wordbreakers/src/main/default/searchForProperty.ts @@ -1,20 +1,19 @@ -import { WordBreakProperty } from "./data.js"; +import { WordBreakProperty, WORD_BREAK_PROPERTY_BMP, WORD_BREAK_PROPERTY_NON_BMP } from "./data.js"; export function searchForProperty(codePoint: number): WordBreakProperty { const bucketSize = codePoint <= 0xFFFF ? 2 : 3; // SMP chars take a bit more space to encode. - // TODO: encode the strings & import them here. - const encodedArray = bucketSize == 2 ? "" /* BMP string */ : "" /* non-BMP string */; + const encodedArray = bucketSize == 2 ? WORD_BREAK_PROPERTY_BMP : WORD_BREAK_PROPERTY_NON_BMP; - return _searchForProperty(encodedArray, codePoint, bucketSize, 0, encodedArray.length / bucketSize - 1); + return _searchForProperty(encodedArray, codePoint, bucketSize, 0, encodedArray.length / bucketSize - 1) - 0x20; } /** * Binary search for the word break property of a given CODE POINT. * - * The auto-generated data.ts master array defines a **character range** - * lookup table. If a character's codepoint is equal to or greater than + * The auto-generated data.ts master strings encode **character range** + * lookup tables. If a character's codepoint is equal to or greater than * the start-of-range value for an entry and exclusively less than the next * entry's start-of-range, it falls within the first entry's range bucket * and is classified accordingly by this method. From b145adfaf8cccfb4923c14dc1e534929f0a93b88 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 09:50:45 +0700 Subject: [PATCH 23/89] fix(web): fixes value for end of BMP range --- .../wordbreakers/src/data-compiler/index.ts | 2 +- .../wordbreakers/src/main/default/data.ts | Bin 9188 -> 9188 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/common/models/wordbreakers/src/data-compiler/index.ts b/common/models/wordbreakers/src/data-compiler/index.ts index e4b5d72357..1ff2f6dccf 100644 --- a/common/models/wordbreakers/src/data-compiler/index.ts +++ b/common/models/wordbreakers/src/data-compiler/index.ts @@ -109,7 +109,7 @@ for(let range of ranges) { // already sorted const finalBmpRange = bmpRanges[bmpRanges.length - 1]; bmpRanges.push({ start: 0xFFFF, - property: range.property, + property: finalBmpRange.property, end: undefined }); diff --git a/common/models/wordbreakers/src/main/default/data.ts b/common/models/wordbreakers/src/main/default/data.ts index 8713fad43c0a0abfae8ca05a9d42141aa230afb2..5a4062be830d67e97df5794c78f10c50e190cf6a 100644 GIT binary patch delta 14 VcmaFj{=|L5EfGeA&9_B3`2jT-1<(Kh delta 14 VcmaFj{=|L5EfGfT&9_B3`2jUq1=|1s From 02f721dc24247b9e8b2b9c9652e4ec29ba8e353b Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 09:51:49 +0700 Subject: [PATCH 24/89] feat(common/models): add property-lookup unit test set --- .../wordbreakers/test/test-search-property.js | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 common/models/wordbreakers/test/test-search-property.js diff --git a/common/models/wordbreakers/test/test-search-property.js b/common/models/wordbreakers/test/test-search-property.js new file mode 100644 index 0000000000..cdf80c45f4 --- /dev/null +++ b/common/models/wordbreakers/test/test-search-property.js @@ -0,0 +1,33 @@ +/** + * Smoke-test the default + */ + +import { assert } from 'chai'; +import { searchForProperty } from '../build/obj/default/searchForProperty.js'; +import { propertyMap } from '../build/obj/default/data.js'; + +describe('searchForProperty', () => { + it('correctly finds character classes for standard ASCII characters', () => { + assert.equal(searchForProperty('a'.codePointAt(0)), propertyMap.indexOf('ALetter')); + assert.equal(searchForProperty('Z'.codePointAt(0)), propertyMap.indexOf('ALetter')); + + assert.equal(searchForProperty("'".codePointAt(0)), propertyMap.indexOf('Single_Quote')); + assert.equal(searchForProperty('"'.codePointAt(0)), propertyMap.indexOf('Double_Quote')); + assert.equal(searchForProperty(','.codePointAt(0)), propertyMap.indexOf('MidNum')); + assert.equal(searchForProperty('.'.codePointAt(0)), propertyMap.indexOf('MidNumLet')); + assert.equal(searchForProperty('-'.codePointAt(0)), propertyMap.indexOf('Other')); + }); + + it('correctly finds character classes for specialized BMP characters', () => { + assert.equal(searchForProperty(0x05D0), propertyMap.indexOf('Hebrew_Letter')); + assert.equal(searchForProperty(0x3031), propertyMap.indexOf('Katakana')); + assert.equal(searchForProperty(0xFFFE), propertyMap.indexOf('Other')); + assert.equal(searchForProperty(0xFFFF), propertyMap.indexOf('Other')); + }); + + it('correctly finds character classes for non-BMP characters', () => { + assert.equal(searchForProperty(0x0001F1E6), propertyMap.indexOf('Regional_Indicator')); + assert.equal(searchForProperty(0x00013430), propertyMap.indexOf('Format')); + assert.equal(searchForProperty(0x00010000), propertyMap.indexOf('ALetter')); + }); +}); \ No newline at end of file From 6f1d4374e9fb315b6fd7a661b2029fa6ab2e583d Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 7 Aug 2024 10:05:53 +0700 Subject: [PATCH 25/89] feat(web): enable utf8 charset encoding for the build artifacts --- common/web/es-bundling/src/common-bundle.mts | 31 +++++++++++++++----- common/web/lm-worker/build.sh | 2 ++ web/src/app/browser/build.sh | 3 ++ web/src/app/webview/build.sh | 2 ++ 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/common/web/es-bundling/src/common-bundle.mts b/common/web/es-bundling/src/common-bundle.mts index fb3dfb95a4..856d08ec05 100644 --- a/common/web/es-bundling/src/common-bundle.mts +++ b/common/web/es-bundling/src/common-bundle.mts @@ -3,6 +3,7 @@ import esbuild from 'esbuild'; import { esmConfiguration, forES6, iifeConfiguration } from './configuration.mjs'; import { prepareTslibTreeshaking } from './tslibTreeshaking.mjs'; +let CHARSET = 'ascii'; let FORMAT = 'iife'; let MINIFY = false; @@ -28,6 +29,8 @@ Parameters: Options: --help Shows this script's documentation + --charset= Sets the charset type for esbuild to emit. Defaults to 'ascii' + but may also be 'utf8'. --format= Sets the format type to use for the generated bundle. Should be 'iife' or 'esm'. @@ -49,15 +52,28 @@ if(process.argv.length > 2) { case '--help': doHelp(); break; - case '--format': // bc TS uses this exact flag. esbuild... uses sourcemap (in the JS config) - let input = process.argv[++i]; - switch(input) { - case 'iife': - case 'esm': - FORMAT = input; + case '--charset': + let charsetOption = process.argv[++i]; + switch(charsetOption) { + case 'ascii': + case 'utf8': + CHARSET = charsetOption; break; default: - console.error(`Invalid bundling format specified: ${input}. Must be 'iife' or 'esm'.`); + console.error(`Invalid bundling format specified: ${charsetOption}. Must be 'ascii' or 'utf8'.`); + doHelp(1); + break; + } + break; + case '--format': // bc TS uses this exact flag. esbuild... uses sourcemap (in the JS config) + let formatOption = process.argv[++i]; + switch(formatOption) { + case 'iife': + case 'esm': + FORMAT = formatOption; + break; + default: + console.error(`Invalid bundling format specified: ${formatOption}. Must be 'iife' or 'esm'.`); doHelp(1); break; } @@ -128,6 +144,7 @@ const baseConfig = FORMAT == 'iife' ? iifeConfiguration : esmConfiguration; const config: esbuild.BuildOptions = { ...jsVersionTarget == 'es6' ? forES6(baseConfig) : baseConfig, entryPoints: [sourceFile], + charset: CHARSET as 'ascii' | 'utf8', outfile: destFile, minify: MINIFY, metafile: !!profilePath, diff --git a/common/web/lm-worker/build.sh b/common/web/lm-worker/build.sh index 22ffa9208c..cfad5b4071 100755 --- a/common/web/lm-worker/build.sh +++ b/common/web/lm-worker/build.sh @@ -64,6 +64,7 @@ function do_build() { # The ES6 target needs no polyfills - we go straight to the wrapped version. $bundle_cmd src/main/worker-main.ts \ --out $INTERMEDIATE/worker-main.js \ + --charset "utf8" \ --target "es6" \ --sourceRoot '@keymanapp/keyman/common/web/lm-worker/src/main' @@ -75,6 +76,7 @@ function do_build() { $bundle_cmd src/main/worker-main.ts \ --out $INTERMEDIATE/worker-main.min.js \ --minify \ + --charset "utf8" \ --profile build/filesize-profile.log \ --target "es6" \ --sourceRoot '@keymanapp/keyman/common/web/lm-worker/src/main' diff --git a/web/src/app/browser/build.sh b/web/src/app/browser/build.sh index 049bc056b5..85c982ec79 100755 --- a/web/src/app/browser/build.sh +++ b/web/src/app/browser/build.sh @@ -55,11 +55,13 @@ compile_and_copy() { $BUNDLE_CMD "${SRC_ROOT}/debug-main.js" \ --out "${BUILD_ROOT}/debug/keymanweb.js" \ + --charset "utf8" \ --sourceRoot "@keymanapp/keyman/web/build/app/browser/debug" \ --target "es6" $BUNDLE_CMD "${SRC_ROOT}/release-main.js" \ --out "${BUILD_ROOT}/release/keymanweb.js" \ + --charset "utf8" \ --profile "${BUILD_ROOT}/filesize-profile.log" \ --sourceRoot "@keymanapp/keyman/web/build/app/browser/release" \ --minify \ @@ -67,6 +69,7 @@ compile_and_copy() { $BUNDLE_CMD "${BUILD_ROOT}/obj/test-index.js" \ --out "${BUILD_ROOT}/lib/index.mjs" \ + --charset "utf8" \ --sourceRoot "@keymanapp/keyman/web/build/app/browser/lib" \ --format esm diff --git a/web/src/app/webview/build.sh b/web/src/app/webview/build.sh index e22e1b470e..371c9325f2 100755 --- a/web/src/app/webview/build.sh +++ b/web/src/app/webview/build.sh @@ -45,11 +45,13 @@ compile_and_copy() { $BUNDLE_CMD "${SRC_ROOT}/debug-main.js" \ --out "${BUILD_ROOT}/debug/keymanweb-webview.js" \ + --charset "utf8" \ --sourceRoot "@keymanapp/keyman/web/build/app/webview/debug" \ --target "es6" $BUNDLE_CMD "${SRC_ROOT}/release-main.js" \ --out "${BUILD_ROOT}/release/keymanweb-webview.js" \ + --charset "utf8" \ --profile "${BUILD_ROOT}/filesize-profile.log" \ --sourceRoot "@keymanapp/keyman/web/build/app/webview/release" \ --minify \ From dda43aa3994623da489ca7787aaf7b9539d468ca Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 8 Aug 2024 12:51:30 +0700 Subject: [PATCH 26/89] change(common/models): moves wordbreaker data-gen from src/ to tools/, removes old data.ts --- common/models/wordbreakers/.gitignore | 3 +- common/models/wordbreakers/build.sh | 7 +- .../wordbreakers/src/main/default/data.ts | 1917 ----------------- .../wordbreakers/src/main/default/index.ts | 2 +- .../src/main/default/searchForProperty.ts | 2 +- .../wordbreakers/src/main/test-index.ts | 2 +- .../{src => tools}/data-compiler/index.ts | 2 +- .../data-compiler/tsconfig.json | 0 8 files changed, 11 insertions(+), 1924 deletions(-) delete mode 100644 common/models/wordbreakers/src/main/default/data.ts rename common/models/wordbreakers/{src => tools}/data-compiler/index.ts (99%) rename common/models/wordbreakers/{src => tools}/data-compiler/tsconfig.json (100%) diff --git a/common/models/wordbreakers/.gitignore b/common/models/wordbreakers/.gitignore index d16386367f..c51c25f2fd 100644 --- a/common/models/wordbreakers/.gitignore +++ b/common/models/wordbreakers/.gitignore @@ -1 +1,2 @@ -build/ \ No newline at end of file +build/ +**/**.inc.ts \ No newline at end of file diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index e6b503be17..38123ee01c 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -21,7 +21,7 @@ builder_describe "Builds the predictive-text wordbreaker implementation module" "--ci" builder_describe_outputs \ - configure /node_modules \ + configure src/main/default/data.inc.ts \ build build/obj/index.js builder_parse "$@" @@ -29,7 +29,10 @@ builder_parse "$@" function do_configure() { verify_npm_setup - tsc -b src/data-compiler/tsconfig.json + # This is a script used to build the data.inc.ts file needed by the + # default wordbreaker. We rarely update the backing data, but it + # is needed _before_ the `build` action's compilation step. + tsc -b tools/data-compiler/tsconfig.json node ./build/obj/data-compiler/index.js } diff --git a/common/models/wordbreakers/src/main/default/data.ts b/common/models/wordbreakers/src/main/default/data.ts deleted file mode 100644 index e1cd8aeb88..0000000000 --- a/common/models/wordbreakers/src/main/default/data.ts +++ /dev/null @@ -1,1917 +0,0 @@ -// Automatically generated file. DO NOT MODIFY. -// The generator script is defined at /common/models/wordbreakers/src/data-compiler/index.ts. - -/** - * Valid values for a word break property. - * - * Is optimized away at compile-time; use `propertyMap` to find the mapped - * value at runtime for a property name if needed. - */ -export const enum WordBreakProperty { - Other, - LF, - Newline, - CR, - WSegSpace, - Double_Quote, - Single_Quote, - MidNum, - MidNumLet, - Numeric, - MidLetter, - ALetter, - ExtendNumLet, - Format, - Extend, - Hebrew_Letter, - ZWJ, - Katakana, - Regional_Indicator, - sot, - eot -}; - -/** - * Contains property names per associated index, as this is compiled away - * by TypeScript for `const enum` cases like `WordBreakProperty`. - */ -export const propertyMap = [ - "Other", - "LF", - "Newline", - "CR", - "WSegSpace", - "Double_Quote", - "Single_Quote", - "MidNum", - "MidNumLet", - "Numeric", - "MidLetter", - "ALetter", - "ExtendNumLet", - "Format", - "Extend", - "Hebrew_Letter", - "ZWJ", - "Katakana", - "Regional_Indicator", - "sot", - "eot" -]; - -/** - * Constants for indexing values in WORD_BREAK_PROPERTY. - */ -export const enum I { - Start = 0, - Value = 1 -} - -/** - * Defines a mapping of all characters to their assigned word-breaking - * property type. - * - * There are implicit buckets starting at the char with specified code `number` - * of an entry up to, but not including, the value in the next entry. All - * entries in each bucket share the same property value. - * - * Consider the following two consecutive buckets: - * - [0x0041, WordBreakProperty.ALetter] - * - [0x005B, WordBreakProperty.Other] - * - * For this example, all characters from 0x0041 to 0x005B (that is, 'A'-'Z') - * have the wordbreaking property `ALetter`. - */ -export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ - [/*start*/ 0x0, WordBreakProperty.Other], - [/*start*/ 0xA, WordBreakProperty.LF], - [/*start*/ 0xB, WordBreakProperty.Newline], - [/*start*/ 0xD, WordBreakProperty.CR], - [/*start*/ 0xE, WordBreakProperty.Other], - [/*start*/ 0x20, WordBreakProperty.WSegSpace], - [/*start*/ 0x21, WordBreakProperty.Other], - [/*start*/ 0x22, WordBreakProperty.Double_Quote], - [/*start*/ 0x23, WordBreakProperty.Other], - [/*start*/ 0x27, WordBreakProperty.Single_Quote], - [/*start*/ 0x28, WordBreakProperty.Other], - [/*start*/ 0x2C, WordBreakProperty.MidNum], - [/*start*/ 0x2D, WordBreakProperty.Other], - [/*start*/ 0x2E, WordBreakProperty.MidNumLet], - [/*start*/ 0x2F, WordBreakProperty.Other], - [/*start*/ 0x30, WordBreakProperty.Numeric], - [/*start*/ 0x3A, WordBreakProperty.MidLetter], - [/*start*/ 0x3B, WordBreakProperty.MidNum], - [/*start*/ 0x3C, WordBreakProperty.Other], - [/*start*/ 0x41, WordBreakProperty.ALetter], - [/*start*/ 0x5B, WordBreakProperty.Other], - [/*start*/ 0x5F, WordBreakProperty.ExtendNumLet], - [/*start*/ 0x60, WordBreakProperty.Other], - [/*start*/ 0x61, WordBreakProperty.ALetter], - [/*start*/ 0x7B, WordBreakProperty.Other], - [/*start*/ 0x85, WordBreakProperty.Newline], - [/*start*/ 0x86, WordBreakProperty.Other], - [/*start*/ 0xAA, WordBreakProperty.ALetter], - [/*start*/ 0xAB, WordBreakProperty.Other], - [/*start*/ 0xAD, WordBreakProperty.Format], - [/*start*/ 0xAE, WordBreakProperty.Other], - [/*start*/ 0xB5, WordBreakProperty.ALetter], - [/*start*/ 0xB6, WordBreakProperty.Other], - [/*start*/ 0xB7, WordBreakProperty.MidLetter], - [/*start*/ 0xB8, WordBreakProperty.Other], - [/*start*/ 0xBA, WordBreakProperty.ALetter], - [/*start*/ 0xBB, WordBreakProperty.Other], - [/*start*/ 0xC0, WordBreakProperty.ALetter], - [/*start*/ 0xD7, WordBreakProperty.Other], - [/*start*/ 0xD8, WordBreakProperty.ALetter], - [/*start*/ 0xF7, WordBreakProperty.Other], - [/*start*/ 0xF8, WordBreakProperty.ALetter], - [/*start*/ 0x2D8, WordBreakProperty.Other], - [/*start*/ 0x2DE, WordBreakProperty.ALetter], - [/*start*/ 0x300, WordBreakProperty.Extend], - [/*start*/ 0x370, WordBreakProperty.ALetter], - [/*start*/ 0x375, WordBreakProperty.Other], - [/*start*/ 0x376, WordBreakProperty.ALetter], - [/*start*/ 0x378, WordBreakProperty.Other], - [/*start*/ 0x37A, WordBreakProperty.ALetter], - [/*start*/ 0x37E, WordBreakProperty.MidNum], - [/*start*/ 0x37F, WordBreakProperty.ALetter], - [/*start*/ 0x380, WordBreakProperty.Other], - [/*start*/ 0x386, WordBreakProperty.ALetter], - [/*start*/ 0x387, WordBreakProperty.MidLetter], - [/*start*/ 0x388, WordBreakProperty.ALetter], - [/*start*/ 0x38B, WordBreakProperty.Other], - [/*start*/ 0x38C, WordBreakProperty.ALetter], - [/*start*/ 0x38D, WordBreakProperty.Other], - [/*start*/ 0x38E, WordBreakProperty.ALetter], - [/*start*/ 0x3A2, WordBreakProperty.Other], - [/*start*/ 0x3A3, WordBreakProperty.ALetter], - [/*start*/ 0x3F6, WordBreakProperty.Other], - [/*start*/ 0x3F7, WordBreakProperty.ALetter], - [/*start*/ 0x482, WordBreakProperty.Other], - [/*start*/ 0x483, WordBreakProperty.Extend], - [/*start*/ 0x48A, WordBreakProperty.ALetter], - [/*start*/ 0x530, WordBreakProperty.Other], - [/*start*/ 0x531, WordBreakProperty.ALetter], - [/*start*/ 0x557, WordBreakProperty.Other], - [/*start*/ 0x559, WordBreakProperty.ALetter], - [/*start*/ 0x55D, WordBreakProperty.Other], - [/*start*/ 0x55E, WordBreakProperty.ALetter], - [/*start*/ 0x55F, WordBreakProperty.MidLetter], - [/*start*/ 0x560, WordBreakProperty.ALetter], - [/*start*/ 0x589, WordBreakProperty.MidNum], - [/*start*/ 0x58A, WordBreakProperty.ALetter], - [/*start*/ 0x58B, WordBreakProperty.Other], - [/*start*/ 0x591, WordBreakProperty.Extend], - [/*start*/ 0x5BE, WordBreakProperty.Other], - [/*start*/ 0x5BF, WordBreakProperty.Extend], - [/*start*/ 0x5C0, WordBreakProperty.Other], - [/*start*/ 0x5C1, WordBreakProperty.Extend], - [/*start*/ 0x5C3, WordBreakProperty.Other], - [/*start*/ 0x5C4, WordBreakProperty.Extend], - [/*start*/ 0x5C6, WordBreakProperty.Other], - [/*start*/ 0x5C7, WordBreakProperty.Extend], - [/*start*/ 0x5C8, WordBreakProperty.Other], - [/*start*/ 0x5D0, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0x5EB, WordBreakProperty.Other], - [/*start*/ 0x5EF, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0x5F3, WordBreakProperty.ALetter], - [/*start*/ 0x5F4, WordBreakProperty.MidLetter], - [/*start*/ 0x5F5, WordBreakProperty.Other], - [/*start*/ 0x600, WordBreakProperty.Numeric], - [/*start*/ 0x606, WordBreakProperty.Other], - [/*start*/ 0x60C, WordBreakProperty.MidNum], - [/*start*/ 0x60E, WordBreakProperty.Other], - [/*start*/ 0x610, WordBreakProperty.Extend], - [/*start*/ 0x61B, WordBreakProperty.Other], - [/*start*/ 0x61C, WordBreakProperty.Format], - [/*start*/ 0x61D, WordBreakProperty.Other], - [/*start*/ 0x620, WordBreakProperty.ALetter], - [/*start*/ 0x64B, WordBreakProperty.Extend], - [/*start*/ 0x660, WordBreakProperty.Numeric], - [/*start*/ 0x66A, WordBreakProperty.Other], - [/*start*/ 0x66B, WordBreakProperty.Numeric], - [/*start*/ 0x66C, WordBreakProperty.MidNum], - [/*start*/ 0x66D, WordBreakProperty.Other], - [/*start*/ 0x66E, WordBreakProperty.ALetter], - [/*start*/ 0x670, WordBreakProperty.Extend], - [/*start*/ 0x671, WordBreakProperty.ALetter], - [/*start*/ 0x6D4, WordBreakProperty.Other], - [/*start*/ 0x6D5, WordBreakProperty.ALetter], - [/*start*/ 0x6D6, WordBreakProperty.Extend], - [/*start*/ 0x6DD, WordBreakProperty.Numeric], - [/*start*/ 0x6DE, WordBreakProperty.Other], - [/*start*/ 0x6DF, WordBreakProperty.Extend], - [/*start*/ 0x6E5, WordBreakProperty.ALetter], - [/*start*/ 0x6E7, WordBreakProperty.Extend], - [/*start*/ 0x6E9, WordBreakProperty.Other], - [/*start*/ 0x6EA, WordBreakProperty.Extend], - [/*start*/ 0x6EE, WordBreakProperty.ALetter], - [/*start*/ 0x6F0, WordBreakProperty.Numeric], - [/*start*/ 0x6FA, WordBreakProperty.ALetter], - [/*start*/ 0x6FD, WordBreakProperty.Other], - [/*start*/ 0x6FF, WordBreakProperty.ALetter], - [/*start*/ 0x700, WordBreakProperty.Other], - [/*start*/ 0x70F, WordBreakProperty.ALetter], - [/*start*/ 0x711, WordBreakProperty.Extend], - [/*start*/ 0x712, WordBreakProperty.ALetter], - [/*start*/ 0x730, WordBreakProperty.Extend], - [/*start*/ 0x74B, WordBreakProperty.Other], - [/*start*/ 0x74D, WordBreakProperty.ALetter], - [/*start*/ 0x7A6, WordBreakProperty.Extend], - [/*start*/ 0x7B1, WordBreakProperty.ALetter], - [/*start*/ 0x7B2, WordBreakProperty.Other], - [/*start*/ 0x7C0, WordBreakProperty.Numeric], - [/*start*/ 0x7CA, WordBreakProperty.ALetter], - [/*start*/ 0x7EB, WordBreakProperty.Extend], - [/*start*/ 0x7F4, WordBreakProperty.ALetter], - [/*start*/ 0x7F6, WordBreakProperty.Other], - [/*start*/ 0x7F8, WordBreakProperty.MidNum], - [/*start*/ 0x7F9, WordBreakProperty.Other], - [/*start*/ 0x7FA, WordBreakProperty.ALetter], - [/*start*/ 0x7FB, WordBreakProperty.Other], - [/*start*/ 0x7FD, WordBreakProperty.Extend], - [/*start*/ 0x7FE, WordBreakProperty.Other], - [/*start*/ 0x800, WordBreakProperty.ALetter], - [/*start*/ 0x816, WordBreakProperty.Extend], - [/*start*/ 0x81A, WordBreakProperty.ALetter], - [/*start*/ 0x81B, WordBreakProperty.Extend], - [/*start*/ 0x824, WordBreakProperty.ALetter], - [/*start*/ 0x825, WordBreakProperty.Extend], - [/*start*/ 0x828, WordBreakProperty.ALetter], - [/*start*/ 0x829, WordBreakProperty.Extend], - [/*start*/ 0x82E, WordBreakProperty.Other], - [/*start*/ 0x840, WordBreakProperty.ALetter], - [/*start*/ 0x859, WordBreakProperty.Extend], - [/*start*/ 0x85C, WordBreakProperty.Other], - [/*start*/ 0x860, WordBreakProperty.ALetter], - [/*start*/ 0x86B, WordBreakProperty.Other], - [/*start*/ 0x870, WordBreakProperty.ALetter], - [/*start*/ 0x888, WordBreakProperty.Other], - [/*start*/ 0x889, WordBreakProperty.ALetter], - [/*start*/ 0x88F, WordBreakProperty.Other], - [/*start*/ 0x890, WordBreakProperty.Numeric], - [/*start*/ 0x892, WordBreakProperty.Other], - [/*start*/ 0x898, WordBreakProperty.Extend], - [/*start*/ 0x8A0, WordBreakProperty.ALetter], - [/*start*/ 0x8CA, WordBreakProperty.Extend], - [/*start*/ 0x8E2, WordBreakProperty.Numeric], - [/*start*/ 0x8E3, WordBreakProperty.Extend], - [/*start*/ 0x904, WordBreakProperty.ALetter], - [/*start*/ 0x93A, WordBreakProperty.Extend], - [/*start*/ 0x93D, WordBreakProperty.ALetter], - [/*start*/ 0x93E, WordBreakProperty.Extend], - [/*start*/ 0x950, WordBreakProperty.ALetter], - [/*start*/ 0x951, WordBreakProperty.Extend], - [/*start*/ 0x958, WordBreakProperty.ALetter], - [/*start*/ 0x962, WordBreakProperty.Extend], - [/*start*/ 0x964, WordBreakProperty.Other], - [/*start*/ 0x966, WordBreakProperty.Numeric], - [/*start*/ 0x970, WordBreakProperty.Other], - [/*start*/ 0x971, WordBreakProperty.ALetter], - [/*start*/ 0x981, WordBreakProperty.Extend], - [/*start*/ 0x984, WordBreakProperty.Other], - [/*start*/ 0x985, WordBreakProperty.ALetter], - [/*start*/ 0x98D, WordBreakProperty.Other], - [/*start*/ 0x98F, WordBreakProperty.ALetter], - [/*start*/ 0x991, WordBreakProperty.Other], - [/*start*/ 0x993, WordBreakProperty.ALetter], - [/*start*/ 0x9A9, WordBreakProperty.Other], - [/*start*/ 0x9AA, WordBreakProperty.ALetter], - [/*start*/ 0x9B1, WordBreakProperty.Other], - [/*start*/ 0x9B2, WordBreakProperty.ALetter], - [/*start*/ 0x9B3, WordBreakProperty.Other], - [/*start*/ 0x9B6, WordBreakProperty.ALetter], - [/*start*/ 0x9BA, WordBreakProperty.Other], - [/*start*/ 0x9BC, WordBreakProperty.Extend], - [/*start*/ 0x9BD, WordBreakProperty.ALetter], - [/*start*/ 0x9BE, WordBreakProperty.Extend], - [/*start*/ 0x9C5, WordBreakProperty.Other], - [/*start*/ 0x9C7, WordBreakProperty.Extend], - [/*start*/ 0x9C9, WordBreakProperty.Other], - [/*start*/ 0x9CB, WordBreakProperty.Extend], - [/*start*/ 0x9CE, WordBreakProperty.ALetter], - [/*start*/ 0x9CF, WordBreakProperty.Other], - [/*start*/ 0x9D7, WordBreakProperty.Extend], - [/*start*/ 0x9D8, WordBreakProperty.Other], - [/*start*/ 0x9DC, WordBreakProperty.ALetter], - [/*start*/ 0x9DE, WordBreakProperty.Other], - [/*start*/ 0x9DF, WordBreakProperty.ALetter], - [/*start*/ 0x9E2, WordBreakProperty.Extend], - [/*start*/ 0x9E4, WordBreakProperty.Other], - [/*start*/ 0x9E6, WordBreakProperty.Numeric], - [/*start*/ 0x9F0, WordBreakProperty.ALetter], - [/*start*/ 0x9F2, WordBreakProperty.Other], - [/*start*/ 0x9FC, WordBreakProperty.ALetter], - [/*start*/ 0x9FD, WordBreakProperty.Other], - [/*start*/ 0x9FE, WordBreakProperty.Extend], - [/*start*/ 0x9FF, WordBreakProperty.Other], - [/*start*/ 0xA01, WordBreakProperty.Extend], - [/*start*/ 0xA04, WordBreakProperty.Other], - [/*start*/ 0xA05, WordBreakProperty.ALetter], - [/*start*/ 0xA0B, WordBreakProperty.Other], - [/*start*/ 0xA0F, WordBreakProperty.ALetter], - [/*start*/ 0xA11, WordBreakProperty.Other], - [/*start*/ 0xA13, WordBreakProperty.ALetter], - [/*start*/ 0xA29, WordBreakProperty.Other], - [/*start*/ 0xA2A, WordBreakProperty.ALetter], - [/*start*/ 0xA31, WordBreakProperty.Other], - [/*start*/ 0xA32, WordBreakProperty.ALetter], - [/*start*/ 0xA34, WordBreakProperty.Other], - [/*start*/ 0xA35, WordBreakProperty.ALetter], - [/*start*/ 0xA37, WordBreakProperty.Other], - [/*start*/ 0xA38, WordBreakProperty.ALetter], - [/*start*/ 0xA3A, WordBreakProperty.Other], - [/*start*/ 0xA3C, WordBreakProperty.Extend], - [/*start*/ 0xA3D, WordBreakProperty.Other], - [/*start*/ 0xA3E, WordBreakProperty.Extend], - [/*start*/ 0xA43, WordBreakProperty.Other], - [/*start*/ 0xA47, WordBreakProperty.Extend], - [/*start*/ 0xA49, WordBreakProperty.Other], - [/*start*/ 0xA4B, WordBreakProperty.Extend], - [/*start*/ 0xA4E, WordBreakProperty.Other], - [/*start*/ 0xA51, WordBreakProperty.Extend], - [/*start*/ 0xA52, WordBreakProperty.Other], - [/*start*/ 0xA59, WordBreakProperty.ALetter], - [/*start*/ 0xA5D, WordBreakProperty.Other], - [/*start*/ 0xA5E, WordBreakProperty.ALetter], - [/*start*/ 0xA5F, WordBreakProperty.Other], - [/*start*/ 0xA66, WordBreakProperty.Numeric], - [/*start*/ 0xA70, WordBreakProperty.Extend], - [/*start*/ 0xA72, WordBreakProperty.ALetter], - [/*start*/ 0xA75, WordBreakProperty.Extend], - [/*start*/ 0xA76, WordBreakProperty.Other], - [/*start*/ 0xA81, WordBreakProperty.Extend], - [/*start*/ 0xA84, WordBreakProperty.Other], - [/*start*/ 0xA85, WordBreakProperty.ALetter], - [/*start*/ 0xA8E, WordBreakProperty.Other], - [/*start*/ 0xA8F, WordBreakProperty.ALetter], - [/*start*/ 0xA92, WordBreakProperty.Other], - [/*start*/ 0xA93, WordBreakProperty.ALetter], - [/*start*/ 0xAA9, WordBreakProperty.Other], - [/*start*/ 0xAAA, WordBreakProperty.ALetter], - [/*start*/ 0xAB1, WordBreakProperty.Other], - [/*start*/ 0xAB2, WordBreakProperty.ALetter], - [/*start*/ 0xAB4, WordBreakProperty.Other], - [/*start*/ 0xAB5, WordBreakProperty.ALetter], - [/*start*/ 0xABA, WordBreakProperty.Other], - [/*start*/ 0xABC, WordBreakProperty.Extend], - [/*start*/ 0xABD, WordBreakProperty.ALetter], - [/*start*/ 0xABE, WordBreakProperty.Extend], - [/*start*/ 0xAC6, WordBreakProperty.Other], - [/*start*/ 0xAC7, WordBreakProperty.Extend], - [/*start*/ 0xACA, WordBreakProperty.Other], - [/*start*/ 0xACB, WordBreakProperty.Extend], - [/*start*/ 0xACE, WordBreakProperty.Other], - [/*start*/ 0xAD0, WordBreakProperty.ALetter], - [/*start*/ 0xAD1, WordBreakProperty.Other], - [/*start*/ 0xAE0, WordBreakProperty.ALetter], - [/*start*/ 0xAE2, WordBreakProperty.Extend], - [/*start*/ 0xAE4, WordBreakProperty.Other], - [/*start*/ 0xAE6, WordBreakProperty.Numeric], - [/*start*/ 0xAF0, WordBreakProperty.Other], - [/*start*/ 0xAF9, WordBreakProperty.ALetter], - [/*start*/ 0xAFA, WordBreakProperty.Extend], - [/*start*/ 0xB00, WordBreakProperty.Other], - [/*start*/ 0xB01, WordBreakProperty.Extend], - [/*start*/ 0xB04, WordBreakProperty.Other], - [/*start*/ 0xB05, WordBreakProperty.ALetter], - [/*start*/ 0xB0D, WordBreakProperty.Other], - [/*start*/ 0xB0F, WordBreakProperty.ALetter], - [/*start*/ 0xB11, WordBreakProperty.Other], - [/*start*/ 0xB13, WordBreakProperty.ALetter], - [/*start*/ 0xB29, WordBreakProperty.Other], - [/*start*/ 0xB2A, WordBreakProperty.ALetter], - [/*start*/ 0xB31, WordBreakProperty.Other], - [/*start*/ 0xB32, WordBreakProperty.ALetter], - [/*start*/ 0xB34, WordBreakProperty.Other], - [/*start*/ 0xB35, WordBreakProperty.ALetter], - [/*start*/ 0xB3A, WordBreakProperty.Other], - [/*start*/ 0xB3C, WordBreakProperty.Extend], - [/*start*/ 0xB3D, WordBreakProperty.ALetter], - [/*start*/ 0xB3E, WordBreakProperty.Extend], - [/*start*/ 0xB45, WordBreakProperty.Other], - [/*start*/ 0xB47, WordBreakProperty.Extend], - [/*start*/ 0xB49, WordBreakProperty.Other], - [/*start*/ 0xB4B, WordBreakProperty.Extend], - [/*start*/ 0xB4E, WordBreakProperty.Other], - [/*start*/ 0xB55, WordBreakProperty.Extend], - [/*start*/ 0xB58, WordBreakProperty.Other], - [/*start*/ 0xB5C, WordBreakProperty.ALetter], - [/*start*/ 0xB5E, WordBreakProperty.Other], - [/*start*/ 0xB5F, WordBreakProperty.ALetter], - [/*start*/ 0xB62, WordBreakProperty.Extend], - [/*start*/ 0xB64, WordBreakProperty.Other], - [/*start*/ 0xB66, WordBreakProperty.Numeric], - [/*start*/ 0xB70, WordBreakProperty.Other], - [/*start*/ 0xB71, WordBreakProperty.ALetter], - [/*start*/ 0xB72, WordBreakProperty.Other], - [/*start*/ 0xB82, WordBreakProperty.Extend], - [/*start*/ 0xB83, WordBreakProperty.ALetter], - [/*start*/ 0xB84, WordBreakProperty.Other], - [/*start*/ 0xB85, WordBreakProperty.ALetter], - [/*start*/ 0xB8B, WordBreakProperty.Other], - [/*start*/ 0xB8E, WordBreakProperty.ALetter], - [/*start*/ 0xB91, WordBreakProperty.Other], - [/*start*/ 0xB92, WordBreakProperty.ALetter], - [/*start*/ 0xB96, WordBreakProperty.Other], - [/*start*/ 0xB99, WordBreakProperty.ALetter], - [/*start*/ 0xB9B, WordBreakProperty.Other], - [/*start*/ 0xB9C, WordBreakProperty.ALetter], - [/*start*/ 0xB9D, WordBreakProperty.Other], - [/*start*/ 0xB9E, WordBreakProperty.ALetter], - [/*start*/ 0xBA0, WordBreakProperty.Other], - [/*start*/ 0xBA3, WordBreakProperty.ALetter], - [/*start*/ 0xBA5, WordBreakProperty.Other], - [/*start*/ 0xBA8, WordBreakProperty.ALetter], - [/*start*/ 0xBAB, WordBreakProperty.Other], - [/*start*/ 0xBAE, WordBreakProperty.ALetter], - [/*start*/ 0xBBA, WordBreakProperty.Other], - [/*start*/ 0xBBE, WordBreakProperty.Extend], - [/*start*/ 0xBC3, WordBreakProperty.Other], - [/*start*/ 0xBC6, WordBreakProperty.Extend], - [/*start*/ 0xBC9, WordBreakProperty.Other], - [/*start*/ 0xBCA, WordBreakProperty.Extend], - [/*start*/ 0xBCE, WordBreakProperty.Other], - [/*start*/ 0xBD0, WordBreakProperty.ALetter], - [/*start*/ 0xBD1, WordBreakProperty.Other], - [/*start*/ 0xBD7, WordBreakProperty.Extend], - [/*start*/ 0xBD8, WordBreakProperty.Other], - [/*start*/ 0xBE6, WordBreakProperty.Numeric], - [/*start*/ 0xBF0, WordBreakProperty.Other], - [/*start*/ 0xC00, WordBreakProperty.Extend], - [/*start*/ 0xC05, WordBreakProperty.ALetter], - [/*start*/ 0xC0D, WordBreakProperty.Other], - [/*start*/ 0xC0E, WordBreakProperty.ALetter], - [/*start*/ 0xC11, WordBreakProperty.Other], - [/*start*/ 0xC12, WordBreakProperty.ALetter], - [/*start*/ 0xC29, WordBreakProperty.Other], - [/*start*/ 0xC2A, WordBreakProperty.ALetter], - [/*start*/ 0xC3A, WordBreakProperty.Other], - [/*start*/ 0xC3C, WordBreakProperty.Extend], - [/*start*/ 0xC3D, WordBreakProperty.ALetter], - [/*start*/ 0xC3E, WordBreakProperty.Extend], - [/*start*/ 0xC45, WordBreakProperty.Other], - [/*start*/ 0xC46, WordBreakProperty.Extend], - [/*start*/ 0xC49, WordBreakProperty.Other], - [/*start*/ 0xC4A, WordBreakProperty.Extend], - [/*start*/ 0xC4E, WordBreakProperty.Other], - [/*start*/ 0xC55, WordBreakProperty.Extend], - [/*start*/ 0xC57, WordBreakProperty.Other], - [/*start*/ 0xC58, WordBreakProperty.ALetter], - [/*start*/ 0xC5B, WordBreakProperty.Other], - [/*start*/ 0xC5D, WordBreakProperty.ALetter], - [/*start*/ 0xC5E, WordBreakProperty.Other], - [/*start*/ 0xC60, WordBreakProperty.ALetter], - [/*start*/ 0xC62, WordBreakProperty.Extend], - [/*start*/ 0xC64, WordBreakProperty.Other], - [/*start*/ 0xC66, WordBreakProperty.Numeric], - [/*start*/ 0xC70, WordBreakProperty.Other], - [/*start*/ 0xC80, WordBreakProperty.ALetter], - [/*start*/ 0xC81, WordBreakProperty.Extend], - [/*start*/ 0xC84, WordBreakProperty.Other], - [/*start*/ 0xC85, WordBreakProperty.ALetter], - [/*start*/ 0xC8D, WordBreakProperty.Other], - [/*start*/ 0xC8E, WordBreakProperty.ALetter], - [/*start*/ 0xC91, WordBreakProperty.Other], - [/*start*/ 0xC92, WordBreakProperty.ALetter], - [/*start*/ 0xCA9, WordBreakProperty.Other], - [/*start*/ 0xCAA, WordBreakProperty.ALetter], - [/*start*/ 0xCB4, WordBreakProperty.Other], - [/*start*/ 0xCB5, WordBreakProperty.ALetter], - [/*start*/ 0xCBA, WordBreakProperty.Other], - [/*start*/ 0xCBC, WordBreakProperty.Extend], - [/*start*/ 0xCBD, WordBreakProperty.ALetter], - [/*start*/ 0xCBE, WordBreakProperty.Extend], - [/*start*/ 0xCC5, WordBreakProperty.Other], - [/*start*/ 0xCC6, WordBreakProperty.Extend], - [/*start*/ 0xCC9, WordBreakProperty.Other], - [/*start*/ 0xCCA, WordBreakProperty.Extend], - [/*start*/ 0xCCE, WordBreakProperty.Other], - [/*start*/ 0xCD5, WordBreakProperty.Extend], - [/*start*/ 0xCD7, WordBreakProperty.Other], - [/*start*/ 0xCDD, WordBreakProperty.ALetter], - [/*start*/ 0xCDF, WordBreakProperty.Other], - [/*start*/ 0xCE0, WordBreakProperty.ALetter], - [/*start*/ 0xCE2, WordBreakProperty.Extend], - [/*start*/ 0xCE4, WordBreakProperty.Other], - [/*start*/ 0xCE6, WordBreakProperty.Numeric], - [/*start*/ 0xCF0, WordBreakProperty.Other], - [/*start*/ 0xCF1, WordBreakProperty.ALetter], - [/*start*/ 0xCF3, WordBreakProperty.Extend], - [/*start*/ 0xCF4, WordBreakProperty.Other], - [/*start*/ 0xD00, WordBreakProperty.Extend], - [/*start*/ 0xD04, WordBreakProperty.ALetter], - [/*start*/ 0xD0D, WordBreakProperty.Other], - [/*start*/ 0xD0E, WordBreakProperty.ALetter], - [/*start*/ 0xD11, WordBreakProperty.Other], - [/*start*/ 0xD12, WordBreakProperty.ALetter], - [/*start*/ 0xD3B, WordBreakProperty.Extend], - [/*start*/ 0xD3D, WordBreakProperty.ALetter], - [/*start*/ 0xD3E, WordBreakProperty.Extend], - [/*start*/ 0xD45, WordBreakProperty.Other], - [/*start*/ 0xD46, WordBreakProperty.Extend], - [/*start*/ 0xD49, WordBreakProperty.Other], - [/*start*/ 0xD4A, WordBreakProperty.Extend], - [/*start*/ 0xD4E, WordBreakProperty.ALetter], - [/*start*/ 0xD4F, WordBreakProperty.Other], - [/*start*/ 0xD54, WordBreakProperty.ALetter], - [/*start*/ 0xD57, WordBreakProperty.Extend], - [/*start*/ 0xD58, WordBreakProperty.Other], - [/*start*/ 0xD5F, WordBreakProperty.ALetter], - [/*start*/ 0xD62, WordBreakProperty.Extend], - [/*start*/ 0xD64, WordBreakProperty.Other], - [/*start*/ 0xD66, WordBreakProperty.Numeric], - [/*start*/ 0xD70, WordBreakProperty.Other], - [/*start*/ 0xD7A, WordBreakProperty.ALetter], - [/*start*/ 0xD80, WordBreakProperty.Other], - [/*start*/ 0xD81, WordBreakProperty.Extend], - [/*start*/ 0xD84, WordBreakProperty.Other], - [/*start*/ 0xD85, WordBreakProperty.ALetter], - [/*start*/ 0xD97, WordBreakProperty.Other], - [/*start*/ 0xD9A, WordBreakProperty.ALetter], - [/*start*/ 0xDB2, WordBreakProperty.Other], - [/*start*/ 0xDB3, WordBreakProperty.ALetter], - [/*start*/ 0xDBC, WordBreakProperty.Other], - [/*start*/ 0xDBD, WordBreakProperty.ALetter], - [/*start*/ 0xDBE, WordBreakProperty.Other], - [/*start*/ 0xDC0, WordBreakProperty.ALetter], - [/*start*/ 0xDC7, WordBreakProperty.Other], - [/*start*/ 0xDCA, WordBreakProperty.Extend], - [/*start*/ 0xDCB, WordBreakProperty.Other], - [/*start*/ 0xDCF, WordBreakProperty.Extend], - [/*start*/ 0xDD5, WordBreakProperty.Other], - [/*start*/ 0xDD6, WordBreakProperty.Extend], - [/*start*/ 0xDD7, WordBreakProperty.Other], - [/*start*/ 0xDD8, WordBreakProperty.Extend], - [/*start*/ 0xDE0, WordBreakProperty.Other], - [/*start*/ 0xDE6, WordBreakProperty.Numeric], - [/*start*/ 0xDF0, WordBreakProperty.Other], - [/*start*/ 0xDF2, WordBreakProperty.Extend], - [/*start*/ 0xDF4, WordBreakProperty.Other], - [/*start*/ 0xE31, WordBreakProperty.Extend], - [/*start*/ 0xE32, WordBreakProperty.Other], - [/*start*/ 0xE34, WordBreakProperty.Extend], - [/*start*/ 0xE3B, WordBreakProperty.Other], - [/*start*/ 0xE47, WordBreakProperty.Extend], - [/*start*/ 0xE4F, WordBreakProperty.Other], - [/*start*/ 0xE50, WordBreakProperty.Numeric], - [/*start*/ 0xE5A, WordBreakProperty.Other], - [/*start*/ 0xEB1, WordBreakProperty.Extend], - [/*start*/ 0xEB2, WordBreakProperty.Other], - [/*start*/ 0xEB4, WordBreakProperty.Extend], - [/*start*/ 0xEBD, WordBreakProperty.Other], - [/*start*/ 0xEC8, WordBreakProperty.Extend], - [/*start*/ 0xECF, WordBreakProperty.Other], - [/*start*/ 0xED0, WordBreakProperty.Numeric], - [/*start*/ 0xEDA, WordBreakProperty.Other], - [/*start*/ 0xF00, WordBreakProperty.ALetter], - [/*start*/ 0xF01, WordBreakProperty.Other], - [/*start*/ 0xF18, WordBreakProperty.Extend], - [/*start*/ 0xF1A, WordBreakProperty.Other], - [/*start*/ 0xF20, WordBreakProperty.Numeric], - [/*start*/ 0xF2A, WordBreakProperty.Other], - [/*start*/ 0xF35, WordBreakProperty.Extend], - [/*start*/ 0xF36, WordBreakProperty.Other], - [/*start*/ 0xF37, WordBreakProperty.Extend], - [/*start*/ 0xF38, WordBreakProperty.Other], - [/*start*/ 0xF39, WordBreakProperty.Extend], - [/*start*/ 0xF3A, WordBreakProperty.Other], - [/*start*/ 0xF3E, WordBreakProperty.Extend], - [/*start*/ 0xF40, WordBreakProperty.ALetter], - [/*start*/ 0xF48, WordBreakProperty.Other], - [/*start*/ 0xF49, WordBreakProperty.ALetter], - [/*start*/ 0xF6D, WordBreakProperty.Other], - [/*start*/ 0xF71, WordBreakProperty.Extend], - [/*start*/ 0xF85, WordBreakProperty.Other], - [/*start*/ 0xF86, WordBreakProperty.Extend], - [/*start*/ 0xF88, WordBreakProperty.ALetter], - [/*start*/ 0xF8D, WordBreakProperty.Extend], - [/*start*/ 0xF98, WordBreakProperty.Other], - [/*start*/ 0xF99, WordBreakProperty.Extend], - [/*start*/ 0xFBD, WordBreakProperty.Other], - [/*start*/ 0xFC6, WordBreakProperty.Extend], - [/*start*/ 0xFC7, WordBreakProperty.Other], - [/*start*/ 0x102B, WordBreakProperty.Extend], - [/*start*/ 0x103F, WordBreakProperty.Other], - [/*start*/ 0x1040, WordBreakProperty.Numeric], - [/*start*/ 0x104A, WordBreakProperty.Other], - [/*start*/ 0x1056, WordBreakProperty.Extend], - [/*start*/ 0x105A, WordBreakProperty.Other], - [/*start*/ 0x105E, WordBreakProperty.Extend], - [/*start*/ 0x1061, WordBreakProperty.Other], - [/*start*/ 0x1062, WordBreakProperty.Extend], - [/*start*/ 0x1065, WordBreakProperty.Other], - [/*start*/ 0x1067, WordBreakProperty.Extend], - [/*start*/ 0x106E, WordBreakProperty.Other], - [/*start*/ 0x1071, WordBreakProperty.Extend], - [/*start*/ 0x1075, WordBreakProperty.Other], - [/*start*/ 0x1082, WordBreakProperty.Extend], - [/*start*/ 0x108E, WordBreakProperty.Other], - [/*start*/ 0x108F, WordBreakProperty.Extend], - [/*start*/ 0x1090, WordBreakProperty.Numeric], - [/*start*/ 0x109A, WordBreakProperty.Extend], - [/*start*/ 0x109E, WordBreakProperty.Other], - [/*start*/ 0x10A0, WordBreakProperty.ALetter], - [/*start*/ 0x10C6, WordBreakProperty.Other], - [/*start*/ 0x10C7, WordBreakProperty.ALetter], - [/*start*/ 0x10C8, WordBreakProperty.Other], - [/*start*/ 0x10CD, WordBreakProperty.ALetter], - [/*start*/ 0x10CE, WordBreakProperty.Other], - [/*start*/ 0x10D0, WordBreakProperty.ALetter], - [/*start*/ 0x10FB, WordBreakProperty.Other], - [/*start*/ 0x10FC, WordBreakProperty.ALetter], - [/*start*/ 0x1249, WordBreakProperty.Other], - [/*start*/ 0x124A, WordBreakProperty.ALetter], - [/*start*/ 0x124E, WordBreakProperty.Other], - [/*start*/ 0x1250, WordBreakProperty.ALetter], - [/*start*/ 0x1257, WordBreakProperty.Other], - [/*start*/ 0x1258, WordBreakProperty.ALetter], - [/*start*/ 0x1259, WordBreakProperty.Other], - [/*start*/ 0x125A, WordBreakProperty.ALetter], - [/*start*/ 0x125E, WordBreakProperty.Other], - [/*start*/ 0x1260, WordBreakProperty.ALetter], - [/*start*/ 0x1289, WordBreakProperty.Other], - [/*start*/ 0x128A, WordBreakProperty.ALetter], - [/*start*/ 0x128E, WordBreakProperty.Other], - [/*start*/ 0x1290, WordBreakProperty.ALetter], - [/*start*/ 0x12B1, WordBreakProperty.Other], - [/*start*/ 0x12B2, WordBreakProperty.ALetter], - [/*start*/ 0x12B6, WordBreakProperty.Other], - [/*start*/ 0x12B8, WordBreakProperty.ALetter], - [/*start*/ 0x12BF, WordBreakProperty.Other], - [/*start*/ 0x12C0, WordBreakProperty.ALetter], - [/*start*/ 0x12C1, WordBreakProperty.Other], - [/*start*/ 0x12C2, WordBreakProperty.ALetter], - [/*start*/ 0x12C6, WordBreakProperty.Other], - [/*start*/ 0x12C8, WordBreakProperty.ALetter], - [/*start*/ 0x12D7, WordBreakProperty.Other], - [/*start*/ 0x12D8, WordBreakProperty.ALetter], - [/*start*/ 0x1311, WordBreakProperty.Other], - [/*start*/ 0x1312, WordBreakProperty.ALetter], - [/*start*/ 0x1316, WordBreakProperty.Other], - [/*start*/ 0x1318, WordBreakProperty.ALetter], - [/*start*/ 0x135B, WordBreakProperty.Other], - [/*start*/ 0x135D, WordBreakProperty.Extend], - [/*start*/ 0x1360, WordBreakProperty.Other], - [/*start*/ 0x1380, WordBreakProperty.ALetter], - [/*start*/ 0x1390, WordBreakProperty.Other], - [/*start*/ 0x13A0, WordBreakProperty.ALetter], - [/*start*/ 0x13F6, WordBreakProperty.Other], - [/*start*/ 0x13F8, WordBreakProperty.ALetter], - [/*start*/ 0x13FE, WordBreakProperty.Other], - [/*start*/ 0x1401, WordBreakProperty.ALetter], - [/*start*/ 0x166D, WordBreakProperty.Other], - [/*start*/ 0x166F, WordBreakProperty.ALetter], - [/*start*/ 0x1680, WordBreakProperty.WSegSpace], - [/*start*/ 0x1681, WordBreakProperty.ALetter], - [/*start*/ 0x169B, WordBreakProperty.Other], - [/*start*/ 0x16A0, WordBreakProperty.ALetter], - [/*start*/ 0x16EB, WordBreakProperty.Other], - [/*start*/ 0x16EE, WordBreakProperty.ALetter], - [/*start*/ 0x16F9, WordBreakProperty.Other], - [/*start*/ 0x1700, WordBreakProperty.ALetter], - [/*start*/ 0x1712, WordBreakProperty.Extend], - [/*start*/ 0x1716, WordBreakProperty.Other], - [/*start*/ 0x171F, WordBreakProperty.ALetter], - [/*start*/ 0x1732, WordBreakProperty.Extend], - [/*start*/ 0x1735, WordBreakProperty.Other], - [/*start*/ 0x1740, WordBreakProperty.ALetter], - [/*start*/ 0x1752, WordBreakProperty.Extend], - [/*start*/ 0x1754, WordBreakProperty.Other], - [/*start*/ 0x1760, WordBreakProperty.ALetter], - [/*start*/ 0x176D, WordBreakProperty.Other], - [/*start*/ 0x176E, WordBreakProperty.ALetter], - [/*start*/ 0x1771, WordBreakProperty.Other], - [/*start*/ 0x1772, WordBreakProperty.Extend], - [/*start*/ 0x1774, WordBreakProperty.Other], - [/*start*/ 0x17B4, WordBreakProperty.Extend], - [/*start*/ 0x17D4, WordBreakProperty.Other], - [/*start*/ 0x17DD, WordBreakProperty.Extend], - [/*start*/ 0x17DE, WordBreakProperty.Other], - [/*start*/ 0x17E0, WordBreakProperty.Numeric], - [/*start*/ 0x17EA, WordBreakProperty.Other], - [/*start*/ 0x180B, WordBreakProperty.Extend], - [/*start*/ 0x180E, WordBreakProperty.Format], - [/*start*/ 0x180F, WordBreakProperty.Extend], - [/*start*/ 0x1810, WordBreakProperty.Numeric], - [/*start*/ 0x181A, WordBreakProperty.Other], - [/*start*/ 0x1820, WordBreakProperty.ALetter], - [/*start*/ 0x1879, WordBreakProperty.Other], - [/*start*/ 0x1880, WordBreakProperty.ALetter], - [/*start*/ 0x1885, WordBreakProperty.Extend], - [/*start*/ 0x1887, WordBreakProperty.ALetter], - [/*start*/ 0x18A9, WordBreakProperty.Extend], - [/*start*/ 0x18AA, WordBreakProperty.ALetter], - [/*start*/ 0x18AB, WordBreakProperty.Other], - [/*start*/ 0x18B0, WordBreakProperty.ALetter], - [/*start*/ 0x18F6, WordBreakProperty.Other], - [/*start*/ 0x1900, WordBreakProperty.ALetter], - [/*start*/ 0x191F, WordBreakProperty.Other], - [/*start*/ 0x1920, WordBreakProperty.Extend], - [/*start*/ 0x192C, WordBreakProperty.Other], - [/*start*/ 0x1930, WordBreakProperty.Extend], - [/*start*/ 0x193C, WordBreakProperty.Other], - [/*start*/ 0x1946, WordBreakProperty.Numeric], - [/*start*/ 0x1950, WordBreakProperty.Other], - [/*start*/ 0x19D0, WordBreakProperty.Numeric], - [/*start*/ 0x19DA, WordBreakProperty.Other], - [/*start*/ 0x1A00, WordBreakProperty.ALetter], - [/*start*/ 0x1A17, WordBreakProperty.Extend], - [/*start*/ 0x1A1C, WordBreakProperty.Other], - [/*start*/ 0x1A55, WordBreakProperty.Extend], - [/*start*/ 0x1A5F, WordBreakProperty.Other], - [/*start*/ 0x1A60, WordBreakProperty.Extend], - [/*start*/ 0x1A7D, WordBreakProperty.Other], - [/*start*/ 0x1A7F, WordBreakProperty.Extend], - [/*start*/ 0x1A80, WordBreakProperty.Numeric], - [/*start*/ 0x1A8A, WordBreakProperty.Other], - [/*start*/ 0x1A90, WordBreakProperty.Numeric], - [/*start*/ 0x1A9A, WordBreakProperty.Other], - [/*start*/ 0x1AB0, WordBreakProperty.Extend], - [/*start*/ 0x1ACF, WordBreakProperty.Other], - [/*start*/ 0x1B00, WordBreakProperty.Extend], - [/*start*/ 0x1B05, WordBreakProperty.ALetter], - [/*start*/ 0x1B34, WordBreakProperty.Extend], - [/*start*/ 0x1B45, WordBreakProperty.ALetter], - [/*start*/ 0x1B4D, WordBreakProperty.Other], - [/*start*/ 0x1B50, WordBreakProperty.Numeric], - [/*start*/ 0x1B5A, WordBreakProperty.Other], - [/*start*/ 0x1B6B, WordBreakProperty.Extend], - [/*start*/ 0x1B74, WordBreakProperty.Other], - [/*start*/ 0x1B80, WordBreakProperty.Extend], - [/*start*/ 0x1B83, WordBreakProperty.ALetter], - [/*start*/ 0x1BA1, WordBreakProperty.Extend], - [/*start*/ 0x1BAE, WordBreakProperty.ALetter], - [/*start*/ 0x1BB0, WordBreakProperty.Numeric], - [/*start*/ 0x1BBA, WordBreakProperty.ALetter], - [/*start*/ 0x1BE6, WordBreakProperty.Extend], - [/*start*/ 0x1BF4, WordBreakProperty.Other], - [/*start*/ 0x1C00, WordBreakProperty.ALetter], - [/*start*/ 0x1C24, WordBreakProperty.Extend], - [/*start*/ 0x1C38, WordBreakProperty.Other], - [/*start*/ 0x1C40, WordBreakProperty.Numeric], - [/*start*/ 0x1C4A, WordBreakProperty.Other], - [/*start*/ 0x1C4D, WordBreakProperty.ALetter], - [/*start*/ 0x1C50, WordBreakProperty.Numeric], - [/*start*/ 0x1C5A, WordBreakProperty.ALetter], - [/*start*/ 0x1C7E, WordBreakProperty.Other], - [/*start*/ 0x1C80, WordBreakProperty.ALetter], - [/*start*/ 0x1C89, WordBreakProperty.Other], - [/*start*/ 0x1C90, WordBreakProperty.ALetter], - [/*start*/ 0x1CBB, WordBreakProperty.Other], - [/*start*/ 0x1CBD, WordBreakProperty.ALetter], - [/*start*/ 0x1CC0, WordBreakProperty.Other], - [/*start*/ 0x1CD0, WordBreakProperty.Extend], - [/*start*/ 0x1CD3, WordBreakProperty.Other], - [/*start*/ 0x1CD4, WordBreakProperty.Extend], - [/*start*/ 0x1CE9, WordBreakProperty.ALetter], - [/*start*/ 0x1CED, WordBreakProperty.Extend], - [/*start*/ 0x1CEE, WordBreakProperty.ALetter], - [/*start*/ 0x1CF4, WordBreakProperty.Extend], - [/*start*/ 0x1CF5, WordBreakProperty.ALetter], - [/*start*/ 0x1CF7, WordBreakProperty.Extend], - [/*start*/ 0x1CFA, WordBreakProperty.ALetter], - [/*start*/ 0x1CFB, WordBreakProperty.Other], - [/*start*/ 0x1D00, WordBreakProperty.ALetter], - [/*start*/ 0x1DC0, WordBreakProperty.Extend], - [/*start*/ 0x1E00, WordBreakProperty.ALetter], - [/*start*/ 0x1F16, WordBreakProperty.Other], - [/*start*/ 0x1F18, WordBreakProperty.ALetter], - [/*start*/ 0x1F1E, WordBreakProperty.Other], - [/*start*/ 0x1F20, WordBreakProperty.ALetter], - [/*start*/ 0x1F46, WordBreakProperty.Other], - [/*start*/ 0x1F48, WordBreakProperty.ALetter], - [/*start*/ 0x1F4E, WordBreakProperty.Other], - [/*start*/ 0x1F50, WordBreakProperty.ALetter], - [/*start*/ 0x1F58, WordBreakProperty.Other], - [/*start*/ 0x1F59, WordBreakProperty.ALetter], - [/*start*/ 0x1F5A, WordBreakProperty.Other], - [/*start*/ 0x1F5B, WordBreakProperty.ALetter], - [/*start*/ 0x1F5C, WordBreakProperty.Other], - [/*start*/ 0x1F5D, WordBreakProperty.ALetter], - [/*start*/ 0x1F5E, WordBreakProperty.Other], - [/*start*/ 0x1F5F, WordBreakProperty.ALetter], - [/*start*/ 0x1F7E, WordBreakProperty.Other], - [/*start*/ 0x1F80, WordBreakProperty.ALetter], - [/*start*/ 0x1FB5, WordBreakProperty.Other], - [/*start*/ 0x1FB6, WordBreakProperty.ALetter], - [/*start*/ 0x1FBD, WordBreakProperty.Other], - [/*start*/ 0x1FBE, WordBreakProperty.ALetter], - [/*start*/ 0x1FBF, WordBreakProperty.Other], - [/*start*/ 0x1FC2, WordBreakProperty.ALetter], - [/*start*/ 0x1FC5, WordBreakProperty.Other], - [/*start*/ 0x1FC6, WordBreakProperty.ALetter], - [/*start*/ 0x1FCD, WordBreakProperty.Other], - [/*start*/ 0x1FD0, WordBreakProperty.ALetter], - [/*start*/ 0x1FD4, WordBreakProperty.Other], - [/*start*/ 0x1FD6, WordBreakProperty.ALetter], - [/*start*/ 0x1FDC, WordBreakProperty.Other], - [/*start*/ 0x1FE0, WordBreakProperty.ALetter], - [/*start*/ 0x1FED, WordBreakProperty.Other], - [/*start*/ 0x1FF2, WordBreakProperty.ALetter], - [/*start*/ 0x1FF5, WordBreakProperty.Other], - [/*start*/ 0x1FF6, WordBreakProperty.ALetter], - [/*start*/ 0x1FFD, WordBreakProperty.Other], - [/*start*/ 0x2000, WordBreakProperty.WSegSpace], - [/*start*/ 0x2007, WordBreakProperty.Other], - [/*start*/ 0x2008, WordBreakProperty.WSegSpace], - [/*start*/ 0x200B, WordBreakProperty.Other], - [/*start*/ 0x200C, WordBreakProperty.Extend], - [/*start*/ 0x200D, WordBreakProperty.ZWJ], - [/*start*/ 0x200E, WordBreakProperty.Format], - [/*start*/ 0x2010, WordBreakProperty.Other], - [/*start*/ 0x2018, WordBreakProperty.MidNumLet], - [/*start*/ 0x201A, WordBreakProperty.Other], - [/*start*/ 0x2024, WordBreakProperty.MidNumLet], - [/*start*/ 0x2025, WordBreakProperty.Other], - [/*start*/ 0x2027, WordBreakProperty.MidLetter], - [/*start*/ 0x2028, WordBreakProperty.Newline], - [/*start*/ 0x202A, WordBreakProperty.Format], - [/*start*/ 0x202F, WordBreakProperty.ExtendNumLet], - [/*start*/ 0x2030, WordBreakProperty.Other], - [/*start*/ 0x203F, WordBreakProperty.ExtendNumLet], - [/*start*/ 0x2041, WordBreakProperty.Other], - [/*start*/ 0x2044, WordBreakProperty.MidNum], - [/*start*/ 0x2045, WordBreakProperty.Other], - [/*start*/ 0x2054, WordBreakProperty.ExtendNumLet], - [/*start*/ 0x2055, WordBreakProperty.Other], - [/*start*/ 0x205F, WordBreakProperty.WSegSpace], - [/*start*/ 0x2060, WordBreakProperty.Format], - [/*start*/ 0x2065, WordBreakProperty.Other], - [/*start*/ 0x2066, WordBreakProperty.Format], - [/*start*/ 0x2070, WordBreakProperty.Other], - [/*start*/ 0x2071, WordBreakProperty.ALetter], - [/*start*/ 0x2072, WordBreakProperty.Other], - [/*start*/ 0x207F, WordBreakProperty.ALetter], - [/*start*/ 0x2080, WordBreakProperty.Other], - [/*start*/ 0x2090, WordBreakProperty.ALetter], - [/*start*/ 0x209D, WordBreakProperty.Other], - [/*start*/ 0x20D0, WordBreakProperty.Extend], - [/*start*/ 0x20F1, WordBreakProperty.Other], - [/*start*/ 0x2102, WordBreakProperty.ALetter], - [/*start*/ 0x2103, WordBreakProperty.Other], - [/*start*/ 0x2107, WordBreakProperty.ALetter], - [/*start*/ 0x2108, WordBreakProperty.Other], - [/*start*/ 0x210A, WordBreakProperty.ALetter], - [/*start*/ 0x2114, WordBreakProperty.Other], - [/*start*/ 0x2115, WordBreakProperty.ALetter], - [/*start*/ 0x2116, WordBreakProperty.Other], - [/*start*/ 0x2119, WordBreakProperty.ALetter], - [/*start*/ 0x211E, WordBreakProperty.Other], - [/*start*/ 0x2124, WordBreakProperty.ALetter], - [/*start*/ 0x2125, WordBreakProperty.Other], - [/*start*/ 0x2126, WordBreakProperty.ALetter], - [/*start*/ 0x2127, WordBreakProperty.Other], - [/*start*/ 0x2128, WordBreakProperty.ALetter], - [/*start*/ 0x2129, WordBreakProperty.Other], - [/*start*/ 0x212A, WordBreakProperty.ALetter], - [/*start*/ 0x212E, WordBreakProperty.Other], - [/*start*/ 0x212F, WordBreakProperty.ALetter], - [/*start*/ 0x213A, WordBreakProperty.Other], - [/*start*/ 0x213C, WordBreakProperty.ALetter], - [/*start*/ 0x2140, WordBreakProperty.Other], - [/*start*/ 0x2145, WordBreakProperty.ALetter], - [/*start*/ 0x214A, WordBreakProperty.Other], - [/*start*/ 0x214E, WordBreakProperty.ALetter], - [/*start*/ 0x214F, WordBreakProperty.Other], - [/*start*/ 0x2160, WordBreakProperty.ALetter], - [/*start*/ 0x2189, WordBreakProperty.Other], - [/*start*/ 0x24B6, WordBreakProperty.ALetter], - [/*start*/ 0x24EA, WordBreakProperty.Other], - [/*start*/ 0x2C00, WordBreakProperty.ALetter], - [/*start*/ 0x2CE5, WordBreakProperty.Other], - [/*start*/ 0x2CEB, WordBreakProperty.ALetter], - [/*start*/ 0x2CEF, WordBreakProperty.Extend], - [/*start*/ 0x2CF2, WordBreakProperty.ALetter], - [/*start*/ 0x2CF4, WordBreakProperty.Other], - [/*start*/ 0x2D00, WordBreakProperty.ALetter], - [/*start*/ 0x2D26, WordBreakProperty.Other], - [/*start*/ 0x2D27, WordBreakProperty.ALetter], - [/*start*/ 0x2D28, WordBreakProperty.Other], - [/*start*/ 0x2D2D, WordBreakProperty.ALetter], - [/*start*/ 0x2D2E, WordBreakProperty.Other], - [/*start*/ 0x2D30, WordBreakProperty.ALetter], - [/*start*/ 0x2D68, WordBreakProperty.Other], - [/*start*/ 0x2D6F, WordBreakProperty.ALetter], - [/*start*/ 0x2D70, WordBreakProperty.Other], - [/*start*/ 0x2D7F, WordBreakProperty.Extend], - [/*start*/ 0x2D80, WordBreakProperty.ALetter], - [/*start*/ 0x2D97, WordBreakProperty.Other], - [/*start*/ 0x2DA0, WordBreakProperty.ALetter], - [/*start*/ 0x2DA7, WordBreakProperty.Other], - [/*start*/ 0x2DA8, WordBreakProperty.ALetter], - [/*start*/ 0x2DAF, WordBreakProperty.Other], - [/*start*/ 0x2DB0, WordBreakProperty.ALetter], - [/*start*/ 0x2DB7, WordBreakProperty.Other], - [/*start*/ 0x2DB8, WordBreakProperty.ALetter], - [/*start*/ 0x2DBF, WordBreakProperty.Other], - [/*start*/ 0x2DC0, WordBreakProperty.ALetter], - [/*start*/ 0x2DC7, WordBreakProperty.Other], - [/*start*/ 0x2DC8, WordBreakProperty.ALetter], - [/*start*/ 0x2DCF, WordBreakProperty.Other], - [/*start*/ 0x2DD0, WordBreakProperty.ALetter], - [/*start*/ 0x2DD7, WordBreakProperty.Other], - [/*start*/ 0x2DD8, WordBreakProperty.ALetter], - [/*start*/ 0x2DDF, WordBreakProperty.Other], - [/*start*/ 0x2DE0, WordBreakProperty.Extend], - [/*start*/ 0x2E00, WordBreakProperty.Other], - [/*start*/ 0x2E2F, WordBreakProperty.ALetter], - [/*start*/ 0x2E30, WordBreakProperty.Other], - [/*start*/ 0x3000, WordBreakProperty.WSegSpace], - [/*start*/ 0x3001, WordBreakProperty.Other], - [/*start*/ 0x3005, WordBreakProperty.ALetter], - [/*start*/ 0x3006, WordBreakProperty.Other], - [/*start*/ 0x302A, WordBreakProperty.Extend], - [/*start*/ 0x3030, WordBreakProperty.Other], - [/*start*/ 0x3031, WordBreakProperty.Katakana], - [/*start*/ 0x3036, WordBreakProperty.Other], - [/*start*/ 0x303B, WordBreakProperty.ALetter], - [/*start*/ 0x303D, WordBreakProperty.Other], - [/*start*/ 0x3099, WordBreakProperty.Extend], - [/*start*/ 0x309B, WordBreakProperty.Katakana], - [/*start*/ 0x309D, WordBreakProperty.Other], - [/*start*/ 0x30A0, WordBreakProperty.Katakana], - [/*start*/ 0x30FB, WordBreakProperty.Other], - [/*start*/ 0x30FC, WordBreakProperty.Katakana], - [/*start*/ 0x3100, WordBreakProperty.Other], - [/*start*/ 0x3105, WordBreakProperty.ALetter], - [/*start*/ 0x3130, WordBreakProperty.Other], - [/*start*/ 0x3131, WordBreakProperty.ALetter], - [/*start*/ 0x318F, WordBreakProperty.Other], - [/*start*/ 0x31A0, WordBreakProperty.ALetter], - [/*start*/ 0x31C0, WordBreakProperty.Other], - [/*start*/ 0x31F0, WordBreakProperty.Katakana], - [/*start*/ 0x3200, WordBreakProperty.Other], - [/*start*/ 0x32D0, WordBreakProperty.Katakana], - [/*start*/ 0x32FF, WordBreakProperty.Other], - [/*start*/ 0x3300, WordBreakProperty.Katakana], - [/*start*/ 0x3358, WordBreakProperty.Other], - [/*start*/ 0xA000, WordBreakProperty.ALetter], - [/*start*/ 0xA48D, WordBreakProperty.Other], - [/*start*/ 0xA4D0, WordBreakProperty.ALetter], - [/*start*/ 0xA4FE, WordBreakProperty.Other], - [/*start*/ 0xA500, WordBreakProperty.ALetter], - [/*start*/ 0xA60D, WordBreakProperty.Other], - [/*start*/ 0xA610, WordBreakProperty.ALetter], - [/*start*/ 0xA620, WordBreakProperty.Numeric], - [/*start*/ 0xA62A, WordBreakProperty.ALetter], - [/*start*/ 0xA62C, WordBreakProperty.Other], - [/*start*/ 0xA640, WordBreakProperty.ALetter], - [/*start*/ 0xA66F, WordBreakProperty.Extend], - [/*start*/ 0xA673, WordBreakProperty.Other], - [/*start*/ 0xA674, WordBreakProperty.Extend], - [/*start*/ 0xA67E, WordBreakProperty.Other], - [/*start*/ 0xA67F, WordBreakProperty.ALetter], - [/*start*/ 0xA69E, WordBreakProperty.Extend], - [/*start*/ 0xA6A0, WordBreakProperty.ALetter], - [/*start*/ 0xA6F0, WordBreakProperty.Extend], - [/*start*/ 0xA6F2, WordBreakProperty.Other], - [/*start*/ 0xA708, WordBreakProperty.ALetter], - [/*start*/ 0xA7CB, WordBreakProperty.Other], - [/*start*/ 0xA7D0, WordBreakProperty.ALetter], - [/*start*/ 0xA7D2, WordBreakProperty.Other], - [/*start*/ 0xA7D3, WordBreakProperty.ALetter], - [/*start*/ 0xA7D4, WordBreakProperty.Other], - [/*start*/ 0xA7D5, WordBreakProperty.ALetter], - [/*start*/ 0xA7DA, WordBreakProperty.Other], - [/*start*/ 0xA7F2, WordBreakProperty.ALetter], - [/*start*/ 0xA802, WordBreakProperty.Extend], - [/*start*/ 0xA803, WordBreakProperty.ALetter], - [/*start*/ 0xA806, WordBreakProperty.Extend], - [/*start*/ 0xA807, WordBreakProperty.ALetter], - [/*start*/ 0xA80B, WordBreakProperty.Extend], - [/*start*/ 0xA80C, WordBreakProperty.ALetter], - [/*start*/ 0xA823, WordBreakProperty.Extend], - [/*start*/ 0xA828, WordBreakProperty.Other], - [/*start*/ 0xA82C, WordBreakProperty.Extend], - [/*start*/ 0xA82D, WordBreakProperty.Other], - [/*start*/ 0xA840, WordBreakProperty.ALetter], - [/*start*/ 0xA874, WordBreakProperty.Other], - [/*start*/ 0xA880, WordBreakProperty.Extend], - [/*start*/ 0xA882, WordBreakProperty.ALetter], - [/*start*/ 0xA8B4, WordBreakProperty.Extend], - [/*start*/ 0xA8C6, WordBreakProperty.Other], - [/*start*/ 0xA8D0, WordBreakProperty.Numeric], - [/*start*/ 0xA8DA, WordBreakProperty.Other], - [/*start*/ 0xA8E0, WordBreakProperty.Extend], - [/*start*/ 0xA8F2, WordBreakProperty.ALetter], - [/*start*/ 0xA8F8, WordBreakProperty.Other], - [/*start*/ 0xA8FB, WordBreakProperty.ALetter], - [/*start*/ 0xA8FC, WordBreakProperty.Other], - [/*start*/ 0xA8FD, WordBreakProperty.ALetter], - [/*start*/ 0xA8FF, WordBreakProperty.Extend], - [/*start*/ 0xA900, WordBreakProperty.Numeric], - [/*start*/ 0xA90A, WordBreakProperty.ALetter], - [/*start*/ 0xA926, WordBreakProperty.Extend], - [/*start*/ 0xA92E, WordBreakProperty.Other], - [/*start*/ 0xA930, WordBreakProperty.ALetter], - [/*start*/ 0xA947, WordBreakProperty.Extend], - [/*start*/ 0xA954, WordBreakProperty.Other], - [/*start*/ 0xA960, WordBreakProperty.ALetter], - [/*start*/ 0xA97D, WordBreakProperty.Other], - [/*start*/ 0xA980, WordBreakProperty.Extend], - [/*start*/ 0xA984, WordBreakProperty.ALetter], - [/*start*/ 0xA9B3, WordBreakProperty.Extend], - [/*start*/ 0xA9C1, WordBreakProperty.Other], - [/*start*/ 0xA9CF, WordBreakProperty.ALetter], - [/*start*/ 0xA9D0, WordBreakProperty.Numeric], - [/*start*/ 0xA9DA, WordBreakProperty.Other], - [/*start*/ 0xA9E5, WordBreakProperty.Extend], - [/*start*/ 0xA9E6, WordBreakProperty.Other], - [/*start*/ 0xA9F0, WordBreakProperty.Numeric], - [/*start*/ 0xA9FA, WordBreakProperty.Other], - [/*start*/ 0xAA00, WordBreakProperty.ALetter], - [/*start*/ 0xAA29, WordBreakProperty.Extend], - [/*start*/ 0xAA37, WordBreakProperty.Other], - [/*start*/ 0xAA40, WordBreakProperty.ALetter], - [/*start*/ 0xAA43, WordBreakProperty.Extend], - [/*start*/ 0xAA44, WordBreakProperty.ALetter], - [/*start*/ 0xAA4C, WordBreakProperty.Extend], - [/*start*/ 0xAA4E, WordBreakProperty.Other], - [/*start*/ 0xAA50, WordBreakProperty.Numeric], - [/*start*/ 0xAA5A, WordBreakProperty.Other], - [/*start*/ 0xAA7B, WordBreakProperty.Extend], - [/*start*/ 0xAA7E, WordBreakProperty.Other], - [/*start*/ 0xAAB0, WordBreakProperty.Extend], - [/*start*/ 0xAAB1, WordBreakProperty.Other], - [/*start*/ 0xAAB2, WordBreakProperty.Extend], - [/*start*/ 0xAAB5, WordBreakProperty.Other], - [/*start*/ 0xAAB7, WordBreakProperty.Extend], - [/*start*/ 0xAAB9, WordBreakProperty.Other], - [/*start*/ 0xAABE, WordBreakProperty.Extend], - [/*start*/ 0xAAC0, WordBreakProperty.Other], - [/*start*/ 0xAAC1, WordBreakProperty.Extend], - [/*start*/ 0xAAC2, WordBreakProperty.Other], - [/*start*/ 0xAAE0, WordBreakProperty.ALetter], - [/*start*/ 0xAAEB, WordBreakProperty.Extend], - [/*start*/ 0xAAF0, WordBreakProperty.Other], - [/*start*/ 0xAAF2, WordBreakProperty.ALetter], - [/*start*/ 0xAAF5, WordBreakProperty.Extend], - [/*start*/ 0xAAF7, WordBreakProperty.Other], - [/*start*/ 0xAB01, WordBreakProperty.ALetter], - [/*start*/ 0xAB07, WordBreakProperty.Other], - [/*start*/ 0xAB09, WordBreakProperty.ALetter], - [/*start*/ 0xAB0F, WordBreakProperty.Other], - [/*start*/ 0xAB11, WordBreakProperty.ALetter], - [/*start*/ 0xAB17, WordBreakProperty.Other], - [/*start*/ 0xAB20, WordBreakProperty.ALetter], - [/*start*/ 0xAB27, WordBreakProperty.Other], - [/*start*/ 0xAB28, WordBreakProperty.ALetter], - [/*start*/ 0xAB2F, WordBreakProperty.Other], - [/*start*/ 0xAB30, WordBreakProperty.ALetter], - [/*start*/ 0xAB6A, WordBreakProperty.Other], - [/*start*/ 0xAB70, WordBreakProperty.ALetter], - [/*start*/ 0xABE3, WordBreakProperty.Extend], - [/*start*/ 0xABEB, WordBreakProperty.Other], - [/*start*/ 0xABEC, WordBreakProperty.Extend], - [/*start*/ 0xABEE, WordBreakProperty.Other], - [/*start*/ 0xABF0, WordBreakProperty.Numeric], - [/*start*/ 0xABFA, WordBreakProperty.Other], - [/*start*/ 0xAC00, WordBreakProperty.ALetter], - [/*start*/ 0xD7A4, WordBreakProperty.Other], - [/*start*/ 0xD7B0, WordBreakProperty.ALetter], - [/*start*/ 0xD7C7, WordBreakProperty.Other], - [/*start*/ 0xD7CB, WordBreakProperty.ALetter], - [/*start*/ 0xD7FC, WordBreakProperty.Other], - [/*start*/ 0xFB00, WordBreakProperty.ALetter], - [/*start*/ 0xFB07, WordBreakProperty.Other], - [/*start*/ 0xFB13, WordBreakProperty.ALetter], - [/*start*/ 0xFB18, WordBreakProperty.Other], - [/*start*/ 0xFB1D, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB1E, WordBreakProperty.Extend], - [/*start*/ 0xFB1F, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB29, WordBreakProperty.Other], - [/*start*/ 0xFB2A, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB37, WordBreakProperty.Other], - [/*start*/ 0xFB38, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB3D, WordBreakProperty.Other], - [/*start*/ 0xFB3E, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB3F, WordBreakProperty.Other], - [/*start*/ 0xFB40, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB42, WordBreakProperty.Other], - [/*start*/ 0xFB43, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB45, WordBreakProperty.Other], - [/*start*/ 0xFB46, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB50, WordBreakProperty.ALetter], - [/*start*/ 0xFBB2, WordBreakProperty.Other], - [/*start*/ 0xFBD3, WordBreakProperty.ALetter], - [/*start*/ 0xFD3E, WordBreakProperty.Other], - [/*start*/ 0xFD50, WordBreakProperty.ALetter], - [/*start*/ 0xFD90, WordBreakProperty.Other], - [/*start*/ 0xFD92, WordBreakProperty.ALetter], - [/*start*/ 0xFDC8, WordBreakProperty.Other], - [/*start*/ 0xFDF0, WordBreakProperty.ALetter], - [/*start*/ 0xFDFC, WordBreakProperty.Other], - [/*start*/ 0xFE00, WordBreakProperty.Extend], - [/*start*/ 0xFE10, WordBreakProperty.MidNum], - [/*start*/ 0xFE11, WordBreakProperty.Other], - [/*start*/ 0xFE13, WordBreakProperty.MidLetter], - [/*start*/ 0xFE14, WordBreakProperty.MidNum], - [/*start*/ 0xFE15, WordBreakProperty.Other], - [/*start*/ 0xFE20, WordBreakProperty.Extend], - [/*start*/ 0xFE30, WordBreakProperty.Other], - [/*start*/ 0xFE33, WordBreakProperty.ExtendNumLet], - [/*start*/ 0xFE35, WordBreakProperty.Other], - [/*start*/ 0xFE4D, WordBreakProperty.ExtendNumLet], - [/*start*/ 0xFE50, WordBreakProperty.MidNum], - [/*start*/ 0xFE51, WordBreakProperty.Other], - [/*start*/ 0xFE52, WordBreakProperty.MidNumLet], - [/*start*/ 0xFE53, WordBreakProperty.Other], - [/*start*/ 0xFE54, WordBreakProperty.MidNum], - [/*start*/ 0xFE55, WordBreakProperty.MidLetter], - [/*start*/ 0xFE56, WordBreakProperty.Other], - [/*start*/ 0xFE70, WordBreakProperty.ALetter], - [/*start*/ 0xFE75, WordBreakProperty.Other], - [/*start*/ 0xFE76, WordBreakProperty.ALetter], - [/*start*/ 0xFEFD, WordBreakProperty.Other], - [/*start*/ 0xFEFF, WordBreakProperty.Format], - [/*start*/ 0xFF00, WordBreakProperty.Other], - [/*start*/ 0xFF07, WordBreakProperty.MidNumLet], - [/*start*/ 0xFF08, WordBreakProperty.Other], - [/*start*/ 0xFF0C, WordBreakProperty.MidNum], - [/*start*/ 0xFF0D, WordBreakProperty.Other], - [/*start*/ 0xFF0E, WordBreakProperty.MidNumLet], - [/*start*/ 0xFF0F, WordBreakProperty.Other], - [/*start*/ 0xFF10, WordBreakProperty.Numeric], - [/*start*/ 0xFF1A, WordBreakProperty.MidLetter], - [/*start*/ 0xFF1B, WordBreakProperty.MidNum], - [/*start*/ 0xFF1C, WordBreakProperty.Other], - [/*start*/ 0xFF21, WordBreakProperty.ALetter], - [/*start*/ 0xFF3B, WordBreakProperty.Other], - [/*start*/ 0xFF3F, WordBreakProperty.ExtendNumLet], - [/*start*/ 0xFF40, WordBreakProperty.Other], - [/*start*/ 0xFF41, WordBreakProperty.ALetter], - [/*start*/ 0xFF5B, WordBreakProperty.Other], - [/*start*/ 0xFF66, WordBreakProperty.Katakana], - [/*start*/ 0xFF9E, WordBreakProperty.Extend], - [/*start*/ 0xFFA0, WordBreakProperty.ALetter], - [/*start*/ 0xFFBF, WordBreakProperty.Other], - [/*start*/ 0xFFC2, WordBreakProperty.ALetter], - [/*start*/ 0xFFC8, WordBreakProperty.Other], - [/*start*/ 0xFFCA, WordBreakProperty.ALetter], - [/*start*/ 0xFFD0, WordBreakProperty.Other], - [/*start*/ 0xFFD2, WordBreakProperty.ALetter], - [/*start*/ 0xFFD8, WordBreakProperty.Other], - [/*start*/ 0xFFDA, WordBreakProperty.ALetter], - [/*start*/ 0xFFDD, WordBreakProperty.Other], - [/*start*/ 0xFFF9, WordBreakProperty.Format], - [/*start*/ 0xFFFC, WordBreakProperty.Other], - [/*start*/ 0x10000, WordBreakProperty.ALetter], - [/*start*/ 0x1000C, WordBreakProperty.Other], - [/*start*/ 0x1000D, WordBreakProperty.ALetter], - [/*start*/ 0x10027, WordBreakProperty.Other], - [/*start*/ 0x10028, WordBreakProperty.ALetter], - [/*start*/ 0x1003B, WordBreakProperty.Other], - [/*start*/ 0x1003C, WordBreakProperty.ALetter], - [/*start*/ 0x1003E, WordBreakProperty.Other], - [/*start*/ 0x1003F, WordBreakProperty.ALetter], - [/*start*/ 0x1004E, WordBreakProperty.Other], - [/*start*/ 0x10050, WordBreakProperty.ALetter], - [/*start*/ 0x1005E, WordBreakProperty.Other], - [/*start*/ 0x10080, WordBreakProperty.ALetter], - [/*start*/ 0x100FB, WordBreakProperty.Other], - [/*start*/ 0x10140, WordBreakProperty.ALetter], - [/*start*/ 0x10175, WordBreakProperty.Other], - [/*start*/ 0x101FD, WordBreakProperty.Extend], - [/*start*/ 0x101FE, WordBreakProperty.Other], - [/*start*/ 0x10280, WordBreakProperty.ALetter], - [/*start*/ 0x1029D, WordBreakProperty.Other], - [/*start*/ 0x102A0, WordBreakProperty.ALetter], - [/*start*/ 0x102D1, WordBreakProperty.Other], - [/*start*/ 0x102E0, WordBreakProperty.Extend], - [/*start*/ 0x102E1, WordBreakProperty.Other], - [/*start*/ 0x10300, WordBreakProperty.ALetter], - [/*start*/ 0x10320, WordBreakProperty.Other], - [/*start*/ 0x1032D, WordBreakProperty.ALetter], - [/*start*/ 0x1034B, WordBreakProperty.Other], - [/*start*/ 0x10350, WordBreakProperty.ALetter], - [/*start*/ 0x10376, WordBreakProperty.Extend], - [/*start*/ 0x1037B, WordBreakProperty.Other], - [/*start*/ 0x10380, WordBreakProperty.ALetter], - [/*start*/ 0x1039E, WordBreakProperty.Other], - [/*start*/ 0x103A0, WordBreakProperty.ALetter], - [/*start*/ 0x103C4, WordBreakProperty.Other], - [/*start*/ 0x103C8, WordBreakProperty.ALetter], - [/*start*/ 0x103D0, WordBreakProperty.Other], - [/*start*/ 0x103D1, WordBreakProperty.ALetter], - [/*start*/ 0x103D6, WordBreakProperty.Other], - [/*start*/ 0x10400, WordBreakProperty.ALetter], - [/*start*/ 0x1049E, WordBreakProperty.Other], - [/*start*/ 0x104A0, WordBreakProperty.Numeric], - [/*start*/ 0x104AA, WordBreakProperty.Other], - [/*start*/ 0x104B0, WordBreakProperty.ALetter], - [/*start*/ 0x104D4, WordBreakProperty.Other], - [/*start*/ 0x104D8, WordBreakProperty.ALetter], - [/*start*/ 0x104FC, WordBreakProperty.Other], - [/*start*/ 0x10500, WordBreakProperty.ALetter], - [/*start*/ 0x10528, WordBreakProperty.Other], - [/*start*/ 0x10530, WordBreakProperty.ALetter], - [/*start*/ 0x10564, WordBreakProperty.Other], - [/*start*/ 0x10570, WordBreakProperty.ALetter], - [/*start*/ 0x1057B, WordBreakProperty.Other], - [/*start*/ 0x1057C, WordBreakProperty.ALetter], - [/*start*/ 0x1058B, WordBreakProperty.Other], - [/*start*/ 0x1058C, WordBreakProperty.ALetter], - [/*start*/ 0x10593, WordBreakProperty.Other], - [/*start*/ 0x10594, WordBreakProperty.ALetter], - [/*start*/ 0x10596, WordBreakProperty.Other], - [/*start*/ 0x10597, WordBreakProperty.ALetter], - [/*start*/ 0x105A2, WordBreakProperty.Other], - [/*start*/ 0x105A3, WordBreakProperty.ALetter], - [/*start*/ 0x105B2, WordBreakProperty.Other], - [/*start*/ 0x105B3, WordBreakProperty.ALetter], - [/*start*/ 0x105BA, WordBreakProperty.Other], - [/*start*/ 0x105BB, WordBreakProperty.ALetter], - [/*start*/ 0x105BD, WordBreakProperty.Other], - [/*start*/ 0x10600, WordBreakProperty.ALetter], - [/*start*/ 0x10737, WordBreakProperty.Other], - [/*start*/ 0x10740, WordBreakProperty.ALetter], - [/*start*/ 0x10756, WordBreakProperty.Other], - [/*start*/ 0x10760, WordBreakProperty.ALetter], - [/*start*/ 0x10768, WordBreakProperty.Other], - [/*start*/ 0x10780, WordBreakProperty.ALetter], - [/*start*/ 0x10786, WordBreakProperty.Other], - [/*start*/ 0x10787, WordBreakProperty.ALetter], - [/*start*/ 0x107B1, WordBreakProperty.Other], - [/*start*/ 0x107B2, WordBreakProperty.ALetter], - [/*start*/ 0x107BB, WordBreakProperty.Other], - [/*start*/ 0x10800, WordBreakProperty.ALetter], - [/*start*/ 0x10806, WordBreakProperty.Other], - [/*start*/ 0x10808, WordBreakProperty.ALetter], - [/*start*/ 0x10809, WordBreakProperty.Other], - [/*start*/ 0x1080A, WordBreakProperty.ALetter], - [/*start*/ 0x10836, WordBreakProperty.Other], - [/*start*/ 0x10837, WordBreakProperty.ALetter], - [/*start*/ 0x10839, WordBreakProperty.Other], - [/*start*/ 0x1083C, WordBreakProperty.ALetter], - [/*start*/ 0x1083D, WordBreakProperty.Other], - [/*start*/ 0x1083F, WordBreakProperty.ALetter], - [/*start*/ 0x10856, WordBreakProperty.Other], - [/*start*/ 0x10860, WordBreakProperty.ALetter], - [/*start*/ 0x10877, WordBreakProperty.Other], - [/*start*/ 0x10880, WordBreakProperty.ALetter], - [/*start*/ 0x1089F, WordBreakProperty.Other], - [/*start*/ 0x108E0, WordBreakProperty.ALetter], - [/*start*/ 0x108F3, WordBreakProperty.Other], - [/*start*/ 0x108F4, WordBreakProperty.ALetter], - [/*start*/ 0x108F6, WordBreakProperty.Other], - [/*start*/ 0x10900, WordBreakProperty.ALetter], - [/*start*/ 0x10916, WordBreakProperty.Other], - [/*start*/ 0x10920, WordBreakProperty.ALetter], - [/*start*/ 0x1093A, WordBreakProperty.Other], - [/*start*/ 0x10980, WordBreakProperty.ALetter], - [/*start*/ 0x109B8, WordBreakProperty.Other], - [/*start*/ 0x109BE, WordBreakProperty.ALetter], - [/*start*/ 0x109C0, WordBreakProperty.Other], - [/*start*/ 0x10A00, WordBreakProperty.ALetter], - [/*start*/ 0x10A01, WordBreakProperty.Extend], - [/*start*/ 0x10A04, WordBreakProperty.Other], - [/*start*/ 0x10A05, WordBreakProperty.Extend], - [/*start*/ 0x10A07, WordBreakProperty.Other], - [/*start*/ 0x10A0C, WordBreakProperty.Extend], - [/*start*/ 0x10A10, WordBreakProperty.ALetter], - [/*start*/ 0x10A14, WordBreakProperty.Other], - [/*start*/ 0x10A15, WordBreakProperty.ALetter], - [/*start*/ 0x10A18, WordBreakProperty.Other], - [/*start*/ 0x10A19, WordBreakProperty.ALetter], - [/*start*/ 0x10A36, WordBreakProperty.Other], - [/*start*/ 0x10A38, WordBreakProperty.Extend], - [/*start*/ 0x10A3B, WordBreakProperty.Other], - [/*start*/ 0x10A3F, WordBreakProperty.Extend], - [/*start*/ 0x10A40, WordBreakProperty.Other], - [/*start*/ 0x10A60, WordBreakProperty.ALetter], - [/*start*/ 0x10A7D, WordBreakProperty.Other], - [/*start*/ 0x10A80, WordBreakProperty.ALetter], - [/*start*/ 0x10A9D, WordBreakProperty.Other], - [/*start*/ 0x10AC0, WordBreakProperty.ALetter], - [/*start*/ 0x10AC8, WordBreakProperty.Other], - [/*start*/ 0x10AC9, WordBreakProperty.ALetter], - [/*start*/ 0x10AE5, WordBreakProperty.Extend], - [/*start*/ 0x10AE7, WordBreakProperty.Other], - [/*start*/ 0x10B00, WordBreakProperty.ALetter], - [/*start*/ 0x10B36, WordBreakProperty.Other], - [/*start*/ 0x10B40, WordBreakProperty.ALetter], - [/*start*/ 0x10B56, WordBreakProperty.Other], - [/*start*/ 0x10B60, WordBreakProperty.ALetter], - [/*start*/ 0x10B73, WordBreakProperty.Other], - [/*start*/ 0x10B80, WordBreakProperty.ALetter], - [/*start*/ 0x10B92, WordBreakProperty.Other], - [/*start*/ 0x10C00, WordBreakProperty.ALetter], - [/*start*/ 0x10C49, WordBreakProperty.Other], - [/*start*/ 0x10C80, WordBreakProperty.ALetter], - [/*start*/ 0x10CB3, WordBreakProperty.Other], - [/*start*/ 0x10CC0, WordBreakProperty.ALetter], - [/*start*/ 0x10CF3, WordBreakProperty.Other], - [/*start*/ 0x10D00, WordBreakProperty.ALetter], - [/*start*/ 0x10D24, WordBreakProperty.Extend], - [/*start*/ 0x10D28, WordBreakProperty.Other], - [/*start*/ 0x10D30, WordBreakProperty.Numeric], - [/*start*/ 0x10D3A, WordBreakProperty.Other], - [/*start*/ 0x10E80, WordBreakProperty.ALetter], - [/*start*/ 0x10EAA, WordBreakProperty.Other], - [/*start*/ 0x10EAB, WordBreakProperty.Extend], - [/*start*/ 0x10EAD, WordBreakProperty.Other], - [/*start*/ 0x10EB0, WordBreakProperty.ALetter], - [/*start*/ 0x10EB2, WordBreakProperty.Other], - [/*start*/ 0x10EFD, WordBreakProperty.Extend], - [/*start*/ 0x10F00, WordBreakProperty.ALetter], - [/*start*/ 0x10F1D, WordBreakProperty.Other], - [/*start*/ 0x10F27, WordBreakProperty.ALetter], - [/*start*/ 0x10F28, WordBreakProperty.Other], - [/*start*/ 0x10F30, WordBreakProperty.ALetter], - [/*start*/ 0x10F46, WordBreakProperty.Extend], - [/*start*/ 0x10F51, WordBreakProperty.Other], - [/*start*/ 0x10F70, WordBreakProperty.ALetter], - [/*start*/ 0x10F82, WordBreakProperty.Extend], - [/*start*/ 0x10F86, WordBreakProperty.Other], - [/*start*/ 0x10FB0, WordBreakProperty.ALetter], - [/*start*/ 0x10FC5, WordBreakProperty.Other], - [/*start*/ 0x10FE0, WordBreakProperty.ALetter], - [/*start*/ 0x10FF7, WordBreakProperty.Other], - [/*start*/ 0x11000, WordBreakProperty.Extend], - [/*start*/ 0x11003, WordBreakProperty.ALetter], - [/*start*/ 0x11038, WordBreakProperty.Extend], - [/*start*/ 0x11047, WordBreakProperty.Other], - [/*start*/ 0x11066, WordBreakProperty.Numeric], - [/*start*/ 0x11070, WordBreakProperty.Extend], - [/*start*/ 0x11071, WordBreakProperty.ALetter], - [/*start*/ 0x11073, WordBreakProperty.Extend], - [/*start*/ 0x11075, WordBreakProperty.ALetter], - [/*start*/ 0x11076, WordBreakProperty.Other], - [/*start*/ 0x1107F, WordBreakProperty.Extend], - [/*start*/ 0x11083, WordBreakProperty.ALetter], - [/*start*/ 0x110B0, WordBreakProperty.Extend], - [/*start*/ 0x110BB, WordBreakProperty.Other], - [/*start*/ 0x110BD, WordBreakProperty.Numeric], - [/*start*/ 0x110BE, WordBreakProperty.Other], - [/*start*/ 0x110C2, WordBreakProperty.Extend], - [/*start*/ 0x110C3, WordBreakProperty.Other], - [/*start*/ 0x110CD, WordBreakProperty.Numeric], - [/*start*/ 0x110CE, WordBreakProperty.Other], - [/*start*/ 0x110D0, WordBreakProperty.ALetter], - [/*start*/ 0x110E9, WordBreakProperty.Other], - [/*start*/ 0x110F0, WordBreakProperty.Numeric], - [/*start*/ 0x110FA, WordBreakProperty.Other], - [/*start*/ 0x11100, WordBreakProperty.Extend], - [/*start*/ 0x11103, WordBreakProperty.ALetter], - [/*start*/ 0x11127, WordBreakProperty.Extend], - [/*start*/ 0x11135, WordBreakProperty.Other], - [/*start*/ 0x11136, WordBreakProperty.Numeric], - [/*start*/ 0x11140, WordBreakProperty.Other], - [/*start*/ 0x11144, WordBreakProperty.ALetter], - [/*start*/ 0x11145, WordBreakProperty.Extend], - [/*start*/ 0x11147, WordBreakProperty.ALetter], - [/*start*/ 0x11148, WordBreakProperty.Other], - [/*start*/ 0x11150, WordBreakProperty.ALetter], - [/*start*/ 0x11173, WordBreakProperty.Extend], - [/*start*/ 0x11174, WordBreakProperty.Other], - [/*start*/ 0x11176, WordBreakProperty.ALetter], - [/*start*/ 0x11177, WordBreakProperty.Other], - [/*start*/ 0x11180, WordBreakProperty.Extend], - [/*start*/ 0x11183, WordBreakProperty.ALetter], - [/*start*/ 0x111B3, WordBreakProperty.Extend], - [/*start*/ 0x111C1, WordBreakProperty.ALetter], - [/*start*/ 0x111C5, WordBreakProperty.Other], - [/*start*/ 0x111C9, WordBreakProperty.Extend], - [/*start*/ 0x111CD, WordBreakProperty.Other], - [/*start*/ 0x111CE, WordBreakProperty.Extend], - [/*start*/ 0x111D0, WordBreakProperty.Numeric], - [/*start*/ 0x111DA, WordBreakProperty.ALetter], - [/*start*/ 0x111DB, WordBreakProperty.Other], - [/*start*/ 0x111DC, WordBreakProperty.ALetter], - [/*start*/ 0x111DD, WordBreakProperty.Other], - [/*start*/ 0x11200, WordBreakProperty.ALetter], - [/*start*/ 0x11212, WordBreakProperty.Other], - [/*start*/ 0x11213, WordBreakProperty.ALetter], - [/*start*/ 0x1122C, WordBreakProperty.Extend], - [/*start*/ 0x11238, WordBreakProperty.Other], - [/*start*/ 0x1123E, WordBreakProperty.Extend], - [/*start*/ 0x1123F, WordBreakProperty.ALetter], - [/*start*/ 0x11241, WordBreakProperty.Extend], - [/*start*/ 0x11242, WordBreakProperty.Other], - [/*start*/ 0x11280, WordBreakProperty.ALetter], - [/*start*/ 0x11287, WordBreakProperty.Other], - [/*start*/ 0x11288, WordBreakProperty.ALetter], - [/*start*/ 0x11289, WordBreakProperty.Other], - [/*start*/ 0x1128A, WordBreakProperty.ALetter], - [/*start*/ 0x1128E, WordBreakProperty.Other], - [/*start*/ 0x1128F, WordBreakProperty.ALetter], - [/*start*/ 0x1129E, WordBreakProperty.Other], - [/*start*/ 0x1129F, WordBreakProperty.ALetter], - [/*start*/ 0x112A9, WordBreakProperty.Other], - [/*start*/ 0x112B0, WordBreakProperty.ALetter], - [/*start*/ 0x112DF, WordBreakProperty.Extend], - [/*start*/ 0x112EB, WordBreakProperty.Other], - [/*start*/ 0x112F0, WordBreakProperty.Numeric], - [/*start*/ 0x112FA, WordBreakProperty.Other], - [/*start*/ 0x11300, WordBreakProperty.Extend], - [/*start*/ 0x11304, WordBreakProperty.Other], - [/*start*/ 0x11305, WordBreakProperty.ALetter], - [/*start*/ 0x1130D, WordBreakProperty.Other], - [/*start*/ 0x1130F, WordBreakProperty.ALetter], - [/*start*/ 0x11311, WordBreakProperty.Other], - [/*start*/ 0x11313, WordBreakProperty.ALetter], - [/*start*/ 0x11329, WordBreakProperty.Other], - [/*start*/ 0x1132A, WordBreakProperty.ALetter], - [/*start*/ 0x11331, WordBreakProperty.Other], - [/*start*/ 0x11332, WordBreakProperty.ALetter], - [/*start*/ 0x11334, WordBreakProperty.Other], - [/*start*/ 0x11335, WordBreakProperty.ALetter], - [/*start*/ 0x1133A, WordBreakProperty.Other], - [/*start*/ 0x1133B, WordBreakProperty.Extend], - [/*start*/ 0x1133D, WordBreakProperty.ALetter], - [/*start*/ 0x1133E, WordBreakProperty.Extend], - [/*start*/ 0x11345, WordBreakProperty.Other], - [/*start*/ 0x11347, WordBreakProperty.Extend], - [/*start*/ 0x11349, WordBreakProperty.Other], - [/*start*/ 0x1134B, WordBreakProperty.Extend], - [/*start*/ 0x1134E, WordBreakProperty.Other], - [/*start*/ 0x11350, WordBreakProperty.ALetter], - [/*start*/ 0x11351, WordBreakProperty.Other], - [/*start*/ 0x11357, WordBreakProperty.Extend], - [/*start*/ 0x11358, WordBreakProperty.Other], - [/*start*/ 0x1135D, WordBreakProperty.ALetter], - [/*start*/ 0x11362, WordBreakProperty.Extend], - [/*start*/ 0x11364, WordBreakProperty.Other], - [/*start*/ 0x11366, WordBreakProperty.Extend], - [/*start*/ 0x1136D, WordBreakProperty.Other], - [/*start*/ 0x11370, WordBreakProperty.Extend], - [/*start*/ 0x11375, WordBreakProperty.Other], - [/*start*/ 0x11400, WordBreakProperty.ALetter], - [/*start*/ 0x11435, WordBreakProperty.Extend], - [/*start*/ 0x11447, WordBreakProperty.ALetter], - [/*start*/ 0x1144B, WordBreakProperty.Other], - [/*start*/ 0x11450, WordBreakProperty.Numeric], - [/*start*/ 0x1145A, WordBreakProperty.Other], - [/*start*/ 0x1145E, WordBreakProperty.Extend], - [/*start*/ 0x1145F, WordBreakProperty.ALetter], - [/*start*/ 0x11462, WordBreakProperty.Other], - [/*start*/ 0x11480, WordBreakProperty.ALetter], - [/*start*/ 0x114B0, WordBreakProperty.Extend], - [/*start*/ 0x114C4, WordBreakProperty.ALetter], - [/*start*/ 0x114C6, WordBreakProperty.Other], - [/*start*/ 0x114C7, WordBreakProperty.ALetter], - [/*start*/ 0x114C8, WordBreakProperty.Other], - [/*start*/ 0x114D0, WordBreakProperty.Numeric], - [/*start*/ 0x114DA, WordBreakProperty.Other], - [/*start*/ 0x11580, WordBreakProperty.ALetter], - [/*start*/ 0x115AF, WordBreakProperty.Extend], - [/*start*/ 0x115B6, WordBreakProperty.Other], - [/*start*/ 0x115B8, WordBreakProperty.Extend], - [/*start*/ 0x115C1, WordBreakProperty.Other], - [/*start*/ 0x115D8, WordBreakProperty.ALetter], - [/*start*/ 0x115DC, WordBreakProperty.Extend], - [/*start*/ 0x115DE, WordBreakProperty.Other], - [/*start*/ 0x11600, WordBreakProperty.ALetter], - [/*start*/ 0x11630, WordBreakProperty.Extend], - [/*start*/ 0x11641, WordBreakProperty.Other], - [/*start*/ 0x11644, WordBreakProperty.ALetter], - [/*start*/ 0x11645, WordBreakProperty.Other], - [/*start*/ 0x11650, WordBreakProperty.Numeric], - [/*start*/ 0x1165A, WordBreakProperty.Other], - [/*start*/ 0x11680, WordBreakProperty.ALetter], - [/*start*/ 0x116AB, WordBreakProperty.Extend], - [/*start*/ 0x116B8, WordBreakProperty.ALetter], - [/*start*/ 0x116B9, WordBreakProperty.Other], - [/*start*/ 0x116C0, WordBreakProperty.Numeric], - [/*start*/ 0x116CA, WordBreakProperty.Other], - [/*start*/ 0x1171D, WordBreakProperty.Extend], - [/*start*/ 0x1172C, WordBreakProperty.Other], - [/*start*/ 0x11730, WordBreakProperty.Numeric], - [/*start*/ 0x1173A, WordBreakProperty.Other], - [/*start*/ 0x11800, WordBreakProperty.ALetter], - [/*start*/ 0x1182C, WordBreakProperty.Extend], - [/*start*/ 0x1183B, WordBreakProperty.Other], - [/*start*/ 0x118A0, WordBreakProperty.ALetter], - [/*start*/ 0x118E0, WordBreakProperty.Numeric], - [/*start*/ 0x118EA, WordBreakProperty.Other], - [/*start*/ 0x118FF, WordBreakProperty.ALetter], - [/*start*/ 0x11907, WordBreakProperty.Other], - [/*start*/ 0x11909, WordBreakProperty.ALetter], - [/*start*/ 0x1190A, WordBreakProperty.Other], - [/*start*/ 0x1190C, WordBreakProperty.ALetter], - [/*start*/ 0x11914, WordBreakProperty.Other], - [/*start*/ 0x11915, WordBreakProperty.ALetter], - [/*start*/ 0x11917, WordBreakProperty.Other], - [/*start*/ 0x11918, WordBreakProperty.ALetter], - [/*start*/ 0x11930, WordBreakProperty.Extend], - [/*start*/ 0x11936, WordBreakProperty.Other], - [/*start*/ 0x11937, WordBreakProperty.Extend], - [/*start*/ 0x11939, WordBreakProperty.Other], - [/*start*/ 0x1193B, WordBreakProperty.Extend], - [/*start*/ 0x1193F, WordBreakProperty.ALetter], - [/*start*/ 0x11940, WordBreakProperty.Extend], - [/*start*/ 0x11941, WordBreakProperty.ALetter], - [/*start*/ 0x11942, WordBreakProperty.Extend], - [/*start*/ 0x11944, WordBreakProperty.Other], - [/*start*/ 0x11950, WordBreakProperty.Numeric], - [/*start*/ 0x1195A, WordBreakProperty.Other], - [/*start*/ 0x119A0, WordBreakProperty.ALetter], - [/*start*/ 0x119A8, WordBreakProperty.Other], - [/*start*/ 0x119AA, WordBreakProperty.ALetter], - [/*start*/ 0x119D1, WordBreakProperty.Extend], - [/*start*/ 0x119D8, WordBreakProperty.Other], - [/*start*/ 0x119DA, WordBreakProperty.Extend], - [/*start*/ 0x119E1, WordBreakProperty.ALetter], - [/*start*/ 0x119E2, WordBreakProperty.Other], - [/*start*/ 0x119E3, WordBreakProperty.ALetter], - [/*start*/ 0x119E4, WordBreakProperty.Extend], - [/*start*/ 0x119E5, WordBreakProperty.Other], - [/*start*/ 0x11A00, WordBreakProperty.ALetter], - [/*start*/ 0x11A01, WordBreakProperty.Extend], - [/*start*/ 0x11A0B, WordBreakProperty.ALetter], - [/*start*/ 0x11A33, WordBreakProperty.Extend], - [/*start*/ 0x11A3A, WordBreakProperty.ALetter], - [/*start*/ 0x11A3B, WordBreakProperty.Extend], - [/*start*/ 0x11A3F, WordBreakProperty.Other], - [/*start*/ 0x11A47, WordBreakProperty.Extend], - [/*start*/ 0x11A48, WordBreakProperty.Other], - [/*start*/ 0x11A50, WordBreakProperty.ALetter], - [/*start*/ 0x11A51, WordBreakProperty.Extend], - [/*start*/ 0x11A5C, WordBreakProperty.ALetter], - [/*start*/ 0x11A8A, WordBreakProperty.Extend], - [/*start*/ 0x11A9A, WordBreakProperty.Other], - [/*start*/ 0x11A9D, WordBreakProperty.ALetter], - [/*start*/ 0x11A9E, WordBreakProperty.Other], - [/*start*/ 0x11AB0, WordBreakProperty.ALetter], - [/*start*/ 0x11AF9, WordBreakProperty.Other], - [/*start*/ 0x11C00, WordBreakProperty.ALetter], - [/*start*/ 0x11C09, WordBreakProperty.Other], - [/*start*/ 0x11C0A, WordBreakProperty.ALetter], - [/*start*/ 0x11C2F, WordBreakProperty.Extend], - [/*start*/ 0x11C37, WordBreakProperty.Other], - [/*start*/ 0x11C38, WordBreakProperty.Extend], - [/*start*/ 0x11C40, WordBreakProperty.ALetter], - [/*start*/ 0x11C41, WordBreakProperty.Other], - [/*start*/ 0x11C50, WordBreakProperty.Numeric], - [/*start*/ 0x11C5A, WordBreakProperty.Other], - [/*start*/ 0x11C72, WordBreakProperty.ALetter], - [/*start*/ 0x11C90, WordBreakProperty.Other], - [/*start*/ 0x11C92, WordBreakProperty.Extend], - [/*start*/ 0x11CA8, WordBreakProperty.Other], - [/*start*/ 0x11CA9, WordBreakProperty.Extend], - [/*start*/ 0x11CB7, WordBreakProperty.Other], - [/*start*/ 0x11D00, WordBreakProperty.ALetter], - [/*start*/ 0x11D07, WordBreakProperty.Other], - [/*start*/ 0x11D08, WordBreakProperty.ALetter], - [/*start*/ 0x11D0A, WordBreakProperty.Other], - [/*start*/ 0x11D0B, WordBreakProperty.ALetter], - [/*start*/ 0x11D31, WordBreakProperty.Extend], - [/*start*/ 0x11D37, WordBreakProperty.Other], - [/*start*/ 0x11D3A, WordBreakProperty.Extend], - [/*start*/ 0x11D3B, WordBreakProperty.Other], - [/*start*/ 0x11D3C, WordBreakProperty.Extend], - [/*start*/ 0x11D3E, WordBreakProperty.Other], - [/*start*/ 0x11D3F, WordBreakProperty.Extend], - [/*start*/ 0x11D46, WordBreakProperty.ALetter], - [/*start*/ 0x11D47, WordBreakProperty.Extend], - [/*start*/ 0x11D48, WordBreakProperty.Other], - [/*start*/ 0x11D50, WordBreakProperty.Numeric], - [/*start*/ 0x11D5A, WordBreakProperty.Other], - [/*start*/ 0x11D60, WordBreakProperty.ALetter], - [/*start*/ 0x11D66, WordBreakProperty.Other], - [/*start*/ 0x11D67, WordBreakProperty.ALetter], - [/*start*/ 0x11D69, WordBreakProperty.Other], - [/*start*/ 0x11D6A, WordBreakProperty.ALetter], - [/*start*/ 0x11D8A, WordBreakProperty.Extend], - [/*start*/ 0x11D8F, WordBreakProperty.Other], - [/*start*/ 0x11D90, WordBreakProperty.Extend], - [/*start*/ 0x11D92, WordBreakProperty.Other], - [/*start*/ 0x11D93, WordBreakProperty.Extend], - [/*start*/ 0x11D98, WordBreakProperty.ALetter], - [/*start*/ 0x11D99, WordBreakProperty.Other], - [/*start*/ 0x11DA0, WordBreakProperty.Numeric], - [/*start*/ 0x11DAA, WordBreakProperty.Other], - [/*start*/ 0x11EE0, WordBreakProperty.ALetter], - [/*start*/ 0x11EF3, WordBreakProperty.Extend], - [/*start*/ 0x11EF7, WordBreakProperty.Other], - [/*start*/ 0x11F00, WordBreakProperty.Extend], - [/*start*/ 0x11F02, WordBreakProperty.ALetter], - [/*start*/ 0x11F03, WordBreakProperty.Extend], - [/*start*/ 0x11F04, WordBreakProperty.ALetter], - [/*start*/ 0x11F11, WordBreakProperty.Other], - [/*start*/ 0x11F12, WordBreakProperty.ALetter], - [/*start*/ 0x11F34, WordBreakProperty.Extend], - [/*start*/ 0x11F3B, WordBreakProperty.Other], - [/*start*/ 0x11F3E, WordBreakProperty.Extend], - [/*start*/ 0x11F43, WordBreakProperty.Other], - [/*start*/ 0x11F50, WordBreakProperty.Numeric], - [/*start*/ 0x11F5A, WordBreakProperty.Other], - [/*start*/ 0x11FB0, WordBreakProperty.ALetter], - [/*start*/ 0x11FB1, WordBreakProperty.Other], - [/*start*/ 0x12000, WordBreakProperty.ALetter], - [/*start*/ 0x1239A, WordBreakProperty.Other], - [/*start*/ 0x12400, WordBreakProperty.ALetter], - [/*start*/ 0x1246F, WordBreakProperty.Other], - [/*start*/ 0x12480, WordBreakProperty.ALetter], - [/*start*/ 0x12544, WordBreakProperty.Other], - [/*start*/ 0x12F90, WordBreakProperty.ALetter], - [/*start*/ 0x12FF1, WordBreakProperty.Other], - [/*start*/ 0x13000, WordBreakProperty.ALetter], - [/*start*/ 0x13430, WordBreakProperty.Format], - [/*start*/ 0x13440, WordBreakProperty.Extend], - [/*start*/ 0x13441, WordBreakProperty.ALetter], - [/*start*/ 0x13447, WordBreakProperty.Extend], - [/*start*/ 0x13456, WordBreakProperty.Other], - [/*start*/ 0x14400, WordBreakProperty.ALetter], - [/*start*/ 0x14647, WordBreakProperty.Other], - [/*start*/ 0x16800, WordBreakProperty.ALetter], - [/*start*/ 0x16A39, WordBreakProperty.Other], - [/*start*/ 0x16A40, WordBreakProperty.ALetter], - [/*start*/ 0x16A5F, WordBreakProperty.Other], - [/*start*/ 0x16A60, WordBreakProperty.Numeric], - [/*start*/ 0x16A6A, WordBreakProperty.Other], - [/*start*/ 0x16A70, WordBreakProperty.ALetter], - [/*start*/ 0x16ABF, WordBreakProperty.Other], - [/*start*/ 0x16AC0, WordBreakProperty.Numeric], - [/*start*/ 0x16ACA, WordBreakProperty.Other], - [/*start*/ 0x16AD0, WordBreakProperty.ALetter], - [/*start*/ 0x16AEE, WordBreakProperty.Other], - [/*start*/ 0x16AF0, WordBreakProperty.Extend], - [/*start*/ 0x16AF5, WordBreakProperty.Other], - [/*start*/ 0x16B00, WordBreakProperty.ALetter], - [/*start*/ 0x16B30, WordBreakProperty.Extend], - [/*start*/ 0x16B37, WordBreakProperty.Other], - [/*start*/ 0x16B40, WordBreakProperty.ALetter], - [/*start*/ 0x16B44, WordBreakProperty.Other], - [/*start*/ 0x16B50, WordBreakProperty.Numeric], - [/*start*/ 0x16B5A, WordBreakProperty.Other], - [/*start*/ 0x16B63, WordBreakProperty.ALetter], - [/*start*/ 0x16B78, WordBreakProperty.Other], - [/*start*/ 0x16B7D, WordBreakProperty.ALetter], - [/*start*/ 0x16B90, WordBreakProperty.Other], - [/*start*/ 0x16E40, WordBreakProperty.ALetter], - [/*start*/ 0x16E80, WordBreakProperty.Other], - [/*start*/ 0x16F00, WordBreakProperty.ALetter], - [/*start*/ 0x16F4B, WordBreakProperty.Other], - [/*start*/ 0x16F4F, WordBreakProperty.Extend], - [/*start*/ 0x16F50, WordBreakProperty.ALetter], - [/*start*/ 0x16F51, WordBreakProperty.Extend], - [/*start*/ 0x16F88, WordBreakProperty.Other], - [/*start*/ 0x16F8F, WordBreakProperty.Extend], - [/*start*/ 0x16F93, WordBreakProperty.ALetter], - [/*start*/ 0x16FA0, WordBreakProperty.Other], - [/*start*/ 0x16FE0, WordBreakProperty.ALetter], - [/*start*/ 0x16FE2, WordBreakProperty.Other], - [/*start*/ 0x16FE3, WordBreakProperty.ALetter], - [/*start*/ 0x16FE4, WordBreakProperty.Extend], - [/*start*/ 0x16FE5, WordBreakProperty.Other], - [/*start*/ 0x16FF0, WordBreakProperty.Extend], - [/*start*/ 0x16FF2, WordBreakProperty.Other], - [/*start*/ 0x1AFF0, WordBreakProperty.Katakana], - [/*start*/ 0x1AFF4, WordBreakProperty.Other], - [/*start*/ 0x1AFF5, WordBreakProperty.Katakana], - [/*start*/ 0x1AFFC, WordBreakProperty.Other], - [/*start*/ 0x1AFFD, WordBreakProperty.Katakana], - [/*start*/ 0x1AFFF, WordBreakProperty.Other], - [/*start*/ 0x1B000, WordBreakProperty.Katakana], - [/*start*/ 0x1B001, WordBreakProperty.Other], - [/*start*/ 0x1B120, WordBreakProperty.Katakana], - [/*start*/ 0x1B123, WordBreakProperty.Other], - [/*start*/ 0x1B155, WordBreakProperty.Katakana], - [/*start*/ 0x1B156, WordBreakProperty.Other], - [/*start*/ 0x1B164, WordBreakProperty.Katakana], - [/*start*/ 0x1B168, WordBreakProperty.Other], - [/*start*/ 0x1BC00, WordBreakProperty.ALetter], - [/*start*/ 0x1BC6B, WordBreakProperty.Other], - [/*start*/ 0x1BC70, WordBreakProperty.ALetter], - [/*start*/ 0x1BC7D, WordBreakProperty.Other], - [/*start*/ 0x1BC80, WordBreakProperty.ALetter], - [/*start*/ 0x1BC89, WordBreakProperty.Other], - [/*start*/ 0x1BC90, WordBreakProperty.ALetter], - [/*start*/ 0x1BC9A, WordBreakProperty.Other], - [/*start*/ 0x1BC9D, WordBreakProperty.Extend], - [/*start*/ 0x1BC9F, WordBreakProperty.Other], - [/*start*/ 0x1BCA0, WordBreakProperty.Format], - [/*start*/ 0x1BCA4, WordBreakProperty.Other], - [/*start*/ 0x1CF00, WordBreakProperty.Extend], - [/*start*/ 0x1CF2E, WordBreakProperty.Other], - [/*start*/ 0x1CF30, WordBreakProperty.Extend], - [/*start*/ 0x1CF47, WordBreakProperty.Other], - [/*start*/ 0x1D165, WordBreakProperty.Extend], - [/*start*/ 0x1D16A, WordBreakProperty.Other], - [/*start*/ 0x1D16D, WordBreakProperty.Extend], - [/*start*/ 0x1D173, WordBreakProperty.Format], - [/*start*/ 0x1D17B, WordBreakProperty.Extend], - [/*start*/ 0x1D183, WordBreakProperty.Other], - [/*start*/ 0x1D185, WordBreakProperty.Extend], - [/*start*/ 0x1D18C, WordBreakProperty.Other], - [/*start*/ 0x1D1AA, WordBreakProperty.Extend], - [/*start*/ 0x1D1AE, WordBreakProperty.Other], - [/*start*/ 0x1D242, WordBreakProperty.Extend], - [/*start*/ 0x1D245, WordBreakProperty.Other], - [/*start*/ 0x1D400, WordBreakProperty.ALetter], - [/*start*/ 0x1D455, WordBreakProperty.Other], - [/*start*/ 0x1D456, WordBreakProperty.ALetter], - [/*start*/ 0x1D49D, WordBreakProperty.Other], - [/*start*/ 0x1D49E, WordBreakProperty.ALetter], - [/*start*/ 0x1D4A0, WordBreakProperty.Other], - [/*start*/ 0x1D4A2, WordBreakProperty.ALetter], - [/*start*/ 0x1D4A3, WordBreakProperty.Other], - [/*start*/ 0x1D4A5, WordBreakProperty.ALetter], - [/*start*/ 0x1D4A7, WordBreakProperty.Other], - [/*start*/ 0x1D4A9, WordBreakProperty.ALetter], - [/*start*/ 0x1D4AD, WordBreakProperty.Other], - [/*start*/ 0x1D4AE, WordBreakProperty.ALetter], - [/*start*/ 0x1D4BA, WordBreakProperty.Other], - [/*start*/ 0x1D4BB, WordBreakProperty.ALetter], - [/*start*/ 0x1D4BC, WordBreakProperty.Other], - [/*start*/ 0x1D4BD, WordBreakProperty.ALetter], - [/*start*/ 0x1D4C4, WordBreakProperty.Other], - [/*start*/ 0x1D4C5, WordBreakProperty.ALetter], - [/*start*/ 0x1D506, WordBreakProperty.Other], - [/*start*/ 0x1D507, WordBreakProperty.ALetter], - [/*start*/ 0x1D50B, WordBreakProperty.Other], - [/*start*/ 0x1D50D, WordBreakProperty.ALetter], - [/*start*/ 0x1D515, WordBreakProperty.Other], - [/*start*/ 0x1D516, WordBreakProperty.ALetter], - [/*start*/ 0x1D51D, WordBreakProperty.Other], - [/*start*/ 0x1D51E, WordBreakProperty.ALetter], - [/*start*/ 0x1D53A, WordBreakProperty.Other], - [/*start*/ 0x1D53B, WordBreakProperty.ALetter], - [/*start*/ 0x1D53F, WordBreakProperty.Other], - [/*start*/ 0x1D540, WordBreakProperty.ALetter], - [/*start*/ 0x1D545, WordBreakProperty.Other], - [/*start*/ 0x1D546, WordBreakProperty.ALetter], - [/*start*/ 0x1D547, WordBreakProperty.Other], - [/*start*/ 0x1D54A, WordBreakProperty.ALetter], - [/*start*/ 0x1D551, WordBreakProperty.Other], - [/*start*/ 0x1D552, WordBreakProperty.ALetter], - [/*start*/ 0x1D6A6, WordBreakProperty.Other], - [/*start*/ 0x1D6A8, WordBreakProperty.ALetter], - [/*start*/ 0x1D6C1, WordBreakProperty.Other], - [/*start*/ 0x1D6C2, WordBreakProperty.ALetter], - [/*start*/ 0x1D6DB, WordBreakProperty.Other], - [/*start*/ 0x1D6DC, WordBreakProperty.ALetter], - [/*start*/ 0x1D6FB, WordBreakProperty.Other], - [/*start*/ 0x1D6FC, WordBreakProperty.ALetter], - [/*start*/ 0x1D715, WordBreakProperty.Other], - [/*start*/ 0x1D716, WordBreakProperty.ALetter], - [/*start*/ 0x1D735, WordBreakProperty.Other], - [/*start*/ 0x1D736, WordBreakProperty.ALetter], - [/*start*/ 0x1D74F, WordBreakProperty.Other], - [/*start*/ 0x1D750, WordBreakProperty.ALetter], - [/*start*/ 0x1D76F, WordBreakProperty.Other], - [/*start*/ 0x1D770, WordBreakProperty.ALetter], - [/*start*/ 0x1D789, WordBreakProperty.Other], - [/*start*/ 0x1D78A, WordBreakProperty.ALetter], - [/*start*/ 0x1D7A9, WordBreakProperty.Other], - [/*start*/ 0x1D7AA, WordBreakProperty.ALetter], - [/*start*/ 0x1D7C3, WordBreakProperty.Other], - [/*start*/ 0x1D7C4, WordBreakProperty.ALetter], - [/*start*/ 0x1D7CC, WordBreakProperty.Other], - [/*start*/ 0x1D7CE, WordBreakProperty.Numeric], - [/*start*/ 0x1D800, WordBreakProperty.Other], - [/*start*/ 0x1DA00, WordBreakProperty.Extend], - [/*start*/ 0x1DA37, WordBreakProperty.Other], - [/*start*/ 0x1DA3B, WordBreakProperty.Extend], - [/*start*/ 0x1DA6D, WordBreakProperty.Other], - [/*start*/ 0x1DA75, WordBreakProperty.Extend], - [/*start*/ 0x1DA76, WordBreakProperty.Other], - [/*start*/ 0x1DA84, WordBreakProperty.Extend], - [/*start*/ 0x1DA85, WordBreakProperty.Other], - [/*start*/ 0x1DA9B, WordBreakProperty.Extend], - [/*start*/ 0x1DAA0, WordBreakProperty.Other], - [/*start*/ 0x1DAA1, WordBreakProperty.Extend], - [/*start*/ 0x1DAB0, WordBreakProperty.Other], - [/*start*/ 0x1DF00, WordBreakProperty.ALetter], - [/*start*/ 0x1DF1F, WordBreakProperty.Other], - [/*start*/ 0x1DF25, WordBreakProperty.ALetter], - [/*start*/ 0x1DF2B, WordBreakProperty.Other], - [/*start*/ 0x1E000, WordBreakProperty.Extend], - [/*start*/ 0x1E007, WordBreakProperty.Other], - [/*start*/ 0x1E008, WordBreakProperty.Extend], - [/*start*/ 0x1E019, WordBreakProperty.Other], - [/*start*/ 0x1E01B, WordBreakProperty.Extend], - [/*start*/ 0x1E022, WordBreakProperty.Other], - [/*start*/ 0x1E023, WordBreakProperty.Extend], - [/*start*/ 0x1E025, WordBreakProperty.Other], - [/*start*/ 0x1E026, WordBreakProperty.Extend], - [/*start*/ 0x1E02B, WordBreakProperty.Other], - [/*start*/ 0x1E030, WordBreakProperty.ALetter], - [/*start*/ 0x1E06E, WordBreakProperty.Other], - [/*start*/ 0x1E08F, WordBreakProperty.Extend], - [/*start*/ 0x1E090, WordBreakProperty.Other], - [/*start*/ 0x1E100, WordBreakProperty.ALetter], - [/*start*/ 0x1E12D, WordBreakProperty.Other], - [/*start*/ 0x1E130, WordBreakProperty.Extend], - [/*start*/ 0x1E137, WordBreakProperty.ALetter], - [/*start*/ 0x1E13E, WordBreakProperty.Other], - [/*start*/ 0x1E140, WordBreakProperty.Numeric], - [/*start*/ 0x1E14A, WordBreakProperty.Other], - [/*start*/ 0x1E14E, WordBreakProperty.ALetter], - [/*start*/ 0x1E14F, WordBreakProperty.Other], - [/*start*/ 0x1E290, WordBreakProperty.ALetter], - [/*start*/ 0x1E2AE, WordBreakProperty.Extend], - [/*start*/ 0x1E2AF, WordBreakProperty.Other], - [/*start*/ 0x1E2C0, WordBreakProperty.ALetter], - [/*start*/ 0x1E2EC, WordBreakProperty.Extend], - [/*start*/ 0x1E2F0, WordBreakProperty.Numeric], - [/*start*/ 0x1E2FA, WordBreakProperty.Other], - [/*start*/ 0x1E4D0, WordBreakProperty.ALetter], - [/*start*/ 0x1E4EC, WordBreakProperty.Extend], - [/*start*/ 0x1E4F0, WordBreakProperty.Numeric], - [/*start*/ 0x1E4FA, WordBreakProperty.Other], - [/*start*/ 0x1E7E0, WordBreakProperty.ALetter], - [/*start*/ 0x1E7E7, WordBreakProperty.Other], - [/*start*/ 0x1E7E8, WordBreakProperty.ALetter], - [/*start*/ 0x1E7EC, WordBreakProperty.Other], - [/*start*/ 0x1E7ED, WordBreakProperty.ALetter], - [/*start*/ 0x1E7EF, WordBreakProperty.Other], - [/*start*/ 0x1E7F0, WordBreakProperty.ALetter], - [/*start*/ 0x1E7FF, WordBreakProperty.Other], - [/*start*/ 0x1E800, WordBreakProperty.ALetter], - [/*start*/ 0x1E8C5, WordBreakProperty.Other], - [/*start*/ 0x1E8D0, WordBreakProperty.Extend], - [/*start*/ 0x1E8D7, WordBreakProperty.Other], - [/*start*/ 0x1E900, WordBreakProperty.ALetter], - [/*start*/ 0x1E944, WordBreakProperty.Extend], - [/*start*/ 0x1E94B, WordBreakProperty.ALetter], - [/*start*/ 0x1E94C, WordBreakProperty.Other], - [/*start*/ 0x1E950, WordBreakProperty.Numeric], - [/*start*/ 0x1E95A, WordBreakProperty.Other], - [/*start*/ 0x1EE00, WordBreakProperty.ALetter], - [/*start*/ 0x1EE04, WordBreakProperty.Other], - [/*start*/ 0x1EE05, WordBreakProperty.ALetter], - [/*start*/ 0x1EE20, WordBreakProperty.Other], - [/*start*/ 0x1EE21, WordBreakProperty.ALetter], - [/*start*/ 0x1EE23, WordBreakProperty.Other], - [/*start*/ 0x1EE24, WordBreakProperty.ALetter], - [/*start*/ 0x1EE25, WordBreakProperty.Other], - [/*start*/ 0x1EE27, WordBreakProperty.ALetter], - [/*start*/ 0x1EE28, WordBreakProperty.Other], - [/*start*/ 0x1EE29, WordBreakProperty.ALetter], - [/*start*/ 0x1EE33, WordBreakProperty.Other], - [/*start*/ 0x1EE34, WordBreakProperty.ALetter], - [/*start*/ 0x1EE38, WordBreakProperty.Other], - [/*start*/ 0x1EE39, WordBreakProperty.ALetter], - [/*start*/ 0x1EE3A, WordBreakProperty.Other], - [/*start*/ 0x1EE3B, WordBreakProperty.ALetter], - [/*start*/ 0x1EE3C, WordBreakProperty.Other], - [/*start*/ 0x1EE42, WordBreakProperty.ALetter], - [/*start*/ 0x1EE43, WordBreakProperty.Other], - [/*start*/ 0x1EE47, WordBreakProperty.ALetter], - [/*start*/ 0x1EE48, WordBreakProperty.Other], - [/*start*/ 0x1EE49, WordBreakProperty.ALetter], - [/*start*/ 0x1EE4A, WordBreakProperty.Other], - [/*start*/ 0x1EE4B, WordBreakProperty.ALetter], - [/*start*/ 0x1EE4C, WordBreakProperty.Other], - [/*start*/ 0x1EE4D, WordBreakProperty.ALetter], - [/*start*/ 0x1EE50, WordBreakProperty.Other], - [/*start*/ 0x1EE51, WordBreakProperty.ALetter], - [/*start*/ 0x1EE53, WordBreakProperty.Other], - [/*start*/ 0x1EE54, WordBreakProperty.ALetter], - [/*start*/ 0x1EE55, WordBreakProperty.Other], - [/*start*/ 0x1EE57, WordBreakProperty.ALetter], - [/*start*/ 0x1EE58, WordBreakProperty.Other], - [/*start*/ 0x1EE59, WordBreakProperty.ALetter], - [/*start*/ 0x1EE5A, WordBreakProperty.Other], - [/*start*/ 0x1EE5B, WordBreakProperty.ALetter], - [/*start*/ 0x1EE5C, WordBreakProperty.Other], - [/*start*/ 0x1EE5D, WordBreakProperty.ALetter], - [/*start*/ 0x1EE5E, WordBreakProperty.Other], - [/*start*/ 0x1EE5F, WordBreakProperty.ALetter], - [/*start*/ 0x1EE60, WordBreakProperty.Other], - [/*start*/ 0x1EE61, WordBreakProperty.ALetter], - [/*start*/ 0x1EE63, WordBreakProperty.Other], - [/*start*/ 0x1EE64, WordBreakProperty.ALetter], - [/*start*/ 0x1EE65, WordBreakProperty.Other], - [/*start*/ 0x1EE67, WordBreakProperty.ALetter], - [/*start*/ 0x1EE6B, WordBreakProperty.Other], - [/*start*/ 0x1EE6C, WordBreakProperty.ALetter], - [/*start*/ 0x1EE73, WordBreakProperty.Other], - [/*start*/ 0x1EE74, WordBreakProperty.ALetter], - [/*start*/ 0x1EE78, WordBreakProperty.Other], - [/*start*/ 0x1EE79, WordBreakProperty.ALetter], - [/*start*/ 0x1EE7D, WordBreakProperty.Other], - [/*start*/ 0x1EE7E, WordBreakProperty.ALetter], - [/*start*/ 0x1EE7F, WordBreakProperty.Other], - [/*start*/ 0x1EE80, WordBreakProperty.ALetter], - [/*start*/ 0x1EE8A, WordBreakProperty.Other], - [/*start*/ 0x1EE8B, WordBreakProperty.ALetter], - [/*start*/ 0x1EE9C, WordBreakProperty.Other], - [/*start*/ 0x1EEA1, WordBreakProperty.ALetter], - [/*start*/ 0x1EEA4, WordBreakProperty.Other], - [/*start*/ 0x1EEA5, WordBreakProperty.ALetter], - [/*start*/ 0x1EEAA, WordBreakProperty.Other], - [/*start*/ 0x1EEAB, WordBreakProperty.ALetter], - [/*start*/ 0x1EEBC, WordBreakProperty.Other], - [/*start*/ 0x1F130, WordBreakProperty.ALetter], - [/*start*/ 0x1F14A, WordBreakProperty.Other], - [/*start*/ 0x1F150, WordBreakProperty.ALetter], - [/*start*/ 0x1F16A, WordBreakProperty.Other], - [/*start*/ 0x1F170, WordBreakProperty.ALetter], - [/*start*/ 0x1F18A, WordBreakProperty.Other], - [/*start*/ 0x1F1E6, WordBreakProperty.Regional_Indicator], - [/*start*/ 0x1F200, WordBreakProperty.Other], - [/*start*/ 0x1F3FB, WordBreakProperty.Extend], - [/*start*/ 0x1F400, WordBreakProperty.Other], - [/*start*/ 0x1FBF0, WordBreakProperty.Numeric], - [/*start*/ 0x1FBFA, WordBreakProperty.Other], - [/*start*/ 0xE0001, WordBreakProperty.Format], - [/*start*/ 0xE0002, WordBreakProperty.Other], - [/*start*/ 0xE0020, WordBreakProperty.Extend], - [/*start*/ 0xE0080, WordBreakProperty.Other], - [/*start*/ 0xE0100, WordBreakProperty.Extend], - [/*start*/ 0xE01F0, WordBreakProperty.Other], -]; diff --git a/common/models/wordbreakers/src/main/default/index.ts b/common/models/wordbreakers/src/main/default/index.ts index ef50ab4b31..8df6774de2 100644 --- a/common/models/wordbreakers/src/main/default/index.ts +++ b/common/models/wordbreakers/src/main/default/index.ts @@ -1,4 +1,4 @@ -import { WordBreakProperty, WORD_BREAK_PROPERTY, I, propertyMap } from "./data.js"; +import { WordBreakProperty, WORD_BREAK_PROPERTY, I, propertyMap } from "./data.inc.js"; /** * A set of options used to customize and extend the behavior of the default diff --git a/common/models/wordbreakers/src/main/default/searchForProperty.ts b/common/models/wordbreakers/src/main/default/searchForProperty.ts index 45a1641bd9..fda82dd762 100644 --- a/common/models/wordbreakers/src/main/default/searchForProperty.ts +++ b/common/models/wordbreakers/src/main/default/searchForProperty.ts @@ -1,4 +1,4 @@ -import { WordBreakProperty } from "./data.js"; +import { WordBreakProperty } from "./data.inc.js"; export function searchForProperty(codePoint: number): WordBreakProperty { const bucketSize = codePoint <= 0xFFFF ? 2 : 3; diff --git a/common/models/wordbreakers/src/main/test-index.ts b/common/models/wordbreakers/src/main/test-index.ts index a69cc42ae3..da24a4fcf8 100644 --- a/common/models/wordbreakers/src/main/test-index.ts +++ b/common/models/wordbreakers/src/main/test-index.ts @@ -2,5 +2,5 @@ export * from './index.js'; // Exposes some internal properties for unit-test accessibility -export { WordBreakProperty } from './default/data.js'; +export { WordBreakProperty } from './default/data.inc.js'; export { searchForProperty } from './default/searchForProperty.js'; diff --git a/common/models/wordbreakers/src/data-compiler/index.ts b/common/models/wordbreakers/tools/data-compiler/index.ts similarity index 99% rename from common/models/wordbreakers/src/data-compiler/index.ts rename to common/models/wordbreakers/tools/data-compiler/index.ts index c986d13281..28c52be1aa 100644 --- a/common/models/wordbreakers/src/data-compiler/index.ts +++ b/common/models/wordbreakers/tools/data-compiler/index.ts @@ -31,7 +31,7 @@ const MAX_CODE_POINT = 0x10FFFF; //////////////////////////////////// Main //////////////////////////////////// const projectDir = path.dirname(require.resolve("@keymanapp/models-wordbreakers/README.md")); -const generatedFilename = path.join(projectDir, 'src', 'main', 'default', 'data.ts'); +const generatedFilename = path.join(projectDir, 'src', 'main', 'default', 'data.inc.ts'); // The data files should be in this repository, with names matching the // Unicode version. diff --git a/common/models/wordbreakers/src/data-compiler/tsconfig.json b/common/models/wordbreakers/tools/data-compiler/tsconfig.json similarity index 100% rename from common/models/wordbreakers/src/data-compiler/tsconfig.json rename to common/models/wordbreakers/tools/data-compiler/tsconfig.json From 7016e5b40bdbff256641689a88ad2ffadda22cff Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 8 Aug 2024 12:53:04 +0700 Subject: [PATCH 27/89] chore(common/models): removes incomplete early check-in --- .../src/main/default/searchForProperty.ts | 44 ------------------- .../wordbreakers/src/main/test-index.ts | 1 - 2 files changed, 45 deletions(-) delete mode 100644 common/models/wordbreakers/src/main/default/searchForProperty.ts diff --git a/common/models/wordbreakers/src/main/default/searchForProperty.ts b/common/models/wordbreakers/src/main/default/searchForProperty.ts deleted file mode 100644 index fda82dd762..0000000000 --- a/common/models/wordbreakers/src/main/default/searchForProperty.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { WordBreakProperty } from "./data.inc.js"; - -export function searchForProperty(codePoint: number): WordBreakProperty { - const bucketSize = codePoint <= 0xFFFF ? 2 : 3; - - // SMP chars take a bit more space to encode. - // TODO: encode the strings & import them here. - const encodedArray = bucketSize == 2 ? "" /* BMP string */ : "" /* non-BMP string */; - - return _searchForProperty(encodedArray, codePoint, bucketSize, 0, encodedArray.length / bucketSize - 1); -} - -/** - * Binary search for the word break property of a given CODE POINT. - * - * The auto-generated data.ts master array defines a **character range** - * lookup table. If a character's codepoint is equal to or greater than - * the start-of-range value for an entry and exclusively less than the next - * entry's start-of-range, it falls within the first entry's range bucket - * and is classified accordingly by this method. - */ -function _searchForProperty(encodedArray: string, codePoint: number, bucketSize: number, left: number, right: number): WordBreakProperty { - // All items that are not found in the array are assigned the 'Other' property. - if (right < left) { // May need special handling at end of BMP / start of non-BMP. - return WordBreakProperty.Other; - } - - let midpoint = left + ~~((right - left) / 2); - let candidate = encodedArray.codePointAt(bucketSize * midpoint); - - // If out-of-bounds, gives NaN. - let nextRange = encodedArray.codePointAt(bucketSize * (midpoint + 1)); - let startOfNextRange = isNaN(nextRange) ? Infinity : nextRange; - - if (codePoint < candidate) { - return _searchForProperty(encodedArray, codePoint, bucketSize, left, midpoint - 1); - } else if (codePoint >= startOfNextRange) { - return _searchForProperty(encodedArray, codePoint, bucketSize, midpoint + 1, right); - } - - // We found it! - const propertyCode = encodedArray.charCodeAt(bucketSize * (midpoint + 1) - 1); - return propertyCode as WordBreakProperty; -} \ No newline at end of file diff --git a/common/models/wordbreakers/src/main/test-index.ts b/common/models/wordbreakers/src/main/test-index.ts index da24a4fcf8..6ea7b04532 100644 --- a/common/models/wordbreakers/src/main/test-index.ts +++ b/common/models/wordbreakers/src/main/test-index.ts @@ -3,4 +3,3 @@ export * from './index.js'; // Exposes some internal properties for unit-test accessibility export { WordBreakProperty } from './default/data.inc.js'; -export { searchForProperty } from './default/searchForProperty.js'; From e5387f0947dd226a129384a3b60a4e4d0f5a73ee Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 8 Aug 2024 13:07:56 +0700 Subject: [PATCH 28/89] change(web): Unicode data-fetcher build.sh -> download.sh --- common/models/wordbreakers/build.sh | 3 ++- .../{build.sh => download.sh} | 22 +++++-------------- 2 files changed, 8 insertions(+), 17 deletions(-) rename resources/standards-data/unicode-character-database/{build.sh => download.sh} (77%) diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index 38123ee01c..e0edda0977 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -12,8 +12,9 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ################################ Main script ################################ +# Note: the raw text files used for data.inc.ts are found within +# /resources/standards-data/unicode-character-database. builder_describe "Builds the predictive-text wordbreaker implementation module" \ - "@/resources/standards-data/unicode-character-database configure" \ "clean" \ "configure" \ "build" \ diff --git a/resources/standards-data/unicode-character-database/build.sh b/resources/standards-data/unicode-character-database/download.sh similarity index 77% rename from resources/standards-data/unicode-character-database/build.sh rename to resources/standards-data/unicode-character-database/download.sh index edb3c1e6ba..4b972e7afa 100755 --- a/resources/standards-data/unicode-character-database/build.sh +++ b/resources/standards-data/unicode-character-database/download.sh @@ -1,7 +1,5 @@ #!/usr/bin/env bash -# -# Compile our sourcemap-path remapping module for use by Web builds, releases, etc. -# + ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" @@ -13,12 +11,11 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ################################ Main script ################################ builder_describe \ - "Downloads Unicode data consumed by various Keyman platforms." \ - clean configure build + "Downloads Unicode data files, version $KEYMAN_VERSION_UNICODE (see minimum-versions.inc.sh), to be committed to repo." \ + download+ builder_describe_outputs \ - configure /resources/standards-data/unicode-character-database/UnicodeData.txt \ - build /resources/standards-data/unicode-character-database/UnicodeData.txt + download /resources/standards-data/unicode-character-database/UnicodeData.txt builder_parse "$@" @@ -50,13 +47,7 @@ function downloadPropertyFile() { } } -do_clean() { - mv unicode-copyright.txt unicode-copyright.txt.bak - rm -rf *.txt - mv unicode-copyright.txt.bak unicode-copyright.txt -} - -do_configure() { +do_download() { downloadPropertyFile "${BLOCKS_SRC_HREF}" "${BLOCKS_SRC_LOCAL}" downloadPropertyFile "${UNICODE_DATA_SRC_HREF}" "${UNICODE_DATA_SRC_LOCAL}" @@ -64,5 +55,4 @@ do_configure() { downloadPropertyFile "${EMOJI_DATA_SRC_HREF}" "${EMOJI_DATA_SRC_LOCAL}" } -builder_run_action clean do_clean -builder_run_action configure do_configure \ No newline at end of file +builder_run_action download do_download \ No newline at end of file From 4159bab4586a237b7c846ae9fad8ea27841dc881 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Fri, 9 Aug 2024 09:30:50 +0700 Subject: [PATCH 29/89] fix(common/models): fix unit-test reference to renamed file --- common/models/wordbreakers/test/test-search-property.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/models/wordbreakers/test/test-search-property.js b/common/models/wordbreakers/test/test-search-property.js index cdf80c45f4..85996c7286 100644 --- a/common/models/wordbreakers/test/test-search-property.js +++ b/common/models/wordbreakers/test/test-search-property.js @@ -4,7 +4,7 @@ import { assert } from 'chai'; import { searchForProperty } from '../build/obj/default/searchForProperty.js'; -import { propertyMap } from '../build/obj/default/data.js'; +import { propertyMap } from '../build/obj/default/data.inc.js'; describe('searchForProperty', () => { it('correctly finds character classes for standard ASCII characters', () => { From 2d59ee8a946aa1f4aad818b78b016b01e72d51ab Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Thu, 15 Aug 2024 13:18:05 +0700 Subject: [PATCH 30/89] change(ios): defer registration of fonts past initialization --- ios/engine/KMEI/KeymanEngine/Classes/Manager.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift index 5b77f79307..d1d134b249 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift @@ -831,12 +831,22 @@ public class Manager: NSObject, UIGestureRecognizerDelegate { shared.copyUserDefaults(to: nonShared, withKeys: keysToCopy, shouldOverwrite: true) do { try shared.copyFiles(to: nonShared) - FontManager.shared.registerCustomFonts() } catch { let message = ("Failed to copy from shared container: \(error)") os_log("%{public}s", log:KeymanEngineLogger.settings, type: .error, message) SentryManager.capture(error, message:message) } + + // This operation has a surprisingly high cost and isn't critical + // for getting the keyboard loaded and available to the OS. + // + // We certainly want it done _soon_... but we don't want it to cause + // the primary, synchronous initialization call from the OS to run so + // long that the keyboard fails to start due to its enforced time + // constraints. + DispatchQueue.main.async { + FontManager.shared.registerCustomFonts() + } } } From 72da3d8099d2e890f3941acfa13001684b9da7a4 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 16 Aug 2024 14:59:28 +0700 Subject: [PATCH 31/89] refactor(ios): optimize font registration --- .../Classes/Resource Data/FontManager.swift | 151 ++++++++++++------ 1 file changed, 102 insertions(+), 49 deletions(-) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift index d64019cc27..4a50650100 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift @@ -26,6 +26,17 @@ public class FontManager { fonts[url] = RegisteredFont(name: name, isRegistered: false) return name } + + private func cachedFont(at url: URL) -> RegisteredFont? { + if let font = fonts[url] { + return font + } + guard let name = readFontName(at: url) else { + return nil + } + fonts[url] = RegisteredFont(name: name, isRegistered: false) + return fonts[url] + } /// Registers all new fonts found in the font path. Call this after you have preloaded all your font files /// with `preloadFontFile(atPath:shouldOverwrite:)` @@ -33,8 +44,45 @@ public class FontManager { guard let keyboardDirs = Storage.active.keyboardDirs else { return } + + var fontSet: Set = [] for dir in keyboardDirs { - registerFonts(in: dir) + fontSet = fontSet.union(listFonts(in: dir)) + } + + registerListedFonts(fontSet) + } + + /** + * Iterates across all listed fonts, registering those not yet registered. + * Checks for, and filters out, any fonts already registered on the system. + */ + private func registerListedFonts(_ initialFontSet: Set) { + // If we are unable to read the font file's properties sufficiently, + // skip it. We also don't need to register anything already registered. + var fontSet = initialFontSet.filter { !(cachedFont(at: $0)?.isRegistered ?? true) } + + // The prior line filters out any entries where cachedFont(at: $0) would be nil. + // Batch-lookups all fonts lacking cache-confirmation of prior registration. + var fontNamesToRegister = missingFonts(from: Set(fontSet.map { cachedFont(at: $0)!.name })) + + for fontUrl in fontSet { + let fontName = cachedFont(at: fontUrl)!.name + + guard fontNamesToRegister.contains(fontName) else { + let message = "Did not register font at \(fontUrl) because font name \(fontName) is already registered" + os_log("%{public}s", log:KeymanEngineLogger.resources, type: .info, message) + continue + } + + let didRegister = _registerFont(at: fontUrl) + fonts[fontUrl] = RegisteredFont(name: fontName, isRegistered: didRegister) + + // We no longer need to register a font with this name, so drop it from + // the set to register. + if didRegister { + fontNamesToRegister.remove(fontName) + } } } @@ -43,6 +91,8 @@ public class FontManager { guard let keyboardDirs = Storage.active.keyboardDirs else { return } + // This doesn't use the expensive looped lookup operation seen in missingFonts, + // so there's no need to batch similar operations here. for dir in keyboardDirs { unregisterFonts(in: dir) } @@ -63,44 +113,29 @@ public class FontManager { } return name as String } + + private func _registerFont(at url: URL) -> Bool { + var errorRef: Unmanaged? + let fontName = fontName(at: url)! + let didRegister = CTFontManagerRegisterFontsForURL(url as CFURL, .none, &errorRef) + let error = errorRef?.takeRetainedValue() // Releases errorRef + if !didRegister { + let message = "Failed to register font \(fontName) at \(url) reason: \(String(describing: error))" + os_log("%{public}s", log:KeymanEngineLogger.resources, type: .error, message) + } else { + let message = "Registered font \(fontName) at \(url)" + os_log("%{public}s", log:KeymanEngineLogger.resources, type: .info, message) + } + + return didRegister + } /// - Parameters: /// - url: URL of the font to register /// - Returns: Font is registered. public func registerFont(at url: URL) -> Bool { - let fontName: String - if let font = fonts[url] { - if font.isRegistered { - return true - } - fontName = font.name - } else { - guard let name = readFontName(at: url) else { - return false - } - fontName = name - } - - let didRegister: Bool - if !fontExists(fontName) { - var errorRef: Unmanaged? - didRegister = CTFontManagerRegisterFontsForURL(url as CFURL, .none, &errorRef) - let error = errorRef?.takeRetainedValue() // Releases errorRef - if !didRegister { - let message = "Failed to register font \(fontName) at \(url) reason: \(String(describing: error))" - os_log("%{public}s", log:KeymanEngineLogger.resources, type: .error, message) - } else { - let message = "Registered font \(fontName) at \(url)" - os_log("%{public}s", log:KeymanEngineLogger.resources, type: .info, message) - } - } else { - didRegister = false - let message = "Did not register font at \(url) because font name \(fontName) is already registered" - os_log("%{public}s", log:KeymanEngineLogger.resources, type: .info, message) - } - let font = RegisteredFont(name: fontName, isRegistered: didRegister) - fonts[url] = font - return didRegister + registerListedFonts([url]) + return fonts[url]?.isRegistered ?? false } /// - Parameters: @@ -133,32 +168,50 @@ public class FontManager { return font.isRegistered } - - public func registerFonts(in directory: URL) { + + private func listFonts(in directory: URL) -> [URL] { guard let urls = try? FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) else { let message = "Could not list contents of directory \(directory)" os_log("%{public}s", log:KeymanEngineLogger.resources, type: .error, message) - return - } - for url in urls where url.lastPathComponent.hasFontExtension { - _ = registerFont(at: url) + return [] } + return urls.filter { $0.lastPathComponent.hasFontExtension } + } + + public func registerFonts(in directory: URL) { + let fontsToRegister = listFonts(in: directory) + registerListedFonts(Set(fontsToRegister)) } public func unregisterFonts(in directory: URL, fromSystemOnly: Bool = true) { - guard let urls = try? FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) else { - let message = "Could not list contents of directory \(directory)" - os_log("%{public}s", log:KeymanEngineLogger.resources, type: .error, message) - return - } - for url in urls where url.lastPathComponent.hasFontExtension { + let fontsToUnregister = listFonts(in: directory) + for url in fontsToUnregister { _ = unregisterFont(at: url, fromSystemOnly: fromSystemOnly) } } - private func fontExists(_ fontName: String) -> Bool { - return UIFont.familyNames.contains { familyName in - UIFont.fontNames(forFamilyName: familyName).contains(fontName) + /** + * Queries the system for existing registrations for the specified fonts with a single batch run. + * Only fonts that could not be found will be returned within the result set. + */ + private func missingFonts(from fontNames: Set) -> Set { + // Arrays are treated 'by value'; it's already a shallow copy. + var fontsToFind = fontNames + + UIFont.familyNames.forEach { familyName in + let familyFonts = UIFont.fontNames(forFamilyName: familyName) + + for font in familyFonts { + if let index = fontsToFind.firstIndex(where: { $0 == font }) { + fontsToFind.remove(at: index) + } + + if fontsToFind.count == 0 { + break + } + } } + + return fontsToFind } } From e28d8a341a02477cab1b7e841187679917d5048c Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 16 Aug 2024 15:15:32 +0700 Subject: [PATCH 32/89] change(ios): cleaner set-based fonts-to-find maintenance --- .../KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift index 4a50650100..6dd114d375 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift @@ -202,8 +202,8 @@ public class FontManager { let familyFonts = UIFont.fontNames(forFamilyName: familyName) for font in familyFonts { - if let index = fontsToFind.firstIndex(where: { $0 == font }) { - fontsToFind.remove(at: index) + if fontsToFind.contains(font) { + fontsToFind.remove(font) } if fontsToFind.count == 0 { From 289dda0fcab73ae94938e9a69ec599f2c7efb0cf Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 16 Aug 2024 15:17:05 +0700 Subject: [PATCH 33/89] change(ios): better early-exit if all font data found --- .../KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift index 6dd114d375..9f0047d7f7 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift @@ -199,6 +199,10 @@ public class FontManager { var fontsToFind = fontNames UIFont.familyNames.forEach { familyName in + if fontsToFind.count == 0 { + return + } + let familyFonts = UIFont.fontNames(forFamilyName: familyName) for font in familyFonts { From c712d35984d4bad2d515a2852953af17d804ffe5 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 19 Aug 2024 12:16:04 +0700 Subject: [PATCH 34/89] chore(ios): adjustments per review --- .../KeymanEngine/Classes/Resource Data/FontManager.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift index 9f0047d7f7..6070de2c96 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift @@ -56,10 +56,15 @@ public class FontManager { /** * Iterates across all listed fonts, registering those not yet registered. * Checks for, and filters out, any fonts already registered on the system. + * Also initializes the registration cache per URL if needed. */ private func registerListedFonts(_ initialFontSet: Set) { // If we are unable to read the font file's properties sufficiently, - // skip it. We also don't need to register anything already registered. + // skip it. We also don't need to register anything already registered or + // that cannot be registered due to loading/parsing errors. + // + // Calls to `cachedFont` after the `.filter` below may be assumed to have + // non-nil return values. var fontSet = initialFontSet.filter { !(cachedFont(at: $0)?.isRegistered ?? true) } // The prior line filters out any entries where cachedFont(at: $0) would be nil. @@ -195,7 +200,6 @@ public class FontManager { * Only fonts that could not be found will be returned within the result set. */ private func missingFonts(from fontNames: Set) -> Set { - // Arrays are treated 'by value'; it's already a shallow copy. var fontsToFind = fontNames UIFont.familyNames.forEach { familyName in From 97697b695ff85eed11047489b08c1f9299f559ca Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 14:19:14 +0700 Subject: [PATCH 35/89] fix(web): fix documentation-keyboard spacebar-text scaling Fixes: #12231 --- web/src/engine/osk/src/visualKeyboard.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index 26b269d7f2..0d529af651 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1246,6 +1246,7 @@ export default class VisualKeyboard extends EventEmitter implements Ke const groupStyle = getComputedStyle(this.layerGroup.element); const isInDOM = computedStyle.height != '' && computedStyle.height != 'auto'; + const isGroupInDOM = groupStyle.height != '' && groupStyle.height != 'auto'; if (computedStyle.border) { this._borderWidth = new ParsedLengthStyle(computedStyle.borderWidth).val; @@ -1258,10 +1259,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke this._computedHeight = this.height; } else if (isInDOM) { this._computedWidth = parseInt(computedStyle.width, 10); - if (!this._computedWidth) { - this._computedWidth = parseInt(groupStyle.width, 10); - } this._computedHeight = parseInt(computedStyle.height, 10); + } else if (isGroupInDOM) { + // May occur for documentation-keyboards, which are detached from their VisualKeyboard base. + this._computedWidth = parseInt(groupStyle.width, 10); + this._computedHeight = parseInt(groupStyle.height, 10); } else { // Cannot perform layout operations! return; @@ -1604,6 +1606,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke // the page. kbdObj.appendStyleSheet(); + // Unset the width + height we used thus far; this method's consumer may choose to rescale + // the returned element. If so, we don't want to use our outdated value by mistake. + delete kbdObj._width; + delete kbdObj._height; + return classWrapper; } From 23e02d2a86812e7807fdad6304db99abf1d773de Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 14:38:58 +0700 Subject: [PATCH 36/89] change(web): better way to re-establish default sizing --- web/src/engine/osk/src/visualKeyboard.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index 0d529af651..a70c6b68ed 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1608,8 +1608,7 @@ export default class VisualKeyboard extends EventEmitter implements Ke // Unset the width + height we used thus far; this method's consumer may choose to rescale // the returned element. If so, we don't want to use our outdated value by mistake. - delete kbdObj._width; - delete kbdObj._height; + kbdObj.setSize(); return classWrapper; } From 01ae0c0a9ac23df03482223390a1a8f0ceba3d43 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 14:40:24 +0700 Subject: [PATCH 37/89] chore(web): Revert "change(web): better way to re-establish default sizing" This reverts commit 23e02d2a86812e7807fdad6304db99abf1d773de. --- web/src/engine/osk/src/visualKeyboard.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index a70c6b68ed..0d529af651 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1608,7 +1608,8 @@ export default class VisualKeyboard extends EventEmitter implements Ke // Unset the width + height we used thus far; this method's consumer may choose to rescale // the returned element. If so, we don't want to use our outdated value by mistake. - kbdObj.setSize(); + delete kbdObj._width; + delete kbdObj._height; return classWrapper; } From 5c96f8f76921ef23f70a827eb483f5f60580b23a Mon Sep 17 00:00:00 2001 From: sgschantz Date: Tue, 20 Aug 2024 16:14:40 +0700 Subject: [PATCH 38/89] fix(mac): remove text from short bundle version string in info.plist for both input method and engine, remove the framing text so that it just contains the version number triplet Fixes: #12197 --- mac/Keyman4MacIM/Keyman4MacIM/Info.plist | 2 +- mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/Info.plist b/mac/Keyman4MacIM/Keyman4MacIM/Info.plist index 29451d4cce..49f532055e 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/Info.plist +++ b/mac/Keyman4MacIM/Keyman4MacIM/Info.plist @@ -36,7 +36,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - Keyman $(PRODUCT_VERSION) for macOS + $(PRODUCT_VERSION) CFBundleSignature ???? CFBundleURLTypes diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist b/mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist index 970606a26a..3f42d3e63f 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - Keyman Engine $(PRODUCT_VERSION) for macOS + $(PRODUCT_VERSION) CFBundleSignature ???? CFBundleVersion From 45dee1c504afdd40f5df000b08d07f7a810acbb3 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 21 Aug 2024 09:05:48 +0700 Subject: [PATCH 39/89] docs(web): extends doc-comment per review comment --- web/src/engine/osk/src/visualKeyboard.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index 0d529af651..3a439c1db4 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1608,6 +1608,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke // Unset the width + height we used thus far; this method's consumer may choose to rescale // the returned element. If so, we don't want to use our outdated value by mistake. + // + // While `kbdObj.setSize()` could be used in theory, it _also_ unsets the element styling. + // We actually wish to _leave_ this styling in place - one of our parameters is `height`, and + // it should remain in place in the styling on the output element as the default in case + // the consumer _doesn't_ add styling afterward. delete kbdObj._width; delete kbdObj._height; From dc434a776a59dcbf417730c3a3753fd97b44c04c Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 21 Aug 2024 10:51:35 +0700 Subject: [PATCH 40/89] fix(android): Use increment and decrement arrows on longpress delay --- .../src/main/res/layout/activity_adjust_longpress_delay.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml index ed0bed54a9..ef1ebd613b 100644 --- a/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml +++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml @@ -23,7 +23,7 @@ android:layout_marginStart="5dp" android:layout_marginEnd="5dp" android:contentDescription="@string/ic_delay_time_down" - android:src="@drawable/ic_light_dialog_textsize_down" /> + android:src="@drawable/ic_action_decrement" /> + android:src="@drawable/ic_action_increment" /> From 88df68cf9f96308431f6dbf843adabe9d75c42bb Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 21 Aug 2024 10:53:57 +0700 Subject: [PATCH 41/89] chore(common/models): reorganize wordbreaker build outputs --- common/models/wordbreakers/build.sh | 6 +++--- common/models/wordbreakers/package.json | 12 ++++++------ .../wordbreakers/tools/data-compiler/tsconfig.json | 4 ++-- common/models/wordbreakers/tsconfig.json | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index e0edda0977..0cad38b1fe 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -23,7 +23,7 @@ builder_describe "Builds the predictive-text wordbreaker implementation module" builder_describe_outputs \ configure src/main/default/data.inc.ts \ - build build/obj/index.js + build build/main/obj/index.js builder_parse "$@" @@ -34,14 +34,14 @@ function do_configure() { # default wordbreaker. We rarely update the backing data, but it # is needed _before_ the `build` action's compilation step. tsc -b tools/data-compiler/tsconfig.json - node ./build/obj/data-compiler/index.js + node ./build/data-compiler/obj/index.js } function do_build() { tsc -b ./tsconfig.json # Declaration bundling. - tsc -p ./tsconfig.json --emitDeclarationOnly --outFile ./build/lib/index.d.ts + tsc -p ./tsconfig.json --emitDeclarationOnly --outFile ./build/main/lib/index.d.ts } function do_test() { diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index d433bcdff4..f896050ecb 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -14,19 +14,19 @@ ], "homepage": "https://github.com/keymanapp/keyman", "license": "MIT", - "main": "build/obj/index.js", - "types": "build/obj/index.d.ts", + "main": "build/main/obj/index.js", + "types": "build/main/obj/index.d.ts", "exports": { ".": { "es6-bundling": "./src/main/index.ts", - "default": "./build/obj/index.js" + "default": "./build/main/obj/index.js" }, "./lib": { - "types": "./build/lib/index.d.ts" + "types": "./build/main/lib/index.d.ts" }, - "./obj/*.js": "./build/obj/*.js", + "./obj/*.js": "./build/main/obj/*.js", "./test-index": { - "default": "./build/obj/test-index.js" + "default": "./build/main/obj/test-index.js" }, "./README.md": { "default": "./README.md" diff --git a/common/models/wordbreakers/tools/data-compiler/tsconfig.json b/common/models/wordbreakers/tools/data-compiler/tsconfig.json index 19f5dfbab0..74a8bb005e 100644 --- a/common/models/wordbreakers/tools/data-compiler/tsconfig.json +++ b/common/models/wordbreakers/tools/data-compiler/tsconfig.json @@ -3,8 +3,8 @@ "compilerOptions": { "baseUrl": "./", - "outDir": "../../build/obj/data-compiler", - "tsBuildInfoFile": "../../build/obj/data-compiler/tsconfig.tsbuildinfo", + "outDir": "../../build/data-compiler/obj", + "tsBuildInfoFile": "../../build/data-compiler/obj/tsconfig.tsbuildinfo", "rootDir": "./", "module": "node16", "moduleResolution": "node16" diff --git a/common/models/wordbreakers/tsconfig.json b/common/models/wordbreakers/tsconfig.json index 64d193242d..46095418b2 100644 --- a/common/models/wordbreakers/tsconfig.json +++ b/common/models/wordbreakers/tsconfig.json @@ -3,8 +3,8 @@ "compilerOptions": { "baseUrl": "./", - "outDir": "./build/obj", - "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", + "outDir": "./build/main/obj", + "tsBuildInfoFile": "./build/main/obj/tsconfig.tsbuildinfo", "rootDir": "./src/main" }, "references": [ From a26389bfeabe4313e77e4afad4530f90fa4ed907 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Wed, 21 Aug 2024 11:12:43 +0700 Subject: [PATCH 42/89] test(mac): removed commented code --- mac/Keyman4MacIM/KeymanTests/InputMethodTests.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m b/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m index a2953c44cf..7372a2a548 100644 --- a/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m +++ b/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m @@ -96,7 +96,6 @@ id testClient = nil; */ - (void)testCheckCompliance_withUnknownApplicationId_createsComplianceObject { id client = [[AppleCompliantTestClient alloc] init]; - //NSString *clientAppId = @"com.compliant.app"; KMInputMethodEventHandler *eventHandler = [[KMInputMethodEventHandler alloc]initWithClient:nil client:client]; [eventHandler checkTextApiCompliance:client]; XCTAssertNotNil(eventHandler.apiCompliance, @"apiCompliance object was not created"); @@ -129,7 +128,4 @@ id testClient = nil; XCTAssertNotEqualObjects(originalComplianceObject, testEventHandler.apiCompliance, @"New TextApiCompliance object not created after contextChanged flag set"); } - - - @end From 17f903d4c70efb164fa29534acc6766c74373de9 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 21 Aug 2024 15:08:51 +0700 Subject: [PATCH 43/89] fix(android): Fix navigation arrows in Info Activity for RTL --- .../src/main/res/layout/activity_info.xml | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml index 3b71e87178..314a503412 100644 --- a/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml +++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml @@ -1,12 +1,12 @@ + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:background="@color/ms_white" + tools:context=".InfoActivity" > - - + android:orientation="horizontal"> - + + + + + Date: Wed, 21 Aug 2024 18:57:45 +0200 Subject: [PATCH 44/89] docs: refresh windows.md @keymanapp-test-bot skip --- docs/build/windows.md | 177 +++++++++++++++++------------------------- 1 file changed, 72 insertions(+), 105 deletions(-) diff --git a/docs/build/windows.md b/docs/build/windows.md index dcb55ce4a4..bb8ce8f0fe 100644 --- a/docs/build/windows.md +++ b/docs/build/windows.md @@ -63,10 +63,6 @@ Dependencies: * [Base](#base-dependencies) * [Windows Platform](#windows-platform-dependencies) -**Note**: Keyman for Windows is currently built together with Keyman Developer. -We are working on splitting these projects. For now, you will need the Keyman -Developer dependencies as well. - Building: * [Building Keyman for Windows](../../windows/src/README.md) @@ -75,7 +71,7 @@ Building: Dependencies: * [Base](#base-dependencies) * [Web](#web-dependencies) -* [Windows Platform](#windows-platform-dependencies) +* [Windows Platform](#windows-platform-dependencies) (optional, for Windows-only components) Building: * [Building Keyman Developer](../../windows/src/README.md) @@ -94,42 +90,19 @@ Building: **Dependencies**: * [Base](#base-dependencies) * [Web](#web-dependencies) - -**Additional requirements**: -* Android SDK -* Android Studio -* Ant -* Gradle -* Maven -* Optional: OpenJDK 11 (https://learn.microsoft.com/en-us/java/openjdk/download) - -```ps1 -# Elevated PowerShell -choco install android-sdk android-studio ant gradle maven -# optionally install sdk images -sdkmanager "system-images;android-33;google_apis;armeabi-v7a" -sdkmanager --update -sdkmanager --licenses -``` - -* Run Android Studio once after installation to install additional components - such as emulator images and SDK updates. - -**Required environment variables**: -* [`JAVA_HOME`](#java_home) - -**Optional environment variables**: -* [`JAVA_HOME_11`](#java_home) +* [Android](#android-dependencies) Building: * [Building Keyman for Android](../../android/README.md) -## Prerequisites +--- + +## Dependencies and Prerequisites Many dependencies are only required for specific projects. We prefer [Chocolatey](https://chocolatey.org/install) at present for -installation of dependencies. Chocolatey should be run in an elevated +installation of most dependencies. Chocolatey should be run in an elevated PowerShell. ### Base Dependencies @@ -155,11 +128,9 @@ refreshenv **Environment variables**: * [`KEYMAN_ROOT`](#keyman_root) -* `PATH`: add your Python scripts folder to your path: it will normally be `%appdata%\Python\Python310\Scripts`. ```bat SET KEYMAN_ROOT=c:\Projects\keyman\keyman -SET PATH=%path%;%appdata%\Python\Python310\Scripts ``` To check whether environment variables are set, run `SET ` in command @@ -181,31 +152,37 @@ You can use Windows Settings to add these environment variables permanently: * KeymanWeb **Requirements**: -* emscripten 3.1.46 or later -* node.js 18+ -* [openjdk 11](https://learn.microsoft.com/en-us/java/openjdk/download#openjdk-11)+ +* Emscripten +* node.js -```ps1 -# Elevated PowerShell +#### Emscripten -# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138) -$ProgressPreference = 'SilentlyContinue' +In an appropriate folder, e.g. `/c/Projects/keyman/`, in bash, run the following commands: -choco install emscripten --version 3.1.46 +```bash +git clone https://github.com/emscripten-core/emsdk +cd emsdk +emsdk install 3.1.58 +emsdk activate 3.1.58 ``` Note: emscripten very unhelpfully overwrites JAVA_HOME, and adds its own -versions of Python, Node and Java to the PATH. For best results, go ahead -and remove those paths from your PATH variable before continuing. +versions of Python, Node and Java to the PATH. For best results, restart +your shell after installing Emscripten so that you don't end up with the +wrong versions. There is no need to add emscripten to the path in order to build Keyman. However, you should set the EMSCRIPTEN_BASE variable to the path where `emcc` can be found, but always in the upstream\emscripten subdirectory where you -installed emsdk (most likely %LocalAppData%\emsdk\upstream\emscripten) +installed emsdk. **Environment variables**: * `EMSCRIPTEN_BASE`: `\upstream\emscripten` +**Optional environment variables**: +* `KEYMAN_USE_EMSDK`: `1` to let the Keyman build scripts control the + version of Emscripten installed on your computer. + After installing emscripten, you'll need to install node.js and openjdk. #### node.js @@ -214,30 +191,17 @@ Our recommended way to install node.js is to use [nvm-windows](https://github.com/coreybutler/nvm-windows). This makes it easy to switch between versions of node.js. -Alternatively, use Powershell + Chocolatey to install node.js: - -```ps1 -# Elevated PowerShell - -# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138) -$ProgressPreference = 'SilentlyContinue' -choco install nodejs +``` +nvm install 20.16.0 +nvm use 20.16.0 ``` -See [node.md](node.md) for more information. - -#### openjdk - -Use Powershell + Chocolatey to install OpenJDK: - -```ps1 -# Elevated PowerShell - -# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138) -$ProgressPreference = 'SilentlyContinue' -choco install openjdk -``` +**Optional environment variables**: +* `KEYMAN_USE_NVM`: `1` to let the Keyman build scripts control the + version of node.js installed and active on your computer. +See [node.md](node.md) for more information, including automatic selection +of appropriate node versions during builds. ### Windows Platform Dependencies @@ -260,8 +224,7 @@ choco install openjdk Start Delphi IDE once after installation as it will create various environment files and take you through required registration. - * Note: It is possible to build all components that do _not_ require Delphi by - adding the environment variable `NODELPHI=1` before starting the build. + * Note: It is possible to build all components that do _not_ require Delphi. Currently many components are Delphi-based, but if you are working just in Keyman Core, the compiler, or Keyman Engine's C++ components, you may be able to get away without building them. In this situation, we recommend @@ -291,13 +254,8 @@ choco install openjdk Keyman's design-time packages to load in Delphi. * [`KEYMAN_CEF4DELPHI_ROOT`](#keyman_cef4delphi_root) -**Optional environment variables**: -* [`GIT_BASH_FOR_KEYMAN`](#git_bash_for_keyman) -* [`USERDEFINES`](#userdefines) - ```bat SET KEYMAN_CEF4DELPHI_ROOT=c:\Projects\keyman\CEF4Delphi_Binary -SET GIT_BASH_FOR_KEYMAN="C:\Program Files\Git\bin\bash.exe" --init-file "c:\Program Files\Git\etc\profile" -l ``` **Additional requirements for release builds**: @@ -314,6 +272,46 @@ choco install wixtoolset --version=3.11.1 git clone https://github.com/keymanapp/CEF4Delphi_Binary C:\Projects\keyman\CEF4Delphi_Binary ``` +### Android dependencies + +**Projects**: +* Keyman for Android + +**Requirements**: +* Android SDK +* Android Studio +* Ant +* Gradle +* Maven +* Optional: OpenJDK 11 (https://learn.microsoft.com/en-us/java/openjdk/download) + +```ps1 +# Elevated PowerShell +choco install android-sdk android-studio ant gradle maven +# optionally install sdk images +sdkmanager "system-images;android-33;google_apis;armeabi-v7a" +sdkmanager --update +sdkmanager --licenses +``` + +#### openjdk + +Use Powershell + Chocolatey to install OpenJDK: + +```ps1 +# Elevated PowerShell + +# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138) +$ProgressPreference = 'SilentlyContinue' +choco install openjdk +``` + +* Run Android Studio once after installation to install additional components + such as emulator images and SDK updates. + +**Required environment variables**: +* [`JAVA_HOME`](#java_home) + ## Certificates In order to make a release build, you need to sign all the executables. See @@ -349,41 +347,10 @@ release build, the common/windows/cef-checkout.sh script will checkout the corre branch of the repository automatically and extract any compressed files found in it. -### GIT_BASH_FOR_KEYMAN - -This environment variable is optional: the build will run bash in a separate -window in order to build KeymanWeb if it isn't present, but you'll lose logging -and have the annoyance of a window popping up halfway through the build. To -resolve both of those issues, set the environment variable to: - -```bat -SET GIT_BASH_FOR_KEYMAN="C:\Program Files\Git\bin\bash.exe" --init-file "c:\Program Files\Git\etc\profile" -l -``` - -You should verify the install location of Git on your computer as it may vary. - -### USERDEFINES - -You can specify defines that will not be added to the git repository and will be -used in the build in the UserDefines.mak file in the root folder. This is used -mostly for code signing certificates. If not specified, a test certificate will -be used to sign executables when you build a release. - -To include UserDefines.mak in the build, use the command line parameter -`-DUSERDEFINES`. You can also set an environment variable `USERDEFINES=1` to get -the same result. - ### JAVA_HOME This environment variable tells Gradle what version of Java to use for building Keyman for Android. -**Multiple versions of Java:** If you need to build Keyman for Android 16.0 or older versions, you can set `JAVA_HOME_11` to the OpenJDK 11 path and `JAVA_HOME` to the OpenJDK 8 path. This will build both versions correctly from command line. But note that you do need to update your `JAVA_HOME` env var to the associated version before opening Android Studio and loading any Android projects. `JAVA_HOME_11` is mostly used by CI. - -```bat -SET JAVA_HOME="path to OpenJDK 8" -SET JAVA_HOME_11="path to OpenJDK 11" -``` - ## Optional Tools * sentry-cli (optional) From 002970d7cb750b00c38757e91978db27bdfa00de Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 21 Aug 2024 19:10:56 +0200 Subject: [PATCH 45/89] Update windows.md --- docs/build/windows.md | 115 +++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 52 deletions(-) diff --git a/docs/build/windows.md b/docs/build/windows.md index bb8ce8f0fe..83839f91a1 100644 --- a/docs/build/windows.md +++ b/docs/build/windows.md @@ -127,22 +127,32 @@ refreshenv ``` **Environment variables**: -* [`KEYMAN_ROOT`](#keyman_root) + +If you pull the entire `keyman.git` repo to `c:\keyman`, then the paths by +default will work without changes. Otherwise, you will need to set an +environment variable `KEYMAN_ROOT` to the root path of the Keyman repo. For +example: ```bat -SET KEYMAN_ROOT=c:\Projects\keyman\keyman +SETX KEYMAN_ROOT "c:\Projects\keyman\keyman" ``` -To check whether environment variables are set, run `SET ` in command -prompt. +> [!NOTE] +> The `SETX` command will set persistent environment variables but they do not +> impact the current shell environment. Start a new shell to see the variables. -You can use Windows Settings to add these environment variables permanently: - -1. In Windows Search, type "environment" and select "Edit System Environment - Variables" -2. Click `Environment Variables...` -3. You can add or edit variables in either User or System settings, as you - prefer. +> [!TIP] +> +> To check whether environment variables are set, run `SET ` in command +> prompt. +> +> You can use Windows Settings to add these environment variables permanently: +> +> 1. In Windows Search, type "environment" and select "Edit System Environment +> Variables" +> 2. Click `Environment Variables...` +> 3. You can add or edit variables in either User or System settings, as you +> prefer. ### Web Dependencies @@ -177,11 +187,19 @@ can be found, but always in the upstream\emscripten subdirectory where you installed emsdk. **Environment variables**: -* `EMSCRIPTEN_BASE`: `\upstream\emscripten` + +```bat +SETX EMSCRIPTEN_BASE "\upstream\emscripten" +``` **Optional environment variables**: -* `KEYMAN_USE_EMSDK`: `1` to let the Keyman build scripts control the - version of Emscripten installed on your computer. + +To let the Keyman build scripts control the version of Emscripten +installed on your computer: + +```bat +SETX KEYMAN_USE_EMSDK 1 +``` After installing emscripten, you'll need to install node.js and openjdk. @@ -191,14 +209,19 @@ Our recommended way to install node.js is to use [nvm-windows](https://github.com/coreybutler/nvm-windows). This makes it easy to switch between versions of node.js. -``` +```bat nvm install 20.16.0 nvm use 20.16.0 ``` **Optional environment variables**: -* `KEYMAN_USE_NVM`: `1` to let the Keyman build scripts control the - version of node.js installed and active on your computer. + +To let the Keyman build scripts control the version of node.js installed +and active on your computer: + +```bat +SETX KEYMAN_USE_NVM 1 +```` See [node.md](node.md) for more information, including automatic selection of appropriate node versions during builds. @@ -252,10 +275,27 @@ of appropriate node versions during builds. * Add the C:\Projects\keyman\keyman\windows\lib folder in the Keyman repository to your `PATH` environment variable. This is required for Keyman's design-time packages to load in Delphi. -* [`KEYMAN_CEF4DELPHI_ROOT`](#keyman_cef4delphi_root) + +### KEYMAN_CEF4DELPHI_ROOT + +Keyman and Keyman Developer use Chromium Embedded Framework. The source repo is +at https://github.com/keymanapp/CEF4Delphi. In order to build the installers, we +need to source the binary files from the +https://github.com/keymanapp/CEF4Delphi_binary repo. The +`KEYMAN_CEF4DELPHI_ROOT` environment variable should be set to the root of this +repo on your local machine. + +The version of CEF in use is determined by CEF_VERSION.md. This maps to a branch +prefixed with `v` e.g. `v89.0.18` in the CEF4Delphi_binary repository. During a +release build, the common/windows/cef-checkout.sh script will checkout the correct +branch of the repository automatically and extract any compressed files found in +it. + +The [`KEYMAN_CEF4DELPHI_ROOT`](#keyman_cef4delphi_root) variable is +used to specify the path to the CEF4Delphi binaries. ```bat -SET KEYMAN_CEF4DELPHI_ROOT=c:\Projects\keyman\CEF4Delphi_Binary +SETX KEYMAN_CEF4DELPHI_ROOT "c:\Projects\keyman\CEF4Delphi_Binary" ``` **Additional requirements for release builds**: @@ -309,8 +349,11 @@ choco install openjdk * Run Android Studio once after installation to install additional components such as emulator images and SDK updates. + ## Certificates @@ -319,38 +362,6 @@ In order to make a release build, you need to sign all the executables. See for details on how to create test code signing certificates or specify your own certificates for the build. -## Notes on Environment Variables - -### KEYMAN_ROOT - -If you pull the entire `keyman.git` repo to `c:\keyman`, then the paths by -default will work without changes. Otherwise, you will need to set an -environment variable `KEYMAN_ROOT` to the root path of the Keyman repo. For -example: - -```bat -SET KEYMAN_ROOT=c:\projects\keyman\keyman -``` - -### KEYMAN_CEF4DELPHI_ROOT - -Keyman and Keyman Developer use Chromium Embedded Framework. The source repo is -at https://github.com/keymanapp/CEF4Delphi. In order to build the installers, we -need to source the binary files from the -https://github.com/keymanapp/CEF4Delphi_binary repo. The -`KEYMAN_CEF4DELPHI_ROOT` environment variable should be set to the root of this -repo on your local machine. - -The version of CEF in use is determined by CEF_VERSION.md. This maps to a branch -prefixed with `v` e.g. `v89.0.18` in the CEF4Delphi_binary repository. During a -release build, the common/windows/cef-checkout.sh script will checkout the correct -branch of the repository automatically and extract any compressed files found in -it. - -### JAVA_HOME - -This environment variable tells Gradle what version of Java to use for building Keyman for Android. - ## Optional Tools * sentry-cli (optional) From b87b107966dab09840bab8503f58dd54355767c5 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 21 Aug 2024 22:12:00 +0200 Subject: [PATCH 46/89] Update windows.md --- docs/build/windows.md | 47 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/docs/build/windows.md b/docs/build/windows.md index 83839f91a1..47b3e8696d 100644 --- a/docs/build/windows.md +++ b/docs/build/windows.md @@ -6,13 +6,13 @@ On Windows, you can build the following projects: * [Keyman for Android](#keyman-for-android) * [Keyman for Windows](#keyman-for-windows) -* [Keyman Developer](#keyman-developer) (together with Keyman for Windows) +* [Keyman Developer](#keyman-developer) * [KeymanWeb](#keymanweb) The following libraries can also be built: -* Keyman Core (Windows, wasm targets) (aka core) -* Common/Web +* Keyman Core (Windows, wasm targets) +* Common libraries The following projects **cannot** be built on Windows: @@ -123,7 +123,6 @@ PowerShell. # for *much* faster download, hide progress bar (PowerShell/PowerShell#2138) $ProgressPreference = 'SilentlyContinue' choco install git jq python ninja pandoc meson -refreshenv ``` **Environment variables**: @@ -146,7 +145,8 @@ SETX KEYMAN_ROOT "c:\Projects\keyman\keyman" > To check whether environment variables are set, run `SET ` in command > prompt. > -> You can use Windows Settings to add these environment variables permanently: +> You can alternatively use Windows Settings to add these environment variables +> permanently: > > 1. In Windows Search, type "environment" and select "Edit System Environment > Variables" @@ -167,24 +167,26 @@ SETX KEYMAN_ROOT "c:\Projects\keyman\keyman" #### Emscripten -In an appropriate folder, e.g. `/c/Projects/keyman/`, in bash, run the following commands: +In bash, run the following commands: ```bash +cd /c/Projects/keyman git clone https://github.com/emscripten-core/emsdk cd emsdk emsdk install 3.1.58 emsdk activate 3.1.58 ``` -Note: emscripten very unhelpfully overwrites JAVA_HOME, and adds its own -versions of Python, Node and Java to the PATH. For best results, restart -your shell after installing Emscripten so that you don't end up with the -wrong versions. +> ![WARNING] +> Emscripten very unhelpfully overwrites `JAVA_HOME`, and adds its own +> versions of Python, Node and Java to the `PATH`. For best results, restart +> your shell after installing Emscripten so that you don't end up with the +> wrong versions. There is no need to add emscripten to the path in order to build Keyman. -However, you should set the EMSCRIPTEN_BASE variable to the path where `emcc` -can be found, but always in the upstream\emscripten subdirectory where you -installed emsdk. +However, you should set the `EMSCRIPTEN_BASE` variable to the path where `emcc` +can be found, in the `upstream\emscripten` subdirectory of where you installed +emsdk. **Environment variables**: @@ -259,10 +261,12 @@ of appropriate node versions during builds. ```ps1 choco install visualstudio2019community visualstudio2019-workload-nativedesktop visualstudio2019buildtools ``` + * Verify required build tools are installed * Run `Visual Studio Installer` * Check the `Individual components` tab - * Verify `MSVC v142 - VS 2019 c++ x64/x86 build tools (Latest)` is installed. If not, install it. + * Verify `MSVC v142 - VS 2019 c++ x64/x86 build tools (Latest)` is installed. + If not, install it. Recommended: configure Visual Studio to use two-space tab stops: 1. Open the options dialog: Tools > Options. @@ -272,7 +276,7 @@ of appropriate node versions during builds. **Required environment variables**: * `PATH` - * Add the C:\Projects\keyman\keyman\windows\lib folder in the Keyman + * Add the `C:\Projects\keyman\keyman\windows\lib` folder in the Keyman repository to your `PATH` environment variable. This is required for Keyman's design-time packages to load in Delphi. @@ -327,7 +331,12 @@ git clone https://github.com/keymanapp/CEF4Delphi_Binary C:\Projects\keyman\CEF4 ```ps1 # Elevated PowerShell -choco install android-sdk android-studio ant gradle maven +choco install android-sdk androidstudio ant gradle maven +``` + +Start a new shell to get the new paths and then update Android SDKs: + +```ps1 # optionally install sdk images sdkmanager "system-images;android-33;google_apis;armeabi-v7a" sdkmanager --update @@ -349,12 +358,6 @@ choco install openjdk * Run Android Studio once after installation to install additional components such as emulator images and SDK updates. - - ## Certificates In order to make a release build, you need to sign all the executables. See From f0dbcd639330416cbe20789f45fed0b998541825 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 22 Aug 2024 09:28:21 +0200 Subject: [PATCH 47/89] Update windows.md --- docs/build/windows.md | 47 +++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/docs/build/windows.md b/docs/build/windows.md index 47b3e8696d..663b68c2f8 100644 --- a/docs/build/windows.md +++ b/docs/build/windows.md @@ -203,8 +203,6 @@ installed on your computer: SETX KEYMAN_USE_EMSDK 1 ``` -After installing emscripten, you'll need to install node.js and openjdk. - #### node.js Our recommended way to install node.js is to use @@ -327,32 +325,41 @@ git clone https://github.com/keymanapp/CEF4Delphi_Binary C:\Projects\keyman\CEF4 * Ant * Gradle * Maven -* Optional: OpenJDK 11 (https://learn.microsoft.com/en-us/java/openjdk/download) +* JDK 11 (Temurin11) -```ps1 -# Elevated PowerShell -choco install android-sdk androidstudio ant gradle maven -``` +#### JDK 11 -Start a new shell to get the new paths and then update Android SDKs: - -```ps1 -# optionally install sdk images -sdkmanager "system-images;android-33;google_apis;armeabi-v7a" -sdkmanager --update -sdkmanager --licenses -``` - -#### openjdk - -Use Powershell + Chocolatey to install OpenJDK: +Use Powershell + Chocolatey to install JDK 11: ```ps1 # Elevated PowerShell # for *much* faster download, hide progress bar (PowerShell/PowerShell#2138) $ProgressPreference = 'SilentlyContinue' -choco install openjdk +choco install temurin11 +``` + +**Multiple versions of Java:** If you need to build Keyman for Android 16.0 or +older versions, you can set `JAVA_HOME_11` to the JDK 11 path and +`JAVA_HOME` to the JDK 8 path. This will build both versions correctly +from command line. But note that you do need to update your `JAVA_HOME` env +var to the associated version before opening Android Studio and loading any +Android projects. `JAVA_HOME_11` is mostly used by CI. + +#### Android Studio and friends + +```ps1 +# Elevated PowerShell +choco install androidstudio ant gradle maven android-sdk +``` + +Start a new shell to get the new paths and then update Android SDKs: + +```ps1 +# optionally install sdk images +sdkmanager --update +# sdkmanager "system-images;android-33;google_apis;armeabi-v7a" +sdkmanager --licenses ``` * Run Android Studio once after installation to install additional components From 012bbb4c69860caf9a139f25d08277fcbfb9dc83 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 22 Aug 2024 14:24:16 +0700 Subject: [PATCH 48/89] fix(android): Add RTL assets for adjusting keyboard height menu --- .../main/res/drawable-ldrtl-hdpi/blank_osk.png | Bin 0 -> 8973 bytes .../res/drawable-ldrtl-land-hdpi/blank_osk.png | Bin 0 -> 9879 bytes .../drawable-ldrtl-sw600dp-land/blank_osk.png | Bin 0 -> 9268 bytes .../res/drawable-ldrtl-sw600dp/blank_osk.png | Bin 0 -> 8726 bytes .../drawable-ldrtl-sw720dp-land/blank_osk.png | Bin 0 -> 9281 bytes .../res/drawable-ldrtl-sw720dp/blank_osk.png | Bin 0 -> 8808 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-hdpi/blank_osk.png create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-land-hdpi/blank_osk.png create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp-land/blank_osk.png create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp/blank_osk.png create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw720dp-land/blank_osk.png create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw720dp/blank_osk.png diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-hdpi/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-hdpi/blank_osk.png new file mode 100644 index 0000000000000000000000000000000000000000..c5d555cacaebe0de05655e9c94b7b165390d5b36 GIT binary patch literal 8973 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 literal 0 HcmV?d00001 diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-land-hdpi/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-land-hdpi/blank_osk.png new file mode 100644 index 0000000000000000000000000000000000000000..3e41a359a03b58db80c1c62c895e5f327de53e58 GIT binary patch literal 9879 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 Z{{5rYrFPfpRMQSlC@ZPnK`T7*|357?>;?b; literal 0 HcmV?d00001 diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp-land/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp-land/blank_osk.png new file mode 100644 index 0000000000000000000000000000000000000000..282606a9d509fadbeeb4706725b947b72ee0afbd GIT binary patch literal 9268 zcmdsdXIN9+)@>}vD@s!VrHF!nf`EmhAVEZ$3WzkNN|Bn-i>=>6GA7D zgr;;+dI=?>S+4mE=F*1wK`Pd?ju9&k9|{z&Z(q_~TB9$Xx@Rnk;~K+58d?N~5?>!U8} zPuw98mM`?50~{Cc1wkN!9U6C)^q!lM@IHyB2G49P+j5>pS-d^tb?O9zD|4j4m!lFo zLlLLhImXv{tF2C{m|I0eYG}RGc-h>%(M)5N{YE%D5OPkm^+MEXX(sN&TqftD8XK=P z9sjmMS$qU{Ie7q6PJv3ax@F;!vN!eoqgd)9M8d$Jw@ZwxwM@Gw&|f~4dBsj!f= zK5WivG$lwu+ehLOoZS*U>e($bc--pvfBOcuukXGh(9RE2U+dNDBnqxCu?wo=uD0=7 zrOG;^a&vPtIpq6_P34WNozlL)zj@s*(q?;Y-oVVv$ruGYYE&v18X7uOkMQ#&mbDQ> zxy=4D%05r|d4a=kMf17FG>;|!S@Z;}Tb<&+o}?}?c~>-OUFh8vi(oje^t_!?aa43P zzBk&OwqU4q|AwKd=NtKjfu0_=%5#RMSg)!!{=i!+$)PwkE)mM_)VZk{uqYpTf`5Ne z#XsRkCO8YE9lGT@b+`TkdqD^n2gk_f@~@Dj@%ii9m(Ant25bktv(HhMnwE^V_9&x z`ttg!R+=1ox)YIZvKT(aB{Uo^5!Cth>kZj+!U%gQ7=IG9g2cu0vtaQPYq$#WSM&*x zLw}uB=CZgrlSNi^!0=DgAg`^daOB{p8W#2T#+Fub56X z(vLxU|L-l~_vqn6wp*R1iQVVUG@spixl3S0LmSxqeqY}%QT)BVa{>c#a&lrxKOdW$ zyX5+E<&3|6BJ=?PvPJdZA33l;coRGEXcl{-(07 zhIVMm7-(v08jMyIet)-Wy>t&Oh%neYQr2xMW3W)MfL&;^V5izmwWj-@1b^zf0;))u z-uzh|tx+Zogq9f42r00lshRB~mi$I1%0wpbCdBB!H!)9q5>UTxPfofV(A3JOpcDAF zG;G8&CMG6h@9Jgq2J7Hwq_OI1vpVW1!TB;OZzgmv%YUUK5b4~2hcEr8L)JU#3X_@N zNq!&R+jzWNeTtLQXjUS}z-*-7W_Q;cW#6BBE(&6AZn>sYtFR+jZZovaH8_b#yDJ>NA^g` zU1g$svNcFJ`o7#G8+H8kKK_B-3ZeJeM8?OJ7?cI^1{a6@xij)v=VYa2oJ=*;EriLV zLAa}Y9S^w6x;5`Nr~6m9i_^njGp-Ug6L`*FtqYGd>)6d%MRjb#ZV z6?xe1lPK-w0wl7E6}oxOF0v$WZ+ECbSA`^upbg<9s_W_|3=R*E5l1RW$m$6u zqoy(23 zHuJq?7ZZjHPtYsovgBt08L(Vr+-l9ZU=_#bD9x~>!ewebJw5HzBRf-Oa>faqRu$;xVY0Qhr_OtCUo{1z1^@h43;_RTD5i#9irIn#&z?PV3YWSECKbQt zxQS#llpDa@pBK|;J}W;g$`Z=wg|ir{^YaFnfAPcczyL1sl5TL4%i2vuI)B*Gfcc>F zU?4#K-WEFQ%W3irBsS-7g@HjLJA9Hl2WpPZPqAHgw>d_^tzVSshecBuy1+9+RX)c^ z>buDCIz{S}yV(JSyF8#jCI9qihwL5Vua24HmJI}Y(NF@ct<>sA)~A}!qU|{tTvSvT z)MhOmV6e)sU%x&Tm-TIchR+RvD4GN)%PRDitG`H}J^tW5_TPpdY?F>v+<0Zw!MEA& z?Y3*?0Nv9`)2wA1;kY)nI*)7d>EWf`fy9oOu;E*RXpx zQemtU)EX<8il?`giL1xPjv-A8F9xNiriR!?2*P+H{jOy-zs8A#;Hb((`W~@)2S(6K zhkpv^W~6e!L|3=7H|z8o!zEGCa^^uEz!K(Y+q~wb|Grb{`ShK-_1`y?tL6SqJ^$?9 z{Uom|4T&!3fP2L2JC&EYY2=pnOgyJeeilQ!E_VBCWr&c`ovrt1`ZNQYEFcS-|3ugU ze?d^nmWygKT7YlF;iw5Q99uTS_XQ~JnmRUHTSIxf{+mA;QH#5i92^hXw}T zZuP-PhcAzrGhH`-6(7%H&|8;`ccmgxPNY$Qr_`k;R?^a9OnI2NaZy3p`IFQ=A+e+q z^J|yBf|f_tX7w2qZ#SO}So$0J`FJG2+xQ4ji=*)m>d#YjI4u`#0sS+M0Ql?w%UOdS ziIR=IbojGa#h(}C=Q2MGY~fO# zQAxT25}~0nbN_U0P)W{(sxr*z?s`cw=>y}gc@H;p8LLPKoqQ%+)5)hi*uj5c#z%k| zy3R2Dg4=4)ubrL9%qy#TuRo$BS2YVt3M;A{hYvF^>+9(mX@s+EPaic};#f%1{El+M z%N3TC9OM2aNV#eEH+|`WgP^--BXCruV$eQR<@)732Fo~7=b9=;kdDQfBu5Ue&jidu95O6KI`eC9@}ZKRFW`cxpz8=!WP zak$xBAxm=u0~;_QMJ9h|Vlbl%1VTvFW(0y9{}LozcAp#s0OZiPMj?$>RmAeiA92K; zolXr4J5pFsaMUO((gb3tr-xhm*@Wj(VYuS;Ao62zan}T5!_;s3jbZSRU26=FEhDc> zkmr0~i|1ij##Hw2O5b&dR0Tg2(x^)GIRNVn>;LM z`24vT%RmCMdK7SY-pVj#Vs<1CHGsA~f}Tw$sGd%Af5kJ+!>1WAo90a{#*)D#I#21n zzz%q?)SpxVWdiC^jn6YtelwH4#UMGq-MZf2bccOUkydgf(^dwXR?0`?ZpXdnB z0N9ZeAOyXCr~s%R5hvpM&B4Q;nA>H4<{!})|CAyX)x%IKlQ>gQ@gYlBZ8C6=1_VJ2 z@6A3$FPkP9sRZmHMwa77Zfe9|k=%ZD<{AC7>@nNOZRf|$(E5BZ)c|AP0BNQ(jQlb~ z@yrxRZ$78~q&}S6VD4ZI5LhpFT0b%mfqH)`?ky)7a+o77)`_w(DE7FM4@{tY#Pxt! z^|pVXNdGNf2crJ5E19R`93BnkT7*gjNl)?xuu-k=Mhcc`tKx2)*s$)I1!xFnUf`G3 z*EJ#`&_!0)HIaKnG^@+mpBG;%{$ae@iMWcoo%59aSrmZ?`0!sA0+r~4j}0yQY2RwN z=}H^o|HeTG-*jU*N8DZ)Bu>lJG|h8y0uNeZY`m4;gh4m-1P2EOYGy@Wc%$rGT>Eo1 z$v(zCHcU_9?aVwfxUJa?=jsXHLQ}7iXHIDX`z#7I^gz_Eq>f^Q-I_@ybqDUQvLvTE zVLF_!BpLas2tgD0AZOGM86Aji^d#V#BfV<;q)`^d9hcOrR!3C!wTv}vqIN_zhWnXv z*m2hi8^861s-_&f>X!KoQH>e0y6f8N7;tba6ItnLYo&=l<;~%JrA3JfWxp z)|n*kMMlq#E({iu+6Ch(#foc!_h0Dt0s{RUF%>C7q>MSU4t+a|Sku9-cFBiSN%pC` z)N_6IF@}i!VA^5eGI`o|)~{%AXlN948hO-HFB?Incu_`d$5Nyn$FJ;7C!1^S#|1es zcu$UhbHZ=2O6{yqb9&&e4|chg2aj$5Q5>6CR}l?Xi#rP+931p{a(MRHfuh@vl^eCI zT@}A#<-1JZ5G(t&Dq34r4L9$(x|VSOC4I*By#-+i>8>U!1uGFtpCQz@|I^((BCzaxdvj|5U-COTJ zz{vYlH}}C&Gd%Qrvp#c@^GZ2nNPY3g=McO*11*fl$t8Jq$Ygz;FpTx$XssT1i^dAY zpY=2=or|)?tjW@Y{)pe%T7`cOW+0=Fu$udkq_KOuRQz`AoQ#H!Wd5`+2r^~nmh;3d zS!N9ANb(7Mo!1-e*fyeN=Qa zDx$~TyA{YN^^_wDJ}cJ7WtO1;1iI?>CAfW#dr%2xK~#QyKo|by#Zei{=D)C;Q_-Yw z#hnk#yf>~qALc69M9jRiEh;LyY}X;_^8^wdh3iU_$6EM`r&LIY`g;xt7()nEFr}iC zm(I^pcTyG1wW?#9$P9LPFrit4s;?7wn{tI=8fi6#E4 z7~pxmwD7GjzlC`Ub903qC+q9#8Z1?S6JTak*)Eru=)ddCP93+l$|+I9J|LPS*54o{ zU)-jT;6KAD(vMtT)|d4Uf%88y2P$6?ypb0yON?$y|Lt%H@CsOwUi2qnFtCyci^dr< zWFVPH`8sMN*v{l9%1ue%!mL83v-0!XF`fh)yr?g3eV8U}$86iGuUHXJX)!R?{Z)Sj z_wF03o05_+xbCgXqfJXz5Y5@+6WOSx@sTtoMt+!X?t7S{B6R@Ji(vl0awLcmv2)%F z<0A{Qvbd7K_0CLb-hc4v7b^P$Rrkb}&D`fE;>Sz6kqC8-=H2o=_Z)qsDI65pJDlth zB<}T>F9*dWoNWD$^IB_n2aa;qtyzLZ32-!CTl=95TRAF%Ir!N8RQ+Z7EdKB>-&#dc zd&Nf20&9P6XDX!doB2l~+~X92?M|+y**iIvhdp?-)mij}vLGhOi0oyfy2MA(yjgf1 zbhV%(QPEN3-bdvVIy&C%Ar|r8q`lqwFr+3sJ9xclKmmF8_m%E2T6to1zTpvVsoi z?wqpm>WHl|kJYFA{K^0<$tE;Z<(;%ZgTi(^tf&|@-I>fFz6>g$@-C5)h1c5j-u>%} zY|RKNQ&B;|)dXi~Ih|O;!C#nM;0KJ$3B>e@fB;G$!JjCG_3r+iibtx?S~0>mvxo;e zVt5MSBV+gRMtWt(p3>V0vU0$kcmJf|f9eUIe;xgFo+-$V$7t$P;96W-XL6zVLb^A= z55?b|bwwkFcZ=h3wy`FV}GZ#1BC1XqACF#>S3|wX3n;(-p=PoHcQV zcOQ=+X5NSyj(!O}Cb)QAO*BZ}i)fc1tm&rq#-rb+l5gQLpPWbOv(BWEW0JLOfTiw5 zsoKGeD*YugN`?^v+k<6Caf#ZcJBFK16SeQA zxWHoBlTNfSLbXZ5Jd%ML6(LB5x&uaNSYqb%;);3KrQ1^A0W#L@uK+Jxi+g@bwnf`@ zjqdReq1|mAVX)&y03M-z&gg*t^)WIJHA?-?d&CTYpJ&g6q+RaJ){;r+)iz>}lG42#l2`cm{bs)@1n%BnXuwy@RSK ziMXILuTA{9ublpu7Q`c^jnDmWke=OF@T}T#Mza$rP$9Q{A40Mwqn!#43RLb;Iw$L)=s>c+Kl&SM(R4(9rCpFTlj@9W0P2yv?A<`c&k|(u9tnPR z7)*-a1U(2iFT<75j~I*`VH{nd05pr&d`|KxBftNT(Y84L#k1PCmhW!V09mxLt<0)m z4d#Gn_GfynjtVpV;DtH+UhcOs7D@YM3})2ExO*I8tyc}?mkre1Tc9gCp)Z=WG?lMOmh_f;S91cf{ z#g-Em-bzbL(+QxgiUE9NqabZn&6rDw9WKIA0eDyiVgo-+#x6p|BqUJAPUseedlnWS z6gGc^kn6Z<3UiquChY!W@M`pM1%mz*^(cydRmN7`BBDDj%<$pEr8fePt3pTfuNoa; zaJkJ_1Y}y*tL# zklGY?%f@m+Ot<5uBD|JcxUjlQmEGI@8M|x8sA-=rN!`vix_bz2E)mPl&)^a!HwyTv ziLIVep}W%H&9;|ktQ5C<<6wXskx@4T!EHsAl>;12x_Mevvl)RC9A6C0d~(EUe;CRr zy*#Th8bGPYcmjxKDhpC)GCK}B3OA2A(pl@X3In9uYd}X0?b-Y0gJ-GL=F-ohGAp$c zEFiKIIbTrDll7Ffe(f<+Z~U}Y!&zFtuQmz->Ukt}u42pyi#`+OJ&C9`_IN#XQtQU&7`8wlbDUH^6&t!!N!7-lp3>C3 zqnQwveB7Yj50n&x61>8;8wEvd*JNKw`IMP`EhWmOnOzOnA(8>JP4i3=EB8phveS#| zlj-@Zw2P##Qy6VFztANoxw-i(&RaK4W!7o$2cx3PtdHYi^OjOF`z?ooi?RocvSA}S zmLRTkmqu*|Gh>dJd8Bp$^Q12=wm>BWzA@off=$bFA{3-3Q<0OKt+GVcz|BKk4w?|Z z&9M)!%{5~JK)y+J8x!uK2@)@JR9fP5zdGEjj1rpf&1O`yzSS?|vq#&&|5eIl!BNT| zxKkz{cZX4YAlF_fD}=|$5KBI}10Vv^O)znaf!Gd%Jqx-}02yjAl>YVbkTgc(dvbCd zbi19@=@6)=QhLPJ!-0QY)&ErESbHp_uws7hD@eRr_3l)(Bu4BALG()qBdZseZlB4{ z2jy@K_50V!yV<(p!1bqiRR} z-j~lW1|1R&@L(y3EwxL0sAjyDpM4D@P#R?_F2_y-!qc5g3$wG*N$S^D^z6?ZeE04e z!BA#5MJ}tk49tV-;^yTZW!4ekT+QVwM5E@vy}OQ2JlRVb9*G?6y?H2;`xlg|$+u?TyTfp$7RAE7my)>~dv7*W>nb*iOi zAO4UXC1;eIZ8M@Xp^+er7BG~;AbM4}&|eIrqn?=x8D+PE+wU6nV106TnI8E=~_Q;Udxr5$bD1@*4?r<{QZ*Xw8p#CB0 zXijlA!3LvOmzkbcJ`oM_^b?KQHS?X%A%E==jR5AM$wvM<-Mn!ushg2d>DKcC&)v)w zcpP%`ef;pX2+`47LTqUbNC87b$}X{@dpvunV%C%XwSpb>V$f?*?&(3j6RLjnc3Jzc z+gA@EzX;N@1YzsXOnvGbnP53MV*}~-i-R?prB`%$q_GU}$HI!7s_OB8f|Zx)@*>9c z3}*u_jwAshC0p(MdP{TI8S4y4;L#E2sb?8C*F+}Fwo#s9lGVAns&dXe3HWs5YWu&D z+rRtiLToQWm`AKda~Uk;M;bIlf&oarId%dPv{OM^to|pHix3>Mog!X$jF9vw;Zg9a zB{fV2P`Xxf4D=o+ZW+GS>NSv(m3{(@ahc~CG*YtSo_!BD3r#Ti8yEWOs>+1>kEh19 z){zR*-dan+=Gm<;%dT3rjxOvKTgo4Vyo$RAviq$|*?&xLMntNr!P*+N5ukKM>^l3V^DSSE8 QLH~t@iq_rYJ5PiE14n|qQUCw| literal 0 HcmV?d00001 diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp/blank_osk.png b/android/KMAPro/kMAPro/src/main/res/drawable-ldrtl-sw600dp/blank_osk.png new file mode 100644 index 0000000000000000000000000000000000000000..8246a641687a092571b1046ad5296621c2efb50c GIT binary patch literal 8726 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 literal 0 HcmV?d00001 From b721ff6d5deaea46c0f043f03aa25293c87861b2 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 22 Aug 2024 11:19:37 +0100 Subject: [PATCH 49/89] fix(developer): add call test cases from #11990 to GetXStringImpl_type_c test --- .../kmcmplib/tests/gtest-compiler-test.cpp | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp index 1c20597645..9d335de83a 100644 --- a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp +++ b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp @@ -1225,6 +1225,59 @@ TEST_F(CompilerTest, GetXStringImpl_type_o_test) { EXPECT_EQ(0, u16cmp(tstr_outs_space_after_valid, tstr)); } +// tests strings starting with 'c' +TEST_F(CompilerTest, GetXStringImpl_type_c_test) { + KMX_WCHAR tstr[128]; + fileKeyboard.version = VERSION_60; + KMX_WCHAR str[LINESIZE]; + KMX_WCHAR output[GLOBAL_BUFSIZE]; + PKMX_WCHAR newp = nullptr; + PFILE_STORE file_store = new FILE_STORE[100]; + fileKeyboard.cxStoreArray = 3u; + fileKeyboard.dpStoreArray = file_store; + file_store[1].fIsStore = TRUE; + u16cpy(file_store[0].szName, u"a"); + u16cpy(file_store[1].szName, u"b"); + u16cpy(file_store[2].szName, u"c"); + + // call, KmnCompilerMessages::ERROR_501FeatureOnly_Call + fileKeyboard.version = VERSION_50; + u16cpy(str, u"call"); + EXPECT_EQ(KmnCompilerMessages::ERROR_501FeatureOnly_Call, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + + // call, KmnCompilerMessages::ERROR_CallInVirtualKeySection *** TODO *** + + // call, no close delimiter => NULL + fileKeyboard.version = VERSION_501; + u16cpy(str, u"call("); + EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + + // call, empty delimiters => empty string + fileKeyboard.version = VERSION_501; + u16cpy(str, u"call()"); + EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + + // call, space in delimiters (see I11814, I11937, #11910, #11894, #11938) + fileKeyboard.version = VERSION_501; + u16cpy(str, u"call( )"); + EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + + // call, KmnCompilerMessages::ERROR_StoreDoesNotExist + // fileKeyboard.version = VERSION_501; + // u16cpy(str, u"call(d)"); + // EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + + // call, KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store + // fileKeyboard.version = VERSION_501; + // u16cpy(str, u"call( d)"); + // EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + + // call, KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store + // fileKeyboard.version = VERSION_501; + // u16cpy(str, u"call(d )"); + // EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); +} + // KMX_DWORD process_baselayout(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) // KMX_DWORD process_platform(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) // KMX_DWORD process_if_synonym(KMX_DWORD dwSystemID, PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) From 7e2f797dd8d65958e194a03d3696b580677afb96 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 22 Aug 2024 11:35:49 +0100 Subject: [PATCH 50/89] fix(developer): move check on store name search to just after search --- developer/src/kmcmplib/src/Compiler.cpp | 2 +- developer/src/kmcmplib/tests/gtest-compiler-test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index 3893a72855..313cc859e5 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -2310,11 +2310,11 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX { if (u16icmp(q, fk->dpStoreArray[i].szName) == 0) break; } + if (i == fk->cxStoreArray) return KmnCompilerMessages::ERROR_StoreDoesNotExist; if (!kmcmp::IsValidCallStore(&fk->dpStoreArray[i])) return KmnCompilerMessages::ERROR_InvalidCall; kmcmp::CheckStoreUsage(fk, i, FALSE, FALSE, TRUE); - if (i == fk->cxStoreArray) return KmnCompilerMessages::ERROR_StoreDoesNotExist; tstr[mx++] = UC_SENTINEL; tstr[mx++] = CODE_CALL; tstr[mx++] = (KMX_WCHAR)i + 1; diff --git a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp index 9d335de83a..87db0faa66 100644 --- a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp +++ b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp @@ -1235,7 +1235,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_c_test) { PFILE_STORE file_store = new FILE_STORE[100]; fileKeyboard.cxStoreArray = 3u; fileKeyboard.dpStoreArray = file_store; - file_store[1].fIsStore = TRUE; + file_store[1].fIsCall = TRUE; u16cpy(file_store[0].szName, u"a"); u16cpy(file_store[1].szName, u"b"); u16cpy(file_store[2].szName, u"c"); From 75508f46b451f9dde798e9c0832814f443648b92 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 22 Aug 2024 11:43:03 +0100 Subject: [PATCH 51/89] fix(developer): add ERROR_StoreDoesNotExist test cases to GetXStringImpl_type_c test --- .../src/kmcmplib/tests/gtest-compiler-test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp index 87db0faa66..f55bb63ffa 100644 --- a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp +++ b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp @@ -1263,19 +1263,19 @@ TEST_F(CompilerTest, GetXStringImpl_type_c_test) { EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); // call, KmnCompilerMessages::ERROR_StoreDoesNotExist - // fileKeyboard.version = VERSION_501; - // u16cpy(str, u"call(d)"); - // EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + fileKeyboard.version = VERSION_501; + u16cpy(str, u"call(d)"); + EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); // call, KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store - // fileKeyboard.version = VERSION_501; - // u16cpy(str, u"call( d)"); - // EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + fileKeyboard.version = VERSION_501; + u16cpy(str, u"call( d)"); + EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); // call, KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store - // fileKeyboard.version = VERSION_501; - // u16cpy(str, u"call(d )"); - // EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + fileKeyboard.version = VERSION_501; + u16cpy(str, u"call(d )"); + EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); } // KMX_DWORD process_baselayout(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) From f082ddc0708b88b7c5568ce1d69d95f77c09a2c0 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 22 Aug 2024 13:20:52 +0200 Subject: [PATCH 52/89] chore(common): adjust build settings for windows clean builds --- common/windows/.gitignore | 1 + .../delphi/components/common_components.dproj | 63 ++++-------------- .../ext/cef4delphi/packages/CEF4Delphi.res | Bin 708 -> 0 bytes .../delphi/tools/certificates/build.sh | 2 + docs/build/linux-ubuntu.md | 26 ++++++-- docs/build/macos.md | 36 ++++++++-- docs/minimum-versions.md | 3 +- windows/src/.gitignore | 5 ++ windows/src/README.md | 6 +- windows/src/desktop/kmshell/kmshell.res | Bin 7036 -> 0 bytes windows/src/engine/keyman/build.sh | 1 + 11 files changed, 75 insertions(+), 68 deletions(-) delete mode 100644 common/windows/delphi/ext/cef4delphi/packages/CEF4Delphi.res delete mode 100644 windows/src/desktop/kmshell/kmshell.res diff --git a/common/windows/.gitignore b/common/windows/.gitignore index 7af23e7e1a..a6cb808a34 100644 --- a/common/windows/.gitignore +++ b/common/windows/.gitignore @@ -7,3 +7,4 @@ delphi/**/*.~* delphi/**/__recovery/ delphi/**/__history/ delphi/general/keymanversion_build.inc +delphi/ext/cef4delphi/packages/CEF4Delphi.res diff --git a/common/windows/delphi/components/common_components.dproj b/common/windows/delphi/components/common_components.dproj index 2bd91473ab..4ecda90464 100644 --- a/common/windows/delphi/components/common_components.dproj +++ b/common/windows/delphi/components/common_components.dproj @@ -13,31 +13,6 @@ true - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - true Base @@ -59,6 +34,12 @@ Base true + + true + Cfg_2 + true + true + .\obj\$(Platform)\$(Config) .\$(Platform)\$(Config) @@ -77,23 +58,6 @@ 3081 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= - - None - android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar - - - None - android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar - - - None - - - None - - - None - Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) Debug @@ -113,6 +77,7 @@ false true 1033 + ..\..\lib false @@ -120,6 +85,11 @@ 0 0 + + ..\..\lib + true + 1033 + MainSource @@ -164,8 +134,6 @@ common_components.dpk - File c:\projects\keyman\app\windows\lib\DCPdelphi2009.bpl not found - File c:\projects\keyman\app\windows\lib\delphiprojectmanager.bpl not found Microsoft Office 2000 Sample Automation Server Wrapper Components Microsoft Office XP Sample Automation Server Wrapper Components @@ -944,13 +912,6 @@ - False - False - False - False - False - False - False True False diff --git a/common/windows/delphi/ext/cef4delphi/packages/CEF4Delphi.res b/common/windows/delphi/ext/cef4delphi/packages/CEF4Delphi.res deleted file mode 100644 index b9b013c2123fcf20e24680fc5ad3191fc452d216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcmZ{i&q~8U5XQgO9IRfvd-32|A_PGYr5Gy(ZKal8CDvLCZBo*D^K>y3I?ZFSY*+-7ZI zn|uX7zmnlg4!>VHuVjSY^LM3BE^6>Cm209@W7sB|Y6NqtS7ii#xR_9pLY<=#HCRQV zcES4i0hnA1&>2XRQ=JgwRXWo?@y5G!v8fU=by#PdrE7RwFvpyxn(GZNlM?p;d!`q? zYY4tVZO28fzIEJYm76v8bV!XQW=uw_txZKHL-Nn)XTuv$k<~^sAYF^v$mc7QyTSm`Py^eJ3Ubc@nVYUlqm#pzNg71JYrVF$v_UP_TP4(gG W@|W(hn(Vhszt2x7<^TWN;c5kN0bbt# diff --git a/common/windows/delphi/tools/certificates/build.sh b/common/windows/delphi/tools/certificates/build.sh index 378723a125..10ab4c75ce 100755 --- a/common/windows/delphi/tools/certificates/build.sh +++ b/common/windows/delphi/tools/certificates/build.sh @@ -21,6 +21,8 @@ builder_describe_outputs \ function do_certificates() { rm -f KeymanTestCA-sha1.* KeymanTest-sha1.* KeymanTest-sha256.* KeymanTestCA-sha256.* + source "$KEYMAN_ROOT/resources/build/win/visualstudio_environment.inc.sh" + makecert -r -pe -n "CN=Keyman Test CA SHA1" -ss CA -sr CurrentUser -a sha1 -cy authority -sky signature -sv KeymanTestCA-sha1.pvk KeymanTestCA-sha1.cer certutil -user -addstore Root KeymanTestCA-sha1.cer makecert -pe -n "CN=Keyman Test Certificate SHA1" -a sha1 -cy end -sky signature -ic KeymanTestCA-sha1.cer -iv KeymanTestCA-sha1.pvk -sv KeymanTest-sha1.pvk KeymanTest-sha1.cer diff --git a/docs/build/linux-ubuntu.md b/docs/build/linux-ubuntu.md index 0107491dda..a45d9390ba 100644 --- a/docs/build/linux-ubuntu.md +++ b/docs/build/linux-ubuntu.md @@ -63,17 +63,33 @@ See [node.md](node.md) for more information. #### Emscripten -You'll also have to install `emscripten` (version 3.1.44 is known to work): +You'll also have to install `emscripten`: ```shell git clone https://github.com/emscripten-core/emsdk.git cd emsdk -./emsdk install 3.1.44 -./emsdk activate 3.1.44 -export EMSCRIPTEN_BASE=$(pwd)/upstream/emscripten +./emsdk install 3.1.58 +./emsdk activate 3.1.58 +export EMSCRIPTEN_BASE="$(pwd)/upstream/emscripten" +echo "export EMSCRIPTEN_BASE=\"$EMSCRIPTEN_BASE\"" >> .bashrc ``` -**NOTE:** Don't put EMSDK on the path, i.e. don't source `emsdk_env.sh`. +> ![WARNING] +> Don't put EMSDK on the path, i.e. don't source `emsdk_env.sh`. +> +> Emscripten very unhelpfully overwrites `JAVA_HOME`, and adds its own +> versions of Python, Node and Java to the `PATH`. For best results, restart +> your shell after installing Emscripten so that you don't end up with the +> wrong versions. + +**Optional environment variables**: + +To let the Keyman build scripts control the version of Emscripten installed on +your computer: + +```shell +export KEYMAN_USE_EMSDK=1 +``` ## Keyman Core diff --git a/docs/build/macos.md b/docs/build/macos.md index 81b1bcd0e7..25b0c1f82a 100644 --- a/docs/build/macos.md +++ b/docs/build/macos.md @@ -91,16 +91,38 @@ See [node.md](node.md) for more information. ### emscripten -To install emscripten: +The recommended way to install emscripten is with the official method, as that +then allows the build scripts to select the appropriate version automatically. -```shell -brew install emscripten +To install emscripten, `cd` to an appropriate path, and then: + +```bash +git clone https://github.com/emscripten-core/emsdk +cd emsdk +emsdk install 3.1.58 +emsdk activate 3.1.58 +export EMSCRIPTEN_BASE="$(pwd)/upstream/emscripten" +echo "export EMSCRIPTEN_BASE=\"$EMSCRIPTEN_BASE\"" >> .bashrc ``` -Note: if you install emscripten with brew on macOS, only emscripten binaries are -added to the path via symlinks. This makes it reasonably safe to have emscripten -on the path, unlike on other platforms where emscripten also ends up adding its -versions of node, python, and other binaries to the path. +You will want to add `EMSCRIPTEN_BASE` to your .bashrc. + +> ![WARNING] +> Don't put EMSDK on the path, i.e. don't source `emsdk_env.sh`. +> +> Emscripten very unhelpfully overwrites `JAVA_HOME`, and adds its own +> versions of Python, Node and Java to the `PATH`. For best results, restart +> your shell after installing Emscripten so that you don't end up with the +> wrong versions. + +**Optional environment variables**: + +To let the Keyman build scripts control the version of Emscripten installed on +your computer: + +```shell +export KEYMAN_USE_EMSDK=1 +``` ## Keyman for iOS Dependencies diff --git a/docs/minimum-versions.md b/docs/minimum-versions.md index a9a2ead26b..f582632007 100644 --- a/docs/minimum-versions.md +++ b/docs/minimum-versions.md @@ -49,7 +49,6 @@ https://help.keyman.com/developer/engine/android/latest-version/ | KEYMAN Variable | Value | |-----------------------------------|--------------| | KEYMAN_DEFAULT_VERSION_UBUNTU_CONTAINER | noble | -| KEYMAN_MAX_VERSION_EMSCRIPTEN | 3.1.58 | | KEYMAN_MIN_TARGET_VERSION_ANDROID | 5 | | KEYMAN_MIN_TARGET_VERSION_CHROME | 95.0 | | KEYMAN_MIN_TARGET_VERSION_IOS | 12.2 | @@ -58,7 +57,7 @@ https://help.keyman.com/developer/engine/android/latest-version/ | KEYMAN_MIN_TARGET_VERSION_WINDOWS | 10 | | KEYMAN_MIN_VERSION_ANDROID_SDK | 21 | | KEYMAN_MIN_VERSION_CPP | 17 | -| KEYMAN_MIN_VERSION_EMSCRIPTEN | 3.1.44 | +| KEYMAN_MIN_VERSION_EMSCRIPTEN | 3.1.58 | | KEYMAN_MIN_VERSION_MESON | 1.0.0 | | KEYMAN_MIN_VERSION_NODE_MAJOR | 20 | | KEYMAN_MIN_VERSION_NPM | 10.5.1 | diff --git a/windows/src/.gitignore b/windows/src/.gitignore index 350b7e4bdb..065f4a07f3 100644 --- a/windows/src/.gitignore +++ b/windows/src/.gitignore @@ -34,3 +34,8 @@ keyman-windows-coverity.tgz # This file is still generated by devtools. TODO: eliminate in future PathDefines.mak + +# .res files, generated during build +desktop/kmshell/kmshell.res +engine/keyman/keyman.res +engine/keyman32/version64.res diff --git a/windows/src/README.md b/windows/src/README.md index 1d057482bb..ae0090c340 100644 --- a/windows/src/README.md +++ b/windows/src/README.md @@ -45,8 +45,8 @@ build, you will need to obtain valid code signing certificates. See Certificates, below. Official release builds for Keyman are built in the Keyman project's CI environment. -1. Start 'Developer Command Prompt for VS 2019'. -2. Run `nmake release` from the **windows/src** folder. +1. Start bash +2. Run `./build.sh :publish` from the **windows/src** folder. 3. Artifacts from a successful build will be placed in **windows/release** folder. 4. **buildtools/help-keyman-com.sh** will push updated documentation to @@ -65,7 +65,7 @@ globally trusted. The environment variables `SC_PFX_SHA1` and `SC_PFX_SHA256` can be set to custom certificate paths. The Keyman repo can build test certificates for you. To build your own, run -`./build.sh certificates` from **common/windows/delphi/tools/certificates** to +`./common/windows/delphi/tools/certificates/build.sh certificates` to build and install your own local root CA "**KeymanTestCA**" certificates. If you specify a password for the certificate, you'll need to set that in the environment variable `SC_PWD`. diff --git a/windows/src/desktop/kmshell/kmshell.res b/windows/src/desktop/kmshell/kmshell.res deleted file mode 100644 index cfcbd309f137d6a5f5221aba48a1c759c0d56682..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7036 zcmeI1J!~7v6~~`s1u|_|P!*hAZ5EMn2(S`ACF(%RC)jrp6@LgheU!nHyOao#yBjVg zo)iR7mlS_n#!2}n!$--QQ1 zw}VKUad-O3=WLJru871Gadh$=T@Rj&BMP$9%qGz<#XB(zRY#^=#HP2+AL{#8-^a+g zf^j_WLSsz~4mQ`s$Iu3GG1DW)BRWJoD6BQh1`+Me%6}DUhy#9^LSC{pCb2-($ePa zZ9otyYiV#E4^IxM{`WtNd~z23bT;zJ4G&4J|JS2Gef1U9>K^T%d9+#cX!*#asRNIO zcHqU=_6gDYQ=;rcqG^{XIzzQ{@W`jJv-NeiQsM z_$ly1U`1r$2|R(v`XhWM&%qyq-vz$~-UYt^ehz$wPACmN0)7bmRq%E2XW(n#kH8;* z-vPe^ejEHc_$>Ho@KNv{cn`b>-UIJ}_rUY(1h1!fJ;ck!Yew*O@Mqv_;E%u`falS7 zKyQOy2b~2y4LXYP&%qyq-vz$~-UYt^ehz#Fd>VWN{1Eu7;4$w0KKM=W%iyQL4}mA} zo!LRw&cPpp-vz$~-UYt^ehz#Fd>Yw|Ae%$T=2h@@@Mqv_;E%u`fZqYX1AZI)I`}O3 zY4B0-9(WJD2i^nkf%m{8pc4f26mQo0sOlYRP*ZK&%oEf zAAvsrkK}YoPz{OL$F+%T8P^o9Aza-O^!DvrdiClRy?ptSUc7ig&!0c1Cr_Tx&dv@! ze*BoWx3}s3{rj}OzD|~9Q8t^U`T2R8o}Q+Oi3y5EqjdfHb-H%#8Vw8#U`4c-VOfZN zE(-Z(y)HYXO?4E}A#7pF4z{I{Y*jMr?`Us zY(susqo=cM;7b^N_#ze+?r8p?{S4lsgs`EZ@ZQE{&$o%%><9gh1bm&aqqXo4cn=hS z)FJzTuvzv2VGCITY)e@JZ2PhRU_<7e)2VU{up#?4V%Q6bxuuR6_Co9(=vCUo1`Hef zF#OTL-YaZ4umW3d&;$lHo%W)If?n9pz-h0-8#d#x>Gf%^Dkk7jAhWIT45ASB>t0m= zY(o}y06-SD53nq439u|}IR(qU&47@78-VZ*bi^R#Kvzk4L-*h2pG@@^95EC`BhPhx zBChVA19=|VkeGai59g5&=Mi2%AI>8m&Li?0;oW!tfZ|udIYpjUaNdvylmOx(0!f}{ z+H^jBv;%Ga!QrH3gjQY3?IX14f!qc(^`_hkH1t-v1qk$Zxe54sr`!OfE@l6W#V4&s z9)#|D3;m6_LzjtSJs7-07Xb7?mS?!8zZikv5OH|p0qbvsCFkc}RvR+w9GK{3)z<~U z9Qz3!wJ+m5hqE4&@d{=O19uh50_hB@aQZzmcYHd|4_gt7h3P*j8GN42M<4v~spluolzm z-0bICQdQiFZW(&fw#>A;X1eN)i7S^8@5P1ReA{footf3x_YM+MG4qv6ijp!+$FvMYx;6o`rK2+G z$0hrr1c7FNR|=Ii!Lv_g&A|gz3sx+uHaac6gw8v`0}L+|EW@t4!#C|x$+oncwpA(H zMYrkD$ld60m|soBS;-a)x!;&;v-YxyOqtGb)9R*{o( z^I;Wbr7)S}=S{15z37@v$$wl-Fw&TzbNbn z+zI8%rBF(D9K4$t$F@XADD?|Xn_V)M%q=Br7VWBnmBN7ODqt0N#c}L%MakP`#a~3q zd;uRNMbi*fD3tOE)42DAk}=ZiAIxYt5{W0qv`8X8s>Nfugr+C*rWOt-4bwDZMl2ux zqdM~5(~otZI+lpUlG$-xOBmyrI-fPPq!~3dJsOXPqtQfuJf`#1BJdyn;K}YY$MtAF znlxitB9O># zM6+5lW`y&jM%d8De$3pFaQCT`W;j2lN1|FbpN%2mW>Q1?6Iwi(HxgkzlF-LR!b71D zufCCv<(C?1Tc*6sM}jXp7}ytxQsR665`MS6jh$u|e^a@Kzk%IBYZCRZ@z Date: Thu, 22 Aug 2024 13:26:56 +0200 Subject: [PATCH 53/89] Update windows.md --- docs/build/windows.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/build/windows.md b/docs/build/windows.md index 663b68c2f8..3168bcd0ae 100644 --- a/docs/build/windows.md +++ b/docs/build/windows.md @@ -272,6 +272,10 @@ of appropriate node versions during builds. 3. Change 'Tab size' to 2 and 'Indent size' to 2. 4. Select 'Insert spaces'. +* Windows SDK (C++ Desktop Development) + + https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ + **Required environment variables**: * `PATH` * Add the `C:\Projects\keyman\keyman\windows\lib` folder in the Keyman From b608e1ca84cffac3a237f5c5338e60df0c979df9 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 22 Aug 2024 15:15:32 +0100 Subject: [PATCH 54/89] fix(developer): add ERROR_InvalidCall and first valid test case to GetXStringImpl_type_c test --- .../src/kmcmplib/tests/gtest-compiler-test.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp index f55bb63ffa..c3ea2a9037 100644 --- a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp +++ b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp @@ -1236,6 +1236,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_c_test) { fileKeyboard.cxStoreArray = 3u; fileKeyboard.dpStoreArray = file_store; file_store[1].fIsCall = TRUE; + file_store[1].dwSystemID = TSS_NONE; u16cpy(file_store[0].szName, u"a"); u16cpy(file_store[1].szName, u"b"); u16cpy(file_store[2].szName, u"c"); @@ -1276,6 +1277,22 @@ TEST_F(CompilerTest, GetXStringImpl_type_c_test) { fileKeyboard.version = VERSION_501; u16cpy(str, u"call(d )"); EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + + // call, KmnCompilerMessages::ERROR_InvalidCall + fileKeyboard.version = VERSION_501; + file_store[1].dpString = (PKMX_WCHAR)u"*"; // cause IsValidCallStore() to fail + u16cpy(str, u"call(b)"); + EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + + // call, valid + fileKeyboard.version = VERSION_501; + file_store[1].dpString = (PKMX_WCHAR)u"a.dll:A"; + file_store[1].dwSystemID = TSS_NONE; + u16cpy(str, u"call(b)"); + EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + const KMX_WCHAR tstr_call_valid[] = { UC_SENTINEL, CODE_CALL, 2, 0 }; + EXPECT_EQ(0, u16cmp(tstr_call_valid, tstr)); + EXPECT_EQ(TSS_CALLDEFINITION, file_store[1].dwSystemID); } // KMX_DWORD process_baselayout(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) From 862f0d9191896951a7fb929e1991f7a59c8e8122 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 22 Aug 2024 15:21:01 +0100 Subject: [PATCH 55/89] fix(developer): add test cases for spaces before and after valid store in call in GetXStringImpl_type_c test --- .../src/kmcmplib/tests/gtest-compiler-test.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp index c3ea2a9037..aab01f8131 100644 --- a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp +++ b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp @@ -1293,6 +1293,24 @@ TEST_F(CompilerTest, GetXStringImpl_type_c_test) { const KMX_WCHAR tstr_call_valid[] = { UC_SENTINEL, CODE_CALL, 2, 0 }; EXPECT_EQ(0, u16cmp(tstr_call_valid, tstr)); EXPECT_EQ(TSS_CALLDEFINITION, file_store[1].dwSystemID); + + // call, space before store, valid + fileKeyboard.version = VERSION_501; + file_store[1].dpString = (PKMX_WCHAR)u"a.dll:A"; + file_store[1].dwSystemID = TSS_NONE; + u16cpy(str, u"call( b)"); + EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + EXPECT_EQ(0, u16cmp(tstr_call_valid, tstr)); + EXPECT_EQ(TSS_CALLDEFINITION, file_store[1].dwSystemID); + + // call, space after store, valid (see I11937, #11938) + fileKeyboard.version = VERSION_501; + file_store[1].dpString = (PKMX_WCHAR)u"a.dll:A"; + file_store[1].dwSystemID = TSS_NONE; + u16cpy(str, u"call(b )"); + EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); + EXPECT_EQ(0, u16cmp(tstr_call_valid, tstr)); + EXPECT_EQ(TSS_CALLDEFINITION, file_store[1].dwSystemID); } // KMX_DWORD process_baselayout(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) From 5fb374341677db19b0b48c6503ef9cd4e050bb47 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Thu, 22 Aug 2024 14:02:35 -0400 Subject: [PATCH 56/89] auto: increment master version to 18.0.96 --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 7bb236717b..2ee27cd198 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 18.0.95 alpha 2024-08-22 + +* chore(common): allow build agents to automatically select emsdk version, and enable support for 3.1.60+ (#12243) + ## 18.0.94 alpha 2024-08-21 * fix(core): look for `emcc` instead of `emcc.py` (#12235) diff --git a/VERSION.md b/VERSION.md index a41e5425c0..998f9bf6fd 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.95 \ No newline at end of file +18.0.96 \ No newline at end of file From 044c25a0e49b14028507629d36dedf98b433c45d Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Fri, 23 Aug 2024 08:29:08 +0700 Subject: [PATCH 57/89] change(common/models): increase specificity in wordbreaker's .gitignore --- common/models/wordbreakers/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/models/wordbreakers/.gitignore b/common/models/wordbreakers/.gitignore index c51c25f2fd..032a2a523f 100644 --- a/common/models/wordbreakers/.gitignore +++ b/common/models/wordbreakers/.gitignore @@ -1,2 +1,2 @@ build/ -**/**.inc.ts \ No newline at end of file +src/main/default/data.inc.ts \ No newline at end of file From 347b8142e0ee43176bac857d136b7164f80ee6ba Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Fri, 23 Aug 2024 08:37:20 +0700 Subject: [PATCH 58/89] chore(common/models): copies original data-gen's license for attribution --- .../wordbreakers/tools/data-compiler/LICENSE | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 common/models/wordbreakers/tools/data-compiler/LICENSE diff --git a/common/models/wordbreakers/tools/data-compiler/LICENSE b/common/models/wordbreakers/tools/data-compiler/LICENSE new file mode 100644 index 0000000000..14c39a294a --- /dev/null +++ b/common/models/wordbreakers/tools/data-compiler/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2019 National Research Council Canada +Copyright (c) 2024 Eddie Antonio Santos + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From ecaef394ceccb32327ecbf38f469ccd34f2723c6 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Fri, 23 Aug 2024 08:37:39 +0700 Subject: [PATCH 59/89] docs(common/models): fixes relative path in doc-comment --- common/models/wordbreakers/tools/data-compiler/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/models/wordbreakers/tools/data-compiler/index.ts b/common/models/wordbreakers/tools/data-compiler/index.ts index 28c52be1aa..d2effa5856 100644 --- a/common/models/wordbreakers/tools/data-compiler/index.ts +++ b/common/models/wordbreakers/tools/data-compiler/index.ts @@ -19,7 +19,7 @@ const require = createRequire(import.meta.url); * * For internal use only. Please keep away from children. * - * The generated file is saved to ../src/gen/WordBreakProperty.ts + * The generated file is saved to ../../src/main/default/data.inc.ts */ const MAX_CODE_POINT = 0x10FFFF; From d461c4872a43aa7b16abc08cc1abd78a8a2ea9aa Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 23 Aug 2024 07:01:33 +0200 Subject: [PATCH 60/89] chore(common): use `npm install` in emsdk update --- resources/locate_emscripten.inc.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh index f678e8449e..f20ac5d0e9 100644 --- a/resources/locate_emscripten.inc.sh +++ b/resources/locate_emscripten.inc.sh @@ -69,5 +69,6 @@ _select_emscripten_version_with_emsdk() { git pull ./emsdk install "$KEYMAN_MIN_VERSION_EMSCRIPTEN" ./emsdk activate "$KEYMAN_MIN_VERSION_EMSCRIPTEN" + npm install popd > /dev/null } From 47b952f9609594c86c2c050d6b3bd6aad03dbfb3 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 23 Aug 2024 07:10:48 +0200 Subject: [PATCH 61/89] chore(common): npm install should be in emscripten folder --- resources/locate_emscripten.inc.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh index f20ac5d0e9..3d470f7577 100644 --- a/resources/locate_emscripten.inc.sh +++ b/resources/locate_emscripten.inc.sh @@ -69,6 +69,7 @@ _select_emscripten_version_with_emsdk() { git pull ./emsdk install "$KEYMAN_MIN_VERSION_EMSCRIPTEN" ./emsdk activate "$KEYMAN_MIN_VERSION_EMSCRIPTEN" + cd upstream/emscripten npm install popd > /dev/null } From 046bd25f63fa2b1a6dab9f4f7963b56bba372217 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 23 Aug 2024 07:47:53 +0200 Subject: [PATCH 62/89] chore(developer): improve build order of operations so builds work on new machines --- developer/src/tike/build.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/developer/src/tike/build.sh b/developer/src/tike/build.sh index 1ab9dbe320..fd81ca692d 100755 --- a/developer/src/tike/build.sh +++ b/developer/src/tike/build.sh @@ -19,7 +19,7 @@ source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh" WIN32_TARGET="$WIN32_TARGET_PATH/tike.exe" builder_describe_outputs \ - configure:project /resources/build/win/delphi_environment_generated.inc.sh \ + configure:project /developer/src/tike/xml/layoutbuilder/keymanweb-osk.ttf \ build:project /developer/src/tike/$WIN32_TARGET #------------------------------------------------------------------------------------------------------------------- @@ -31,6 +31,7 @@ function do_configure() { mkdir -p "$DEVELOPER_PROGRAM" cp "$KEYMAN_ROOT/common/schemas/kps/kps.xsd" "$DEVELOPER_PROGRAM" cp "$KEYMAN_ROOT/common/resources/fonts/keymanweb-osk.ttf" "$DEVELOPER_ROOT/src/tike/xml/layoutbuilder/keymanweb-osk.ttf" + run_in_vs_env rc icons.rc } function do_monaco_copy() { @@ -52,8 +53,6 @@ function do_monaco_copy() { pushd "$DEVELOPER_ROOT/src/tike/xml/app/lib/sentry" replaceVersionStrings_Mkver init.js.in init.js popd - - run_in_vs_env rc icons.rc } KEYMANCORE_DLL=keymancore-2.dll From 74f586574590feb5b31e351e81a41a112de72a00 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 23 Aug 2024 15:10:43 +0200 Subject: [PATCH 63/89] docs(developer): update build documentation to refer to build.sh Fixes: #12270 --- developer/src/README.md | 40 +++++++++++++++++++++++++++++++++++++++- windows/src/README.md | 37 ++++++++++++++++++------------------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/developer/src/README.md b/developer/src/README.md index 7e7ea9d336..d789b63f08 100644 --- a/developer/src/README.md +++ b/developer/src/README.md @@ -2,6 +2,42 @@ This is the current home for Keyman Developer. +## Build Prerequisites + +* See [Windows Build Environment Configuration](../../docs/build/windows.md). + +## Building Keyman Developer + +1. Start 'Git Bash' (part of Git for Windows). +2. Run `developer/src/build.sh`. +3. Artifacts from a successful build will be placed in **developer/bin** folder. + +*Note*: running `build.sh` will currently reset the packages and path settings +in your Delphi environment. If you use Delphi for other projects, you should +consider building Keyman under a login user dedicated to it, or in a VM. + +Type `build.sh` to see build targets and actions. Common build actions are: + +* `build.sh build` +: builds Keyman Developer + +* `build.sh clean` +: remove temporary files and build artifacts + +* `build.sh publish` +: makes a release of all Keyman Developer projects + +* `build.sh install` +: install some or all components to Program Files (requires elevated command prompt). + +### Building without Delphi + +It is possible to build all components that do _not_ require Delphi. Currently a +few components are Delphi-based (TIKE, setup, a few others), but you may be able +to get away without building them. In this situation, we recommend copying the +relevant Delphi-built components into developer/bin folders from a compatible +installed version of Keyman Developer for testing and debugging purposes. + # Folders ## common @@ -106,4 +142,6 @@ testing and packing keyboards for distribution. ## tools -Various build-time tools for Keyman Developer. \ No newline at end of file +Various build-time tools for Keyman Developer. + + diff --git a/windows/src/README.md b/windows/src/README.md index 1d057482bb..1e66443ce7 100644 --- a/windows/src/README.md +++ b/windows/src/README.md @@ -1,40 +1,39 @@ -# Keyman for Windows and Keyman Developer +# Keyman for Windows ## Build Prerequisites * See [Windows Build Environment Configuration](../../docs/build/windows.md). -## Building Keyman for Windows and Keyman Developer +## Building Keyman for Windows -1. Start 'Developer Command Prompt for VS 2019'. -2. Run `nmake build` from the **windows/src** folder. +1. Start 'Git Bash' (part of Git for Windows). +2. Run `windows/src/build.sh`. 3. Artifacts from a successful build will be placed in **windows/bin** folder. -*Note*: running `nmake build` will currently reset the packages and path settings +*Note*: running `build.sh` will currently reset the packages and path settings in your Delphi environment. If you use Delphi for other projects, you should consider building Keyman under a login user dedicated to it, or in a VM. -Type `nmake` to see build targets. Common build targets are: +Type `build.sh` to see build targets and actions. Common build actions are: -* `nmake build` -: builds Keyman for Windows and Keyman Developer +* `build.sh build` +: builds Keyman for Windows -* `nmake clean` +* `build.sh clean` : remove temporary files and build artifacts -* `nmake release` +* `build.sh publish` : makes a release of all Keyman Windows projects -* `nmake install` +* `build.sh install` : install some or all components to Program Files (requires elevated command prompt). ### Building without Delphi -It is possible to build all components that do _not_ require Delphi by adding -the environment variable `NODELPHI=1` before starting the build. Currently many -components are Delphi-based, but if you are working just in Keyman Core, the -compiler, or Keyman Engine's C++ components, you may be able to get away without -building them. In this situation, we recommend copying the relevant Delphi-built +It is possible to build all components that do _not_ require Delphi. Currently +many components are Delphi-based, but if you are working just in Keyman Core, or +Keyman Engine's C++ components, you may be able to get away without building +them. In this situation, we recommend copying the relevant Delphi-built components into windows/bin folders from a compatible installed version of Keyman for testing and debugging purposes. @@ -45,8 +44,8 @@ build, you will need to obtain valid code signing certificates. See Certificates, below. Official release builds for Keyman are built in the Keyman project's CI environment. -1. Start 'Developer Command Prompt for VS 2019'. -2. Run `nmake release` from the **windows/src** folder. +1. Start 'Git Bash'. +2. Run `windows/src/build.sh publish`. 3. Artifacts from a successful build will be placed in **windows/release** folder. 4. **buildtools/help-keyman-com.sh** will push updated documentation to @@ -76,7 +75,7 @@ You do not need to install the **KeymanTest** certificates, only the **KeymanTestCA** certificates. If you have not already installed the **KeymanTestCA** certificates using the -`nmake` command above, to manually install the Keyman **KeymanTestCA** +`build.sh` command above, to manually install the Keyman **KeymanTestCA** certificates, do the following in **common/windows/delphi/tools/certificates**: 1. Open the certificate and click 'Install certificate...' to open the From 8457f9527a51a734b8fa8afb77ad1ba16a72a3eb Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 23 Aug 2024 17:53:48 +0200 Subject: [PATCH 64/89] chore(developer): extend timeouts for lm compiler tests to 5 secs Fixes: #12271 --- developer/src/kmc-model/test/test-compile-model.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/developer/src/kmc-model/test/test-compile-model.ts b/developer/src/kmc-model/test/test-compile-model.ts index e3074d697a..7de9d6d5da 100644 --- a/developer/src/kmc-model/test/test-compile-model.ts +++ b/developer/src/kmc-model/test/test-compile-model.ts @@ -9,6 +9,8 @@ import { KeymanFileTypes } from '@keymanapp/common-types'; describe('LexicalModelCompiler', function () { let callbacks = new TestCompilerCallbacks(); + this.timeout(5000); + // Try to compile ALL of the correct models. const MODELS = [ 'example.qaa.sencoten', From 9a8b6d1279e9070caf21103cdae6aa3db5e8c72e Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 23 Aug 2024 18:12:06 +0200 Subject: [PATCH 65/89] chore(windows): remove remaining unused Makefiles Fixes: #12247 --- common/windows/delphi/Defines.mak | 299 ------------------ common/windows/delphi/Header.mak | 59 ---- common/windows/delphi/Target.mak | 14 - resources/build/win/environment.inc.sh | 4 + windows/src/build.sh | 1 + windows/src/support/Makefile | 38 --- windows/src/support/build.sh | 22 ++ windows/src/support/charident/Makefile | 20 -- windows/src/support/etl2log/Makefile | 22 -- windows/src/support/etl2log/build.sh | 40 +++ windows/src/support/kdebug/Makefile | 21 -- windows/src/support/keycodetester/Makefile | 15 - windows/src/support/km_yim/Makefile | 24 -- windows/src/support/kmkb0045/Makefile | 19 -- windows/src/support/oskbulkrenderer/Makefile | 24 -- windows/src/support/oskbulkrenderer/build.sh | 39 +++ windows/src/support/richedit_examine/Makefile | 15 - windows/src/support/texteditor/Makefile | 36 --- windows/src/support/texteditor/build.sh | 44 +++ windows/src/support/windowinfo/Makefile | 15 - .../manual-tests/integration-tests/Makefile | 26 -- .../integration-tests/keymanapi/Makefile | 23 -- .../test/manual-tests/regressiontest/Makefile | 16 - .../regressiontest/tests/Makefile | 11 - .../manual-tests/test_httpuploader/Makefile | 18 -- 25 files changed, 150 insertions(+), 715 deletions(-) delete mode 100644 common/windows/delphi/Defines.mak delete mode 100644 common/windows/delphi/Header.mak delete mode 100644 common/windows/delphi/Target.mak delete mode 100644 windows/src/support/Makefile create mode 100755 windows/src/support/build.sh delete mode 100644 windows/src/support/charident/Makefile delete mode 100644 windows/src/support/etl2log/Makefile create mode 100755 windows/src/support/etl2log/build.sh delete mode 100644 windows/src/support/kdebug/Makefile delete mode 100644 windows/src/support/keycodetester/Makefile delete mode 100644 windows/src/support/km_yim/Makefile delete mode 100644 windows/src/support/kmkb0045/Makefile delete mode 100644 windows/src/support/oskbulkrenderer/Makefile create mode 100755 windows/src/support/oskbulkrenderer/build.sh delete mode 100644 windows/src/support/richedit_examine/Makefile delete mode 100644 windows/src/support/texteditor/Makefile create mode 100755 windows/src/support/texteditor/build.sh delete mode 100644 windows/src/support/windowinfo/Makefile delete mode 100644 windows/src/test/manual-tests/integration-tests/Makefile delete mode 100644 windows/src/test/manual-tests/integration-tests/keymanapi/Makefile delete mode 100644 windows/src/test/manual-tests/regressiontest/Makefile delete mode 100644 windows/src/test/manual-tests/regressiontest/tests/Makefile delete mode 100644 windows/src/test/manual-tests/test_httpuploader/Makefile diff --git a/common/windows/delphi/Defines.mak b/common/windows/delphi/Defines.mak deleted file mode 100644 index 50210e5fea..0000000000 --- a/common/windows/delphi/Defines.mak +++ /dev/null @@ -1,299 +0,0 @@ -# DEBUG=1 - -# TODO: this should be a shared Defines.mak for common,developer,windows. So we -# need to move any project-specific stuff into a defines-windows.mak, -# defines-etc.mak - -# -# Paths -# - -!IFNDEF KEYMAN_ROOT -!ERROR KEYMAN_ROOT must be defined! -!ENDIF - -# TODO: COMMON_ROOT should be common\windows -COMMON_ROOT=$(KEYMAN_ROOT)\common\windows\delphi -WINDOWS_ROOT=$(KEYMAN_ROOT)\windows -OUTLIB=$(WINDOWS_ROOT)\lib -COMMON_OUTLIB=$(KEYMAN_ROOT)\windows\lib -COMMON_BIN=$(KEYMAN_ROOT)\windows\bin - -# INCLUDE=$(ROOT)\src\global\inc;$(INCLUDE) - -!IFDEF DEBUG -GO_FAST=1 -MAKEFLAG_DEBUG="DEBUG=$(DEBUG)" -DELPHI_MSBUILD_FLAG_DEBUG="/p:Config=Debug" -!ELSE -!IFDEF TEAMCITY_PR_NUMBER -GO_FAST=1 -!ENDIF -DELPHI_MSBUILD_FLAG_DEBUG="/p:Config=Release" -!ENDIF - -!IFDEF USERDEFINES -MAKEFLAG_USERDEFINES="USERDEFINES=$(USERDEFINES)" -!ENDIF - -!IFDEF SC_TIMESTAMP -MAKEFLAG_SC_TIMESTAMP="SC_TIMESTAMP=$(SC_TIMESTAMP)" -!ENDIF - -!IFDEF BUILDHELP -MAKEFLAG_BUILDHELP="BUILDHELP=$(BUILDHELP)" -!ENDIF - -!IFDEF LINT -MAKEFLAG_LINT="LINT=$(LINT)" -!ENDIF - -!IFDEF NOUI -MAKEFLAG_QUIET="NOUI=$(NOUI)" -!ELSE -!IFDEF QUIET -MAKEFLAG_QUIET="QUIET=$(QUIET)" -!ENDIF -!ENDIF - -!IFDEF RELEASE_OEM -MAKEFLAG_RELEASE_OEM="RELEASE_OEM=$(RELEASE_OEM)" -!ENDIF - -# -# USERDEFINES allows the developer to specify overrides for various settings. We need a variable -# because Makefiles cannot test for file existence -# - -# TODO: can we eliminate this? - -!ifdef USERDEFINES -!include $(WINDOWS_ROOT)\src\UserDefines.mak -!endif - -# -# Delphi Compiler Configuration - Delphi 10.3.2 -# - -!IFNDEF DELPHI_VERSION -DELPHI_VERSION=20.0 -!ENDIF - -DCC32PATH=C:\Program Files (x86)\Embarcadero\Studio\$(DELPHI_VERSION)\bin - -# -# Pass local configuration through to sub-instances of MAKE -# - -MAKE="nmake" /C $(MAKEFLAG_QUICK_BUILD_KEYMAN) $(MAKEFLAG_USERDEFINES) $(MAKEFLAG_DEBUG) $(MAKEFLAG_BUILDHELP) $(MAKEFLAG_BUILDRTF) $(MAKEFLAG_SC_TIMESTAMP) $(MAKEFLAG_LINT) $(MAKEFLAG_QUIET) $(MAKEFLAG_RELEASE_OEM) - -# -# Delphi build commands -# - -!IFDEF DEBUG -TARGET_PATH=Debug -!ELSE -TARGET_PATH=Release -!ENDIF - -!IFDEF LINT -DELPHIWARNINGS=-W+MESSAGE_DIRECTIVE -W+IMPLICIT_STRING_CAST -W+IMPLICIT_STRING_CAST_LOSS -W+EXPLICIT_STRING_CAST -W+EXPLICIT_STRING_CAST_LOSS -W+CVT_WCHAR_TO_ACHAR -W+CVT_NARROWING_STRING_LOST -W+CVT_ACHAR_TO_WCHAR -W+CVT_WIDENING_STRING_LOST -W+UNICODE_TO_LOCALE -W+LOCALE_TO_UNICODE -W+IMPLICIT_VARIANTS -!ELSE -DELPHIWARNINGS=-W-MESSAGE_DIRECTIVE -W-IMPLICIT_STRING_CAST -W-IMPLICIT_STRING_CAST_LOSS -W-EXPLICIT_STRING_CAST -W-EXPLICIT_STRING_CAST_LOSS -W-CVT_WCHAR_TO_ACHAR -W-CVT_NARROWING_STRING_LOST -W-CVT_ACHAR_TO_WCHAR -W-CVT_WIDENING_STRING_LOST -W-UNICODE_TO_LOCALE -W-LOCALE_TO_UNICODE -W-IMPLICIT_VARIANTS -W-IMPLICIT_INTEGER_CAST_LOSS -W-IMPLICIT_CONVERSION_LOSS -W-COMBINING_SIGNED_UNSIGNED64 -W-COMBINING_SIGNED_UNSIGNED64 -!ENDIF - -DELPHIDPRPARAMS=-Q -B -GD -H -VT -^$C+ -^$D+ -^$J+ -^$L+ -^$O+ -^$Q- -^$R- -^$W+ -^$Y+ -E. $(DELPHIWARNINGS) -I$(DELPHIINCLUDES) -U$(DELPHIINCLUDES) -R$(DELPHIINCLUDES) -NSVcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Web;Soap;Winapi;System.Win -NU.\obj\Win32\$(TARGET_PATH) -E.\bin\Win32\$(TARGET_PATH) -DELPHIDPRPARAMS64=-Q -B -GD -H -VT -^$C+ -^$D+ -^$J+ -^$L+ -^$O+ -^$Q- -^$R- -^$W+ -^$Y+ -E. $(DELPHIWARNINGS) -I$(DELPHIINCLUDES) -U$(DELPHIINCLUDES) -R$(DELPHIINCLUDES) -NSVcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Web;Soap;Winapi;System.Win -NU.\obj\Win64\$(TARGET_PATH) -E.\bin\Win64\$(TARGET_PATH) -DELPHIDPKPARAMS=-Q -B -GD -VT -^$C+ -^$D+ -^$J+ -^$L+ -^$O+ -^$Q- -^$R- -^$W+ -^$Y+ -E. $(DELPHIWARNINGS) -I$(DELPHIINCLUDES) -U$(DELPHIINCLUDES) -R$(DELPHIINCLUDES) -NSVcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Web;Soap;Winapi;System.Win -LE$(OUTLIB) -LN$(OUTLIB) -NSData -NUobj\Win32\$(TARGET_PATH) - -COMMON_DELPHIDPKPARAMS=-Q -B -GD -VT -^$C+ -^$D+ -^$J+ -^$L+ -^$O+ -^$Q- -^$R- -^$W+ -^$Y+ -E. $(DELPHIWARNINGS) -I$(DELPHIINCLUDES) -U$(DELPHIINCLUDES) -R$(DELPHIINCLUDES) -NSVcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Web;Soap;Winapi;System.Win -LE$(COMMON_OUTLIB) -LN$(COMMON_OUTLIB) -NSData -NUobj\Win32\$(TARGET_PATH) - -# we are using cmd /c because dcc32/dcc64 are failing on direct execution -# from nmake -DCC32=cmd /c "$(DCC32PATH)\dcc32.exe" $(DELPHIDPRPARAMS) -DCC32DPK=cmd /c "$(DCC32PATH)\dcc32.exe" $(DELPHIDPKPARAMS) -COMMON_DCC32DPK=cmd /c "$(DCC32PATH)\dcc32.exe" $(COMMON_DELPHIDPKPARAMS) -DCC64=cmd /c "$(DCC32PATH)\dcc64.exe" $(DELPHIDPRPARAMS64) -N0x64\ -Ex64\ - -# -# Delphi MSBuild related commands and macros -# - -DELPHI_MSBUILD="$(COMMON_ROOT)\tools\msbuild-wrapper.bat" "$(DCC32PATH)" $(DELPHI_MSBUILD_FLAG_DEBUG) - -!IFDEF NODELPHI -DCC32=echo skipping -DCC32DPK=echo skipping -DCC64=echo skipping -DELPHI_MSBUILD=echo skipping -!ENDIF - -# Visual C++ x86, x64 -WIN32_TARGET_PATH=bin\Win32\$(TARGET_PATH) -X64_TARGET_PATH=bin\x64\$(TARGET_PATH) - -# Delphi x86, x64 -# WIN32_TARGET_PATH=... -WIN64_TARGET_PATH=bin\Win64\$(TARGET_PATH) - -# -# Shared devtools app for common Delphi source manipulation -# - -DEVTOOLS=$(COMMON_ROOT)\tools\devtools\$(WIN32_TARGET_PATH)\devtools.exe - -# -# Other program build commands -# - -BRCC32=rc.exe - -HHC="C:\Program Files (x86)\HTML Help Workshop\hhc.exe" -NMAKE=nmake.exe -CL=cl.exe -MSBUILD=msbuild.exe -# /maxcpucount see https://devblogs.microsoft.com/cppblog/precompiled-header-pch-issues-and-recommendations/ -MT=mt.exe -VCBUILD=error - -!IFDEF DEBUG -MSBUILD_BUILD=/t:Build /p:Configuration=Debug -MSBUILD_CLEAN=/t:Clean /p:Configuration=Debug -!ELSE -MSBUILD_BUILD=/t:Rebuild /p:Configuration=Release -MSBUILD_CLEAN=/t:Clean /p:Configuration=Release -!ENDIF - -COPY=copy -ISXBUILD=C:\PROGRA~1\INSTALLSHIELD\Express\System\IsExpCmdBld -WZZIPPATH="C:\program files\7-zip\7z.exe" -!IFDEF GO_FAST -WZZIP=$(WZZIPPATH) a -mx1 -!ELSE -WZZIP=$(WZZIPPATH) a -mx9 -!ENDIF -WZUNZIP=$(WZZIPPATH) e - -# we are using cmd /c because tds2dbg is failing on direct execution -# from nmake -TDS2DBG=cmd /c $(KEYMAN_ROOT)\common\windows\bin\tools\tds2dbg -SENTRYTOOL=$(COMMON_ROOT)\tools\sentrytool\$(WIN32_TARGET_PATH)\sentrytool.exe -SENTRYTOOL_DELPHIPREP=$(SENTRYTOOL) delphiprep -r $(KEYMAN_ROOT) -i $(DELPHIINCLUDES) - -WIXPATH="c:\program files (x86)\WiX Toolset v3.11\bin" -WIXCANDLE=$(WIXPATH)\candle.exe -wx -nologo - -!IFDEF LINT -WIXLIGHTLINT= -!ELSE -# we suppress ICE82 because it reports spurious errors with merge module keymanengine to do with duplicate sequence numbers. Safely ignored. -WIXLIGHTLINT= -sice:ICE82 -sice:ICE80 -!ENDIF - -!IFDEF GO_FAST -# for debug builds, we turn off compression because it is so hideously slow -# for test builds, we also turn off compression -WIXLIGHTCOMPRESSION=-dcl:none -!ELSE -WIXLIGHTCOMPRESSION=-dcl:high -!ENDIF - -WIXLIGHT=$(WIXPATH)\light.exe -wx -nologo $(WIXLIGHTLINT) $(WIXLIGHTCOMPRESSION) - -WIXLIT=$(WIXPATH)\lit.exe -wx -nologo -WIXHEAT=$(WIXPATH)\heat.exe - -LINKPATH=link.exe - -# -# Certificates and code signing -# - -!ifdef SIGNCODE_BUILD -MAKE=$(MAKE) "SIGNCODE_BUILD=$(SIGNCODE_BUILD)" -!else -MAKE=$(MAKE) -!endif - -# -# To get a .pfx from a .spc and .pvk, run pvk2pfx.exe -# - -!IFNDEF SC_PFX_SHA1 -SC_PFX_SHA1="$(COMMON_ROOT)\tools\certificates\keymantest-sha1.pfx" -!ENDIF - -!IFNDEF SC_PFX_SHA256 -SC_PFX_SHA256="$(COMMON_ROOT)\tools\certificates\keymantest-sha256.pfx" -!ENDIF - -!IFNDEF SC_URL -SC_URL="https://keyman.com/" -!ENDIF - -!IFNDEF SC_PWD -SC_PWD="" -!ENDIF - -SIGNCODE=@"$(KEYMAN_ROOT)\common\windows\signtime.bat" signtool.exe $(SC_PFX_SHA1) $(SC_PFX_SHA256) $(SC_URL) $(SC_PWD) - -# -# On some computers, the PLATFORM environment variable is set to x86. This can break msbuild -# with our projects. This may be resolvable in the future, but for now the easy fix is ... -# - -PLATFORM=Win32 - -# -# mkver commands. mkver determines tag from the local build environment variables -# in the same way as /resources/build/build-utils.sh. -# - -!ifdef GIT_BASH_FOR_KEYMAN -MKVER_SH=$(GIT_BASH_FOR_KEYMAN) $(KEYMAN_ROOT)\common\windows\mkver.sh -!else -MKVER_SH=start /wait $(KEYMAN_ROOT)\common\windows\mkver.sh -!endif - -MKVER_M=$(MKVER_SH) manifest.in manifest.xml -MKVER_U=$(MKVER_SH) - -# -# Symstore -# - -# KEYMAN_SYMSTOREPATH defaults to sibling folder "symbols". If it is not present, -# then we won't attempt to write symbols to the store. -!IFNDEF KEYMAN_SYMSTOREPATH -KEYMAN_SYMSTOREPATH=$(KEYMAN_ROOT)\..\symbols -!ENDIF - -# Nearly matches algorithm from resources/build/build-utils.sh -# For now, we'll use it only for SYMSTORE, where it is for reference -# only. Thus using the variable name __VERSION_WITH_TAG. Issues: -# 1. always appends tier, even for stable -# 2. test builds will append a branch name for master/beta/stable-x.y -# 3. this is only available for `make symbols` (VERSION_WIN, VERSION_TIER -# are defined in Targets.mak only here) -# Fixing this properly would be possible but take a fair bit more -# work than I want to do just now. The intent is to make it possible to find -# symbols in the symstore index which we can purge later on. -__VERSION_WITH_TAG=$(VERSION_WIN)-$(VERSION_TIER) -!IFNDEF TEAMCITY_VERSION -__VERSION_WITH_TAG=$(__VERSION_WITH_TAG)-local -!ELSE -!IFDEF TEAMCITY_PR_NUMBER -__VERSION_WITH_TAG=$(__VERSION_WITH_TAG)-test-$(TEAMCITY_PR_NUMBER) -!ENDIF -!ENDIF - -# This command depends on VERSION_WIN and VERSION_TIER being defined, through -# `make symbols` (i.e. don't call `make wrap-symbols`) -SYMSTORE="C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\symstore.exe" add \ - /s "$(KEYMAN_SYMSTOREPATH)" \ - /v "$(VERSION_WIN)" \ - /c "Version: $(__VERSION_WITH_TAG)" \ - /compress /f - -CLEAN=-del /S /Q diff --git a/common/windows/delphi/Header.mak b/common/windows/delphi/Header.mak deleted file mode 100644 index 6c78b3724e..0000000000 --- a/common/windows/delphi/Header.mak +++ /dev/null @@ -1,59 +0,0 @@ -# -# Header.mak - used for makefiles which are in parent folders -# - -HEADER_MAK=1 - -!IFNDEF TARGETS -!ERROR You must define the targets before including the Header.mak file! -!ENDIF - -!IFNDEF KEYMAN_ROOT -!ERROR KEYMAN_ROOT must be defined! -!ENDIF - -# This path will need to be updated if the root path changes - -!include $(KEYMAN_ROOT)\common\windows\delphi\Defines.mak - -# -# The targets build, signcode, symbols are standard -# targets for all projects -# - -build: $(BUILDPREREQ) - $(MAKE) "TARGET=build" $(TARGETS) - -!IFNDEF NOTARGET_SIGNCODE -signcode: - $(MAKE) "TARGET=signcode" $(TARGETS) - -symbols: - $(MAKE) "TARGET=symbols" $(TARGETS) -!ELSE -signcode: - rem no signcode required - -symbols: - rem no symbols required -!ENDIF - -build-release: -!IFDEF RELEASE_TARGETS - $(MAKE) "TARGET=build-release" $(RELEASE_TARGETS) -!ELSE - @rem -!ENDIF - -clean: - $(MAKE) "TARGET=clean" $(TARGETS) $(CLEANS) - -install: - $(MAKE) "TARGET=install" $(TARGETS) - -test-manifest: -!IFDEF MANIFESTS - $(MAKE) "TARGET=test-manifest" $(MANIFESTS) -!ELSE - $(MAKE) "TARGET=test-manifest" $(TARGETS) -!ENDIF \ No newline at end of file diff --git a/common/windows/delphi/Target.mak b/common/windows/delphi/Target.mak deleted file mode 100644 index 777bd84beb..0000000000 --- a/common/windows/delphi/Target.mak +++ /dev/null @@ -1,14 +0,0 @@ -!CMDSWITCHES +S - -def-clean: - $(CLEAN) *.err *.stat *.dproj.local *.Build.CppClean.Log *.suo *.jdbg *.dbg *.dcu *.~* *.dsk *.exe *.rsm *.ncb *.opt *.pch *.plg *.aps *.001 *.sbr *.dep *.drc *.bak *.pdb *.lib *.cod *.ilk *.tds vc80.idb *.map *.bsc version.res manifest.xml manifest.res >nul 2>nul - $(CLEAN) ExcMagic.Debug *.wixpdb *.identcache *.embed.manifest *.embed.manifest.res *.intermediate.manifest error.log >nul 2>nul - if exist bin rd /s/q bin - if exist obj rd /s/q obj - -!CMDSWITCHES -S - -# This virtual rule forces targets which are folders, e.g. `kmshell` to -# always execute -.virtual: - rem always execute diff --git a/resources/build/win/environment.inc.sh b/resources/build/win/environment.inc.sh index d2b351fcbc..620e96146a 100644 --- a/resources/build/win/environment.inc.sh +++ b/resources/build/win/environment.inc.sh @@ -23,8 +23,10 @@ source "$KEYMAN_ROOT/resources/build/win/environment_generated.inc.sh" WINDOWS_ROOT="$KEYMAN_ROOT/windows" WINDOWS_PROGRAM_APP="$WINDOWS_ROOT/bin/desktop" WINDOWS_PROGRAM_ENGINE="$WINDOWS_ROOT/bin/engine" +WINDOWS_PROGRAM_SUPPORT="$WINDOWS_ROOT/bin/support" WINDOWS_DEBUGPATH_APP="$WINDOWS_ROOT/debug/desktop" WINDOWS_DEBUGPATH_ENGINE="$WINDOWS_ROOT/debug/engine" +WINDOWS_DEBUGPATH_SUPPORT="$WINDOWS_ROOT/debug/suppor" COMMON_ROOT="$KEYMAN_ROOT/common/windows/delphi" OUTLIB="$WINDOWS_ROOT/lib" @@ -141,6 +143,8 @@ create-windows-output-folders() { mkdir -p "$OUTLIB" mkdir -p "$WINDOWS_PROGRAM_APP" mkdir -p "$WINDOWS_PROGRAM_ENGINE" + mkdir -p "$WINDOWS_PROGRAM_SUPPORT" mkdir -p "$WINDOWS_DEBUGPATH_APP" mkdir -p "$WINDOWS_DEBUGPATH_ENGINE" + mkdir -p "$WINDOWS_DEBUGPATH_SUPPORT" } \ No newline at end of file diff --git a/windows/src/build.sh b/windows/src/build.sh index a1fc4d0e1a..4ef6da65b8 100755 --- a/windows/src/build.sh +++ b/windows/src/build.sh @@ -18,6 +18,7 @@ builder_describe \ ":engine Keyman Engine for Windows" \ ":desktop Keyman for Windows" \ ":components=global/delphi Delphi components" \ + ":support Support tools" \ ":test=test/unit-tests Shared unit tests" \ ":fv=../../oem/firstvoices/windows/src/inst OEM FirstVoices for Windows app" diff --git a/windows/src/support/Makefile b/windows/src/support/Makefile deleted file mode 100644 index 56609e21e4..0000000000 --- a/windows/src/support/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# -# Support Makefile -# - -!ifdef NODELPHI -TARGETS=etl2log texteditor -!else -TARGETS=oskbulkrenderer etl2log texteditor -!endif -CLEANS=clean-support - -!include ..\Header.mak - -# ---------------------------------------------------------------------- - -oskbulkrenderer: .virtual - cd $(ROOT)\src\support\oskbulkrenderer - $(MAKE) $(TARGET) - -etl2log: .virtual - cd $(ROOT)\src\support\etl2log - $(MAKE) $(TARGET) - -texteditor: .virtual - cd $(ROOT)\src\support\texteditor - $(MAKE) $(TARGET) - -# ---------------------------------------------------------------------- - -clean-support: - cd $(ROOT)\src\support - -del version.txt - -!include ..\Target.mak - -# ---------------------------------------------------------------------- -# EOF -# ---------------------------------------------------------------------- diff --git a/windows/src/support/build.sh b/windows/src/support/build.sh new file mode 100755 index 0000000000..f9f20f1716 --- /dev/null +++ b/windows/src/support/build.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../resources/build/builder.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +builder_describe \ + "Keyman for Windows support tools" \ + \ + clean \ + configure \ + build \ + test \ + \ + :oskbulkrenderer \ + :etl2log \ + :texteditor + +builder_parse "$@" + +builder_run_child_actions clean configure build test publish install diff --git a/windows/src/support/charident/Makefile b/windows/src/support/charident/Makefile deleted file mode 100644 index cff6741677..0000000000 --- a/windows/src/support/charident/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# charident Makefile -# - -!include ..\..\Defines.mak - -build: version.res dirs - $(DCC32) charident.dpr - $(COPY) charident.exe $(PROGRAM)\support - -clean: def-clean - -signcode: - $(SIGNCODE) /d "Character Identifier" $(PROGRAM)\support\charident.exe - -wrap-symbols: - $(SYMSTORE) $(PROGRAM)\support\charident.exe /t keyman-windows -#TODO: $(SYMSTORE) $(DEBUGPATH)\support\charident.dbg /t keyman-windows - -!include ..\..\Target.mak diff --git a/windows/src/support/etl2log/Makefile b/windows/src/support/etl2log/Makefile deleted file mode 100644 index 48bdb1a592..0000000000 --- a/windows/src/support/etl2log/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# -# etl2log Makefile -# - -!include ..\..\Defines.mak - -build: version.res dirs - $(MSBUILD) etl2log.vcxproj $(MSBUILD_BUILD) - $(COPY) $(WIN32_TARGET_PATH)\etl2log.exe $(PROGRAM)\support - $(COPY) $(WIN32_TARGET_PATH)\etl2log.pdb $(DEBUGPATH)\support - -clean: def-clean - $(MSBUILD) etl2log.vcxproj $(MSBUILD_CLEAN) - -signcode: - $(SIGNCODE) /d "Keyman Engine Tools" $(PROGRAM)\support\etl2log.exe - -wrap-symbols: - $(SYMSTORE) $(PROGRAM)\support\etl2log.exe /t keyman-windows - $(SYMSTORE) $(DEBUGPATH)\support\etl2log.pdb /t keyman-windows - -!include ..\..\Target.mak diff --git a/windows/src/support/etl2log/build.sh b/windows/src/support/etl2log/build.sh new file mode 100755 index 0000000000..e2fdee1acd --- /dev/null +++ b/windows/src/support/etl2log/build.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +builder_describe "etl2log" \ + clean configure build test + +builder_parse "$@" + +#------------------------------------------------------------------------------------------------------------------- + +source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh" +WIN32_TARGET="$WIN32_TARGET_PATH/etl2log.exe" + +builder_describe_outputs \ + configure:project /resources/build/win/delphi_environment_generated.inc.sh \ + build:project /windows/src/support/etl2log/$WIN32_TARGET + +#------------------------------------------------------------------------------------------------------------------- + +function do_clean() { + vs_msbuild etl2log.vcxproj //t:Clean + clean_windows_project_files +} + +function do_build() { + create-windows-output-folders + build_version.res + vs_msbuild etl2log.vcxproj //t:Build "//p:Platform=Win32" + cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_SUPPORT" + cp "$WIN32_TARGET_PATH/etl2log.pdb" "$WINDOWS_DEBUGPATH_SUPPORT" +} + +builder_run_action clean:project do_clean +builder_run_action configure:project configure_windows_build_environment +builder_run_action build:project do_build +# builder_run_action test:project do_test diff --git a/windows/src/support/kdebug/Makefile b/windows/src/support/kdebug/Makefile deleted file mode 100644 index 1a13a18ebe..0000000000 --- a/windows/src/support/kdebug/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# KDebug Makefile -# - -!include ..\..\Defines.mak - -!ifdef DEBUG - NMCFG=kdebug - Win32 Debug -!else - NMCFG=kdebug - Win32 Release -!endif - -install: dirs build - -build: version.res - $(NMAKE) /f kdebug.mak "CFG=$(NMCFG)" - -clean: def-clean - $(NMAKE) /f kdebug.mak "CFG=$(NMCFG)" CLEAN - -!include ..\..\Target.mak diff --git a/windows/src/support/keycodetester/Makefile b/windows/src/support/keycodetester/Makefile deleted file mode 100644 index 38687abaeb..0000000000 --- a/windows/src/support/keycodetester/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Keycodetester Makefile -# - -!include ..\..\Defines.mak - -install: dirs build - $(COPY) keycodetester.exe $(PROGRAM)\bldutil - -build: - $(DCC32) keycodetester.dpr - -clean: def-clean - -!include ..\..\Target.mak diff --git a/windows/src/support/km_yim/Makefile b/windows/src/support/km_yim/Makefile deleted file mode 100644 index 1aef5f80f0..0000000000 --- a/windows/src/support/km_yim/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# TODO: remove this project -# - -!include ..\..\Defines.mak - -build: -# version.res - $(DCC32) km_yim.dpr - rem $(TDSPACK) $(PROGRAM)\desktop\km_yim.exe km_yim.tds - rem $(TDS2DBG) $(PROGRAM)\desktop\km_yim.exe - $(WZZIP) inst_km_yim.zip km_yim.exe -# $(WZSE) inst_km_yim -setup -t inst_km_yim.dialog.txt -st "Tavultesoft Keyman Desktop Yahoo Messenger Addin" -c km_yim.exe - -clean: def-clean - if exist inst_km_yim.zip del inst_km_yim.zip - -signcode: - $(SIGNCODE) /d "Tavultesoft Keyman Desktop Yahoo Messenger Addin" inst_km_yim.exe - -wrap-symbols: - rem - -!include ..\..\Target.mak diff --git a/windows/src/support/kmkb0045/Makefile b/windows/src/support/kmkb0045/Makefile deleted file mode 100644 index 3e914c8acd..0000000000 --- a/windows/src/support/kmkb0045/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# -# TODO: remove this project -# - -!include ..\..\Defines.mak - -build: version.res manifest.res - $(DCC32) kmkb0045.dpr - $(SENTRYTOOL_DELPHIPREP) kmkb0045.exe -dpr kmkb0045.dpr - $(TDS2DBG) kmkb0045.exe - $(COPY) kmkb0045.exe $(PROGRAM)\support - -clean: def-clean - -signcode: - $(SIGNCODE) /d "Tavultesoft KMKB0045" $(PROGRAM)\support\kmkb0045.exe - - -!include ..\..\Target.mak diff --git a/windows/src/support/oskbulkrenderer/Makefile b/windows/src/support/oskbulkrenderer/Makefile deleted file mode 100644 index 65b8e02ba6..0000000000 --- a/windows/src/support/oskbulkrenderer/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# oskbulkrenderer Makefile -# - -!include ..\..\Defines.mak - -build: version.res dirs - $(DELPHI_MSBUILD) oskbulkrenderer.dproj "/p:Platform=Win32" - - $(SENTRYTOOL_DELPHIPREP) $(WIN32_TARGET_PATH)\oskbulkrenderer.exe -dpr oskbulkrenderer.dpr - $(TDS2DBG) $(WIN32_TARGET_PATH)\oskbulkrenderer.exe - $(COPY) $(WIN32_TARGET_PATH)\oskbulkrenderer.exe $(PROGRAM)\support - if exist $(WIN32_TARGET_PATH)\oskbulkrenderer.dbg $(COPY) $(WIN32_TARGET_PATH)\oskbulkrenderer.dbg $(DEBUGPATH)\support - -clean: def-clean - -rd /s/q Win32 - -signcode: - rem Not signing this utility - -wrap-symbols: - @rem - -!include ..\..\Target.mak diff --git a/windows/src/support/oskbulkrenderer/build.sh b/windows/src/support/oskbulkrenderer/build.sh new file mode 100755 index 0000000000..76fa8a4032 --- /dev/null +++ b/windows/src/support/oskbulkrenderer/build.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +builder_describe "oskbuildrenderer" \ + clean configure build test + +builder_parse "$@" + +#------------------------------------------------------------------------------------------------------------------- + +source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh" +WIN32_TARGET="$WIN32_TARGET_PATH/oskbulkrenderer.exe" + +builder_describe_outputs \ + configure:project /resources/build/win/delphi_environment_generated.inc.sh \ + build:project /windows/src/support/oskbulkrenderer/$WIN32_TARGET + +#------------------------------------------------------------------------------------------------------------------- + +function do_clean() { + clean_windows_project_files +} + +function do_build() { + create-windows-output-folders + build_version.res + delphi_msbuild oskbulkrenderer.dproj "//p:Platform=Win32" + + cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_SUPPORT" +} + +builder_run_action clean:project do_clean +builder_run_action configure:project configure_windows_build_environment +builder_run_action build:project do_build +# builder_run_action test:project do_test diff --git a/windows/src/support/richedit_examine/Makefile b/windows/src/support/richedit_examine/Makefile deleted file mode 100644 index adacba5901..0000000000 --- a/windows/src/support/richedit_examine/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# richedit_examine Makefile -# - -!include ..\..\Defines.mak - -install: dirs build - $(COPY) richedit_examine.exe $(PROGRAM)\bldutil - -build: version.res - $(DCC32) richedit_examine.dpr - -clean: def-clean - -!include ..\..\Target.mak diff --git a/windows/src/support/texteditor/Makefile b/windows/src/support/texteditor/Makefile deleted file mode 100644 index 473bf57598..0000000000 --- a/windows/src/support/texteditor/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# Keyman Text Editor Makefile -# - -!include ..\..\Defines.mak - -build: - $(MSBUILD) editor.vcxproj $(MSBUILD_BUILD) /p:Platform=x86 - $(MSBUILD) editor.vcxproj $(MSBUILD_BUILD) /p:Platform=x64 - $(COPY) $(WIN32_TARGET_PATH)\editor32.exe $(PROGRAM)\support - $(COPY) $(WIN32_TARGET_PATH)\editor32.pdb $(DEBUGPATH)\support - $(COPY) $(X64_TARGET_PATH)\editor64.exe $(PROGRAM)\support - $(COPY) $(X64_TARGET_PATH)\editor64.pdb $(DEBUGPATH)\support - -clean: def-clean - $(MSBUILD) $(MSBUILD_CLEAN) editor.sln - -signcode: - $(SIGNCODE) /d "Text Editor for testing Keyman" $(PROGRAM)\support\editor32.exe - $(SIGNCODE) /d "Text Editor for testing Keyman" $(PROGRAM)\support\editor64.exe - -install: - $(COPY) $(PROGRAM)\support\editor32.exe "$(INSTALLPATH_KEYMANENGINE)" - $(COPY) $(PROGRAM)\support\editor64.exe "$(INSTALLPATH_KEYMANENGINE)" - -wrap-symbols: - $(SYMSTORE) $(PROGRAM)\support\editor32.exe /t keyman-windows - $(SYMSTORE) $(PROGRAM)\support\editor64.exe /t keyman-windows - $(SYMSTORE) $(DEBUGPATH)\support\editor32.pdb /t keyman-windows - $(SYMSTORE) $(DEBUGPATH)\support\editor64.pdb /t keyman-windows - - -!include ..\..\Target.mak -# ---------------------------------------------------------------------- -# EOF -# ---------------------------------------------------------------------- diff --git a/windows/src/support/texteditor/build.sh b/windows/src/support/texteditor/build.sh new file mode 100755 index 0000000000..312ee1d0f4 --- /dev/null +++ b/windows/src/support/texteditor/build.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +builder_describe "texteditor" \ + clean configure build test + +builder_parse "$@" + +#------------------------------------------------------------------------------------------------------------------- + +source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh" +WIN32_TARGET="$WIN32_TARGET_PATH/editor32.exe" +X64_TARGET="$X64_TARGET_PATH/editor64.exe" + +builder_describe_outputs \ + configure:project /resources/build/win/delphi_environment_generated.inc.sh \ + build:project /windows/src/support/texteditor/$WIN32_TARGET + +#------------------------------------------------------------------------------------------------------------------- + +function do_clean() { + vs_msbuild Editor.vcxproj //t:Clean + clean_windows_project_files +} + +function do_build() { + create-windows-output-folders + # build_version.res + vs_msbuild Editor.vcxproj //t:Build "//p:Platform=Win32" + vs_msbuild Editor.vcxproj //t:Build "//p:Platform=x64" + cp "$WIN32_TARGET" "$WINDOWS_PROGRAM_SUPPORT" + cp "$X64_TARGET" "$WINDOWS_PROGRAM_SUPPORT" + cp "$WIN32_TARGET_PATH/editor32.pdb" "$WINDOWS_DEBUGPATH_SUPPORT" + cp "$X64_TARGET_PATH/editor64.pdb" "$WINDOWS_DEBUGPATH_SUPPORT" +} + +builder_run_action clean:project do_clean +builder_run_action configure:project configure_windows_build_environment +builder_run_action build:project do_build +# builder_run_action test:project do_test diff --git a/windows/src/support/windowinfo/Makefile b/windows/src/support/windowinfo/Makefile deleted file mode 100644 index ac7da2c182..0000000000 --- a/windows/src/support/windowinfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# windowinfo Makefile -# - -!include ..\..\Defines.mak - -install: dirs build - $(COPY) windowinfo.exe $(PROGRAM)\bldutil - -build: version.res - $(DCC32) windowinfo.dpr - -clean: def-clean - -!include ..\..\Target.mak diff --git a/windows/src/test/manual-tests/integration-tests/Makefile b/windows/src/test/manual-tests/integration-tests/Makefile deleted file mode 100644 index 093dc44140..0000000000 --- a/windows/src/test/manual-tests/integration-tests/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Integration Tests Makefile. -# - -# ---------------------------------------------------------------------- - -TARGETS=keymanapi - -test: - $(MAKE) "TARGET=test" $(TARGETS) - -!include ..\..\Header.mak - -# ---------------------------------------------------------------------- - -keymanapi: - cd $(ROOT)\src\test\integration-tests\keymanapi - $(MAKE) $(TARGET) - -# ---------------------------------------------------------------------- - -!include ..\..\Target.mak - -# ---------------------------------------------------------------------- -# EOF -# ---------------------------------------------------------------------- diff --git a/windows/src/test/manual-tests/integration-tests/keymanapi/Makefile b/windows/src/test/manual-tests/integration-tests/keymanapi/Makefile deleted file mode 100644 index 7becbb044d..0000000000 --- a/windows/src/test/manual-tests/integration-tests/keymanapi/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# -# Integration tests for keymanapi -# - -!include ..\..\..\Defines.mak - -!ifdef EXCLUDE_ELEVATED -TEST_MODE=--exclude:Elevated -!endif - -test: build - $(WIN32_TARGET_PATH)\keymanapi_test.exe -b -exit:continue $(TEST_MODE) - $(WIN64_TARGET_PATH)\keymanapi_test.exe -b -exit:continue $(TEST_MODE) - -build: - $(DELPHI_MSBUILD) "/p:Platform=Win32" keymanapi_test.dproj - $(DELPHI_MSBUILD) "/p:Platform=Win64" keymanapi_test.dproj - -clean: def-clean - -rd /s/q Win32 - -rd /s/q Win64 - -!include ..\..\..\Target.mak diff --git a/windows/src/test/manual-tests/regressiontest/Makefile b/windows/src/test/manual-tests/regressiontest/Makefile deleted file mode 100644 index dbfa70078c..0000000000 --- a/windows/src/test/manual-tests/regressiontest/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# REGRESSIONTEST Makefile -# - - -!include ..\..\Defines.mak - -build: dirs - $(DCC32) regressiontest.dpr - $(COPY) regressiontest.exe $(PROGRAM)\support - -clean: def-clean - cd tests - $(MAKE) clean - -!include ..\..\Target.mak diff --git a/windows/src/test/manual-tests/regressiontest/tests/Makefile b/windows/src/test/manual-tests/regressiontest/tests/Makefile deleted file mode 100644 index 01f8705399..0000000000 --- a/windows/src/test/manual-tests/regressiontest/tests/Makefile +++ /dev/null @@ -1,11 +0,0 @@ - -!include ..\..\..\Defines.mak - -all: - for %d in (*.kmn) do $(PROGRAM)\bin\kmc.cmd build "%d" - -.kmn.kmx: - &$(PROGRAM)\bin\kmc.cmd build $** - -clean: - -del *.kmx diff --git a/windows/src/test/manual-tests/test_httpuploader/Makefile b/windows/src/test/manual-tests/test_httpuploader/Makefile deleted file mode 100644 index b6250f4bfd..0000000000 --- a/windows/src/test/manual-tests/test_httpuploader/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# test_httpuploader Makefile -# - -!include ..\..\Defines.mak - -build: version.res manifest.res - $(DCC32) test_httpuploader.dpr - -icons: - rc icons.rc - -clean: def-clean - -signcode: - rem no signcode - -!include ..\..\Target.mak From 91465f22b3770d163f27f388d32e2b4d161cd30a Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Fri, 23 Aug 2024 14:03:25 -0400 Subject: [PATCH 66/89] auto: increment master version to 18.0.97 --- HISTORY.md | 9 +++++++++ VERSION.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 2ee27cd198..bf768c67d5 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,14 @@ # Keyman Version History +## 18.0.96 alpha 2024-08-23 + +* fix(android): Fix navigation arrows in Info Activity for RTL (#12244) +* fix(web): fix documentation-keyboard spacebar-text scaling (#12232) +* fix(android): Use increment and decrement arrows on longpress delay menu (#12242) +* fix(android): Add RTL assets for adjusting keyboard height menu (#12261) +* chore(common): use `npm install` in emsdk update (#12269) +* docs: refresh windows.md (#12248) + ## 18.0.95 alpha 2024-08-22 * chore(common): allow build agents to automatically select emsdk version, and enable support for 3.1.60+ (#12243) diff --git a/VERSION.md b/VERSION.md index 998f9bf6fd..2558c437be 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.96 \ No newline at end of file +18.0.97 \ No newline at end of file From 6bfa8a438f76efa2e5f03bc1dad7e629a3602890 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 23 Aug 2024 15:30:40 +0200 Subject: [PATCH 67/89] refactor(linux): cleanup API of kvk2ldml.py Make methods private that are only used inside of kvk2ldml.py. --- linux/keyman-config/keyman_config/kvk2ldml.py | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/linux/keyman-config/keyman_config/kvk2ldml.py b/linux/keyman-config/keyman_config/kvk2ldml.py index 5b3ab85ae8..3b3aee281b 100755 --- a/linux/keyman-config/keyman_config/kvk2ldml.py +++ b/linux/keyman-config/keyman_config/kvk2ldml.py @@ -164,43 +164,43 @@ VKey_to_Iso = { } -def bytecheck(value, check): +def _bytecheck(value, check): if bytes([value & check[0]]) == check: return True else: return False -def get_nkey(file, fileContent, offset): +def _get_nkey(file, fileContent, offset): nkey = NKey() data = struct.unpack_from(" 256: @@ -224,7 +224,7 @@ def get_nstring(file, fileContent, offset): return stringdata.decode('utf-16'), offset + 2 + (2 * stringlength[0]) -def get_nbitmap(file, fileContent, offset): +def _get_nbitmap(file, fileContent, offset): bitmap = None bitmaplength = struct.unpack_from(" Date: Sat, 24 Aug 2024 00:15:33 +0200 Subject: [PATCH 68/89] fix(developer): find last matching key in LDML key bag when building KVK Fixes: #12056 --- .../src/compiler/visual-keyboard-compiler.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts index 6182e6e2c8..4c51078af8 100644 --- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts @@ -3,6 +3,23 @@ import { LDMLKeyboard, CompilerCallbacks } from "@keymanapp/developer-utils"; import { KeysCompiler } from "./keys.js"; import { LdmlCompilerMessages } from "./ldml-compiler-messages.js"; +// This is a partial polyfill for findLast, so not polluting Array.prototype +// +// TODO: remove and replace with Array.prototype.findLast when it is +// well-supported +function findLast(arr: any, callback: any) { + if (!arr) { + return undefined; + } + const len = arr.length >>> 0; + for (let i = len - 1; i >= 0; i--) { + if (callback(arr[i], i, arr)) { + return arr[i]; + } + } + return undefined; +} + export class LdmlKeyboardVisualKeyboardCompiler { public constructor(private callbacks: CompilerCallbacks) { } @@ -57,7 +74,8 @@ export class LdmlKeyboardVisualKeyboardCompiler { const keyId = key; x++; - let keydef = source.keyboard3.keys?.key?.find(x => x.id == key); + //@ts-ignore + let keydef = findLast(source.keyboard3.keys?.key, x => x.id == key); if (!keydef) { this.callbacks.reportMessage( From f5066174cd929eef02d127ed747a698fe16344e6 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Sat, 24 Aug 2024 10:28:48 +0800 Subject: [PATCH 69/89] fix(developer): make LDML import path consistent for all bundlings of kmc The default import path is relative to ldml-keyboard-xml-reader.js. The bundling of kmc with Keyman Developer reduces the directory tree depth, so we move the import path to be a subdirectory of the immediate parent directory, rather than two levels up, so that `C:\Program Files\Keyman\Keyman Developer\kmc` can refer to `C:\Program Files\Keyman\Keyman Developer\import` when kmc is bundled. Fixes: #12279 --- developer/src/common/web/utils/build.sh | 4 ++-- .../utils/src/types/ldml-keyboard/ldml-keyboard-xml-reader.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/developer/src/common/web/utils/build.sh b/developer/src/common/web/utils/build.sh index 8829765237..2209463e18 100755 --- a/developer/src/common/web/utils/build.sh +++ b/developer/src/common/web/utils/build.sh @@ -35,9 +35,9 @@ function copy_cldr_imports() { # TODO-LDML: developer/src/inst/download.in.mak needs these also... CLDR_PATH=$(dirname "$CLDR_INFO_PATH") CLDR_VER=$(basename "$CLDR_PATH") - mkdir -p "$THIS_SCRIPT_PATH/build/src/import/$CLDR_VER" + mkdir -p "$THIS_SCRIPT_PATH/build/src/types/import/$CLDR_VER" # TODO-LDML: When these are copied, the DOCTYPE will break due to the wrong path. We don't use the DTD so it should be OK. - cp "$CLDR_INFO_PATH" "$CLDR_PATH/import/"*.xml "$THIS_SCRIPT_PATH/build/src/import/$CLDR_VER/" + cp "$CLDR_INFO_PATH" "$CLDR_PATH/import/"*.xml "$THIS_SCRIPT_PATH/build/src/types/import/$CLDR_VER/" done } diff --git a/developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml-reader.ts b/developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml-reader.ts index 162cac4aac..ddeaf719ab 100644 --- a/developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml-reader.ts +++ b/developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml-reader.ts @@ -23,7 +23,7 @@ export class LDMLKeyboardXMLSourceFileReader { } static get defaultImportsURL(): [string,string] { - return ['../../import/', import.meta.url]; + return ['../import/', import.meta.url]; } readImportFile(version: string, subpath: string): Uint8Array { From 96f288a83d7e23500f5ec723dddded99789efa98 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Sat, 24 Aug 2024 12:08:29 +0800 Subject: [PATCH 70/89] fix(core): properly support 'other' modifier state with `uint32_t` type While the modifier state property in core's API is 16-bit, internally ldml_processor supports the modifier flag LDML_KEYS_MOD_OTHER with a value of `0x10000`, which requires widening the value (we match the 32-bit size of the KMX_DWORD value from KMX+). Note: this is not yet well unit-tested. Relates-to: #11072 Fixes: #12057 --- core/src/ldml/ldml_processor.cpp | 2 +- core/src/ldml/ldml_vkeys.cpp | 2 +- core/src/ldml/ldml_vkeys.hpp | 13 ++++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/core/src/ldml/ldml_processor.cpp b/core/src/ldml/ldml_processor.cpp index f90fcfaa94..fcadda629c 100644 --- a/core/src/ldml/ldml_processor.cpp +++ b/core/src/ldml/ldml_processor.cpp @@ -85,7 +85,7 @@ ldml_processor::ldml_processor(path const & kb_path, const std::vector } else { str = keyEntry->get_to_string(); } - keys.add((km_core_virtual_key)kmapEntry->vkey, (uint16_t)kmapEntry->mod, str); + keys.add((km_core_virtual_key)kmapEntry->vkey, kmapEntry->mod, str); } } // else: no keys! but still valid. Just, no keys. diff --git a/core/src/ldml/ldml_vkeys.cpp b/core/src/ldml/ldml_vkeys.cpp index 07a2ff08ad..f79f82141f 100644 --- a/core/src/ldml/ldml_vkeys.cpp +++ b/core/src/ldml/ldml_vkeys.cpp @@ -17,7 +17,7 @@ vkeys::vkeys() : vkey_to_string() { } void -vkeys::add(km_core_virtual_key vk, uint16_t modifier_state, std::u16string output) { +vkeys::add(km_core_virtual_key vk, km_core_ldml_modifier_state modifier_state, std::u16string output) { // construct key const vkey_id id(vk, modifier_state); // assign the string diff --git a/core/src/ldml/ldml_vkeys.hpp b/core/src/ldml/ldml_vkeys.hpp index ed3368dc7e..6a54d77065 100644 --- a/core/src/ldml/ldml_vkeys.hpp +++ b/core/src/ldml/ldml_vkeys.hpp @@ -19,10 +19,17 @@ namespace km { namespace core { namespace ldml { +/** + * LDML keyboards have 32-bit modifier flags in order to support + * LDML_KEYS_MOD_OTHER (0x10000), unlike the Core APIs which have only 16 bit + * modifier flags. + */ +typedef uint32_t km_core_ldml_modifier_state; + /** * identifier for keybag lookup */ -typedef std::pair vkey_id; +typedef std::pair vkey_id; /** * LDML Class to manage all things key related: vkey remapping and vkey to string @@ -35,9 +42,9 @@ public: vkeys(); /** - * add a vkey to the bag + * add a vkey to the bag. */ - void add(km_core_virtual_key vk, uint16_t modifier_state, std::u16string output); + void add(km_core_virtual_key vk, km_core_ldml_modifier_state ldml_modifier_state, std::u16string output); /** * Lookup a vkey, returns an empty string if not found From b0e8b903740f307bbcccdee3a1274a998f30f204 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Sat, 24 Aug 2024 14:03:24 -0400 Subject: [PATCH 71/89] auto: increment master version to 18.0.98 --- HISTORY.md | 7 +++++++ VERSION.md | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index bf768c67d5..904e03468a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,12 @@ # Keyman Version History +## 18.0.97 alpha 2024-08-24 + +* refactor(linux): cleanup API of kvk2ldml.py (#12276) +* chore(common): adjust build settings for windows clean builds (#12264) +* chore(windows): remove remaining unused Makefiles (#12274) +* docs(developer): update build documentation to refer to build.sh (#12272) + ## 18.0.96 alpha 2024-08-23 * fix(android): Fix navigation arrows in Info Activity for RTL (#12244) diff --git a/VERSION.md b/VERSION.md index 2558c437be..48b8081cd1 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.97 \ No newline at end of file +18.0.98 \ No newline at end of file From be24a7d6056e6d651555379dfb39285f63cf4dbf Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 26 Aug 2024 09:26:08 +0700 Subject: [PATCH 72/89] chore(common/models): moves data-compiler artifacts to /tools subfolder --- common/models/wordbreakers/build.sh | 2 +- .../models/wordbreakers/tools/data-compiler/tsconfig.json | 4 ++-- package-lock.json | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/models/wordbreakers/build.sh b/common/models/wordbreakers/build.sh index 0cad38b1fe..725436c60e 100755 --- a/common/models/wordbreakers/build.sh +++ b/common/models/wordbreakers/build.sh @@ -34,7 +34,7 @@ function do_configure() { # default wordbreaker. We rarely update the backing data, but it # is needed _before_ the `build` action's compilation step. tsc -b tools/data-compiler/tsconfig.json - node ./build/data-compiler/obj/index.js + node ./build/tools/data-compiler/obj/index.js } function do_build() { diff --git a/common/models/wordbreakers/tools/data-compiler/tsconfig.json b/common/models/wordbreakers/tools/data-compiler/tsconfig.json index 74a8bb005e..577d1174df 100644 --- a/common/models/wordbreakers/tools/data-compiler/tsconfig.json +++ b/common/models/wordbreakers/tools/data-compiler/tsconfig.json @@ -3,8 +3,8 @@ "compilerOptions": { "baseUrl": "./", - "outDir": "../../build/data-compiler/obj", - "tsBuildInfoFile": "../../build/data-compiler/obj/tsconfig.tsbuildinfo", + "outDir": "../../build/tools/data-compiler/obj", + "tsBuildInfoFile": "../../build/tools/data-compiler/obj/tsconfig.tsbuildinfo", "rootDir": "./", "module": "node16", "moduleResolution": "node16" diff --git a/package-lock.json b/package-lock.json index cee7d8528b..a835d0cbd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -404,7 +404,7 @@ "eventemitter3": "^5.0.0", "restructure": "^3.0.1", "sax": ">=0.6.0", - "semver": "^7.5.2", + "semver": "^7.5.4", "xmlbuilder": "~11.0.0" }, "devDependencies": { @@ -1153,7 +1153,7 @@ "@keymanapp/keyman-version": "*", "@keymanapp/kmc-kmn": "*", "@keymanapp/ldml-keyboard-constants": "*", - "semver": "^7.5.2" + "semver": "^7.5.4" }, "devDependencies": { "@keymanapp/developer-test-helpers": "*", @@ -1942,7 +1942,7 @@ "open": "^8.4.0", "restructure": "^3.0.1", "sax": ">=0.6.0", - "semver": "^7.5.2", + "semver": "^7.5.4", "ws": "^8.17.1", "xmlbuilder": "~11.0.0" }, @@ -14630,7 +14630,7 @@ "devDependencies": { "@types/semver": "^7.1.0", "@types/yargs": "^17.0.26", - "semver": "^7.5.2" + "semver": "^7.5.4" } }, "resources/build/version/node_modules/ansi-regex": { From f3461b3307284b42ac789d02b0393d4684764a9b Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 26 Aug 2024 12:59:48 +0700 Subject: [PATCH 73/89] chore(windows): fix typo in environment.inc.sh Co-authored-by: 58423624+rc-swag@users.noreply.github.com --- resources/build/win/environment.inc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/build/win/environment.inc.sh b/resources/build/win/environment.inc.sh index 620e96146a..71c18f305b 100644 --- a/resources/build/win/environment.inc.sh +++ b/resources/build/win/environment.inc.sh @@ -26,7 +26,7 @@ WINDOWS_PROGRAM_ENGINE="$WINDOWS_ROOT/bin/engine" WINDOWS_PROGRAM_SUPPORT="$WINDOWS_ROOT/bin/support" WINDOWS_DEBUGPATH_APP="$WINDOWS_ROOT/debug/desktop" WINDOWS_DEBUGPATH_ENGINE="$WINDOWS_ROOT/debug/engine" -WINDOWS_DEBUGPATH_SUPPORT="$WINDOWS_ROOT/debug/suppor" +WINDOWS_DEBUGPATH_SUPPORT="$WINDOWS_ROOT/debug/support" COMMON_ROOT="$KEYMAN_ROOT/common/windows/delphi" OUTLIB="$WINDOWS_ROOT/lib" From 6353f926ba31f8d776a05cfd395770f580cd2dfd Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 26 Aug 2024 09:09:00 +0200 Subject: [PATCH 74/89] chore: Update developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts --- developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts index 4c51078af8..6d76bc403e 100644 --- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts @@ -4,7 +4,7 @@ import { KeysCompiler } from "./keys.js"; import { LdmlCompilerMessages } from "./ldml-compiler-messages.js"; // This is a partial polyfill for findLast, so not polluting Array.prototype -// +// https://medium.com/@stheodorejohn/findlast-method-polyfill-in-javascript-bridging-browser-gaps-c3baf6aabae1 // TODO: remove and replace with Array.prototype.findLast when it is // well-supported function findLast(arr: any, callback: any) { From 8c959f7eb2697895e4e94bda9531fd0af736e435 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 26 Aug 2024 14:35:54 +0700 Subject: [PATCH 75/89] chore(android): Cleanup stray debug statements in console --- android/KMEA/app/src/main/assets/android-host.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/KMEA/app/src/main/assets/android-host.js b/android/KMEA/app/src/main/assets/android-host.js index 62d396aae0..5e5d724123 100644 --- a/android/KMEA/app/src/main/assets/android-host.js +++ b/android/KMEA/app/src/main/assets/android-host.js @@ -117,7 +117,7 @@ function notifyHost(event, params) { function setLongpressDelay(delay) { if (keyman.osk) { keyman.osk.gestureParams.longpress.waitLength = delay; - console.debug('setLongpressDelay('+delay+')'); + console_debug('setLongpressDelay('+delay+')'); } else { window.console.log('setLongpressDelay error: keyman.osk undefined'); } @@ -304,7 +304,7 @@ function updateKMSelectionRange(start, end) { console_debug('result:\n' + build_context_string(context)); } else { - console.debug('range unchanged'); + console_debug('range unchanged'); } } From 7dabd30caebc3d3589910b756fd7f9a03ab6ab1d Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 13 Aug 2024 19:32:12 +0200 Subject: [PATCH 76/89] =?UTF-8?q?refactor(web):=20move=20`gesture-recogniz?= =?UTF-8?q?er`=20=E2=86=92=20`gesture-processor`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves `common/web/gesture-recognizer/` → `web/src/engine/osk/gesture-processor`. Fixes: #12151 --- package-lock.json | 5 +- package.json | 1 + tsconfig.json | 4 +- web/README.md | 2 +- web/ci.sh | 2 +- web/src/engine/osk/build.sh | 2 +- .../engine/osk/gesture-processor}/.c8rc.json | 0 .../engine/osk/gesture-processor}/.gitignore | 0 .../engine/osk/gesture-processor}/README.md | 2 +- .../engine/osk/gesture-processor}/build.sh | 50 +++++++++--------- .../gesture-processor}/docs/host-page-viz.png | Bin .../docs/recognizer-configuration.md | 0 .../osk/gesture-processor}/package.json | 1 + .../gestureRecognizerConfiguration.ts | 0 .../engine/configuration/paddedZoneSource.ts | 0 .../configuration/recognitionZoneSource.ts | 0 .../configuration/viewportZoneSource.ts | 0 .../configuration/zoneBoundaryChecker.ts | 0 .../src/engine/gestureRecognizer.ts | 0 .../headless/asyncClosureDispatchQueue.ts | 0 .../engine/headless/cumulativePathStats.ts | 0 .../src/engine/headless/gestureDebugPath.ts | 0 .../src/engine/headless/gestureDebugSource.ts | 0 .../src/engine/headless/gesturePath.ts | 0 .../src/engine/headless/gestureSource.ts | 0 .../src/engine/headless/gestures/index.ts | 0 .../gestures/matchers/gestureMatcher.ts | 0 .../gestures/matchers/gestureSequence.ts | 0 .../headless/gestures/matchers/index.ts | 0 .../gestures/matchers/matcherSelector.ts | 0 .../headless/gestures/matchers/pathMatcher.ts | 0 .../headless/gestures/specs/contactModel.ts | 0 .../headless/gestures/specs/gestureModel.ts | 0 .../gestures/specs/gestureModelDefs.ts | 0 .../engine/headless/gestures/specs/index.ts | 0 .../gestures/specs/modelDefValidator.ts | 0 .../headless/gestures/specs/pathModel.ts | 0 .../src/engine/headless/inputEngineBase.ts | 0 .../src/engine/headless/inputSample.ts | 0 .../src/engine/headless/segmentClassifier.ts | 0 .../engine/headless/touchpointCoordinator.ts | 0 .../gesture-processor}/src/engine/index.ts | 0 .../src/engine/inputEventEngine.ts | 0 .../src/engine/mouseEventEngine.ts | 0 .../gesture-processor}/src/engine/mutable.ts | 0 .../src/engine/nonoptional.ts | 0 .../src/engine/reportError.ts | 0 .../src/engine/touchEventEngine.ts | 0 .../src/test/auto/browser/cases/canary.def.ts | 0 .../test/auto/browser/cases/gestureHost.css | 0 .../auto/browser/cases/host-page.spec.html | 0 .../auto/browser/cases/ignoredInputs.def.ts | 0 .../cases/recordedCoordSequences.def.ts | 0 .../browser/web-test-runner.CI.config.mjs | 0 .../auto/browser/web-test-runner.config.mjs | 2 +- .../asyncClosureDispatchQueue.spec.ts | 0 .../test/auto/headless/gesturePath.spec.ts | 0 .../test/auto/headless/gestureSource.spec.ts | 0 .../headless/gestures/gestureMatcher.spec.ts | 0 .../gestures/gestureModelDefs.spec.ts | 0 .../headless/gestures/gestureSequence.spec.ts | 0 .../headless/gestures/isolatedGestureSpecs.ts | 0 .../headless/gestures/isolatedPathSpecs.ts | 0 .../headless/gestures/matcherSelector.spec.ts | 0 .../headless/gestures/pathMatcher.spec.ts | 0 .../gestures/touchpointCoordinator.spec.ts | 0 .../src/test/auto/headless/pathStats.spec.ts | 0 .../test/resources/@types/promiseStatus.d.ts | 0 .../test/resources/assertSegmentSimilarity.js | 0 .../test/resources/assertingPromiseStatus.ts | 0 .../test/resources/json/canaryRecording.json | 0 .../json/receiver/basicMultitouch.json | 0 .../json/receiver/desktopRoamAndReturn.json | 0 .../json/receiver/embeddedBorderCancel.json | 0 .../json/receiver/hardBorderCancel.json | 0 .../receiver/mobileProximityApproach.json | 0 .../json/receiver/mobileSafeZoneCancel.json | 0 .../json/receiver/popupLongRoamingEnd.json | 0 .../json/receiver/popupSafePersistence.json | 0 .../json/receiver/popupShimCancel.json | 0 .../json/segmentation/flick_ne_se.json | 0 .../json/segmentation/longpress_to_ne.json | 0 .../json/segmentation/nonstationary_hold.json | 0 .../json/segmentation/quick_small_square.json | 0 .../json/segmentation/simple_ne_move.json | 0 .../src/test/resources/sequenceAssertions.ts | 0 .../resources/simulateMultiSourceInput.ts | 0 .../gesture-processor}/src/test/tsconfig.json | 0 .../osk/gesture-processor}/src/tools/build.sh | 19 ++++--- .../src/tools/host-fixture/extract-fixture.sh | 0 .../src/tools/host-fixture/extractor.cjs | 0 .../src/tools/host-fixture/gestureHost.css | 0 .../src/tools/host-fixture/host-fixture.html | 0 .../src/tools/recorder/src/index.html | 0 .../src/tools/recorder/src/pageStyle.css | 0 .../src/tools/recorder/src/recorder.mjs | 0 .../src/tools/recorder/update-index.cjs | 0 .../unit-test-resources/build-bundler.js | 0 .../src/fixtureLayoutConfiguration.ts | 0 .../src/headlessInputEngine.ts | 0 .../src/hostFixtureLayoutController.ts | 0 .../tools/unit-test-resources/src/index.ts | 0 .../unit-test-resources/src/inputRecording.ts | 0 .../src/inputSequenceSimulator.ts | 0 .../unit-test-resources/src/jsonObject.ts | 0 .../src/sequenceRecorder.ts | 0 .../src/touchpathTurtle.ts | 0 .../tools/unit-test-resources/tsconfig.json | 2 +- .../src/engine/osk/gesture-processor}/test.sh | 6 +-- .../osk/gesture-processor}/tsconfig.json | 8 +-- web/src/engine/osk/tsconfig.json | 2 +- web/src/test/manual/build.sh | 8 +-- .../gesture-recognizer/hostConfiguration.mjs | 2 +- 113 files changed, 62 insertions(+), 56 deletions(-) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/.c8rc.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/.gitignore (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/README.md (78%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/build.sh (59%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/docs/host-page-viz.png (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/docs/recognizer-configuration.md (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/package.json (95%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/configuration/gestureRecognizerConfiguration.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/configuration/paddedZoneSource.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/configuration/recognitionZoneSource.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/configuration/viewportZoneSource.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/configuration/zoneBoundaryChecker.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/gestureRecognizer.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/asyncClosureDispatchQueue.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/cumulativePathStats.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestureDebugPath.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestureDebugSource.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gesturePath.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestureSource.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/index.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/matchers/gestureMatcher.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/matchers/gestureSequence.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/matchers/index.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/matchers/matcherSelector.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/matchers/pathMatcher.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/specs/contactModel.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/specs/gestureModel.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/specs/gestureModelDefs.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/specs/index.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/specs/modelDefValidator.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/gestures/specs/pathModel.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/inputEngineBase.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/inputSample.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/segmentClassifier.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/headless/touchpointCoordinator.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/index.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/inputEventEngine.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/mouseEventEngine.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/mutable.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/nonoptional.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/reportError.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/engine/touchEventEngine.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/browser/cases/canary.def.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/browser/cases/gestureHost.css (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/browser/cases/host-page.spec.html (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/browser/cases/ignoredInputs.def.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/browser/cases/recordedCoordSequences.def.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/browser/web-test-runner.CI.config.mjs (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/browser/web-test-runner.config.mjs (96%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/asyncClosureDispatchQueue.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gesturePath.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestureSource.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestures/gestureMatcher.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestures/gestureModelDefs.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestures/gestureSequence.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestures/isolatedGestureSpecs.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestures/isolatedPathSpecs.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestures/matcherSelector.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestures/pathMatcher.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/gestures/touchpointCoordinator.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/auto/headless/pathStats.spec.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/@types/promiseStatus.d.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/assertSegmentSimilarity.js (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/assertingPromiseStatus.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/canaryRecording.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/basicMultitouch.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/desktopRoamAndReturn.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/embeddedBorderCancel.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/hardBorderCancel.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/mobileProximityApproach.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/mobileSafeZoneCancel.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/popupLongRoamingEnd.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/popupSafePersistence.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/receiver/popupShimCancel.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/segmentation/flick_ne_se.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/segmentation/longpress_to_ne.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/segmentation/nonstationary_hold.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/segmentation/quick_small_square.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/json/segmentation/simple_ne_move.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/sequenceAssertions.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/resources/simulateMultiSourceInput.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/test/tsconfig.json (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/build.sh (78%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/host-fixture/extract-fixture.sh (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/host-fixture/extractor.cjs (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/host-fixture/gestureHost.css (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/host-fixture/host-fixture.html (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/recorder/src/index.html (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/recorder/src/pageStyle.css (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/recorder/src/recorder.mjs (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/recorder/update-index.cjs (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/build-bundler.js (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/fixtureLayoutConfiguration.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/headlessInputEngine.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/hostFixtureLayoutController.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/index.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/inputRecording.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/inputSequenceSimulator.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/jsonObject.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/sequenceRecorder.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/src/touchpathTurtle.ts (100%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/src/tools/unit-test-resources/tsconfig.json (84%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/test.sh (93%) rename {common/web/gesture-recognizer => web/src/engine/osk/gesture-processor}/tsconfig.json (61%) diff --git a/package-lock.json b/package-lock.json index cee7d8528b..515b2fefc8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "common/web/*", "common/tools/hextobin", "web", + "web/src/engine/osk/gesture-processor", "web/src/engine/predictive-text/*" ], "dependencies": { @@ -159,7 +160,7 @@ }, "devDependencies": {} }, - "common/web/gesture-recognizer": { + "web/src/engine/osk/gesture-processor": { "name": "@keymanapp/gesture-recognizer", "dependencies": { "eventemitter3": "^5.0.0" @@ -2795,7 +2796,7 @@ "link": true }, "node_modules/@keymanapp/gesture-recognizer": { - "resolved": "common/web/gesture-recognizer", + "resolved": "web/src/engine/osk/gesture-processor", "link": true }, "node_modules/@keymanapp/hextobin": { diff --git a/package.json b/package.json index 3f0012db10..23970ceff2 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "common/web/*", "common/tools/hextobin", "web", + "web/src/engine/osk/gesture-processor", "web/src/engine/predictive-text/*" ], "dependencies": { diff --git a/tsconfig.json b/tsconfig.json index 1a02e20ff1..fc9c15a34f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,8 +7,6 @@ { "path": "./common/models/wordbreakers/tsconfig.json" }, { "path": "./common/tools/hextobin/" }, - { "path": "./common/web/gesture-recognizer/tsconfig.json" }, - { "path": "./common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json" }, { "path": "./common/web/keyman-version" }, { "path": "./common/web/recorder/tsconfig.json" }, { "path": "./common/web/sentry-manager/src/tsconfig.json" }, @@ -43,6 +41,8 @@ { "path": "./web/src/engine/predictive-text/types/" }, { "path": "./web/src/engine/predictive-text/worker-main/tsconfig.all.json" }, { "path": "./web/src/engine/predictive-text/worker-thread" }, + { "path": "./web/src/engine/osk/gesture-processor/tsconfig.json" }, + { "path": "./web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/tsconfig.json" }, // { "path": "./web/tools/recorder/tsconfig.json" }, // { "path": "./web/tools/sourcemap-root/tsconfig.json" }, ] diff --git a/web/README.md b/web/README.md index f09fe519bb..9e7d896c7b 100644 --- a/web/README.md +++ b/web/README.md @@ -94,7 +94,7 @@ graph TD; LMWorker-->Wordbreakers; LMLayer["@keymanapp/lexical-model-layer
(/web/src/engine/predictive-text/worker-main)"]; LMLayer-->LMWorker; - Gestures["@keymanapp/gesture-recognizer
(/common/web/gesture-recognizer)"]; + Gestures["@keymanapp/gesture-recognizer
(/web/src/engine/osk/gesture-recognizer)"]; Gestures-->WebUtils; subgraph PredText["PredText: WebWorker + its interface"] diff --git a/web/ci.sh b/web/ci.sh index 5e26a1e30e..a466417275 100755 --- a/web/ci.sh +++ b/web/ci.sh @@ -86,7 +86,7 @@ if builder_start_action test; then # No --reporter option exists yet for the headless modules. "$KEYMAN_ROOT/web/src/engine/keyboard/build.sh" test $OPTIONS - "$KEYMAN_ROOT/common/web/gesture-recognizer/test.sh" $OPTIONS + "$KEYMAN_ROOT/web/src/engine/osk/gesture-processor/test.sh" $OPTIONS ./build.sh test $OPTIONS diff --git a/web/src/engine/osk/build.sh b/web/src/engine/osk/build.sh index 0d676a2d3e..e54a75bad1 100755 --- a/web/src/engine/osk/build.sh +++ b/web/src/engine/osk/build.sh @@ -14,10 +14,10 @@ SUBPROJECT_NAME=engine/osk builder_describe "Builds the Keyman Engine for Web's On-Screen Keyboard package (OSK)." \ "@/web/src/engine/keyboard build" \ - "@/common/web/gesture-recognizer build" \ "@/web/src/engine/interfaces build" \ "@/web/src/engine/dom-utils build" \ "@/web/src/engine/events build" \ + "@/web/src/engine/osk/gesture-processor" \ "clean" \ "configure" \ "build" \ diff --git a/common/web/gesture-recognizer/.c8rc.json b/web/src/engine/osk/gesture-processor/.c8rc.json similarity index 100% rename from common/web/gesture-recognizer/.c8rc.json rename to web/src/engine/osk/gesture-processor/.c8rc.json diff --git a/common/web/gesture-recognizer/.gitignore b/web/src/engine/osk/gesture-processor/.gitignore similarity index 100% rename from common/web/gesture-recognizer/.gitignore rename to web/src/engine/osk/gesture-processor/.gitignore diff --git a/common/web/gesture-recognizer/README.md b/web/src/engine/osk/gesture-processor/README.md similarity index 78% rename from common/web/gesture-recognizer/README.md rename to web/src/engine/osk/gesture-processor/README.md index cbb310092d..3b941963de 100644 --- a/common/web/gesture-recognizer/README.md +++ b/web/src/engine/osk/gesture-processor/README.md @@ -6,6 +6,6 @@ KeymanWeb, seen within this repo at /web/. ## Minimum Compilation Requirements -See the repo-level [document for build configuration](../../../docs/build/index.md) for details on how to +See the repo-level [document for build configuration](../../../../../docs/build/index.md) for details on how to configure your build environment. - Follow the Keyman Engine for Web (KeymanWeb) requirements where appropriate. \ No newline at end of file diff --git a/common/web/gesture-recognizer/build.sh b/web/src/engine/osk/gesture-processor/build.sh similarity index 59% rename from common/web/gesture-recognizer/build.sh rename to web/src/engine/osk/gesture-processor/build.sh index a27cd3f8d1..37cd785623 100755 --- a/common/web/gesture-recognizer/build.sh +++ b/web/src/engine/osk/gesture-processor/build.sh @@ -3,13 +3,15 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "$(dirname "$THIS_SCRIPT")/../../../resources/build/builder.inc.sh" +. "$(dirname "$THIS_SCRIPT")/../../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" BUNDLE_CMD="node $KEYMAN_ROOT/common/web/es-bundling/build/common-bundle.mjs" +BUILD_DIR="/web/src/engine/osk/gesture-processor/build" + ################################ Main script ################################ builder_describe "Builds the gesture-recognition model for Web-based on-screen keyboards" \ @@ -25,8 +27,8 @@ builder_describe "Builds the gesture-recognition model for Web-based on-screen k builder_describe_outputs \ configure /node_modules \ - build:module /common/web/gesture-recognizer/build/lib/index.mjs \ - build:tools /common/web/gesture-recognizer/build/tools/lib/index.mjs + build:module "${BUILD_DIR}/lib/index.mjs" \ + build:tools "${BUILD_DIR}/tools/lib/index.mjs" builder_parse "$@" @@ -41,38 +43,36 @@ function do_configure() { playwright install } -builder_run_action configure do_configure - -if builder_start_action clean; then - rm -rf build/ - builder_finish_action success clean -fi - -if builder_start_action build:module; then +function do_build_module() { # Build tsc --build $builder_verbose - $BUNDLE_CMD "${KEYMAN_ROOT}/common/web/gesture-recognizer/build/obj/index.js" \ - --out "${KEYMAN_ROOT}/common/web/gesture-recognizer/build/lib/index.mjs" \ + $BUNDLE_CMD "${KEYMAN_ROOT}/${BUILD_DIR}/obj/index.js" \ + --out "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.mjs" \ --format esm +} - builder_finish_action success build:module -fi - -if builder_start_action build:tools; then +function do_build_tools() { src/tools/build.sh build - builder_finish_action success build:tools -fi +} -if builder_start_action test:module; then +function do_test_module() { if builder_has_option --ci; then ./test.sh --ci else ./test.sh fi - builder_finish_action success test:module -fi +} -if builder_has_action test:tools && ! builder_has_action test:module; then - echo "The $(builder_term test:tools) action is currently a no-op." -fi \ No newline at end of file +function do_test_tools() { + if ! builder_has_action test:module; then + echo "The $(builder_term test:tools) action is currently a no-op." + fi +} + +builder_run_action configure do_configure +builder_run_action clean rm -rf build/ intermediate/ +builder_run_action build:module do_build_module +builder_run_action build:tools do_build_tools +builder_run_action test:module do_test_module +builder_run_action test:tools do_test_tools diff --git a/common/web/gesture-recognizer/docs/host-page-viz.png b/web/src/engine/osk/gesture-processor/docs/host-page-viz.png similarity index 100% rename from common/web/gesture-recognizer/docs/host-page-viz.png rename to web/src/engine/osk/gesture-processor/docs/host-page-viz.png diff --git a/common/web/gesture-recognizer/docs/recognizer-configuration.md b/web/src/engine/osk/gesture-processor/docs/recognizer-configuration.md similarity index 100% rename from common/web/gesture-recognizer/docs/recognizer-configuration.md rename to web/src/engine/osk/gesture-processor/docs/recognizer-configuration.md diff --git a/common/web/gesture-recognizer/package.json b/web/src/engine/osk/gesture-processor/package.json similarity index 95% rename from common/web/gesture-recognizer/package.json rename to web/src/engine/osk/gesture-processor/package.json index 66cf248c0f..9ec0606ebd 100644 --- a/common/web/gesture-recognizer/package.json +++ b/web/src/engine/osk/gesture-processor/package.json @@ -16,6 +16,7 @@ "test": "gosh ./test.sh" }, "dependencies": { + "@keymanapp/web-utils": "*", "eventemitter3": "^5.0.0" }, "main": "./build/obj/index.js", diff --git a/common/web/gesture-recognizer/src/engine/configuration/gestureRecognizerConfiguration.ts b/web/src/engine/osk/gesture-processor/src/engine/configuration/gestureRecognizerConfiguration.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/configuration/gestureRecognizerConfiguration.ts rename to web/src/engine/osk/gesture-processor/src/engine/configuration/gestureRecognizerConfiguration.ts diff --git a/common/web/gesture-recognizer/src/engine/configuration/paddedZoneSource.ts b/web/src/engine/osk/gesture-processor/src/engine/configuration/paddedZoneSource.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/configuration/paddedZoneSource.ts rename to web/src/engine/osk/gesture-processor/src/engine/configuration/paddedZoneSource.ts diff --git a/common/web/gesture-recognizer/src/engine/configuration/recognitionZoneSource.ts b/web/src/engine/osk/gesture-processor/src/engine/configuration/recognitionZoneSource.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/configuration/recognitionZoneSource.ts rename to web/src/engine/osk/gesture-processor/src/engine/configuration/recognitionZoneSource.ts diff --git a/common/web/gesture-recognizer/src/engine/configuration/viewportZoneSource.ts b/web/src/engine/osk/gesture-processor/src/engine/configuration/viewportZoneSource.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/configuration/viewportZoneSource.ts rename to web/src/engine/osk/gesture-processor/src/engine/configuration/viewportZoneSource.ts diff --git a/common/web/gesture-recognizer/src/engine/configuration/zoneBoundaryChecker.ts b/web/src/engine/osk/gesture-processor/src/engine/configuration/zoneBoundaryChecker.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/configuration/zoneBoundaryChecker.ts rename to web/src/engine/osk/gesture-processor/src/engine/configuration/zoneBoundaryChecker.ts diff --git a/common/web/gesture-recognizer/src/engine/gestureRecognizer.ts b/web/src/engine/osk/gesture-processor/src/engine/gestureRecognizer.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/gestureRecognizer.ts rename to web/src/engine/osk/gesture-processor/src/engine/gestureRecognizer.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/asyncClosureDispatchQueue.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/asyncClosureDispatchQueue.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/asyncClosureDispatchQueue.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/asyncClosureDispatchQueue.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/cumulativePathStats.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/cumulativePathStats.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/cumulativePathStats.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/cumulativePathStats.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestureDebugPath.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestureDebugPath.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestureDebugPath.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestureDebugPath.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestureDebugSource.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestureDebugSource.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestureDebugSource.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestureDebugSource.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gesturePath.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gesturePath.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gesturePath.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gesturePath.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestureSource.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestureSource.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestureSource.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestureSource.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/index.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/index.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/index.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/index.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/gestureMatcher.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/gestureMatcher.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/matchers/gestureMatcher.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/gestureMatcher.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/gestureSequence.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/gestureSequence.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/matchers/gestureSequence.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/gestureSequence.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/index.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/index.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/matchers/index.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/index.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/matcherSelector.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/matcherSelector.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/matchers/matcherSelector.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/matcherSelector.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/pathMatcher.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/pathMatcher.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/matchers/pathMatcher.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/matchers/pathMatcher.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/contactModel.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/contactModel.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/specs/contactModel.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/contactModel.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/gestureModel.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/gestureModel.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/specs/gestureModel.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/gestureModel.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/gestureModelDefs.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/gestureModelDefs.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/specs/gestureModelDefs.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/gestureModelDefs.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/index.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/index.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/specs/index.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/index.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/modelDefValidator.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/modelDefValidator.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/pathModel.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/pathModel.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/gestures/specs/pathModel.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/gestures/specs/pathModel.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/inputEngineBase.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/inputEngineBase.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/inputEngineBase.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/inputEngineBase.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/inputSample.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/inputSample.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/inputSample.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/inputSample.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/segmentClassifier.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/segmentClassifier.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/segmentClassifier.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/segmentClassifier.ts diff --git a/common/web/gesture-recognizer/src/engine/headless/touchpointCoordinator.ts b/web/src/engine/osk/gesture-processor/src/engine/headless/touchpointCoordinator.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/headless/touchpointCoordinator.ts rename to web/src/engine/osk/gesture-processor/src/engine/headless/touchpointCoordinator.ts diff --git a/common/web/gesture-recognizer/src/engine/index.ts b/web/src/engine/osk/gesture-processor/src/engine/index.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/index.ts rename to web/src/engine/osk/gesture-processor/src/engine/index.ts diff --git a/common/web/gesture-recognizer/src/engine/inputEventEngine.ts b/web/src/engine/osk/gesture-processor/src/engine/inputEventEngine.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/inputEventEngine.ts rename to web/src/engine/osk/gesture-processor/src/engine/inputEventEngine.ts diff --git a/common/web/gesture-recognizer/src/engine/mouseEventEngine.ts b/web/src/engine/osk/gesture-processor/src/engine/mouseEventEngine.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/mouseEventEngine.ts rename to web/src/engine/osk/gesture-processor/src/engine/mouseEventEngine.ts diff --git a/common/web/gesture-recognizer/src/engine/mutable.ts b/web/src/engine/osk/gesture-processor/src/engine/mutable.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/mutable.ts rename to web/src/engine/osk/gesture-processor/src/engine/mutable.ts diff --git a/common/web/gesture-recognizer/src/engine/nonoptional.ts b/web/src/engine/osk/gesture-processor/src/engine/nonoptional.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/nonoptional.ts rename to web/src/engine/osk/gesture-processor/src/engine/nonoptional.ts diff --git a/common/web/gesture-recognizer/src/engine/reportError.ts b/web/src/engine/osk/gesture-processor/src/engine/reportError.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/reportError.ts rename to web/src/engine/osk/gesture-processor/src/engine/reportError.ts diff --git a/common/web/gesture-recognizer/src/engine/touchEventEngine.ts b/web/src/engine/osk/gesture-processor/src/engine/touchEventEngine.ts similarity index 100% rename from common/web/gesture-recognizer/src/engine/touchEventEngine.ts rename to web/src/engine/osk/gesture-processor/src/engine/touchEventEngine.ts diff --git a/common/web/gesture-recognizer/src/test/auto/browser/cases/canary.def.ts b/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/canary.def.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/browser/cases/canary.def.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/canary.def.ts diff --git a/common/web/gesture-recognizer/src/test/auto/browser/cases/gestureHost.css b/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/gestureHost.css similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/browser/cases/gestureHost.css rename to web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/gestureHost.css diff --git a/common/web/gesture-recognizer/src/test/auto/browser/cases/host-page.spec.html b/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/host-page.spec.html similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/browser/cases/host-page.spec.html rename to web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/host-page.spec.html diff --git a/common/web/gesture-recognizer/src/test/auto/browser/cases/ignoredInputs.def.ts b/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/ignoredInputs.def.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/browser/cases/ignoredInputs.def.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/ignoredInputs.def.ts diff --git a/common/web/gesture-recognizer/src/test/auto/browser/cases/recordedCoordSequences.def.ts b/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/recordedCoordSequences.def.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/browser/cases/recordedCoordSequences.def.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/recordedCoordSequences.def.ts diff --git a/common/web/gesture-recognizer/src/test/auto/browser/web-test-runner.CI.config.mjs b/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.CI.config.mjs similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/browser/web-test-runner.CI.config.mjs rename to web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.CI.config.mjs diff --git a/common/web/gesture-recognizer/src/test/auto/browser/web-test-runner.config.mjs b/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.config.mjs similarity index 96% rename from common/web/gesture-recognizer/src/test/auto/browser/web-test-runner.config.mjs rename to web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.config.mjs index 0d5bac8508..4487912e0d 100644 --- a/common/web/gesture-recognizer/src/test/auto/browser/web-test-runner.config.mjs +++ b/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.config.mjs @@ -34,7 +34,7 @@ export default { // Rewrites short-hand paths for test resources, making them fully relative to the repo root. function rewriteResourcePath(context, next) { if(context.url.startsWith('/resources/')) { - context.url = '/common/web/gesture-recognizer/src/test' + context.url; + context.url = '/web/src/engine/osk/gesture-processor/src/test' + context.url; } return next(); diff --git a/common/web/gesture-recognizer/src/test/auto/headless/asyncClosureDispatchQueue.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/asyncClosureDispatchQueue.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/asyncClosureDispatchQueue.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/asyncClosureDispatchQueue.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gesturePath.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gesturePath.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gesturePath.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gesturePath.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestureSource.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestureSource.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestureSource.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestureSource.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestures/gestureMatcher.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureMatcher.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestures/gestureMatcher.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureMatcher.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestures/gestureModelDefs.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureModelDefs.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestures/gestureModelDefs.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureModelDefs.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestures/gestureSequence.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureSequence.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestures/gestureSequence.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureSequence.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestures/isolatedGestureSpecs.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/isolatedGestureSpecs.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestures/isolatedGestureSpecs.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/isolatedGestureSpecs.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestures/isolatedPathSpecs.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/isolatedPathSpecs.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestures/isolatedPathSpecs.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/isolatedPathSpecs.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestures/matcherSelector.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/matcherSelector.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestures/matcherSelector.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/matcherSelector.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestures/pathMatcher.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/pathMatcher.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestures/pathMatcher.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/pathMatcher.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/gestures/touchpointCoordinator.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/touchpointCoordinator.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/gestures/touchpointCoordinator.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/touchpointCoordinator.spec.ts diff --git a/common/web/gesture-recognizer/src/test/auto/headless/pathStats.spec.ts b/web/src/engine/osk/gesture-processor/src/test/auto/headless/pathStats.spec.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/auto/headless/pathStats.spec.ts rename to web/src/engine/osk/gesture-processor/src/test/auto/headless/pathStats.spec.ts diff --git a/common/web/gesture-recognizer/src/test/resources/@types/promiseStatus.d.ts b/web/src/engine/osk/gesture-processor/src/test/resources/@types/promiseStatus.d.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/@types/promiseStatus.d.ts rename to web/src/engine/osk/gesture-processor/src/test/resources/@types/promiseStatus.d.ts diff --git a/common/web/gesture-recognizer/src/test/resources/assertSegmentSimilarity.js b/web/src/engine/osk/gesture-processor/src/test/resources/assertSegmentSimilarity.js similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/assertSegmentSimilarity.js rename to web/src/engine/osk/gesture-processor/src/test/resources/assertSegmentSimilarity.js diff --git a/common/web/gesture-recognizer/src/test/resources/assertingPromiseStatus.ts b/web/src/engine/osk/gesture-processor/src/test/resources/assertingPromiseStatus.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/assertingPromiseStatus.ts rename to web/src/engine/osk/gesture-processor/src/test/resources/assertingPromiseStatus.ts diff --git a/common/web/gesture-recognizer/src/test/resources/json/canaryRecording.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/canaryRecording.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/canaryRecording.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/canaryRecording.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/basicMultitouch.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/basicMultitouch.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/basicMultitouch.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/basicMultitouch.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/desktopRoamAndReturn.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/desktopRoamAndReturn.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/desktopRoamAndReturn.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/desktopRoamAndReturn.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/embeddedBorderCancel.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/embeddedBorderCancel.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/embeddedBorderCancel.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/embeddedBorderCancel.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/hardBorderCancel.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/hardBorderCancel.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/hardBorderCancel.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/hardBorderCancel.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/mobileProximityApproach.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/mobileProximityApproach.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/mobileProximityApproach.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/mobileProximityApproach.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/mobileSafeZoneCancel.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/mobileSafeZoneCancel.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/mobileSafeZoneCancel.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/mobileSafeZoneCancel.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/popupLongRoamingEnd.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupLongRoamingEnd.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/popupLongRoamingEnd.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupLongRoamingEnd.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/popupSafePersistence.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupSafePersistence.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/popupSafePersistence.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupSafePersistence.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/receiver/popupShimCancel.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupShimCancel.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/receiver/popupShimCancel.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupShimCancel.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/segmentation/flick_ne_se.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/flick_ne_se.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/segmentation/flick_ne_se.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/flick_ne_se.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/segmentation/longpress_to_ne.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/longpress_to_ne.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/segmentation/longpress_to_ne.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/longpress_to_ne.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/segmentation/nonstationary_hold.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/nonstationary_hold.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/segmentation/nonstationary_hold.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/nonstationary_hold.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/segmentation/quick_small_square.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/quick_small_square.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/segmentation/quick_small_square.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/quick_small_square.json diff --git a/common/web/gesture-recognizer/src/test/resources/json/segmentation/simple_ne_move.json b/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/simple_ne_move.json similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/json/segmentation/simple_ne_move.json rename to web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/simple_ne_move.json diff --git a/common/web/gesture-recognizer/src/test/resources/sequenceAssertions.ts b/web/src/engine/osk/gesture-processor/src/test/resources/sequenceAssertions.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/sequenceAssertions.ts rename to web/src/engine/osk/gesture-processor/src/test/resources/sequenceAssertions.ts diff --git a/common/web/gesture-recognizer/src/test/resources/simulateMultiSourceInput.ts b/web/src/engine/osk/gesture-processor/src/test/resources/simulateMultiSourceInput.ts similarity index 100% rename from common/web/gesture-recognizer/src/test/resources/simulateMultiSourceInput.ts rename to web/src/engine/osk/gesture-processor/src/test/resources/simulateMultiSourceInput.ts diff --git a/common/web/gesture-recognizer/src/test/tsconfig.json b/web/src/engine/osk/gesture-processor/src/test/tsconfig.json similarity index 100% rename from common/web/gesture-recognizer/src/test/tsconfig.json rename to web/src/engine/osk/gesture-processor/src/test/tsconfig.json diff --git a/common/web/gesture-recognizer/src/tools/build.sh b/web/src/engine/osk/gesture-processor/src/tools/build.sh similarity index 78% rename from common/web/gesture-recognizer/src/tools/build.sh rename to web/src/engine/osk/gesture-processor/src/tools/build.sh index 657a8ab1bf..ca951721b6 100755 --- a/common/web/gesture-recognizer/src/tools/build.sh +++ b/web/src/engine/osk/gesture-processor/src/tools/build.sh @@ -3,29 +3,32 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "$(dirname "$THIS_SCRIPT")/../../../../../resources/build/builder.inc.sh" +. "$(dirname "$THIS_SCRIPT")/../../../../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" BUNDLE_CMD="node $KEYMAN_ROOT/common/web/es-bundling/build/common-bundle.mjs" +BASE_DIR="/web/src/engine/osk/gesture-processor" +BUILD_DIR="${BASE_DIR}/build" + ################################ Main script ################################ -builder_describe "Testing-oriented tools for the Gesture Recognizer module of web-based Keyman OSKs" \ +builder_describe "Testing-oriented tools for the Gesture Processor module of web-based Keyman OSKs" \ "clean" \ "build" \ ":fixture The HTML-element fixture and CSS fixture used for both user-testing and unit-testing" \ ":recorder The web page used for recording input sequences for use in unit-testing" \ - ":test-module The TS library used to interface with the main gesture-recognizer module for tests" + ":test-module The TS library used to interface with the main gesture-processor module for tests" builder_parse "$@" builder_describe_outputs \ configure /node_modules \ - build:fixture /common/web/gesture-recognizer/build/tools/host-fixture.html \ - build:recorder /common/web/gesture-recognizer/src/tools/recorder/build/recorder.mjs \ - build:test-module /common/web/gesture-recognizer/build/tools/lib/index.mjs + build:fixture "${BUILD_DIR}/tools/host-fixture.html" \ + build:recorder "${BASE_DIR}/src/tools/recorder/build/recorder.mjs" \ + build:test-module "${BUILD_DIR}/tools/lib/index.mjs" # TODO: build if out-of-date if test is specified # TODO: configure if npm has not been run, and build is specified @@ -76,8 +79,8 @@ fi if builder_start_action build:test-module; then tsc -b "$THIS_SCRIPT_PATH/unit-test-resources/tsconfig.json" - $BUNDLE_CMD "${KEYMAN_ROOT}/common/web/gesture-recognizer/build/tools/obj/index.js" \ - --out "${KEYMAN_ROOT}/common/web/gesture-recognizer/build/tools/lib/index.mjs" \ + $BUNDLE_CMD "${KEYMAN_ROOT}/${BUILD_DIR}/tools/obj/index.js" \ + --out "${KEYMAN_ROOT}/${BUILD_DIR}/tools/lib/index.mjs" \ --format "esm" builder_finish_action success build:test-module diff --git a/common/web/gesture-recognizer/src/tools/host-fixture/extract-fixture.sh b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/extract-fixture.sh similarity index 100% rename from common/web/gesture-recognizer/src/tools/host-fixture/extract-fixture.sh rename to web/src/engine/osk/gesture-processor/src/tools/host-fixture/extract-fixture.sh diff --git a/common/web/gesture-recognizer/src/tools/host-fixture/extractor.cjs b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/extractor.cjs similarity index 100% rename from common/web/gesture-recognizer/src/tools/host-fixture/extractor.cjs rename to web/src/engine/osk/gesture-processor/src/tools/host-fixture/extractor.cjs diff --git a/common/web/gesture-recognizer/src/tools/host-fixture/gestureHost.css b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/gestureHost.css similarity index 100% rename from common/web/gesture-recognizer/src/tools/host-fixture/gestureHost.css rename to web/src/engine/osk/gesture-processor/src/tools/host-fixture/gestureHost.css diff --git a/common/web/gesture-recognizer/src/tools/host-fixture/host-fixture.html b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html similarity index 100% rename from common/web/gesture-recognizer/src/tools/host-fixture/host-fixture.html rename to web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html diff --git a/common/web/gesture-recognizer/src/tools/recorder/src/index.html b/web/src/engine/osk/gesture-processor/src/tools/recorder/src/index.html similarity index 100% rename from common/web/gesture-recognizer/src/tools/recorder/src/index.html rename to web/src/engine/osk/gesture-processor/src/tools/recorder/src/index.html diff --git a/common/web/gesture-recognizer/src/tools/recorder/src/pageStyle.css b/web/src/engine/osk/gesture-processor/src/tools/recorder/src/pageStyle.css similarity index 100% rename from common/web/gesture-recognizer/src/tools/recorder/src/pageStyle.css rename to web/src/engine/osk/gesture-processor/src/tools/recorder/src/pageStyle.css diff --git a/common/web/gesture-recognizer/src/tools/recorder/src/recorder.mjs b/web/src/engine/osk/gesture-processor/src/tools/recorder/src/recorder.mjs similarity index 100% rename from common/web/gesture-recognizer/src/tools/recorder/src/recorder.mjs rename to web/src/engine/osk/gesture-processor/src/tools/recorder/src/recorder.mjs diff --git a/common/web/gesture-recognizer/src/tools/recorder/update-index.cjs b/web/src/engine/osk/gesture-processor/src/tools/recorder/update-index.cjs similarity index 100% rename from common/web/gesture-recognizer/src/tools/recorder/update-index.cjs rename to web/src/engine/osk/gesture-processor/src/tools/recorder/update-index.cjs diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/build-bundler.js b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/build-bundler.js similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/build-bundler.js rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/build-bundler.js diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/fixtureLayoutConfiguration.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/fixtureLayoutConfiguration.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/fixtureLayoutConfiguration.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/fixtureLayoutConfiguration.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/headlessInputEngine.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/headlessInputEngine.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/headlessInputEngine.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/headlessInputEngine.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/hostFixtureLayoutController.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/hostFixtureLayoutController.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/hostFixtureLayoutController.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/hostFixtureLayoutController.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/index.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/index.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/index.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/index.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputRecording.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputRecording.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputRecording.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputRecording.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputSequenceSimulator.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputSequenceSimulator.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/jsonObject.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/jsonObject.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/jsonObject.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/jsonObject.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/sequenceRecorder.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/sequenceRecorder.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/sequenceRecorder.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/sequenceRecorder.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/touchpathTurtle.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/touchpathTurtle.ts similarity index 100% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/src/touchpathTurtle.ts rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/touchpathTurtle.ts diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/tsconfig.json similarity index 84% rename from common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json rename to web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/tsconfig.json index 7254159211..34d1929af1 100644 --- a/common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json +++ b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../../tsconfig.kmw-main-base.json", + "extends": "../../../../../../../tsconfig.base.json", "compilerOptions": { "baseUrl": "./", "lib": [ "dom", "es6" ], diff --git a/common/web/gesture-recognizer/test.sh b/web/src/engine/osk/gesture-processor/test.sh similarity index 93% rename from common/web/gesture-recognizer/test.sh rename to web/src/engine/osk/gesture-processor/test.sh index 03d0e32fa1..f1c50eeed4 100755 --- a/common/web/gesture-recognizer/test.sh +++ b/web/src/engine/osk/gesture-processor/test.sh @@ -3,7 +3,7 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" -. "$(dirname "$THIS_SCRIPT")/../../../resources/build/build-utils.sh" +. "$(dirname "$THIS_SCRIPT")/../../../../../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE . $KEYMAN_ROOT/resources/shellHelperFunctions.sh @@ -13,8 +13,8 @@ cd "$(dirname $THIS_SCRIPT)" ################################ Main script ################################ -builder_describe "Runs all tests for the gesture-recognizer module" \ - "@/common/web/gesture-recognizer" \ +builder_describe "Runs all tests for the gesture-processor module" \ + "@../gesture-processor" \ "test+" \ ":headless Runs headless user tests" \ ":browser Runs browser-based user tests" \ diff --git a/common/web/gesture-recognizer/tsconfig.json b/web/src/engine/osk/gesture-processor/tsconfig.json similarity index 61% rename from common/web/gesture-recognizer/tsconfig.json rename to web/src/engine/osk/gesture-processor/tsconfig.json index c4ff34e963..0b2d3a87b9 100644 --- a/common/web/gesture-recognizer/tsconfig.json +++ b/web/src/engine/osk/gesture-processor/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig.kmw-main-base.json", + "extends": "../../../../tsconfig.base.json", "compilerOptions": { "baseUrl": "./", "lib": [ "dom", "es6" ], @@ -8,8 +8,8 @@ "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", }, "include": ["./src/engine/**/*.ts"], - "exclude": ["./src/test/**/*.ts", "./src/tools/**/*.ts"], "references": [ - { "path": "../utils" } - ] + { "path": "../../../../../common/web/utils" }, + ], + "exclude": ["./src/test/**/*.ts", "./src/tools/**/*.ts"] } diff --git a/web/src/engine/osk/tsconfig.json b/web/src/engine/osk/tsconfig.json index 0f24be8efa..629443ed50 100644 --- a/web/src/engine/osk/tsconfig.json +++ b/web/src/engine/osk/tsconfig.json @@ -12,7 +12,7 @@ "include": [ "src/**/*.ts" ], "references": [ - { "path": "../../../../common/web/gesture-recognizer" }, + { "path": "./gesture-processor" }, { "path": "../interfaces" }, { "path": "../dom-utils" }, { "path": "../events" } diff --git a/web/src/test/manual/build.sh b/web/src/test/manual/build.sh index 046cefe152..905a799ab5 100755 --- a/web/src/test/manual/build.sh +++ b/web/src/test/manual/build.sh @@ -49,11 +49,11 @@ function do_copy() { cp "$SENTRY_SRC" "$KEYMAN_ROOT/$DEST/sentry-bundle.min.js" cp "$SENTRY_MAP" "$KEYMAN_ROOT/$DEST/sentry-bundle.min.js.map" - GESTURE_RECOGNIZER_BUILD="$KEYMAN_ROOT/common/web/gesture-recognizer/build/lib/." - GESTURE_RECOGNIZER_TARGET="$KEYMAN_ROOT/web/build/engine/gesture-recognizer/lib/" + GESTURE_PROCESSOR_BUILD="$KEYMAN_ROOT/web/src/engine/osk/gesture-processor/build/lib/." + GESTURE_PROCESSOR_TARGET="$KEYMAN_ROOT/web/build/engine/gesture-processor/lib/" - mkdir -p "$GESTURE_RECOGNIZER_TARGET" - cp -a "$GESTURE_RECOGNIZER_BUILD" "$GESTURE_RECOGNIZER_TARGET" + mkdir -p "$GESTURE_PROCESSOR_TARGET" + cp -a "$GESTURE_PROCESSOR_BUILD" "$GESTURE_PROCESSOR_TARGET" } builder_run_action clean rm -rf "$KEYMAN_ROOT/$DEST" diff --git a/web/src/test/manual/web/gesture-recognizer/hostConfiguration.mjs b/web/src/test/manual/web/gesture-recognizer/hostConfiguration.mjs index 7bd1426a58..2e40a29640 100644 --- a/web/src/test/manual/web/gesture-recognizer/hostConfiguration.mjs +++ b/web/src/test/manual/web/gesture-recognizer/hostConfiguration.mjs @@ -1,6 +1,6 @@ // -- BEGIN: Code for controlling the layout-simulation elements -- -import { GestureRecognizer } from '../../../../../build/engine/gesture-recognizer/lib/index.mjs'; +import { GestureRecognizer } from '../../../../../build/engine/gesture-processor/lib/index.mjs'; function updateConfig() { let layout = document.config.screen; From b1fb8122c2f2df887cd193ee7bac167dc64fe966 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 15 Aug 2024 19:40:44 +0200 Subject: [PATCH 77/89] refactor(web): move `gesture-processor` tests under `web/src/test` `gesture-processor/src/test/auto/browser/web-test-runner.config.mjs` run the tests on iOS and Android. However, if we enable these browsers in `web/src/test/auto/dom/web-test-runner.config.mjs` we get failing tests in osk, therefore these browsers are commented for now. --- package-lock.json | 35 ++++---- web/build.sh | 5 ++ web/common.inc.sh | 8 +- web/package.json | 1 + web/src/engine/keyboard/build.sh | 6 -- web/src/engine/osk/gesture-processor/build.sh | 25 ++---- .../engine/osk/gesture-processor/package.json | 5 +- .../browser/web-test-runner.CI.config.mjs | 13 --- .../auto/browser/web-test-runner.config.mjs | 69 --------------- .../gesture-processor/src/test/tsconfig.json | 30 ------- .../osk/gesture-processor/src/tools/build.sh | 53 ++++++------ .../tools/unit-test-resources/src/index.ts | 1 + web/src/engine/osk/gesture-processor/test.sh | 84 ------------------- .../cases/gesture-processor/canary.spec.ts} | 16 ++-- .../cases/gesture-processor}/gestureHost.css | 0 .../gesture-processor}/host-page.spec.html | 8 +- .../gesture-processor/ignoredInputs.spec.ts} | 20 +++-- .../recordedCoordSequences.spec.ts} | 23 ++--- .../cases/keyboard/domKeyboardLoader.spec.ts | 12 +-- .../test/auto/dom/web-test-runner.config.mjs | 37 ++++++-- .../asyncClosureDispatchQueue.spec.ts | 0 .../gesture-processor}/gesturePath.spec.ts | 4 +- .../gesture-processor}/gestureSource.spec.ts | 0 .../gestures/gestureMatcher.spec.ts | 6 +- .../gestures/gestureModelDefs.spec.ts | 0 .../gestures/gestureSequence.spec.ts | 6 +- .../gestures/isolatedGestureSpecs.ts | 0 .../gestures/isolatedPathSpecs.ts | 0 .../gestures/matcherSelector.spec.ts | 6 +- .../gestures/pathMatcher.spec.ts | 2 +- .../gestures/touchpointCoordinator.spec.ts | 6 +- .../osk/gesture-processor}/pathStats.spec.ts | 0 .../auto}/resources/@types/promiseStatus.d.ts | 0 .../resources/assertSegmentSimilarity.js | 0 .../auto}/resources/assertingPromiseStatus.ts | 0 .../auto}/resources/json/canaryRecording.json | 0 .../json/receiver/basicMultitouch.json | 0 .../json/receiver/desktopRoamAndReturn.json | 0 .../json/receiver/embeddedBorderCancel.json | 0 .../json/receiver/hardBorderCancel.json | 0 .../receiver/mobileProximityApproach.json | 0 .../json/receiver/mobileSafeZoneCancel.json | 0 .../json/receiver/popupLongRoamingEnd.json | 0 .../json/receiver/popupSafePersistence.json | 0 .../json/receiver/popupShimCancel.json | 0 .../json/segmentation/flick_ne_se.json | 0 .../json/segmentation/longpress_to_ne.json | 0 .../json/segmentation/nonstationary_hold.json | 0 .../json/segmentation/quick_small_square.json | 0 .../json/segmentation/simple_ne_move.json | 0 .../auto}/resources/sequenceAssertions.ts | 0 .../resources/simulateMultiSourceInput.ts | 0 web/src/test/auto/tsconfig.json | 3 +- 53 files changed, 156 insertions(+), 328 deletions(-) delete mode 100644 web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.CI.config.mjs delete mode 100644 web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.config.mjs delete mode 100644 web/src/engine/osk/gesture-processor/src/test/tsconfig.json delete mode 100755 web/src/engine/osk/gesture-processor/test.sh rename web/src/{engine/osk/gesture-processor/src/test/auto/browser/cases/canary.def.ts => test/auto/dom/cases/gesture-processor/canary.spec.ts} (87%) rename web/src/{engine/osk/gesture-processor/src/test/auto/browser/cases => test/auto/dom/cases/gesture-processor}/gestureHost.css (100%) rename web/src/{engine/osk/gesture-processor/src/test/auto/browser/cases => test/auto/dom/cases/gesture-processor}/host-page.spec.html (90%) rename web/src/{engine/osk/gesture-processor/src/test/auto/browser/cases/ignoredInputs.def.ts => test/auto/dom/cases/gesture-processor/ignoredInputs.spec.ts} (82%) rename web/src/{engine/osk/gesture-processor/src/test/auto/browser/cases/recordedCoordSequences.def.ts => test/auto/dom/cases/gesture-processor/recordedCoordSequences.spec.ts} (88%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/asyncClosureDispatchQueue.spec.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gesturePath.spec.ts (99%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestureSource.spec.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestures/gestureMatcher.spec.ts (99%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestures/gestureModelDefs.spec.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestures/gestureSequence.spec.ts (99%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestures/isolatedGestureSpecs.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestures/isolatedPathSpecs.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestures/matcherSelector.spec.ts (99%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestures/pathMatcher.spec.ts (99%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/gestures/touchpointCoordinator.spec.ts (99%) rename web/src/{engine/osk/gesture-processor/src/test/auto/headless => test/auto/headless/engine/osk/gesture-processor}/pathStats.spec.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/@types/promiseStatus.d.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/assertSegmentSimilarity.js (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/assertingPromiseStatus.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/canaryRecording.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/basicMultitouch.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/desktopRoamAndReturn.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/embeddedBorderCancel.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/hardBorderCancel.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/mobileProximityApproach.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/mobileSafeZoneCancel.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/popupLongRoamingEnd.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/popupSafePersistence.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/receiver/popupShimCancel.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/segmentation/flick_ne_se.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/segmentation/longpress_to_ne.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/segmentation/nonstationary_hold.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/segmentation/quick_small_square.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/json/segmentation/simple_ne_move.json (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/sequenceAssertions.ts (100%) rename web/src/{engine/osk/gesture-processor/src/test => test/auto}/resources/simulateMultiSourceInput.ts (100%) diff --git a/package-lock.json b/package-lock.json index 515b2fefc8..05f215f316 100644 --- a/package-lock.json +++ b/package-lock.json @@ -160,19 +160,6 @@ }, "devDependencies": {} }, - "web/src/engine/osk/gesture-processor": { - "name": "@keymanapp/gesture-recognizer", - "dependencies": { - "eventemitter3": "^5.0.0" - }, - "devDependencies": { - "@keymanapp/resources-gosh": "*", - "mocha": "^10.0.0", - "mocha-teamcity-reporter": "^4.0.0", - "promise-status-async": "^1.2.10", - "typescript": "^5.4.5" - } - }, "common/web/keyman-version": { "name": "@keymanapp/keyman-version", "license": "MIT", @@ -405,7 +392,7 @@ "eventemitter3": "^5.0.0", "restructure": "^3.0.1", "sax": ">=0.6.0", - "semver": "^7.5.2", + "semver": "^7.5.4", "xmlbuilder": "~11.0.0" }, "devDependencies": { @@ -1154,7 +1141,7 @@ "@keymanapp/keyman-version": "*", "@keymanapp/kmc-kmn": "*", "@keymanapp/ldml-keyboard-constants": "*", - "semver": "^7.5.2" + "semver": "^7.5.4" }, "devDependencies": { "@keymanapp/developer-test-helpers": "*", @@ -1943,7 +1930,7 @@ "open": "^8.4.0", "restructure": "^3.0.1", "sax": ">=0.6.0", - "semver": "^7.5.2", + "semver": "^7.5.4", "ws": "^8.17.1", "xmlbuilder": "~11.0.0" }, @@ -14631,7 +14618,7 @@ "devDependencies": { "@types/semver": "^7.1.0", "@types/yargs": "^17.0.26", - "semver": "^7.5.2" + "semver": "^7.5.4" } }, "resources/build/version/node_modules/ansi-regex": { @@ -14765,6 +14752,20 @@ "mocha": "^10.0.0" } }, + "web/src/engine/osk/gesture-processor": { + "name": "@keymanapp/gesture-recognizer", + "dependencies": { + "@keymanapp/web-utils": "*", + "eventemitter3": "^5.0.0" + }, + "devDependencies": { + "@keymanapp/resources-gosh": "*", + "mocha": "^10.0.0", + "mocha-teamcity-reporter": "^4.0.0", + "promise-status-async": "^1.2.10", + "typescript": "^5.4.5" + } + }, "web/src/engine/predictive-text/types": { "name": "@keymanapp/lm-message-types", "license": "MIT", diff --git a/web/build.sh b/web/build.sh index 16d3d11235..445c4b2e63 100755 --- a/web/build.sh +++ b/web/build.sh @@ -109,6 +109,11 @@ precompile() { build_action() { builder_echo "Building auto tests..." + + # The currently-bundled declaration file for gesture-processor generates + # errors when compiling against it with current tsc versions. + rm -f "${KEYMAN_ROOT}/node_modules/promise-status-async/lib/index.d.ts" + tsc --project "${KEYMAN_ROOT}/web/src/test/auto/tsconfig.json" for dir in \ diff --git a/web/common.inc.sh b/web/common.inc.sh index 9457fa5a41..8edfb9f4fa 100644 --- a/web/common.inc.sh +++ b/web/common.inc.sh @@ -10,6 +10,8 @@ BUNDLE_CMD="node $KEYMAN_ROOT/common/web/es-bundling/build/common-bundle.mjs" # ### Parameters # # * 1: `product` the product's source path under src/ +# * 2: `src_dir` the source directory. Optional. Default: ${KEYMAN_ROOT}/web/src +# * 3: `build_dir` the build directory. Optional. Default: ${KEYMAN_ROOT}/web/build # # ### Example # @@ -22,11 +24,13 @@ function compile() { fi local COMPILE_TARGET="$1" + local SRC_DIR=${2:-"${KEYMAN_ROOT}/web/src"} + local BUILD_DIR=${3:-"${KEYMAN_ROOT}/web/build"} - tsc -b "${KEYMAN_ROOT}/web/src/$COMPILE_TARGET" + tsc -b "${SRC_DIR}/$COMPILE_TARGET" # So... tsc does declaration-bundling on its own pretty well, at least for local development. - tsc --emitDeclarationOnly --outFile "${KEYMAN_ROOT}/web/build/$COMPILE_TARGET/lib/index.d.ts" -p "${KEYMAN_ROOT}/web/src/$COMPILE_TARGET" + tsc --emitDeclarationOnly --outFile "${BUILD_DIR}/$COMPILE_TARGET/lib/index.d.ts" -p "${SRC_DIR}/$COMPILE_TARGET" } function _copy_dir_if_exists() { diff --git a/web/package.json b/web/package.json index 96a11c0cd3..5c6684afd3 100644 --- a/web/package.json +++ b/web/package.json @@ -89,6 +89,7 @@ } }, "imports": { + "#gesture-tools": "./src/engine/osk/gesture-processor/build/tools/obj/index.js", "#recorder": "./build/tools/testing/recorder/obj/index.js" }, "repository": { diff --git a/web/src/engine/keyboard/build.sh b/web/src/engine/keyboard/build.sh index 226a7d9d75..7b04e478a0 100755 --- a/web/src/engine/keyboard/build.sh +++ b/web/src/engine/keyboard/build.sh @@ -66,12 +66,6 @@ function do_build() { --format esm \ --platform node - # # Tests - # builder_echo "Bundle tests" - # ${BUNDLE_CMD} "${BUILD_DIR}/tests/dom/cases/domKeyboardLoader.spec.js" \ - # --out "${BUILD_DIR}/tests/dom/domKeyboardLoader.spec.mjs" \ - # --format esm - # Declaration bundling. builder_echo "Declaration bundling" tsc --emitDeclarationOnly --outFile "${BUILD_DIR}/lib/index.d.ts" diff --git a/web/src/engine/osk/gesture-processor/build.sh b/web/src/engine/osk/gesture-processor/build.sh index 37cd785623..f3bafab5ed 100755 --- a/web/src/engine/osk/gesture-processor/build.sh +++ b/web/src/engine/osk/gesture-processor/build.sh @@ -6,7 +6,10 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "$(dirname "$THIS_SCRIPT")/../../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE -. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +SUBPROJECT_NAME=engine/osk/gesture-processor + +. "${KEYMAN_ROOT}/web/common.inc.sh" +. "${KEYMAN_ROOT}/resources/shellHelperFunctions.sh" BUNDLE_CMD="node $KEYMAN_ROOT/common/web/es-bundling/build/common-bundle.mjs" @@ -37,10 +40,6 @@ builder_parse "$@" function do_configure() { verify_npm_setup - - # Configure Web browser-engine testing environments. As is, this should only - # make changes when we update the dependency, even on our CI build agents. - playwright install } function do_build_module() { @@ -52,18 +51,6 @@ function do_build_module() { --format esm } -function do_build_tools() { - src/tools/build.sh build -} - -function do_test_module() { - if builder_has_option --ci; then - ./test.sh --ci - else - ./test.sh - fi -} - function do_test_tools() { if ! builder_has_action test:module; then echo "The $(builder_term test:tools) action is currently a no-op." @@ -73,6 +60,6 @@ function do_test_tools() { builder_run_action configure do_configure builder_run_action clean rm -rf build/ intermediate/ builder_run_action build:module do_build_module -builder_run_action build:tools do_build_tools -builder_run_action test:module do_test_module +builder_run_action build:tools src/tools/build.sh build +builder_run_action test:module test-headless "${SUBPROJECT_NAME}" builder_run_action test:tools do_test_tools diff --git a/web/src/engine/osk/gesture-processor/package.json b/web/src/engine/osk/gesture-processor/package.json index 9ec0606ebd..fd8e7fcddf 100644 --- a/web/src/engine/osk/gesture-processor/package.json +++ b/web/src/engine/osk/gesture-processor/package.json @@ -8,12 +8,9 @@ "promise-status-async": "^1.2.10", "typescript": "^5.4.5" }, - "imports": { - "#tools": "./build/tools/obj/index.js" - }, "scripts": { "build": "gosh ./build.sh", - "test": "gosh ./test.sh" + "test": "gosh ./build.sh test" }, "dependencies": { "@keymanapp/web-utils": "*", diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.CI.config.mjs b/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.CI.config.mjs deleted file mode 100644 index d18a8a9cb0..0000000000 --- a/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.CI.config.mjs +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -import BASE_CONFIG from './web-test-runner.config.mjs'; -import teamcityReporter from '@keymanapp/common-test-resources/test-runner-TC-reporter.mjs'; -import { sessionStabilityReporter } from '@keymanapp/common-test-resources/test-runner-stability-reporter.mjs'; - -/** @type {import('@web/test-runner').TestRunnerConfig} */ -export default { - ...BASE_CONFIG, - reporters: [ - teamcityReporter(), /* custom-written, for CI-friendly reports */ - sessionStabilityReporter({ciMode: true}) - ] -} \ No newline at end of file diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.config.mjs b/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.config.mjs deleted file mode 100644 index 4487912e0d..0000000000 --- a/web/src/engine/osk/gesture-processor/src/test/auto/browser/web-test-runner.config.mjs +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-check -import { devices, playwrightLauncher } from '@web/test-runner-playwright'; -import { defaultReporter, summaryReporter } from '@web/test-runner'; -import { LauncherWrapper, sessionStabilityReporter } from '@keymanapp/common-test-resources/test-runner-stability-reporter.mjs'; -import named from '@keymanapp/common-test-resources/test-runner-rename-browser.mjs' -import { esbuildPlugin } from '@web/dev-server-esbuild'; -import { importMapsPlugin } from '@web/dev-server-import-maps'; -import { dirname, resolve } from 'path'; -import { fileURLToPath } from 'url'; - -const dir = dirname(fileURLToPath(import.meta.url)); -const KEYMAN_ROOT = resolve(dir, '../../../../../../../'); - -/** @type {import('@web/test-runner').TestRunnerConfig} */ -export default { - // debug: true, - browsers: [ - new LauncherWrapper(playwrightLauncher({ product: 'chromium' })), - new LauncherWrapper(playwrightLauncher({ product: 'firefox' })), - playwrightLauncher({ product: 'webkit', concurrency: 1}), - named(new LauncherWrapper(playwrightLauncher({ product: 'webkit', concurrency: 1, createBrowserContext({browser}) { - return browser.newContext({...devices['iPhone X'] }); - }})), 'iOS Phone (emulated)'), - named(new LauncherWrapper(playwrightLauncher({ product: 'chromium' , createBrowserContext({browser}) { - return browser.newContext({...devices['Pixel 4'] }) - }})), 'Android Phone (emulated)'), - ], - concurrency: 10, - nodeResolve: true, - files: [ - '**/*.spec.html' - ], - middleware: [ - // Rewrites short-hand paths for test resources, making them fully relative to the repo root. - function rewriteResourcePath(context, next) { - if(context.url.startsWith('/resources/')) { - context.url = '/web/src/engine/osk/gesture-processor/src/test' + context.url; - } - - return next(); - } - ], - plugins: [ - esbuildPlugin({ ts: true, target: 'auto'}), - importMapsPlugin({ - inject: { - importMap: { - // Redirects `eventemitter3` imports to the bundled ESM library. The standard import is an - // ESM wrapper around the CommonJS implementation, and WTR fails when it hits the CommonJS. - imports: { - 'eventemitter3': '/node_modules/eventemitter3/dist/eventemitter3.esm.js' - } - } - } - }) - ], - reporters: [ - summaryReporter({}), /* local-dev mocha-style */ - sessionStabilityReporter({}), - defaultReporter({}) - ], - /* - Un-comment the next two lines for easy interactive debugging; it'll launch the - test page in your preferred browser. - */ - // open: true, - // manual: true, - rootDir: KEYMAN_ROOT -} \ No newline at end of file diff --git a/web/src/engine/osk/gesture-processor/src/test/tsconfig.json b/web/src/engine/osk/gesture-processor/src/test/tsconfig.json deleted file mode 100644 index 4eea3ef803..0000000000 --- a/web/src/engine/osk/gesture-processor/src/test/tsconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -/* - * VS Code Intellisense needs this helper in order to properly use subpath imports in the - * test specs found under the `headless` subfolder. Otherwise, it'll report errors while - * editing - even if the tests themselves actually work. - */ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "../../build/test/", - // Not needed when testing via Node, and when `true` it seems to desync preset breakpoints - // worse than when `false`. - "importHelpers": false, - - "allowJs": true, - - "baseUrl": "../../", - "tsBuildInfoFile": "../../build/test/tsconfig.tsbuildinfo", - "rootDir": "./", - "typeRoots": ["./resources/@types", "../../../../../node_modules/@types"] - }, - "include": [ - "./auto/headless/**/*.ts", - "./resources/**/*.ts" - ], - // Undo the base config's exclude. - "exclude": ["../../../../../node_modules/promise-status-async/lib/index.d.ts"], - "references": [ - {"path": "../../"} - ] -} diff --git a/web/src/engine/osk/gesture-processor/src/tools/build.sh b/web/src/engine/osk/gesture-processor/src/tools/build.sh index ca951721b6..1813ab62a8 100755 --- a/web/src/engine/osk/gesture-processor/src/tools/build.sh +++ b/web/src/engine/osk/gesture-processor/src/tools/build.sh @@ -6,6 +6,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "$(dirname "$THIS_SCRIPT")/../../../../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE +. "$KEYMAN_ROOT/web/common.inc.sh" . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" BUNDLE_CMD="node $KEYMAN_ROOT/common/web/es-bundling/build/common-bundle.mjs" @@ -33,34 +34,18 @@ builder_describe_outputs \ # TODO: build if out-of-date if test is specified # TODO: configure if npm has not been run, and build is specified -if builder_start_action clean:recorder; then - rm -rf ./recorder/build - builder_finish_action success clean:recorder -fi - -if builder_start_action clean:fixture; then +function do_clean_fixture() { rm -f ../../build/tools/host-fixture.html rm -f ../../build/tools/gestureHost.css - builder_finish_action success clean:fixture -fi +} -if builder_start_action clean:test-module; then +function do_clean_testmodule() { rm -rf ../../build/tools/*.ts* rm -rf ../../build/tools/*.js* - builder_finish_action success clean:test-module -fi +} -if builder_start_action build:fixture; then - if [ ! -d ../../build/tools ]; then - mkdir -p ../../build/tools - fi - ./host-fixture/extract-fixture.sh > ../../build/tools/host-fixture.html - cp ./host-fixture/gestureHost.css ../../build/tools/gestureHost.css - builder_finish_action success build:fixture -fi - -if builder_start_action build:recorder; then - if [ ! -d recorder/build ]; then +function do_build_recorder() { + if [[ ! -d recorder/build ]]; then mkdir -p recorder/build fi cp recorder/src/pageStyle.css recorder/build/pageStyle.css @@ -73,15 +58,27 @@ if builder_start_action build:recorder; then pushd recorder >/dev/null node update-index.cjs build/index.html popd >/dev/null - builder_finish_action success build:recorder -fi +} -if builder_start_action build:test-module; then - tsc -b "$THIS_SCRIPT_PATH/unit-test-resources/tsconfig.json" +function do_build_fixture() { + if [[ ! -d ../../build/tools ]]; then + mkdir -p ../../build/tools + fi + ./host-fixture/extract-fixture.sh > ../../build/tools/host-fixture.html + cp ./host-fixture/gestureHost.css ../../build/tools/gestureHost.css +} + +function do_build_testmodule() { + compile "" "${THIS_SCRIPT_PATH}/unit-test-resources" "${KEYMAN_ROOT}/${BUILD_DIR}/tools" $BUNDLE_CMD "${KEYMAN_ROOT}/${BUILD_DIR}/tools/obj/index.js" \ --out "${KEYMAN_ROOT}/${BUILD_DIR}/tools/lib/index.mjs" \ --format "esm" +} - builder_finish_action success build:test-module -fi \ No newline at end of file +builder_run_action clean:recorder rm -rf ./recorder/build +builder_run_action clean:fixture do_clean_fixture +builder_run_action clean:test-module do_clean_testmodule +builder_run_action build:recorder do_build_recorder +builder_run_action build:fixture do_build_fixture +builder_run_action build:test-module do_build_testmodule diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/index.ts b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/index.ts index e3bf02cc37..dfc9740330 100644 --- a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/index.ts +++ b/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/index.ts @@ -1,6 +1,7 @@ export * from './fixtureLayoutConfiguration.js'; export * from './headlessInputEngine.js'; export * from './hostFixtureLayoutController.js'; +export * from './inputRecording.js'; export * from './inputSequenceSimulator.js'; export * from './sequenceRecorder.js'; export * from './touchpathTurtle.js'; \ No newline at end of file diff --git a/web/src/engine/osk/gesture-processor/test.sh b/web/src/engine/osk/gesture-processor/test.sh deleted file mode 100755 index f1c50eeed4..0000000000 --- a/web/src/engine/osk/gesture-processor/test.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env bash - -## START STANDARD BUILD SCRIPT INCLUDE -# adjust relative paths as necessary -THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" -. "$(dirname "$THIS_SCRIPT")/../../../../../resources/build/build-utils.sh" -## END STANDARD BUILD SCRIPT INCLUDE - -. $KEYMAN_ROOT/resources/shellHelperFunctions.sh - -# This script runs from its own folder -cd "$(dirname $THIS_SCRIPT)" - -################################ Main script ################################ - -builder_describe "Runs all tests for the gesture-processor module" \ - "@../gesture-processor" \ - "test+" \ - ":headless Runs headless user tests" \ - ":browser Runs browser-based user tests" \ - "--ci Uses CI-based test configurations & emits CI-friendly test reports" - -builder_parse "$@" - -# TODO: build if out-of-date if test is specified -# TODO: configure if npm has not been run, and build is specified - -# START - Script parameter configuration -REPORT_STYLE="local" # Default setting. - -if builder_has_option --ci; then - REPORT_STYLE="ci" - - echo "Replacing user-friendly test reports & configurations with CI-friendly versions." -fi - -# END - Script parameter configuration - -test-headless ( ) { - # During debugging, "--slow 0" allows reporting the duration of ALL tests, not just the ones that run long. - # Can be useful... but probably shouldn't be the default. - MOCHA_FLAGS= - - if [ $REPORT_STYLE == "ci" ]; then - MOCHA_FLAGS="$MOCHA_FLAGS --reporter mocha-teamcity-reporter" - fi - - # The currently-bundled declaration file for this package generates errors when compiling against it - # with current tsc versions. - rm -f "${KEYMAN_ROOT}/node_modules/promise-status-async/lib/index.d.ts" - - tsc -b ./src/test/tsconfig.json - c8 mocha --recursive $MOCHA_FLAGS ./build/test/auto/headless/ -} - -test-browser ( ) { - local WTR_DEBUG= - local WTR_CONFIG= - if [[ $# -eq 1 && $1 == "debug" ]]; then - WTR_DEBUG=" --manual" - elif [ $REPORT_STYLE != "local" ]; then - WTR_CONFIG=.CI - fi - - web-test-runner --config src/test/auto/browser/web-test-runner${WTR_CONFIG}.config.mjs ${WTR_DEBUG} -} - -if builder_start_action test:headless; then - test-headless - builder_finish_action success test:headless -fi - -if builder_start_action test:browser; then - if builder_has_option --debug; then - echo "Running browser-based unit tests in debug-mode configuration..." - echo - echo "${COLOR_YELLOW}You must manually terminate this mode (CTRL-C) for the script to exit.${COLOR_RESET}" - sleep 2 - test-browser debug - else - test-browser - fi - builder_finish_action success test:browser -fi \ No newline at end of file diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/canary.def.ts b/web/src/test/auto/dom/cases/gesture-processor/canary.spec.ts similarity index 87% rename from web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/canary.def.ts rename to web/src/test/auto/dom/cases/gesture-processor/canary.spec.ts index 241977b322..78fbcf6f79 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/canary.def.ts +++ b/web/src/test/auto/dom/cases/gesture-processor/canary.spec.ts @@ -2,10 +2,14 @@ import { assert } from 'chai'; import sinon from 'sinon'; import { + DeviceLayoutClass, FixtureLayoutConfiguration, HostFixtureLayoutController, - InputSequenceSimulator -} from '#tools'; + InputSequenceSimulator, + ReceiverLayoutClass, + RoamingLayoutClass, + SafeLayoutClass +} from '#gesture-tools'; import { DEFAULT_BROWSER_TIMEOUT } from '@keymanapp/common-test-resources/test-timeouts.mjs'; @@ -75,11 +79,11 @@ describe("'Canary' checks", function() { it("InputSequenceSimulator.replayTouchSample", async function() { let playbackEngine = new InputSequenceSimulator(this.controller); - let layout = new FixtureLayoutConfiguration("screen2", "bounds1", "full", "safe-loose"); + let layout = new FixtureLayoutConfiguration("screen2" as DeviceLayoutClass, "bounds1" as RoamingLayoutClass, "full" as ReceiverLayoutClass, "safe-loose" as SafeLayoutClass); this.controller.layoutConfiguration = layout; let fireEvent = () => { - playbackEngine.replayTouchSamples(/*relative coord:*/ [ { sample: {targetX: 10, targetY: 10}, identifier: 1}], + playbackEngine.replayTouchSamples(/*relative coord:*/ [ { sample: {targetX: 10, targetY: 10, t: 0}, identifier: 1}], /*state:*/ "start", /*recentTouches:*/ [], ); @@ -101,11 +105,11 @@ describe("'Canary' checks", function() { it("InputSequenceSimulator.replayMouseSample", async function() { let playbackEngine = new InputSequenceSimulator(this.controller); - let layout = new FixtureLayoutConfiguration("screen2", "bounds1", "full", "safe-loose"); + let layout = new FixtureLayoutConfiguration("screen2" as DeviceLayoutClass, "bounds1" as RoamingLayoutClass, "full" as ReceiverLayoutClass, "safe-loose" as SafeLayoutClass); this.controller.layoutConfiguration = layout; let fireEvent = () => { - playbackEngine.replayMouseSample(/*relative coord:*/ {targetX: 15, targetY: 15}, + playbackEngine.replayMouseSample(/*relative coord:*/ {targetX: 15, targetY: 15, t: 0}, /*state:*/ "start" ); } diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/gestureHost.css b/web/src/test/auto/dom/cases/gesture-processor/gestureHost.css similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/gestureHost.css rename to web/src/test/auto/dom/cases/gesture-processor/gestureHost.css diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/host-page.spec.html b/web/src/test/auto/dom/cases/gesture-processor/host-page.spec.html similarity index 90% rename from web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/host-page.spec.html rename to web/src/test/auto/dom/cases/gesture-processor/host-page.spec.html index c4a4d7a47e..ce3aae6c48 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/host-page.spec.html +++ b/web/src/test/auto/dom/cases/gesture-processor/host-page.spec.html @@ -1,6 +1,6 @@ + imports for the .spec.js test suites. --> @@ -18,9 +18,9 @@ import { runTests } from '@web/test-runner-mocha'; runTests(async() => { - await import('./canary.def.ts'); - await import('./ignoredInputs.def.ts'); - await import('./recordedCoordSequences.def.ts'); + await import('./canary.spec.ts'); + await import('./ignoredInputs.spec.ts'); + await import('./recordedCoordSequences.spec.ts'); }); diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/ignoredInputs.def.ts b/web/src/test/auto/dom/cases/gesture-processor/ignoredInputs.spec.ts similarity index 82% rename from web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/ignoredInputs.def.ts rename to web/src/test/auto/dom/cases/gesture-processor/ignoredInputs.spec.ts index b107fdea5d..a288f925a3 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/ignoredInputs.def.ts +++ b/web/src/test/auto/dom/cases/gesture-processor/ignoredInputs.spec.ts @@ -5,8 +5,12 @@ import { FixtureLayoutConfiguration, HostFixtureLayoutController, InputSequenceSimulator, - SequenceRecorder -} from '#tools'; + SequenceRecorder, + DeviceLayoutClass, + RoamingLayoutClass, + ReceiverLayoutClass, + SafeLayoutClass +} from '#gesture-tools'; import { DEFAULT_BROWSER_TIMEOUT } from '@keymanapp/common-test-resources/test-timeouts.mjs'; @@ -28,19 +32,20 @@ describe("Layer one - DOM -> InputSequence", function() { it("starts in roaming zone are ignored", function() { let playbackEngine = new InputSequenceSimulator(controller); let recorder = new SequenceRecorder(controller); - let layout = new FixtureLayoutConfiguration("screen2", "bounds1", "full", "safe-loose"); + let layout = new FixtureLayoutConfiguration("screen2" as DeviceLayoutClass, "bounds1" as RoamingLayoutClass, "full" as ReceiverLayoutClass, "safe-loose" as SafeLayoutClass); controller.layoutConfiguration = layout; let fireEvent = () => { - playbackEngine.replayTouchSamples(/*relative coord:*/ [{sample: {targetX: 10, targetY: -5}, identifier: 1}], + playbackEngine.replayTouchSamples(/*relative coord:*/ [{sample: {targetX: 10, targetY: -5, t: 0}, identifier: 1}], /*state:*/ "start", /*recentTouches:*/ [], - /*targetElement:*/ controller.recognizer.config.maxRoamingBounds + /*targetElement:*/ controller.recognizer.config.maxRoamingBounds as HTMLElement ); } // This test is invalidated if the handler itself isn't called. So... let's verify that! // This requires white-box inspection of the actual handler control-flow, and we must do + // @ts-ignore // touchEngine is private let touchEngine = controller.recognizer.touchEngine; let trueHandler = touchEngine.onTouchStart; let fakeHandler = touchEngine.onTouchStart = sinon.fake(); @@ -61,11 +66,11 @@ describe("Layer one - DOM -> InputSequence", function() { it("ignores target-external events", function() { let playbackEngine = new InputSequenceSimulator(controller); let recorder = new SequenceRecorder(controller); - let layout = new FixtureLayoutConfiguration("screen2", "bounds1", "full", "safe-loose"); + let layout = new FixtureLayoutConfiguration("screen2" as DeviceLayoutClass, "bounds1" as RoamingLayoutClass, "full" as ReceiverLayoutClass, "safe-loose" as SafeLayoutClass); controller.layoutConfiguration = layout; let fireEvent = () => { - playbackEngine.replayMouseSample(/*relative coord:*/ {targetX: -5, targetY: 15}, + playbackEngine.replayMouseSample(/*relative coord:*/ {targetX: -5, targetY: 15, t: 0}, /*state:*/ "start", /*targetElement:*/ document.body ); @@ -73,6 +78,7 @@ describe("Layer one - DOM -> InputSequence", function() { // This test is invalidated if the handler itself isn't called. So... let's verify that! // Not quite covered by the canary cases b/c of the distinct targetElement. + // @ts-ignore // touchEngine is private let mouseEngine = controller.recognizer.mouseEngine; let trueHandler = mouseEngine.onMouseStart; let fakeHandler = mouseEngine.onMouseStart = sinon.fake(); diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/recordedCoordSequences.def.ts b/web/src/test/auto/dom/cases/gesture-processor/recordedCoordSequences.spec.ts similarity index 88% rename from web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/recordedCoordSequences.def.ts rename to web/src/test/auto/dom/cases/gesture-processor/recordedCoordSequences.spec.ts index 95af23b61d..06136c66a7 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/browser/cases/recordedCoordSequences.def.ts +++ b/web/src/test/auto/dom/cases/gesture-processor/recordedCoordSequences.spec.ts @@ -5,12 +5,13 @@ import type { GestureDebugSource, InputSample, SerializedGestureSource } from '@ import { HostFixtureLayoutController, - InputSequenceSimulator -} from '#tools'; + InputSequenceSimulator, + RecordedCoordSequenceSet +} from '#gesture-tools'; function isOnAndroid() { const agent=navigator.userAgent; - return agent.indexOf('Android' >= 0); + return agent.indexOf('Android') >= 0; } const loc = document.location; @@ -18,7 +19,7 @@ const loc = document.location; // filesystem for the drive. const domain = `${loc.protocol}/${loc.host}` -async function fetchRecording(jsonFilename) { +async function fetchRecording(jsonFilename: string): Promise { const jsonResponse = await fetch(new URL(`${domain}/resources/json/${jsonFilename}.json`)); return await jsonResponse.json(); } @@ -47,7 +48,7 @@ describe("Layer one - DOM -> InputSequence", function() { }); // We rely on this function to have the same context as `it` - the test-definition function. - let replayAndCompare = function(testObj) { + let replayAndCompare = function(testObj: RecordedCoordSequenceSet, mochaContext: Mocha.Context) { let playbackEngine = new InputSequenceSimulator(controller); // ********************************** @@ -68,18 +69,18 @@ describe("Layer one - DOM -> InputSequence", function() { // replayAsync sets up timeouts against the `clock` object. // This will run through the simulated timeout queue asynchronously. - this.clock.runAllAsync(); + mochaContext.clock.runAllAsync(); // resultPromise resolves on the final timeout in the queue. - return resultPromise.then((result) => { + return resultPromise.then((result: RecordedCoordSequenceSet) => { assert.equal(result.inputs.length, testObj.inputs.length); // Removes the timestamp element; we know that this component may not match perfectly. - let sampleCleaner = (sample) => { return {targetX: sample.targetX, targetY: sample.targetY} }; + let sampleCleaner = (sample: InputSample) => { return {targetX: sample.targetX, targetY: sample.targetY} }; // Returns just the observed, cleaned samples for a sequence object. The recorded coordinates // should match perfectly. - let seqCleaner = (input) => { + let seqCleaner = (input: SerializedGestureSource) => { return input.path.coords.map(sampleCleaner); }; @@ -124,7 +125,7 @@ describe("Layer one - DOM -> InputSequence", function() { // The 'terminationEvent' property should match. Any sequence that was "canceled" should still // cancel; that's a pretty critical detail! - let terminationEventMapper = (seq) => { + let terminationEventMapper = (seq: SerializedGestureSource) => { return seq.path.wasCancelled; } @@ -151,7 +152,7 @@ describe("Layer one - DOM -> InputSequence", function() { // 'describe' has a notably different `this` reference than `it`, `before`, etc, // hence the `.call` construction. - return replayAndCompare.call(this, testObj); + return replayAndCompare.call(this, testObj, this); }); } }); diff --git a/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts b/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts index da610402eb..95db91b0f8 100644 --- a/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts +++ b/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts @@ -30,7 +30,7 @@ describe('Keyboard loading in DOM', function() { it('`window`, disabled rule processing', async () => { const harness = new KeyboardHarness(window, MinimalKeymanGlobal); let keyboardLoader = new DOMKeyboardLoader(harness); - let keyboard: Keyboard = await keyboardLoader.loadKeyboardFromPath('/resources/keyboards/khmer_angkor.js'); + let keyboard: Keyboard = await keyboardLoader.loadKeyboardFromPath('/common/test/resources/keyboards/khmer_angkor.js'); assert.isOk(keyboard); assert.equal(keyboard.id, 'Keyboard_khmer_angkor'); @@ -48,7 +48,7 @@ describe('Keyboard loading in DOM', function() { it('`window`, enabled rule processing', async () => { const harness = new KeyboardInterface(window, MinimalKeymanGlobal); const keyboardLoader = new DOMKeyboardLoader(harness); - const keyboard: Keyboard = await keyboardLoader.loadKeyboardFromPath('/resources/keyboards/khmer_angkor.js'); + const keyboard: Keyboard = await keyboardLoader.loadKeyboardFromPath('/common/test/resources/keyboards/khmer_angkor.js'); harness.activeKeyboard = keyboard; assert.isOk(keyboard); @@ -80,14 +80,14 @@ describe('Keyboard loading in DOM', function() { let keyboardLoader = new DOMKeyboardLoader(harness); // Preload a keyboard and make it active. - const test_kbd: Keyboard = await keyboardLoader.loadKeyboardFromPath('/resources/keyboards/test_917.js'); + const test_kbd: Keyboard = await keyboardLoader.loadKeyboardFromPath('/common/test/resources/keyboards/test_917.js'); harness.activeKeyboard = test_kbd; assert.isNotOk(harness.loadedKeyboard); // With an active keyboard, load three keyboards but activate none of them. - const lao_keyboard_promise = keyboardLoader.loadKeyboardFromPath('/resources/keyboards/lao_2008_basic.js'); - const khmer_keyboard_promise = keyboardLoader.loadKeyboardFromPath('/resources/keyboards/khmer_angkor.js'); - const chiral_keyboard_promise = keyboardLoader.loadKeyboardFromPath('/resources/keyboards/test_chirality.js'); + const lao_keyboard_promise = keyboardLoader.loadKeyboardFromPath('/common/test/resources/keyboards/lao_2008_basic.js'); + const khmer_keyboard_promise = keyboardLoader.loadKeyboardFromPath('/common/test/resources/keyboards/khmer_angkor.js'); + const chiral_keyboard_promise = keyboardLoader.loadKeyboardFromPath('/common/test/resources/keyboards/test_chirality.js'); // Sure, why not `await` out of order? const chiral_keyboard = await chiral_keyboard_promise; diff --git a/web/src/test/auto/dom/web-test-runner.config.mjs b/web/src/test/auto/dom/web-test-runner.config.mjs index 62edfc7dbf..3050837cd5 100644 --- a/web/src/test/auto/dom/web-test-runner.config.mjs +++ b/web/src/test/auto/dom/web-test-runner.config.mjs @@ -1,8 +1,8 @@ // @ts-check import { devices, playwrightLauncher } from '@web/test-runner-playwright'; import { defaultReporter, summaryReporter } from '@web/test-runner'; -import teamcityReporter from '@keymanapp/common-test-resources/test-runner-TC-reporter.mjs'; import { LauncherWrapper, sessionStabilityReporter } from '@keymanapp/common-test-resources/test-runner-stability-reporter.mjs'; +import named from '@keymanapp/common-test-resources/test-runner-rename-browser.mjs' import { importMapsPlugin } from '@web/dev-server-import-maps'; import { dirname, resolve } from 'path'; import { fileURLToPath } from 'url'; @@ -17,7 +17,17 @@ export default { browsers: [ new LauncherWrapper(playwrightLauncher({ product: 'chromium' })), new LauncherWrapper(playwrightLauncher({ product: 'firefox' })), - new LauncherWrapper(playwrightLauncher({ product: 'webkit', concurrency: 1 })) + new LauncherWrapper(playwrightLauncher({ product: 'webkit', concurrency: 1 })), + // named(new LauncherWrapper(playwrightLauncher({ + // product: 'webkit', concurrency: 1, createBrowserContext({ browser }) { + // return browser.newContext({ ...devices['iPhone X'] }); + // } + // })), 'iOS Phone (emulated)'), + // named(new LauncherWrapper(playwrightLauncher({ + // product: 'chromium', createBrowserContext({ browser }) { + // return browser.newContext({ ...devices['Pixel 4'] }) + // } + // })), 'Android Phone (emulated)'), ], concurrency: 10, nodeResolve: true, @@ -51,14 +61,25 @@ export default { files: ['build/test/dom/cases/element-wrappers/**/*.spec.mjs'] }, { - name: 'engine/osk', + name: 'engine/gesture-processor', // Relative, from the containing package.json - files: ['build/test/dom/cases/osk/**/*.spec.mjs'] + // Note: here we use the .spec.html file in the src directory! + files: ['src/test/auto/dom/cases/gesture-processor/**/*.spec.html'] + }, + { + name: 'engine/keyboard', + // Relative, from the containing package.json + files: ['build/test/dom/cases/keyboard/**/*.spec.mjs'] }, { name: 'engine/keyboard-storage', // Relative, from the containing package.json files: ['build/test/dom/cases/keyboard-storage/**/*.spec.mjs'] + }, + { + name: 'engine/osk', + // Relative, from the containing package.json + files: ['build/test/dom/cases/osk/**/*.spec.mjs'] } ], middleware: [ @@ -72,7 +93,7 @@ export default { } ], plugins: [ - esbuildPlugin({ts: true}), + esbuildPlugin({ts: true, target: 'auto'}), importMapsPlugin({ inject: { importMap: { @@ -88,8 +109,12 @@ export default { reporters: [ summaryReporter({}), /* local-dev mocha-style */ sessionStabilityReporter({}), - defaultReporter() + defaultReporter({}) ], + /* + Un-comment the next two lines for easy interactive debugging; it'll launch the + test page in your preferred browser. + */ // open: true, // manual: true, rootDir: KEYMAN_ROOT diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/asyncClosureDispatchQueue.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/asyncClosureDispatchQueue.spec.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/asyncClosureDispatchQueue.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/asyncClosureDispatchQueue.spec.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gesturePath.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.spec.ts similarity index 99% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gesturePath.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.spec.ts index 111e00ee93..1159d969fa 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gesturePath.spec.ts +++ b/web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.spec.ts @@ -6,14 +6,14 @@ import fs from 'fs'; import { GestureDebugPath } from '@keymanapp/gesture-recognizer'; import { timedPromise } from '@keymanapp/web-utils'; -import { TouchpathTurtle } from '#tools'; +import { TouchpathTurtle } from '#gesture-tools'; // Ensures that the resources are resolved relative to this script's source, not // to the cwd when the test runner was launched or to its built version. const scriptFolder = path.dirname(url.fileURLToPath(import.meta.url)) .replace("build/test/auto", "src/test/auto") // Mac/Linux .replace("build\\test\\auto", "src\\test\\auto"); // Windows -const SEGMENT_TEST_JSON_FOLDER = path.resolve(`${scriptFolder}/../../resources/json/segmentation`); +const SEGMENT_TEST_JSON_FOLDER = path.resolve(`${scriptFolder}/../../../../resources/json/segmentation`); describe("GesturePath", function() { // Note: if part of the suite below fails, it'll probably cascade into failures for some of the diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestureSource.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestureSource.spec.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestureSource.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestureSource.spec.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureMatcher.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureMatcher.spec.ts similarity index 99% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureMatcher.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureMatcher.spec.ts index aea79a15a9..ede257ca75 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureMatcher.spec.ts +++ b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureMatcher.spec.ts @@ -3,13 +3,13 @@ import sinon from 'sinon'; import * as PromiseStatusModule from 'promise-status-async'; const PromiseStatuses = PromiseStatusModule.PromiseStatuses; -import { assertingPromiseStatus as promiseStatus } from '../../../resources/assertingPromiseStatus.js'; +import { assertingPromiseStatus as promiseStatus } from '../../../../../resources/assertingPromiseStatus.js'; import { InputSample, gestures, GestureDebugPath } from '@keymanapp/gesture-recognizer'; -import { TouchpathTurtle } from '#tools'; +import { TouchpathTurtle } from '#gesture-tools'; -import { simulateMultiSourceMatcherInput } from "../../../resources/simulateMultiSourceInput.js"; +import { simulateMultiSourceMatcherInput } from "../../../../../resources/simulateMultiSourceInput.js"; import { FlickEndModel, diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureModelDefs.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureModelDefs.spec.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureModelDefs.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureModelDefs.spec.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureSequence.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureSequence.spec.ts similarity index 99% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureSequence.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureSequence.spec.ts index 346e146809..fe3837e42f 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/gestureSequence.spec.ts +++ b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureSequence.spec.ts @@ -2,7 +2,7 @@ import { assert } from 'chai' import sinon from 'sinon'; import * as PromiseStatusModule from 'promise-status-async'; -import { assertingPromiseStatus as promiseStatus } from '../../../resources/assertingPromiseStatus.js'; +import { assertingPromiseStatus as promiseStatus } from '../../../../../resources/assertingPromiseStatus.js'; import { GestureModelDefs, buildGestureMatchInspector, gestures } from '@keymanapp/gesture-recognizer'; const { matchers } = gestures; @@ -16,10 +16,10 @@ type MatcherSelection = gestures.matchers.MatcherSelection; const getGestureModelSet = gestures.specs.getGestureModelSet; const modelSetForAction = gestures.matchers.modelSetForAction; -import { HeadlessInputEngine, TouchpathTurtle } from '#tools'; +import { HeadlessInputEngine, TouchpathTurtle } from '#gesture-tools'; import { ManagedPromise, timedPromise } from '@keymanapp/web-utils'; -import { assertGestureSequence, SequenceAssertion } from "../../../resources/sequenceAssertions.js"; +import { assertGestureSequence, SequenceAssertion } from "../../../../../resources/sequenceAssertions.js"; import { LongpressModel, diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/isolatedGestureSpecs.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/isolatedGestureSpecs.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/isolatedGestureSpecs.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/isolatedGestureSpecs.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/isolatedPathSpecs.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/isolatedPathSpecs.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/isolatedPathSpecs.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/isolatedPathSpecs.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/matcherSelector.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/matcherSelector.spec.ts similarity index 99% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/matcherSelector.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/matcherSelector.spec.ts index 8fdfd936a6..583e0c6031 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/matcherSelector.spec.ts +++ b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/matcherSelector.spec.ts @@ -3,14 +3,14 @@ import sinon from 'sinon'; import * as PromiseStatusModule from 'promise-status-async'; const PromiseStatuses = PromiseStatusModule.PromiseStatuses; -import { assertingPromiseStatus as promiseStatus } from '../../../resources/assertingPromiseStatus.js'; +import { assertingPromiseStatus as promiseStatus } from '../../../../../resources/assertingPromiseStatus.js'; -import { simulateMultiSourceMatcherInput, simulateSelectorInput } from "../../../resources/simulateMultiSourceInput.js"; +import { simulateMultiSourceMatcherInput, simulateSelectorInput } from "../../../../../resources/simulateMultiSourceInput.js"; import { timedPromise } from '@keymanapp/web-utils'; import { gestures } from '@keymanapp/gesture-recognizer'; -import { TouchpathTurtle } from '#tools'; +import { TouchpathTurtle } from '#gesture-tools'; type MatcherSelection = gestures.matchers.MatcherSelection; type GestureModel = gestures.specs.GestureModel; diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/pathMatcher.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/pathMatcher.spec.ts similarity index 99% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/pathMatcher.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/pathMatcher.spec.ts index 4678efed71..ac2250f5f9 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/pathMatcher.spec.ts +++ b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/pathMatcher.spec.ts @@ -3,7 +3,7 @@ import sinon from 'sinon'; import * as PromiseStatusModule from 'promise-status-async'; const PromiseStatuses = PromiseStatusModule.PromiseStatuses; -import { assertingPromiseStatus as promiseStatus } from '../../../resources/assertingPromiseStatus.js'; +import { assertingPromiseStatus as promiseStatus } from '../../../../../resources/assertingPromiseStatus.js'; import { InputSample, GestureSource, gestures, CumulativePathStats } from '@keymanapp/gesture-recognizer'; import { timedPromise } from '@keymanapp/web-utils'; diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/touchpointCoordinator.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/touchpointCoordinator.spec.ts similarity index 99% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/touchpointCoordinator.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/touchpointCoordinator.spec.ts index 784d7e30b6..44f0bce4f7 100644 --- a/web/src/engine/osk/gesture-processor/src/test/auto/headless/gestures/touchpointCoordinator.spec.ts +++ b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/touchpointCoordinator.spec.ts @@ -2,7 +2,7 @@ import { assert } from 'chai' import sinon from 'sinon'; import * as PromiseStatusModule from 'promise-status-async'; -import { assertingPromiseStatus as promiseStatus } from '../../../resources/assertingPromiseStatus.js'; +import { assertingPromiseStatus as promiseStatus } from '../../../../../resources/assertingPromiseStatus.js'; import { GestureModelDefs, GestureSource, gestures, TouchpointCoordinator } from '@keymanapp/gesture-recognizer'; const { matchers } = gestures; @@ -11,10 +11,10 @@ const { matchers } = gestures; const { GestureSequence } = matchers; type GestureSequence = gestures.matchers.GestureSequence; -import { HeadlessInputEngine, TouchpathTurtle } from '#tools'; +import { HeadlessInputEngine, TouchpathTurtle } from '#gesture-tools'; import { ManagedPromise, timedPromise } from '@keymanapp/web-utils'; -import { assertGestureSequence, SequenceAssertion } from "../../../resources/sequenceAssertions.js"; +import { assertGestureSequence, SequenceAssertion } from "../../../../../resources/sequenceAssertions.js"; import { LongpressModel, diff --git a/web/src/engine/osk/gesture-processor/src/test/auto/headless/pathStats.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/pathStats.spec.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/auto/headless/pathStats.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/pathStats.spec.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/@types/promiseStatus.d.ts b/web/src/test/auto/resources/@types/promiseStatus.d.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/@types/promiseStatus.d.ts rename to web/src/test/auto/resources/@types/promiseStatus.d.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/assertSegmentSimilarity.js b/web/src/test/auto/resources/assertSegmentSimilarity.js similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/assertSegmentSimilarity.js rename to web/src/test/auto/resources/assertSegmentSimilarity.js diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/assertingPromiseStatus.ts b/web/src/test/auto/resources/assertingPromiseStatus.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/assertingPromiseStatus.ts rename to web/src/test/auto/resources/assertingPromiseStatus.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/canaryRecording.json b/web/src/test/auto/resources/json/canaryRecording.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/canaryRecording.json rename to web/src/test/auto/resources/json/canaryRecording.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/basicMultitouch.json b/web/src/test/auto/resources/json/receiver/basicMultitouch.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/basicMultitouch.json rename to web/src/test/auto/resources/json/receiver/basicMultitouch.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/desktopRoamAndReturn.json b/web/src/test/auto/resources/json/receiver/desktopRoamAndReturn.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/desktopRoamAndReturn.json rename to web/src/test/auto/resources/json/receiver/desktopRoamAndReturn.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/embeddedBorderCancel.json b/web/src/test/auto/resources/json/receiver/embeddedBorderCancel.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/embeddedBorderCancel.json rename to web/src/test/auto/resources/json/receiver/embeddedBorderCancel.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/hardBorderCancel.json b/web/src/test/auto/resources/json/receiver/hardBorderCancel.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/hardBorderCancel.json rename to web/src/test/auto/resources/json/receiver/hardBorderCancel.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/mobileProximityApproach.json b/web/src/test/auto/resources/json/receiver/mobileProximityApproach.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/mobileProximityApproach.json rename to web/src/test/auto/resources/json/receiver/mobileProximityApproach.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/mobileSafeZoneCancel.json b/web/src/test/auto/resources/json/receiver/mobileSafeZoneCancel.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/mobileSafeZoneCancel.json rename to web/src/test/auto/resources/json/receiver/mobileSafeZoneCancel.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupLongRoamingEnd.json b/web/src/test/auto/resources/json/receiver/popupLongRoamingEnd.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupLongRoamingEnd.json rename to web/src/test/auto/resources/json/receiver/popupLongRoamingEnd.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupSafePersistence.json b/web/src/test/auto/resources/json/receiver/popupSafePersistence.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupSafePersistence.json rename to web/src/test/auto/resources/json/receiver/popupSafePersistence.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupShimCancel.json b/web/src/test/auto/resources/json/receiver/popupShimCancel.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/receiver/popupShimCancel.json rename to web/src/test/auto/resources/json/receiver/popupShimCancel.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/flick_ne_se.json b/web/src/test/auto/resources/json/segmentation/flick_ne_se.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/flick_ne_se.json rename to web/src/test/auto/resources/json/segmentation/flick_ne_se.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/longpress_to_ne.json b/web/src/test/auto/resources/json/segmentation/longpress_to_ne.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/longpress_to_ne.json rename to web/src/test/auto/resources/json/segmentation/longpress_to_ne.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/nonstationary_hold.json b/web/src/test/auto/resources/json/segmentation/nonstationary_hold.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/nonstationary_hold.json rename to web/src/test/auto/resources/json/segmentation/nonstationary_hold.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/quick_small_square.json b/web/src/test/auto/resources/json/segmentation/quick_small_square.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/quick_small_square.json rename to web/src/test/auto/resources/json/segmentation/quick_small_square.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/simple_ne_move.json b/web/src/test/auto/resources/json/segmentation/simple_ne_move.json similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/json/segmentation/simple_ne_move.json rename to web/src/test/auto/resources/json/segmentation/simple_ne_move.json diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/sequenceAssertions.ts b/web/src/test/auto/resources/sequenceAssertions.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/sequenceAssertions.ts rename to web/src/test/auto/resources/sequenceAssertions.ts diff --git a/web/src/engine/osk/gesture-processor/src/test/resources/simulateMultiSourceInput.ts b/web/src/test/auto/resources/simulateMultiSourceInput.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/test/resources/simulateMultiSourceInput.ts rename to web/src/test/auto/resources/simulateMultiSourceInput.ts diff --git a/web/src/test/auto/tsconfig.json b/web/src/test/auto/tsconfig.json index f61a4f23a8..f88f147539 100644 --- a/web/src/test/auto/tsconfig.json +++ b/web/src/test/auto/tsconfig.json @@ -11,6 +11,7 @@ "include": [ "dom/**/*.ts", "headless/**/*.ts", - "integrated/**/*.ts" + "integrated/**/*.ts", + "resources/**/*.ts" ] } From 6276b1ecc35c3031940556c74761f471c3a972ed Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 26 Aug 2024 12:35:55 +0700 Subject: [PATCH 78/89] fix(web): fixes build issue due to unreferenced --ci flag inclusion in app/browser build --- web/src/app/browser/build.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/web/src/app/browser/build.sh b/web/src/app/browser/build.sh index 1d757e264a..e068e43888 100755 --- a/web/src/app/browser/build.sh +++ b/web/src/app/browser/build.sh @@ -44,11 +44,7 @@ do_clean() { } compile_and_copy() { - local COMPILE_FLAGS= - if builder_has_option --ci; then - COMPILE_FLAGS=--ci - fi - compile $SUBPROJECT_NAME $COMPILE_FLAGS + compile $SUBPROJECT_NAME BUILD_ROOT="${KEYMAN_ROOT}/web/build/app/browser" SRC_ROOT="${KEYMAN_ROOT}/web/src/app/browser/src" From 663dbede4c089c3a74c30461e62e46dedb2e9f32 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 26 Aug 2024 14:36:20 +0700 Subject: [PATCH 79/89] fix(web): fix build by calling correct script `test.sh` got removed since it did the same as `build.sh test`. --- web/ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ci.sh b/web/ci.sh index a466417275..0dd42fa61e 100755 --- a/web/ci.sh +++ b/web/ci.sh @@ -86,7 +86,7 @@ if builder_start_action test; then # No --reporter option exists yet for the headless modules. "$KEYMAN_ROOT/web/src/engine/keyboard/build.sh" test $OPTIONS - "$KEYMAN_ROOT/web/src/engine/osk/gesture-processor/test.sh" $OPTIONS + "$KEYMAN_ROOT/web/src/engine/osk/gesture-processor/build.sh" test $OPTIONS ./build.sh test $OPTIONS From e788bf50773b7e1476d3bedf00346be796ea015f Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 26 Aug 2024 16:04:17 +0700 Subject: [PATCH 80/89] fix(web): enable tests to run on Ubuntu 24.04 Noble Previously running the tests failed because it couldn't find ICU 70 when running webkit. Ubuntu 24.04 Noble comes with ICU 74. Updating playwright to 1.46 fixes this. --- package-lock.json | 22 ++++++++++++---------- package.json | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 05f215f316..29f478ef07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,7 +60,7 @@ "eslint-plugin-promise": "^6.1.1", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "playwright": "^1.43.1", + "playwright": "^1.46.1", "sinon": "^17.0.1", "source-map-support": "^0.5.21", "tslib": "^2.5.2", @@ -12065,33 +12065,35 @@ } }, "node_modules/playwright": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz", - "integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==", + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", + "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.43.1" + "playwright-core": "1.46.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz", - "integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==", + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", + "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/portfinder": { diff --git a/package.json b/package.json index 23970ceff2..72508afc03 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "eslint-plugin-promise": "^6.1.1", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "playwright": "^1.43.1", + "playwright": "^1.46.1", "sinon": "^17.0.1", "source-map-support": "^0.5.21", "tslib": "^2.5.2", From 77d9c386ae91cc48e811d411e5ab6c21655906c0 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Mon, 26 Aug 2024 14:03:46 -0400 Subject: [PATCH 81/89] auto: increment master version to 18.0.99 --- HISTORY.md | 11 +++++++++++ VERSION.md | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 904e03468a..8f5778c223 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,16 @@ # Keyman Version History +## 18.0.98 alpha 2024-08-26 + +* change(ios): defer registration of fonts past initialization (#12190) +* refactor(ios): optimize font registration (#12210) +* test(mac): add unit tests to validate first calls to compliance check (#11724) +* fix(mac): limit short bundle version string to x.y.z format in info.plist (#12233) +* chore(developer): extend timeouts for lm compiler tests to 5 secs (#12273) +* fix(developer): find last matching key in LDML key bag when building KVK (#12278) +* chore(android): Cleanup stray debug statements in console (#12287) +* fix(developer): ensure call() detects invalid store in kmcmplib compiler (#12263) + ## 18.0.97 alpha 2024-08-24 * refactor(linux): cleanup API of kvk2ldml.py (#12276) diff --git a/VERSION.md b/VERSION.md index 48b8081cd1..6ad090d9d6 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.98 \ No newline at end of file +18.0.99 \ No newline at end of file From 0d194faa71840a4cea57ec6863dbdeac0a4632dd Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 27 Aug 2024 09:37:43 +0700 Subject: [PATCH 82/89] refactor(web): fix tests --- web/src/engine/osk/gesture-processor/build.sh | 2 +- ...spatchQueue.spec.ts => asyncClosureDispatchQueue.tests.ts} | 0 .../{gesturePath.spec.ts => gesturePath.tests.ts} | 4 ++-- .../{gestureSource.spec.ts => gestureSource.tests.ts} | 0 .../{gestureMatcher.spec.ts => gestureMatcher.tests.ts} | 0 .../{gestureModelDefs.spec.ts => gestureModelDefs.tests.ts} | 0 .../{gestureSequence.spec.ts => gestureSequence.tests.ts} | 0 .../{matcherSelector.spec.ts => matcherSelector.tests.ts} | 0 .../gestures/{pathMatcher.spec.ts => pathMatcher.tests.ts} | 0 ...ointCoordinator.spec.ts => touchpointCoordinator.tests.ts} | 0 .../{pathStats.spec.ts => pathStats.tests.ts} | 0 11 files changed, 3 insertions(+), 3 deletions(-) rename web/src/test/auto/headless/engine/osk/gesture-processor/{asyncClosureDispatchQueue.spec.ts => asyncClosureDispatchQueue.tests.ts} (100%) rename web/src/test/auto/headless/engine/osk/gesture-processor/{gesturePath.spec.ts => gesturePath.tests.ts} (98%) rename web/src/test/auto/headless/engine/osk/gesture-processor/{gestureSource.spec.ts => gestureSource.tests.ts} (100%) rename web/src/test/auto/headless/engine/osk/gesture-processor/gestures/{gestureMatcher.spec.ts => gestureMatcher.tests.ts} (100%) rename web/src/test/auto/headless/engine/osk/gesture-processor/gestures/{gestureModelDefs.spec.ts => gestureModelDefs.tests.ts} (100%) rename web/src/test/auto/headless/engine/osk/gesture-processor/gestures/{gestureSequence.spec.ts => gestureSequence.tests.ts} (100%) rename web/src/test/auto/headless/engine/osk/gesture-processor/gestures/{matcherSelector.spec.ts => matcherSelector.tests.ts} (100%) rename web/src/test/auto/headless/engine/osk/gesture-processor/gestures/{pathMatcher.spec.ts => pathMatcher.tests.ts} (100%) rename web/src/test/auto/headless/engine/osk/gesture-processor/gestures/{touchpointCoordinator.spec.ts => touchpointCoordinator.tests.ts} (100%) rename web/src/test/auto/headless/engine/osk/gesture-processor/{pathStats.spec.ts => pathStats.tests.ts} (100%) diff --git a/web/src/engine/osk/gesture-processor/build.sh b/web/src/engine/osk/gesture-processor/build.sh index f3bafab5ed..b2ea635d8a 100755 --- a/web/src/engine/osk/gesture-processor/build.sh +++ b/web/src/engine/osk/gesture-processor/build.sh @@ -61,5 +61,5 @@ builder_run_action configure do_configure builder_run_action clean rm -rf build/ intermediate/ builder_run_action build:module do_build_module builder_run_action build:tools src/tools/build.sh build -builder_run_action test:module test-headless "${SUBPROJECT_NAME}" +builder_run_action test:module test-headless-typescript "${SUBPROJECT_NAME}" builder_run_action test:tools do_test_tools diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/asyncClosureDispatchQueue.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/asyncClosureDispatchQueue.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/asyncClosureDispatchQueue.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/asyncClosureDispatchQueue.tests.ts diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.tests.ts similarity index 98% rename from web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.tests.ts index 1159d969fa..0a90b0c628 100644 --- a/web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.spec.ts +++ b/web/src/test/auto/headless/engine/osk/gesture-processor/gesturePath.tests.ts @@ -11,8 +11,8 @@ import { TouchpathTurtle } from '#gesture-tools'; // Ensures that the resources are resolved relative to this script's source, not // to the cwd when the test runner was launched or to its built version. const scriptFolder = path.dirname(url.fileURLToPath(import.meta.url)) - .replace("build/test/auto", "src/test/auto") // Mac/Linux - .replace("build\\test\\auto", "src\\test\\auto"); // Windows + .replace("build/test", "src/test/auto") // Mac/Linux + .replace("build\\test", "src\\test\\auto"); // Windows const SEGMENT_TEST_JSON_FOLDER = path.resolve(`${scriptFolder}/../../../../resources/json/segmentation`); describe("GesturePath", function() { diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/gestureSource.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestureSource.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/gestureSource.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestureSource.tests.ts diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureMatcher.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureMatcher.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureMatcher.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureMatcher.tests.ts diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureModelDefs.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureModelDefs.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureModelDefs.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureModelDefs.tests.ts diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureSequence.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureSequence.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureSequence.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/gestureSequence.tests.ts diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/matcherSelector.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/matcherSelector.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/gestures/matcherSelector.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/matcherSelector.tests.ts diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/pathMatcher.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/pathMatcher.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/gestures/pathMatcher.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/pathMatcher.tests.ts diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/touchpointCoordinator.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/gestures/touchpointCoordinator.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/gestures/touchpointCoordinator.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/gestures/touchpointCoordinator.tests.ts diff --git a/web/src/test/auto/headless/engine/osk/gesture-processor/pathStats.spec.ts b/web/src/test/auto/headless/engine/osk/gesture-processor/pathStats.tests.ts similarity index 100% rename from web/src/test/auto/headless/engine/osk/gesture-processor/pathStats.spec.ts rename to web/src/test/auto/headless/engine/osk/gesture-processor/pathStats.tests.ts From 8c4c4855785637581b78ddced75e7c29a1652146 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 27 Aug 2024 14:02:05 +0700 Subject: [PATCH 83/89] fix(web): fixes wordbreaker test import path --- common/models/wordbreakers/test/test-search-property.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/models/wordbreakers/test/test-search-property.js b/common/models/wordbreakers/test/test-search-property.js index 85996c7286..9f33e4cc0c 100644 --- a/common/models/wordbreakers/test/test-search-property.js +++ b/common/models/wordbreakers/test/test-search-property.js @@ -3,8 +3,8 @@ */ import { assert } from 'chai'; -import { searchForProperty } from '../build/obj/default/searchForProperty.js'; -import { propertyMap } from '../build/obj/default/data.inc.js'; +import { searchForProperty } from '../build/main/obj/default/searchForProperty.js'; +import { propertyMap } from '../build/main/obj/default/data.inc.js'; describe('searchForProperty', () => { it('correctly finds character classes for standard ASCII characters', () => { From 9cf996a1841ee2a3c608f57b7db6f1fda89a94bf Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 27 Aug 2024 14:02:05 +0700 Subject: [PATCH 84/89] fix(web): fixes wordbreaker test import path --- common/models/wordbreakers/test/test-search-property.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/models/wordbreakers/test/test-search-property.js b/common/models/wordbreakers/test/test-search-property.js index 85996c7286..9f33e4cc0c 100644 --- a/common/models/wordbreakers/test/test-search-property.js +++ b/common/models/wordbreakers/test/test-search-property.js @@ -3,8 +3,8 @@ */ import { assert } from 'chai'; -import { searchForProperty } from '../build/obj/default/searchForProperty.js'; -import { propertyMap } from '../build/obj/default/data.inc.js'; +import { searchForProperty } from '../build/main/obj/default/searchForProperty.js'; +import { propertyMap } from '../build/main/obj/default/data.inc.js'; describe('searchForProperty', () => { it('correctly finds character classes for standard ASCII characters', () => { From 0daf91021c90f5b490261e6db83b9defeff8d9e8 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Tue, 27 Aug 2024 14:03:04 -0400 Subject: [PATCH 85/89] auto: increment master version to 18.0.100 --- HISTORY.md | 7 +++++++ VERSION.md | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 8f5778c223..0972d98324 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,12 @@ # Keyman Version History +## 18.0.99 alpha 2024-08-27 + +* feat(web): import the generator for the pred-text wordbreaker's Unicode-property data-table (#10690) +* feat(web): optimize the wordbreaker data table for filesize and ease of first-load parsing (#10692) +* (#12297) +* (#12115) + ## 18.0.98 alpha 2024-08-26 * change(ios): defer registration of fonts past initialization (#12190) diff --git a/VERSION.md b/VERSION.md index 6ad090d9d6..59ec57bac2 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.99 \ No newline at end of file +18.0.100 \ No newline at end of file From 0b1f85bd77282c345fe1890125d699ccb4cddc96 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 28 Aug 2024 06:56:21 +0700 Subject: [PATCH 86/89] chore(android,ios): Update FirstVoices keyboards to 12.15 * Keyboard version updates corresponding to fv_all.kmp version 12.15 --- oem/firstvoices/keyboards.csv | 71 ++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/oem/firstvoices/keyboards.csv b/oem/firstvoices/keyboards.csv index cbede23edc..22812ec14d 100644 --- a/oem/firstvoices/keyboards.csv +++ b/oem/firstvoices/keyboards.csv @@ -7,57 +7,58 @@ fv,fv_uummarmiutun,Uummarmiutun,Arctic,fv_uummarmiutun_kmw-9.0.js,9.1.1,ikt-Latn fv,fv_eastern_canadian_inuktitut,ᐃᓄᒃᑎᑐᑦ (Eastern Canadian Inuktitut),Arctic,fv_eastern_canadian_inuktitut_kmw-9.0.js,9.2.1,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics) fv,fv_migmaq,Mi'gmawi'simg / Mi'kmawi'simk,Atlantic,fv_migmaq_kmw-9.0.js,9.1.2,mic-Latn,Mi'kmaq (Latin) fv,fv_skicinuwatuwewakon,Skicinuwatuwewakon,Atlantic,fv_skicinuwatuwewakon_kmw-9.0.js,9.1.1,pqm-Latn,Malecite-Passamaquoddy (Latin) -fv,fv_uwikala,'Uwik̓ala,BC Coast,fv_uwikala_kmw-9.0.js,9.3,hei,Heiltsuk +fv,fv_uwikala,'Uwik̓ala,BC Coast,fv_uwikala_kmw-9.0.js,9.4,hei,Heiltsuk fv,fv_dexwlesucid,Dəxʷləšucid,BC Coast,fv_dexwlesucid_kmw-9.0.js,9.2.1,lut-Latn,Lushootseed (Latin) fv,fv_diitiidatx,Diidiitidq,BC Coast,fv_diitiidatx_kmw-9.0.js,9.2.1,nuk-Latn,Nuu-chah-nulth (Latin) -fv,fv_gitsenimx,Gitsenimx̱,BC Coast,fv_gitsenimx_kmw-9.0.js,10.1.1,git,Gitxsan (Latin) +fv,fv_gitsenimx,Gitsenimx̱,BC Coast,fv_gitsenimx_kmw-9.0.js,10.1.2,git,Gitxsan (Latin) fv,fv_hailzaqvla,Haiɫzaqvla,BC Coast,fv_hailzaqvla_kmw-9.0.js,9.5.2,hei,Heiltsuk (Latin) -fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1,has-Latn,Haisla (Latin) +fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1.2,has-Latn,Haisla (Latin) fv,fv_halqemeylem,Halq'eméylem,BC Coast,fv_halqemeylem_kmw-9.0.js,9.2,hur-Latn,Halkomelem (Latin) fv,fv_henqeminem,Hǝn̓q̓ǝmin̓ǝm,BC Coast,fv_henqeminem_kmw-9.0.js,10.1,hur-Latn,Halkomelem (Latin) fv,fv_klahoose,Homalco-Klahoose-Sliammon,BC Coast,fv_klahoose_kmw-9.0.js,10.1,coo,Comox fv,fv_hulquminum,Hul’q’umi’num’,BC Coast,fv_hulquminum_kmw-9.0.js,9.1,hur-Latn,Halkomelem (Latin) fv,fv_hulquminum_combine,Hul̓q̓umin̓um̓,BC Coast,fv_hulquminum_combine_kmw-9.0.js,2.0.1,hur-Latn,Halkomelem (Latin) -fv,fv_kwakwala_liqwala,Kʷak̓ʷala,BC Coast,fv_kwakwala_liqwala_kmw-9.0.js,9.2.5,kwk-Latn,Kwakiutl (Latin) -fv,fv_kwakwala,Kwak̕wala,BC Coast,fv_kwakwala_kmw-9.0.js,9.1.2,kwk-Latn,Kwakiutl (Latin) -fv,fv_nexwslayemucen,Nəxʷsƛ̓ay̓əmúcən,BC Coast,fv_nexwslayemucen_kmw-9.0.js,9.2.1,clm-Latn,Clallam (Latin) -fv,fv_nisgaa,Nisg̱a'a,BC Coast,fv_nisgaa_kmw-9.0.js,9.1.2,ncg-Latn,Nisga'a (Latin) -fv,fv_nuucaanul,Nuučaan̓uł,BC Coast,fv_nuucaanul_kmw-9.0.js,9.1.4,nuk-Latn,Nuu-chah-nulth (Latin) -fv,fv_nuxalk,Nuxalk,BC Coast,fv_nuxalk_kmw-9.0.js,10.0,blc-Latn,Bella Coola (Latin) +fv,fv_kwakwala_liqwala,Kʷak̓ʷala,BC Coast,fv_kwakwala_liqwala_kmw-9.0.js,9.3,kwk-Latn,Kwakiutl (Latin) +fv,fv_kwakwala,Kwak̕wala,BC Coast,fv_kwakwala_kmw-9.0.js,9.2,kwk-Latn,Kwakiutl (Latin) +fv,fv_lekwungen,Lək̓ʷəŋən,BC Coast,fv_lekwungen-9.0.js,1.0,str,Lekwungen +fv,fv_nexwslayemucen,Nəxʷsƛ̓ay̓əmúcən,BC Coast,fv_nexwslayemucen_kmw-9.0.js,10.0,clm-Latn,Clallam (Latin) +fv,fv_nisgaa,Nisg̱a'a,BC Coast,fv_nisgaa_kmw-9.0.js,9.2,ncg-Latn,Nisga'a (Latin) +fv,fv_nuucaanul,Nuučaan̓uł,BC Coast,fv_nuucaanul_kmw-9.0.js,9.2,nuk-Latn,Nuu-chah-nulth (Latin) +fv,fv_nuxalk,Nuxalk,BC Coast,fv_nuxalk_kmw-9.0.js,10.0.1,blc-Latn,Bella Coola (Latin) fv,fv_sencoten,SENĆOŦEN,BC Coast,fv_sencoten_kmw-9.0.js,9.2.2,str,Straits Salish -fv,fv_sguuxs,Sgüüx̱s,BC Coast,fv_sguuxs.js,1.0.1,tsi,Tsimshian +fv,fv_sguuxs,Sgüüx̱s,BC Coast,fv_sguuxs.js,1.1,tsi,Tsimshian fv,fv_shashishalhem,Shashishalhem,BC Coast,fv_shashishalhem_kmw-9.0.js,9.2,sec-Latn,Sechelt (Latin) -fv,fv_skwxwumesh_snichim,Sḵwx̱wúmesh sníchim,BC Coast,fv_skwxwumesh_snichim_kmw-9.0.js,9.3,squ-Latn,Squamish (Latin) +fv,fv_skwxwumesh_snichim,Sḵwx̱wúmesh sníchim,BC Coast,fv_skwxwumesh_snichim_kmw-9.0.js,10.0,squ-Latn,Squamish (Latin) fv,fv_smalgyax,Sm'algya̱x,BC Coast,fv_smalgyax_kmw-9.0.js,9.2,tsi-Latn,Tsimshian (Latin) -fv,fv_xaislakala,X̄a'ʼislak̓ala,BC Coast,fv_xaislakala_kmw-9.0.js,9.1.1,has-Latn,Haisla (Latin) -fv,fv_hlgaagilda_xaayda_kil,X̱aayda-X̱aad Kil,BC Coast,fv_hlgaagilda_xaayda_kil_kmw-9.0.js,9.3,hax,Southern Haida -fv,fv_dakelh,Dakelh,BC Interior,fv_dakelh_kmw-9.0.js,9.2,caf-Latn,Southern Carrier (Latin) +fv,fv_xaislakala,X̄a'ʼislak̓ala,BC Coast,fv_xaislakala_kmw-9.0.js,10.0,has-Latn,Haisla (Latin) +fv,fv_hlgaagilda_xaayda_kil,X̱aayda-X̱aad Kil,BC Coast,fv_hlgaagilda_xaayda_kil_kmw-9.0.js,9.4,hax,Southern Haida +fv,fv_dakelh,Dakelh,BC Interior,fv_dakelh_kmw-9.0.js,9.2.1,caf-Latn,Southern Carrier (Latin) fv,fv_ktunaxa,Ktunaxa,BC Interior,fv_ktunaxa_kmw-9.0.js,10.0,kut-Latn,Kutenai (Latin) -fv,fv_kwadacha_tsekene,Kwadacha Tsek’ene,BC Interior,fv_kwadacha_tsekene_kmw-9.0.js,1.0,sek-Latn,Sekani +fv,fv_kwadacha_tsekene,Kwadacha Tsek’ene,BC Interior,fv_kwadacha_tsekene_kmw-9.0.js,1.1,sek-Latn,Sekani fv,fv_natwits,Nedut’en-Witsuwit'en,BC Interior,fv_natwits_kmw-9.0.js,9.1.3,caf-Latn,Southern Carrier (Latin) -fv,fv_nlekepmxcin,Nłeʔkepmxcin,BC Interior,fv_nlekepmxcin_kmw-9.0.js,9.4,thp-Latn,Thompson (Latin) -fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.0,thp-Latn,Thompson (Latin) -fv,fv_nlakapamuxcheen,Nlakapamuxcheen,BC Interior,fv_nlakapamuxcheen_kmw-9.0.js,1.0.2,thp,Thompson -fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,9.3,oka,Okanagan +fv,fv_nlekepmxcin,Nłeʔkepmxcin,BC Interior,fv_nlekepmxcin_kmw-9.0.js,9.5.1,thp-Latn,Thompson (Latin) +fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.1.1,thp-Latn,Thompson (Latin) +fv,fv_nlakapamuxcheen,Nlakapamuxcheen,BC Interior,fv_nlakapamuxcheen_kmw-9.0.js,1.1,thp,Thompson +fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,10.0,oka,Okanagan fv,fv_secwepemctsin,Secwepemctsín,BC Interior,fv_secwepemctsin_kmw-9.0.js,9.2,shs-Latn,Shuswap (Latin) fv,fv_stlatlimxec,Sƛ̓aƛ̓imxəc,BC Interior,fv_stlatlimxec_kmw-9.0.js,9.3,lil-Latn,Lillooet (Latin) -fv,fv_statimcets,St̓át̓imcets,BC Interior,fv_statimcets_kmw-9.0.js,9.1.4,lil-Latn,Lillooet (Latin) -fv,fv_taltan,Tāłtān,BC Interior,fv_taltan_kmw-9.0.js,9.1.5,tht-Latn,Tahltan (Latin) -fv,fv_tsekehne,Tsek'ehne,BC Interior,fv_tsekehne_kmw-9.0.js,9.1.2,sek-Latn,Sekani (Latin) -fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.1.3,clc-Latn,Chilcotin (Latin) -fv,fv_southern_carrier,ᑐᑊᘁᗕᑋᗸ (Southern Carrier),BC Interior,fv_southern_carrier_kmw-9.0.js,10.0.1,caf-Cans,Southern Carrier (Unified Canadian Aboriginal Syllabics) +fv,fv_statimcets,St̓át̓imcets,BC Interior,fv_statimcets_kmw-9.0.js,9.2,lil-Latn,Lillooet (Latin) +fv,fv_taltan,Tāłtān,BC Interior,fv_taltan_kmw-9.0.js,9.2,tht-Latn,Tahltan (Latin) +fv,fv_tsekehne,Tsek'ehne,BC Interior,fv_tsekehne_kmw-9.0.js,9.2,sek-Latn,Sekani (Latin) +fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.2,clc-Latn,Chilcotin (Latin) +fv,fv_southern_carrier,ᑐᑊᘁᗕᑋᗸ (Southern Carrier),BC Interior,fv_southern_carrier_kmw-9.0.js,10.1,caf-Cans,Southern Carrier (Unified Canadian Aboriginal Syllabics) fv,fv_anicinapemi8in,Anicinapemi8in/Anishinàbemiwin,Eastern Subarctic,fv_anicinapemi8in_kmw-9.0.js,9.1.1,alq-Latn,Algonquin (Latin) fv,fv_atikamekw,Atikamekw,Eastern Subarctic,fv_atikamekw_kmw-9.0.js,9.1.1,atj-Latn,Atikamekw (Latin) fv,fv_ilnu_innu_aimun,Ilnu-Innu Aimun,Eastern Subarctic,fv_ilnu_innu_aimun_kmw-9.0.js,9.1.1,moe-Latn,Montagnais (Latin) fv,fv_swampy_cree,ᐃᓂᓂᒧᐎᐣ (Swampy Cree),Eastern Subarctic,fv_swampy_cree_kmw-9.0.js,9.2.1,csw-Cans,Swampy Cree (Unified Canadian Aboriginal Syllabics) fv,fv_moose_cree,ᐃᓕᓖᒧᐎᓐ (Moose Cree),Eastern Subarctic,fv_moose_cree_kmw-9.0.js,9.2.1,crm-Cans,Moose Cree (Unified Canadian Aboriginal Syllabics) fv,fv_northern_east_cree,ᐄᔨᔫ-ᐄᓅ ᐊᔨᒨᓐ (Northern East Cree),Eastern Subarctic,fv_northern_east_cree_kmw-9.0.js,9.2.1,crl-Cans,Northern East Cree (Unified Canadian Aboriginal Syllabics) -fv,fv_severn_ojibwa,ᐊᓂᔑᓂᓂᒧᐎᐣ (Severn Ojibwa),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,10.0.1,ojs-Cans,Severn Ojibwa (Unified Canadian Aboriginal Syllabics) -fv,fv_severn_ojibwa_rdot,ᐊᓂᔑᓂᓂᒧᐏᐣ (Severn Ojibwa right w-dot),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,1.0.1,ojs,Oji-Cree -fv,fv_ojibwa,ᐊᓂᔑᓇᐯᒧᐎᓐ (a-finals),Eastern Subarctic,fv_ojibwa_kmw-9.0.js,10.0.1,ojb-Cans,Northwestern Ojibwa (Unified Canadian Aboriginal Syllabics) -fv,fv_ojibwa_rdot,ᐁᓂᔑᓇᐯᒧᐏᓐ (a-finals right w-dot),Eastern Subarctic,fv_ojibwa_rdot_kmw-9.0.js,1.0.1,oj,Ojibwa -fv,fv_ojibwa_ifinal,ᐊᓂᔑᓇᐯᒧᐎᣙ (i-finals),Eastern Subarctic,fv_ojibwa_ifinal_kmw-9.0.js,1.0,oj,Ojibwa -fv,fv_ojibwa_ifinal_rdot,ᐊᓂᔑᓇᐯᒧᐏᣙ (i-finals right w-dot),Eastern Subarctic,fv_ojibwa_ifinal_rdot_kmw-9.0.js,1.0,oj,Ojibwa +fv,fv_severn_ojibwa,ᐊᓂᔑᓂᓂᒧᐎᐣ (Severn Ojibwa),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,10.1,ojs-Cans,Severn Ojibwa (Unified Canadian Aboriginal Syllabics) +fv,fv_severn_ojibwa_rdot,ᐊᓂᔑᓂᓂᒧᐏᐣ (Severn Ojibwa right w-dot),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,1.1,ojs,Oji-Cree +fv,fv_ojibwa,ᐊᓂᔑᓇᐯᒧᐎᓐ (a-finals),Eastern Subarctic,fv_ojibwa_kmw-9.0.js,10.1,ojb-Cans,Northwestern Ojibwa (Unified Canadian Aboriginal Syllabics) +fv,fv_ojibwa_rdot,ᐁᓂᔑᓇᐯᒧᐏᓐ (a-finals right w-dot),Eastern Subarctic,fv_ojibwa_rdot_kmw-9.0.js,1.0.2,oj,Ojibwa +fv,fv_ojibwa_ifinal,ᐊᓂᔑᓇᐯᒧᐎᣙ (i-finals),Eastern Subarctic,fv_ojibwa_ifinal_kmw-9.0.js,1.0.1,oj,Ojibwa +fv,fv_ojibwa_ifinal_rdot,ᐊᓂᔑᓇᐯᒧᐏᣙ (i-finals right w-dot),Eastern Subarctic,fv_ojibwa_ifinal_rdot_kmw-9.0.js,1.0.1,oj,Ojibwa fv,fv_naskapi,ᓇᔅᑲᐱ (Naskapi),Eastern Subarctic,fv_naskapi_kmw-9.0.js,9.3.1,nsk-Cans,Naskapi (Unified Canadian Aboriginal Syllabics) sil,sil_euro_latin,English,European,european2-1.6.js,3.0.2,en,English basic,basic_kbdcan,Français,European,canadian_french-1.0.js,1.1.1,fr-CA,French (Canada) @@ -82,23 +83,23 @@ fv,fv_isga_iabi,Isga Iʔabi,Prairies,fv_isga_iabi_kmw-9.0.js,9.1.1,sto-Latn,Ston fv,fv_lakota,Lak̇ot̄a,Prairies,fv_lakota-9.0.js,9.1.1,lkt-Latn,Lakota (Latin) fv,fv_nakoda,Nakoda,Prairies,fv_nakoda_kmw-9.0.js,9.1.1,asb-Latn,Assiniboine (Latin) fv,fv_tsuutina,Tsúùt'ínà,Prairies,fv_tsuutina_kmw-9.0.js,9.1.1,srs-Latn,Sarsi (Latin) -fv,fv_plains_cree,ᓀᐦᐃᔭᐍᐏᐣ (Plains Cree),Prairies,fv_plains_cree_kmw-9.0.js,11.0.2,crk-Cans,ᓀᐦᐃᔭᐍᐏᐣ (Cree syllabics) +fv,fv_plains_cree,ᓀᐦᐃᔭᐍᐏᐣ (Plains Cree),Prairies,fv_plains_cree_kmw-9.0.js,11.1,crk-Cans,ᓀᐦᐃᔭᐍᐏᐣ (Cree syllabics) fv,fv_dine_bizaad,Diné Bizaad,South West,fv_dine_bizaad_kmw-9.0.js,9.1.1,nv-Latn,Navajo (Latin) fv,fv_dane_zaa_zaage,Dane-Z̲aa Z̲áágéʔ,Western Subarctic,fv_dane_zaa_zaage_kmw-9.0.js,9.4,bea,Beaver fv,fv_dene_dzage,Dene Dzage,Western Subarctic,fv_dene_dzage_kmw-9.0.js,11.0.1,kkz-Latn,Kaska (Latin) -fv,fv_dene_zhatie,Dene Zhatié,Western Subarctic,fv_dene_zhatie_kmw-9.0.js,10.2,den,Dene Zhatıé +fv,fv_dene_zhatie,Dene Zhatié,Western Subarctic,fv_dene_zhatie_kmw-9.0.js,10.2.1,den,Dene Zhatıé fv,fv_denesuline_epsilon,Dënesųłıné,Western Subarctic,fv_denesuline_epsilon_kmw-9.0.js,10.0.1,chp,Chipewyan fv,fv_denesuline,Dɛnɛsųłiné,Western Subarctic,fv_denesuline_kmw-9.0.js,10.0.1,chp,Chipewyan (Latin) fv,fv_gwichin,Gwich'in,Western Subarctic,fv_gwichin_kmw-9.0.js,9.2.1,gwi-Latn,Gwichʼin (Latin) fv,fv_han,Hän,Western Subarctic,fv_han_kmw-9.0.js,9.2,haa-Latn,Han (Latin) -fv,fv_kashogotine_yati,K'áshogot'ı̨nę́ Yatı̨́,Western Subarctic,fv_kashogotine_yati_kmw-9.0.js,10.0,scs,North Slavey -fv,fv_tlingit,Łingít,Western Subarctic,fv_tlingit_kmw-9.0.js,10.0.1,tli,Tlingit (Latin) +fv,fv_kashogotine_yati,K'áshogot'ı̨nę́ Yatı̨́,Western Subarctic,fv_kashogotine_yati_kmw-9.0.js,10.1,scs,North Slavey +fv,fv_tlingit,Łingít,Western Subarctic,fv_tlingit_kmw-9.0.js,10.1,tli,Tlingit (Latin) fv,fv_neeaandeg,Nee'aanděg',Western Subarctic,fv_neeaandeg_kmw-9.0.js,9.1.1,tcb-Latn,Tanacross (Latin) fv,fv_neeaaneegn,Nee'aaneegn',Western Subarctic,fv_neeaaneegn_kmw-9.0.js,9.1,tau-Latn,Upper Tanana (Latin) fv,fv_northern_tutchone,Northern Tutchone,Western Subarctic,fv_northern_tutchone_kmw-9.0.js,9.2,ttm-Latn,Northern Tutchone (Latin) fv,fv_sahugotine_yati,Sahtúgot'ı̨nę́ Yatı̨́,Western Subarctic,fv_sahugotine_yati_kmw-9.0.js,9.1.1,scs-Latn,North Slavey (Latin) fv,fv_shihgotine_yati,Shıhgot'ı̨nę́ Yatı̨́,Western Subarctic,fv_shihgotine_yati_kmw-9.0.js,9.1.1,scs-Latn,North Slavey (Latin) -fv,fv_southern_tutchone,Southern Tutchone,Western Subarctic,fv_southern_tutchone_kmw-9.0.js,9.2.2,tce-Latn,Southern Tutchone (Latin) +fv,fv_southern_tutchone,Southern Tutchone,Western Subarctic,fv_southern_tutchone_kmw-9.0.js,9.3,tce-Latn,Southern Tutchone (Latin) fv,fv_tagizi_dene,Tāgizi Dene,Western Subarctic,fv_tagizi_dene_kmw-9.0.js,9.3,tgx-Latn,Tagish (Latin) fv,fv_tlicho_yatii,Tłı̨chǫ Yatıı̀,Western Subarctic,fv_tlicho_yatii_kmw-9.0.js,9.1.1,dgr-Latn,Dogrib (Latin) fv,fv_dene_mb,ᑌᓀ ᔭᕠᐁ (Dene MB),Western Subarctic,fv_dene_mb_kmw-9.0.js,9.2.1,chp-Cans,Chipewyan (Unified Canadian Aboriginal Syllabics) From 0aec7237c4a7ccb2ecc01ebbc65762c4bb9cee1a Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 28 Aug 2024 14:29:19 +0700 Subject: [PATCH 87/89] docs(core): fix a typo in the KMX+ doc --- docs/file-formats/kmx-plus-file-format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/file-formats/kmx-plus-file-format.md b/docs/file-formats/kmx-plus-file-format.md index 75e1df4295..3b7003f09a 100644 --- a/docs/file-formats/kmx-plus-file-format.md +++ b/docs/file-formats/kmx-plus-file-format.md @@ -456,7 +456,7 @@ For each key: |---|------|---------|------------------------------------------| |16+| 32 | vkey | int: vkey ID | |20+| 32 | mod | int: modifier key flags | -|24+| 32 | key | int: index into `key` sibling subtable | +|24+| 32 | key | int: index into `keys` sibling subtable | - `vkey`: If this is 0-255, it is the resolved standard/predefined vkey (K_A, etc.). It is resolved because the `vkeyMap` from LDML has already been From cf3eef418a31e8d1d1aedb534656dcb1a234b467 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 28 Aug 2024 14:32:27 +0700 Subject: [PATCH 88/89] chore(web): remove obsolete comment --- web/src/engine/js-processor/src/mock.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/src/engine/js-processor/src/mock.ts b/web/src/engine/js-processor/src/mock.ts index 151d8313ca..e44b76e759 100644 --- a/web/src/engine/js-processor/src/mock.ts +++ b/web/src/engine/js-processor/src/mock.ts @@ -1,7 +1,5 @@ import OutputTarget from './outputTarget.js'; -// Due to some interesting requirements on compile ordering in TS, -// this needs to be in the same file as OutputTarget now. export class Mock extends OutputTarget { text: string; From 00a88fbe304bea31b2fa5ec1fe3afe2ee9ecc625 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Wed, 28 Aug 2024 14:02:38 -0400 Subject: [PATCH 89/89] auto: increment master version to 18.0.101 --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 0972d98324..1afecba649 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 18.0.100 alpha 2024-08-28 + +* fix(windows): check IM window will be in a visible location (#11967) + ## 18.0.99 alpha 2024-08-27 * feat(web): import the generator for the pred-text wordbreaker's Unicode-property data-table (#10690) diff --git a/VERSION.md b/VERSION.md index 59ec57bac2..5e9ac7140c 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.100 \ No newline at end of file +18.0.101 \ No newline at end of file