Make the quote generator generically extensible & declarative

This commit is contained in:
kiril 2024-08-11 00:25:41 +00:00
parent 9168154c79
commit f4f0939cee

View File

@ -13,27 +13,59 @@
text-decoration-style: dotted; text-decoration-style: dotted;
text-decoration: underline; text-decoration: underline;
} }
html {
background-color: black;
filter: invert(1);
}
</style> </style>
<script> <script>
const basic = "basic";
const additional = "additional";
const parameters = { const parameters = {
"type": "Type", "type": {label: "Type", section: basic, type: "dropdown", fields: {
"language": "Language(s)", "book": "Book",
"text": "Text", "web": "Web",
"t": "Translation or re-wording", "song": "Song",
"year": "Year", "journal": "Journal",
"author": "Author", "wikipedia": "Wikipedia"
"title": "Title", }},
"volume": "Volume", "language": {label: "Language(s)", section: basic},
"translator": "Translator", "text": {label: "Text", section: basic, type: "textarea"},
"trans-title": "Translated title", "t": {label: "Translation or re-wording", section: basic, type: "textarea"},
"series": "Series", "year": {label: "Year", section: basic},
"isbn": "ISBN" "author": {label: "Author", section: basic},
"title": {label: "Title", section: basic},
"volume": {label: "Volume", section: additional},
"chapter": {label: "Chapter", section: additional},
"page": {label: "Page", section: additional},
"publisher": {label: "Publisher", section: additional},
"location": {label: "Location", section: additional},
"url": {label: "URL", section: additional},
"pageurl": {label: "Page URL", section: additional},
"original": {label: "Original title", section: additional},
"origlang": {label: "Original language", section: additional},
"origyear": {label: "Original year", section: additional},
"translator": {label: "Translator", section: additional},
"trans-title": {label: "Translated title", section: additional},
"series": {label: "Series", section: additional},
"isbn": {label: "ISBN", section: additional},
"format": {label: "Format", section: additional, type: "dropdown", fields: {
"": "(unspecified)",
"hardcover": "Hardcover",
"paperback": "Paperback",
"blog": "Blog"
}},
"genre": {label: "Genre", section: additional, type: "dropdown", fields: {
"": "(unspecified)",
"fiction": "Fiction",
"non-fiction": "Non-fiction"
}}
} }
let presetMenu; let presetMenu;
addEventListener("DOMContentLoaded", (event) => { addEventListener("DOMContentLoaded", (event) => {
presetMenu = document.getElementById("presets"); presetMenu = document.getElementById("presets");
presetMenu.addEventListener("change", () => loadPreset(presetMenu.value)); presetMenu.addEventListener("change", () => loadPreset(presetMenu.value));
generatePropertyInputs();
loadPresetList(); loadPresetList();
}); });
</script> </script>
@ -42,36 +74,21 @@
<h1 style="display: inline-block">en.wiktionary Quote Generator</h1> <span class="gloss" title="Enter values for each of the quote template fields. Once you're done, click Generate or Copy to clipboard to get the output as wikitext. You may set presets to skip out the repetitive bits if quoting from the same book many times.">(?)</span> <h1 style="display: inline-block">en.wiktionary Quote Generator</h1> <span class="gloss" title="Enter values for each of the quote template fields. Once you're done, click Generate or Copy to clipboard to get the output as wikitext. You may set presets to skip out the repetitive bits if quoting from the same book many times.">(?)</span>
<form> <form>
<hr> <hr>
<h2>Basic information</h2> <div id="basic">
<h2>Basic information</h2>
<hr>
</div>
<hr> <hr>
<label for="type">Type</label> <div id="additional">
<select id="type"> <h2>Additional information</h2>
<option value="book">Book</option> <hr>
<option value="web">Web</option> <br>
<option value="song">Song</option> </div>
<option value="journal">Journal</option>
<option value="wikipedia">Wikipedia</option>
</select>
<label>Language(s)</label> <input type="text" id="language">
<label>Text</label> <input type="text" id="text">
<label>Translation or re-wording</label> <input type="text" id="t">
<label>Year</label> <input type="text" id="year">
<label>Author</label> <input type="text" id="author">
<label>Title</label> <input type="text" id="title">
<hr>
<h2>Additional information</h2>
<hr>
<br>
<label>Volume</label> <input type="text" id="volume">
<label>Translator</label> <input type="text" id="translator">
<label>Translated title</label> <input type="text" id="trans-title">
<label>Series</label> <input type="text" id="series">
<label>ISBN</label> <input type="text" id="isbn">
<br> <br>
<input type="button" onclick="generate()" value="Generate" title="Generate"> <input type="button" onclick="generate()" value="Generate" title="Generate">
<input type="button" onclick="copy()" value="Copy to clipboard" title="Copy to clipboard"> <input type="button" onclick="copy()" value="Copy to clipboard" title="Copy to clipboard">
<br> <br>
<textarea readonly="true" id="out" cols="40" rows="4"></textarea> <textarea readonly="true" id="out" cols="60" rows="6"></textarea>
<hr> <hr>
<label>Preset <span class="gloss" title="When a preset name is input in the 'preset name' box below, you can save the current state of each option as a preset, which will be loaded again even if the page is refreshed.">(?)</span></label> <label>Preset <span class="gloss" title="When a preset name is input in the 'preset name' box below, you can save the current state of each option as a preset, which will be loaded again even if the page is refreshed.">(?)</span></label>
@ -105,20 +122,50 @@
generate(); generate();
navigator.clipboard.writeText(document.getElementById("out").innerHTML); navigator.clipboard.writeText(document.getElementById("out").innerHTML);
} }
function addNamedParameters(obj) { function addNamedParameters(obj, ignore = ["type", "language"]) {
let out = ""; let out = "";
for (const key in obj) { for (const key in obj) {
if (obj[key] == "" || ignore.includes(key)) continue;
out += `|${key}=${obj[key]}`; out += `|${key}=${obj[key]}`;
} }
return out; return out;
} }
function loadPresetList() { function loadPresetList() {
const items = {...localStorage}; const items = {...localStorage}; delete items.latestPreset;
for (const key in items) { for (const key in items) {
addPresetToMenu(key); addPresetToMenu(key);
} }
console.log(localStorage.getItem("latestPreset"));
loadPreset(localStorage.getItem("latestPreset"));
} }
function addPresetToMenu(key) { function generatePropertyInputs() {
for (const key in parameters) {
const label = document.createElement("label");
label.innerText = parameters[key].label;
let input;
if (parameters[key].type === "dropdown") {
input = document.createElement("select");
for (const optionName in parameters[key].fields) {
const option = document.createElement("option");
option.value = optionName;
option.innerText = parameters[key].fields[optionName];
input.appendChild(option)
}
} else if (parameters[key].type === "textarea") {
input = document.createElement("textarea");
input.cols = 60;
input.rows = 6;
} else {
input = document.createElement("input");
input.type = "text";
}
input.id = key;
document.getElementById(parameters[key].section).appendChild(label);
document.getElementById(parameters[key].section).appendChild(input);
}
}
function addPresetToMenu(key) {
const existingPresets = document.querySelectorAll("#presets option"); const existingPresets = document.querySelectorAll("#presets option");
for (const node of existingPresets) { for (const node of existingPresets) {
if (node.value === key) { if (node.value === key) {
@ -146,19 +193,17 @@
function loadPreset(presetName) { function loadPreset(presetName) {
document.getElementById("preset-name").value = presetMenu.value; document.getElementById("preset-name").value = presetMenu.value;
const parameterValues = JSON.parse(localStorage.getItem(presetName)); const parameterValues = JSON.parse(localStorage.getItem(presetName));
console.log(parameterValues)
for (const key in parameterValues) { for (const key in parameterValues) {
document.getElementById(key).value = parameterValues[key]; document.getElementById(key).value = parameterValues[key];
} }
localStorage.setItem("latestPreset", presetName);
} }
function deletePreset() { function deletePreset() {
const presetName = document.getElementById("preset-name").value; const presetName = document.getElementById("preset-name").value;
localStorage.removeItem(presetName); localStorage.removeItem(presetName);
const existingPresets = presetMenu.children; const existingPresets = presetMenu.children;
let currentPresetOptionNode; let currentPresetOptionNode;
console.log(presetName);
for (const node of existingPresets) { for (const node of existingPresets) {
console.log(node.value);
if (node.value === presetName) { if (node.value === presetName) {
currentPresetOptionNode = node; currentPresetOptionNode = node;
break; break;