remove jquery all together

This commit is contained in:
Aaron Qian 2023-01-04 18:12:39 -08:00
parent b0f5b0b059
commit 8580a1f463
No known key found for this signature in database
GPG key ID: BF1A987C395B5B0E
61 changed files with 4113 additions and 684 deletions

1
.eslintignore Normal file
View file

@ -0,0 +1 @@
node_modules

12
.eslintrc.yml Normal file
View file

@ -0,0 +1,12 @@
env:
browser: true
es2021: true
extends:
- standard
- plugin:no-jquery/all
- prettier
plugins:
- no-jquery
parserOptions:
ecmaVersion: latest
sourceType: module

5
.prettierrc.yml Normal file
View file

@ -0,0 +1,5 @@
printWidth: 100
tabWidth: 2
semi: false
singleQuote: true
trailingComma: "all"

1
.tool-versions Normal file
View file

@ -0,0 +1 @@
nodejs 18.12.1

View file

@ -1,9 +1,8 @@
import 'jquery'; import 'popper.js'
import 'popper.js'; import 'bootstrap'
import 'bootstrap'; import '@fortawesome/fontawesome-free/js/all'
import '@fortawesome/fontawesome-free/js/all';
import './core'; import './core'
import './features'; import './features'
import './sections'; import './sections'
import './pages'; import './pages'

View file

@ -1,36 +1,36 @@
let deviceState = { let deviceState = {
isMobile: false, isMobile: false,
isTablet: false, isTablet: false,
isLaptop: false, isLaptop: false
}; }
function detectDeviceState() { function detectDeviceState () {
if (window.innerWidth <= 425) { if (window.innerWidth <= 425) {
deviceState = { deviceState = {
isMobile: true, isMobile: true,
isTablet: false, isTablet: false,
isLaptop: false, isLaptop: false
}; }
} else if (window.innerWidth <= 768) { } else if (window.innerWidth <= 768) {
deviceState = { deviceState = {
isMobile: false, isMobile: false,
isTablet: true, isTablet: true,
isLaptop: false, isLaptop: false
}; }
} else { } else {
deviceState = { deviceState = {
isMobile: false, isMobile: false,
isTablet: false, isTablet: false,
isLaptop: true, isLaptop: true
}; }
} }
} }
detectDeviceState(); detectDeviceState()
window.addEventListener('resize', detectDeviceState); window.addEventListener('resize', detectDeviceState)
// returns a copy of the device state // returns a copy of the device state
// so other parts of code can't override this. // so other parts of code can't override this.
export function getDeviceState() { export function getDeviceState () {
return { ... deviceState }; return { ...deviceState }
} }

View file

@ -1,2 +1,2 @@
export * from './device'; export * from './device'
export * from './insertScript'; export * from './insertScript'

View file

@ -1,14 +1,14 @@
export const insertScript = (id, src, onload) => { export const insertScript = (id, src, onload) => {
// script is already inserted, do nothing // script is already inserted, do nothing
if (document.getElementById(id)) return; if (document.getElementById(id)) return
// insert script // insert script
const firstScriptTag = document.getElementsByTagName('script')[0]; const firstScriptTag = document.getElementsByTagName('script')[0]
const scriptTag = document.createElement('script'); const scriptTag = document.createElement('script')
scriptTag.id = id; scriptTag.id = id
scriptTag.onload = onload; scriptTag.onload = onload
scriptTag.src = src; scriptTag.src = src
scriptTag.defer = true; scriptTag.defer = true
scriptTag.async = true; scriptTag.async = true
firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag); firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag)
}; }

View file

@ -1,30 +1,30 @@
import { enable, disable, auto, setFetchMethod } from 'darkreader'; import { enable, disable, auto, setFetchMethod } from 'darkreader'
import * as params from "@params"; import * as params from '@params'
const darkreader = params?.darkmode?.darkreader || {}; const darkreader = params?.darkmode?.darkreader || {}
const defaultColorScheme = darkreader.defaultColorScheme || 'system'; const defaultColorScheme = darkreader.defaultColorScheme || 'system'
const theme = { const theme = {
brightness: 100, brightness: 100,
contrast: 100, contrast: 100,
sepia: 0, sepia: 0,
...(darkreader.theme || {}), ...(darkreader.theme || {})
}; }
const fixes = { const fixes = {
invert: ['img[src$=".svg"]'], invert: ['img[src$=".svg"]'],
...(darkreader.fixes || {}), ...(darkreader.fixes || {})
}; }
setFetchMethod(window.fetch); setFetchMethod(window.fetch)
export function setSchemeDark() { export function setSchemeDark () {
enable(theme, fixes); enable(theme, fixes)
} }
export function setSchemeLight() { export function setSchemeLight () {
disable(); disable()
} }
export function setSchemeSystem() { export function setSchemeSystem () {
auto(theme, fixes); auto(theme, fixes)
} }
export { defaultColorScheme }; export { defaultColorScheme }

View file

@ -1,60 +1,60 @@
const PERSISTENCE_KEY = 'darkmode:color-scheme'; const PERSISTENCE_KEY = 'darkmode:color-scheme'
async function getService() { async function getService () {
if(process.env.FEATURE_DARKMODE_DARKREADER === '1') { if (process.env.FEATURE_DARKMODE_DARKREADER === '1') {
return await import('./darkreader'); return await import('./darkreader')
} }
throw Error(' No service defined for feature markMode.'); throw Error(' No service defined for feature darkMode.')
} }
window.addEventListener('DOMContentLoaded', async () => { window.addEventListener('DOMContentLoaded', async () => {
const $menu = document.getElementById('themeMenu'); const menu = document.getElementById('themeMenu')
const $icon = document.getElementById('navbar-theme-icon-svg'); const $icon = document.getElementById('navbar-theme-icon-svg')
if ($menu == null || $icon == null) return; if (menu == null || $icon == null) return
const $btns = $menu.getElementsByTagName('a'); const btns = menu.getElementsByTagName('a')
const iconMap = Array.from($btns).reduce((map, $btn) => { const iconMap = Array.from(btns).reduce((map, btn) => {
$img = $btn.getElementsByTagName('img')[0]; const $img = btn.getElementsByTagName('img')[0]
map[$btn.dataset.scheme] = $img.src; map[btn.dataset.scheme] = $img.src
return map; return map
}, {}); }, {})
const { const {
setSchemeDark, setSchemeDark,
setSchemeLight, setSchemeLight,
setSchemeSystem, setSchemeSystem,
defaultColorScheme, defaultColorScheme
} = await getService(); } = await getService()
function loadScheme() { function loadScheme () {
return localStorage.getItem(PERSISTENCE_KEY) || defaultColorScheme; return localStorage.getItem(PERSISTENCE_KEY) || defaultColorScheme
} }
function saveScheme(scheme) { function saveScheme (scheme) {
localStorage.setItem(PERSISTENCE_KEY, scheme); localStorage.setItem(PERSISTENCE_KEY, scheme)
} }
function setScheme(newScheme) { function setScheme (newScheme) {
$icon.src = iconMap[newScheme]; $icon.src = iconMap[newScheme]
if (newScheme === 'dark') { if (newScheme === 'dark') {
setSchemeDark(); setSchemeDark()
} else if (newScheme === 'system') { } else if (newScheme === 'system') {
setSchemeSystem(); setSchemeSystem()
} else { } else {
setSchemeLight(); setSchemeLight()
} }
saveScheme(newScheme); saveScheme(newScheme)
} }
setScheme(loadScheme()); setScheme(loadScheme())
Array.from($menu.getElementsByTagName('a')).forEach(($btn) => { Array.from(menu.getElementsByTagName('a')).forEach((btn) => {
$btn.addEventListener('click', () => { btn.addEventListener('click', () => {
const { scheme } = $btn.dataset; const { scheme } = btn.dataset
setScheme(scheme); setScheme(scheme)
}); })
}); })
}); })

View file

