Skip to content

Commit

Permalink
Document namespace imports, extensionless imports, svelte $app path a…
Browse files Browse the repository at this point in the history
…lias, and some edits
  • Loading branch information
webpro committed May 14, 2024
1 parent 79918d3 commit 20f5502
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 27 deletions.
21 changes: 21 additions & 0 deletions packages/docs/src/content/docs/features/compilers.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ to Knip. This means you don't need to add something like `**/*.{ts,css}` to the

:::

### Svelte

In a project with Svelte, the compiler is automatically enabled, but you may
have unresolved imports starting with `$app/`:

```shell
Unresolved imports (5)
$app/stores src/routes/Header.svelte:1:9
$app/environment src/routes/about/+page.ts:1:9
```

In this case, you can manually add the `$app` path alias:

```json title="knip.json"
{
"paths": {
"$app/*": ["node_modules/@sveltejs/kit/src/runtime/app/*"]
}
}
```

### CSS

Here's an example, minimal compiler for CSS files:
Expand Down
35 changes: 20 additions & 15 deletions packages/docs/src/content/docs/guides/handling-issues.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -264,22 +264,21 @@ listed.

By default, Knip does not report unused exports of `entry` files.

When unused exports are reported, and you want to keep exporting it, there are a
few options:
When unused exports are reported, and you want to keep exporting those, there
are a few options:

- [Ignore exports used in file][19] for exports used internally.
- Individual exports can be [tagged as `@public`][20].
- Individual exports can be excluded using arbitrary [tags][21].
- Make sure the export ends up in an [entry file][2]:
- Individual exports can be [tagged using JSDoc syntax][20].
- Have the export in or re-exported by an [entry file][2]:
- Add the file to the `entry` file patterns array in the configuration
- Move the export(s) to an entry file
- Re-export the unused export(s) from an entry file
- Add the file to the `exports` field of `package.json`

:::tip

Use the `--exports` flag to [filter][5] and focus only on exports related
issues:
Use the `--exports` flag to [filter][5] and focus only on issues related to
exports:

```sh
knip --exports
Expand All @@ -290,7 +289,9 @@ knip --exports
### External libraries

Are the exports consumed or imported by an external library, resulting in a
non-standard consumption of your exports? Here's an example:
non-standard consumption of your exports? Try the `--include-libs` flag.

Here's an example:

<Tabs>
<TabItem label="index.js">
Expand Down Expand Up @@ -320,8 +321,12 @@ non-standard consumption of your exports? Here's an example:
</Tabs>

Knip understands `Apple` is used, since it's standard usage. But `Orange` is
referenced though a function of an external library. To include the type
definitions of external libraries, use the `--include-libs` flag:
referenced through a function of an external library. For performance reasons,
Knip does not include external type definitions by default so it won't see the
export being referenced.

To include the type definitions of external libraries, use the
[--include-libs][21] flag:

```shell
knip --include-libs
Expand Down Expand Up @@ -349,10 +354,10 @@ This option is also available in the Knip configuration file. Note that this
feature comes at a cost: linting will take more time and more memory (in rare
cases it may even run out of memory in large repositories).

Individual class members can be [tagged as `@public`][20].
Individual class members can be [tagged using JSDoc syntax][20].

Classes exported from entry files are ignored, and so are their members. Use
[--include-entry-exports][23] to make Knip also report members of unused export
[--include-entry-exports][23] to make Knip also report members of unused exports
in entry files.

## Enum members
Expand All @@ -364,7 +369,7 @@ members can also be disabled altogether, for example:
knip --exclude enumMembers
```

Individual enum members can be [tagged as `@public`][20].
Individual enum members can be [tagged using JSDoc syntax][20].

Enums exported from entry files are ignored, and so are their members. Use
[--include-entry-exports][23] to make Knip also report members of unused exports
Expand Down Expand Up @@ -401,8 +406,8 @@ Also see [troubleshooting][26] if you haven't already.
[17]: https://eslint.org/docs/latest/use/configure/configuration-files-new
[18]: ../features/monorepos-and-workspaces.md#lint-a-single-workspace
[19]: ../reference/configuration.md#ignoreexportsusedinfile
[20]: ../reference/jsdoc-tsdoc-tags.md#public
[21]: ../reference/cli.md#--tags
[20]: ../reference/jsdoc-tsdoc-tags.md
[21]: ../reference/cli#--include-libs
[22]: #class-members
[23]: ../reference/configuration.md#includeentryexports
[24]: ../reference/configuration.md#paths
Expand Down
116 changes: 116 additions & 0 deletions packages/docs/src/content/docs/guides/namespace-imports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
title: Namespace Imports
---

The intention of exports used through namespace imports may not always be clear
to Knip. Here's a guide to better understand how Knip handles such exports.

## Example

We start off by having two exports:

```ts title="my-namespace.js"
export const version = 'v5';
export const getRocket = () => '🚀';
```

The next snippet shows how to import all the exports above on a namespace. All
exports of the `my-namespace.js` module will be members on the `NS` object:

```ts title="my-module.ts"
import * as NS from './my-namespace.js';
import send from 'stats';
send(NS);
```

The intention of export usage is not always clear. In the example above is
`version` or `getRocket` used? We're not sure, but we _probably_ don't want them
to be reported as unused. The same goes for the next example:

```ts title="my-module.ts"
import * as NS from './my-namespace.js';

