diff --git a/.gitignore b/.gitignore index 6ec85c7..9f21b18 100644 --- a/.gitignore +++ b/.gitignore @@ -167,4 +167,4 @@ test_output/ !build.spec **/.vitepress/cache docs/frontend/components/** -docs/frontend/composables/** +# docs/frontend/composables/** diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 3be3514..496a6a1 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -1,12 +1,21 @@ import path from 'node:path' import fs from 'node:fs' import { defineConfig } from 'vitepress' +import { genTsDocs } from './scripts' +/** + * Paths + */ const projectPath = path.resolve(__filename, '..', '..', '..') -const docsFrontendPath = path.join(projectPath, 'docs', 'frontend') + const srcFrontendPath = path.join(projectPath, 'src', 'frontend') +const srcComposablesPath = path.join(srcFrontendPath, 'composables') + +const docsFrontendPath = path.join(projectPath, 'docs', 'frontend') +const docsComponentsPath = path.join(docsFrontendPath, 'components') +const docsComposablesPath = path.join(docsFrontendPath, 'composables') -const docsComponents = fs.readdirSync(path.join(docsFrontendPath, 'components')) +const docsComponents = fs.readdirSync(docsComponentsPath) const componentsSidebarItems = docsComponents .filter((f) => { const [name, ext] = f.split('.') @@ -16,6 +25,21 @@ const componentsSidebarItems = docsComponents return { text: name, link: `/${name}` } }) +const srcComposables = fs.readdirSync(srcComposablesPath) +genTsDocs({ + dirPath: docsComposablesPath, + inputFiles: srcComposables.map(f => path.join(srcComposablesPath, f)), +}) +const docsComposables = fs.readdirSync(docsComposablesPath) +const composablesSidebarItems = docsComposables + .filter((f) => { + const [name, ext] = f.split('.') + return name !== 'index' && ext === 'md' + }).map((f) => { + const name = f.split('.')[0] + return { text: name, link: `/${name}` } + }) + export default defineConfig({ lang: 'en-US', title: 'AudioSplitter', @@ -61,7 +85,7 @@ export default defineConfig({ text: 'Composables', base: '/frontend/composables', collapsed: false, - items: [], + items: composablesSidebarItems, }, ], }, diff --git a/docs/.vitepress/scripts.ts b/docs/.vitepress/scripts.ts new file mode 100644 index 0000000..a2cf203 --- /dev/null +++ b/docs/.vitepress/scripts.ts @@ -0,0 +1,54 @@ +import { existsSync, mkdirSync, writeFileSync } from 'node:fs' +import path from 'node:path' +import type { DocEntry } from 'tsdoc-markdown' +import { buildDocumentation } from 'tsdoc-markdown' + +export function genTsDocs({ dirPath, inputFiles }: { inputFiles: string[]; dirPath: string }) { + const entries = buildDocumentation({ inputFiles }) + + if (!existsSync(dirPath)) + mkdirSync(dirPath) + + entries.forEach((entry) => { + const md = genMD(entry) + const targetPath = path.join(dirPath, `${entry.name}.md`) + writeFileSync(targetPath, md, { flag: 'w' }) + }) +} + +function genMD(entry: DocEntry) { + // entry.name === 'useRandomColor' && console.log(JSON.stringify(entry, null, 4)) + const md = [] + + md.push(`# ${entry.name}`) + md.push(`${entry.documentation}`) + + const params = entry.jsDocs.filter(d => d.name === 'param') + if (params.length) { + md.push('## Parameters') + md.push('| Name | Description |') + md.push('|------|-------------|') + + params.forEach((d) => { + const [name, desc] = d.text.filter(t => t.kind !== 'space') + md.push(`|${name?.text}|${desc?.text}|`) + }) + } + + // TODO Make this section better + if (entry.type) { + const returns = entry.jsDocs.find(d => d.name === 'returns') + + md.push('## Returns') + md.push(returns?.text?.[0]?.text) + md.push(`\`\`\`\n${entry.type}\n\`\`\``) + } + + const examples = entry.jsDocs.filter(d => d.name === 'example') + if (examples.length) { + md.push('## Examples') + examples.forEach(e => e.text.forEach(t => md.push(t.text))) + } + + return md.join('\n') +} diff --git a/docs/frontend/composables/useConvertSecToMin.md b/docs/frontend/composables/useConvertSecToMin.md new file mode 100644 index 0000000..edf33aa --- /dev/null +++ b/docs/frontend/composables/useConvertSecToMin.md @@ -0,0 +1,18 @@ +# useConvertSecToMin +Converts a duration in seconds to a formatted string representation in minutes and seconds. +## Parameters +| Name | Description | +|------|-------------| +|secs|The duration in seconds to convert.| +## Returns +A formatted string representing the duration in minutes and seconds. +``` +(secs: number) => string +``` +## Examples +```ts +useConvertSecToMin(135) // 2m 15s + +useConvertSecToMin(120) // 2m + +``` \ No newline at end of file diff --git a/docs/frontend/composables/useDarkToggle.md b/docs/frontend/composables/useDarkToggle.md new file mode 100644 index 0000000..2fd6b98 --- /dev/null +++ b/docs/frontend/composables/useDarkToggle.md @@ -0,0 +1,16 @@ +# useDarkToggle +Toggles between light and dark modes. +## Returns +An object with `isDark` (current mode) and `toggle` (toggle function). +``` +() => { isDark: WritableComputedRef; toggle: (value?: boolean) => boolean; } +``` +## Examples +```ts +const {isDark, toggle} = useDark() + +isDark.value // false +toggle() +isDark.value // true + +``` \ No newline at end of file diff --git a/docs/frontend/composables/useDateFormat.md b/docs/frontend/composables/useDateFormat.md new file mode 100644 index 0000000..a524a47 --- /dev/null +++ b/docs/frontend/composables/useDateFormat.md @@ -0,0 +1,18 @@ +# useDateFormat +Format a date-like object into a predefined or custom format. +## Parameters +| Name | Description | +|------|-------------| +|date|The date-like object to format.| +|format|The date format, either a predefined format ('DD/MM/YYYY') or a custom format string.| +## Returns +The formatted date as a string. +``` +(date: DateLike, format: "DD/MM/YYYY" | Omit) => string +``` +## Examples +```ts +useDateFormat(new Date(), 'DD/MM/YYYY') // 22/09/2023 + +useDateFormat(new Date(), 'dddd DD/MM') // Friday 22/09 +``` \ No newline at end of file diff --git a/docs/frontend/composables/useDocTitle.md b/docs/frontend/composables/useDocTitle.md new file mode 100644 index 0000000..08ba2e7 --- /dev/null +++ b/docs/frontend/composables/useDocTitle.md @@ -0,0 +1,20 @@ +# useDocTitle +Set the document's title with an optional prefix. +## Parameters +| Name | Description | +|------|-------------| +|title|The title to set.| +|prefix|An optional prefix to prepend to the title.| +## Returns + +``` +(title: string, prefix?: string) => void +``` +## Examples +```ts +useDocTitle('New Title') +document.title // DefaultPrefix New Title + +useDocTitle('New Title', 'MyPrefix') +document.title // MyPrefix New Title +``` \ No newline at end of file diff --git a/docs/frontend/composables/useDriver.md b/docs/frontend/composables/useDriver.md new file mode 100644 index 0000000..f7845ac --- /dev/null +++ b/docs/frontend/composables/useDriver.md @@ -0,0 +1,14 @@ +# useDriver +Provides access to the Driver.js instance and configuration for guided tours. +## Returns +An object containing the Driver.js instance and a function to set its configuration. +``` +() => { driver: any; setConfig: (config: Omit) => void; } +``` +## Examples +```ts +const {driver, setConfig} = useDriver() + +setConfig({}) +driver.value.doSomething() +``` \ No newline at end of file diff --git a/docs/frontend/composables/useGet.md b/docs/frontend/composables/useGet.md new file mode 100644 index 0000000..ee0ef25 --- /dev/null +++ b/docs/frontend/composables/useGet.md @@ -0,0 +1,20 @@ +# useGet +Execute a GET request and manage the response data, loading state, and errors. +## Parameters +| Name | Description | +|------|-------------| +|config|The configuration for the GET request.| +## Returns +An object containing the response data, loading state, error message, and an execution function. +``` +(config: GetConfig) => { data: any; isFetching: any; error: any; execute: () => void; } +``` +## Examples +```ts +const { data, isFetching, error, execute } = useGet({ + url: '/api/example', + onSuccess(data){ + // + } +}) +``` \ No newline at end of file diff --git a/docs/frontend/composables/useHash.md b/docs/frontend/composables/useHash.md new file mode 100644 index 0000000..c5f76dc --- /dev/null +++ b/docs/frontend/composables/useHash.md @@ -0,0 +1,15 @@ +# useHash +Generate a hash value for a given string. +## Parameters +| Name | Description | +|------|-------------| +|str|The input string to hash.| +## Returns +A hashed representation of the input string. +``` +(str: string) => string +``` +## Examples +```ts +useHash('somerandomstring') // 19viky0 +``` \ No newline at end of file diff --git a/docs/frontend/composables/useLocale.md b/docs/frontend/composables/useLocale.md new file mode 100644 index 0000000..af21a76 --- /dev/null +++ b/docs/frontend/composables/useLocale.md @@ -0,0 +1,17 @@ +# useLocale +Manage the application's locale and localization settings. +## Returns +An object containing available locales and the current locale. +``` +() => { availableLocales: string[]; currentLocale: RemovableRef; } +``` +## Examples +```ts +const { currentLocale } = useLocale() + +currentLocale.value // en +document.documentElement.lang // en + +currentLocale.value = 'de' +document.documentElement.lang // de +``` \ No newline at end of file diff --git a/docs/frontend/composables/usePost.md b/docs/frontend/composables/usePost.md new file mode 100644 index 0000000..75bd17c --- /dev/null +++ b/docs/frontend/composables/usePost.md @@ -0,0 +1,21 @@ +# usePost +Execute a POST request and manage the response data, loading state, and errors. +## Parameters +| Name | Description | +|------|-------------| +|config|The configuration for the POST request.| +## Returns +An object containing the response data, loading state, error message, and an execution function. +``` +(config: PostConfig) => { data: any; isFetching: any; error: any; execute: (body?: unknown) => void; } +``` +## Examples +```ts +const { data, isFetching, error, execute } = useGet({ + url: '/api/example', + body: { filePath: '/tmp/some.mp3' }, + onSuccess(data){ + // + } +}) +``` \ No newline at end of file diff --git a/docs/frontend/composables/useRandomColor.md b/docs/frontend/composables/useRandomColor.md new file mode 100644 index 0000000..546d83e --- /dev/null +++ b/docs/frontend/composables/useRandomColor.md @@ -0,0 +1,11 @@ +# useRandomColor +Generate a random RGBA color string with 50% opacity. +## Returns +A random RGBA color string in the format "rgba(r, g, b, 0.5)". +``` +() => string +``` +## Examples +```ts +useRandomColor() // rgba(123, 203, 78, 0.5) +``` \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b8024c0..de2c02e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "jsdom": "^22.1.0", "orval": "^6.17.0", "taze": "^0.11.2", + "tsdoc-markdown": "^0.1.0", "typescript": "^5.1.3", "unocss": "^0.55.7", "unplugin-auto-import": "^0.16.6", @@ -12677,6 +12678,18 @@ } } }, + "node_modules/tsdoc-markdown": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tsdoc-markdown/-/tsdoc-markdown-0.1.0.tgz", + "integrity": "sha512-V2zayxM+QPukAoTs0WZhkL2SxX2he9l0PXlmkkB5rQN7mpwuk02zTnOAtKOZiU069QzBK51Jy7lBwQPfZvwglw==", + "dev": true, + "bin": { + "tsdoc": "bin/index.js" + }, + "peerDependencies": { + "typescript": "^5" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", diff --git a/package.json b/package.json index d7c93c7..b5e2198 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "jsdom": "^22.1.0", "orval": "^6.17.0", "taze": "^0.11.2", + "tsdoc-markdown": "^0.1.0", "typescript": "^5.1.3", "unocss": "^0.55.7", "unplugin-auto-import": "^0.16.6", diff --git a/src/frontend/components/SettingsGeneral.vue b/src/frontend/components/SettingsGeneral.vue index 6de5bd4..aefa421 100644 --- a/src/frontend/components/SettingsGeneral.vue +++ b/src/frontend/components/SettingsGeneral.vue @@ -4,7 +4,7 @@ import { LangMap, SUPPORT_FILE_TYPES } from '../includes/constants' const { t } = useI18n() -const { currentLocal } = useLocale() +const { currentLocale } = useLocale() const localOpts = Object.entries(LangMap).map(([key, value]) => ({ label: value, value: key })) const saveSettings = useLocalStorage('save-settings', { fileType: 'mp3', shouldAsk: true }) @@ -23,7 +23,7 @@ const saveSettings = useLocalStorage('save-settings', { fileType: 'mp3', shouldA

{{ t('settings.general.language') }}

diff --git a/src/frontend/composables/useConvertSecToMin.ts b/src/frontend/composables/useConvertSecToMin.ts index 056bfa1..a707f54 100644 --- a/src/frontend/composables/useConvertSecToMin.ts +++ b/src/frontend/composables/useConvertSecToMin.ts @@ -1,8 +1,16 @@ /** * Converts a duration in seconds to a formatted string representation in minutes and seconds. * - * @param secs - The duration in seconds to convert. - * @returns A formatted string representing the duration in minutes and seconds, + * @param secs The duration in seconds to convert. + * @returns A formatted string representing the duration in minutes and seconds. + * + * @example + * ```ts + * useConvertSecToMin(135) // 2m 15s + * + * useConvertSecToMin(120) // 2m + * + * ``` */ export function useConvertSecToMin(secs: number) { const _secs = Math.floor(secs) diff --git a/src/frontend/composables/useDarkToggle.ts b/src/frontend/composables/useDarkToggle.ts index 441efbf..b75e794 100644 --- a/src/frontend/composables/useDarkToggle.ts +++ b/src/frontend/composables/useDarkToggle.ts @@ -4,6 +4,16 @@ import { useDark, useToggle } from '@vueuse/core' * Toggles between light and dark modes. * * @returns An object with `isDark` (current mode) and `toggle` (toggle function). + * + * @example + * ```ts + * const {isDark, toggle} = useDark() + * + * isDark.value // false + * toggle() + * isDark.value // true + * + * ``` */ export function useDarkToggle() { const isDark = useDark() diff --git a/src/frontend/composables/useDateFormat.ts b/src/frontend/composables/useDateFormat.ts index d22bb43..d14a893 100644 --- a/src/frontend/composables/useDateFormat.ts +++ b/src/frontend/composables/useDateFormat.ts @@ -6,11 +6,17 @@ type PredefinedFormats = 'DD/MM/YYYY' /** * Format a date-like object into a predefined or custom format. * - * @param date - The date-like object to format. - * @param format - The date format, either a predefined format ('DD/MM/YYYY') - * or a custom format string. + * @param date The date-like object to format. + * @param format The date format, either a predefined format ('DD/MM/YYYY') or a custom format string. * * @returns The formatted date as a string. + * + * @example + * ```ts + * useDateFormat(new Date(), 'DD/MM/YYYY') // 22/09/2023 + * + * useDateFormat(new Date(), 'dddd DD/MM') // Friday 22/09 + * ``` */ export function useDateFormat(date: DateLike, format: PredefinedFormats | Omit) { return formatter(date, format as string).value diff --git a/src/frontend/composables/useDocTitle.ts b/src/frontend/composables/useDocTitle.ts index ed92264..6973aeb 100644 --- a/src/frontend/composables/useDocTitle.ts +++ b/src/frontend/composables/useDocTitle.ts @@ -1,8 +1,17 @@ /** * Set the document's title with an optional prefix. * - * @param title - The title to set. - * @param prefix - An optional prefix to prepend to the title. + * @param title The title to set. + * @param prefix An optional prefix to prepend to the title. + * + * @example + * ```ts + * useDocTitle('New Title') + * document.title // DefaultPrefix New Title + * + * useDocTitle('New Title', 'MyPrefix') + * document.title // MyPrefix New Title + * ``` */ export function useDocTitle(title: string, prefix = `${import.meta.env.VITE_APP_NAME} | `) { if (!document) diff --git a/src/frontend/composables/useDriver.ts b/src/frontend/composables/useDriver.ts index 081aa05..cb2ef74 100644 --- a/src/frontend/composables/useDriver.ts +++ b/src/frontend/composables/useDriver.ts @@ -7,6 +7,14 @@ const driver = shallowRef(createDriver()) * Provides access to the Driver.js instance and configuration for guided tours. * * @returns An object containing the Driver.js instance and a function to set its configuration. + * + * @example + * ```ts + * const {driver, setConfig} = useDriver() + * + * setConfig({}) + * driver.value.doSomething() + * ``` */ export function useDriver() { const { t } = useI18n() diff --git a/src/frontend/composables/useGet.ts b/src/frontend/composables/useGet.ts index c906977..cae8f19 100644 --- a/src/frontend/composables/useGet.ts +++ b/src/frontend/composables/useGet.ts @@ -9,8 +9,18 @@ interface GetConfig { /** * Execute a GET request and manage the response data, loading state, and errors. * - * @param config - The configuration for the GET request. + * @param config The configuration for the GET request. * @returns An object containing the response data, loading state, error message, and an execution function. + * + * @example + * ```ts + * const { data, isFetching, error, execute } = useGet({ + * url: '/api/example', + * onSuccess(data){ + * // + * } + * }) + * ``` */ export function useGet(config: GetConfig) { const data = ref() diff --git a/src/frontend/composables/useHash.ts b/src/frontend/composables/useHash.ts index b72f4ce..68239c6 100644 --- a/src/frontend/composables/useHash.ts +++ b/src/frontend/composables/useHash.ts @@ -2,8 +2,13 @@ /** * Generate a hash value for a given string. * - * @param str - The input string to hash. + * @param str The input string to hash. * @returns A hashed representation of the input string. + * + * @example + * ```ts + * useHash('somerandomstring') // 19viky0 + * ``` */ export function useHash(str: string) { let hash = 0 diff --git a/src/frontend/composables/useLocale.ts b/src/frontend/composables/useLocale.ts index 64ab2b9..1db8742 100644 --- a/src/frontend/composables/useLocale.ts +++ b/src/frontend/composables/useLocale.ts @@ -8,21 +8,26 @@ import { * Manage the application's locale and localization settings. * * @returns An object containing available locales and the current locale. + * + * @example + * ```ts + * const { currentLocale } = useLocale() + * + * currentLocale.value // en + * document.documentElement.lang // en + * + * currentLocale.value = 'de' + * document.documentElement.lang // de + * ``` */ export function useLocale() { + const currentLocale = useLocalStorage('locale', 'en') const { locale } = useI18n() - if (!locale.value) - locale.value = 'en' - - const currentLocal = useLocalStorage('locale', locale.value) - - if (currentLocal.value !== locale.value) - currentLocal.value = locale.value - watch(currentLocal, () => { - setI18nLanguage(currentLocal.value) - locale.value = currentLocal.value - }) + watch(currentLocale, () => { + setI18nLanguage(currentLocale.value) + locale.value = currentLocale.value + }, { immediate: true }) - return { availableLocales, currentLocal } + return { availableLocales, currentLocale } } diff --git a/src/frontend/composables/usePost.ts b/src/frontend/composables/usePost.ts index 4222add..f72f2fb 100644 --- a/src/frontend/composables/usePost.ts +++ b/src/frontend/composables/usePost.ts @@ -10,8 +10,19 @@ interface PostConfig { /** * Execute a POST request and manage the response data, loading state, and errors. * - * @param config - The configuration for the POST request. + * @param config The configuration for the POST request. * @returns An object containing the response data, loading state, error message, and an execution function. + * + * @example + * ```ts + * const { data, isFetching, error, execute } = useGet({ + * url: '/api/example', + * body: { filePath: '/tmp/some.mp3' }, + * onSuccess(data){ + * // + * } + * }) + * ``` */ export function usePost(config: PostConfig) { const data = ref() diff --git a/src/frontend/composables/useRandomColor.ts b/src/frontend/composables/useRandomColor.ts index 45b30d4..6a2016a 100644 --- a/src/frontend/composables/useRandomColor.ts +++ b/src/frontend/composables/useRandomColor.ts @@ -3,6 +3,11 @@ const random = (min: number, max: number) => Math.random() * (max - min) + min * Generate a random RGBA color string with 50% opacity. * * @returns A random RGBA color string in the format "rgba(r, g, b, 0.5)". + * + * @example + * ```ts + * useRandomColor() // rgba(123, 203, 78, 0.5) + * ``` */ export function useRandomColor() { return `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.5)` diff --git a/src/frontend/docgen.config.js b/src/frontend/docgen.config.js index 14635a3..820c953 100644 --- a/src/frontend/docgen.config.js +++ b/src/frontend/docgen.config.js @@ -7,19 +7,22 @@ module.exports = defineConfig({ outDir: 'docs/frontend/components', templates: { props(props) { - let md = '| Name | Description | Type | Default |\n | ----------- | ----------- |----------- |----------- |\n' + const md = [] + md.push('## Props') + md.push('| Name | Description | Type | Default |') + md.push('| ---- | ----------- |----- |-------- |') - props.forEach(({ name, description, required, type, defaultValue, tags }) => { + props.forEach(({ name, description, required, type, defaultValue }) => { let typeCol = type.elements?.length ? type.elements.map(e => e.name.replaceAll('\"', '\'')).join(', ') : type.name if (!required) typeCol += ' (optional)' - md += `|${name}| ${description ?? ''}|${typeCol}|${defaultValue?.value ?? ''}|\n` + md.push(`|${name}| ${description ?? ''}|${typeCol}|${defaultValue?.value ?? ''}|`) }) - return md + return md.join('\n') }, }, })