Optimize shiki and add skipped and left data
This commit is contained in:
parent
2c50459501
commit
f6123f53e7
@ -1,7 +1,14 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<Suspense>
|
||||||
|
<template #default>
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</template>
|
</template>
|
||||||
|
<template #fallback>
|
||||||
|
<div>Loading</div>
|
||||||
|
</template>
|
||||||
|
</Suspense>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -68,7 +68,7 @@ header {
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
margin-top: 60px;
|
margin-top: 60px;
|
||||||
padding: 30px 30px 0 30px;
|
padding: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
@media only screen and (max-width: 800px) {
|
||||||
@ -105,3 +105,16 @@ header .logo-text h1 {
|
|||||||
background-color: #d1d;
|
background-color: #d1d;
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.code-action {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data {
|
||||||
|
padding: 10px;
|
||||||
|
color: var(--primary);
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
import { ref, reactive, computed, useTemplateRef, watch, onUpdated } from 'vue'
|
import { ref, reactive, computed, useTemplateRef, watch, onUpdated } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { computedAsync } from '@vueuse/core'
|
import { computedAsync } from '@vueuse/core'
|
||||||
import { codeToHtml } from 'shiki'
|
import { createHighlighterCore } from 'shiki/core'
|
||||||
|
import { createJavaScriptRegexEngine } from 'shiki/engine/javascript'
|
||||||
|
import catppuccinLatte from '@shikijs/themes/catppuccin-latte'
|
||||||
|
import bash from '@shikijs/langs/bash'
|
||||||
|
|
||||||
import Header from '../components/Header.vue'
|
import Header from '../components/Header.vue'
|
||||||
|
|
||||||
@ -24,33 +27,6 @@ const codeDiv = useTemplateRef('codeDiv')
|
|||||||
const size = 32 * 1024
|
const size = 32 * 1024
|
||||||
const maxViewSize = size * 16
|
const maxViewSize = size * 16
|
||||||
|
|
||||||
// Add ellipsis to start or end if there is more content available
|
|
||||||
const displayedContent = computedAsync(async () => {
|
|
||||||
const prefix = start.value ? '...\n' : ''
|
|
||||||
const suffix = end.value < totalSize.value ? '\n...' : ''
|
|
||||||
const decorations = []
|
|
||||||
if (searched) {
|
|
||||||
const currentMatch = searchResults.matches[searchResults.current]
|
|
||||||
searchResults.matches.forEach((match) => {
|
|
||||||
if (match < end.value && match > start.value) {
|
|
||||||
decorations.push({
|
|
||||||
start: match - start.value + prefix.length,
|
|
||||||
end: match - start.value + query.value.length + prefix.length,
|
|
||||||
properties: {
|
|
||||||
class: currentMatch === match ? 'current-highlighted-word' : 'highlighted-word',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return await codeToHtml(prefix + content.value + suffix, {
|
|
||||||
lang: 'bash',
|
|
||||||
theme: 'catppuccin-latte',
|
|
||||||
decorations,
|
|
||||||
})
|
|
||||||
}, '')
|
|
||||||
|
|
||||||
function scrollToSelectedSearch() {
|
function scrollToSelectedSearch() {
|
||||||
if (!searched.value) return
|
if (!searched.value) return
|
||||||
// fragile constants
|
// fragile constants
|
||||||
@ -78,6 +54,7 @@ async function getSection(start: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getNextSection() {
|
function getNextSection() {
|
||||||
|
query.value = ""
|
||||||
resetSearch()
|
resetSearch()
|
||||||
getSection(end.value).then((data) => {
|
getSection(end.value).then((data) => {
|
||||||
content.value = content.value + data.content
|
content.value = content.value + data.content
|
||||||
@ -92,6 +69,7 @@ function getNextSection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getPreviousSection() {
|
function getPreviousSection() {
|
||||||
|
query.value = ""
|
||||||
resetSearch()
|
resetSearch()
|
||||||
if (start.value) {
|
if (start.value) {
|
||||||
getSection(start.value - size).then((data) => {
|
getSection(start.value - size).then((data) => {
|
||||||
@ -144,7 +122,9 @@ function resetSearch() {
|
|||||||
|
|
||||||
// +1 for next, -1 for previous
|
// +1 for next, -1 for previous
|
||||||
function moveSearchResult(n) {
|
function moveSearchResult(n) {
|
||||||
|
if (searchResults.current + n < searchResults.matches.length && searchResults.current + n >= 0)
|
||||||
searchResults.current += n
|
searchResults.current += n
|
||||||
|
else return
|
||||||
const matchPos = searchResults.matches[searchResults.current]
|
const matchPos = searchResults.matches[searchResults.current]
|
||||||
getNthByte(matchPos)
|
getNthByte(matchPos)
|
||||||
}
|
}
|
||||||
@ -158,6 +138,53 @@ function findError() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getNextSection()
|
getNextSection()
|
||||||
|
|
||||||
|
function convertBytes(bytes) {
|
||||||
|
const suffixes = ["bytes", "KiB", "MiB", "GiB"];
|
||||||
|
for (let suffix of suffixes) {
|
||||||
|
if (bytes < 1024)
|
||||||
|
return `${bytes.toFixed(2).replace(/\.?0*$/,'')} ${suffix}`
|
||||||
|
bytes /= 1024;
|
||||||
|
}
|
||||||
|
return `${bytes.toFixed(2).replace(/\.?0*$/,'')} TiB`
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataSkipped = computed(() => convertBytes(start.value))
|
||||||
|
const dataLeft = computed(() => convertBytes(totalSize.value - end.value))
|
||||||
|
|
||||||
|
const highlighter = await createHighlighterCore({
|
||||||
|
langs: [bash],
|
||||||
|
themes: [catppuccinLatte],
|
||||||
|
engine: createJavaScriptRegexEngine(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add ellipsis to start or end if there is more content available
|
||||||
|
const displayedContent = computed(() => {
|
||||||
|
const prefix = start.value ? '...\n' : ''
|
||||||
|
const suffix = end.value < totalSize.value ? '\n...' : ''
|
||||||
|
const decorations = []
|
||||||
|
if (searched) {
|
||||||
|
const currentMatch = searchResults.matches[searchResults.current]
|
||||||
|
searchResults.matches.forEach((match) => {
|
||||||
|
if (match < end.value && match > start.value) {
|
||||||
|
decorations.push({
|
||||||
|
start: match - start.value + prefix.length,
|
||||||
|
end: match - start.value + query.value.length + prefix.length,
|
||||||
|
properties: {
|
||||||
|
class: currentMatch === match ? 'current-highlighted-word' : 'highlighted-word',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return highlighter.codeToHtml(prefix + content.value + suffix, {
|
||||||
|
lang: 'bash',
|
||||||
|
theme: 'catppuccin-latte',
|
||||||
|
decorations,
|
||||||
|
})
|
||||||
|
}, '')
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script></script>
|
<script></script>
|
||||||
@ -175,7 +202,7 @@ getNextSection()
|
|||||||
Previous
|
Previous
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
:disabled="searchResults.current >= searchResults.matches.length"
|
:disabled="searchResults.current >= searchResults.matches.length - 1"
|
||||||
@click="moveSearchResult(1)"
|
@click="moveSearchResult(1)"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
@ -189,8 +216,14 @@ getNextSection()
|
|||||||
</form>
|
</form>
|
||||||
</Header>
|
</Header>
|
||||||
<main>
|
<main>
|
||||||
|
<div class="code-action">
|
||||||
<button @click="getPreviousSection" :disabled="!start">Load Previous</button>
|
<button @click="getPreviousSection" :disabled="!start">Load Previous</button>
|
||||||
|
<span v-if="start" class="data">{{ dataSkipped }} skipped</span>
|
||||||
|
</div>
|
||||||
<div ref="codeDiv" v-html="displayedContent"></div>
|
<div ref="codeDiv" v-html="displayedContent"></div>
|
||||||
|
<div class="code-action">
|
||||||
<button @click="getNextSection" :disabled="end >= totalSize">Load More</button>
|
<button @click="getNextSection" :disabled="end >= totalSize">Load More</button>
|
||||||
|
<span v-if="end < totalSize" class="data">{{ dataLeft }} left</span>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user