FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
modelcontextprotocol/docs/version-warning.js at main · modelcontextprotocol/modelcontextprotocol · GitHub
modelcontextprotocol
modelcontextprotocol
Repository navigation
Code
Issues
60
(60)
Pull requests
58
(58)
Only collaborators can create PRs
Discussions
Actions
Projects
Security and quality
1
(1)
Insights
Expand file tree
Breadcrumbs
modelcontextprotocol
/
docs
/
version-warning.js
Copy path
More file actions
More file actions
Latest commit
History
History
History
197 lines (171 loc) · 7.29 KB
Breadcrumbs
modelcontextprotocol
/
docs
/
version-warning.js
Copy path
File metadata and controls
197 lines (171 loc) · 7.29 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Version Warning Banner
// Displays a warning banner on older spec and documentation versions and
// on draft spec pages.
//
// Mintlify automatically loads all .js files in the docs directory, and
// the site maintains /specification/latest/* and /docs/latest/* redirects
// that always point to the current latest version of each section. We use
// those redirects as the source of truth, so this script requires no
// updates when a new version is published. Styling re-uses Mintlify's
// native callout classes.
const
DRAFT_VERSION
=
"draft"
;
const
SECTIONS
=
[
{
pathRegex
:
/
\/
s
p
e
c
i
f
i
c
a
t
i
o
n
\/
(
\d
{
4
}
-
\d
{
2
}
-
\d
{
2
}
|
d
r
a
f
t
|
l
a
t
e
s
t
)
(
\/
.
*
)
?
$
/
,
latestAliasPath
:
"/specification/latest"
,
storageKey
:
"mcp-latest-spec-version"
,
noun
:
"specification"
,
draftMessage
:
"You are viewing a draft of a not-yet-finalized specification."
,
}
,
{
pathRegex
:
/
\/
d
o
c
s
\/
(
\d
{
4
}
-
\d
{
2
}
-
\d
{
2
}
|
d
r
a
f
t
|
l
a
t
e
s
t
)
(
\/
.
*
)
?
$
/
,
latestAliasPath
:
"/docs/latest"
,
storageKey
:
"mcp-latest-docs-version"
,
noun
:
"documentation"
,
draftMessage
:
"You are viewing draft documentation for a not-yet-finalized specification."
,
}
,
]
;
const
BANNER_ATTR
=
"data-spec-version-banner"
;
const
CALLOUT_CLASS_WARNING
=
"callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 "
+
"border border-yellow-200 bg-yellow-50 "
+
"dark:border-yellow-900 dark:bg-yellow-600/20 "
+
"[&_[data-component-part='callout-icon']]:mt-px"
;
const
CALLOUT_CLASS_INFO
=
"callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 "
+
"border border-neutral-200 bg-neutral-50 "
+
"dark:border-neutral-700 dark:bg-white/10"
;
const
CONTENT_CLASS_BASE
=
"text-sm prose dark:prose-invert min-w-0 w-full "
+
"[&_a]:!text-current [&_a]:border-current [&_strong]:!text-current "
;
const
CONTENT_CLASS_WARNING
=
CONTENT_CLASS_BASE
+
"text-yellow-800 dark:text-yellow-300"
;
const
CONTENT_CLASS_INFO
=
CONTENT_CLASS_BASE
+
"text-neutral-800 dark:text-neutral-300"
;
const
ICON_WRAPPER_CLASS
=
"mt-0.5 w-4"
;
const
ICON_SVG_WARNING
=
'<svg class="flex-none size-5 text-yellow-800 dark:text-yellow-300" '
+
'fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" '
+
'aria-label="Warning">'
+
'<path stroke-linecap="round" stroke-linejoin="round" '
+
'd="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 '
+
"4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
+
'"></path></svg>'
;
const
ICON_SVG_INFO
=
'<svg class="flex-none size-5 text-neutral-800 dark:text-neutral-300" '
+
'viewBox="0 0 20 20" fill="currentColor" aria-label="Info">'
+
'<path d="M8 0C3.58125 0 0 3.58125 0 8C0 12.4187 3.58125 16 8 '
+
"16C12.4187 16 16 12.4187 16 8C16 3.58125 12.4187 0 8 0ZM8 14.5C4.41563 "
+
"14.5 1.5 11.5841 1.5 8C1.5 4.41594 4.41563 1.5 8 1.5C11.5844 1.5 14.5 "
+
"4.41594 14.5 8C14.5 11.5841 11.5844 14.5 8 14.5ZM9.25 10.5H8.75V7.75C8.75 "
+
"7.3375 8.41563 7 8 7H7C6.5875 7 6.25 7.3375 6.25 7.75C6.25 8.1625 6.5875 "
+
"8.5 7 8.5H7.25V10.5H6.75C6.3375 10.5 6 10.8375 6 11.25C6 11.6625 6.3375 "
+
"12 6.75 12H9.25C9.66406 12 10 11.6641 10 11.25C10 10.8359 9.66563 10.5 "
+
"9.25 10.5ZM8 6C8.55219 6 9 5.55219 9 5C9 4.44781 8.55219 4 8 4C7.44781 "
+
'4 7 4.44687 7 5C7 5.55313 7.44687 6 8 6Z"></path></svg>'
;
function
parseVersionedPath
(
pathname
)
{
for
(
const
section
of
SECTIONS
)
{
const
match
=
pathname
.
match
(
section
.
pathRegex
)
;
if
(
match
)
return
{
section
,
version
:
match
[
1
]
,
subPath
:
match
[
2
]
||
""
}
;
}
return
null
;
}
async
function
resolveLatestVersion
(
section
)
{
const
cached
=
sessionStorage
.
getItem
(
section
.
storageKey
)
;
if
(
cached
)
return
cached
;
const
response
=
await
fetch
(
section
.
latestAliasPath
,
{
method
:
"HEAD"
}
)
;
const
resolvedPath
=
new
URL
(
response
.
url
)
.
pathname
;
const
match
=
resolvedPath
.
match
(
section
.
pathRegex
)
;
const
version
=
match
?
match
[
1
]
:
null
;
if
(
version
&&
version
!==
"latest"
)
{
sessionStorage
.
setItem
(
section
.
storageKey
,
version
)
;
}
return
version
;
}
function
createBanner
(
message
,
linkHref
,
linkText
,
isDraft
)
{
const
banner
=
document
.
createElement
(
"div"
)
;
banner
.
className
=
isDraft
?
CALLOUT_CLASS_INFO
:
CALLOUT_CLASS_WARNING
;
banner
.
setAttribute
(
"role"
,
"alert"
)
;
banner
.
setAttribute
(
BANNER_ATTR
,
""
)
;
banner
.
setAttribute
(
"data-callout-type"
,
isDraft
?
"info"
:
"warning"
)
;
const
iconWrapper
=
document
.
createElement
(
"div"
)
;
iconWrapper
.
className
=
ICON_WRAPPER_CLASS
;
iconWrapper
.
setAttribute
(
"data-component-part"
,
"callout-icon"
)
;
iconWrapper
.
innerHTML
=
isDraft
?
ICON_SVG_INFO
:
ICON_SVG_WARNING
;
const
content
=
document
.
createElement
(
"div"
)
;
content
.
className
=
isDraft
?
CONTENT_CLASS_INFO
:
CONTENT_CLASS_WARNING
;
content
.
setAttribute
(
"data-component-part"
,
"callout-content"
)
;
const
text
=
document
.
createElement
(
"span"
)
;
text
.
textContent
=
message
+
" "
;
const
link
=
document
.
createElement
(
"a"
)
;
link
.
href
=
linkHref
;
link
.
textContent
=
linkText
;
content
.
appendChild
(
text
)
;
content
.
appendChild
(
link
)
;
banner
.
appendChild
(
iconWrapper
)
;
banner
.
appendChild
(
content
)
;
return
banner
;
}
let
inserting
=
false
;
async
function
insertWarningBanner
(
)
{
if
(
inserting
)
return
;
if
(
document
.
querySelector
(
`[
${
BANNER_ATTR
}
]`
)
)
return
;
const
current
=
parseVersionedPath
(
window
.
location
.
pathname
)
;
if
(
!
current
)
return
;
inserting
=
true
;
try
{
const
latest
=
await
resolveLatestVersion
(
current
.
section
)
.
catch
(
(
)
=>
null
,
)
;
if
(
!
latest
||
current
.
version
===
latest
)
return
;
// Re-check after the await — a concurrent call may have already
// inserted a banner, or SPA navigation may have changed the page.
if
(
document
.
querySelector
(
`[
${
BANNER_ATTR
}
]`
)
)
return
;
if
(
parseVersionedPath
(
window
.
location
.
pathname
)
?.
version
!==
current
.
version
)
return
;
const
contentArea
=
document
.
querySelector
(
"#content-area, main, article, .content"
,
)
;
if
(
!
contentArea
)
return
;
// Mintlify redirects <section>/latest/<sub-path> to the actual
// version, so users land on the equivalent page in the latest version.
const
latestHref
=
current
.
section
.
latestAliasPath
+
current
.
subPath
;
const
linkText
=
`View the latest version (
${
latest
}
)`
;
const
isDraft
=
current
.
version
===
DRAFT_VERSION
;
const
message
=
isDraft
?
current
.
section
.
draftMessage
:
`You are viewing an older version (
${
current
.
version
}
) of the
${
current
.
section
.
noun
}
.`
;
const
banner
=
createBanner
(
message
,
latestHref
,
linkText
,
isDraft
)
;
// Place the banner just below the page title block. Mintlify wraps
// the H1 in <header id="header">; fall back to a raw <h1> or the
// top of the content area.
const
header
=
contentArea
.
querySelector
(
"header#header"
)
||
contentArea
.
querySelector
(
"h1"
)
;
if
(
header
)
{
header
.
insertAdjacentElement
(
"afterend"
,
banner
)
;
}
else
{
contentArea
.
insertBefore
(
banner
,
contentArea
.
firstChild
)
;
}
}
finally
{
inserting
=
false
;
}
}
if
(
document
.
readyState
===
"loading"
)
{
document
.
addEventListener
(
"DOMContentLoaded"
,
insertWarningBanner
)
;
}
else
{
insertWarningBanner
(
)
;
}
// Re-insert after SPA navigation.
const
observer
=
new
MutationObserver
(
(
)
=>
{
if
(
!
document
.
querySelector
(
`[
${
BANNER_ATTR
}
]`
)
&&
parseVersionedPath
(
window
.
location
.
pathname
)
)
{
insertWarningBanner
(
)
;
}
}
)
;
observer
.
observe
(
document
.
body
,
{
childList
:
true
,
subtree
:
true
}
)
;
Back
|
FazBrowse Home
|
New Git URL