Skip to content

Commit

Permalink
feat: Nuxt Dev Tools integration
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Oct 31, 2023
1 parent a9e8046 commit 2fdeb4c
Show file tree
Hide file tree
Showing 14 changed files with 848 additions and 118 deletions.
38 changes: 36 additions & 2 deletions .playground/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { resolve } from 'node:path'
import { defineNuxtConfig } from 'nuxt/config'
import { defineNuxtModule } from '@nuxt/kit'
import { startSubprocess } from '@nuxt/devtools-kit'
import NuxtSimpleSitemap from '../src/module'

export default defineNuxtConfig({
Expand All @@ -9,6 +12,39 @@ export default defineNuxtConfig({
'@nuxt/content',
'@nuxt/ui',
'nuxt-icon',
/**
* Start a sub Nuxt Server for developing the client
*
* The terminal output can be found in the Terminals tab of the devtools.
*/
defineNuxtModule({
setup(_, nuxt) {
if (!nuxt.options.dev)
return

const subprocess = startSubprocess(
{
command: 'npx',
args: ['nuxi', 'dev', '--port', '3030'],
cwd: resolve(__dirname, '../client'),
},
{
id: 'nuxt-simple-sitemap:client',
name: 'Nuxt Simple Sitemap Client Dev',
},
)
subprocess.getProcess().stdout?.on('data', (data) => {
console.log(` sub: ${data.toString()}`)
})

process.on('exit', () => {
subprocess.terminate()
})

// process.getProcess().stdout?.pipe(process.stdout)
// process.getProcess().stderr?.pipe(process.stderr)
},
}),
],
ignorePrefix: 'ignore-',
i18n: {
Expand Down Expand Up @@ -39,8 +75,6 @@ export default defineNuxtConfig({
// baseURL: '/base'
// },

devtools: true,

robots: {
indexable: true,
},
Expand Down
1 change: 1 addition & 0 deletions client/.nuxtrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
imports.autoImport=true
69 changes: 69 additions & 0 deletions client/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script setup lang="ts">
import { ref } from 'vue'
import { loadShiki } from './composables/shiki'
import { data, refreshSources } from './composables/state'
await loadShiki()
const loading = ref(false)
async function refresh() {
loading.value = true
await refreshSources()
setTimeout(() => {
loading.value = false
}, 300)
}
</script>

<template>
<div class="relative p8 n-bg-base flex flex-col h-screen">
<div>
<div class="flex justify-between" mb6>
<div>
<h1 text-xl mb2 flex items-center gap-2>
<NIcon icon="carbon:load-balancer-application text-blue-300" />
Nuxt Simple Sitemap <span v-if="data?.buildTimeMeta" class="text-sm opacity-60">{{ data.buildTimeMeta.version }}</span>
</h1>
</div>
</div>
</div>
<div class="flex items-center space-x-5">
<div>
<h2 text-lg mb2 flex items-center gap-2>
<NIcon icon="carbon:connect-source opacity-50" />
Sources <span class="text-sm opacity-60">{{ data?.sources.length }}</span>
</h2>
<p text-sm op60 mb3>
See the sources used to generate your sitemap.
</p>
</div>
<button
class="mr-5 hover:shadow-lg text-xs transition items-center gap-2 inline-flex border-green-500/50 border-1 rounded-lg shadow-sm px-3 py-1"
@click="refresh"
>
<div v-if="!loading">
Refresh
</div>
<NIcon v-else icon="carbon:progress-bar-round" class="animated animate-spin op50 text-xs" />
</button>
</div>
<div class="space-y-10">
<div v-for="source in data?.sources">
<div v-if="source.count > 0" class="mb-3">
<h3 class="text-gray-800 text-base mb-1">
{{ source.context }} <span class="bg-gray-100 rounded text-gray-500 px-1 text-xs">{{ source.count }}</span>
</h3>
<div v-if="source.path" class="text-sm flex items-center opacity-70 space-x-3">
<div>{{ source.path }}</div>
<div v-if="source.timeTakenMs" class="text-gray-700">
{{ source.timeTakenMs }}ms
</div>
</div>
</div>
<OCodeBlock class="max-h-[350px] max-w-2/3 overflow-y-auto" :code="JSON.stringify(source.urls, null, 2)" lang="json" />
</div>
</div>
<div class="flex-auto" />
</div>
</template>
46 changes: 46 additions & 0 deletions client/components/OCodeBlock.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script setup lang="ts">
import type { Lang } from 'shiki-es'
import { computed } from 'vue'
import { renderCodeHighlight } from '../composables/shiki'
const props = withDefaults(
defineProps<{
code: string
lang?: Lang
lines?: boolean
transformRendered?: (code: string) => string
}>(),
{
lines: true,
},
)
const rendered = computed(() => {
const code = renderCodeHighlight(props.code, props.lang)
return props.transformRendered ? props.transformRendered(code.value || '') : code.value
})
</script>

<template>
<pre
class="n-code-block"
:class="lines ? 'n-code-block-lines' : ''"
v-html="rendered"
/>
</template>

<style>
.n-code-block-lines .shiki code {
counter-reset: step;
counter-increment: step calc(var(--start, 1) - 1);
}
.n-code-block-lines .shiki code .line::before {
content: counter(step);
counter-increment: step;
width: 2rem;
padding-right: 0.5rem;
margin-right: 0.5rem;
display: inline-block;
text-align: right;
--at-apply: text-truegray:50;
}
</style>
3 changes: 3 additions & 0 deletions client/composables/dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createTemplatePromise } from '@vueuse/core'

export const FixDialog = createTemplatePromise<boolean, [any]>()
15 changes: 15 additions & 0 deletions client/composables/rpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { onDevtoolsClientConnected } from '@nuxt/devtools-kit/iframe-client'
import type { $Fetch } from 'nitropack'
import { ref } from 'vue'
import type { NuxtDevtoolsClient } from '@nuxt/devtools-kit/dist/types'
import { refreshSources } from './state'

export const appFetch = ref<$Fetch>()

export const devtools = ref<NuxtDevtoolsClient>()

onDevtoolsClientConnected(async (client) => {
appFetch.value = client.host.app.$fetch
devtools.value = client.devtools
refreshSources()
})
39 changes: 39 additions & 0 deletions client/composables/shiki.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { Highlighter, Lang } from 'shiki-es'
import { getHighlighter } from 'shiki-es'
import { computed, ref, unref } from 'vue'
import type { MaybeRef } from '@vueuse/core'
import { devtools } from './rpc'

export const shiki = ref<Highlighter>()

export function loadShiki() {
// Only loading when needed
return getHighlighter({
themes: [
'vitesse-dark',
'vitesse-light',
],
langs: [
'css',
'javascript',
'typescript',
'html',
'vue',
'vue-html',
'bash',
'diff',
],
}).then((i) => {
shiki.value = i
})
}

export function renderCodeHighlight(code: MaybeRef<string>, lang?: Lang) {
return computed(() => {
const colorMode = devtools.value?.colorMode || 'light'
return shiki.value!.codeToHtml(unref(code), {
lang,
theme: colorMode === 'dark' ? 'vitesse-dark' : 'vitesse-light',
}) || ''
})
}
9 changes: 9 additions & 0 deletions client/composables/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ref } from 'vue'
import { appFetch } from './rpc'

export const data = ref<any>(null)

export async function refreshSources() {
if (appFetch.value)
data.value = await appFetch.value('/api/__sitemap__/debug')
}
20 changes: 20 additions & 0 deletions client/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { resolve } from 'pathe'
import DevtoolsUIKit from '@nuxt/devtools-ui-kit'

export default defineNuxtConfig({
ssr: false,
modules: [
DevtoolsUIKit,
],
devtools: {
enabled: false,
},
nitro: {
output: {
publicDir: resolve(__dirname, '../dist/client'),
},
},
app: {
baseURL: '/__nuxt-simple-sitemap',
},
})
4 changes: 4 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "nuxt-simple-sitemap-client",
"private": true
}
23 changes: 14 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "nuxt-simple-sitemap",
"type": "module",
"version": "3.4.1",
"packageManager": "pnpm@8.9.2",
"packageManager": "pnpm@8.10.0",
"description": "Powerfully flexible XML Sitemaps that integrate seamlessly, for Nuxt.",
"license": "MIT",
"funding": "https://github.com/sponsors/harlan-zw",
Expand All @@ -28,8 +28,11 @@
],
"scripts": {
"lint": "eslint . --fix",
"build": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt-module-build build",
"client:build": "nuxi generate client",
"client:dev": "nuxi dev client --port 3300",
"build": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt-module-build build && npm run client:build",
"dev": "nuxi dev .playground",
"dev:devtool": "nuxi dev .playground-devtools",
"dev:build": "nuxi build .playground",
"dev:prepare": "nuxt-module-build --stub && nuxi prepare .playground",
"release": "bumpp package.json --commit --push --tag",
Expand All @@ -40,20 +43,22 @@
"@nuxt/kit": "^3.8.0",
"chalk": "^5.3.0",
"defu": "^6.1.3",
"@nuxt/devtools-ui-kit": "^1.0.0",
"sirv": "^2.0.3",
"escape-string-regexp": "^5.0.0",
"fast-glob": "^3.3.1",
"knitwork": "^1.0.0",
"nuxt-site-config": "^1.5.4",
"nuxt-site-config-kit": "^1.5.4",
"nuxt-site-config": "^1.5.5",
"nuxt-site-config-kit": "^1.5.5",
"pathe": "^1.1.1",
"radix3": "^1.1.0",
"semver": "^7.5.4",
"site-config-stack": "^1.5.4",
"site-config-stack": "^1.5.5",
"ufo": "^1.3.1"
},
"devDependencies": {
"@antfu/eslint-config": "^1.0.0-beta.28",
"@nuxt/content": "^2.8.5",
"@antfu/eslint-config": "^1.0.0-beta.29",
"@nuxt/content": "^2.9.0",
"@nuxt/kit": "^3.8.0",
"@nuxt/module-builder": "^0.5.2",
"@nuxt/test-utils": "^3.8.0",
Expand All @@ -64,8 +69,8 @@
"eslint": "8.52.0",
"execa": "^8.0.1",
"nuxt": "^3.8.0",
"nuxt-icon": "^0.5.0",
"nuxt-simple-robots": "^3.1.6",
"nuxt-icon": "^0.6.1",
"nuxt-simple-robots": "^3.1.9",
"vitest": "^0.34.6"
},
"build": {
Expand Down
Loading

0 comments on commit 2fdeb4c

Please sign in to comment.