Browse Source

analytics

GA
Pavle Golubovic 3 years ago
parent
commit
0182c97df4
100 changed files with 9306 additions and 22 deletions
  1. 1
    0
      frontend/.env
  2. 11
    19
      frontend/src/App.js
  3. 7
    3
      frontend/src/components/shared/Navigation.jsx
  4. 10
    0
      frontend/src/hooks/useAnalyticsEventTracker.jsx
  5. 12
    0
      node_modules/.bin/loose-envify
  6. 17
    0
      node_modules/.bin/loose-envify.cmd
  7. 28
    0
      node_modules/.bin/loose-envify.ps1
  8. 72
    0
      node_modules/.package-lock.json
  9. 151
    0
      node_modules/js-tokens/CHANGELOG.md
  10. 21
    0
      node_modules/js-tokens/LICENSE
  11. 240
    0
      node_modules/js-tokens/README.md
  12. 23
    0
      node_modules/js-tokens/index.js
  13. 30
    0
      node_modules/js-tokens/package.json
  14. 21
    0
      node_modules/loose-envify/LICENSE
  15. 45
    0
      node_modules/loose-envify/README.md
  16. 16
    0
      node_modules/loose-envify/cli.js
  17. 4
    0
      node_modules/loose-envify/custom.js
  18. 3
    0
      node_modules/loose-envify/index.js
  19. 36
    0
      node_modules/loose-envify/loose-envify.js
  20. 36
    0
      node_modules/loose-envify/package.json
  21. 65
    0
      node_modules/loose-envify/replace.js
  22. 90
    0
      node_modules/object-assign/index.js
  23. 21
    0
      node_modules/object-assign/license
  24. 42
    0
      node_modules/object-assign/package.json
  25. 61
    0
      node_modules/object-assign/readme.md
  26. 21
    0
      node_modules/prop-types/LICENSE
  27. 302
    0
      node_modules/prop-types/README.md
  28. 103
    0
      node_modules/prop-types/checkPropTypes.js
  29. 19
    0
      node_modules/prop-types/factory.js
  30. 65
    0
      node_modules/prop-types/factoryWithThrowingShims.js
  31. 610
    0
      node_modules/prop-types/factoryWithTypeCheckers.js
  32. 19
    0
      node_modules/prop-types/index.js
  33. 12
    0
      node_modules/prop-types/lib/ReactPropTypesSecret.js
  34. 1
    0
      node_modules/prop-types/lib/has.js
  35. 60
    0
      node_modules/prop-types/package.json
  36. 1315
    0
      node_modules/prop-types/prop-types.js
  37. 1
    0
      node_modules/prop-types/prop-types.min.js
  38. 6
    0
      node_modules/react-ga/.eslintignore
  39. 58
    0
      node_modules/react-ga/.eslintrc.js
  40. 23
    0
      node_modules/react-ga/.github/workflows/release.yml
  41. 26
    0
      node_modules/react-ga/.github/workflows/tests.yml
  42. 4
    0
      node_modules/react-ga/.husky/commit-msg
  43. 4
    0
      node_modules/react-ga/.husky/pre-commit
  44. 3
    0
      node_modules/react-ga/.lintstagedrc.js
  45. 4
    0
      node_modules/react-ga/.prettierrc.js
  46. 3
    0
      node_modules/react-ga/.releaserc.json
  47. 10
    0
      node_modules/react-ga/CONTRIBUTING.md
  48. 13
    0
      node_modules/react-ga/LICENSE
  49. 484
    0
      node_modules/react-ga/README.md
  50. 27
    0
      node_modules/react-ga/bower.json
  51. 1
    0
      node_modules/react-ga/commitlint.config.js
  52. 2
    0
      node_modules/react-ga/core.d.ts
  53. 4
    0
      node_modules/react-ga/core.js
  54. 55
    0
      node_modules/react-ga/demo/app/Events.jsx
  55. 91
    0
      node_modules/react-ga/demo/app/Router.jsx
  56. 173
    0
      node_modules/react-ga/demo/app/index.jsx
  57. 43
    0
      node_modules/react-ga/demo/app/withTracker.jsx
  58. 8
    0
      node_modules/react-ga/demo/index.jsx
  59. 131
    0
      node_modules/react-ga/dist/esm/components/OutboundLink.js
  60. 635
    0
      node_modules/react-ga/dist/esm/core.js
  61. 40
    0
      node_modules/react-ga/dist/esm/index.js
  62. 1
    0
      node_modules/react-ga/dist/esm/utils/__mocks__/loadGA.js
  63. 3
    0
      node_modules/react-ga/dist/esm/utils/console/log.js
  64. 3
    0
      node_modules/react-ga/dist/esm/utils/console/warn.js
  65. 19
    0
      node_modules/react-ga/dist/esm/utils/format.js
  66. 30
    0
      node_modules/react-ga/dist/esm/utils/loadGA.js
  67. 6
    0
      node_modules/react-ga/dist/esm/utils/mightBeEmail.js
  68. 11
    0
      node_modules/react-ga/dist/esm/utils/redactEmail.js
  69. 7
    0
      node_modules/react-ga/dist/esm/utils/removeLeadingSlash.js
  70. 14
    0
      node_modules/react-ga/dist/esm/utils/testModeAPI.js
  71. 21
    0
      node_modules/react-ga/dist/esm/utils/toTitleCase.js
  72. 5
    0
      node_modules/react-ga/dist/esm/utils/trim.js
  73. 1034
    0
      node_modules/react-ga/dist/react-ga-core.js
  74. 1
    0
      node_modules/react-ga/dist/react-ga-core.min.js
  75. 1267
    0
      node_modules/react-ga/dist/react-ga.js
  76. 1
    0
      node_modules/react-ga/dist/react-ga.min.js
  77. 3
    0
      node_modules/react-ga/jest.config.js
  78. 4
    0
      node_modules/react-ga/jest.setup.js
  79. 88
    0
      node_modules/react-ga/package.json
  80. 75
    0
      node_modules/react-ga/src/components/OutboundLink.js
  81. 591
    0
      node_modules/react-ga/src/core.js
  82. 25
    0
      node_modules/react-ga/src/index.js
  83. 1
    0
      node_modules/react-ga/src/utils/__mocks__/loadGA.js
  84. 3
    0
      node_modules/react-ga/src/utils/console/log.js
  85. 3
    0
      node_modules/react-ga/src/utils/console/warn.js
  86. 20
    0
      node_modules/react-ga/src/utils/format.js
  87. 31
    0
      node_modules/react-ga/src/utils/loadGA.js
  88. 6
    0
      node_modules/react-ga/src/utils/mightBeEmail.js
  89. 13
    0
      node_modules/react-ga/src/utils/redactEmail.js
  90. 7
    0
      node_modules/react-ga/src/utils/removeLeadingSlash.js
  91. 11
    0
      node_modules/react-ga/src/utils/testModeAPI.js
  92. 35
    0
      node_modules/react-ga/src/utils/toTitleCase.js
  93. 6
    0
      node_modules/react-ga/src/utils/trim.js
  94. 203
    0
      node_modules/react-ga/types/index.d.ts
  95. 168
    0
      node_modules/react-ga/types/react-ga-tests.ts
  96. 17
    0
      node_modules/react-ga/types/tsconfig.json
  97. 9
    0
      node_modules/react-ga/version-bower.js
  98. 21
    0
      node_modules/react-is/LICENSE
  99. 104
    0
      node_modules/react-is/README.md
  100. 0
    0
      node_modules/react-is/build-info.json

+ 1
- 0
frontend/.env View File

@@ -8,3 +8,4 @@ REACT_APP_USER_ID = 27spvSZ2Lsf2j8RKw
REACT_APP_API_URL = "https://websitediligentapi.azurewebsites.net"
//http://localhost:1337
MAILCHIMP_FORM_URL = http://eepurl.com/iaRrv1
GOOGLE_TRACKING_ID = G-PTZC3WLTZ1

+ 11
- 19
frontend/src/App.js View File

@@ -1,26 +1,12 @@
import React, { useEffect, lazy, Suspense } from 'react';
import React, { useEffect, lazy, Suspense, useRef, useState } from 'react';
import './App.css';
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import Navigation from './components/shared/Navigation';
// import Home from './pages/Home';
// import Portfolio from './pages/Portfolio';
// import Services from './pages/Services';
// import Careers from './pages/Careers';
// import About from './pages/About';
// import BlogPost from './components/BlogPost';
import Footer from './components/shared/Footer';
import { useRef, useState } from 'react';
import Loader from './components/shared/Loader';
// import ProcessPage from './pages/ProcessPage';
// import ContactPage from './pages/ContactPage';
// import CaseStudyBI from './pages/CaseStudyBI';
// import CaseStudyFinantial from './pages/CaseStudyFinantial';
// import CaseStudyTicketing from './pages/CaseStudyTicketing';
// import CaseStudyCentralized from './pages/CaseStudyCentralized';
// import CaseStudyResource from './pages/CaseStudyResource';
// import CaseStudyStrata from './pages/CaseStudyStrata';
// import PrivacyPolicy from './pages/PrivacyPolicy';
// import WorkWithUs from './pages/WorkWithUs';
import ScrollToTop from './components/root/ScrollToTop';

import ReactGa from 'react-ga';

const Home = lazy(() => import('./pages/Home'));
const Portfolio = lazy(() => import('./pages/Portfolio'));
@@ -38,7 +24,11 @@ const CaseStudyResource = lazy(() => import('./pages/CaseStudyResource'));
const CaseStudyStrata = lazy(() => import('./pages/CaseStudyStrata'));
const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy'));
const WorkWithUs = lazy(() => import('./pages/WorkWithUs'));
import ScrollToTop from './components/root/ScrollToTop';

const trackingId = process.env.GOOGLE_TRACKING_ID;

//Initalize analytics
ReactGa.initialize(trackingId);

// Navigation Links
const links = [
@@ -103,6 +93,8 @@ function App() {
}
}



