Files
hawkbit/docs/index.html

305 lines
10 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--
Copyright (c) 2025 Contributors to the Eclipse Foundation
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Eclipse hawkBit</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="icon" href="images/hawkbit.svg" type="image/svg+xml">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
copyCode: {
buttonText: 'Copy',
errorText: 'Error',
successText: 'Copied',
},
name: ' ',
themeColor: '#0ea5ea',
coverpage: true,
auto2top: true,
loadSidebar: true,
subMaxLevel: 2,
maxLevel: 2,
sidebarDisplayLevel: 1,
search: {
placeholder: 'Type to search',
noData: 'No results!',
paths: 'auto',
depth: 3
}
}
</script>
<script>
(function () {
function logoPlugin(hook) {
hook.ready(function () {
fetch('images/hawkbit_logo.svg')
.then(function (r) { return r.text(); })
.then(function (svg) {
var el = document.querySelector('.app-name');
if (!el) return;
var div = document.createElement('div');
div.innerHTML = svg;
var svgEl = div.querySelector('svg');
svgEl.setAttribute('width', '200');
svgEl.removeAttribute('height');
svgEl.style.setProperty('--logo-color', '#F0EEEA');
var link = el.querySelector('a') || document.createElement('a');
link.href = '#/';
link.innerHTML = '';
link.appendChild(svgEl);
el.innerHTML = '';
el.appendChild(link);
});
});
}
window.$docsify.plugins = [].concat(logoPlugin, window.$docsify.plugins || []);
})();
</script>
<!-- Docsify v4 -->
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-clike.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-java.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-json.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-markdown.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-properties.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-nginx.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-yaml.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-ini.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-http.min.js"></script>
<!-- Latest v2.x.x -->
<script src="https://unpkg.com/docsify-copy-code@2"></script>
<!-- Mermaid -->
<script src="//cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script src="//unpkg.com/docsify-mermaid@2.0.1/dist/docsify-mermaid.js"></script>
<script>mermaid.initialize({ startOnLoad: false, theme: 'default' });</script>
</body>
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.1.6/dist/purify.min.js"></script>
<style>
body, input {
background-color: #F0EEEA;
}
.sidebar-sep {
margin: 12px 0;
border: 0;
height: 1px;
}
.sidebar, .sidebar-toggle, .sidebar ul li a {
background-color: #43464A;
color: #f0eeea;
}
.sidebar ul li.active>a {
color: #027abe;
}
thead tr {
background-color: #015585;
color: #f0eeea;
}
tbody tr:nth-child(odd) {
background-color: #9abfdf;
}
tbody tr:nth-child(even) {
background-color: #ffffff;
}
.markdown-section code,.markdown-section pre {
background-color: #f8f8f8;
}
</style>
<style>
.rn-list { display:grid; gap:1rem; }
.rn-card {
border:1px solid rgba(0,0,0,.08);
border-radius:12px;
padding:16px;
background: var(--docsearch-modal-background, #fff);
}
.rn-header { display:flex; align-items:baseline; gap:.5rem; justify-content:space-between; }
.rn-title { margin:0; font-size:1.1rem; font-weight:600; } /* ← no real <h*> */
.rn-badge { font-size:.75rem; padding:.1rem .4rem; border-radius:4px; border:1px solid rgba(0,0,0,.15); }
.rn-date { font-size:1rem; opacity:.75; }
.rn-search {
display:block;
width:100%;
max-width:520px;
padding:.6rem .8rem;
margin:0 0 1rem 0;
border:1px solid rgba(0,0,0,.15);
border-radius:10px;
outline:none;
box-sizing:border-box;
}
.rn-search:focus {
border-color: rgba(64,128,255,.5);
box-shadow:0 0 0 3px rgba(64,128,255,.15);
}
.rn-body { font-size:.95rem; line-height:1.6; }
.rn-body p { margin:.45rem 0; }
.rn-body ul, .rn-body ol { margin:.4rem 0 .6rem 1.2rem; }
.rn-body a { text-decoration:none; border-bottom:1px dotted currentColor; }
.rn-body code {
background:rgba(0,0,0,.06);
padding:.1rem .3rem;
border-radius:.3rem;
font-size:.9em;
}
.rn-h { margin:.35rem 0 .15rem; font-weight:600; } /* “fake headings” inside cards */
.rn-h1 { font-size:1rem; }
.rn-h2 { font-size:1rem; }
.rn-h3 { font-size:.98rem; }
.rn-actions { margin-top:.6rem; }
.rn-btn {
display:inline-block;
padding:.5rem .8rem;
border-radius:8px;
border:1px solid rgba(0,0,0,.15);
text-decoration:none;
}
/* Scope details styling to release cards only */
.rn-card details summary { cursor:pointer; font-weight:600; margin:.25rem 0; }
</style>
<script>
(function () {
// --- settings ---
const owner = 'eclipse-hawkbit';
const repo = 'hawkbit';
const targetFile = 'markdown/release-notes.md';
const perPage = 100;
// Compile markdown BUT render headings as <p class="rn-h rn-h{level}"><strong>..</strong></p>
// so Docsify won't see <h1..h6> and won't add them to the sidebar.
function compileMd(md) {
const renderer = new marked.Renderer();
renderer.heading = (text, level) =>
`<p class="rn-h rn-h${level}"><strong>${text}</strong></p>`;
const html = marked.parse(md || '', { renderer });
return DOMPurify.sanitize(html, { USE_PROFILES: { html: true }});
}
// Follow GitHub API pagination via Link header
async function fetchAllReleases(page = 1, acc = []) {
const url = `https://api.github.com/repos/${owner}/${repo}/releases?per_page=${perPage}&page=${page}`;
const res = await fetch(url, { headers: { 'Accept': 'application/vnd.github+json' } });
if (!res.ok) throw new Error('GitHub API error: ' + res.status);
const list = await res.json();
const link = res.headers.get('Link') || '';
const next = /<([^>]+)>;\s*rel="next"/.exec(link);
const all = acc.concat(list);
return next ? fetchAllReleases(page + 1, all) : all;
}
function renderCard(r, prevTag) {
const name = r.name || r.tag_name;
const date = r.published_at ? new Date(r.published_at).toISOString().slice(0,10) : '';
const pre = r.prerelease ? '<span class="rn-badge">pre-release</span>' : '';
const bodyHtml = compileMd(r.body || '');
const compareBtn = prevTag
? `<a class="rn-btn" href="https://github.com/${owner}/${repo}/compare/${encodeURIComponent(prevTag)}...${encodeURIComponent(r.tag_name)}" target="_blank" rel="noopener">Compare</a>`
: '';
return `
<div class="rn-card">
<div class="rn-header">
<div class="rn-title">${name}</div>
<div>${pre} <span class="rn-date">${date}</span></div>
</div>
<details>
<summary>View release notes</summary>
<div class="rn-body">${bodyHtml || '<p>No summary provided.</p>'}</div>
</details>
<div class="rn-actions">
<a class="rn-btn" href="${r.html_url}" target="_blank" rel="noopener">Open on GitHub</a>
${compareBtn}
</div>
</div>
`;
}
function mountUI(root, releases) {
releases.sort((a,b) => new Date(b.published_at||b.created_at) - new Date(a.published_at||a.created_at));
root.innerHTML = `
<input class="rn-search" id="rn-search" placeholder="Filter releases (e.g. 0.4, prerelease, 2024)" />
<div class="rn-list">
${releases.map((r, i) => renderCard(r, i < releases.length - 1 ? releases[i + 1].tag_name : null)).join('')}
</div>
`;
const input = root.querySelector('#rn-search');
const cards = Array.from(root.querySelectorAll('.rn-card'));
input.addEventListener('input', () => {
const q = input.value.toLowerCase();
cards.forEach(c => { c.style.display = c.textContent.toLowerCase().includes(q) ? '' : 'none'; });
});
}
// ---- docsify plugin ----
function plugin(hook, vm) {
hook.afterEach(function (html, next) {
const isRN = vm.route.file === targetFile || vm.route.path.toLowerCase().includes('release-notes');
if (!isRN) return next(html);
next('<div id="release-notes-root"><p>Loading releases…</p></div>');
});
hook.doneEach(async function () {
const isRN =
(vm.route.file || '').toLowerCase() === targetFile.toLowerCase() ||
vm.route.path.toLowerCase().includes('release-notes');
if (!isRN) return;
const root = Docsify.dom.find('#release-notes-root');
if (!root) return;
try {
const releases = await fetchAllReleases();
mountUI(root, releases);
} catch (e) {
console.error(e);
root.innerHTML = `
<p>Couldnt load releases from GitHub right now.</p>
<p><a class="rn-btn" href="https://github.com/${owner}/${repo}/releases" target="_blank" rel="noopener">
Open on GitHub ↗
</a></p>`;
}
});
}
window.$docsify = window.$docsify || {};
window.$docsify.plugins = [].concat(plugin, window.$docsify.plugins || []);
})();
</script>
</html>