manual refactoring

This commit is contained in:
Marc Froehlich
2026-07-20 22:27:53 +02:00
parent 273becf793
commit 334e5b03a8
18 changed files with 409 additions and 169 deletions
+78 -1
View File
@@ -3,6 +3,74 @@ const path = require("path");
const markdownIt = require("markdown-it");
const markdownItAnchor = require("markdown-it-anchor");
const MANUAL_PAGE_ORDER = {
de: [
"home",
"installation",
"konfiguration",
"log-synchronisation",
"airscout-integration",
"dx-cluster-server",
"funktionen",
"makros-und-variablen",
"benutzeroberflaeche",
"changelog"
],
en: [
"home",
"installation",
"configuration",
"log-sync",
"airscout-integration",
"dx-cluster-server",
"features",
"macros-and-variables",
"user-interface",
"changelog"
]
};
function markdownToPlainText(value) {
return (value || "")
.replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1")
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
.replace(/<[^>]+>/g, "")
.replace(/[*_~`]/g, "")
.replace(/\s+/g, " ")
.trim();
}
function extractManualTitle(raw, fallbackTitle) {
const heading = (raw || "").match(/^#\s+(.+)$/m);
return heading ? markdownToPlainText(heading[1]) : fallbackTitle;
}
function extractManualSummary(raw) {
const blocks = (raw || "").split(/\r?\n\s*\r?\n/);
for (const block of blocks) {
const trimmed = block.trim();
if (!trimmed
|| /^(#|>|\||---|```|!\[)/.test(trimmed)
|| /^[-*+]\s/.test(trimmed)
|| /^\d+[.)]\s/.test(trimmed)) {
continue;
}
return markdownToPlainText(trimmed);
}
return "";
}
function getManualPageOrder(lang, slug) {
const configuredOrder = MANUAL_PAGE_ORDER[lang] || [];
const index = configuredOrder.indexOf(slug);
return index >= 0 ? index : 999;
}
function rewriteManualLinks(content, lang) {
return (content || "")
// GitHub-Wiki-Links im Stil [[de-Installation]] oder [[en-Installation]]
@@ -96,19 +164,28 @@ module.exports = function (eleventyConfig) {
.replace(/\.md$/, "")
.toLowerCase();
const title = file
const fallbackTitle = file
.replace(/^en-/, "")
.replace(/^de-/, "")
.replace(/\.md$/, "")
.replace(/-/g, " ");
const title = extractManualTitle(raw, fallbackTitle);
return {
file,
lang,
slug,
title,
summary: extractManualSummary(raw),
order: getManualPageOrder(lang, slug),
content: rewriteManualLinks(raw, lang)
};
})
.sort((a, b) => {
return a.lang.localeCompare(b.lang)
|| a.order - b.order
|| a.title.localeCompare(b.title);
});
});
+4 -4
View File
@@ -5,12 +5,12 @@
<title>{{ title or "KST4Contest" }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#08110b">
<meta name="description" content="{{ description or 'KST4Contest is a contest-optimized ON4KST chat client for VHF, UHF and SHF ham radio contests.' }}">
<meta name="description" content="{{ description or 'KST4Contest connects ON4KST chat, candidate selection, sked planning and station software for VHF, UHF and SHF contest operation.' }}">
<link rel="canonical" href="https://kst4contest.hamradioonline.de{{ page.url }}">
<meta property="og:type" content="website">
<meta property="og:title" content="{{ title or 'KST4Contest' }}">
<meta property="og:description" content="{{ description or 'Contest-optimized ON4KST chat client for VHF, UHF and SHF ham radio contests.' }}">
<meta property="og:description" content="{{ description or 'ON4KST chat, candidate selection, sked planning and station software in one VHF, UHF and SHF contest workflow.' }}">
<meta property="og:url" content="https://kst4contest.hamradioonline.de{{ page.url }}">
<meta property="og:site_name" content="KST4Contest">
<meta property="og:locale" content="en_GB">
@@ -20,7 +20,7 @@
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ title or 'KST4Contest' }}">
<meta name="twitter:description" content="{{ description or 'Contest-optimized ON4KST chat client for VHF, UHF and SHF ham radio contests.' }}">
<meta name="twitter:description" content="{{ description or 'ON4KST chat, candidate selection, sked planning and station software in one VHF, UHF and SHF contest workflow.' }}">
<meta name="twitter:image" content="https://kst4contest.hamradioonline.de/assets/social/kst4contest-og.png">
<link rel="stylesheet" href="/assets/css/main.css?v={{ build.version }}">
@@ -53,7 +53,7 @@
<div class="footer-grid">
<div>
<strong>KST4Contest</strong>
<p>Contest-optimized ON4KST workflow for VHF/UHF/SHF operators.</p>
<p>ON4KST chat, candidate selection and sked planning for VHF, UHF and SHF contest operation.</p>
</div>
<div>
<strong>Project</strong>
+2 -2
View File
@@ -3,8 +3,8 @@ title: AirScout Integration
icon: ✈️
category: Aircraft Scatter
since: "1.26"
summary: Use aircraft scatter awareness directly inside your ON4KST contest workflow.
description: AirScout information helps operators evaluate AP windows, aircraft scatter timing and candidate stations during VHF/UHF/SHF contests.
summary: Use AirScout AP predictions in candidate evaluation, the timeline and sked planning.
description: KST4Contest receives aircraft scatter information from AirScout and relates AP timing to active ON4KST stations.
tagsList:
- AirScout
- airplane scatter
+3 -2
View File
@@ -3,8 +3,9 @@ title: Dual Chat Categories
icon: 💬
category: ON4KST Chat
since: "1.26"
summary: Operate in two ON4KST categories at once, for example VHF/UHF and microwave.
description: Dual category support gives contest operators better overview when working across multiple ON4KST chat rooms.
since: "1.26"
summary: Log in to two ON4KST categories and handle both message streams in one station list and interface.
description: KST4Contest combines two ON4KST chat categories while retaining the category required for messages and station context.
tagsList:
- ON4KST
- dual chat
+3 -2
View File
@@ -3,8 +3,8 @@ title: DXCluster Server
icon: 📡
category: Radio Workflow
since: "1.23"
summary: Use DXCluster information as part of the wider contest operating workflow.
description: KST4Contest includes DXCluster functionality to support situational awareness during contest operation.
summary: Send direction warnings as DX Cluster spots to compatible logging software when a usable QRG is known.
description: The built-in DX Cluster server forwards KST4Contest direction warnings and known frequency information to compatible contest loggers.
tagsList:
- DXCluster
- ham radio
@@ -14,6 +14,7 @@ related:
- priority-score
---
## More situational awareness
DXCluster information can support contest operators by adding another source of activity information.
+2 -2
View File
@@ -3,8 +3,8 @@ title: Log Synchronization
icon: 🔄
category: Logger Integration
since: "1.31"
summary: Connect ON4KST chat workflow with Win-Test, UCXLog and contest logging state.
description: Log synchronization helps KST4Contest understand worked stations, active bands and contest context.
summary: Import worked stations and current frequencies from supported contest loggers so filters and band information follow the log.
description: KST4Contest receives worked-station and, where supported, frequency data from UCXLog, N1MM+, QARTest, DXLog.net and Win-Test through file and UDP interfaces.
tagsList:
- Win-Test
- UCXLog
+2 -2
View File
@@ -3,8 +3,8 @@ title: Macros and Variables
icon:
category: Operator Speed
since: "1.0"
summary: Send recurring contest messages faster with configurable macros and variables.
description: Macros reduce repetitive typing and help operators respond quickly during active ON4KST contest sessions.
summary: Build recurring chat messages from configurable text blocks and variables such as the current QRG or locator.
description: KST4Contest macros combine reusable message text with values taken from the current station, frequency and operating context.
tagsList:
- macros
- ON4KST
+2 -2
View File
@@ -3,8 +3,8 @@ title: Priority Score System
icon: 🎯
category: Contest Workflow
since: "1.40"
summary: Find the most promising stations faster using contest-aware candidate scoring.
description: KST4Contest ranks stations by activity, direction, sked context, band information, QRG hints and operator workflow signals.
summary: Rank active stations from known context such as direction, activity, band, QRG, AP and sked information.
description: The Priority Score System combines available contest information to populate a separate list of currently relevant candidates.
tagsList:
- ON4KST
- VHF
+2 -2
View File
@@ -3,8 +3,8 @@ title: Sked Reminder
icon: 🔔
category: Sked Management
since: "1.40"
summary: Keep scheduled contacts visible and avoid missing time-critical skeds.
description: KST4Contest keeps skeds in focus while the operator handles chat traffic, logging, bands and aircraft scatter timing.
summary: Store planned contacts and issue configurable chat messages plus local alerts before the agreed time.
description: Sked Reminder keeps scheduled contacts visible and provides automatic advance messages together with acoustic and visual operator alerts.
tagsList:
- sked
- ON4KST
+2 -2
View File
@@ -3,8 +3,8 @@ title: Timeline View
icon: ⏱️
category: Contest Awareness
since: "1.40"
summary: See upcoming AP windows and candidate timing in a compact contest timeline.
description: The timeline view helps operators understand short propagation windows and candidate timing during active contest operation.
summary: Show AP-based priority candidates and scheduled contacts on a shared timeline.
description: The Timeline View places upcoming aircraft scatter candidates and planned skeds into a common time-based overview.
tagsList:
- timeline
- AP windows
+102 -30
View File
@@ -1,7 +1,7 @@
---
layout: base.njk
title: KST4Contest Contest-Optimized ON4KST Chat Client
description: KST4Contest is a modern ON4KST chat client built for VHF, UHF and SHF contest operation.
title: KST4Contest ON4KST Contest Client for VHF, UHF and SHF
description: KST4Contest combines ON4KST chat, candidate prioritisation, sked planning, AirScout data and logger integration in one desktop client.
heroFx: true
---
@@ -10,25 +10,32 @@ heroFx: true
<div class="hero-fx-vignette" aria-hidden="true"></div>
<div class="hero-copy">
<p class="badge">The contest-optimized ON4KST client</p>
<p class="badge">ON4KST contest workflow for 144 MHz and above</p>
<h1>KST4Contest</h1>
<p class="lead">
Work smarter. Make more QSOs. KST4Contest brings priority candidates,
AirScout workflow, sked reminders, dual chat categories and log synchronization
into one contest-focused ON4KST client.
ON4KST shows you the traffic. KST4Contest helps turn it into an operating
decision by combining chat, candidate prioritisation, sked planning,
AirScout data and logger integration in one desktop client.
</p>
<p>
The available information is filtered, related to active stations and
presented in a contest-oriented workflow. The final decision still
belongs to the operator.
</p>
<div class="actions">
<a class="button" href="/download/">Download KST4Contest</a>
<a class="button secondary" href="https://github.com/praktimarc/kst4contest">View on GitHub</a>
<a class="button ghost" href="/manual/">Read manual</a>
<a class="button secondary" href="/manual/">Read the manual</a>
<a class="button ghost" href="https://github.com/praktimarc/kst4contest">View source code</a>
</div>
</div>
<div class="hero-panel">
<div class="terminal-bar">
<span></span><span></span><span></span>
<strong>KST4Contest workflow</strong>
<strong>Functions sharing the same station context</strong>
</div>
<div class="mock-grid">
@@ -46,21 +53,63 @@ heroFx: true
<section class="section">
<div class="section-heading">
<p class="eyebrow">Powerful features</p>
<h2>Everything you need for contest success</h2>
<p class="eyebrow">The operating problem</p>
<h2>The useful station is rarely the only station in the chat</h2>
<p>
Every feature is designed to reduce operator workload and improve decision speed during real contest operation.
During an active contest, messages, sked requests, frequency information
and band changes arrive continuously. The task is to identify which part
of that traffic matters now, which candidate should be monitored and
which contact is better scheduled for later.
</p>
</div>
<div class="grid">
{% for feature in collections.features %}
<article class="card">
<h3>Observe</h3>
<p>
Messages, locators, detected frequencies and known band activity are
assigned to stations across as many as two ON4KST chat categories.
</p>
</article>
<article class="card">
<h3>Evaluate</h3>
<p>
Direction, distance, worked status, NOT-QRV information, chat activity,
sked context and aircraft scatter data feed filters and candidate scores.
</p>
</article>
<article class="card">
<h3>Act</h3>
<p>
Candidates can be contacted, scheduled or monitored. Skeds remain
visible, while supported loggers and station interfaces receive the
information required for the next operating step.
</p>
</article>
</div>
</section>
<section class="section">
<div class="section-heading">
<p class="eyebrow">Functions</p>
<h2>One workflow, shared context</h2>
<p>
The individual functions are not isolated tools. They use the same
station, message, band and timing information, so that a change in one
part of the workflow can also affect filters, priorities and reminders.
</p>
</div>
<div class="grid">
{% for feature in collections.sortedFeatures %}
<article class="card feature-card">
<div class="feature-icon">{{ feature.data.icon }}</div>
<p class="eyebrow">{{ feature.data.category }}</p>
<h3><a href="{{ feature.url }}">{{ feature.data.title }}</a></h3>
<p>{{ feature.data.summary }}</p>
<a href="{{ feature.url }}">Learn more →</a>
<a href="{{ feature.url }}">Read how it works →</a>
</article>
{% endfor %}
</div>
@@ -68,29 +117,52 @@ heroFx: true
<section class="section">
<div class="cta-panel">
<p class="eyebrow">Open Source</p>
<h2>Built by contesters for contesters.</h2>
<p class="eyebrow">Limits</p>
<h2>A priority score is not a propagation forecast</h2>
<p>
KST4Contest is developed around real VHF/UHF/SHF contest workflows:
ON4KST chat, aircraft scatter, skeds, logging and fast operator decisions.
KST4Contest can only evaluate the information it knows. Scores, AP
windows, filters and path profiles support the operator's decision; they
do not guarantee a contact. If the input data is incomplete or outdated,
the result can be incomplete or outdated as well.
</p>
<div class="actions">
<a class="button" href="/download/">Download KST4Contest</a>
<a class="button secondary" href="/features/">Explore features</a>
<a class="button ghost" href="/support/">❤️ Support development</a>
<a class="button" href="/features/">Explore the functions</a>
<a class="button secondary" href="/manual/">Read the technical details</a>
</div>
</div>
</section>
<section class="section">
<div class="cta-panel">
<p class="eyebrow">Project status</p>
<h2>Stable for operation, Nightly for testing</h2>
<p>
KST4Contest is open-source software. The current stable release is the
normal choice for contest operation. Nightly builds follow ongoing
development and are useful when a particular fix or feature needs
testing. A few minutes before a contest is not the ideal time to discover
what changed.
</p>
<div class="actions">
<a class="button" href="/download/">Download the stable release</a>
<a class="button secondary" href="/roadmap/">Development status</a>
<a class="button ghost" href="/support/">Support development</a>
</div>
</div>
</section>
<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"SoftwareApplication",
"name":"KST4Contest",
"applicationCategory":"CommunicationApplication",
"operatingSystem":"Windows, Linux, macOS",
"url":"https://kst4contest.hamradioonline.de",
"downloadUrl":"https://github.com/praktimarc/kst4contest/releases",
"description":"Contest-optimized ON4KST client for VHF, UHF and SHF amateur radio contests."
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "KST4Contest",
"applicationCategory": "CommunicationApplication",
"operatingSystem": "Windows, Linux, macOS",
"url": "https://kst4contest.hamradioonline.de/",
"downloadUrl": "https://github.com/praktimarc/kst4contest/releases/latest",
"description": "KST4Contest combines ON4KST chat, candidate prioritisation, sked planning, AirScout data and logger integration for VHF, UHF and SHF contest operation.",
"license": "https://github.com/praktimarc/kst4contest/blob/main/LICENSE"
}
</script>
</script>
+3 -1
View File
@@ -15,7 +15,9 @@ description: Deutsches Benutzerhandbuch für KST4Contest.
{% if manual.lang == "de" %}
<div class="card">
<h3><a href="/manual/de/{{ manual.slug }}/">{{ manual.title }}</a></h3>
<p>Handbuchseite „{{ manual.title }}“ öffnen.</p>
{% if manual.summary %}
<p>{{ manual.summary }}</p>
{% endif %}
</div>
{% endif %}
{% endfor %}
+3 -1
View File
@@ -15,7 +15,9 @@ description: English user manual for KST4Contest.
{% if manual.lang == "en" %}
<div class="card">
<h3><a href="/manual/en/{{ manual.slug }}/">{{ manual.title }}</a></h3>
<p>Open the {{ manual.title }} manual page.</p>
{% if manual.summary %}
<p>{{ manual.summary }}</p>
{% endif %}
</div>
{% endif %}
{% endfor %}