Files
content/new-tool.md

434 lines
20 KiB
Markdown

+++
title = 'New Tool Page Generator'
subtitle = "Creates nicely formatted markdown for a new tool, so you don't have to"
date = 2025-08-21
+++
This page is useful to generate copy-and-paste source code in Markdown for a new tool.
**Publications:** Coming soon.
Reset the form with **Double Click** on reset button for safety.
{{<rawhtml>}}
<script>
function arr(str) {
return str.split(',').map(s => s.trim()).filter(Boolean);
}
function bool(val) {
return val ? 'false' : 'true';
}
function generateMarkdown() {
const title = document.getElementById('title').value;
const subtitle = document.getElementById('subtitle').value;
const date = new Date().toISOString().slice(0, 10);
const homepage = arr(document.getElementById('homepage').value);
const sourcecode = arr(document.getElementById('sourcecode').value);
const playground = arr(document.getElementById('playground').value);
const applications = arr(document.getElementById('applications').value);
const developers = arr(document.getElementById('developers').value);
const licenses = arr(document.getElementById('licenses').value);
const inputs = arr(document.getElementById('inputs').value);
const interfaces = arr(document.getElementById('interfaces').value);
const updatedYear = parseInt(document.getElementById('updated-year').value, 10);
const currentYear = new Date().getFullYear();
let maintenance = "Actively Maintained";
let maintenance_year = "";
if (updatedYear && currentYear - updatedYear > 5) {
maintenance = "Not Maintained";
maintenance_year = `updated_year = ${updatedYear}\n`;
}
const description = document.getElementById('description').value;
let md = `+++
title = '${title}'
subtitle = '${subtitle}'
links = [${homepage.length ? `\n\t{ title = "Homepage", url = "${homepage}", icon = 'fa-solid fa-home' },\n` : ''}${sourcecode.length ? `\t{ title = "Source Code", url = "${sourcecode}", icon = 'fa-solid fa-code' },\n` : ''}${playground.length ? `\t{ title = "Playground", url = "${playground}", icon = 'fa-solid fa-gamepad' }\n` : ''}]
applications = ${JSON.stringify(applications)}
developers = ${JSON.stringify(developers)}
licenses = ${JSON.stringify(licenses)}
inputs = ${JSON.stringify(inputs)}
interfaces = ${JSON.stringify(interfaces)}
maintenance = [${JSON.stringify(maintenance)}]
${maintenance_year}draft = false
date = ${date}
+++\n\n`;
md += description;
document.getElementById('output').textContent = md;
}
</script>
<table style="width: 100%">
<style>
input[type="text"],
input[type="url"],
input[type="date"],
textarea {
width: 100%;
box-sizing: border-box;
}
input,textarea {
margin: 0.2rem 0.2rem;
font-weight: 500;
}
table {
border-collapse: collapse;
width: 100%;
background: #eee;
color: #000;
border-radius: 0.5rem;
}
th, td {
padding: 8px;
text-align: left;
}
tr:nth-child(even) {
background: #ccc;
}
label {
color: #000;
font-weight: 600;
margin-right: 0.5rem;
}
input, textarea, select {
background: #fff;
color: #000;
border: 2px solid #888;
padding: 4px;
padding: 0.2rem 1rem;
font-size: 0.9rem;
}
button {
background: #000;
color: #ccc;
border: 2px solid white;
padding: 8px 38px;
font-size: 1rem;
font-weight: bold;
cursor: pointer;
}
button:hover {
background: #444;
}
</style>
<tr>
<td><label for="title">Title:</label></td>
<td><input type="text" id="title" required></td>
</tr>
<tr>
<td><label for="subtitle">Subtitle:</label></td>
<td><input type="text" id="subtitle"></td>
</tr>
<tr>
<td><label for="description">Description:</label></td>
<td><textarea id="description" rows="3" cols="50"></textarea></td>
</tr>
<tr>
<td><label for="homepage">Homepage URL:</label></td>
<td><input type="url" id="homepage" placeholder="https://example.com"></td>
</tr>
<tr>
<td><label for="sourcecode">Source Code URL:</label></td>
<td><input type="url" id="sourcecode" placeholder="https://github.com/example"></td>
</tr>
<tr>
<td><label for="playground">Playground URL:</label></td>
<td><input type="url" id="playground" placeholder="https://play.example.com"></td>
</tr>
<tr>
<td><label for="applications">Applications:</label></td>
<td>
<div id="applications-checkboxes">
<label><input type="checkbox" value="Theorem Prover">Theorem Prover</label> &nbsp;
<label><input type="checkbox" value="SMT Solver">SMT Solver</label> &nbsp;
<label><input type="checkbox" value="SAT Solver">SAT Solver</label>
<label><input type="checkbox" value="SAT Solver">Constraint Solver</label>
<br>
<label><input type="checkbox" value="Model Checker">Model Checker</label> &nbsp;
<label><input type="checkbox" value="Runtime Verifier">Runtime Verifier</label> &nbsp;
<label><input type="checkbox" value="Proof Assistant">Proof Assistant</label> &nbsp;
<label><input type="checkbox" value="Program Prover">Program Prover</label> &nbsp;
<label><input type="checkbox" value="Protocol Verifier">Protocol Verifier</label> &nbsp;
<br>
<label><input type="checkbox" value="Static Analyzer">Static Analyzer</label> &nbsp;
<label><input type="checkbox" value="Type Checker">Type Checker</label> &nbsp;
<label><input type="checkbox" value="Code Synthesizer">Code Synthesizer</label>
<label><input type="checkbox" value="Parameter Synthesizer">Parameter Synthesizer</label> &nbsp;
<br>
<label><input type="checkbox" value="Test Generator">Test Generator</label> &nbsp;
<label><input type="checkbox" value="Model Simulator">Model Simulator</label> &nbsp;
<label><input type="checkbox" value="Counterexample Generator">Counterexample Generator</label> &nbsp;
<br>
<label><input type="checkbox" value="Specification Language">Specification Language</label> &nbsp;
<label><input type="checkbox" value="Refinement Tool">Refinement Tool</label> &nbsp;
<label><input type="checkbox" value="Visualizer">Visualizer</label> &nbsp;
<br>
<label><input type="checkbox" value="Probabilistic Program Prover">Probabilistic Program Prover</label> &nbsp;
<label><input type="checkbox" value="Probabilistic Model Checker">Probabilistic Model Checker</label> &nbsp;
<label><input type="checkbox" value="Stochastic Simulator">Stochastic Simulator</label>
<br>
<!-- <label for="other-applications">Other:</label> -->
<input type="text" id="other-applications" placeholder="Other application">
<script>
document.getElementById('other-applications').addEventListener('input', updateApplications);
Array.from(document.querySelectorAll('#applications-checkboxes input[type="checkbox"]')).forEach(cb => {
cb.addEventListener('change', updateApplications);
});
function updateApplications() {
const otherValue = document.getElementById('other-applications').value.trim();
const checkboxes = Array.from(document.querySelectorAll('#applications-checkboxes input[type="checkbox"]:checked')).map(cb => cb.value);
const applications = otherValue ? [...checkboxes, otherValue] : checkboxes;
document.getElementById('applications').value = applications.join(', ');
}
</script> </script>
<input type="hidden" id="applications">
</div>
</td>
<script>
function getCheckedApplications() {
return Array.from(document.querySelectorAll('#applications-checkboxes input[type="checkbox"]:checked'))
.map(cb => cb.value);
}
</script>
</tr>
<tr>
<td><label for="developers">Developers:</label></td>
<td>
<input type="text" id="developers" placeholder="Devs separated by commas, e.g. Alice, Bob, Carol">
</td>
</tr>
</tr>
<tr>
<td><label for="licenses">License:</label></td>
<td>
<select id="licenses">
<optgroup label="Copyleft (GPL)">
<option value="GPL-1.0">GPL-1.0</option>
<option value="GPL-2.0">GPL-2.0</option>
<option value="GPL-3.0">GPL-3.0</option>
<option value="AGPL-3.0">AGPL-3.0</option>
</optgroup>
<optgroup label="Copyleft (LGPL)">
<option value="LGPL-2.1">LGPL-2.1</option>
<option value="LGPL-3.0">LGPL-3.0</option>
</optgroup>
<optgroup label="Copyleft (Other)">
<option value="EPL-2.0">EPL-2.0</option>
<option value="CDDL-1.0">CDDL-1.0</option>
<option value="OSL-3.0">OSL-3.0</option>
<option value="CECILL-2.1">CECILL-2.1</option>
<option value="Artistic-2.0">Artistic-2.0</option>
<option value="IPL-1.0">IPL-1.0</option>
<option value="OCamlPro Non-Commercial">OCamlPro Non-Commercial</option>
</optgroup>
<optgroup label="Permissive">
<option value="MIT">MIT</option>
<option value="Apache-1.1">Apache-1.1</option>
<option value="Apache-2.0">Apache-2.0</option>
<option value="BSD-2-Clause">BSD-2-Clause</option>
<option value="BSD-3-Clause">BSD-3-Clause</option>
<option value="ISC">ISC</option>
<option value="MPL-2.0">MPL-2.0</option>
<option value="Zlib">Zlib</option>
<option value="Unlicense">Unlicense</option>
<option value="CC0-1.0">CC0-1.0</option>
</optgroup>
<optgroup label="Proprietary / Other">
<option value="All Rights Reserved">All Rights Reserved</option>
</optgroup>
<option value="">Select a license</option> document.getElementById('licenses').addEventListener('change', function() {
document.getElementById('licenses-hidden').value = this.value;
});
</script>
<input type="hidden" id="licenses-hidden">
</td>
</tr>
<tr>
<td><label for="inputs">Inputs:</label></td>
<td>
<div id="inputs-checkboxes">
<!-- SAT/SMT/Model Checking formats -->
<label><input type="checkbox" value="SMT-LIB">SMT-LIB</label> &nbsp;
<label><input type="checkbox" value="DIMACS CNF">DIMACS CNF</label> &nbsp;
<label><input type="checkbox" value="AIGER">AIGER</label> &nbsp;
<label><input type="checkbox" value="TPTP">TPTP</label> &nbsp;
<label><input type="checkbox" value="SyGuS">SyGuS</label> &nbsp;
<label><input type="checkbox" value="WhyML">WhyML</label> &nbsp;
<br>
<!-- Model Checking languages -->
<label><input type="checkbox" value="Promela">Promela</label> &nbsp;
<label><input type="checkbox" value="NuSMV">NuSMV</label> &nbsp;
<label><input type="checkbox" value="LTL">LTL</label> &nbsp;
<label><input type="checkbox" value="CTL">CTL</label> &nbsp;
<br>
<!-- Hardware description languages -->
<label><input type="checkbox" value="Verilog">Verilog</label> &nbsp;
<label><input type="checkbox" value="VHDL">VHDL</label> &nbsp;
<br>
<!-- Formal specification languages -->
<label><input type="checkbox" value="B">B</label> &nbsp;
<label><input type="checkbox" value="Z">Z</label> &nbsp;
<label><input type="checkbox" value="Alloy">Alloy</label> &nbsp;
<label><input type="checkbox" value="TLA+">TLA+</label> &nbsp;
<br>
<!-- Proof assistant formats -->
<label><input type="checkbox" value="Coq">Coq</label> &nbsp;
<label><input type="checkbox" value="Isabelle/HOL">Isabelle/HOL</label> &nbsp;
<label><input type="checkbox" value="HOL Light">HOL Light</label> &nbsp;
<label><input type="checkbox" value="ACL2">ACL2</label> &nbsp;
<label><input type="checkbox" value="PVS">PVS</label> &nbsp;
<br>
<!-- Rewriting and algebraic specification -->
<label><input type="checkbox" value="Maude">Maude</label> &nbsp;
<label><input type="checkbox" value="CASL">CASL</label> &nbsp;
<br>
<!-- Simulation/visualization formats -->
<label><input type="checkbox" value="SPIN">SPIN</label> &nbsp;
<label><input type="checkbox" value="DOT">DOT (Graphviz)</label> &nbsp;
<br>
<!-- Data formats -->
<label><input type="checkbox" value="JSON">JSON</label> &nbsp;
<label><input type="checkbox" value="XML">XML</label> &nbsp;
<label><input type="checkbox" value="CSV">CSV</label> &nbsp;
<br>
<input type="text" id="other-inputs" placeholder="Other input format(s), separated by commas">
<script>
document.getElementById('other-inputs').addEventListener('input', function() {
const otherValues = this.value.split(',').map(s => s.trim()).filter(Boolean);
const checkboxes = Array.from(document.querySelectorAll('#inputs-checkboxes input[type="checkbox"]:checked'))
.map(cb => cb.value);
const inputs = otherValues.length ? [...checkboxes, ...otherValues] : checkboxes;
document.getElementById('inputs').value = inputs.join(', ');
});
</script> <script>
document.getElementById('other-inputs').addEventListener('input', function() {
const otherValue = this.value.trim();
const checkboxes = Array.from(document.querySelectorAll('#inputs-checkboxes input[type="checkbox"]:checked'))
.map(cb => cb.value);
const inputs = otherValue ? [...checkboxes, otherValue] : checkboxes;
document.getElementById('inputs').value = inputs.join(', ');
});
</script>
<input type="hidden" id="inputs">
</div>
</td>
<script>
function getCheckedInputs() {
return Array.from(document.querySelectorAll('#inputs-checkboxes input[type="checkbox"]:checked'))
.map(cb => cb.value);
}
</script>
</tr>
<tr>
<td><label for="interfaces">Interfaces:</label></td>
<td>
<div id="interfaces-checkboxes">
<!-- Web interfaces -->
<label><input type="checkbox" value="Web">Web</label> &nbsp;
<label><input type="checkbox" value="REST">REST</label> &nbsp;
<label><input type="checkbox" value="gRPC">gRPC</label> &nbsp;
<label><input type="checkbox" value="API">API</label> &nbsp;
<br>
<!-- Desktop interfaces -->
<label><input type="checkbox" value="CLI">CLI (Command Line)</label> &nbsp;
<label><input type="checkbox" value="GUI">GUI (Graphical)</label> &nbsp;
<label><input type="checkbox" value="REPL">REPL</label> &nbsp;
<br>
<!-- Integration interfaces -->
<label><input type="checkbox" value="Toolset Integration">Toolset Integration</label> &nbsp;
<label><input type="checkbox" value="Library">Library</label> &nbsp;
<label><input type="checkbox" value="Plugin">Plugin</label> &nbsp;
<label><input type="checkbox" value="IDE Integration">IDE Integration</label> &nbsp;
<br>
<!-- Other interfaces -->
<!-- <label for="other-interfaces">Other:</label> -->
<input type="text" id="other-interfaces" placeholder="Other interface(s), separated by commas">
<script>
document.getElementById('other-interfaces').addEventListener('input', updateInterfaces);
Array.from(document.querySelectorAll('#interfaces-checkboxes input[type="checkbox"]')).forEach(cb => {
cb.addEventListener('change', updateInterfaces);
});
function updateInterfaces() {
const otherValues = document.getElementById('other-interfaces').value.split(',').map(s => s.trim()).filter(Boolean);
const checkboxes = Array.from(document.querySelectorAll('#interfaces-checkboxes input[type="checkbox"]:checked')).map(cb => cb.value);
const interfaces = otherValues.length ? [...checkboxes, ...otherValues] : checkboxes;
document.getElementById('interfaces').value = interfaces.join(', ');
} </script>
<input type="hidden" id="interfaces"> </div>
</td>
<script>
function getCheckedInterfaces() {
return Array.from(document.querySelectorAll('#interfaces-checkboxes input[type="checkbox"]:checked'))
.map(cb => cb.value);
}
</script>
</tr>
<tr>
<td><label for="updated-year">Last Updated:</label></td>
<td>
<input type="number" id="updated-year" min="1900" max="2099" style="width:6em;">
<script>
document.getElementById('updated-year').addEventListener('input', function() {
const year = parseInt(this.value, 10);
const currentYear = new Date().getFullYear();
let status = "Actively Maintained";
if (currentYear - year > 5) {
status = "Not Maintained";
}
});
// Update hidden input when radio changes
Array.from(document.getElementsByName('maintenance')).forEach(radio => {
radio.addEventListener('change', function() {
document.getElementById('maintenance').value = this.value;
});
});
</script>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:center;">
<button type="button" onclick="generateMarkdown()">Generate Markdown</button>
<button type="button" ondblclick="resetForm()" onclick="this.style.background='rgba(255, 0, 0, 0.85)';" style="background: rgba(85, 6, 6, 1)">Reset Form</button>
<script>
function resetForm() {
document.getElementById('title').value = '';
document.getElementById('subtitle').value = '';
document.getElementById('homepage').value = '';
document.getElementById('sourcecode').value = '';
document.getElementById('playground').value = '';
document.getElementById('developers').value = '';
document.getElementById('licenses').value = '';
document.getElementById('licenses-hidden').value = '';
document.getElementById('inputs').value = '';
document.getElementById('interfaces').value = '';
document.getElementById('updated-year').value = '';
document.getElementById('description').value = '';
document.getElementById('other-applications').value = '';
document.getElementById('other-inputs').value = '';
// Uncheck all checkboxes
Array.from(document.querySelectorAll('input[type="checkbox"]')).forEach(cb => cb.checked = false);
// Clear output
document.getElementById('output').textContent = '';
}
// Accept "Enter" to trigger Generate Markdown in any field
Array.from(document.querySelectorAll('input,select,number')).forEach(el => {
el.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
generateMarkdown();
}
});
});
</script>
</td>
</tr>
</table>
<h3>Output Markdown:</h3>
<button type="button" onclick="navigator.clipboard.writeText(document.getElementById('output').textContent)">Copy to Clipboard</button>
<pre id="output" style="background:#000; padding:1em; border:1px solid #ccc;"></pre>
{{</rawhtml>}}