| <!-- | |
| Licensed to the Apache Software Foundation (ASF) under one | |
| or more contributor license agreements. See the NOTICE file | |
| distributed with this work for additional information | |
| regarding copyright ownership. The ASF licenses this file | |
| to you under the Apache License, Version 2.0 (the | |
| "License"); you may not use this file except in compliance | |
| with the License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, | |
| software distributed under the License is distributed on an | |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| KIND, either express or implied. See the License for the | |
| specific language governing permissions and limitations | |
| under the License. | |
| --> | |
| {{define "header"}} | |
| <!DOCTYPE html> | |
| <html lang="{{.lang}}"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <title>{{.title}}</title> | |
| <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> | |
| <meta name="theme-color" /> | |
| <meta name="description" content="{{.description}}" data-rh="true" /> | |
| <meta name="generator" content="Answer {{.Version}} - https://github.com/apache/answer version {{.Revision}}"> | |
| {{if .keywords }}<meta name="keywords" content="{{.keywords}}" data-rh="true" />{{end}} | |
| {{if .noindex }}<meta name="robots" content="noindex">{{end}} | |
| <link rel="canonical" href="{{.siteinfo.Canonical}}" /> | |
| <link rel="manifest" href="{{$.baseURL}}/manifest.json" /> | |
| <link rel="search" type="application/opensearchdescription+xml" href="{{$.baseURL}}/opensearch.xml" title="{{.siteinfo.General.Name}}" /> | |
| {{range $path := .cssPath}} | |
| <link href="{{$path}}" rel="stylesheet" /> | |
| {{end}} | |
| <link href="{{$.baseURL}}/custom.css" rel="stylesheet" /> | |
| <link | |
| rel="icon" | |
| type="image/png" | |
| href="{{if $.siteinfo.Branding.Favicon }}{{$.siteinfo.Branding.Favicon}}{{else}}{{$.baseURL}}/favicon.ico{{end}}" | |
| data-rh="true" | |
| /> | |
| <link | |
| rel="icon" | |
| type="image/png" | |
| sizes="192x192" | |
| href="{{.siteinfo.Branding.SquareIcon}}" | |
| data-rh="true" | |
| /> | |
| <link | |
| rel="apple-touch-icon" | |
| type="image/png" | |
| href="{{.siteinfo.Branding.SquareIcon}}" | |
| data-rh="true" | |
| /> | |
| {{range $path := .scriptPath}} | |
| <script type="module" crossorigin src="{{$path}}"></script> | |
| {{end}} | |
| {{if $.siteinfo.JsonLD }}{{ .siteinfo.JsonLD | templateHTML}}{{end}} | |
| <meta property="og:type" content="website" /> | |
| <meta property="og:title" name="twitter:title" content="{{.title}}" /> | |
| <meta property="og:site_name" content="{{.siteinfo.General.Name}}" /> | |
| <meta property="og:url" content="{{.siteinfo.Canonical}}" /> | |
| <meta property="og:description" content="{{.description}}" /> | |
| <meta | |
| property="og:image" | |
| itemProp="image primaryImageOfPage" | |
| content="{{if $.siteinfo.Branding.Favicon }}{{$.siteinfo.Branding.Favicon}}{{else}}{{$.baseURL}}/favicon.ico{{end}}" | |
| /> | |
| <meta name="twitter:card" content="summary" /> | |
| <meta name="twitter:domain" content="{{.siteinfo.General.SiteUrl}}" /> | |
| <meta name="twitter:description" content="{{.description}}" /> | |
| <meta | |
| name="twitter:image" | |
| content="{{if $.siteinfo.Branding.Favicon }}{{$.siteinfo.Branding.Favicon}}{{else}}{{$.baseURL}}/favicon.ico{{end}}" | |
| /> | |
| <meta name="go-template"> | |
| <!--customize_head--> | |
| {{if .HeadCode }} {{.HeadCode | templateHTML}} {{end}} | |
| <!--customize_head--> | |
| </head> | |
| <body> | |
| <!--customize_header--> | |
| {{if .HeaderCode }} {{.HeaderCode | templateHTML}} {{end}} | |
| <!--customize_header--> | |
| <div id="root"> | |
| <div id="spin-mask"> | |
| <noscript> | |
| <style> | |
| #spin-mask { | |
| display: none !important; | |
| } | |
| #protect-browser { | |
| display: none; | |
| } | |
| </style> | |
| </noscript> | |
| <style> | |
| @keyframes _doc-spin { | |
| to { transform: rotate(360deg) } | |
| } | |
| #spin-mask { | |
| position: fixed; | |
| top: 0; | |
| right: 0; | |
| bottom: 0; | |
| left: 0; | |
| background-color: white; | |
| z-index: 9999; | |
| } | |
| #spin-container { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| } | |
| #spin-container .spinner { | |
| box-sizing: border-box; | |
| display: inline-block; | |
| width: 2rem; | |
| height: 2rem; | |
| vertical-align: -.125em; | |
| border: .25rem solid currentColor; | |
| border-right-color: transparent; | |
| color: rgba(108, 117, 125, .75); | |
| border-radius: 50%; | |
| animation: 0.75s linear infinite _doc-spin; | |
| } | |
| #protect-browser { | |
| padding: 20px; | |
| text-align: center; | |
| } | |
| </style> | |
| <div id="spin-container"> | |
| <div class="spinner"></div> | |
| </div> | |
| <div id="protect-browser"></div> | |
| </div> | |
| <nav id="header" class="sticky-top theme-dark navbar navbar-expand-xl navbar-light"> | |
| <div class="w-100 d-flex align-items-center px-3"> | |
| <button | |
| aria-controls="navBarContent" | |
| type="button" | |
| aria-label="Toggle navigation" | |
| class="answer-navBar me-2 navbar-toggler collapsed" | |
| > | |
| <span class="navbar-toggler-icon"></span> | |
| </button> | |
| <div | |
| class="d-flex justify-content-between align-items-center nav-grow flex-nowrap" | |
| > | |
| {{if .siteinfo.Branding.Logo}} | |
| <a class="lh-1 me-0 me-sm-5 p-0 navbar-brand" href="{{$.baseURL}}/"> | |
| <img class="logo me-0" src="{{.siteinfo.Branding.Logo}}" alt="{{.siteinfo.General.Name}}"> | |
| </a> | |
| {{else}} | |
| <a class="lh-1 me-0 me-sm-3 navbar-brand" href="{{$.baseURL}}/"> | |
| {{.siteinfo.General.Name}} | |
| </a> | |
| {{end}} | |
| </div> | |
| <div class="d-none d-xl-block flex-grow-1 me-auto"> | |
| <div class="d-none d-xl-block ps-0 col-lg-8"> | |
| <form action="/search" class="w-100 maxw-400"> | |
| <input placeholder="Search" name="q" type="search" class="placeholder-search form-control" value=""> | |
| </form> | |
| </div> | |
| <!-- <div class="xl-none mt-3 pb-1 nav-item"> | |
| <a class="text-capitalize text-nowrap btn btn-light" href="/questions/add">{{translator $.language "ui.btns.add_question"}}</a> | |
| </div> --> | |
| <div class="d-none d-xl-flex justify-content-start justify-content-sm-end col-lg-4"> | |
| <!-- <a role="button" tabindex="0" href="/users/login" class="me-2 link-light btn btn-link"> | |
| {{translator $.language "ui.btns.login"}} | |
| </a> | |
| <a role="button" tabindex="0" href="/users/register" class="btn btn-light"> | |
| {{translator $.language "ui.btns.signup"}} | |
| </a> --> | |
| </div> | |
| </div> | |
| </div> | |
| </nav> | |
| <div class="position-relative page-wrap d-flex flex-column flex-fill"> | |
| <div class="d-flex"> | |
| <div class="position-sticky px-3 border-end pt-4 d-none d-xl-block" id="pcSideNav"> | |
| {{template "sidenav" . }} | |
| </div> | |
| <div class="flex-fill w-100 overflow-x-hidden"> | |
| {{end}} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </body> | |
| <script> | |
| /** | |
| * @description: Prompt that the browser version is too low | |
| */ | |
| const defaultList = [ | |
| { | |
| name: 'Edge', | |
| version: '100' | |
| }, | |
| { | |
| name: 'Firefox', | |
| version: '100' | |
| }, | |
| { | |
| name: 'Chrome', | |
| version: '90' | |
| }, | |
| { | |
| name: 'Safari', | |
| version: '15' | |
| }, | |
| { | |
| name: 'IE', | |
| } | |
| ]; | |
| function getBrowserTypeAndVersion(){ | |
| var browser = { | |
| name: '', | |
| version: '' | |
| }; | |
| var ua = navigator.userAgent.toLowerCase(); | |
| var s; | |
| ((ua.indexOf("compatible") > -1 && ua.indexOf("MSIE") > -1) || (ua.indexOf('Trident') > -1 && ua.indexOf("rv:11.0") > -1)) ? browser = { name: 'IE', version: '' } : | |
| (s = ua.match(/edge\/([\d\.]+)/)) ? browser = { name: 'Edge', version: s[1] } : | |
| (s = ua.match(/firefox\/([\d\.]+)/)) ? browser = { name: 'Firefox', version: s[1] } : | |
| (s = ua.match(/chrome\/([\d\.]+)/)) ? browser = { name: 'Chrome', version: s[1] } : | |
| (s = ua.match(/version\/([\d\.]+).*safari/)) ? browser = { name: 'Safari', version: s[1] } : browser = { name: 'unknown', version: '' }; | |
| // 根据关系进行判断 | |
| return browser; | |
| } | |
| function compareVersion(version1, version2) { | |
| var v1 = version1.split('.'); | |
| var v2 = version2.split('.'); | |
| var len = Math.max(v1.length, v2.length); | |
| while (v1.length < len) { | |
| v1.push('0'); | |
| } | |
| while (v2.length < len) { | |
| v2.push('0'); | |
| } | |
| for (var i = 0; i < len; i++) { | |
| var num1 = parseInt(v1[i]); | |
| var num2 = parseInt(v2[i]); | |
| if (num1 >= num2) { | |
| return 1; | |
| } else if (num1 < num2) { | |
| return -1; | |
| } | |
| } | |
| return 0; | |
| } | |
| const browserInfo = getBrowserTypeAndVersion(); | |
| if (browserInfo.name === 'IE') { | |
| const div = document.getElementById('protect-browser'); | |
| div.innerText = 'Sorry, this site does not support Internet Explorer. In order to avoid affecting the normal use of our features, please use a more modern browser such as Edge, Firefox, Chrome, or Safari.' | |
| } else { | |
| const notSupport = defaultList.some(item => { | |
| if (item.name === browserInfo.name) { | |
| return compareVersion(browserInfo.version, item.version) === -1; | |
| } | |
| return false; | |
| }); | |
| if (notSupport) { | |
| const div = document.getElementById('protect-browser'); | |
| div.innerText = 'The current browser version is too low, in order not to affect the normal use of the function, please upgrade the browser to the latest version.' | |
| } | |
| } | |
| </script> | |
| </html> |