Hi,
It would break if you display what’s inside the notes without properly cleaning up? Worst case scenarios: you get some <table>
code displayed on your app, right?
Hi,
It would break if you display what’s inside the notes without properly cleaning up? Worst case scenarios: you get some <table>
code displayed on your app, right?
Well, no, it depends on how an app is specifically parsing the rich text. Worst case scenario is that the app crashes if it encounters an unknown html element. Just depends on how the code is written.
(FYI I’m speaking generally, not about my app!)
Yep @Phil_Seeman 's comment is spot on. Your app shouldn’t crash if it can handle arbitrary html tags correctly.
Good point, thanks to both of you.
Well, it will affect in some way. I’m close to releasing Prana, my lightweight Mac client for Asana. It’s mostly a native Mac app, but for HTML editing I use an embedded web view with the Quill editor, configured as possibly close to how it was configured in Asana (I think Asana used to use Quill in the past). I couldn’t get the official configuration, of course, but I limited it to available options, more or less. And then there’s this little bit of processing related to everything being wrapped in body
tags. So, the effect on Prana will depend on what it’ll require from the editor. But I mostly don’t parse the HTML directly in Swift.
Please don’t forget about <img>
!!
One inline image worth 1000 words, so please allow it. Almost every modern text editor supports this.
We’re definitely considering those! Project briefs support them, and we’re investigating that as part of our rollout
Update: We have finalized the tags and attributes for all new rich text formats and created guidelines for handling new tags in the future. Please feel free to leave questions or comments below, including how this may affect your apps. Before launch, we’ll be publishing this content on our developer docs.
For examples in this post, we’ve added indentation and newlines to make it easier to read. When implemented, rich text routes won’t include these.
<h1></h1>
and <h2></h2>
Attributes: None
Inner content: Only <strong>
, <em>
, <u>
, <s>
, <code>
, <a>
allowed inside header tags, and no new line character allowed in the inner content.
Example: <h1>This is a header with some <strong>Strong<strong> and <em>Emphasized</em> words</h1>
Notes:
Note that we do not support h3+.
These are rendered like a heading element if possible, otherwise should be rendered as bold.
<hr>
Attributes: None
Inner content: None
Example: <hr>
Notes:
This is an empty element, i.e. no closing tag.
These are rendered as a horizontal rule if possible, otherwise should be rendered as a newline.
<img>
Attributes:
Inner content: None
Example:
<img
data-gid=”12345”
src=”https://s3.amazonaws.com/assets/123/Screenshot.png”
alt=”\nhttps://s3.amazonaws.com/assets/123/Screenshot.png”
style=”display:block;max-width: 100%; margin-left: auto;
margin-right: auto;”
>
Notes:
This is also an empty element, so no closing tag supported.
This represents an image block. Even though <img>
is not a block level element , we render them as blocks in our product. Therefore we also supply a style attribute with “display: block”
. The style attribute also contains other styles to make the image display in a similar fashion as the ones in our project. We will always supply this style attribute.
Attributes required for writes: data-gid
. All other attributes are ignored on write. Note that we do not support referencing external images via the src
attribute - all image blocks have to reference images uploaded to Asana.
We currently have no way to create image blocks through the API, but do plan to provide a route to do this. We will update the forum when this is available.
<object></object>
As part of rich text work, we’ve started adding the ability to embed rich content into text. These include both embedding views for Asana objects, like milestones, as well as external media. When exposing this in the API, we want to both support developers who want to richly display this content in their apps, as well as support a graceful fallback.
To do this, we’re using an <object>
tag. Each tag will have:
type
attribute: This is MIME type. You can use this to determine the type of embed, and decide how you want to display it. This is required for writes.data
attributes: these will contain the data you need to richly display the embed.<object>
tag to display a less rich version of the content. This content will always be constructed and supplied by Asana. Developers will not have control over it - it will be ignored if you create or edit a <object>
tag.<object>
tags are blocks, and we similarly supply a style attribute with “display: block”
. If clients use the inner fallback content, they must render the content as it is and not try to transform it, because we may update the fallback content in the future.
For this launch, we will introduce 3 new types of embeds: external, project milestone, and project goals.
Attributes:
style
: used to help render in a webview.type
: see above.data
: URL to the external media.type
and data
Example:
<object
style=”display:block”
type=”application/vnd.asana.external_media”
data=”https://www.youtube.com/embed/VqnMA3K6-e0”
>
<a href=”https://www.youtube.com/embed/VqnMA3K6-e0”>
https://www.youtube.com/embed/VqnMA3K6-e0
</a>
</object>
Notes: We recommend rendering these as either links or rich previews of the content.
Attributes:
style
: used to help render in a webview.type
: see above.data-project-gid
: the id of the project we want to render milestones for.type
and data-project-gid
Example:
<object
style=”display:block”
type=”application/vnd.asana.project_milestone_list”
data-project-gid=”12345”
>
<a href=”https://app.asana.com/0/12345/list”>project name</a>
<ul>
<li><a href=”https://app.asana.com/0/12345/23456”>milestone name 1</a></li>
<li><a href=”https://app.asana.com/0/12345/23457”>milestone name 2</a></li>
</ul>
</object>
Notes: We recommend rendering this as a list of milestones in the project.
Attributes:
style
: used to help render in a webview.type
: see above.data-project-gid
: the id of the project we want to render goals for.type
and data-project-gid
Example:
<object
style=”display:block”
type=”application/vnd.asana.project_goal_list”
data-project-gid=”12345”
>
<a href=”https://app.asana.com/0/12345/list”>project name</a>
<ul>
<li><a href=”https://app.asana.com/0/goal/23456”>goal name</a></li>
<li><a href=”https://app.asana.com/0/goal/23457”>goal name</a></li>
</ul>
</object>
Notes: We recommend rendering this as a list of goals associated with the project.
<table></table>
, <tr></tr>
and <td></td>
Tags:
<table>
for the table,<tr>
for each table row<td>
for each table cell.Attributes:
<table>
or <tr>
<td>
can have these optional attributes:
colspan
, rowspan
- these denote how much the cell spans in the row and column direction, the same as html. Note that if you provide a colspan
attribute, you must also provide data-cell-widths
(see below)data-cell-widths
- this denotes the width of the cell in pixels. It is a list of comma separated numbers. The length of the list is the same as colspan.width
: this will be the sum of widths in data-cell-widths
. We supply this to make sure that the table cell renders as expected. To set the width, however, use data-cell-widths
Inner content:
<tr>
allowed in <table>
<td>
allowed in <tr>
<strong>
, <em>
, <u>
, <s>
, <code>
, <a>
, <img>
, <ul>
, <ol>
, <li>
allowed in <td>
. New line characters also allowed in <td>
Example:
<table>
<tr>
<td data-colwidth="320" width="320">
Heading 1
</td>
<td data-colwidth="180" width="180">
Heading 2
</td>
<td data-colwidth="120" width="120">
Heading 3
</td>
</tr>
<tr>
<td data-colwidth="320" width="320">
text
<img
data-gid=”12345”
src=”https://s3.amazonaws.com/assets/123/Screenshot.png”
alt=”\nhttps://s3.amazonaws.com/assets/123/Screenshot.png”
style=”display:block;max-width: 100%; margin-left: auto;
margin-right: auto;”
>
</td>
<td colspan="2" data-colwidth="180,120" width="300">
text
<ol>
<li>List iem</li>
<li>List item</li>
</ol>
</td>
</tr>
</table>
We plan to add new rich text elements going forward, and we want you to be able to design parsers and display logic for our rich text in a forward compatible way. To do this, we’re providing two mechanisms for you to be able to parse and display new tags that you don’t explicitly support: giving sane defaults to render it in a webview, and guidelines for how to handle new tags.
You can expect the rich text HTML to render reasonably in a web view if you apply the following css style to the wrapping DOM node:
overflow-wrap: break-word;
white-space: pre-wrap;
Note that this won’t look like it does in Asana necessarily, and you may find that you want to add your own styles.
If you aren’t using a webview, in order to avoid missing or mangled text, here is how you should render tags you don’t explicitly handle:
<object>
with an unhandled typeRender the <object>
tag as a block and render the contained HTML with the same behavior as if it weren’t inside an <object>
. We will never send an <object>
tag nested inside another <object>
tag.
<img>
Fall back to the alt text if the image can’t be displayed. Render \n<alt text>\n
since <img>
are blocks
<img>
It is ok to omit them. Render as a new line if the tag is a block.
Ignore the tag and render whatever is inside. Follow the html convention for whether it is a block or not.
<object>
or <img>
, render it as a blockIt’s ok to ignore tags or attributes on tags that are unknown for rendering/processing. But it’s very important to send everything back (attributes and inner content) to avoid data loss. <object>
is an exception where it’s ok to not send any inner content back (all inner content in <object>
will be ignored).
For editing, even if the tag and attributes are known, if it contains any unknown attributes, it must be treated as unknown.
If a tag is unknown, first determine if the tag is block or inline and render it as a block or inline atomic and non-copiable (and non-cut&paste-able) editor node (all inner content is non-editable). This is because we don’t know if the unknown node has constraints on inner content or where it can appear. The node must also keep track of all attributes and inner content to be serialized back.
Hello there!
My name is Rohan Ranade and I am an Engineering Manager here at Asana. Back in March, we announced upcoming changes to rich text in Asana. I wanted to follow up and provide an update about the launch timeline.
Due to changes in related front end work, this API change is now rolling out in early 2022. Please note that while the timeline is changing, the shape of these new formats is the same as we announced back in March.
Our hope is that this extended launch timeline will give you additional time to make changes to your apps to handle the upcoming formats. We will post updates here with additional resources and more precise details about the launch date as we get closer to 2022.
Thank you!
Hi there!
While you’re at it, would be great to also address HTML escaping/unescaping issues with html_text
parameters. Common sense says such values should have all HTML-special characters escaped, but apparently some of these special characters don’t get unescaped before posting. (An example would be quotation makrs.)
To be exact, it’s the unescaping of single-quote (U+0027 APOSTROPHE) that seem to be problematic, while double-quote (U+0022 QUOTATION MARK) working fine.
Hello there!
We just announced the availability of the preview version of an API to work with project briefs. Since Project Briefs are the first surface in Asana to support these enhanced formats, this API will allow you to experience how the enhanced formats behave, as you prepare your applications for these formats to come to task descriptions in the near future.
The development team is working hard in bringing these enhanced formats to task descriptions and we remain on track for a launch in the next few months.
Thank you!
Thanks for the update! Any more info about when these changes will be coming to task descriptions or comments?
This sounds interesting.
The OP said that the original plan was to launch in early 2022. Do you have any updates?
As per the docs, the new enhanced HTML tags are still in preview for Project Briefs only:
“Please note that the Project Brief API and enhanced rich text features are in preview”
Will enhanced rich text support be rolled out to Task Comments? If so, can it be sooner than later?
If I try using <h1>
in a Comment via the API, i get “XML is invalid”.
Project Briefs don’t get anywhere near as much reading & editing time as Comments - and we really can do with the formatting in Comments, especially headings and tables.
Thanks!
I’m also interested in whether this HTML text support will be rolled out to comments. Any info would be appreciated!
Hey Everyone, we recently posted an update to the rich text launch. The rollout is beginning today.
I tried the table example using the API and keep getting a 400 error.
Hello. Can you please tell me which line break tag? I don’t see it in the documentation