-
Notifications
You must be signed in to change notification settings - Fork 309
content: Handle <table>
elements
#1031
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
8db80df
to
ce3b7fe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great to see this! I might be jumping on this draft PR too early, but I had a few thoughts from a quick skim 🙂. One comment below, and:
In the 'strong (bold)' tests, let's test that a **bold**
span in a header cell gets a font weight of 900, even when that span is nested inside another span. (900 is 700 from the header-cell styling plus 200 from the bold-span code.) So, another pair of tests like these:
testFontWeight('in spoiler header',
expectedWght: 900,
// ```spoiler regular **bold**
// content
// ```
content: plainContent(
'<div class="spoiler-block"><div class="spoiler-header">\n'
'<p>regular <strong>bold</strong></p>\n'
'</div><div class="spoiler-content" aria-hidden="true">\n'
'<p>content</p>\n'
'</div></div>'
),
styleFinder: findWordBold,
);
testFontWeight('in different kind of span in spoiler header',
expectedWght: 900,
// ```spoiler *italic **bold***
// content
// ```
content: plainContent(
'<div class="spoiler-block"><div class="spoiler-header">\n'
'<p><em>italic <strong>bold</strong></em></p>\n'
'</div><div class="spoiler-content" aria-hidden="true">\n'
'<p>content</p>\n'
'</div></div>'
),
styleFinder: findWordBold,
);
lib/widgets/content.dart
Outdated
.merge(weightVariableTextStyle(context, wght: 700)) | ||
: DefaultTextStyle.of(context).style, | ||
textAlign: node.textAlign)) | ||
: const SizedBox.shrink()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we include the Padding
in this case too? This looks like it could make a cell that doesn't take up any space at all, and I don't think that's consistent with the web app. Here's what the web app does with a table that's nothing but empty cells:
https://chat.zulip.org/#narrow/channel/7-test-here/topic/Chris/near/1971419
and each one does take up some space, and from the inspector it looks like that's coming from some padding (though 4px in all directions instead of 5px).
ce3b7fe
to
8bbca00
Compare
Thanks for the initial comments @chrisbobbe! This is now ready for review, PTAL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Comments below.
I wonder if tools/content/check-features
shows any surprises after implementing table support; do you have time to run that?
lib/model/content.dart
Outdated
@@ -1,3 +1,5 @@ | |||
import 'dart:ui'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might prefer keeping dart:ui
out of our model code, I'm not sure. @gnprice, what do you think? This revision uses this to put TextAlign
enum values in content-node objects. Instead, we could use our own small custom enum and give our widget code the job of invoking dart:ui
code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that adjustment SGTM.
We already import package:flutter/foundation.dart
in a number of places in our model code, I think mostly for ChangeNotifier, and that transitively pulls in dart:ui
. So if something would be messy to do without dart:ui
, it'd be fine to import it.
But referring to something UI-specific like TextAlign
is definitely a good prompt to think about if the logic would best live in our widgets code. In this example, I think this resulting change in the later revision, where this bit of logic moved from the parser to the widget:
switch (cellStyle) {
case null:
- // Default text alignment specified in for `tr > th` element
- // in `web/styles/rendered_markdown.css`:
- // https://github.com/zulip/zulip/blob/d556c0e0a5e9e8ba0ff548354bf2ba6ef2c97d4b/web/styles/rendered_markdown.css#L140
- textAlign = isHeader ? TextAlign.left : null;
+ textAlignment = TableCellTextAlignment.defaults;
+ // The web client sets `text-align: left;` for the header cells,
+ // overriding the default browser alignment (which is `center` for header
+ // and `start` for body). By default, the [Table] widget uses `start` for
+ // text alignment, a saner choice that supports RTL text. So, defer to that.
+ // See discussion:
+ // https://github.com/zulip/zulip-flutter/pull/1031#discussion_r1831950371
+ TableCellTextAlignment.defaults => null,
was a improvement in clarity.
lib/model/content.dart
Outdated
switch (cellStyle) { | ||
case null: | ||
// Default text alignment specified in for `tr > th` element | ||
// in `web/styles/rendered_markdown.css`: | ||
// https://github.com/zulip/zulip/blob/d556c0e0a5e9e8ba0ff548354bf2ba6ef2c97d4b/web/styles/rendered_markdown.css#L140 | ||
textAlign = isHeader ? TextAlign.left : null; | ||
case 'text-align: left;': | ||
textAlign = TextAlign.left; | ||
case 'text-align: center;': | ||
textAlign = TextAlign.center; | ||
case 'text-align: right;': | ||
textAlign = TextAlign.right; | ||
default: | ||
return null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some thoughts on what we're modeling, and how to split responsibilities between model code and UI code.
A message author has four options to set the text alignment of a column's cells (as in GFM):
|: - |
all cells' text left-aligned|: - :|
all cells' text center-aligned| - :|
all cells' text right-aligned| - |
accept default for each cell.
In the HTML we're parsing, the setting is represented as:
- all the column's cells have
style="text-align: left;"
- all the column's cells have
style="text-align: center;"
- all the column's cells have
style="text-align: right;"
- all the column's cells have no
style
attribute.
Putting something on each cell is understandable, I guess, since there isn't a per-column element to attach it to; a table's cells are organized as a list of rows, not columns.
I have doubts about RTL support with the "left" and "right" options, but I don't fully understand the bugs involved, so for now I think it's best to just interpret and apply those options literally. So, as in this revision, left-aligning each cell that has text-align: left;
and right-aligning each cell that has text-align: right;
, whether the text is LTR or RTL. Let's include a TODO(i18n)
pointing to that RTL issue I filed in zulip/zulip.
The "center" option should be fine because center means the same in RTL and LTR.
For the fourth option, "defaults", how about we let UI code handle the specifics of what the defaults are? So, remove (from this file) the code that sets left-alignment for header cells. Web's idea of "default" alignment comes from the user-agent stylesheet (typically start-alignment for non-header cells) and from some custom CSS that you linked to (left-alignment for header cells)1. Actually, web's choice to left-align instead of start-align header cells sounds like a bug that we don't want to carry over; let's start-align all cells. From a quick test, that's the default behavior from Flutter's table widgets anyway, so that'll be easy.
How about representing those four options with an enum, like:
// The text-alignment setting that applies to a cell's column, from the delimiter row.
//
// See GitHub-flavored Markdown:
// https://github.github.com/gfm/#tables-extension-
enum TableColumnTextAlignment {
/// All cells' text left-aligned, represented in Markdown as `|: --- |`.
left, // TODO(i18n) RTL issues? https://github.com/zulip/zulip/issues/32265
/// All cells' text center-aligned, represented in Markdown as `|: --- :|`.
center,
/// All cells' text right-aligned, represented in Markdown as `| --- :|`.
right, // TODO(i18n) RTL issues? https://github.com/zulip/zulip/issues/32265
/// Cells' text aligned the default way, represented in Markdown as `| --- |`.
defaults,
}
? And the widget code does the appropriate thing with those values. It'll be fine to store the value on each cell, given that our representation (like the HTML) lacks a single per-column place for it.
I understand we could get correct behavior by just having a dart:ui
TextAlign?
on the TableCellNode
. But I think it's helpful to connect the HTML to the per-column setting, for readers, and the enum's dartdoc is a convenient place to do that. Also, as mentioned, I like delegating the details of the defaults
option to UI code, even if the details are very simple, as they (currently) are.
Footnotes
-
Apparently the user-agent stylesheet typically center-aligns text in header cells; I guess the custom CSS is a reaction to that. ↩
lib/widgets/content.dart
Outdated
return TableCell( | ||
verticalAlignment: TableCellVerticalAlignment.middle, | ||
child: Padding( | ||
padding: const EdgeInsets.all(4), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
padding: const EdgeInsets.all(4), | |
// Web has 4px padding and 1px border on all sides. | |
// In web, the 1px border grows each cell by 0.5px in all directions. | |
// Our border doesn't affect the layout, it's just painted on, | |
// so we add 0.5px on all sides to match web. | |
padding: const EdgeInsets.all(4 + 0.5), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, found an upstream issue for this: flutter/flutter#78691.
Included the link for reference.
9450a99
to
979b7ce
Compare
Thanks for the review @chrisbobbe! Pushed a new revision. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Small comments below.
lib/model/content.dart
Outdated
// row based and needs alignment information to be per cell. | ||
enum TableCellTextAlignment { | ||
/// Text inside the table cell is left-aligned. | ||
// Represented in markdown as `|: --- |` for the specific column in the delimeter row. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "delimiter" (here and below)
lib/model/content.dart
Outdated
/// The text-alignment that applies to text inside the table cell. | ||
/// | ||
/// See GitHub-flavored Markdown: | ||
/// https://github.github.com/gfm/#tables-extension- | ||
// In Markdown, alignment is defined per column using the delimiter row. | ||
// However, the generated HTML specifies alignment for each cell in a row | ||
// individually, that matches the UI widget implementation which is also | ||
// row based and needs alignment information to be per cell. | ||
enum TableCellTextAlignment { | ||
/// Text inside the table cell is left-aligned. | ||
// Represented in markdown as `|: --- |` for the specific column in the delimeter row. | ||
// TODO(i18n) RTL issues? https://github.com/zulip/zulip/issues/32265 | ||
left, | ||
/// Text inside the table cell is center-aligned. | ||
// Represented in markdown as `|: --- :|` for the specific column in the delimeter row. | ||
center, | ||
/// Text inside the table cell is right-aligned. | ||
// Represented in markdown as `| --- :|` for the specific column in the delimeter row. | ||
// TODO(i18n) RTL issues? https://github.com/zulip/zulip/issues/32265 | ||
right, | ||
/// Text inside the table cell is aligned the default way. | ||
// Represented in markdown as `| --- |` for the specific column in the delimeter row. | ||
defaults | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In how we name and document this enum, I'd like to be more explicit that what's being represented is a per-column setting, in the string from the server and in our model. That's how users experience the feature: we tell them they can set the alignment per-column, but not per individual cell (or for a row, or for the whole table, etc.).
It's true that the enum value is repeated on all of a column's cells, and our parsing logic has to understand that fact in order to recognize what the setting is for a given column. I also think it's fine for our model to repeat something on all of a column's cells too, because that's convenient for our parsing code and our UI code. But when doing those things, I'd still like the per-column abstraction to be clear somewhere, and I think the best place for that is in this enum's name and documentation. As in my proposal in #1031 (comment) :
// The text-alignment setting that applies to a cell's column, from the delimiter row.
//
// See GitHub-flavored Markdown:
// https://github.github.com/gfm/#tables-extension-
enum TableColumnTextAlignment {
/// All cells' text left-aligned, represented in Markdown as `|: --- |`.
left, // TODO(i18n) RTL issues? https://github.com/zulip/zulip/issues/32265
/// All cells' text center-aligned, represented in Markdown as `|: --- :|`.
center,
/// All cells' text right-aligned, represented in Markdown as `| --- :|`.
right, // TODO(i18n) RTL issues? https://github.com/zulip/zulip/issues/32265
/// Cells' text aligned the default way, represented in Markdown as `| --- |`.
defaults,
}
In theory, our parsing code could grow a validation step to make sure the setting is expressed coherently, i.e., scan through a column's cells to check that their style
attribute is consistent. I don't think we have to do that (could be expensive), but I do think it would be consistent with what's supposed to be represented.
I think the explicit per-column abstraction will be helpful when we come back to address the RTL issues. As part of that work, we'll want to get clear ideas of what we expect to happen vs. what's actually happening, at all of the steps from the compose-box input to how the message appears in the message list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, updated the enum's name and the documentation with this proposal.
979b7ce
to
2e5200d
Compare
Thanks for the review @chrisbobbe! Pushed a new revision, PTAL. |
Thanks, LGTM! Marking for Greg's review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @rajveermalviya for building this, and @chrisbobbe for the previous reviews!
Generally this looks great. Various comments below, mainly small.
lib/model/content.dart
Outdated
@override | ||
void debugFillProperties(DiagnosticPropertiesBuilder properties) { | ||
super.debugFillProperties(properties); | ||
properties.add(DiagnosticsProperty<bool>('isHeader', isHeader)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: instead of DiagnosticsProperty<bool>
, use FlagProperty
(see the latter's docs; and for examples, see the handful of existing places we use it in this file)
test/model/content_test.dart
Outdated
static const tableWithDifferentTextAligmentInColumns = ContentExample( | ||
'table with different text aligment in columns', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: spelling
static const tableWithDifferentTextAligmentInColumns = ContentExample( | |
'table with different text aligment in columns', | |
static const tableWithDifferentTextAlignmentInColumns = ContentExample( | |
'table with different text alignment in columns', |
lib/model/content.dart
Outdated
@override | ||
void debugFillProperties(DiagnosticPropertiesBuilder properties) { | ||
super.debugFillProperties(properties); | ||
properties.add(DiagnosticsProperty<TableColumnTextAlignment>('textAlign', textAlignment)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use EnumProperty
And set defaultValue
to TableColumnTextAlignment.defaults
— that way this won't get printed when that's the value, since that's the typical value and it's boring for a cell/column to have that value
lib/model/content.dart
Outdated
case 'blockquote': | ||
case 'div': | ||
case 'table': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: keep in same order as parsing logic above, for ease of comparison
case 'blockquote': | |
case 'div': | |
case 'table': | |
case 'blockquote': | |
case 'table': | |
case 'div': |
lib/model/content.dart
Outdated
TableCellNode? parseTableCell(dom.Element node, bool isHeader) { | ||
assert(node.localName == (isHeader ? 'th' : 'td')); | ||
assert(node.className.isEmpty); | ||
assert(node.attributes.length <= 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our existing parsing code tolerates attributes it didn't expect, while being strict about classes it didn't expect. So let's follow that here.
(It's possible somewhere else would be a better place to draw the line in general. But until we revisit that, it's easier to think about if the line is the same for different types of content.)
lib/widgets/content.dart
Outdated
? _buildBlockInlineContainer( | ||
node: node, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: indentation
? _buildBlockInlineContainer( | |
node: node, | |
? _buildBlockInlineContainer( | |
node: node, |
lib/widgets/content.dart
Outdated
child: node.nodes.isNotEmpty | ||
? _buildBlockInlineContainer( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: put short exceptional case first, then long normal case (just like we regularly do with early returns)
child: node.nodes.isNotEmpty | |
? _buildBlockInlineContainer( | |
child: node.nodes.isEmpty | |
? const SizedBox.shrink() | |
: _buildBlockInlineContainer( |
test/model/content_test.dart
Outdated
]), | ||
]); | ||
|
||
static const tableWithLinksInHeaderCells = ContentExample( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the one with links in body cells can be just one example, with one column and a total of two cells, and a link in each of them.
That'd cover everything these do, right?
test/model/content_test.dart
Outdated
]), | ||
]); | ||
|
||
static const tableWithImagesInCells = ContentExample( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about a version of this with just one column, and one image?
lib/model/content.dart
Outdated
if (node.localName != 'tr') return false; | ||
if (node.className.isNotEmpty) return false; | ||
if (node.attributes.isNotEmpty) return false; | ||
if (node.nodes.isEmpty) return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this case can happen:
https://chat.zulip.org/#narrow/channel/7-test-here/topic/table/near/1987383
| table |
| - |
… Huh but I'm puzzled because the app with this PR handles that message just fine. Not sure how.
Oh I see, it's that the HTML has no tbody
element at all.
Anyway, let's have a test for that edge case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I found this edge case by following the handy link to here: https://github.github.com/gfm/#tables-extension- and then reading through it looking for any odd cases that would make it through to the HTML. That's the only one I found.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, looks like for this case the generated HTML adds the empty <td>
node:
<table>
<thead>
<tr>
<th>table</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
Something similar happens when markdown misses a column in the body row, the generated HTML here again contains an empty <td>
node for the missing cell in markdown:
| a | b |
| - | - |
| a |
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td></td>
</tr>
</tbody>
</table>
I've added tests for these two cases, and kept this assert in to catch if that changes in future.
Additionally, I've also restructured the parsing code for <thead>
and <tbody>
elements to ensure that both nodes are always present.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, looks like for this case the generated HTML adds the empty
<td>
node:
I see — and a <tr>
around that. I guess that also suffices for causing this code (with the rejection on node.nodes.isEmpty
) to work correctly.
I was looking at the GFM spec:
https://github.github.com/gfm/#example-205
but hadn't checked what Zulip actually produces. Good to have checked!
Something similar happens when markdown misses a column in the body row,
Yeah. That part matches the spec:
https://github.github.com/gfm/#example-204
2e5200d
to
0bc7383
Compare
Thanks for the review @gnprice! Pushed a new revision, PTAL. |
lib/model/content.dart
Outdated
properties.add(EnumProperty<TableColumnTextAlignment>( | ||
'textAlignment', textAlignment, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: type can be inferred
properties.add(EnumProperty<TableColumnTextAlignment>( | |
'textAlignment', textAlignment, | |
properties.add(EnumProperty('textAlignment', textAlignment, |
lib/model/content.dart
Outdated
if (node.localName != 'tr') return false; | ||
if (node.className.isNotEmpty) return false; | ||
if (node.attributes.isNotEmpty) return false; | ||
if (node.nodes.isEmpty) return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, looks like for this case the generated HTML adds the empty
<td>
node:
I see — and a <tr>
around that. I guess that also suffices for causing this code (with the rejection on node.nodes.isEmpty
) to work correctly.
I was looking at the GFM spec:
https://github.github.com/gfm/#example-205
but hadn't checked what Zulip actually produces. Good to have checked!
Something similar happens when markdown misses a column in the body row,
Yeah. That part matches the spec:
https://github.github.com/gfm/#example-204
0bc7383
to
0b6fb83
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the revision! Comments below — one more test case and otherwise all nits.
lib/model/content.dart
Outdated
if (tbodyElement.className.isNotEmpty) return null; | ||
if (tbodyElement.nodes.isEmpty) return null; | ||
|
||
late final int headerColumnCount; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can avoid late
:
late final int headerColumnCount; | |
final int headerColumnCount; |
That way the compiler is asked to prove to itself that the variable gets correctly initialized, so we'd get a static error if some future change broke that.
test/model/content_test.dart
Outdated
static const tableWithDifferentTextAlignmentInColumns = ContentExample( | ||
'table with different text aligment in columns', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: bump #1031 (comment) 🙂
static const tableWithDifferentTextAlignmentInColumns = ContentExample( | |
'table with different text aligment in columns', | |
static const tableWithDifferentTextAlignmentInColumns = ContentExample( | |
'table with different text alignment in columns', |
super.debugHtmlNode, | ||
required super.nodes, | ||
required super.links, | ||
required this.textAlignment, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
content: Handle column `text-alignment` in `<table>`
The backticks on "text-alignment
" mark it as code, not prose. When a name is formatted as code, it should match exactly the name of something it's referring to in the code. But I don't think there's anything in the code called text-alignment
.
Could make it not code, just normal English prose:
content: Handle column text-alignment in
<table>
Or could refer to a name found in the code; for example:
content: Handle
text-align
in<table>
(for the CSS property; which then isn't so much about a column as a cell).
lib/model/content.dart
Outdated
properties.add(EnumProperty( | ||
'textAlignment', textAlignment, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: tighten (bump #1031 (comment))
properties.add(EnumProperty( | |
'textAlignment', textAlignment, | |
properties.add(EnumProperty('textAlignment', textAlignment, |
test/model/content_test.dart
Outdated
]) | ||
]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use trailing comma whenever not closing list on same line
]) | |
]); | |
]), | |
]); |
(here and a couple of other spots)
test/model/content_test.dart
Outdated
static const tableWithImagesInCells = ContentExample( | ||
'table with images in cells', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: just one image (and "in cells" is redundant):
static const tableWithImagesInCells = ContentExample( | |
'table with images in cells', | |
static const tableWithImage = ContentExample( | |
'table with image', |
]) | ||
]); | ||
|
||
static const tableWithoutAnyBodyCellsInMarkdown = ContentExample( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a comment to clarify a bit why we bother to have this test case:
static const tableWithoutAnyBodyCellsInMarkdown = ContentExample( | |
// As is, this HTML doesn't look particularly different to our parser. | |
// But if Zulip's table support followed GFM, this would have no <tbody>: | |
// https://github.github.com/gfm/#example-205 | |
// https://github.com/zulip/zulip-flutter/pull/1031#discussion_r1855931989 | |
static const tableWithoutAnyBodyCellsInMarkdown = ContentExample( |
style: widget.style, nodes: widget.nodes); | ||
style: widget.style, nodes: widget.nodes, textAlign: widget.textAlign); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I think this fixes #1031 (comment) .
Let's have a test case that would have caught that bug. Doesn't need to exercise all the possible alignments (that's covered by another test case you already have), just one of them.
0b6fb83
to
f8b1334
Compare
Thanks for the review @gnprice! Pushed a new revision, PTAL. |
Thanks! Looks good; merging. |
Fixes: #360