| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:test/bootstrap/browser.dart'; |
| import 'package:test/test.dart'; |
| import 'package:ui/src/engine.dart'; |
| import 'package:ui/ui.dart'; |
| |
| import '../html/paragraph/helper.dart'; |
| |
| void main() { |
| internalBootstrapBrowserTest(() => testMain); |
| } |
| |
| Future<void> testMain() async { |
| group('$BidiFragmenter', () { |
| test('empty string', () { |
| expect(split(''), <_Bidi>[ |
| _Bidi('', null, ffPrevious), |
| ]); |
| }); |
| |
| test('basic cases', () { |
| expect(split('Lorem 11 $rtlWord1 22 ipsum'), <_Bidi>[ |
| _Bidi('Lorem', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('11', ltr, ffPrevious), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi(rtlWord1, rtl, ffRtl), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('22', ltr, ffPrevious), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('ipsum', ltr, ffLtr), |
| ]); |
| }); |
| |
| test('text and digits', () { |
| expect(split('Lorem11 ${rtlWord1}22 33ipsum44dolor ${rtlWord2}55$rtlWord1'), <_Bidi>[ |
| _Bidi('Lorem11', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi(rtlWord1, rtl, ffRtl), |
| _Bidi('22', ltr, ffPrevious), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('33ipsum44dolor', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi(rtlWord2, rtl, ffRtl), |
| _Bidi('55', ltr, ffPrevious), |
| _Bidi(rtlWord1, rtl, ffRtl), |
| ]); |
| }); |
| |
| test('Mashriqi digits', () { |
| expect(split('foo ١١ ٢٢ bar'), <_Bidi>[ |
| _Bidi('foo', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('١١', ltr, ffRtl), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('٢٢', ltr, ffRtl), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('bar', ltr, ffLtr), |
| ]); |
| |
| expect(split('$rtlWord1 ١١ ٢٢ $rtlWord2'), <_Bidi>[ |
| _Bidi(rtlWord1, rtl, ffRtl), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('١١', ltr, ffRtl), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('٢٢', ltr, ffRtl), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi(rtlWord2, rtl, ffRtl), |
| ]); |
| }); |
| |
| test('spaces', () { |
| expect(split(' '), <_Bidi>[ |
| _Bidi(' ', null, ffSandwich), |
| ]); |
| }); |
| |
| test('symbols', () { |
| expect(split('Calculate 2.2 + 4.5 and write the result'), <_Bidi>[ |
| _Bidi('Calculate', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('2', ltr, ffPrevious), |
| _Bidi('.', null, ffSandwich), |
| _Bidi('2', ltr, ffPrevious), |
| _Bidi(' + ', null, ffSandwich), |
| _Bidi('4', ltr, ffPrevious), |
| _Bidi('.', null, ffSandwich), |
| _Bidi('5', ltr, ffPrevious), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('and', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('write', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('the', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('result', ltr, ffLtr), |
| ]); |
| |
| expect(split('Calculate $rtlWord1 2.2 + 4.5 and write the result'), <_Bidi>[ |
| _Bidi('Calculate', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi(rtlWord1, rtl, ffRtl), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('2', ltr, ffPrevious), |
| _Bidi('.', null, ffSandwich), |
| _Bidi('2', ltr, ffPrevious), |
| _Bidi(' + ', null, ffSandwich), |
| _Bidi('4', ltr, ffPrevious), |
| _Bidi('.', null, ffSandwich), |
| _Bidi('5', ltr, ffPrevious), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('and', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('write', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('the', ltr, ffLtr), |
| _Bidi(' ', null, ffSandwich), |
| _Bidi('result', ltr, ffLtr), |
| ]); |
| |
| expect(split('12 + 24 = 36'), <_Bidi>[ |
| _Bidi('12', ltr, ffPrevious), |
| _Bidi(' + ', null, ffSandwich), |
| _Bidi('24', ltr, ffPrevious), |
| _Bidi(' = ', null, ffSandwich), |
| _Bidi('36', ltr, ffPrevious), |
| ]); |
| }); |
| |
| test('handles new lines', () { |
| expect(split('Lorem\n12\nipsum \n'), <_Bidi>[ |
| _Bidi('Lorem', ltr, ffLtr), |
| _Bidi('\n', null, ffSandwich), |
| _Bidi('12', ltr, ffPrevious), |
| _Bidi('\n', null, ffSandwich), |
| _Bidi('ipsum', ltr, ffLtr), |
| _Bidi(' \n', null, ffSandwich), |
| ]); |
| |
| expect(split('$rtlWord1\n $rtlWord2 \n'), <_Bidi>[ |
| _Bidi(rtlWord1, rtl, ffRtl), |
| _Bidi('\n ', null, ffSandwich), |
| _Bidi(rtlWord2, rtl, ffRtl), |
| _Bidi(' \n', null, ffSandwich), |
| ]); |
| }); |
| |
| test('surrogates', () { |
| expect(split('A\u{1F600}'), <_Bidi>[ |
| _Bidi('A', ltr, ffLtr), |
| _Bidi('\u{1F600}', null, ffSandwich), |
| ]); |
| }); |
| }); |
| } |
| |
| /// Holds information about how a bidi region was split from a string. |
| class _Bidi { |
| _Bidi(this.text, this.textDirection, this.fragmentFlow); |
| |
| factory _Bidi.fromBidiFragment(String text, BidiFragment bidiFragment) { |
| return _Bidi( |
| text.substring(bidiFragment.start, bidiFragment.end), |
| bidiFragment.textDirection, |
| bidiFragment.fragmentFlow, |
| ); |
| } |
| |
| final String text; |
| final TextDirection? textDirection; |
| final FragmentFlow fragmentFlow; |
| |
| @override |
| int get hashCode => Object.hash(text, textDirection); |
| |
| @override |
| bool operator ==(Object other) { |
| return other is _Bidi && |
| other.text == text && |
| other.textDirection == textDirection && |
| other.fragmentFlow == fragmentFlow; |
| } |
| |
| @override |
| String toString() { |
| return '"$text" ($textDirection | $fragmentFlow)'; |
| } |
| } |
| |
| List<_Bidi> split(String text) { |
| return <_Bidi>[ |
| for (final BidiFragment bidiFragment in BidiFragmenter(text).fragment()) |
| _Bidi.fromBidiFragment(text, bidiFragment) |
| ]; |
| } |