@ -1,171 +1,165 @@
import { insertScript } from '../../core'; import { insertScript } from '../../core'
const PDFJS_BUNDLE = "https://cdn.jsdelivr.net/npm/pdfjs-dist@3.0.279/build/pdf.min.js"; const PDFJS_BUNDLE = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.0.279/build/pdf.min.js'
const WORKER_BUNDLE = "https://cdn.jsdelivr.net/npm/pdfjs-dist@3.0.279/build/pdf.worker.min.js"; const WORKER_BUNDLE = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.0.279/build/pdf.worker.min.js'
class PDFViewer { class PDFViewer {
constructor(el) { constructor (el) {
const { const {
url, url,
hidePaginator, hidePaginator,
hideLoader, hideLoader,
scale, scale,
pageNum pageNum
} = el.dataset; } = el.dataset
if(url == null) { if (url == null) {
throw new Error('Cannot load PDF! Attribute `data-url` is not set.'); throw new Error('Cannot load PDF! Attribute `data-url` is not set.')
} }
// props // props
this.url = url; this.url = url
this.hidePaginator = hidePaginator !== 'false'; this.hidePaginator = hidePaginator !== 'false'
this.hideLoader = hideLoader !== 'false'; this.hideLoader = hideLoader !== 'false'
this.scale = scale || 3; this.scale = scale || 3
// initial state // initial state
this.pageNum = parseInt(pageNum ,10) || 1; this.pageNum = parseInt(pageNum, 10) || 1
this.loaded = false; this.loaded = false
this.pageRendering = false; this.pageRendering = false
this.pageNumPending = null; this.pageNumPending = null
// DOM elements // DOM elements
this.$canvas = el.getElementsByClassName('pdf-canvas')[0]; this.canvas = el.getElementsByClassName('pdf-canvas')[0]
if(this.$canvas == null) { if (this.canvas == null) {
throw new Error('canvas element not found!'); throw new Error('canvas element not found!')
}; };
this.$paginator = el.getElementsByClassName("paginator")[0]; this.paginator = el.getElementsByClassName('paginator')[0]
this.$loadingWrapper = el.getElementsByClassName('loading-wrapper')[0]; this.loadingWrapper = el.getElementsByClassName('loading-wrapper')[0]
this.$next = el.getElementsByClassName('next')[0]; this.next = el.getElementsByClassName('next')[0]
this.$prev = el.getElementsByClassName('prev')[0]; this.prev = el.getElementsByClassName('prev')[0]
this.$pageNum = el.getElementsByClassName('page-num')[0]; this.pageNum = el.getElementsByClassName('page-num')[0]
this.$pageCount = el.getElementsByClassName('page-count')[0]; this.pageCount = el.getElementsByClassName('page-count')[0]
// context // context
this.ctx = this.$canvas.getContext('2d'); this.ctx = this.canvas.getContext('2d')
// events // events
this.$next.addEventListener('click', this.handleNextPage.bind(this)); this.next.addEventListener('click', this.handleNextPage.bind(this))
this.$prev.addEventListener('click', this.handlePrevPage.bind(this)); this.prev.addEventListener('click', this.handlePrevPage.bind(this))
this.showPaginator(); this.showPaginator()
this.showLoader(); this.showLoader()
this.loadPDF(); this.loadPDF()
} }
/** /**
* If we haven't disabled the loader, show loader and hide canvas * If we haven't disabled the loader, show loader and hide canvas
*/ */
showLoader() { showLoader () {
if(this.hideLoader) return; if (this.hideLoader) return
this.$loadingWrapper.style.display = 'flex'; this.loadingWrapper.style.display = 'flex'
this.$canvas.style.display = 'none'; this.canvas.style.display = 'none'
} }
/** /**
* If we haven't disabled the paginator, show paginator * If we haven't disabled the paginator, show paginator
*/ */
showPaginator() { showPaginator () {
if(this.hidePaginator) return; if (this.hidePaginator) return
this.$paginator.style.display = 'block'; this.paginator.style.display = 'block'
} }
/** /**
* Hides loader and shows canvas * Hides loader and shows canvas
*/ */
showContent() { showContent () {
this.$loadingWrapper.style.display = 'none'; this.loadingWrapper.style.display = 'none'
this.$canvas.style.display = 'block'; this.canvas.style.display = 'block'
} }
/** /**
* Asynchronously downloads PDF. * Asynchronously downloads PDF.
*/ */
async loadPDF() { async loadPDF () {
this.pdfDoc = await window.pdfjsLib.getDocument(this.url).promise; this.pdfDoc = await window.pdfjsLib.getDocument(this.url).promise
this.$pageCount.textContent = this.pdfDoc.numPages; this.pageCount.textContent = this.pdfDoc.numPages
// If the user passed in a number that is out of range, render the last page. // If the user passed in a number that is out of range, render the last page.
if(this.pageNum > this.pdfDoc.numPages) { if (this.pageNum > this.pdfDoc.numPages) {
this.pageNum = this.pdfDoc.numPages this.pageNum = this.pdfDoc.numPages
} }
this.renderPage(this.pageNum); this.renderPage(this.pageNum)
} }
/** /**
* Get page info from document, resize canvas accordingly, and render page. * Get page info from document, resize canvas accordingly, and render page.
* @param num Page number. * @param num Page number.
*/ */
async renderPage(num) { async renderPage (num) {
this.pageRendering = true; this.pageRendering = true
const page = await this.pdfDoc.getPage(num); const page = await this.pdfDoc.getPage(num)
const viewport = page.getViewport({ scale: this.scale }); const viewport = page.getViewport({ scale: this.scale })
this.$canvas.height = viewport.height; this.canvas.height = viewport.height
this.$canvas.width = viewport.width; this.canvas.width = viewport.width
// Wait for rendering to finish // Wait for rendering to finish
await page.render({ await page.render({
canvasContext: this.ctx, canvasContext: this.ctx,
viewport, viewport
}).promise; }).promise
this.pageRendering = false; this.pageRendering = false
this.showContent(); this.showContent()
if (this.pageNumPending !== null) { if (this.pageNumPending !== null) {
// New page rendering is pending // New page rendering is pending
this.renderPage(this.pageNumPending); this.renderPage(this.pageNumPending)
this.pageNumPending = null; this.pageNumPending = null
} }
// Update page counters // Update page counters
this.$pageNum.textContent = num; this.pageNum.textContent = num
} }
/** /**
* If another page rendering in progress, waits until the rendering is * If another page rendering in progress, waits until the rendering is
* finished. Otherwise, executes rendering immediately. * finished. Otherwise, executes rendering immediately.
*/ */
queueRenderPage(num) { queueRenderPage (num) {
if (this.pageRendering) { if (this.pageRendering) {
this.pageNumPending = num; this.pageNumPending = num
} else { } else {
this.renderPage(num); this.renderPage(num)
} }
} }
/** /**
* Displays previous page. * Displays previous page.
*/ */
handlePrevPage() { handlePrevPage () {
if (this.pageNum <= 1) { if (this.pageNum <= 1) {
return; return
} }
this.pageNum--; this.pageNum--
this.queueRenderPage(this.pageNum); this.queueRenderPage(this.pageNum)
} }
/** /**
* Displays next page. * Displays next page.
*/ */
handleNextPage() { handleNextPage () {
if (this.pageNum >= this.pdfDoc.numPages) { if (this.pageNum >= this.pdfDoc.numPages) {
return; return
} }
this.pageNum++; this.pageNum++
this.queueRenderPage(this.pageNum); this.queueRenderPage(this.pageNum)
} }
} }
insertScript('pdfjs', PDFJS_BUNDLE, () => { insertScript('pdfjs', PDFJS_BUNDLE, () => {
window.pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_BUNDLE; window.pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_BUNDLE
Array.from(document.getElementsByClassName('pdf-viewer')).forEach(el => new PDFViewer(el))
Array.from(document.getElementsByClassName('pdf-viewer')).forEach(el => { })
console.log(el);
new PDFViewer(el);
});
});

