@@ -15,7 +15,7 @@ enum _Mode { on, off }
1515/// ╭──────╮ Highlight
1616/// │ Data │ ╭─────────────────────────────────╮
1717/// ╰──────╯ │ ╭─────────╮ ╭───────────────╮ │
18- /// │ ╭──▶ │ │ Pattern │ & │ Words/Letters │ │
18+ /// │ ╭─── │ │ Pattern │ & │ Words/Letters │ │
1919/// │ │ │ ╰─────────╯ ╰───────────────╯ │
2020/// │ │ ╰─────────────────────────────────╯
2121/// ╰───────╯
@@ -24,7 +24,7 @@ enum _Mode { on, off }
2424/// │ Parser ───▶ ... │ Highlighted Data as Text Widget │
2525/// ╰───────╯ ╰─────────────────────────────────╯
2626///
27- class HighlightText extends StatefulWidget {
27+ class HighlightText extends StatelessWidget {
2828 /// The default string data.
2929 /// Like [Text] widget's first required value.
3030 ///
@@ -74,7 +74,7 @@ class HighlightText extends StatefulWidget {
7474 /// If unset, defaults to the ─▶ [false] .
7575 final bool detectWords;
7676
77- const HighlightText (
77+ HighlightText (
7878 this .data, {
7979 Key ? key,
8080 required this .highlight,
@@ -87,61 +87,54 @@ class HighlightText extends StatefulWidget {
8787 this .detectWords = false ,
8888 }) : super (key: key);
8989
90- @override
91- _HighlightTextState createState () => _HighlightTextState ();
92- }
93-
94- class _HighlightTextState extends State <HighlightText > {
95- TextStyle ? style;
96- List <InlineSpan > _spans = [];
90+ // The highlight sequence spans.
91+ // Which's actual [rich-text-widget]'s childrens value.
92+ final List <InlineSpan > _spans = [];
9793
9894 // Main method that used to generate text splans.
9995 // Compares [data] to [highlight] to catch highlightable and non-highlightable
10096 // words/letters, which would be the "NEXT" text-span's text data.
101- void parse () {
102- // Clear splans before generating.
103- _spans.clear ();
97+ void _parse ({
98+ required TextStyle ds,
99+ required TextStyle hs,
100+ }) {
101+ if (_spans.isNotEmpty) _spans.clear ();
104102
105- // Shouldn't waste time/effort in comparing [data]
106- // to [highlight] object.
107- if (widget.highlight.words == null && widget.highlight.pattern == null ) {
103+ if (highlight.words == null && highlight.pattern == null ) {
108104 return ;
109105 }
110106
107+ // Matching sequence representer.
111108 String hp = '' ;
112109
113110 // Creates a span with [highlight-part] and [highlight-mode].
114- final cutHP = (_Mode mode) {
115- createSpan (hp, mode);
111+ void cutHP (_Mode mode) {
112+ _createSpan (hp, mode, ds : ds, hs : hs );
116113 hp = '' ;
117- };
118-
119- for (var i = 0 ; i < widget.data.length; i++ ) {
120- final el = widget.data[i];
114+ }
121115
122- // Directly add element to
123- // highlight-part when it's empty.
116+ for (var i = 0 ; i < data.length; i++ ) {
124117 if (hp.isEmpty) {
125- hp += el ;
118+ hp += data[i] ;
126119 continue ;
127120 }
128121
129122 // Cut [highlight-part] as [highlight-mode-off].
130- if (isMatches (el ) && ! isMatches (hp)) {
123+ if (_isMatches (data[i] ) && ! _isMatches (hp)) {
131124 cutHP (_Mode .off);
132125 // Cut [highlight-part] as [highlight-mode-on].
133- } else if (! isMatches (el ) && isMatches (hp)) {
134- final isNotDetectable = widget. detectWords && hp.length == 1 ;
126+ } else if (! _isMatches (data[i] ) && _isMatches (hp)) {
127+ final isNotDetectable = detectWords && hp.length == 1 ;
135128 cutHP (isNotDetectable ? _Mode .off : _Mode .on );
136129 }
137130
138- hp += el ;
131+ hp += data[i] ;
139132
140133 // Finish cutting highlight-part.
141- if (hp.isNotEmpty && i == widget. data.length - 1 ) {
134+ if (hp.isNotEmpty && i == data.length - 1 ) {
142135 // Determine mode by matching of [element] and [highlight-part]+[element].
143- final mode = isMatches (el ) && isMatches (hp + el) ? _Mode . on : _Mode .off ;
144- cutHP (mode );
136+ final matches = _isMatches (data[i] ) && _isMatches (hp + data[i]) ;
137+ cutHP (matches ? _Mode . on : _Mode .off );
145138 }
146139 }
147140 }
@@ -152,36 +145,39 @@ class _HighlightTextState extends State<HighlightText> {
152145 // Mode determines the style of generated text-span.
153146 // If mode is on, text-span's style would be [highlightStyle].
154147 // If not, style would be (default)[style].
155- void createSpan (String data, _Mode mode) {
148+ void _createSpan (
149+ String data,
150+ _Mode mode, {
151+ required TextStyle ds,
152+ required TextStyle hs,
153+ }) {
156154 final textSpan = TextSpan (
157155 text: data,
158- style: (mode == _Mode .on ) ? widget.highlightStyle : style ,
156+ style: (mode == _Mode .on ) ? hs : ds ,
159157 );
160158
161159 _spans.add (textSpan);
162160 }
163161
164162 // Matching checker for [parse] method.
165163 // Would be used to check matching of one letter or split word.
166- bool isMatches (String data) {
167- final h = widget.highlight;
168-
164+ bool _isMatches (String data) {
169165 // Ignore case sensitive.
170- if (! widget. caseSensitive) data = data.toLowerCase ();
166+ if (! caseSensitive) data = data.toLowerCase ();
171167
172168 // Check matching by pattern.
173- if (h.pattern != null && RegExp (h.pattern! ).hasMatch (data)) {
169+ if (highlight.pattern != null &&
170+ RegExp (highlight.pattern! ).hasMatch (data)) {
174171 return true ;
175172 }
176173
177174 // Check matching by words/words.
178- if (h .words != null && h .words! .isNotEmpty) {
179- for (var i = 0 ; i < h .words! .length; i++ ) {
180- var word = h .words! [i];
175+ if (highlight .words != null && highlight .words! .isNotEmpty) {
176+ for (var i = 0 ; i < highlight .words! .length; i++ ) {
177+ var word = highlight .words! [i];
181178
182179 // Ignore case sensitive.
183- if (! widget.caseSensitive) word = word.toLowerCase ();
184-
180+ if (! caseSensitive) word = word.toLowerCase ();
185181 if (word.contains (data) || data.contains (word)) return true ;
186182 }
187183 }
@@ -192,14 +188,17 @@ class _HighlightTextState extends State<HighlightText> {
192188 @override
193189 Widget build (BuildContext context) {
194190 // Define style of normal text.
195- style = widget.style ?? Theme .of (context).textTheme.bodyText1;
191+ final DefaultTextStyle defaultTextStyle = DefaultTextStyle .of (context);
192+ TextStyle effectiveStyle = style ?? defaultTextStyle.style;
193+ if (style == null || style! .inherit) {
194+ effectiveStyle = defaultTextStyle.style.merge (style);
195+ }
196196
197- // Execute [parse] in each build
198- // i.e -> [hot-reload].
199- parse ();
197+ // Generate highlight-sequence text-spans.
198+ _parse (ds: effectiveStyle, hs: highlightStyle);
200199
201200 // Build the default text, if there is no spans.
202- if (_spans.isEmpty) return Text (widget. data, style: style );
201+ if (_spans.isEmpty) return Text (data, style: effectiveStyle );
203202
204203 // Build the highlighted text with rich-text.
205204 return RichText (text: TextSpan (text: '' , children: _spans));
0 commit comments