Skip to content
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

add support for colspan/rowspan in tables #46

Merged
merged 3 commits into from
Sep 14, 2022

Conversation

QuietMisdreavus
Copy link

@QuietMisdreavus QuietMisdreavus commented Aug 2, 2022

Resolves rdar://97739626

Overview and syntax

This PR updates the tables extension to support column span and row span. The design is inspired by the discussion in this CommonMark Forum thread discussing table syntax, as well as precedent set by existing implementations.

Column span is indicated by placing empty cells (with no spaces) after the spanning cell:

| one | two |
| --- | --- |
| hello    ||
Screenshot of rendered result rendering of an HTML table with two columns, where one row says 'hello' spanning both of them

Row span is indicated by placing a caret in cells that should be spanned over:

| one | two   |
| --- | ---   |
| big | small |
| ^   | small |
Screenshot of rendered result rendering of an HTML table with two rows, where one cell says 'big' and spans both rows

These can be combined by indicating column span on cells with the row span indicator:

| one | two | three |
| --- | --- | ----- |
| big      || small |
| ^        || small |
Screenshot of rendered result rendering of an HTML table with three columns and two rows, where one cell says 'big' and spans both rows and two columns

This is a slight breaking change in syntax for tables which wrote empty cells without a space. These cells will now be treated as having column span.

API modifications

A new option flag, CMARK_OPT_TABLE_SPANS, has been added to enable the new syntax. (This was done since there is a slight breakage for existing tables with zero-width cells, which currently are parsed as empty cells.) If this option is absent while parsing, no spanning information is parsed, and the new data fields return their default value.

Table cell nodes have accessor functions to get/set their column span and row span. These are stored in the node's opaque pointer, which is allocated and freed by the table extension. A span value of zero indicates that this cell is being spanned over in the given dimension. When rendering to HTML or other output format that support spanning, these cells should be omitted. Wrapper libraries that use the cmark AST directly (like Swift-Markdown) will need to use these new values to handle spanning information.

A new option flag, CMARK_OPT_TABLE_ROWSPAN_DITTO, has been added to change the row-span sigil from a caret character to a double-quote (or "ditto mark"). This can be set from the cmark-gfm-bin binary via a new flag, --table-rowspan-ditto.

The spec document has been updated to add new cases for column span and row span. These outputs have been verified via make test.

A new accessor function on nodes, cmark_node_nth_child, has been added to return the N'th child of the given node. (This is used in the table extension when handling row span.)

HTML, XML, and CommonMark output has been updated to reflect the spanning syntax and output. (I don't know the LaTeX or troff format for cell spanning, so i haven't updated those. 😅)

cell->cell_data->rowspan = 0;
}
} else {
if (strcmp(cmark_strbuf_cstr(cell->buf), "^") == 0) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should declaring row-spans using caret also be opt-in?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting adding an option(s) to enable spanning behavior in the first place?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I'm wondering if it should be so that existing Markdown content isn't affected by this change, e.g., the test in extensions.txt below

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, if i make spans "opt-in" in this way, there's no way to enable that per-test in the spec documents. So my choices are to either not document it in the spec document, or turn them on for all the spec tests and have the change to extensions.txt regardless. I could see about setting up a new test scaffold just for table spans, but that would complicate the PR more and feel a bit like overkill.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@franklinsch I looked into whether i could add a new test file or flag to use to selectively enable table spans on a specific test file, and it will require changing the python wrapper used in the tests to include a hardcoded option constant that is optionally turned on or off. I'm not comfortable adding a copy/pasted constant to the Python code, since i don't know of a way to automatically populate values from C constants in Python. If we still want to have the table spans be fully optional, we effectively cannot document them. (The tests would need to move into api_test instead of being hosted in the spec docs.) Since i would like to generate and host the spec document for swift-cmark eventually, it would be unfortunate to completely miss this important feature.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition, if we add more options like this, i would prefer it if something like swiftlang/swift-markdown#23 landed alongside it so that users of swift-markdown can use more than just what its default settings are.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned that if we're going to be breaking existing content here. Clients that use this library directly would see a change in behaviour right, at least compared to the upstream fork? This is something that we can enable by default for DocC, though. Or am I missing something?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clients that use Swift-Markdown or Swift-DocC will also see a change in behavior. However, i've already implemented the code change locally to use an option, so i can at least finish the job and move the tests into api_test. I'll push up the change today. (I still want that Swift-Markdown change to land, though, so people who use Swift-Markdown directly can avoid the content breakage.)

@@ -429,7 +429,7 @@ Here's a link to [Freedom Planet 2][].
```````````````````````````````` example
| a | b | c |
| --- | --- | --- |
| d || e |
| d | | e |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question for col spans.

extensions/table.c Outdated Show resolved Hide resolved
extensions/table.c Outdated Show resolved Hide resolved
Copy link

@daniel-grumberg daniel-grumberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@QuietMisdreavus
Copy link
Author

I've pushed a new commit which adds the option CMARK_OPT_TABLE_SPANS, which enables the new behavior. Because the new syntax is being hidden behind an option, i had to move the tests out of the spec doc and into api_test. I've verified that everything still passes with make test.

Copy link

@franklinsch franklinsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants