diff --git a/.gitignore b/.gitignore index 427f298836..11fd77067a 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ Temporary Items # Workspaces packages/devtools/README.md + +clones diff --git a/package.json b/package.json index d82e5eb7ef..b502b11e5d 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "type": "module", "version": "0.5.5", "private": false, "packageManager": "pnpm@8.6.1", @@ -34,10 +35,12 @@ "eslint": "8.42.0", "esno": "^0.16.3", "execa": "^7.1.1", + "gray-matter": "^4.0.3", "lint-staged": "^13.2.2", "nuxt": "^3.5.2", "pathe": "^1.1.1", "simple-git-hooks": "^2.8.1", + "tiged": "^2.12.5", "typescript": "5.0.4", "unocss": "^0.53.0", "vite-hot-client": "^0.2.1", diff --git a/packages/devtools/client/components/CommandPalette.vue b/packages/devtools/client/components/CommandPalette.vue index 916f5fc154..544d17d0b6 100644 --- a/packages/devtools/client/components/CommandPalette.vue +++ b/packages/devtools/client/components/CommandPalette.vue @@ -1,67 +1,108 @@ @@ -71,27 +112,29 @@ useEventListener('keydown', (e) => { - - - {{ item.title }} + + + {{ item.title }} + {{ item.description }} - + @@ -105,12 +148,6 @@ useEventListener('keydown', (e) => { diff --git a/packages/devtools/client/composables/state-commands.ts b/packages/devtools/client/composables/state-commands.ts index f616dae8a1..3e3ff4bec7 100644 --- a/packages/devtools/client/composables/state-commands.ts +++ b/packages/devtools/client/composables/state-commands.ts @@ -4,8 +4,9 @@ import type { MaybeRefOrGetter } from 'vue' export interface CommandItem { id: string title: string + description?: string icon?: string - action: () => void + action: () => void | CommandItem[] | Promise } const registeredCommands = reactive(new Map>()) @@ -19,7 +20,17 @@ export function useCommands() { id: 'fixed:settings', title: 'Settings', icon: 'carbon-settings-adjust', - action: () => router.push('/settings'), + action: () => { + router.push('/settings') + }, + }, + { + id: 'fixed:docs', + title: 'Nuxt Documentations', + icon: 'logos-nuxt-icon', + action: () => { + return getNuxtDocsCommands() + }, }, ] @@ -58,3 +69,29 @@ export function registerCommands(getter: MaybeRefOrGetter) { registeredCommands.delete(id) }) } + +let _nuxtDocsCommands: CommandItem[] | undefined + +const docsIcons = [ + [':components:', 'i-carbon-assembly-cluster'], + [':modules:', 'i-carbon-cube'], + [':commands:', 'i-carbon-terminal'], + [':directory-structure:', 'i-carbon-folder'], + [':composables:', 'i-carbon-function'], + [':getting-started:', 'i-carbon-idea'], + [':api:', 'carbon-api-1'], +] + +export async function getNuxtDocsCommands() { + if (!_nuxtDocsCommands) { + const list = await import('../data/nuxt-docs.json').then(i => i.default) + _nuxtDocsCommands = list.map(i => ({ + ...i, + icon: docsIcons.find(([k]) => i.id.includes(k))?.[1] || 'i-carbon-document-multiple-01', + action: () => { + window.open(i.url, '_blank') + }, + })) + } + return _nuxtDocsCommands +} diff --git a/packages/devtools/client/data/nuxt-docs.json b/packages/devtools/client/data/nuxt-docs.json new file mode 100644 index 0000000000..42c3361b0a --- /dev/null +++ b/packages/devtools/client/data/nuxt-docs.json @@ -0,0 +1,722 @@ +[ + { + "id": "doc:getting-started:introduction", + "title": "Introduction", + "description": "Nuxt's goal is to make web development intuitive and performant with a great Developer Experience in mind.", + "url": "https://nuxt.com/docs/getting-started/introduction" + }, + { + "id": "doc:getting-started:deployment", + "title": "Deployment", + "description": "Deploy on a Node.js server, pre-render for static hosting and to serverless or edge environments.", + "url": "https://nuxt.com/docs/getting-started/deployment" + }, + { + "id": "doc:getting-started:testing", + "title": "Testing", + "url": "https://nuxt.com/docs/getting-started/testing" + }, + { + "id": "doc:getting-started:upgrade", + "title": "Upgrade Guide", + "description": "Have a Nuxt 2 project to migrate? Use these guides to upgrade your applications to Nuxt 3.", + "url": "https://nuxt.com/docs/getting-started/upgrade" + }, + { + "id": "doc:getting-started:installation", + "title": "Installation", + "url": "https://nuxt.com/docs/getting-started/installation" + }, + { + "id": "doc:getting-started:configuration", + "title": "Configuration", + "description": "Nuxt is configured with sensible defaults. The config file can override or extend them.", + "url": "https://nuxt.com/docs/getting-started/configuration" + }, + { + "id": "doc:getting-started:views", + "title": "Views", + "url": "https://nuxt.com/docs/getting-started/views" + }, + { + "id": "doc:getting-started:assets", + "title": "Assets", + "url": "https://nuxt.com/docs/getting-started/assets" + }, + { + "id": "doc:getting-started:routing", + "title": "Routing", + "description": "Nuxt file-system routing creates a route for every file in the pages/ directory.", + "url": "https://nuxt.com/docs/getting-started/routing" + }, + { + "id": "doc:getting-started:seo-meta", + "title": "SEO and Meta", + "description": "Improve your Nuxt app's SEO with powerful head config, composables and components.", + "url": "https://nuxt.com/docs/getting-started/seo-meta" + }, + { + "id": "doc:getting-started:transitions", + "title": "Transitions", + "description": "Nuxt leverages Vue's Transition component to apply transitions between pages and layouts.", + "url": "https://nuxt.com/docs/getting-started/transitions" + }, + { + "id": "doc:getting-started:data-fetching", + "title": "Data fetching", + "description": "Nuxt provides composables to handle data fetching within your application.", + "url": "https://nuxt.com/docs/getting-started/data-fetching" + }, + { + "id": "doc:getting-started:state-management", + "title": "State Management", + "description": "Nuxt provides powerful state management libraries and the useState composable to create a reactive and SSR-friendly shared state.", + "url": "https://nuxt.com/docs/getting-started/state-management" + }, + { + "id": "doc:getting-started:error-handling", + "title": "Error handling", + "url": "https://nuxt.com/docs/getting-started/error-handling" + }, + { + "id": "doc:getting-started:layers", + "title": "Layers", + "description": "Nuxt provides a powerful system that allows you to extend the default files, configs, and much more.", + "url": "https://nuxt.com/docs/getting-started/layers" + }, + { + "id": "doc:guide:concepts:auto-imports", + "title": "Auto imports", + "description": "Nuxt auto-imports helper functions, composables and Vue APIs.", + "url": "https://nuxt.com/docs/guide/concepts/auto-imports" + }, + { + "id": "doc:guide:concepts:vuejs-development", + "title": "Vue.js Development", + "description": "Nuxt uses Vue and adds features such as component auto-imports and file-based routing.", + "url": "https://nuxt.com/docs/guide/concepts/vuejs-development" + }, + { + "id": "doc:guide:concepts:rendering", + "title": "Rendering Modes", + "description": "Nuxt supports different rendering modes, univeral rendering, client-side rendering but also offers hybrid-rendering and the possibility to render on CDN Edge Servers.", + "url": "https://nuxt.com/docs/guide/concepts/rendering" + }, + { + "id": "doc:guide:concepts:server-engine", + "title": "Server Engine", + "url": "https://nuxt.com/docs/guide/concepts/server-engine" + }, + { + "id": "doc:guide:concepts:modules", + "title": "Modules", + "description": "Nuxt provides a module system to extend the framework core and simplify integrations.", + "url": "https://nuxt.com/docs/guide/concepts/modules" + }, + { + "id": "doc:guide:concepts:esm", + "title": "ES Modules", + "description": "Nuxt 3 (and Bridge) uses Native ES Modules.", + "url": "https://nuxt.com/docs/guide/concepts/esm" + }, + { + "id": "doc:guide:concepts:typescript", + "title": "TypeScript", + "description": "Nuxt 3 is fully typed and provides accurate type information when you are coding.", + "url": "https://nuxt.com/docs/guide/concepts/typescript" + }, + { + "id": "doc:guide:directory-structure:nuxt", + "title": ".nuxt", + "description": "Nuxt uses the .nuxt/ directory in development to generate your Vue application.", + "url": "https://nuxt.com/docs/guide/directory-structure/nuxt" + }, + { + "id": "doc:guide:directory-structure:output", + "title": ".output", + "description": "Nuxt creates the .output/ directory when building your application for production.", + "url": "https://nuxt.com/docs/guide/directory-structure/output" + }, + { + "id": "doc:guide:directory-structure:assets", + "title": "assets", + "description": "The assets/ directory is used to add all the website's assets that the build tool will process.", + "url": "https://nuxt.com/docs/guide/directory-structure/assets" + }, + { + "id": "doc:guide:directory-structure:components", + "title": "components", + "description": "The components/ directory is where you put all your Vue components.", + "url": "https://nuxt.com/docs/guide/directory-structure/components" + }, + { + "id": "doc:guide:directory-structure:composables", + "title": "composables", + "description": "Use the composables/ directory to auto-import your Vue composables into your application.", + "url": "https://nuxt.com/docs/guide/directory-structure/composables" + }, + { + "id": "doc:guide:directory-structure:content", + "title": "content", + "description": "The Content module reads the content/ directory to create a file-based CMS for your application.", + "url": "https://nuxt.com/docs/guide/directory-structure/content" + }, + { + "id": "doc:guide:directory-structure:layouts", + "title": "layouts", + "description": "Nuxt provides a layouts framework to extract common UI patterns into reusable layouts.", + "url": "https://nuxt.com/docs/guide/directory-structure/layouts" + }, + { + "id": "doc:guide:directory-structure:middleware", + "title": "middleware", + "description": "Nuxt provides middleware to run code before navigating to a particular route.", + "url": "https://nuxt.com/docs/guide/directory-structure/middleware" + }, + { + "id": "doc:guide:directory-structure:modules", + "title": "modules", + "description": "Use the modules/ directory to automatically register local modules within your application.", + "url": "https://nuxt.com/docs/guide/directory-structure/modules" + }, + { + "id": "doc:guide:directory-structure:node_modules", + "title": "node_modules", + "description": "The package manager stores the dependencies of your project in the node_modules/ directory.", + "url": "https://nuxt.com/docs/guide/directory-structure/node_modules" + }, + { + "id": "doc:guide:directory-structure:pages", + "title": "pages", + "description": "Nuxt provides a file-based routing to create routes within your web application.", + "url": "https://nuxt.com/docs/guide/directory-structure/pages" + }, + { + "id": "doc:guide:directory-structure:plugins", + "title": "plugins", + "description": "Nuxt reads the files in your plugins directory and loads them at the creation of the Vue application.", + "url": "https://nuxt.com/docs/guide/directory-structure/plugins" + }, + { + "id": "doc:guide:directory-structure:public", + "title": "public", + "description": "The public/ directory is used to serve your website's static assets.", + "url": "https://nuxt.com/docs/guide/directory-structure/public" + }, + { + "id": "doc:guide:directory-structure:server", + "title": "server", + "description": "The server/ directory is used to register API and server handlers to your application.", + "url": "https://nuxt.com/docs/guide/directory-structure/server" + }, + { + "id": "doc:guide:directory-structure:utils", + "title": "utils", + "description": "Use the utils/ directory to auto-import your utility functions throughout your application.", + "url": "https://nuxt.com/docs/guide/directory-structure/utils" + }, + { + "id": "doc:guide:directory-structure:env", + "title": ".env", + "description": "A .env file specifies your build/dev-time environment variables.", + "url": "https://nuxt.com/docs/guide/directory-structure/env" + }, + { + "id": "doc:guide:directory-structure:gitignore", + "title": ".gitignore", + "description": "A .gitignore file specifies intentionally untracked files that git should ignore.", + "url": "https://nuxt.com/docs/guide/directory-structure/gitignore" + }, + { + "id": "doc:guide:directory-structure:nuxtignore", + "title": ".nuxtignore", + "description": "The .nuxtignore file lets Nuxt ignore files in your project’s root directory during the build phase.", + "url": "https://nuxt.com/docs/guide/directory-structure/nuxtignore" + }, + { + "id": "doc:guide:directory-structure:app-config", + "title": "app.config.ts", + "description": "Nuxt 3 provides the app.config file to expose reactive configuration within your application.", + "url": "https://nuxt.com/docs/guide/directory-structure/app-config" + }, + { + "id": "doc:guide:directory-structure:app", + "title": "app.vue", + "description": "The app.vue file is the main component in your Nuxt 3 applications.", + "url": "https://nuxt.com/docs/guide/directory-structure/app" + }, + { + "id": "doc:guide:directory-structure:nuxt.config", + "title": "nuxt.config.ts", + "description": "Nuxt can be easily configured with a single nuxt.config file.", + "url": "https://nuxt.com/docs/guide/directory-structure/nuxt.config" + }, + { + "id": "doc:guide:directory-structure:package", + "title": "package.json", + "description": "The package.json file contains all the dependencies and scripts for your application.", + "url": "https://nuxt.com/docs/guide/directory-structure/package" + }, + { + "id": "doc:guide:directory-structure:tsconfig", + "title": "tsconfig.json", + "description": "Nuxt generates a .nuxt/tsconfig.json file with sensible defaults and your aliases.", + "url": "https://nuxt.com/docs/guide/directory-structure/tsconfig" + }, + { + "id": "doc:guide:going-further:internals", + "title": "How Nuxt Works?", + "description": "Nuxt is a minimal but highly customizable framework to build web applications.", + "url": "https://nuxt.com/docs/guide/going-further/internals" + }, + { + "id": "doc:guide:going-further:runtime-config", + "title": "Runtime Config", + "description": "Nuxt provides a runtime config API to expose configuration within your application.", + "url": "https://nuxt.com/docs/guide/going-further/runtime-config" + }, + { + "id": "doc:guide:going-further:edge-channel", + "title": "Edge Channel", + "description": "Edge channel allows to use latest commits from the repository.", + "url": "https://nuxt.com/docs/guide/going-further/edge-channel" + }, + { + "id": "doc:guide:going-further:hooks", + "title": "Lifecycle Hooks", + "description": "Nuxt provides a powerful hooking system to expand almost every aspect using hooks.", + "url": "https://nuxt.com/docs/guide/going-further/hooks" + }, + { + "id": "doc:guide:going-further:modules", + "title": "Module Author Guide", + "description": "Learn how to create a Nuxt Module to integrate, enhance or extend any Nuxt applications.", + "url": "https://nuxt.com/docs/guide/going-further/modules" + }, + { + "id": "doc:guide:going-further:kit", + "title": "Nuxt Kit", + "description": "@nuxt/kit provides features for module authors.", + "url": "https://nuxt.com/docs/guide/going-further/kit" + }, + { + "id": "doc:guide:going-further:nuxt-app", + "title": "NuxtApp", + "description": "In Nuxt 3, you can access runtime app context within composables, components and plugins.", + "url": "https://nuxt.com/docs/guide/going-further/nuxt-app" + }, + { + "id": "doc:guide:going-further:layers", + "title": "Authoring Nuxt Layers", + "description": "Nuxt provides a powerful system that allows you to extend the default files, configs, and much more.", + "url": "https://nuxt.com/docs/guide/going-further/layers" + }, + { + "id": "doc:guide:going-further:custom-routing", + "title": "Custom routing", + "description": "In Nuxt 3, your routing is defined by the structure of your files inside the pages directory. However, since it uses vue-router under the hood, Nuxt offers you several ways to add custom routes in your project.", + "url": "https://nuxt.com/docs/guide/going-further/custom-routing" + }, + { + "id": "doc:guide:going-further:debugging", + "title": "Debugging", + "description": "In Nuxt 3, you can get started with debugging your application directly in the browser as well as in your IDE.", + "url": "https://nuxt.com/docs/guide/going-further/debugging" + }, + { + "id": "doc:api:composables:use-app-config", + "title": "useAppConfig", + "url": "https://nuxt.com/docs/api/composables/use-app-config" + }, + { + "id": "doc:api:composables:use-async-data", + "title": "useAsyncData", + "description": "useAsyncData provides access to data that resolves asynchronously.", + "url": "https://nuxt.com/docs/api/composables/use-async-data" + }, + { + "id": "doc:api:composables:use-cookie", + "title": "useCookie", + "description": "useCookie is an SSR-friendly composable to read and write cookies.", + "url": "https://nuxt.com/docs/api/composables/use-cookie" + }, + { + "id": "doc:api:composables:use-error", + "title": "useError", + "description": "useError composable returns the global Nuxt error that is being handled.", + "url": "https://nuxt.com/docs/api/composables/use-error" + }, + { + "id": "doc:api:composables:use-fetch", + "title": "useFetch", + "url": "https://nuxt.com/docs/api/composables/use-fetch" + }, + { + "id": "doc:api:composables:use-head-safe", + "title": "useHeadSafe", + "description": "The recommended way to provide head data with user input.", + "url": "https://nuxt.com/docs/api/composables/use-head-safe" + }, + { + "id": "doc:api:composables:use-head", + "title": "useHead", + "description": "useHead customizes the head properties of individual pages of your Nuxt app.", + "url": "https://nuxt.com/docs/api/composables/use-head" + }, + { + "id": "doc:api:composables:use-hydration", + "title": "useHydration", + "url": "https://nuxt.com/docs/api/composables/use-hydration" + }, + { + "id": "doc:api:composables:use-lazy-async-data", + "title": "useLazyAsyncData", + "description": "This wrapper around useAsyncData triggers navigation immediately.", + "url": "https://nuxt.com/docs/api/composables/use-lazy-async-data" + }, + { + "id": "doc:api:composables:use-lazy-fetch", + "title": "useLazyFetch", + "description": "This wrapper around useFetch triggers navigation immediately.", + "url": "https://nuxt.com/docs/api/composables/use-lazy-fetch" + }, + { + "id": "doc:api:composables:use-nuxt-app", + "title": "useNuxtApp", + "url": "https://nuxt.com/docs/api/composables/use-nuxt-app" + }, + { + "id": "doc:api:composables:use-nuxt-data", + "title": "useNuxtData", + "url": "https://nuxt.com/docs/api/composables/use-nuxt-data" + }, + { + "id": "doc:api:composables:use-request-event", + "title": "useRequestEvent", + "description": "You can use useRequestEvent to access the incoming request.", + "url": "https://nuxt.com/docs/api/composables/use-request-event" + }, + { + "id": "doc:api:composables:use-request-headers", + "title": "useRequestHeaders", + "description": "Use useRequestHeaders to access the incoming request headers.", + "url": "https://nuxt.com/docs/api/composables/use-request-headers" + }, + { + "id": "doc:api:composables:use-request-url", + "title": "useRequestURL", + "url": "https://nuxt.com/docs/api/composables/use-request-url" + }, + { + "id": "doc:api:composables:use-route", + "title": "useRoute", + "description": "The useRoute composable returns the current route.", + "url": "https://nuxt.com/docs/api/composables/use-route" + }, + { + "id": "doc:api:composables:use-router", + "title": "useRouter", + "description": "The useRouter composable returns the router instance.", + "url": "https://nuxt.com/docs/api/composables/use-router" + }, + { + "id": "doc:api:composables:use-runtime-config", + "title": "useRuntimeConfig", + "url": "https://nuxt.com/docs/api/composables/use-runtime-config" + }, + { + "id": "doc:api:composables:use-seo-meta", + "title": "useSeoMeta", + "description": "The useSeoMeta composable lets you define your site's SEO meta tags as a flat object with full TypeScript support.", + "url": "https://nuxt.com/docs/api/composables/use-seo-meta" + }, + { + "id": "doc:api:composables:use-server-seo-meta", + "title": "useServerSeoMeta", + "description": "The useServerSeoMeta composable lets you define your site's SEO meta tags as a flat object with full TypeScript support.", + "url": "https://nuxt.com/docs/api/composables/use-server-seo-meta" + }, + { + "id": "doc:api:composables:use-state", + "title": "useState", + "description": "The useState composable creates a reactive and SSR-friendly shared state.", + "url": "https://nuxt.com/docs/api/composables/use-state" + }, + { + "id": "doc:api:components:client-only", + "title": "", + "description": "The component renders its slot only in client-side.", + "url": "https://nuxt.com/docs/api/components/client-only" + }, + { + "id": "doc:api:components:nuxt-client-fallback", + "title": "", + "description": "Nuxt provides `` component to render its content on the client if any of its children trigger an error in SSR", + "url": "https://nuxt.com/docs/api/components/nuxt-client-fallback" + }, + { + "id": "doc:api:components:nuxt-page", + "title": "", + "description": "The NuxtPage component is required to display pages located in the pages/ directory.", + "url": "https://nuxt.com/docs/api/components/nuxt-page" + }, + { + "id": "doc:api:components:nuxt-layout", + "title": "", + "url": "https://nuxt.com/docs/api/components/nuxt-layout" + }, + { + "id": "doc:api:components:nuxt-link", + "title": "", + "description": "Nuxt provides component to handle any kind of links within your application.", + "url": "https://nuxt.com/docs/api/components/nuxt-link" + }, + { + "id": "doc:api:components:nuxt-loading-indicator", + "title": "", + "url": "https://nuxt.com/docs/api/components/nuxt-loading-indicator" + }, + { + "id": "doc:api:components:nuxt-error-boundary", + "title": "", + "description": "The component handles client-side errors happening in its default slot.", + "url": "https://nuxt.com/docs/api/components/nuxt-error-boundary" + }, + { + "id": "doc:api:components:nuxt-welcome", + "title": "", + "description": "The `` component greets users in new projects made from the starter template.", + "url": "https://nuxt.com/docs/api/components/nuxt-welcome" + }, + { + "id": "doc:api:components:teleports", + "title": "", + "description": "The component teleports a component to a different location in the DOM.", + "url": "https://nuxt.com/docs/api/components/teleports" + }, + { + "id": "doc:api:utils:$fetch", + "title": "$fetch", + "description": "Nuxt uses ofetch to expose globally the $fetch helper for making HTTP requests.", + "url": "https://nuxt.com/docs/api/utils/$fetch" + }, + { + "id": "doc:api:utils:abort-navigation", + "title": "abortNavigation", + "url": "https://nuxt.com/docs/api/utils/abort-navigation" + }, + { + "id": "doc:api:utils:add-route-middleware", + "title": "addRouteMiddleware", + "description": "addRouteMiddleware() is a helper function to dynamically add middleware in your application.", + "url": "https://nuxt.com/docs/api/utils/add-route-middleware" + }, + { + "id": "doc:api:utils:clear-error", + "title": "clearError", + "description": "The clearError composable clears all handled errors.", + "url": "https://nuxt.com/docs/api/utils/clear-error" + }, + { + "id": "doc:api:utils:clear-nuxt-data", + "title": "clearNuxtData", + "url": "https://nuxt.com/docs/api/utils/clear-nuxt-data" + }, + { + "id": "doc:api:utils:create-error", + "title": "createError", + "description": "You can use this function to create an error object with additional metadata.", + "url": "https://nuxt.com/docs/api/utils/create-error" + }, + { + "id": "doc:api:utils:define-nuxt-component", + "title": "defineNuxtComponent", + "description": "defineNuxtComponent() is a helper function for defining type safe components with Options API.", + "url": "https://nuxt.com/docs/api/utils/define-nuxt-component" + }, + { + "id": "doc:api:utils:define-nuxt-route-middleware", + "title": "defineNuxtRouteMiddleware", + "url": "https://nuxt.com/docs/api/utils/define-nuxt-route-middleware" + }, + { + "id": "doc:api:utils:define-page-meta", + "title": "definePageMeta", + "url": "https://nuxt.com/docs/api/utils/define-page-meta" + }, + { + "id": "doc:api:utils:navigate-to", + "title": "navigateTo", + "description": "navigateTo is a helper function that programmatically navigates users.", + "url": "https://nuxt.com/docs/api/utils/navigate-to" + }, + { + "id": "doc:api:utils:on-before-route-leave", + "title": "onBeforeRouteLeave", + "description": "The onBeforeRouteLeave composable allows registering a route guard within a component.", + "url": "https://nuxt.com/docs/api/utils/on-before-route-leave" + }, + { + "id": "doc:api:utils:on-before-route-update", + "title": "onBeforeRouteUpdate", + "description": "The onBeforeRouteUpdate composable allows registering a route guard within a component.", + "url": "https://nuxt.com/docs/api/utils/on-before-route-update" + }, + { + "id": "doc:api:utils:on-nuxt-ready", + "title": "onNuxtReady", + "description": "The onNuxtReady composable allows running a callback after your app has finished initializing.", + "url": "https://nuxt.com/docs/api/utils/on-nuxt-ready" + }, + { + "id": "doc:api:utils:prefetch-components", + "title": "prefetchComponents", + "description": "Nuxt provides utilities to give you control over prefetching and preloading components.", + "url": "https://nuxt.com/docs/api/utils/prefetch-components" + }, + { + "id": "doc:api:utils:preload-components", + "title": "preloadComponents", + "description": "Nuxt provides utilities to give you control over prefetching and preloading components.", + "url": "https://nuxt.com/docs/api/utils/preload-components" + }, + { + "id": "doc:api:utils:preload-route-components", + "title": "preloadRouteComponents", + "url": "https://nuxt.com/docs/api/utils/preload-route-components" + }, + { + "id": "doc:api:utils:refresh-nuxt-data", + "title": "refreshNuxtData", + "description": "refreshNuxtData refetches all data from the server and updates the page.", + "url": "https://nuxt.com/docs/api/utils/refresh-nuxt-data" + }, + { + "id": "doc:api:utils:reload-nuxt-app", + "title": "reloadNuxtApp", + "description": "reloadNuxtApp will perform a hard reload of the page.", + "url": "https://nuxt.com/docs/api/utils/reload-nuxt-app" + }, + { + "id": "doc:api:utils:set-page-layout", + "title": "setPageLayout", + "description": "setPageLayout allows you to dynamically change the layout of a page.", + "url": "https://nuxt.com/docs/api/utils/set-page-layout" + }, + { + "id": "doc:api:utils:set-response-status", + "title": "setResponseStatus", + "description": "setResponseStatus sets the statusCode (and optionally the statusMessage) of the response.", + "url": "https://nuxt.com/docs/api/utils/set-response-status" + }, + { + "id": "doc:api:utils:show-error", + "title": "showError", + "url": "https://nuxt.com/docs/api/utils/show-error" + }, + { + "id": "doc:api:utils:update-app-config", + "title": "updateAppConfig", + "url": "https://nuxt.com/docs/api/utils/update-app-config" + }, + { + "id": "doc:api:advanced:hooks", + "title": "Lifecycle Hooks", + "description": "Nuxt provides a powerful hooking system to expand almost every aspect using hooks.", + "url": "https://nuxt.com/docs/api/advanced/hooks" + }, + { + "id": "doc:api:advanced:kit", + "title": "Kit Utilities", + "description": "Nuxt Kit provides composable utilities to help interacting with Nuxt Hooks and Nuxt Builder.", + "url": "https://nuxt.com/docs/api/advanced/kit" + }, + { + "id": "doc:api:commands:add", + "title": "nuxi add", + "description": "Scaffold an entity into your Nuxt application.", + "url": "https://nuxt.com/docs/api/commands/add" + }, + { + "id": "doc:api:commands:analyze", + "title": "nuxi analyze", + "description": "Analyze the production bundle or your Nuxt application.", + "url": "https://nuxt.com/docs/api/commands/analyze" + }, + { + "id": "doc:api:commands:build-module", + "title": "nuxi build-module", + "url": "https://nuxt.com/docs/api/commands/build-module" + }, + { + "id": "doc:api:commands:build", + "title": "nuxi build", + "description": "Build your Nuxt application.", + "url": "https://nuxt.com/docs/api/commands/build" + }, + { + "id": "doc:api:commands:cleanup", + "title": "nuxi cleanup", + "description": "Remove common generated Nuxt files and caches.", + "url": "https://nuxt.com/docs/api/commands/cleanup" + }, + { + "id": "doc:api:commands:dev", + "title": "nuxi dev", + "description": "The dev command starts a development server with hot module replacement at http://localhost:3000", + "url": "https://nuxt.com/docs/api/commands/dev" + }, + { + "id": "doc:api:commands:devtools", + "title": "nuxi devtools", + "description": "The devtools command allows you to enable or disable Nuxt DevTools on a per-project basis.", + "url": "https://nuxt.com/docs/api/commands/devtools" + }, + { + "id": "doc:api:commands:generate", + "title": "nuxi generate", + "description": "Pre-renders every route of the application and stores the result in plain HTML files.", + "url": "https://nuxt.com/docs/api/commands/generate" + }, + { + "id": "doc:api:commands:info", + "title": "nuxi info", + "description": "The info command logs information about the current or specified Nuxt project.", + "url": "https://nuxt.com/docs/api/commands/info" + }, + { + "id": "doc:api:commands:init", + "title": "nuxi init", + "description": "The init command initializes a fresh Nuxt project.", + "url": "https://nuxt.com/docs/api/commands/init" + }, + { + "id": "doc:api:commands:prepare", + "title": "nuxi prepare", + "description": "The prepare command creates a .nuxt directory in your application and generates types.", + "url": "https://nuxt.com/docs/api/commands/prepare" + }, + { + "id": "doc:api:commands:preview", + "title": "nuxi preview", + "description": "The preview command starts a server to preview your application after the build command.", + "url": "https://nuxt.com/docs/api/commands/preview" + }, + { + "id": "doc:api:commands:typecheck", + "title": "nuxi typecheck", + "description": "The typecheck command runs vue-tsc to check types throughout your app.", + "url": "https://nuxt.com/docs/api/commands/typecheck" + }, + { + "id": "doc:api:commands:upgrade", + "title": "nuxi upgrade", + "description": "The upgrade command upgrades Nuxt 3 to the latest version.", + "url": "https://nuxt.com/docs/api/commands/upgrade" + }, + { + "id": "doc:api:configuration:nuxt-config", + "title": "Nuxt Config", + "url": "https://nuxt.com/docs/api/configuration/nuxt-config" + } +] diff --git a/packages/devtools/client/pages/modules/analyze-build.vue b/packages/devtools/client/pages/modules/analyze-build.vue index 920b602846..c6e4bfc79e 100644 --- a/packages/devtools/client/pages/modules/analyze-build.vue +++ b/packages/devtools/client/pages/modules/analyze-build.vue @@ -53,7 +53,7 @@ function formatDuration(build: AnalyzeBuildMeta) { registerCommands(() => [ { - id: 'analyze-build: start', + id: 'action:analyze-build: start', title: 'Start a new analyze build', icon: 'i-carbon-edge-node', action: start, diff --git a/packages/devtools/client/pages/modules/modules.vue b/packages/devtools/client/pages/modules/modules.vue index 6688eeae99..7b47114cd1 100644 --- a/packages/devtools/client/pages/modules/modules.vue +++ b/packages/devtools/client/pages/modules/modules.vue @@ -15,7 +15,7 @@ const iconBase = 'https://api.nuxtjs.org/api/ipx/s_80,f_webp/gh/nuxt/modules/mai registerCommands(() => [ { - id: 'modules:install', + id: 'action:modules:install', title: 'Install a new module', icon: 'i-carbon-intent-request-create ', action: () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b039503143..b93e6312f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,6 +62,9 @@ importers: execa: specifier: ^7.1.1 version: 7.1.1 + gray-matter: + specifier: ^4.0.3 + version: 4.0.3 lint-staged: specifier: ^13.2.2 version: 13.2.2 @@ -74,6 +77,9 @@ importers: simple-git-hooks: specifier: ^2.8.1 version: 2.8.1 + tiged: + specifier: ^2.12.5 + version: 2.12.5 typescript: specifier: 5.0.4 version: 5.0.4 @@ -4404,6 +4410,10 @@ packages: /colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + /colorette@1.2.1: + resolution: {integrity: sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==} + dev: true + /colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -5175,6 +5185,13 @@ packages: graceful-fs: 4.2.11 tapable: 2.2.1 + /enquirer@2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + dev: true + /entities@3.0.1: resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} engines: {node: '>=0.12'} @@ -6238,6 +6255,10 @@ packages: engines: {node: '>=10'} dev: true + /fuzzysearch@1.0.3: + resolution: {integrity: sha512-s+kNWQuI3mo9OALw0HJ6YGmMbLqEufCh2nX/zzV5CrICQ/y4AwPxM+6TIiF9ItFCHXFCyM/BfCCmN57NTIJuPg==} + dev: true + /gauge@3.0.2: resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} engines: {node: '>=10'} @@ -6450,6 +6471,10 @@ packages: define-properties: 1.2.0 dev: true + /globalyzer@0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + dev: true + /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -6472,6 +6497,10 @@ packages: merge2: 1.4.1 slash: 4.0.0 + /globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + dev: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -6758,6 +6787,16 @@ packages: resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + /https-proxy-agent@5.0.0: + resolution: {integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -8438,6 +8477,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /mri@1.1.6: + resolution: {integrity: sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==} + engines: {node: '>=4'} + dev: true + /mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -10942,6 +10986,24 @@ packages: /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + /tiged@2.12.5: + resolution: {integrity: sha512-divl34KaEXBUO8N2m5UcMdQZjqLZRzEq+ychP5bNYSGF0JQq1j6m4uF7WuQOCRomlBeu5vJfjkXtyYumijX+bA==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + colorette: 1.2.1 + enquirer: 2.3.6 + fs-extra: 10.1.0 + fuzzysearch: 1.0.3 + https-proxy-agent: 5.0.0 + mri: 1.1.6 + rimraf: 3.0.2 + tar: 6.1.13 + tiny-glob: 0.2.8 + transitivePeerDependencies: + - supports-color + dev: true + /time-zone@1.0.0: resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} engines: {node: '>=4'} @@ -10951,6 +11013,13 @@ packages: resolution: {integrity: sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==} dev: true + /tiny-glob@0.2.8: + resolution: {integrity: sha512-vkQP7qOslq63XRX9kMswlby99kyO5OvKptw7AMwBVMjXEI7Tb61eoI5DydyEMOseyGS5anDN1VPoVxEvH01q8w==} + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + dev: true + /tiny-invariant@1.3.1: resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} diff --git a/scripts/nuxt-docs-manifest.ts b/scripts/nuxt-docs-manifest.ts new file mode 100644 index 0000000000..5653d3bc7d --- /dev/null +++ b/scripts/nuxt-docs-manifest.ts @@ -0,0 +1,64 @@ +import { existsSync } from 'node:fs' +import { fileURLToPath } from 'node:url' +import fs from 'node:fs/promises' +import { join } from 'node:path' +import fg from 'fast-glob' +import matter from 'gray-matter' + +// @ts-expect-error missing types +import tiged from 'tiged' + +const dir = fileURLToPath(new URL('../clones/nuxt', import.meta.url)) + +// clone nuxt/nuxt repo and get the docs +if (!existsSync(dir)) + await tiged('nuxt/nuxt').clone(dir) + +const files = await fg(['docs/**/*.md'], { + ignore: [ + '**/README.md', + '**/**index.md', + 'docs/4.examples/**', + 'docs/5.community/**', + 'docs/6.bridge/**', + 'docs/7.migration/**', + ], + cwd: dir, + onlyFiles: true, +}).then(r => r.sort()) + +const headerMatch = /^#+(.*)$/ +function getTitleMarkdown(text: string) { + const lines = text.split('\n') + const noEmptyLines = lines.filter((line) => { + return line.length > 0 + }) + if (noEmptyLines.length === 0) + throw new Error('no content') + + const firstLine = noEmptyLines[0] + const match = firstLine.match(headerMatch) + if (match == null) + return + + const title = match && match[1] + return title.trim() +} + +const manifest = await Promise.all(files.map(async (file) => { + const filepath = join(dir, file) + const { data, content } = matter(await fs.readFile(filepath, 'utf-8')) + const path = file.replace(/\/\d+\./g, '/').replace(/\.md$/, '').replace(/\/index$/, '').replace(/^docs/, '') + const id = `doc${path.replace(/\//g, ':')}` + const title = (data.title || getTitleMarkdown(content) || '').trim().replace(/`/g, '').replace(/\s/g, ' ') + if (!title) + return + return { + id, + title, + description: data.description?.replace(/\s/g, ' '), + url: `https://nuxt.com/docs${path}`, + } +})).then(r => r.filter(Boolean)) + +await fs.writeFile(fileURLToPath(new URL('../packages/devtools/client/data/nuxt-docs.json', import.meta.url)), JSON.stringify(manifest, null, 2))