| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/editing/EditingUtilities.h" | 5 #include "core/editing/EditingUtilities.h" |
| 6 | 6 |
| 7 #include "core/dom/StaticNodeList.h" | 7 #include "core/dom/StaticNodeList.h" |
| 8 #include "core/editing/EditingTestBase.h" | 8 #include "core/editing/EditingTestBase.h" |
| 9 | 9 |
| 10 namespace blink { | 10 namespace blink { |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 << "Can't merge a element with no attributes and another element with an
attribute."; | 193 << "Can't merge a element with no attributes and another element with an
attribute."; |
| 194 | 194 |
| 195 // We can't use contenteditable attribute to make editability difference | 195 // We can't use contenteditable attribute to make editability difference |
| 196 // because the hasEquivalentAttributes check is done earier. | 196 // because the hasEquivalentAttributes check is done earier. |
| 197 EXPECT_FALSE(areIdenticalElements(*items->item(0), *items->item(1))) | 197 EXPECT_FALSE(areIdenticalElements(*items->item(0), *items->item(1))) |
| 198 << "Can't merge non-editable nodes."; | 198 << "Can't merge non-editable nodes."; |
| 199 | 199 |
| 200 EXPECT_TRUE(areIdenticalElements(*items->item(1), *items->item(3))); | 200 EXPECT_TRUE(areIdenticalElements(*items->item(1), *items->item(3))); |
| 201 } | 201 } |
| 202 | 202 |
| 203 // Following breaking rules come from http://unicode.org/reports/tr29/ |
| 204 // Note that some of rules are in draft. Also see |
| 205 // http://www.unicode.org/reports/tr29/proposed.html |
| 206 TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) |
| 207 { |
| 208 // GB1: Break at the start of text. |
| 209 setBodyContent("<p id='target'>a</p>"); |
| 210 Node* node = document().getElementById("target")->firstChild(); |
| 211 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 212 |
| 213 // GB2: Break at the end of text. |
| 214 setBodyContent("<p id='target'>a</p>"); |
| 215 node = document().getElementById("target")->firstChild(); |
| 216 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 217 |
| 218 // GB3: Do not break between CR and LF. |
| 219 setBodyContent("<p id='target'>a
b</p>"); |
| 220 node = document().getElementById("target")->firstChild(); |
| 221 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 222 // TODO(nona) : Enable following expectation. |
| 223 // EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 224 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 225 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 226 // TODO(nona) : Enable following expectation. |
| 227 // EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 228 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 229 |
| 230 // GB4,GB5: Break before and after CR/LF/Control. |
| 231 setBodyContent("<p id='target'>a
b</p>"); // CR |
| 232 node = document().getElementById("target")->firstChild(); |
| 233 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); |
| 234 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 235 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 236 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 237 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); |
| 238 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); |
| 239 setBodyContent("<p id='target'>a
b</p>"); // LF |
| 240 node = document().getElementById("target")->firstChild(); |
| 241 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); |
| 242 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 243 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 244 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 245 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); |
| 246 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); |
| 247 setBodyContent("<p id='target'>a­b</p>"); // U+00AD(SOFT HYPHEN) has Co
ntrol property. |
| 248 node = document().getElementById("target")->firstChild(); |
| 249 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); |
| 250 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 251 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 252 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 253 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); |
| 254 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); |
| 255 |
| 256 // GB6: Don't break Hangul sequence. |
| 257 const std::string L = "ᄀ"; // U+1100 (HANGUL CHOSEONG KIYEOK) has L p
roperty. |
| 258 const std::string V = "ᅠ"; // U+1160 (HANGUL JUNGSEONG FILLER) has V
property. |
| 259 const std::string LV = "가"; // U+AC00 (HANGUL SYLLABLE GA) has LV pro
perty. |
| 260 const std::string LVT = "각"; // U+AC01 (HANGUL SYLLABLE GAG) has LVT
property. |
| 261 const std::string T = "ᆨ"; // U+11A8 (HANGUL JONGSEONG KIYEOK) has T
property. |
| 262 setBodyContent("<p id='target'>a" + L + L + "b</p>"); // L x L |
| 263 node = document().getElementById("target")->firstChild(); |
| 264 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 265 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 266 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 267 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 268 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 269 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 270 setBodyContent("<p id='target'>a" + L + V +"b</p>"); // L x V |
| 271 node = document().getElementById("target")->firstChild(); |
| 272 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 273 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 274 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 275 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 276 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 277 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 278 setBodyContent("<p id='target'>a" + L + LV + "b</p>"); // L x LV |
| 279 node = document().getElementById("target")->firstChild(); |
| 280 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 281 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 282 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 283 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 284 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 285 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 286 setBodyContent("<p id='target'>a" + L + LVT + "b</p>"); // L x LVT |
| 287 node = document().getElementById("target")->firstChild(); |
| 288 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 289 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 290 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 291 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 292 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 293 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 294 |
| 295 // GB7: Don't break Hangul sequence. |
| 296 setBodyContent("<p id='target'>a" + LV + V + "b</p>"); // LV x V |
| 297 node = document().getElementById("target")->firstChild(); |
| 298 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 299 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 300 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 301 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 302 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 303 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 304 setBodyContent("<p id='target'>a" + LV + T + "b</p>"); // LV x T |
| 305 node = document().getElementById("target")->firstChild(); |
| 306 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 307 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 308 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 309 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 310 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 311 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 312 setBodyContent("<p id='target'>a" + V + V + "b</p>"); // V x V |
| 313 node = document().getElementById("target")->firstChild(); |
| 314 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 315 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 316 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 317 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 318 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 319 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 320 setBodyContent("<p id='target'>a" + V + T + "b</p>"); // V x T |
| 321 node = document().getElementById("target")->firstChild(); |
| 322 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 323 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 324 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 325 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 326 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 327 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 328 |
| 329 // GB8: Don't break Hangul sequence. |
| 330 setBodyContent("<p id='target'>a" + LVT + T + "b</p>"); // LVT x T |
| 331 node = document().getElementById("target")->firstChild(); |
| 332 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 333 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 334 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 335 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 336 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 337 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 338 setBodyContent("<p id='target'>a" + T + T + "b</p>"); // T x T |
| 339 node = document().getElementById("target")->firstChild(); |
| 340 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 341 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 342 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 343 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 344 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 345 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 346 |
| 347 // Break other Hangul syllable combination. See test of GB999. |
| 348 |
| 349 // GB8a: Don't break between regional indicator if there are even numbered r
egional indicator symbols before. |
| 350 // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U. |
| 351 // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S. |
| 352 const std::string flag = "🇺🇸"; // US flag. |
| 353 setBodyContent("<p id='target'>" + flag + flag + flag + flag + "a</p>"); //
^(RI RI)* RI x RI |
| 354 node = document().getElementById("target")->firstChild(); |
| 355 EXPECT_EQ(16, uncheckedPreviousOffset(node, 17)); |
| 356 EXPECT_EQ(12, uncheckedPreviousOffset(node, 16)); |
| 357 // TODO(nona): Enable following expectations. |
| 358 // EXPECT_EQ(8, uncheckedPreviousOffset(node, 12)); |
| 359 // EXPECT_EQ(4, uncheckedPreviousOffset(node, 8)); |
| 360 // EXPECT_EQ(0, uncheckedPreviousOffset(node, 4)); |
| 361 // EXPECT_EQ(4, uncheckedNextOffset(node, 0)); |
| 362 // EXPECT_EQ(8, uncheckedNextOffset(node, 4)); |
| 363 EXPECT_EQ(12, uncheckedNextOffset(node, 8)); |
| 364 EXPECT_EQ(16, uncheckedNextOffset(node, 12)); |
| 365 EXPECT_EQ(17, uncheckedNextOffset(node, 16)); |
| 366 |
| 367 // GB8c: Don't break between regional indicator if there are even numbered r
egional indicator symbols before. |
| 368 setBodyContent("<p id='target'>a" + flag + flag + flag + flag + "b</p>"); //
[^RI] (RI RI)* RI x RI |
| 369 node = document().getElementById("target")->firstChild(); |
| 370 EXPECT_EQ(17, uncheckedPreviousOffset(node, 18)); |
| 371 EXPECT_EQ(13, uncheckedPreviousOffset(node, 17)); |
| 372 // TODO(nona): Enable following expectations. |
| 373 // EXPECT_EQ(9, uncheckedPreviousOffset(node, 13)); |
| 374 // EXPECT_EQ(5, uncheckedPreviousOffset(node, 9)); |
| 375 EXPECT_EQ(1, uncheckedPreviousOffset(node, 5)); |
| 376 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 377 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 378 // TODO(nona): Enable following expectations. |
| 379 // EXPECT_EQ(5, uncheckedNextOffset(node, 1)); |
| 380 // EXPECT_EQ(9, uncheckedNextOffset(node, 5)); |
| 381 EXPECT_EQ(13, uncheckedNextOffset(node, 9)); |
| 382 EXPECT_EQ(17, uncheckedNextOffset(node, 13)); |
| 383 EXPECT_EQ(18, uncheckedNextOffset(node, 17)); |
| 384 |
| 385 // GB8c: Break if there is an odd number of regional indicator symbols befor
e. |
| 386 setBodyContent("<p id='target'>a" + flag + flag + flag + flag + "🇸b<
/p>"); // RI รท RI |
| 387 node = document().getElementById("target")->firstChild(); |
| 388 EXPECT_EQ(19, uncheckedPreviousOffset(node, 20)); |
| 389 // TODO(nona): Enable following expectations. |
| 390 // EXPECT_EQ(17, uncheckedPreviousOffset(node, 19)); |
| 391 // EXPECT_EQ(13, uncheckedPreviousOffset(node, 17)); |
| 392 // EXPECT_EQ(9, uncheckedPreviousOffset(node, 13)); |
| 393 // EXPECT_EQ(5, uncheckedPreviousOffset(node, 9)); |
| 394 EXPECT_EQ(1, uncheckedPreviousOffset(node, 5)); |
| 395 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 396 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 397 // TODO(nona): Enable following expectations. |
| 398 // EXPECT_EQ(5, uncheckedNextOffset(node, 1)); |
| 399 // EXPECT_EQ(9, uncheckedNextOffset(node, 5)); |
| 400 // EXPECT_EQ(13, uncheckedNextOffset(node, 9)); |
| 401 EXPECT_EQ(17, uncheckedNextOffset(node, 13)); |
| 402 EXPECT_EQ(19, uncheckedNextOffset(node, 17)); |
| 403 EXPECT_EQ(20, uncheckedNextOffset(node, 19)); |
| 404 |
| 405 // GB9: Do not break before extending characters or ZWJ. |
| 406 // U+0300(COMBINING GRAVE ACCENT) has Extend property. |
| 407 setBodyContent("<p id='target'>àb</p>"); // x Extend |
| 408 node = document().getElementById("target")->firstChild(); |
| 409 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); |
| 410 EXPECT_EQ(0, uncheckedPreviousOffset(node, 2)); |
| 411 EXPECT_EQ(2, uncheckedNextOffset(node, 0)); |
| 412 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); |
| 413 // U+200D is ZERO WIDTH JOINER. |
| 414 setBodyContent("<p id='target'>a‍b</p>"); // x ZWJ |
| 415 node = document().getElementById("target")->firstChild(); |
| 416 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); |
| 417 EXPECT_EQ(0, uncheckedPreviousOffset(node, 2)); |
| 418 EXPECT_EQ(2, uncheckedNextOffset(node, 0)); |
| 419 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); |
| 420 |
| 421 // GB9a: Do not break before SpacingMarks. |
| 422 // U+0903(DEVANAGARI SIGN VISARGA) has SpacingMark property. |
| 423 setBodyContent("<p id='target'>aःb</p>"); // x SpacingMark |
| 424 node = document().getElementById("target")->firstChild(); |
| 425 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); |
| 426 EXPECT_EQ(0, uncheckedPreviousOffset(node, 2)); |
| 427 EXPECT_EQ(2, uncheckedNextOffset(node, 0)); |
| 428 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); |
| 429 |
| 430 // GB9b: Do not break after Prepend but Blink breaks after Prepend char to a
ddress Bug 24342. |
| 431 // U+0600(ARABIC NUMBER SIGN) has Prepend property. |
| 432 setBodyContent("<p id='target'>a؀b</p>"); // Prepend x |
| 433 node = document().getElementById("target")->firstChild(); |
| 434 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); |
| 435 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 436 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 437 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 438 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); |
| 439 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); |
| 440 |
| 441 // Blink customization: Don't break before Japanese half-width katakana voic
ed marks. |
| 442 setBodyContent("<p id='target'>aガb</p>"); |
| 443 node = document().getElementById("target")->firstChild(); |
| 444 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 445 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 446 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 447 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 448 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 449 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 450 |
| 451 // Additional rule for Virama: Do not break after Virama except for Tamil. |
| 452 // See http://www.unicode.org/Public/9.0.0/ucd/IndicSyllabicCategory-9.0.0d2
.txt |
| 453 // U+0905 is DEVANAGARI LETTER A. This has Extend property. |
| 454 // U+094D is DEVANAGARI SIGN VIRAMA. This has Virama property. |
| 455 // U+0915 is DEVANAGARI LETTER KA. |
| 456 setBodyContent("<p id='target'>aअ्कb</p>"); |
| 457 node = document().getElementById("target")->firstChild(); |
| 458 EXPECT_EQ(4, uncheckedPreviousOffset(node, 5)); |
| 459 EXPECT_EQ(1, uncheckedPreviousOffset(node, 4)); |
| 460 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 461 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 462 EXPECT_EQ(4, uncheckedNextOffset(node, 1)); |
| 463 EXPECT_EQ(5, uncheckedNextOffset(node, 4)); |
| 464 // U+0B85 is TAMIL LETTER A. This has Extend property. |
| 465 // U+0BCD is TAMIL SIGN VIRAMA. This has Virama property. |
| 466 // U+0B95 is TAMIL LETTER KA. |
| 467 setBodyContent("<p id='target'>aஅ்கb</p>"); |
| 468 node = document().getElementById("target")->firstChild(); |
| 469 EXPECT_EQ(4, uncheckedPreviousOffset(node, 5)); |
| 470 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 471 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 472 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 473 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 474 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); |
| 475 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 476 EXPECT_EQ(5, uncheckedNextOffset(node, 4)); |
| 477 // TODO(nona): Consider to add Sinhala, Balinese, etc. |
| 478 |
| 479 // GB10: Do not break within emoji modifier. |
| 480 // U+1F385(FATHER CHRISTMAS) has E_Base property. |
| 481 // U+1F3FB(EMOJI MODIFIER FITZPATRICK TYPE-1-2) has E_Modifier property. |
| 482 setBodyContent("<p id='target'>a🎅🏻b</p>"); // E_Base x E_Mod
ifier |
| 483 node = document().getElementById("target")->firstChild(); |
| 484 EXPECT_EQ(5, uncheckedPreviousOffset(node, 6)); |
| 485 // TODO(nona): Enable following expectation. |
| 486 // EXPECT_EQ(1, uncheckedPreviousOffset(node, 5)); |
| 487 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 488 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 489 // TODO(nona): Enable following expectation. |
| 490 // EXPECT_EQ(5, uncheckedNextOffset(node, 1)); |
| 491 EXPECT_EQ(6, uncheckedNextOffset(node, 5)); |
| 492 // U+1F466(BOY) has EBG property. |
| 493 setBodyContent("<p id='target'>a👦🏻b</p>"); // EBG x E_Modifi
er |
| 494 node = document().getElementById("target")->firstChild(); |
| 495 EXPECT_EQ(5, uncheckedPreviousOffset(node, 6)); |
| 496 // TODO(nona): Enable following expectation. |
| 497 // EXPECT_EQ(1, uncheckedPreviousOffset(node, 5)); |
| 498 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); |
| 499 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 500 // TODO(nona): Enable following expectation. |
| 501 // EXPECT_EQ(5, uncheckedNextOffset(node, 1)); |
| 502 EXPECT_EQ(6, uncheckedNextOffset(node, 5)); |
| 503 |
| 504 // GB11: Do not break within ZWJ emoji sequence. |
| 505 // U+2764(HEAVY BLACK HEART) has Glue_After_Zwj property. |
| 506 setBodyContent("<p id='target'>a‍❤b</p>"); // ZWJ x Glue_After
_Zwj |
| 507 node = document().getElementById("target")->firstChild(); |
| 508 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); |
| 509 // TODO(nona): Enable following expectation. |
| 510 // EXPECT_EQ(0, uncheckedPreviousOffset(node, 3)); |
| 511 // EXPECT_EQ(3, uncheckedNextOffset(node, 0)); |
| 512 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); |
| 513 setBodyContent("<p id='target'>a‍👦b</p>"); // ZWJ x EBG |
| 514 node = document().getElementById("target")->firstChild(); |
| 515 EXPECT_EQ(4, uncheckedPreviousOffset(node, 5)); |
| 516 // TODO(nona): Enable following expectation. |
| 517 // EXPECT_EQ(0, uncheckedPreviousOffset(node, 4)); |
| 518 // EXPECT_EQ(4, uncheckedNextOffset(node, 0)); |
| 519 EXPECT_EQ(5, uncheckedNextOffset(node, 4)); |
| 520 |
| 521 // GB999: Otherwise break everywhere. |
| 522 // Breaks between Hangul syllable except for GB6, GB7, GB8. |
| 523 setBodyContent("<p id='target'>" + L + T + "</p>"); |
| 524 node = document().getElementById("target")->firstChild(); |
| 525 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 526 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 527 setBodyContent("<p id='target'>" + V + L + "</p>"); |
| 528 node = document().getElementById("target")->firstChild(); |
| 529 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 530 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 531 setBodyContent("<p id='target'>" + V + LV + "</p>"); |
| 532 node = document().getElementById("target")->firstChild(); |
| 533 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 534 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 535 setBodyContent("<p id='target'>" + V + LVT + "</p>"); |
| 536 node = document().getElementById("target")->firstChild(); |
| 537 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 538 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 539 setBodyContent("<p id='target'>" + LV + L + "</p>"); |
| 540 node = document().getElementById("target")->firstChild(); |
| 541 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 542 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 543 setBodyContent("<p id='target'>" + LV + LV + "</p>"); |
| 544 node = document().getElementById("target")->firstChild(); |
| 545 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 546 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 547 setBodyContent("<p id='target'>" + LV + LVT + "</p>"); |
| 548 node = document().getElementById("target")->firstChild(); |
| 549 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 550 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 551 setBodyContent("<p id='target'>" + LVT + L + "</p>"); |
| 552 node = document().getElementById("target")->firstChild(); |
| 553 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 554 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 555 setBodyContent("<p id='target'>" + LVT + V + "</p>"); |
| 556 node = document().getElementById("target")->firstChild(); |
| 557 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 558 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 559 setBodyContent("<p id='target'>" + LVT + LV + "</p>"); |
| 560 node = document().getElementById("target")->firstChild(); |
| 561 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 562 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 563 setBodyContent("<p id='target'>" + LVT + LVT + "</p>"); |
| 564 node = document().getElementById("target")->firstChild(); |
| 565 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 566 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 567 setBodyContent("<p id='target'>" + T + L + "</p>"); |
| 568 node = document().getElementById("target")->firstChild(); |
| 569 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 570 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 571 setBodyContent("<p id='target'>" + T + V + "</p>"); |
| 572 node = document().getElementById("target")->firstChild(); |
| 573 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 574 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 575 setBodyContent("<p id='target'>" + T + LV + "</p>"); |
| 576 node = document().getElementById("target")->firstChild(); |
| 577 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 578 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 579 setBodyContent("<p id='target'>" + T + LVT + "</p>"); |
| 580 node = document().getElementById("target")->firstChild(); |
| 581 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); |
| 582 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 583 |
| 584 // For GB10, if base emoji character is not E_Base or EBG, break happens bef
ore E_Modifier. |
| 585 setBodyContent("<p id='target'>a🏻</p>"); |
| 586 node = document().getElementById("target")->firstChild(); |
| 587 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 588 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 589 // U+1F5FA(WORLD MAP) doesn't have either E_Base or EBG property. |
| 590 setBodyContent("<p id='target'>🗺🏻</p>"); |
| 591 node = document().getElementById("target")->firstChild(); |
| 592 EXPECT_EQ(2, uncheckedPreviousOffset(node, 4)); |
| 593 EXPECT_EQ(2, uncheckedNextOffset(node, 0)); |
| 594 |
| 595 // For GB11, if trailing character is not Glue_After_Zwj or EBG, break happe
ns after ZWJ. |
| 596 // U+1F5FA(WORLD MAP) doesn't have either Glue_After_Zwj or EBG. |
| 597 setBodyContent("<p id='target'>‍🗺</p>"); |
| 598 node = document().getElementById("target")->firstChild(); |
| 599 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); |
| 600 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); |
| 601 } |
| 602 |
| 203 } // namespace blink | 603 } // namespace blink |
| OLD | NEW |