Skip to content

Commit

Permalink
feat: add check links plugin (#134)
Browse files Browse the repository at this point in the history
  • Loading branch information
sanyuan0704 authored Nov 1, 2022
1 parent 3d349d5 commit 72cdd5f
Show file tree
Hide file tree
Showing 22 changed files with 202 additions and 39 deletions.
8 changes: 8 additions & 0 deletions .changeset/poor-wolves-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'islandjs': patch
'@islandjs/plugin-backtop': patch
'@islandjs/plugin-check-links': patch
'@islandjs/plugin-search': patch
---

init check links plugin
3 changes: 2 additions & 1 deletion docs/.island/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineConfig } from 'islandjs';
import { pluginCheckLinks } from '@islandjs/plugin-check-links';

function getI18nHelper(lang: 'zh' | 'en') {
const cn = lang === 'zh';
Expand All @@ -22,7 +23,7 @@ export default defineConfig({
route: {
exclude: ['custom.tsx', '**/fragments/**']
},
plugins: [],
plugins: [pluginCheckLinks({})],
themeConfig: {
locales: {
'/zh/': {
Expand Down
8 changes: 4 additions & 4 deletions docs/en/guide/islands-arch.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ Island.js will combine all island components into a virtual module and bundle th

There are the some relevant code in repository:

[island-jsx-runtime.js](https://github.com/sanyuan0704/island.js/blob/master/src/runtime/island-jsx-runtime.js): The jsx runtime will collect the islands information when `__island` prop is found in the component, served as the server runtime.
[island-jsx-runtime.js](https://github.com/sanyuan0704/island.js/blob/master/packages/island/src/runtime/island-jsx-runtime.js): The jsx runtime will collect the islands information when `__island` prop is found in the component, served as the server runtime.

[babel-plugin-island](https://github.com/sanyuan0704/island.js/blob/master/src/node/babel-plugin-island.ts): The babel plugin will transform the `__island` prop to `__island=${islandAbsoluteFilePath}` prop, so in build time, bundler will find the island component file path.
[babel-plugin-island](https://github.com/sanyuan0704/island.js/blob/master/packages/island/src/node/babel-plugin-island.ts): The babel plugin will transform the `__island` prop to `__island=${islandAbsoluteFilePath}` prop, so in build time, bundler will find the island component file path.

[SSGBuilder](https://github.com/sanyuan0704/island.js/blob/master/src/node/build.ts): The complete build time implement.
[SSGBuilder](https://github.com/sanyuan0704/island.js/blob/master/packages/island/src/node/build.ts): The complete build time implement.

[client-entry](https://github.com/sanyuan0704/island.js/blob/master/src/runtime/client-entry.tsx#L50): The client runtime will hydrate the islands in browser to make them interactive.
[client-entry](https://github.com/sanyuan0704/island.js/blob/master/packages/island/src/runtime/client-entry.tsx#L50): The client runtime will hydrate the islands in browser to make them interactive.
8 changes: 4 additions & 4 deletions docs/zh/guide/islands-arch.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ export function Layout() {

下面是一些相关的实现代码:

[island-jsx-runtime.js](https://github.com/sanyuan0704/island.js/blob/master/src/runtime/island-jsx-runtime.js): 拦截 jsx 运行时,收集孤岛组件信息。
[island-jsx-runtime.js](https://github.com/sanyuan0704/island.js/blob/master/packages/island/src/runtime/island-jsx-runtime.js): 拦截 jsx 运行时,收集孤岛组件信息。

[babel-plugin-island](https://github.com/sanyuan0704/island.js/blob/master/src/node/babel-plugin-island.ts): 注册孤岛组件文件路径的 babel 插件。
[babel-plugin-island](https://github.com/sanyuan0704/island.js/blob/master/packages/island/src/node/babel-plugin-island.ts): 注册孤岛组件文件路径的 babel 插件。

[SSGBuilder](https://github.com/sanyuan0704/island.js/blob/master/src/node/build.ts): 完整的构建时实现。
[SSGBuilder](https://github.com/sanyuan0704/island.js/blob/master/packages/island/src/node/build.ts): 完整的构建时实现。

[client-entry](https://github.com/sanyuan0704/island.js/blob/master/src/runtime/client-entry.tsx#L50): 客户端运行时代码,主要是负责孤岛组件的 hydration。
[client-entry](https://github.com/sanyuan0704/island.js/blob/master/packages/island/src/runtime/client-entry.tsx#L50): 客户端运行时代码,主要是负责孤岛组件的 hydration。
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"@changesets/cli": "^2.25.1",
"@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.1.0",
"@islandjs/plugin-search": "workspace:*",
"@islandjs/plugin-check-links": "workspace:*",
"@playwright/test": "^1.26.1",
"@types/node": "^18.11.7",
"@typescript-eslint/eslint-plugin": "^5.36.1",
Expand Down
1 change: 0 additions & 1 deletion packages/island/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
"@vitejs/plugin-react": "2.0.1",
"acorn": "^8.8.0",
"cac": "6.7.12",
"check-links": "^1.1.8",
"chokidar": "^3.5.3",
"compression": "^1.7.4",
"copy-to-clipboard": "^3.3.2",
Expand Down
3 changes: 2 additions & 1 deletion packages/island/src/node/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { routeService } from './plugin-routes';
export { isProduction } from './constants';
export { routeService, normalizeRoutePath } from './plugin-routes';
export { defineConfig } from './config';
export type { IslandPlugin } from 'shared/types/Plugin';
export * from '../shared/types/index';
3 changes: 1 addition & 2 deletions packages/island/src/node/plugin-island/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ export function pluginConfig(
'react/jsx-runtime',
'react-helmet-async',
'lodash-es',
'copy-to-clipboard',
'flexsearch'
'copy-to-clipboard'
],
exclude: [
'islandjs',
Expand Down
2 changes: 0 additions & 2 deletions packages/island/src/node/plugin-mdx/pluginMdxRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { rehypePluginPreWrapper } from './rehypePlugins/preWrapper';
import remarkPluginGFM from 'remark-gfm';
import remarkPluginFrontMatter from 'remark-frontmatter';
import remarkDirective from 'remark-directive';
import { remarkCheckDeadLinks } from './remarkPlugins/deadLinks';
import remarkPluginMDXFrontMatter from 'remark-mdx-frontmatter';
import remarkGemoji from 'remark-gemoji';
import { remarkPluginNormalizeLink } from './remarkPlugins/link';
Expand Down Expand Up @@ -37,7 +36,6 @@ export async function pluginMdxRollup(
remarkPluginToc,
remarkDirective,
remarkPluginTip,
[remarkCheckDeadLinks, { checkLink: config.markdown?.checkLink }],
[
remarkPluginNormalizeLink,
{ base: config.base || '/', enableSpa: config.enableSpa }
Expand Down
2 changes: 2 additions & 0 deletions packages/island/src/node/plugin-routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,5 @@ export function pluginRoutes(options: RouteOptions = {}): Plugin {
}
};
}

export { normalizeRoutePath } from './RouteService';
2 changes: 0 additions & 2 deletions packages/island/src/node/type.d.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/island/src/runtime/lazyWithPreload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type PreloadableComponent<T extends ComponentType<unknown>> = T & {
preload: () => Promise<PageModule<T>>;
};

// Inspired by https://github.com/ianschmitz/react-lazy-with-preload/blob/master/src/index.ts
// Inspired by https://github.com/ianschmitz/react-lazy-with-preload/blob/master/packages/island/src/index.ts
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function lazyWithPreload<T extends ComponentType<any>>(
factory: () => Promise<{ default: T }>
Expand Down
5 changes: 0 additions & 5 deletions packages/island/src/shared/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,5 @@ export interface MarkdownOptions {
remarkPlugins?: PluggableList;
rehypePlugins?: PluggableList;
lineNumbers?: boolean;
checkLink?: {
exclude?: (string | RegExp)[];
timeout?: number;
enable?: boolean;
};
targetBlankWhiteList?: (string | RegExp)[];
}
10 changes: 10 additions & 0 deletions packages/plugin-check-links/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
**/dist/**
**/node_modules/**
**/package.json
*.d.ts
.eslintrc.cjs
**/tsconfig.json
**/tsconfig.base.json
turbo.json
vendors
**/__tests__/**
28 changes: 28 additions & 0 deletions packages/plugin-check-links/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# @islandjs/plugin-check-links

[![npm version](https://badge.fury.io/js/%40islandjs%2Fplugin-check-links.svg)](https://badge.fury.io/js/%40islandjs%2Fplugin-check-links)

A plugin for [Island.js](https://github.com/sanyuan0704/island.js) to check links in markdown files.

## Install

```bash
# npm
npm install @islandjs/plugin-check-links
# yarn
yarn add @islandjs/plugin-check-links
# pnpm
pnpm install @islandjs/plugin-check-links
```

## Usage

```js
// .island/config.ts
import { pluginCheckLinks } from '@islandjs/plugin-check-links';
import { defineConfig } from 'islandjs';

export default defineConfig({
plugins: [pluginCheckLinks()]
});
```
62 changes: 62 additions & 0 deletions packages/plugin-check-links/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "@islandjs/plugin-check-links",
"version": "0.6.3",
"description": "Dead links check plugin for islandjs",
"packageManager": "pnpm@7.9.2",
"type": "module",
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./dist/*": "./dist/*",
"./package.json": "./package.json"
},
"scripts": {
"pnpm-install": "pnpm install",
"dev": "tsup --watch --format=cjs,esm",
"build": "cross-env NODE_ENV=production tsup --format=cjs,esm",
"prepublishOnly": "pnpm build",
"release": "release-it"
},
"keywords": [
"vite",
"ssg",
"island architecture",
"docs",
"framework"
],
"author": "Sanyuan0704",
"license": "MIT",
"devDependencies": {
"@types/lodash-es": "^4.17.6",
"@types/node": "^18.11.7",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@unocss/preset-attributify": "^0.45.26",
"react": "^18.2.0"
},
"peerDependencies": {
"islandjs": "*"
},
"files": [
"dist",
"src",
"README.md"
],
"lint-staged": {
"**/*.{js,jsx,tsx,ts,json}": [
"eslint --fix"
]
},
"dependencies": {
"check-links": "^1.1.8",
"ora": "^6.1.2",
"unified": "^10.1.2",
"unist-util-visit": "^4.1.1"
}
}
18 changes: 18 additions & 0 deletions packages/plugin-check-links/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { IslandPlugin } from 'islandjs/plugin';
import { remarkCheckDeadLinks } from './remarkPlugin';

export interface DeadLinkCheckOptions {
exclude?: (string | RegExp)[];
timeout?: number;
}

export function pluginCheckLinks(
options: DeadLinkCheckOptions = {}
): IslandPlugin {
return {
name: 'island:plugin-check-links',
markdown: {
remarkPlugins: [[remarkCheckDeadLinks, options]]
}
};
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import { isProduction } from '../../constants';
import { normalizeRoutePath } from '../../plugin-routes/RouteService';
import type { Plugin } from 'unified';
import { visit } from 'unist-util-visit';
import { routeService } from '../../plugin-routes';
import checkLinks from 'check-links';
import ora from 'ora';
import { MarkdownOptions } from 'shared/types/index';
import type { DeadLinkCheckOptions } from './index';
import type { Plugin } from 'unified';

const checkedLinks = new Map();
/**
* Remark plugin to normalize a link href
*/
export const remarkCheckDeadLinks: Plugin<
[{ checkLink: MarkdownOptions['checkLink'] }]
[{ checkLink: DeadLinkCheckOptions }]
> = ({ checkLink }) => {
if (!checkLink?.enable) {
return;
}

const { exclude = [], timeout = 10000 } = checkLink || {};

return async (tree) => {
const { isProduction, routeService, normalizeRoutePath } = await import(
'islandjs'
);

const externalLinks: string[] = [];
const internalLinks: string[] = [];

Expand Down Expand Up @@ -81,7 +78,6 @@ export const remarkCheckDeadLinks: Plugin<
}
errorInfos.push(`External link to ${url} is dead`);
});

// output error info
if (errorInfos.length > 0) {
errorInfos?.forEach((err) => ora().fail(err));
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-check-links/src/shims.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module 'check-links';
7 changes: 7 additions & 0 deletions packages/plugin-check-links/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": ".",
"baseUrl": "src",
}
}
17 changes: 17 additions & 0 deletions packages/plugin-check-links/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineConfig } from 'tsup';

export default defineConfig([
{
entry: ['src/index.ts'],
minifyIdentifiers: false,
bundle: true,
dts: true,
sourcemap: true,
splitting: true,
minify: process.env.NODE_ENV === 'production',
skipNodeModulesBundle: true,
outDir: 'dist',
clean: true,
shims: true
}
]);
31 changes: 27 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 comment on commit 72cdd5f

@vercel
Copy link

@vercel vercel bot commented on 72cdd5f Nov 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.