Skip to content

Commit 6407466

Browse files
committed
chore(svelte): Detect SvelteKit usage
1 parent 8c58e0d commit 6407466

File tree

4 files changed

+65
-13
lines changed

4 files changed

+65
-13
lines changed

packages/svelte/src/sdk.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { BrowserOptions, init as browserInit, SDK_VERSION } from '@sentry/browser';
2-
1+
import { addGlobalEventProcessor, BrowserOptions, init as browserInit, SDK_VERSION } from '@sentry/browser';
2+
import { getDomElement } from '@sentry/utils';
33
/**
44
* Inits the Svelte SDK
55
*/
@@ -17,4 +17,35 @@ export function init(options: BrowserOptions): void {
1717
};
1818

1919
browserInit(options);
20+
21+
detectSvelteKit();
22+
}
23+
24+
/**
25+
* Detects if the SDK is initialized in a SvelteKit frontend, in which case
26+
* we add a global event processor to add it as a module to outgoing events.
27+
*/
28+
function detectSvelteKit(): void {
29+
setTimeout(() => {
30+
if (isSvelteKitApp()) {
31+
addGlobalEventProcessor(event => {
32+
event.modules = {
33+
svelteKit: '1.0',
34+
...event.modules,
35+
};
36+
return event;
37+
});
38+
}
39+
}, 0);
40+
}
41+
42+
/**
43+
* To actually detect a SvelteKit frontend, we search the DOM for a special
44+
* div that's inserted by SvelteKit when the page is rendered. It's identifyed
45+
* by 'svelte-announcer' and used to improve page accessibility.
46+
*
47+
* @see https://github.com/sveltejs/kit/issues/307 for more information
48+
*/
49+
function isSvelteKitApp(): boolean {
50+
return getDomElement('div#svelte-announcer') !== null;
2051
}

packages/tracing/src/browser/browsertracing.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable max-lines */
22
import { Hub } from '@sentry/hub';
33
import { EventProcessor, Integration, Transaction, TransactionContext } from '@sentry/types';
4-
import { getGlobalObject, logger, parseBaggageSetMutability } from '@sentry/utils';
4+
import { getDomElement, getGlobalObject, logger, parseBaggageSetMutability } from '@sentry/utils';
55

66
import { startIdleTransaction } from '../hubextensions';
77
import { DEFAULT_FINAL_TIMEOUT, DEFAULT_IDLE_TIMEOUT } from '../idletransaction';
@@ -294,13 +294,6 @@ export function extractTraceDataFromMetaTags(): Partial<TransactionContext> | un
294294

295295
/** Returns the value of a meta tag */
296296
export function getMetaContent(metaName: string): string | null {
297-
const globalObject = getGlobalObject<Window>();
298-
299-
// DOM/querySelector is not available in all environments
300-
if (globalObject.document && globalObject.document.querySelector) {
301-
const el = globalObject.document.querySelector(`meta[name=${metaName}]`);
302-
return el ? el.getAttribute('content') : null;
303-
} else {
304-
return null;
305-
}
297+
const metaTag = getDomElement(`meta[name=${metaName}]`);
298+
return metaTag ? metaTag.getAttribute('content') : null;
306299
}

packages/utils/src/browser.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,21 @@ export function getLocationHref(): string {
122122
return '';
123123
}
124124
}
125+
126+
/**
127+
* Gets a DOM element via document.querySelector.
128+
*
129+
* This wrapper will first check for the existance of the function before
130+
* actually calling it so that we don't have to take care of this check,
131+
* every time we want to access the DOM.
132+
* Reason: DOM/querySelector is not available in all environments
133+
*
134+
* @param selector the selector string passed on to document.querySelector
135+
*/
136+
export function getDomElement(selector: string): Element | null {
137+
const global = getGlobalObject<Window>();
138+
if (global.document && global.document.querySelector) {
139+
return global.document.querySelector(selector);
140+
}
141+
return null;
142+
}

packages/utils/test/browser.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { JSDOM } from 'jsdom';
22

3-
import { htmlTreeAsString } from '../src/browser';
3+
import { getDomElement, htmlTreeAsString } from '../src/browser';
44

55
beforeAll(() => {
66
const dom = new JSDOM();
@@ -45,3 +45,13 @@ describe('htmlTreeAsString', () => {
4545
);
4646
});
4747
});
48+
49+
describe('getDomElement', () => {
50+
it('returns the element for a given query selector', () => {
51+
document.head.innerHTML = '<div id="mydiv">Hello</div>';
52+
const el = getDomElement('div#mydiv');
53+
expect(el).toBeDefined();
54+
expect(el?.tagName).toEqual('DIV');
55+
expect(el?.id).toEqual('mydiv');
56+
});
57+
});

0 commit comments

Comments
 (0)