return (
<div>
<ScrollToTop />

+ 7
- 3
frontend/src/components/shared/Navigation.jsx View File

@@ -7,6 +7,7 @@ import { NavLink, useLocation, useNavigate } from 'react-router-dom';
import '../../App.css';
import Wrapper from '../../layout/Wrapper';
import menuIcon from './../../assets/icons/menu.svg';
import useAnalyticsEventTracker from '../../hooks/useAnalyticsEventTracker';

export default function Navigation({ links, scrollToView, activeLinks }) {
const location = useLocation();
@@ -15,9 +16,11 @@ export default function Navigation({ links, scrollToView, activeLinks }) {
home('/');
}

function checkUrl(event) {
//console.log(location.pathname);
const gaEventTracker = useAnalyticsEventTracker('Contact Us')

// Check if you are on HomePage to scroll to Contact us, or open a sepperate Contact us Page
function checkUrl(event) {
if (location.pathname === '/') scrollToView(event);
else home('/contact');
}
@@ -64,7 +67,7 @@ export default function Navigation({ links, scrollToView, activeLinks }) {
{/* React Router Link does not support Anchor tags */}
<div
// onClick={event => scrollToView(event)}
onClick={event => checkUrl(event)}
onClick={event => {gaEventTracker('contact');checkUrl(event)}}
href="#contact"
className="contact-us-link text-p"
>
@@ -133,6 +136,7 @@ export default function Navigation({ links, scrollToView, activeLinks }) {
<a
href="#contact"
onClick={event => {
gaEventTracker('contact');
close();
checkUrl(event);
}}

+ 10
- 0
frontend/src/hooks/useAnalyticsEventTracker.jsx View File

@@ -0,0 +1,10 @@
import React from "react";
import ReactGA from 'react-ga';

const useAnalyticsEventTracker = (category="Contact category") => {
const eventTracker = (action = "test action", label = "test label") => {
ReactGA.event({category, action, label});
}
return eventTracker;
}
export default useAnalyticsEventTracker;

+ 12
- 0
node_modules/.bin/loose-envify View File

@@ -0,0 +1,12 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../loose-envify/cli.js" "$@"
else
exec node "$basedir/../loose-envify/cli.js" "$@"
fi

+ 17
- 0
node_modules/.bin/loose-envify.cmd View File

@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0

IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)

endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\loose-envify\cli.js" %*

+ 28
- 0
node_modules/.bin/loose-envify.ps1 View File

@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent

$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../loose-envify/cli.js" $args
} else {
& "$basedir/node$exe" "$basedir/../loose-envify/cli.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../loose-envify/cli.js" $args
} else {
& "node$exe" "$basedir/../loose-envify/cli.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret

+ 72
- 0
node_modules/.package-lock.json View File

@@ -0,0 +1,72 @@
{
"name": "website-new",
"lockfileVersion": 2,
"requires": true,
"packages": {
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"peer": true
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"peer": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"peer": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.13.1"
}
},
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-ga": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.1.tgz",
"integrity": "sha512-4Vc0W5EvXAXUN/wWyxvsAKDLLgtJ3oLmhYYssx+YzphJpejtOst6cbIHCIyF50Fdxuf5DDKqRYny24yJ2y7GFQ==",
"peerDependencies": {
"prop-types": "^15.6.0",
"react": "^15.6.2 || ^16.0 || ^17 || ^18"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"peer": true
}
}
}

+ 151
- 0
node_modules/js-tokens/CHANGELOG.md View File

@@ -0,0 +1,151 @@
### Version 4.0.0 (2018-01-28) ###

- Added: Support for ES2018. The only change needed was recognizing the `s`
regex flag.
- Changed: _All_ tokens returned by the `matchToToken` function now have a
`closed` property. It is set to `undefined` for the tokens where “closed”
doesn’t make sense. This means that all tokens objects have the same shape,
which might improve performance.

These are the breaking changes:

- `'/a/s'.match(jsTokens)` no longer returns `['/', 'a', '/', 's']`, but
`['/a/s']`. (There are of course other variations of this.)
- Code that rely on some token objects not having the `closed` property could
now behave differently.


### Version 3.0.2 (2017-06-28) ###

- No code changes. Just updates to the readme.


### Version 3.0.1 (2017-01-30) ###

- Fixed: ES2015 unicode escapes with more than 6 hex digits are now matched
correctly.


### Version 3.0.0 (2017-01-11) ###

This release contains one breaking change, that should [improve performance in
V8][v8-perf]:

> So how can you, as a JavaScript developer, ensure that your RegExps are fast?
> If you are not interested in hooking into RegExp internals, make sure that
> neither the RegExp instance, nor its prototype is modified in order to get the
> best performance:
>
> ```js
> var re = /./g;
> re.exec(''); // Fast path.
> re.new_property = 'slow';
> ```

This module used to export a single regex, with `.matchToToken` bolted
on, just like in the above example. This release changes the exports of
the module to avoid this issue.

Before:

```js
import jsTokens from "js-tokens"
// or:
var jsTokens = require("js-tokens")
var matchToToken = jsTokens.matchToToken
```

After:

```js
import jsTokens, {matchToToken} from "js-tokens"
// or:
var jsTokens = require("js-tokens").default
var matchToToken = require("js-tokens").matchToToken
```

[v8-perf]: http://v8project.blogspot.se/2017/01/speeding-up-v8-regular-expressions.html


### Version 2.0.0 (2016-06-19) ###

- Added: Support for ES2016. In other words, support for the `**` exponentiation
operator.

These are the breaking changes:

- `'**'.match(jsTokens)` no longer returns `['*', '*']`, but `['**']`.
- `'**='.match(jsTokens)` no longer returns `['*', '*=']`, but `['**=']`.


### Version 1.0.3 (2016-03-27) ###

- Improved: Made the regex ever so slightly smaller.
- Updated: The readme.


### Version 1.0.2 (2015-10-18) ###

- Improved: Limited npm package contents for a smaller download. Thanks to
@zertosh!


### Version 1.0.1 (2015-06-20) ###

- Fixed: Declared an undeclared variable.


### Version 1.0.0 (2015-02-26) ###

- Changed: Merged the 'operator' and 'punctuation' types into 'punctuator'. That
type is now equivalent to the Punctuator token in the ECMAScript
specification. (Backwards-incompatible change.)
- Fixed: A `-` followed by a number is now correctly matched as a punctuator
followed by a number. It used to be matched as just a number, but there is no
such thing as negative number literals. (Possibly backwards-incompatible
change.)


### Version 0.4.1 (2015-02-21) ###

- Added: Support for the regex `u` flag.


### Version 0.4.0 (2015-02-21) ###

- Improved: `jsTokens.matchToToken` performance.
- Added: Support for octal and binary number literals.
- Added: Support for template strings.


### Version 0.3.1 (2015-01-06) ###

- Fixed: Support for unicode spaces. They used to be allowed in names (which is
very confusing), and some unicode newlines were wrongly allowed in strings and
regexes.


### Version 0.3.0 (2014-12-19) ###

- Changed: The `jsTokens.names` array has been replaced with the
`jsTokens.matchToToken` function. The capturing groups of `jsTokens` are no
longer part of the public API; instead use said function. See this [gist] for
an example. (Backwards-incompatible change.)
- Changed: The empty string is now considered an “invalid” token, instead an
“empty” token (its own group). (Backwards-incompatible change.)
- Removed: component support. (Backwards-incompatible change.)

[gist]: https://gist.github.com/lydell/be49dbf80c382c473004


### Version 0.2.0 (2014-06-19) ###

- Changed: Match ES6 function arrows (`=>`) as an operator, instead of its own
category (“functionArrow”), for simplicity. (Backwards-incompatible change.)
- Added: ES6 splats (`...`) are now matched as an operator (instead of three
punctuations). (Backwards-incompatible change.)


### Version 0.1.0 (2014-03-08) ###

- Initial release.

+ 21
- 0
node_modules/js-tokens/LICENSE View File

@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2014, 2015, 2016, 2017, 2018 Simon Lydell

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 240
- 0
node_modules/js-tokens/README.md View File

@@ -0,0 +1,240 @@
Overview [![Build Status](https://travis-ci.org/lydell/js-tokens.svg?branch=master)](https://travis-ci.org/lydell/js-tokens)
========

A regex that tokenizes JavaScript.

```js
var jsTokens = require("js-tokens").default

var jsString = "var foo=opts.foo;\n..."

jsString.match(jsTokens)
// ["var", " ", "foo", "=", "opts", ".", "foo", ";", "\n", ...]
```


Installation
============

`npm install js-tokens`

```js
import jsTokens from "js-tokens"
// or:
var jsTokens = require("js-tokens").default
```


Usage
=====

### `jsTokens` ###

A regex with the `g` flag that matches JavaScript tokens.

The regex _always_ matches, even invalid JavaScript and the empty string.

The next match is always directly after the previous.

### `var token = matchToToken(match)` ###

```js
import {matchToToken} from "js-tokens"
// or:
var matchToToken = require("js-tokens").matchToToken
```

Takes a `match` returned by `jsTokens.exec(string)`, and returns a `{type:
String, value: String}` object. The following types are available:

- string
- comment
- regex
- number
- name
- punctuator
- whitespace
- invalid

Multi-line comments and strings also have a `closed` property indicating if the
token was closed or not (see below).

Comments and strings both come in several flavors. To distinguish them, check if
the token starts with `//`, `/*`, `'`, `"` or `` ` ``.

Names are ECMAScript IdentifierNames, that is, including both identifiers and
keywords. You may use [is-keyword-js] to tell them apart.

Whitespace includes both line terminators and other whitespace.

[is-keyword-js]: https://github.com/crissdev/is-keyword-js


ECMAScript support
==================

The intention is to always support the latest ECMAScript version whose feature
set has been finalized.

If adding support for a newer version requires changes, a new version with a
major verion bump will be released.

Currently, ECMAScript 2018 is supported.


Invalid code handling
=====================

Unterminated strings are still matched as strings. JavaScript strings cannot
contain (unescaped) newlines, so unterminated strings simply end at the end of
the line. Unterminated template strings can contain unescaped newlines, though,
so they go on to the end of input.

Unterminated multi-line comments are also still matched as comments. They
simply go on to the end of the input.

Unterminated regex literals are likely matched as division and whatever is
inside the regex.

Invalid ASCII characters have their own capturing group.

Invalid non-ASCII characters are treated as names, to simplify the matching of
names (except unicode spaces which are treated as whitespace). Note: See also
the [ES2018](#es2018) section.

Regex literals may contain invalid regex syntax. They are still matched as
regex literals. They may also contain repeated regex flags, to keep the regex
simple.

Strings may contain invalid escape sequences.


Limitations
===========

Tokenizing JavaScript using regexes—in fact, _one single regex_—won’t be
perfect. But that’s not the point either.

You may compare jsTokens with [esprima] by using `esprima-compare.js`.
See `npm run esprima-compare`!

[esprima]: http://esprima.org/

### Template string interpolation ###

Template strings are matched as single tokens, from the starting `` ` `` to the
ending `` ` ``, including interpolations (whose tokens are not matched
individually).

Matching template string interpolations requires recursive balancing of `{` and
`}`—something that JavaScript regexes cannot do. Only one level of nesting is
supported.

### Division and regex literals collision ###

Consider this example:

```js
var g = 9.82
var number = bar / 2/g

var regex = / 2/g
```

A human can easily understand that in the `number` line we’re dealing with
division, and in the `regex` line we’re dealing with a regex literal. How come?
Because humans can look at the whole code to put the `/` characters in context.
A JavaScript regex cannot. It only sees forwards. (Well, ES2018 regexes can also
look backwards. See the [ES2018](#es2018) section).

When the `jsTokens` regex scans throught the above, it will see the following
at the end of both the `number` and `regex` rows:

```js
/ 2/g
```

It is then impossible to know if that is a regex literal, or part of an
expression dealing with division.

Here is a similar case:

```js
foo /= 2/g
foo(/= 2/g)
```

The first line divides the `foo` variable with `2/g`. The second line calls the
`foo` function with the regex literal `/= 2/g`. Again, since `jsTokens` only
sees forwards, it cannot tell the two cases apart.

There are some cases where we _can_ tell division and regex literals apart,
though.

First off, we have the simple cases where there’s only one slash in the line:

```js
var foo = 2/g
foo /= 2
```

Regex literals cannot contain newlines, so the above cases are correctly
identified as division. Things are only problematic when there are more than
one non-comment slash in a single line.

Secondly, not every character is a valid regex flag.

```js
var number = bar / 2/e
```

The above example is also correctly identified as division, because `e` is not a
valid regex flag. I initially wanted to future-proof by allowing `[a-zA-Z]*`
(any letter) as flags, but it is not worth it since it increases the amount of
ambigous cases. So only the standard `g`, `m`, `i`, `y` and `u` flags are
allowed. This means that the above example will be identified as division as
long as you don’t rename the `e` variable to some permutation of `gmiyus` 1 to 6
characters long.

Lastly, we can look _forward_ for information.

- If the token following what looks like a regex literal is not valid after a
regex literal, but is valid in a division expression, then the regex literal
is treated as division instead. For example, a flagless regex cannot be
followed by a string, number or name, but all of those three can be the
denominator of a division.
- Generally, if what looks like a regex literal is followed by an operator, the
regex literal is treated as division instead. This is because regexes are
seldomly used with operators (such as `+`, `*`, `&&` and `==`), but division
could likely be part of such an expression.

Please consult the regex source and the test cases for precise information on
when regex or division is matched (should you need to know). In short, you
could sum it up as:

If the end of a statement looks like a regex literal (even if it isn’t), it
will be treated as one. Otherwise it should work as expected (if you write sane
code).

### ES2018 ###

ES2018 added some nice regex improvements to the language.

- [Unicode property escapes] should allow telling names and invalid non-ASCII
characters apart without blowing up the regex size.
- [Lookbehind assertions] should allow matching telling division and regex
literals apart in more cases.
- [Named capture groups] might simplify some things.

These things would be nice to do, but are not critical. They probably have to
wait until the oldest maintained Node.js LTS release supports those features.

[Unicode property escapes]: http://2ality.com/2017/07/regexp-unicode-property-escapes.html
[Lookbehind assertions]: http://2ality.com/2017/05/regexp-lookbehind-assertions.html
[Named capture groups]: http://2ality.com/2017/05/regexp-named-capture-groups.html


License
=======

[MIT](LICENSE).

+ 23
- 0
node_modules/js-tokens/index.js View File

@@ -0,0 +1,23 @@
// Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell
// License: MIT. (See LICENSE.)

Object.defineProperty(exports, "__esModule", {
value: true
})

// This regex comes from regex.coffee, and is inserted here by generate-index.js
// (run `npm run build`).
exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g

exports.matchToToken = function(match) {
var token = {type: "invalid", value: match[0], closed: undefined}
if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4])
else if (match[ 5]) token.type = "comment"
else if (match[ 6]) token.type = "comment", token.closed = !!match[7]
else if (match[ 8]) token.type = "regex"
else if (match[ 9]) token.type = "number"
else if (match[10]) token.type = "name"
else if (match[11]) token.type = "punctuator"
else if (match[12]) token.type = "whitespace"
return token
}

+ 30
- 0
node_modules/js-tokens/package.json View File

@@ -0,0 +1,30 @@
{
"name": "js-tokens",
"version": "4.0.0",
"author": "Simon Lydell",
"license": "MIT",
"description": "A regex that tokenizes JavaScript.",
"keywords": [
"JavaScript",
"js",
"token",
"tokenize",
"regex"
],
"files": [
"index.js"
],
"repository": "lydell/js-tokens",
"scripts": {
"test": "mocha --ui tdd",
"esprima-compare": "node esprima-compare ./index.js everything.js/es5.js",
"build": "node generate-index.js",
"dev": "npm run build && npm test"
},
"devDependencies": {
"coffeescript": "2.1.1",
"esprima": "4.0.0",
"everything.js": "1.0.3",
"mocha": "5.0.0"
}
}

+ 21
- 0
node_modules/loose-envify/LICENSE View File

@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2015 Andres Suarez <zertosh@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 45
- 0
node_modules/loose-envify/README.md View File

@@ -0,0 +1,45 @@
# loose-envify

[![Build Status](https://travis-ci.org/zertosh/loose-envify.svg?branch=master)](https://travis-ci.org/zertosh/loose-envify)

Fast (and loose) selective `process.env` replacer using [js-tokens](https://github.com/lydell/js-tokens) instead of an AST. Works just like [envify](https://github.com/hughsk/envify) but much faster.

## Gotchas

* Doesn't handle broken syntax.
* Doesn't look inside embedded expressions in template strings.
- **this won't work:**
```js
console.log(`the current env is ${process.env.NODE_ENV}`);
```
* Doesn't replace oddly-spaced or oddly-commented expressions.
- **this won't work:**
```js
console.log(process./*won't*/env./*work*/NODE_ENV);
```

## Usage/Options

loose-envify has the exact same interface as [envify](https://github.com/hughsk/envify), including the CLI.

## Benchmark

```
envify:

$ for i in {1..5}; do node bench/bench.js 'envify'; done
708ms
727ms
791ms
719ms
720ms

loose-envify:

$ for i in {1..5}; do node bench/bench.js '../'; done
51ms
52ms
52ms
52ms
52ms
```

+ 16
- 0
node_modules/loose-envify/cli.js View File

@@ -0,0 +1,16 @@
#!/usr/bin/env node
'use strict';

var looseEnvify = require('./');
var fs = require('fs');

if (process.argv[2]) {
fs.createReadStream(process.argv[2], {encoding: 'utf8'})
.pipe(looseEnvify(process.argv[2]))
.pipe(process.stdout);
} else {
process.stdin.resume()
process.stdin
.pipe(looseEnvify(__filename))
.pipe(process.stdout);
}

+ 4
- 0
node_modules/loose-envify/custom.js View File

@@ -0,0 +1,4 @@
// envify compatibility
'use strict';

module.exports = require('./loose-envify');

+ 3
- 0
node_modules/loose-envify/index.js View File

@@ -0,0 +1,3 @@
'use strict';

module.exports = require('./loose-envify')(process.env);

+ 36
- 0
node_modules/loose-envify/loose-envify.js View File

@@ -0,0 +1,36 @@
'use strict';

var stream = require('stream');
var util = require('util');
var replace = require('./replace');

var jsonExtRe = /\.json$/;

module.exports = function(rootEnv) {
rootEnv = rootEnv || process.env;
return function (file, trOpts) {
if (jsonExtRe.test(file)) {
return stream.PassThrough();
}
var envs = trOpts ? [rootEnv, trOpts] : [rootEnv];
return new LooseEnvify(envs);
};
};

function LooseEnvify(envs) {
stream.Transform.call(this);
this._data = '';
this._envs = envs;
}
util.inherits(LooseEnvify, stream.Transform);

LooseEnvify.prototype._transform = function(buf, enc, cb) {
this._data += buf;
cb();
};

LooseEnvify.prototype._flush = function(cb) {
var replaced = replace(this._data, this._envs);
this.push(replaced);
cb();
};

+ 36
- 0
node_modules/loose-envify/package.json View File

@@ -0,0 +1,36 @@
{
"name": "loose-envify",
"version": "1.4.0",
"description": "Fast (and loose) selective `process.env` replacer using js-tokens instead of an AST",
"keywords": [
"environment",
"variables",
"browserify",
"browserify-transform",
"transform",
"source",
"configuration"
],
"homepage": "https://github.com/zertosh/loose-envify",
"license": "MIT",
"author": "Andres Suarez <zertosh@gmail.com>",
"main": "index.js",
"bin": {
"loose-envify": "cli.js"
},
"repository": {
"type": "git",
"url": "git://github.com/zertosh/loose-envify.git"
},
"scripts": {
"test": "tap test/*.js"
},
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"devDependencies": {
"browserify": "^13.1.1",
"envify": "^3.4.0",
"tap": "^8.0.0"
}
}

+ 65
- 0
node_modules/loose-envify/replace.js View File

@@ -0,0 +1,65 @@
'use strict';

var jsTokens = require('js-tokens').default;

var processEnvRe = /\bprocess\.env\.[_$a-zA-Z][$\w]+\b/;
var spaceOrCommentRe = /^(?:\s|\/[/*])/;

function replace(src, envs) {
if (!processEnvRe.test(src)) {
return src;
}

var out = [];
var purge = envs.some(function(env) {
return env._ && env._.indexOf('purge') !== -1;
});

jsTokens.lastIndex = 0
var parts = src.match(jsTokens);

for (var i = 0; i < parts.length; i++) {
if (parts[i ] === 'process' &&
parts[i + 1] === '.' &&
parts[i + 2] === 'env' &&
parts[i + 3] === '.') {
var prevCodeToken = getAdjacentCodeToken(-1, parts, i);
var nextCodeToken = getAdjacentCodeToken(1, parts, i + 4);
var replacement = getReplacementString(envs, parts[i + 4], purge);
if (prevCodeToken !== '.' &&
nextCodeToken !== '.' &&
nextCodeToken !== '=' &&
typeof replacement === 'string') {
out.push(replacement);
i += 4;
continue;
}
}
out.push(parts[i]);
}

return out.join('');
}

function getAdjacentCodeToken(dir, parts, i) {
while (true) {
var part = parts[i += dir];
if (!spaceOrCommentRe.test(part)) {
return part;
}
}
}

function getReplacementString(envs, name, purge) {
for (var j = 0; j < envs.length; j++) {
var env = envs[j];
if (typeof env[name] !== 'undefined') {
return JSON.stringify(env[name]);
}
}
if (purge) {
return 'undefined';
}
}

module.exports = replace;

+ 90
- 0
node_modules/object-assign/index.js View File

@@ -0,0 +1,90 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/

'use strict';
/* eslint-disable no-unused-vars */
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;

function toObject(val) {
if (val === null || val === undefined) {
throw new TypeError('Object.assign cannot be called with null or undefined');
}

return Object(val);
}

function shouldUseNative() {
try {
if (!Object.assign) {
return false;
}

// Detect buggy property enumeration order in older V8 versions.

// https://bugs.chromium.org/p/v8/issues/detail?id=4118
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
test1[5] = 'de';
if (Object.getOwnPropertyNames(test1)[0] === '5') {
return false;
}

// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test2 = {};
for (var i = 0; i < 10; i++) {
test2['_' + String.fromCharCode(i)] = i;
}
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
return test2[n];
});
if (order2.join('') !== '0123456789') {
return false;
}

// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test3 = {};
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
test3[letter] = letter;
});
if (Object.keys(Object.assign({}, test3)).join('') !==
'abcdefghijklmnopqrst') {
return false;
}

return true;
} catch (err) {
// We don't expect any of the above to throw, but better to be safe.
return false;
}
}

module.exports = shouldUseNative() ? Object.assign : function (target, source) {
var from;
var to = toObject(target);
var symbols;

for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);

for (var key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}

if (getOwnPropertySymbols) {
symbols = getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}

return to;
};

+ 21
- 0
node_modules/object-assign/license View File

@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 42
- 0
node_modules/object-assign/package.json View File

@@ -0,0 +1,42 @@
{
"name": "object-assign",
"version": "4.1.1",
"description": "ES2015 `Object.assign()` ponyfill",
"license": "MIT",
"repository": "sindresorhus/object-assign",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "xo && ava",
"bench": "matcha bench.js"
},
"files": [
"index.js"
],
"keywords": [
"object",
"assign",
"extend",
"properties",
"es2015",
"ecmascript",
"harmony",
"ponyfill",
"prollyfill",
"polyfill",
"shim",
"browser"
],
"devDependencies": {
"ava": "^0.16.0",
"lodash": "^4.16.4",
"matcha": "^0.7.0",
"xo": "^0.16.0"
}
}

+ 61
- 0
node_modules/object-assign/readme.md View File

@@ -0,0 +1,61 @@
# object-assign [![Build Status](https://travis-ci.org/sindresorhus/object-assign.svg?branch=master)](https://travis-ci.org/sindresorhus/object-assign)

> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com)


## Use the built-in

Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari),
support `Object.assign()` :tada:. If you target only those environments, then by all
means, use `Object.assign()` instead of this package.


## Install

```
$ npm install --save object-assign
```


## Usage

```js
const objectAssign = require('object-assign');

objectAssign({foo: 0}, {bar: 1});
//=> {foo: 0, bar: 1}

// multiple sources
objectAssign({foo: 0}, {bar: 1}, {baz: 2});
//=> {foo: 0, bar: 1, baz: 2}

// overwrites equal keys
objectAssign({foo: 0}, {foo: 1}, {foo: 2});
//=> {foo: 2}

// ignores null and undefined sources
objectAssign({foo: 0}, null, {bar: 1}, undefined);
//=> {foo: 0, bar: 1}
```


## API

### objectAssign(target, [source, ...])

Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones.


## Resources

- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign)


## Related

- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()`


## License

MIT © [Sindre Sorhus](https://sindresorhus.com)

+ 21
- 0
node_modules/prop-types/LICENSE View File

@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2013-present, Facebook, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 302
- 0
node_modules/prop-types/README.md View File

@@ -0,0 +1,302 @@
# prop-types [![Build Status](https://travis-ci.com/facebook/prop-types.svg?branch=main)](https://travis-ci.org/facebook/prop-types)

Runtime type checking for React props and similar objects.

You can use prop-types to document the intended types of properties passed to
components. React (and potentially other libraries—see the `checkPropTypes()`
reference below) will check props passed to your components against those
definitions, and warn in development if they don’t match.

## Installation

```shell
npm install --save prop-types
```

## Importing

```js
import PropTypes from 'prop-types'; // ES6
var PropTypes = require('prop-types'); // ES5 with npm
```

### CDN

If you prefer to exclude `prop-types` from your application and use it
globally via `window.PropTypes`, the `prop-types` package provides
single-file distributions, which are hosted on the following CDNs:

* [**unpkg**](https://unpkg.com/prop-types/)
```html
<!-- development version -->
<script src="https://unpkg.com/prop-types@15.6/prop-types.js"></script>

<!-- production version -->
<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
```

* [**cdnjs**](https://cdnjs.com/libraries/prop-types)
```html
<!-- development version -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>

<!-- production version -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.min.js"></script>
```

To load a specific version of `prop-types` replace `15.6.0` with the version number.

## Usage

PropTypes was originally exposed as part of the React core module, and is
commonly used with React components.
Here is an example of using PropTypes with a React component, which also
documents the different validators provided:

```js
import React from 'react';
import PropTypes from 'prop-types';

class MyComponent extends React.Component {
render() {
// ... do things with the props
}
}

MyComponent.propTypes = {
// You can declare that a prop is a specific JS primitive. By default, these
// are all optional.
optionalArray: PropTypes.array,
optionalBigInt: PropTypes.bigint,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,

// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
// see https://reactjs.org/docs/rendering-elements.html for more info
optionalNode: PropTypes.node,

// A React element (ie. <MyComponent />).
optionalElement: PropTypes.element,

// A React element type (eg. MyComponent).
// a function, string, or "element-like" object (eg. React.Fragment, Suspense, etc.)
// see https://github.com/facebook/react/blob/HEAD/packages/shared/isValidElementType.js
optionalElementType: PropTypes.elementType,

// You can also declare that a prop is an instance of a class. This uses
// JS's instanceof operator.
optionalMessage: PropTypes.instanceOf(Message),

// You can ensure that your prop is limited to specific values by treating
// it as an enum.
optionalEnum: PropTypes.oneOf(['News', 'Photos']),

// An object that could be one of many types
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),

// An array of a certain type
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

// An object with property values of a certain type
optionalObjectOf: PropTypes.objectOf(PropTypes.number),

// You can chain any of the above with `isRequired` to make sure a warning
// is shown if the prop isn't provided.

// An object taking on a particular shape
optionalObjectWithShape: PropTypes.shape({
optionalProperty: PropTypes.string,
requiredProperty: PropTypes.number.isRequired
}),

// An object with warnings on extra properties
optionalObjectWithStrictShape: PropTypes.exact({
optionalProperty: PropTypes.string,
requiredProperty: PropTypes.number.isRequired
}),

requiredFunc: PropTypes.func.isRequired,

// A value of any data type
requiredAny: PropTypes.any.isRequired,

// You can also specify a custom validator. It should return an Error
// object if the validation fails. Don't `console.warn` or throw, as this
// won't work inside `oneOfType`.
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},

// You can also supply a custom validator to `arrayOf` and `objectOf`.
// It should return an Error object if the validation fails. The validator
// will be called for each key in the array or object. The first two
// arguments of the validator are the array or object itself, and the
// current item's key.
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})
};
```

Refer to the [React documentation](https://facebook.github.io/react/docs/typechecking-with-proptypes.html) for more information.

## Migrating from React.PropTypes

Check out [Migrating from React.PropTypes](https://facebook.github.io/react/blog/2017/04/07/react-v15.5.0.html#migrating-from-react.proptypes) for details on how to migrate to `prop-types` from `React.PropTypes`.

Note that this blog posts **mentions a codemod script that performs the conversion automatically**.

There are also important notes below.

## How to Depend on This Package?

For apps, we recommend putting it in `dependencies` with a caret range.
For example:

```js
"dependencies": {
"prop-types": "^15.5.7"
}
```

For libraries, we *also* recommend leaving it in `dependencies`:

```js
"dependencies": {
"prop-types": "^15.5.7"
},
"peerDependencies": {
"react": "^15.5.0"
}
```

**Note:** there are known issues in versions before 15.5.7 so we recommend using it as the minimal version.

Make sure that the version range uses a caret (`^`) and thus is broad enough for npm to efficiently deduplicate packages.

For UMD bundles of your components, make sure you **don’t** include `PropTypes` in the build. Usually this is done by marking it as an external (the specifics depend on your bundler), just like you do with React.

## Compatibility

### React 0.14

This package is compatible with **React 0.14.9**. Compared to 0.14.8 (which was released in March of 2016), there are no other changes in 0.14.9, so it should be a painless upgrade.

```shell
# ATTENTION: Only run this if you still use React 0.14!
npm install --save react@^0.14.9 react-dom@^0.14.9
```

### React 15+

This package is compatible with **React 15.3.0** and higher.

```
npm install --save react@^15.3.0 react-dom@^15.3.0
```

### What happens on other React versions?

It outputs warnings with the message below even though the developer doesn’t do anything wrong. Unfortunately there is no solution for this other than updating React to either 15.3.0 or higher, or 0.14.9 if you’re using React 0.14.

## Difference from `React.PropTypes`: Don’t Call Validator Functions

First of all, **which version of React are you using**? You might be seeing this message because a component library has updated to use `prop-types` package, but your version of React is incompatible with it. See the [above section](#compatibility) for more details.

Are you using either React 0.14.9 or a version higher than React 15.3.0? Read on.

When you migrate components to use the standalone `prop-types`, **all validator functions will start throwing an error if you call them directly**. This makes sure that nobody relies on them in production code, and it is safe to strip their implementations to optimize the bundle size.

Code like this is still fine:

```js
MyComponent.propTypes = {
myProp: PropTypes.bool
};
```

However, code like this will not work with the `prop-types` package:

```js
// Will not work with `prop-types` package!
var errorOrNull = PropTypes.bool(42, 'myProp', 'MyComponent', 'prop');
```

It will throw an error:

```
Calling PropTypes validators directly is not supported by the `prop-types` package.
Use PropTypes.checkPropTypes() to call them.
```

(If you see **a warning** rather than an error with this message, please check the [above section about compatibility](#compatibility).)

This is new behavior, and you will only encounter it when you migrate from `React.PropTypes` to the `prop-types` package. For the vast majority of components, this doesn’t matter, and if you didn’t see [this warning](https://facebook.github.io/react/warnings/dont-call-proptypes.html) in your components, your code is safe to migrate. This is not a breaking change in React because you are only opting into this change for a component by explicitly changing your imports to use `prop-types`. If you temporarily need the old behavior, you can keep using `React.PropTypes` until React 16.

**If you absolutely need to trigger the validation manually**, call `PropTypes.checkPropTypes()`. Unlike the validators themselves, this function is safe to call in production, as it will be replaced by an empty function:

```js
// Works with standalone PropTypes
PropTypes.checkPropTypes(MyComponent.propTypes, props, 'prop', 'MyComponent');
```
See below for more info.

**If you DO want to use validation in production**, you can choose to use the **development version** by importing/requiring `prop-types/prop-types` instead of `prop-types`.

**You might also see this error** if you’re calling a `PropTypes` validator from your own custom `PropTypes` validator. In this case, the fix is to make sure that you are passing *all* of the arguments to the inner function. There is a more in-depth explanation of how to fix it [on this page](https://facebook.github.io/react/warnings/dont-call-proptypes.html#fixing-the-false-positive-in-third-party-proptypes). Alternatively, you can temporarily keep using `React.PropTypes` until React 16, as it would still only warn in this case.

If you use a bundler like Browserify or Webpack, don’t forget to [follow these instructions](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build) to correctly bundle your application in development or production mode. Otherwise you’ll ship unnecessary code to your users.

## PropTypes.checkPropTypes

React will automatically check the propTypes you set on the component, but if
you are using PropTypes without React then you may want to manually call
`PropTypes.checkPropTypes`, like so:

```js
const myPropTypes = {
name: PropTypes.string,
age: PropTypes.number,
// ... define your prop validations
};

const props = {
name: 'hello', // is valid
age: 'world', // not valid
};

// Let's say your component is called 'MyComponent'

// Works with standalone PropTypes
PropTypes.checkPropTypes(myPropTypes, props, 'prop', 'MyComponent');
// This will warn as follows:
// Warning: Failed prop type: Invalid prop `age` of type `string` supplied to
// `MyComponent`, expected `number`.
```

## PropTypes.resetWarningCache()

`PropTypes.checkPropTypes(...)` only `console.error`s a given message once. To reset the error warning cache in tests, call `PropTypes.resetWarningCache()`

### License

prop-types is [MIT licensed](./LICENSE).

+ 103
- 0
node_modules/prop-types/checkPropTypes.js View File

@@ -0,0 +1,103 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var printWarning = function() {};

if (process.env.NODE_ENV !== 'production') {
var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');
var loggedTypeFailures = {};
var has = require('./lib/has');

printWarning = function(text) {
var message = 'Warning: ' + text;
if (typeof console !== 'undefined') {
console.error(message);
}
try {
// --- Welcome to debugging React ---
// This error was thrown as a convenience so that you can use this stack
// to find the callsite that caused this warning to fire.
throw new Error(message);
} catch (x) { /**/ }
};
}

/**
* Assert that the values match with the type specs.
* Error messages are memorized and will only be shown once.
*
* @param {object} typeSpecs Map of name to a ReactPropType
* @param {object} values Runtime values that need to be type-checked
* @param {string} location e.g. "prop", "context", "child context"
* @param {string} componentName Name of the component for error messages.
* @param {?Function} getStack Returns the component stack.
* @private
*/
function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
if (process.env.NODE_ENV !== 'production') {
for (var typeSpecName in typeSpecs) {
if (has(typeSpecs, typeSpecName)) {
var error;
// Prop type validation may throw. In case they do, we don't want to
// fail the render phase where it didn't fail before. So we log it.
// After these have been cleaned up, we'll let them throw.
try {
// This is intentionally an invariant that gets caught. It's the same
// behavior as without this statement except with a better message.
if (typeof typeSpecs[typeSpecName] !== 'function') {
var err = Error(
(componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' +
'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' +
'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.'
);
err.name = 'Invariant Violation';
throw err;
}
error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
} catch (ex) {
error = ex;
}
if (error && !(error instanceof Error)) {
printWarning(
(componentName || 'React class') + ': type specification of ' +
location + ' `' + typeSpecName + '` is invalid; the type checker ' +
'function must return `null` or an `Error` but returned a ' + typeof error + '. ' +
'You may have forgotten to pass an argument to the type checker ' +
'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +
'shape all require an argument).'
);
}
if (error instanceof Error && !(error.message in loggedTypeFailures)) {
// Only monitor this failure once because there tends to be a lot of the
// same error.
loggedTypeFailures[error.message] = true;

var stack = getStack ? getStack() : '';

printWarning(
'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '')
);
}
}
}
}
}

/**
* Resets warning cache when testing.
*
* @private
*/
checkPropTypes.resetWarningCache = function() {
if (process.env.NODE_ENV !== 'production') {
loggedTypeFailures = {};
}
}

module.exports = checkPropTypes;

+ 19
- 0
node_modules/prop-types/factory.js View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

// React 15.5 references this module, and assumes PropTypes are still callable in production.
// Therefore we re-export development-only version with all the PropTypes checks here.
// However if one is migrating to the `prop-types` npm library, they will go through the
// `index.js` entry point, and it will branch depending on the environment.
var factory = require('./factoryWithTypeCheckers');
module.exports = function(isValidElement) {
// It is still allowed in 15.5.
var throwOnDirectAccess = false;
return factory(isValidElement, throwOnDirectAccess);
};

+ 65
- 0
node_modules/prop-types/factoryWithThrowingShims.js View File

@@ -0,0 +1,65 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');

function emptyFunction() {}
function emptyFunctionWithReset() {}
emptyFunctionWithReset.resetWarningCache = emptyFunction;

module.exports = function() {
function shim(props, propName, componentName, location, propFullName, secret) {
if (secret === ReactPropTypesSecret) {
// It is still safe when called from React.
return;
}
var err = new Error(
'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
'Use PropTypes.checkPropTypes() to call them. ' +
'Read more at http://fb.me/use-check-prop-types'
);
err.name = 'Invariant Violation';
throw err;
};
shim.isRequired = shim;
function getShim() {
return shim;
};
// Important!
// Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.
var ReactPropTypes = {
array: shim,
bigint: shim,
bool: shim,
func: shim,
number: shim,
object: shim,
string: shim,
symbol: shim,

any: shim,
arrayOf: getShim,
element: shim,
elementType: shim,
instanceOf: getShim,
node: shim,
objectOf: getShim,
oneOf: getShim,
oneOfType: getShim,
shape: getShim,
exact: getShim,

checkPropTypes: emptyFunctionWithReset,
resetWarningCache: emptyFunction
};

ReactPropTypes.PropTypes = ReactPropTypes;

return ReactPropTypes;
};

+ 610
- 0
node_modules/prop-types/factoryWithTypeCheckers.js View File

@@ -0,0 +1,610 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var ReactIs = require('react-is');
var assign = require('object-assign');

var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');
var has = require('./lib/has');
var checkPropTypes = require('./checkPropTypes');

var printWarning = function() {};

if (process.env.NODE_ENV !== 'production') {
printWarning = function(text) {
var message = 'Warning: ' + text;
if (typeof console !== 'undefined') {
console.error(message);
}
try {
// --- Welcome to debugging React ---
// This error was thrown as a convenience so that you can use this stack
// to find the callsite that caused this warning to fire.
throw new Error(message);
} catch (x) {}
};
}

function emptyFunctionThatReturnsNull() {
return null;
}

module.exports = function(isValidElement, throwOnDirectAccess) {
/* global Symbol */
var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.

/**
* Returns the iterator method function contained on the iterable object.
*
* Be sure to invoke the function with the iterable as context:
*
* var iteratorFn = getIteratorFn(myIterable);
* if (iteratorFn) {
* var iterator = iteratorFn.call(myIterable);
* ...
* }
*
* @param {?object} maybeIterable
* @return {?function}
*/
function getIteratorFn(maybeIterable) {
var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
if (typeof iteratorFn === 'function') {
return iteratorFn;
}
}

/**
* Collection of methods that allow declaration and validation of props that are
* supplied to React components. Example usage:
*
* var Props = require('ReactPropTypes');
* var MyArticle = React.createClass({
* propTypes: {
* // An optional string prop named "description".
* description: Props.string,
*
* // A required enum prop named "category".
* category: Props.oneOf(['News','Photos']).isRequired,
*
* // A prop named "dialog" that requires an instance of Dialog.
* dialog: Props.instanceOf(Dialog).isRequired
* },
* render: function() { ... }
* });
*
* A more formal specification of how these methods are used:
*
* type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
* decl := ReactPropTypes.{type}(.isRequired)?
*
* Each and every declaration produces a function with the same signature. This
* allows the creation of custom validation functions. For example:
*
* var MyLink = React.createClass({
* propTypes: {
* // An optional string or URI prop named "href".
* href: function(props, propName, componentName) {
* var propValue = props[propName];
* if (propValue != null && typeof propValue !== 'string' &&
* !(propValue instanceof URI)) {
* return new Error(
* 'Expected a string or an URI for ' + propName + ' in ' +
* componentName
* );
* }
* }
* },
* render: function() {...}
* });
*
* @internal
*/

var ANONYMOUS = '<<anonymous>>';

// Important!
// Keep this list in sync with production version in `./factoryWithThrowingShims.js`.
var ReactPropTypes = {
array: createPrimitiveTypeChecker('array'),
bigint: createPrimitiveTypeChecker('bigint'),
bool: createPrimitiveTypeChecker('boolean'),
func: createPrimitiveTypeChecker('function'),
number: createPrimitiveTypeChecker('number'),
object: createPrimitiveTypeChecker('object'),
string: createPrimitiveTypeChecker('string'),
symbol: createPrimitiveTypeChecker('symbol'),

any: createAnyTypeChecker(),
arrayOf: createArrayOfTypeChecker,
element: createElementTypeChecker(),
elementType: createElementTypeTypeChecker(),
instanceOf: createInstanceTypeChecker,
node: createNodeChecker(),
objectOf: createObjectOfTypeChecker,
oneOf: createEnumTypeChecker,
oneOfType: createUnionTypeChecker,
shape: createShapeTypeChecker,
exact: createStrictShapeTypeChecker,
};

/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
/*eslint-disable no-self-compare*/
function is(x, y) {
// SameValue algorithm
if (x === y) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
}
/*eslint-enable no-self-compare*/

/**
* We use an Error-like object for backward compatibility as people may call
* PropTypes directly and inspect their output. However, we don't use real
* Errors anymore. We don't inspect their stack anyway, and creating them
* is prohibitively expensive if they are created too often, such as what
* happens in oneOfType() for any type before the one that matched.
*/
function PropTypeError(message, data) {
this.message = message;
this.data = data && typeof data === 'object' ? data: {};
this.stack = '';
}
// Make `instanceof Error` still work for returned errors.
PropTypeError.prototype = Error.prototype;

function createChainableTypeChecker(validate) {
if (process.env.NODE_ENV !== 'production') {
var manualPropTypeCallCache = {};
var manualPropTypeWarningCount = 0;
}
function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
componentName = componentName || ANONYMOUS;
propFullName = propFullName || propName;

if (secret !== ReactPropTypesSecret) {
if (throwOnDirectAccess) {
// New behavior only for users of `prop-types` package
var err = new Error(
'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
'Use `PropTypes.checkPropTypes()` to call them. ' +
'Read more at http://fb.me/use-check-prop-types'
);
err.name = 'Invariant Violation';
throw err;
} else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') {
// Old behavior for people using React.PropTypes
var cacheKey = componentName + ':' + propName;
if (
!manualPropTypeCallCache[cacheKey] &&
// Avoid spamming the console because they are often not actionable except for lib authors
manualPropTypeWarningCount < 3
) {
printWarning(
'You are manually calling a React.PropTypes validation ' +
'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' +
'and will throw in the standalone `prop-types` package. ' +
'You may be seeing this warning due to a third-party PropTypes ' +
'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.'
);
manualPropTypeCallCache[cacheKey] = true;
manualPropTypeWarningCount++;
}
}
}
if (props[propName] == null) {
if (isRequired) {
if (props[propName] === null) {
return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
}
return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
}
return null;
} else {
return validate(props, propName, componentName, location, propFullName);
}
}

var chainedCheckType = checkType.bind(null, false);
chainedCheckType.isRequired = checkType.bind(null, true);

return chainedCheckType;
}

function createPrimitiveTypeChecker(expectedType) {
function validate(props, propName, componentName, location, propFullName, secret) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== expectedType) {
// `propValue` being instance of, say, date/regexp, pass the 'object'
// check, but we can offer a more precise error message here rather than
// 'of type `object`'.
var preciseType = getPreciseType(propValue);

return new PropTypeError(
'Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'),
{expectedType: expectedType}
);
}
return null;
}
return createChainableTypeChecker(validate);
}

function createAnyTypeChecker() {
return createChainableTypeChecker(emptyFunctionThatReturnsNull);
}

function createArrayOfTypeChecker(typeChecker) {
function validate(props, propName, componentName, location, propFullName) {
if (typeof typeChecker !== 'function') {
return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');
}
var propValue = props[propName];
if (!Array.isArray(propValue)) {
var propType = getPropType(propValue);
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
}
for (var i = 0; i < propValue.length; i++) {
var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);
if (error instanceof Error) {
return error;
}
}
return null;
}
return createChainableTypeChecker(validate);
}

function createElementTypeChecker() {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
if (!isValidElement(propValue)) {
var propType = getPropType(propValue);
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));
}
return null;
}
return createChainableTypeChecker(validate);
}

function createElementTypeTypeChecker() {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
if (!ReactIs.isValidElementType(propValue)) {
var propType = getPropType(propValue);
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.'));
}
return null;
}
return createChainableTypeChecker(validate);
}

function createInstanceTypeChecker(expectedClass) {
function validate(props, propName, componentName, location, propFullName) {
if (!(props[propName] instanceof expectedClass)) {
var expectedClassName = expectedClass.name || ANONYMOUS;
var actualClassName = getClassName(props[propName]);
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
}
return null;
}
return createChainableTypeChecker(validate);
}

function createEnumTypeChecker(expectedValues) {
if (!Array.isArray(expectedValues)) {
if (process.env.NODE_ENV !== 'production') {
if (arguments.length > 1) {
printWarning(
'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' +
'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).'
);
} else {
printWarning('Invalid argument supplied to oneOf, expected an array.');
}
}
return emptyFunctionThatReturnsNull;
}

function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
for (var i = 0; i < expectedValues.length; i++) {
if (is(propValue, expectedValues[i])) {
return null;
}
}

var valuesString = JSON.stringify(expectedValues, function replacer(key, value) {
var type = getPreciseType(value);
if (type === 'symbol') {
return String(value);
}
return value;
});
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
}
return createChainableTypeChecker(validate);
}

function createObjectOfTypeChecker(typeChecker) {
function validate(props, propName, componentName, location, propFullName) {
if (typeof typeChecker !== 'function') {
return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
}
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== 'object') {
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
}
for (var key in propValue) {
if (has(propValue, key)) {
var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
if (error instanceof Error) {
return error;
}
}
}
return null;
}
return createChainableTypeChecker(validate);
}

function createUnionTypeChecker(arrayOfTypeCheckers) {
if (!Array.isArray(arrayOfTypeCheckers)) {
process.env.NODE_ENV !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0;
return emptyFunctionThatReturnsNull;
}

for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
var checker = arrayOfTypeCheckers[i];
if (typeof checker !== 'function') {
printWarning(
'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +
'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.'
);
return emptyFunctionThatReturnsNull;
}
}

function validate(props, propName, componentName, location, propFullName) {
var expectedTypes = [];
for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
var checker = arrayOfTypeCheckers[i];
var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret);
if (checkerResult == null) {
return null;
}
if (checkerResult.data && has(checkerResult.data, 'expectedType')) {
expectedTypes.push(checkerResult.data.expectedType);
}
}
var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': '';
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.'));
}
return createChainableTypeChecker(validate);
}

