Compare commits

...

39 Commits

Author SHA1 Message Date
ef9aed3126 uwu 2022-07-31 09:28:37 +02:00
b6b3655142 aa 2022-06-25 11:50:01 +02:00
38376225c8 huh 2022-06-25 11:49:44 +02:00
00032f9cc0 validate json 2022-06-25 11:47:58 +02:00
c35d27198c close #28 i think 2022-06-19 11:55:12 +02:00
82e4d36b14 fix funny html bug 2022-06-19 11:35:33 +02:00
a6542fbe60 hhh 2022-06-19 11:04:43 +02:00
30b3cf0d0a uncrash everything on pressing all 2022-06-19 11:00:08 +02:00
132e49b589 HELP 2022-06-12 00:33:34 +02:00
19b1c73dca help 2022-06-12 00:32:19 +02:00
b8ae68eff8 swupdate test 2022-06-12 00:23:29 +02:00
05623222c8 service worker, attempt 1 2022-06-12 00:14:06 +02:00
9fb89f31d5 oop 2022-06-11 23:32:31 +02:00
2c1164a6bc basic pwa stuff 2022-06-11 23:27:17 +02:00
65aec63e12 oops forgot to. 2022-06-11 23:10:32 +02:00
56f524df38 move wordlist 2022-06-11 23:10:19 +02:00
0e8ac06e26 mess with how the code looks too much. sorry, yari >~< 2022-06-11 22:58:22 +02:00
Bizcochito
ce1c8c7bbb worked on #14, now show:random gets a random english word with translation and querries it with an aux array 2022-06-11 09:23:53 +02:00
Bizcochito
2e235e575f worked on #20 and #21, also removed the all var, in exange for checking it on show:all 2022-06-11 09:14:50 +02:00
4d56328ceb work on #2, #7. need to make it so it acutally opens in new tab (*or atleast, like, you can cmd-click to do that. that might be preferable, actually...) 2022-06-11 02:28:35 +02:00
1d4caa5f2b close #6 2022-06-11 02:03:52 +02:00
e153143a7a Merge branch 'main' of ssh.succubi.services:heonian.org/heonian-webdic 2022-06-11 01:41:16 +02:00
04058a3be3 close #13, more or less 2022-06-11 01:41:14 +02:00
UndeadMaelys
926bbf927b fixed a Umyr definition written in heonian script. Umyr language is solely spoken. 2022-06-11 01:32:25 +02:00
285c707290 close #3. needs to look better, but good enuff for now 2022-06-11 01:29:35 +02:00
03d6ad19f3 very very simple readme. update this for gods sake remi 2022-06-11 01:07:46 +02:00
8cbb971c40 fix heo not being displayed in notes/meta 2022-06-11 01:05:52 +02:00
f88202b792 close #1 2022-06-11 01:03:01 +02:00
baa691fa03 history popstate stuff. lil messy implementation, but idfk how to clean up,,,, 2022-06-11 00:47:43 +02:00
980ab5b84c ! 2022-06-11 00:22:47 +02:00
UndeadMaelys
b2ef344949 added some etymologies 2022-06-11 00:12:13 +02:00
UndeadMaelys
b19dc38898 Words up to 69 2022-06-11 00:04:57 +02:00
UndeadMaelys
9b5f272cd5 Words up to 69 2022-06-11 00:04:38 +02:00
08b5f6daf6 ruby++ 2022-06-10 05:12:45 +02:00
85f9625fea pushing despite. not very done cuz i wanna upload 2022-06-10 04:53:11 +02:00
fad6471e48 simple search results stats 2022-06-10 03:41:44 +02:00
260e25e37a trying diffrent design for translations. not sure if i like this more than just hiding the tl, but also. hiding the tl is silly? 2022-06-10 01:33:31 +02:00
a035ea3201 merge + fix a bit 2022-06-10 01:18:38 +02:00
UndeadMaelys
a2e7559f5d words up to 40 2022-06-09 08:26:25 +02:00
21 changed files with 548 additions and 202 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
update.php

1
.gitignore_global Normal file
View File

@@ -0,0 +1 @@
.DS_Store

3
.gitmodules vendored
View File

@@ -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
View 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

Submodule heonian-resources added at 9f0c4998ee

BIN
icons/icon-128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
icons/icon-144x144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
icons/icon-152x152.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
icons/icon-192x192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
icons/icon-384x384.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
icons/icon-512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
icons/icon-72x72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
icons/icon-96x96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
icons/maskable_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -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>

View File