View file

@ -1,3 +1,3 @@
if (process.env.FEATURE_FLOWCHART_MERMAID === '1') { if (process.env.FEATURE_FLOWCHART_MERMAID === '1') {
import('./mermaid'); import('./mermaid')
} }

View file

@ -1,7 +1,7 @@
import mermaid from 'mermaid'; import mermaid from 'mermaid'
import * as params from '@params'; import * as params from '@params'
const mermaidOptions = params.flowchart?.mermaid || {}; const mermaidOptions = params.flowchart?.mermaid || {}
const options = Object.assign({}, mermaidOptions, { startOnLoad: true }); const options = Object.assign({}, mermaidOptions, { startOnLoad: true })
mermaid.initialize(options); mermaid.initialize(options)

View file

@ -1,27 +1,27 @@
if (process.env.FEATURE_VIDEOPLAYER === '1') { if (process.env.FEATURE_VIDEOPLAYER === '1') {
import('./videoplayer'); import('./videoplayer')
} }
if (process.env.FEATURE_TOC === '1') { if (process.env.FEATURE_TOC === '1') {
import('./toc'); import('./toc')
} }
if (process.env.FEATURE_DARKMODE === '1') { if (process.env.FEATURE_DARKMODE === '1') {
import('./darkmode'); import('./darkmode')
} }
if (process.env.FEATURE_FLOWCHART === '1') { if (process.env.FEATURE_FLOWCHART === '1') {
import('./flowchart'); import('./flowchart')
} }
if (process.env.FEATURE_SYNTAXHIGHLIGHT === '1') { if (process.env.FEATURE_SYNTAXHIGHLIGHT === '1') {
import('./syntaxhighlight'); import('./syntaxhighlight')
} }
if (process.env.FEATURE_MATH === '1') { if (process.env.FEATURE_MATH === '1') {
import('./math'); import('./math')
} }
if (process.env.FEATURE_EMBEDPDF === '1') { if (process.env.FEATURE_EMBEDPDF === '1') {
import('./embedpdf'); import('./embedpdf')
} }

View file

@ -1,3 +1,3 @@
if (process.env.FEATURE_MATH_KATEX === '1') { if (process.env.FEATURE_MATH_KATEX === '1') {
import('./katex'); import('./katex')
} }

View file

@ -1,12 +1,12 @@
import renderMathInElement from 'katex/contrib/auto-render'; import renderMathInElement from 'katex/contrib/auto-render'
import * as params from '@params'; import * as params from '@params'
const defaultOptions = { const defaultOptions = {
delimiters: [ delimiters: [
{left: "$$", right: "$$", display: true}, { left: '$$', right: '$$', display: true },
{left: "\\[", right: "\\]", display: true}, { left: '\\[', right: '\\]', display: true },
{left: "$", right: "$", display: false}, { left: '$', right: '$', display: false },
{left: "\\(", right: "\\)", display: false} { left: '\\(', right: '\\)', display: false }
] ]
} }
@ -15,7 +15,7 @@ window.addEventListener('DOMContentLoaded', () => {
document.body, document.body,
{ {
...defaultOptions, ...defaultOptions,
...(params.math?.katex || {}), ...(params.math?.katex || {})
} }
); )
}); })

View file

@ -1,4 +1,4 @@
import hljs from 'highlight.js'; import hljs from 'highlight.js'
import * as params from '@params'; import * as params from '@params'
hljs.highlightAll(params.syntaxhighlight?.hljs); hljs.highlightAll(params.syntaxhighlight?.hljs)

View file

@ -1,3 +1,3 @@
if (process.env.FEATURE_SYNTAXHIGHLIGHT_HLJS === '1') { if (process.env.FEATURE_SYNTAXHIGHLIGHT_HLJS === '1') {
import('./hljs'); import('./hljs')
} }

View file

@ -1,48 +1,48 @@
import { getDeviceState } from '../../core'; import { getDeviceState } from '../../core'
// Toggle Table of Contents on click. Here, class "hide" open the toc // Toggle Table of Contents on click. Here, class "hide" open the toc
function toggleTOC() { function toggleTOC () {
let toc = document.getElementById("toc-section"); const toc = document.getElementById('toc-section')
if (toc == null) { if (toc == null) {
return return
} }
if (toc.classList.contains("hide")) { if (toc.classList.contains('hide')) {
toc.classList.remove("hide"); toc.classList.remove('hide')
} else { } else {
// if sidebar-section is open, then close it first // if sidebar-section is open, then close it first
let sidebar = document.getElementById("sidebar-section"); const sidebar = document.getElementById('sidebar-section')
if (sidebar != null && sidebar.classList.contains("hide")) { if (sidebar != null && sidebar.classList.contains('hide')) {
sidebar.classList.remove("hide"); sidebar.classList.remove('hide')
} }
// add "hide" class // add "hide" class
toc.classList.add("hide"); toc.classList.add('hide')
// if it is mobile device. then scroll to top. // if it is mobile device. then scroll to top.
const { isMobile } = getDeviceState(); const { isMobile } = getDeviceState()
if (isMobile && toc.classList.contains("hide")) { if (isMobile && toc.classList.contains('hide')) {
document.body.scrollTop = 0; document.body.scrollTop = 0
document.documentElement.scrollTop = 0; document.documentElement.scrollTop = 0
} }
} }
if (document.getElementById("hero-area") != null) { if (document.getElementById('hero-area') != null) {
document.getElementById("hero-area").classList.toggle("hide"); document.getElementById('hero-area').classList.toggle('hide')
} }
} }
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
// bind click event to #toc-toggle in navbar-2.html // bind click event to #toc-toggle in navbar-2.html
const $toggle = document.getElementById('toc-toggler'); const toggle = document.getElementById('toc-toggler')
if ($toggle) $toggle.addEventListener('click', toggleTOC); if (toggle) toggle.addEventListener('click', toggleTOC)
// hide TOC when user clicks on a TOC link. // hide TOC when user clicks on a TOC link.
// Only applies if it's mobile. // Only applies if it's mobile.
const $toc = document.getElementById("TableOfContents"); const toc = document.getElementById('TableOfContents')
if ($toc) { if (toc) {
$toc.addEventListener('click', (event) => { toc.addEventListener('click', (event) => {
const { isMobile } = getDeviceState(); const { isMobile } = getDeviceState()
if (isMobile && event.target.nodeName === 'A') { if (isMobile && event.target.nodeName === 'A') {
toggleTOC(); toggleTOC()
} }
}); })
} }
}); })

View file

@ -1,3 +1,3 @@
if (process.env.FEATURE_VIDEOPLAYER_PLYR === '1') { if (process.env.FEATURE_VIDEOPLAYER_PLYR === '1') {
import('./plyr'); import('./plyr')
} }

View file

@ -1,5 +1,5 @@
import Plyr from 'plyr'; import Plyr from 'plyr'
import * as params from '@params'; import * as params from '@params'
const options = params.videoplayer?.plyr; const options = params.videoplayer?.plyr
window.addEventListener('DOMContentLoaded', () => Plyr.setup('.video-player', options)); window.addEventListener('DOMContentLoaded', () => Plyr.setup('.video-player', options))

View file

@ -1,16 +1,16 @@
import {init} from 'ityped'; import { init } from 'ityped'
// =========== Typing Carousel ================ // =========== Typing Carousel ================
// get data from hidden ul and set as typing data // get data from hidden ul and set as typing data
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
$ul = document.getElementById('typing-carousel-data')?.children; const $ul = document.getElementById('typing-carousel-data')?.children
if($ul == null || $ul.length === 0) return; if ($ul == null || $ul.length === 0) return
const strings = Array.from($ul).map($el => $el.textContent); const strings = Array.from($ul).map($el => $el.textContent)
init('#ityped', { init('#ityped', {
strings, strings,
startDelay: 200, startDelay: 200,
loop: true loop: true
}); })
}); })