function createNodeChecker() {
function validate(props, propName, componentName, location, propFullName) {
if (!isNode(props[propName])) {
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
}
return null;
}
return createChainableTypeChecker(validate);
}

function invalidValidatorError(componentName, location, propFullName, key, type) {
return new PropTypeError(
(componentName || 'React class') + ': ' + location + ' type `' + propFullName + '.' + key + '` is invalid; ' +
'it must be a function, usually from the `prop-types` package, but received `' + type + '`.'
);
}

function createShapeTypeChecker(shapeTypes) {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== 'object') {
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
}
for (var key in shapeTypes) {
var checker = shapeTypes[key];
if (typeof checker !== 'function') {
return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));
}
var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
if (error) {
return error;
}
}
return null;
}
return createChainableTypeChecker(validate);
}

function createStrictShapeTypeChecker(shapeTypes) {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== 'object') {
return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
}
// We need to check all keys in case some are required but missing from props.
var allKeys = assign({}, props[propName], shapeTypes);
for (var key in allKeys) {
var checker = shapeTypes[key];
if (has(shapeTypes, key) && typeof checker !== 'function') {
return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));
}
if (!checker) {
return new PropTypeError(
'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +
'\nBad object: ' + JSON.stringify(props[propName], null, ' ') +
'\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ')
);
}
var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
if (error) {
return error;
}
}
return null;
}

