PageSourceSearch

https://ip.im/myip/

html ip.im collected 2026-10-06 17:57:51 UTC 27,920 bytes, 517 lines download raw bytes

1<!DOCTYPE html>
2<html lang="zh-CN">
3
4<head>
5  <meta charset="UTF-8">
6  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7  <meta name="keywords" content="IP,IP查询,IP地址查询,IP地址,IP地址归属地,查询本机IP,网速测试">
8  <meta name="description"
9    content="A better IP Toolbox. Easy to check what's your IPs, IP informations, check for DNS leaks, examine WebRTC connections, and test website availability">
10  <meta name="apple-mobile-web-app-capable" content="yes">
11  <meta name="theme-color" content="#f8f9fa">
12  <meta name="background-color" content="#ffffff">
13  <link rel="apple-touch-icon" href="res/img/logo-512.png">
14  <title>查看我的 IP 地址 | 查询本机 IP 地址及归属地 | 查看 WebRTC 连接 IP | DNS 泄露检测 | 网速测试 | Jason Ng 阿禅开源作品 </title>
15  <!--  Bootstrap CSS -->
16  <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css" rel="stylesheet"
17    integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
18  <link rel="stylesheet"
19    href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.11.2/font/bootstrap-icons.min.css">
20  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.5.0/css/flag-icon.min.css">
21  <link rel="icon" href="favicon.ico">
22  <link rel="stylesheet" href="res/css/style.css">
23  <link rel="manifest" href="manifest.json">
24</head>
25
26<body>
27
28  <!-- Loading -->
29  <div id="loading" class="d-flex justify-content-center jn-loading">
30    <div class="spinner-border text-success" role="status">
31      <span class="visually-hidden">Loading...</span>
32    </div>
33  </div>
34
35  <div id="app" v-cloak>
36    <!-- Nav -->
37    <nav id="navbar-top" class="navbar navbar-expand-lg bg-body-tertiary px-3 mb-3 jn-navbar-top"
38      :class="{ 'dark-mode-nav navbar-dark bg-dark': isDarkMode }">
39      <div class="jn-logo">
40        <a class="navbar-brand" :class="{ 'text-white': isDarkMode }" href="/" @click="handleLogoClick"><i
41            class="bi bi-box-seam-fill"></i>
42          {{currentTexts.nav.Title}}</a>
43        <div class="form-check form-switch">
44          <input class="form-check-input" type="checkbox" role="switch" id="darkModeSwitch" @change="toggleDarkMode"
45            :checked="isDarkMode">
46          <label class="form-check-label" for="darkModeSwitch">
47            <i v-if="isDarkMode" class="bi bi-moon-stars"></i>
48            <i v-else class="bi bi-brightness-high"></i>
49          </label>
50        </div>
51
52      </div>
53      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup"
54        aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
55        <span class="navbar-toggler-icon bg-transparent "></span>
56      </button>
57      <div class="collapse navbar-collapse justify-content-end" id="navbarNavAltMarkup">
58        <div class="navbar-nav ">
59          <a class="nav-link" :class="{ 'text-white jn-deactive': isDarkMode }"
60            href="#IPInfo">{{currentTexts.nav.IPinfo}}</a>
61          <a class="nav-link" :class="{ 'text-white jn-deactive': isDarkMode }"
62            href="#Connectivity">{{currentTexts.nav.Connectivity}}</a>
63          <a class="nav-link" :class="{ 'text-white jn-deactive': isDarkMode }"
64            href="#WebRTC">{{currentTexts.nav.WebRTC}}</a>
65          <a class="nav-link" :class="{ 'text-white jn-deactive': isDarkMode }"
66            href="#DNSLeakTest">{{currentTexts.nav.DNSLeakTest}}</a>
67          <a class="nav-link" :class="{ 'text-white jn-deactive': isDarkMode }"
68            href="#SpeedTest">{{currentTexts.nav.SpeedTest}}</a>
69        </div>
70      </div>
71    </nav>
72
73
74
75
76    <!-- Proxy Alerts -->
77    <div class="toast-container position-fixed bottom-0 end-0 p-3 jn-toast">
78      <div id="toast" class="toast" :class="{ 'dark-mode': isDarkMode }" role="alert" ref="toast" aria-live="assertive"
79        aria-atomic="true">
80        <div class="toast-header" :class="{ 'dark-mode-title': isDarkMode }">
81          <strong class="me-auto" :class="alertStyle">{{ alertTitle }}</strong>
82          <button type="button" class="btn-close" :class="{ 'dark-mode-close-button': isDarkMode }"
83            data-bs-dismiss="toast" aria-label="Close"></button>
84        </div>
85        <div class="toast-body">
86          {{ alertMessage }}
87        </div>
88      </div>
89    </div>
90
91
92    <div id="mainpart" class="container mt-5 jn-container">
93      <div data-bs-spy="scroll" data-bs-target="#navbar-top" data-bs-root-margin="0px 0px -40%"
94        data-bs-smooth-scroll="true" class="rounded-2" tabindex="0">
95        <!-- IP Infos -->
96        <div class="ip-data-section mb-4">
97          <div class="row" :class="{'jn-title2': !isMobile,'jn-title':isMobile}">
98            <h2 id="IPInfo" class="col-4" :class="{'mobile-h2' : isMobile }">🕵️
99              {{currentTexts.ipInfos.Title}}</h2>
100            <div class="form-check form-switch col-8 jn-radio">
101
102              <div :class="{'col-4': isMobile }">
103                <input v-if="isMobile" class="form-check-input" type="checkbox" id="collapseSwitch"
104                  @change="toggleCollapse" :checked="!isCardsCollapsed">
105                <label v-if="isMobile" class="form-check-label" for="collapseSwitch">&nbsp;<i
106                    class="bi bi-list-columns-reverse"></i></label>
107              </div>
108
109              <div>
110                <input class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckDefault"
111                  @change="toggleMaps" :checked="isMapShown" :disabled="!bingMapAPIKEY">
112
113                <label class="form-check-label" for="flexSwitchCheckDefault">
114                  <i :class="['bi', bingMapAPIKEY ? 'bi bi-map-fill':'bi bi-map']"></i>
115                </label>
116                <i :class="['bi ', !bingMapAPIKEY ? 'bi-plus-circle-fill':'bi-pencil-square']" data-bs-toggle="modal"
117                  data-bs-target="#addBingMapKey"></i>
118
119              </div>
120
121
122
123            </div>
124          </div>
125          <div class="text-secondary">
126            <p>{{currentTexts.ipInfos.Notes}}</p>
127          </div>
128          <div class="jn-card-deck">
129            <div class="row">
130              <div v-for="card in ipDataCards" :key="card.id" :ref="card.id"
131                :class="{'jn-opacity': !card.asn, 'col-xl-4': true, 'col-lg-6': true, 'col-md-6': true, 'mb-4': true}">
132                <div class="card jn-card" :class="{ 'dark-mode dark-mode-border': isDarkMode }">
133                  <div class="card-header jn-ip-title" :class="{ 'dark-mode-title': isDarkMode }"
134                    style="font-weight: bold;">
135                    <span>{{currentTexts.ipInfos.Source}}: {{ card.source }}</span>
136                    <button @click="refreshCard(card)"
137                      :class="['btn', isDarkMode ? 'btn-dark dark-mode-refresh' : 'btn-light']">
138                      <i class="bi bi-arrow-clockwise"></i></button>
139                  </div>
140
141                  <!--  Google Maps iFrame -->
142                  <!-- <iframe class="card-img-top" :src="card.mapUrl" width="100%" height="200" frameborder="0"
143                  style="border:0;" allowfullscreen>
144                </iframe> -->
145
146                  <img v-if="isMapShown" v-if="!isMobile" :src="card.mapUrl" class="card-img-top jn-map-image"
147                    alt="Map">
148                  <div class="card-body">
149                    <ul class="list-group list-group-flush">
150                      <li class="list-group-item jn-list-group-item" :class="{ 'dark-mode': isDarkMode }"><span
151                          class="jn-text">🖥️ {{currentTexts.ipInfos.IP}}</span>: {{ card.ip
152                        }}
153                      </li>
154                      <li class="list-group-item jn-list-group-item"
155                        :class="{ 'dark-mode': isDarkMode,'mobile-list': isMobile && isCardsCollapsed }">
156                        <span class="jn-text">🌍 {{currentTexts.ipInfos.Country}}</span>: {{
157                        card.country_name }}&nbsp;<span v-if="card.country_code"
158                          :class="'flag-icon flag-icon-' + card.country_code.toLowerCase()"></span>
159                      </li>
160                      <li v-show="!isMobile || !isCardsCollapsed" class="list-group-item jn-list-group-item"
161                        :class="{ 'dark-mode': isDarkMode }"><span class="jn-text">🏚️
162                          {{currentTexts.ipInfos.Region}}</span>: {{ card.region
163                        }}</li>
164                      <li v-show="!isMobile || !isCardsCollapsed" class="list-group-item jn-list-group-item"
165                        :class="{ 'dark-mode': isDarkMode }"><span class="jn-text">🚏
166                          {{currentTexts.ipInfos.City}}</span>: {{ card.city }}
167                      </li>
168                      <li v-show="!isMobile || !isCardsCollapsed" class="list-group-item jn-list-group-item"
169                        :class="{ 'dark-mode': isDarkMode }"><span class="jn-text">🏢
170                          {{currentTexts.ipInfos.ISP}}</span>: {{ card.isp }}
171                      </li>
172                      <li v-show="!isMobile || !isCardsCollapsed" class="list-group-item jn-list-group-item"
173                        :class="{ 'dark-mode': isDarkMode }"><span class="jn-text">📶
174                          {{currentTexts.ipInfos.ASN}}</span>: <a v-if="card.asnlink" :href="card.asnlink"
175                          target="_blank">{{
176                          card.asn }}</a><a v-else>{{
177                          card.asn
178                          }}</a></li>
179                    </ul>
180                  </div>
181
182                </div>
183              </div>
184            </div>
185          </div>
186        </div>
187
188        <!-- Connectivity -->
189        <div class="availability-test-section mb-4">
190          <div class="jn-title2">
191            <h2 id="Connectivity" :class="{'mobile-h2' : isMobile }">🚦 {{currentTexts.connectivity.Title}}</h2>
192            <button @click="checkAllConnectivity(false)"
193              :class="['btn', isDarkMode ? 'btn-dark dark-mode-refresh' : 'btn-light']"><i
194                class="bi bi-arrow-clockwise"></i></button>
195          </div>
196          <div class="text-secondary">
197            <p>{{currentTexts.connectivity.Note}}</p>
198          </div>
199          <div class="row">
200            <div v-for="test in connectivityTests" :key="test.id" class="col-6 col-md-3 mb-4">
201              <div class="card jn-card" :class="{ 'dark-mode dark-mode-border': isDarkMode }">
202                <div class="card-body">
203                  <h5 class="card-title"><i class="bi" :class="'bi-'+test.icon"></i> {{ test.name }}</h5>
204
205                  <p class="card-text"
206                    :class="{'text-info': test.status === currentTexts.connectivity.StatusWait, 'text-success': test.status.includes(currentTexts.connectivity.StatusAvailable), 'text-danger': test.status === currentTexts.connectivity.StatusUnavailable || test.status === currentTexts.connectivity.StatusTimeout}"
207                    v-html="test.status">
208                  </p>
209                </div>
210              </div>
211            </div>
212          </div>
213        </div>
214
215        <!-- WebRTC Test -->
216        <div class="webrtc-test-section mb-4">
217          <div class="jn-title2">
218            <h2 id="WebRTC" :class="{'mobile-h2' : isMobile }">🚥 {{currentTexts.webrtc.Title}}</h2>
219            <button @click="checkAllWebRTC" :class="['btn', isDarkMode ? 'btn-dark dark-mode-refresh' : 'btn-light']"><i
220                class="bi bi-arrow-clockwise"></i></button>
221          </div>
222          <div class="text-secondary">
223            <p>{{currentTexts.webrtc.Note}}</p>
224          </div>
225          <div class="row">
226            <div v-for="stun in stunServers" :key="stun.id" class="col-6 col-md-3 mb-4">
227              <div class="card jn-card" :class="{ 'dark-mode dark-mode-border': isDarkMode }">
228                <div class="card-body">
229                  <h5 class="card-title"><i class="bi bi-sign-merge-left-fill"></i> {{ stun.name }}</h5>
230                  <p class="card-text text-secondary" style="font-size: 10pt;">{{ stun.url }}</p>
231                  <p class="card-text"
232                    :class="{'text-info': stun.ip === currentTexts.webrtc.StatusWait, 'text-success': stun.ip.includes('.'|':'), 'text-danger': stun.ip === currentTexts.webrtc.StatusError}"
233                    v-html="stun.ip"></p>
234                  </p>
235                </div>
236              </div>
237            </div>
238          </div>
239        </div>
240
241        <!-- DNS Leaks Test -->
242        <div class="dnsleak-test-section mb-4">
243          <div class="jn-title2">
244            <h2 id="DNSLeakTest" :class="{'mobile-h2' : isMobile }">🛑 {{currentTexts.dnsleaktest.Title}}</h2>
245            <button @click="checkAllDNSLeakTest"
246              :class="['btn', isDarkMode ? 'btn-dark dark-mode-refresh' : 'btn-light']"><i
247                class="bi bi-arrow-clockwise"></i></button>
248          </div>
249          <div class="text-secondary">
250            <p>{{currentTexts.dnsleaktest.Note}}</p>
251            <p>{{currentTexts.dnsleaktest.Note2}}</p>
252          </div>
253          <div class="row">
254            <div v-for="leak in leakTest" :key="leak.id" class="col-6 col-md-3 mb-4">
255              <div class="card jn-card" :class="{ 'dark-mode dark-mode-border': isDarkMode }">
256                <div class="card-body">
257                  <h5 class="card-title"><i class="bi bi-server"></i> {{ leak.name }}</h5>
258                  <p class="card-text text-secondary" style="font-size: 10pt;">{{currentTexts.dnsleaktest.Endpoint}}: {{
259                    leak.ip }}</p>
260                  <p class="card-text" :class="[
261                        'text-success',
262                        {'text-info': leak.geo === currentTexts.dnsleaktest.StatusWait, 'text-danger': leak.geo.includes('
262China') || leak.geo.includes('china')}
263                      ]">{{currentTexts.dnsleaktest.EndpointCountry}}: {{ leak.geo }}</p>
264                  </p>
265                </div>
266              </div>
267            </div>
268          </div>
269        </div>
270
271
272        <!-- Speed Test -->
273        <div class="speed-test-section mb-4">
274          <div class="jn-title2">
275            <h2 id="SpeedTest" :class="{'mobile-h2' : isMobile }">🚀 {{currentTexts.speedtest.Title}}</h2>
276            <button @click="startSpeedTest" :class="['btn', isDarkMode ? 'btn-dark dark-mode-refresh' : 'btn-light']"
277              :disabled="speedTestStatus === 'running'">
278              <i :class="speedTestStatus === 'running' ? 'bi bi-slash-circle' : 'bi bi-caret-right-fill'"></i>
279            </button>
280
281          </div>
282          <div class="text-secondary">
283            <p>{{currentTexts.speedtest.Note}}</p>
284          </div>
285          <div class="row">
286            <div class="col-12">
287              <div class="card jn-card" :class="{ 'dark-mode dark-mode-border': isDarkMode }">
288                <div class="card-body">
289                  <div class="progress" style="height: 20px; margin: 4pt 0 10pt 0;"
290                    :class="{ 'jn-opacity-0': speedTestStatus == 'idle', 'jn-progress-dark': isDarkMode }">
291                    <div class="progress-bar progress-bar-striped progress-bar-animated bg-success jn-progress"
292                      role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
293                      id="speedtest-progress">
294                    </div>
295                  </div>
296                  <div class="row" v-if="speedTestStatus === 'finished'">
297                    <p id="score" class="speedtest-p">📋 {{currentTexts.speedtest.score}}
298                      {{currentTexts.speedtest.videoStreaming}}
299                      <span :class="speedTest.streamingScore >= 50 ? 'text-success' : 'text-warning'">
300                        {{speedTest.streamingScore}}
301                      </span>
302                      {{currentTexts.speedtest.gaming}}
303                      <span :class="speedTest.gamingScore >= 50 ? 'text-success' : 'text-warning'">
304                        {{speedTest.gamingScore}}
305                      </span>
306                      {{currentTexts.speedtest.rtc}}
307                      <span :class="speedTest.rtcScore >= 50 ? 'text-success' : 'text-warning'">
308                        {{speedTest.rtcScore}}
309                      </span>
310                      {{currentTexts.speedtest.resultNote}}
311                    </p>
312                  </div>
313
314                  <div class="row" style="margin-bottom: 10pt;">
315                    <div class="col-3 text-center">
316                      <h5 class="speedtest-h5">{{currentTexts.speedtest.Download}}</h5>
317                      <p id="download-speed" class="speedtest-h5" :class="updateSpeedTestColor(speedTestStatus)">
318                        {{speedTest.downloadSpeed}}
319                        <br />Mb/s
320                      </p>
321                    </div>
322                    <div class="col-3 text-center">
323                      <h5 class="speedtest-h5">{{currentTexts.speedtest.Upload}}</h5>
324                      <p id="upload-speed" class="speedtest-h5" :class="updateSpeedTestColor(speedTestStatus)">
325                        {{speedTest.uploadSpeed}} <br />Mb/s
326                      </p>
327                    </div>
328                    <div class="col-3 text-center">
329                      <h5 class="speedtest-h5">{{currentTexts.speedtest.Latency}}</h5>
330                      <p id="latency" class="speedtest-h5" :class="updateSpeedTestColor(speedTestStatus)">
331                        {{speedTest.latency}} <br />ms</p>
332                    </div>
333                    <div class="col-3 text-center">
334                      <h5 class="speedtest-h5">{{currentTexts.speedtest.Jitter}}</h5>
335                      <p id="jitter" class="speedtest-h5" :class="updateSpeedTestColor(speedTestStatus)">
336                        {{speedTest.jitter}} <br />ms</p>
337                    </div>
338                  </div>
339                  <div id="result"></div>
340                </div>
341              </div>
342            </div>
343          </div>
344        </div>
345
346
347
348
349      </div>
350    </div>
351
352    <!-- Info Mask BTN-->
353    <button v-if="isInfosLoaded" class="btn position-fixed"
354      :class="infoMaskLevel === 0 ? 'btn-success' : infoMaskLevel === 1 ? 'btn-warning' : 'btn-secondary'"
355      style="bottom: 66px; right: 20px; z-index: 1050;" @click="toggleInfoMask">
356      <i :class="infoMaskLevel === 0 ? 'bi bi-eye' : 'bi bi-eye-slash'"></i>
357    </button>
358
359    <!-- Search BTN -->
360    <button class="btn btn-primary position-fixed" style="bottom: 20px; right: 20px; z-index: 1050;"
361      data-bs-toggle="modal" data-bs-target="#IPCheck"><i class="bi bi-search"></i></button>
362
363    <!-- Search Modal -->
364    <div class="modal fade" id="IPCheck" tabindex="-1" aria-labelledby="IPCheck" aria-hidden="true">
365      <div class="modal-dialog modal-dialog-centered">
366        <div class="modal-content" :class="{ 'dark-mode dark-mode-border': isDarkMode }">
367          <div class="modal-header" :class="{ 'dark-mode-border': isDarkMode }">
368            <h5 class="modal-title" id="IPCheck">{{currentTexts.ipcheck.Title}}</h5>
369            <button type="button" class="btn-close" :class="{ 'dark-mode-close-button': isDarkMode }"
370              data-bs-dismiss="modal" aria-label="Close"></button>
371
372          </div>
373          <div class="modal-body" :class="{ 'dark-mode': isDarkMode }">
374            <input type="text" class="form-control mb-2" :class="{ 'dark-mode': isDarkMode }"
375              :placeholder="currentTexts.ipcheck.Placeholder" v-model="inputIP" @keyup.enter="submitQuery">
376            <div v-if="modalQueryError" class="text-danger">{{ modalQueryError }}</div>
377            <div v-if="modalQueryResult" class="mt-2">
378              <div class="card-body">
379                <ul class="list-group list-group-flush">
380                  <li class="list-group-item jn-list-group-item" :class="{ 'dark-mode': isDarkMode }"><span
381                      class="jn-text">🖥️ {{currentTexts.ipInfos.IP}}</span>: {{
382                    modalQueryResult.ip }}
383                  </li>
384                  <li class="list-group-item jn-list-group-item" :class="{ 'dark-mode': isDarkMode }">
385                    <span class="jn-text">🌍 {{currentTexts.ipInfos.Country}}</span>: {{
386                    modalQueryResult.country_name }}&nbsp;<span v-if="modalQueryResult.country_code"
387                      :class="'flag-icon flag-icon-' + modalQueryResult.country_code.toLowerCase()"></span>
388                  </li>
389                  <li class="list-group-item jn-list-group-item" :class="{ 'dark-mode': isDarkMode }"><span
390                      class="jn-text">🏚️ {{currentTexts.ipInfos.Region}}</span>: {{
391                    modalQueryResult.region
392                    }}</li>
393                  <li class="list-group-item jn-list-group-item" :class="{ 'dark-mode': isDarkMode }"><span
394                      class="jn-text">🚏 {{currentTexts.ipInfos.City}}</span>: {{
395                    modalQueryResult.city }}
396                  </li>
397                  <li class="list-group-item jn-list-group-item" :class="{ 'dark-mode': isDarkMode }"><span
398                      class="jn-text">🏢 {{currentTexts.ipInfos.ISP}}</span>: {{
399                    modalQueryResult.isp }}
400                  </li>
401                  <li class="list-group-item jn-list-group-item" :class="{ 'dark-mode': isDarkMode }"><span
402                      class="jn-text">📶 {{currentTexts.ipInfos.ASN}}</span>: <a v-if="modalQueryResult.asnlink"
403                      :href="modalQueryResult.asnlink" target="_blank">{{
404                      modalQueryResult.asn }}</a><a v-else>{{ modalQueryResult.asn
405                      }}</a></li>
406                </ul>
407              </div>
408
409            </div>
410          </div>
411          <div class="modal-footer" :class="{ 'dark-mode-border': isDarkMode }">
412            <button type="button" class="btn btn-primary"
413              :class="{ 'btn-secondary': !isValidIP(inputIP), 'btn-primary': isValidIP(inputIP) }" @click="submitQuery"
414              :disabled="!isValidIP(inputIP)">{{currentTexts.ipcheck.Button}}</button>
415
416          </div>
417
418        </div>
419      </div>
420    </div>
421
422    <!-- BingMap Modal -->
423    <div class="modal fade" id="addBingMapKey" tabindex="-1" aria-labelledby="addBingMapKey" aria-hidden="true">
424      <div class="modal-dialog modal-dialog-centered">
425        <div class="modal-content" :class="{ 'dark-mode dark-mode-border': isDarkMode }">
426          <div class="modal-header" :class="{ 'dark-mode-border': isDarkMode }">
427            <h5 class="modal-title" id="addBingMapKey">{{currentTexts.addBingMapKey.Title}}</h5>
428            <button type="button" class="btn-close" :class="{ 'dark-mode-close-button': isDarkMode }"
429              data-bs-dismiss="modal" aria-label="Close"></button>
430
431          </div>
432          <div class="modal-body" :class="{ 'dark-mode': isDarkMode }">
433            <p class="fw-light">{{ currentTexts.addBingMapKey.Note }}</p>
434            <input type="text" class="form-control mb-2" :class="{ 'dark-mode': isDarkMode }"
435              :placeholder="currentTexts.addBingMapKey.Placeholder" v-model="inputBingMapAPIKEY"
436              @keyup.enter="addBingMapKey">
437            <div v-if="bingMapAPIKEYError" class="text-danger">{{ currentTexts.addBingMapKey.Error }}</div>
438
439
440          </div>
441          <div class="modal-footer" :class="{ 'dark-mode-border': isDarkMode }">
442            <button v-if="bingMapAPIKEY" type="button" class="btn btn-danger"
443              @click="removeBingMapKey">{{currentTexts.addBingMapKey.removeButton}}</button>
444
445            <button type="button" class="btn btn-primary"
446              :class="{ 'btn-secondary': !isValidKey(inputBingMapAPIKEY), 'btn-primary': isValidKey(inputBingMapAPIKEY) }"
447              @click="addBingMapKey"
448              :disabled="!isValidKey(inputBingMapAPIKEY)">{{currentTexts.addBingMapKey.Button}}</button>
449
450          </div>
451
452        </div>
453      </div>
454    </div>
455
456    <!-- help modal -->
457    <div class="modal fade" id="helpModal" tabindex="-1" aria-labelledby="helpModal" aria-hidden="true">
458      <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
459        <div class="modal-content" :class="{ 'dark-mode dark-mode-border': isDarkMode }">
460          <div class="modal-header" :class="{ 'dark-mode-border': isDarkMode }">
461            <h5 class="modal-title" id="helpModal">{{currentTexts.helpModal.Title}}</h5>
462            <button type="button" class="btn-close" :class="{ 'dark-mode-close-button': isDarkMode }"
463              data-bs-dismiss="modal" aria-label="Close"></button>
464
465          </div>
466          <div class="modal-body" :class="{'dark-mode' : isDarkMode }">
467            <p class="jn-help-note "><i class="bi bi-hand-thumbs-up-fill"></i> {{currentTexts.shortcutKeys.HelpNote}}
468            </p>
469            <div v-for="(key, index) in keyMap" :key="key.keys" class="row p-2 jn-shortcut-row"
470              :class="[ isDarkMode ? 'border-dark-subtle jn-dark-mode-help-border' : 'border-light-subtle', index === keyMap.length - 1 ? 'jn-border-bottom-none' : '' ]">
471              <div class="col">
472                <kbd :class="{ 'text-bg-light': isDarkMode }">
473                  {{ key.keys.replace(/[\[\]\\\(\)]/g, '') }}
474                </kbd>
475              </div>
476              <div class="col-8">{{ key.description }}</div>
477            </div>
478          </div>
479        </div>
480      </div>
481    </div>
482
483
484    <footer>
485      <p class="text-center">{{currentTexts.page.footerName}} <a :href="currentTexts.page.footerLink" class="link-dark"
486          target="_blank"><i class="bi bi-github" :class="{ 'dark-mode': isDarkMode }"></i></a>
487      </p>
488    </footer>
489
490  </div>
491
492
493  
493<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.bundle.min.js"
494    integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
495    crossorigin="anonymous"></script>
495
496
497  <!-- 引入 Vue.js -->
498  
498<script src="res/vue.js"></script>
498
499  
499<script type="module" src="res/app.js"></script>
499
500  <!-- 
500<script type="module" src="res/cfSpeedTest.js"></script>
500 -->
501
502  
502<script>
503    if ('serviceWorker' in navigator) {
504      window.addEventListener('load', function () {
505        navigator.serviceWorker.register('service-worker.js').then(function (registration) {
506          console.log('ServiceWorker Success : ', registration.scope);
507        }, function (err) {
508          console.log('ServiceWorker Error: ', err);
509        });
510      });
511    }
512  </script>
512
513
514<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"eea42aa2a4a0421b81d77a89273043a3","r":1,"spa":2}' crossorigin="anonymous"></script>
vendor: 1 bytes, line 514
514
515<script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a4668d02bd612af4',t:'MTc5MTMwOTQ3MQ=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>
515</body>
516
517</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.