View file

@ -1,4 +1,4 @@
import './note'; import './note'
import './search'; import './search'
import './single'; import './single'
import './home'; import './home'

View file

@ -1,32 +1,30 @@
import $ from 'jquery'; import imagesLoaded from 'imagesloaded'
import imagesLoaded from 'imagesloaded';
$(document).ready(function () { document.addEventListener('DOMContentLoaded', function () {
function resizeGridItem(item) { function resizeGridItem (item) {
var grid = document.getElementsByClassName("note-card-holder")[0]; const grid = document.getElementsByClassName('note-card-holder')[0]
var rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-auto-rows')); const rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-auto-rows'))
var rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-row-gap')); const rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-row-gap'))
var rowSpan = Math.ceil((item.querySelector('.item').getBoundingClientRect().height + rowGap) / (rowHeight + rowGap)); const rowSpan = Math.ceil((item.querySelector('.item').getBoundingClientRect().height + rowGap) / (rowHeight + rowGap))
item.style.gridRowEnd = "span " + rowSpan; item.style.gridRowEnd = 'span ' + rowSpan
} }
function resizeAllGridItems() { function resizeAllGridItems () {
var allItems = document.getElementsByClassName("note-card"); const allItems = document.getElementsByClassName('note-card')
for (var x = 0; x < allItems.length; x++) { for (let x = 0; x < allItems.length; x++) {
resizeGridItem(allItems[x]); resizeGridItem(allItems[x])
} }
} }
function resizeInstance(instance) { function resizeInstance (instance) {
var item = instance.elements[0]; const item = instance.elements[0]
resizeGridItem(item); resizeGridItem(item)
} }
// window.onload = resizeAllGridItems(); window.addEventListener('resize', resizeAllGridItems)
window.addEventListener("resize", resizeAllGridItems);
var allItems = document.getElementsByClassName("note-card"); const allItems = document.getElementsByClassName('note-card')
for (var x = 0; x < allItems.length; x++) { for (let x = 0; x < allItems.length; x++) {
imagesLoaded(allItems[x], resizeInstance); imagesLoaded(allItems[x], resizeInstance)
} }
}); })

View file

@ -1,132 +1,133 @@
import $ from 'jquery'; import Fuse from 'fuse.js'
import Fuse from 'fuse.js'; import Mark from 'mark.js'
import Mark from 'mark.js';
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
var summaryInclude=60; const summaryInclude = 60
var fuseOptions = { const fuseOptions = {
shouldSort: true, shouldSort: true,
includeMatches: true, includeMatches: true,
threshold: 0.0, threshold: 0.0,
tokenize:true, tokenize: true,
location: 0, location: 0,
distance: 100, distance: 100,
maxPatternLength: 32, maxPatternLength: 32,
minMatchCharLength: 1, minMatchCharLength: 1,
keys: [ keys: [
{name:"title",weight:0.8}, { name: 'title', weight: 0.8 },
{name:"hero",weight:0.7}, { name: 'hero', weight: 0.7 },
{name:"summary",weight:0.6}, { name: 'summary', weight: 0.6 },
{name:"date",weight:0.5}, { name: 'date', weight: 0.5 },
{name:"contents",weight:0.5}, { name: 'contents', weight: 0.5 },
{name:"tags",weight:0.3}, { name: 'tags', weight: 0.3 },
{name:"categories",weight:0.3} { name: 'categories', weight: 0.3 }
] ]
};
var searchQuery = param("keyword");
if(searchQuery){
$("#search-query").val(searchQuery);
executeSearch(searchQuery);
}else {
$('#search-results').append("<p>Please enter a word or phrase above</p>");
} }
const searchQuery = param('keyword')
if (searchQuery) {
document.getElementById('search-query').value = searchQuery
executeSearch(searchQuery)
} else {
const node = document.createElement('p')
node.textContent = 'Please enter a word or phrase above'
window.getElementById('search-results').append(node)
}
function executeSearch (searchQuery) {
const url = window.location.href.split('/search/')[0] + '/index.json'
function executeSearch(searchQuery){ fetch(url).then(function (data) {
$.getJSON( window.location.href.split("/search/")[0] + "/index.json", function( data ) { const pages = data
console.log(data); const fuse = new Fuse(pages, fuseOptions)
const results = fuse.search(searchQuery)
var pages = data; document.getElementById('search-box').value = searchQuery
var fuse = new Fuse(pages, fuseOptions); if (results.length > 0) {
var result = fuse.search(searchQuery); populateResults(results)
// console.log({"matches":result}); } else {
document.getElementById("search-box").value = searchQuery const node = document.createElement('p')
if(result.length > 0){ node.textContent = 'No matches found'
populateResults(result); window.getElementById('search-results').append(node)
}else{
$('#search-results').append("<p>No matches found</p>");
} }
}); })
} }
function populateResults(result){ function populateResults (results) {
$.each(result,function(key,value){ results.forEach(function (value, key) {
var contents= value.item.contents; const contents = value.item.contents
var snippet = ""; let snippet = ''
var snippetHighlights=[]; const snippetHighlights = []
var tags =[]; if (fuseOptions.tokenize) {
if( fuseOptions.tokenize ){ snippetHighlights.push(searchQuery)
snippetHighlights.push(searchQuery); } else {
}else{ value.matches.forEach(function (mvalue) {
$.each(value.matches,function(matchKey,mvalue){ if (mvalue.key === 'tags' || mvalue.key === 'categories') {
if(mvalue.key == "tags" || mvalue.key == "categories" ){ snippetHighlights.push(mvalue.value)
snippetHighlights.push(mvalue.value); } else if (mvalue.key === 'contents') {
}else if(mvalue.key == "contents"){ const start = mvalue.indices[0][0] - summaryInclude > 0 ? mvalue.indices[0][0] - summaryInclude : 0
start = mvalue.indices[0][0]-summaryInclude>0?mvalue.indices[0][0]-summaryInclude:0; const end = mvalue.indices[0][1] + summaryInclude < contents.length ? mvalue.indices[0][1] + summaryInclude : contents.length
end = mvalue.indices[0][1]+summaryInclude<contents.length?mvalue.indices[0][1]+summaryInclude:contents.length; snippet += contents.substring(start, end)
snippet += contents.substring(start,end); snippetHighlights.push(mvalue.value.substring(mvalue.indices[0][0], mvalue.indices[0][1] - mvalue.indices[0][0] + 1))
snippetHighlights.push(mvalue.value.substring(mvalue.indices[0][0],mvalue.indices[0][1]-mvalue.indices[0][0]+1));
} }
}); })
} }
if(snippet.length<1){ if (snippet.length < 1) {
snippet += contents.substring(0,summaryInclude*2); snippet += contents.substring(0, summaryInclude * 2)
} }
//pull template from hugo templarte definition // pull template from hugo template definition
var templateDefinition = $('#search-result-template').html(); const templateDefinition = document.getElementById('search-result-template').innerHTML
//replace values // replace values
var output = render(templateDefinition, { const output = render(templateDefinition, {
key:key, key,
title:value.item.title, title: value.item.title,
hero:value.item.hero, hero: value.item.hero,
date:value.item.date, date: value.item.date,
summary:value.item.summary, summary: value.item.summary,
link:value.item.permalink, link: value.item.permalink,
tags:value.item.tags, tags: value.item.tags,
categories:value.item.categories, categories: value.item.categories,
snippet:snippet snippet
}); })
$('#search-results').append(output);
$.each(snippetHighlights,function(snipkey,snipvalue) { const doc = new DOMParser().parseFromString(output, 'text/html')
const context = document.getElementById("#summary-"+key); document.getElementById('search-results').append(doc)
var instance = new Mark(context);
instance.mark(snipvalue);
});
}); snippetHighlights.forEach(function (snipvalue) {
const context = document.getElementById('#summary-' + key)
const instance = new Mark(context)
instance.mark(snipvalue)
})
})
} }
function param(name) { function param (name) {
return decodeURIComponent((location.search.split(name + '=')[1] || '').split('&')[0]).replace(/\+/g, ' '); return decodeURIComponent((location.search.split(name + '=')[1] || '').split('&')[0]).replace(/\+/g, ' ')
} }
function render(templateString, data) { function render (templateString, data) {
var conditionalMatches,conditionalPattern,copy; let conditionalMatches, copy
conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g; const conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g
//since loop below depends on re.lastInxdex, we use a copy to capture any manipulations whilst inside the loop // since loop below depends on re.lastInxdex, we use a copy to capture any manipulations whilst inside the loop
copy = templateString; copy = templateString
while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) { while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) {
if(data[conditionalMatches[1]]){ if (data[conditionalMatches[1]]) {
//valid key, remove conditionals, leave contents. // valid key, remove conditionals, leave contents.
copy = copy.replace(conditionalMatches[0],conditionalMatches[2]); copy = copy.replace(conditionalMatches[0], conditionalMatches[2])
}else{ } else {
//not valid, remove entire section // not valid, remove entire section
copy = copy.replace(conditionalMatches[0],''); copy = copy.replace(conditionalMatches[0], '')
} }
} }
templateString = copy; templateString = copy
//now any conditionals removed we can do simple substitution // now any conditionals removed we can do simple substitution
var key, find, re; let key, find, re
for (key in data) { for (key in data) {
find = '\\$\\{\\s*' + key + '\\s*\\}'; find = '\\$\\{\\s*' + key + '\\s*\\}'
re = new RegExp(find, 'g'); re = new RegExp(find, 'g')
templateString = templateString.replace(re, data[key]); templateString = templateString.replace(re, data[key])
} }
return templateString; return templateString
} }
}); })

