`;
return html;
}
function genAccordion(cfg){
if (!cfg.cmp.accordion) return '';
return `
`;
}
function genTabs(cfg){
if (!cfg.cmp.tabs) return '';
return `
Home content...
Profile content...
Contact content...
`;
}
function genModal(cfg){
if (!cfg.cmp.modal) return '';
return `
This is a Bootstrap modal.
`;
}
function genToast(cfg){
if (!cfg.cmp.toast) return '';
return `
Hello, world! This is a toast message.
`;
}
function genFooter(cfg){
if (!cfg.cmp.footer) return '';
const year = new Date().getFullYear();
return `
`;
}
function generateHtml(cfg){
const cdn = cdnLinks(cfg.bsVersion);
const head = `
${cdn.css}
${escapeHtml(cfg.siteName||'Bootstrap Page')}`;
const bodyOpen = ``;
const bodyContent = [
genNavbar(cfg),
genHero(cfg),
genGrid(cfg),
genAccordion(cfg),
genTabs(cfg),
genModal(cfg),
genToast(cfg),
genFooter(cfg)
].join('\n');
const bodyClose = `${cdn.js}`;
return head + bodyOpen + bodyContent + bodyClose;
}
function render(html){
document.getElementById('htmlOut').textContent = html;
const iframe = document.getElementById('livePreview');
const blob = new Blob([html], { type: 'text/html' });
const url = URL.createObjectURL(blob);
iframe.src = url;
window.__lastHtml = html;
window.__lastCfg = getInputs();
}
function download(filename, text, mime){
const a = document.createElement('a');
a.href = 'data:' + (mime||'text/plain') + ';charset=utf-8,' + encodeURIComponent(text);
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
function saveHistory(cfg){
const key = 'bootstrapGenHistory';
const prev = JSON.parse(localStorage.getItem(key) || '[]');
prev.unshift({ ts: Date.now(), siteName: cfg.siteName, cfg });
localStorage.setItem(key, JSON.stringify(prev.slice(0,20)));
}
function renderHistory(){
const key = 'bootstrapGenHistory';
const list = JSON.parse(localStorage.getItem(key) || '[]');
const container = document.getElementById('historyList');
container.innerHTML = '';
if (!list.length){ container.textContent = 'No history yet.'; return; }
list.forEach((item, idx)=>{
const row = document.createElement('div'); row.className='row';
const title = document.createElement('div'); const d=new Date(item.ts);
title.textContent = `${item.siteName||'Untitled'} — ${d.toLocaleString()}`;
const btnLoad = document.createElement('button'); btnLoad.className='btn'; btnLoad.textContent='Load';
btnLoad.onclick = () => { fillFrom(item.cfg); const html = generateHtml(item.cfg); render(html); };
const btnJson = document.createElement('button'); btnJson.className='btn'; btnJson.textContent='Export JSON';
btnJson.onclick = () => { download('bootstrap-config.json', JSON.stringify(item.cfg, null, 2)); };
row.appendChild(title); row.appendChild(btnLoad); row.appendChild(btnJson);
container.appendChild(row);
});
}
function fillFrom(cfg){
document.getElementById('siteName').value = cfg.siteName||'';
document.getElementById('bsVersion').value = cfg.bsVersion||'5.3';
document.getElementById('cdn').value = cfg.cdn||'yes';
document.getElementById('container').value = cfg.container||'container';
document.getElementById('theme').value = cfg.theme||'primary';
document.getElementById('customCss').value = cfg.customCss||'';
document.getElementById('navBrand').value = (cfg.nav&&cfg.nav.brand)||'';
document.getElementById('navLinks').value = (cfg.nav&&cfg.nav.links||[]).join(', ');
document.getElementById('navSticky').checked = !!(cfg.nav&&cfg.nav.sticky);
document.getElementById('navShadow').checked = !!(cfg.nav&&cfg.nav.shadow);
document.getElementById('heroTitle').value = (cfg.hero&&cfg.hero.title)||'';
document.getElementById('heroSub').value = (cfg.hero&&cfg.hero.sub)||'';
document.getElementById('heroCtaLabel').value = (cfg.hero&&cfg.hero.ctaLabel)||'';
document.getElementById('heroCtaHref').value = (cfg.hero&&cfg.hero.ctaHref)||'';
document.getElementById('gridRows').value = (cfg.grid&&cfg.grid.rows)||2;
document.getElementById('gridCols').value = (cfg.grid&&cfg.grid.cols)||3;
document.getElementById('cmpCards').checked = !!(cfg.cmp&&cfg.cmp.cards);
document.getElementById('cmpAccordion').checked = !!(cfg.cmp&&cfg.cmp.accordion);
document.getElementById('cmpTabs').checked = !!(cfg.cmp&&cfg.cmp.tabs);
document.getElementById('cmpModal').checked = !!(cfg.cmp&&cfg.cmp.modal);
document.getElementById('cmpToast').checked = !!(cfg.cmp&&cfg.cmp.toast);
document.getElementById('cmpFooter').checked = !!(cfg.cmp&&cfg.cmp.footer);
}
function currentPermalink(){
const cfg = getInputs();
const p = new URLSearchParams();
p.set('v', cfg.bsVersion); p.set('c', cfg.container); p.set('t', cfg.theme); p.set('cdn', cfg.cdn);
if (cfg.siteName) p.set('n', cfg.siteName);
if (cfg.nav.brand) p.set('nb', cfg.nav.brand);
if (cfg.nav.links && cfg.nav.links.length) p.set('nl', cfg.nav.links.join('|'));
if (cfg.hero.title) p.set('ht', cfg.hero.title);
if (cfg.hero.sub) p.set('hs', cfg.hero.sub);
if (cfg.hero.ctaLabel) p.set('hl', cfg.hero.ctaLabel);
if (cfg.hero.ctaHref) p.set('hh', cfg.hero.ctaHref);
p.set('gr', String(cfg.grid.rows)); p.set('gc', String(cfg.grid.cols));
['cards','accordion','tabs','modal','toast','footer'].forEach(k=>{ if (cfg.cmp[k]) p.set('x_'+k,'1'); });
return location.origin + location.pathname + '?' + p.toString();
}
function loadFromParams(){
const qs = new URLSearchParams(location.search);
if (!qs.has('v')) return;
const cfg = {
siteName: qs.get('n')||'', bsVersion: qs.get('v')||'5.3', cdn: qs.get('cdn')||'yes', container: qs.get('c')||'container', theme: qs.get('t')||'primary', customCss: '',
nav: { brand: qs.get('nb')||'', links: (qs.get('nl')||'').split('|').filter(Boolean), sticky:false, shadow:false },
hero: { title: qs.get('ht')||'', sub: qs.get('hs')||'', ctaLabel: qs.get('hl')||'', ctaHref: qs.get('hh')||'' },
grid: { rows: Number(qs.get('gr')||2), cols: Number(qs.get('gc')||3) },
cmp: { cards: !!qs.get('x_cards'), accordion: !!qs.get('x_accordion'), tabs: !!qs.get('x_tabs'), modal: !!qs.get('x_modal'), toast: !!qs.get('x_toast'), footer: !!qs.get('x_footer') }
};
fillFrom(cfg);
const html = generateHtml(cfg);
render(html);
}
document.getElementById('btnGen').addEventListener('click', () => {
const cfg = getInputs();
const html = generateHtml(cfg);
render(html);
});
document.getElementById('btnClear').addEventListener('click', () => {
fillFrom({ siteName:'', bsVersion:'5.3', cdn:'yes', container:'container', theme:'primary', customCss:'', nav:{ brand:'', links:[], sticky:false, shadow:false }, hero:{ title:'', sub:'', ctaLabel:'', ctaHref:'' }, grid:{ rows:2, cols:3 }, cmp:{ cards:true, accordion:false, tabs:false, modal:false, toast:false, footer:true } });
document.getElementById('htmlOut').textContent=''; document.getElementById('livePreview').src='about:blank';
});
document.getElementById('btnExample').addEventListener('click', () => {
fillFrom({ siteName:'BoostMySite', bsVersion:'5.3', cdn:'yes', container:'container', theme:'primary', customCss:'.hero{min-height:300px}', nav:{ brand:'BoostMySite', links:['Home','Features','Pricing','Contact'], sticky:true, shadow:true }, hero:{ title:'Build faster with Bootstrap', sub:'Responsive components and utilities', ctaLabel:'Get Started', ctaHref:'#features' }, grid:{ rows:2, cols:3 }, cmp:{ cards:true, accordion:true, tabs:true, modal:true, toast:true, footer:true } });
});
document.getElementById('btnSave').addEventListener('click', () => { const cfg=getInputs(); saveHistory(cfg); renderHistory(); });
document.getElementById('btnHistoryRefresh').addEventListener('click', renderHistory);
document.getElementById('btnHistoryClear').addEventListener('click', () => { localStorage.removeItem('bootstrapGenHistory'); renderHistory(); });
document.getElementById('btnCopy').addEventListener('click', async () => {
if (!window.__lastHtml){ alert('Generate first'); return; }
try { await navigator.clipboard.writeText(window.__lastHtml); alert('HTML copied'); } catch(e){ alert('Copy failed: ' + e.message); }
});
document.getElementById('btnHtml').addEventListener('click', () => {
const cfg = window.__lastCfg || getInputs();
const name = (cfg.siteName||'bootstrap-page').toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/(^-|-$)/g,'');
const html = window.__lastHtml || generateHtml(cfg);
download(`${name}.html`, html, 'text/html');
});
document.getElementById('btnJson').addEventListener('click', () => {
const cfg = window.__lastCfg || getInputs();
download('bootstrap-config.json', JSON.stringify(cfg, null, 2));
});
document.getElementById('btnPermalink').addEventListener('click', async () => {
const url = currentPermalink();
try { await navigator.clipboard.writeText(url); alert('Permalink copied'); } catch(e){ alert('Copy failed: ' + e.message); }
});
// init
renderHistory();
loadFromParams();