Skip to content

Commit

Permalink
Merge branch 'master' into no-result-found-helper
Browse files Browse the repository at this point in the history
  • Loading branch information
khaitruong922 authored Jul 14, 2024
2 parents 07d586b + ee6185a commit 8d6f154
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 47 deletions.
2 changes: 1 addition & 1 deletion ext/js/accessibility/google-docs-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export class GoogleDocsUtil {
const mid = Math.floor((start + end) / 2);
range.setStart(textNode, mid);
range.setEnd(textNode, end);
if (isPointInAnyRect(x, y, range.getClientRects())) {
if (isPointInAnyRect(x, y, range.getClientRects(), null)) {
start = mid;
} else {
end = mid;
Expand Down
19 changes: 16 additions & 3 deletions ext/js/dom/document-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
*/
let cssZoomSupported = null;

/** @type {Set<?string>} */
const FIREFOX_RECT_EXCLUDED_LANGUAGES = new Set(['th']);

/**
* Computes the scaling adjustment that is necessary for client space coordinates based on the
* CSS zoom level.
Expand Down Expand Up @@ -107,9 +110,18 @@ export function isPointInRect(x, y, rect) {
* @param {number} x The horizontal coordinate.
* @param {number} y The vertical coordinate.
* @param {DOMRect[]|DOMRectList} rects The rect to check.
* @param {?string} language
* @returns {boolean} `true` if the point is inside any of the rects, `false` otherwise.
*/
export function isPointInAnyRect(x, y, rects) {
export function isPointInAnyRect(x, y, rects, language) {
// Always return true for Firefox due to inconsistencies with Range.getClientRects() implementation from unclear W3C spec
// https://drafts.csswg.org/cssom-view/#dom-range-getclientrects
// https://bugzilla.mozilla.org/show_bug.cgi?id=816238
// Firefox returns only the first level nodes, Chromium returns every text node
// This only affects specific languages
if (typeof browser !== 'undefined' && FIREFOX_RECT_EXCLUDED_LANGUAGES.has(language)) {
return true;
}
for (const rect of rects) {
if (isPointInRect(x, y, rect)) {
return true;
Expand All @@ -123,12 +135,13 @@ export function isPointInAnyRect(x, y, rects) {
* @param {number} x The horizontal coordinate.
* @param {number} y The vertical coordinate.
* @param {Selection} selection The selection to check.
* @param {string} language
* @returns {boolean} `true` if the point is inside the selection, `false` otherwise.
*/
export function isPointInSelection(x, y, selection) {
export function isPointInSelection(x, y, selection, language) {
for (let i = 0; i < selection.rangeCount; ++i) {
const range = selection.getRangeAt(i);
if (isPointInAnyRect(x, y, range.getClientRects())) {
if (isPointInAnyRect(x, y, range.getClientRects(), language)) {
return true;
}
}
Expand Down
16 changes: 9 additions & 7 deletions ext/js/dom/text-source-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export class TextSourceGenerator {
* @returns {?import('text-source').TextSource} A range for the hovered text or element, or `null` if no applicable content was found.
*/
_getRangeFromPointInternal(x, y, options) {
const {deepContentScan, normalizeCssZoom} = options;
const {deepContentScan, normalizeCssZoom, language} = options;

const elements = this._getElementsFromPoint(x, y, deepContentScan);
/** @type {?HTMLDivElement} */
Expand Down Expand Up @@ -216,7 +216,7 @@ export class TextSourceGenerator {
}
}

const range = this._caretRangeFromPointExt(x, y, deepContentScan ? elements : [], normalizeCssZoom);
const range = this._caretRangeFromPointExt(x, y, deepContentScan ? elements : [], normalizeCssZoom, language);
if (range !== null) {
if (imposter !== null) {
this._setImposterStyle(/** @type {HTMLDivElement} */ (imposterContainer).style, 'z-index', '-2147483646');
Expand Down Expand Up @@ -347,9 +347,10 @@ export class TextSourceGenerator {
* @param {number} y
* @param {Range} range
* @param {boolean} normalizeCssZoom
* @param {?string} language
* @returns {boolean}
*/
_isPointInRange(x, y, range, normalizeCssZoom) {
_isPointInRange(x, y, range, normalizeCssZoom, language) {
// Require a text node to start
const {startContainer} = range;
if (startContainer.nodeType !== Node.TEXT_NODE) {
Expand All @@ -370,7 +371,7 @@ export class TextSourceGenerator {
const {node, offset, content} = new DOMTextScanner(nodePre, offsetPre, true, false).seek(1);
range.setEnd(node, offset);

if (!this._isWhitespace(content) && isPointInAnyRect(x, y, range.getClientRects())) {
if (!this._isWhitespace(content) && isPointInAnyRect(x, y, range.getClientRects(), language)) {
return true;
}
} finally {
Expand All @@ -381,7 +382,7 @@ export class TextSourceGenerator {
const {node, offset, content} = new DOMTextScanner(startContainer, range.startOffset, true, false).seek(-1);
range.setStart(node, offset);

if (!this._isWhitespace(content) && isPointInAnyRect(x, y, range.getClientRects())) {
if (!this._isWhitespace(content) && isPointInAnyRect(x, y, range.getClientRects(), language)) {
// This purposefully leaves the starting offset as modified and sets the range length to 0.
range.setEnd(node, offset);
return true;
Expand Down Expand Up @@ -522,9 +523,10 @@ export class TextSourceGenerator {
* @param {number} y
* @param {Element[]} elements
* @param {boolean} normalizeCssZoom
* @param {?string} language
* @returns {?Range}
*/
_caretRangeFromPointExt(x, y, elements, normalizeCssZoom) {
_caretRangeFromPointExt(x, y, elements, normalizeCssZoom, language) {
/** @type {?Map<Element, ?string>} */
let previousStyles = null;
try {
Expand All @@ -538,7 +540,7 @@ export class TextSourceGenerator {

const startContainer = range.startContainer;
if (startContinerPre !== startContainer) {
if (this._isPointInRange(x, y, range, normalizeCssZoom)) {
if (this._isPointInRange(x, y, range, normalizeCssZoom, language)) {
return range;
}
startContinerPre = startContainer;
Expand Down
45 changes: 28 additions & 17 deletions ext/js/language/ja/japanese.js
Original file line number Diff line number Diff line change
Expand Up @@ -747,29 +747,40 @@ export function isEmphaticCodePoint(codePoint) {
* @returns {string}
*/
export function collapseEmphaticSequences(text, fullCollapse) {
let result = '';
let collapseCodePoint = -1;
for (let i = 0; i < text.length; ++i) {
const char = text[i];
const c = char.codePointAt(0) ?? -1;
if (isEmphaticCodePoint(c)) {
// Prevent match trailing emphatic
if (i === text.length - 1) {
result += char;
continue;
}
let left = 0;
while (left < text.length && isEmphaticCodePoint(/** @type {number} */ (text.codePointAt(left)))) {
++left;
}
let right = text.length - 1;
while (right >= 0 && isEmphaticCodePoint(/** @type {number} */ (text.codePointAt(right)))) {
--right;
}
// Whole string is emphatic
if (left > right) {
return text;
}

const leadingEmphatics = text.substring(0, left);
const trailingEmphatics = text.substring(right + 1);
let middle = '';
let currentCollapsedCodePoint = -1;

if (collapseCodePoint !== c) {
collapseCodePoint = c;
for (let i = left; i <= right; ++i) {
const char = text[i];
const codePoint = /** @type {number} */ (char.codePointAt(0));
if (isEmphaticCodePoint(codePoint)) {
if (currentCollapsedCodePoint !== codePoint) {
currentCollapsedCodePoint = codePoint;
if (!fullCollapse) {
result += char;
middle += char;
continue;
}
}
} else {
collapseCodePoint = -1;
result += char;
currentCollapsedCodePoint = -1;
middle += char;
}
}
return result;

return leadingEmphatics + middle + trailingEmphatics;
}
4 changes: 3 additions & 1 deletion ext/js/language/text-scanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -732,8 +732,9 @@ export class TextScanner extends EventDispatcher {
this._preventNextClick = false;
this._touchTapValid = true;

const languageNotNull = this._language !== null ? this._language : '';
const selection = window.getSelection();
if (selection !== null && isPointInSelection(x, y, selection)) {
if (selection !== null && isPointInSelection(x, y, selection, languageNotNull)) {
return;
}

Expand Down Expand Up @@ -1357,6 +1358,7 @@ export class TextScanner extends EventDispatcher {
const textSource = this._textSourceGenerator.getRangeFromPoint(x, y, {
deepContentScan: this._deepContentScan,
normalizeCssZoom: this._normalizeCssZoom,
language: this._language,
});
if (textSource !== null) {
try {
Expand Down
1 change: 1 addition & 0 deletions test/document-util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ describe('Document utility tests', () => {
const source = textSourceGenerator.getRangeFromPoint(0, 0, {
deepContentScan: false,
normalizeCssZoom: true,
language: null,
});
switch (resultType) {
case 'TextSourceRange':
Expand Down
51 changes: 33 additions & 18 deletions test/japanese-util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -767,15 +767,6 @@ describe('Japanese utility functions', () => {
[['かっっっこい', false], 'かっこい'],
[['かっっっこい', true], 'かこい'],

[['こい', false], 'こい'],
[['こい', true], 'こい'],
[['っこい', false], 'っこい'],
[['っこい', true], 'こい'],
[['っっこい', false], 'っこい'],
[['っっこい', true], 'こい'],
[['っっっこい', false], 'っこい'],
[['っっっこい', true], 'こい'],

[['すごい', false], 'すごい'],
[['すごい', true], 'すごい'],
[['すごーい', false], 'すごーい'],
Expand All @@ -787,21 +778,45 @@ describe('Japanese utility functions', () => {
[['すっっごーーい', false], 'すっごーい'],
[['すっっごーーい', true], 'すごい'],

[['こい', false], 'こい'],
[['こい', true], 'こい'],
[['っこい', false], 'っこい'],
[['っこい', true], 'っこい'],
[['っっこい', false], 'っっこい'],
[['っっこい', true], 'っっこい'],
[['っっっこい', false], 'っっっこい'],
[['っっっこい', true], 'っっっこい'],
[['こいっ', false], 'こいっ'],
[['こいっ', true], 'こいっ'],
[['こいっっ', false], 'こいっっ'],
[['こいっっ', true], 'こいっっ'],
[['こいっっっ', false], 'こいっっっ'],
[['こいっっっ', true], 'こいっっっ'],
[['っこいっ', false], 'っこいっ'],
[['っこいっ', true], 'っこいっ'],
[['っっこいっっ', false], 'っっこいっっ'],
[['っっこいっっ', true], 'っっこいっっ'],
[['っっっこいっっっ', false], 'っっっこいっっっ'],
[['っっっこいっっっ', true], 'っっっこいっっっ'],

[['', false], ''],
[['', true], ''],
[['っ', false], 'っ'],
[['っ', true], 'っ'],
[['っっ', false], 'っっ'],
[['っっ', true], 'っ'],
[['っっっ', false], 'っっ'],
[['っっっ', true], 'っ'],
[['っっ', true], 'っっ'],
[['っっっ', false], 'っっっ'],
[['っっっ', true], 'っっっ'],

[['っーッかっこいいっーッ', false], 'っーッかっこいいっーッ'],
[['っーッかっこいいっーッ', true], 'っーッかこいいっーッ'],
[['っっーーッッかっこいいっっーーッッ', false], 'っっーーッッかっこいいっっーーッッ'],
[['っっーーッッかっこいいっっーーッッ', true], 'っっーーッッかこいいっっーーッッ'],

[['かっこいいっ', false], 'かっこいいっ'],
[['かっこいいっ', true], 'かこいいっ'],
[['かっこいいっっ', false], 'かっこいいっっ'],
[['かっこいいっっ', true], 'かこいいっ'],
[['かっこいいっっっ', false], 'かっこいいっっ'],
[['かっこいいっっっ', true], 'かこいいっ'],
[['っーッ', false], 'っーッ'],
[['っーッ', true], 'っーッ'],
[['っっーーッッ', false], 'っっーーッッ'],
[['っっーーッッ', true], 'っっーーッッ'],
];

test.each(data)('%o -> %o', (input, output) => {
Expand Down
4 changes: 4 additions & 0 deletions types/ext/document-util.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export type GetRangeFromPointOptions = {
* Whether or not zoom coordinates should be normalized.
*/
normalizeCssZoom: boolean;
/**
* ISO-639 code of the language.
*/
language: string | null;
};

export type ToNumberConstraints = {
Expand Down

0 comments on commit 8d6f154

Please sign in to comment.