View file

@ -1,58 +1,58 @@
import $ from 'jquery';
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
// =========== Add anchor to the headers ================ // =========== Add anchor to the headers ================
function addAnchor(element) { function addAnchor (element) {
element.innerHTML = `<a href="#${element.id}" class="header-anchor">${element.innerHTML}<sup><i class="fas fa-link fa-sm"></i></sup></a>`; element.innerHTML = `<a href="#${element.id}" class="header-anchor">${element.innerHTML}<sup><i class="fas fa-link fa-sm"></i></sup></a>`
} }
var postContent = document.getElementById("post-content"); const postContent = document.getElementById('post-content')
if (postContent != null) { if (postContent != null) {
var headerTypes = ["h1", "h2", "h3", "h4", "h5", "h6"]; const headerTypes = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
for (var i = 0; i < headerTypes.length; i++) { for (let i = 0; i < headerTypes.length; i++) {
var headers = postContent.querySelectorAll(headerTypes[i]); const headers = postContent.querySelectorAll(headerTypes[i])
if (headers) { if (headers) {
headers.forEach(addAnchor); headers.forEach(addAnchor)
} }
} }
} }
// =============== Make TOC Compatible wit Bootstrap Scroll Spy ======== // =============== Make TOC Compatible wit Bootstrap Scroll Spy ========
// add "navbar" class to the "nav" element // add "navbar" class to the "nav" element
let toc = document.getElementById("TableOfContents"); const toc = document.getElementById('TableOfContents')
if (toc) { if (toc) {
toc.classList.add("navbar"); toc.classList.add('navbar')
// add "nav-pills" class to the "ul" elements // add "nav-pills" class to the "ul" elements
let elems = toc.getElementsByTagName("ul"); let elems = toc.getElementsByTagName('ul')
for (let i = 0; i < elems.length; i++) { for (let i = 0; i < elems.length; i++) {
elems[i].classList.add("nav-pills"); elems[i].classList.add('nav-pills')
} }
// add "nav-item" class to the "li" elements // add "nav-item" class to the "li" elements
elems = toc.getElementsByTagName("li"); elems = toc.getElementsByTagName('li')
for (let i = 0; i < elems.length; i++) { for (let i = 0; i < elems.length; i++) {
elems[i].classList.add("nav-item"); elems[i].classList.add('nav-item')
} }
// add "nav-link" class to the "a" elements // add "nav-link" class to the "a" elements
elems = toc.getElementsByTagName("a"); elems = toc.getElementsByTagName('a')
for (let i = 0; i < elems.length; i++) { for (let i = 0; i < elems.length; i++) {
elems[i].classList.add("nav-link"); elems[i].classList.add('nav-link')
} }
} }
// add scroll to top button // add scroll to top button
var btn = $('#scroll-to-top'); const btn = document.getElementById('scroll-to-top')
$(window).scroll(function () { window.addEventListener('scroll', function () {
if ($(window).scrollTop() > 300) { if (window.scrollY > 300) {
btn.addClass('show'); btn.classList.add('show')
} else { } else {
btn.removeClass('show'); btn.classList.remove('show')
} }
}); })
btn.on('click', function (e) { btn.addEventListener('click', function (e) {
e.preventDefault(); e.preventDefault()
$('html, body').animate({ scrollTop: 0 }, '300'); window.scrollTo({
}); top: 0,
}); behavior: 'smooth'
})
})
})

View file

@ -1,3 +1,3 @@
export const process = { export const process = {
env: {}, env: {}
}; }

View file

