190 lines
12 KiB
HTML
190 lines
12 KiB
HTML
<!doctype html><html lang=en>
|
|
<meta charset=UTF-8>
|
|
<meta http-equiv=X-UA-Compatible content="IE=edge">
|
|
<meta name=viewport content="width=device-width,initial-scale=1">
|
|
<title>Integrity Checker - caileb.com</title>
|
|
<meta name=description content="Demonstrates the SRI integrity checker feature">
|
|
<link rel=icon href=/images/favi.png type=image/png>
|
|
<link rel=apple-touch-icon href=/images/favi.png>
|
|
<link rel="shortcut icon" href=/images/favi.png>
|
|
<link rel=preload href=/webfonts/Poppins-Regular.woff2 as=font type=font/woff2 crossorigin>
|
|
<link rel=preload href=/webfonts/Poppins-SemiBold.woff2 as=font type=font/woff2 crossorigin>
|
|
<link rel=stylesheet href=/css/u.css>
|
|
<link rel=stylesheet href=/css/docs.css>
|
|
<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css integrity=sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN crossorigin=anonymous>
|
|
<link rel=preload href=/js/u.js as=script>
|
|
<link rel=preload href=https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js as=script integrity=sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs crossorigin=anonymous>
|
|
<link rel=preload href=https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js as=script integrity=sha384-H6KKS1H1WwuERMSm+54dYLzjg0fKqRK5ZRyASdbrI/lwrCc6bXEmtGYr5SwvP1pZ crossorigin=anonymous>
|
|
<script src=https://cdnjs.cloudflare.com/ajax/libs/quicklink/2.3.0/quicklink.umd.js integrity=sha384-aD7FsuQkS1ohgFKY41fJfeA+Wd/QRNnrOd9Bs58K3FzKdJJv8yPnYU8Tnp5z1agS crossorigin=anonymous></script>
|
|
<style>:root{--background-color:#121212;--card-gradient-start:#1e1e1e;--card-gradient-end:#333;--header-background:#262626;--text-color:#fff;--accent-color:#9B59B6;--subtext-color:#ccc;--success-color:#2ecc71;--error-color:#e74c3c;--warning-color:#f39c12}body{background:#1c1c1c;color:var(--text-color);font-family:Poppins,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;margin:0;padding:20px;min-height:100vh}.container{max-width:800px;width:100%}header{text-align:center;margin-bottom:2rem}header h1{font-size:2.5rem;margin-bottom:.5rem;color:var(--accent-color)}header p{font-size:1.25rem;color:var(--subtext-color)}.info-box{background:linear-gradient(135deg,rgba(30,30,30,.8),rgba(51,51,51,.8));border-radius:12px;padding:1.5rem;margin:1.5rem 0;box-shadow:0 4px 10px rgba(0,0,0,.25)}h2{color:var(--accent-color);margin:1.5rem 0 1rem;font-size:1.8rem;font-weight:600}h3{color:var(--accent-color);margin:1rem 0;font-size:1.4rem;font-weight:600}p,li{color:var(--text-color);margin-bottom:.75rem;line-height:1.6}code{background-color:rgba(0,0,0,.3);padding:2px 6px;border-radius:4px;font-family:monospace;color:#e0e0e0}.resource-table{width:100%;border-collapse:collapse;margin:1.5rem 0;background:rgba(30,30,30,.6);border-radius:8px;overflow:hidden}.resource-table th,.resource-table td{padding:12px 15px;text-align:left;border-bottom:1px solid #444}.resource-table tr:last-child td{border-bottom:none}.resource-table th{background-color:rgba(0,0,0,.3);color:var(--accent-color);font-weight:600}.external{color:#e74c3c}.local{color:#2ecc71}ol,ul{padding-left:1.5rem;margin-bottom:1.5rem}.demo-section{margin:2rem 0}.status-indicator{display:inline-block;width:12px;height:12px;border-radius:50%;margin-right:8px}.status-loaded{background-color:var(--success-color)}.status-error{background-color:var(--error-color)}.status-pending{background-color:var(--warning-color)}.script-status{display:flex;align-items:center;margin-bottom:.75rem;padding:.75rem;border-radius:8px;background:rgba(0,0,0,.2)}.demo-card{background:linear-gradient(135deg,rgba(30,30,30,.6),rgba(51,51,51,.6));border-radius:12px;padding:1.5rem;margin:1rem 0;box-shadow:0 4px 8px rgba(0,0,0,.2)}.demo-card h4{color:var(--accent-color);margin-top:0;margin-bottom:1rem;font-size:1.2rem;font-weight:600}.demo-result{background:rgba(0,0,0,.3);border-radius:8px;padding:1rem;margin-top:1rem;font-family:monospace;color:#e0e0e0;min-height:24px}button{background:var(--accent-color);color:#fff;border:none;padding:.75rem 1.5rem;border-radius:8px;font-size:1rem;font-family:Poppins,sans-serif;font-weight:600;cursor:pointer;transition:all .2s ease}button:hover{background:#8e44ad;transform:translateY(-2px);box-shadow:0 4px 12px rgba(155,89,182,.4)}.flex-container{display:flex;gap:1rem;flex-wrap:wrap}.flex-container>div{flex:1;min-width:250px}.toc{background-color:rgba(30,30,30,.5);border-radius:8px;padding:20px;margin:20px 0 30px;border:1px solid var(--border-color)}.toc h2{margin-top:0;text-align:center;border-bottom:1px solid var(--border-color);padding-bottom:10px;margin-bottom:15px;color:var(--accent-color)}.toc ul{list-style-type:none;padding-left:0;margin:0;display:flex;flex-wrap:wrap;gap:10px;justify-content:center}.toc li{margin-bottom:8px;flex:none}.toc a{display:block;padding:5px 15px;border-radius:4px;transition:background-color .2s ease;background-color:rgba(20,20,20,.5);white-space:nowrap}.toc a:hover{background-color:rgba(50,50,50,.5);text-decoration:none}.section{scroll-margin-top:20px;margin-bottom:2.5rem}.feature-card{background-color:rgba(40,40,40,.5);border-radius:8px;padding:20px;border:1px solid var(--border-color);margin-bottom:15px}.feature-card h3{color:var(--accent-color);margin-top:0;text-align:left;border-bottom:1px solid rgba(255,255,255,.1);padding-bottom:10px}.code-example{position:relative;margin:1.5rem 0}.code-label{position:absolute;top:-12px;right:10px;background-color:var(--accent-color);color:#fff;font-size:.8rem;padding:2px 8px;border-radius:4px}pre{background-color:rgba(0,0,0,.3);border-radius:8px;padding:1rem;overflow-x:auto;margin:0}code{font-family:monospace;color:#e0e0e0}@media(max-width:768px){.toc ul{flex-direction:column;align-items:stretch}.toc a{text-align:center;white-space:normal}.resource-status,.demo-cards{grid-template-columns:1fr}}</style>
|
|
<script src=/js/u.js async></script>
|
|
<div class=container>
|
|
<h1>Auto-Integrity Hash Demo</h1>
|
|
<div class=info-box>
|
|
<p><strong>This is a live demonstration of automatic SRI hash generation.</strong>
|
|
<p>The server automatically adds integrity hashes to all external resources when the site is built - no manual work required.
|
|
<p>If you view the source code of this page, you'll see all external CSS and JavaScript files have <code>integrity</code> and <code>crossorigin</code> attributes that were added automatically during build.
|
|
<p>This security feature protects against compromised CDNs and ensures resources haven't been tampered with.
|
|
</div>
|
|
<h2>External Scripts Working</h2>
|
|
<p>These demos confirm that the external scripts are loaded and working correctly with their integrity hashes:
|
|
<div class=demo-cards>
|
|
<div class=demo-card>
|
|
<h3>jQuery Demo</h3>
|
|
<p>jQuery provides DOM manipulation and animation capabilities.
|
|
<div class=demo-result id=jquery-result>Running jQuery test...</div>
|
|
</div>
|
|
<div class=demo-card>
|
|
<h3>Lodash Demo</h3>
|
|
<p>Lodash provides utility functions for common programming tasks.
|
|
<div class=demo-result id=lodash-result>Running Lodash test...</div>
|
|
</div>
|
|
</div>
|
|
<div class=demo-cards>
|
|
<div class=demo-card>
|
|
<h3>Bootstrap Components</h3>
|
|
<p>Bootstrap provides responsive UI components.
|
|
<div class=demo-result id=bootstrap-result>
|
|
<div class="alert alert-info">
|
|
This is a Bootstrap alert component
|
|
</div>
|
|
<div class=progress style=height:20px;background-color:#444>
|
|
<div class="progress-bar bg-success" role=progressbar style=width:75% aria-valuenow=75 aria-valuemin=0 aria-valuemax=100>75%</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class=demo-card>
|
|
<h3>Quicklink Demo</h3>
|
|
<p>Quicklink prefetches links that are in the viewport.
|
|
<div class=demo-result id=quicklink-result>Running Quicklink test...</div>
|
|
</div>
|
|
</div>
|
|
<h2>Monitored Resources</h2>
|
|
<p>The following resources have integrity checks automatically applied during build:
|
|
<div class=table-container>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Resource Type
|
|
<th>Location
|
|
<th>Integrity Added?
|
|
<tbody>
|
|
<tr>
|
|
<td>Stylesheet
|
|
<td class=local>/css/u.css
|
|
<td>No (Local)
|
|
<tr>
|
|
<td>Stylesheet
|
|
<td class=external>Bootstrap CSS (CDN)
|
|
<td>Yes (External)
|
|
<tr>
|
|
<td>Preloaded Script
|
|
<td class=local>/js/u.js
|
|
<td>No (Local)
|
|
<tr>
|
|
<td>Preloaded Script
|
|
<td class=external>jQuery (CDN)
|
|
<td>Yes (External)
|
|
<tr>
|
|
<td>Preloaded Script
|
|
<td class=external>Lodash (CDN)
|
|
<td>Yes (External)
|
|
<tr>
|
|
<td>Script
|
|
<td class=external>Quicklink (CDN)
|
|
<td>Yes (External)
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<script src=/js/u.js></script>
|
|
<script src=https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js integrity=sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs crossorigin=anonymous></script>
|
|
<script src=https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js integrity=sha384-H6KKS1H1WwuERMSm+54dYLzjg0fKqRK5ZRyASdbrI/lwrCc6bXEmtGYr5SwvP1pZ crossorigin=anonymous></script>
|
|
<script>
|
|
// Auto-run jQuery demo
|
|
function runJqueryDemo() {
|
|
const resultElement = document.getElementById('jquery-result');
|
|
|
|
try {
|
|
if (typeof jQuery !== 'undefined') {
|
|
resultElement.textContent = '';
|
|
const demoText = document.createElement('div');
|
|
demoText.textContent = 'jQuery ' + jQuery.fn.jquery + ' loaded successfully! This color animation is powered by jQuery.';
|
|
resultElement.appendChild(demoText);
|
|
|
|
// Use jQuery for color animation
|
|
jQuery(demoText).css('color', '#e74c3c')
|
|
.animate({ color: '#2ecc71' }, 1000)
|
|
.animate({ color: '#3498db' }, 1000)
|
|
.animate({ color: '#f39c12' }, 1000)
|
|
.animate({ color: '#9b59b6' }, 1000);
|
|
} else {
|
|
resultElement.textContent = 'Error: jQuery is not loaded';
|
|
}
|
|
} catch (e) {
|
|
resultElement.textContent = 'Error: ' + e.message;
|
|
}
|
|
}
|
|
|
|
// Auto-run Lodash demo
|
|
function runLodashDemo() {
|
|
const resultElement = document.getElementById('lodash-result');
|
|
|
|
try {
|
|
if (typeof _ !== 'undefined') {
|
|
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
const chunked = _.chunk(array, 3);
|
|
const shuffled = _.shuffle([...array]);
|
|
const summed = _.sum(array);
|
|
|
|
resultElement.innerHTML =
|
|
'<div>Lodash ' + _.VERSION + ' loaded successfully!</div>' +
|
|
'<div>• Chunking [1-10] into groups of 3: ' + JSON.stringify(chunked) + '</div>' +
|
|
'<div>• Shuffled array: ' + JSON.stringify(shuffled) + '</div>' +
|
|
'<div>• Sum of array: ' + summed + '</div>';
|
|
} else {
|
|
resultElement.textContent = 'Error: Lodash is not loaded';
|
|
}
|
|
} catch (e) {
|
|
resultElement.textContent = 'Error: ' + e.message;
|
|
}
|
|
}
|
|
|
|
// Auto-run Quicklink check
|
|
function runQuicklinkCheck() {
|
|
const resultElement = document.getElementById('quicklink-result');
|
|
|
|
try {
|
|
if (typeof quicklink !== 'undefined') {
|
|
// Call quicklink to prefetch
|
|
quicklink.listen();
|
|
resultElement.innerHTML =
|
|
'<div>Quicklink loaded successfully!</div>' +
|
|
'<div>Now prefetching links as you scroll near them.</div>' +
|
|
'<div style="margin-top: 10px; font-size: 0.9em; color: #aaa;">Check network tab in dev tools to see prefetch requests.</div>';
|
|
} else {
|
|
resultElement.textContent = 'Error: Quicklink is not loaded';
|
|
}
|
|
} catch (e) {
|
|
resultElement.textContent = 'Error: ' + e.message;
|
|
}
|
|
}
|
|
|
|
// Check when DOM is fully loaded
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Small delay to ensure scripts are fully initialized
|
|
setTimeout(function() {
|
|
runJqueryDemo();
|
|
runLodashDemo();
|
|
runQuicklinkCheck();
|
|
}, 300);
|
|
});
|
|
|
|
// Fallback if DOMContentLoaded already fired
|
|
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
|
setTimeout(function() {
|
|
runJqueryDemo();
|
|
runLodashDemo();
|
|
runQuicklinkCheck();
|
|
}, 300);
|
|
}
|
|
</script>
|