pmp / index.html
izuemon's picture
Update index.html
680d8c1 verified
Raw
History Blame Contribute Delete
4.35 kB
<!doctype html><html><head><script src="https://cdn.jsdelivr.net/npm/eruda@3.4.3/eruda.min.js"></script><script>eruda.init();</script><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>PenguinMod Packager - Convert PenguinMod projects to HTML, EXE, and more</title><meta name="description" content="Converts PenguinMod projects into HTML files, zip archives, or executable programs for Windows, macOS, and Linux."><style>body[p4-splash-theme="dark"]:not([p4-loaded]) {
background-color: #111;
color-scheme: dark;
}
.input-for-remembering-project-file {
display: none;
}</style></head><body><noscript>This page requires JavaScript.</noscript><input type="file" class="input-for-remembering-project-file" autocomplete="on"><div id="app"></div><script>(function() {
// This logic is only for the "splash" screen.
// It's used to prevent a momentary white screen while the page is loading in dark mode.
var theme = 'system';
try {
var local = localStorage.getItem('P4.theme')
if (typeof local === 'string') theme = local;
} catch (e) { /* ignore */ }
if (theme === 'system') theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
document.body.setAttribute('p4-splash-theme', theme);
})();</script><script>(function(){
if (typeof window.showSaveFilePicker !== 'function') {
alert('このブラウザはshowSaveFilePickerに対応していません(Chrome/Edge 86+などが必要です)');
return;
}
function getFileNameFromUrl(url, defaultName = 'download') {
try {
if (url.includes('/')) {
const parts = url.split('/');
const last = parts.pop();
if (last && last.includes('.')) return last;
}
} catch(e) {}
return defaultName;
}
async function downloadBlobAsFile(blobUrl, suggestedName) {
try {
const response = await fetch(blobUrl);
if (!response.ok) throw new Error('Fetch failed');
const blob = await response.blob();
const fileHandle = await window.showSaveFilePicker({
suggestedName: suggestedName,
types: [{
description: 'ダウンロードファイル',
accept: { 'application/octet-stream': ['.' + (suggestedName.split('.').pop() || 'bin')] }
}]
});
const writable = await fileHandle.createWritable();
await writable.write(blob);
await writable.close();
console.log('ダウンロード完了:', suggestedName);
return true;
} catch(err) {
if (err.name !== 'AbortError') {
console.error('ダウンロードエラー:', err);
alert('ダウンロードに失敗しました: ' + err.message);
}
return false;
}
}
async function processLink(link) {
const href = link.href;
if (!href || !href.startsWith('blob:')) return;
const originalClick = link.onclick;
const originalTarget = link.target;
link.onclick = null;
link.target = '_self';
const fileName = link.download || getFileNameFromUrl(href, 'blob_download');
link.style.opacity = '0.5';
const success = await downloadBlobAsFile(href, fileName);
link.style.opacity = '';
if (!success) {
window.open(href, originalTarget || '_blank');
}
return false;
}
function attachBlobHandlers() {
const links = document.querySelectorAll('a[href^="blob:"]');
console.log(`blobリンクを${links.length}個検出しました`);
links.forEach(link => {
if (link.dataset.blobHandlerAttached) return;
link.dataset.blobHandlerAttached = 'true';
link.addEventListener('click', async (e) => {
e.preventDefault();
e.stopPropagation();
await processLink(link);
return false;
});
link.style.cursor = 'pointer';
});
}
attachBlobHandlers();
const observer = new MutationObserver(() => attachBlobHandlers());
observer.observe(document.body, { childList: true, subtree: true });
console.log('blobリンク監視を開始しました');
alert('blob: URLのリンクをshowSaveFilePickerで保存します');
})();</script><script src="js/p4.ff4a8adaa005c53fac81.js"></script></body></html>