nuxt-link-checker 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
  <p align="center">
13
- Improve your sites SEO by identifying and fixing link issues in your Nuxt v3 app.
13
+ Improve your sites SEO by identifying and fixing link issues in your Nuxt 3 app.
14
14
  </p>
15
15
 
16
16
  <p align="center">
@@ -27,6 +27,8 @@ Improve your sites SEO by identifying and fixing link issues in your Nuxt v3 app
27
27
  </table>
28
28
  </p>
29
29
 
30
+ ℹ️ Looking for a complete SEO solution? Check out [nuxt-seo-kit](https://github.com/harlan-zw/nuxt-seo-kit).
31
+
30
32
  ## Features
31
33
 
32
34
  - ✅ Discover broken links - 404s and internal redirects
@@ -102,7 +104,7 @@ If set to `true`, the build will fail if any broken links are found.
102
104
  ### `host`
103
105
 
104
106
  - Type: `string`
105
- - Default: `runtimeConfig.public.siteUrl`
107
+ - Default: `runtimeConfig.public.siteUrl || localhost`
106
108
  - Required: `false`
107
109
 
108
110
  The host of your site. This is required to validate absolute URLs which may be internal.
package/dist/module.d.ts CHANGED
@@ -10,7 +10,7 @@ interface ModuleOptions {
10
10
  /**
11
11
  * Your site hostname. Used to determine if absolute links are internal.
12
12
  */
13
- host?: string;
13
+ host: string;
14
14
  /**
15
15
  * Whether the build should fail when a 404 is encountered.
16
16
  */
package/dist/module.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "bridge": false
6
6
  },
7
7
  "configKey": "linkChecker",
8
- "version": "0.1.5"
8
+ "version": "0.2.0"
9
9
  }
package/dist/module.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defineNuxtModule } from '@nuxt/kit';
2
2
  import chalk from 'chalk';
3
- import { isRelative, parseURL } from 'ufo';
3
+ import { parseURL, hasProtocol } from 'ufo';
4
4
  import { load } from 'cheerio';
5
5
 
6
6
  const linkMap = {};
@@ -11,36 +11,25 @@ function getExtension(path) {
11
11
  }
12
12
  function extractLinks(html, from, { host, trailingSlash }) {
13
13
  const links = [];
14
- const _links = [];
14
+ const hostname = parseURL(host).host;
15
15
  const $ = load(html);
16
16
  $("[href]").each((i, el) => {
17
17
  const href = $(el).attr("href");
18
18
  if (!href)
19
19
  return;
20
- if (host && !isRelative(href) && href.startsWith(host))
20
+ const url = parseURL(href);
21
+ if (hasProtocol(href) && !href.startsWith("/") && url.host !== hostname)
21
22
  return;
22
23
  if (!allowedExtensions.has(getExtension(href)))
23
24
  return;
24
- _links.push({
25
- href,
26
- badTrailingSlash: href !== "/" && (trailingSlash && !href.endsWith("/") || !trailingSlash && href.endsWith("/")),
25
+ links.push({
26
+ pathname: url.pathname || "/",
27
+ url,
28
+ badAbsolute: Boolean(hostname) && hostname === url.host,
29
+ badTrailingSlash: url.pathname !== "/" && (trailingSlash && !url.pathname.endsWith("/") || !trailingSlash && url.pathname.endsWith("/")),
27
30
  element: $.html(el) || ""
28
31
  });
29
32
  });
30
- for (const link of _links.filter(Boolean)) {
31
- const parsed = parseURL(link.href);
32
- if (parsed.protocol)
33
- continue;
34
- let { pathname } = parsed;
35
- if (!pathname.startsWith("/")) {
36
- const fromURL = new URL(from, "http://localhost");
37
- pathname = new URL(pathname, fromURL).pathname;
38
- }
39
- links.push({
40
- ...link,
41
- href: pathname
42
- });
43
- }
44
33
  return links;
45
34
  }
46
35
 
@@ -56,12 +45,14 @@ const module = defineNuxtModule({
56
45
  },
57
46
  defaults(nuxt) {
58
47
  return {
59
- host: nuxt.options.runtimeConfig.public?.siteUrl,
48
+ host: nuxt.options.runtimeConfig.public?.siteUrl || "localhost",
60
49
  trailingSlash: nuxt.options.runtimeConfig.public?.trailingSlash || false,
61
50
  failOn404: true
62
51
  };
63
52
  },
64
53
  setup(config, nuxt) {
54
+ if (nuxt.options.dev)
55
+ return;
65
56
  nuxt.hooks.hook("nitro:init", async (nitro) => {
66
57
  const invalidRoutes = {};
67
58
  nitro.hooks.hook("prerender:generate", async (ctx) => {
@@ -71,15 +62,17 @@ const module = defineNuxtModule({
71
62
  invalidRoutes[ctx.route] = ctx.error.statusCode;
72
63
  });
73
64
  nitro.hooks.hook("close", async () => {
74
- nitro.logger.info("Scanning routes for broken links...");
75
65
  const links = Object.entries(linkMap);
66
+ if (!links.length)
67
+ return;
68
+ nitro.logger.info(`Scanning routes for broken links... ${chalk.gray(`trailingSlashes: ${config.trailingSlash ? "`true`" : "`false`"}`)}`);
76
69
  let routeCount = 0;
77
70
  let badLinkCount = 0;
78
71
  links.forEach(([route, routes]) => {
79
72
  const brokenLinks = routes.map((r) => {
80
73
  return {
81
74
  ...r,
82
- statusCode: invalidRoutes[r.href] || 200
75
+ statusCode: invalidRoutes[r.pathname] || 200
83
76
  };
84
77
  }).filter((r) => r.statusCode !== 200 || r.badTrailingSlash);
85
78
  if (brokenLinks.length) {
@@ -93,9 +86,13 @@ const module = defineNuxtModule({
93
86
  nitro.logger.log(chalk.red(
94
87
  ` ${link.statusCode} ${link.statusCode === 404 ? "Not Found" : "Redirect"}`
95
88
  ));
89
+ } else if (link.badAbsolute) {
90
+ nitro.logger.log(chalk.yellow(
91
+ " Absolute link, should be relative"
92
+ ));
96
93
  } else if (link.badTrailingSlash) {
97
94
  nitro.logger.log(chalk.yellow(
98
- ` ${config.trailingSlash ? "Missing" : "Has added"} trailing slash`
95
+ " Incorrect trailing slash"
99
96
  ));
100
97
  }
101
98
  nitro.logger.log(` ${chalk.gray(link.element)}`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-link-checker",
3
3
  "type": "module",
4
- "version": "0.1.5",
4
+ "version": "0.2.0",
5
5
  "packageManager": "pnpm@7.18.0",
6
6
  "license": "MIT",
7
7
  "funding": "https://github.com/sponsors/harlan-zw",
@@ -38,11 +38,11 @@
38
38
  "@nuxt/test-utils": "3.0.0",
39
39
  "@nuxtjs/eslint-config-typescript": "^12.0.0",
40
40
  "bumpp": "^8.2.1",
41
- "eslint": "8.30.0",
41
+ "eslint": "8.31.0",
42
42
  "execa": "^6.1.0",
43
43
  "nuxt": "^3.0.0",
44
44
  "pathe": "^1.0.0",
45
- "vitest": "^0.25.8"
45
+ "vitest": "^0.26.3"
46
46
  },
47
47
  "scripts": {
48
48
  "lint": "eslint \"**/*.{ts,vue,json,yml}\" --fix",