mirror of
https://github.com/Sped0n/bridget.git
synced 2026-04-14 10:09:31 -07:00
transition from javascript to typescript
This commit is contained in:
@@ -1,233 +0,0 @@
|
||||
const imagesArray = JSON.parse(document.getElementById('images_array').textContent).sort((a, b) => {
|
||||
if (a.index < b.index) {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
})
|
||||
|
||||
const imagesArrayLen = imagesArray.length
|
||||
|
||||
const thresholdNum = document.getElementsByClassName('thid')
|
||||
|
||||
const threshold = [0, 40, 80, 120, 160, 200]
|
||||
|
||||
const thresholdSensitivity = [100, 40, 18, 14, 9, 5]
|
||||
|
||||
const r = document.querySelector(':root')
|
||||
|
||||
const posXArray = ['0px', '0px', '0px', '0px', '0px']
|
||||
|
||||
const posYArray = ['0px', '0px', '0px', '0px', '0px']
|
||||
|
||||
const layer5 = document.getElementById('layer5')
|
||||
const layer4 = document.getElementById('layer4')
|
||||
const layer3 = document.getElementById('layer3')
|
||||
const layer2 = document.getElementById('layer2')
|
||||
const layer1 = document.getElementById('layer1')
|
||||
|
||||
let thresholdIndex = 2
|
||||
|
||||
let globalIndex = 0
|
||||
|
||||
let last = { x: 0, y: 0 }
|
||||
|
||||
function sleep (ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
// fulfill space with zero
|
||||
function duper (num) {
|
||||
return ('0000' + num).slice(-4)
|
||||
}
|
||||
|
||||
// threshold display update
|
||||
function thresholdUpdate () {
|
||||
thresholdNum.item(0).innerText = duper(threshold[thresholdIndex])
|
||||
}
|
||||
|
||||
function footerHeightUpdate () {
|
||||
if (window.innerWidth > 768) {
|
||||
r.style.setProperty('--footer-height', '38px')
|
||||
} else {
|
||||
r.style.setProperty('--footer-height', '31px')
|
||||
}
|
||||
}
|
||||
|
||||
function overlayInit () {
|
||||
// largest z index
|
||||
document.getElementsByClassName('overlay').item(0).style.zIndex = '7'
|
||||
}
|
||||
|
||||
const numSpan = (numOne, numTwo) => {
|
||||
// footer index number display module
|
||||
const footerIndex = document.getElementsByClassName('ftid')
|
||||
const numOneString = duper(numOne)
|
||||
const numTwoString = duper(numTwo)
|
||||
for (let i = 0; i <= 7; i++) {
|
||||
if (i > 3) {
|
||||
footerIndex.item(i).innerText = numTwoString[i - 4]
|
||||
} else {
|
||||
footerIndex.item(i).innerText = numOneString[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initialization
|
||||
function init () {
|
||||
numSpan(0, imagesArrayLen)
|
||||
thresholdUpdate()
|
||||
footerHeightUpdate()
|
||||
// threshold buttons initialization
|
||||
document.getElementById('thresholdDec').addEventListener('click', function () {
|
||||
if (thresholdIndex > 0) {
|
||||
thresholdIndex--
|
||||
thresholdUpdate()
|
||||
}
|
||||
}, { passive: true })
|
||||
|
||||
document.getElementById('thresholdInc').addEventListener('click', function () {
|
||||
if (thresholdIndex < 5) {
|
||||
thresholdIndex++
|
||||
thresholdUpdate()
|
||||
}
|
||||
}, { passive: true })
|
||||
}
|
||||
|
||||
const center = e => {
|
||||
e.style.left = '50%'
|
||||
if (window.innerWidth > 768) {
|
||||
e.style.top = 'calc((100% - 38px) / 2)'
|
||||
} else {
|
||||
e.style.top = 'calc((100% - 31px) / 2 + 31px)'
|
||||
}
|
||||
}
|
||||
|
||||
const overlayCursor = e => {
|
||||
const overlayCursor = document.getElementsByClassName('overlay_cursor').item(0)
|
||||
overlayCursor.style.left = `${e.clientX}px`
|
||||
overlayCursor.style.top = `${e.clientY}px`
|
||||
}
|
||||
|
||||
const FIFO = element => {
|
||||
function layerProcess (layerL, layerH) {
|
||||
if (layerL.childElementCount) layerL.removeChild(layerL.lastElementChild)
|
||||
if (layerH.childElementCount) layerL.appendChild(layerH.lastElementChild.cloneNode(true))
|
||||
}
|
||||
layerProcess(layer1, layer2)
|
||||
layerProcess(layer2, layer3)
|
||||
layerProcess(layer3, layer4)
|
||||
layerProcess(layer4, layer5)
|
||||
if (layer5.childElementCount) layer5.removeChild(layer5.lastElementChild)
|
||||
layer5.appendChild(element)
|
||||
}
|
||||
|
||||
const posCache = (x, y) => {
|
||||
// pop element if length surpass limitation
|
||||
posXArray.shift()
|
||||
posYArray.shift()
|
||||
// push new element
|
||||
posXArray.push(`${x}px`)
|
||||
posYArray.push(`${y}px`)
|
||||
}
|
||||
|
||||
function layersPosSet () {
|
||||
function posSet (layer, index) {
|
||||
layer.style.left = posXArray[index]
|
||||
layer.style.top = posYArray[index]
|
||||
}
|
||||
posSet(layer5, 4)
|
||||
posSet(layer4, 3)
|
||||
posSet(layer3, 2)
|
||||
posSet(layer2, 1)
|
||||
posSet(layer1, 0)
|
||||
}
|
||||
|
||||
// let specified image show
|
||||
const activate = (index, x, y) => {
|
||||
const img = document.createElement('img')
|
||||
img.setAttribute('src', imagesArray[index].url)
|
||||
img.setAttribute('alt', imagesArray[index].index)
|
||||
img.setAttribute('height', imagesArray[index].height)
|
||||
img.setAttribute('width', imagesArray[index].width)
|
||||
posCache(x, y)
|
||||
layersPosSet()
|
||||
FIFO(img)
|
||||
// top
|
||||
layer5.addEventListener('click', () => {
|
||||
// stop images animation
|
||||
window.removeEventListener('mousemove', handleOnMove)
|
||||
// set top image
|
||||
center(layer5)
|
||||
layer5.dataset.status = 't0'
|
||||
layer4.dataset.status = 't1'
|
||||
layer3.dataset.status = 't2'
|
||||
layer2.dataset.status = 't3'
|
||||
layer1.dataset.status = 't4'
|
||||
// overlay init
|
||||
overlayInit()
|
||||
window.addEventListener('mousemove', overlayCursor)
|
||||
}, {
|
||||
passive: true,
|
||||
once: true
|
||||
})
|
||||
|
||||
last = { x, y }
|
||||
}
|
||||
|
||||
// absolute distance calculation
|
||||
const distanceFromLast = (x, y) => {
|
||||
return Math.hypot(x - last.x, y - last.y)
|
||||
}
|
||||
|
||||
// move handler
|
||||
const handleOnMove = e => {
|
||||
if (distanceFromLast(e.clientX, e.clientY) > (window.innerWidth / thresholdSensitivity[thresholdIndex])) {
|
||||
// images showing array
|
||||
const imageIndex = globalIndex % imagesArrayLen
|
||||
// show top image and change index
|
||||
activate(imageIndex, e.clientX, e.clientY)
|
||||
numSpan((imageIndex + 1), imagesArrayLen)
|
||||
// self increment
|
||||
globalIndex++
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
|
||||
window.addEventListener('mousemove', handleOnMove)
|
||||
window.addEventListener('resize', () => {
|
||||
const isTop = document.getElementsByClassName('top')
|
||||
if (isTop.length) {
|
||||
center(isTop.item(0))
|
||||
}
|
||||
footerHeightUpdate()
|
||||
})
|
||||
|
||||
document.getElementsByClassName('prev_section').item(0).addEventListener('mouseover', () => {
|
||||
document.getElementsByClassName('overlay_cursor').item(0).innerText = 'PREV'
|
||||
})
|
||||
|
||||
document.getElementsByClassName('close_section').item(0).addEventListener('click', async function f () {
|
||||
document.getElementsByClassName('overlay').item(0).style.zIndex = '-1'
|
||||
layersPosSet()
|
||||
layer5.dataset.status = 'r0'
|
||||
layer4.dataset.status = 'r1'
|
||||
layer3.dataset.status = 'r2'
|
||||
layer2.dataset.status = 'r3'
|
||||
layer1.dataset.status = 'r4'
|
||||
await sleep(2500)
|
||||
layer5.dataset.status = 'null'
|
||||
layer4.dataset.status = 'null'
|
||||
layer3.dataset.status = 'null'
|
||||
layer2.dataset.status = 'null'
|
||||
layer1.dataset.status = 'null'
|
||||
window.addEventListener('mousemove', handleOnMove)
|
||||
})
|
||||
|
||||
document.getElementsByClassName('close_section').item(0).addEventListener('mouseover', () => {
|
||||
document.getElementsByClassName('overlay_cursor').item(0).innerText = 'CLOSE'
|
||||
})
|
||||
|
||||
document.getElementsByClassName('next_section').item(0).addEventListener('mouseover', () => {
|
||||
document.getElementsByClassName('overlay_cursor').item(0).innerText = 'NEXT'
|
||||
})
|
||||
17
assets/ts/indexDisp.ts
Normal file
17
assets/ts/indexDisp.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { duper } from './utils'
|
||||
|
||||
// update index of displaying image
|
||||
export function imgIndexSpanUpdate(numOne: number, numTwo: number): void {
|
||||
// footer index number display module
|
||||
const footerIndexDisp = document.getElementsByClassName('ftid')
|
||||
const numOneString: string = duper(numOne)
|
||||
const numTwoString: string = duper(numTwo)
|
||||
for (let i: number = 0; i <= 7; i++) {
|
||||
const footerIndex = footerIndexDisp[i] as HTMLSpanElement
|
||||
if (i > 3) {
|
||||
footerIndex.innerText = numTwoString[i - 4]
|
||||
} else {
|
||||
footerIndex.innerText = numOneString[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
13
assets/ts/main.ts
Normal file
13
assets/ts/main.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { footerHeightUpdateInit } from './utils'
|
||||
import { imgIndexSpanUpdate } from './indexDisp'
|
||||
import { imagesArrayLen, trackMouseInit } from './trackMouse'
|
||||
import { thresholdCtlInit } from './thresholdCtl'
|
||||
|
||||
function init(): void {
|
||||
footerHeightUpdateInit()
|
||||
imgIndexSpanUpdate(0, imagesArrayLen)
|
||||
thresholdCtlInit()
|
||||
trackMouseInit()
|
||||
}
|
||||
|
||||
init()
|
||||
85
assets/ts/overlay.ts
Normal file
85
assets/ts/overlay.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { delay, removeAllEventListeners, layersPosSet } from './utils'
|
||||
import { posArray, layers, handleOnMove } from './trackMouse'
|
||||
|
||||
// get components of overlay
|
||||
const overlay = document.getElementsByClassName('overlay').item(0) as HTMLDivElement
|
||||
let closeSection = document.getElementsByClassName('close_section').item(0) as Node
|
||||
let prevSection = document.getElementsByClassName('prev_section').item(0) as Node
|
||||
let nextSection = document.getElementsByClassName('next_section').item(0) as Node
|
||||
const cursor = document
|
||||
.getElementsByClassName('overlay_cursor')
|
||||
.item(0) as HTMLDivElement
|
||||
|
||||
// set cursor text
|
||||
function setCursorText(text: string): void {
|
||||
cursor.innerText = text
|
||||
}
|
||||
|
||||
// overlay cursor event handler
|
||||
const overlayCursor = (e: MouseEvent): void => {
|
||||
cursor.style.left = `${e.clientX}px`
|
||||
cursor.style.top = `${e.clientY}px`
|
||||
}
|
||||
|
||||
function disableListener(): void {
|
||||
window.removeEventListener('mousemove', overlayCursor)
|
||||
closeSection = removeAllEventListeners(closeSection)
|
||||
prevSection = removeAllEventListeners(prevSection)
|
||||
nextSection = removeAllEventListeners(nextSection)
|
||||
}
|
||||
|
||||
export function overlayEnable(): void {
|
||||
overlay.style.zIndex = '7'
|
||||
setListener()
|
||||
}
|
||||
|
||||
export function overlayDisable(): void {
|
||||
overlay.style.zIndex = '-1'
|
||||
disableListener()
|
||||
}
|
||||
|
||||
async function handleCloseClick(): Promise<void> {
|
||||
overlayDisable()
|
||||
layersPosSet(posArray, layers)
|
||||
for (let i: number = 4; i >= 0; i--) {
|
||||
layers[i].dataset.status = `r${4 - i}`
|
||||
}
|
||||
await delay(2500)
|
||||
for (let i: number = 4; i >= 0; i--) {
|
||||
layers[i].dataset.status = 'null'
|
||||
}
|
||||
window.addEventListener('mousemove', handleOnMove)
|
||||
}
|
||||
|
||||
// set hover event listener
|
||||
function setListener(): void {
|
||||
window.addEventListener('mousemove', overlayCursor, { passive: true })
|
||||
closeSection.addEventListener(
|
||||
'mouseover',
|
||||
() => {
|
||||
setCursorText('CLOSE')
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
closeSection.addEventListener(
|
||||
'click',
|
||||
() => {
|
||||
void handleCloseClick()
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
prevSection.addEventListener(
|
||||
'mouseover',
|
||||
() => {
|
||||
setCursorText('PREV')
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
nextSection.addEventListener(
|
||||
'mouseover',
|
||||
() => {
|
||||
setCursorText('NEXT')
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
}
|
||||
40
assets/ts/thresholdCtl.ts
Normal file
40
assets/ts/thresholdCtl.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { duper } from './utils'
|
||||
|
||||
// get threshold display element
|
||||
const thresholdDisp = document.getElementsByClassName('thid').item(0) as HTMLSpanElement
|
||||
|
||||
// threshold data
|
||||
const threshold: number[] = [0, 40, 80, 120, 160, 200]
|
||||
export const thresholdSensitivityArray: number[] = [100, 40, 18, 14, 9, 5]
|
||||
export let thresholdIndex: number = 2
|
||||
|
||||
function thresholdUpdate(): void {
|
||||
thresholdDisp.innerText = duper(threshold[thresholdIndex])
|
||||
}
|
||||
|
||||
export function thresholdCtlInit(): void {
|
||||
thresholdUpdate()
|
||||
const dec = document.getElementById('thresholdDec') as HTMLButtonElement
|
||||
dec.addEventListener(
|
||||
'click',
|
||||
function () {
|
||||
if (thresholdIndex > 0) {
|
||||
thresholdIndex--
|
||||
thresholdUpdate()
|
||||
}
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
|
||||
const inc = document.getElementById('thresholdInc') as HTMLButtonElement
|
||||
inc.addEventListener(
|
||||
'click',
|
||||
function () {
|
||||
if (thresholdIndex < 5) {
|
||||
thresholdIndex++
|
||||
thresholdUpdate()
|
||||
}
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
}
|
||||
107
assets/ts/trackMouse.ts
Normal file
107
assets/ts/trackMouse.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { overlayEnable } from './overlay'
|
||||
import { posCache, FIFO, layersPosSet, center } from './utils'
|
||||
import { thresholdSensitivityArray, thresholdIndex } from './thresholdCtl'
|
||||
import { imgIndexSpanUpdate } from './indexDisp'
|
||||
|
||||
interface ImageData {
|
||||
index: string
|
||||
url: string
|
||||
imgH: string
|
||||
imgW: string
|
||||
}
|
||||
|
||||
export interface position {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
|
||||
// get images info from JSON
|
||||
const imageArrayElement = document.getElementById('images_array') as HTMLElement
|
||||
const rawImageArray = imageArrayElement.textContent as string
|
||||
export const imagesArray: ImageData[] = JSON.parse(rawImageArray).sort(
|
||||
(a: ImageData, b: ImageData) => {
|
||||
if (a.index < b.index) {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
)
|
||||
export const imagesArrayLen: number = imagesArray.length
|
||||
|
||||
// get layer divs
|
||||
const layer5 = document.getElementById('layer5') as HTMLDivElement
|
||||
const layer4 = document.getElementById('layer4') as HTMLDivElement
|
||||
const layer3 = document.getElementById('layer3') as HTMLDivElement
|
||||
const layer2 = document.getElementById('layer2') as HTMLDivElement
|
||||
const layer1 = document.getElementById('layer1') as HTMLDivElement
|
||||
export const layers: HTMLDivElement[] = [layer1, layer2, layer3, layer4, layer5]
|
||||
|
||||
// layers position caching
|
||||
export const posArray: string[][] = [
|
||||
['0px', '0px', '0px', '0px', '0px'],
|
||||
['0px', '0px', '0px', '0px', '0px']
|
||||
]
|
||||
|
||||
// global index for "activated"
|
||||
let globalIndex: number = 0
|
||||
|
||||
// last position set as "activated"
|
||||
let last: position = { x: 0, y: 0 }
|
||||
|
||||
const activate = (index: number, x: number, y: number): void => {
|
||||
const img = document.createElement('img')
|
||||
img.setAttribute('src', imagesArray[index].url)
|
||||
img.setAttribute('alt', imagesArray[index].index)
|
||||
img.setAttribute('height', imagesArray[index].imgH)
|
||||
img.setAttribute('width', imagesArray[index].imgW)
|
||||
posCache(x, y, posArray)
|
||||
layersPosSet(posArray, layers)
|
||||
FIFO(img, layers)
|
||||
// top
|
||||
layer5.addEventListener(
|
||||
'click',
|
||||
() => {
|
||||
// stop images animation
|
||||
window.removeEventListener('mousemove', handleOnMove)
|
||||
// set top image
|
||||
center(layer5)
|
||||
layer5.dataset.status = 't0'
|
||||
layer4.dataset.status = 't1'
|
||||
layer3.dataset.status = 't2'
|
||||
layer2.dataset.status = 't3'
|
||||
layer1.dataset.status = 't4'
|
||||
// overlay init
|
||||
overlayEnable()
|
||||
},
|
||||
{
|
||||
passive: true,
|
||||
once: true
|
||||
}
|
||||
)
|
||||
|
||||
last = { x, y }
|
||||
}
|
||||
|
||||
const distanceFromLast = (x: number, y: number): number => {
|
||||
return Math.hypot(x - last.x, y - last.y)
|
||||
}
|
||||
|
||||
export const handleOnMove = (e: MouseEvent): void => {
|
||||
// meet threshold
|
||||
if (
|
||||
distanceFromLast(e.clientX, e.clientY) >
|
||||
window.innerWidth / thresholdSensitivityArray[thresholdIndex]
|
||||
) {
|
||||
// images showing array
|
||||
const imageIndex = globalIndex % imagesArrayLen
|
||||
// show top image and change index
|
||||
activate(imageIndex, e.clientX, e.clientY)
|
||||
imgIndexSpanUpdate(imageIndex + 1, imagesArrayLen)
|
||||
// self increment
|
||||
globalIndex++
|
||||
}
|
||||
}
|
||||
|
||||
export function trackMouseInit(): void {
|
||||
window.addEventListener('mousemove', handleOnMove)
|
||||
}
|
||||
78
assets/ts/utils.ts
Normal file
78
assets/ts/utils.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
export const posCache = (x: number, y: number, xyArray: string[][]): void => {
|
||||
// pop element if length surpass limitation
|
||||
xyArray[0].shift()
|
||||
xyArray[1].shift()
|
||||
// push new element
|
||||
xyArray[0].push(`${x}px`)
|
||||
xyArray[1].push(`${y}px`)
|
||||
}
|
||||
|
||||
export function duper(num: number): string {
|
||||
return ('0000' + num.toString()).slice(-4)
|
||||
}
|
||||
|
||||
export const FIFO = (
|
||||
element: HTMLImageElement,
|
||||
layersArray: HTMLDivElement[]
|
||||
): void => {
|
||||
function layerProcess(layerL: HTMLDivElement, layerH: HTMLDivElement): void {
|
||||
if (layerL.childElementCount !== 0)
|
||||
layerL.removeChild(layerL.lastElementChild as HTMLImageElement)
|
||||
if (layerH.childElementCount !== 0) {
|
||||
const layerHNode = layerH.lastElementChild as HTMLImageElement
|
||||
layerL.appendChild(layerHNode.cloneNode(true))
|
||||
}
|
||||
}
|
||||
for (let i: number = 0; i <= 3; i++) {
|
||||
layerProcess(layersArray[i], layersArray[i + 1])
|
||||
}
|
||||
if (layersArray[4].childElementCount !== 0)
|
||||
layersArray[4].removeChild(layersArray[4].lastElementChild as HTMLImageElement)
|
||||
layersArray[4].appendChild(element)
|
||||
}
|
||||
|
||||
export const layersPosSet = (
|
||||
xyArray: string[][],
|
||||
layersArray: HTMLDivElement[]
|
||||
): void => {
|
||||
function posSet(layer: HTMLDivElement, index: number): void {
|
||||
layer.style.left = xyArray[0][index]
|
||||
layer.style.top = xyArray[1][index]
|
||||
}
|
||||
for (let i = 4; i >= 0; i--) {
|
||||
posSet(layersArray[i], i)
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
export function delay(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
export function removeAllEventListeners(e: Node): Node {
|
||||
return e.cloneNode(true)
|
||||
}
|
||||
|
||||
export const center = (e: HTMLDivElement): void => {
|
||||
e.style.left = '50%'
|
||||
if (window.innerWidth > 768) {
|
||||
e.style.top = 'calc((100% - 38px) / 2)'
|
||||
} else {
|
||||
e.style.top = 'calc((100% - 31px) / 2 + 31px)'
|
||||
}
|
||||
}
|
||||
|
||||
export function footerHeightUpdateInit(): void {
|
||||
window.addEventListener(
|
||||
'resize',
|
||||
() => {
|
||||
const r = document.querySelector(':root') as HTMLElement
|
||||
if (window.innerWidth > 768) {
|
||||
r.style.setProperty('--footer-height', '38px')
|
||||
} else {
|
||||
r.style.setProperty('--footer-height', '31px')
|
||||
}
|
||||
},
|
||||
{ passive: true }
|
||||
)
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
{{ $.Scratch.Add "img" slice }}
|
||||
{{ range . }}
|
||||
{{ $index = sub $index 1}}
|
||||
{{ $.Scratch.Add "img" (dict "index" (string $index) "url" (string .RelPermalink) "height" (string .Height) "width" (string .Width)) }}
|
||||
{{ $.Scratch.Add "img" (dict "index" (string $index) "url" (string .RelPermalink) "imgH" (string .Height) "imgW" (string .Width)) }}
|
||||
{{ end }}
|
||||
<script id="images_array" type="application/json">{{ $.Scratch.Get "img" | jsonify | safeJS }}</script>
|
||||
{{ end }}
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
{{- $style = dict "Context" . "ToCSS" $options | merge $style -}}
|
||||
{{- partial "plugin/style.html" $style -}}
|
||||
|
||||
{{ $js := resources.Get "js/theme.js" }}
|
||||
<script type="text/javascript" src="{{ $js.RelPermalink }}" defer></script>
|
||||
{{ $script := resources.Get "ts/main.ts" | js.Build }}
|
||||
<script type="text/javascript" src="{{ $script.RelPermalink }}" defer></script>
|
||||
Reference in New Issue
Block a user