@mintlify/common 1.0.780 → 1.0.782
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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/AnalyticsEvent.d.ts +1 -1
- package/dist/types/AnalyticsEvent.js +3 -0
- package/dist/validateRedirectUrl.d.ts +7 -0
- package/dist/validateRedirectUrl.js +77 -0
- package/package.json +2 -2
|
@@ -7,7 +7,7 @@ export declare const PAGE_VIEW_EVENT = "docs.content.view";
|
|
|
7
7
|
* - **noun**: The component or feature being interacted with (e.g., 'expandable', 'search')
|
|
8
8
|
* - **action**: The specific action taken (e.g., 'open', 'click', 'copy')
|
|
9
9
|
*/
|
|
10
|
-
export declare const ANALYTICS_EVENTS: readonly ["docs.content.view", "docs.expandable.open", "docs.expandable.close", "docs.accordion.open", "docs.accordion.close", "docs.navitem.click", "docs.navitem.cta_click", "docs.search.query", "docs.search.close", "docs.api_playground.request", "docs.search.result_click", "docs.code_block.copy", "docs.code_block.ask_ai", "docs.feedback.thumbs_up", "docs.feedback.thumbs_down", "docs.footer.powered_by_mintlify_click", "docs.assistant.enter", "docs.assistant.completed", "docs.assistant.shared", "docs.assistant.source_click", "docs.assistant.web_search_click", "docs.assistant.thumbs_up", "docs.assistant.thumbs_down", "docs.assistant.suggestion_click", "docs.assistant.starter_question_clicked", "docs.assistant.maximize_click", "docs.assistant.minimize_click", "docs.assistant.copy_response", "docs.assistant.ask_ai_on_text_selection", "docs.assistant.spam_detected", "docs.context_menu.copy_page", "docs.context_menu.copy_mcp_link", "docs.context_menu.ai_provider_click", "docs.context_menu.install_mcp_server", "docs.context_menu.copy_add_mcp_command", "docs.autopilot.suggestion.created", "docs.autopilot.suggestion.no_suggestion", "mcp.tool_call.search", "docs.content.md.view", "docs.banner.atlas_signup_click", "docs.banner.atlas_share_click", "docs.atlas_content.view"];
|
|
10
|
+
export declare const ANALYTICS_EVENTS: readonly ["docs.content.view", "docs.expandable.open", "docs.expandable.close", "docs.accordion.open", "docs.accordion.close", "docs.navitem.click", "docs.navitem.cta_click", "docs.search.query", "docs.search.close", "docs.api_playground.request", "docs.search.result_click", "docs.code_block.copy", "docs.code_block.ask_ai", "docs.feedback.thumbs_up", "docs.feedback.thumbs_down", "docs.footer.powered_by_mintlify_click", "docs.assistant.enter", "docs.assistant.completed", "docs.assistant.shared", "docs.assistant.source_click", "docs.assistant.web_search_click", "docs.assistant.thumbs_up", "docs.assistant.thumbs_down", "docs.assistant.suggestion_click", "docs.assistant.starter_question_clicked", "docs.assistant.maximize_click", "docs.assistant.minimize_click", "docs.assistant.copy_response", "docs.assistant.ask_ai_on_text_selection", "docs.assistant.spam_detected", "docs.assistant.attachment_upload", "docs.assistant.attachment_rejected", "docs.assistant.attachment_limit_exceeded", "docs.context_menu.copy_page", "docs.context_menu.copy_mcp_link", "docs.context_menu.ai_provider_click", "docs.context_menu.install_mcp_server", "docs.context_menu.copy_add_mcp_command", "docs.autopilot.suggestion.created", "docs.autopilot.suggestion.no_suggestion", "mcp.tool_call.search", "docs.content.md.view", "docs.banner.atlas_signup_click", "docs.banner.atlas_share_click", "docs.atlas_content.view"];
|
|
11
11
|
export type AnalyticsEvent = (typeof ANALYTICS_EVENTS)[number];
|
|
12
12
|
export declare function isAnalyticsEvent(value: string): value is AnalyticsEvent;
|
|
13
13
|
/**
|
|
@@ -38,6 +38,9 @@ export const ANALYTICS_EVENTS = [
|
|
|
38
38
|
'docs.assistant.copy_response',
|
|
39
39
|
'docs.assistant.ask_ai_on_text_selection',
|
|
40
40
|
'docs.assistant.spam_detected',
|
|
41
|
+
'docs.assistant.attachment_upload',
|
|
42
|
+
'docs.assistant.attachment_rejected',
|
|
43
|
+
'docs.assistant.attachment_limit_exceeded',
|
|
41
44
|
'docs.context_menu.copy_page',
|
|
42
45
|
'docs.context_menu.copy_mcp_link',
|
|
43
46
|
'docs.context_menu.ai_provider_click',
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface ValidateRedirectUrlOptions {
|
|
2
|
+
redirectUrl: string | null | undefined;
|
|
3
|
+
currentOrigin: string;
|
|
4
|
+
allowedOrigins?: string[];
|
|
5
|
+
allowDifferentOrigin?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function validateRedirectUrl(options: ValidateRedirectUrlOptions): string | null | true;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const dangerousProtocols = ['javascript:', 'data:', 'vbscript:', 'file:', 'about:', 'blob:'];
|
|
2
|
+
function hasDangerousPatterns(str) {
|
|
3
|
+
const lowerCased = str.toLowerCase();
|
|
4
|
+
for (const protocol of dangerousProtocols) {
|
|
5
|
+
if (lowerCased.startsWith(protocol)) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
if (str.startsWith('//')) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
if (str.includes('\t') || str.includes('\n') || str.includes('\r') || str.includes('\x00')) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (str.includes('&#')) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
export function validateRedirectUrl(options) {
|
|
21
|
+
const { redirectUrl, currentOrigin, allowedOrigins, allowDifferentOrigin } = options;
|
|
22
|
+
if (!redirectUrl) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
if (typeof redirectUrl !== 'string') {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const trimmed = redirectUrl.trim();
|
|
29
|
+
if (trimmed.length === 0) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if (hasDangerousPatterns(trimmed)) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
let decoded = trimmed;
|
|
36
|
+
for (let i = 0; i < 3; i++) {
|
|
37
|
+
try {
|
|
38
|
+
const nextDecoded = decodeURIComponent(decoded);
|
|
39
|
+
if (nextDecoded === decoded) {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
decoded = nextDecoded;
|
|
43
|
+
if (hasDangerousPatterns(decoded)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (_a) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (trimmed.startsWith('/')) {
|
|
52
|
+
return trimmed;
|
|
53
|
+
}
|
|
54
|
+
if (!trimmed.includes('://')) {
|
|
55
|
+
return trimmed;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const url = new URL(trimmed);
|
|
59
|
+
if (url.protocol !== 'https:') {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
if (allowDifferentOrigin) {
|
|
63
|
+
return trimmed;
|
|
64
|
+
}
|
|
65
|
+
const urlOrigin = url.origin;
|
|
66
|
+
if (urlOrigin === currentOrigin) {
|
|
67
|
+
return trimmed;
|
|
68
|
+
}
|
|
69
|
+
if (allowedOrigins && allowedOrigins.includes(urlOrigin)) {
|
|
70
|
+
return trimmed;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
catch (_b) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintlify/common",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.782",
|
|
4
4
|
"description": "Commonly shared code within Mintlify",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -124,5 +124,5 @@
|
|
|
124
124
|
"typescript": "5.5.3",
|
|
125
125
|
"vitest": "2.0.4"
|
|
126
126
|
},
|
|
127
|
-
"gitHead": "
|
|
127
|
+
"gitHead": "b8bbe7fe6abd35c1966c8f9c32c8f63b99aad83b"
|
|
128
128
|
}
|