Skip to content

Commit 9843739

Browse files
authored
Merge pull request #355 from wordpress-mobile/issue/332-keep-whitespaces-inside-pre-tags
Issue/322 keep whitespaces inside pre tags
2 parents 465d13c + b62ed91 commit 9843739

File tree

3 files changed

+56
-36
lines changed

3 files changed

+56
-36
lines changed

aztec/src/main/java/org/wordpress/aztec/Html.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,11 @@ public interface ImageGetter {
9090

9191
interface Callbacks {
9292
void onUseDefaultImage();
93+
9394
void onImageFailed();
95+
9496
void onImageLoaded(Drawable drawable);
97+
9598
void onImageLoading(Drawable drawable);
9699
}
97100
}
@@ -106,7 +109,7 @@ public interface TagHandler {
106109
* a tag that it does not know how to interpret.
107110
*/
108111
boolean handleTag(boolean opening, String tag, Editable output, OnMediaTappedListener onMediaTappedListener,
109-
Context context, Attributes attributes, int nestingLevel);
112+
Context context, Attributes attributes, int nestingLevel);
110113
}
111114

112115
private Html() {
@@ -181,6 +184,8 @@ class HtmlToSpannedConverter implements ContentHandler, LexicalHandler {
181184

182185
public int unknownTagLevel = 0;
183186
public Unknown unknown;
187+
private boolean insidePreTag = false;
188+
private boolean insideCodeTag = false;
184189

185190
private String mSource;
186191
private UnknownHtmlSpan.OnUnknownHtmlClickListener onUnknownHtmlClickListener;
@@ -289,9 +294,14 @@ private void handleStartTag(String tag, Attributes attributes, int nestingLevel)
289294
} else if (tag.equalsIgnoreCase("sub")) {
290295
start(spannableStringBuilder, TextFormat.FORMAT_SUBSCRIPT, attributes);
291296
} else if (tag.equalsIgnoreCase("code")) {
297+
insideCodeTag = true;
292298
start(spannableStringBuilder, TextFormat.FORMAT_CODE, attributes);
293299
} else {
294300
if (tagHandler != null) {
301+
if (tag.equalsIgnoreCase("pre")) {
302+
insidePreTag = true;
303+
}
304+
295305
boolean tagHandled = tagHandler.handleTag(true, tag, spannableStringBuilder, onMediaTappedListener,
296306
context, attributes, nestingLevel);
297307
if (tagHandled) {
@@ -364,8 +374,12 @@ private void handleEndTag(String tag, int nestingLevel) {
364374
} else if (tag.equalsIgnoreCase("sub")) {
365375
end(spannableStringBuilder, TextFormat.FORMAT_SUBSCRIPT);
366376
} else if (tag.equalsIgnoreCase("code")) {
377+
insideCodeTag = false;
367378
end(spannableStringBuilder, TextFormat.FORMAT_CODE);
368379
} else if (tagHandler != null) {
380+
if (tag.equalsIgnoreCase("pre")) {
381+
insidePreTag = false;
382+
}
369383
tagHandler.handleTag(false, tag, spannableStringBuilder, onMediaTappedListener, context, new AztecAttributes(),
370384
nestingLevel);
371385
}
@@ -596,14 +610,14 @@ public void characters(char ch[], int start, int length) throws SAXException {
596610
StringBuilder sb = new StringBuilder();
597611

598612
/*
599-
* Ignore whitespace that immediately follows other whitespace;
613+
* Ignore whitespace that immediately follows other whitespace, unless in pre or comment tags;
600614
* newlines count as spaces.
601615
*/
602616

603617
for (int i = 0; i < length; i++) {
604618
char c = ch[i + start];
605619

606-
if (c == ' ' || c == '\n') {
620+
if (!insidePreTag && !insideCodeTag && c == ' ' || c == '\n') {
607621
char pred;
608622
int len = sb.length();
609623

aztec/src/main/kotlin/org/wordpress/aztec/watchers/EndOfParagraphMarkerAdder.kt

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ import android.text.Editable
44
import android.text.Spanned
55
import android.text.TextWatcher
66
import org.wordpress.aztec.AztecText
7-
import org.wordpress.aztec.spans.AztecHeadingSpan
8-
import org.wordpress.aztec.spans.AztecListItemSpan
9-
import org.wordpress.aztec.spans.EndOfParagraphMarker
7+
import org.wordpress.aztec.spans.*
108
import java.lang.ref.WeakReference
119

1210
class EndOfParagraphMarkerAdder(aztecText: AztecText, val verticalParagraphMargin: Int) : TextWatcher {
@@ -32,21 +30,29 @@ class EndOfParagraphMarkerAdder(aztecText: AztecText, val verticalParagraphMargi
3230
val inputStart = textChangedEventDetails.inputStart
3331
val inputEnd = textChangedEventDetails.inputEnd
3432

35-
val isInsideList = aztecText.text.getSpans(inputStart, inputEnd, AztecListItemSpan::class.java).isNotEmpty()
36-
var insideHeading = aztecText.text.getSpans(inputStart, inputEnd, AztecHeadingSpan::class.java).isNotEmpty()
37-
38-
if (insideHeading && (aztecText.text.length > inputEnd
39-
&& aztecText.text[inputEnd] == '\n')) {
40-
insideHeading = false
41-
}
42-
43-
if (!isInsideList && !insideHeading) {
33+
if (paragraphMarkerCanBeApplied(aztecText.text)) {
4434
aztecText.text.setSpan(EndOfParagraphMarker(verticalParagraphMargin), inputStart, inputEnd,
4535
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
4636
}
4737
}
4838
}
4939

40+
fun paragraphMarkerCanBeApplied(text: Editable): Boolean {
41+
val inputStart = textChangedEventDetails.inputStart
42+
val inputEnd = textChangedEventDetails.inputEnd
43+
44+
val isInsideList = text.getSpans(inputStart, inputEnd, AztecListItemSpan::class.java).isNotEmpty()
45+
val isInsidePre = text.getSpans(inputStart, inputEnd, AztecPreformatSpan::class.java).isNotEmpty()
46+
val isInsideCode = text.getSpans(inputStart, inputEnd, AztecCodeSpan::class.java).isNotEmpty()
47+
var insideHeading = text.getSpans(inputStart, inputEnd, AztecHeadingSpan::class.java).isNotEmpty()
48+
49+
if (insideHeading && (text.length > inputEnd && text[inputEnd] == '\n')) {
50+
insideHeading = false
51+
}
52+
53+
return !isInsideList && !insideHeading && !isInsidePre && !isInsideCode
54+
}
55+
5056
override fun afterTextChanged(text: Editable) {
5157
text.getSpans(0, text.length, EndOfParagraphMarker::class.java).forEach {
5258
text.setSpan(it, text.getSpanStart(it), text.getSpanEnd(it), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

aztec/src/test/kotlin/org/wordpress/aztec/PreformatTest.kt

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class PreformatTest {
5858
safeAppend(editText, "\n")
5959
safeAppend(editText, "\n")
6060
safeAppend(editText, "not preformat")
61-
Assert.assertEquals("<$tag>first item\n\nsecond item</$tag>\n\nnot preformat", editText.toHtml())
61+
Assert.assertEquals("<$tag>first item\nsecond item</$tag>not preformat", editText.toHtml())
6262
}
6363

6464
@Test
@@ -134,7 +134,7 @@ class PreformatTest {
134134
safeAppend(editText, "first item")
135135
safeAppend(editText, "\n")
136136
safeAppend(editText, "second item")
137-
Assert.assertEquals("<$tag>first item\n\nsecond item</$tag>", editText.toHtml())
137+
Assert.assertEquals("<$tag>first item\nsecond item</$tag>", editText.toHtml())
138138
}
139139

140140
@Test
@@ -143,7 +143,7 @@ class PreformatTest {
143143
toolbar.onMenuItemClick(menuPreformat)
144144
editText.append("firstitem")
145145
editText.text.insert(5, "\n")
146-
Assert.assertEquals("<$tag>first\n\nitem</$tag>", editText.toHtml())
146+
Assert.assertEquals("<$tag>first\nitem</$tag>", editText.toHtml())
147147
}
148148

149149
@Test
@@ -152,7 +152,7 @@ class PreformatTest {
152152
editText.fromHtml("<$tag>Preformat 1</$tag><$tag>Preformat 2</$tag>")
153153
val mark = editText.text.indexOf("Preformat 2") - 1
154154
editText.text.insert(mark, "\n")
155-
Assert.assertEquals("<$tag>Preformat 1</$tag>\n<$tag>Preformat 2</$tag>", editText.toHtml())
155+
Assert.assertEquals("<$tag>Preformat 1</$tag><$tag>Preformat 2</$tag>", editText.toHtml())
156156
}
157157

158158
@Test
@@ -181,7 +181,7 @@ class PreformatTest {
181181
editText.fromHtml("<$tag>Preformat 1</$tag><$tag>Preformat 2</$tag>")
182182
val mark = editText.text.indexOf("Preformat 2")
183183
editText.text.insert(mark, "\n")
184-
Assert.assertEquals("<$tag>Preformat 1</$tag><$tag>\n\nPreformat 2</$tag>", editText.toHtml())
184+
Assert.assertEquals("<$tag>Preformat 1</$tag><$tag>\nPreformat 2</$tag>", editText.toHtml())
185185
}
186186

187187
@Test
@@ -223,7 +223,7 @@ class PreformatTest {
223223
val secondMark = safeLength(editText)
224224
safeAppend(editText, "third item")
225225
editText.text.delete(firstMark, secondMark - 1)
226-
Assert.assertEquals("<$tag>first item\n\n\n\nthird item</$tag>", editText.toHtml())
226+
Assert.assertEquals("<$tag>first item\n\nthird item</$tag>", editText.toHtml())
227227
}
228228

229229
@Test
@@ -236,11 +236,11 @@ class PreformatTest {
236236
safeAppend(editText, "\n")
237237
safeAppend(editText, "third item")
238238
safeAppend(editText, "\n")
239-
Assert.assertEquals("<$tag>first item\n\nsecond item\n\nthird item</$tag>", editText.toHtml())
239+
Assert.assertEquals("<$tag>first item\nsecond item\nthird item</$tag>", editText.toHtml())
240240
safeAppend(editText, "\n")
241-
Assert.assertEquals("<$tag>first item\n\nsecond item\n\nthird item</$tag>", editText.toHtml())
241+
Assert.assertEquals("<$tag>first item\nsecond item\nthird item</$tag>", editText.toHtml())
242242
safeAppend(editText, "not preformat")
243-
Assert.assertEquals("<$tag>first item\n\nsecond item\n\nthird item</$tag>\n\nnot preformat", editText.toHtml())
243+
Assert.assertEquals("<$tag>first item\nsecond item\nthird item</$tag>not preformat", editText.toHtml())
244244
}
245245

246246
@Test
@@ -250,7 +250,7 @@ class PreformatTest {
250250
val mark = editText.text.indexOf("second item") + "second item".length
251251
editText.text.insert(mark, "\n")
252252
editText.text.insert(mark + 1, "third item")
253-
Assert.assertEquals("<$tag>first item\nsecond item\n\nthird item</$tag>not preformat", editText.toHtml())
253+
Assert.assertEquals("<$tag>first item\nsecond item\nthird item</$tag>not preformat", editText.toHtml())
254254
}
255255

256256
@Test
@@ -289,17 +289,17 @@ class PreformatTest {
289289
editText.setSelection(safeLength(editText))
290290
safeAppend(editText, "\n")
291291
safeAppend(editText, "third item")
292-
Assert.assertEquals("<$tag>first item\nsecond item\n\nthird item</$tag>", editText.toHtml())
292+
Assert.assertEquals("<$tag>first item\nsecond item\nthird item</$tag>", editText.toHtml())
293293
safeAppend(editText, "\n")
294294
safeAppend(editText, "\n")
295295
val mark = safeLength(editText) - 1
296296
safeAppend(editText, "not preformat")
297-
Assert.assertEquals("<$tag>first item\nsecond item\n\nthird item</$tag>\n\nnot preformat", editText.toHtml())
297+
Assert.assertEquals("<$tag>first item\nsecond item\nthird item</$tag>not preformat", editText.toHtml())
298298
safeAppend(editText, "\n")
299299
safeAppend(editText, "foo")
300-
Assert.assertEquals("<$tag>first item\nsecond item\n\nthird item</$tag>\n\nnot preformat\n\nfoo", editText.toHtml())
300+
Assert.assertEquals("<$tag>first item\nsecond item\nthird item</$tag>not preformat\n\nfoo", editText.toHtml())
301301
editText.text.delete(mark, mark + 1)
302-
Assert.assertEquals("<$tag>first item\nsecond item\n\nthird itemnot preformat</$tag>\n\nfoo", editText.toHtml())
302+
Assert.assertEquals("<$tag>first item\nsecond item\nthird itemnot preformat</$tag>\n\nfoo", editText.toHtml())
303303
}
304304

305305
@Test
@@ -316,7 +316,7 @@ class PreformatTest {
316316
editText.text.insert(editText.text.indexOf("not preformat") - 1, "\n")
317317
editText.text.insert(editText.text.indexOf("not preformat") - 1, "third item")
318318
Assert.assertEquals("first item\nsecond item addition\nthird item\nnot preformat", editText.text.toString())
319-
Assert.assertEquals("<$tag>first item\nsecond item addition\n\nthird item</$tag>not preformat", editText.toHtml())
319+
Assert.assertEquals("<$tag>first item\nsecond item addition\nthird item</$tag>not preformat", editText.toHtml())
320320
}
321321

322322
@Test
@@ -330,9 +330,9 @@ class PreformatTest {
330330
safeAppend(editText, "\n")
331331
safeAppend(editText, "\n")
332332
safeAppend(editText, "not preformat")
333-
Assert.assertEquals("<$tag>first item\n\nsecond item</$tag>\n\nnot preformat", editText.toHtml())
333+
Assert.assertEquals("<$tag>first item\nsecond item</$tag>not preformat", editText.toHtml())
334334
editText.text.insert(mark, " (addition)")
335-
Assert.assertEquals("<$tag>first item\n\nsecond item (addition)</$tag>\n\nnot preformat", editText.toHtml())
335+
Assert.assertEquals("<$tag>first item\nsecond item (addition)</$tag>not preformat", editText.toHtml())
336336
}
337337

338338
@Test
@@ -344,7 +344,7 @@ class PreformatTest {
344344
safeAppend(editText, "second item")
345345
editText.setSelection(0)
346346
editText.text.insert(0, "addition ")
347-
Assert.assertEquals("<$tag>addition first item\n\nsecond item</$tag>", editText.toHtml())
347+
Assert.assertEquals("<$tag>addition first item\nsecond item</$tag>", editText.toHtml())
348348
}
349349

350350
@Test
@@ -359,7 +359,7 @@ class PreformatTest {
359359
safeAppend(editText, "second item")
360360
editText.setSelection(mark)
361361
editText.text.insert(mark, "addition ")
362-
Assert.assertEquals("not preformat\n<$tag>addition first item\n\nsecond item</$tag>", editText.toHtml())
362+
Assert.assertEquals("not preformat\n<$tag>addition first item\nsecond item</$tag>", editText.toHtml())
363363
}
364364

365365
@Test
@@ -377,8 +377,8 @@ class PreformatTest {
377377
Assert.assertEquals("first item\nsecond item\nthird item", editText.text.toString())
378378
editText.text.delete(firstMark + 1, secondMark)
379379
Assert.assertEquals("first item\n\nthird item", editText.text.toString())
380-
Assert.assertEquals("<$tag>first item\n\n\n\nthird item</$tag>", editText.toHtml())
380+
Assert.assertEquals("<$tag>first item\n\nthird item</$tag>", editText.toHtml())
381381
editText.text.delete(0, firstMark)
382-
Assert.assertEquals("<$tag>\n\n\n\nthird item</$tag>", editText.toHtml())
382+
Assert.assertEquals("<$tag>\n\nthird item</$tag>", editText.toHtml())
383383
}
384384
}

0 commit comments

Comments
 (0)