diff --git a/.eslintignore b/.eslintignore index c75dfdc424..8343f84b97 100644 --- a/.eslintignore +++ b/.eslintignore @@ -13,6 +13,7 @@ packages/lqip-loader/lib/ packages/docusaurus/lib/ packages/docusaurus-*/lib/* packages/docusaurus-*/lib-next/ +packages/docusaurus-plugin-pwa/copyUntypedFiles.js packages/docusaurus-plugin-ideal-image/copyUntypedFiles.js packages/docusaurus-theme-search-algolia/copyUntypedFiles.js diff --git a/packages/docusaurus-plugin-pwa/copyUntypedFiles.js b/packages/docusaurus-plugin-pwa/copyUntypedFiles.js new file mode 100644 index 0000000000..e5555c5536 --- /dev/null +++ b/packages/docusaurus-plugin-pwa/copyUntypedFiles.js @@ -0,0 +1,20 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +const path = require('path'); +const fs = require('fs-extra'); + +/** + * Copy all untyped and static assets files to lib. + */ +const srcDir = path.resolve(__dirname, 'src'); +const libDir = path.resolve(__dirname, 'lib'); +fs.copySync(srcDir, libDir, { + filter(filepath) { + return !/__tests__/.test(filepath) && !/\.tsx?$/.test(filepath); + }, +}); diff --git a/packages/docusaurus-plugin-pwa/package.json b/packages/docusaurus-plugin-pwa/package.json index fa7c48b0f8..8673e05684 100644 --- a/packages/docusaurus-plugin-pwa/package.json +++ b/packages/docusaurus-plugin-pwa/package.json @@ -2,7 +2,14 @@ "name": "@docusaurus/plugin-pwa", "version": "2.0.0-beta.9", "description": "Docusaurus Plugin to add PWA support.", - "main": "src/index.js", + "main": "lib/index.js", + "types": "src/plugin-pwa.d.ts", + "scripts": { + "build": "yarn build:server && yarn build:browser && yarn build:copy", + "build:server": "tsc --project tsconfig.server.json", + "build:browser": "tsc --project tsconfig.browser.json", + "build:copy": "node copyUntypedFiles.js" + }, "publishConfig": { "access": "public" }, @@ -30,6 +37,10 @@ "workbox-precaching": "^6.1.1", "workbox-window": "^6.1.1" }, + "devDependencies": { + "@docusaurus/module-type-aliases": "2.0.0-beta.9", + "fs-extra": "^10.0.0" + }, "peerDependencies": { "@babel/core": "^7.0.0", "react": "^16.8.4 || ^17.0.0", diff --git a/packages/docusaurus-plugin-pwa/src/index.js b/packages/docusaurus-plugin-pwa/src/index.ts similarity index 79% rename from packages/docusaurus-plugin-pwa/src/index.js rename to packages/docusaurus-plugin-pwa/src/index.ts index 50677a0c33..918353a0c4 100644 --- a/packages/docusaurus-plugin-pwa/src/index.js +++ b/packages/docusaurus-plugin-pwa/src/index.ts @@ -5,15 +5,17 @@ * LICENSE file in the root directory of this source tree. */ -const LogPlugin = - require('@docusaurus/core/lib/webpack/plugins/LogPlugin').default; -const {compile} = require('@docusaurus/core/lib/webpack/utils'); -const {normalizeUrl} = require('@docusaurus/utils'); -const path = require('path'); -const webpack = require('webpack'); -const {injectManifest} = require('workbox-build'); -const {PluginOptionSchema} = require('./pluginOptionSchema'); -const Terser = require('terser-webpack-plugin'); +import type {HtmlTags, LoadContext, Plugin} from '@docusaurus/types'; +import type {PluginOptions} from '@docusaurus/plugin-pwa'; +import {normalizeUrl} from '@docusaurus/utils'; +import {compile} from '@docusaurus/core/lib/webpack/utils'; +import LogPlugin from '@docusaurus/core/lib/webpack/plugins/LogPlugin'; + +import path from 'path'; +import webpack, {Configuration} from 'webpack'; +import Terser from 'terser-webpack-plugin'; + +import {injectManifest} from 'workbox-build'; const isProd = process.env.NODE_ENV === 'production'; @@ -43,7 +45,10 @@ function getSWBabelLoader() { }; } -function plugin(context, options) { +export default function ( + context: LoadContext, + options: PluginOptions, +): Plugin { const {outDir, baseUrl} = context; const { debug, @@ -76,7 +81,7 @@ function plugin(context, options) { new webpack.EnvironmentPlugin({ PWA_DEBUG: debug, PWA_SERVICE_WORKER_URL: path.posix.resolve( - `${config.output.publicPath || '/'}`, + `${config.output?.publicPath || '/'}`, 'sw.js', ), PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES: @@ -88,10 +93,10 @@ function plugin(context, options) { }, injectHtmlTags() { - const headTags = []; + const headTags: HtmlTags = []; if (isProd && pwaHead) { pwaHead.forEach(({tagName, ...attributes}) => { - ['href', 'content'].forEach((attribute) => { + (['href', 'content'] as const).forEach((attribute) => { const attributeValue = attributes[attribute]; if (!attributeValue) { @@ -122,7 +127,7 @@ function plugin(context, options) { const swSourceFileTest = /\.m?js$/; - const swWebpackConfig = { + const swWebpackConfig: Configuration = { entry: path.resolve(__dirname, 'sw.js'), output: { path: outDir, @@ -136,12 +141,13 @@ function plugin(context, options) { splitChunks: false, minimize: !debug, // see https://developers.google.com/web/tools/workbox/guides/using-bundlers#webpack - minimizer: [ - !debug && - new Terser({ - test: swSourceFileTest, - }), - ].filter(Boolean), + minimizer: debug + ? [] + : [ + new Terser({ + test: swSourceFileTest, + }), + ], }, plugins: [ new webpack.EnvironmentPlugin({ @@ -173,6 +179,8 @@ function plugin(context, options) { '**/*.{js,json,css,html}', '**/*.{png,jpg,jpeg,gif,svg,ico}', '**/*.{woff,woff2,eot,ttf,otf}', + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore ...(injectManifest.globPatterns || []), ], // those attributes are not overrideable @@ -184,8 +192,4 @@ function plugin(context, options) { }; } -module.exports = plugin; - -plugin.validateOptions = function validateOptions({validate, options}) { - return validate(PluginOptionSchema, options); -}; +export {validateOptions} from './options'; diff --git a/packages/docusaurus-plugin-pwa/src/pluginOptionSchema.js b/packages/docusaurus-plugin-pwa/src/options.ts similarity index 75% rename from packages/docusaurus-plugin-pwa/src/pluginOptionSchema.js rename to packages/docusaurus-plugin-pwa/src/options.ts index 8dad8e3af1..a866b3bc0c 100644 --- a/packages/docusaurus-plugin-pwa/src/pluginOptionSchema.js +++ b/packages/docusaurus-plugin-pwa/src/options.ts @@ -4,9 +4,14 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ - -const {Joi} = require('@docusaurus/utils-validation'); -const path = require('path'); +import path from 'path'; +import {Joi} from '@docusaurus/utils-validation'; +import type { + ThemeConfig, + ValidationResult, + OptionValidationContext, +} from '@docusaurus/types'; +import type {PluginOptions} from '@docusaurus/plugin-pwa'; const DEFAULT_OPTIONS = { debug: false, @@ -22,7 +27,7 @@ const DEFAULT_OPTIONS = { reloadPopup: '@theme/PwaReloadPopup', }; -exports.PluginOptionSchema = Joi.object({ +export const Schema = Joi.object({ debug: Joi.bool().default(DEFAULT_OPTIONS.debug), offlineModeActivationStrategies: Joi.array() .items( @@ -52,3 +57,10 @@ exports.PluginOptionSchema = Joi.object({ .try(Joi.string(), Joi.bool().valid(false)) .default(DEFAULT_OPTIONS.reloadPopup), }); + +export function validateOptions({ + validate, + options, +}: OptionValidationContext): ValidationResult { + return validate(Schema, options); +} diff --git a/packages/docusaurus-plugin-pwa/src/plugin-pwa.d.ts b/packages/docusaurus-plugin-pwa/src/plugin-pwa.d.ts new file mode 100644 index 0000000000..86786b48f1 --- /dev/null +++ b/packages/docusaurus-plugin-pwa/src/plugin-pwa.d.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +declare module '@docusaurus/plugin-pwa' { + export type pwaHead = { + tagName: string; + href?: string; + content?: string; + [attributeName: string]: string | boolean; + }; + + export type PluginOptions = { + debug?: boolean; + offlineModeActivationStrategies; + injectManifestConfig; + reloadPopup; + pwaHead: pwaHead[]; + swCustom; + swRegister; + }; +} + +declare module '@theme/PwaReloadPopup' { + export type PwaReloadPopupProps = { + readonly onReload: () => void; + }; + + const PwaReloadPopup: (props: PwaReloadPopupProps) => JSX.Element; + export default PwaReloadPopup; +} diff --git a/packages/docusaurus-plugin-pwa/src/theme/PwaReloadPopup/index.js b/packages/docusaurus-plugin-pwa/src/theme/PwaReloadPopup/index.tsx similarity index 90% rename from packages/docusaurus-plugin-pwa/src/theme/PwaReloadPopup/index.js rename to packages/docusaurus-plugin-pwa/src/theme/PwaReloadPopup/index.tsx index 0e270892b5..5938859679 100644 --- a/packages/docusaurus-plugin-pwa/src/theme/PwaReloadPopup/index.js +++ b/packages/docusaurus-plugin-pwa/src/theme/PwaReloadPopup/index.tsx @@ -9,9 +9,11 @@ import React, {useState} from 'react'; import clsx from 'clsx'; import Translate, {translate} from '@docusaurus/Translate'; +import type {PwaReloadPopupProps} from '@theme/PwaReloadPopup'; + import styles from './styles.module.css'; -export default function PwaReloadPopup({onReload}) { +function PwaReloadPopup({onReload}: PwaReloadPopupProps): JSX.Element | false { const [isVisible, setIsVisible] = useState(true); return ( @@ -56,3 +58,5 @@ export default function PwaReloadPopup({onReload}) { ) ); } + +export default PwaReloadPopup; diff --git a/packages/docusaurus-plugin-pwa/src/types.d.ts b/packages/docusaurus-plugin-pwa/src/types.d.ts new file mode 100644 index 0000000000..6f6f99f127 --- /dev/null +++ b/packages/docusaurus-plugin-pwa/src/types.d.ts @@ -0,0 +1,8 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/// diff --git a/packages/docusaurus-plugin-pwa/tsconfig.browser.json b/packages/docusaurus-plugin-pwa/tsconfig.browser.json new file mode 100644 index 0000000000..3af8257cdf --- /dev/null +++ b/packages/docusaurus-plugin-pwa/tsconfig.browser.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "esnext", + "jsx": "react-native" + }, + "include": ["src/theme/", "src/*.d.ts"] +} diff --git a/packages/docusaurus-plugin-pwa/tsconfig.json b/packages/docusaurus-plugin-pwa/tsconfig.json new file mode 100644 index 0000000000..4b7c4f42a6 --- /dev/null +++ b/packages/docusaurus-plugin-pwa/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "lib": ["DOM", "ES2019"], + "rootDir": "src", + "baseUrl": "src", + "outDir": "lib" + } +} diff --git a/packages/docusaurus-plugin-pwa/tsconfig.server.json b/packages/docusaurus-plugin-pwa/tsconfig.server.json new file mode 100644 index 0000000000..1a463cd83a --- /dev/null +++ b/packages/docusaurus-plugin-pwa/tsconfig.server.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/*.ts"] +} diff --git a/packages/docusaurus-theme-classic/update-code-translations.js b/packages/docusaurus-theme-classic/update-code-translations.js index 73cba2ff96..6ae652abbe 100644 --- a/packages/docusaurus-theme-classic/update-code-translations.js +++ b/packages/docusaurus-theme-classic/update-code-translations.js @@ -17,7 +17,7 @@ const CodeDirPaths = [ path.join(__dirname, '..', 'docusaurus-theme-common', 'lib'), path.join(__dirname, '..', 'docusaurus-theme-search-algolia', 'lib', 'theme'), path.join(__dirname, '..', 'docusaurus-theme-live-codeblock', 'src', 'theme'), - path.join(__dirname, '..', 'docusaurus-plugin-pwa', 'src', 'theme'), + path.join(__dirname, '..', 'docusaurus-plugin-pwa', 'lib', 'theme'), ]; console.log('Will scan folders for code translations:', CodeDirPaths);