From: Eduardo San Martin Morote Date: Tue, 10 Jan 2023 22:50:20 +0000 (+0100) Subject: docs: fix slug generation api X-Git-Tag: @pinia/nuxt@0.4.7~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e7fe4d7f4f21afb132074f5865747f4730a51b5;p=thirdparty%2Fvuejs%2Fpinia.git docs: fix slug generation api --- diff --git a/packages/docs-new/.vitepress/config/shared.ts b/packages/docs-new/.vitepress/config/shared.ts index 0a20fd94..514837f5 100644 --- a/packages/docs-new/.vitepress/config/shared.ts +++ b/packages/docs-new/.vitepress/config/shared.ts @@ -23,17 +23,11 @@ export const sharedConfig = defineConfig({ dark: 'dracula-soft', light: 'vitesse-light', }, + attrs: { leftDelimiter: '%{', rightDelimiter: '}%', }, - // TODO: are these needed for API maybe? - // anchor: { - // permalink: renderPermaLink, - // }, - // config: (md) => { - // md.use(MarkDownItCustomAnchor) - // }, }, head: [ diff --git a/packages/docs-new/run-typedoc.js b/packages/docs-new/run-typedoc.js new file mode 100644 index 00000000..841fbe0f --- /dev/null +++ b/packages/docs-new/run-typedoc.js @@ -0,0 +1,15 @@ +const { createTypeDocApp } = require('./typedoc-markdown') +const path = require('path') + +createTypeDocApp({ + name: 'API Documentation', + tsconfig: path.resolve(__dirname, './typedoc.tsconfig.json'), + // entryPointStrategy: 'packages', + githubPages: false, + disableSources: true, + entryPoints: [ + path.resolve(__dirname, '../pinia/src/index.ts'), + path.resolve(__dirname, '../testing/src/index.ts'), + path.resolve(__dirname, '../nuxt/src/module.ts'), + ], +}).build() diff --git a/packages/docs-new/typedoc-markdown.js b/packages/docs-new/typedoc-markdown.js new file mode 100644 index 00000000..c94b3c70 --- /dev/null +++ b/packages/docs-new/typedoc-markdown.js @@ -0,0 +1,154 @@ +const _fs = require('fs') +const path = require('path') +const TypeDoc = require('typedoc') +const { PageEvent } = TypeDoc +const { + prependYAML, +} = require('typedoc-plugin-markdown/dist/utils/front-matter') + +const fs = _fs.promises + +const DEFAULT_OPTIONS = { + // disableOutputCheck: true, + cleanOutputDir: true, + excludeInternal: true, + readme: 'none', + out: path.resolve(__dirname, './api'), + entryDocument: 'index.md', + hideBreadcrumbs: false, + hideInPageTOC: true, +} + +/** + * + * @param {Partial} config + */ +exports.createTypeDocApp = function createTypeDocApp(config = {}) { + const options = { + ...DEFAULT_OPTIONS, + ...config, + } + + const app = new TypeDoc.Application() + + // If you want TypeDoc to load tsconfig.json / typedoc.json files + app.options.addReader(new TypeDoc.TSConfigReader()) + // app.options.addReader(new TypeDoc.TypeDocReader()) + + /** @type {'build' | 'serve'} */ + let targetMode = 'build' + + const slugify = (s) => s.replaceAll(' ', '-') + // encodeURIComponent(String(s).trim().toLowerCase().replace(/\s+/g, '-')) + + app.renderer.on( + PageEvent.END, + /** + * + * @param {import('typedoc/dist/lib/output/events').PageEvent} page + */ + (page) => { + if (page.url !== 'index.md' && page.contents) { + page.contents = prependYAML(page.contents, { + sidebar: 'auto', + // TODO: figure out a way to point to the source files? + editLinks: false, + sidebarDepth: 3, + }) + } + + // avoid duplicated id titles + if (page.contents) { + const lines = page.contents.split('\n') + const titleStack = [] + let currentLevel = 0 + const TITLE_LEVEL = /^#+/ + const existingIds = new Map() + for (let i = 0; i < lines.length; i++) { + const line = lines[i] + if (!line.startsWith('#')) continue + const level = line.match(TITLE_LEVEL)[0].length + + // remove extra levels + if (level <= currentLevel) { + titleStack.splice(level - 1) + } + // add the current title + titleStack.push(line.slice(level).trim()) + currentLevel = level + + const slugifiedTitle = slugify(titleStack.join('-')) + let id + if (existingIds.has(slugifiedTitle)) { + const current = existingIds.get(slugifiedTitle) + existingIds.set(slugifiedTitle, current + 1) + id = ` %{#${slugifiedTitle}_${current + 1}}%` + } else { + existingIds.set(slugifiedTitle, 0) + id = ` %{#${slugifiedTitle}}%` + } + const newLine = line + id + lines.splice(i, 1, newLine) + } + + page.contents = lines.join('\n') + } + } + ) + + async function serve() { + app.bootstrap(options) + app.convertAndWatch(handleProject) + } + + async function build() { + if ( + (await exists(options.out)) && + (await fs.stat(options.out)).isDirectory() + ) { + await fs.rm(options.out, { recursive: true }) + } + app.bootstrap(options) + const project = app.convert() + return handleProject(project) + } + + /** + * + * @param {import('typedoc').ProjectReflection} project + */ + async function handleProject(project) { + if (project) { + // Rendered docs + try { + await app.generateDocs(project, options.out) + app.logger.info(`generated at ${options.out}.`) + } catch (error) { + app.logger.error(error) + } + } else { + app.logger.error('No project') + } + } + + return { + build, + serve, + /** + * + * @param {'build' | 'serve'} command + */ + setTargetMode(command) { + targetMode = command + }, + } +} + +async function exists(path) { + try { + await fs.access(path) + return true + } catch { + return false + } +} diff --git a/packages/docs-new/typedoc.tsconfig.json b/packages/docs-new/typedoc.tsconfig.json new file mode 100644 index 00000000..a93dc1c7 --- /dev/null +++ b/packages/docs-new/typedoc.tsconfig.json @@ -0,0 +1,46 @@ +{ + "include": ["../pinia/src/global.d.ts", "../*/src/**/*.ts"], + "exclude": [ + "../test-vue-2", + "../pinia/__tests__/test-utils.ts", + "../pinia/test-dts", + "../*/__tests__/**/*.ts", + "../*/src/*.spec.ts", + "../nuxt/playground", + "../nuxt/src/runtime", + "**/*.spec.ts" + ], + "compilerOptions": { + "baseUrl": ".", + "rootDir": "..", + "outDir": "dist", + "sourceMap": false, + "noEmit": true, + "paths": { + "@pinia/*": ["../*/src"], + "pinia": ["../pinia/src"] + }, + + "target": "esnext", + "module": "esnext", + "moduleResolution": "node", + "allowJs": false, + "skipLibCheck": true, + + "noUnusedLocals": true, + "strictNullChecks": true, + "noImplicitAny": true, + "noImplicitThis": true, + "noImplicitReturns": false, + "strict": true, + "isolatedModules": true, + + "experimentalDecorators": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "removeComments": false, + "jsx": "preserve", + "lib": ["esnext", "dom"], + "types": ["vitest", "node", "vite/client"] + } +} diff --git a/packages/docs-new/vite-typedoc-plugin.ts b/packages/docs-new/vite-typedoc-plugin.ts new file mode 100644 index 00000000..006b644a --- /dev/null +++ b/packages/docs-new/vite-typedoc-plugin.ts @@ -0,0 +1,19 @@ +import { Plugin } from 'vite' +import _fs from 'fs' +import { TypeDocOptions } from 'typedoc' +import { createTypeDocApp } from './typedoc-markdown' + +export default function TypeDocPlugin( + config: Partial = {} +): Plugin { + const { serve, setTargetMode } = createTypeDocApp(config) + setTargetMode('serve') + + return { + name: 'typedoc', + apply: 'serve', + buildStart() { + return serve() + }, + } +} diff --git a/packages/docs-new/vite.config.ts b/packages/docs-new/vite.config.ts new file mode 100644 index 00000000..a084967b --- /dev/null +++ b/packages/docs-new/vite.config.ts @@ -0,0 +1,47 @@ +import { defineConfig, Plugin } from 'vite' +import _fs from 'fs' +import path from 'path' +// import TypeDocPlugin from './vite-typedoc-plugin' + +const fs = _fs.promises + +export default defineConfig({ + clearScreen: false, + plugins: [ + ...(process.env.NETLIFY ? [] : [copyPiniaPlugin()]), + // TODO: actual plugin that works well + // TypeDocPlugin({ + // name: 'Pinia', + // entryPoints: [ + // path.resolve(__dirname, '../pinia/src/index.ts'), + // path.resolve(__dirname, '../testing/src/index.ts'), + // path.resolve(__dirname, '../nuxt/src/index.ts'), + // ], + // }), + ], + define: { + __DEV__: 'true', + __BROWSER__: 'true', + }, + optimizeDeps: { + exclude: ['vue-demi', '@vueuse/shared', '@vueuse/core', 'pinia'], + }, +}) + +function copyPiniaPlugin(): Plugin { + return { + name: 'copy-pinia', + async generateBundle() { + const filePath = path.resolve(__dirname, '../pinia/dist/pinia.mjs') + + // throws if file doesn't exist + await fs.access(filePath) + + this.emitFile({ + type: 'asset', + fileName: 'pinia.mjs', + source: await fs.readFile(filePath, 'utf-8'), + }) + }, + } +}