@@ -67,6 +67,10 @@ a:hover {
cursor: pointer;
}
.clickable {
cursor: pointer;
}
.heonian {
font-family: "heonian";
}
@@ -128,6 +132,9 @@ header input:focus {
header span.heonian {
font-size: 1.5rem;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
}
header.fullscreen {
@@ -145,6 +152,7 @@ header.fullscreen {
header.fullscreen span.heonian {
font-size: 8rem;
cursor: default;
}
header.fullscreen #search {
@@ -152,6 +160,10 @@ header.fullscreen #search {
max-width: 500px;
}
header #update {
display: none;
}
.header-animation {
animation: clearly-cheating 1s ease-in-out;
}
@@ -191,6 +203,10 @@ main {
padding-top: 0;
}
.result:last-child {
border-bottom: none;
}
.result-meaning {
padding-bottom: 8px;
}
@@ -222,6 +238,14 @@ main {
color: var(--darkgrey);
margin-top: 6px;
margin-bottom: 6px;
border-left: 3px solid var(--darkgrey);
padding-left: 4px;
font-family: var(--font-h);
}
.result-translation {
font-size: 0.9rem;
color: var(--darkgrey);
}
.result summary {
@@ -235,4 +259,17 @@ main {
font-size: 1.25rem;
}
.result details.result-meta p {
font-size: 1rem;
font-family: var(--font-h);
}
.results-header-count::after {
content: ", ";
}
.results-header-count:last-child::after {
content: "";
}
/* todo. organize this file better. this is a fucking mess */

369
main.js
View File

@@ -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")) {
@@ -78,8 +80,9 @@ document.addEventListener("keydown", (e) => {
}
});
function stripWord(word) {
return word.replace(/[^a-zA-Z-]/gu, "").toLowerCase();
function stripWord(word, space = false) {
return space == false ? word.replace(/[^a-zA-Z-]/gu, "").toLowerCase() :
word.replace(/[^a-zA-Z-\s]/gu, "").toLowerCase();
}
heonianVowels = {
@@ -131,7 +134,7 @@ heonianConsonants = {
"10": "h",
};
function heonianToRoman(text) {
function heonianToRoman(text, strict = false) {
let roman = "";
for (let i = 0; i < text.length; i++) {
let h = text.codePointAt(i);
@@ -146,15 +149,64 @@ function heonianToRoman(text) {
roman += heonianConsonants[h[1] + "" + h[2]] + heonianVowels[h[3] - 1];
}
}
} else {
} else if (strict == false) {
roman += text.charAt(i);
}
}
return roman;
}
function processVerb(word) {
//basically, turn welikanyapash into liku
//and uhhhhhhhhhhh maybe. return as an object with. all the things . used, for info
return word;
//but ... not yet uwu
}
function isHeonian(word) {
letters = word.split("");
for (let i = 0; i < letters.length; i++) {
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) => {
@@ -164,24 +216,40 @@ function loadDictionary() {
let keys = Object.keys(json);
//prepare search. maybe async this if we're loading a specific word?
for (let i = 0; i < keys.length; i++) {
//create array
searchDictionary[keys[i]] = [];
try {
if (keys[i] == "") continue;
//create array
searchDictionary[keys[i]] = [];
//add: word
searchDictionary[keys[i]].push(keys[i]);
//add: word
// searchDictionary[keys[i]].push(keys[i]);
//add: romanized word
searchDictionary[keys[i]].push(stripWord(heonianToRoman(keys[i])));
//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")));
//add: translations, meanings
for (let o = 0; o < values[i].length; o++) {
searchDictionary[keys[i]].push(stripWord(values[i][o]["meaning"]));
searchDictionary[keys[i]].push(stripWord(values[i][o]["translation"]));
//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("meaning")) searchDictionary[keys[i]].push(stripWord(values[i][o]["meaning"], true));
}
} catch (e) {
console.log(keys[i] + " failed to load :/");
}
}
//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");
@@ -190,41 +258,104 @@ function loadDictionary() {
});
}
function search(word) {
word = stripWord(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]);
words[i] = heonianToRoman(words[i]);
words[i] = processVerb(words[i]);
}
word = words.join("");
console.log("debug - search: " + word);
let result = [];
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() {
let results = search(header.querySelector("input").value);
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;
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 = "";
/*
[words - 420 found / expressions - 69 found / wahtever else - ygettheidea] (click one to filter to just those)
*/
let types = {}
for (let i = 0; i < results.length; i++) {
let result = document.createElement("div");
result.classList.add("result");
// 1. add word in heo + romanized ruby as header
let header = document.createElement("ruby");
let header = document.createElement("span");
header.classList.add("result-header");
header.innerHTML = results[i] + " <rt>" + heonianToRoman(results[i]) + "</rt>";
header.innerHTML = generateRuby(results[i]);
// 2. add tags [tags like. common word, slang, formal???, type, etc]
// hhh how do i do this part, what tags. would i add. would this be. per word, or per definition?
// 3. formal/nonformal versions, inflections button
// could try to work on this though
// 4. audio clip if found
@@ -236,49 +367,215 @@ function doSearch() {
repeat for all meanings of word,
*/
result.appendChild(header);
let last = "";
for (let o = 0; o < json[results[i]].length; o++) {
let meaning = document.createElement("div");
meaning.classList.add("result-meaning");
//ripping off jisho: Bold, word type (*required)
meaning.innerHTML += "<b class='capitalize'>"+json[results[i]][o]["type"]+"</b>";
//number, meaning (*required)
meaning.innerHTML += "<br><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) {
meaning.innerHTML += "<br><details><summary>Translation</summary><p>"+json[results[i]][o]["translation"]+"</p></details>";
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"]]++;
}
//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'>"+e+"</span> - "+json[results[i]][o]["examples"][e];
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><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><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.
}
main.appendChild(result);
}
types = sortObject(types);
let header = document.createElement("div");
header.classList.add("results-header");
//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) {
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")) {
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
View 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
View 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
View 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
})
);
});

View File

@@ -1,164 +0,0 @@
{
"": [
{
"type": "modifier",
"meaning": "In an early stage of development.",
"translation": "Young",
"antonym": ""
}
],
" ": [
{
"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",
"antonym": ""
}
],
"": [
{
"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": "noun",
"meaning": "snow",
"translation": "snow",
"notes": "this is where notes go",
"meta-etymology": "I want one my names to mean something pretty - Ari.",
"examples": {
"     ": "i hope ari can see snow"
}
},
{
"type": "noun",
"meaning": "safety",
"translation": "Safety",
"meta-etymology": "Suggested by @taminaminam@tech.lgbt"
},
{
"type": "modifier",
"meaning": "safety",
"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"
}
]
}