-
Notifications
You must be signed in to change notification settings - Fork 331
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
fix: Markdown support in listings templates #11760
Changes from 11 commits
f9a5250
4b4c36b
0f779cf
911207e
8463bc7
0af2dd7
5d1ef85
0aafe42
43ff451
f03ee1e
d52e2ba
2b73ea2
61094dd
9c43d63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
<div class="listing-no-matching d-none"><%- listing.utilities.localizedString("listing-page-no-matches")%></div> | ||
<% if (listing["page-size"] < items.length) { %> | ||
```{=html} | ||
<div class="listing-no-matching d-none"><%= listing.utilities.localizedString("listing-page-no-matches") %></div> | ||
<% if (listing["page-size"] < items.length) { %> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here: |
||
<nav id="<%- listing.id %>-pagination" class="listing-pagination" aria-label="Page Navigation"> | ||
<ul class="pagination"></ul> | ||
</nav> | ||
``` | ||
<% } %> | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,83 +37,147 @@ return !["title", "image", "image-alt", "date", "author", "subtitle", "descripti | |
}); | ||
%> | ||
|
||
<div class="g-col-1" <%= listing.utilities.metadataAttrs(item) %>> | ||
::: {.g-col-1 <%= listing.utilities.metadataAttrs(item) %> } | ||
mcanouil marked this conversation as resolved.
Show resolved
Hide resolved
cscheid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```{=html} | ||
<a href="<%- item.path %>" class="quarto-grid-link"> | ||
<div class="quarto-grid-item card h-100 <%-`card-${align}`%><%= hideBorders ? ' borderless' : '' %>"> | ||
<div class="quarto-grid-item card h-100 <%= `card-${align}` %><%= hideBorders ? ' borderless' : '' %>"> | ||
``` | ||
|
||
<% if (fields.includes('image')) { %> | ||
|
||
<% if (item.image) { %> | ||
|
||
```{=html} | ||
<p class="card-img-top"> | ||
<%= listing.utilities.img(itemNumber, item.image, "thumbnail-image card-img", item['image-alt'], item['image-lazy-loading'] ?? listing['image-lazy-loading']) %> | ||
</p> | ||
``` | ||
|
||
<% } else { %> | ||
|
||
```{=html} | ||
<%= listing.utilities.imgPlaceholder(listing.id, itemNumber, item.outputHref) %> | ||
<% } %> | ||
``` | ||
|
||
<% } %> | ||
<% } %> | ||
|
||
<% if (showField('title') || showField('subtitle') || showField('description') || showField('author') || showField('date') || otherFields.length > 0) { %> | ||
|
||
<div class="card-body post-contents"> | ||
<% if (showField('title')) { %><h5 class="no-anchor card-title listing-title"><%= item.title %></h5><% } %> | ||
<% if (showField('subtitle')) { %><div class="card-subtitle listing-subtitle"><%= item.subtitle %></div><% } %> | ||
<% if (showField('reading-time')) { %><div class="listing-reading-time card-text text-muted"><%= item['reading-time'] %></div> <% } %> | ||
::: {.card-body .post-contents} | ||
|
||
<% if (showField('title')) { %> | ||
<h5 class="no-anchor card-title listing-title"><%= item.title %></h5> | ||
cderv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<% } %> | ||
|
||
<% if (showField('subtitle')) { %> | ||
<div class="card-subtitle listing-subtitle"><%= item.subtitle %></div> | ||
cderv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<% } %> | ||
|
||
<% if (showField('reading-time')) { %> | ||
|
||
```{=html} | ||
<div class="listing-reading-time card-text text-muted"><%= item['reading-time'] %></div> | ||
``` | ||
|
||
<% } %> | ||
|
||
<% if (fields.includes('categories') && item.categories) { %> | ||
|
||
```{=html} | ||
<div class="listing-categories"> | ||
<% for (const category of item.categories) { %> | ||
<div class="listing-category" onclick="window.quartoListingCategory('<%=utils.b64encode(category)%>'); return false;"><%= category %></div> | ||
<% } %> | ||
<% for (const category of item.categories) { %> | ||
<div class="listing-category" onclick="window.quartoListingCategory('<%= utils.b64encode(category ) %>'); return false;"><%= category %></div> | ||
<% } %> | ||
</div> | ||
``` | ||
|
||
<% } %> | ||
|
||
<% if (showField('description')) { %> | ||
|
||
<div class="card-text listing-description delink"><%= item.description %></div> | ||
```{=html} | ||
<div class="card-text listing-description delink"> | ||
``` | ||
|
||
<%= item.description %> | ||
|
||
```{=html} | ||
</div> | ||
``` | ||
|
||
<% } %> | ||
<% | ||
|
||
<% | ||
const flexJustify = showField('author') && showField('date') ? "justify" : showField('author') ? "start" : "end"; | ||
%> | ||
|
||
<% if (showField('author') || showField('date')) { %> | ||
<div class="card-attribution card-text-small <%-flexJustify%>"> | ||
<% if (showField('author')) { %><div class="listing-author"><%= item.author %></div><% } %> | ||
<% if (showField('date')) { %><div class="listing-date"><%= item.date %></div><% } %> | ||
|
||
```{=html} | ||
<div class="card-attribution card-text-small <%- flexJustify %>"> | ||
``` | ||
|
||
<% if (showField('author')) { %> | ||
<div class="listing-author"><%= item.author %></div> | ||
cderv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<% } %> | ||
|
||
<% if (showField('date')) { %> | ||
<div class="listing-date"><%= item.date %></div> | ||
cderv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<% } %> | ||
|
||
```{=html} | ||
</div> | ||
``` | ||
|
||
<% } %> | ||
|
||
<% if (otherFields.length > 0) { %> | ||
|
||
```{=html} | ||
<table class="card-other-values"> | ||
<% for (const field of otherFields) { | ||
let value = readField(item, field); | ||
<% for (const field of otherFields) { | ||
let value = readField(item, field); | ||
%> | ||
<tr> | ||
<td><%= listing.utilities.fieldName(field) %></td> | ||
<td class="<%-field%>"><%= listing.utilities.outputLink(item, field, value) %></td> | ||
<td class="<%- field %>"><%= listing.utilities.outputLink(item, field, value) %></td> | ||
</tr> | ||
<% } %> | ||
</table> | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No markdown supports in metadata with this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency until there is a decision, I switched to using raw blocks except for the lines with the variables to allow markdown. This means, there is still inline HTML. |
||
|
||
<% } %> | ||
|
||
</div> | ||
::: | ||
<% } %> | ||
|
||
<% if (fields.includes('filename') || fields.includes('file-modified')) { %> | ||
|
||
<div class="card-footer"> | ||
::: {.card-footer} | ||
|
||
<% if (fields.includes('filename')) { %> | ||
<div class="card-filename listing-filename"> | ||
<%= item.filename ? item.filename : " " %> | ||
</div> | ||
|
||
```{=html} | ||
<div class="card-filename listing-filename"><%= item.filename ? item.filename : " " %></div> | ||
``` | ||
|
||
<% } %> | ||
|
||
<% if (fields.includes('file-modified')) { %> | ||
<div class="card-file-modified listing-file-modified"> | ||
<%= item['file-modified'] ? item['file-modified'] : " "%> | ||
</div> | ||
|
||
```{=html} | ||
<div class="card-file-modified listing-file-modified"><%= item['file-modified'] ? item['file-modified'] : " " %></div> | ||
``` | ||
|
||
<% } %> | ||
</div> | ||
|
||
::: | ||
<% } %> | ||
</div></a></div> | ||
|
||
```{=html} | ||
</div></a> | ||
``` | ||
|
||
::: |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
:::{.list .quarto-listing-default} | ||
``````{=html} | ||
::: {.list .quarto-listing-default} | ||
|
||
<% for (const item of items) { %> | ||
<% partial('item-default.ejs.md', {listing, item, utils }) %> | ||
<% } %> | ||
`````` | ||
|
||
::: |
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.
localizedString()
usage here will insert a user provided value. I think it is safer to keep using<%-
here, especially when used in HTML attribute, as we can't know which character would be used.Maybe there won't be any
<
used forlisting-page-order-by
but if so, then I think it could break HTML.That is my thinking. If there is a specific reason, I am missing it, so I would really like to understand and learn something new. Why replacing ?
My first though is that using
%<-
for escaping is safer.Thank you
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.
The value is used inside text attribute or inside div which means the content is directly displayed to the users.
Escaping what's supposed to be a string would lead to weird
placeholder
,aria-label
, andoption
text display.Why would the text need escaping? I might have missed something but to me, there are no reasons to escape those values.
Both "work" and both can lead to unexpected outputs when non ASCII string provided.
I don't think there is a perfect solution. The rational being the use of
=
was the same as the overall PR, i.e., allow Markdown/HTML (of course no markdown evaluation is possible anyway when inside raw block).