Compare commits
31 Commits
b19dc38898
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ef9aed3126 | |||
| b6b3655142 | |||
| 38376225c8 | |||
| 00032f9cc0 | |||
| c35d27198c | |||
| 82e4d36b14 | |||
| a6542fbe60 | |||
| 30b3cf0d0a | |||
| 132e49b589 | |||
| 19b1c73dca | |||
| b8ae68eff8 | |||
| 05623222c8 | |||
| 9fb89f31d5 | |||
| 2c1164a6bc | |||
| 65aec63e12 | |||
| 56f524df38 | |||
| 0e8ac06e26 | |||
|
|
ce1c8c7bbb | ||
|
|
2e235e575f | ||
| 4d56328ceb | |||
| 1d4caa5f2b | |||
| e153143a7a | |||
| 04058a3be3 | |||
|
|
926bbf927b | ||
| 285c707290 | |||
| 03d6ad19f3 | |||
| 8cbb971c40 | |||
| f88202b792 | |||
| baa691fa03 | |||
| 980ab5b84c | |||
|
|
b2ef344949 |
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
update.php
|
||||
1
.gitignore_global
Normal file
@@ -0,0 +1 @@
|
||||
.DS_Store
|
||||
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "heonian-ime"]
|
||||
path = heonian-ime
|
||||
url = https://git.succubi.services/heonian.org/heonian-ime
|
||||
[submodule "heonian-resources"]
|
||||
path = heonian-resources
|
||||
url = https://git.succubi.services/heonian.org/heonian-resources
|
||||
|
||||
5
README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# heonian web dictionary
|
||||
|
||||
your beloved heonian dictionary, now in .html form
|
||||
|
||||
[live-ish here](https://dreamnotes.space/hw/)
|
||||
1
heonian-resources
Submodule
BIN
icons/icon-128x128.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
icons/icon-144x144.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
icons/icon-152x152.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
icons/icon-192x192.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
icons/icon-384x384.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
icons/icon-512x512.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
icons/icon-72x72.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
icons/icon-96x96.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
icons/maskable_icon.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
13
index.html
@@ -6,7 +6,15 @@
|
||||
<meta name="description" content="now with 50% less unix requirement">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="./main.css">
|
||||
<link rel="preload" href="./wordlist.json" as="fetch">
|
||||
<link rel="manifest" href="./manifest.json">
|
||||
<meta name="apple-mobile-web-app-title" content="hisho">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<link rel="apple-touch-icon" href="./icons/icon-512x512.png" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="./icons/icon-72x72.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="./icons/icon-144x144.png" />
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="./icons/icon-152x152.png" />
|
||||
<!-- <link rel="preload" href="./heonian-resources/wordlist.json" as="fetch"> this doesnt seem to do shit so /shrug -->
|
||||
</head>
|
||||
<body>
|
||||
<!--
|
||||
@@ -29,9 +37,10 @@
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#">show all words</a> <a href="#">uh. something else</a>
|
||||
<a id="showAllWords">show all words</a> <a id="randomWord">random word</a> <a href="https://heonian.dreamnotes.space">wiki</a>
|
||||
</div>
|
||||
<noscript>turn on js doofus</noscript>
|
||||
<span id="update">update available! close all open hisho tabs and reopen hisho to update.</span>
|
||||
</header>
|
||||
<main>
|
||||
|
||||
|
||||
10
main.css
@@ -67,6 +67,10 @@ a:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.heonian {
|
||||
font-family: "heonian";
|
||||
}
|
||||
@@ -156,6 +160,10 @@ header.fullscreen #search {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
header #update {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header-animation {
|
||||
animation: clearly-cheating 1s ease-in-out;
|
||||
}
|
||||
@@ -232,6 +240,7 @@ main {
|
||||
margin-bottom: 6px;
|
||||
border-left: 3px solid var(--darkgrey);
|
||||
padding-left: 4px;
|
||||
font-family: var(--font-h);
|
||||
}
|
||||
|
||||
.result-translation {
|
||||
@@ -252,6 +261,7 @@ main {
|
||||
|
||||
.result details.result-meta p {
|
||||
font-size: 1rem;
|
||||
font-family: var(--font-h);
|
||||
}
|
||||
|
||||
.results-header-count::after {
|
||||
|
||||
295
main.js
@@ -20,6 +20,7 @@ function toggleIME() {
|
||||
|
||||
function animateHeader(inout = false) {
|
||||
//todo: debounce this
|
||||
// const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)"); //do shit
|
||||
if (inout) {
|
||||
header.classList.add("header-animation-reverse");
|
||||
header.classList.remove("header-animation");
|
||||
@@ -28,6 +29,7 @@ function animateHeader(inout = false) {
|
||||
header.classList.add("fullscreen");
|
||||
main.style.opacity = "0";
|
||||
main.classList.remove("main-animation-reverse");
|
||||
main.innerHTML = "";
|
||||
}, 500);
|
||||
setTimeout(() => {
|
||||
header.classList.remove("header-animation-reverse");
|
||||
@@ -59,7 +61,7 @@ document.addEventListener("keydown", (e) => {
|
||||
//if search box not focused, and if we're not on the home page, go back to home page
|
||||
if (!header.querySelector("input").matches(":focus") && !header.classList.contains("fullscreen")) {
|
||||
e.preventDefault();
|
||||
animateHeader(true);
|
||||
goHome();
|
||||
} else if (header.querySelector("input").matches(":focus") && ime != null) {
|
||||
toggleIME();
|
||||
} else if (header.querySelector("input").matches(":focus")) {
|
||||
@@ -80,7 +82,7 @@ document.addEventListener("keydown", (e) => {
|
||||
|
||||
function stripWord(word, space = false) {
|
||||
return space == false ? word.replace(/[^a-zA-Z-]/gu, "").toLowerCase() :
|
||||
word.replace(/[^a-zA-Z-\s]/gu, "").toLowerCase();
|
||||
word.replace(/[^a-zA-Z-\s]/gu, "").toLowerCase();
|
||||
}
|
||||
|
||||
heonianVowels = {
|
||||
@@ -161,17 +163,50 @@ function processVerb(word) {
|
||||
//but ... not yet uwu
|
||||
}
|
||||
|
||||
function generateRuby(word) {
|
||||
function isHeonian(word) {
|
||||
letters = word.split("");
|
||||
ruby = "";
|
||||
for (let i = 0; i < letters.length; i++) {
|
||||
ruby += `<ruby>${letters[i]}<rt>${heonianToRoman(letters[i])}</rt></ruby>`;
|
||||
if (letters[i].codePointAt(0) < 57344 || letters[i].codePointAt(0) > 57606) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function generateRuby(word, addLinks = false) {
|
||||
ruby = "";
|
||||
if (addLinks == true) {
|
||||
//split by space
|
||||
let split = word.split(" ");
|
||||
for (let i = 0; i < split.length; i++) {
|
||||
letters = word.split("");
|
||||
for (let i = 0; i < letters.length; i++) {
|
||||
if (letters[i] == " ") {
|
||||
ruby += " ";
|
||||
} else if (json[letters[i]] != undefined) {
|
||||
ruby += `<ruby class="clickable" onclick='clickSearch(\"${letters[i]}\")'>${letters[i]}<rt>${heonianToRoman(letters[i])}</rt></ruby>`;
|
||||
} else {
|
||||
ruby += `<ruby>${letters[i]}<rt>${heonianToRoman(letters[i])}</rt></ruby>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
//somehow figure out how to get links in
|
||||
} else {
|
||||
letters = word.split("");
|
||||
for (let i = 0; i < letters.length; i++) {
|
||||
if (letters[i] == " ") {
|
||||
ruby += " ";
|
||||
} else {
|
||||
ruby += `<ruby>${letters[i]}<rt>${heonianToRoman(letters[i])}</rt></ruby>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ruby;
|
||||
}
|
||||
|
||||
function loadDictionary() {
|
||||
fetch("./wordlist.json").then((e) => {
|
||||
fetch("./heonian-resources/wordlist.json").then((e) => {
|
||||
if (e.status === 200) {
|
||||
//convert to json lmao
|
||||
e.json().then((e) => {
|
||||
@@ -182,6 +217,7 @@ function loadDictionary() {
|
||||
//prepare search. maybe async this if we're loading a specific word?
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
try {
|
||||
if (keys[i] == "") continue;
|
||||
//create array
|
||||
searchDictionary[keys[i]] = [];
|
||||
|
||||
@@ -191,11 +227,13 @@ function loadDictionary() {
|
||||
//add: romanized word
|
||||
searchDictionary[keys[i]].push(stripWord(heonianToRoman(keys[i])));
|
||||
//what if i add it here.
|
||||
searchDictionary[keys[i]].push(stripWord(heonianToRoman(keys[i]).replace("dsh","z")));
|
||||
searchDictionary[keys[i]].push(stripWord(heonianToRoman(keys[i]).replace("dsh", "z")));
|
||||
|
||||
//add: translations, meanings
|
||||
for (let o = 0; o < values[i].length; o++) {
|
||||
if (values[i][o].hasOwnProperty("translation")) searchDictionary[keys[i]].push(stripWord(values[i][o]["translation"], true));
|
||||
if (values[i][o].hasOwnProperty("translation")) {
|
||||
searchDictionary[keys[i]].push(stripWord(values[i][o]["translation"], true))
|
||||
};
|
||||
if (values[i][o].hasOwnProperty("meaning")) searchDictionary[keys[i]].push(stripWord(values[i][o]["meaning"], true));
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -205,6 +243,13 @@ function loadDictionary() {
|
||||
|
||||
//ok, we're all ready!
|
||||
document.querySelector("header input").placeholder = "search";
|
||||
const url = new URL(window.location);
|
||||
const val = url.searchParams.get('s');
|
||||
if (val != null) {
|
||||
header.querySelector("input").value = val;
|
||||
doSearch(false);
|
||||
animateHeader(false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert("yeah something went horribly wrong loading the wordlist so uh,,, certified ike moment");
|
||||
@@ -213,7 +258,12 @@ function loadDictionary() {
|
||||
});
|
||||
}
|
||||
|
||||
function search(word) {
|
||||
function search(word, type) {
|
||||
if (type == "all") { word = "" };
|
||||
if (type == "random") {
|
||||
let random = Math.floor(Math.random() * Object.keys(json).length);
|
||||
return [Object.keys(json)[random]];
|
||||
}
|
||||
let words = word.split(" ");
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
words[i] = stripWord(words[i]);
|
||||
@@ -226,19 +276,66 @@ function search(word) {
|
||||
for (let key in searchDictionary) {
|
||||
for (let value in searchDictionary[key]) {
|
||||
if (searchDictionary[key][value].includes(word)) {
|
||||
if (value == 0) {
|
||||
result.push(key);
|
||||
break;
|
||||
} else {
|
||||
//if its a description (i.e: includes a space)
|
||||
//do startsWith or something instead to prevent
|
||||
//false positive search results
|
||||
let t = false;
|
||||
let d = searchDictionary[key][value].split(" ")
|
||||
for (let w in d) {
|
||||
if (d[w].startsWith(word)) {
|
||||
t = true;
|
||||
}
|
||||
}
|
||||
if (t) {
|
||||
result.push(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (words.length > 1 && stripWord(searchDictionary[key][value]).includes(word)) {
|
||||
result.push(key);
|
||||
break; //????
|
||||
break;
|
||||
//can still produce false positives, but... very low chance
|
||||
//i'll fix it once it starts happening...
|
||||
//(just... re-creating the search tems to actually have spaces should do the trick, right?)
|
||||
//(yeah, i'll wanna . strip spaces to not be more than one in a row and all that but. H)
|
||||
//idk. this should be fine for now, and possibly, ever
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function doSearch() {
|
||||
function clickSearch(word) {
|
||||
header.querySelector("input").value = word;
|
||||
doSearch();
|
||||
//TODO: scroll to top of page or w/e.
|
||||
//maybe dosearch should do that instead
|
||||
//minds too hazy for this rn though...
|
||||
}
|
||||
|
||||
function doSearch(state = true) {
|
||||
let val = header.querySelector("input").value;
|
||||
let results = search(val);
|
||||
if (val == "") {
|
||||
main.innerHTML = "enter some search terms...";
|
||||
return;
|
||||
}
|
||||
|
||||
//Manage search methods
|
||||
let type = "normal";
|
||||
if (val.includes("show:random")) {
|
||||
type = "random";
|
||||
} else if (val.includes("show:all")) {
|
||||
type = "all";
|
||||
}
|
||||
|
||||
//Results
|
||||
let results = search(val, type);
|
||||
if (results.length == 0) {
|
||||
main.innerHTML = "no results lulw";
|
||||
main.innerHTML = "no results (todo: cool form)";
|
||||
} else {
|
||||
main.innerHTML = "";
|
||||
/*
|
||||
@@ -275,39 +372,80 @@ function doSearch() {
|
||||
let meaning = document.createElement("div");
|
||||
meaning.classList.add("result-meaning");
|
||||
//ripping off jisho: Bold, word type (*required)
|
||||
if (last != json[results[i]][o]["type"]) meaning.innerHTML += "<b class='capitalize'>"+json[results[i]][o]["type"]+"</b><br>";
|
||||
if (last != json[results[i]][o]["type"]) meaning.innerHTML += "<b class='capitalize'>" + json[results[i]][o]["type"] + "</b><br>";
|
||||
last = json[results[i]][o]["type"];
|
||||
if (types[json[results[i]][o]["type"]] == undefined) {
|
||||
types[json[results[i]][o]["type"]] = 1;
|
||||
} else {
|
||||
types[json[results[i]][o]["type"]]++;
|
||||
}
|
||||
//number, meaning (*required)
|
||||
meaning.innerHTML += "<span class='result-number'>"+(o+1)+"</span><span class='result-big'>"+json[results[i]][o]["meaning"]+"</span>";
|
||||
//longer translation (below are not required, make sure to check for them)
|
||||
if (json[results[i]][o]["translation"] != undefined && json[results[i]][o]["translation"].toLowerCase() != json[results[i]][o]["meaning"].toLowerCase()) {
|
||||
meaning.innerHTML += "<br><span class='result-translation'>"+json[results[i]][o]["translation"]+"</span>";
|
||||
//meaning, tl, etc
|
||||
if (json[results[i]][o]["meaning"] != undefined) {
|
||||
meaning.innerHTML += "<span class='result-number'>" + (o + 1) + "</span><span class='result-big'>" + escapeHTML(json[results[i]][o]["meaning"]) + "</span>";
|
||||
} else if (json[results[i]][o]["translation"] != undefined) {
|
||||
meaning.innerHTML += "<span class='result-number'>" + (o + 1) + "</span><span class='result-big'>" + escapeHTML(json[results[i]][o]["translation"]) + "</span>";
|
||||
}
|
||||
if (json[results[i]][o]["translation"] != undefined && json[results[i]][o]["meaning"] != undefined) {
|
||||
if (json[results[i]][o]["translation"].toLowerCase() != json[results[i]][o]["meaning"].toLowerCase())
|
||||
meaning.innerHTML += "<br><span class='result-translation'>" + json[results[i]][o]["translation"] + "</span>";
|
||||
}
|
||||
//example
|
||||
if (json[results[i]][o]["examples"] != undefined) {
|
||||
let temp = ""
|
||||
temp += "<details><summary>Examples</summary><p>";
|
||||
for (let e in json[results[i]][o]["examples"]) {
|
||||
temp += "<span class='heonian'>"+generateRuby(e)+"</span> - "+json[results[i]][o]["examples"][e]+"<br>";
|
||||
temp += "<span class='heonian'>" + generateRuby(e, true) + "</span> - " + json[results[i]][o]["examples"][e] + "<br>";
|
||||
}
|
||||
temp += "</p></details>";
|
||||
meaning.innerHTML += temp;
|
||||
}
|
||||
//antonyms, synonyms
|
||||
if (json[results[i]][o]["antonyms"] != undefined) {
|
||||
let temp = ""
|
||||
temp += "<details class='result-nyms'><summary>Antonyms</summary><p>";
|
||||
for (let e in json[results[i]][o]["antonyms"]) {
|
||||
let r = json[results[i]][o]["antonyms"][e];
|
||||
temp += "<span class='heonian'>" + generateRuby(r, true);
|
||||
if (json[r] != undefined) {
|
||||
temp += " - ";
|
||||
for (let i in json[r]) {
|
||||
if (i != 0) temp += ", ";
|
||||
temp += json[r][i]["translation"];
|
||||
}
|
||||
}
|
||||
temp += "</span><br>";
|
||||
}
|
||||
temp += "</p></details>";
|
||||
meaning.innerHTML += temp;
|
||||
}
|
||||
if (json[results[i]][o]["synonyms"] != undefined) {
|
||||
let temp = ""
|
||||
temp += "<details class='result-nyms'><summary>Synonyms</summary><p>";
|
||||
for (let e in json[results[i]][o]["synonyms"]) {
|
||||
let r = json[results[i]][o]["synonyms"][e];
|
||||
temp += "<span class='heonian'>" + generateRuby(r, true);
|
||||
if (json[r] != undefined) {
|
||||
temp += " - ";
|
||||
for (let i in json[r]) {
|
||||
if (i != 0) temp += ", ";
|
||||
temp += json[r][i]["translation"];
|
||||
}
|
||||
}
|
||||
temp += "</span><br>";
|
||||
}
|
||||
temp += "</p></details>";
|
||||
meaning.innerHTML += temp;
|
||||
}
|
||||
//notes
|
||||
if (json[results[i]][o]["notes"] != undefined) {
|
||||
meaning.innerHTML += "<p class='result-notes'>"+json[results[i]][o]["notes"]+"</p>";
|
||||
meaning.innerHTML += "<p class='result-notes'>" + escapeHTML(json[results[i]][o]["notes"]) + "</p>";
|
||||
}
|
||||
//(source, etc)
|
||||
if (json[results[i]][o]["canon-etymology"] != undefined) {
|
||||
meaning.innerHTML += "<details class='result-meta'><summary>Canon Etymology</summary><p>"+json[results[i]][o]["canon-etymology"]+"</p></details>";
|
||||
meaning.innerHTML += "<details class='result-meta'><summary>Canon Etymology</summary><p>" + escapeHTML(json[results[i]][o]["canon-etymology"]) + "</p></details>";
|
||||
}
|
||||
if (json[results[i]][o]["meta-etymology"] != undefined) {
|
||||
meaning.innerHTML += "<details class='result-meta'><summary>Meta Etymology</summary><p>"+json[results[i]][o]["meta-etymology"]+"</p></details>";
|
||||
meaning.innerHTML += "<details class='result-meta'><summary>Meta Etymology</summary><p>" + escapeHTML(json[results[i]][o]["meta-etymology"]) + "</p></details>";
|
||||
}
|
||||
//todo
|
||||
result.appendChild(meaning); //y, yeah.
|
||||
@@ -317,24 +455,127 @@ function doSearch() {
|
||||
types = sortObject(types);
|
||||
let header = document.createElement("div");
|
||||
header.classList.add("results-header");
|
||||
header.innerHTML += "<span class='heonian'>search results for: " + val + "</span><br>";
|
||||
//When using search methods, accomodate search text.
|
||||
//we dont wanna actually change val, because this breaks searchParams
|
||||
switch (type) {
|
||||
//show:all
|
||||
case "all":
|
||||
header.innerHTML += "<span class='heonian'>showing all words</span><br>";
|
||||
break;
|
||||
case "random":
|
||||
//think about whether we wanna set searchparams to this, though..?
|
||||
header.innerHTML += "<span class='heonian'>showing random word: " + results[0] + "</span><br>";
|
||||
break;
|
||||
//OMG A WORD
|
||||
default:
|
||||
header.innerHTML += "<span class='heonian'>search results for: " + val + "</span><br>";
|
||||
break;
|
||||
}
|
||||
for (let i in types) {
|
||||
header.innerHTML += "<span class='results-header-count'>"+i+"s - "+types[i]+"</span>";
|
||||
if (i !== "") { header.innerHTML += "<span class='results-header-count'>" + i + "s - " + types[i] + "</span>"; }
|
||||
}
|
||||
main.prepend(header);
|
||||
}
|
||||
const url = new URL(window.location);
|
||||
url.searchParams.set('s', val);
|
||||
if (state == true) history.pushState(val, "", url);
|
||||
}
|
||||
|
||||
function goHome(state = true) {
|
||||
animateHeader(true);
|
||||
const url = new URL(window.location);
|
||||
url.searchParams.delete('s');
|
||||
if (state == true) history.pushState(null, "", url);
|
||||
}
|
||||
|
||||
async function registerSW() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
|
||||
console.log("localhost - not registering sw"); //because spamming removeSW() every time i make a change is annoying;
|
||||
removeSW(); //just in case =w=
|
||||
return;
|
||||
}
|
||||
navigator.serviceWorker.register('./sw.js').then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
header.querySelector("#update").style.display = "block";
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}).catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function removeSW() {
|
||||
caches.keys().then(function(names) {
|
||||
for (let name of names)
|
||||
caches.delete(name);
|
||||
}); //this doesnt actually seem to work :/ but . i'll leave it in for later fixing
|
||||
navigator.serviceWorker.getRegistrations().then(function(registrations) {
|
||||
for (let registration of registrations)
|
||||
registration.unregister();
|
||||
}); //dev use only!! or whatever... i just copypasted this from SO
|
||||
}
|
||||
|
||||
function escapeHTML(str){
|
||||
return new Option(str).innerHTML;
|
||||
}
|
||||
|
||||
window.onload = () => {
|
||||
header = document.querySelector("header");
|
||||
main = document.querySelector("main");
|
||||
header.querySelector("#search button").onclick = () => {toggleIME();};
|
||||
header.querySelector("#search button").onclick = () => { toggleIME(); };
|
||||
header.querySelector("span.heonian").onclick = () => {
|
||||
if (!header.classList.contains("fullscreen")) {
|
||||
animateHeader(true);
|
||||
goHome();
|
||||
}
|
||||
};
|
||||
header.querySelector("#showAllWords").onclick = () => {
|
||||
if (header.classList.contains("fullscreen")) {
|
||||
animateHeader(false);
|
||||
}
|
||||
header.querySelector("input").value = "show:all";
|
||||
doSearch(true);
|
||||
};
|
||||
header.querySelector("#randomWord").onclick = () => {
|
||||
if (header.classList.contains("fullscreen")) {
|
||||
animateHeader(false);
|
||||
}
|
||||
header.querySelector("input").value = "show:random";
|
||||
doSearch(true);
|
||||
};
|
||||
loadDictionary();
|
||||
window.addEventListener('popstate', (e) => {
|
||||
if (e.state == null) {
|
||||
if (!header.classList.contains("fullscreen")) {
|
||||
goHome(false);
|
||||
}
|
||||
} else {
|
||||
if (header.classList.contains("fullscreen")) {
|
||||
animateHeader(false);
|
||||
}
|
||||
header.querySelector("input").value = e.state;
|
||||
doSearch(false);
|
||||
}
|
||||
});
|
||||
registerSW(); //considering disabling this for now,.... itso nly lead to trouble :////
|
||||
}
|
||||
|
||||
const sortObject = obj => Object.keys(obj).sort().reduce((res, key) => (res[key] = obj[key], res), {})
|
||||
58
manifest.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "hisho",
|
||||
"short_name": "hisho",
|
||||
"theme_color": "#fff",
|
||||
"background_color": "#fff",
|
||||
"display": "fullScreen",
|
||||
"orientation": "portrait",
|
||||
"scope": "/hw/",
|
||||
"start_url": "/hw/",
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/maskable_icon.png",
|
||||
"sizes": "640x640",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
7
pre-commit
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
VAR="const currentVersion = '$RANDOM';"
|
||||
sed "1s/.*/$VAR/" sw.js > sw.js.new
|
||||
mv sw.js.new sw.js
|
||||
git add sw.js
|
||||
91
sw.js
Normal file
@@ -0,0 +1,91 @@
|
||||
const currentVersion = '7675';
|
||||
|
||||
const addResourcesToCache = async (resources) => {
|
||||
const cache = await caches.open(currentVersion);
|
||||
await cache.addAll(resources);
|
||||
};
|
||||
|
||||
const putInCache = async (request, response) => {
|
||||
const cache = await caches.open(currentVersion);
|
||||
await cache.put(request, response);
|
||||
};
|
||||
|
||||
const cacheFirst = async ({ request, preloadResponsePromise }) => {
|
||||
// First try to get the resource from the cache
|
||||
const responseFromCache = await caches.match(request);
|
||||
if (responseFromCache) {
|
||||
return responseFromCache;
|
||||
}
|
||||
|
||||
// Next try to use the preloaded response, if it's there
|
||||
const preloadResponse = await preloadResponsePromise;
|
||||
if (preloadResponse) {
|
||||
console.info('using preload response', preloadResponse);
|
||||
putInCache(request, preloadResponse.clone());
|
||||
return preloadResponse;
|
||||
}
|
||||
|
||||
// Next try to get the resource from the network
|
||||
try {
|
||||
const responseFromNetwork = await fetch(request);
|
||||
// response may be used only once
|
||||
// we need to save clone to put one copy in cache
|
||||
// and serve second one
|
||||
putInCache(request, responseFromNetwork.clone());
|
||||
return responseFromNetwork;
|
||||
} catch (error) {
|
||||
return new Response('Network error happened', {
|
||||
status: 408,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const deleteCache = async key => {
|
||||
await caches.delete(key)
|
||||
}
|
||||
|
||||
const deleteOldCaches = async () => {
|
||||
const cacheKeepList = [currentVersion];
|
||||
const keyList = await caches.keys()
|
||||
const cachesToDelete = keyList.filter(key => !cacheKeepList.includes(key))
|
||||
await Promise.all(cachesToDelete.map(deleteCache));
|
||||
}
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(deleteOldCaches());
|
||||
});
|
||||
|
||||
const enableNavigationPreload = async () => {
|
||||
if (self.registration.navigationPreload) {
|
||||
// Enable navigation preloads!
|
||||
await self.registration.navigationPreload.enable();
|
||||
}
|
||||
};
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(enableNavigationPreload());
|
||||
});
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(
|
||||
addResourcesToCache([
|
||||
'./heonian-resources/wordlist.json',
|
||||
'./heonian-ime/ime.js',
|
||||
'./font.otf',
|
||||
'./index.html',
|
||||
'./main.css',
|
||||
'./main.js',
|
||||
'./manifest.json'
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
event.respondWith(
|
||||
cacheFirst({
|
||||
request: event.request,
|
||||
preloadResponsePromise: event.preloadResponse
|
||||
})
|
||||
);
|
||||
});
|
||||
586
wordlist.json
@@ -1,586 +0,0 @@
|
||||
{
|
||||
"": [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "In an early stage of development.",
|
||||
"translation": "Young",
|
||||
"antonyms": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
" ": [
|
||||
{
|
||||
"type": "expression",
|
||||
"meaning": "Utilized to seek confirmation from listener.",
|
||||
"translation": "Isn't that right?"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "marker",
|
||||
"meaning": "Follows an object in which the action of the verb is intended to.",
|
||||
"translation": "At, to, towards, for, into"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To rest in an horizontal position.",
|
||||
"translation": "To lie."
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Usable heat or power.",
|
||||
"translation": "Energy"
|
||||
},
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Source of sorcery power.",
|
||||
"translation": "Magic energy"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Animated entity powered by sorcery or any other energy source.",
|
||||
"translation": "Animated construct."
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Inducement, reason or goal that motivates someone to do something.",
|
||||
"translation": "Desire"
|
||||
},
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The ability to control oneself and determine oneself's course of action.",
|
||||
"translation": "Willpower"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "A kind of genderless shapeshifting spirits who got sealed in the depths of the world during the old era, characteristic for having intrinsic power to control a specific feeling of any conscious being.",
|
||||
"translation": "Demon"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Having little length, not long.",
|
||||
"translation": "Short",
|
||||
"antonyms": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "expression",
|
||||
"meaning": "A consenting reply.",
|
||||
"translation": "Yes, correct",
|
||||
"antonym": ""
|
||||
},
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "To a high degree or intensity.",
|
||||
"translation": "Very"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The route or course along which something travels or moves.",
|
||||
"translation": "Path",
|
||||
"meta-etymology": "Used to derive meaning for a word suggested by @taminaminam@tech.lgbt"
|
||||
},
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The single complete movement of raising one foot and putting it down in another spot, as in walking.",
|
||||
"translation": "Step",
|
||||
"meta-etymology": "Used to derive meaning for a word suggested by @taminaminam@tech.lgbt"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "expression",
|
||||
"meaning": "Used to express gratitude or grateful thoughts.",
|
||||
"translation": "Thanks",
|
||||
"meta-etymology": "Suggested by @gamer@bungle.online"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To move over a surface by taking steps.",
|
||||
"translation": "To walk",
|
||||
"canon-etymology": "Derived from the word , meaning step."
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": " A style of animation developed in Japan, characterized by stylized colorful art and often adult themes.",
|
||||
"translation": "Anime",
|
||||
"meta-etymology": "Yeah it comes from the word \"anime\"."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "pronoun",
|
||||
"meaning": "The second-person singular pronoun.",
|
||||
"translation": "You",
|
||||
"examples": {
|
||||
" ?":"Were you sleeping?",
|
||||
" ": "I like you."
|
||||
}
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": " To name or list (the units of a group or collection) one by one in order to determine a total; number.",
|
||||
"translation": "To count"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To move through or on top of a liquid.",
|
||||
"translation": "To swim"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The terminal part of the humanoid arm located below the forearm, used for grasping and holding and consisting of the wrist, palm, several fingers, and an opposable thumb.",
|
||||
"translation": "Hand"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To have and keep in one's grasp, preventing from falling or moving.",
|
||||
"translation": "To hold"
|
||||
},
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To clasp or hold closely, especially in the arms, as in affection; embrace.",
|
||||
"translation": "To hug"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Below average in size or extent.",
|
||||
"translation": "Small",
|
||||
"antonyms": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Above average in size or extent.",
|
||||
"translation": "Large",
|
||||
"antonyms": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The round or oval reproductive body of various animals, including birds, reptiles, amphibians, fishes, and insects, consisting usually of an embryo surrounded by nutrient material and a protective covering.",
|
||||
"translation": "Egg."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The day before the present day.",
|
||||
"translation": "Yesterday",
|
||||
"canon-etymology": "Fusion of words and ."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "A kind of plant characteristic for having jointed stems sheathed by long narrow leaves, flowers in spikes, and seedlike fruits. This includes cereals, bamboo, etc",
|
||||
"translation": "Grass"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "A kind of various long-eared, short-tailed, small to moderate size burrowing mammals. They have long hind legs, with four toes on each foot, and shorter fore legs, with five toes each.",
|
||||
"translation": "Rabbit",
|
||||
"meta-etymology": "Meme of mispelling bunny."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Existing in plentiful supply.",
|
||||
"translation": "Abundant",
|
||||
},
|
||||
{
|
||||
"type": "pronoun",
|
||||
"meaning": "A large number of something.",
|
||||
"translation": "Many",
|
||||
"meta-etymology": "From english \"Big\"."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Any kind of warm-blooded vertebrates characterised by feathers, toothless beaked jaws, the laying of hard-shelled eggs, a high metabolic rate, a four-chambered heart, and a strong yet lightweight skeleton.",
|
||||
"translation": "Bird"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To make, join or decorate pieces of fabric by means of a thread repeatedly passed through with a needle or similar implement.",
|
||||
"translation": "To sew"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Garments for the body; articles of dress; wearing apparel.",
|
||||
"translation": "Clothes",
|
||||
"canon-etymology": "Noun formed from the verb ."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To deprive of life.",
|
||||
"translation": "To kill",
|
||||
},
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To destroy a vitally essential quality in.",
|
||||
"translation": "To kill",
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Of small or limited width, especially in comparison with length.",
|
||||
"translation": "Narrow"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The fleshy, movable, muscular organ, found mostly in most vertebrates to the floor of the mouth, that is the principal organ of taste, an aid in chewing and swallowing, and, in sometimes an important aspect of speech.",
|
||||
"translation": "Tongue"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The organ of smell and entrance to the respiratory tract, consisting of a prominent structure divided into two hair-lined air passages by a median septum.",
|
||||
"translation": "Nose"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Being such that every part of the surface or the circumference is equidistant from the center.",
|
||||
"translation": "Round",
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To increase in size or volume as a result of internal pressure; expand.",
|
||||
"translation": "To swell"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "marker",
|
||||
"meaning": "Follows the subject in a clause of a sentence"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To form letters, words, or symbols on a surface with an instrument.",
|
||||
"translation": "To write"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Zenish is the deceased wind and movement god in the Myr religion. Sibling of Olidia, they both ruled over the development of the physical world with kind and honest intentions. Anciently cherished, they are now mostly forgotten, yet signs of their existance can be found in dialectical expressions, ancient books and old inscryptions.",
|
||||
"translation": "God of Change",
|
||||
"canon-etymology": "Umyr: \" (greater) + (movement) + (power)\"",
|
||||
"meta-etymology": "Like most myrean religion, from old minecraft SMP lore."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Any kind of the sometimes winged reptile-like, horned, four-legged creatures capable of the use of magic, specifically elemental magic and shapeshifting. They are are said to be able to utilize great amounts of magic energy naturally.",
|
||||
"translation": "Dragon"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "(Slang) Domestic species of small carnivorous mammal, who have a strong flexible body, quick reflexes, sharp teeth and retractable claws adapted to killing small prey, with night vision and sense of smell well developed.",
|
||||
"translation": "Cat",
|
||||
"canon-etymology": "Heon: \" (dragon) + (companion) \"",
|
||||
"meta-etymology": "Suggested by @lunadragofelis@embracing.space"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Intelligent humanoid race with dragon-like features.",
|
||||
"translation": "Dragonborn",
|
||||
"canon-etymology": "Heon: \" (dragon) + (being)\"",
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Not clean or pure.",
|
||||
"translation": "Dirty"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": ":Having a relatively low temperature or one lower than normal or expected.",
|
||||
"translation": "Cold"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Free from curves, bends, angles, or irregularities.",
|
||||
"translation": "straight"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Deerfox"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Any of various carnivorous mammals related to but smaller than wolves with shorter legs, more pointed muzzle, large erect ears, and long bushy tail",
|
||||
"translation": "Fox"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To be not dead or inanimate,",
|
||||
"translation": "To live"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "marker",
|
||||
"meaning": "Follows an object in which the action of the verb happens inside something or somewhere.",
|
||||
"translation": "In, inside."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Fine particles of matter.",
|
||||
"translation": "Dust"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "marker",
|
||||
"meaning": "Follows the whole sentence to denote it as a question."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The determining cause by which things in general are believed to happen as they do, specially when causing people to meet eachother.",
|
||||
"translation": "Fate",
|
||||
"meta-etymology": "To derive a term suggested by fern."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Of two or more things that are fated to walk the same path together.",
|
||||
"translation": "Fated",
|
||||
"canon-etymology": "Heon: \" (fate) + (path, step)\"",
|
||||
"meta-etymology": "Suggested by fern."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "A dearly loved person who is considered to be mutually fated.",
|
||||
"translation": "Beloved",
|
||||
"canon-etymology": "Heon: \" (fated) + (being)\"",
|
||||
"meta-etymology": "Suggested by fern."
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "A suspension of particles in a gas.",
|
||||
"translation": "Smoke"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "The fertilized ripened ovule of a flowering plant containing an embryo and capable normally of germination to produce a new plant.",
|
||||
"translation": "Seed"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "pronoun",
|
||||
"meaning": "(Interrogative) One out of a group",
|
||||
"translation": "Which"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "pronoun",
|
||||
"meaning": "(Interrogative) Which person",
|
||||
"translation": "Who"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "pronoun",
|
||||
"meaning": "(Interrogative) Which location",
|
||||
"translation": "Where"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "pronoun",
|
||||
"meaning": "(Interrogative) Which time",
|
||||
"translation": "When"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "pronoun",
|
||||
"meaning": "(Interrogative) Which manner",
|
||||
"translation": "How"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "pronoun",
|
||||
"meaning": "(Interrogative) Which matter",
|
||||
"translation": "What"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Any subterranean plant part.",
|
||||
"translation": "Root"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "expression",
|
||||
"meaning": "An affirmative reply.",
|
||||
"translation": "Yes"
|
||||
},
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "Having recently come into existence.",
|
||||
"translation": "New"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Beings generally capable of rapid movement and reaction to stimuli, breathing oxygen, consume organic material, sexual reproduction and an ontogenetic stage in early development.",
|
||||
"translation": "Animal"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Any of various swimming birds in which the neck and legs are short, the feet typically webbed, the bill often broad and flat, and the sexes usually different from each other in plumage.",
|
||||
"translation": "Duck"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "A lateral outgrowth from a plant stem that is typically a flattened expanded variably shaped greenish organ, constitutes a unit of the foliage, and functions primarily in food manufacture by photosynthesis or anything similar.",
|
||||
"translation": "Leaf"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To drink in small quantities.",
|
||||
"translation": "To sip"
|
||||
}
|
||||
],
|
||||
"" : [
|
||||
{
|
||||
"type": "",
|
||||
"meaning": "",
|
||||
"translation": ""
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "snow",
|
||||
"translation": "snow",
|
||||
"meta-etymology": "I want one my names to mean something pretty - Ari.",
|
||||
"examples": {
|
||||
" ": "i hope ari can see snow"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "noun",
|
||||
"meaning": "Free from harm or risk.",
|
||||
"translation": "Safety",
|
||||
"meta-etymology": "Suggested by @taminaminam@tech.lgbt"
|
||||
},
|
||||
{
|
||||
"type": "modifier",
|
||||
"meaning": "The condition of being safe from undergoing or causing hurt, injury, or loss",
|
||||
"translation": "Safe",
|
||||
"meta-etymology": "Suggested by @taminaminam@tech.lgbt"
|
||||
}
|
||||
],
|
||||
"": [
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To have an inclination or preference",
|
||||
"translation": "To like"
|
||||
},
|
||||
{
|
||||
"type": "verb",
|
||||
"meaning": "To find pleasant or attractive, to enjoy",
|
||||
"translation": "To enjoy"
|
||||
}
|
||||
]
|
||||
}
|
||||