export { NS };
```

If this all usage of the `NS` namespace object, we also don't know whether
individual exports like `version` or `getRocket` will be used. However, if at
least one reference to a property such as `NS.end` is found, then the individual
exports are considered separately again and `start` will be marked as unused:

```ts title="index.ts"
import { NS } from './my-module.js';

const finish = NS.end;
```

## The default heuristic

Knip uses the following heuristic to determine which of the individual exports
are used:

- If there's one or more references to the import namespace object, but without
any property access, all exports on that namespace are considered used.
- Otherwise, exports are considered separately.

Below are a few more examples, and a way to disable this default behavior.

## Examples

Let's take a look at more examples:

```ts title="my-namespace.ts"
export const start = 1;

export const end = 1;
```

In the following cases all exports of `my-namespace.ts` are considered used:

```ts title="index.ts"
import * as NS from './my-namespace.js';
import send from 'stats';

send(NS);

const spread = { ...NS };

const shorthand = { NS };

const assignment = NS;

type TypeOf = typeof NS;

export { NS };

export { NS as AliasedNS };

export = NS;
```

However, this is no longer the case when one of the properties is accessed:

```ts title="index.js"
import * as NS from './namespace.js';

const begin = NS.start;

send(NS);
```

In this case, the `end` export will be reported as unused, even though the `NS`
object itself is referenced on its own as well.

## Include `nsExports` and `nsTypes`

To disable the heuristic as explained above, and enforce Knip to consider each
export on a namespace individually, include the `nsExports` issue type:

```json
{
"include": ["nsExports"]
}
```

Or use the `--include nsExports` argument from the CLI. The `nsTypes` can be
added as well to do the same for exported types.
7 changes: 5 additions & 2 deletions packages/docs/src/content/docs/guides/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ This way, the `project` files cover all source files, and most other files don't
even need to be ignored anymore. This may have a significant impact on
performance.

Also see [configuring project files][1].

## Workspace sharing

Knip shares files from separate workspaces if the configuration in
Expand Down Expand Up @@ -96,6 +98,7 @@ up symbols and caching.
## A last resort

In case Knip is unbearable slow (or even crashes), you could resort to [lint
individual workspaces][1].
individual workspaces][2].

[1]: ../features/monorepos-and-workspaces.md#lint-a-single-workspace
[1]: ./configuring-project-files.md
[2]: ../features/monorepos-and-workspaces.md#lint-a-single-workspace
20 changes: 13 additions & 7 deletions packages/docs/src/content/docs/guides/using-knip-in-ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,22 @@ jobs:

## Notes

In CI environments, the [--no-progress](../reference/cli.md#--no-progress) flag
is set automatically.
In CI environments, the [--no-progress][1] flag is set automatically.

## Related features

- [--cache](../reference/cli.md#--cache)
- [--max-issues](../reference/cli.md#--max-issues)
- [--no-exit-code](../reference/cli.md#--no-exit-code)
- [--reporter](../reference/cli.md#--reporter-reporter)
- [--cache][2]
- [--max-issues][3]
- [--no-exit-code][4]
- [--reporter][5]

## Related reading

- [Why use Knip?](../explanations/why-use-knip.md)
- [Why use Knip?][6]

[1]: ../reference/cli.md#--no-progress
[2]: ../reference/cli.md#--cache
[3]: ../reference/cli.md#--max-issues
[4]: ../reference/cli.md#--no-exit-code
[5]: ../reference/cli.md#--reporter-reporter
[6]: ../explanations/why-use-knip.md
4 changes: 2 additions & 2 deletions packages/docs/src/content/docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ Also see [includeEntryExports][3].

### `--include-libs`

If Knip report false positives for exports consumed by external libraries, you
can try the `--include-libs` flag:
Getting false positives for exports consumed by external libraries? Try the
`--include-libs` flag:

```sh
knip --include-libs
Expand Down
14 changes: 14 additions & 0 deletions packages/docs/src/content/docs/reference/known-issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ projects are published with one or more Definitely Typed packages (`@types/*`)
bundled. Knip does not detect/report such DT packages that are expected to be
listed in `dependencies`.

## Extensionless imports

Knip does not support extensionless imports for non-standard extensions, such as
for `.vue` or `.svg` files. Bundlers like Webpack may support this, but Knip
does not. Examples:

```ts title="App.vue"
import Component from './Component'; // → Does not resolve to ./Component.vue
import ArrowIcon from '../icons/Arrow'; // → Does not resolve to ../icons/Arrow.svg
```

The recommendation is to add the extension when importing such files, similar to
how standard ES Modules work.

[1]: https://github.com/unjs/jiti
[2]: ./configuration.md#plugins
[3]: https://github.com/unjs/jiti/issues/72
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/styles/content.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
border-bottom: 1px solid var(--sl-color-gray-1);
}

h2 em {
.sl-markdown-content em {
font-weight: bold;
}

Expand Down

0 comments on commit 20f5502

Please sign in to comment.