Update plausible
This commit is contained in:
parent
787450e064
commit
f7d069458f
6 changed files with 29 additions and 416 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
|
@ -7,6 +7,7 @@
|
||||||
"name": "portfolio",
|
"name": "portfolio",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@plausible-analytics/tracker": "^0.4.0",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
||||||
"css-loader": "^6.8.1",
|
"css-loader": "^6.8.1",
|
||||||
|
|
@ -809,6 +810,13 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@plausible-analytics/tracker": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@plausible-analytics/tracker/-/tracker-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-KXwttotIZymo3yGzargrsxl9hjXJo5N+Kips3ZMamYqJxJqv1Zx+POC6WOFxYwDe1iJW7T91ItQYD8mZsznpXQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@pnpm/network.ca-file": {
|
"node_modules/@pnpm/network.ca-file": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.1.tgz",
|
||||||
|
|
@ -11369,6 +11377,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@plausible-analytics/tracker": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@plausible-analytics/tracker/-/tracker-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-KXwttotIZymo3yGzargrsxl9hjXJo5N+Kips3ZMamYqJxJqv1Zx+POC6WOFxYwDe1iJW7T91ItQYD8mZsznpXQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@pnpm/network.ca-file": {
|
"@pnpm/network.ca-file": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
],
|
],
|
||||||
"homepage": "https://github.com/schmelczer/schmelczer.github.io#readme",
|
"homepage": "https://github.com/schmelczer/schmelczer.github.io#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@plausible-analytics/tracker": "^0.4.0",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
||||||
"css-loader": "^6.8.1",
|
"css-loader": "^6.8.1",
|
||||||
|
|
|
||||||
16
src/index.ts
16
src/index.ts
|
|
@ -8,6 +8,7 @@ import '../static/no-change/favicons/favicon.ico';
|
||||||
import '../static/no-change/favicons/site.webmanifest';
|
import '../static/no-change/favicons/site.webmanifest';
|
||||||
import '../static/no-change/og-image.jpg';
|
import '../static/no-change/og-image.jpg';
|
||||||
import '../static/no-change/robots.txt';
|
import '../static/no-change/robots.txt';
|
||||||
|
import { init as plausibleInit } from '@plausible-analytics/tracker'
|
||||||
import { portfolio } from './data/portfolio';
|
import { portfolio } from './data/portfolio';
|
||||||
import {
|
import {
|
||||||
addSupportForTabNavigation,
|
addSupportForTabNavigation,
|
||||||
|
|
@ -15,16 +16,17 @@ import {
|
||||||
} from './helper/accessibility';
|
} from './helper/accessibility';
|
||||||
import { scrollToFragment } from './helper/scroll-to-fragment';
|
import { scrollToFragment } from './helper/scroll-to-fragment';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
import Plausible from './plausible/tracker';
|
|
||||||
|
|
||||||
const plausible = Plausible({
|
plausibleInit({
|
||||||
hashMode: true,
|
domain: 'schmelczer.dev',
|
||||||
trackLocalhost: true,
|
endpoint: 'https://stats.schmelczer.dev/status',
|
||||||
apiURI: 'https://stats.schmelczer.dev/status',
|
autoCapturePageviews: true,
|
||||||
|
captureOnLocalhost: true,
|
||||||
|
logging: true,
|
||||||
|
fileDownloads: true,
|
||||||
|
hashBasedRouting: true
|
||||||
});
|
});
|
||||||
|
|
||||||
plausible.enableAutoPageviews();
|
|
||||||
plausible.enableAutoOutboundTracking();
|
|
||||||
|
|
||||||
addSupportForTabNavigation();
|
addSupportForTabNavigation();
|
||||||
removeUnnecessaryOutlines();
|
removeUnnecessaryOutlines();
|
||||||
|
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
import type { PlausibleOptions } from './tracker';
|
|
||||||
|
|
||||||
type EventPayload = {
|
|
||||||
readonly n: string;
|
|
||||||
readonly u: Location['href'];
|
|
||||||
readonly d: Location['hostname'];
|
|
||||||
readonly r: Document['referrer'] | null;
|
|
||||||
readonly w: Window['innerWidth'];
|
|
||||||
readonly h: 1 | 0;
|
|
||||||
readonly p?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type EventOptions = {
|
|
||||||
/**
|
|
||||||
* Callback called when the event is successfully sent.
|
|
||||||
*/
|
|
||||||
readonly callback?: () => void;
|
|
||||||
/**
|
|
||||||
* Properties to be bound to the event.
|
|
||||||
*/
|
|
||||||
readonly props?: { readonly [propName: string]: string };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* Sends an event to Plausible's API
|
|
||||||
*
|
|
||||||
* @param data - Event data to send
|
|
||||||
* @param options - Event options
|
|
||||||
*/
|
|
||||||
export function sendEvent(
|
|
||||||
eventName: string,
|
|
||||||
data: Required<PlausibleOptions>,
|
|
||||||
options?: EventOptions
|
|
||||||
): void {
|
|
||||||
const isLocalhost =
|
|
||||||
/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*:)*?:?0*1$/.test(
|
|
||||||
window.location.hostname
|
|
||||||
) || window.location.protocol === 'file:';
|
|
||||||
|
|
||||||
if (!data.trackLocalhost && isLocalhost) {
|
|
||||||
return console.warn('[Plausible] Ignoring event because website is running locally');
|
|
||||||
}
|
|
||||||
|
|
||||||
const shouldIgnoreCurrentBrowser = localStorage.getItem('plausible_ignore') === 'true';
|
|
||||||
if (shouldIgnoreCurrentBrowser) {
|
|
||||||
return console.warn(
|
|
||||||
'[Plausible] Ignoring event because "plausible_ignore" is set to "true" in localStorage'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const payload: EventPayload = {
|
|
||||||
n: eventName,
|
|
||||||
u: data.url,
|
|
||||||
d: data.domain,
|
|
||||||
r: data.referrer,
|
|
||||||
w: data.deviceWidth,
|
|
||||||
h: data.hashMode ? 1 : 0,
|
|
||||||
p: options && options.props ? JSON.stringify(options.props) : undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = new XMLHttpRequest();
|
|
||||||
req.open('POST', data.apiURI, true);
|
|
||||||
req.setRequestHeader('Content-Type', 'text/plain');
|
|
||||||
req.send(JSON.stringify(payload));
|
|
||||||
|
|
||||||
req.onreadystatechange = () => {
|
|
||||||
if (req.readyState !== 4) return;
|
|
||||||
if (options && options.callback) {
|
|
||||||
options.callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,334 +0,0 @@
|
||||||
import { EventOptions, sendEvent } from './request';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options used when initializing the tracker.
|
|
||||||
*/
|
|
||||||
export type PlausibleInitOptions = {
|
|
||||||
/**
|
|
||||||
* If true, pageviews will be tracked when the URL hash changes.
|
|
||||||
* Enable this if you are using a frontend that uses hash-based routing.
|
|
||||||
*/
|
|
||||||
readonly hashMode?: boolean;
|
|
||||||
/**
|
|
||||||
* Set to true if you want events to be tracked when running the site locally.
|
|
||||||
*/
|
|
||||||
readonly trackLocalhost?: boolean;
|
|
||||||
/**
|
|
||||||
* The domain to bind the event to.
|
|
||||||
* Defaults to `location.hostname`
|
|
||||||
*/
|
|
||||||
readonly domain?: Location['hostname'];
|
|
||||||
/**
|
|
||||||
* The API host where the events will be sent.
|
|
||||||
* Defaults to `'https://plausible.io/api/event'`
|
|
||||||
*/
|
|
||||||
readonly apiURI?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data passed to Plausible as events.
|
|
||||||
*/
|
|
||||||
export type PlausibleEventData = {
|
|
||||||
/**
|
|
||||||
* The URL to bind the event to.
|
|
||||||
* Defaults to `location.href`.
|
|
||||||
*/
|
|
||||||
readonly url?: Location['href'];
|
|
||||||
/**
|
|
||||||
* The referrer to bind the event to.
|
|
||||||
* Defaults to `document.referrer`
|
|
||||||
*/
|
|
||||||
readonly referrer?: Document['referrer'] | null;
|
|
||||||
/**
|
|
||||||
* The current device's width.
|
|
||||||
* Defaults to `window.innerWidth`
|
|
||||||
*/
|
|
||||||
readonly deviceWidth?: Window['innerWidth'];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options used when tracking Plausible events.
|
|
||||||
*/
|
|
||||||
export type PlausibleOptions = PlausibleInitOptions & PlausibleEventData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks a custom event.
|
|
||||||
*
|
|
||||||
* Use it to track your defined goals by providing the goal's name as `eventName`.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
* ```js
|
|
||||||
* import Plausible from 'plausible-tracker'
|
|
||||||
*
|
|
||||||
* const { trackEvent } = Plausible()
|
|
||||||
*
|
|
||||||
* // Tracks the 'signup' goal
|
|
||||||
* trackEvent('signup')
|
|
||||||
*
|
|
||||||
* // Tracks the 'Download' goal passing a 'method' property.
|
|
||||||
* trackEvent('Download', { props: { method: 'HTTP' } })
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @param eventName - Name of the event to track
|
|
||||||
* @param options - Event options.
|
|
||||||
* @param eventData - Optional event data to send. Defaults to the current page's data merged with the default options provided earlier.
|
|
||||||
*/
|
|
||||||
type TrackEvent = (
|
|
||||||
eventName: string,
|
|
||||||
options?: EventOptions,
|
|
||||||
eventData?: PlausibleOptions
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually tracks a page view.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
* ```js
|
|
||||||
* import Plausible from 'plausible-tracker'
|
|
||||||
*
|
|
||||||
* const { trackPageview } = Plausible()
|
|
||||||
*
|
|
||||||
* // Track a page view
|
|
||||||
* trackPageview()
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @param eventData - Optional event data to send. Defaults to the current page's data merged with the default options provided earlier.
|
|
||||||
* @param options - Event options.
|
|
||||||
*/
|
|
||||||
type TrackPageview = (eventData?: PlausibleOptions, options?: EventOptions) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleans up all event listeners attached.
|
|
||||||
*/
|
|
||||||
type Cleanup = () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks the current page and all further pages automatically.
|
|
||||||
*
|
|
||||||
* Call this if you don't want to manually manage pageview tracking.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
* ```js
|
|
||||||
* import Plausible from 'plausible-tracker'
|
|
||||||
*
|
|
||||||
* const { enableAutoPageviews } = Plausible()
|
|
||||||
*
|
|
||||||
* // This tracks the current page view and all future ones as well
|
|
||||||
* enableAutoPageviews()
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* The returned value is a callback that removes the added event listeners and restores `history.pushState`
|
|
||||||
* ```js
|
|
||||||
* import Plausible from 'plausible-tracker'
|
|
||||||
*
|
|
||||||
* const { enableAutoPageviews } = Plausible()
|
|
||||||
*
|
|
||||||
* const cleanup = enableAutoPageviews()
|
|
||||||
*
|
|
||||||
* // Remove event listeners and restore `history.pushState`
|
|
||||||
* cleanup()
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
type EnableAutoPageviews = () => Cleanup;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks all outbound link clicks automatically
|
|
||||||
*
|
|
||||||
* Call this if you don't want to manually manage these links.
|
|
||||||
*
|
|
||||||
* It works using a **[MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)** to automagically detect link nodes throughout your application and bind `click` events to them.
|
|
||||||
*
|
|
||||||
* Optionally takes the same parameters as [`MutationObserver.observe`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe).
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
* ```js
|
|
||||||
* import Plausible from 'plausible-tracker'
|
|
||||||
*
|
|
||||||
* const { enableAutoOutboundTracking } = Plausible()
|
|
||||||
*
|
|
||||||
* // This tracks all the existing and future outbound links on your page.
|
|
||||||
* enableAutoOutboundTracking()
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* The returned value is a callback that removes the added event listeners and disconnects the observer
|
|
||||||
* ```js
|
|
||||||
* import Plausible from 'plausible-tracker'
|
|
||||||
*
|
|
||||||
* const { enableAutoOutboundTracking } = Plausible()
|
|
||||||
*
|
|
||||||
* const cleanup = enableAutoOutboundTracking()
|
|
||||||
*
|
|
||||||
* // Remove event listeners and disconnect the observer
|
|
||||||
* cleanup()
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
type EnableAutoOutboundTracking = (
|
|
||||||
targetNode?: Node & ParentNode,
|
|
||||||
observerInit?: MutationObserverInit
|
|
||||||
) => Cleanup;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the tracker with your default values.
|
|
||||||
*
|
|
||||||
* ### Example (es module)
|
|
||||||
* ```js
|
|
||||||
* import Plausible from 'plausible-tracker'
|
|
||||||
*
|
|
||||||
* const { enableAutoPageviews, trackEvent } = Plausible({
|
|
||||||
* domain: 'my-app-domain.com',
|
|
||||||
* hashMode: true
|
|
||||||
* })
|
|
||||||
*
|
|
||||||
* enableAutoPageviews()
|
|
||||||
*
|
|
||||||
* function onUserRegister() {
|
|
||||||
* trackEvent('register')
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ### Example (commonjs)
|
|
||||||
* ```js
|
|
||||||
* var Plausible = require('plausible-tracker');
|
|
||||||
*
|
|
||||||
* var { enableAutoPageviews, trackEvent } = Plausible({
|
|
||||||
* domain: 'my-app-domain.com',
|
|
||||||
* hashMode: true
|
|
||||||
* })
|
|
||||||
*
|
|
||||||
* enableAutoPageviews()
|
|
||||||
*
|
|
||||||
* function onUserRegister() {
|
|
||||||
* trackEvent('register')
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @param defaults - Default event parameters that will be applied to all requests.
|
|
||||||
*/
|
|
||||||
export default function Plausible(defaults?: PlausibleInitOptions): {
|
|
||||||
readonly trackEvent: TrackEvent;
|
|
||||||
readonly trackPageview: TrackPageview;
|
|
||||||
readonly enableAutoPageviews: EnableAutoPageviews;
|
|
||||||
readonly enableAutoOutboundTracking: EnableAutoOutboundTracking;
|
|
||||||
} {
|
|
||||||
const getConfig = (): Required<PlausibleOptions> => ({
|
|
||||||
hashMode: false,
|
|
||||||
trackLocalhost: false,
|
|
||||||
url: window.location.href,
|
|
||||||
domain: window.location.hostname,
|
|
||||||
referrer: document.referrer || null,
|
|
||||||
deviceWidth: window.innerWidth,
|
|
||||||
apiURI: 'https://plausible.io/api/event/',
|
|
||||||
...defaults,
|
|
||||||
});
|
|
||||||
|
|
||||||
const trackEvent: TrackEvent = (eventName, options, eventData) => {
|
|
||||||
sendEvent(eventName, { ...getConfig(), ...eventData }, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
const trackPageview: TrackPageview = (eventData, options) => {
|
|
||||||
trackEvent('pageview', options, eventData);
|
|
||||||
};
|
|
||||||
|
|
||||||
const enableAutoPageviews: EnableAutoPageviews = () => {
|
|
||||||
const page = () => trackPageview();
|
|
||||||
// Attach pushState and popState listeners
|
|
||||||
const originalPushState = window.history.pushState;
|
|
||||||
if (originalPushState) {
|
|
||||||
window.history.pushState = function (data, title, url) {
|
|
||||||
originalPushState.apply(this, [data, title, url]);
|
|
||||||
page();
|
|
||||||
};
|
|
||||||
window.addEventListener('popstate', page);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach hashchange listener
|
|
||||||
if (defaults && defaults.hashMode) {
|
|
||||||
window.addEventListener('hashchange', page);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger first page view
|
|
||||||
trackPageview();
|
|
||||||
|
|
||||||
return function cleanup() {
|
|
||||||
if (originalPushState) {
|
|
||||||
window.history.pushState = originalPushState;
|
|
||||||
window.removeEventListener('popstate', page);
|
|
||||||
}
|
|
||||||
if (defaults && defaults.hashMode) {
|
|
||||||
window.removeEventListener('hashchange', page);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const enableAutoOutboundTracking: EnableAutoOutboundTracking = (
|
|
||||||
targetNode: Node & ParentNode = document,
|
|
||||||
observerInit: MutationObserverInit = {
|
|
||||||
subtree: true,
|
|
||||||
childList: true,
|
|
||||||
attributes: true,
|
|
||||||
attributeFilter: ['href'],
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
function trackClick(this: HTMLAnchorElement, _event: MouseEvent) {
|
|
||||||
trackEvent('Outbound Link: Click', { props: { url: this.href } });
|
|
||||||
}
|
|
||||||
|
|
||||||
const tracked: Set<HTMLAnchorElement> = new Set();
|
|
||||||
|
|
||||||
function addNode(node: Node | ParentNode) {
|
|
||||||
if (node instanceof HTMLAnchorElement) {
|
|
||||||
if (node.host !== window.location.host) {
|
|
||||||
node.addEventListener('click', trackClick);
|
|
||||||
tracked.add(node);
|
|
||||||
}
|
|
||||||
} /* istanbul ignore next */ else if ('querySelectorAll' in node) {
|
|
||||||
node.querySelectorAll('a').forEach(addNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeNode(node: Node | ParentNode) {
|
|
||||||
if (node instanceof HTMLAnchorElement) {
|
|
||||||
node.removeEventListener('click', trackClick);
|
|
||||||
tracked.delete(node);
|
|
||||||
} /* istanbul ignore next */ else if ('querySelectorAll' in node) {
|
|
||||||
node.querySelectorAll('a').forEach(removeNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
|
||||||
mutations.forEach((mutation) => {
|
|
||||||
if (mutation.type === 'attributes') {
|
|
||||||
// Handle changed href
|
|
||||||
removeNode(mutation.target);
|
|
||||||
addNode(mutation.target);
|
|
||||||
} /* istanbul ignore next */ else if (mutation.type === 'childList') {
|
|
||||||
// Handle added nodes
|
|
||||||
mutation.addedNodes.forEach(addNode);
|
|
||||||
// Handle removed nodes
|
|
||||||
mutation.removedNodes.forEach(removeNode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Track existing nodes
|
|
||||||
targetNode.querySelectorAll('a').forEach(addNode);
|
|
||||||
|
|
||||||
// Observe mutations
|
|
||||||
observer.observe(targetNode, observerInit);
|
|
||||||
|
|
||||||
return function cleanup() {
|
|
||||||
tracked.forEach((a) => {
|
|
||||||
a.removeEventListener('click', trackClick);
|
|
||||||
});
|
|
||||||
tracked.clear();
|
|
||||||
observer.disconnect();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
trackEvent,
|
|
||||||
trackPageview,
|
|
||||||
enableAutoPageviews,
|
|
||||||
enableAutoOutboundTracking,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -5,8 +5,11 @@
|
||||||
"module": "es6",
|
"module": "es6",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"lib": ["dom"]
|
"lib": [
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue