diff --git a/CHANGELOG.md b/CHANGELOG.md index 69acb42..efa8f18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.9.2](https://github.com/aspida/pathpida/compare/v0.9.1...v0.9.2) (2020-12-25) + + +### Bug Fixes + +* replace params of nuxtjs ([8ef26ef](https://github.com/aspida/pathpida/commit/8ef26ef46a0759e2f1f826f1080d2688c3d22dfa)) + ### [0.9.1](https://github.com/aspida/pathpida/compare/v0.9.0...v0.9.1) (2020-12-25) diff --git a/README.md b/README.md index f28c42c..4cf8df9 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ import { pagesPath } from '../lib/$path' console.log(pagesPath.post.create.$url({ query: { userId: 1 }})) // { pathname: '/post/create', query: { userId: 1 }} console.log(pagesPath.post.create.$url()) // type error console.log(pagesPath.post._pid(1).$url()) // { pathname: '/post/[pid]', query: { pid: 1 }} -console.log(pagesPath.post._pid(1).$url({ query: { limit: 10 }, hash: '#sample' })) // { pathname: '/post/[pid]', query: { pid: 1, limit: 10 }, hash: '#sample' } +console.log(pagesPath.post._pid(1).$url({ query: { limit: 10 }, hash: 'sample' })) // { pathname: '/post/[pid]', query: { pid: 1, limit: 10 }, hash: 'sample' } export default () => { const onclick = useCallback(() => { @@ -312,7 +312,7 @@ export default Vue.extend({ methods: { onclick() { this.$router.push(this.$pagesPath.post._pid(1).$url()) - this.$router.push(this.$pagesPath.post._pid(1).$url({ query: { limit: 10 }, hash: '#sample' })) + this.$router.push(this.$pagesPath.post._pid(1).$url({ query: { limit: 10 }, hash: 'sample' })) } } }) diff --git a/__tests__/index.spec.ts b/__tests__/index.spec.ts index 67b9d5d..78c2fea 100644 --- a/__tests__/index.spec.ts +++ b/__tests__/index.spec.ts @@ -1,6 +1,6 @@ import fs from 'fs' import { version } from '../package.json' -import build from '../src/buildTemplate' +import build, { resetCache } from '../src/buildTemplate' import getConfig from '../src/getConfig' import { run } from '../src/cli' @@ -18,8 +18,13 @@ describe('cli test', () => { test('main', () => { fs.readdirSync('projects').forEach(dir => { + resetCache() + const basePath = `projects/${dir}` - const { type, input, staticDir, output, trailingSlash } = getConfig(true, basePath) + const { type, input, staticDir, output, trailingSlash } = getConfig( + dir !== 'nuxtjs-no-slash', + basePath + ) const result = fs.readFileSync(`${output}/$path.ts`, 'utf8') const { filePath, text } = build({ type, input, staticDir, output, trailingSlash }) diff --git a/package.json b/package.json index bfee6bd..f146dc0 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "pathpida", - "version": "0.9.1", + "version": "0.9.2", "description": "TypeScript friendly pages path generator for Next.js and Nuxt.js", "author": "Solufa ", "license": "MIT", "types": "dist/cli.d.ts", "bin": "bin/index.js", "scripts": { - "dev": "npm run build && cd projects/nextjs && node ../../bin/index.js -s && cd ../nuxtjs && node ../../bin/index.js --enableStatic", + "dev": "npm run build && cd projects/nextjs && node ../../bin/index.js -s && cd ../nuxtjs && node ../../bin/index.js --enableStatic && cd ../nuxtjs-no-slash && node ../../bin/index.js", "build": "npm run rimraf && tsc", "rimraf": "node -e \"require('fs').rmdirSync('dist', { recursive: true })\"", "release": "standard-version --skip.tag", diff --git a/projects/nuxtjs-no-slash/nuxt.config.ts b/projects/nuxtjs-no-slash/nuxt.config.ts new file mode 100644 index 0000000..b7e0acd --- /dev/null +++ b/projects/nuxtjs-no-slash/nuxt.config.ts @@ -0,0 +1,3 @@ +export default { + router: {} +} diff --git a/projects/nuxtjs-no-slash/pages/_pid.tsx b/projects/nuxtjs-no-slash/pages/_pid.tsx new file mode 100644 index 0000000..77fe644 --- /dev/null +++ b/projects/nuxtjs-no-slash/pages/_pid.tsx @@ -0,0 +1,23 @@ +import Link from 'next/link' + +export type OptionalQuery = { hoge: string } + +// `onClick`, `href`, and `ref` need to be passed to the DOM element +// for proper handling +const MyButton = React.forwardRef(({ onClick, href }, ref) => { + return ( + + Click Me + + ) +}) + +function Home() { + return ( + + + + ) +} + +export default Home diff --git a/projects/nuxtjs-no-slash/pages/aaa/_bbb/ccc.vue b/projects/nuxtjs-no-slash/pages/aaa/_bbb/ccc.vue new file mode 100644 index 0000000..e69de29 diff --git a/projects/nuxtjs-no-slash/pages/blog/_slug.tsx b/projects/nuxtjs-no-slash/pages/blog/_slug.tsx new file mode 100644 index 0000000..7ae7fce --- /dev/null +++ b/projects/nuxtjs-no-slash/pages/blog/_slug.tsx @@ -0,0 +1,23 @@ +import Link from 'next/link' + +export type Query = { hoge: string } + +// `onClick`, `href`, and `ref` need to be passed to the DOM element +// for proper handling +const MyButton = React.forwardRef(({ onClick, href }, ref) => { + return ( + + Click Me + + ) +}) + +function Home() { + return ( + + + + ) +} + +export default Home diff --git a/projects/nuxtjs-no-slash/pages/index.tsx b/projects/nuxtjs-no-slash/pages/index.tsx new file mode 100644 index 0000000..b559183 --- /dev/null +++ b/projects/nuxtjs-no-slash/pages/index.tsx @@ -0,0 +1,94 @@ +import Head from 'next/head' +import { useCallback, useState, FormEvent, ChangeEvent } from 'react' +import useAspidaSWR from '@aspida/swr' +import styles from '~/styles/Home.module.css' +import { apiClient } from '~/utils/apiClient' +import { Task } from '<%= orm === "prisma" ? "$prisma/client" : "$/types" %>' +import UserBanner from '~/components/UserBanner' + +export type Query = { hoge: string } + +const Home = () => { + const { data: tasks, error, revalidate } = useAspidaSWR(apiClient.tasks) + const [label, setLabel] = useState('') + const inputLabel = useCallback((e: ChangeEvent) => setLabel(e.target.value), []) + + const createTask = useCallback( + async (e: FormEvent) => { + e.preventDefault() + if (!label) return + + await apiClient.tasks.post({ body: { label } }) + setLabel('') + revalidate() + }, + [label] + ) + + const toggleDone = useCallback(async (task: Task) => { + await apiClient.tasks._taskId(task.id).patch({ body: { done: !task.done } }) + revalidate() + }, []) + + const deleteTask = useCallback(async (task: Task) => { + await apiClient.tasks._taskId(task.id).delete() + revalidate() + }, []) + + if (error) return
failed to load
+ if (!tasks) return
loading...
+ + return ( +
+ + frourio-todo-app + + + +
+ + +

+ Welcome to Next.js! +

+ +

frourio-todo-app

+ +
+
+ + +
+
    + {tasks.map(task => ( +
  • + + deleteTask(task)} + /> +
  • + ))} +
+
+
+ + +
+ ) +} + +export default Home diff --git a/projects/nuxtjs-no-slash/plugins/$path.ts b/projects/nuxtjs-no-slash/plugins/$path.ts new file mode 100644 index 0000000..6465089 --- /dev/null +++ b/projects/nuxtjs-no-slash/plugins/$path.ts @@ -0,0 +1,57 @@ +/* eslint-disable */ +import { Plugin } from '@nuxt/types' + +type Query0 = { hoge: string } + +type OptionalQuery1 = { hoge: string } + +type Query2 = { hoge: string } + +export const pagesPath = { + _pid: (pid: string | number) => ({ + $url: (url?: { query?: OptionalQuery1, hash?: string }) => ({ path: `/${pid}`, query: url?.query as any, hash: url?.hash }) + }), + aaa: { + _bbb: (bbb: string | number) => ({ + ccc: { + $url: (url?: { hash?: string }) => ({ path: `/aaa/${bbb}/ccc`, hash: url?.hash }) + } + }) + }, + blog: { + _slug: (slug: string | number) => ({ + $url: (url: { query: Query2, hash?: string }) => ({ path: `/blog/${slug}`, query: url.query as any, hash: url.hash }) + }) + }, + $url: (url: { query: Query0, hash?: string }) => ({ path: '/', query: url.query as any, hash: url.hash }) +} + +export type PagesPath = typeof pagesPath + +declare module 'vue/types/vue' { + interface Vue { + $pagesPath: PagesPath + } +} + +declare module '@nuxt/types' { + interface NuxtAppOptions { + $pagesPath: PagesPath + } + + interface Context { + $pagesPath: PagesPath + } +} + +declare module 'vuex/types/index' { + interface Store { + $pagesPath: PagesPath + } +} + +const pathPlugin: Plugin = (_, inject) => { + inject('pagesPath', pagesPath) +} + +export default pathPlugin diff --git a/projects/nuxtjs-no-slash/static/aa.json b/projects/nuxtjs-no-slash/static/aa.json new file mode 100644 index 0000000..e69de29 diff --git a/projects/nuxtjs-no-slash/static/bb/cc.png b/projects/nuxtjs-no-slash/static/bb/cc.png new file mode 100644 index 0000000..e69de29 diff --git a/projects/nuxtjs/plugins/$path.ts b/projects/nuxtjs/plugins/$path.ts index 52f4fa0..55308b5 100644 --- a/projects/nuxtjs/plugins/$path.ts +++ b/projects/nuxtjs/plugins/$path.ts @@ -9,21 +9,21 @@ type Query2 = { hoge: string } export const pagesPath = { _pid: (pid: string | number) => ({ - $url: (url?: { query?: OptionalQuery1, hash?: string }) => ({ path: '/:pid/' as const, params: { pid } as any, query: url?.query as any, hash: url?.hash }) + $url: (url?: { query?: OptionalQuery1, hash?: string }) => ({ path: `/${pid}/`, query: url?.query as any, hash: url?.hash }) }), aaa: { _bbb: (bbb: string | number) => ({ ccc: { - $url: (url?: { hash?: string }) => ({ path: '/aaa/:bbb/ccc/' as const, params: { bbb } as any, hash: url?.hash }) + $url: (url?: { hash?: string }) => ({ path: `/aaa/${bbb}/ccc/`, hash: url?.hash }) } }) }, blog: { _slug: (slug: string | number) => ({ - $url: (url: { query: Query2, hash?: string }) => ({ path: '/blog/:slug/' as const, params: { slug } as any, query: url.query as any, hash: url.hash }) + $url: (url: { query: Query2, hash?: string }) => ({ path: `/blog/${slug}/`, query: url.query as any, hash: url.hash }) }) }, - $url: (url: { query: Query0, hash?: string }) => ({ path: '/' as const, query: url.query as any, hash: url.hash }) + $url: (url: { query: Query0, hash?: string }) => ({ path: '/', query: url.query as any, hash: url.hash }) } export type PagesPath = typeof pagesPath diff --git a/src/buildTemplate.ts b/src/buildTemplate.ts index ffebca6..61dfff5 100644 --- a/src/buildTemplate.ts +++ b/src/buildTemplate.ts @@ -7,6 +7,11 @@ import createStaticTemplate from './createStaticTemplate' let prevPagesText = '' let prevStaticText = '' +export const resetCache = () => { + prevPagesText = '' + prevStaticText = '' +} + export default ( { type, input, staticDir, output, trailingSlash }: Config, mode?: 'pages' | 'static' diff --git a/src/createNuxtTemplate.ts b/src/createNuxtTemplate.ts index ca02c10..c0011fe 100644 --- a/src/createNuxtTemplate.ts +++ b/src/createNuxtTemplate.ts @@ -1,20 +1,17 @@ import fs from 'fs' import path from 'path' -type Slugs = string[] - const createMethods = ( indent: string, importName: string | undefined, - slugs: Slugs, pathname: string, trailingSlash: boolean ) => `${indent} $url: (url${importName?.startsWith('Query') ? '' : '?'}: { ${ importName ? `query${importName.startsWith('Optional') ? '?' : ''}: ${importName}, ` : '' - }hash?: string }) => ({ path: '${pathname}${trailingSlash ? '/' : ''}' as const${ - slugs.length ? `, params: { ${slugs.join(', ')} } as any` : '' - }${ + }hash?: string }) => ({ path: ${/\${/.test(pathname) ? '`' : "'"}${pathname}${ + trailingSlash || pathname === '' ? '/' : '' + }${/\${/.test(pathname) ? '`' : "'"}${ importName ? `, query: url${importName.startsWith('Query') ? '' : '?'}.query as any` : '' }, hash: url${importName?.startsWith('Query') ? '' : '?'}.hash })` @@ -58,7 +55,6 @@ export default (input: string, trailingSlash = false) => { importBasePath: string, indent: string, url: string, - slugs: Slugs, text: string, methodsOfIndexTsFile?: string ) => { @@ -70,7 +66,6 @@ export default (input: string, trailingSlash = false) => { .filter(file => !file.startsWith('-')) .sort() .forEach((file, _, arr) => { - const newSlugs = [...slugs] const basename = path.basename(file, path.extname(file)) let valFn = `${indent}${basename .replace(/(-|\.|!| |'|\*|\(|\))/g, '_') @@ -80,8 +75,7 @@ export default (input: string, trailingSlash = false) => { if (basename.startsWith('_')) { const slug = basename.slice(1) valFn = `${indent}_${slug}: (${slug}: string | number) => ({\n<% next %>\n${indent}})` - newSlugs.push(slug) - newUrl = `${url}/:${slug}` + newUrl = `${url}/\${${slug}}` } const target = path.posix.join(targetDir, file) @@ -90,7 +84,7 @@ export default (input: string, trailingSlash = false) => { props.push( valFn.replace( '<% next %>', - createMethods(indent, getImportName(target), newSlugs, newUrl, trailingSlash) + createMethods(indent, getImportName(target), newUrl, trailingSlash) ) ) } else if (fs.statSync(target).isDirectory()) { @@ -103,7 +97,6 @@ export default (input: string, trailingSlash = false) => { methods = createMethods( indent, getImportName(path.posix.join(target, indexFile)), - newSlugs, newUrl, trailingSlash ) @@ -115,7 +108,6 @@ export default (input: string, trailingSlash = false) => { `${importBasePath}/${file}`, indent, newUrl, - newSlugs, valFn.replace('<% next %>', '<% props %>'), methods ) @@ -141,13 +133,12 @@ export default (input: string, trailingSlash = false) => { rootMethods = createMethods( rootIndent, getImportName(path.posix.join(input, rootIndexFile)), - [], '', trailingSlash ) } - const text = createQueryString(input, '.', rootIndent, '', [], `{\n<% props %>\n}`, rootMethods) + const text = createQueryString(input, '.', rootIndent, '', `{\n<% props %>\n}`, rootMethods) return `/* eslint-disable */ import { Plugin } from '@nuxt/types'