return createChainableTypeChecker(validate);
}

function isNode(propValue) {
switch (typeof propValue) {
case 'number':
case 'string':
case 'undefined':
return true;
case 'boolean':
return !propValue;
case 'object':
if (Array.isArray(propValue)) {
return propValue.every(isNode);
}
if (propValue === null || isValidElement(propValue)) {
return true;
}

var iteratorFn = getIteratorFn(propValue);
if (iteratorFn) {
var iterator = iteratorFn.call(propValue);
var step;
if (iteratorFn !== propValue.entries) {
while (!(step = iterator.next()).done) {
if (!isNode(step.value)) {
return false;
}
}
} else {
// Iterator will provide entry [k,v] tuples rather than values.
while (!(step = iterator.next()).done) {
var entry = step.value;
if (entry) {
if (!isNode(entry[1])) {
return false;
}
}
}
}
} else {
return false;
}

return true;
default:
return false;
}
}

function isSymbol(propType, propValue) {
// Native Symbol.
if (propType === 'symbol') {
return true;
}

// falsy value can't be a Symbol
if (!propValue) {
return false;
}

// 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
if (propValue['@@toStringTag'] === 'Symbol') {
return true;
}

// Fallback for non-spec compliant Symbols which are polyfilled.
if (typeof Symbol === 'function' && propValue instanceof Symbol) {
return true;
}

return false;
}

// Equivalent of `typeof` but with special handling for array and regexp.
function getPropType(propValue) {
var propType = typeof propValue;
if (Array.isArray(propValue)) {
return 'array';
}
if (propValue instanceof RegExp) {
// Old webkits (at least until Android 4.0) return 'function' rather than
// 'object' for typeof a RegExp. We'll normalize this here so that /bla/
// passes PropTypes.object.
return 'object';
}
if (isSymbol(propType, propValue)) {
return 'symbol';
}
return propType;
}

// This handles more types than `getPropType`. Only used for error messages.
// See `createPrimitiveTypeChecker`.
function getPreciseType(propValue) {
if (typeof propValue === 'undefined' || propValue === null) {
return '' + propValue;
}
var propType = getPropType(propValue);
if (propType === 'object') {
if (propValue instanceof Date) {
return 'date';
} else if (propValue instanceof RegExp) {
return 'regexp';
}
}
return propType;
}

// Returns a string that is postfixed to a warning about an invalid type.
// For example, "undefined" or "of type array"
function getPostfixForTypeWarning(value) {
var type = getPreciseType(value);
switch (type) {
case 'array':
case 'object':
return 'an ' + type;
case 'boolean':
case 'date':
case 'regexp':
return 'a ' + type;
default:
return type;
}
}

// Returns class name of the object, if any.
function getClassName(propValue) {
if (!propValue.constructor || !propValue.constructor.name) {
return ANONYMOUS;
}
return propValue.constructor.name;
}

ReactPropTypes.checkPropTypes = checkPropTypes;
ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache;
ReactPropTypes.PropTypes = ReactPropTypes;

return ReactPropTypes;
};

+ 19
- 0
node_modules/prop-types/index.js View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

if (process.env.NODE_ENV !== 'production') {
var ReactIs = require('react-is');

// By explicitly using `prop-types` you are opting into new development behavior.
// http://fb.me/prop-types-in-prod
var throwOnDirectAccess = true;
module.exports = require('./factoryWithTypeCheckers')(ReactIs.isElement, throwOnDirectAccess);
} else {
// By explicitly using `prop-types` you are opting into new production behavior.
// http://fb.me/prop-types-in-prod
module.exports = require('./factoryWithThrowingShims')();
}

+ 12
- 0
node_modules/prop-types/lib/ReactPropTypesSecret.js View File

@@ -0,0 +1,12 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';

module.exports = ReactPropTypesSecret;

+ 1
- 0
node_modules/prop-types/lib/has.js View File

@@ -0,0 +1 @@
module.exports = Function.call.bind(Object.prototype.hasOwnProperty);

+ 60
- 0
node_modules/prop-types/package.json View File

@@ -0,0 +1,60 @@
{
"name": "prop-types",
"version": "15.8.1",
"description": "Runtime type checking for React props and similar objects.",
"sideEffects": false,
"main": "index.js",
"license": "MIT",
"files": [
"LICENSE",
"README.md",
"checkPropTypes.js",
"factory.js",
"factoryWithThrowingShims.js",
"factoryWithTypeCheckers.js",
"index.js",
"prop-types.js",
"prop-types.min.js",
"lib"
],
"repository": "facebook/prop-types",
"keywords": [
"react"
],
"bugs": {
"url": "https://github.com/facebook/prop-types/issues"
},
"homepage": "https://facebook.github.io/react/",
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.13.1"
},
"scripts": {
"pretest": "npm run lint",
"lint": "eslint .",
"test": "npm run tests-only",
"tests-only": "jest",
"umd": "NODE_ENV=development browserify index.js -t loose-envify --standalone PropTypes -o prop-types.js",
"umd-min": "NODE_ENV=production browserify index.js -t loose-envify -t uglifyify --standalone PropTypes -p bundle-collapser/plugin -o | uglifyjs --compress unused,dead_code -o prop-types.min.js",
"build": "yarn umd && yarn umd-min",
"prepublish": "not-in-publish || yarn build"
},
"devDependencies": {
"babel-jest": "^19.0.0",
"babel-preset-react": "^6.24.1",
"browserify": "^16.5.0",
"bundle-collapser": "^1.4.0",
"eslint": "^8.6.0",
"in-publish": "^2.0.1",
"jest": "^19.0.2",
"react": "^15.7.0",
"uglifyify": "^5.0.2",
"uglifyjs": "^2.4.11"
},
"browserify": {
"transform": [
"loose-envify"
]
}
}

+ 1315
- 0
node_modules/prop-types/prop-types.js
File diff suppressed because it is too large
View File


+ 1
- 0
node_modules/prop-types/prop-types.min.js View File

