divan/DiwanRazor/Pages/DiwanPage.cshtml
Anas Rashid eb0a353cf2 Urdu public pages (#2); hide unconfigured semantic search; safe defaults
- translate reading-path views (poet, category, poem, search, header, login, partials)
  from Persian to Urdu (exact-run dictionary, 262 strings; AI-summary data marker kept)
- semantic search widget only when SemanticSearchAPIRoot is configured
- appsettings defaults: no Ganjoor tracking script, no Ganjoor semantic search,
  API/site roots default to the local Diwan stack instead of api.ganjoor.net

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 00:18:00 +02:00

252 lines
9.0 KiB
Plaintext

@page
@model DiwanPageModel
@{
Layout = "_Layout";
}
@if (Model.DiwanPage == null)
{
return;
}
@section Head {
<script src="/js/chart.js"></script>
<script src="/js/jquery.mark.min.js"></script>
<script>
var cookieValue = getCookie("lineNumbers");
var lineNumbers = cookieValue != "false";
</script>
@if ((Model.DiwanPage != null && Model.DiwanPage.NoIndex) || !string.IsNullOrEmpty(Model.PinterestUrl))
{
<meta name="robots" content="noindex, nofollow">
}
@if (Model.DiwanPage != null)
{
<link rel="canonical" href="@Model.CanonicalUrl">
if (Model.IsPoemPage)
{
<script>
var currentPoemId = @Model.DiwanPage.Id;
$(document).ready(function() {
checkWebShareSupport();
if (lineNumbers) {
btshmr(@Model.DiwanPage.Id);
}
checkIfBookmarked(@Model.DiwanPage.Id);
paginateComments();
revealCommentFromUrlHash();
});
</script>
}
<script type="application/ld+json">
{
@Html.Raw(@ViewData["BrearCrumpList"])
}
</script>
}
@if ((Model.IsCatPage || Model.IsPoetPage) && Model.CategoryPoemGeoDateTags != null && Model.CategoryPoemGeoDateTags.Length > 0)
{
<link rel="stylesheet" href="/css/leaflet.css?version=2">
<style>
.leaflet-container {
background-color: #c5e8ff;
}
.leaflet-popup-content {
font-family: 'Vazirmatn'
}
</style>
<script src="~/js/leaflet.js"></script>
<script src="~/js/leaflet-providers.js"></script>
@if (!Model.OfflineMode)
{
<script src="https://cdnjs.cloudflare.com/ajax/libs/OverlappingMarkerSpiderfier-Leaflet/0.2.6/oms.min.js"></script>
}
}
@if (Model.IsPoemPage && Model.DiwanPage.Poem.GeoDateTags.Length > 0)
{
<link rel="stylesheet" href="/css/leaflet.css?version=2">
<style>
.leaflet-container {
background-color: #c5e8ff;
}
.leaflet-popup-content {
font-family: 'Vazirmatn'
}
</style>
<script src="~/js/leaflet.js"></script>
<script src="~/js/leaflet-providers.js"></script>
@if (!Model.OfflineMode)
{
<script src="https://cdnjs.cloudflare.com/ajax/libs/OverlappingMarkerSpiderfier-Leaflet/0.2.6/oms.min.js"></script>
}
}
}
@if (Model.OfflineMode)
{
<div class="notice">
<p>
آپ دیوان کا آف لائن نسخہ دیکھ رہے ہیں.
</p>
<p>
یہ دیوان کا پرانی معلومات والا آف لائن نسخہ ہے.
</p>
<p>
انٹرنیٹ پر منحصر کچھ سہولتیں ہٹا دی گئی ہیں اور کچھ شاید ٹھیک کام نہ کریں.
</p>
<p>
رکنیت اور حاشیہ لکھنے کی سہولت بند ہے؛ یہاں درج کی گئی کوئی بھی چیز محفوظ نہیں رہے گی.
</p>
<p>
دیوان کا تازہ نسخہ انٹرنیٹ پر دستیاب ہے.
</p>
</div>
}
else if (Model.ReadOnlyMode)
{
<div class="notice">
<p>
دیوان اس وقت صرف پڑھنے کے لیے دستیاب ہے.
</p>
<p>
رکنیت اور حاشیہ لکھنے کی سہولت بند ہے؛ یہاں درج کی گئی کوئی بھی چیز محفوظ نہیں رہے گی.
</p>
</div>
}
<partial name="_SearchHeaderPartial" model="@(new _SearchHeaderPartialModel()
{
Poets = Model.Poets,
SelectedPoetId = Model.DiwanPage?.PoetOrCat?.Poet?.Id ?? 0,
CurrentCategory = (!Model.IsPoetPage && Model.DiwanPage?.PoetOrCat != null) ? Model.DiwanPage.PoetOrCat.Cat : null,
WideCategorySelect = false
})" /><!-- #hdr2 -->
<div id="fa">
<partial name="_InlineLoginPartial" model="Model" />
<div id="maincnt">
@if (!string.IsNullOrEmpty(Model.LastError))
{
<div class="poem">
@Model.LastError
</div>
}
else
{
@if (Model.IsPoetPage)
{
<partial name="Partials/DiwanPage/PageTypes/_PoetPagePartial" model="Model" />
}
else if (Model.IsCatPage)
{
<partial name="Partials/DiwanPage/PageTypes/_CatPagePartial" model="Model" />
}
else if (Model.IsPoemPage)
{
<partial name="Partials/DiwanPage/PageTypes/_PoemPagePartial" model="Model" />
}
else
{
<partial name="Partials/DiwanPage/PageTypes/_GenericPagePartial" model="Model" />
}
}
</div>
<partial name="_FooterPartial" model=@(new _FooterPartialModel() { StickyEnabled = true, DiwanPage = Model.DiwanPage }) />
</div>
@{
if (!string.IsNullOrEmpty(Model.PinterestUrl))
{
// PinterestUrl comes straight from the untrusted "pinterest_url" query string
// (see DiwanPage.cshtml.cs). It must never be emitted with @Html.Raw into a
// <script> block - that allowed a reflected XSS via payloads such as
// "</script><script>alert(document.cookie)</script>". Instead it is serialized
// as a JSON string literal (which escapes '<', '>', '&', quotes, etc.) and then
// URL-encoded again before being appended to href values.
<script>
$(function() {
var pinterestUrl = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.PinterestUrl));
$("a").attr('href', function(i, h) {
if (h != null) {
return h + (h.indexOf('?') != -1 ? "&pinterest_url=" + encodeURIComponent(pinterestUrl) : "?pinterest_url=" + encodeURIComponent(pinterestUrl));
}
return h;
});
});
</script>
}
}
@if (Model.IsPoemPage)
{
<script src="/lib/tinymce/tinymce.min.js"></script>
<script>
var userNotifiedOnEditInsteadOfComment = false;
function createInformationNotification() {
tinymce.activeEditor.notificationManager.open({
text: 'گزارش ہے کہ املا یا ٹائپ کی غلطیاں حاشیوں میں بتانے کے بجائے «ترمیم» کا بٹن استعمال کر کے خود درست کریں.',
type: 'info'
});
}
tinymce.init({
selector: 'textarea.editor',
language: 'fa_IR',
menubar: false,
plugins: 'link paste image',
toolbar: 'undo redo | alignleft aligncenter alignright alignjustify | link',
contextmenu: false,
paste_auto_cleanup_on_paste: true,
paste_remove_styles: true,
paste_remove_styles_if_webkit: true,
paste_strip_class_attributes: true,
a11y_advanced_options: true,
skin: (window.matchMedia("(prefers-color-scheme: dark)").matches && localStorage.getItem("scheme") != "light" ? "oxide-dark" : localStorage.getItem("scheme") == "dark" ? "oxide-dark" : "oxide"),
content_css: (window.matchMedia("(prefers-color-scheme: dark)").matches && localStorage.getItem("scheme") != "light" ? "dark" : localStorage.getItem("scheme") == "dark" ? "dark" : false),
setup: function(editor) {
editor.on('tap', function(e, f) {
var editor_id = e.view.frameElement.id.slice(0, -4);
if (editor_id != 'editNoteText') {
if (userNotifiedOnEditInsteadOfComment == false) {
userNotifiedOnEditInsteadOfComment = true;
createInformationNotification();
}
}
},
);
editor.on('click', function(e, f) {
var editor_id = e.view.frameElement.id.slice(0, -4);
if (editor_id != 'editNoteText') {
if (userNotifiedOnEditInsteadOfComment == false) {
userNotifiedOnEditInsteadOfComment = true;
createInformationNotification();
}
}
},
);
},
});
</script>
}
@if (ViewData["TrackingScript"] != null && !string.IsNullOrEmpty(ViewData["TrackingScript"].ToString()))
{
@Html.Raw(ViewData["TrackingScript"])
}
<script>
document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll("table.stats").forEach(table => {
plotChart(table.getAttribute("id"));
});
});
</script>