Skip to content

Commit 42fb60e

Browse files
authored
fix: normalizer keeping empty src (#743)
# Summary Now if no `src` attribute is present inside `<img>`, the normalizer adds an empty one - `src=""`. This is done for the sake of structural consistency, which also fixed a couple of issues: - on web, when you inserted an `<img>` with no `src` attribute, the inline image would get dropped, whereas we want to still display the placeholder - on iOS and Android, the parser would break if passed an empty `src` or no at all ## Test Plan Set input's value with a `<img>` tag and a `src=""`, `src="something" and no attribute at all. Each case should have the same effect - a placeholder inline image. ## Screenshots / Videos iOS Before: https://github.com/user-attachments/assets/5fbd6bf4-1170-497e-a539-45fdc7509111 After: https://github.com/user-attachments/assets/b794d6d9-e3f1-4622-88e3-d677c32812da ## Compatibility | OS | Implemented | | ------- | :---------: | | iOS | ✅ | | Android | ✅ | | Web | ✅ | ## Checklist - [x] E2E tests are passing - [ ] Required E2E tests have been added (if applicable)
1 parent d389e5f commit 42fb60e

5 files changed

Lines changed: 21 additions & 3 deletions

File tree

cpp/parser/GumboNormalizer.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,12 @@ static void emit_attributes(GumboElement *el, const char *tag_name,
491491
if (strcmp(tag_name, "a") == 0) {
492492
emit_one_attr(out, el, "href");
493493
} else if (strcmp(tag_name, "img") == 0) {
494-
emit_one_attr(out, el, "src");
494+
const char *src_val = get_attr(el, "src");
495+
if (src_val && src_val[0]) {
496+
emit_one_attr(out, el, "src");
497+
} else {
498+
buffer_append_str(out, " src=\"\"");
499+
}
495500
emit_one_attr(out, el, "alt");
496501
emit_one_attr(out, el, "width");
497502
emit_one_attr(out, el, "height");

cpp/tests/GumboParserTest.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,11 @@ TEST(GumboParserTest, EnrichedTagRemappings) {
282282
EXPECT_EQ(
283283
GumboParser::normalizeHtml("<img src='x' width='100' height='100' />"),
284284
"<img src=\"x\" width=\"100\" height=\"100\" />");
285+
EXPECT_EQ(GumboParser::normalizeHtml("<img width=\"100\" height=\"100\" />"),
286+
"<img src=\"\" width=\"100\" height=\"100\" />");
287+
EXPECT_EQ(GumboParser::normalizeHtml(
288+
"<img src=\"\" width=\"100\" height=\"100\" />"),
289+
"<img src=\"\" width=\"100\" height=\"100\" />");
285290

286291
// Lists
287292
EXPECT_EQ(GumboParser::normalizeHtml("<ul><li>x</li></ul>"),

ios/htmlParser/HtmlParser.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ + (NSArray *_Nonnull)getTextAndStylesFromHtml:(NSString *_Nonnull)fixedHtml
670670
[styleArr addObject:@([ItalicStyle getType])];
671671
} else if ([tagName isEqualToString:@"img"]) {
672672
NSRegularExpression *srcRegex =
673-
[NSRegularExpression regularExpressionWithPattern:@"src=\"([^\"]+)\""
673+
[NSRegularExpression regularExpressionWithPattern:@"src=\"([^\"]*)\""
674674
options:0
675675
error:nullptr];
676676
NSTextCheckingResult *match =

src/web/__tests__/htmlNormalizer.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,14 @@ describe('htmlNormalizer', () => {
262262
"<img src='x' width='100' height='100' />",
263263
'<img src="x" width="100" height="100" />',
264264
],
265+
[
266+
'<img width="100" height="100" />',
267+
'<img src="" width="100" height="100" />',
268+
],
269+
[
270+
'<img src="" width="100" height="100" />',
271+
'<img src="" width="100" height="100" />',
272+
],
265273

266274
// Lists
267275
['<ul><li>x</li></ul>', '<ul><li>x</li></ul>'],

src/web/normalization/htmlNormalizer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ function emitAttributes(el: Element, name: string): string {
267267
return emitOneAttr(el, 'href');
268268
case 'img':
269269
return (
270-
emitOneAttr(el, 'src') +
270+
(el.getAttribute('src') ? emitOneAttr(el, 'src') : ' src=""') +
271271
emitOneAttr(el, 'alt') +
272272
emitOneAttr(el, 'width') +
273273
emitOneAttr(el, 'height')

0 commit comments

Comments
 (0)