@@ -0,0 +1 @@
!function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).PropTypes=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var p="function"==typeof require&&require;if(!f&&p)return p(i,!0);if(u)return u(i,!0);throw(p=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",p}p=n[i]={exports:{}},e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(require,module,exports){"use strict";var ReactPropTypesSecret=require(3);function emptyFunction(){}function emptyFunctionWithReset(){}emptyFunctionWithReset.resetWarningCache=emptyFunction,module.exports=function(){function e(e,t,n,r,o,c){if(c!==ReactPropTypesSecret){c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}var n={array:e.isRequired=e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:emptyFunctionWithReset,resetWarningCache:emptyFunction};return n.PropTypes=n}},{3:3}],2:[function(require,module,exports){module.exports=require(1)()},{1:1}],3:[function(require,module,exports){"use strict";module.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},{}]},{},[2])(2)});

+ 6
- 0
node_modules/react-ga/.eslintignore View File

@@ -0,0 +1,6 @@
node_modules
coverage
.nyc_output
dist
.github
.husky

+ 58
- 0
node_modules/react-ga/.eslintrc.js View File

@@ -0,0 +1,58 @@
module.exports = {
parser: '@babel/eslint-parser',
extends: ['airbnb', 'prettier', 'plugin:jest/recommended'],
plugins: ['prettier', 'jest'],
env: {
browser: true
},
rules: {
'prettier/prettier': 'error',
'react/no-find-dom-node': 'off',
'arrow-body-style': 'off',
'no-mixed-operators': 'off',
'no-shadow': ['error', { allow: ['err', 'error'] }],
'react/prefer-stateless-function': [
'error',
{ ignorePureComponents: true }
],

'no-console': ['error', { allow: ['warn', 'error', 'info'] }],
'no-underscore-dangle': 'off',
'guard-for-in': 'off',
'no-param-reassign': ['error', { props: false }],
'jsx-a11y/label-has-associated-control': 'off',
'jsx-a11y/control-has-associated-control': 'off',
'react/jsx-curly-brace-presence': 'off',
'react/jsx-one-expression-per-line': 'off',
'react/jsx-props-no-spreading': 'off'
},
overrides: [
{
files: ['demo/**/*', 'src/components/*.js'],
rules: {
'import/no-extraneous-dependencies': [
'error',
{ devDependencies: true }
],
'import/no-named-as-default-member': 'off',
'react/no-array-index-key': 'off',
'react/jsx-no-bind': 'off',
'react/prop-types': 'off'
}
},
{
files: ['test/**/*'],
env: {
browser: true,
node: true,
'jest/globals': true
},
rules: {
'import/no-extraneous-dependencies': [
'error',
{ devDependencies: true }
]
}
}
]
};

+ 23
- 0
node_modules/react-ga/.github/workflows/release.yml View File

@@ -0,0 +1,23 @@
name: Release
on:
push:
branches:
- master
jobs:
release:
name: Release
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 16
- name: Install dependencies
run: npm ci
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-release

+ 26
- 0
node_modules/react-ga/.github/workflows/tests.yml View File

@@ -0,0 +1,26 @@
name: Tests

on:
pull_request:
branches: [master]

jobs:
test:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node.js 12
uses: actions/setup-node@v1
with:
node-version: 16
- run: npm ci
- run: npm install react prop-types
- run: npm run build
- run: npm run lint
- run: npm test
- run: npm test:types
- uses: wagoid/commitlint-github-action@v1

+ 4
- 0
node_modules/react-ga/.husky/commit-msg View File

@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx commitlint -e

+ 4
- 0
node_modules/react-ga/.husky/pre-commit View File

@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged

+ 3
- 0
node_modules/react-ga/.lintstagedrc.js View File

@@ -0,0 +1,3 @@
module.exports = {
'*.{js,jsx}': 'eslint --ext .js,.jsx'
};

+ 4
- 0
node_modules/react-ga/.prettierrc.js View File

@@ -0,0 +1,4 @@
module.exports = {
trailingComma: 'none',
singleQuote: true
};

+ 3
- 0
node_modules/react-ga/.releaserc.json View File

@@ -0,0 +1,3 @@
{
"branches": ["master"]
}

+ 10
- 0
node_modules/react-ga/CONTRIBUTING.md View File

@@ -0,0 +1,10 @@
- Always work on a new branch
- Submit Pull Requests against `master`
- Follow the commitlint and eslint conventions
- Don't forget to run tests and linters before pushing

1. Open a PR
1. Request code review
1. Complete code review with fixes
1. A maintainer will merge the PR, checking commit code and squashing if necessary
1. travis-ci will automatically run semantic-version and publish the new code!

+ 13
- 0
node_modules/react-ga/LICENSE View File

@@ -0,0 +1,13 @@
Apache License

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

+ 484
- 0
node_modules/react-ga/README.md View File

@@ -0,0 +1,484 @@
# react-ga

### React Google Analytics Module

[![Build Status](https://img.shields.io/travis/react-ga/react-ga/master.svg?style=flat-square)](https://travis-ci.org/react-ga/react-ga)
[![npm version](https://img.shields.io/npm/v/react-ga.svg?style=flat-square)](https://www.npmjs.com/package/react-ga)
[![npm downloads](https://img.shields.io/npm/dm/react-ga.svg?style=flat-square)](https://www.npmjs.com/package/react-ga)

This is a JavaScript module that can be used to include Google Analytics tracking code in a website or app that uses [React](https://facebook.github.io/react/) for its front-end codebase. It does not currently use any React code internally, but has been written for use with a number of Mozilla Foundation websites that are using React, as a way to standardize our GA Instrumentation across projects.

It is designed to work with [Universal Analytics](https://support.google.com/analytics/answer/2790010) and will not support the older `ga.js` implementation.

This module is mildly opinionated in how we instrument tracking within our front-end code. Our API is slightly more verbose than the core Google Analytics library, in the hope that the code is easier to read and understand for our engineers. See examples below.

If you use `react-ga` too, we'd love your feedback. Feel free to file [issues, ideas and pull requests against this repo](https://github.com/react-ga/react-ga/issues).

## Installation

With [npm](https://www.npmjs.com/):

```bash
npm install react-ga --save
```

With [bower](http://bower.io/):

```bash
bower install react-ga --save
```

Note that [React](https://github.com/facebook/react) >= 0.14.0 is needed in order to use the `<OutboundLink>` component.

## Usage

### With npm

Initializing GA and Tracking Pageviews:

```js
import ReactGA from 'react-ga';
ReactGA.initialize('UA-000000-01');
ReactGA.pageview(window.location.pathname + window.location.search);
```

### With bower

When included as a script tag, a variable `ReactGA` is exposed in the global scope.

```js

<!-- The core React library -->
<script src="https://unpkg.com/react@15.5.0/dist/react.min.js"></script>
<!-- The ReactDOM Library -->
<script src="https://unpkg.com/react-dom@15.5.0/dist/react-dom.min.js"></script>
<!-- ReactGA library -->
<script src="/path/to/bower_components/react-ga/dist/react-ga.min.js"></script>

<script>
ReactGA.initialize('UA-000000-01', { debug: true });
</script>
```

### Demo Code

For a working demo have a look at the [demo files](/demo) or clone this repo and run `npm install` `npm start` then open http://localhost:8080 and follow the instructions.
Demo requires you to have your own TrackingID.

## Upgrading from `1.x` to `2.x`

You can safely upgrade to `2.x` as there are no breaking changes. The main new feature is that the underlying `ga` function is now exposed via the property `ReactGA.ga`. This can be helpful when you need a function that `ReactGA` doesn't support at the moment. Also, for that reason, it is recommended that you rename your imported value as `ReactGA` rather than `ga` so as to distinguish between the React GA wrapper and the original `ga` function.

## Community Components

While some convenience components are included inside the package, some are specific to each application.
A community curated list of these is available in the wiki: https://github.com/react-ga/react-ga/wiki/Community-Components. Feel free to add any you have found useful.

## API

#### ReactGA.initialize(gaTrackingID, options)

GA must be initialized using this function before any of the other tracking functions will record any data. The values are checked and sent through to the `ga('create', ...` call.

If you aren't getting any data back from Page Timings, you may have to add `siteSpeedSampleRate: 100` to the `gaOptions` object. This will send 100% of hits to Google Analytics. By default only 1% are sent.

###### Example

```js
ReactGA.initialize('UA-000000-01', {
debug: true,
titleCase: false,
gaOptions: {
userId: 123
}
});
```

Or with multiple trackers

```js
ReactGA.initialize(
[
{
trackingId: 'UA-000000-01',
gaOptions: {
name: 'tracker1',
userId: 123
}
},
{
trackingId: 'UA-000000-02',
gaOptions: { name: 'tracker2' }
}
],
{ debug: true, alwaysSendToDefaultTracker: false }
);
```

| Value | Notes |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| gaTrackingID | `String`. Required. GA Tracking ID like `UA-000000-01`. |
| options.debug | `Boolean`. Optional. If set to `true`, will output additional feedback to the console. |
| options.titleCase | `Boolean`. Optional. Defaults to `true`. If set to `false`, strings will not be converted to title case before sending to GA. |
| options.gaOptions | `Object`. Optional. [GA configurable create only fields.](https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference) |
| options.gaAddress | `String`. Optional. If you are self-hosting your `analytics.js`, you can specify the URL for it here. |
| options.alwaysSendToDefaultTracker | `Boolean`. Optional. Defaults to `true`. If set to `false` _and_ using multiple trackers, the event will not be send to the default tracker. |
| options.testMode | `Boolean`. Optional. Defaults to `false`. Enables test mode. See [here](https://github.com/react-ga/react-ga#test-mode) for more information. |
| options.standardImplementation | `Boolean`. Optional. Defaults to `false`. Enables loading GA as google expects it. See [here](https://github.com/react-ga/react-ga#standard-implementation) for more information. |
| options.useExistingGa | `Boolean`. Optional. Skips call to `window.ga()`, assuming you have manually run it. |
| options.redactEmail | `Boolean`. Optional. Defaults to `true`. Enables redacting a email as the string that in "Event Category" and "Event Action". |

If you are having additional troubles and setting `debug = true` shows as working please try using the [Chrome GA Debugger Extension](https://chrome.google.com/webstore/detail/google-analytics-debugger/jnkmfdileelhofjcijamephohjechhna).
This will help you figure out if your implementation is off or your GA Settings are not correct.

#### ReactGA.set(fieldsObject)

This will set the values of [custom dimensions](https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#dimension) in Google Analytics.

###### Example

```js
ReactGA.set({ dimension14: 'Sports' });
```

Or with multiple trackers

```js
ReactGA.set({ userId: 123 }, ['tracker2']);
```

| Value | Notes |
| ------------ | ----------------------------------------------------------------- |
| fieldsObject | `Object`. e.g. `{ userId: 123 }` |
| trackerNames | `Array`. Optional. A list of extra trackers to run the command on |

#### ReactGA.pageview(path)

###### Example

```js
ReactGA.pageview('/about/contact-us');
```

Or with multiple trackers

```js
ReactGA.pageview('/about/contact-us', ['tracker2']);
```

This will send all the named trackers listed in the array parameter. The default tracker will or will not send according to the `initialize()` setting `alwaysSendToDefaultTracker` (defaults to `true` if not provided).

| Value | Notes |
| ------------ | ----------------------------------------------------------------- |
| path | `String`. e.g. '/get-involved/other-ways-to-help' |
| trackerNames | `Array`. Optional. A list of extra trackers to run the command on |
| title | `String`. Optional. e.g. 'Other Ways to Help' |

See example above for use with `react-router`.

#### ReactGA.modalview(modalName)

A modal view is often an equivalent to a pageview in our UX, but without a change in URL that would record a standard GA pageview. For example, a 'contact us' modal may be accessible from any page in a site, even if we don't have a standalone 'contact us' page on its own URL. In this scenario, the modalview should be recorded using this function.

###### Example

```js
ReactGA.modalview('/about/contact-us');
```

| Value | Notes |
| --------- | --------------------------------------------------- |
| modalName | `String`. E.g. 'login', 'read-terms-and-conditions' |

#### ReactGA.event(args)

Tracking in-page `event` interactions is key to understanding the use of any interactive web property. This is how we record user interactions that don't trigger a change in URL.

###### Examples

```js
ReactGA.event({
category: 'User',
action: 'Created an Account'
});

ReactGA.event({
category: 'Social',
action: 'Rated an App',
value: 3
});

ReactGA.event({
category: 'Editing',
action: 'Deleted Component',
label: 'Game Widget'
});

ReactGA.event({
category: 'Promotion',
action: 'Displayed Promotional Widget',
label: 'Homepage Thing',
nonInteraction: true
});
```

| Value | Notes |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| args.category | `String`. Required. A top level category for these events. E.g. 'User', 'Navigation', 'App Editing', etc. |
| args.action | `String`. Required. A description of the behaviour. E.g. 'Clicked Delete', 'Added a component', 'Deleted account', etc. |
| args.label | `String`. Optional. More precise labelling of the related action. E.g. alongside the 'Added a component' action, we could add the name of a component as the label. E.g. 'Survey', 'Heading', 'Button', etc. |
| args.value | `Int`. Optional. A means of recording a numerical value against an event. E.g. a rating, a score, etc. |
| args.nonInteraction | `Boolean`. Optional. If an event is not triggered by a user interaction, but instead by our code (e.g. on page load), it should be flagged as a `nonInteraction` event to avoid skewing bounce rate data. |
| args.transport | `String`. Optional. This specifies the transport mechanism with which hits will be sent. Valid values include 'beacon', 'xhr', or 'image'. |

#### ReactGA.timing(args)

Allow to measure periods of time such as AJAX requests and resources loading by sending hits using the analytics.js library. For more detailed description, please refer to https://developers.google.com/analytics/devguides/collection/analyticsjs/user-timings.

###### Example

Usage:

```js
ReactGA.timing({
category: 'JS Libraries',
variable: 'load',
value: 20, // in milliseconds
label: 'CDN libs'
});
```

This is equivalent to the following Google Analytics command:

```js
ga('send', 'timing', 'JS Libraries', 'load', 20, 'CDN libs');
```

| Value | Notes |
| ------------- | ------------------------------------------------------------------------------------------------- |
| args.category | `String`. Required. A string for categorizing all user timing variables into logical groups. |
| args.variable | `String`. Required. Name of the variable being recorded. |
| args.value | `Int`. Required. Number of milliseconds elapsed time to report. |
| args.label | `String`. Optional. It can be used to add flexibility in visualizing user timings in the reports. |

#### ReactGA.ga()

The original `ga` function can be accessed via this method. This gives developers the flexibility of directly
using `ga.js` features that have not yet been implemented in `ReactGA`. No validations will be done
by `ReactGA` as it is being bypassed if this approach is used.

If no arguments are passed to `ReactGA.ga()`, the `ga` object is returned instead.

###### Example

Usage with arguments:

```js
ReactGA.ga('send', 'pageview', '/mypage');
```

Usage without arguments:

```js
var ga = ReactGA.ga();
ga('send', 'pageview', '/mypage');
```

#### ReactGA.outboundLink(args, hitCallback)

Tracking links out to external URLs (including id.webmaker.org for OAuth 2.0 login flow). A declarative approach is found in the next section, by using an `<OutboundLink>` component.

###### Example

```js
ReactGA.outboundLink(
{
label: 'Clicked Create an Account'
},
function () {
console.log('redirect here');
},
['tracker2']
);
```

| Value | Notes |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| args.label | `String`. Required. Description of where the outbound link points to. Either as a URL, or a string. |
| hitCallback | `function`. The react-ga implementation accounts for the possibility that GA servers are down, or GA is blocked, by using a fallback 250ms timeout. See [notes in GA Dev Guide](https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#hitCallback) |
| trackerNames | `Array<String>` Optional. A list of extra trackers to run the command on. |

### `<OutboundLink>` Component

Outbound links can directly be used as a component in your React code and the event label will be sent directly to ReactGA.

###### Example

```js
var ReactGA = require('react-ga');

render() {
return (
<div>
<ReactGA.OutboundLink
eventLabel="myLabel"
to="http://www.example.com"
target="_blank"
trackerNames={['tracker2']}
>
My Link
</ReactGA.OutboundLink>
</div>
);
}
```

| Value | Notes |
| ------------ | --------------------------------------------------------------------------------------------------- |
| eventLabel | `String`. Required. Description of where the outbound link points to. Either as a URL, or a string. |
| to | `String`. Required. URL the link leads to. |
| target | `String`. Optional. To open the link in a new tab, use a value of `_blank`. |
| trackerNames | `Array<String>` Optional. A list of extra trackers to run the command on. |

For bower, use the `<ReactGA.OutboundLink>` component.

#### ReactGA.exception(args)

[GA exception tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/exceptions)

###### Example

```js
ReactGA.exception({
description: 'An error occurred',
fatal: true
});
```

| Value | Notes |
| ---------------- | -------------------------------------------------------------- |
| args.description | `String`. Optional. Description of what happened. |
| args.fatal | `boolean`. Optional. Set to `true` if it was a fatal exception. |

#### ReactGA.plugin.require(name, [options])

Require GA plugins.

###### Example

```js
ReactGA.plugin.require('localHitSender', { path: '/log', debug: true });
```

| Value | Notes |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name | `String`. Required. The name of the plugin to be required. Note: if the plugin is not an official analytics.js plugin, it must be provided elsewhere on the page. |
| options | `Object`. Optional. An initialization object that will be passed to the plugin constructor upon instantiation. |

#### ReactGA.plugin.execute(pluginName, action, [actionType], [payload])

Execute the `action` for the `pluginName` with the payload.

###### Example

```js
ReactGA.plugin.execute('ecommerce', 'addTransaction', {
id: 'jd38je31j',
revenue: '3.50'
});
```

You can use this function with four arguments to pass `actionType` and `payload` along with executed action

###### Example

```js
ReactGA.plugin.execute('ec', 'setAction', 'purchase', {
id: 'jd38je31j',
revenue: '3.50'
});
```

### Test Mode

To enable test mode, initialize ReactGA with the `testMode: true` option. Here's an example from `tests/utils/testMode.test.js`

```js
// This should be part of your setup
ReactGA.initialize('foo', { testMode: true });
// This would be in the component/js you are testing
ReactGA.ga('send', 'pageview', '/mypage');
// This would be how you check that the calls are made correctly
expect(ReactGA.testModeAPI.calls).toEqual([
['create', 'foo', 'auto'],
['send', 'pageview', '/mypage']
]);
```

### Standard Implementation

To enable standard implemention of google analytics.

Add this script to your html

```html
<!-- Google Analytics -->
<script>
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
(i[r] =
i[r] ||
function () {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(
window,
document,
'script',
'<%=htmlWebpackPlugin.options.analyticsURL%>',
'ga'
);
ga('create', 'UA-XXX-X', 'auto');
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->
```

Initialize ReactGA with `standardImplementation: true` option.

```js
// This should be part of your setup
ReactGA.initialize('UA-XXX-X', { standardImplementation: true });
```

---

## Development

### Prerequisites

- node.js
- npm
- `npm install`
- `npm install react@^15.6.1 prop-types@^15.5.10` - This is for the optional dependencies.

### To Test

```bash
npm test
```

### Submitting changes/fixes

Follow instructions inside [CONTRIBUTING.md](https://github.com/react-ga/react-ga/blob/master/CONTRIBUTING.md)

---

#### Acknowledgements

- Quite a lot of the code in this repo, came from [webmaker-analytics](https://github.com/mozilla/webmaker-analytics).

+ 27
- 0
node_modules/react-ga/bower.json View File

@@ -0,0 +1,27 @@
{
"name": "react-ga",
"version": "3.3.1",
"homepage": "https://github.com/react-ga/react-ga",
"authors": [
"Tay Yang Shun <tay.yang.shun@gmail.com>"
],
"description": "React Google Analytics module",
"main": "dist/react-ga.min.js",
"moduleType": [
"amd",
"globals",
"node"
],
"keywords": [
"react",
"google",
"analytics"
],
"license": "Apache-2.0",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test"
]
}

+ 1
- 0
node_modules/react-ga/commitlint.config.js View File

@@ -0,0 +1 @@
module.exports = { extends: ['@commitlint/config-conventional'] };

+ 2
- 0
node_modules/react-ga/core.d.ts View File

@@ -0,0 +1,2 @@
export { default } from './types/index';
export * from './types/index';

+ 4
- 0
node_modules/react-ga/core.js View File

@@ -0,0 +1,4 @@
// eslint-disable-next-line
const index = require('./dist/react-ga-core.js');

module.exports = index.default;

+ 55
- 0
node_modules/react-ga/demo/app/Events.jsx View File

@@ -0,0 +1,55 @@
import React, { PureComponent } from 'react';
import ReactGA from '../../src';

export default class Events extends PureComponent {
constructor(props, context) {
super(props, context);
this.state = {
category: '',
action: '',
label: ''
};
}

setValue = (key, event) => {
this.setState({
[key]: event.target.value
});
};

sendEvent = (event) => {
event.preventDefault();
ReactGA.event(this.state);
this.setState({
category: '',
action: '',
label: ''
});
};

render() {
const { category, action, label } = this.state;
return (
<form onSubmit={this.sendEvent}>
<h2>Events</h2>
<p>Enter in details below to trigger an ReactGA.event call</p>
<div>
category{' '}
<input
value={category}
onChange={this.setValue.bind(this, 'category')}
/>
</div>
<div>
action{' '}
<input value={action} onChange={this.setValue.bind(this, 'action')} />
</div>
<div>
label{' '}
<input value={label} onChange={this.setValue.bind(this, 'label')} />
</div>
<button type="submit">Send Event.</button>
</form>
);
}
}

+ 91
- 0
node_modules/react-ga/demo/app/Router.jsx View File

@@ -0,0 +1,91 @@
/**
* Original Source code from https://reacttraining.com/react-router/web/example/basic
*/

import React from 'react';
import { HashRouter as Router, Route, Link } from 'react-router-dom';
import withTracker from './withTracker';

import Events from './Events';

function Topic({ match }) {
return (
<div>
<h3>{match.params.topicId}</h3>
</div>
);
}

function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}

function About() {
return (
<div>
<h2>About</h2>
</div>
);
}

function Topics({ match }) {
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>Rendering with React</Link>
</li>
<li>
<Link to={`${match.url}/components`}>Components</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>Props v. State</Link>
</li>
</ul>

<Route path={`${match.url}/:topicId`} component={withTracker(Topic)} />
<Route
exact
path={match.url}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
);
}

function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
<li>
<Link to="/events">Events</Link>
</li>
</ul>

<hr />

<Route exact path="/" component={withTracker(Home)} />
<Route path="/about" component={withTracker(About)} />
<Route path="/topics" component={withTracker(Topics)} />
<Route path="/events" component={withTracker(Events)} />
</div>
</Router>
);
}

export default BasicExample;

+ 173
- 0
node_modules/react-ga/demo/app/index.jsx View File

@@ -0,0 +1,173 @@
import React, { PureComponent } from 'react';
import ReactGA from '../../src';

import Router from './Router';

function asDisplayString(value) {
if (typeof value === 'string') return `'${value}'`;
return value.toString();
}

function renderConfigString(config, indent = '') {
return [
'{',
...Object.keys(config)
.map((key) => {
if (config[key] === undefined || config[key] === null) return '';
return `\t${key}: ${asDisplayString(config[key])}`;
})
.filter((value) => value),
'}'
].reduce((result, element, index, array) => {
return `${result}${indent}${element}${
index < array.length - 1 ? '\n' : ''
}`;
}, '');
}

const DEFAULT_CONFIG = {
trackingId: '',
debug: true,
gaOptions: {
cookieDomain: 'none'
}
};

export default class App extends PureComponent {
constructor(props, context) {
super(props, context);

this.state = {
reactGaInitialised: false,
configs: [DEFAULT_CONFIG]
};
}

filteredConfigs = () => {
const { configs } = this.state;
return configs.filter(({ trackingId: id }) => id);
};

initReactGA = (event) => {
event.preventDefault();
if (this.filteredConfigs().length === 0) {
return;
}
const { configs } = this.state;
ReactGA.initialize(configs);
// Send initial test view
ReactGA.pageview('test-init-pageview');
this.setState({ reactGaInitialised: true });
};

addConfig = () => {
const { configs } = this.state;
this.setState({
configs: [configs, DEFAULT_CONFIG]
});
};

updateConfig = (configIndex, key, type, event) => {
const { configs } = this.state;
const config = configs[configIndex];
let value;
if (type === 'checkbox') {
value = !config[key];
} else {
value = event.target.value;
}
const newConfig = {
...config,
[key]: value
};
this.setState({
configs: [
...configs.slice(0, configIndex),
newConfig,
...configs.slice(configIndex + 1)
]
});
};

renderConfigs = () => {
const configs = this.filteredConfigs();
if (configs.length === 0) return '';
if (configs.length === 1) {
const { trackingId, ...options } = configs[0];
return `'${trackingId}'${
Object.values(options).filter((val) => val).length
? `, ${JSON.stringify(options)}`
: ''
}`;
}
return `[\n${configs.reduce((result, config, index, array) => {
const configString = renderConfigString(config, '\t');
return `${result}${result ? '\n' : ''}${configString}${
index < array.length - 1 ? ',' : ''
}`;
}, '')}\n]`;
};

render() {
const { configs, reactGaInitialised } = this.state;
if (reactGaInitialised) {
return (
<div>
<h4>App is Initialised. Refresh page to reset.</h4>
<Router />
</div>
);
}
let initializationDebug = (
<pre>
ReactGA.initialize(
{this.renderConfigs()}
);
</pre>
);
if (this.filteredConfigs().length === 0) {
initializationDebug = <p>No Valid Configs set.</p>;
}
return (
<form onSubmit={this.initReactGA}>
<p>Input your configs below:</p>
{configs.map(({ trackingId, debug }, index) => (
<div key={index}>
<div>
TrackingID:&nbsp;
<input
value={trackingId}
onChange={this.updateConfig.bind(
this,
index,
'trackingId',
'text'
)}
/>
&nbsp;Debug&nbsp;
<input
type="checkbox"
checked={debug || false}
onChange={this.updateConfig.bind(
this,
index,
'debug',
'checkbox'
)}
/>
</div>
</div>
))}
<button type="button" onClick={this.addConfig}>
Add Config
</button>
<button type="submit" disabled={configs.length < 1}>
{configs.length < 1
? 'Add Configs first'
: 'Run the initialize function as below'}
</button>
{initializationDebug}
</form>
);
}
}

+ 43
- 0
node_modules/react-ga/demo/app/withTracker.jsx View File

@@ -0,0 +1,43 @@
/**
* From ReactGA Community Wiki Page https://github.com/react-ga/react-ga/wiki/React-Router-v4-withTracker
*/

import React, { Component } from 'react';
import ReactGA from '../../src';

export default function withTracker(WrappedComponent, options = {}) {
const trackPage = (page) => {
ReactGA.set({
page,
...options
});
ReactGA.pageview(page);
};

const HOC = class extends Component {
componentDidMount() {
const {
location: { pathname: page }
} = this.props;
trackPage(page);
}

// eslint-disable-next-line camelcase
UNSAFE_componentWillReceiveProps(nextProps) {
const {
location: { pathname: currentPage }
} = this.props;
const nextPage = nextProps.location.pathname;

if (currentPage !== nextPage) {
trackPage(nextPage);
}
}

render() {
return <WrappedComponent {...this.props} />;
}
};

return HOC;
}

+ 8
- 0
node_modules/react-ga/demo/index.jsx View File

@@ -0,0 +1,8 @@
import React from 'react';
import { render } from 'react-dom';
import App from './app';

const container = document.createElement('div');
document.body.appendChild(container);

render(<App />, container);

+ 131
- 0
node_modules/react-ga/dist/esm/components/OutboundLink.js View File

@@ -0,0 +1,131 @@
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }

var _excluded = ["to", "target"];

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import warn from '../utils/console/warn';
var NEWTAB = '_blank';
var MIDDLECLICK = 1;

var OutboundLink = /*#__PURE__*/function (_Component) {
_inherits(OutboundLink, _Component);

var _super = _createSuper(OutboundLink);

function OutboundLink() {
var _this;

_classCallCheck(this, OutboundLink);

for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}

_this = _super.call.apply(_super, [this].concat(args));

_defineProperty(_assertThisInitialized(_this), "handleClick", function (event) {
var _this$props = _this.props,
target = _this$props.target,
eventLabel = _this$props.eventLabel,
to = _this$props.to,
onClick = _this$props.onClick,
trackerNames = _this$props.trackerNames;
var eventMeta = {
label: eventLabel
};
var sameTarget = target !== NEWTAB;
var normalClick = !(event.ctrlKey || event.shiftKey || event.metaKey || event.button === MIDDLECLICK);

if (sameTarget && normalClick) {
event.preventDefault();
OutboundLink.trackLink(eventMeta, function () {
window.location.href = to;
}, trackerNames);
} else {
OutboundLink.trackLink(eventMeta, function () {}, trackerNames);
}

if (onClick) {
onClick(event);
}
});

return _this;
}

_createClass(OutboundLink, [{
key: "render",
value: function render() {
var _this$props2 = this.props,
href = _this$props2.to,
target = _this$props2.target,
oldProps = _objectWithoutProperties(_this$props2, _excluded);

var props = _objectSpread(_objectSpread({}, oldProps), {}, {
target: target,
href: href,
onClick: this.handleClick
});

if (target === NEWTAB) {
props.rel = "".concat(props.rel ? props.rel : '', " noopener noreferrer").trim();
}

delete props.eventLabel;
delete props.trackerNames;
return /*#__PURE__*/React.createElement('a', props);
}
}]);

return OutboundLink;
}(Component);

_defineProperty(OutboundLink, "trackLink", function () {
warn('ga tracking not enabled');
});

export { OutboundLink as default };
OutboundLink.propTypes = {
eventLabel: PropTypes.string.isRequired,
target: PropTypes.string,
to: PropTypes.string,
onClick: PropTypes.func,
trackerNames: PropTypes.arrayOf(PropTypes.string)
};
OutboundLink.defaultProps = {
target: null,
to: null,
onClick: null,
trackerNames: null
};

+ 635
- 0
node_modules/react-ga/dist/esm/core.js View File

@@ -0,0 +1,635 @@
var _excluded = ["category", "action", "label", "value", "nonInteraction", "transport"];

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }

function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

/**
* React Google Analytics Module
*
* @package react-ga
* @author Adam Lofting <adam@mozillafoundation.org>
* Atul Varma <atul@mozillafoundation.org>
*/

/**
* Utilities
*/
import format from './utils/format';
import removeLeadingSlash from './utils/removeLeadingSlash';
import trim from './utils/trim';
import loadGA from './utils/loadGA';
import warn from './utils/console/warn';
import log from './utils/console/log';
import TestModeAPI from './utils/testModeAPI';

var _isNotBrowser = typeof window === 'undefined' || typeof document === 'undefined';

var _debug = false;
var _titleCase = true;
var _testMode = false;
var _alwaysSendToDefaultTracker = true;
var _redactEmail = true;

var internalGa = function internalGa() {
var _window;

if (_testMode) return TestModeAPI.ga.apply(TestModeAPI, arguments);
if (_isNotBrowser) return false;
if (!window.ga) return warn('ReactGA.initialize must be called first or GoogleAnalytics should be loaded manually');
return (_window = window).ga.apply(_window, arguments);
};

function _format(s) {
return format(s, _titleCase, _redactEmail);
}

function _gaCommand(trackerNames) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}

var command = args[0];

if (typeof internalGa === 'function') {
if (typeof command !== 'string') {
warn('ga command must be a string');
return;
}

if (_alwaysSendToDefaultTracker || !Array.isArray(trackerNames)) internalGa.apply(void 0, args);

if (Array.isArray(trackerNames)) {
trackerNames.forEach(function (name) {
internalGa.apply(void 0, _toConsumableArray(["".concat(name, ".").concat(command)].concat(args.slice(1))));
});
}
}
}

function _initialize(gaTrackingID, options) {
if (!gaTrackingID) {
warn('gaTrackingID is required in initialize()');
return;
}

if (options) {
if (options.debug && options.debug === true) {
_debug = true;
}

if (options.titleCase === false) {
_titleCase = false;
}

if (options.redactEmail === false) {
_redactEmail = false;
}

if (options.useExistingGa) {
return;
}
}

if (options && options.gaOptions) {
internalGa('create', gaTrackingID, options.gaOptions);
} else {
internalGa('create', gaTrackingID, 'auto');
}
}

export function addTrackers(configsOrTrackingId, options) {
if (Array.isArray(configsOrTrackingId)) {
configsOrTrackingId.forEach(function (config) {
if (_typeof(config) !== 'object') {
warn('All configs must be an object');
return;
}

_initialize(config.trackingId, config);
});
} else {
_initialize(configsOrTrackingId, options);
}

return true;
}
export function initialize(configsOrTrackingId, options) {
if (options && options.testMode === true) {
_testMode = true;
} else {
if (_isNotBrowser) {
return;
}

if (!options || options.standardImplementation !== true) loadGA(options);
}

_alwaysSendToDefaultTracker = options && typeof options.alwaysSendToDefaultTracker === 'boolean' ? options.alwaysSendToDefaultTracker : true;
addTrackers(configsOrTrackingId, options);
}
/**
* ga:
* Returns the original GA object.
*/

export function ga() {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}

if (args.length > 0) {
internalGa.apply(void 0, args);

if (_debug) {
log("called ga('arguments');");
log("with arguments: ".concat(JSON.stringify(args)));
}
}

return window.ga;
}
/**
* set:
* GA tracker set method
* @param {Object} fieldsObject - a field/value pair or a group of field/value pairs on the tracker
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/

export function set(fieldsObject, trackerNames) {
if (!fieldsObject) {
warn('`fieldsObject` is required in .set()');
return;
}

if (_typeof(fieldsObject) !== 'object') {
warn('Expected `fieldsObject` arg to be an Object');
return;
}

if (Object.keys(fieldsObject).length === 0) {
warn('empty `fieldsObject` given to .set()');
}

_gaCommand(trackerNames, 'set', fieldsObject);

if (_debug) {
log("called ga('set', fieldsObject);");
log("with fieldsObject: ".concat(JSON.stringify(fieldsObject)));
}
}
/**
* send:
* Clone of the low level `ga.send` method
* WARNING: No validations will be applied to this
* @param {Object} fieldObject - field object for tracking different analytics
* @param {Array} trackerNames - trackers to send the command to
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/

export function send(fieldObject, trackerNames) {
_gaCommand(trackerNames, 'send', fieldObject);

if (_debug) {
log("called ga('send', fieldObject);");
log("with fieldObject: ".concat(JSON.stringify(fieldObject)));
log("with trackers: ".concat(JSON.stringify(trackerNames)));
}
}
/**
* pageview:
* Basic GA pageview tracking
* @param {String} path - the current page page e.g. '/about'
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
* @param {String} title - (optional) the page title e. g. 'My Website'
*/

export function pageview(rawPath, trackerNames, title) {
if (!rawPath) {
warn('path is required in .pageview()');
return;
}

var path = trim(rawPath);

if (path === '') {
warn('path cannot be an empty string in .pageview()');
return;
}

var extraFields = {};

if (title) {
extraFields.title = title;
}

if (typeof ga === 'function') {
_gaCommand(trackerNames, 'send', _objectSpread({
hitType: 'pageview',
page: path
}, extraFields));

if (_debug) {
log("called ga('send', 'pageview', path);");
var extraLog = '';

if (title) {
extraLog = " and title: ".concat(title);
}

log("with path: ".concat(path).concat(extraLog));
}
}
}
/**
* modalview:
* a proxy to basic GA pageview tracking to consistently track
* modal views that are an equivalent UX to a traditional pageview
* @param {String} modalName e.g. 'add-or-edit-club'
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/

export function modalview(rawModalName, trackerNames) {
if (!rawModalName) {
warn('modalName is required in .modalview(modalName)');
return;
}

var modalName = removeLeadingSlash(trim(rawModalName));

if (modalName === '') {
warn('modalName cannot be an empty string or a single / in .modalview()');
return;
}

if (typeof ga === 'function') {
var path = "/modal/".concat(modalName);

_gaCommand(trackerNames, 'send', 'pageview', path);

if (_debug) {
log("called ga('send', 'pageview', path);");
log("with path: ".concat(path));
}
}
}
/**
* timing:
* GA timing
* @param args.category {String} required
* @param args.variable {String} required
* @param args.value {Int} required
* @param args.label {String} required
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/

export function timing() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
category = _ref.category,
variable = _ref.variable,
value = _ref.value,
label = _ref.label;

var trackerNames = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

if (typeof ga === 'function') {
if (!category || !variable || typeof value !== 'number') {
warn('args.category, args.variable ' + 'AND args.value are required in timing() ' + 'AND args.value has to be a number');
return;
} // Required Fields


var fieldObject = {
hitType: 'timing',
timingCategory: _format(category),
timingVar: _format(variable),
timingValue: value
};

if (label) {
fieldObject.timingLabel = _format(label);
}

send(fieldObject, trackerNames);
}
}
/**
* event:
* GA event tracking
* @param args.category {String} required
* @param args.action {String} required
* @param args.label {String} optional
* @param args.value {Int} optional
* @param args.nonInteraction {boolean} optional
* @param args.transport {string} optional
* @param {{action: string, category: string}} trackerNames - (optional) a list of extra trackers to run the command on
*/

export function event() {
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
category = _ref2.category,
action = _ref2.action,
label = _ref2.label,
value = _ref2.value,
nonInteraction = _ref2.nonInteraction,
transport = _ref2.transport,
args = _objectWithoutProperties(_ref2, _excluded);

var trackerNames = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

if (typeof ga === 'function') {
// Simple Validation
if (!category || !action) {
warn('args.category AND args.action are required in event()');
return;
} // Required Fields


var fieldObject = {
hitType: 'event',
eventCategory: _format(category),
eventAction: _format(action)
}; // Optional Fields

if (label) {
fieldObject.eventLabel = _format(label);
}

if (typeof value !== 'undefined') {
if (typeof value !== 'number') {
warn('Expected `args.value` arg to be a Number.');
} else {
fieldObject.eventValue = value;
}
}

if (typeof nonInteraction !== 'undefined') {
if (typeof nonInteraction !== 'boolean') {
warn('`args.nonInteraction` must be a boolean.');
} else {
fieldObject.nonInteraction = nonInteraction;
}
}

if (typeof transport !== 'undefined') {
if (typeof transport !== 'string') {
warn('`args.transport` must be a string.');
} else {
if (['beacon', 'xhr', 'image'].indexOf(transport) === -1) {
warn('`args.transport` must be either one of these values: `beacon`, `xhr` or `image`');
}

fieldObject.transport = transport;
}
}

Object.keys(args).filter(function (key) {
return key.substr(0, 'dimension'.length) === 'dimension';
}).forEach(function (key) {
fieldObject[key] = args[key];
});
Object.keys(args).filter(function (key) {
return key.substr(0, 'metric'.length) === 'metric';
}).forEach(function (key) {
fieldObject[key] = args[key];
}); // Send to GA

send(fieldObject, trackerNames);
}
}
/**
* exception:
* GA exception tracking
* @param args.description {String} optional
* @param args.fatal {boolean} optional
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/

export function exception(_ref3, trackerNames) {
var description = _ref3.description,
fatal = _ref3.fatal;

if (typeof ga === 'function') {
// Required Fields
var fieldObject = {
hitType: 'exception'
}; // Optional Fields

if (description) {
fieldObject.exDescription = _format(description);
}

if (typeof fatal !== 'undefined') {
if (typeof fatal !== 'boolean') {
warn('`args.fatal` must be a boolean.');
} else {
fieldObject.exFatal = fatal;
}
} // Send to GA


send(fieldObject, trackerNames);
}
}
export var plugin = {
/**
* require:
* GA requires a plugin
* @param name {String} e.g. 'ecommerce' or 'myplugin'
* @param options {Object} optional e.g {path: '/log', debug: true}
* @param trackerName {String} optional e.g 'trackerName'
*/
require: function require(rawName, options, trackerName) {
if (typeof ga === 'function') {
// Required Fields
if (!rawName) {
warn('`name` is required in .require()');
return;
}

var name = trim(rawName);

if (name === '') {
warn('`name` cannot be an empty string in .require()');
return;
}

var requireString = trackerName ? "".concat(trackerName, ".require") : 'require'; // Optional Fields

if (options) {
if (_typeof(options) !== 'object') {
warn('Expected `options` arg to be an Object');
return;
}

if (Object.keys(options).length === 0) {
warn('Empty `options` given to .require()');
}

ga(requireString, name, options);

if (_debug) {
log("called ga('require', '".concat(name, "', ").concat(JSON.stringify(options)));
}
} else {
ga(requireString, name);

if (_debug) {
log("called ga('require', '".concat(name, "');"));
}
}
}
},

/**
* execute:
* GA execute action for plugin
* Takes variable number of arguments
* @param pluginName {String} e.g. 'ecommerce' or 'myplugin'
* @param action {String} e.g. 'addItem' or 'myCustomAction'
* @param actionType {String} optional e.g. 'detail'
* @param payload {Object} optional e.g { id: '1x5e', name : 'My product to track' }
*/
execute: function execute(pluginName, action) {
var payload;
var actionType;

for (var _len3 = arguments.length, args = new Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) {
args[_key3 - 2] = arguments[_key3];
}

if (args.length === 1) {
payload = args[0];
} else {
actionType = args[0];
payload = args[1];
}

if (typeof ga === 'function') {
if (typeof pluginName !== 'string') {
warn('Expected `pluginName` arg to be a String.');
} else if (typeof action !== 'string') {
warn('Expected `action` arg to be a String.');
} else {
var command = "".concat(pluginName, ":").concat(action);
payload = payload || null;

if (actionType && payload) {
ga(command, actionType, payload);

if (_debug) {
log("called ga('".concat(command, "');"));
log("actionType: \"".concat(actionType, "\" with payload: ").concat(JSON.stringify(payload)));
}
} else if (payload) {
ga(command, payload);

if (_debug) {
log("called ga('".concat(command, "');"));
log("with payload: ".concat(JSON.stringify(payload)));
}
} else {
ga(command);

if (_debug) {
log("called ga('".concat(command, "');"));
}
}
}
}
}
};
/**
* outboundLink:
* GA outboundLink tracking
* @param args.label {String} e.g. url, or 'Create an Account'
* @param {function} hitCallback - Called after processing a hit.
*/

export function outboundLink(args, hitCallback, trackerNames) {
if (typeof hitCallback !== 'function') {
warn('hitCallback function is required');
return;
}

if (typeof ga === 'function') {
// Simple Validation
if (!args || !args.label) {
warn('args.label is required in outboundLink()');
return;
} // Required Fields


var fieldObject = {
hitType: 'event',
eventCategory: 'Outbound',
eventAction: 'Click',
eventLabel: _format(args.label)
};
var safetyCallbackCalled = false;

var safetyCallback = function safetyCallback() {
// This prevents a delayed response from GA
// causing hitCallback from being fired twice
safetyCallbackCalled = true;
hitCallback();
}; // Using a timeout to ensure the execution of critical application code
// in the case when the GA server might be down
// or an ad blocker prevents sending the data
// register safety net timeout:


var t = setTimeout(safetyCallback, 250);

var clearableCallbackForGA = function clearableCallbackForGA() {
clearTimeout(t);

if (!safetyCallbackCalled) {
hitCallback();
}
};

fieldObject.hitCallback = clearableCallbackForGA; // Send to GA

send(fieldObject, trackerNames);
} else {
// if ga is not defined, return the callback so the application
// continues to work as expected
setTimeout(hitCallback, 0);
}
}
export var testModeAPI = TestModeAPI;
export default {
initialize: initialize,
ga: ga,
set: set,
send: send,
pageview: pageview,
modalview: modalview,
timing: timing,
event: event,
exception: exception,
plugin: plugin,
outboundLink: outboundLink,
testModeAPI: TestModeAPI
};

+ 40
- 0
node_modules/react-ga/dist/esm/index.js View File

@@ -0,0 +1,40 @@
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

import UnboundOutboundLink from './components/OutboundLink';
import * as Defaults from './core';
var initialize = Defaults.initialize;
export { initialize };
var addTrackers = Defaults.addTrackers;
export { addTrackers };
var ga = Defaults.ga;
export { ga };
var set = Defaults.set;
export { set };
var send = Defaults.send;
export { send };
var pageview = Defaults.pageview;
export { pageview };
var modalview = Defaults.modalview;
export { modalview };
var timing = Defaults.timing;
export { timing };
var event = Defaults.event;
export { event };
var exception = Defaults.exception;
export { exception };
var plugin = Defaults.plugin;
export { plugin };
var outboundLink = Defaults.outboundLink;
export { outboundLink };
var testModeAPI = Defaults.testModeAPI;
export { testModeAPI };
UnboundOutboundLink.origTrackLink = UnboundOutboundLink.trackLink;
UnboundOutboundLink.trackLink = Defaults.outboundLink;
export var OutboundLink = UnboundOutboundLink;
export default _objectSpread(_objectSpread({}, Defaults), {}, {
OutboundLink: OutboundLink
});

+ 1
- 0
node_modules/react-ga/dist/esm/utils/__mocks__/loadGA.js View File

@@ -0,0 +1 @@
export default function loadGA() {}

+ 3
- 0
node_modules/react-ga/dist/esm/utils/console/log.js View File

@@ -0,0 +1,3 @@
export default function log(s) {
console.info('[react-ga]', s);
}

+ 3
- 0
node_modules/react-ga/dist/esm/utils/console/warn.js View File

@@ -0,0 +1,3 @@
export default function warn(s) {
console.warn('[react-ga]', s);
}

+ 19
- 0
node_modules/react-ga/dist/esm/utils/format.js View File

@@ -0,0 +1,19 @@
import redactEmail from './redactEmail';
import toTitleCase from './toTitleCase';
export default function format() {
var s = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var titleCase = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var redactingEmail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

var _str = s || '';

if (titleCase) {
_str = toTitleCase(s);
}

if (redactingEmail) {
_str = redactEmail(_str);
}

return _str;
}

+ 30
- 0
node_modules/react-ga/dist/esm/utils/loadGA.js View File

@@ -0,0 +1,30 @@
var isLoaded = false;
export default function (options) {
if (isLoaded) return;
isLoaded = true;
var gaAddress = 'https://www.google-analytics.com/analytics.js';

if (options && options.gaAddress) {
gaAddress = options.gaAddress;
} else if (options && options.debug) {
gaAddress = 'https://www.google-analytics.com/analytics_debug.js';
}

var onerror = options && options.onerror; // https://developers.google.com/analytics/devguides/collection/analyticsjs/

/* eslint-disable */

(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments);
}, i[r].l = 1 * new Date();
a = s.createElement(o), m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
a.onerror = onerror;
m.parentNode.insertBefore(a, m);
})(window, document, 'script', gaAddress, 'ga');
/* eslint-enable */

}

+ 6
- 0
node_modules/react-ga/dist/esm/utils/mightBeEmail.js View File

@@ -0,0 +1,6 @@
// See if s could be an email address. We don't want to send personal data like email.
// https://support.google.com/analytics/answer/2795983?hl=en
export default function mightBeEmail(s) {
// There's no point trying to validate rfc822 fully, just look for ...@...
return typeof s === 'string' && s.indexOf('@') !== -1;
}

+ 11
- 0
node_modules/react-ga/dist/esm/utils/redactEmail.js View File

@@ -0,0 +1,11 @@
import warn from './console/warn';
import mightBeEmail from './mightBeEmail';
var redacted = 'REDACTED (Potential Email Address)';
export default function redactEmail(string) {
if (mightBeEmail(string)) {
warn('This arg looks like an email address, redacting.');
return redacted;
}

return string;
}

+ 7
- 0
node_modules/react-ga/dist/esm/utils/removeLeadingSlash.js View File

@@ -0,0 +1,7 @@
export default function removeLeadingSlash(string) {
if (string.substring(0, 1) === '/') {
return string.substring(1);
}

return string;
}

+ 14
- 0
node_modules/react-ga/dist/esm/utils/testModeAPI.js View File

@@ -0,0 +1,14 @@
export var gaCalls = [];
export default {
calls: gaCalls,
ga: function ga() {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}

gaCalls.push([].concat(args));
},
resetCalls: function resetCalls() {
gaCalls.length = 0;
}
};

+ 21
- 0
node_modules/react-ga/dist/esm/utils/toTitleCase.js View File

@@ -0,0 +1,21 @@
/**
* To Title Case 2.1 - http://individed.com/code/to-title-case/
* Copyright 2008-2013 David Gouch. Licensed under the MIT License.
* https://github.com/gouch/to-title-case
*/
import trim from './trim';
var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i; // test

export default function toTitleCase(string) {
return trim(string).replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, function (match, index, title) {
if (index > 0 && index + match.length !== title.length && match.search(smallWords) > -1 && title.charAt(index - 2) !== ':' && (title.charAt(index + match.length) !== '-' || title.charAt(index - 1) === '-') && title.charAt(index - 1).search(/[^\s-]/) < 0) {
return match.toLowerCase();
}

if (match.substr(1).search(/[A-Z]|\../) > -1) {
return match;
}

return match.charAt(0).toUpperCase() + match.substr(1);
});
}

+ 5
- 0
node_modules/react-ga/dist/esm/utils/trim.js View File

@@ -0,0 +1,5 @@
// GA strings need to have leading/trailing whitespace trimmed, and not all
// browsers have String.prototoype.trim().
export default function trim(s) {
return s && s.toString().replace(/^\s+|\s+$/g, '');
}

+ 1034
- 0
node_modules/react-ga/dist/react-ga-core.js
File diff suppressed because it is too large
View File


+ 1
- 0
node_modules/react-ga/dist/react-ga-core.min.js
File diff suppressed because it is too large
View File


+ 1267
- 0
node_modules/react-ga/dist/react-ga.js
File diff suppressed because it is too large
View File


+ 1
- 0
node_modules/react-ga/dist/react-ga.min.js
File diff suppressed because it is too large
View File


+ 3
- 0
node_modules/react-ga/jest.config.js View File

@@ -0,0 +1,3 @@
module.exports = {
setupFilesAfterEnv: ['./jest.setup.js']
};

+ 4
- 0
node_modules/react-ga/jest.setup.js View File

@@ -0,0 +1,4 @@
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

+ 88
- 0
node_modules/react-ga/package.json View File

@@ -0,0 +1,88 @@
{
"name": "react-ga",
"version": "3.3.1",
"description": "React Google Analytics Module",
"main": "dist/react-ga.js",
"module": "dist/esm/index.js",
"scripts": {
"start": "webpack-dev-server --config demo/webpack.config.js --hot --inline",
"test": "cross-env BABEL_ENV=test jest --env=jsdom --coverage",
"test:watch": "cross-env BABEL_ENV=test jest --env=jsdom --watch",
"test:types": "tsc -p ./types/tsconfig.json",
"build": "npm run build:umd && npm run build:esm",
"build:esm": "cross-env BABEL_ENV=esm babel src --out-dir dist/esm",
"build:umd": "cross-env BABEL_ENV=umd webpack --mode=production",
"lint": "eslint ./src/**/*.js ./src/*.js ./*.js ./test/**/*.{js,jsx} ./test/*.js ./demo/**/*.{js,jsx} ./demo/*.{js,jsx} --ext .js,.jsx",
"prepare": "husky install",
"prettier": "prettier --write demo/**/* src/**/* test/**/* types/**/* *.js *.ts",
"preversion": "npm test && npm run lint",
"version": "node ./version-bower.js && npm run build && git add -A bower.json"
},
"types": "./types/index.d.ts",
"repository": {
"type": "git",
"url": "git@github.com:react-ga/react-ga"
},
"keywords": [
"React",
"GA",
"Google Analytics",
"Universal Analytics"
],
"author": "@adamlofting",
"contributors": [
"@toolness"
],
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/react-ga/react-ga/issues"
},
"homepage": "https://github.com/react-ga/react-ga",
"peerDependencies": {
"prop-types": "^15.6.0",
"react": "^15.6.2 || ^16.0 || ^17 || ^18"
},
"devDependencies": {
"@babel/cli": "7.17.10",
"@babel/core": "7.18.5",
"@babel/eslint-parser": "7.18.2",
"@babel/plugin-proposal-class-properties": "7.17.12",
"@babel/preset-env": "7.18.2",
"@babel/preset-flow": "^7.17.12",
"@babel/preset-react": "^7.17.12",
"@babel/register": "7.17.7",
"@commitlint/cli": "17.0.2",
"@commitlint/config-conventional": "17.0.2",
"@types/react": "18.0.12",
"babel-jest": "26.0.1",
"babel-loader": "8.2.5",
"conventional-changelog-cli": "2.2.2",
"cross-env": "7.0.3",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"eslint": "8.17.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jest": "26.5.3",
"eslint-plugin-jsx-a11y": "6.5.1",
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-react": "7.30.0",
"fs-extra": "10.1.0",
"html-webpack-plugin": "3.2.0",
"husky": "8.0.1",
"jest": "26.0.1",
"lint-staged": "13.0.1",
"prettier": "2.7.0",
"prop-types": "15.7.2",
"react": "16.14",
"react-dom": "16.14",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"terser-webpack-plugin": "1.4.1",
"typescript": "4.7.3",
"webpack": "4.46.0",
"webpack-cli": "3.3.9",
"webpack-dev-server": "3.8.2"
}
}

+ 75
- 0
node_modules/react-ga/src/components/OutboundLink.js View File

@@ -0,0 +1,75 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';

import warn from '../utils/console/warn';

const NEWTAB = '_blank';
const MIDDLECLICK = 1;

export default class OutboundLink extends Component {
static trackLink = () => {
warn('ga tracking not enabled');
};

handleClick = (event) => {
const { target, eventLabel, to, onClick, trackerNames } = this.props;
const eventMeta = { label: eventLabel };
const sameTarget = target !== NEWTAB;
const normalClick = !(
event.ctrlKey ||
event.shiftKey ||
event.metaKey ||
event.button === MIDDLECLICK
);

if (sameTarget && normalClick) {
event.preventDefault();
OutboundLink.trackLink(
eventMeta,
() => {
window.location.href = to;
},
trackerNames
);
} else {
OutboundLink.trackLink(eventMeta, () => {}, trackerNames);
}

if (onClick) {
onClick(event);
}
};

render() {
const { to: href, target, ...oldProps } = this.props;
const props = {
...oldProps,
target,
href,
onClick: this.handleClick
};

if (target === NEWTAB) {
props.rel = `${props.rel ? props.rel : ''} noopener noreferrer`.trim();
}

delete props.eventLabel;
delete props.trackerNames;
return React.createElement('a', props);
}
}

OutboundLink.propTypes = {
eventLabel: PropTypes.string.isRequired,
target: PropTypes.string,
to: PropTypes.string,
onClick: PropTypes.func,
trackerNames: PropTypes.arrayOf(PropTypes.string)
};

OutboundLink.defaultProps = {
target: null,
to: null,
onClick: null,
trackerNames: null
};

+ 591
- 0
node_modules/react-ga/src/core.js View File

@@ -0,0 +1,591 @@
/**
* React Google Analytics Module
*
* @package react-ga
* @author Adam Lofting <adam@mozillafoundation.org>
* Atul Varma <atul@mozillafoundation.org>
*/

/**
* Utilities
*/
import format from './utils/format';
import removeLeadingSlash from './utils/removeLeadingSlash';
import trim from './utils/trim';
import loadGA from './utils/loadGA';

import warn from './utils/console/warn';
import log from './utils/console/log';
import TestModeAPI from './utils/testModeAPI';

const _isNotBrowser =
typeof window === 'undefined' || typeof document === 'undefined';

let _debug = false;
let _titleCase = true;
let _testMode = false;
let _alwaysSendToDefaultTracker = true;
let _redactEmail = true;

const internalGa = (...args) => {
if (_testMode) return TestModeAPI.ga(...args);
if (_isNotBrowser) return false;
if (!window.ga)
return warn(
'ReactGA.initialize must be called first or GoogleAnalytics should be loaded manually'
);
return window.ga(...args);
};

function _format(s) {
return format(s, _titleCase, _redactEmail);
}

function _gaCommand(trackerNames, ...args) {
const command = args[0];
if (typeof internalGa === 'function') {
if (typeof command !== 'string') {
warn('ga command must be a string');
return;
}

if (_alwaysSendToDefaultTracker || !Array.isArray(trackerNames))
internalGa(...args);
if (Array.isArray(trackerNames)) {
trackerNames.forEach((name) => {
internalGa(...[`${name}.${command}`].concat(args.slice(1)));
});
}
}
}

function _initialize(gaTrackingID, options) {
if (!gaTrackingID) {
warn('gaTrackingID is required in initialize()');
return;
}
if (options) {
if (options.debug && options.debug === true) {
_debug = true;
}

if (options.titleCase === false) {
_titleCase = false;
}

if (options.redactEmail === false) {
_redactEmail = false;
}

if (options.useExistingGa) {
return;
}
}

if (options && options.gaOptions) {
internalGa('create', gaTrackingID, options.gaOptions);
} else {
internalGa('create', gaTrackingID, 'auto');
}
}

export function addTrackers(configsOrTrackingId, options) {
if (Array.isArray(configsOrTrackingId)) {
configsOrTrackingId.forEach((config) => {
if (typeof config !== 'object') {
warn('All configs must be an object');
return;
}
_initialize(config.trackingId, config);
});
} else {
_initialize(configsOrTrackingId, options);
}
return true;
}

export function initialize(configsOrTrackingId, options) {
if (options && options.testMode === true) {
_testMode = true;
} else {
if (_isNotBrowser) {
return;
}

if (!options || options.standardImplementation !== true) loadGA(options);
}

_alwaysSendToDefaultTracker =
options && typeof options.alwaysSendToDefaultTracker === 'boolean'
? options.alwaysSendToDefaultTracker
: true;

addTrackers(configsOrTrackingId, options);
}

/**
* ga:
* Returns the original GA object.
*/
export function ga(...args) {
if (args.length > 0) {
internalGa(...args);
if (_debug) {
log("called ga('arguments');");
log(`with arguments: ${JSON.stringify(args)}`);
}
}

return window.ga;
}

/**
* set:
* GA tracker set method
* @param {Object} fieldsObject - a field/value pair or a group of field/value pairs on the tracker
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/
export function set(fieldsObject, trackerNames) {
if (!fieldsObject) {
warn('`fieldsObject` is required in .set()');
return;
}

if (typeof fieldsObject !== 'object') {
warn('Expected `fieldsObject` arg to be an Object');
return;
}

if (Object.keys(fieldsObject).length === 0) {
warn('empty `fieldsObject` given to .set()');
}

_gaCommand(trackerNames, 'set', fieldsObject);

if (_debug) {
log("called ga('set', fieldsObject);");
log(`with fieldsObject: ${JSON.stringify(fieldsObject)}`);
}
}

/**
* send:
* Clone of the low level `ga.send` method
* WARNING: No validations will be applied to this
* @param {Object} fieldObject - field object for tracking different analytics
* @param {Array} trackerNames - trackers to send the command to
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/
export function send(fieldObject, trackerNames) {
_gaCommand(trackerNames, 'send', fieldObject);
if (_debug) {
log("called ga('send', fieldObject);");
log(`with fieldObject: ${JSON.stringify(fieldObject)}`);
log(`with trackers: ${JSON.stringify(trackerNames)}`);
}
}

/**
* pageview:
* Basic GA pageview tracking
* @param {String} path - the current page page e.g. '/about'
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
* @param {String} title - (optional) the page title e. g. 'My Website'
*/
export function pageview(rawPath, trackerNames, title) {
if (!rawPath) {
warn('path is required in .pageview()');
return;
}

const path = trim(rawPath);
if (path === '') {
warn('path cannot be an empty string in .pageview()');
return;
}

const extraFields = {};
if (title) {
extraFields.title = title;
}

if (typeof ga === 'function') {
_gaCommand(trackerNames, 'send', {
hitType: 'pageview',
page: path,
...extraFields
});

if (_debug) {
log("called ga('send', 'pageview', path);");
let extraLog = '';
if (title) {
extraLog = ` and title: ${title}`;
}
log(`with path: ${path}${extraLog}`);
}
}
}

/**
* modalview:
* a proxy to basic GA pageview tracking to consistently track
* modal views that are an equivalent UX to a traditional pageview
* @param {String} modalName e.g. 'add-or-edit-club'
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/
export function modalview(rawModalName, trackerNames) {
if (!rawModalName) {
warn('modalName is required in .modalview(modalName)');
return;
}

const modalName = removeLeadingSlash(trim(rawModalName));

if (modalName === '') {
warn('modalName cannot be an empty string or a single / in .modalview()');
return;
}

if (typeof ga === 'function') {
const path = `/modal/${modalName}`;
_gaCommand(trackerNames, 'send', 'pageview', path);

if (_debug) {
log("called ga('send', 'pageview', path);");
log(`with path: ${path}`);
}
}
}

/**
* timing:
* GA timing
* @param args.category {String} required
* @param args.variable {String} required
* @param args.value {Int} required
* @param args.label {String} required
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/
export function timing(
{ category, variable, value, label } = {},
trackerNames = undefined
) {
if (typeof ga === 'function') {
if (!category || !variable || typeof value !== 'number') {
warn(
'args.category, args.variable ' +
'AND args.value are required in timing() ' +
'AND args.value has to be a number'
);
return;
}

// Required Fields
const fieldObject = {
hitType: 'timing',
timingCategory: _format(category),
timingVar: _format(variable),
timingValue: value
};

if (label) {
fieldObject.timingLabel = _format(label);
}

send(fieldObject, trackerNames);
}
}

/**
* event:
* GA event tracking
* @param args.category {String} required
* @param args.action {String} required
* @param args.label {String} optional
* @param args.value {Int} optional
* @param args.nonInteraction {boolean} optional
* @param args.transport {string} optional
* @param {{action: string, category: string}} trackerNames - (optional) a list of extra trackers to run the command on
*/
export function event(
{ category, action, label, value, nonInteraction, transport, ...args } = {},
trackerNames = undefined
) {
if (typeof ga === 'function') {
// Simple Validation
if (!category || !action) {
warn('args.category AND args.action are required in event()');
return;
}

// Required Fields
const fieldObject = {
hitType: 'event',
eventCategory: _format(category),
eventAction: _format(action)
};

// Optional Fields
if (label) {
fieldObject.eventLabel = _format(label);
}

if (typeof value !== 'undefined') {
if (typeof value !== 'number') {
warn('Expected `args.value` arg to be a Number.');
} else {
fieldObject.eventValue = value;
}
}

if (typeof nonInteraction !== 'undefined') {
if (typeof nonInteraction !== 'boolean') {
warn('`args.nonInteraction` must be a boolean.');
} else {
fieldObject.nonInteraction = nonInteraction;
}
}

if (typeof transport !== 'undefined') {
if (typeof transport !== 'string') {
warn('`args.transport` must be a string.');
} else {
if (['beacon', 'xhr', 'image'].indexOf(transport) === -1) {
warn(
'`args.transport` must be either one of these values: `beacon`, `xhr` or `image`'
);
}

fieldObject.transport = transport;
}
}

Object.keys(args)
.filter((key) => key.substr(0, 'dimension'.length) === 'dimension')
.forEach((key) => {
fieldObject[key] = args[key];
});

Object.keys(args)
.filter((key) => key.substr(0, 'metric'.length) === 'metric')
.forEach((key) => {
fieldObject[key] = args[key];
});

// Send to GA
send(fieldObject, trackerNames);
}
}

/**
* exception:
* GA exception tracking
* @param args.description {String} optional
* @param args.fatal {boolean} optional
* @param {Array} trackerNames - (optional) a list of extra trackers to run the command on
*/
export function exception({ description, fatal }, trackerNames) {
if (typeof ga === 'function') {
// Required Fields
const fieldObject = {
hitType: 'exception'
};

// Optional Fields
if (description) {
fieldObject.exDescription = _format(description);
}

if (typeof fatal !== 'undefined') {
if (typeof fatal !== 'boolean') {
warn('`args.fatal` must be a boolean.');
} else {
fieldObject.exFatal = fatal;
}
}

// Send to GA
send(fieldObject, trackerNames);
}
}

export const plugin = {
/**
* require:
* GA requires a plugin
* @param name {String} e.g. 'ecommerce' or 'myplugin'
* @param options {Object} optional e.g {path: '/log', debug: true}
* @param trackerName {String} optional e.g 'trackerName'
*/
require: (rawName, options, trackerName) => {
if (typeof ga === 'function') {
// Required Fields
if (!rawName) {
warn('`name` is required in .require()');
return;
}

const name = trim(rawName);
if (name === '') {
warn('`name` cannot be an empty string in .require()');
return;
}
const requireString = trackerName ? `${trackerName}.require` : 'require';
// Optional Fields
if (options) {
if (typeof options !== 'object') {
warn('Expected `options` arg to be an Object');
return;
}

if (Object.keys(options).length === 0) {
warn('Empty `options` given to .require()');
}

ga(requireString, name, options);

if (_debug) {
log(`called ga('require', '${name}', ${JSON.stringify(options)}`);
}
} else {
ga(requireString, name);

if (_debug) {
log(`called ga('require', '${name}');`);
}
}
}
},

/**
* execute:
* GA execute action for plugin
* Takes variable number of arguments
* @param pluginName {String} e.g. 'ecommerce' or 'myplugin'
* @param action {String} e.g. 'addItem' or 'myCustomAction'
* @param actionType {String} optional e.g. 'detail'
* @param payload {Object} optional e.g { id: '1x5e', name : 'My product to track' }
*/
execute: (pluginName, action, ...args) => {
let payload;
let actionType;

if (args.length === 1) {
[payload] = args;
} else {
[actionType, payload] = args;
}

if (typeof ga === 'function') {
if (typeof pluginName !== 'string') {
warn('Expected `pluginName` arg to be a String.');
} else if (typeof action !== 'string') {
warn('Expected `action` arg to be a String.');
} else {
const command = `${pluginName}:${action}`;
payload = payload || null;
if (actionType && payload) {
ga(command, actionType, payload);
if (_debug) {
log(`called ga('${command}');`);
log(
`actionType: "${actionType}" with payload: ${JSON.stringify(
payload
)}`
);
}
} else if (payload) {
ga(command, payload);
if (_debug) {
log(`called ga('${command}');`);
log(`with payload: ${JSON.stringify(payload)}`);
}
} else {
ga(command);
if (_debug) {
log(`called ga('${command}');`);
}
}
}
}
}
};

/**
* outboundLink:
* GA outboundLink tracking
* @param args.label {String} e.g. url, or 'Create an Account'
* @param {function} hitCallback - Called after processing a hit.
*/
export function outboundLink(args, hitCallback, trackerNames) {
if (typeof hitCallback !== 'function') {
warn('hitCallback function is required');
return;
}

if (typeof ga === 'function') {
// Simple Validation
if (!args || !args.label) {
warn('args.label is required in outboundLink()');
return;
}

// Required Fields
const fieldObject = {
hitType: 'event',
eventCategory: 'Outbound',
eventAction: 'Click',
eventLabel: _format(args.label)
};

let safetyCallbackCalled = false;
const safetyCallback = () => {
// This prevents a delayed response from GA
// causing hitCallback from being fired twice
safetyCallbackCalled = true;

hitCallback();
};

// Using a timeout to ensure the execution of critical application code
// in the case when the GA server might be down
// or an ad blocker prevents sending the data

// register safety net timeout:
const t = setTimeout(safetyCallback, 250);

const clearableCallbackForGA = () => {
clearTimeout(t);
if (!safetyCallbackCalled) {
hitCallback();
}
};

fieldObject.hitCallback = clearableCallbackForGA;

// Send to GA
send(fieldObject, trackerNames);
} else {
// if ga is not defined, return the callback so the application
// continues to work as expected
setTimeout(hitCallback, 0);
}
}

export const testModeAPI = TestModeAPI;

export default {
initialize,
ga,
set,
send,
pageview,
modalview,
timing,
event,
exception,
plugin,
outboundLink,
testModeAPI: TestModeAPI
};

+ 25
- 0
node_modules/react-ga/src/index.js View File

@@ -0,0 +1,25 @@
import UnboundOutboundLink from './components/OutboundLink';
import * as Defaults from './core';

export const { initialize } = Defaults;
export const { addTrackers } = Defaults;
export const { ga } = Defaults;
export const { set } = Defaults;
export const { send } = Defaults;
export const { pageview } = Defaults;
export const { modalview } = Defaults;
export const { timing } = Defaults;
export const { event } = Defaults;
export const { exception } = Defaults;
export const { plugin } = Defaults;
export const { outboundLink } = Defaults;
export const { testModeAPI } = Defaults;

UnboundOutboundLink.origTrackLink = UnboundOutboundLink.trackLink;
UnboundOutboundLink.trackLink = Defaults.outboundLink;
export const OutboundLink = UnboundOutboundLink;

export default {
...Defaults,
OutboundLink
};

+ 1
- 0
node_modules/react-ga/src/utils/__mocks__/loadGA.js View File

@@ -0,0 +1 @@
export default function loadGA() {}

+ 3
- 0
node_modules/react-ga/src/utils/console/log.js View File

@@ -0,0 +1,3 @@
export default function log(s) {
console.info('[react-ga]', s);
}

+ 3
- 0
node_modules/react-ga/src/utils/console/warn.js View File

@@ -0,0 +1,3 @@
export default function warn(s) {
console.warn('[react-ga]', s);
}

+ 20
- 0
node_modules/react-ga/src/utils/format.js View File

@@ -0,0 +1,20 @@
import redactEmail from './redactEmail';
import toTitleCase from './toTitleCase';

export default function format(
s = '',
titleCase = false,
redactingEmail = true
) {
let _str = s || '';

if (titleCase) {
_str = toTitleCase(s);
}

if (redactingEmail) {
_str = redactEmail(_str);
}

return _str;
}

+ 31
- 0
node_modules/react-ga/src/utils/loadGA.js View File

@@ -0,0 +1,31 @@
let isLoaded = false;
export default function (options) {
if (isLoaded) return;
isLoaded = true;
let gaAddress = 'https://www.google-analytics.com/analytics.js';
if (options && options.gaAddress) {
gaAddress = options.gaAddress;
} else if (options && options.debug) {
gaAddress = 'https://www.google-analytics.com/analytics_debug.js';
}

const onerror = options && options.onerror;

// https://developers.google.com/analytics/devguides/collection/analyticsjs/
/* eslint-disable */
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
(i[r] =
i[r] ||
function () {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
a.onerror = onerror;
m.parentNode.insertBefore(a, m);
})(window, document, 'script', gaAddress, 'ga');
/* eslint-enable */
}

+ 6
- 0
node_modules/react-ga/src/utils/mightBeEmail.js View File

@@ -0,0 +1,6 @@
// See if s could be an email address. We don't want to send personal data like email.
// https://support.google.com/analytics/answer/2795983?hl=en
export default function mightBeEmail(s) {
// There's no point trying to validate rfc822 fully, just look for ...@...
return typeof s === 'string' && s.indexOf('@') !== -1;
}

+ 13
- 0
node_modules/react-ga/src/utils/redactEmail.js View File

@@ -0,0 +1,13 @@
import warn from './console/warn';
import mightBeEmail from './mightBeEmail';

const redacted = 'REDACTED (Potential Email Address)';

export default function redactEmail(string) {
if (mightBeEmail(string)) {
warn('This arg looks like an email address, redacting.');
return redacted;
}

return string;
}

+ 7
- 0
node_modules/react-ga/src/utils/removeLeadingSlash.js View File

@@ -0,0 +1,7 @@
export default function removeLeadingSlash(string) {
if (string.substring(0, 1) === '/') {
return string.substring(1);
}

return string;
}

+ 11
- 0
node_modules/react-ga/src/utils/testModeAPI.js View File

@@ -0,0 +1,11 @@
export const gaCalls = [];

export default {
calls: gaCalls,
ga: (...args) => {
gaCalls.push([...args]);
},
resetCalls: () => {
gaCalls.length = 0;
}
};

+ 35
- 0
node_modules/react-ga/src/utils/toTitleCase.js View File

@@ -0,0 +1,35 @@
/**
* To Title Case 2.1 - http://individed.com/code/to-title-case/
* Copyright 2008-2013 David Gouch. Licensed under the MIT License.
* https://github.com/gouch/to-title-case
*/

import trim from './trim';

const smallWords =
/^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
// test
export default function toTitleCase(string) {
return trim(string).replace(
/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g,
(match, index, title) => {
if (
index > 0 &&
index + match.length !== title.length &&
match.search(smallWords) > -1 &&
title.charAt(index - 2) !== ':' &&
(title.charAt(index + match.length) !== '-' ||
title.charAt(index - 1) === '-') &&
title.charAt(index - 1).search(/[^\s-]/) < 0
) {
return match.toLowerCase();
}

if (match.substr(1).search(/[A-Z]|\../) > -1) {
return match;
}

return match.charAt(0).toUpperCase() + match.substr(1);
}
);
}

+ 6
- 0
node_modules/react-ga/src/utils/trim.js View File

@@ -0,0 +1,6 @@
// GA strings need to have leading/trailing whitespace trimmed, and not all
// browsers have String.prototoype.trim().

export default function trim(s) {
return s && s.toString().replace(/^\s+|\s+$/g, '');
}

+ 203
- 0
node_modules/react-ga/types/index.d.ts View File

@@ -0,0 +1,203 @@
// Type definitions for react-ga 2.4
// Project: https://github.com/react-ga/react-ga
// Definitions by: Tim Aldridge <https://github.com/telshin>
// Philip Karpiak <https://github.com/eswat>
// Jerry Reptak <https://github.com/jetfault>
// Definitions: https://github.com/react-ga/react-ga

import * as React from 'react';

/* tslint:disable no-any */

/**
* Events are user interactions with content that can be measured independently from
* a web page or a screen load. Downloads, mobile ad clicks, gadgets, Flash elements,
* AJAX embedded elements, and video plays are all examples of actions you might want
* to measure as Events.
* @see https://developers.google.com/analytics/devguides/collection/analyticsjs/events
*/
export interface EventArgs {
/** Typically the object that was interacted with (e.g. 'Video') */
category: string;
/** The type of interaction (e.g. 'play') */
action: string;
/** Useful for categorizing events (e.g. 'Fall Campaign') */
label?: string;
/** A numeric value associated with the event (e.g. 42) */
value?: number;
/** Specifies that a hit be considered non-interactive. */
nonInteraction?: boolean;
/**
* This specifies the transport mechanism with which hits will be sent.
* The options are 'beacon', 'xhr', or 'image'. By default, analytics.js
* will try to figure out the best method based on the hit size and browser
* capabilities. If you specify 'beacon' and the user's browser does not support
* the `navigator.sendBeacon` method, it will fall back to 'image' or 'xhr'
* depending on hit size.
*/
transport?: 'beacon' | 'xhr' | 'image';
/** Custom dimensions */
dimension1?: string;
dimension2?: string;
dimension3?: string;
dimension4?: string;
dimension5?: string;
dimension6?: string;
dimension7?: string;
dimension8?: string;
dimension9?: string;
dimension10?: string;
dimension11?: string;
dimension12?: string;
dimension13?: string;
dimension14?: string;
dimension15?: string;
dimension16?: string;
dimension17?: string;
dimension18?: string;
dimension19?: string;
dimension20?: string;
/** Custom metrics */
metric1?: number;
metric2?: number;
metric3?: number;
metric4?: number;
metric5?: number;
metric6?: number;
metric7?: number;
metric8?: number;
metric9?: number;
metric10?: number;
metric11?: number;
metric12?: number;
metric13?: number;
metric14?: number;
metric15?: number;
metric16?: number;
metric17?: number;
metric18?: number;
metric19?: number;
metric20?: number;
}

export interface GaOptions {
name?: string;
clientId?: string;
sampleRate?: number;
siteSpeedSampleRate?: number;
alwaysSendReferrer?: boolean;
allowAnchor?: boolean;
cookieName?: string;
cookieDomain?: string;
cookieExpires?: number;
cookieUpdate?: boolean;
legacyCookieDomain?: string;
legacyHistoryImport?: boolean;
allowLinker?: boolean;
userId?: string;
storage?: string;
storeGac?: boolean;
cookieFlags?: string;
}

export interface InitializeOptions {
debug?: boolean;
gaAddress?: string;
testMode?: boolean;
titleCase?: boolean;
gaOptions?: GaOptions;
alwaysSendToDefaultTracker?: boolean;
standardImplementation?: boolean;
/** Optional. Defaults to `true`. Enables redacting a email as the string that in "Event Category" and "Event Action". */
redactEmail?: boolean;
useExistingGa?: boolean;
}

export type Tracker = {
trackingId: string;
} & InitializeOptions;

export type TrackerNames = string[];

export interface FieldsObject {
[i: string]: any;
}

export interface TimingArgs {
category: string;
variable: string;
value: number;
label?: string;
}

export interface Plugin {
require(name: string, options?: any, trackerName?: string): void;
execute(
pluginName: string,
action: string,
actionTypeOrPayload: string | any,
payload?: any
): void;
}

export interface TestModeAPI {
calls: any[][];
ga: (...args: any[]) => any;
resetCalls: Function;
}

export interface OutboundLinkArgs {
label: string;
}

export interface OutboundLinkProps {
eventLabel: string;
to: string;
target?: string;
onClick?: Function;
trackerNames?: TrackerNames;
}

export function initialize(
trackingCode: string,
options?: InitializeOptions
): void;
export function initialize(
trackers: Tracker[],
options?: InitializeOptions
): void;
export function addTrackers(trackingCode: string): void;
export function addTrackers(trackers: Tracker[]): void;
export function ga(): (...args: any[]) => void;
export function ga(...args: any[]): void;
export function resetCalls(): void;
export function set(
fieldsObject: FieldsObject,
trackerNames?: TrackerNames
): void;
export function send(
fieldsObject: FieldsObject,
trackerNames?: TrackerNames
): void;
export function pageview(
path: string,
trackerNames?: TrackerNames,
title?: string
): void;
export function modalview(name: string, trackerNames?: TrackerNames): void;
export function timing(args: TimingArgs, trackerNames?: TrackerNames): void;
export function event(args: EventArgs, trackerNames?: TrackerNames): void;
export function exception(
fieldsObject: FieldsObject,
trackerNames?: TrackerNames
): void;
export const plugin: Plugin;
export const testModeAPI: TestModeAPI;
export function outboundLink(
args: OutboundLinkArgs,
hitCallback: () => void,
trackerNames?: TrackerNames
): void;
export const OutboundLink: React.ComponentClass<
OutboundLinkProps & React.HTMLProps<HTMLAnchorElement>
>;

+ 168
- 0
node_modules/react-ga/types/react-ga-tests.ts View File

@@ -0,0 +1,168 @@
import * as ga from './index';

declare function describe(desc: string, f: () => void): void;
declare function it(desc: string, f: () => void): void;

describe('Testing react-ga initialize object', () => {
it('Able to initialize react-ga object', () => {
ga.initialize('UA-65432-1');
});
it('Able to initailize react-ga object', () => {
const options: ga.InitializeOptions = {
debug: true
};

ga.initialize('UA-65432-1', options);
});

it('Able to initialize multiple trackers', () => {
ga.initialize([
{ trackingId: 'abc', debug: true },
{ trackingId: 'efg', debug: true, gaOptions: { name: 'blah' } }
]);
});
});

describe('Testing react-ga pageview calls', () => {
it('Able to make pageview calls', () => {
ga.initialize('UA-65432-1');
ga.pageview('http://telshin.com');
});

it('Able to make pageview calls with multiple trackers', () => {
ga.initialize([
{ trackingId: 'abc', debug: true },
{ trackingId: 'efg', debug: true, gaOptions: { name: 'blah' } }
]);
ga.pageview('http://telshin.com', ['blah']);
});

it('Able to make pageview calls with custom title', () => {
ga.initialize('UA-65432-1');
ga.pageview('http://telshin.com', undefined, 'custom title');
});
});

describe('Testing react-ga modal calls', () => {
it('Able to make modal calls', () => {
ga.initialize('UA-65432-1');

ga.modalview('Test modal');
});
it('Able to make modal calls with multiple trackers', () => {
ga.initialize([
{ trackingId: 'abc', debug: true },
{ trackingId: 'efg', debug: true, gaOptions: { name: 'blah' } }
]);
ga.modalview('Test modal', ['blah']);
});
});

describe('Testing react-ga event calls', () => {
const options: ga.EventArgs = {
category: 'Test',
action: 'CI',
label: 'Running Jasmine tests for react-ga typscript library',
value: 4,
nonInteraction: true
};

it('Able to make event calls', () => {
ga.initialize('UA-65432-1');

ga.event(options);
});
it('Able to make event calls with multiple trackers', () => {
ga.initialize([
{ trackingId: 'abc', debug: true },
{ trackingId: 'efg', debug: true, gaOptions: { name: 'blah' } }
]);

ga.event(options, ['blah']);
});

it('Able to pass custom dimensions with events', () => {
const payloadWithDimensions: ga.EventArgs = {
dimension1: 'foo',
dimension20: 'bar',
...options
};
ga.initialize('UA-65432-1');

ga.event(payloadWithDimensions);
});

it('Able to pass custom metrics with events', () => {
const payloadWithmetrics: ga.EventArgs = {
metric1: 1,
metric20: 2.99,
...options
};
ga.initialize('UA-65432-1');

ga.event(payloadWithmetrics);
});
});

describe('Testing react-ga set calls', () => {
const fieldObject: ga.FieldsObject = {
page: '/users'
};

it('Able to make set calls', () => {
ga.initialize('UA-65432-1');

ga.set(fieldObject);
});
it('Able to make set calls with multiple trackers', () => {
ga.initialize([
{ trackingId: 'abc', debug: true },
{ trackingId: 'efg', debug: true, gaOptions: { name: 'blah' } }
]);

ga.set(fieldObject, ['blah']);
});
});

describe('Testing react-ga v2.1.2', () => {
it('Able to make ga calls', () => {
ga.ga();
});
it('Able to make send calls', () => {
let fieldObject: ga.FieldsObject = {
page: '/users'
};

ga.send(fieldObject, []);
});
it('Able to make timing calls', () => {
ga.timing(
{
category: 'string',
variable: 'string',
value: 1,
label: 'string'
},
[]
);
});
it('Able to make exception calls', () => {
let fieldObject: ga.FieldsObject = {
page: '/users'
};
ga.exception(fieldObject, []);
});
it('Able to make plugin object calls', () => {
const execute = ga.plugin.execute;
const require = ga.plugin.require;
const payload = {};

execute('name', 'action', payload);
execute('name', 'action', 'type', payload);
require('name', {});
require('name', {}, 'trackerName');
});
it('Able to make outboundLink calls', () => {
ga.outboundLink({ label: 'string' }, () => {}, []);
});
});

+ 17
- 0
node_modules/react-ga/types/tsconfig.json View File

@@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es6", "dom"],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"jsx": "react",
"typeRoots": ["../"],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": ["index.d.ts", "react-ga-tests.ts"]
}