@ -1,221 +1,220 @@
import { getDeviceState } from '../core'; import { getDeviceState } from '../core'
function fourColumRow(gallery, entries, i) { function fourColumRow (gallery, entries, i) {
let entry1 = document.createElement("div"); const entry1 = document.createElement('div')
entry1.classList.add("col-lg-6", "m-0", "p-0"); entry1.classList.add('col-lg-6', 'm-0', 'p-0')
entry1.appendChild(entries[i].cloneNode(true)); entry1.appendChild(entries[i].cloneNode(true))
entry1.children[0].classList.add("img-type-1"); entry1.children[0].classList.add('img-type-1')
gallery.appendChild(entry1); gallery.appendChild(entry1)
i++; i++
let entry2 = document.createElement("div"); const entry2 = document.createElement('div')
entry2.classList.add("col-lg-3", "m-0", "p-0"); entry2.classList.add('col-lg-3', 'm-0', 'p-0')
entry2.appendChild(entries[i].cloneNode(true)); entry2.appendChild(entries[i].cloneNode(true))
entry2.children[0].classList.add("img-type-1"); entry2.children[0].classList.add('img-type-1')
gallery.appendChild(entry2); gallery.appendChild(entry2)
i++; i++
let entry3 = document.createElement("div"); const entry3 = document.createElement('div')
entry3.classList.add("col-lg-3", "m-0", "p-0"); entry3.classList.add('col-lg-3', 'm-0', 'p-0')
entry3.appendChild(entries[i].cloneNode(true)); entry3.appendChild(entries[i].cloneNode(true))
entry3.children[0].classList.add("img-type-2"); entry3.children[0].classList.add('img-type-2')
i++; i++
entry3.appendChild(entries[i].cloneNode(true)); entry3.appendChild(entries[i].cloneNode(true))
entry3.children[1].classList.add("img-type-2"); entry3.children[1].classList.add('img-type-2')
gallery.appendChild(entry3); gallery.appendChild(entry3)
i++; i++
} }
function fourColumnReversedRow(gallery, entries, i) { function fourColumnReversedRow (gallery, entries, i) {
let entry1 = document.createElement("div"); const entry1 = document.createElement('div')
entry1.classList.add("col-lg-3", "m-0", "p-0"); entry1.classList.add('col-lg-3', 'm-0', 'p-0')
entry1.appendChild(entries[i].cloneNode(true)); entry1.appendChild(entries[i].cloneNode(true))
entry1.children[0].classList.add("img-type-2"); entry1.children[0].classList.add('img-type-2')
i++; i++
entry1.appendChild(entries[i].cloneNode(true)); entry1.appendChild(entries[i].cloneNode(true))
entry1.children[1].classList.add("img-type-2"); entry1.children[1].classList.add('img-type-2')
gallery.appendChild(entry1); gallery.appendChild(entry1)
i++; i++
let entry2 = document.createElement("div"); const entry2 = document.createElement('div')
entry2.classList.add("col-lg-3", "m-0", "p-0"); entry2.classList.add('col-lg-3', 'm-0', 'p-0')
entry2.appendChild(entries[i].cloneNode(true)); entry2.appendChild(entries[i].cloneNode(true))
entry2.children[0].classList.add("img-type-1"); entry2.children[0].classList.add('img-type-1')
gallery.appendChild(entry2); gallery.appendChild(entry2)
i++; i++
let entry3 = document.createElement("div"); const entry3 = document.createElement('div')
entry3.classList.add("col-lg-6", "m-0", "p-0"); entry3.classList.add('col-lg-6', 'm-0', 'p-0')
entry3.appendChild(entries[i].cloneNode(true)); entry3.appendChild(entries[i].cloneNode(true))
entry3.children[0].classList.add("img-type-1"); entry3.children[0].classList.add('img-type-1')
gallery.appendChild(entry3); gallery.appendChild(entry3)
i++; i++
} }
function threeColumnRow(gallery, entries, i) { function threeColumnRow (gallery, entries, i) {
console.log(i); console.log(i)
let entry1 = document.createElement("div"); const entry1 = document.createElement('div')
entry1.classList.add("col-lg-6", "col-md-6", "m-0", "p-0"); entry1.classList.add('col-lg-6', 'col-md-6', 'm-0', 'p-0')
entry1.appendChild(entries[i].cloneNode(true)); entry1.appendChild(entries[i].cloneNode(true))
entry1.children[0].classList.add("img-type-1"); entry1.children[0].classList.add('img-type-1')
gallery.appendChild(entry1); gallery.appendChild(entry1)
i++; i++
let entry2 = document.createElement("div"); const entry2 = document.createElement('div')
entry2.classList.add("col-lg-3", "col-md-3", "m-0", "p-0"); entry2.classList.add('col-lg-3', 'col-md-3', 'm-0', 'p-0')
entry2.appendChild(entries[i].cloneNode(true)); entry2.appendChild(entries[i].cloneNode(true))
entry2.children[0].classList.add("img-type-1"); entry2.children[0].classList.add('img-type-1')
gallery.appendChild(entry2); gallery.appendChild(entry2)
i++; i++
let entry3 = document.createElement("div"); const entry3 = document.createElement('div')
entry3.classList.add("col-lg-3", "col-md-3", "m-0", "p-0"); entry3.classList.add('col-lg-3', 'col-md-3', 'm-0', 'p-0')
entry3.appendChild(entries[i].cloneNode(true)); entry3.appendChild(entries[i].cloneNode(true))
entry3.children[0].classList.add("img-type-1"); entry3.children[0].classList.add('img-type-1')
gallery.appendChild(entry3); gallery.appendChild(entry3)
i++; i++
} }
function threeColumnReversedRow(gallery, entries, i) { function threeColumnReversedRow (gallery, entries, i) {
let entry1 = document.createElement("div"); const entry1 = document.createElement('div')
entry1.classList.add("col-lg-3", "col-md-3", "m-0", "p-0"); entry1.classList.add('col-lg-3', 'col-md-3', 'm-0', 'p-0')
entry1.appendChild(entries[i].cloneNode(true)); entry1.appendChild(entries[i].cloneNode(true))
entry1.children[0].classList.add("img-type-1"); entry1.children[0].classList.add('img-type-1')
gallery.appendChild(entry1); gallery.appendChild(entry1)
i++; i++
let entry2 = document.createElement("div"); const entry2 = document.createElement('div')
entry2.classList.add("col-lg-3", "col-md-3", "m-0", "p-0"); entry2.classList.add('col-lg-3', 'col-md-3', 'm-0', 'p-0')
entry2.appendChild(entries[i].cloneNode(true)); entry2.appendChild(entries[i].cloneNode(true))
entry2.children[0].classList.add("img-type-1"); entry2.children[0].classList.add('img-type-1')
gallery.appendChild(entry2); gallery.appendChild(entry2)
i++; i++
let entry3 = document.createElement("div"); const entry3 = document.createElement('div')
entry3.classList.add("col-lg-6", "col-md-3", "m-0", "p-0"); entry3.classList.add('col-lg-6', 'col-md-3', 'm-0', 'p-0')
entry3.appendChild(entries[i].cloneNode(true)); entry3.appendChild(entries[i].cloneNode(true))
entry3.children[0].classList.add("img-type-1"); entry3.children[0].classList.add('img-type-1')
gallery.appendChild(entry3); gallery.appendChild(entry3)
i++; i++
} }
function twoColumnRow(gallery, entries, i) { function twoColumnRow (gallery, entries, i) {
let entry1 = document.createElement("div"); const entry1 = document.createElement('div')
entry1.classList.add("col-6", "m-0", "p-0"); entry1.classList.add('col-6', 'm-0', 'p-0')
entry1.appendChild(entries[i].cloneNode(true)); entry1.appendChild(entries[i].cloneNode(true))
entry1.children[0].classList.add("img-type-1"); entry1.children[0].classList.add('img-type-1')
gallery.appendChild(entry1); gallery.appendChild(entry1)
i++; i++
let entry2 = document.createElement("div"); const entry2 = document.createElement('div')
entry2.classList.add("col-6", "m-0", "p-0"); entry2.classList.add('col-6', 'm-0', 'p-0')
entry2.appendChild(entries[i].cloneNode(true)); entry2.appendChild(entries[i].cloneNode(true))
entry2.children[0].classList.add("img-type-1"); entry2.children[0].classList.add('img-type-1')
gallery.appendChild(entry2); gallery.appendChild(entry2)
i++; i++
} }
function singleColumnRow(gallery, entries, i) { function singleColumnRow (gallery, entries, i) {
let entry1 = document.createElement("div"); const entry1 = document.createElement('div')
entry1.classList.add("col-12", "m-0", "p-0"); entry1.classList.add('col-12', 'm-0', 'p-0')
entry1.appendChild(entries[i].cloneNode(true)); entry1.appendChild(entries[i].cloneNode(true))
entry1.children[0].classList.add("img-type-1"); entry1.children[0].classList.add('img-type-1')
gallery.appendChild(entry1); gallery.appendChild(entry1)
i++; i++
} }
function showAchievements() { function showAchievements () {
const { isLaptop, isTablet } = getDeviceState() const { isLaptop, isTablet } = getDeviceState()
// show achievements from achievements-holder div // show achievements from achievements-holder div
let gallery = document.getElementById("gallery"); const gallery = document.getElementById('gallery')
if (gallery == null) { if (gallery == null) {
return return
} }
gallery.innerHTML = ""; gallery.innerHTML = ''
const entries = document.getElementById("achievements-holder").children; const entries = document.getElementById('achievements-holder').children
let len = entries.length; let len = entries.length
let i = 0; let i = 0
let rowNumber = 1; let rowNumber = 1
while (i < len) { while (i < len) {
if (isLaptop) { if (isLaptop) {
if (i + 4 <= len) { if (i + 4 <= len) {
if (rowNumber % 2) { if (rowNumber % 2) {
fourColumRow(gallery, entries, i); fourColumRow(gallery, entries, i)
} else { } else {
fourColumnReversedRow(gallery, entries, i); fourColumnReversedRow(gallery, entries, i)
} }
i += 4; i += 4
} else if (i + 3 <= len) { } else if (i + 3 <= len) {
if (rowNumber % 2) { if (rowNumber % 2) {
threeColumnRow(gallery, entries, i); threeColumnRow(gallery, entries, i)
} else { } else {
threeColumnReversedRow(gallery, entries, i); threeColumnReversedRow(gallery, entries, i)
} }
i += 3; i += 3
} else if (i + 2 <= len) { } else if (i + 2 <= len) {
twoColumnRow(gallery, entries, i); twoColumnRow(gallery, entries, i)
i += 2; i += 2
} else { } else {
singleColumnRow(gallery, entries, i); singleColumnRow(gallery, entries, i)
i++; i++
} }
} else if (isTablet) { } else if (isTablet) {
if (i + 2 <= len) { if (i + 2 <= len) {
twoColumnRow(gallery, entries, i); twoColumnRow(gallery, entries, i)
i += 2; i += 2
} else { } else {
singleColumnRow(gallery, entries, i); singleColumnRow(gallery, entries, i)
i++; i++
} }
} else { } else {
singleColumnRow(gallery, entries, i); singleColumnRow(gallery, entries, i)
i++; i++
} }
rowNumber++; rowNumber++
} }
// show full image on click // show full image on click
let elements = document.getElementsByClassName("achievement-entry"); const elements = document.getElementsByClassName('achievement-entry')
len = elements.length; len = elements.length
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
elements[i].onclick = function () { elements[i].onclick = function () {
let achievements = document.getElementsByClassName("achievement-entry"); const achievements = document.getElementsByClassName('achievement-entry')
let len2 = achievements.length; const len2 = achievements.length
for (let j = 0; j < len2; j++) { for (let j = 0; j < len2; j++) {
achievements[j].classList.toggle("hidden"); achievements[j].classList.toggle('hidden')
} }
this.classList.toggle("achievement-details"); this.classList.toggle('achievement-details')
this.classList.toggle("hidden"); this.classList.toggle('hidden')
this.parentElement.classList.toggle("col-lg-12"); this.parentElement.classList.toggle('col-lg-12')
this.parentElement.classList.toggle("col-md-12"); this.parentElement.classList.toggle('col-md-12')
this.parentElement.classList.toggle("col-sm-12"); this.parentElement.classList.toggle('col-sm-12')
if (this.children["SmallImage"].hasAttribute("active")) { if (this.children.SmallImage.hasAttribute('active')) {
let mainLogo = this.children["LargeImage"].getAttribute("Style"); const mainLogo = this.children.LargeImage.getAttribute('Style')
this.children["LargeImage"].setAttribute("active", true); this.children.LargeImage.setAttribute('active', true)
this.children["SmallImage"].removeAttribute("active"); this.children.SmallImage.removeAttribute('active')
this.setAttribute("Style", mainLogo); this.setAttribute('Style', mainLogo)
} else { } else {
let mainLogo = this.children["SmallImage"].getAttribute("Style"); const mainLogo = this.children.SmallImage.getAttribute('Style')
this.children["SmallImage"].setAttribute("active", true); this.children.SmallImage.setAttribute('active', true)
this.children["LargeImage"].removeAttribute("active"); this.children.LargeImage.removeAttribute('active')
this.setAttribute("Style", mainLogo); this.setAttribute('Style', mainLogo)
} }
if (this.children["caption"] != undefined) { if (this.children.caption !== undefined) {
this.children["caption"].classList.toggle("hidden"); this.children.caption.classList.toggle('hidden')
} }
if (this.children["enlarge-icon"] != undefined) { if (this.children['enlarge-icon'] !== undefined) {
this.getElementsByClassName('fa-xmark')[0].classList.toggle('hidden'); this.getElementsByClassName('fa-xmark')[0].classList.toggle('hidden')
this.getElementsByClassName('fa-magnifying-glass-plus')[0].classList.toggle('hidden'); this.getElementsByClassName('fa-magnifying-glass-plus')[0].classList.toggle('hidden')
} }
if (this.children["achievement-title"] != undefined) { if (this.children['achievement-title'] !== undefined) {
this.children["achievement-title"].classList.toggle("hidden"); this.children['achievement-title'].classList.toggle('hidden')
} }
} }
} }
} }
['DOMContentLoaded', 'resize'].forEach((event) => ['DOMContentLoaded', 'resize'].forEach((event) =>
document.addEventListener(event, showAchievements)); document.addEventListener(event, showAchievements))

