Compare commits
3 Commits
c4b7fa4257
...
0673a2378e
Author | SHA1 | Date |
---|---|---|
Robbie Antenesse | 0673a2378e | |
Robbie Antenesse | 5c4e8197b9 | |
Robbie Antenesse | 5311aeea9d |
|
@ -39,10 +39,10 @@
|
||||||
<h2>Dictionary Name</h2>
|
<h2>Dictionary Name</h2>
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li id="toggleDescription">Description</li><li id="toggleDetails">Details</li><li id="toggleStats" class="active">Stats</li><li id="showEdit" onclick="document.getElementById('editModal').style.display='block'">Edit</li>
|
<li>Description</li><li>Details</li><li>Stats</li><li onclick="document.getElementById('editModal').style.display='block'">Edit</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<article id="detailsPanel">
|
<article id="detailsPanel" style="display:none;">
|
||||||
<p>The dictionary details</p>
|
<p>The dictionary details</p>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"sass": "^1.19.0"
|
"sass": "^1.19.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"normalize.css": "^8.0.1"
|
"normalize.css": "^8.0.1",
|
||||||
|
"snarkdown": "^1.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
export const DEFAULT_DICTIONARY = {
|
||||||
|
name: 'New',
|
||||||
|
specification: 'Dictionary',
|
||||||
|
description: 'A new dictionary.',
|
||||||
|
partsOfSpeech: ['Noun', 'Adjective', 'Verb'],
|
||||||
|
alphabeticalOrder: [],
|
||||||
|
details: {
|
||||||
|
phonology: {
|
||||||
|
consonants: [],
|
||||||
|
vowels: [],
|
||||||
|
blends: [],
|
||||||
|
phonotactics: {
|
||||||
|
onset: [],
|
||||||
|
nucleus: [],
|
||||||
|
coda: [],
|
||||||
|
exceptions: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
orthography: {
|
||||||
|
notes: '',
|
||||||
|
},
|
||||||
|
grammar: {
|
||||||
|
notes: '',
|
||||||
|
},
|
||||||
|
// custom: [
|
||||||
|
// // {
|
||||||
|
// // name: 'Example Tab',
|
||||||
|
// // content: `This is an _example_ tab to show how **tabs** work with [Markdown](${ MARKDOWN_LINK })!`,
|
||||||
|
// // }
|
||||||
|
// ],
|
||||||
|
},
|
||||||
|
words: [
|
||||||
|
/* {
|
||||||
|
name: '',
|
||||||
|
pronunciation: '',
|
||||||
|
partOfSpeech: '',
|
||||||
|
simpleDefinition: '',
|
||||||
|
longDefinition: '',
|
||||||
|
wordId: 0
|
||||||
|
}, */
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
allowDuplicates: false,
|
||||||
|
caseSensitive: false,
|
||||||
|
sortByDefinition: false,
|
||||||
|
isComplete: false,
|
||||||
|
isPublic: false,
|
||||||
|
},
|
||||||
|
lastUpdated: null,
|
||||||
|
createdOn: 0,
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
export function removeTags(html) {
|
||||||
|
var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
|
||||||
|
|
||||||
|
var tagOrComment = new RegExp(
|
||||||
|
'<(?:'
|
||||||
|
// Comment body.
|
||||||
|
+ '!--(?:(?:-*[^->])*--+|-?)'
|
||||||
|
// Special "raw text" elements whose content should be elided.
|
||||||
|
+ '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
|
||||||
|
+ '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
|
||||||
|
// Regular name
|
||||||
|
+ '|/?[a-z]'
|
||||||
|
+ tagBody
|
||||||
|
+ ')>',
|
||||||
|
'gi');
|
||||||
|
var oldHtml;
|
||||||
|
do {
|
||||||
|
oldHtml = html;
|
||||||
|
html = html.replace(tagOrComment, '');
|
||||||
|
} while (html !== oldHtml);
|
||||||
|
return html.replace(/</g, '<');
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
import './main.scss';
|
import './main.scss';
|
||||||
|
|
||||||
|
import { DEFAULT_DICTIONARY } from './constants';
|
||||||
|
import setupListeners from './js/setupListeners';
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
console.log('initializing');
|
console.log('initializing');
|
||||||
|
window.currentDictionary = JSON.parse(JSON.stringify(DEFAULT_DICTIONARY));
|
||||||
|
setupListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onload = (function (oldLoad) {
|
window.onload = (function (oldLoad) {
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
import md from 'snarkdown';
|
||||||
|
import {removeTags} from '../helpers';
|
||||||
|
|
||||||
|
export function showSection(sectionName) {
|
||||||
|
switch (sectionName) {
|
||||||
|
case 'description': showDescription(); break;
|
||||||
|
case 'details': showDetails(); break;
|
||||||
|
case 'stats': showStats(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDescription() {
|
||||||
|
const detailsPanel = document.getElementById('detailsPanel');
|
||||||
|
detailsPanel.style.display = 'block';
|
||||||
|
const {description} = window.currentDictionary;
|
||||||
|
const descriptionHTML = md(removeTags(description));
|
||||||
|
|
||||||
|
detailsPanel.innerHTML = descriptionHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDetails() {
|
||||||
|
const detailsPanel = document.getElementById('detailsPanel');
|
||||||
|
detailsPanel.style.display = 'block';
|
||||||
|
const {partsOfSpeech, alphabeticalOrder} = window.currentDictionary;
|
||||||
|
const {phonology, orthography, grammar} = window.currentDictionary.details;
|
||||||
|
const partsOfSpeechHTML = `<p><strong>Parts of Speech:</strong> ${partsOfSpeech.map(partOfSpeech => '<span class="tag">' + partOfSpeech + '</span>').join(' ')}</p>`;
|
||||||
|
const alphabeticalOrderHTML = `<p><strong>Alphabetical Order:</strong> ${
|
||||||
|
(alphabeticalOrder.length > 0 ? alphabeticalOrder : ['English Alphabet']).map(letter => `<span class="tag">${letter}</span>`).join(' ')
|
||||||
|
}</p>`;
|
||||||
|
const generalHTML = `<h3>General</h3>${partsOfSpeechHTML}${alphabeticalOrderHTML}`;
|
||||||
|
|
||||||
|
const {consonants, vowels, blends, phonotactics} = phonology
|
||||||
|
const consonantHTML = `<p><strong>Consonants:</strong> ${consonants.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||||
|
const vowelHTML = `<p><strong>Vowels:</strong> ${vowels.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||||
|
const blendHTML = blends.length > 0 ? `<p><strong>Polyphthongs / Blends:</strong> ${blends.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>` : '';
|
||||||
|
const phonologyHTML = `<h3>Phonology</h3>
|
||||||
|
<div class="split two">
|
||||||
|
<div>${consonantHTML}</div>
|
||||||
|
<div>${vowelHTML}</div>
|
||||||
|
</div>
|
||||||
|
${blendHTML}`;
|
||||||
|
|
||||||
|
const {onset, nucleus, coda, exceptions} = phonotactics;
|
||||||
|
const onsetHTML = `<p><strong>Onset:</strong> ${onset.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||||
|
const nucleusHTML = `<p><strong>Nucleus:</strong> ${nucleus.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||||
|
const codaHTML = `<p><strong>Coda:</strong> ${coda.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||||
|
const exceptionsHTML = exceptions.trim().length > 0 ? '<p><strong>Exceptions:</strong></p><div>' + md(removeTags(exceptions)) + '</div>' : '';
|
||||||
|
const phonotacticsHTML = `<h3>Phonotactics</h3>
|
||||||
|
<div class="split three">
|
||||||
|
<div>${onsetHTML}</div>
|
||||||
|
<div>${nucleusHTML}</div>
|
||||||
|
<div>${codaHTML}</div>
|
||||||
|
</div>
|
||||||
|
${exceptionsHTML}`;
|
||||||
|
|
||||||
|
const orthographyHTML = '<h3>Orthography</h3><p><strong>Notes:</strong></p><div>' + md(removeTags(orthography.notes)) + '</div>';
|
||||||
|
const grammarHTML = '<h3>Grammar</h3><p><strong>Notes:</strong></p><div>' + md(removeTags(grammar.notes)) + '</div>';
|
||||||
|
|
||||||
|
detailsPanel.innerHTML = generalHTML + phonologyHTML + phonotacticsHTML + orthographyHTML + grammarHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showStats() {
|
||||||
|
const detailsPanel = document.getElementById('detailsPanel');
|
||||||
|
detailsPanel.style.display = 'block';
|
||||||
|
const wordStats = getWordsStats();
|
||||||
|
const numberOfWordsHTML = `<p><strong>Number of Words</strong><br>${wordStats.numberOfWords.map(stat => `<span><span class="tag">${stat.name}</span><span class="tag">${stat.value}</span></span>`).join(' ')}</p>`;
|
||||||
|
const wordLengthHTML = `<p><strong>Word Length</strong><br><span><span class="tag">Shortest</span><span class="tag">${wordStats.wordLength.shortest}</span></span>
|
||||||
|
<span><span class="tag">Longest</span><span class="tag">${wordStats.wordLength.longest}</span></span>
|
||||||
|
<span><span class="tag">Average</span><span class="tag">${wordStats.wordLength.average}</span></span></p>`;
|
||||||
|
const letterDistributionHTML = `<p><strong>Letter Distribution</strong><br>${wordStats.letterDistribution.map(stat => `<span title="${stat.number} ${stat.letter}'s total"><span class="tag">${stat.letter}</span><span class="tag">${stat.percentage.toFixed(2)}</span></span>`).join(' ')}</p>`;
|
||||||
|
const totalLettersHTML = `<p><strong>${wordStats.totalLetters} Total Letters</strong></p>`;
|
||||||
|
|
||||||
|
detailsPanel.innerHTML = numberOfWordsHTML + wordLengthHTML + letterDistributionHTML + totalLettersHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWordsStats() {
|
||||||
|
const {words, partsOfSpeech} = window.currentDictionary;
|
||||||
|
const {caseSensitive} = window.currentDictionary.settings;
|
||||||
|
|
||||||
|
const wordStats = {
|
||||||
|
numberOfWords: [
|
||||||
|
{
|
||||||
|
name: 'Total',
|
||||||
|
value: words.length,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
wordLength: {
|
||||||
|
shortest: 0,
|
||||||
|
longest: 0,
|
||||||
|
average: 0,
|
||||||
|
},
|
||||||
|
letterDistribution: [
|
||||||
|
/* {
|
||||||
|
letter: '',
|
||||||
|
number: 0,
|
||||||
|
percentage: 0.00,
|
||||||
|
} */
|
||||||
|
],
|
||||||
|
totalLetters: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
partsOfSpeech.forEach(partOfSpeech => {
|
||||||
|
const wordsWithPartOfSpeech = words.filter(word => word.partOfSpeech === partOfSpeech);
|
||||||
|
wordStats.numberOfWords.push({
|
||||||
|
name: partOfSpeech,
|
||||||
|
value: wordsWithPartOfSpeech.length,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
wordStats.numberOfWords.push({
|
||||||
|
name: 'Unclassified',
|
||||||
|
value: words.filter(word => !partsOfSpeech.includes(word.partOfSpeech)).length,
|
||||||
|
});
|
||||||
|
|
||||||
|
let totalLetters = 0;
|
||||||
|
const numberOfLetters = {};
|
||||||
|
|
||||||
|
words.forEach(word => {
|
||||||
|
const shortestWord = wordStats.wordLength.shortest;
|
||||||
|
const longestWord = wordStats.wordLength.longest;
|
||||||
|
const wordLetters = word.name.split('');
|
||||||
|
const lettersInWord = wordLetters.length;
|
||||||
|
|
||||||
|
totalLetters += lettersInWord;
|
||||||
|
|
||||||
|
if (shortestWord === 0 || lettersInWord < shortestWord) {
|
||||||
|
wordStats.wordLength.shortest = lettersInWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (longestWord === 0 || lettersInWord > longestWord) {
|
||||||
|
wordStats.wordLength.longest = lettersInWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
wordLetters.forEach(letter => {
|
||||||
|
const letterToUse = caseSensitive ? letter : letter.toLowerCase();
|
||||||
|
if (!numberOfLetters.hasOwnProperty(letterToUse)) {
|
||||||
|
numberOfLetters[letterToUse] = 1;
|
||||||
|
} else {
|
||||||
|
numberOfLetters[letterToUse]++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
wordStats.totalLetters = totalLetters;
|
||||||
|
wordStats.wordLength.average = words.length > 0 ? totalLetters / words.length : 0;
|
||||||
|
|
||||||
|
for (const letter in numberOfLetters) {
|
||||||
|
if (numberOfLetters.hasOwnProperty(letter)) {
|
||||||
|
const number = numberOfLetters[letter];
|
||||||
|
wordStats.letterDistribution.push({
|
||||||
|
letter,
|
||||||
|
number,
|
||||||
|
percentage: number / totalLetters,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wordStats.letterDistribution.sort((a, b) => {
|
||||||
|
if (a.percentage === b.percentage) return 0;
|
||||||
|
return (a.percentage > b.percentage) ? -1 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return wordStats;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import {showSection} from './displayToggles';
|
||||||
|
|
||||||
|
export default function setupListeners() {
|
||||||
|
setupDetailsTabs();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupDetailsTabs () {
|
||||||
|
let tabs = document.querySelectorAll('#detailsSection nav li');
|
||||||
|
tabs.forEach(tab => {
|
||||||
|
tab.addEventListener('click', () => {
|
||||||
|
const section = tab.innerText.toLowerCase();
|
||||||
|
const isActive = tab.classList.contains('active');
|
||||||
|
tabs.forEach(t => t.classList.remove('active'));
|
||||||
|
if (isActive) {
|
||||||
|
document.getElementById('detailsPanel').style.display = 'none';
|
||||||
|
} else {
|
||||||
|
tab.classList.add('active');
|
||||||
|
showSection(section);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,9 +1,26 @@
|
||||||
.button {
|
.tag {
|
||||||
cursor: pointer;
|
|
||||||
padding: 3px 9px;
|
padding: 3px 9px;
|
||||||
border: $border;
|
border: $border;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background-color: $light;
|
background-color: $light;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span .tag {
|
||||||
|
@extend .tag;
|
||||||
|
|
||||||
|
border-radius: 3px 0 0 3px;
|
||||||
|
|
||||||
|
&+.tag {
|
||||||
|
border-left: none;
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
background-color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
@extend .tag;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal {
|
.modal {
|
||||||
|
@ -58,3 +75,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.split {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
div {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
margin: 0;
|
||||||
|
margin-right: 2%;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: unset;
|
||||||
|
margin-left: 2%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.two div {
|
||||||
|
width: 46%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.three div {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,6 +72,8 @@
|
||||||
#detailsPanel {
|
#detailsPanel {
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4542,6 +4542,11 @@ snapdragon@^0.8.1:
|
||||||
source-map-resolve "^0.5.0"
|
source-map-resolve "^0.5.0"
|
||||||
use "^3.1.0"
|
use "^3.1.0"
|
||||||
|
|
||||||
|
snarkdown@^1.2.2:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/snarkdown/-/snarkdown-1.2.2.tgz#0cfe2f3012b804de120fc0c9f7791e869c59cc74"
|
||||||
|
integrity sha1-DP4vMBK4BN4SD8DJ93kehpxZzHQ=
|
||||||
|
|
||||||
source-map-resolve@^0.5.0:
|
source-map-resolve@^0.5.0:
|
||||||
version "0.5.2"
|
version "0.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"
|
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"
|
||||||
|
|
Loading…
Reference in New Issue