+ 9
- 0
node_modules/react-ga/version-bower.js View File

@@ -0,0 +1,9 @@
// eslint-disable-next-line import/no-extraneous-dependencies
const fs = require('fs-extra');

const mainPackage = require('./package.json');
const bower = require('./bower.json');

bower.version = mainPackage.version;

fs.writeJsonSync('./bower.json', bower, { spaces: 2 });

+ 21
- 0
node_modules/react-is/LICENSE View File

@@ -0,0 +1,21 @@
MIT License

Copyright (c) Facebook, Inc. and its affiliates.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 104
- 0
node_modules/react-is/README.md View File

@@ -0,0 +1,104 @@
# `react-is`

This package allows you to test arbitrary values and see if they're a particular React element type.

## Installation

```sh
# Yarn
yarn add react-is

# NPM
npm install react-is
```

## Usage

### Determining if a Component is Valid

```js
import React from "react";
import * as ReactIs from "react-is";

class ClassComponent extends React.Component {
render() {
return React.createElement("div");
}
}

const FunctionComponent = () => React.createElement("div");

const ForwardRefComponent = React.forwardRef((props, ref) =>
React.createElement(Component, { forwardedRef: ref, ...props })
);

const Context = React.createContext(false);

ReactIs.isValidElementType("div"); // true
ReactIs.isValidElementType(ClassComponent); // true
ReactIs.isValidElementType(FunctionComponent); // true
ReactIs.isValidElementType(ForwardRefComponent); // true
ReactIs.isValidElementType(Context.Provider); // true
ReactIs.isValidElementType(Context.Consumer); // true
ReactIs.isValidElementType(React.createFactory("div")); // true
```

