Skip to content

Commit a423d31

Browse files
committedOct 15, 2024
fix(devtools): add robots.txt code highlighting
1 parent 53631bd commit a423d31

File tree

3 files changed

+123
-35
lines changed

3 files changed

+123
-35
lines changed
 

Diff for: ‎client/app.vue

+10-13
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import {
33
appFetch,
44
colorMode,
55
computed,
6-
highlight,
76
useAsyncData,
87
useHead,
98
} from '#imports'
109
import { useLocalStorage } from '@vueuse/core'
10+
import { loadShiki } from '~/composables/shiki'
1111
import {
1212
envTab,
1313
path,
@@ -18,6 +18,7 @@ import 'floating-vue/dist/style.css'
1818
useHead({
1919
title: 'Nuxt Robots',
2020
})
21+
await loadShiki()
2122
2223
const globalDebugFetch = useAsyncData<{ indexable: boolean, hints: string[], runtimeConfig: { version: string } }>(() => {
2324
if (!appFetch.value || typeof appFetch.value !== 'function') {
@@ -65,6 +66,10 @@ const version = computed(() => {
6566
return globalDebugData.value?.runtimeConfig?.version || ''
6667
})
6768
69+
const metaTag = computed(() => {
70+
return `<meta name="robots" content="${pathDebugData.value?.rule}">`
71+
})
72+
6873
const tab = useLocalStorage('nuxt-robots:tab', 'overview')
6974
</script>
7075

@@ -221,7 +226,7 @@ const tab = useLocalStorage('nuxt-robots:tab', 'overview')
221226
Robots are blocked from crawling <code class="opacity-60 text-sm">{{ path }}</code>.
222227
</div>
223228
</div>
224-
<pre of-auto h-full text-sm style="white-space: break-spaces;" v-html="highlight(JSON.stringify(pathDebugData.rule || {}, null, 2), 'json')" />
229+
<OCodeBlock :code="metaTag" lang="html" />
225230
<div v-if="pathDebugData?.debug" class="mt-3 flex gap-2">
226231
<div v-if="pathDebugData?.debug?.source" class="text-xs text-gray-300 mt-3 border-gray-600 rounded-xl border-1 px-2 py-1 inline-flex">
227232
Source: {{ pathDebugData?.debug?.source }}
@@ -264,11 +269,11 @@ const tab = useLocalStorage('nuxt-robots:tab', 'overview')
264269
<OSectionBlock>
265270
<template #text>
266271
<h3 class="opacity-80 text-base mb-1">
267-
robots.txt
272+
/robots.txt
268273
</h3>
269274
</template>
270275
<div class="px-3 py-2 space-y-5">
271-
<pre of-auto h-full text-sm style="white-space: break-spaces;" v-html="globalDebugData.robotsTxt" />
276+
<OCodeBlock :code="globalDebugData.robotsTxt" lang="robots-txt" />
272277
</div>
273278
</OSectionBlock>
274279
</div>
@@ -281,7 +286,7 @@ const tab = useLocalStorage('nuxt-robots:tab', 'overview')
281286
</h3>
282287
</template>
283288
<div class="px-3 py-2 space-y-5">
284-
<pre of-auto h-full text-sm style="white-space: break-spaces;" v-html="highlight(JSON.stringify(globalDebugData?.runtimeConfig || {}, null, 2), 'json')" />
289+
<OCodeBlock :code="JSON.stringify(globalDebugData?.runtimeConfig || {}, null, 2)" lang="json" />
285290
</div>
286291
</OSectionBlock>
287292
</div>
@@ -360,14 +365,6 @@ html.dark {
360365
--uno: border-solid border-1 border-b border-base h-1px w-full block my-2 op50;
361366
}
362367
363-
.dark .shiki {
364-
background: var(--shiki-dark-bg, inherit) !important;
365-
}
366-
367-
.dark .shiki span {
368-
color: var(--shiki-dark, inherit) !important;
369-
}
370-
371368
/* JSON Editor */
372369
textarea {
373370
background: #8881

Diff for: ‎client/components/OCodeBlock.vue

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<script setup lang="ts">
2+
import type { BundledLanguage } from 'shiki'
3+
import { computed } from 'vue'
4+
import { renderCodeHighlight } from '../composables/shiki'
5+
6+
const props = withDefaults(
7+
defineProps<{
8+
code: string
9+
lang?: BundledLanguage | 'robots-txt'
10+
lines?: boolean
11+
transformRendered?: (code: string) => string
12+
}>(),
13+
{
14+
lines: false,
15+
},
16+
)
17+
const rendered = computed(() => {
18+
const code = renderCodeHighlight(props.code, props.lang)
19+
return props.transformRendered ? props.transformRendered(code.value || '') : code.value
20+
})
21+
</script>
22+
23+
<template>
24+
<pre
25+
class="n-code-block p-5"
26+
:class="lines ? 'n-code-block-lines' : ''"
27+
v-html="rendered"
28+
/>
29+
</template>
30+
31+
<style>
32+
.n-code-block-lines .shiki code .line::before {
33+
display: none;
34+
}
35+
</style>

Diff for: ‎client/composables/shiki.ts

+78-22
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,84 @@
1-
import type { BundledLanguage, Highlighter } from 'shiki'
2-
import { useColorMode } from '#imports'
3-
import { getHighlighter } from 'shiki'
4-
import { ref } from 'vue'
1+
import type { MaybeRef } from '@vueuse/core'
2+
import type { Highlighter, BundledLanguage } from 'shiki'
3+
import { createHighlighter } from 'shiki'
4+
import { computed, ref, toValue } from 'vue'
5+
import { devtools } from './rpc'
56

67
export const shiki = ref<Highlighter>()
7-
const mode = useColorMode()
88

9-
// TODO: Only loading when needed
10-
getHighlighter({
11-
themes: [
12-
'vitesse-dark',
13-
'vitesse-light',
14-
],
15-
langs: [
16-
'html',
17-
'json',
18-
],
19-
}).then((i) => { shiki.value = i })
9+
export async function loadShiki() {
10+
// Only loading when needed
11+
shiki.value = await createHighlighter({
12+
themes: [
13+
'vitesse-dark',
14+
'vitesse-light',
15+
],
16+
langs: [
17+
'html',
18+
'json',
19+
Object.freeze({
20+
displayName: 'robots.txt',
21+
name: 'robots-txt',
22+
patterns: [
23+
{ include: '#main' },
24+
],
25+
repository: {
26+
$base: { patterns: [] },
27+
$self: { name: 'source.robots-txt' },
28+
main: {
29+
patterns: [
30+
{ include: '#comment' },
31+
{ include: '#directive' },
32+
{ include: '#wildcard' },
33+
{ include: '#uri' },
34+
{ include: '#text' },
35+
{ include: '#number' },
36+
],
37+
},
38+
comment: {
39+
name: 'comment.line.hash.robots-txt',
40+
begin: '#',
41+
end: '$',
42+
beginCaptures: {
43+
0: { name: 'punctuation.definition.comment.robots-txt' },
44+
},
45+
},
46+
directive: {
47+
name: 'keyword.control.directive.robots-txt',
48+
begin: '^[A-Z][a-z-]*',
49+
end: '\\s*:',
50+
},
51+
wildcard: {
52+
name: 'constant.character.wildcard.robots-txt',
53+
match: '\\*',
54+
},
55+
uri: {
56+
name: 'string.unquoted.uri.robots-txt',
57+
begin: '(?:[a-z]+:)\\/',
58+
end: '$',
59+
},
60+
text: {
61+
name: 'string.unquoted.text.robots-txt',
62+
match: '[A-Za-z-]+',
63+
},
64+
number: {
65+
name: 'constant.numeric.integer.robots-txt',
66+
match: '\\d',
67+
},
68+
},
69+
scopeName: 'text.robots-txt',
70+
}),
71+
],
72+
})
73+
return shiki.value
74+
}
2075

21-
export function highlight(code: string, lang: BundledLanguage) {
22-
if (!shiki.value)
23-
return code
24-
return shiki.value.codeToHtml(code, {
25-
lang,
26-
theme: mode.value === 'dark' ? 'vitesse-dark' : 'vitesse-light',
76+
export function renderCodeHighlight(code: MaybeRef<string>, lang?: BundledLanguage | 'robots-txt') {
77+
return computed(() => {
78+
const colorMode = devtools.value?.colorMode || 'light'
79+
return shiki.value!.codeToHtml(toValue(code), {
80+
lang,
81+
theme: colorMode === 'dark' ? 'vitesse-dark' : 'vitesse-light',
82+
}) || ''
2783
})
2884
}

0 commit comments

Comments
 (0)
Please sign in to comment.