refactor(ganalytics, gtag): move options out of themeConfig (#5832)

* refactor(ganalytics, gtag): move options out of themeConfig

* Forbid themeConfig options

* Add PR link

* Add key names to error message

* Fix?

* Doc updates

Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
This commit is contained in:
Joshua Chen 2021-11-10 19:04:43 +08:00 committed by GitHub
parent f5732e7589
commit ac88d979f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 274 additions and 106 deletions

View file

@ -22,7 +22,7 @@ declare module '@generated/site-metadata' {
import type {DocusaurusSiteMetadata} from '@docusaurus/types';
const siteMetadata: DocusaurusSiteMetadata;
export default siteMetadata;
export = siteMetadata;
}
declare module '@generated/registry' {
@ -48,13 +48,13 @@ declare module '@generated/routes' {
declare module '@generated/routesChunkNames' {
const routesChunkNames: Record<string, Record<string, string>>;
export default routesChunkNames;
export = routesChunkNames;
}
declare module '@generated/globalData' {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const globalData: Record<string, any>;
export default globalData;
export = globalData;
}
declare module '@generated/i18n' {
@ -64,12 +64,12 @@ declare module '@generated/i18n' {
currentLocale: string;
localeConfigs: Record<string, {label: string; direction: string}>;
};
export default i18n;
export = i18n;
}
declare module '@generated/codeTranslations' {
const codeTranslations: Record<string, string>;
export default codeTranslations;
export = codeTranslations;
}
declare module '@theme-original/*';

View file

@ -18,7 +18,8 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "2.0.0-beta.9"
"@docusaurus/core": "2.0.0-beta.9",
"@docusaurus/utils-validation": "2.0.0-beta.9"
},
"devDependencies": {
"@docusaurus/types": "2.0.0-beta.9"

View file

@ -6,30 +6,23 @@
*/
import path from 'path';
import type {LoadContext, Plugin, HtmlTags} from '@docusaurus/types';
import type {ThemeConfig} from '@docusaurus/plugin-google-analytics';
export default function pluginGoogleAnalytics(context: LoadContext): Plugin {
const {
siteConfig: {themeConfig},
} = context;
const {googleAnalytics} = themeConfig as ThemeConfig;
if (!googleAnalytics) {
throw new Error(
`You need to specify "googleAnalytics" object in "themeConfig" with "trackingId" field in it to use docusaurus-plugin-google-analytics.`,
);
}
const {trackingID, anonymizeIP} = googleAnalytics;
if (!trackingID) {
throw new Error(
'You specified the "googleAnalytics" object in "themeConfig" but the "trackingID" field was missing. ' +
'Please ensure this is not a mistake.',
);
}
import {Joi} from '@docusaurus/utils-validation';
import type {
LoadContext,
Plugin,
HtmlTags,
OptionValidationContext,
ValidationResult,
ThemeConfig,
ThemeConfigValidationContext,
} from '@docusaurus/types';
import type {PluginOptions} from '@docusaurus/plugin-google-analytics';
export default function pluginGoogleAnalytics(
context: LoadContext,
options: PluginOptions,
): Plugin {
const {trackingID, anonymizeIP} = options;
const isProd = process.env.NODE_ENV === 'production';
return {
@ -74,3 +67,26 @@ export default function pluginGoogleAnalytics(context: LoadContext): Plugin {
},
};
}
const pluginOptionsSchema = Joi.object<PluginOptions>({
trackingID: Joi.string().required(),
anonymizeIP: Joi.boolean().default(false),
});
export function validateOptions({
validate,
options,
}: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions> {
return validate(pluginOptionsSchema, options);
}
export function validateThemeConfig({
themeConfig,
}: ThemeConfigValidationContext<ThemeConfig>): ValidationResult<ThemeConfig> {
if (themeConfig.googleAnalytics) {
throw new Error(
'The "googleAnalytics" field in themeConfig should now be specified as option for plugin-google-analytics. More information at https://github.com/facebook/docusaurus/pull/5832.',
);
}
return themeConfig;
}

View file

@ -5,9 +5,9 @@
* LICENSE file in the root directory of this source tree.
*/
export interface ThemeConfig {
googleAnalytics?: {
export type PluginOptions = {
trackingID: string;
anonymizeIP?: boolean;
anonymizeIP: boolean;
};
}
export type Options = Partial<PluginOptions>;

View file

@ -18,7 +18,8 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "2.0.0-beta.9"
"@docusaurus/core": "2.0.0-beta.9",
"@docusaurus/utils-validation": "2.0.0-beta.9"
},
"devDependencies": {
"@docusaurus/types": "2.0.0-beta.9"

View file

@ -6,17 +6,16 @@
*/
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
import siteConfig from '@generated/docusaurus.config';
import type {ThemeConfig} from '@docusaurus/plugin-google-gtag';
import globalData from '@generated/globalData';
import type {PluginOptions} from '@docusaurus/plugin-google-gtag';
export default (function () {
if (!ExecutionEnvironment.canUseDOM) {
return null;
}
const {themeConfig} = siteConfig;
const {gtag} = themeConfig as ThemeConfig;
const {trackingID} = gtag!;
const {trackingID} = globalData['docusaurus-plugin-google-gtag']
.default as PluginOptions;
return {
onRouteUpdate({location}: {location: Location}) {

View file

@ -6,35 +6,32 @@
*/
import path from 'path';
import type {LoadContext, Plugin, HtmlTags} from '@docusaurus/types';
import type {ThemeConfig} from '@docusaurus/plugin-google-gtag';
export default function pluginGoogleGtag(context: LoadContext): Plugin {
const {
siteConfig: {themeConfig},
} = context;
const {gtag} = themeConfig as ThemeConfig;
if (!gtag) {
throw new Error(
`You need to specify "gtag" object in "themeConfig" with "trackingId" field in it to use docusaurus-plugin-google-gtag.`,
);
}
const {anonymizeIP, trackingID} = gtag;
if (!trackingID) {
throw new Error(
'You specified the "gtag" object in "themeConfig" but the "trackingID" field was missing. ' +
'Please ensure this is not a mistake.',
);
}
import {Joi} from '@docusaurus/utils-validation';
import type {
LoadContext,
Plugin,
HtmlTags,
OptionValidationContext,
ValidationResult,
ThemeConfig,
ThemeConfigValidationContext,
} from '@docusaurus/types';
import type {PluginOptions} from '@docusaurus/plugin-google-gtag';
export default function pluginGoogleGtag(
context: LoadContext,
options: PluginOptions,
): Plugin {
const {anonymizeIP, trackingID} = options;
const isProd = process.env.NODE_ENV === 'production';
return {
name: 'docusaurus-plugin-google-gtag',
async contentLoaded({actions}) {
actions.setGlobalData(options);
},
getClientModules() {
return isProd ? [path.resolve(__dirname, './gtag')] : [];
},
@ -83,3 +80,26 @@ export default function pluginGoogleGtag(context: LoadContext): Plugin {
},
};
}
const pluginOptionsSchema = Joi.object<PluginOptions>({
trackingID: Joi.string().required(),
anonymizeIP: Joi.boolean().default(false),
});
export function validateOptions({
validate,
options,
}: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions> {
return validate(pluginOptionsSchema, options);
}
export function validateThemeConfig({
themeConfig,
}: ThemeConfigValidationContext<ThemeConfig>): ValidationResult<ThemeConfig> {
if (themeConfig.gtag) {
throw new Error(
'The "gtag" field in themeConfig should now be specified as option for plugin-google-gtag. More information at https://github.com/facebook/docusaurus/pull/5832.',
);
}
return themeConfig;
}

View file

@ -5,9 +5,9 @@
* LICENSE file in the root directory of this source tree.
*/
export interface ThemeConfig {
gtag?: {
export type PluginOptions = {
trackingID: string;
anonymizeIP?: boolean;
anonymizeIP: boolean;
};
}
export type Options = Partial<PluginOptions>;

View file

@ -29,9 +29,19 @@ export default function preset(
): Preset {
const {siteConfig} = context;
const {themeConfig} = siteConfig;
const {algolia, googleAnalytics, gtag} = themeConfig as Partial<ThemeConfig>;
const {algolia} = themeConfig as Partial<ThemeConfig>;
const isProd = process.env.NODE_ENV === 'production';
const {debug, docs, blog, pages, sitemap, theme, ...rest} = opts;
const {
debug,
docs,
blog,
pages,
sitemap,
theme,
googleAnalytics,
gtag,
...rest
} = opts;
const themes: PluginConfig[] = [];
themes.push(makePluginConfig('@docusaurus/theme-classic', theme));
@ -50,13 +60,15 @@ export default function preset(
plugins.push(makePluginConfig('@docusaurus/plugin-content-pages', pages));
}
if (isProd && googleAnalytics) {
plugins.push(require.resolve('@docusaurus/plugin-google-analytics'));
plugins.push(
makePluginConfig('@docusaurus/plugin-google-analytics', googleAnalytics),
);
}
if (debug || (debug === undefined && !isProd)) {
plugins.push(require.resolve('@docusaurus/plugin-debug'));
}
if (isProd && gtag) {
plugins.push(require.resolve('@docusaurus/plugin-google-gtag'));
plugins.push(makePluginConfig('@docusaurus/plugin-google-gtag', gtag));
}
if (isProd && sitemap !== false) {
plugins.push(makePluginConfig('@docusaurus/plugin-sitemap', sitemap));
@ -65,7 +77,7 @@ export default function preset(
throw new Error(
`Unrecognized keys ${Object.keys(rest).join(
', ',
)} found in preset-classic configuration. The allowed keys are debug, docs, blog, pages, sitemap, theme. Check the documentation: https://docusaurus.io/docs/presets#docusauruspreset-classic for more information on how to configure individual plugins.`,
)} found in preset-classic configuration. The allowed keys are debug, docs, blog, pages, sitemap, theme, googleAnalytics, gtag. Check the documentation: https://docusaurus.io/docs/presets#docusauruspreset-classic for more information on how to configure individual plugins.`,
);
}

View file

@ -12,13 +12,11 @@ export type Options = {
pages?: false | import('@docusaurus/plugin-content-pages').Options;
sitemap?: false | import('@docusaurus/plugin-sitemap').Options;
theme?: import('@docusaurus/theme-classic').Options;
googleAnalytics?: import('@docusaurus/plugin-google-analytics').Options;
gtag?: import('@docusaurus/plugin-google-gtag').Options;
};
export type ThemeConfig = import('@docusaurus/types').ThemeConfig &
import('@docusaurus/theme-common').UserThemeConfig &
// Those plugins themeConfigs should rather be moved to preset/plugin options
// Plugin data can be made available to browser thank to the globalData api
import('@docusaurus/plugin-google-analytics').ThemeConfig &
import('@docusaurus/plugin-google-gtag').ThemeConfig & {
import('@docusaurus/theme-common').UserThemeConfig & {
algolia?: unknown; // TODO type plugin
};

View file

@ -21,15 +21,74 @@ If you have installed `@docusaurus/preset-classic`, you don't need to install it
## Configuration {#configuration}
```js title="docusaurus.config.js"
module.exports = {
plugins: ['@docusaurus/plugin-google-analytics'],
themeConfig: {
googleAnalytics: {
Accepted fields:
<small>
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `trackingID` | `string` | **Required** | The tracking ID of your analytics service. |
| `anonymizeIP` | `boolean` | `false` | Whether the IP should be anonymized when sending requests. |
</small>
## Example configuration {#ex-config}
Here's an example configuration object.
You can provide it as [preset options](#ex-config-preset) or [plugin options](#ex-config-plugin).
:::tip
Most Docusaurus users configure this plugin through the [preset options](#ex-config-preset).
:::
```js
const config = {
trackingID: 'UA-141789564-1',
// Optional fields.
anonymizeIP: true, // Should IPs be anonymized?
},
},
anonymizeIP: true,
};
```
### Preset options {#ex-config-preset}
If you use a preset, configure this plugin through the [preset options](presets.md#docusauruspreset-classic):
```js title="docusaurus.config.js"
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
// highlight-start
googleAnalytics: {
trackingID: 'UA-141789564-1',
anonymizeIP: true,
},
// highlight-end
},
],
],
};
```
### Plugin options {#ex-config-plugin}
If you are using a standalone plugin, provide options directly to the plugin:
```js title="docusaurus.config.js"
module.exports = {
plugins: [
[
'@docusaurus/plugin-google-analytics',
// highlight-start
{
trackingID: 'UA-141789564-1',
anonymizeIP: true,
},
// highlight-end
],
],
};
```

View file

@ -27,16 +27,74 @@ If you have installed `@docusaurus/preset-classic`, you don't need to install it
## Configuration {#configuration}
```js title="docusaurus.config.js"
module.exports = {
plugins: ['@docusaurus/plugin-google-gtag'],
themeConfig: {
gtag: {
// You can also use your "G-" Measurement ID here.
Accepted fields:
<small>
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `trackingID` | `string` | **Required** | The tracking ID of your gtag service. |
| `anonymizeIP` | `boolean` | `false` | Whether the IP should be anonymized when sending requests. |
</small>
## Example configuration {#ex-config}
Here's an example configuration object.
You can provide it as [preset options](#ex-config-preset) or [plugin options](#ex-config-plugin).
:::tip
Most Docusaurus users configure this plugin through the [preset options](#ex-config-preset).
:::
```js
const config = {
trackingID: 'UA-141789564-1',
// Optional fields.
anonymizeIP: true, // Should IPs be anonymized?
},
},
anonymizeIP: true,
};
```
### Preset options {#ex-config-preset}
If you use a preset, configure this plugin through the [preset options](presets.md#docusauruspreset-classic):
```js title="docusaurus.config.js"
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
// highlight-start
gtag: {
trackingID: 'UA-141789564-1',
anonymizeIP: true,
},
// highlight-end
},
],
],
};
```
### Plugin options {#ex-config-plugin}
If you are using a standalone plugin, provide options directly to the plugin:
```js title="docusaurus.config.js"
module.exports = {
plugins: [
[
'@docusaurus/plugin-google-gtag',
// highlight-start
{
trackingID: 'UA-141789564-1',
anonymizeIP: true,
},
// highlight-end
],
],
};
```

View file

@ -106,6 +106,10 @@ module.exports = {
pages: {},
// Will be passed to @docusaurus/plugin-content-sitemap (false to disable)
sitemap: {},
// Will be passed to @docusaurus/plugin-google-gtag (only enabled when explicitly specified)
gtag: {},
// Will be passed to @docusaurus/plugin-google-analytics (only enabled when explicitly specified)
googleAnalytics: {},
},
],
],

View file

@ -301,6 +301,11 @@ const config = {
theme: {
customCss: [require.resolve('./src/css/custom.css')],
},
gtag: !isDeployPreview
? {
trackingID: 'UA-141789564-1',
}
: undefined,
}),
],
],
@ -328,11 +333,6 @@ const config = {
},
image: 'img/docusaurus-soc.png',
// metadata: [{name: 'twitter:card', content: 'summary'}],
gtag: !isDeployPreview
? {
trackingID: 'UA-141789564-1',
}
: undefined,
algolia: {
appId: 'X1Z85QJPUV',
apiKey: 'bf7211c161e8205da2f933a02534105a',