### Determining an Element's Type

#### Context

```js
import React from "react";
import * as ReactIs from 'react-is';

const ThemeContext = React.createContext("blue");

ReactIs.isContextConsumer(<ThemeContext.Consumer />); // true
ReactIs.isContextProvider(<ThemeContext.Provider />); // true
ReactIs.typeOf(<ThemeContext.Provider />) === ReactIs.ContextProvider; // true
ReactIs.typeOf(<ThemeContext.Consumer />) === ReactIs.ContextConsumer; // true
```

#### Element

```js
import React from "react";
import * as ReactIs from 'react-is';

ReactIs.isElement(<div />); // true
ReactIs.typeOf(<div />) === ReactIs.Element; // true
```

#### Fragment

```js
import React from "react";
import * as ReactIs from 'react-is';

ReactIs.isFragment(<></>); // true
ReactIs.typeOf(<></>) === ReactIs.Fragment; // true
```

#### Portal

```js
import React from "react";
import ReactDOM from "react-dom";
import * as ReactIs from 'react-is';

const div = document.createElement("div");
const portal = ReactDOM.createPortal(<div />, div);

ReactIs.isPortal(portal); // true
ReactIs.typeOf(portal) === ReactIs.Portal; // true
```

#### StrictMode

```js
import React from "react";
import * as ReactIs from 'react-is';

ReactIs.isStrictMode(<React.StrictMode />); // true
ReactIs.typeOf(<React.StrictMode />) === ReactIs.StrictMode; // true
```

+ 0
- 0
node_modules/react-is/build-info.json View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save