Compare commits
11 Commits
d3c5633821
...
3a29d56072
Author | SHA1 | Date |
---|---|---|
Robbie Antenesse | 3a29d56072 | |
Robbie Antenesse | d737ec9944 | |
Robbie Antenesse | 6c14398521 | |
Robbie Antenesse | cc70e14437 | |
Robbie Antenesse | 6f649d1790 | |
Robbie Antenesse | 2bd8645430 | |
Robbie Antenesse | 1a22fbd699 | |
Robbie Antenesse | 4cad266d52 | |
Robbie Antenesse | c5c17d022e | |
Robbie Antenesse | 72041ecafb | |
Robbie Antenesse | d5edcaf6a5 |
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"plugins": {
|
||||
"autoprefixer": {
|
||||
"browsers": [
|
||||
">1%",
|
||||
"last 4 versions",
|
||||
"Firefox ESR",
|
||||
"not ie < 9"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
22
index.html
22
index.html
|
@ -26,6 +26,19 @@
|
|||
</a>
|
||||
</section>
|
||||
<footer id="searchOptions" style="display:none;">
|
||||
<div class="split">
|
||||
<div class="quarter category">
|
||||
<h3>Search For</h3>
|
||||
</div>
|
||||
<div class="three-quarter options">
|
||||
<label>Case-Sensitive
|
||||
<input type="checkbox" id="searchCaseSensitive">
|
||||
</label>
|
||||
<label>Exact Words
|
||||
<input type="checkbox" id="searchExactWords">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="split">
|
||||
<div class="quarter category">
|
||||
<h3>Include in Search</h3>
|
||||
|
@ -55,6 +68,7 @@
|
|||
|
||||
<main>
|
||||
<aside id="sideColumn">
|
||||
<div id="mobileWordFormShow">+</div>
|
||||
<form id="wordForm">
|
||||
<label>Word<span class="red">*</span><br>
|
||||
<input id="wordName">
|
||||
|
@ -68,7 +82,7 @@
|
|||
<label>Definition<span class="red">*</span><br>
|
||||
<input id="wordDefinition" placeholder="Equivalent words">
|
||||
</label>
|
||||
<label>Details<span class="red">*</span><a class="label-button">Maximize</a><br>
|
||||
<label>Details<span class="red">*</span><a class="label-button maximize-button">Maximize</a><br>
|
||||
<textarea id="wordDetails" placeholder="Markdown formatting allowed"></textarea>
|
||||
</label>
|
||||
<div id="wordErrorMessage"></div>
|
||||
|
@ -136,7 +150,7 @@
|
|||
<label>Specification<br>
|
||||
<input id="editSpecification">
|
||||
</label>
|
||||
<label>Description<a class="label-button">Maximize</a><br>
|
||||
<label>Description<a class="label-button maximize-button">Maximize</a><br>
|
||||
<textarea id="editDescription"></textarea>
|
||||
</label>
|
||||
</section>
|
||||
|
@ -188,11 +202,11 @@
|
|||
<textarea id="editExceptions"></textarea>
|
||||
</label>
|
||||
<h3>Orthography</h3>
|
||||
<label>Notes<a class="label-button">Maximize</a><br>
|
||||
<label>Notes<a class="label-button maximize-button">Maximize</a><br>
|
||||
<textarea id="editOrthography"></textarea>
|
||||
</label>
|
||||
<h3>Grammar</h3>
|
||||
<label>Notes<a class="label-button">Maximize</a><br>
|
||||
<label>Notes<a class="label-button maximize-button">Maximize</a><br>
|
||||
<textarea id="editGrammar"></textarea>
|
||||
</label>
|
||||
</section>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"bundle": "parcel build index.html"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^9.5.1",
|
||||
"parcel-bundler": "^1.12.3",
|
||||
"sass": "^1.19.0"
|
||||
},
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
import { DEFAULT_PAGE_SIZE } from '../constants';
|
||||
import { renderWords } from "./render";
|
||||
|
||||
export function getPaginationData(words) {
|
||||
const numWords = words.length;
|
||||
const pageSize = window.localStorage.getItem('pageSize') ? parseInt(window.localStorage.getItem('pageSize')) : DEFAULT_PAGE_SIZE;
|
||||
const pages = Math.floor(numWords / pageSize);
|
||||
const currentPage = window.hasOwnProperty('currentPage') ? window.currentPage : 0;
|
||||
const pageStart = currentPage * pageSize;
|
||||
const pageEnd = typeof words[pageStart + pageSize] !== 'undefined'
|
||||
? pageStart + pageSize : words.length - 1;
|
||||
|
||||
return { numWords, pageSize, pages, currentPage, pageStart, pageEnd, };
|
||||
}
|
||||
|
||||
export function goToPage(page) {
|
||||
if (typeof page.target !== 'undefined') {
|
||||
page = page.target.value;
|
||||
|
|
|
@ -3,8 +3,9 @@ import { removeTags, slugify } from '../helpers';
|
|||
import { getWordsStats, wordExists } from './utilities';
|
||||
import { getMatchingSearchWords, highlightSearchTerm, getSearchFilters, getSearchTerm } from './search';
|
||||
import { showSection } from './displayToggles';
|
||||
import { setupSearchFilters, setupWordOptionButtons, setupPagination, setupWordOptionSelections, setupEditFormButtons } from './setupListeners';
|
||||
import { DEFAULT_PAGE_SIZE } from '../constants';
|
||||
import { setupSearchFilters, setupWordOptionButtons, setupPagination, setupWordOptionSelections, setupWordEditFormButtons, setupMaximizeModal } from './setupListeners';
|
||||
import { getPaginationData } from './pagination';
|
||||
import { getOpenEditForms } from './wordManagement';
|
||||
|
||||
export function renderAll() {
|
||||
renderDictionaryDetails();
|
||||
|
@ -108,12 +109,19 @@ export function renderWords() {
|
|||
const words = getMatchingSearchWords();
|
||||
let wordsHTML = '';
|
||||
|
||||
const pageSize = window.localStorage.getItem('pageSize') ? parseInt(window.localStorage.getItem('pageSize')) : DEFAULT_PAGE_SIZE;
|
||||
const currentPage = window.hasOwnProperty('currentPage') ? window.currentPage : 0;
|
||||
const start = currentPage * pageSize;
|
||||
const end = typeof words[start + pageSize] !== 'undefined' ? start + pageSize : words.length - 1;
|
||||
const openEditForms = getOpenEditForms();
|
||||
|
||||
words.slice(start, end).forEach(originalWord => {
|
||||
if (openEditForms.length > 0) {
|
||||
// Clone the dom nodes
|
||||
openEditForms.forEach((wordFormId, index) => {
|
||||
openEditForms[index] = document.getElementById(wordFormId.toString()).cloneNode(true);
|
||||
});
|
||||
}
|
||||
|
||||
// const { pageStart, pageEnd } = getPaginationData(words);
|
||||
|
||||
// words.slice(pageStart, pageEnd).forEach(originalWord => {
|
||||
words.forEach(originalWord => {
|
||||
let detailsMarkdown = removeTags(originalWord.longDefinition);
|
||||
const references = detailsMarkdown.match(/\{\{.+?\}\}/g);
|
||||
if (references && Array.isArray(references)) {
|
||||
|
@ -155,6 +163,16 @@ export function renderWords() {
|
|||
});
|
||||
|
||||
document.getElementById('entries').innerHTML = wordsHTML;
|
||||
|
||||
if (openEditForms.length > 0) {
|
||||
// Clone the dom nodes
|
||||
openEditForms.forEach(editForm => {
|
||||
const entryElement = document.getElementById(editForm.id);
|
||||
entryElement.parentNode.replaceChild(editForm, entryElement);
|
||||
});
|
||||
setupWordEditFormButtons();
|
||||
}
|
||||
|
||||
setupWordOptionButtons();
|
||||
setupWordOptionSelections();
|
||||
|
||||
|
@ -165,23 +183,20 @@ export function renderWords() {
|
|||
resultsText += !filters.allPartsOfSpeechChecked ? ' (Filtered)' : '';
|
||||
document.getElementById('searchResults').innerHTML = resultsText;
|
||||
|
||||
renderPagination();
|
||||
// renderPagination(words);
|
||||
}
|
||||
|
||||
export function renderPagination() {
|
||||
const numWords = window.currentDictionary.words.length;
|
||||
const pageSize = window.localStorage.getItem('pageSize') ? parseInt(window.localStorage.getItem('pageSize')) : DEFAULT_PAGE_SIZE;
|
||||
const pages = Math.floor(numWords / pageSize);
|
||||
const currentPage = window.hasOwnProperty('currentPage') ? window.currentPage : 0;
|
||||
export function renderPagination(filteredWords) {
|
||||
const paginationData = getPaginationData(filteredWords);
|
||||
|
||||
if (pages > 0) {
|
||||
let paginationHTML = (currentPage > 0 ? '<span class="button prev-button">« Previous</span>' : '')
|
||||
if (paginationData.pages > 0) {
|
||||
let paginationHTML = (paginationData.currentPage > 0 ? '<span class="button prev-button">« Previous</span>' : '')
|
||||
+ '<select class="page-selector">';
|
||||
for (let i = 0; i < pages; i++) {
|
||||
paginationHTML += `<option value="${i}"${currentPage === i ? ' selected' : ''}>Page ${i + 1}</option>`;
|
||||
for (let i = 0; i < paginationData.pages; i++) {
|
||||
paginationHTML += `<option value="${i}"${paginationData.currentPage === i ? ' selected' : ''}>Page ${i + 1}</option>`;
|
||||
}
|
||||
paginationHTML += '</select>'
|
||||
+ (currentPage < pages - 1 ? '<span class="button next-button">Next »</span>' : '');
|
||||
+ (paginationData.currentPage < paginationData.pages - 1 ? '<span class="button next-button">Next »</span>' : '');
|
||||
|
||||
Array.from(document.getElementsByClassName('pagination')).forEach(pagination => {
|
||||
pagination.innerHTML = paginationHTML;
|
||||
|
@ -191,8 +206,8 @@ export function renderPagination() {
|
|||
}
|
||||
}
|
||||
|
||||
export function renderEditForm() {
|
||||
const wordId = parseInt(this.id.replace('edit_', ''));
|
||||
export function renderEditForm(wordId = false) {
|
||||
wordId = typeof wordId.target === 'undefined' ? wordId : parseInt(this.id.replace('edit_', ''));
|
||||
const word = window.currentDictionary.words.find(w => w.wordId === wordId);
|
||||
if (word) {
|
||||
const editForm = `<form id="editForm_${wordId}" class="edit-form">
|
||||
|
@ -210,7 +225,7 @@ export function renderEditForm() {
|
|||
<label>Definition<span class="red">*</span><br>
|
||||
<input id="wordDefinition_${wordId}" value="${word.simpleDefinition}" placeholder="Equivalent words">
|
||||
</label>
|
||||
<label>Details<span class="red">*</span><a class="label-button">Maximize</a><br>
|
||||
<label>Details<span class="red">*</span><a class="label-button maximize-button">Maximize</a><br>
|
||||
<textarea id="wordDetails_${wordId}" placeholder="Markdown formatting allowed">${word.longDefinition}</textarea>
|
||||
</label>
|
||||
<div id="wordErrorMessage_${wordId}"></div>
|
||||
|
@ -219,6 +234,28 @@ export function renderEditForm() {
|
|||
</form>`;
|
||||
|
||||
document.getElementById(wordId.toString()).innerHTML = editForm;
|
||||
setupEditFormButtons();
|
||||
setupWordEditFormButtons();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function renderMaximizedTextbox(maximizeButton) {
|
||||
maximizeButton = typeof maximizeButton.target === 'undefined' ? maximizeButton : maximizeButton.target;
|
||||
const label = maximizeButton.parentElement.innerText.replace(/(\*|Maximize)/g, '').trim();
|
||||
const textBox = maximizeButton.parentElement.querySelector('textarea');
|
||||
const modalElement = document.createElement('section');
|
||||
modalElement.classList.add('modal');
|
||||
modalElement.innerHTML = `<section class="modal maximize-modal"><div class="modal-background"></div>
|
||||
<div class="modal-content">
|
||||
<a class="close-button">×︎</a>
|
||||
<header><h3>${label}</h3></header>
|
||||
<section>
|
||||
<textarea>${textBox.value}</textarea>
|
||||
</section>
|
||||
<footer><a class="button done-button">Done</a></footer>
|
||||
</div>
|
||||
</section>`;
|
||||
|
||||
document.body.appendChild(modalElement);
|
||||
|
||||
setupMaximizeModal(modalElement, textBox);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ export function getSearchTerm() {
|
|||
|
||||
export function getSearchFilters() {
|
||||
const filters = {
|
||||
caseSensitive: document.getElementById('searchCaseSensitive').checked,
|
||||
exact: document.getElementById('searchExactWords').checked,
|
||||
name: document.getElementById('searchIncludeName').checked,
|
||||
definition: document.getElementById('searchIncludeDefinition').checked,
|
||||
details: document.getElementById('searchIncludeDetails').checked,
|
||||
|
@ -26,31 +28,48 @@ export function getSearchFilters() {
|
|||
}
|
||||
|
||||
export function getMatchingSearchWords() {
|
||||
const searchTerm = getSearchTerm();
|
||||
let searchTerm = getSearchTerm();
|
||||
const filters = getSearchFilters();
|
||||
const matchingWords = window.currentDictionary.words.slice().filter(word => {
|
||||
if (!filters.allPartsOfSpeechChecked) {
|
||||
const partOfSpeech = word.partOfSpeech === '' ? 'Unclassified' : word.partOfSpeech;
|
||||
console.log('partOfSpeech', partOfSpeech);
|
||||
return filters.partsOfSpeech.hasOwnProperty(partOfSpeech) && filters.partsOfSpeech[partOfSpeech];
|
||||
}
|
||||
return true;
|
||||
}).filter(word => {
|
||||
const isInName = filters.name && new RegExp(searchTerm, 'g').test(word.name);
|
||||
const isInDefinition = filters.definition && new RegExp(searchTerm, 'g').test(word.simpleDefinition);
|
||||
const isInDetails = filters.details && new RegExp(searchTerm, 'g').test(word.longDefinition);
|
||||
return searchTerm === '' || isInName || isInDefinition || isInDetails;
|
||||
});
|
||||
return matchingWords;
|
||||
if (searchTerm !== '' || !filters.allPartsOfSpeechChecked) {
|
||||
const matchingWords = window.currentDictionary.words.slice().filter(word => {
|
||||
if (!filters.allPartsOfSpeechChecked) {
|
||||
const partOfSpeech = word.partOfSpeech === '' ? 'Unclassified' : word.partOfSpeech;
|
||||
console.log('partOfSpeech', partOfSpeech);
|
||||
return filters.partsOfSpeech.hasOwnProperty(partOfSpeech) && filters.partsOfSpeech[partOfSpeech];
|
||||
}
|
||||
return true;
|
||||
}).filter(word => {
|
||||
searchTerm = filters.caseSensitive ? searchTerm : searchTerm.toLowerCase();
|
||||
const name = filters.caseSensitive ? word.name : word.name.toLowerCase();
|
||||
const simpleDefinition = filters.caseSensitive ? word.simpleDefinition : word.simpleDefinition.toLowerCase();
|
||||
const longDefinition = filters.caseSensitive ? word.longDefinition : word.longDefinition.toLowerCase();
|
||||
|
||||
const isInName = filters.name
|
||||
&& (filters.exact
|
||||
? searchTerm == name
|
||||
: new RegExp(searchTerm, 'g').test(name));
|
||||
const isInDefinition = filters.definition
|
||||
&& (filters.exact
|
||||
? searchTerm == simpleDefinition
|
||||
: new RegExp(searchTerm, 'g').test(simpleDefinition));
|
||||
const isInDetails = filters.details && new RegExp(searchTerm, 'g').test(longDefinition);
|
||||
return searchTerm === '' || isInName || isInDefinition || isInDetails;
|
||||
});
|
||||
return matchingWords;
|
||||
}
|
||||
|
||||
return window.currentDictionary.words
|
||||
}
|
||||
|
||||
export function highlightSearchTerm(word) {
|
||||
const searchTerm = getSearchTerm();
|
||||
if (searchTerm) {
|
||||
const filters = getSearchFilters();
|
||||
const regexMethod = 'g' + (filters.caseSensitive ? '' : 'i');
|
||||
const markedUpWord = cloneObject(word);
|
||||
markedUpWord.name = markedUpWord.name.replace(new RegExp(searchTerm, 'g'), `<mark>${searchTerm}</mark>`);
|
||||
markedUpWord.simpleDefinition = markedUpWord.simpleDefinition.replace(new RegExp(searchTerm, 'g'), `<mark>${searchTerm}</mark>`);
|
||||
markedUpWord.longDefinition = markedUpWord.longDefinition.replace(new RegExp(searchTerm, 'g'), `<mark>${searchTerm}</mark>`);
|
||||
markedUpWord.name = markedUpWord.name.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||
markedUpWord.simpleDefinition = markedUpWord.simpleDefinition.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||
markedUpWord.longDefinition = markedUpWord.longDefinition.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||
return markedUpWord;
|
||||
}
|
||||
return word;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {showSection} from './displayToggles';
|
||||
import { renderWords, renderWordOptions, destroyWordOptions, renderEditForm } from './render';
|
||||
import { validateWord, addWord } from './wordManagement';
|
||||
import { renderWords, renderEditForm, renderMaximizedTextbox } from './render';
|
||||
import { validateWord, addWord, confirmEditWord, cancelEditWord, confirmDeleteWord } from './wordManagement';
|
||||
import { removeTags } from '../helpers';
|
||||
import { getNextId } from './utilities';
|
||||
import { openEditModal, save, saveAndClose } from './dictionaryManagement';
|
||||
|
@ -10,6 +10,7 @@ export default function setupListeners() {
|
|||
setupDetailsTabs();
|
||||
setupSearchBar();
|
||||
setupWordForm();
|
||||
setupMobileWordFormButton();
|
||||
}
|
||||
|
||||
function setupDetailsTabs() {
|
||||
|
@ -73,12 +74,16 @@ function setupEditFormInteractions() {
|
|||
function setupEditFormButtons() {
|
||||
document.getElementById('editSave').addEventListener('click', () => save());
|
||||
document.getElementById('editSaveAndClose').addEventListener('click', () => saveAndClose());
|
||||
|
||||
setupMaximizeButtons();
|
||||
}
|
||||
|
||||
function setupSearchBar() {
|
||||
const searchBox = document.getElementById('searchBox'),
|
||||
clearSearchButton = document.getElementById('clearSearchButton'),
|
||||
openSearchModal = document.getElementById('openSearchModal');
|
||||
openSearchModal = document.getElementById('openSearchModal'),
|
||||
searchExactWords = document.getElementById('searchExactWords'),
|
||||
searchIncludeDetails = document.getElementById('searchIncludeDetails');
|
||||
searchBox.addEventListener('change', () => {
|
||||
renderWords();
|
||||
});
|
||||
|
@ -92,6 +97,17 @@ function setupSearchBar() {
|
|||
});
|
||||
openSearchModal.addEventListener('click', () => {
|
||||
document.getElementById('searchModal').style.display = 'block';
|
||||
searchBox.focus();
|
||||
});
|
||||
|
||||
searchExactWords.addEventListener('change', () => {
|
||||
if (searchExactWords.checked) {
|
||||
searchIncludeDetails.checked = false;
|
||||
searchIncludeDetails.disabled = true;
|
||||
} else {
|
||||
searchIncludeDetails.disabled = false;
|
||||
searchIncludeDetails.checked = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -131,6 +147,8 @@ function setupWordForm() {
|
|||
addWord(word);
|
||||
}
|
||||
});
|
||||
|
||||
setupMaximizeButtons();
|
||||
}
|
||||
|
||||
export function setupWordOptionButtons() {
|
||||
|
@ -167,22 +185,41 @@ export function setupWordOptionSelections() {
|
|||
break;
|
||||
}
|
||||
case 'Delete': {
|
||||
option.removeEventListener('click', confirmDeleteWord);
|
||||
option.addEventListener('click', confirmDeleteWord);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function setupEditFormButtons() {
|
||||
export function setupWordEditFormButtons() {
|
||||
const saveChangesButtons = document.getElementsByClassName('edit-save-changes');
|
||||
const cancelChangesButtons = document.getElementsByClassName('edit-cancel');
|
||||
Array.from(saveChangesButtons).forEach(button => {
|
||||
button.removeEventListener('click', renderEditForm);
|
||||
button.addEventListener('click', renderEditForm);
|
||||
button.removeEventListener('click', confirmEditWord);
|
||||
button.addEventListener('click', confirmEditWord);
|
||||
});
|
||||
Array.from(cancelChangesButtons).forEach(button => {
|
||||
button.removeEventListener('click', renderWords);
|
||||
button.addEventListener('click', renderWords);
|
||||
button.removeEventListener('click', cancelEditWord);
|
||||
button.addEventListener('click', cancelEditWord);
|
||||
});
|
||||
|
||||
setupMaximizeButtons();
|
||||
}
|
||||
|
||||
export function setupMobileWordFormButton() {
|
||||
const mobileButton = document.getElementById('mobileWordFormShow'),
|
||||
wordForm = document.getElementById('wordForm');
|
||||
|
||||
mobileButton.addEventListener('click', () => {
|
||||
if (mobileButton.innerText === '+') {
|
||||
wordForm.style.display = 'block';
|
||||
mobileButton.innerHTML = '×︎';
|
||||
} else {
|
||||
wordForm.style.display = '';
|
||||
mobileButton.innerHTML = '+';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -205,3 +242,29 @@ export function setupPagination() {
|
|||
pageSelector.addEventListener('change', goToPage);
|
||||
});
|
||||
}
|
||||
|
||||
export function setupMaximizeButtons() {
|
||||
const maximizeButtons = document.getElementsByClassName('maximize-button');
|
||||
Array.from(maximizeButtons).forEach(button => {
|
||||
button.removeEventListener('click', renderMaximizedTextbox);
|
||||
button.addEventListener('click', renderMaximizedTextbox);
|
||||
});
|
||||
}
|
||||
|
||||
export function setupMaximizeModal(modal, textBox) {
|
||||
const closeElements = modal.querySelectorAll('.modal-background, .close-button, .done-button'),
|
||||
maximizedTextBox = modal.querySelector('textarea');
|
||||
Array.from(closeElements).forEach(close => {
|
||||
close.addEventListener('click', () => {
|
||||
modal.parentElement.removeChild(modal);
|
||||
});
|
||||
});
|
||||
|
||||
maximizedTextBox.addEventListener('change', () => {
|
||||
textBox.value = maximizedTextBox.value;
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
modal.querySelector('textarea').focus();
|
||||
}, 1);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { renderWords } from "./render";
|
||||
import { wordExists } from "./utilities";
|
||||
import removeDiacritics from "./StackOverflow/removeDiacritics";
|
||||
import { removeTags } from "../helpers";
|
||||
|
||||
export function validateWord(word, wordId = false) {
|
||||
const errorElementId = wordId === false ? 'wordErrorMessage' : 'wordErrorMessage_' + wordId,
|
||||
|
@ -18,7 +19,9 @@ export function validateWord(word, wordId = false) {
|
|||
if (!allowDuplicates) {
|
||||
const foundDuplicate = wordExists(word.name, true);
|
||||
if (foundDuplicate !== false) {
|
||||
errorMessage += `<p class="bold red">"<a href="#${foundDuplicate}">${word.name}</a>" already exists, and "Allow Duplicates" is turned off.${!caseSensitive ? ' <em>(Case sensitivity is turned also off)</em>' : ''}</p>`;
|
||||
if (wordId !== false && foundDuplicate !== wordId) {
|
||||
errorMessage += `<p class="bold red">"<a href="#${foundDuplicate}">${word.name}</a>" already exists, and "Prevent Duplicate Words" is turned on.${!caseSensitive ? ' <em>(Case sensitivity is turned off)</em>' : ''}</p>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,11 +29,10 @@ export function validateWord(word, wordId = false) {
|
|||
return errorMessage === '';
|
||||
}
|
||||
|
||||
export function addWord(word, render = true) {
|
||||
export function sortWords(render) {
|
||||
const { sortByDefinition } = window.currentDictionary.settings;
|
||||
const sortBy = sortByDefinition ? 'simpleDefinition' : 'name';
|
||||
|
||||
window.currentDictionary.words.push(word);
|
||||
window.currentDictionary.words.sort((wordA, wordB) => {
|
||||
if (removeDiacritics(wordA[sortBy]).toLowerCase() === removeDiacritics(wordB[sortBy]).toLowerCase()) return 0;
|
||||
return removeDiacritics(wordA[sortBy]).toLowerCase() > removeDiacritics(wordB[sortBy]).toLowerCase() ? 1 : -1;
|
||||
|
@ -40,3 +42,87 @@ export function addWord(word, render = true) {
|
|||
renderWords();
|
||||
}
|
||||
}
|
||||
|
||||
export function addWord(word, render = true) {
|
||||
window.currentDictionary.words.push(word);
|
||||
sortWords(render);
|
||||
}
|
||||
|
||||
export function deleteWord(wordId) {
|
||||
const wordIndex = window.currentDictionary.words.findIndex(word => word.wordId === wordId);
|
||||
if (wordIndex > -1) {
|
||||
window.currentDictionary.words.splice(wordIndex, 1);
|
||||
}
|
||||
sortWords(true);
|
||||
}
|
||||
|
||||
export function updateWord(word, wordId) {
|
||||
const wordIndex = window.currentDictionary.words.findIndex(word => word.wordId === wordId);
|
||||
|
||||
if (wordIndex < 0) {
|
||||
console.error('Could not find word to update');
|
||||
} else {
|
||||
window.currentDictionary.words[wordIndex] = word;
|
||||
sortWords(true);
|
||||
}
|
||||
}
|
||||
|
||||
export function confirmEditWord() {
|
||||
const wordId = parseInt(this.id.replace('editWordButton_', ''));
|
||||
const name = document.getElementById('wordName_' + wordId).value,
|
||||
pronunciation = document.getElementById('wordPronunciation_' + wordId).value,
|
||||
partOfSpeech = document.getElementById('wordPartOfSpeech_' + wordId).value,
|
||||
definition = document.getElementById('wordDefinition_' + wordId).value,
|
||||
details = document.getElementById('wordDetails_' + wordId).value;
|
||||
|
||||
const word = {
|
||||
name: removeTags(name).trim(),
|
||||
pronunciation: removeTags(pronunciation).trim(),
|
||||
partOfSpeech: removeTags(partOfSpeech).trim(),
|
||||
simpleDefinition: removeTags(definition).trim(),
|
||||
longDefinition: removeTags(details).trim(),
|
||||
wordId,
|
||||
};
|
||||
|
||||
if (validateWord(word, wordId)) {
|
||||
if (confirm(`Are you sure you want to save changes to "${word.name}"?`)) {
|
||||
document.getElementById('editForm_' + wordId).classList.add('done');
|
||||
updateWord(word, wordId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function cancelEditWord() {
|
||||
const wordId = parseInt(this.parentElement.id.replace('editForm_', ''));
|
||||
if (confirm(`Are you sure you want to cancel?\n(Any changes will be lost!)`)) {
|
||||
document.getElementById('editForm_' + wordId).classList.add('done');
|
||||
renderWords();
|
||||
}
|
||||
}
|
||||
|
||||
export function confirmDeleteWord(wordId) {
|
||||
wordId = typeof wordId.target === 'undefined' ? wordId : parseInt(wordId.target.id.replace('delete_', ''));
|
||||
const word = window.currentDictionary.words.find(w => w.wordId === wordId);
|
||||
|
||||
if (!word) {
|
||||
console.error('Something went wrong! Couldn\'t find word with id of ' + wordId);
|
||||
} else {
|
||||
if (confirm(`Are you sure you want to delete "${word.name}"?`)) {
|
||||
if (confirm(`Just to double-check:\nDo you really want to delete "${word.name}"?\n\nYou won't be able to undo it!`)) {
|
||||
deleteWord(wordId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getOpenEditForms() {
|
||||
const openEditForms = document.getElementsByClassName('edit-form');
|
||||
const formsToReopen = [];
|
||||
Array.from(openEditForms).forEach(form => {
|
||||
if (!form.classList.contains('done')) {
|
||||
formsToReopen.push(parseInt(form.id.replace('editForm_', '')));
|
||||
}
|
||||
});
|
||||
|
||||
return formsToReopen;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
@import 'styles/containers';
|
||||
@import 'styles/structure';
|
||||
@import 'styles/elements';
|
||||
@import 'styles/mobile/containers';
|
||||
@import 'styles/mobile/structure';
|
||||
@import 'styles/mobile/elements';
|
||||
|
||||
html, body {
|
||||
font-family: $font;
|
||||
|
|
|
@ -12,6 +12,7 @@ header {
|
|||
main {
|
||||
display: block;
|
||||
width: 90%;
|
||||
max-width: 1000px;
|
||||
min-height: 400px;
|
||||
margin: 0 auto;
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ p, span {
|
|||
label {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
line-height: 120%;
|
||||
cursor: pointer;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: $general-padding;
|
||||
|
@ -27,13 +29,19 @@ label {
|
|||
}
|
||||
|
||||
.label-button {
|
||||
@extend .button;
|
||||
|
||||
font-size: 80%;
|
||||
font-weight: normal;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
line-height: 80% !important;
|
||||
padding: 3px 3px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
padding: 3px 9px;
|
||||
border: $border;
|
||||
border-radius: 3px;
|
||||
|
@ -66,6 +74,7 @@ span .tag {
|
|||
.button {
|
||||
@extend .tag;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.modal {
|
||||
|
@ -87,10 +96,6 @@ span .tag {
|
|||
|
||||
.modal-content {
|
||||
position: absolute;
|
||||
// top: 10%;
|
||||
// left: 20%;
|
||||
// bottom: 10%;
|
||||
// right: 20%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
@ -108,6 +113,7 @@ span .tag {
|
|||
right: 10px;
|
||||
font-size: 200%;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#top {
|
||||
#title {
|
||||
display: inline-block;
|
||||
margin: 3px 20px 3px 0;
|
||||
margin: 3px $general-padding 3px 0;
|
||||
}
|
||||
|
||||
#openSearchModal {
|
||||
|
@ -25,7 +25,7 @@
|
|||
max-height: unset;
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
padding: 20px;
|
||||
padding: $general-padding $general-padding ($general-padding / 2);
|
||||
|
||||
label {
|
||||
display: inline;
|
||||
|
@ -43,6 +43,16 @@
|
|||
bottom: unset;
|
||||
right: unset;
|
||||
background-color: $white;
|
||||
padding: ($general-padding / 2) $general-padding ($general-padding * 0.25);
|
||||
font-size: 90%;
|
||||
|
||||
.split {
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +61,7 @@
|
|||
}
|
||||
|
||||
.category {
|
||||
margin-right: 8px;
|
||||
text-align: right;
|
||||
* {
|
||||
margin: 0;
|
||||
|
@ -59,22 +70,30 @@
|
|||
|
||||
.options {
|
||||
label {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#mobileWordFormShow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wordForm {
|
||||
position: fixed;
|
||||
top: auto;
|
||||
width: 24%;
|
||||
max-width: 275px;
|
||||
padding: 10px;
|
||||
background-color: $light;
|
||||
border: $border;
|
||||
border-radius: 5px;
|
||||
max-height: 80%;
|
||||
overflow-y: auto;
|
||||
box-shadow: 4px 4px 5px 0px rgba(50, 50, 50, 0.75);
|
||||
}
|
||||
|
||||
.edit-form {
|
||||
|
@ -83,40 +102,52 @@
|
|||
}
|
||||
|
||||
#detailsSection {
|
||||
padding: 20px;
|
||||
padding: $general-padding;
|
||||
background-color: $white;
|
||||
border: $border;
|
||||
border-radius: 5px;
|
||||
|
||||
nav li {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 10px 20px;
|
||||
border: $border;
|
||||
background-color: $light;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-child {
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0 5px 5px 0;
|
||||
}
|
||||
&:not(:first-child) {
|
||||
border-left: none;
|
||||
}
|
||||
#dictionaryName {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #bababa;
|
||||
nav ul {
|
||||
padding-left: 0;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 10px $general-padding;
|
||||
border: $border;
|
||||
background-color: $light;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-child {
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0 5px 5px 0;
|
||||
}
|
||||
&:not(:first-child) {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #bababa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#detailsPanel {
|
||||
background-color: $white;
|
||||
padding: 20px;
|
||||
padding: $general-padding;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +161,7 @@
|
|||
}
|
||||
|
||||
.pronunciation {
|
||||
margin: 0 20px;
|
||||
margin: 0 $general-padding;
|
||||
}
|
||||
|
||||
.part-of-speech {
|
||||
|
@ -205,6 +236,16 @@
|
|||
}
|
||||
#editDescription {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
height: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
.maximize-modal {
|
||||
textarea {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
min-height: 400px;
|
||||
border: none;
|
||||
padding: $general-padding;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
@media (max-width: 750px) {
|
||||
|
||||
html, body {
|
||||
font-size: 90%;
|
||||
line-height: 90%;
|
||||
}
|
||||
|
||||
header {
|
||||
&#top {
|
||||
margin-bottom: $general-padding;
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
#sideColumn {
|
||||
display: block;
|
||||
width: 0;
|
||||
height: block;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#mainColumn {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
article {
|
||||
dl {
|
||||
padding: 0 ($general-padding / 2);
|
||||
|
||||
dd {
|
||||
margin: 0 ($general-padding * 0.75);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
@media (max-width: 750px) {
|
||||
|
||||
.tag {
|
||||
padding: 2px 6px;
|
||||
font-size: 90%;
|
||||
line-height: 120%;
|
||||
|
||||
&.small {
|
||||
font-size: 70%;
|
||||
line-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
@extend .tag;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
li {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
z-index: 10;
|
||||
|
||||
.modal-content .close-button {
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.split {
|
||||
display: block;
|
||||
|
||||
div {
|
||||
display: block;
|
||||
margin-right: unset;
|
||||
|
||||
&:last-child {
|
||||
margin-left: unset;
|
||||
}
|
||||
}
|
||||
|
||||
&.two div,
|
||||
&.three div,
|
||||
div.third {
|
||||
width: 100%;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
div.quarter,
|
||||
div.three-quarter {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
div.quarter {
|
||||
width: 30%;
|
||||
}
|
||||
div.three-quarter {
|
||||
width: 66%;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
margin: $general-padding 0;
|
||||
|
||||
.page-selector {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.prev-button,
|
||||
.next-button {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.prev-button {
|
||||
left: 2.5%;
|
||||
}
|
||||
|
||||
.next-button {
|
||||
right: 2.5%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
@media (max-width: 750px) {
|
||||
|
||||
#top {
|
||||
#openSearchModal {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
#searchModal {
|
||||
.modal-content {
|
||||
width: 100%;
|
||||
padding: $general-padding ($general-padding / 2) ($general-padding / 4);
|
||||
|
||||
#searchBox {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
section+footer {
|
||||
padding: ($general-padding / 2) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#mobileWordFormShow {
|
||||
position: fixed;
|
||||
top: $header-height;
|
||||
left: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: block;
|
||||
background-color: #00de00;
|
||||
border: $border;
|
||||
border-radius: 0 3px 3px 0;
|
||||
color: $white;
|
||||
font-size: 30px;
|
||||
line-height: 24px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#wordForm {
|
||||
display: none;
|
||||
width: 95%;
|
||||
max-width: unset;
|
||||
top: $header-height + 32px;
|
||||
left: 0;
|
||||
right: 3%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#detailsSection {
|
||||
nav ul li {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
#detailsPanel {
|
||||
max-height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.entry {
|
||||
.pronunciation {
|
||||
margin: 0 ($general-padding / 2);
|
||||
}
|
||||
}
|
||||
|
||||
#editModal {
|
||||
$nav-font-height: 16px;
|
||||
footer {
|
||||
.button {
|
||||
font-size: $nav-font-height - 2px;
|
||||
line-height: $nav-font-height;
|
||||
}
|
||||
}
|
||||
#editDescription {
|
||||
width: 100%;
|
||||
height: 260px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
38
yarn.lock
38
yarn.lock
|
@ -943,6 +943,18 @@ atob@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
||||
autoprefixer@^9.5.1:
|
||||
version "9.5.1"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.5.1.tgz#243b1267b67e7e947f28919d786b50d3bb0fb357"
|
||||
integrity sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ==
|
||||
dependencies:
|
||||
browserslist "^4.5.4"
|
||||
caniuse-lite "^1.0.30000957"
|
||||
normalize-range "^0.1.2"
|
||||
num2fraction "^1.2.2"
|
||||
postcss "^7.0.14"
|
||||
postcss-value-parser "^3.3.1"
|
||||
|
||||
aws-sign2@~0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||
|
@ -1133,7 +1145,7 @@ browserify-zlib@^0.2.0:
|
|||
dependencies:
|
||||
pako "~1.0.5"
|
||||
|
||||
browserslist@^4.0.0, browserslist@^4.1.0, browserslist@^4.3.4:
|
||||
browserslist@^4.0.0, browserslist@^4.1.0, browserslist@^4.3.4, browserslist@^4.5.4:
|
||||
version "4.5.6"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.6.tgz#ea42e8581ca2513fa7f371d4dd66da763938163d"
|
||||
integrity sha512-o/hPOtbU9oX507lIqon+UvPYqpx3mHc8cV3QemSBTXwkG8gSQSK6UKvXcE/DcleU3+A59XTUHyCvZ5qGy8xVAg==
|
||||
|
@ -1225,6 +1237,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000963:
|
|||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000963.tgz#5be481d5292f22aff5ee0db4a6c049b65b5798b1"
|
||||
integrity sha512-n4HUiullc7Lw0LyzpeLa2ffP8KxFBGdxqD/8G3bSL6oB758hZ2UE2CVK+tQN958tJIi0/tfpjAc67aAtoHgnrQ==
|
||||
|
||||
caniuse-lite@^1.0.30000957:
|
||||
version "1.0.30000967"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000967.tgz#a5039577806fccee80a04aaafb2c0890b1ee2f73"
|
||||
integrity sha512-rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ==
|
||||
|
||||
caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
|
@ -3296,6 +3313,11 @@ normalize-path@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
normalize-range@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
||||
integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
|
||||
|
||||
normalize-url@^3.0.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
|
||||
|
@ -3336,6 +3358,11 @@ nth-check@^1.0.2:
|
|||
dependencies:
|
||||
boolbase "~1.0.0"
|
||||
|
||||
num2fraction@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||
integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
|
||||
|
||||
number-is-nan@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
|
@ -3975,6 +4002,15 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.5:
|
|||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^7.0.14:
|
||||
version "7.0.16"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.16.tgz#48f64f1b4b558cb8b52c88987724359acb010da2"
|
||||
integrity sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
posthtml-parser@^0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.3.3.tgz#3fe986fca9f00c0f109d731ba590b192f26e776d"
|
||||
|
|
Loading…
Reference in New Issue