client/views: escape HTML

This lets client use < > in tag names.
This commit is contained in:
rr- 2016-06-23 11:41:52 +02:00
parent b957f3ae36
commit 6ea129a9ef
29 changed files with 97 additions and 85 deletions

View file

@ -1,7 +1,7 @@
<div class='comment'>
<div class='avatar'>
<% if (ctx.comment.user.name && ctx.canViewUsers) { %>
<a href='/user/<%= ctx.comment.user.name %>'>
<a href='/user/<%- ctx.comment.user.name %>'>
<% } %>
<%= ctx.makeThumbnail(ctx.comment.user.avatarUrl) %>
@ -15,10 +15,10 @@
<header><!--
--><span class='nickname'><!--
--><% if (ctx.comment.user.name && ctx.canViewUsers) { %><!--
--><a href='/user/<%= ctx.comment.user.name %>'><!--
--><a href='/user/<%- ctx.comment.user.name %>'><!--
--><% } %><!--
--><%= ctx.comment.user.name %><!--
--><%- ctx.comment.user.name %><!--
--><% if (ctx.comment.user.name && ctx.canViewUsers) { %><!--
--></a><!--

View file

@ -10,7 +10,7 @@
--></div><!--
--><div class='edit tab'><!--
--><textarea required minlength=1><%= ctx.comment.text %></textarea><!--
--><textarea required minlength=1><%- ctx.comment.text %></textarea><!--
--></div><!--
--></div>

View file

@ -4,14 +4,14 @@
--><li><!--
--><div class='post-thumbnail'><!--
--><% if (ctx.canViewPosts) { %><!--
--><a href='/post/<%= post.id %>'><!--
--><a href='/post/<%- post.id %>'><!--
--><% } %><!--
--><%= ctx.makeThumbnail(post.thumbnailUrl) %><!--
--><% if (ctx.canViewPosts) { %><!--
--></a><!--
--><% } %><!--
--></div><!--
--><div class='comments-container' data-for='<%= post.id %>'></div><!--
--><div class='comments-container' data-for='<%- post.id %>'></div><!--
--></li><!--
--><% } %><!--
--></ul>

View file

@ -1,4 +1,4 @@
<div class='page'>
<p class='page-header'><span>Page <%= ctx.page %> of <%= ctx.totalPages %></span></p>
<p class='page-header'><span>Page <%- ctx.page %> of <%- ctx.totalPages %></span></p>
<div class='page-content-holder'></div>
</div>

View file

@ -12,4 +12,4 @@
<% } %>
<span class='vim-nav-hint'>add to favorites</span>
</a>
<span class='value'><%= ctx.favoriteCount %></span>
<span class='value'><%- ctx.favoriteCount %></span>

View file

@ -1,6 +1,6 @@
<div class='file-dropper-holder'>
<input type='file' id='<%= ctx.id %>'/>
<label class='file-dropper' for='<%= ctx.id %>'>
<input type='file' id='<%- ctx.id %>'/>
<label class='file-dropper' for='<%- ctx.id %>'>
<% if (ctx.allowMultiple) { %>
Drop files here!
<% } else { %>

View file

@ -1,4 +1,4 @@
<p>By accessing <%= ctx.name %> (&ldquo;Site&rdquo;) you agree to the following
<p>By accessing <%- ctx.name %> (&ldquo;Site&rdquo;) you agree to the following
Terms of Service. If you do not agree to these terms, then please do not access
the Site.</p>

View file

@ -1,7 +1,7 @@
<div class='content-wrapper transparent' id='home'>
<div class='messages'></div>
<header>
<h1><%= ctx.name %></h1>
<h1><%- ctx.name %></h1>
<aside class='stats-container'></aside>
</header>
<% if (ctx.canListPosts) { %>
@ -27,7 +27,7 @@
<% } %>
<div class='post-container'></div>
<footer>
Build <a class='version' href='https://github.com/rr-/szurubooru/commits/master'><%= ctx.version %></a>
Build <a class='version' href='https://github.com/rr-/szurubooru/commits/master'><%- ctx.version %></a>
from <%= ctx.makeRelativeTime(ctx.buildDate) %>
</footer>
</div>

View file

@ -1 +1 @@
Serving <%= ctx.postCount %> posts (<%= ctx.makeFileSize(ctx.diskUsage) %>)
Serving <%- ctx.postCount %> posts (<%= ctx.makeFileSize(ctx.diskUsage) %>)

View file

@ -2,7 +2,7 @@
<ul>
<li>
<% if (ctx.prevLinkActive) { %>
<a class='prev' href='<%= ctx.prevLink %>'>
<a class='prev' href='<%- ctx.prevLink %>'>
<% } else { %>
<a class='prev disabled'>
<% } %>
@ -20,14 +20,14 @@
<% } else { %>
<li>
<% } %>
<a href='<%= page.link %>'><%= page.number %></a>
<a href='<%- page.link %>'><%- page.number %></a>
</li>
<% } %>
<% } %>
<li>
<% if (ctx.nextLinkActive) { %>
<a class='next' href='<%= ctx.nextLink %>'>
<a class='next' href='<%- ctx.nextLink %>'>
<% } else { %>
<a class='next disabled'>
<% } %>

