Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b0f9ca0ae | |||
| 06fd8e8919 | |||
| 02db3d3044 | |||
| fe14b0fbf5 | |||
| d3c2c6d1fc | |||
| 65c71f88ea | |||
| 58ef60dc65 | |||
| 2d43234614 | |||
| dedd6ca0b7 | |||
| 65de557d60 | |||
| 75845423c9 | |||
| bafd3034ae | |||
| 71d2db71d9 | |||
| 657c50d941 | |||
| 1f22a677ca |
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
@@ -0,0 +1,12 @@
|
||||
env:
|
||||
browser: true
|
||||
es2021: true
|
||||
extends:
|
||||
- standard
|
||||
- plugin:no-jquery/all
|
||||
- prettier
|
||||
plugins:
|
||||
- no-jquery
|
||||
parserOptions:
|
||||
ecmaVersion: latest
|
||||
sourceType: module
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout to latest commit
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
|
||||
@@ -9,20 +9,26 @@ jobs:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
# checkout to the commit that has been pushed
|
||||
- uses: actions/checkout@v3.1.0
|
||||
- uses: actions/checkout@v3.2.0
|
||||
with:
|
||||
submodules: true # Fetch Hugo themes (true OR recursive)
|
||||
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
|
||||
|
||||
# install Hugo
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Install node modules
|
||||
run: npm install
|
||||
|
||||
- name: Setup Hugo
|
||||
uses: peaceiris/actions-hugo@v2.6.0
|
||||
with:
|
||||
hugo-version: 'latest'
|
||||
extended: true
|
||||
|
||||
# build website
|
||||
- name: Create Config
|
||||
run: touch config.toml
|
||||
- name: Build
|
||||
run: hugo --minify
|
||||
run: |
|
||||
cd exampleSite
|
||||
hugo --minify
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3.1.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
@@ -10,6 +10,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Create/Update release draft
|
||||
- uses: release-drafter/release-drafter@v5.21.1
|
||||
- uses: release-drafter/release-drafter@v5.22.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -8,6 +8,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# checkout to latest commit
|
||||
- uses: actions/checkout@v3.1.0
|
||||
- uses: actions/checkout@v3.2.0
|
||||
# run markdown linter
|
||||
- uses: gaurav-nelson/github-action-markdown-link-check@1.0.14
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
printWidth: 100
|
||||
tabWidth: 2
|
||||
semi: false
|
||||
singleQuote: true
|
||||
trailingComma: "all"
|
||||
@@ -0,0 +1 @@
|
||||
nodejs 18.12.1
|
||||
@@ -62,6 +62,7 @@ For more details about the features please visit [here](https://toha-guides.netl
|
||||
- Turkish
|
||||
- Arabic (العربية)
|
||||
- Português
|
||||
- Català
|
||||
|
||||
To know more about how to translate your site, please visit [here](https://toha-guides.netlify.app/posts/translation/). Follow, the data and post format from this [example site](https://hugo-toha.github.io).
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import 'popper.js'
|
||||
import 'bootstrap'
|
||||
import '@fortawesome/fontawesome-free/js/all'
|
||||
|
||||
import './core'
|
||||
import './features'
|
||||
import './sections'
|
||||
import './pages'
|
||||
@@ -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 }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './device'
|
||||
export * from './insertScript'
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 }
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -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))
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
if (process.env.FEATURE_FLOWCHART_MERMAID === '1') {
|
||||
import('./mermaid')
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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')
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
if (process.env.FEATURE_MATH_KATEX === '1') {
|
||||
import('./katex')
|
||||
}
|
||||
@@ -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 || {})
|
||||
}
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
import hljs from 'highlight.js'
|
||||
import * as params from '@params'
|
||||
|
||||
hljs.highlightAll(params.syntaxhighlight?.hljs)
|
||||
@@ -0,0 +1,3 @@
|
||||
if (process.env.FEATURE_SYNTAXHIGHLIGHT_HLJS === '1') {
|
||||
import('./hljs')
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
if (process.env.FEATURE_VIDEOPLAYER_PLYR === '1') {
|
||||
import('./plyr')
|
||||
}
|
||||
@@ -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))
|
||||
@@ -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
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
import './note'
|
||||
import './search'
|
||||
import './single'
|
||||
import './home'
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,60 @@
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
// =========== Add anchor to the headers ================
|
||||
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>`
|
||||
}
|
||||
|
||||
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'
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
export const process = {
|
||||
env: {}
|
||||
}
|
||||
@@ -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))
|
||||
@@ -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)))
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
import './navbar'
|
||||
import './sidebar'
|
||||
|
||||
import './education'
|
||||
import './achievements'
|
||||
import './projects'
|
||||
import './publications'
|
||||
@@ -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()
|
||||
})
|
||||
@@ -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')
|
||||
@@ -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'
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -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)
|
||||
})
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
|
||||
baseURL: http://example.org/
|
||||
languageCode: en-us
|
||||
title: Example Site
|
||||
|
||||
module:
|
||||
imports:
|
||||
- path: github.com/hugo-toha/hugo-toha.github.io
|
||||
disable: false
|
||||
mounts:
|
||||
- source: content
|
||||
target: content
|
||||
- source: layouts
|
||||
target: layouts
|
||||
- source: data
|
||||
target: data
|
||||
- source: assets
|
||||
target: assets
|
||||
- source: static
|
||||
target: static
|
||||
- path: github.com/hugo-toha/toha/v4
|
||||
|
||||
# Manage languages
|
||||
# For any more details, you can check the official documentation: https://gohugo.io/content-management/multilingual/
|
||||
languages:
|
||||
en:
|
||||
languageName: English
|
||||
weight: 1
|
||||
bn:
|
||||
languageName: বাংলা
|
||||
weight: 3
|
||||
|
||||
# Force a locale to be use, really useful to develop the application ! Should be commented in production, the "weight" should rocks.
|
||||
# DefaultContentLanguage: bn
|
||||
|
||||
# Allow raw html in markdown file
|
||||
markup:
|
||||
goldmark:
|
||||
renderer:
|
||||
unsafe: true
|
||||
tableOfContents:
|
||||
startLevel: 2
|
||||
endLevel: 6
|
||||
ordered: false
|
||||
|
||||
# At least HTML and JSON are required for the main HTML content and
|
||||
# client-side JavaScript search
|
||||
outputs:
|
||||
home:
|
||||
- HTML
|
||||
- RSS
|
||||
- JSON
|
||||
|
||||
# Enable global emoji support
|
||||
enableEmoji: true
|
||||
|
||||
# Site parameters
|
||||
params:
|
||||
# Background image of the landing page
|
||||
background: /images/site/background.jpg
|
||||
|
||||
# Provide logos for your site. The inverted logo will be used in the initial
|
||||
# transparent navbar and the main logo will be used in the non-transparent navbar.
|
||||
logo:
|
||||
main: /images/site/main-logo.png
|
||||
inverted: /images/site/inverted-logo.png
|
||||
favicon: /images/site/favicon.png
|
||||
|
||||
# GitHub repo of your site
|
||||
gitRepo: https://github.com/hugo-toha/hugo-toha.github.io
|
||||
# Default branch of your Git repo
|
||||
gitBranch: main
|
||||
|
||||
# Configure the number of section title visible in the top navbar
|
||||
topNavbar:
|
||||
maxVisibleSections: 5
|
||||
|
||||
# Configure various features of this theme
|
||||
features:
|
||||
|
||||
# Enable dark theme
|
||||
darkMode:
|
||||
enable: false
|
||||
services:
|
||||
darkreader:
|
||||
defaultColorScheme: system # options are 'system', 'dark', 'light'
|
||||
fixes:
|
||||
invert: ['img[src$=".svg"]'] # inverts svg colors.
|
||||
theme:
|
||||
brightness: 100
|
||||
contrast: 100
|
||||
sepia: 0
|
||||
|
||||
# Enable and configure portfolio
|
||||
portfolio:
|
||||
enable: true
|
||||
|
||||
# Enable and configure blog posts
|
||||
blog:
|
||||
enable: true
|
||||
# Share post on different social media
|
||||
shareButtons:
|
||||
facebook: true
|
||||
twitter: true
|
||||
linkedin: true
|
||||
reddit: true
|
||||
whatsapp: true
|
||||
email: true
|
||||
# tumblr: true
|
||||
# pocket: true
|
||||
# diaspora: true
|
||||
# mastodon: true
|
||||
|
||||
# Enable & configure "Notes" features
|
||||
notes:
|
||||
enable: true
|
||||
|
||||
# Enable comment feature. There, should be only one of them.
|
||||
comment:
|
||||
enable: false
|
||||
services:
|
||||
disqus:
|
||||
shortName: toha-example-site
|
||||
# valine:
|
||||
# appId: HTV6askWxVo3vOxlqjjaq2hd-MsYXbMMI
|
||||
# appKey: pVrT3C85KGIuk27t07eh6bUC
|
||||
# avatar: retro
|
||||
# placeholder: Share your thought.
|
||||
# lang: en
|
||||
# recordIP: true
|
||||
# enableQQ: true
|
||||
# utteranc:
|
||||
# repo: github.com/hugo-toha/hugo-toha.github.io
|
||||
# issueTerm: title
|
||||
# theme: github-light
|
||||
# giscus:
|
||||
# repo: your-repo/name
|
||||
# repoID: your-repo-id
|
||||
# category: your-category
|
||||
# categoryID: your-category-id
|
||||
# theme: light
|
||||
# map: url
|
||||
# reaction: 1
|
||||
# metadata: 0
|
||||
# inputPosition: bottom
|
||||
# crossOrigin: anonymous
|
||||
# commento:
|
||||
# serverURL: cdn.commento.io
|
||||
# autoInit: true
|
||||
# hideDeleted: false
|
||||
|
||||
# Enable Analytics
|
||||
analytics:
|
||||
enabled: false
|
||||
services:
|
||||
# Google Analytics
|
||||
google:
|
||||
id: G-H4LBG7NDFZ
|
||||
# # CounterDev
|
||||
# counterDev:
|
||||
# id: <your counterdev id>
|
||||
# # GoatCounter
|
||||
# goatCounter:
|
||||
# code: <your goat counter code>
|
||||
# # Matomo / Piwik
|
||||
# matomo:
|
||||
# instance: matomo.example.com
|
||||
# siteId: 1 # Or any other number
|
||||
|
||||
# Enable Support
|
||||
support:
|
||||
enable: false
|
||||
services:
|
||||
kofi:
|
||||
user: hossainemruz
|
||||
text: Tip Me
|
||||
textColor: '#f9fafc'
|
||||
backgroundColor: '#248aaa'
|
||||
# buymeacoffee:
|
||||
# user: <your buymeacoffee.com user>
|
||||
# text: Support me on Buy me a coffee!
|
||||
# info: Buy me a coffee!
|
||||
# color: '#FFDD00'
|
||||
|
||||
# specify whether you want to show Table of Contents in reading page
|
||||
toc:
|
||||
enable: true
|
||||
|
||||
# Show tags under the post title
|
||||
tags:
|
||||
enable: true
|
||||
|
||||
# Specify whether to show flag in the language selector. Default is true.
|
||||
flags:
|
||||
enable: true
|
||||
# # If you want to use different country flag for a language, specify them here.
|
||||
# flagOverwrites:
|
||||
# - languageCode: en
|
||||
# countryCode: us
|
||||
|
||||
# Enable this to use `embed-pdf` shortcode.
|
||||
embedpdf:
|
||||
enable: false
|
||||
|
||||
# Enable this to create flowcharts using shortcodes.
|
||||
flowchart:
|
||||
enable: false
|
||||
services:
|
||||
# Uncomment for `mermaid` shortcode.
|
||||
mermaid:
|
||||
# For config options, see: https://mermaid-js.github.io/mermaid/#/Setup?id=configuration
|
||||
# theme: dark
|
||||
|
||||
# Enable this to create mathematic expressions using `$$` blocks
|
||||
math:
|
||||
enable: false
|
||||
services:
|
||||
# https://katex.org/docs/autorender.html#api for more configurations
|
||||
katex:
|
||||
delimiters:
|
||||
- left: $$
|
||||
right: $$
|
||||
display: true
|
||||
- left: \\[
|
||||
right: \\]
|
||||
display: true
|
||||
- left: $
|
||||
right: $
|
||||
display: false
|
||||
- left: \\(
|
||||
right: \\)
|
||||
display: false
|
||||
|
||||
# Enable to use custom syntax highlight
|
||||
# Please note, Hugo comes with it's own html based syntax highlighter.
|
||||
# Your code block will still be syntax highlighted by hugo.
|
||||
# For more details: https://gohugo.io/content-management/syntax-highlighting/
|
||||
# To disable Hugo's builtin syntax highlight,
|
||||
# see: https://gohugo.io/getting-started/configuration-markup#highlight
|
||||
# ```
|
||||
# # config.yaml
|
||||
# markup:
|
||||
# # this disables hugo's syntax highlighting.
|
||||
# codeFences: false
|
||||
# ```
|
||||
syntaxHighlight:
|
||||
enable: true
|
||||
services:
|
||||
hljs:
|
||||
# see: https://highlightjs.readthedocs.io/en/latest/api.html#configure
|
||||
noHighlightRe: /^no-highlight$/i
|
||||
|
||||
# Enable to use `video-player` shortcode
|
||||
videoPlayer:
|
||||
enable: false
|
||||
services:
|
||||
# convert .js-player class into video player via https://plyr.io/
|
||||
# Can play HTML5 Video, Audio, Youtube, Vimeo.
|
||||
# For more info on setup: https://github.com/sampotts/plyr#quick-setup
|
||||
plyr:
|
||||
# options doc: https://github.com/sampotts/plyr#options
|
||||
# fullscreen: true
|
||||
|
||||
|
||||
# Provide footer configuration.
|
||||
footer:
|
||||
enable: true
|
||||
# You can provide your custom footer template using this option.
|
||||
# Put your template in "layouts/partials" folder of your repo.
|
||||
template: footer.html
|
||||
# Show/hide navigation in the footer. Default is "true".
|
||||
navigation:
|
||||
enable: true
|
||||
# show custom menus in the footer
|
||||
customMenus: true
|
||||
# Show/hide "Contact Me" section in the footer. Default is "true".
|
||||
contactMe:
|
||||
enable: true
|
||||
# Show/hide credentials section in the footer. Default is "true".
|
||||
credentials:
|
||||
enable: true
|
||||
|
||||
# Show/hide newsletter section in the footer. Default is "true".
|
||||
# Currently, it supports "mailchimp".
|
||||
newsletter:
|
||||
enable: true
|
||||
provider: mailchimp
|
||||
mailchimpURL: https://github.us1.list-manage.com/subscribe/post?u=19de52a4603135aae97163fd8&id=094a24c76e
|
||||
|
||||
# Show/hide disclaimer notice in the footer. Default is "false".
|
||||
disclaimer:
|
||||
enable: true
|
||||
@@ -0,0 +1,7 @@
|
||||
module github.com/hugo-toha/toha/exampleSite
|
||||
|
||||
go 1.19
|
||||
|
||||
require github.com/hugo-toha/hugo-toha.github.io v0.0.0-20221228191121-007f31838bd6 // indirect
|
||||
|
||||
replace github.com/hugo-toha/toha/v4 => ../../toha
|
||||
@@ -0,0 +1,2 @@
|
||||
github.com/hugo-toha/hugo-toha.github.io v0.0.0-20221228191121-007f31838bd6 h1:TPFhOZAnuH4wjLIdzimswCRa2qCcc1teKVTatADJU2g=
|
||||
github.com/hugo-toha/hugo-toha.github.io v0.0.0-20221228191121-007f31838bd6/go.mod h1:OMMaP9Hh9NsKd41lVIazBQRPa0s6Z57AfJoY3DcCNNY=
|
||||
@@ -1,7 +1,3 @@
|
||||
module github.com/hugo-toha/toha
|
||||
module github.com/hugo-toha/toha/v4
|
||||
|
||||
go 1.12
|
||||
|
||||
// require(
|
||||
|
||||
// )
|
||||
go 1.19
|
||||
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
# More documentation here: https://github.com/nicksnyder/go-i18n
|
||||
[home]
|
||||
other = "Inici"
|
||||
|
||||
[posts]
|
||||
other = "Publicacions"
|
||||
|
||||
[toc_heading]
|
||||
other = "Taula de Continguts"
|
||||
|
||||
[tags]
|
||||
other = "Etiquetes"
|
||||
|
||||
[categories]
|
||||
other = "Categories"
|
||||
|
||||
[at]
|
||||
other = "a"
|
||||
|
||||
[resume]
|
||||
other = "El meu currículum"
|
||||
|
||||
[navigation]
|
||||
other = "Navegació"
|
||||
|
||||
[contact_me]
|
||||
other = "Contacta'm:"
|
||||
|
||||
[email]
|
||||
other = "Correu electrònic"
|
||||
|
||||
[phone]
|
||||
other = "Telèfon"
|
||||
|
||||
[newsletter_text]
|
||||
other = "Subscriure's"
|
||||
|
||||
[newsletter_input_placeholder]
|
||||
other = "Entra l'email"
|
||||
|
||||
[newsletter_warning]
|
||||
other = "Al entrar la vostra direcció de correu electrònic, esteu acceptant rebre el butlletí d'aquest lloc web."
|
||||
|
||||
[submit]
|
||||
other = "Enviar"
|
||||
|
||||
[hugoAttributionText]
|
||||
other = "Impulsat per"
|
||||
|
||||
[prev]
|
||||
other = "Anterior"
|
||||
|
||||
[next]
|
||||
other = "Següent"
|
||||
|
||||
[share_on]
|
||||
other = "Compartir a"
|
||||
|
||||
[improve_this_page]
|
||||
other = "Millorar aquesta pàgina"
|
||||
|
||||
[out_of]
|
||||
other = "de"
|
||||
|
||||
[publications]
|
||||
other = "Publicacions"
|
||||
|
||||
[taken_courses]
|
||||
other = "Cursos realitzats"
|
||||
|
||||
[course_name]
|
||||
other = "Nom del curs"
|
||||
|
||||
[total_credit]
|
||||
other = "Crèdits Totals"
|
||||
|
||||
[obtained_credit]
|
||||
other = "Crèdits Obtinguts"
|
||||
|
||||
[extracurricular_activities]
|
||||
other = "Activitats Extracurriculars"
|
||||
|
||||
[show_more]
|
||||
other = "Mostra'n més"
|
||||
|
||||
[show_less]
|
||||
other = "Mostra'n menys"
|
||||
|
||||
[responsibilities]
|
||||
other = "Responsabilitats:"
|
||||
|
||||
[present]
|
||||
other = "Actualitat"
|
||||
|
||||
[comments_javascript]
|
||||
other = "Si us plau, activa Javascript per mostrar"
|
||||
|
||||
[comments_by]
|
||||
other = "Comentaris per"
|
||||
|
||||
[read]
|
||||
other = "Llegir"
|
||||
|
||||
[project_star]
|
||||
other = "Preferit"
|
||||
|
||||
[project_details]
|
||||
other = "Detalls"
|
||||
|
||||
[err_404]
|
||||
other = "La pàgina que està cercant encara no existeix."
|
||||
|
||||
[more]
|
||||
other = "Més"
|
||||
|
||||
[view_certificate]
|
||||
other = "Mostrar Certificat"
|
||||
|
||||
[notes]
|
||||
other = "Notes"
|
||||
|
||||
[disclaimer_text]
|
||||
other = "Avís de Responsabilitat"
|
||||
|
||||
[search]
|
||||
other = "Cerca"
|
||||
+2
-2
@@ -6,7 +6,7 @@ other = "Anasayfa"
|
||||
other = "Gönderiler"
|
||||
|
||||
[toc_heading]
|
||||
other = "İçerik Tablous"
|
||||
other = "İçerik Tablosu"
|
||||
|
||||
[tags]
|
||||
other = "Etiketler"
|
||||
@@ -108,7 +108,7 @@ other = "Star"
|
||||
other = "Detaylar"
|
||||
|
||||
[err_404]
|
||||
other = "Aradığınız sayfa bulunmamakta."
|
||||
other = "Aradığınız sayfa bulunamadı."
|
||||
|
||||
[more]
|
||||
other = "Devamını Göster"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener"{{ end }}>{{ .Text | safeHTML }}</a>
|
||||
@@ -55,7 +55,3 @@
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{ define "scripts" }}
|
||||
<script src="{{ "/js/list.js" | relURL }}"></script>
|
||||
{{ end }}
|
||||
|
||||
@@ -66,9 +66,3 @@
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{ define "scripts" }}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/3.2.0/fuse.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/jquery.mark.min.js"></script>
|
||||
<script src="{{ "/js/search.js" | absURL }}"></script>
|
||||
{{ end }}
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<div class="title">
|
||||
<h1>{{ .Page.Title }}</h1>
|
||||
</div>
|
||||
{{ if site.Params.enableTags }}
|
||||
{{ if site.Params.features.tags.enable }}
|
||||
<div class="taxonomy-terms">
|
||||
<ul style="padding-left: 0;">
|
||||
{{ range .Params.tags }}
|
||||
@@ -158,7 +158,7 @@
|
||||
|
||||
<!----- Add comment support ----->
|
||||
{{ if site.Params.features.comment.enable }}
|
||||
{{ partial "comments.html" site.Params.features.comment }}
|
||||
{{ partial "comments.html" site.Params.features.comment.services }}
|
||||
{{ end }}
|
||||
|
||||
<!-- Keep backward compatibility with old config.yaml -->
|
||||
@@ -179,7 +179,7 @@
|
||||
|
||||
{{ define "toc" }}
|
||||
<section class="toc-section" id="toc-section">
|
||||
{{ if and site.Params.enableTOC ( .Params.enableTOC | default true ) }}
|
||||
{{ if and site.Params.features.toc.enable ( .Params.enableTOC | default true ) }}
|
||||
<div class="toc-holder">
|
||||
<h5 class="text-center pl-3">{{ i18n "toc_heading" }}</h5>
|
||||
<hr>
|
||||
@@ -192,20 +192,9 @@
|
||||
{{ end }}
|
||||
|
||||
{{ define "scripts" }}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.1/highlight.min.js"></script>
|
||||
<script src="{{ "/js/single.js" | relURL }}"></script>
|
||||
<script>
|
||||
hljs.initHighlightingOnLoad();
|
||||
</script>
|
||||
|
||||
<!-------------- Enable Math support for this page ---------------->
|
||||
{{ if .Params.math }}
|
||||
{{ if site.Params.features.math.enable }}
|
||||
{{ partial "math.html" . }}
|
||||
{{ end }}
|
||||
|
||||
<!-------------- Enable mermaid support for this page ---------------->
|
||||
{{ if .Params.mermaid }}
|
||||
{{ partial "mermaid.html" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
|
||||
@@ -56,7 +56,3 @@
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{ define "scripts" }}
|
||||
<script src="{{ "/js/list.js" | relURL }}"></script>
|
||||
{{ end }}
|
||||
|
||||
@@ -75,12 +75,6 @@
|
||||
<!--- ADD COMMON SCRIPTS --------------->
|
||||
{{ partial "scripts.html" . }}
|
||||
|
||||
<!--- ADD INDEX PAGE SPECIFIC SCRIPTS -->
|
||||
<script src="{{ "/js/itype.min.js" | relURL }}"></script>
|
||||
<script src="{{ "/js/github-button.js" | relURL }}"></script>
|
||||
<script src="{{ "/js/home.js" | relURL }}"></script>
|
||||
<script src="{{ "/js/jquery.filterizr.min.js" | relURL }}"></script>
|
||||
|
||||
<!------ ADD SUPPORT LINKS -------->
|
||||
{{- partial "misc/support.html" . -}}
|
||||
|
||||
|
||||
@@ -57,13 +57,7 @@
|
||||
{{ end }}
|
||||
|
||||
{{ define "scripts" }}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.1/highlight.min.js"></script>
|
||||
<script src="{{ "/js/imagesloaded.pkgd.min.js" | relURL }}"></script>
|
||||
<script src="{{ "/js/note.js" | relURL }}"></script>
|
||||
<script>
|
||||
hljs.initHighlightingOnLoad();
|
||||
</script>
|
||||
{{ if .Params.math }}
|
||||
{{ if site.Params.features.math.enable }}
|
||||
{{ partial "math.html" . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -47,13 +47,7 @@
|
||||
{{ end }}
|
||||
|
||||
{{ define "scripts" }}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.1/highlight.min.js"></script>
|
||||
<script src="{{ "/js/imagesloaded.pkgd.min.js" | relURL }}"></script>
|
||||
<script src="{{ "/js/note.js" | relURL }}"></script>
|
||||
<script>
|
||||
hljs.initHighlightingOnLoad();
|
||||
</script>
|
||||
{{ if .Params.math }}
|
||||
{{ if site.Params.features.math.enable }}
|
||||
{{ partial "math.html" . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<!-- Add Analytics if enabled in configuration -->
|
||||
{{ with site.Params.features.analytics }}
|
||||
{{ if .enabled }}
|
||||
{{ with .services }}
|
||||
<!-- Google Analytics -->
|
||||
{{ with .google }}
|
||||
{{ $privacyConfig:= dict (slice "Site" "Config" "Privacy" "GoogleAnalytics") $.Site.Config.Privacy.GoogleAnalytics }}
|
||||
@@ -21,7 +22,7 @@
|
||||
<script
|
||||
data-goatcounter="https://{{ .code }}.goatcounter.com/count"
|
||||
async
|
||||
src="/js/goat-counter.js"
|
||||
src="//gc.zgo.at/count.js"
|
||||
></script>
|
||||
{{ end }}
|
||||
|
||||
@@ -42,6 +43,7 @@
|
||||
})();
|
||||
</script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
@@ -42,8 +42,9 @@
|
||||
{{ end }}
|
||||
<div class="project-btn-holder">
|
||||
{{ if .repo }}
|
||||
<!-- Place this tag where you want the button to render. -->
|
||||
<a
|
||||
class="github-button-inactive project-btn"
|
||||
class="github-button project-btn d-none"
|
||||
href="{{ .repo }}"
|
||||
data-icon="octicon-standard"
|
||||
data-show-count="true"
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
<form method='post' action='https://blogtrottr.com'>
|
||||
<div class="form-group">
|
||||
<input type='email' class="form-control" name='btr_email' placeholder="{{ i18n "newsletter_input_placeholder" }}"/><br />
|
||||
<input type='hidden' name='btr_url' value='{{ "" | absLangURL }}index.xml' />
|
||||
<input type='hidden' name='btr_url' value='{{ "" | absLangURL }}/index.xml' />
|
||||
<input type='hidden' name='schedule_type' value='1' />
|
||||
<small id="emailHelp" class="form-text text-muted">{{ i18n "newsletter_warning" }}</small>
|
||||
<button type="submit" class="btn btn-info"> {{ i18n "submit" }} </button>
|
||||
|
||||
@@ -7,17 +7,14 @@
|
||||
<link rel="stylesheet" href="{{ "/css/layouts/main.css" | relURL }}"/>
|
||||
<link rel="stylesheet" href="{{ "/css/navigators/navbar.css" | relURL }}"/>
|
||||
<link rel="stylesheet" href="{{ "/css/plyr.css" | relURL }}"/>
|
||||
{{ if ne site.Params.showFlags false }}
|
||||
{{ if ne site.Params.features.flags.enable false }}
|
||||
<link rel="stylesheet" href="{{ "/css/flag-icon.min.css" | relURL }}"/>
|
||||
{{ end }}
|
||||
<!--=================== fonts ==============================-->
|
||||
<link rel="stylesheet" href="{{ "/google-fonts/Mulish/mulish.css" | relURL }}"/>
|
||||
|
||||
<!--=================== icons ==============================-->
|
||||
<link rel="stylesheet" href="{{ "/fontawesome/css/all.min.css" | relURL }}"/>
|
||||
|
||||
<!--=================== dark mode ==========================-->
|
||||
{{ if site.Params.darkMode.enable }}
|
||||
{{ if site.Params.features.darkMode.enable }}
|
||||
<link rel="stylesheet" href="{{ "/css/colortheme/colortheme.css" | relURL }}"/>
|
||||
{{ end }}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
|
||||
{{/* if the user specify a country code for a language via "params.flagOverwrites" field, then use it. */}}
|
||||
{{ range site.Params.flagOverwrites }}
|
||||
{{ range site.Params.features.flags.flagOverwrites }}
|
||||
{{ if eq $languageCode .languageCode }}
|
||||
{{ $countryCode = .countryCode }}
|
||||
{{ end }}
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
{{/*
|
||||
|
||||
## Overview
|
||||
|
||||
This helper returns options dictionary used to configure ESBuild.
|
||||
The following configurations are set:
|
||||
|
||||
* Enable JS minification.
|
||||
* Enable source map if not building for production.
|
||||
* Prepare `process.env.<ENVIRONMENT VARIABLE>` defines based on enabled features.
|
||||
This allows ESBuild to optimize JS bundle size by removing code related
|
||||
to unused features.
|
||||
* Added `process-shim.js` so `process.env` is defined.
|
||||
This way we don't have to explicitly specify every environment
|
||||
variable via `defines` value.
|
||||
* Prepare `params` for feature and service configs used in JS.
|
||||
|
||||
For more details on ESBuild configuration, see: https://gohugo.io/hugo-pipes/js/
|
||||
|
||||
## Detailed Concepts
|
||||
|
||||
### `feature` and `service`
|
||||
|
||||
Features configured in site wide `config.yml` file under `params.features` section.
|
||||
A **feature** provides a certain functionality to the user via one or more services.
|
||||
A feature be can enabled or disabled.
|
||||
|
||||
A **service** is a 3rd party service, or JS library that implements a feature.
|
||||
|
||||
For example, `analytics` is considered a feature.
|
||||
There are many services that can provide this feature, to name a few:
|
||||
|
||||
* Google Analytics
|
||||
* Counter.Dev
|
||||
* GoatCounter
|
||||
|
||||
To maximize extendibility and therefore usefulness as an open source project,
|
||||
it is important to define a standard interface that is easy to understand,
|
||||
configure, and extend.
|
||||
|
||||
In this file, I took the liberty of standardizing this interface under `params.features`.
|
||||
Please note that this breaks compatibility with previous versions of `config.yaml`.
|
||||
I will provide sample `config.yaml` files with fully documented features, as well as
|
||||
documentation on migrating the `config.yaml` file to the new standard.
|
||||
|
||||
Here is a sample config file for the new `params.features` section. Notice that each `service`
|
||||
is a dictionary with `enable` and `services` key. `services` is a dictionary with each key
|
||||
corresponding to a concrete service, and value as configuration / settings. In the case of
|
||||
services that need no configuration, an empty dictionary is created.
|
||||
|
||||
```yml
|
||||
params:
|
||||
features:
|
||||
|
||||
# This is the `analytics` feature
|
||||
analytics:
|
||||
# This feature is enabled
|
||||
enable: true
|
||||
# List of services to enable
|
||||
services:
|
||||
|
||||
# Google Analytics is enabled
|
||||
google:
|
||||
# settings for Google Analytics
|
||||
id: G-xxxxx
|
||||
|
||||
# # Counter Dev is disabled
|
||||
# counterDev:
|
||||
# id: foo
|
||||
# name: bar
|
||||
|
||||
# The `darkMode` feature
|
||||
darkmode:
|
||||
enable: true
|
||||
services:
|
||||
# darkmode is realized by using DarkReader library
|
||||
darkreader:
|
||||
# options are 'system', 'dark', 'light'
|
||||
defaultColorScheme: system
|
||||
# For all available options, see `interface DynamicThemeFix`:
|
||||
# https://github.com/darkreader/darkreader/blob/main/index.d.ts#L125
|
||||
fixes:
|
||||
invert: ['img[src$=".svg"]'] # inverts svg colors.
|
||||
# For all available options, see `interface Theme` in:
|
||||
# https://github.com/darkreader/darkreader/blob/main/index.d.ts#L45
|
||||
theme:
|
||||
brightness: 100
|
||||
contrast: 100
|
||||
sepia: 0
|
||||
```
|
||||
|
||||
This helper will convert the above config into the following env vars:
|
||||
|
||||
* `FEATURE_ANALYTICS=1`
|
||||
* `FEATURE_ANALYTICS_GOOGLE=1`
|
||||
* `FEATURE_DARKMODE=1`
|
||||
* `FEATURE_DARKMODE_DARKREADER=1`
|
||||
|
||||
In JS, you can use it like this:
|
||||
|
||||
```js
|
||||
import * as params from '@params';
|
||||
|
||||
if (process.env.FEATURE_ANALYTICS) {
|
||||
// Do things to enable this feature here
|
||||
|
||||
if (process.env.FEATURE_ANALYTICS_GOOGLE) {
|
||||
// Do things things to enable google analytics
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can also access service configs via params:
|
||||
|
||||
```js
|
||||
import * as params from '@params';
|
||||
|
||||
console.log(params);
|
||||
```
|
||||
|
||||
You will see console output like below. Note, each service configuration is
|
||||
namespaced by their corresponding feature.
|
||||
|
||||
```json
|
||||
{
|
||||
"analytics": {
|
||||
"google": {
|
||||
"id": "G-xxxxx"
|
||||
}
|
||||
},
|
||||
"darkmode": {
|
||||
"darkreader": {
|
||||
"defaultColorScheme": "system",
|
||||
"fixes": {
|
||||
"invert": "['img[src$=\".svg\"]']"
|
||||
},
|
||||
"theme": {
|
||||
"brightness": 100,
|
||||
"contrast": 100,
|
||||
"sepia": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
*/}}
|
||||
|
||||
{{/* Holds all the feature flag environment variables for `process.env.*` in JS land */}}
|
||||
{{ $defines := dict }}
|
||||
|
||||
{{/* Holds all the feature configuration variables exposed to JS side */}}
|
||||
{{ $params := dict }}
|
||||
|
||||
{{/* set NODE_ENV depending on if we are building for production use. */}}
|
||||
{{ $defines = $defines | merge (dict
|
||||
"process.env.NODE_ENV" (cond hugo.IsProduction `"production"` `"development"` )
|
||||
)}}
|
||||
|
||||
{{/* Go through each feature defined in our config.yml/config.toml/config.json file. */}}
|
||||
{{ range $feature, $featureDef := site.Params.features }}
|
||||
{{/* Initialize a dictionary that will hold all service configs for this specific feature */}}
|
||||
{{ $featureParams := dict }}
|
||||
|
||||
{{ with $featureDef }}
|
||||
{{/* convert feature name to uppercase and remove '_', e.g. `darkMode` becomes `DARKMODE` */}}
|
||||
{{ $featureName := replace $feature "_" "" | upper }}
|
||||
|
||||
{{/* The feature is enabled if the `enable` key is absent, or is set to `true` */}}
|
||||
{{ $featureEnabled := or (not (isset . "enable")) .enable }}
|
||||
|
||||
{{/* Sets `FEATURE_<FEATURE_NAME>` env var to "1" or "0" depending on if the feature is enabled. */}}
|
||||
{{ $defines = $defines | merge (dict
|
||||
(printf "process.env.FEATURE_%s" $featureName) (cond $featureEnabled `'1'` `'0'`)
|
||||
) }}
|
||||
|
||||
{{ if $featureEnabled }}
|
||||
{{/* Loop through each service under this feature */}}
|
||||
{{ range $service, $config := .services }}
|
||||
{{/*
|
||||
We assume all services are enabled. To disable a service,
|
||||
simply comment it out from `config.yaml`.
|
||||
*/}}
|
||||
|
||||
{{/* Convert name to all uppercase, removing underscore */}}
|
||||
{{ $serviceName := replace $service "_" "" | upper }}
|
||||
|
||||
{{/* let JS side know this service is enabled */}}
|
||||
{{ $defines = $defines | merge (dict
|
||||
(printf "process.env.FEATURE_%s_%s" $featureName $serviceName) `'1'`
|
||||
) }}
|
||||
|
||||
{{/* add service configuration to feature params */}}
|
||||
{{ $featureParams = $featureParams | merge (dict $service $config) }}
|
||||
{{ end }}
|
||||
|
||||
{{/* add feature params to top level params */}}
|
||||
{{ $params = $params | merge (dict $feature $featureParams) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{
|
||||
return dict
|
||||
"defines" $defines
|
||||
"params" $params
|
||||
"minify" true
|
||||
"sourceMap" (cond hugo.IsProduction "" "inline")
|
||||
"inject" "scripts/process-shim.js"
|
||||
}}
|
||||
@@ -0,0 +1,5 @@
|
||||
{{- $options := partial "helpers/get-esbuild-options.html" -}}
|
||||
{{- $options = $options | merge (dict "targetPath" "application.js") -}}
|
||||
{{- $app := resources.Get "scripts/application.js" -}}
|
||||
{{- $bundle := $app | js.Build $options | fingerprint -}}
|
||||
<script src="{{ $bundle.RelPermalink }}" integrity="{{ $bundle.Data.Integrity }}" defer></script>
|
||||
@@ -1,15 +1 @@
|
||||
<link rel="stylesheet" href="{{ "/katex/katex.min.css" | relURL }}">
|
||||
<script type="text/javascript" defer src="{{ "/katex/katex.min.js" | relURL }}"></script>
|
||||
<script type="text/javascript" defer src="{{ "/katex/auto-render.min.js" | relURL }}" onload="renderMathInElement(document.body);">
|
||||
renderMathInElement(
|
||||
document.body,
|
||||
{
|
||||
delimiters: [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
{left: "\\[", right: "\\]", display: true},
|
||||
{left: "$", right: "$", display: false},
|
||||
{left: "\\(", right: "\\)", display: false}
|
||||
]
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<script src="{{ "/js/mermaid-8.14.0.min.js" | relURL }}"></script>
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
startOnLoad:true
|
||||
});
|
||||
</script>
|
||||
@@ -1,5 +1,6 @@
|
||||
{{ with site.Params.features.support }}
|
||||
{{ if .enabled }}
|
||||
{{ if .enable }}
|
||||
{{ with .services }}
|
||||
<!-- Enable Ko-Fi floating button -->
|
||||
{{ with .kofi }}
|
||||
<script src='https://storage.ko-fi.com/cdn/scripts/overlay-widget.js'></script>
|
||||
@@ -12,5 +13,10 @@
|
||||
});
|
||||
</script>
|
||||
{{ end }}
|
||||
<!-- Enable Buy Me a Coffee (buymeacoffee.com) floating button -->
|
||||
{{ with .buymeacoffee }}
|
||||
<script data-name="BMC-Widget" data-cfasync="false" src="https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js" data-id="{{ .user }}" data-description="{{ .text }}" data-message="{{ .info }}" data-color="{{ .color }}" data-position="Right" data-x_margin="10" data-y_margin="18"></script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<div class="dropdown languageSelector">
|
||||
<a class="btn dropdown-toggle" href="#" id="languageSelector" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{ if ne site.Params.showFlags false }}
|
||||
{{ if ne site.Params.features.flags.enable false }}
|
||||
{{ $countryCode := partial "helpers/country-code.html" . }}
|
||||
<span class="flag-icon flag-icon-{{$countryCode}}"></span>
|
||||
{{ end }}
|
||||
@@ -14,7 +14,7 @@
|
||||
<div class="dropdown-menu" aria-labelledby="languageSelector">
|
||||
{{ range .Translations }}
|
||||
<a class="dropdown-item nav-link languages-item" href="{{ path.Join "/" (cond (eq .Language.Lang "en") "" .Language.Lang) $pageURL }}">
|
||||
{{ if ne site.Params.showFlags false }}
|
||||
{{ if ne site.Params.features.flags.enable false }}
|
||||
{{ $countryCode := partial "helpers/country-code.html" . }}
|
||||
<span class="flag-icon flag-icon-{{$countryCode}}"></span>
|
||||
{{ end }}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="languageSelector" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{ if ne site.Params.showFlags false }}
|
||||
{{ if ne site.Params.features.flags.enable false }}
|
||||
{{ $countryCode := partial "helpers/country-code.html" . }}
|
||||
<span class="flag-icon flag-icon-{{$countryCode}}"></span>
|
||||
{{ end }}
|
||||
@@ -14,7 +14,7 @@
|
||||
<div class="dropdown-menu" aria-labelledby="languageSelector">
|
||||
{{ range .Translations }}
|
||||
<a class="dropdown-item nav-link languages-item" href="{{ path.Join "/" (cond (eq .Language.Lang "en") "" .Language.Lang) $pageURL }}">
|
||||
{{ if ne site.Params.showFlags false }}
|
||||
{{ if ne site.Params.features.flags.enable false }}
|
||||
{{ $countryCode := partial "helpers/country-code.html" . }}
|
||||
<span class="flag-icon flag-icon-{{$countryCode}}"></span>
|
||||
{{ end }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="languageSelector" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{ if ne site.Params.showFlags false }}
|
||||
{{ if ne site.Params.features.flags.enable false }}
|
||||
{{ $countryCode := partial "helpers/country-code.html" . }}
|
||||
<span class="flag-icon flag-icon-{{$countryCode}}"></span>
|
||||
{{ end }}
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="dropdown-menu" aria-labelledby="languageSelector">
|
||||
{{ range site.Home.AllTranslations }}
|
||||
<a class="dropdown-item nav-link languages-item" href="{{ .RelPermalink }}">
|
||||
{{ if ne site.Params.showFlags false }}
|
||||
{{ if ne site.Params.features.flags.enable false }}
|
||||
{{ $countryCode := partial "helpers/country-code.html" . }}
|
||||
<span class="flag-icon flag-icon-{{$countryCode}}"></span>
|
||||
{{ end }}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<nav class="navbar navbar-expand-xl top-navbar final-navbar shadow">
|
||||
<div class="container">
|
||||
<button class="navbar-toggler navbar-light" id="sidebar-toggler" type="button" onclick="toggleSidebar()">
|
||||
<button class="navbar-toggler navbar-light" id="sidebar-toggler" type="button">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="{{ site.BaseURL | relLangURL }}">
|
||||
@@ -38,7 +38,7 @@
|
||||
{{ end }}
|
||||
{{- site.Title -}}
|
||||
</a>
|
||||
<button class="navbar-toggler navbar-light" id="toc-toggler" type="button" onclick="toggleTOC()">
|
||||
<button class="navbar-toggler navbar-light" id="toc-toggler" type="button">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
{{ if .IsTranslated }}
|
||||
{{ partial "navigators/lang-selector-2.html" . }}
|
||||
{{ end }}
|
||||
{{ if site.Params.darkMode.enable }}
|
||||
{{ if site.Params.features.darkMode.enable }}
|
||||
{{ partial "navigators/theme-selector.html" . }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
{{ if .IsTranslated }}
|
||||
{{ partial "navigators/lang-selector.html" . }}
|
||||
{{ end }}
|
||||
{{ if site.Params.darkMode.enable }}
|
||||
{{ if site.Params.features.darkMode.enable }}
|
||||
{{ partial "navigators/theme-selector.html" . }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
<li class="nav-item dropdown">
|
||||
<!-- This is for initializing the color scheme selection for new visitors. See /js/darkmode.js -->
|
||||
<div id="theme-initialization" style="display: none;"
|
||||
default-theme="{{ site.Params.darkMode.default }}"></div>
|
||||
<a class="nav-link dropdown-toggle" href="#" id="themeSelector" role="button"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<img id="navbar-theme-icon-svg" src="{{ "/icons/moon-svgrepo-com.svg" }}" width=20 alt="Dark Theme">
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-icons-only" aria-labelledby="themeSelector">
|
||||
<a class="dropdown-item nav-link" href="#" onclick="enableLightTheme()">
|
||||
<div id="themeMenu" class="dropdown-menu dropdown-menu-icons-only" aria-labelledby="themeSelector">
|
||||
<a class="dropdown-item nav-link" href="#" data-scheme="light">
|
||||
<img class="menu-icon-center" src="{{ "/icons/sun-svgrepo-com.svg" }}" width=20 alt="Light Theme">
|
||||
</a>
|
||||
<a class="dropdown-item nav-link" href="#" onclick="enableDarkTheme()">
|
||||
<a class="dropdown-item nav-link" href="#" data-scheme="dark">
|
||||
<img class="menu-icon-center" src="{{ "/icons/moon-svgrepo-com.svg" }}" width=20 alt="Dark Theme">
|
||||
</a>
|
||||
<a class="dropdown-item nav-link" href="#" onclick="useSystemTheme()">
|
||||
<a class="dropdown-item nav-link" href="#" data-scheme="system">
|
||||
<img class="menu-icon-center" src="{{ "/icons/computer-svgrepo-com.svg" }}" width=20 alt="System Theme">
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</li>
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
<meta property="og:title" content="{{ $title }}"/>
|
||||
<meta property="og:type" content="{{ $type }}"/>
|
||||
<meta property="og:description" content="{{ $description }}"/>
|
||||
<meta property="og:image" content="{{ $image | absURL }}">
|
||||
<meta property="og:image" content="{{ $image | relURL }}">
|
||||
<meta property="og:url" content="{{ $url }}">
|
||||
|
||||
@@ -1,14 +1 @@
|
||||
<script type="text/javascript" src="{{ "/js/jquery-3.4.1.min.js" | relURL }}"></script>
|
||||
<script type="text/javascript" src="{{ "/js/popper.min.js" | relURL }}"></script>
|
||||
<script type="text/javascript" src="{{ "/js/bootstrap.min.js" | relURL }}"></script>
|
||||
|
||||
<script type="text/javascript" src="{{ "/js/navbar.js" | relURL }}"></script>
|
||||
<script type="text/javascript" src="{{ "/js/plyr.js" | relURL }}"></script>
|
||||
<script type="text/javascript" src="{{ "/js/main.js" | relURL }}"></script>
|
||||
|
||||
{{ if site.Params.darkMode.enable }}
|
||||
{{ if eq site.Params.darkMode.provider "darkreader" }}
|
||||
<script type="text/javascript" src="{{ "/js/darkreader.js" | relURL }}"></script>
|
||||
<script type="text/javascript" src="{{ "/js/darkmode-darkreader.js" | relURL }}"></script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ partial "helpers/script-bundle.html" }}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
class="achievement-entry text-center"
|
||||
style="background-image: url('{{ $achievementImageSm }}');"
|
||||
>
|
||||
<i class="fas fa-search-plus" id="enlarge-icon"></i>
|
||||
<i class="fa-solid fa-xmark hidden"></i>
|
||||
<i class="fa-solid fa-magnifying-glass-plus" id="enlarge-icon"></i>
|
||||
<h4 class="title" id="achievement-title">{{ .title }}</h4>
|
||||
<div class="caption hidden col-lg-6 text-left" id="caption">
|
||||
<h4>{{ .title }}</h4>
|
||||
|
||||
@@ -90,9 +90,9 @@
|
||||
{{ end }}
|
||||
{{ if gt (len .takenCourses.courses) $collapseAfter }}
|
||||
<button type="button" class="btn btn-link show-more-btn pt-0 {{ if .takenCourses.showGrades }}ml-1{{ else }}ml-2{{ end }}"
|
||||
onclick="toggleCourseVisibility(this);" id="show-more-btn" aria-label="{{ i18n "show_more"}}">{{ i18n "show_more"}}</button>
|
||||
id="show-more-btn" aria-label="{{ i18n "show_more"}}">{{ i18n "show_more"}}</button>
|
||||
<button type="button" class="btn btn-link show-more-btn hidden pt-0 {{ if .takenCourses.showGrades }}ml-1{{ else }}ml-2{{ end }}"
|
||||
onclick="toggleCourseVisibility(this);" id="show-less-btn" aria-label="{{ i18n "show_less"}}">{{ i18n "show_less"}}</button>
|
||||
id="show-less-btn" aria-label="{{ i18n "show_less"}}">{{ i18n "show_less"}}</button>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user