@reykjavik/webtools 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/CookieHubConsent.d.ts +2 -2
- package/CookieHubConsent.js +2 -2
- package/README.md +195 -235
- package/esm/CookieHubConsent.d.ts +2 -2
- package/esm/CookieHubConsent.js +2 -2
- package/esm/fixIcelandicLocale.d.ts +1 -0
- package/esm/fixIcelandicLocale.js +21 -0
- package/esm/http.d.ts +3 -3
- package/esm/http.js +2 -2
- package/esm/index.d.ts +2 -0
- package/esm/next/SiteImprove.d.ts +4 -94
- package/esm/next/SiteImprove.js +12 -93
- package/esm/next/SiteImprove.privates.d.ts +100 -0
- package/esm/next/SiteImprove.privates.js +83 -0
- package/esm/next/http.d.ts +2 -2
- package/esm/next/http.js +3 -3
- package/esm/vanillaExtract.d.ts +46 -0
- package/esm/vanillaExtract.js +45 -0
- package/fixIcelandicLocale.d.ts +2 -0
- package/fixIcelandicLocale.js +21 -0
- package/http.d.ts +3 -3
- package/http.js +2 -2
- package/index.d.ts +2 -0
- package/next/SiteImprove.d.ts +4 -94
- package/next/SiteImprove.js +15 -96
- package/next/SiteImprove.privates.d.ts +100 -0
- package/next/SiteImprove.privates.js +91 -0
- package/next/http.d.ts +2 -2
- package/next/http.js +3 -3
- package/package.json +24 -1
- package/vanillaExtract.d.ts +46 -0
- package/vanillaExtract.js +53 -0
|
@@ -1,101 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
_sz?: Array<SiteImproveEvent> & {
|
|
6
|
-
/**
|
|
7
|
-
* Set if posting a tracking event is attempted before SiteImprove has
|
|
8
|
-
* been initialized, and the window._sz array had to be initialized
|
|
9
|
-
* just-in-time.
|
|
10
|
-
*/
|
|
11
|
-
_jit_defined_?: true;
|
|
12
|
-
core?: {
|
|
13
|
-
data: Array<SiteImproveEvent>;
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
type SiteImproveEvent = SiteImprovePageView | SiteImproveRequest | SiteImproveCustomEvent;
|
|
19
|
-
type SiteImprovePageView = [
|
|
20
|
-
type: 'trackdynamic',
|
|
21
|
-
data: {
|
|
22
|
-
/** New page URL */
|
|
23
|
-
url: string;
|
|
24
|
-
/** The previous (referer) URL */
|
|
25
|
-
ref?: string;
|
|
26
|
-
/** New page title */
|
|
27
|
-
title?: string;
|
|
28
|
-
}
|
|
29
|
-
];
|
|
30
|
-
type SiteImproveRequest = [
|
|
31
|
-
type: 'request',
|
|
32
|
-
data: {
|
|
33
|
-
/** Outbound URL */
|
|
34
|
-
ourl: string;
|
|
35
|
-
/** The current page URL */
|
|
36
|
-
ref: string;
|
|
37
|
-
autoonclick?: 1;
|
|
38
|
-
}
|
|
39
|
-
];
|
|
40
|
-
type SiteImproveCustomEvent = [
|
|
41
|
-
type: 'event',
|
|
42
|
-
category: string,
|
|
43
|
-
action: string,
|
|
44
|
-
label?: string
|
|
45
|
-
];
|
|
46
|
-
/**
|
|
47
|
-
* A small helper for tracking custom UI events and reporting them to SiteImrove.
|
|
48
|
-
*
|
|
49
|
-
* @see https://github.com/reykjavikcity/webtools/tree/v0.1##pingsiteimprove-helper
|
|
50
|
-
*/
|
|
51
|
-
export declare const pingSiteImprove: (category: string, action: string, label?: string) => void;
|
|
52
|
-
/**
|
|
53
|
-
* A small helper for reporting to SiteImrove when the user is programmatically
|
|
54
|
-
* being sent to a different URL/resource.
|
|
55
|
-
*
|
|
56
|
-
* @see https://github.com/reykjavikcity/webtools/tree/v0.1##pingsiteimproveoutbound-helper
|
|
57
|
-
*/
|
|
58
|
-
export declare const pingSiteImproveOutbound: (ourl: string) => void;
|
|
59
|
-
export type SiteImproveProps = EitherObj<{
|
|
60
|
-
/**
|
|
61
|
-
* Your SiteImprove account ID.
|
|
62
|
-
*
|
|
63
|
-
* It's a random-looking numerical string, and it can usually be
|
|
64
|
-
* extracted from the script embed URL like this:
|
|
65
|
-
* `"https://siteimproveanalytics.com/js/siteanalyze_[ACCOUNT_ID].js"`
|
|
66
|
-
*/
|
|
67
|
-
accountId: string;
|
|
68
|
-
}, {
|
|
69
|
-
/**
|
|
70
|
-
* The full SiteImprove analytics script URL.
|
|
71
|
-
*
|
|
72
|
-
* Something like `"https://siteimproveanalytics.com/js/siteanalyze_[ACCOUNT_ID].js"`
|
|
73
|
-
*/
|
|
74
|
-
scriptUrl: string;
|
|
75
|
-
}> & {
|
|
76
|
-
/**
|
|
77
|
-
* Manual GDPR 'analytics' consent flag.
|
|
78
|
-
*
|
|
79
|
-
* A value of `false` prevents the analytics script being loaded.
|
|
80
|
-
*
|
|
81
|
-
* A value of `true` still defers to the 'analytics' consent state provided
|
|
82
|
-
* by the `CookieHubProvider` component (if present).
|
|
83
|
-
*/
|
|
84
|
-
hasConstented?: boolean;
|
|
85
|
-
/**
|
|
86
|
-
* Custom callback for when the SiteImprove script has loaded.
|
|
87
|
-
*/
|
|
88
|
-
onLoad?: (e: unknown) => void;
|
|
89
|
-
/**
|
|
90
|
-
* Error callback for if the SiteImprove script fails to load.
|
|
91
|
-
*/
|
|
92
|
-
onError?: (e: unknown) => void;
|
|
93
|
-
};
|
|
2
|
+
import { SiteImproveProps } from './SiteImprove.privates.js';
|
|
3
|
+
export type { SiteImproveProps } from './SiteImprove.privates.js';
|
|
4
|
+
export { pingSiteImprove, pingSiteImproveOutbound } from './SiteImprove.privates.js';
|
|
94
5
|
/**
|
|
95
6
|
* A component for loading a SiteImprove analytics script and set up page-view
|
|
96
7
|
* tracking across Next.js routes.
|
|
97
8
|
*
|
|
98
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
9
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#siteimprove-component
|
|
99
10
|
*/
|
|
100
11
|
export declare const SiteImprove: (props: SiteImproveProps) => React.JSX.Element | null;
|
|
101
|
-
export {};
|
package/esm/next/SiteImprove.js
CHANGED
|
@@ -2,56 +2,13 @@ import React, { useEffect } from 'react';
|
|
|
2
2
|
import { Router } from 'next/router.js';
|
|
3
3
|
import NextScript from 'next/script.js';
|
|
4
4
|
import { useCookieHubConsent } from '../CookieHubConsent.js';
|
|
5
|
+
import { logOutboundLinks, makeScriptUrl, trackDynamicPageView, } from './SiteImprove.privates.js';
|
|
5
6
|
// Fixes an issue with `next/script`'s types and mixture of default and named exports.
|
|
6
7
|
// This workaround doesn't seem to be necessary in Next.js 13.5 (pages router), but
|
|
7
8
|
// is definitely needed for the webpack bundler used by Next.js 11. (v12 is untested.)
|
|
8
9
|
const Script = ('__esModule' in NextScript && 'default' in NextScript
|
|
9
10
|
? NextScript.default
|
|
10
11
|
: NextScript);
|
|
11
|
-
// END: Mock typing of SiteImprove's event tracking API
|
|
12
|
-
// --------------------------------------------------------------------------
|
|
13
|
-
//
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
const _emitEvent = typeof window === 'undefined'
|
|
16
|
-
? () => undefined
|
|
17
|
-
: (event) => {
|
|
18
|
-
let _sz = window._sz;
|
|
19
|
-
if (!_sz) {
|
|
20
|
-
_sz = window._sz = [];
|
|
21
|
-
_sz._jit_defined_ = true;
|
|
22
|
-
}
|
|
23
|
-
_sz.push(event);
|
|
24
|
-
if (process.env.NODE_ENV === 'development') {
|
|
25
|
-
console.info('SiteImprove:', event);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
/**
|
|
30
|
-
* A small helper for tracking custom UI events and reporting them to SiteImrove.
|
|
31
|
-
*
|
|
32
|
-
* @see https://github.com/reykjavikcity/webtools/tree/v0.1##pingsiteimprove-helper
|
|
33
|
-
*/
|
|
34
|
-
export const pingSiteImprove = (category, action, label) => {
|
|
35
|
-
if (process.env.NODE_ENV === 'development' &&
|
|
36
|
-
(!window._sz || window._sz._jit_defined_)) {
|
|
37
|
-
console.warn('`pingSiteImprove` was called before SiteImprove script was loaded.');
|
|
38
|
-
}
|
|
39
|
-
_emitEvent(['event', category, action, label]);
|
|
40
|
-
};
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
/**
|
|
43
|
-
* A small helper for reporting to SiteImrove when the user is programmatically
|
|
44
|
-
* being sent to a different URL/resource.
|
|
45
|
-
*
|
|
46
|
-
* @see https://github.com/reykjavikcity/webtools/tree/v0.1##pingsiteimproveoutbound-helper
|
|
47
|
-
*/
|
|
48
|
-
export const pingSiteImproveOutbound = (ourl) => {
|
|
49
|
-
if (process.env.NODE_ENV === 'development' &&
|
|
50
|
-
(!window._sz || window._sz._jit_defined_)) {
|
|
51
|
-
console.warn('`pingSiteImproveOutbound` was called before SiteImprove script was loaded.');
|
|
52
|
-
}
|
|
53
|
-
_emitEvent(['request', { ourl, ref: document.location.href }]);
|
|
54
|
-
};
|
|
55
12
|
// ---------------------------------------------------------------------------
|
|
56
13
|
/*
|
|
57
14
|
SiteImprove's "trackdynamic" (page view) event requires both the new URL
|
|
@@ -64,59 +21,23 @@ export const pingSiteImproveOutbound = (ourl) => {
|
|
|
64
21
|
and it is thus safe to simply store the old URL in a local variable.
|
|
65
22
|
This may look dodgy, but should prove reasonably safe in practice.
|
|
66
23
|
*/
|
|
67
|
-
let
|
|
24
|
+
let _refUrl = '';
|
|
68
25
|
const captureRefUrl = () => {
|
|
69
|
-
|
|
26
|
+
_refUrl = document.location.pathname + document.location.search;
|
|
70
27
|
};
|
|
71
|
-
const sendRoutingEvent = (url) =>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// in that case we suppress the `ref`
|
|
78
|
-
ref: refUrl !== url ? refUrl : undefined,
|
|
79
|
-
title: document.title,
|
|
80
|
-
},
|
|
81
|
-
]);
|
|
82
|
-
// ---------------------------------------------------------------------------
|
|
83
|
-
const logOutboundLinks = () => {
|
|
84
|
-
const captureLinkClicks = (e) => {
|
|
85
|
-
const link = e.target.closest('a[href]');
|
|
86
|
-
if (!link || link.$$bound) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
link.$$bound = true;
|
|
90
|
-
// Waiting for the bubble phase allows other click handlers to preventDefault()
|
|
91
|
-
link.addEventListener('click', (e) => {
|
|
92
|
-
var _a, _b;
|
|
93
|
-
if (e.defaultPrevented) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
// Skip logging outbound request if SiteImprove has already done so.
|
|
97
|
-
// BTW, SiteImprove binds its autoonclick handlers on "mousedown"
|
|
98
|
-
// so they're guaranteed to have run before our "click" listener.
|
|
99
|
-
const events = (_b = (_a = window._sz) === null || _a === void 0 ? void 0 : _a.core) === null || _b === void 0 ? void 0 : _b.data;
|
|
100
|
-
const [type, data] = (events && events[events.length - 1]) || [];
|
|
101
|
-
if (type === 'request' && data.autoonclick && data.ourl === link.href) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
pingSiteImproveOutbound(link.href);
|
|
105
|
-
});
|
|
106
|
-
};
|
|
107
|
-
const { body } = document;
|
|
108
|
-
// bind 'click' listener to the capture phase
|
|
109
|
-
body.addEventListener('click', captureLinkClicks, true);
|
|
110
|
-
return () => body.removeEventListener('click', captureLinkClicks, true);
|
|
28
|
+
const sendRoutingEvent = (url) => {
|
|
29
|
+
// On `history.back()`/`history.forward()` the URL change happens before
|
|
30
|
+
// `routeChangeStart`, so `refUrl` and `url` become the same.
|
|
31
|
+
// in that case we suppress the `ref`
|
|
32
|
+
const refUrl = _refUrl !== url ? _refUrl : undefined;
|
|
33
|
+
trackDynamicPageView(url, refUrl, document.title);
|
|
111
34
|
};
|
|
112
|
-
|
|
113
|
-
const idToken = '[ACCOUNT_ID]';
|
|
114
|
-
const scriptUrlTemplate = `https://siteimproveanalytics.com/js/siteanalyze_${idToken}.js`;
|
|
35
|
+
export { pingSiteImprove, pingSiteImproveOutbound } from './SiteImprove.privates.js';
|
|
115
36
|
/**
|
|
116
37
|
* A component for loading a SiteImprove analytics script and set up page-view
|
|
117
38
|
* tracking across Next.js routes.
|
|
118
39
|
*
|
|
119
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
40
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#siteimprove-component
|
|
120
41
|
*/
|
|
121
42
|
export const SiteImprove = (props) => {
|
|
122
43
|
const { analytics } = useCookieHubConsent();
|
|
@@ -149,8 +70,6 @@ export const SiteImprove = (props) => {
|
|
|
149
70
|
if (!consented || process.env.NODE_ENV !== 'production') {
|
|
150
71
|
return null;
|
|
151
72
|
}
|
|
152
|
-
const scriptUrl = props.scriptUrl != null
|
|
153
|
-
? props.scriptUrl
|
|
154
|
-
: scriptUrlTemplate.replace(idToken, props.accountId);
|
|
73
|
+
const scriptUrl = props.scriptUrl != null ? props.scriptUrl : makeScriptUrl(props.accountId);
|
|
155
74
|
return (React.createElement(Script, { type: "text/javascript", strategy: "afterInteractive", src: scriptUrl, onLoad: props.onLoad, onError: props.onError }));
|
|
156
75
|
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { EitherObj } from '@reykjavik/hanna-utils';
|
|
2
|
+
declare global {
|
|
3
|
+
interface Window {
|
|
4
|
+
_sz?: Array<SiteImproveEvent> & {
|
|
5
|
+
/**
|
|
6
|
+
* Set if posting a tracking event is attempted before SiteImprove has
|
|
7
|
+
* been initialized, and the window._sz array had to be initialized
|
|
8
|
+
* just-in-time.
|
|
9
|
+
*/
|
|
10
|
+
_jit_defined_?: true;
|
|
11
|
+
core?: {
|
|
12
|
+
data: Array<SiteImproveEvent>;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export type SiteImproveEvent = SiteImprovePageView | SiteImproveRequest | SiteImproveCustomEvent;
|
|
18
|
+
export type SiteImprovePageView = [
|
|
19
|
+
type: 'trackdynamic',
|
|
20
|
+
data: {
|
|
21
|
+
/** New page URL */
|
|
22
|
+
url: string;
|
|
23
|
+
/** The previous (referer) URL */
|
|
24
|
+
ref?: string;
|
|
25
|
+
/** New page title */
|
|
26
|
+
title?: string;
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
export type SiteImproveRequest = [
|
|
30
|
+
type: 'request',
|
|
31
|
+
data: {
|
|
32
|
+
/** Outbound URL */
|
|
33
|
+
ourl: string;
|
|
34
|
+
/** The current page URL */
|
|
35
|
+
ref: string;
|
|
36
|
+
autoonclick?: 1;
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
export type SiteImproveCustomEvent = [
|
|
40
|
+
type: 'event',
|
|
41
|
+
category: string,
|
|
42
|
+
action: string,
|
|
43
|
+
label?: string
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* A small helper to send "trackdynamic" page view/load events to SiteImrove.
|
|
47
|
+
*
|
|
48
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#pingsiteimprove-helper
|
|
49
|
+
*/
|
|
50
|
+
export declare const trackDynamicPageView: (url: string, refUrl?: string, title?: string) => void;
|
|
51
|
+
/**
|
|
52
|
+
* A small helper for tracking custom UI events and reporting them to SiteImrove.
|
|
53
|
+
*
|
|
54
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#pingsiteimprove-helper
|
|
55
|
+
*/
|
|
56
|
+
export declare const pingSiteImprove: (category: string, action: string, label?: string) => void;
|
|
57
|
+
/**
|
|
58
|
+
* A small helper for reporting to SiteImrove when the user is programmatically
|
|
59
|
+
* being sent to a different URL/resource.
|
|
60
|
+
*
|
|
61
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#pingsiteimproveoutbound-helper
|
|
62
|
+
*/
|
|
63
|
+
export declare const pingSiteImproveOutbound: (ourl: string) => void;
|
|
64
|
+
export declare const logOutboundLinks: () => () => void;
|
|
65
|
+
export declare const makeScriptUrl: (accountId: string) => string;
|
|
66
|
+
export type SiteImproveProps = EitherObj<{
|
|
67
|
+
/**
|
|
68
|
+
* Your SiteImprove account ID.
|
|
69
|
+
*
|
|
70
|
+
* It's a random-looking numerical string, and it can usually be
|
|
71
|
+
* extracted from the script embed URL like this:
|
|
72
|
+
* `"https://siteimproveanalytics.com/js/siteanalyze_[ACCOUNT_ID].js"`
|
|
73
|
+
*/
|
|
74
|
+
accountId: string;
|
|
75
|
+
}, {
|
|
76
|
+
/**
|
|
77
|
+
* The full SiteImprove analytics script URL.
|
|
78
|
+
*
|
|
79
|
+
* Something like `"https://siteimproveanalytics.com/js/siteanalyze_[ACCOUNT_ID].js"`
|
|
80
|
+
*/
|
|
81
|
+
scriptUrl: string;
|
|
82
|
+
}> & {
|
|
83
|
+
/**
|
|
84
|
+
* Manual GDPR 'analytics' consent flag.
|
|
85
|
+
*
|
|
86
|
+
* A value of `false` prevents the analytics script being loaded.
|
|
87
|
+
*
|
|
88
|
+
* A value of `true` still defers to the 'analytics' consent state provided
|
|
89
|
+
* by the `CookieHubProvider` component (if present).
|
|
90
|
+
*/
|
|
91
|
+
hasConstented?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Custom callback for when the SiteImprove script has loaded.
|
|
94
|
+
*/
|
|
95
|
+
onLoad?: (e: unknown) => void;
|
|
96
|
+
/**
|
|
97
|
+
* Error callback for if the SiteImprove script fails to load.
|
|
98
|
+
*/
|
|
99
|
+
onError?: (e: unknown) => void;
|
|
100
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// END: Mock typing of SiteImprove's event tracking API
|
|
2
|
+
// --------------------------------------------------------------------------
|
|
3
|
+
//
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
const _emitEvent = typeof window === 'undefined'
|
|
6
|
+
? () => undefined
|
|
7
|
+
: (event) => {
|
|
8
|
+
let _sz = window._sz;
|
|
9
|
+
if (!_sz) {
|
|
10
|
+
_sz = window._sz = [];
|
|
11
|
+
_sz._jit_defined_ = true;
|
|
12
|
+
}
|
|
13
|
+
_sz.push(event);
|
|
14
|
+
if (process.env.NODE_ENV === 'development') {
|
|
15
|
+
console.info('SiteImprove:', event);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/**
|
|
20
|
+
* A small helper to send "trackdynamic" page view/load events to SiteImrove.
|
|
21
|
+
*
|
|
22
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#pingsiteimprove-helper
|
|
23
|
+
*/
|
|
24
|
+
export const trackDynamicPageView = (url, refUrl, title) => _emitEvent(['trackdynamic', { url, ref: refUrl, title }]);
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* A small helper for tracking custom UI events and reporting them to SiteImrove.
|
|
28
|
+
*
|
|
29
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#pingsiteimprove-helper
|
|
30
|
+
*/
|
|
31
|
+
export const pingSiteImprove = (category, action, label) => {
|
|
32
|
+
if (process.env.NODE_ENV === 'development' &&
|
|
33
|
+
(!window._sz || window._sz._jit_defined_)) {
|
|
34
|
+
console.warn('`pingSiteImprove` was called before SiteImprove script was loaded.');
|
|
35
|
+
}
|
|
36
|
+
_emitEvent(['event', category, action, label]);
|
|
37
|
+
};
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* A small helper for reporting to SiteImrove when the user is programmatically
|
|
41
|
+
* being sent to a different URL/resource.
|
|
42
|
+
*
|
|
43
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#pingsiteimproveoutbound-helper
|
|
44
|
+
*/
|
|
45
|
+
export const pingSiteImproveOutbound = (ourl) => {
|
|
46
|
+
if (process.env.NODE_ENV === 'development' &&
|
|
47
|
+
(!window._sz || window._sz._jit_defined_)) {
|
|
48
|
+
console.warn('`pingSiteImproveOutbound` was called before SiteImprove script was loaded.');
|
|
49
|
+
}
|
|
50
|
+
_emitEvent(['request', { ourl, ref: document.location.href }]);
|
|
51
|
+
};
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
export const logOutboundLinks = () => {
|
|
54
|
+
const captureLinkClicks = (e) => {
|
|
55
|
+
const link = e.target.closest('a[href]');
|
|
56
|
+
if (!link || link.$$bound) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
link.$$bound = true;
|
|
60
|
+
// Waiting for the bubble phase allows other click handlers to preventDefault()
|
|
61
|
+
link.addEventListener('click', (e) => {
|
|
62
|
+
var _a, _b;
|
|
63
|
+
if (e.defaultPrevented) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Skip logging outbound request if SiteImprove has already done so.
|
|
67
|
+
// BTW, SiteImprove binds its autoonclick handlers on "mousedown"
|
|
68
|
+
// so they're guaranteed to have run before our "click" listener.
|
|
69
|
+
const events = (_b = (_a = window._sz) === null || _a === void 0 ? void 0 : _a.core) === null || _b === void 0 ? void 0 : _b.data;
|
|
70
|
+
const [type, data] = (events && events[events.length - 1]) || [];
|
|
71
|
+
if (type === 'request' && data.autoonclick && data.ourl === link.href) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
pingSiteImproveOutbound(link.href);
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
const { body } = document;
|
|
78
|
+
// bind 'click' listener to the capture phase
|
|
79
|
+
body.addEventListener('click', captureLinkClicks, true);
|
|
80
|
+
return () => body.removeEventListener('click', captureLinkClicks, true);
|
|
81
|
+
};
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
export const makeScriptUrl = (accountId) => `https://siteimproveanalytics.com/js/siteanalyze_${accountId}.js`;
|
package/esm/next/http.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export type InferErrorPageProps<SEP extends ShowErrorPageFn<any>> = Cleanup<Retu
|
|
|
26
26
|
* cases when `getServerSideProps` returns an `__error` prop with `statusCode`
|
|
27
27
|
* and optional friendly `message`.
|
|
28
28
|
*
|
|
29
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
29
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#makeerrorizeapphoc
|
|
30
30
|
*/
|
|
31
31
|
export declare const makeErrorizeAppHOC: <EP extends Partial<ErrorProps>>(ErrorPage: React.FunctionComponent<EP>) => {
|
|
32
32
|
<P extends {
|
|
@@ -48,7 +48,7 @@ export declare const makeErrorizeAppHOC: <EP extends Partial<ErrorProps>>(ErrorP
|
|
|
48
48
|
* to return an `HTTP_304_NotModified` response with an empty props object,
|
|
49
49
|
* in a way that doesn't make TypeScript shout at you.
|
|
50
50
|
*
|
|
51
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
51
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#notmodified304-helper
|
|
52
52
|
*/
|
|
53
53
|
export declare const notModified304: (response: ServerResponse | NextContextLike) => {
|
|
54
54
|
readonly props: any;
|
package/esm/next/http.js
CHANGED
|
@@ -9,7 +9,7 @@ export * from '../http.js';
|
|
|
9
9
|
* Use this method inside a `getServerSideProps` method (or API route)
|
|
10
10
|
* to return an error page with proper HTTP status code and all the shit.
|
|
11
11
|
*
|
|
12
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
12
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#showerrorpage-helper
|
|
13
13
|
*/
|
|
14
14
|
const showErrorPage = (response, error, ttl = '2s') => {
|
|
15
15
|
error =
|
|
@@ -33,7 +33,7 @@ const showErrorPage = (response, error, ttl = '2s') => {
|
|
|
33
33
|
* cases when `getServerSideProps` returns an `__error` prop with `statusCode`
|
|
34
34
|
* and optional friendly `message`.
|
|
35
35
|
*
|
|
36
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
36
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#makeerrorizeapphoc
|
|
37
37
|
*/
|
|
38
38
|
export const makeErrorizeAppHOC = (ErrorPage) => {
|
|
39
39
|
// the HOC
|
|
@@ -62,7 +62,7 @@ export const makeErrorizeAppHOC = (ErrorPage) => {
|
|
|
62
62
|
* to return an `HTTP_304_NotModified` response with an empty props object,
|
|
63
63
|
* in a way that doesn't make TypeScript shout at you.
|
|
64
64
|
*
|
|
65
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
65
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README-nextjs.md#notmodified304-helper
|
|
66
66
|
*/
|
|
67
67
|
export const notModified304 = (response) => {
|
|
68
68
|
response = 'res' in response ? response.res : response;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { GlobalStyleRule } from '@vanilla-extract/css';
|
|
2
|
+
/**
|
|
3
|
+
* Adds free-form CSS as a globalStyle
|
|
4
|
+
*
|
|
5
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#vanillaglobal
|
|
6
|
+
*/
|
|
7
|
+
export declare const vanillaGlobal: (css: string) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Spreads the return value into a style object, to inject free-form CSS
|
|
10
|
+
* properties (or nested blocks)
|
|
11
|
+
*
|
|
12
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#vanillaprops
|
|
13
|
+
*/
|
|
14
|
+
export declare const vanillaProps: (css: string) => GlobalStyleRule;
|
|
15
|
+
/**
|
|
16
|
+
* Returns a scoped cssClassName styled with free-form CSS
|
|
17
|
+
*
|
|
18
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#vanillaclass
|
|
19
|
+
*/
|
|
20
|
+
export declare function vanillaClass(css: string): string;
|
|
21
|
+
export declare function vanillaClass(debugId: string, css: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Replaces all `&` tokens with the given selector string, in a direct
|
|
24
|
+
* (read. "dumb") way. It's mainly useful when used with style-mixins, etc.
|
|
25
|
+
*
|
|
26
|
+
* NOTE: It does NOT support deeply nested blocks, or anything so fancy.
|
|
27
|
+
* It will also replace "&" characters inside values, comments, etc.
|
|
28
|
+
* If you need something more sophisticated, use a custom `postcss` config.
|
|
29
|
+
*
|
|
30
|
+
*
|
|
31
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#vanillanest
|
|
32
|
+
*/
|
|
33
|
+
export declare const vanillaNest: (ampSelector: string, css: string) => string;
|
|
34
|
+
/**
|
|
35
|
+
* Returns a scoped cssClassName styled with free-form CSS.
|
|
36
|
+
*
|
|
37
|
+
* It also automatically replaces all `&`-tokens with
|
|
38
|
+
* the selector for the auto-generated class-name.
|
|
39
|
+
*
|
|
40
|
+
* NOTE: All "bare" (un-nested) style properties must come first,
|
|
41
|
+
* before any nested blocks.
|
|
42
|
+
*
|
|
43
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#vanillaclassnested
|
|
44
|
+
*/
|
|
45
|
+
export declare function vanillaClassNested(css: string): string;
|
|
46
|
+
export declare function vanillaClassNested(debugId: string, css: string): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { globalStyle, style } from '@vanilla-extract/css';
|
|
2
|
+
/**
|
|
3
|
+
* Adds free-form CSS as a globalStyle
|
|
4
|
+
*
|
|
5
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#vanillaglobal
|
|
6
|
+
*/
|
|
7
|
+
export const vanillaGlobal = (css) => globalStyle('x', { x: `} ${css} x{x:` });
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
/**
|
|
10
|
+
* Spreads the return value into a style object, to inject free-form CSS
|
|
11
|
+
* properties (or nested blocks)
|
|
12
|
+
*
|
|
13
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#vanillaprops
|
|
14
|
+
*/
|
|
15
|
+
export const vanillaProps = (css) => ({ x: `; ${css}` });
|
|
16
|
+
export function vanillaClass(cssOrDebugId, css) {
|
|
17
|
+
const debugId = css != null ? cssOrDebugId : undefined;
|
|
18
|
+
css = css != null ? css : cssOrDebugId;
|
|
19
|
+
return style(vanillaProps(css), debugId);
|
|
20
|
+
}
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
/**
|
|
23
|
+
* Replaces all `&` tokens with the given selector string, in a direct
|
|
24
|
+
* (read. "dumb") way. It's mainly useful when used with style-mixins, etc.
|
|
25
|
+
*
|
|
26
|
+
* NOTE: It does NOT support deeply nested blocks, or anything so fancy.
|
|
27
|
+
* It will also replace "&" characters inside values, comments, etc.
|
|
28
|
+
* If you need something more sophisticated, use a custom `postcss` config.
|
|
29
|
+
*
|
|
30
|
+
*
|
|
31
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#vanillanest
|
|
32
|
+
*/
|
|
33
|
+
export const vanillaNest = (ampSelector, css) => css.replace(/&/g, ampSelector);
|
|
34
|
+
export function vanillaClassNested(cssOrDebugId, css) {
|
|
35
|
+
const debugId = css != null ? cssOrDebugId : undefined;
|
|
36
|
+
css = css != null ? css : cssOrDebugId;
|
|
37
|
+
const nestPoint = css.indexOf('&');
|
|
38
|
+
const bareStyles = nestPoint > -1 ? css.slice(0, nestPoint) : css;
|
|
39
|
+
const nestedStyles = nestPoint > -1 ? css.slice(nestPoint) : undefined;
|
|
40
|
+
const className = style(vanillaProps(bareStyles), debugId);
|
|
41
|
+
if (nestedStyles) {
|
|
42
|
+
vanillaGlobal(vanillaNest(`.${className}`, nestedStyles));
|
|
43
|
+
}
|
|
44
|
+
return className;
|
|
45
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const locAliases = {
|
|
3
|
+
// Danish is good enough substitution for Icelandic
|
|
4
|
+
is: 'da',
|
|
5
|
+
'is-is': 'da',
|
|
6
|
+
};
|
|
7
|
+
const mapLocales = (locales) => {
|
|
8
|
+
locales = typeof locales === 'string' ? [locales] : locales || [];
|
|
9
|
+
return locales.map((loc) => locAliases[loc.toLowerCase()] || loc);
|
|
10
|
+
};
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
if ( /*#__PURE__*/'ö'.localeCompare('p', 'is') < 0) {
|
|
13
|
+
const _localeCompare = String.prototype.localeCompare;
|
|
14
|
+
/**
|
|
15
|
+
* Polyfill for String.prototype.localeCompare for the 'is' locale
|
|
16
|
+
* in browsers that don't support it (\*cough* Chrome \*cough*).
|
|
17
|
+
*/
|
|
18
|
+
String.prototype.localeCompare = function (that, locales, options) {
|
|
19
|
+
return _localeCompare.call(this, that, mapLocales(locales), options);
|
|
20
|
+
};
|
|
21
|
+
}
|
package/http.d.ts
CHANGED
|
@@ -153,21 +153,21 @@ type TTLObj = {
|
|
|
153
153
|
/**
|
|
154
154
|
* Configures quick TTL-related settings for a HTTP request object
|
|
155
155
|
*
|
|
156
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
156
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#type-ttlconfig
|
|
157
157
|
*/
|
|
158
158
|
export type TTLConfig = TTL | TTLKeywords | TTLObj;
|
|
159
159
|
/**
|
|
160
160
|
* Converts a `TTL` (max-age) value into seconds, and returns `0` for bad
|
|
161
161
|
* and/or negative input values.
|
|
162
162
|
*
|
|
163
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
163
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#tosec-ttl-helper
|
|
164
164
|
*/
|
|
165
165
|
export declare const toSec: (ttl: TTL) => number;
|
|
166
166
|
/**
|
|
167
167
|
* Use this function to quickly set the `Cache-Control` header with a `max-age=`
|
|
168
168
|
* on a HTTP response
|
|
169
169
|
*
|
|
170
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
170
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#getcssbundleurl
|
|
171
171
|
*/
|
|
172
172
|
export declare const cacheControl: (response: ServerResponse | {
|
|
173
173
|
res: ServerResponse;
|
package/http.js
CHANGED
|
@@ -140,7 +140,7 @@ const unitToSeconds = {
|
|
|
140
140
|
* Converts a `TTL` (max-age) value into seconds, and returns `0` for bad
|
|
141
141
|
* and/or negative input values.
|
|
142
142
|
*
|
|
143
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
143
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#tosec-ttl-helper
|
|
144
144
|
*/
|
|
145
145
|
const toSec = (ttl) => {
|
|
146
146
|
if (typeof ttl === 'string') {
|
|
@@ -173,7 +173,7 @@ const setCC = (response, cc) => {
|
|
|
173
173
|
* Use this function to quickly set the `Cache-Control` header with a `max-age=`
|
|
174
174
|
* on a HTTP response
|
|
175
175
|
*
|
|
176
|
-
* @see https://github.com/reykjavikcity/webtools/
|
|
176
|
+
* @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#getcssbundleurl
|
|
177
177
|
*/
|
|
178
178
|
// eslint-disable-next-line complexity
|
|
179
179
|
const cacheControl = (response, ttlCfg, eTag) => {
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
/// <reference path="./vanillaExtract.d.ts" />
|
|
1
2
|
/// <reference path="./http.d.ts" />
|
|
3
|
+
/// <reference path="./fixIcelandicLocale.d.ts" />
|
|
2
4
|
/// <reference path="./CookieHubConsent.d.tsx" />
|
|
3
5
|
/// <reference path="./next/SiteImprove.d.tsx" />
|
|
4
6
|
/// <reference path="./next/http.d.tsx" />
|