View file

@ -1,34 +1,33 @@
// Show more rows in the taken courses table // Show more rows in the taken courses table
function toggleCourseVisibility(elem) { function toggleCourseVisibility (elem) {
// find the courses // find the courses
let courses = elem.parentNode.getElementsByClassName("course"); const courses = elem.parentNode.getElementsByClassName('course')
if (courses == null) { if (courses == null) {
return return
} }
// toggle hidden-course class from the third elements // toggle hidden-course class from the third elements
for (const course of courses) { for (const course of courses) {
if (course.classList.contains("hidden-course") || course.classList.contains("toggled-hidden-course")) { if (course.classList.contains('hidden-course') || course.classList.contains('toggled-hidden-course')) {
course.classList.toggle("hidden-course"); course.classList.toggle('hidden-course')
course.classList.add("toggled-hidden-course"); course.classList.add('toggled-hidden-course')
} }
} }
// toggle the buttons visibility // toggle the buttons visibility
let buttonsToToggle = elem.parentNode.getElementsByClassName("show-more-btn"); const buttonsToToggle = elem.parentNode.getElementsByClassName('show-more-btn')
for (const buttonToToggle of buttonsToToggle) { for (const buttonToToggle of buttonsToToggle) {
buttonToToggle.classList.toggle("hidden"); buttonToToggle.classList.toggle('hidden')
} }
} }
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
const $els = [ const els = [
document.getElementById('show-more-btn'), document.getElementById('show-more-btn'),
document.getElementById('show-less-btn'), document.getElementById('show-less-btn')
]; ]
$els.filter(($el) => $el != null).forEach(($el) => els.filter((el) => el != null).forEach((el) =>
$el.addEventListener('click', ({target}) => el.addEventListener('click', ({ target }) =>
toggleCourseVisibility(target))); toggleCourseVisibility(target)))
}); })

View file

@ -1,7 +1,7 @@
import './navbar'; import './navbar'
import './sidebar'; import './sidebar'
import './education'; import './education'
import './achievements'; import './achievements'
import './projects'; import './projects'
import './publications'; import './publications'

View file

@ -1,61 +1,60 @@
import $ from 'jquery';
const updateNavBar = () => { const updateNavBar = () => {
if ($(document).scrollTop() > 40) { const topNavbar = document.getElementById('top-navbar')
$('#top-navbar').removeClass('initial-navbar'); const navbarToggler = document.getElementById('navbar-toggler')
$('#top-navbar').addClass('final-navbar shadow'); const themeIcon = document.getElementById('navbar-theme-icon-svg')
$('#navbar-toggler').removeClass('navbar-dark'); if (window.scrollY > 40) {
$('#navbar-toggler').addClass('navbar-light'); topNavbar.classList.remove('initial-navbar')
topNavbar.classList.add('final-navbar', 'shadow')
navbarToggler.classList.remove('navbar-dark')
navbarToggler.classList.add('navbar-light')
// color theme selector a.k.a. dark mode // color theme selector a.k.a. dark mode
$('#navbar-theme-icon-svg').removeClass('navbar-icon-svg-dark'); themeIcon.classList.remove('navbar-icon-svg-dark')
// get the main logo from hidden img tag // get the main logo from hidden img tag
let mainLogo = document.getElementById("main-logo") const mainLogo = document.getElementById('main-logo')
if (mainLogo !== null) { if (mainLogo !== null) {
let logoURL = mainLogo.getAttribute("src"); const logoURL = mainLogo.getAttribute('src')
$('#logo').attr("src", logoURL); document.getElementById('logo').setAttribute('src', logoURL)
} }
} else { } else {
$('#top-navbar').removeClass('final-navbar shadow'); topNavbar.classList.remove('final-navbar', 'shadow')
$('#top-navbar').addClass('initial-navbar'); topNavbar.classList.add('initial-navbar')
$('#navbar-toggler').removeClass('navbar-light'); navbarToggler.classList.remove('navbar-light')
$('#navbar-toggler').addClass('navbar-dark'); navbarToggler.classList.add('navbar-dark')
// color theme selector a.k.a. dark mode // color theme selector a.k.a. dark mode
$('#navbar-theme-icon-svg').addClass('navbar-icon-svg-dark'); themeIcon.classList.add('navbar-icon-svg-dark')
// get the inverted logo from hidden img tag // get the inverted logo from hidden img tag
let invertedLogo = document.getElementById("inverted-logo") const invertedLogo = document.getElementById('inverted-logo')
if (invertedLogo !== null) { if (invertedLogo !== null) {
let logoURL = invertedLogo.getAttribute("src"); const logoURL = invertedLogo.getAttribute('src')
$('#logo').attr("src", logoURL); document.getElementById('logo').setAttribute('src', logoURL)
} }
} }
}; }
$(document).ready(function () {
document.addEventListener('DOMContentLoaded', function () {
// change navbar style on scroll // change navbar style on scroll
// ================================================== // ==================================================
// When the user scrolls down 80px from the top of the document, resize the navbar's padding and the logo's font size // When the user scrolls down 80px from the top of the document,
// $.onscroll = function() {scrollFunction()}; // resize the navbar's padding and the logo's font size
$(document).scroll(function () { document.addEventListener('scroll', updateNavBar)
updateNavBar();
});
// Creates a click handler to collapse the navigation when // Creates a click handler to collapse the navigation when
// anchors in the mobile nav pop up are clicked // anchors in the mobile nav pop up are clicked
var navMain = $(".navbar-collapse"); const navMain = document.getElementsByClassName('navbar-collapse')
if (navMain) { for (const el of navMain) {
navMain.on("click", "a", null, function (e) { el.addEventListener('click', function (e) {
$('.navbar-collapse').collapse('hide'); if (e.target.tagName === 'A') {
}); navMain.collapse('hide')
}
})
} }
updateNavBar(); updateNavBar()
}); })