View file

@ -1,5 +1,5 @@
<div class='not-found'>
<img src='/img/404.png' alt='404 Not found'/>
<p><%= ctx.path %> is not a valid URL.</p>
<p><%- ctx.path %> is not a valid URL.</p>
<p><a href='/'>Back to main page</a></p>
</div>

View file

@ -4,9 +4,9 @@
<article class='next-post'>
<% if (ctx.nextPostId) { %>
<% if (ctx.searchQuery && ctx.searchQuery.text) { %>
<a href='/post/<%= ctx.nextPostId %>/text=<%= ctx.searchQuery.text %>'>
<a href='/post/<%- ctx.nextPostId %>/text=<%- ctx.searchQuery.text %>'>
<% } else { %>
<a href='/post/<%= ctx.nextPostId %>'>
<a href='/post/<%- ctx.nextPostId %>'>
<% } %>
<% } else { %>
<a class='inactive'>
@ -18,9 +18,9 @@
<article class='previous-post'>
<% if (ctx.prevPostId) { %>
<% if (ctx.searchQuery && ctx.searchQuery.text) { %>
<a href='/post/<%= ctx.prevPostId %>/text=<%= ctx.searchQuery.text %>'>
<a href='/post/<%- ctx.prevPostId %>/text=<%- ctx.searchQuery.text %>'>
<% } else { %>
<a href='/post/<%= ctx.prevPostId %>'>
<a href='/post/<%- ctx.prevPostId %>'>
<% } %>
<% } else { %>
<a class='inactive'>
@ -31,16 +31,16 @@
</article>
<article class='edit-post'>
<% if (ctx.editMode) { %>
<a href='/post/<%= ctx.post.id %>'>
<a href='/post/<%- ctx.post.id %>'>
<i class='fa fa-eye'></i>
<span class='vim-nav-hint'>Back to view mode</span>
</a>
<% } else { %>
<% if (ctx.canEditPosts) { %>
<% if (ctx.searchQuery && ctx.searchQuery.text) { %>
<a href='/post/<%= ctx.post.id %>/edit/text=<%= ctx.searchQuery.text %>'>
<a href='/post/<%- ctx.post.id %>/edit/text=<%- ctx.searchQuery.text %>'>
<% } else { %>
<a href='/post/<%= ctx.post.id %>/edit'>
<a href='/post/<%- ctx.post.id %>/edit'>
<% } %>
<% } else { %>
<a class='inactive'>

View file

@ -1,13 +1,13 @@
<div class='post-content post-type-<%= ctx.post.type %>'>
<div class='post-content post-type-<%- ctx.post.type %>'>
<% if (['image', 'animation'].includes(ctx.post.type)) { %>
<img alt='' src='<%= ctx.post.contentUrl %>'/>
<img alt='' src='<%- ctx.post.contentUrl %>'/>
<% } else if (ctx.post.type === 'flash') { %>
<object width='<%= ctx.post.canvasWidth %>' height='<%= ctx.post.canvasHeight %>' data='<%= ctx.post.contentUrl %>'>
<object width='<%- ctx.post.canvasWidth %>' height='<%- ctx.post.canvasHeight %>' data='<%- ctx.post.contentUrl %>'>
<param name='wmode' value='opaque'/>
<param name='movie' value='<%= ctx.post.contentUrl %>'/>
<param name='movie' value='<%- ctx.post.contentUrl %>'/>
</object>
<% } else if (ctx.post.type === 'video') { %>
@ -18,7 +18,7 @@
<video id='video' controls>
<% } %>
<source type='<%= ctx.post.mimeType %>' src='<%= ctx.post.contentUrl %>'/>
<source type='<%- ctx.post.mimeType %>' src='<%- ctx.post.contentUrl %>'/>
Your browser doesn't support HTML5 videos.
</video>

View file

@ -1,9 +1,9 @@
<article class='details'>
<section class='download'>
<a rel='external' href='<%= ctx.post.contentUrl %>'>
<a rel='external' href='<%- ctx.post.contentUrl %>'>
<i class='fa fa-download'></i><!--
--><%= ctx.makeFileSize(ctx.post.fileSize) %> <!--
--><%= {
--><%- {
'image/gif': 'GIF',
'image/jpeg': 'JPEG',
'image/png': 'PNG',
@ -11,7 +11,7 @@
'application/x-shockwave-flash': 'SWF',
}[ctx.post.mimeType] %>
</a>
(<%= ctx.post.canvasWidth %>x<%= ctx.post.canvasHeight %>)
(<%- ctx.post.canvasWidth %>x<%- ctx.post.canvasHeight %>)
</section>
<section class='upload-info'>
@ -20,8 +20,8 @@
</section>
<section class='safety'>
<i class='fa fa-circle safety-<%= ctx.post.safety %>'></i><!--
--><%= ctx.post.safety[0].toUpperCase() + ctx.post.safety.slice(1) %>
<i class='fa fa-circle safety-<%- ctx.post.safety %>'></i><!--
--><%- ctx.post.safety[0].toUpperCase() + ctx.post.safety.slice(1) %>
</section>
<section class='zoom'>
@ -33,8 +33,8 @@
<section class='search'>
Search on
<a href='http://iqdb.org/?url=<%= ctx.post.contentUrl %>'>IQDB</a> &middot;
<a href='https://www.google.com/searchbyimage?&image_url=<%= ctx.post.contentUrl %>'>Google Images</a>
<a href='http://iqdb.org/?url=<%- ctx.post.contentUrl %>'>IQDB</a> &middot;
<a href='https://www.google.com/searchbyimage?&image_url=<%- ctx.post.contentUrl %>'>Google Images</a>
</section>
<section class='social'>
@ -45,25 +45,25 @@
</article>
<nav class='tags'>
<h1>Tags (<%= ctx.post.tags.length %>)</h1>
<h1>Tags (<%- ctx.post.tags.length %>)</h1>
<ul><!--
--><% for (let tag of ctx.post.tags) { %><!--
--><li><!--
--><% if (ctx.canViewTags) { %><!--
--><a href='/tag/<%= tag %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
--><a href='/tag/<%- tag %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
--><i class='fa fa-tag'></i><!--
--><% } %><!--
--><% if (ctx.canListPosts) { %><!--
--></a><!--
--><% } %><!--
--><% if (ctx.canListPosts) { %><!--
--><a href='/posts/text=<%= tag %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
--><a href='/posts/text=<%- tag %>' class='<%= ctx.makeCssName(ctx.getTagCategory(tag), 'tag') %>'><!--
--><% } %><!--
--><%= tag %><!--
--><%- tag %><!--
--><% if (ctx.canListPosts) { %><!--
--></a><!--
--><% } %><!--
--><span class='count'><%= ctx.getTagUsages(tag) %></span><!--
--><span class='count'><%- ctx.getTagUsages(tag) %></span><!--
--></li><!--
--><% } %><!--
--></ul>

View file

@ -9,9 +9,9 @@
</div>
<div class='buttons'>
<input class='mousetrap' type='submit' value='Search'/>
<input data-safety=safe type='button' class='mousetrap safety safety-safe <%= ctx.settings.listPosts.safe ? '' : 'disabled' %>'/>
<input data-safety=sketchy type='button' class='mousetrap safety safety-sketchy <%= ctx.settings.listPosts.sketchy ? '' : 'disabled' %>'/>
<input data-safety=unsafe type='button' class='mousetrap safety safety-unsafe <%= ctx.settings.listPosts.unsafe ? '' : 'disabled' %>'/>
<input data-safety=safe type='button' class='mousetrap safety safety-safe <%- ctx.settings.listPosts.safe ? '' : 'disabled' %>'/>
<input data-safety=sketchy type='button' class='mousetrap safety safety-sketchy <%- ctx.settings.listPosts.sketchy ? '' : 'disabled' %>'/>
<input data-safety=unsafe type='button' class='mousetrap safety safety-unsafe <%- ctx.settings.listPosts.unsafe ? '' : 'disabled' %>'/>
<a class='mousetrap button append' href='/help/search/posts'>Syntax help</a>
</div>
</form>

View file

@ -5,35 +5,35 @@
<li>
<% if (ctx.canViewPosts) { %>
<% if (ctx.searchQuery && ctx.searchQuery.text) { %>
<a href='/post/<%= post.id %>/text=<%= ctx.searchQuery.text %>' title='@<%= post.id %> (<%= post.type %>)&#10;&#10;Tags: <%= post.tags.map(tag => '#' + tag).join(' ') %>'>
<a href='/post/<%- post.id %>/text=<%- ctx.searchQuery.text %>' title='@<%- post.id %> (<%- post.type %>)&#10;&#10;Tags: <%- post.tags.map(tag => '#' + tag).join(' ') %>'>
<% } else { %>
<a href='/post/<%= post.id %>' title='@<%= post.id %> (<%= post.type %>)&#10;&#10;Tags: <%= post.tags.map(tag => '#' + tag).join(' ') %>'>
<a href='/post/<%- post.id %>' title='@<%- post.id %> (<%- post.type %>)&#10;&#10;Tags: <%- post.tags.map(tag => '#' + tag).join(' ') %>'>
<% } %>
<% } else { %>
<a>
<% } %>
<%= ctx.makeThumbnail(post.thumbnailUrl) %>
<span class='type' data-type='<%= post.type %>'>
<%= post.type %>
<span class='type' data-type='<%- post.type %>'>
<%- post.type %>
</span>
<% if (post.score || post.favoriteCount || post.commentCount) { %>
<span class='stats'>
<% if (post.score) { %>
<span class='icon'>
<i class='fa fa-star'></i>
<%= post.score %>
<%- post.score %>
</span>
<% } %>
<% if (post.favoriteCount) { %>
<span class='icon'>
<i class='fa fa-heart'></i>
<%= post.favoriteCount %>
<%- post.favoriteCount %>
</span>
<% } %>
<% if (post.commentCount) { %>
<span class='icon'>
<i class='fa fa-commenting'></i>
<%= post.commentCount %>
<%- post.commentCount %>
</span>
<% } %>
</span>

View file

@ -13,7 +13,7 @@
<i class='fa fa-thumbs-o-up'></i>
</a>
<% } %>
<span class='value'><%= ctx.score %></span>
<span class='value'><%- ctx.score %></span>
<% if (ctx.canScore) { %>
<a class='downvote' href='#'>
<% if (ctx.ownScore == -1) { %>

View file

@ -1,16 +1,16 @@
<div class='content-wrapper tag'>
<h1><%= ctx.tag.names[0] %></h1>
<h1><%- ctx.tag.names[0] %></h1>
<nav class='buttons'><!--
--><ul><!--
--><li data-name='summary'><a href='/tag/<%= ctx.tag.names[0] %>'>Summary</a></li><!--
--><li data-name='summary'><a href='/tag/<%- ctx.tag.names[0] %>'>Summary</a></li><!--
--><% if (ctx.canMerge) { %><!--
--><li data-name='edit'><a href='/tag/<%= ctx.tag.names[0] %>/edit'>Edit</a></li><!--
--><li data-name='edit'><a href='/tag/<%- ctx.tag.names[0] %>/edit'>Edit</a></li><!--
--><% } %><!--
--><% if (ctx.canMerge) { %><!--
--><li data-name='merge'><a href='/tag/<%= ctx.tag.names[0] %>/merge'>Merge with&hellip;</a></li><!--
--><li data-name='merge'><a href='/tag/<%- ctx.tag.names[0] %>/merge'>Merge with&hellip;</a></li><!--
--><% } %><!--
--><% if (ctx.canDelete) { %><!--
--><li data-name='delete'><a href='/tag/<%= ctx.tag.names[0] %>/delete'>Delete</a></li><!--
--><li data-name='delete'><a href='/tag/<%- ctx.tag.names[0] %>/delete'>Delete</a></li><!--
--><% } %><!--
--></ul><!--
--></nav>

View file

@ -1,27 +1,27 @@
<tr data-category='<%= ctx.tagCategory.name %>'
<tr data-category='<%- ctx.tagCategory.name %>'
<% if (ctx.tagCategory.isDefault) { %> class='default' <% } %>
>
<td class='name'>
<% if (ctx.canEditName) { %>
<%= ctx.makeTextInput({value: ctx.tagCategory.name, required: true}) %>
<% } else { %>
<%= ctx.tagCategory.name %>
<%- ctx.tagCategory.name %>
<% } %>
</td>
<td class='color'>
<% if (ctx.canEditColor) { %>
<%= ctx.makeColorInput({value: ctx.tagCategory.color}) %>
<% } else { %>
<%= ctx.tagCategory.color %>
<%- ctx.tagCategory.color %>
<% } %>
</td>
<td class='usages'>
<% if (ctx.tagCategory.name) { %>
<a href='/tags/text=category:<%= ctx.tagCategory.name %>'>
<%= ctx.tagCategory.tagCount %>
<a href='/tags/text=category:<%- ctx.tagCategory.name %>'>
<%- ctx.tagCategory.tagCount %>
</a>
<% } else { %>
<%= ctx.tagCategory.tagCount %>
<%- ctx.tagCategory.tagCount %>
<% } %>
</td>
<% if (ctx.canDelete) { %>

View file

@ -2,7 +2,7 @@
<form>
<% if (ctx.tag.postCount) { %>
<p>For extra <s>paranoia</s> safety, only tags that are unused can be deleted.</p>
<p>Check <a href='/posts/text=<%= ctx.tag.names[0] %>'>which posts</a> are tagged with <%= ctx.tag.names[0] %>.</p>
<p>Check <a href='/posts/text=<%- ctx.tag.names[0] %>'>which posts</a> are tagged with <%- ctx.tag.names[0] %>.</p>
<% } else { %>
<div class='input'>
<ul>

View file

@ -2,7 +2,7 @@
<section class='details'>
<section>
Category:
<span class='<%= ctx.makeCssName(ctx.tag.category, 'tag') %>'><%= ctx.tag.category %></span>
<span class='<%= ctx.makeCssName(ctx.tag.category, 'tag') %>'><%- ctx.tag.category %></span>
</section>
<section>

View file

@ -71,7 +71,7 @@
<% } %>
</td>
<td class='usages'>
<%= tag.postCount %>
<%- tag.postCount %>
</td>
<td class='edit-time'>
<%= ctx.makeRelativeTime(tag.lastEditTime) %>

View file

@ -2,8 +2,8 @@
--><ul><!--
--><% for (let item of ctx.items) { %><!--
--><% if (item.available) { %><!--
--><li data-name='<%= item.key %>'><!--
--><a href='<%= item.url %>' accesskey='<%= item.accessKey %>'><!--
--><li data-name='<%- item.key %>'><!--
--><a href='<%- item.url %>' accesskey='<%- item.accessKey %>'><!--
--><% if (item.imageUrl) { print(ctx.makeThumbnail(item.imageUrl)); } %><!--
--><span class='text'><%= ctx.makeAccessKey(item.title, item.accessKey) %></span><!--
--></a><!--

View file

@ -1,13 +1,13 @@
<div class='content-wrapper' id='user'>
<h1><%= ctx.user.name %></h1>
<h1><%- ctx.user.name %></h1>
<nav class='buttons'><!--
--><ul><!--
--><li data-name='summary'><a href='/user/<%= ctx.user.name %>'>Summary</a></li><!--
--><li data-name='summary'><a href='/user/<%- ctx.user.name %>'>Summary</a></li><!--
--><% if (ctx.canEditAnything) { %><!--
--><li data-name='edit'><a href='/user/<%= ctx.user.name %>/edit'>Account settings</a></li><!--
--><li data-name='edit'><a href='/user/<%- ctx.user.name %>/edit'>Account settings</a></li><!--
--><% } %><!--
--><% if (ctx.canDelete) { %><!--
--><li data-name='delete'><a href='/user/<%= ctx.user.name %>/delete'>Account deletion</a></li><!--
--><li data-name='delete'><a href='/user/<%- ctx.user.name %>/delete'>Account deletion</a></li><!--
--><% } %><!--
--></ul><!--
--></nav>

View file

@ -3,16 +3,16 @@
<ul class='basic-info'>
<li>Registered: <%= ctx.makeRelativeTime(ctx.user.creationTime) %></li>
<li>Last seen: <%= ctx.makeRelativeTime(ctx.user.lastLoginTime) %></li>
<li>Rank: <%= ctx.user.rankName.toLowerCase() %></li>
<li>Rank: <%- ctx.user.rankName.toLowerCase() %></li>
</ul>
<div>
<nav>
<p><strong>Quick links</strong></p>
<ul>
<li><a href='/posts/text=submit:<%= ctx.user.name %>'><%= ctx.user.uploadedPostCount %> uploads</a></li>
<li><a href='/posts/text=fav:<%= ctx.user.name %>'><%= ctx.user.favoritePostCount %> favorites</a></li>
<li><a href='/posts/text=comment:<%= ctx.user.name %>'><%= ctx.user.commentCount %> comments</a></li>
<li><a href='/posts/text=submit:<%- ctx.user.name %>'><%- ctx.user.uploadedPostCount %> uploads</a></li>
<li><a href='/posts/text=fav:<%- ctx.user.name %>'><%- ctx.user.favoritePostCount %> favorites</a></li>
<li><a href='/posts/text=comment:<%- ctx.user.name %>'><%- ctx.user.commentCount %> comments</a></li>
</ul>
</nav>
@ -20,8 +20,8 @@
<nav>
<p><strong>Only visible to you</strong></p>
<ul>
<li><a href='/posts/text=special:liked'><%= ctx.user.likedPostCount %> liked posts</a></li>
<li><a href='/posts/text=special:disliked'><%= ctx.user.dislikedPostCount %> disliked posts</a></li>
<li><a href='/posts/text=special:liked'><%- ctx.user.likedPostCount %> liked posts</a></li>
<li><a href='/posts/text=special:disliked'><%- ctx.user.dislikedPostCount %> disliked posts</a></li>
</ul>
</nav>
<% } %>

View file

@ -4,7 +4,7 @@
--><li>
<div class='wrapper'>
<% if (ctx.canViewUsers) { %>
<a class='image' href='/user/<%= user.name %>'>
<a class='image' href='/user/<%- user.name %>'>
<% } %>
<%= ctx.makeThumbnail(user.avatarUrl) %>
<% if (ctx.canViewUsers) { %>
@ -12,9 +12,9 @@
<% } %>
<div class='details'>
<% if (ctx.canViewUsers) { %>
<a href='/user/<%= user.name %>'>
<a href='/user/<%- user.name %>'>
<% } %>
<%= user.name %>
<%- user.name %>
<% if (ctx.canViewUsers) { %>
</a>
<% } %>

View file

@ -28,8 +28,9 @@ class TagAutoCompleteControl extends AutoCompleteControl {
return kv2[1].usages - kv1[1].usages;
})
.map(kv => {
const origName = misc.escapeHtml(
tags.getOriginalTagName(kv[0]));
const category = kv[1].category;
const origName = tags.getOriginalTagName(kv[0]);
const usages = kv[1].usages;
const cssName = misc.makeCssName(category, 'tag');
return {

View file

@ -224,6 +224,15 @@ function makeCssName(text, suffix) {
return suffix + '-' + text.replace(/[^a-z0-9]/g, '_');
}
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
}
module.exports = {
range: range,
formatSearchQuery: formatSearchQuery,
@ -236,5 +245,6 @@ module.exports = {
enableExitConfirmation: enableExitConfirmation,
disableExitConfirmation: disableExitConfirmation,
confirmPageExit: confirmPageExit,
escapeHtml: escapeHtml,
makeCssName: makeCssName,
};

View file

@ -198,7 +198,8 @@ function _serializeElement(name, attributes) {
attributes[key] === undefined) {
return '';
}
return `${key}="${attributes[key]}"`;
const attribute = misc.escapeHtml(attributes[key] || '');
return `${key}="${attribute}"`;
}))
.join(' ');
}
@ -446,7 +447,6 @@ module.exports = {
replaceContent: replaceContent,
enableForm: enableForm,
disableForm: disableForm,
clearMessages: clearMessages,
decorateValidator: decorateValidator,
makeVoidElement: makeVoidElement,
makeNonVoidElement: makeNonVoidElement,
@ -454,6 +454,7 @@ module.exports = {
slideDown: slideDown,
slideUp: slideUp,
monitorNodeRemoval: monitorNodeRemoval,
clearMessages: clearMessages,
showError: showError,
showSuccess: showSuccess,
showInfo: showInfo,