/* global CodeMirror */ import { Cookies } from './modules/cookies.js' import { Fontsize } from './modules/fontsize.js' import { Filters } from './modules/filters.js' import { Language } from './modules/language.js' import { Spacing } from './modules/spacing.js' import { Theme } from './modules/theme.js' let fontData const fontsize = new Fontsize() window.CMeditor = CodeMirror.fromTextArea(document.getElementById('code'), { lineNumbers: true, styleActiveLine: true, matchBrackets: true, theme: 'pastel-on-dark', lineWrapping: true }) function isVisible (el) { const container = document.querySelector('section.select-list').getBoundingClientRect() const target = el.getBoundingClientRect() return target.bottom > container.top && target.top < container.bottom } /** * Get the font from the #, the cookie, or a default */ function getFont () { let font = window.location.hash.substring(1) if (!font) { font = Cookies.get('font') } if (!font) { font = 'monolisa' } return font } function setDetails (data) { const box = document.querySelector('.info-wrapper') box.querySelector('h2').setAttribute('data-license', data.license ?? '') box.querySelector('a').href = data.website box.querySelector('h2 a').textContent = data.name box.querySelector('p.info').textContent = data.description ?? '' if (typeof data.variants === 'string') { box.querySelector('p.variants').textContent = data.variants } else if (data.variants && data.variants.length > 1) { box.querySelector('p.variants').textContent = data.variants.join(', ') } else { box.querySelector('p.variants').textContent = '' } } // ProgrammingFonts font selector function selectFont () { const codeMirror = document.querySelector('.CodeMirror') const font = getFont() if (typeof fontData !== 'undefined') { setDetails(fontData[font]) } if (typeof fontData !== 'undefined' && fontData[font].rendering === 'bitmap') { codeMirror.classList.add('no-smooth') if (fontData[font]['bitmap size']) { fontsize.forceSize(fontData[font]['bitmap size']) } } else { codeMirror.classList.remove('no-smooth') fontsize.reset() } if (font === 'input') { codeMirror.style.fontFamily = 'Input Mono, monospace' codeMirror.querySelectorAll('pre, textarea').forEach((element) => { element.style.fontFamily = 'Input Mono, monospace' }) } else { codeMirror.style.fontFamily = `${font}, monospace` codeMirror.querySelectorAll('pre, textarea').forEach((element) => { element.style.fontFamily = `${font}, monospace` }) } document.querySelectorAll('#select-font [data-alias]').forEach((element) => { element.classList.remove('active') }) const activeEntry = document.querySelector(`#select-font [data-alias='${font}']`) if (activeEntry) { activeEntry.classList.add('active') if (!isVisible(activeEntry)) { activeEntry.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'smooth' }) } } Cookies.set('font', font) } function renderSelectList () { const icon = '' const pinIcon = '' let favoritesMap = {} let favorites = [] document.getElementById('select-font').innerHTML = '' try { favorites = JSON.parse(localStorage.getItem('favorites')) || [] favoritesMap = favorites.reduce((acc, alias) => { acc[alias] = true return acc }, {}) } catch (err) { // eslint-disable-next-line no-console console.error('could not render favorites', err) } const renderAuthors = (authors) => { authors.sort() authors.forEach((author) => { const option = document.createElement('option') option.innerHTML = author document.getElementById('authors-list').querySelector('.other').appendChild(option) }) } const renderFonts = (fonts) => { fonts.sort((a, b) => { if (favoritesMap[a.alias] && !favoritesMap[b.alias]) { return -1 } if (!favoritesMap[a.alias] && favoritesMap[b.alias]) { return 1 } if (a.name.toLowerCase() < b.name.toLowerCase()) { return -1 } if (a.name.toLowerCase() > b.name.toLowerCase()) { return 1 } return 0 }) fonts.forEach((v) => { const option = document.createElement('div') option.classList.add('entry') if (favoritesMap[v.alias]) { option.classList.add('pinned') } option.setAttribute('data-alias', v.alias) option.innerHTML = `${v.name}${v.year} — ${v.author}${pinIcon} Website${icon}` document.getElementById('select-font').appendChild(option) }) } fetch('fonts.json') .then((response) => { if (response.ok) { return response.json() } else { console.error(response.status + ': ' + response.statusText) } }).then((data) => { const fonts = [] const authors = [] fontData = data Object.keys(data).forEach((key) => { const v = data[key] v.alias = key fonts.push(v) if (authors.indexOf(v.author) < 0) { authors.push(v.author) } }) renderAuthors(authors) renderFonts(fonts) selectFont() new Filters(data).init() }) } window.toggleFavorite = (alias) => { try { let favorites = JSON.parse(localStorage.getItem('favorites')) || [] if (favorites.indexOf(alias) > -1) { favorites = favorites.filter((v) => { return v !== alias }) } else { favorites.push(alias) } localStorage.setItem('favorites', JSON.stringify(Array.from(new Set(favorites)))) } catch (err) { // eslint-disable-next-line no-console console.error('could not save favorite', err) } renderSelectList() return false } function walk (direction) { const activeEntry = document.querySelector('.entry.active') let target = null let next = direction === 'up' ? activeEntry.previousElementSibling : activeEntry.nextElementSibling while (target === null) { if (next) { if (next.matches('.entry:not(.filtered-out)')) { target = next } else { next = direction === 'up' ? next.previousElementSibling : next.nextElementSibling } } else { target = false } } if (target) { target.querySelector('a').click() } } window.onhashchange = () => { selectFont() } window.addEventListener('DOMContentLoaded', () => { renderSelectList() fontsize.init() new Theme().init() new Spacing().init() new Language().init() document.querySelector('.select-list').onkeydown = (event) => { if (event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) { return } if (event.key === 'ArrowUp') { event.preventDefault() event.stopPropagation() walk('up') } else if (event.key === 'ArrowDown') { event.preventDefault() event.stopPropagation() walk('down') } } document.body.addEventListener('keydown', (event) => { if (event.ctrlKey || event.metaKey) { if (event.key === '-') { event.preventDefault() event.stopPropagation() fontsize.down() } else if (event.key === '=') { event.preventDefault() event.stopPropagation() fontsize.up() } } }) })