Skip to content

Commit

Permalink
chore: add back stylistic rules and lint project
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Mar 9, 2024
1 parent 3782ac0 commit 7252b56
Show file tree
Hide file tree
Showing 78 changed files with 433 additions and 301 deletions.
56 changes: 56 additions & 0 deletions .eslintrc
Expand Up @@ -12,11 +12,67 @@
},
"plugins": ["jsdoc", "import", "unicorn", "no-only-tests"],
"extends": [
"standard",
"plugin:jsdoc/recommended",
"@nuxt/eslint-config",
"plugin:import/typescript"
],
"rules": {
// Imports should come first
"import/first": "error",
// Other import rules
"import/no-mutable-exports": "error",
// Allow unresolved imports
"import/no-unresolved": "off",
// Allow paren-less arrow functions only when there's no braces
"arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }],
// Allow async-await
"generator-star-spacing": "off",
// Prefer const over let
"prefer-const": ["error", { "destructuring": "any", "ignoreReadBeforeAssign": false }],
// No single if in an "else" block
"no-lonely-if": "error",
// Force curly braces for control flow,
// including if blocks with a single statement
"curly": ["error", "all"
],
// No async function without await
"require-await": "error",
// Force dot notation when possible
"dot-notation": "error",

"no-var": "error",
// Force object shorthand where possible
"object-shorthand": "error",
// No useless destructuring/importing/exporting renames
"no-useless-rename": "error",
/**********************/
/* Unicorn Rules */
/**********************/
// Pass error message when throwing errors
"unicorn/error-message": "error",
// Uppercase regex escapes
"unicorn/escape-case": "error",
// Array.isArray instead of instanceof
"unicorn/no-array-instanceof": "error",
// Prevent deprecated `new Buffer()`
"unicorn/no-new-buffer": "error",
// Keep regex literals safe!
"unicorn/no-unsafe-regex": "off",
// Lowercase number formatting for octal, hex, binary (0x12 instead of 0X12)
"unicorn/number-literal-case": "error",
// ** instead of Math.pow()
"unicorn/prefer-exponentiation-operator": "error",
// includes over indexOf when checking for existence
"unicorn/prefer-includes": "error",
// String methods startsWith/endsWith instead of more complicated stuff
"unicorn/prefer-starts-ends-with": "error",
// textContent instead of innerText
"unicorn/prefer-text-content": "error",
// Enforce throwing type error when throwing error while checking typeof
"unicorn/prefer-type-error": "error",
// Use new when throwing error
"unicorn/throw-new-error": "error",
"sort-imports": [
"error",
{
Expand Down
4 changes: 2 additions & 2 deletions nuxt.config.ts
Expand Up @@ -9,8 +9,8 @@ export default defineNuxtConfig({
function () {
addPluginTemplate({
filename: 'plugins/my-plugin.mjs',
getContents: () => `export default defineNuxtPlugin({ name: 'my-plugin' })`
getContents: () => 'export default defineNuxtPlugin({ name: \'my-plugin\' })'
})
}
],
]
})
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -60,6 +60,7 @@
"consola": "3.2.3",
"devalue": "4.3.2",
"eslint": "8.57.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jsdoc": "48.2.1",
"eslint-plugin-no-only-tests": "3.1.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/internal/template.ts
Expand Up @@ -9,7 +9,7 @@ import { toArray } from '../utils'

/** @deprecated */
// TODO: Remove support for compiling ejs templates in v4
export async function compileTemplate <T>(template: NuxtTemplate<T>, ctx: any) {
export async function compileTemplate <T> (template: NuxtTemplate<T>, ctx: any) {
const data = { ...ctx, options: template.options }
if (template.src) {
try {
Expand Down
47 changes: 23 additions & 24 deletions packages/kit/src/logger.test.ts
Expand Up @@ -3,13 +3,13 @@ import { describe, expect, it, vi } from 'vitest'
import { consola } from 'consola'
import { logger, useLogger } from './logger'

vi.mock("consola", () => {
const logger = {} as any;
vi.mock('consola', () => {
const logger = {} as any

logger.create = vi.fn(() => ({...logger}));
logger.withTag = vi.fn(() => ({...logger}));
return { consola: logger };
logger.create = vi.fn(() => ({ ...logger }))
logger.withTag = vi.fn(() => ({ ...logger }))

return { consola: logger }
})

describe('logger', () => {
Expand All @@ -20,29 +20,28 @@ describe('logger', () => {

describe('useLogger', () => {
it('should expose consola when not passing a tag', () => {
expect(useLogger()).toBe(consola);
});
expect(useLogger()).toBe(consola)
})

it('should create a new instance when passing a tag', () => {
const logger = vi.mocked(consola);

const instance = useLogger("tag");
const logger = vi.mocked(consola)

expect(instance).toEqual(logger);
expect(instance).not.toBe(logger);
expect(logger.create).toBeCalledWith({});
expect(logger.withTag).toBeCalledWith("tag");
});
const instance = useLogger('tag')

expect(instance).toEqual(logger)
expect(instance).not.toBe(logger)
expect(logger.create).toBeCalledWith({})
expect(logger.withTag).toBeCalledWith('tag')
})

it('should create a new instance when passing a tag and options', () => {
const logger = vi.mocked(consola);

const instance = useLogger("tag", { level: 0 });
const logger = vi.mocked(consola)

expect(instance).toEqual(logger);
expect(instance).not.toBe(logger);
expect(logger.create).toBeCalledWith({ level: 0 });
expect(logger.withTag).toBeCalledWith("tag");
});
const instance = useLogger('tag', { level: 0 })

expect(instance).toEqual(logger)
expect(instance).not.toBe(logger)
expect(logger.create).toBeCalledWith({ level: 0 })
expect(logger.withTag).toBeCalledWith('tag')
})
})
2 changes: 1 addition & 1 deletion packages/kit/src/logger.ts
@@ -1,5 +1,5 @@
import { consola } from 'consola'
import type { ConsolaOptions } from 'consola';
import type { ConsolaOptions } from 'consola'

export const logger = consola

Expand Down
4 changes: 2 additions & 2 deletions packages/kit/test/generate-types.spec.ts
Expand Up @@ -22,9 +22,9 @@ const mockNuxt = {
modules: [],
_layers: [{ config: { srcDir: '/my-app' } }],
_installedModules: [],
_modules: [],
_modules: []
},
callHook: () => {},
callHook: () => {}
} satisfies DeepPartial<Nuxt> as unknown as Nuxt

const mockNuxtWithOptions = (options: NuxtConfig) => defu({ options }, mockNuxt) as Nuxt
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/test/load-nuxt-config.bench.ts
Expand Up @@ -9,7 +9,7 @@ const fixtures = {
'basic test fixture': 'test/fixtures/basic',
'basic test fixture (types)': 'test/fixtures/basic-types',
'minimal test fixture': 'test/fixtures/minimal',
'minimal test fixture (types)': 'test/fixtures/minimal-types',
'minimal test fixture (types)': 'test/fixtures/minimal-types'
}

describe('loadNuxtConfig', () => {
Expand Down
20 changes: 11 additions & 9 deletions packages/nuxt/src/app/compat/interval.ts
Expand Up @@ -2,13 +2,15 @@ import { createError } from '../composables/error'

const intervalError = '[nuxt] `setInterval` should not be used on the server. Consider wrapping it with an `onNuxtReady`, `onBeforeMount` or `onMounted` lifecycle hook, or ensure you only call it in the browser by checking `import.meta.client`.'

export const setInterval = import.meta.client ? window.setInterval : () => {
if (import.meta.dev) {
throw createError({
statusCode: 500,
message: intervalError
})
}
export const setInterval = import.meta.client
? window.setInterval
: () => {
if (import.meta.dev) {
throw createError({
statusCode: 500,
message: intervalError
})
}

console.error(intervalError)
}
console.error(intervalError)
}
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/components/client-only.ts
Expand Up @@ -33,7 +33,7 @@ export default defineComponent({

const cache = new WeakMap()

/*@__NO_SIDE_EFFECTS__*/
/* @__NO_SIDE_EFFECTS__ */
export function createClientOnly<T extends ComponentOptions> (component: T) {
if (cache.has(component)) {
return cache.get(component)
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/components/nuxt-island.ts
Expand Up @@ -213,7 +213,7 @@ export default defineComponent({
}

expose({
refresh: () => fetchComponent(true),
refresh: () => fetchComponent(true)
})

if (import.meta.hot) {
Expand Down Expand Up @@ -264,7 +264,7 @@ export default defineComponent({
const { html, slots } = info
let replaced = html.replaceAll('data-island-uid', `data-island-uid="${uid.value}"`)
for (const slot in slots) {
replaced = replaced.replaceAll(`data-island-slot="${slot}">`, (full) => full + slots[slot])
replaced = replaced.replaceAll(`data-island-slot="${slot}">`, full => full + slots[slot])
}
teleports.push(createVNode(Teleport, { to: `uid=${uid.value};client=${id}` }, {
default: () => [createStaticVNode(replaced, 1)]
Expand Down
48 changes: 24 additions & 24 deletions packages/nuxt/src/app/components/nuxt-link.ts
Expand Up @@ -22,29 +22,6 @@ const firstNonUndefined = <T> (...args: (T | undefined)[]) => args.find(arg => a

const NuxtLinkDevKeySymbol: InjectionKey<boolean> = Symbol('nuxt-link-dev-key')

/**
* Create a NuxtLink component with given options as defaults.
* @see https://nuxt.com/docs/api/components/nuxt-link
*/
export interface NuxtLinkOptions extends
Pick<RouterLinkProps, 'activeClass' | 'exactActiveClass'>,
Pick<NuxtLinkProps, 'prefetchedClass'> {
/**
* The name of the component.
* @default "NuxtLink"
*/
componentName?: string
/**
* A default `rel` attribute value applied on external links. Defaults to `"noopener noreferrer"`. Set it to `""` to disable.
*/
externalRelAttribute?: string | null
/**
* An option to either add or remove trailing slashes in the `href`.
* If unset or not matching the valid values `append` or `remove`, it will be ignored.
*/
trailingSlash?: 'append' | 'remove'
}

/**
* <NuxtLink> is a drop-in replacement for both Vue Router's <RouterLink> component and HTML's <a> tag.
* @see https://nuxt.com/docs/api/components/nuxt-link
Expand Down Expand Up @@ -88,7 +65,30 @@ export interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
noPrefetch?: boolean
}

/*@__NO_SIDE_EFFECTS__*/
/**
* Create a NuxtLink component with given options as defaults.
* @see https://nuxt.com/docs/api/components/nuxt-link
*/
export interface NuxtLinkOptions extends
Pick<RouterLinkProps, 'activeClass' | 'exactActiveClass'>,
Pick<NuxtLinkProps, 'prefetchedClass'> {
/**
* The name of the component.
* @default "NuxtLink"
*/
componentName?: string
/**
* A default `rel` attribute value applied on external links. Defaults to `"noopener noreferrer"`. Set it to `""` to disable.
*/
externalRelAttribute?: string | null
/**
* An option to either add or remove trailing slashes in the `href`.
* If unset or not matching the valid values `append` or `remove`, it will be ignored.
*/
trailingSlash?: 'append' | 'remove'
}

/* @__NO_SIDE_EFFECTS__ */
export function defineNuxtLink (options: NuxtLinkOptions) {
const componentName = options.componentName || 'NuxtLink'

Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/components/nuxt-loading-indicator.ts
Expand Up @@ -23,13 +23,13 @@ export default defineComponent({
estimatedProgress: {
type: Function as unknown as () => (duration: number, elapsed: number) => number,
required: false
},
}
},
setup (props, { slots, expose }) {
const { progress, isLoading, start, finish, clear } = useLoadingIndicator({
duration: props.duration,
throttle: props.throttle,
estimatedProgress: props.estimatedProgress,
estimatedProgress: props.estimatedProgress
})

expose({
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/components/nuxt-teleport-island-slot.ts
Expand Up @@ -40,7 +40,7 @@ export default defineComponent({
vnodes.push(h('div', {
style: 'display: contents;',
'data-island-uid': '',
'data-island-slot': props.name,
'data-island-slot': props.name
}, {
// Teleport in slot to not be hydrated client-side with the staticVNode
default: () => [createVNode(Teleport, { to: `island-slot=${componentName};${props.name}` }, slots.default?.())]
Expand All @@ -49,7 +49,7 @@ export default defineComponent({
vnodes.push(h('div', {
style: 'display: contents;',
'data-island-uid': '',
'data-island-slot': props.name,
'data-island-slot': props.name
}))
}

Expand Down
12 changes: 7 additions & 5 deletions packages/nuxt/src/app/composables/asyncData.ts
Expand Up @@ -214,14 +214,16 @@ export function useAsyncData<
const nuxtApp = useNuxtApp()

// When prerendering, share payload data automatically between requests
const handler = import.meta.client || !import.meta.prerender || !nuxtApp.ssrContext?._sharedPrerenderCache ? _handler : () => {
const value = nuxtApp.ssrContext!._sharedPrerenderCache!.get(key)
if (value) { return value as Promise<ResT> }
const handler = import.meta.client || !import.meta.prerender || !nuxtApp.ssrContext?._sharedPrerenderCache
? _handler
: () => {
const value = nuxtApp.ssrContext!._sharedPrerenderCache!.get(key)
if (value) { return value as Promise<ResT> }

const promise = nuxtApp.runWithContext(_handler)
const promise = nuxtApp.runWithContext(_handler)
nuxtApp.ssrContext!._sharedPrerenderCache!.set(key, promise)
return promise
}
}

// Used to get default values
const getDefault = () => null
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/composables/component.ts
Expand Up @@ -28,7 +28,7 @@ async function runLegacyAsyncData (res: Record<string, any> | Promise<Record<str
}

/** @since 3.0.0 */
/*@__NO_SIDE_EFFECTS__*/
/* @__NO_SIDE_EFFECTS__ */
export const defineNuxtComponent: typeof defineComponent =
function defineNuxtComponent (...args: any[]): any {
const [options, key] = args
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/composables/cookie.ts
Expand Up @@ -92,7 +92,7 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
if (store) {
store.onchange = (event) => {
const cookie = event.changed.find((c: any) => c.name === name)
if (cookie) handleChange({ value: cookie.value })
if (cookie) { handleChange({ value: cookie.value }) }
}
} else if (channel) {
channel.onmessage = ({ data }) => handleChange(data)
Expand Down Expand Up @@ -124,7 +124,7 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
}
/** @since 3.10.0 */
export function refreshCookie (name: string) {
if (store || typeof BroadcastChannel === 'undefined') return
if (store || typeof BroadcastChannel === 'undefined') { return }

new BroadcastChannel(`nuxt:cookies:${name}`)?.postMessage({ refresh: true })
}
Expand Down

0 comments on commit 7252b56

Please sign in to comment.