diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000..fa6d20b --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,12 @@ +env: + browser: true + es2021: true +extends: + - standard + - plugin:no-jquery/all + - prettier +plugins: + - no-jquery +parserOptions: + ecmaVersion: latest + sourceType: module diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 0000000..4f03d60 --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,5 @@ +printWidth: 100 +tabWidth: 2 +semi: false +singleQuote: true +trailingComma: "all" diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..5686ee0 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +nodejs 18.12.1 diff --git a/assets/scripts/application.js b/assets/scripts/application.js new file mode 100644 index 0000000..b6ade04 --- /dev/null +++ b/assets/scripts/application.js @@ -0,0 +1,8 @@ +import 'popper.js' +import 'bootstrap' +import '@fortawesome/fontawesome-free/js/all' + +import './core' +import './features' +import './sections' +import './pages' diff --git a/assets/scripts/core/device.js b/assets/scripts/core/device.js new file mode 100644 index 0000000..797b04e --- /dev/null +++ b/assets/scripts/core/device.js @@ -0,0 +1,36 @@ +let deviceState = { + isMobile: false, + isTablet: false, + isLaptop: false +} + +function detectDeviceState () { + if (window.innerWidth <= 425) { + deviceState = { + isMobile: true, + isTablet: false, + isLaptop: false + } + } else if (window.innerWidth <= 768) { + deviceState = { + isMobile: false, + isTablet: true, + isLaptop: false + } + } else { + deviceState = { + isMobile: false, + isTablet: false, + isLaptop: true + } + } +} + +detectDeviceState() +window.addEventListener('resize', detectDeviceState) + +// returns a copy of the device state +// so other parts of code can't override this. +export function getDeviceState () { + return { ...deviceState } +} diff --git a/assets/scripts/core/index.js b/assets/scripts/core/index.js new file mode 100644 index 0000000..31f9d03 --- /dev/null +++ b/assets/scripts/core/index.js @@ -0,0 +1,2 @@ +export * from './device' +export * from './insertScript' diff --git a/assets/scripts/core/insertScript.js b/assets/scripts/core/insertScript.js new file mode 100644 index 0000000..6fa8bb2 --- /dev/null +++ b/assets/scripts/core/insertScript.js @@ -0,0 +1,14 @@ +export const insertScript = (id, src, onload) => { + // script is already inserted, do nothing + if (document.getElementById(id)) return + + // insert script + const firstScriptTag = document.getElementsByTagName('script')[0] + const scriptTag = document.createElement('script') + scriptTag.id = id + scriptTag.onload = onload + scriptTag.src = src + scriptTag.defer = true + scriptTag.async = true + firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag) +} diff --git a/assets/scripts/features/darkmode/darkreader.js b/assets/scripts/features/darkmode/darkreader.js new file mode 100644 index 0000000..753926c --- /dev/null +++ b/assets/scripts/features/darkmode/darkreader.js @@ -0,0 +1,30 @@ +import { enable, disable, auto, setFetchMethod } from 'darkreader' +import * as params from '@params' + +const darkreader = params?.darkmode?.darkreader || {} +const defaultColorScheme = darkreader.defaultColorScheme || 'system' +const theme = { + brightness: 100, + contrast: 100, + sepia: 0, + ...(darkreader.theme || {}) +} +const fixes = { + invert: ['img[src$=".svg"]'], + ...(darkreader.fixes || {}) +} +setFetchMethod(window.fetch) + +export function setSchemeDark () { + enable(theme, fixes) +} + +export function setSchemeLight () { + disable() +} + +export function setSchemeSystem () { + auto(theme, fixes) +} + +export { defaultColorScheme } diff --git a/assets/scripts/features/darkmode/index.js b/assets/scripts/features/darkmode/index.js new file mode 100644 index 0000000..f207409 --- /dev/null +++ b/assets/scripts/features/darkmode/index.js @@ -0,0 +1,60 @@ +const PERSISTENCE_KEY = 'darkmode:color-scheme' + +async function getService () { + if (process.env.FEATURE_DARKMODE_DARKREADER === '1') { + return await import('./darkreader') + } + + throw Error(' No service defined for feature darkMode.') +} + +window.addEventListener('DOMContentLoaded', async () => { + const menu = document.getElementById('themeMenu') + const $icon = document.getElementById('navbar-theme-icon-svg') + if (menu == null || $icon == null) return + + const btns = menu.getElementsByTagName('a') + const iconMap = Array.from(btns).reduce((map, btn) => { + const $img = btn.getElementsByTagName('img')[0] + map[btn.dataset.scheme] = $img.src + return map + }, {}) + + const { + setSchemeDark, + setSchemeLight, + setSchemeSystem, + defaultColorScheme + } = await getService() + + function loadScheme () { + return localStorage.getItem(PERSISTENCE_KEY) || defaultColorScheme + } + + function saveScheme (scheme) { + localStorage.setItem(PERSISTENCE_KEY, scheme) + } + + function setScheme (newScheme) { + $icon.src = iconMap[newScheme] + + if (newScheme === 'dark') { + setSchemeDark() + } else if (newScheme === 'system') { + setSchemeSystem() + } else { + setSchemeLight() + } + + saveScheme(newScheme) + } + + setScheme(loadScheme()) + + Array.from(menu.getElementsByTagName('a')).forEach((btn) => { + btn.addEventListener('click', () => { + const { scheme } = btn.dataset + setScheme(scheme) + }) + }) +}) diff --git a/assets/scripts/features/embedpdf/index.js b/assets/scripts/features/embedpdf/index.js new file mode 100644 index 0000000..b8146fd --- /dev/null +++ b/assets/scripts/features/embedpdf/index.js @@ -0,0 +1,165 @@ +import { insertScript } from '../../core' + +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' + +class PDFViewer { + constructor (el) { + const { + url, + hidePaginator, + hideLoader, + scale, + pageNum + } = el.dataset + + if (url == null) { + throw new Error('Cannot load PDF! Attribute `data-url` is not set.') + } + + // props + this.url = url + this.hidePaginator = hidePaginator !== 'false' + this.hideLoader = hideLoader !== 'false' + this.scale = scale || 3 + + // initial state + this.pageNum = parseInt(pageNum, 10) || 1 + this.loaded = false + this.pageRendering = false + this.pageNumPending = null + + // DOM elements + this.canvas = el.getElementsByClassName('pdf-canvas')[0] + if (this.canvas == null) { + throw new Error('canvas element not found!') + }; + this.paginator = el.getElementsByClassName('paginator')[0] + this.loadingWrapper = el.getElementsByClassName('loading-wrapper')[0] + this.next = el.getElementsByClassName('next')[0] + this.prev = el.getElementsByClassName('prev')[0] + this.pageNum = el.getElementsByClassName('page-num')[0] + this.pageCount = el.getElementsByClassName('page-count')[0] + + // context + this.ctx = this.canvas.getContext('2d') + + // events + this.next.addEventListener('click', this.handleNextPage.bind(this)) + this.prev.addEventListener('click', this.handlePrevPage.bind(this)) + + this.showPaginator() + this.showLoader() + this.loadPDF() + } + + /** + * If we haven't disabled the loader, show loader and hide canvas + */ + showLoader () { + if (this.hideLoader) return + this.loadingWrapper.style.display = 'flex' + this.canvas.style.display = 'none' + } + + /** + * If we haven't disabled the paginator, show paginator + */ + showPaginator () { + if (this.hidePaginator) return + this.paginator.style.display = 'block' + } + + /** + * Hides loader and shows canvas + */ + showContent () { + this.loadingWrapper.style.display = 'none' + this.canvas.style.display = 'block' + } + + /** + * Asynchronously downloads PDF. + */ + async loadPDF () { + this.pdfDoc = await window.pdfjsLib.getDocument(this.url).promise + + this.pageCount.textContent = this.pdfDoc.numPages + + // If the user passed in a number that is out of range, render the last page. + if (this.pageNum > this.pdfDoc.numPages) { + this.pageNum = this.pdfDoc.numPages + } + + this.renderPage(this.pageNum) + } + + /** + * Get page info from document, resize canvas accordingly, and render page. + * @param num Page number. + */ + async renderPage (num) { + this.pageRendering = true + + const page = await this.pdfDoc.getPage(num) + const viewport = page.getViewport({ scale: this.scale }) + this.canvas.height = viewport.height + this.canvas.width = viewport.width + + // Wait for rendering to finish + await page.render({ + canvasContext: this.ctx, + viewport + }).promise + + this.pageRendering = false + this.showContent() + + if (this.pageNumPending !== null) { + // New page rendering is pending + this.renderPage(this.pageNumPending) + this.pageNumPending = null + } + // Update page counters + this.pageNum.textContent = num + } + + /** + * If another page rendering in progress, waits until the rendering is + * finished. Otherwise, executes rendering immediately. + */ + queueRenderPage (num) { + if (this.pageRendering) { + this.pageNumPending = num + } else { + this.renderPage(num) + } + } + + /** + * Displays previous page. + */ + handlePrevPage () { + if (this.pageNum <= 1) { + return + } + this.pageNum-- + this.queueRenderPage(this.pageNum) + } + + /** + * Displays next page. + */ + handleNextPage () { + if (this.pageNum >= this.pdfDoc.numPages) { + return + } + this.pageNum++ + this.queueRenderPage(this.pageNum) + } +} + +insertScript('pdfjs', PDFJS_BUNDLE, () => { + window.pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_BUNDLE + Array.from(document.getElementsByClassName('pdf-viewer')).forEach(el => new PDFViewer(el)) +}) diff --git a/assets/scripts/features/flowchart/index.js b/assets/scripts/features/flowchart/index.js new file mode 100644 index 0000000..40fd52f --- /dev/null +++ b/assets/scripts/features/flowchart/index.js @@ -0,0 +1,3 @@ +if (process.env.FEATURE_FLOWCHART_MERMAID === '1') { + import('./mermaid') +} diff --git a/assets/scripts/features/flowchart/mermaid.js b/assets/scripts/features/flowchart/mermaid.js new file mode 100644 index 0000000..e8b3e4d --- /dev/null +++ b/assets/scripts/features/flowchart/mermaid.js @@ -0,0 +1,7 @@ +import mermaid from 'mermaid' +import * as params from '@params' + +const mermaidOptions = params.flowchart?.mermaid || {} +const options = Object.assign({}, mermaidOptions, { startOnLoad: true }) + +mermaid.initialize(options) diff --git a/assets/scripts/features/index.js b/assets/scripts/features/index.js new file mode 100644 index 0000000..9682acf --- /dev/null +++ b/assets/scripts/features/index.js @@ -0,0 +1,27 @@ +if (process.env.FEATURE_VIDEOPLAYER === '1') { + import('./videoplayer') +} + +if (process.env.FEATURE_TOC === '1') { + import('./toc') +} + +if (process.env.FEATURE_DARKMODE === '1') { + import('./darkmode') +} + +if (process.env.FEATURE_FLOWCHART === '1') { + import('./flowchart') +} + +if (process.env.FEATURE_SYNTAXHIGHLIGHT === '1') { + import('./syntaxhighlight') +} + +if (process.env.FEATURE_MATH === '1') { + import('./math') +} + +if (process.env.FEATURE_EMBEDPDF === '1') { + import('./embedpdf') +} diff --git a/assets/scripts/features/math/index.js b/assets/scripts/features/math/index.js new file mode 100644 index 0000000..d4c607c --- /dev/null +++ b/assets/scripts/features/math/index.js @@ -0,0 +1,3 @@ +if (process.env.FEATURE_MATH_KATEX === '1') { + import('./katex') +} diff --git a/assets/scripts/features/math/katex.js b/assets/scripts/features/math/katex.js new file mode 100644 index 0000000..6ba0dc8 --- /dev/null +++ b/assets/scripts/features/math/katex.js @@ -0,0 +1,21 @@ +import renderMathInElement from 'katex/contrib/auto-render' +import * as params from '@params' + +const defaultOptions = { + delimiters: [ + { left: '$$', right: '$$', display: true }, + { left: '\\[', right: '\\]', display: true }, + { left: '$', right: '$', display: false }, + { left: '\\(', right: '\\)', display: false } + ] +} + +window.addEventListener('DOMContentLoaded', () => { + renderMathInElement( + document.body, + { + ...defaultOptions, + ...(params.math?.katex || {}) + } + ) +}) diff --git a/assets/scripts/features/syntaxhighlight/hljs.js b/assets/scripts/features/syntaxhighlight/hljs.js new file mode 100644 index 0000000..1835535 --- /dev/null +++ b/assets/scripts/features/syntaxhighlight/hljs.js @@ -0,0 +1,4 @@ +import hljs from 'highlight.js' +import * as params from '@params' + +hljs.highlightAll(params.syntaxhighlight?.hljs) diff --git a/assets/scripts/features/syntaxhighlight/index.js b/assets/scripts/features/syntaxhighlight/index.js new file mode 100644 index 0000000..3356f18 --- /dev/null +++ b/assets/scripts/features/syntaxhighlight/index.js @@ -0,0 +1,3 @@ +if (process.env.FEATURE_SYNTAXHIGHLIGHT_HLJS === '1') { + import('./hljs') +} diff --git a/assets/scripts/features/toc/index.js b/assets/scripts/features/toc/index.js new file mode 100644 index 0000000..56670e7 --- /dev/null +++ b/assets/scripts/features/toc/index.js @@ -0,0 +1,48 @@ +import { getDeviceState } from '../../core' + +// Toggle Table of Contents on click. Here, class "hide" open the toc +function toggleTOC () { + const toc = document.getElementById('toc-section') + if (toc == null) { + return + } + + if (toc.classList.contains('hide')) { + toc.classList.remove('hide') + } else { + // if sidebar-section is open, then close it first + const sidebar = document.getElementById('sidebar-section') + if (sidebar != null && sidebar.classList.contains('hide')) { + sidebar.classList.remove('hide') + } + // add "hide" class + toc.classList.add('hide') + // if it is mobile device. then scroll to top. + const { isMobile } = getDeviceState() + if (isMobile && toc.classList.contains('hide')) { + document.body.scrollTop = 0 + document.documentElement.scrollTop = 0 + } + } + if (document.getElementById('hero-area') != null) { + document.getElementById('hero-area').classList.toggle('hide') + } +} + +window.addEventListener('DOMContentLoaded', () => { + // bind click event to #toc-toggle in navbar-2.html + const toggle = document.getElementById('toc-toggler') + if (toggle) toggle.addEventListener('click', toggleTOC) + + // hide TOC when user clicks on a TOC link. + // Only applies if it's mobile. + const toc = document.getElementById('TableOfContents') + if (toc) { + toc.addEventListener('click', (event) => { + const { isMobile } = getDeviceState() + if (isMobile && event.target.nodeName === 'A') { + toggleTOC() + } + }) + } +}) diff --git a/assets/scripts/features/videoplayer/index.js b/assets/scripts/features/videoplayer/index.js new file mode 100644 index 0000000..57e76e5 --- /dev/null +++ b/assets/scripts/features/videoplayer/index.js @@ -0,0 +1,3 @@ +if (process.env.FEATURE_VIDEOPLAYER_PLYR === '1') { + import('./plyr') +} diff --git a/assets/scripts/features/videoplayer/plyr.js b/assets/scripts/features/videoplayer/plyr.js new file mode 100644 index 0000000..1a08c70 --- /dev/null +++ b/assets/scripts/features/videoplayer/plyr.js @@ -0,0 +1,5 @@ +import Plyr from 'plyr' +import * as params from '@params' + +const options = params.videoplayer?.plyr +window.addEventListener('DOMContentLoaded', () => Plyr.setup('.video-player', options)) diff --git a/assets/scripts/pages/home.js b/assets/scripts/pages/home.js new file mode 100644 index 0000000..4c4bd55 --- /dev/null +++ b/assets/scripts/pages/home.js @@ -0,0 +1,16 @@ +import { init } from 'ityped' + +// =========== Typing Carousel ================ +// get data from hidden ul and set as typing data +document.addEventListener('DOMContentLoaded', () => { + const $ul = document.getElementById('typing-carousel-data')?.children + if ($ul == null || $ul.length === 0) return + + const strings = Array.from($ul).map($el => $el.textContent) + + init('#ityped', { + strings, + startDelay: 200, + loop: true + }) +}) diff --git a/assets/scripts/pages/index.js b/assets/scripts/pages/index.js new file mode 100644 index 0000000..83fb206 --- /dev/null +++ b/assets/scripts/pages/index.js @@ -0,0 +1,4 @@ +import './note' +import './search' +import './single' +import './home' diff --git a/assets/scripts/pages/note.js b/assets/scripts/pages/note.js new file mode 100644 index 0000000..52a6e6b --- /dev/null +++ b/assets/scripts/pages/note.js @@ -0,0 +1,30 @@ +import imagesLoaded from 'imagesloaded' + +document.addEventListener('DOMContentLoaded', function () { + function resizeGridItem (item) { + const grid = document.getElementsByClassName('note-card-holder')[0] + const rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-auto-rows')) + const rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-row-gap')) + const rowSpan = Math.ceil((item.querySelector('.item').getBoundingClientRect().height + rowGap) / (rowHeight + rowGap)) + item.style.gridRowEnd = 'span ' + rowSpan + } + + function resizeAllGridItems () { + const allItems = document.getElementsByClassName('note-card') + for (let x = 0; x < allItems.length; x++) { + resizeGridItem(allItems[x]) + } + } + + function resizeInstance (instance) { + const item = instance.elements[0] + resizeGridItem(item) + } + + window.addEventListener('resize', resizeAllGridItems) + + const allItems = document.getElementsByClassName('note-card') + for (let x = 0; x < allItems.length; x++) { + imagesLoaded(allItems[x], resizeInstance) + } +}) diff --git a/assets/scripts/pages/search.js b/assets/scripts/pages/search.js new file mode 100644 index 0000000..c7b7b73 --- /dev/null +++ b/assets/scripts/pages/search.js @@ -0,0 +1,133 @@ +import Fuse from 'fuse.js' +import Mark from 'mark.js' + +window.addEventListener('DOMContentLoaded', () => { + const summaryInclude = 60 + + const fuseOptions = { + shouldSort: true, + includeMatches: true, + threshold: 0.0, + tokenize: true, + location: 0, + distance: 100, + maxPatternLength: 32, + minMatchCharLength: 1, + keys: [ + { name: 'title', weight: 0.8 }, + { name: 'hero', weight: 0.7 }, + { name: 'summary', weight: 0.6 }, + { name: 'date', weight: 0.5 }, + { name: 'contents', weight: 0.5 }, + { name: 'tags', weight: 0.3 }, + { name: 'categories', weight: 0.3 } + ] + } + + 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' + document.getElementById('search-results')?.append(node) + } + + function executeSearch (searchQuery) { + const url = window.location.href.split('/search/')[0] + '/index.json' + + fetch(url).then(function (data) { + const pages = data + const fuse = new Fuse(pages, fuseOptions) + const results = fuse.search(searchQuery) + + document.getElementById('search-box').value = searchQuery + if (results.length > 0) { + populateResults(results) + } else { + const node = document.createElement('p') + node.textContent = 'No matches found' + document.getElementById('search-results')?.append(node) + } + }) + } + + function populateResults (results) { + results.forEach(function (value, key) { + const contents = value.item.contents + let snippet = '' + const snippetHighlights = [] + if (fuseOptions.tokenize) { + snippetHighlights.push(searchQuery) + } else { + value.matches.forEach(function (mvalue) { + if (mvalue.key === 'tags' || mvalue.key === 'categories') { + snippetHighlights.push(mvalue.value) + } else if (mvalue.key === 'contents') { + const 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 + snippet += contents.substring(start, end) + snippetHighlights.push(mvalue.value.substring(mvalue.indices[0][0], mvalue.indices[0][1] - mvalue.indices[0][0] + 1)) + } + }) + } + + if (snippet.length < 1) { + snippet += contents.substring(0, summaryInclude * 2) + } + // pull template from hugo template definition + const templateDefinition = document.getElementById('search-result-template').innerHTML + // replace values + const output = render(templateDefinition, { + key, + title: value.item.title, + hero: value.item.hero, + date: value.item.date, + summary: value.item.summary, + link: value.item.permalink, + tags: value.item.tags, + categories: value.item.categories, + snippet + }) + + const doc = new DOMParser().parseFromString(output, 'text/html') + document.getElementById('search-results').append(doc) + + snippetHighlights.forEach(function (snipvalue) { + const context = document.getElementById('#summary-' + key) + const instance = new Mark(context) + instance.mark(snipvalue) + }) + }) + } + + function param (name) { + return decodeURIComponent((location.search.split(name + '=')[1] || '').split('&')[0]).replace(/\+/g, ' ') + } + + function render (templateString, data) { + let conditionalMatches, copy + 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 + copy = templateString + while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) { + if (data[conditionalMatches[1]]) { + // valid key, remove conditionals, leave contents. + copy = copy.replace(conditionalMatches[0], conditionalMatches[2]) + } else { + // not valid, remove entire section + copy = copy.replace(conditionalMatches[0], '') + } + } + templateString = copy + // now any conditionals removed we can do simple substitution + let key, find, re + for (key in data) { + find = '\\$\\{\\s*' + key + '\\s*\\}' + re = new RegExp(find, 'g') + templateString = templateString.replace(re, data[key]) + } + return templateString + } +}) diff --git a/assets/scripts/pages/single.js b/assets/scripts/pages/single.js new file mode 100644 index 0000000..717ae6d --- /dev/null +++ b/assets/scripts/pages/single.js @@ -0,0 +1,60 @@ +window.addEventListener('DOMContentLoaded', () => { + // =========== Add anchor to the headers ================ + function addAnchor (element) { + element.innerHTML = `${element.innerHTML}` + } + + const postContent = document.getElementById('post-content') + if (postContent != null) { + const headerTypes = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] + for (let i = 0; i < headerTypes.length; i++) { + const headers = postContent.querySelectorAll(headerTypes[i]) + if (headers) { + headers.forEach(addAnchor) + } + } + } + + // =============== Make TOC Compatible wit Bootstrap Scroll Spy ======== + // add "navbar" class to the "nav" element + const toc = document.getElementById('TableOfContents') + if (toc) { + toc.classList.add('navbar') + // add "nav-pills" class to the "ul" elements + let elems = toc.getElementsByTagName('ul') + for (let i = 0; i < elems.length; i++) { + elems[i].classList.add('nav-pills') + } + // add "nav-item" class to the "li" elements + elems = toc.getElementsByTagName('li') + for (let i = 0; i < elems.length; i++) { + elems[i].classList.add('nav-item') + } + // add "nav-link" class to the "a" elements + elems = toc.getElementsByTagName('a') + for (let i = 0; i < elems.length; i++) { + elems[i].classList.add('nav-link') + } + } + + // add scroll to top button + const btn = document.getElementById('scroll-to-top') + + if(btn) { + window.addEventListener('scroll', function () { + if (window.scrollY > 300) { + btn.classList.add('show') + } else { + btn.classList.remove('show') + } + }) + + btn.addEventListener('click', function (e) { + e.preventDefault() + window.scrollTo({ + top: 0, + behavior: 'smooth' + }) + }) + } +}) diff --git a/assets/scripts/process-shim.js b/assets/scripts/process-shim.js new file mode 100644 index 0000000..02a3a8d --- /dev/null +++ b/assets/scripts/process-shim.js @@ -0,0 +1,3 @@ +export const process = { + env: {} +} diff --git a/assets/scripts/sections/achievements.js b/assets/scripts/sections/achievements.js new file mode 100644 index 0000000..1ba49fc --- /dev/null +++ b/assets/scripts/sections/achievements.js @@ -0,0 +1,220 @@ +import { getDeviceState } from '../core' + +function fourColumRow (gallery, entries, i) { + const entry1 = document.createElement('div') + entry1.classList.add('col-lg-6', 'm-0', 'p-0') + entry1.appendChild(entries[i].cloneNode(true)) + entry1.children[0].classList.add('img-type-1') + gallery.appendChild(entry1) + i++ + + const entry2 = document.createElement('div') + entry2.classList.add('col-lg-3', 'm-0', 'p-0') + entry2.appendChild(entries[i].cloneNode(true)) + entry2.children[0].classList.add('img-type-1') + gallery.appendChild(entry2) + i++ + + const entry3 = document.createElement('div') + entry3.classList.add('col-lg-3', 'm-0', 'p-0') + entry3.appendChild(entries[i].cloneNode(true)) + entry3.children[0].classList.add('img-type-2') + i++ + entry3.appendChild(entries[i].cloneNode(true)) + entry3.children[1].classList.add('img-type-2') + gallery.appendChild(entry3) + i++ +} + +function fourColumnReversedRow (gallery, entries, i) { + const entry1 = document.createElement('div') + entry1.classList.add('col-lg-3', 'm-0', 'p-0') + entry1.appendChild(entries[i].cloneNode(true)) + entry1.children[0].classList.add('img-type-2') + i++ + entry1.appendChild(entries[i].cloneNode(true)) + entry1.children[1].classList.add('img-type-2') + gallery.appendChild(entry1) + i++ + + const entry2 = document.createElement('div') + entry2.classList.add('col-lg-3', 'm-0', 'p-0') + entry2.appendChild(entries[i].cloneNode(true)) + entry2.children[0].classList.add('img-type-1') + gallery.appendChild(entry2) + i++ + + const entry3 = document.createElement('div') + entry3.classList.add('col-lg-6', 'm-0', 'p-0') + entry3.appendChild(entries[i].cloneNode(true)) + entry3.children[0].classList.add('img-type-1') + gallery.appendChild(entry3) + i++ +} + +function threeColumnRow (gallery, entries, i) { + console.log(i) + const entry1 = document.createElement('div') + entry1.classList.add('col-lg-6', 'col-md-6', 'm-0', 'p-0') + entry1.appendChild(entries[i].cloneNode(true)) + entry1.children[0].classList.add('img-type-1') + gallery.appendChild(entry1) + i++ + + const entry2 = document.createElement('div') + entry2.classList.add('col-lg-3', 'col-md-3', 'm-0', 'p-0') + entry2.appendChild(entries[i].cloneNode(true)) + entry2.children[0].classList.add('img-type-1') + gallery.appendChild(entry2) + i++ + + const entry3 = document.createElement('div') + entry3.classList.add('col-lg-3', 'col-md-3', 'm-0', 'p-0') + entry3.appendChild(entries[i].cloneNode(true)) + entry3.children[0].classList.add('img-type-1') + gallery.appendChild(entry3) + i++ +} + +function threeColumnReversedRow (gallery, entries, i) { + const entry1 = document.createElement('div') + entry1.classList.add('col-lg-3', 'col-md-3', 'm-0', 'p-0') + entry1.appendChild(entries[i].cloneNode(true)) + entry1.children[0].classList.add('img-type-1') + gallery.appendChild(entry1) + i++ + + const entry2 = document.createElement('div') + entry2.classList.add('col-lg-3', 'col-md-3', 'm-0', 'p-0') + entry2.appendChild(entries[i].cloneNode(true)) + entry2.children[0].classList.add('img-type-1') + gallery.appendChild(entry2) + i++ + + const entry3 = document.createElement('div') + entry3.classList.add('col-lg-6', 'col-md-3', 'm-0', 'p-0') + entry3.appendChild(entries[i].cloneNode(true)) + entry3.children[0].classList.add('img-type-1') + gallery.appendChild(entry3) + i++ +} + +function twoColumnRow (gallery, entries, i) { + const entry1 = document.createElement('div') + entry1.classList.add('col-6', 'm-0', 'p-0') + entry1.appendChild(entries[i].cloneNode(true)) + entry1.children[0].classList.add('img-type-1') + gallery.appendChild(entry1) + i++ + + const entry2 = document.createElement('div') + entry2.classList.add('col-6', 'm-0', 'p-0') + entry2.appendChild(entries[i].cloneNode(true)) + entry2.children[0].classList.add('img-type-1') + gallery.appendChild(entry2) + i++ +} + +function singleColumnRow (gallery, entries, i) { + const entry1 = document.createElement('div') + entry1.classList.add('col-12', 'm-0', 'p-0') + entry1.appendChild(entries[i].cloneNode(true)) + entry1.children[0].classList.add('img-type-1') + gallery.appendChild(entry1) + i++ +} + +function showAchievements () { + const { isLaptop, isTablet } = getDeviceState() + // show achievements from achievements-holder div + const gallery = document.getElementById('gallery') + if (gallery == null) { + return + } + gallery.innerHTML = '' + const entries = document.getElementById('achievements-holder').children + let len = entries.length + let i = 0 + let rowNumber = 1 + while (i < len) { + if (isLaptop) { + if (i + 4 <= len) { + if (rowNumber % 2) { + fourColumRow(gallery, entries, i) + } else { + fourColumnReversedRow(gallery, entries, i) + } + i += 4 + } else if (i + 3 <= len) { + if (rowNumber % 2) { + threeColumnRow(gallery, entries, i) + } else { + threeColumnReversedRow(gallery, entries, i) + } + i += 3 + } else if (i + 2 <= len) { + twoColumnRow(gallery, entries, i) + i += 2 + } else { + singleColumnRow(gallery, entries, i) + i++ + } + } else if (isTablet) { + if (i + 2 <= len) { + twoColumnRow(gallery, entries, i) + i += 2 + } else { + singleColumnRow(gallery, entries, i) + i++ + } + } else { + singleColumnRow(gallery, entries, i) + i++ + } + rowNumber++ + } + + // show full image on click + const elements = document.getElementsByClassName('achievement-entry') + len = elements.length + for (let i = 0; i < len; i++) { + elements[i].onclick = function () { + const achievements = document.getElementsByClassName('achievement-entry') + const len2 = achievements.length + for (let j = 0; j < len2; j++) { + achievements[j].classList.toggle('hidden') + } + this.classList.toggle('achievement-details') + this.classList.toggle('hidden') + this.parentElement.classList.toggle('col-lg-12') + this.parentElement.classList.toggle('col-md-12') + this.parentElement.classList.toggle('col-sm-12') + if (this.children.SmallImage.hasAttribute('active')) { + const mainLogo = this.children.LargeImage.getAttribute('Style') + this.children.LargeImage.setAttribute('active', true) + this.children.SmallImage.removeAttribute('active') + + this.setAttribute('Style', mainLogo) + } else { + const mainLogo = this.children.SmallImage.getAttribute('Style') + this.children.SmallImage.setAttribute('active', true) + this.children.LargeImage.removeAttribute('active') + this.setAttribute('Style', mainLogo) + } + + if (this.children.caption !== undefined) { + this.children.caption.classList.toggle('hidden') + } + if (this.children['enlarge-icon'] !== undefined) { + this.getElementsByClassName('fa-xmark')[0].classList.toggle('hidden') + this.getElementsByClassName('fa-magnifying-glass-plus')[0].classList.toggle('hidden') + } + if (this.children['achievement-title'] !== undefined) { + this.children['achievement-title'].classList.toggle('hidden') + } + } + } +} + +['DOMContentLoaded', 'resize'].forEach((event) => + document.addEventListener(event, showAchievements)) diff --git a/assets/scripts/sections/education.js b/assets/scripts/sections/education.js new file mode 100644 index 0000000..ea86c7e --- /dev/null +++ b/assets/scripts/sections/education.js @@ -0,0 +1,33 @@ +// Show more rows in the taken courses table +function toggleCourseVisibility (elem) { + // find the courses + const courses = elem.parentNode.getElementsByClassName('course') + if (courses == null) { + return + } + + // toggle hidden-course class from the third elements + for (const course of courses) { + if (course.classList.contains('hidden-course') || course.classList.contains('toggled-hidden-course')) { + course.classList.toggle('hidden-course') + course.classList.add('toggled-hidden-course') + } + } + + // toggle the buttons visibility + const buttonsToToggle = elem.parentNode.getElementsByClassName('show-more-btn') + for (const buttonToToggle of buttonsToToggle) { + buttonToToggle.classList.toggle('hidden') + } +} + +window.addEventListener('DOMContentLoaded', () => { + const els = [ + document.getElementById('show-more-btn'), + document.getElementById('show-less-btn') + ] + + els.filter((el) => el != null).forEach((el) => + el.addEventListener('click', ({ target }) => + toggleCourseVisibility(target))) +}) diff --git a/assets/scripts/sections/index.js b/assets/scripts/sections/index.js new file mode 100644 index 0000000..57dc9fe --- /dev/null +++ b/assets/scripts/sections/index.js @@ -0,0 +1,7 @@ +import './navbar' +import './sidebar' + +import './education' +import './achievements' +import './projects' +import './publications' diff --git a/assets/scripts/sections/navbar.js b/assets/scripts/sections/navbar.js new file mode 100644 index 0000000..0bf75bf --- /dev/null +++ b/assets/scripts/sections/navbar.js @@ -0,0 +1,60 @@ +const updateNavBar = () => { + const topNavbar = document.getElementById('top-navbar') + const navbarToggler = document.getElementById('navbar-toggler') + const themeIcon = document.getElementById('navbar-theme-icon-svg') + + if (window.scrollY > 40) { + 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 + themeIcon?.classList.remove('navbar-icon-svg-dark') + + // get the main logo from hidden img tag + const mainLogo = document.getElementById('main-logo') + if (mainLogo) { + const logoURL = mainLogo.getAttribute('src') + document.getElementById('logo')?.setAttribute('src', logoURL) + } + } else { + topNavbar?.classList.remove('final-navbar', 'shadow') + topNavbar?.classList.add('initial-navbar') + + navbarToggler?.classList.remove('navbar-light') + navbarToggler?.classList.add('navbar-dark') + + // color theme selector a.k.a. dark mode + themeIcon?.classList.add('navbar-icon-svg-dark') + + // get the inverted logo from hidden img tag + const invertedLogo = document.getElementById('inverted-logo') + if (invertedLogo) { + const logoURL = invertedLogo.getAttribute('src') + document.getElementById('logo')?.setAttribute('src', logoURL) + } + } +} + +document.addEventListener('DOMContentLoaded', function () { + // 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 + document.addEventListener('scroll', updateNavBar) + + // Creates a click handler to collapse the navigation when + // anchors in the mobile nav pop up are clicked + const navMain =document.getElementsByClassName('navbar-collapse') + Array.from(navMain).forEach(function(el) { + el.addEventListener('click', function (e) { + if (e.target.tagName === 'A') { + el.classList.add('collapse') + } + }) + }) + + updateNavBar() +}) diff --git a/assets/scripts/sections/projects.js b/assets/scripts/sections/projects.js new file mode 100644 index 0000000..cbe0b79 --- /dev/null +++ b/assets/scripts/sections/projects.js @@ -0,0 +1,19 @@ +import Filterizr from 'filterizr' +import { insertScript } from '../core' + +document.addEventListener('DOMContentLoaded', () => { + // ================== Project cards ===================== + + // setup project filter buttons + const projectCardHolder = document.getElementById('project-card-holder') + if (projectCardHolder != null && projectCardHolder.children.length !== 0) { + // eslint-disable-next-line no-new + new Filterizr('.filtr-projects', { + layout: 'sameWidth', + controlsSelector: '.project-filtr-control' + }) + } +}) + +// dynamically insert github buttons script. +insertScript('github-buttons', 'https://buttons.github.io/buttons.js') diff --git a/assets/scripts/sections/publications.js b/assets/scripts/sections/publications.js new file mode 100644 index 0000000..538f4f8 --- /dev/null +++ b/assets/scripts/sections/publications.js @@ -0,0 +1,13 @@ +import Filterizr from 'filterizr' + +document.addEventListener('DOMContentLoaded', () => { + const publicationCardHolder = document.getElementById('publication-card-holder') + if (publicationCardHolder != null && publicationCardHolder.children.length !== 0) { + // eslint-disable-next-line no-new + new Filterizr('.filtr-publications', { + layout: 'sameWidth', + gridItemsSelector: '.pub-filtr-item', + controlsSelector: '.pub-filtr-control' + }) + } +}) diff --git a/assets/scripts/sections/sidebar.js b/assets/scripts/sections/sidebar.js new file mode 100644 index 0000000..ef90ce2 --- /dev/null +++ b/assets/scripts/sections/sidebar.js @@ -0,0 +1,38 @@ +import { getDeviceState } from '../core/device' + +// Toggle sidebar on click. Here, class "hide" open the sidebar +function toggleSidebar () { + const sidebar = document.getElementById('sidebar-section') + if (sidebar == null) { + return + } + if (sidebar.classList.contains('hide')) { + sidebar.classList.remove('hide') + } else { + // if toc-section is open, then close it first + const toc = document.getElementById('toc-section') + if (toc != null && toc.classList.contains('hide')) { + toc.classList.remove('hide') + } + // add "hide" class + sidebar.classList.add('hide') + // if it is mobile device. then scroll to top. + const { isMobile } = getDeviceState() + if (isMobile && sidebar.classList.contains('hide')) { + document.body.scrollTop = 0 + document.documentElement.scrollTop = 0 + if (document.getElementById('hero-area') != null) { + document.getElementById('hero-area').classList.toggle('hide') + } + } + } + if (document.getElementById('content-section') != null) { + document.getElementById('content-section').classList.toggle('hide') + } +} + +window.addEventListener('DOMContentLoaded', () => { + // bind click event to #sidebar-toggler in navbar-2.html + const toggle = document.getElementById('sidebar-toggler') + if (toggle) toggle.addEventListener('click', toggleSidebar) +}) diff --git a/content/notes/search.bn.md b/content/notes/search.bn.md index 2f67d73..ba89a8a 100644 --- a/content/notes/search.bn.md +++ b/content/notes/search.bn.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.cn.md b/content/notes/search.cn.md index 4586d1f..a694d38 100644 --- a/content/notes/search.cn.md +++ b/content/notes/search.cn.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.de.md b/content/notes/search.de.md index 4586d1f..a694d38 100644 --- a/content/notes/search.de.md +++ b/content/notes/search.de.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.es.md b/content/notes/search.es.md index 77889e8..d2a0d2f 100644 --- a/content/notes/search.es.md +++ b/content/notes/search.es.md @@ -43,7 +43,7 @@ Esto expone los valores en /index.json: por ejemplo, para agregar `categories` \``` ### Editar las opciones de fuse.js para buscar -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.fr.md b/content/notes/search.fr.md index 4586d1f..a694d38 100644 --- a/content/notes/search.fr.md +++ b/content/notes/search.fr.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.hi.md b/content/notes/search.hi.md index 4586d1f..a694d38 100644 --- a/content/notes/search.hi.md +++ b/content/notes/search.hi.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.id.md b/content/notes/search.id.md index 4586d1f..a694d38 100644 --- a/content/notes/search.id.md +++ b/content/notes/search.id.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.it.md b/content/notes/search.it.md index 4586d1f..a694d38 100644 --- a/content/notes/search.it.md +++ b/content/notes/search.it.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.jp.md b/content/notes/search.jp.md index 4586d1f..a694d38 100644 --- a/content/notes/search.jp.md +++ b/content/notes/search.jp.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.ko.md b/content/notes/search.ko.md index 4586d1f..a694d38 100644 --- a/content/notes/search.ko.md +++ b/content/notes/search.ko.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.md b/content/notes/search.md index 0f038c1..d8fe7e9 100644 --- a/content/notes/search.md +++ b/content/notes/search.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -41,7 +41,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.ru.md b/content/notes/search.ru.md index 4586d1f..a694d38 100644 --- a/content/notes/search.ru.md +++ b/content/notes/search.ru.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/notes/search.vn.md b/content/notes/search.vn.md index 4586d1f..a694d38 100644 --- a/content/notes/search.vn.md +++ b/content/notes/search.vn.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.bn.md b/content/posts/search.bn.md index 2f67d73..ba89a8a 100644 --- a/content/posts/search.bn.md +++ b/content/posts/search.bn.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.cn.md b/content/posts/search.cn.md index 4586d1f..a694d38 100644 --- a/content/posts/search.cn.md +++ b/content/posts/search.cn.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.de.md b/content/posts/search.de.md index 4586d1f..a694d38 100644 --- a/content/posts/search.de.md +++ b/content/posts/search.de.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.es.md b/content/posts/search.es.md index 77889e8..d2a0d2f 100644 --- a/content/posts/search.es.md +++ b/content/posts/search.es.md @@ -43,7 +43,7 @@ Esto expone los valores en /index.json: por ejemplo, para agregar `categories` \``` ### Editar las opciones de fuse.js para buscar -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.fr.md b/content/posts/search.fr.md index 4586d1f..a694d38 100644 --- a/content/posts/search.fr.md +++ b/content/posts/search.fr.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.hi.md b/content/posts/search.hi.md index 4586d1f..a694d38 100644 --- a/content/posts/search.hi.md +++ b/content/posts/search.hi.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.id.md b/content/posts/search.id.md index 4586d1f..a694d38 100644 --- a/content/posts/search.id.md +++ b/content/posts/search.id.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.it.md b/content/posts/search.it.md index 4586d1f..a694d38 100644 --- a/content/posts/search.it.md +++ b/content/posts/search.it.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.jp.md b/content/posts/search.jp.md index 4586d1f..a694d38 100644 --- a/content/posts/search.jp.md +++ b/content/posts/search.jp.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.ko.md b/content/posts/search.ko.md index 4586d1f..a694d38 100644 --- a/content/posts/search.ko.md +++ b/content/posts/search.ko.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.md b/content/posts/search.md index 4586d1f..a694d38 100644 --- a/content/posts/search.md +++ b/content/posts/search.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.ru.md b/content/posts/search.ru.md index 4586d1f..a694d38 100644 --- a/content/posts/search.ru.md +++ b/content/posts/search.ru.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/content/posts/search.vn.md b/content/posts/search.vn.md index 4586d1f..a694d38 100644 --- a/content/posts/search.vn.md +++ b/content/posts/search.vn.md @@ -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. -This implementation uses Fusejs, jquery and mark.js +This implementation uses Fusejs and mark.js ## Initial setup @@ -43,7 +43,7 @@ i.e. add `category` \``` ### Edit fuse.js options to Search -`static/js/search.js` +`assets/scripts/pages/search.js` \``` keys: [ "title", diff --git a/layouts/_default/list.html b/layouts/_default/list.html index 15759d3..07a0f00 100644 --- a/layouts/_default/list.html +++ b/layouts/_default/list.html @@ -55,7 +55,3 @@ {{ end }} - -{{ define "scripts" }} - -{{ end }} diff --git a/layouts/_default/search.html b/layouts/_default/search.html index b0d7f86..7c10bcb 100644 --- a/layouts/_default/search.html +++ b/layouts/_default/search.html @@ -66,9 +66,3 @@ {{ end }} - -{{ define "scripts" }} - - - -{{ end }} diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 8b4f608..b7a5a83 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -54,7 +54,7 @@