mirror of
https://github.com/restincode/restincode.git
synced 2026-06-11 08:15:18 +02:00
Use jQuery DOM construction ($("<a>").attr().text()) instead of string
concatenation for reference links, preventing HTML injection from
untrusted title values. Pass fallback issue URL through safeUrl().
262 lines
8.8 KiB
HTML
262 lines
8.8 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>Rest In Code - In Memory of</title>
|
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<meta
|
|
name="author"
|
|
content="Connie 'Sunfire' Hill and Rest In Code contributors"
|
|
/>
|
|
|
|
<link rel="stylesheet" href="style.css" />
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Inter:wght@400;500;600&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
<link rel="shortcut icon" type="image/x-icon" href="/images/favicon.png" />
|
|
|
|
<script
|
|
src="https://code.jquery.com/jquery-3.7.0.min.js"
|
|
integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g="
|
|
crossorigin="anonymous"
|
|
></script>
|
|
<script>
|
|
$(function () {
|
|
var person;
|
|
var params = new URLSearchParams(window.location.search);
|
|
if (params.get("name") != null) {
|
|
var name = params.get("name");
|
|
person = "/people/" + name + ".json";
|
|
} else {
|
|
person = "/people/person.json";
|
|
}
|
|
|
|
function safeUrl(url) {
|
|
try {
|
|
var u = new URL(url, window.location.origin);
|
|
return u.protocol === "http:" || u.protocol === "https:"
|
|
? u.href
|
|
: "#";
|
|
} catch (e) {
|
|
return "#";
|
|
}
|
|
}
|
|
|
|
$.getJSON(person, function (data) {
|
|
var fullname = data.firstname + " " + data.lastname;
|
|
if (data.handle != "") {
|
|
fullname += " (" + data.handle + ")";
|
|
}
|
|
|
|
$("title").append(fullname);
|
|
$("#subtitle").append(fullname);
|
|
$("#memorial-name").append(fullname);
|
|
$(".birth").append(data.birth);
|
|
$(".death").append(data.death);
|
|
$(".issue").append(data.issue);
|
|
|
|
if (data.affiliations == null || data.affiliations == "") {
|
|
$(".affiliations").append("None");
|
|
} else {
|
|
$(".affiliations").append(data.affiliations);
|
|
}
|
|
|
|
if (data.obituary != null && data.obituary != "") {
|
|
$(".obituary").append(
|
|
'<a href="' + safeUrl(data.obituary) + '">Obituary</a>',
|
|
);
|
|
}
|
|
|
|
if (data.issue == null || data.issue == "") {
|
|
data.issue =
|
|
"https://github.com/restincode/restincode/blob/master/CONTRIBUTING.md";
|
|
} else {
|
|
data.issue =
|
|
"https://github.com/restincode/restincode/issues/" + data.issue;
|
|
}
|
|
|
|
if (data.mainimage == "") {
|
|
$(".memorial-main-image")
|
|
.attr("src", "/images/face-silhouette-clipart.png")
|
|
.attr("alt", "placeholder photo");
|
|
} else {
|
|
$(".memorial-main-image")
|
|
.attr("src", data.mainimage)
|
|
.attr("alt", "Main photo of " + fullname);
|
|
}
|
|
|
|
if (data.maintext == "") {
|
|
$("#memorial-text").append(
|
|
"<p>No information has been submitted for this person. Help us by submitting <a href='" +
|
|
data.issue +
|
|
"'>here.</a></p>",
|
|
);
|
|
} else {
|
|
$("#memorial-text").append(data.maintext);
|
|
}
|
|
|
|
if (
|
|
!Array.isArray(data.socialmedialinks) ||
|
|
!data.socialmedialinks.length
|
|
) {
|
|
$("#social-media").append(
|
|
"<p>No social media links have been submitted for this person. Help us by submitting <a href='" +
|
|
data.issue +
|
|
"'>here.</a></p>",
|
|
);
|
|
} else {
|
|
for (var s = 0; s < data.socialmedialinks.length; s++) {
|
|
var sitename = data.socialmedialinks[s]["sitename"];
|
|
var siteurl = data.socialmedialinks[s]["siteurl"];
|
|
var social =
|
|
'<a href="' + safeUrl(siteurl) + '">' + sitename + "</a>";
|
|
$("#social-media").append(social);
|
|
}
|
|
}
|
|
|
|
if (!Array.isArray(data.references) || !data.references.length) {
|
|
$("#references").append(
|
|
$("<p>").append(
|
|
"No references have been submitted for this person. Help us by submitting ",
|
|
$("<a>").attr("href", safeUrl(data.issue)).text("here."),
|
|
),
|
|
);
|
|
} else {
|
|
for (var r = 0; r < data.references.length; r++) {
|
|
$("#references").append(
|
|
$("<a>")
|
|
.attr("href", safeUrl(data.references[r]["url"]))
|
|
.text(data.references[r]["title"]),
|
|
);
|
|
}
|
|
}
|
|
|
|
if (
|
|
!Array.isArray(data.contributions) ||
|
|
!data.contributions.length
|
|
) {
|
|
$("#contributions-list").append(
|
|
"<li>No contributions have been submitted for this person. Help us by submitting <a href='" +
|
|
data.issue +
|
|
"'>here.</a></li>",
|
|
);
|
|
} else {
|
|
for (var x = 0; x < data.contributions.length; x++) {
|
|
var title = data.contributions[x]["title"];
|
|
var url = data.contributions[x]["url"];
|
|
var text = data.contributions[x]["description"];
|
|
var cont;
|
|
if (url == "") {
|
|
cont = "<li><b>" + title + "</b> - " + text + "</li>";
|
|
} else {
|
|
cont =
|
|
"<li><a href='" +
|
|
safeUrl(url) +
|
|
"'>" +
|
|
title +
|
|
"</a> - " +
|
|
text +
|
|
"</li>";
|
|
}
|
|
$("#contributions-list").append(cont);
|
|
}
|
|
}
|
|
|
|
if (!Array.isArray(data.gallery) || !data.gallery.length) {
|
|
$("#nogallery").append(
|
|
"<p>No images have been submitted for this person yet. Help us by submitting <a href='" +
|
|
data.issue +
|
|
"'>here.</a></p>",
|
|
);
|
|
} else {
|
|
for (var i = 0; i < data.gallery.length; i++) {
|
|
var imgurl = safeUrl(data.gallery[i]["url"]);
|
|
var imgtitle = data.gallery[i]["title"];
|
|
var caption = data.gallery[i]["caption"];
|
|
var image =
|
|
"<figure class='memorial-gallery'><img src='" +
|
|
imgurl +
|
|
"' alt='" +
|
|
imgtitle +
|
|
"' loading='lazy'><figcaption>" +
|
|
caption +
|
|
"</figcaption></figure>";
|
|
$("#gallery").append(image);
|
|
}
|
|
}
|
|
|
|
$(".loading-message").remove();
|
|
}).fail(function () {
|
|
$(".loading-message").replaceWith(
|
|
'<p class="error-message">Unable to load memorial data. The person may not exist or there was a network error.</p>',
|
|
);
|
|
});
|
|
});
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<a href="#main-content" class="skip-link">Skip to content</a>
|
|
|
|
<header>
|
|
<div class="header-inner">
|
|
<h1 id="main-title">
|
|
RestInCode - <span id="subtitle">In Memory of </span>
|
|
</h1>
|
|
<nav class="header-nav">
|
|
<a href="about.html">About</a>
|
|
<a href="https://github.com/restincode/restincode">Contribute</a>
|
|
<a href="https://github.com/restincode/restincode/issues">Contact</a>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<main id="main-content" class="memorial-layout">
|
|
<a href="index.html" class="back-link">← Back to memorials</a>
|
|
|
|
<h2 id="memorial-name"></h2>
|
|
|
|
<div class="memorial-content">
|
|
<article class="memorial-main">
|
|
<img src="#" alt="memorial image" class="memorial-main-image" />
|
|
<div id="memorial-text">
|
|
<p class="loading-message">Loading memorial...</p>
|
|
</div>
|
|
|
|
<hr />
|
|
<h3>Contributions</h3>
|
|
<ul id="contributions-list"></ul>
|
|
|
|
<hr />
|
|
<section id="gallery-section" aria-label="Photo gallery">
|
|
<h3>Gallery</h3>
|
|
<div id="nogallery">
|
|
<div id="gallery"></div>
|
|
</div>
|
|
</section>
|
|
</article>
|
|
|
|
<aside>
|
|
<p class="birth"><b>Born:</b></p>
|
|
<p class="death"><b>Died:</b></p>
|
|
<p class="affiliations"><b>Affiliations:</b><br /></p>
|
|
<p class="obituary"></p>
|
|
<div id="social-media">
|
|
<h4>Social Media</h4>
|
|
</div>
|
|
<div id="references">
|
|
<h4>References</h4>
|
|
</div>
|
|
</aside>
|
|
</div>
|
|
</main>
|
|
|
|
<footer>
|
|
<a href="index.html">← Back to memorials</a> | Memorial content
|
|
belongs to its respective creators and rights holders. We do our best to
|
|
identify and credit them.
|
|
</footer>
|
|
</body>
|
|
</html>
|