Sweep all .cshtml files for encoding corruption; add pre-commit guard

Replace all corruption variants with HTML entities across 226 view files:
- 3-char UTF-8-as-Win1252 sequences (ae-corruption)
- Standalone smart/curly quotes that break C# Razor expressions
- Partially re-corrupted variants where the 3rd byte was normalised to ASCII

tools/Fix-Encoding.ps1: re-runnable sweep; uses [char] code points so the
script itself never contains a literal non-ASCII character; supports -DryRun

.githooks/pre-commit: blocks commits containing the ae-corruption byte
signature (xc3xa2xe2x82xac); git core.hooksPath = .githooks so the
hook is repo-committed and active for all future work on this machine.

Build clean; 225 unit tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 21:37:10 -04:00
parent 21b39161a3
commit a0bdd2b5b4
252 changed files with 1785 additions and 1633 deletions
@@ -9,7 +9,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pay Deposit Quote @Model.QuoteNumber @Model.CompanyName</title>
<title>Pay Deposit &mdash; Quote @Model.QuoteNumber &mdash; @Model.CompanyName</title>
<link rel="stylesheet" href="~/lib/bootstrap/css/bootstrap.min.css" />
<style>
body { background: #f0f2f5; font-family: 'Segoe UI', sans-serif; }
@@ -34,14 +34,14 @@
<div id="processing-overlay" aria-live="polite">
<div class="text-center">
<div class="spinner-border text-warning" role="status"></div>
<p class="mt-2 fw-semibold">Processing deposit</p>
<p class="mt-2 fw-semibold">Processing deposit&hellip;</p>
</div>
</div>
<div class="pay-card">
<p class="company-name">@Model.CompanyName</p>
<p class="quote-number">Quote #@Model.QuoteNumber</p>
<span class="deposit-badge">Deposit Required @Model.DepositPercent.ToString("0.##")% of quote total</span>
<span class="deposit-badge">Deposit Required &mdash; @Model.DepositPercent.ToString("0.##")% of quote total</span>
<p class="text-muted mb-0">Hello, @Model.CustomerName</p>
<div class="amount-display">
@@ -92,7 +92,7 @@
<div id="error-msg" class="alert alert-danger d-none mt-3" role="alert"></div>
<button id="pay-btn" type="submit" class="btn btn-warning w-100 mt-3" disabled>
<span id="btn-text">Loading payment form</span>
<span id="btn-text">Loading payment form&hellip;</span>
</button>
</form>
@@ -138,7 +138,7 @@
async function initPaymentElement() {
errorMsg.classList.add('d-none');
payBtn.disabled = true;
btnText.textContent = 'Preparing';
btnText.textContent = 'Preparing&hellip;';
if (paymentElement) { paymentElement.destroy(); paymentElement = null; }
document.getElementById('payment-element').innerHTML = '';
+6 -6
View File
@@ -1,7 +1,7 @@
@using PowderCoating.Web.Controllers
@model PaymentPageViewModel
@{
Layout = null; // Standalone page no app chrome
Layout = null; // Standalone page &mdash; no app chrome
var hasSurcharge = Model.SurchargeType != PowderCoating.Core.Enums.OnlinePaymentSurchargeType.None && Model.SurchargeValue > 0;
}
<!DOCTYPE html>
@@ -9,7 +9,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pay Invoice @Model.InvoiceNumber @Model.CompanyName</title>
<title>Pay Invoice @Model.InvoiceNumber &mdash; @Model.CompanyName</title>
<link rel="stylesheet" href="~/lib/bootstrap/css/bootstrap.min.css" />
<style>
body { background: #f0f2f5; font-family: 'Segoe UI', sans-serif; }
@@ -34,7 +34,7 @@
<div id="processing-overlay" aria-live="polite">
<div class="text-center">
<div class="spinner-border text-success" role="status"></div>
<p class="mt-2 fw-semibold">Processing payment</p>
<p class="mt-2 fw-semibold">Processing payment&hellip;</p>
</div>
</div>
@@ -75,7 +75,7 @@
<div class="form-check">
<input class="form-check-input" type="radio" name="payOption" id="optFull" value="full" checked />
<label class="form-check-label" for="optFull">
Pay full balance <strong>@Model.BalanceDue.ToString("C")</strong>
Pay full balance &mdash; <strong>@Model.BalanceDue.ToString("C")</strong>
</label>
</div>
<div class="form-check mt-1">
@@ -128,7 +128,7 @@
<div id="error-msg" class="alert alert-danger d-none mt-3" role="alert"></div>
<button id="pay-btn" type="submit" class="btn btn-success w-100 mt-3" disabled>
<span id="btn-text">Loading payment form</span>
<span id="btn-text">Loading payment form&hellip;</span>
</button>
</form>
@@ -184,7 +184,7 @@
async function initPaymentElement(amountDollars) {
clearError();
payBtn.disabled = true;
btnText.textContent = 'Preparing';
btnText.textContent = 'Preparing&hellip;';
if (paymentElement) { paymentElement.destroy(); paymentElement = null; }
document.getElementById('payment-element').innerHTML = '';