View file

@ -1,18 +1,19 @@
import Filterizr from 'filterizr'; import Filterizr from 'filterizr'
import { insertScript } from '../core' import { insertScript } from '../core'
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
// ================== Project cards ===================== // ================== Project cards =====================
// setup project filter buttons // setup project filter buttons
var projectCardHolder = document.getElementById("project-card-holder"); const projectCardHolder = document.getElementById('project-card-holder')
if (projectCardHolder != null && projectCardHolder.children.length != 0) { if (projectCardHolder != null && projectCardHolder.children.length !== 0) {
new Filterizr(".filtr-projects", { // eslint-disable-next-line no-new
new Filterizr('.filtr-projects', {
layout: 'sameWidth', layout: 'sameWidth',
controlsSelector: '.project-filtr-control', controlsSelector: '.project-filtr-control'
}); })
} }
}); })
// dynamically insert github buttons script. // dynamically insert github buttons script.
insertScript('github-buttons', 'https://buttons.github.io/buttons.js'); insertScript('github-buttons', 'https://buttons.github.io/buttons.js')

View file

@ -1,12 +1,13 @@
import Filterizr from 'filterizr'; import Filterizr from 'filterizr'
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
var publicationCardHolder = document.getElementById("publication-card-holder"); const publicationCardHolder = document.getElementById('publication-card-holder')
if (publicationCardHolder != null && publicationCardHolder.children.length != 0) { if (publicationCardHolder != null && publicationCardHolder.children.length !== 0) {
new Filterizr(".filtr-publications", { // eslint-disable-next-line no-new
new Filterizr('.filtr-publications', {
layout: 'sameWidth', layout: 'sameWidth',
gridItemsSelector: '.pub-filtr-item', gridItemsSelector: '.pub-filtr-item',
controlsSelector: '.pub-filtr-control', controlsSelector: '.pub-filtr-control'
}); })
} }
}); })

View file

@ -1,39 +1,38 @@
import { getDeviceState } from '../core/device'; import { getDeviceState } from '../core/device'
// Toggle sidebar on click. Here, class "hide" open the sidebar // Toggle sidebar on click. Here, class "hide" open the sidebar
function toggleSidebar() { function toggleSidebar () {
let sidebar = document.getElementById("sidebar-section"); const sidebar = document.getElementById('sidebar-section')
if (sidebar == null) { if (sidebar == null) {
return return
} }
if (sidebar.classList.contains("hide")) { if (sidebar.classList.contains('hide')) {
sidebar.classList.remove("hide") sidebar.classList.remove('hide')
} else { } else {
// if toc-section is open, then close it first // if toc-section is open, then close it first
let toc = document.getElementById("toc-section"); const toc = document.getElementById('toc-section')
if (toc != null && toc.classList.contains("hide")) { if (toc != null && toc.classList.contains('hide')) {
toc.classList.remove("hide"); toc.classList.remove('hide')
} }
// add "hide" class // add "hide" class
sidebar.classList.add("hide"); sidebar.classList.add('hide')
// if it is mobile device. then scroll to top. // if it is mobile device. then scroll to top.
const { isMobile } = getDeviceState(); const { isMobile } = getDeviceState()
if (isMobile && sidebar.classList.contains("hide")) { if (isMobile && sidebar.classList.contains('hide')) {
document.body.scrollTop = 0; document.body.scrollTop = 0
document.documentElement.scrollTop = 0; document.documentElement.scrollTop = 0
if (document.getElementById("hero-area") != null) { if (document.getElementById('hero-area') != null) {
document.getElementById("hero-area").classList.toggle("hide"); document.getElementById('hero-area').classList.toggle('hide')
} }
} }
} }
if (document.getElementById("content-section") != null) { if (document.getElementById('content-section') != null) {
document.getElementById("content-section").classList.toggle("hide"); document.getElementById('content-section').classList.toggle('hide')
} }
} }
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
// bind click event to #sidebar-toggler in navbar-2.html // bind click event to #sidebar-toggler in navbar-2.html
const $toggle = document.getElementById('sidebar-toggler'); const toggle = document.getElementById('sidebar-toggler')
if ($toggle) $toggle.addEventListener('click', toggleSidebar); if (toggle) toggle.addEventListener('click', toggleSidebar)
}); })

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -13,7 +13,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

View file

@ -15,7 +15,7 @@ No content shown here is rendered, all content is based in the template layouts/
Setting a very low sitemap priority will tell search engines this is not important content. Setting a very low sitemap priority will tell search engines this is not important content.
This implementation uses Fusejs, jquery and mark.js This implementation uses Fusejs and mark.js
## Initial setup ## Initial setup

3436
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,6 @@
"highlight.js": "^11.6.0", "highlight.js": "^11.6.0",
"imagesloaded": "^5.0.0", "imagesloaded": "^5.0.0",
"ityped": "^1.0.3", "ityped": "^1.0.3",
"jquery": "^3.6.1",
"katex": "^0.16.3", "katex": "^0.16.3",
"mark.js": "^8.11.1", "mark.js": "^8.11.1",
"mermaid": "^9.2.1", "mermaid": "^9.2.1",

View file

@ -4,6 +4,8 @@
"description": "A [Hugo](https://gohugo.io/) theme for a personal portfolio with minimalist design and responsiveness.", "description": "A [Hugo](https://gohugo.io/) theme for a personal portfolio with minimalist design and responsiveness.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"autoprefixer": "postcss static/css/*/*.css --use autoprefixer -r --no-map" "autoprefixer": "postcss static/css/*/*.css --use autoprefixer -r --no-map"
}, },
"repository": { "repository": {
@ -18,6 +20,13 @@
"homepage": "https://github.com/hugo-toha/toha#readme", "homepage": "https://github.com/hugo-toha/toha#readme",
"devDependencies": { "devDependencies": {
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.6.0",
"eslint-plugin-no-jquery": "^2.7.0",
"eslint-plugin-promise": "^6.1.1",
"postcss": "^8.4.20", "postcss": "^8.4.20",
"postcss-cli": "^8.3.1" "postcss-cli": "^8.3.1"
} }