DOCS-1: Init document work
This commit is contained in:
184
templates/admin_edit.html
Normal file
184
templates/admin_edit.html
Normal file
@@ -0,0 +1,184 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
<title>{{if .Page}}Edit: {{.Page.Title}}{{else}}New Page{{end}} — Admin — Arcline</title>
|
||||
<meta name="robots" content="noindex">
|
||||
<style>
|
||||
.admin-wrap { max-width:860px; margin:2.5rem auto; padding:0 1.5rem; }
|
||||
.admin-header{ display:flex; align-items:center; gap:1rem; margin-bottom:1.75rem; }
|
||||
.admin-header h1 { font-size:1.375rem; font-weight:800; color:var(--text-strong); margin:0; }
|
||||
.form-grid { display:grid; grid-template-columns:1fr 1fr; gap:1rem; }
|
||||
.form-group { display:flex; flex-direction:column; gap:.375rem; }
|
||||
.form-group--full { grid-column:1/-1; }
|
||||
label { font-size:.8125rem; font-weight:600; color:var(--text-strong); }
|
||||
input[type=text], input[type=number], select, textarea {
|
||||
font-family:var(--mono); font-size:.875rem;
|
||||
padding:.5rem .75rem; border:1px solid var(--border);
|
||||
border-radius:var(--radius-sm); background:var(--white);
|
||||
color:var(--text-strong); width:100%; box-sizing:border-box;
|
||||
transition:border-color var(--t);
|
||||
}
|
||||
input:focus, select:focus, textarea:focus { outline:none; border-color:var(--accent); }
|
||||
textarea { font-family:var(--mono); font-size:.8125rem; min-height:420px; resize:vertical; line-height:1.6; }
|
||||
.vis-row { display:flex; gap:.75rem; align-items:center; flex-wrap:wrap; }
|
||||
.vis-radio { display:flex; align-items:center; gap:.375rem; font-size:.875rem; cursor:pointer; }
|
||||
.form-hint { font-size:.75rem; color:var(--text-muted); margin-top:.25rem; }
|
||||
.form-actions{ display:flex; gap:.75rem; margin-top:1.5rem; align-items:center; }
|
||||
.error-box { background:#fef2f2; border:1px solid #fca5a5; border-left:3px solid #ef4444;
|
||||
border-radius:var(--radius-sm); padding:.875rem 1.125rem; margin-bottom:1.25rem;
|
||||
font-size:.9rem; color:#991b1b; }
|
||||
#vis-plan-wrap, #vis-customer-wrap { display:none; }
|
||||
@media(max-width:640px){ .form-grid{ grid-template-columns:1fr; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{template "nav" .}}
|
||||
|
||||
<div class="admin-wrap">
|
||||
<div class="admin-header">
|
||||
<h1>{{if .Page}}Edit page{{else}}New page{{end}}</h1>
|
||||
</div>
|
||||
|
||||
{{if .Error}}
|
||||
<div class="error-box">{{.Error}}</div>
|
||||
{{end}}
|
||||
|
||||
<form method="POST"
|
||||
action="{{if .Page}}/admin/pages/{{.Page.ID}}{{else}}/admin/pages{{end}}">
|
||||
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
||||
|
||||
<div class="form-grid">
|
||||
<div class="form-group">
|
||||
<label for="title">Title</label>
|
||||
<input type="text" id="title" name="title" required
|
||||
value="{{if .Page}}{{.Page.Title}}{{end}}"
|
||||
placeholder="e.g. Server Setup Guide">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="slug">Slug</label>
|
||||
<input type="text" id="slug" name="slug" required
|
||||
value="{{if .Page}}{{.Page.Slug}}{{end}}"
|
||||
placeholder="e.g. server-setup-guide">
|
||||
<span class="form-hint">URL: /client/<em>slug</em>/</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group--full">
|
||||
<label for="description">Description <span style="font-weight:400;color:var(--text-muted)">(optional)</span></label>
|
||||
<input type="text" id="description" name="description"
|
||||
value="{{if .Page}}{{.Page.Description}}{{end}}"
|
||||
placeholder="Short summary shown in listings">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="section">Section</label>
|
||||
<input type="text" id="section" name="section"
|
||||
value="{{if .Page}}{{.Page.Section}}{{else}}client{{end}}"
|
||||
placeholder="client">
|
||||
<span class="form-hint">Use "client" for customer-facing docs.</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="display_order">Display order</label>
|
||||
<input type="number" id="display_order" name="display_order" min="0"
|
||||
value="{{if .Page}}{{.Page.DisplayOrder}}{{else}}0{{end}}">
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group--full">
|
||||
<label>Visibility</label>
|
||||
<div class="vis-row">
|
||||
<label class="vis-radio">
|
||||
<input type="radio" name="vis_type" value="public"
|
||||
{{if or (not .Page) (eq .Page.Visibility "public")}}checked{{end}}>
|
||||
Public
|
||||
</label>
|
||||
<label class="vis-radio">
|
||||
<input type="radio" name="vis_type" value="plan"
|
||||
{{if and .Page (hasPrefix .Page.Visibility "plan:")}}checked{{end}}>
|
||||
Plan
|
||||
</label>
|
||||
<label class="vis-radio">
|
||||
<input type="radio" name="vis_type" value="customer"
|
||||
{{if and .Page (hasPrefix .Page.Visibility "customer:")}}checked{{end}}>
|
||||
Customer
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div id="vis-plan-wrap" style="margin-top:.5rem;">
|
||||
<select name="vis_plan" id="vis_plan">
|
||||
{{range .PlanOptions}}
|
||||
<option value="{{.Key}}"
|
||||
{{if and $.Page (eq $.Page.Visibility (print "plan:" .Key))}}selected{{end}}>
|
||||
{{.Name}}
|
||||
</option>
|
||||
{{end}}
|
||||
</select>
|
||||
<span class="form-hint">Visible to all customers on this plan with an active subscription.</span>
|
||||
</div>
|
||||
|
||||
<div id="vis-customer-wrap" style="margin-top:.5rem;">
|
||||
<select name="vis_customer" id="vis_customer">
|
||||
{{range .Customers}}
|
||||
<option value="{{.ID}}"
|
||||
{{if and $.Page (eq $.Page.Visibility (print "customer:" .ID))}}selected{{end}}>
|
||||
{{.FirstName}} {{.LastName}} ({{.Email}})
|
||||
</option>
|
||||
{{end}}
|
||||
</select>
|
||||
<span class="form-hint">Visible to this customer only.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group--full">
|
||||
<label for="content">Content <span style="font-weight:400;color:var(--text-muted)">(Markdown)</span></label>
|
||||
<textarea id="content" name="content" placeholder="Write markdown here...">{{if .Page}}{{.Page.Content}}{{end}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn--primary">{{if .Page}}Save changes{{else}}Create page{{end}}</button>
|
||||
<a href="/admin/" class="btn btn--ghost">Cancel</a>
|
||||
{{if .Page}}
|
||||
<a href="/client/{{.Page.Slug}}/" class="btn btn--ghost btn--sm" target="_blank"
|
||||
style="margin-left:auto;">View page →</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{template "footer-simple" .}}
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var radios = document.querySelectorAll('[name="vis_type"]');
|
||||
var planWrap = document.getElementById('vis-plan-wrap');
|
||||
var custWrap = document.getElementById('vis-customer-wrap');
|
||||
|
||||
function update() {
|
||||
var val = document.querySelector('[name="vis_type"]:checked');
|
||||
if (!val) return;
|
||||
planWrap.style.display = val.value === 'plan' ? 'block' : 'none';
|
||||
custWrap.style.display = val.value === 'customer' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
radios.forEach(function(r) { r.addEventListener('change', update); });
|
||||
update();
|
||||
|
||||
var titleInput = document.getElementById('title');
|
||||
var slugInput = document.getElementById('slug');
|
||||
var slugTouched = slugInput.value !== '';
|
||||
|
||||
titleInput.addEventListener('input', function() {
|
||||
if (slugTouched) return;
|
||||
slugInput.value = titleInput.value
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-+|-+$/g, '');
|
||||
});
|
||||
slugInput.addEventListener('input', function() { slugTouched = true; });
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
87
templates/admin_pages.html
Normal file
87
templates/admin_pages.html
Normal file
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
<title>Admin — Docs — Arcline</title>
|
||||
<meta name="robots" content="noindex">
|
||||
<style>
|
||||
.admin-wrap { max-width:900px; margin:2.5rem auto; padding:0 1.5rem; }
|
||||
.admin-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:1.75rem; }
|
||||
.admin-header h1 { font-size:1.5rem; font-weight:800; color:var(--text-strong); }
|
||||
.admin-table { width:100%; border-collapse:collapse; font-size:0.875rem; }
|
||||
.admin-table th { background:var(--bg); font-size:.72rem; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:var(--text-muted); padding:.625rem 1rem; text-align:left; border-bottom:1px solid var(--border); }
|
||||
.admin-table td { padding:.75rem 1rem; color:var(--text); border-bottom:1px solid var(--border-subtle); vertical-align:middle; line-height:1.4; }
|
||||
.admin-table tr:last-child td { border-bottom:none; }
|
||||
.admin-table tr:hover td { background:var(--bg); }
|
||||
.vis-badge { display:inline-block; font-size:.7rem; font-weight:600; padding:.2em .5em; border-radius:3px; background:var(--border-subtle); color:var(--text-muted); white-space:nowrap; }
|
||||
.vis-badge--public { background:var(--accent-light); color:var(--accent); }
|
||||
.vis-badge--plan { background:#fef3c7; color:#92400e; }
|
||||
.vis-badge--cust { background:#ede9fe; color:#5b21b6; }
|
||||
.action-btns { display:flex; gap:.5rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{template "nav" .}}
|
||||
|
||||
<div class="admin-wrap">
|
||||
<div class="admin-header">
|
||||
<h1>Docs Admin</h1>
|
||||
<a href="/admin/pages/new" class="btn btn--primary btn--sm">+ New page</a>
|
||||
</div>
|
||||
|
||||
{{if .Pages}}
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Slug</th>
|
||||
<th>Section</th>
|
||||
<th>Visibility</th>
|
||||
<th>Order</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Pages}}
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{.Title}}</strong>
|
||||
{{if .Description}}<br><span style="color:var(--text-muted);font-size:.8rem;">{{.Description}}</span>{{end}}
|
||||
</td>
|
||||
<td><code style="font-size:.8rem;">{{.Slug}}</code></td>
|
||||
<td>{{.Section}}</td>
|
||||
<td>
|
||||
{{$v := visLabel .Visibility}}
|
||||
{{if eq .Visibility "public"}}
|
||||
<span class="vis-badge vis-badge--public">{{$v}}</span>
|
||||
{{else if hasPrefix .Visibility "plan:"}}
|
||||
<span class="vis-badge vis-badge--plan">{{$v}}</span>
|
||||
{{else}}
|
||||
<span class="vis-badge vis-badge--cust">{{$v}}</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td>{{.DisplayOrder}}</td>
|
||||
<td>
|
||||
<div class="action-btns">
|
||||
<a href="/client/{{.Slug}}/" class="btn btn--ghost btn--sm" target="_blank">View</a>
|
||||
<a href="/admin/pages/{{.ID}}/edit" class="btn btn--ghost btn--sm">Edit</a>
|
||||
<form method="POST" action="/admin/pages/{{.ID}}/delete" style="margin:0;"
|
||||
onsubmit="return confirm('Delete {{.Title}}?')">
|
||||
<input type="hidden" name="csrf_token" value="{{$.CSRFToken}}">
|
||||
<button class="btn btn--danger btn--sm" type="submit">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p style="color:var(--text-muted);">No pages yet. <a href="/admin/pages/new">Create the first one.</a></p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{template "footer-simple" .}}
|
||||
</body>
|
||||
</html>
|
||||
39
templates/client_index.html
Normal file
39
templates/client_index.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
<title>My Docs — Arcline</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{template "nav" .}}
|
||||
|
||||
<main class="docs-main">
|
||||
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||||
<a href="/">Docs</a>
|
||||
<span class="breadcrumb__sep">/</span>
|
||||
<span>My Docs</span>
|
||||
</nav>
|
||||
|
||||
<article class="docs-article">
|
||||
<h1>My Docs</h1>
|
||||
<p>Private documentation and guides for your Arcline account.</p>
|
||||
</article>
|
||||
|
||||
{{if .Pages}}
|
||||
<div class="section-index">
|
||||
{{range .Pages}}
|
||||
<a href="/client/{{.Slug}}/" class="section-index__card">
|
||||
<span class="section-index__title">{{.Title}}</span>
|
||||
{{if .Description}}<span class="section-index__desc">{{.Description}}</span>{{end}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else}}
|
||||
<p style="color:var(--text-muted);margin-top:1.5rem;">No private documentation has been added to your account yet.</p>
|
||||
{{end}}
|
||||
</main>
|
||||
|
||||
{{template "footer-simple" .}}
|
||||
</body>
|
||||
</html>
|
||||
34
templates/client_page.html
Normal file
34
templates/client_page.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
<title>{{.Page.Title}} — My Docs — Arcline</title>
|
||||
{{if .Page.Description}}<meta name="description" content="{{.Page.Description}}">{{end}}
|
||||
<meta name="robots" content="noindex">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{template "nav" .}}
|
||||
|
||||
<main class="docs-main">
|
||||
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||||
<a href="/">Docs</a>
|
||||
<span class="breadcrumb__sep">/</span>
|
||||
<a href="/client/">My Docs</a>
|
||||
<span class="breadcrumb__sep">/</span>
|
||||
<span>{{.Page.Title}}</span>
|
||||
</nav>
|
||||
|
||||
<article class="docs-article">
|
||||
{{if .IsAdmin}}
|
||||
<div style="margin-bottom:1.25rem;">
|
||||
<a href="/admin/pages/{{.Page.ID}}/edit" class="btn btn--ghost btn--sm">Edit this page</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{.Content}}
|
||||
</article>
|
||||
</main>
|
||||
|
||||
{{template "footer-simple" .}}
|
||||
</body>
|
||||
</html>
|
||||
181
templates/layout.html
Normal file
181
templates/layout.html
Normal file
@@ -0,0 +1,181 @@
|
||||
{{define "head"}}
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/css/fonts.css">
|
||||
<link rel="stylesheet" href="/css/base.css">
|
||||
<link rel="stylesheet" href="/css/docs.css">
|
||||
<link rel="icon" type="image/svg+xml" href="/public/favicon.svg">
|
||||
<meta property="og:image" content="https://arcline.it/public/brand/og-image.png">
|
||||
<meta property="og:site_name" content="Arcline Docs">
|
||||
{{end}}
|
||||
|
||||
{{define "nav"}}
|
||||
<header class="nav">
|
||||
<div class="container nav__inner">
|
||||
<a href="https://arcline.it" class="nav__logo" aria-label="Arcline home">
|
||||
<svg width="22" height="22" viewBox="0 0 32 32" fill="none" aria-hidden="true">
|
||||
<path d="M5 27L16 5L27 27" stroke="#00c8f0" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9 20H23" stroke="#00c8f0" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
Arcline
|
||||
</a>
|
||||
<a href="/" class="nav__docs-badge">docs</a>
|
||||
{{if .Nav}}
|
||||
<div class="nav__docs-menu">
|
||||
<button class="nav__browse-btn" id="browse-btn" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="label">Browse</span>
|
||||
</button>
|
||||
<nav class="nav__dropdown" id="browse-dropdown" role="menu" aria-label="Documentation sections">
|
||||
{{range .Nav}}
|
||||
<p class="nav__dropdown-section">{{.Title}}</p>
|
||||
{{range .Pages}}
|
||||
<a href="{{.URL}}" class="nav__dropdown-link{{if .Active}} nav__dropdown-link--active{{end}}" role="menuitem">{{.Title}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</nav>
|
||||
</div>
|
||||
<div class="nav__search-wrap search-wrap">
|
||||
<input type="search" id="search-input" class="nav__search" placeholder="Search docs… (⌘K)" autocomplete="off" aria-label="Search documentation">
|
||||
<div id="search-results" class="search-results" hidden role="listbox" aria-label="Search results"></div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="nav__actions">
|
||||
{{if .Customer}}
|
||||
<a href="/client/" class="btn btn--ghost btn--sm">My Docs</a>
|
||||
{{if .IsAdmin}}<a href="/admin/" class="btn btn--ghost btn--sm">Admin</a>{{end}}
|
||||
<a href="/logout" class="btn btn--ghost btn--sm">Log out</a>
|
||||
{{else}}
|
||||
<a href="https://arcline.it/pricing" class="btn btn--ghost btn--sm">Hosting plans</a>
|
||||
<a href="https://arcline.it/contact" class="btn btn--primary btn--sm">Get started</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<button class="nav__hamburger" aria-label="Toggle navigation" aria-expanded="false" id="hamburger">
|
||||
<span></span><span></span><span></span>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{{if .Nav}}
|
||||
<nav class="nav__mobile" id="mobile-nav" aria-label="Mobile navigation">
|
||||
{{range .Nav}}
|
||||
<p class="nav__mobile-section">{{.Title}}</p>
|
||||
{{range .Pages}}
|
||||
<a href="{{.URL}}"{{if .Active}} class="active"{{end}}>{{.Title}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div class="nav__mobile-actions">
|
||||
{{if $.Customer}}
|
||||
<a href="/client/" class="btn btn--ghost btn--sm">My Docs</a>
|
||||
<a href="/logout" class="btn btn--ghost btn--sm">Log out</a>
|
||||
{{else}}
|
||||
<a href="https://arcline.it/contact" class="btn btn--primary btn--sm">Get started</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
// Hamburger toggle (mobile)
|
||||
var btn = document.getElementById('hamburger');
|
||||
var nav = document.getElementById('mobile-nav');
|
||||
if (btn && nav) {
|
||||
btn.addEventListener('click', function() {
|
||||
var open = nav.classList.toggle('open');
|
||||
btn.setAttribute('aria-expanded', open);
|
||||
});
|
||||
}
|
||||
|
||||
// Browse dropdown toggle (desktop)
|
||||
var browseBtn = document.getElementById('browse-btn');
|
||||
var dropdown = document.getElementById('browse-dropdown');
|
||||
if (browseBtn && dropdown) {
|
||||
browseBtn.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
var open = dropdown.classList.toggle('open');
|
||||
browseBtn.setAttribute('aria-expanded', open);
|
||||
});
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!e.target.closest('.nav__docs-menu')) {
|
||||
dropdown.classList.remove('open');
|
||||
browseBtn.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
});
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
dropdown.classList.remove('open');
|
||||
browseBtn.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
{{define "footer"}}
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="footer__grid">
|
||||
<div class="footer__brand">
|
||||
<a href="https://arcline.it" class="footer__logo" aria-label="Arcline home">
|
||||
<svg width="18" height="18" viewBox="0 0 32 32" fill="none" aria-hidden="true">
|
||||
<path d="M5 27L16 5L27 27" stroke="#00c8f0" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9 20H23" stroke="#00c8f0" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
Arcline
|
||||
</a>
|
||||
<p class="footer__tagline">IT infrastructure built for reliability, privacy, and independence. No cloud lock-in. No middlemen. No surprises.</p>
|
||||
<a href="https://arcline.it/status" class="footer__status">All Systems Operational</a>
|
||||
</div>
|
||||
<div>
|
||||
<p class="footer__col-title">Services</p>
|
||||
<ul class="footer__links">
|
||||
<li><a href="https://arcline.it/services" class="footer__link">Server setup & management</a></li>
|
||||
<li><a href="https://arcline.it/services" class="footer__link">Network security</a></li>
|
||||
<li><a href="https://arcline.it/pricing" class="footer__link">Web hosting</a></li>
|
||||
<li><a href="https://arcline.it/contact" class="footer__link">Contact us</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p class="footer__col-title">Docs</p>
|
||||
<ul class="footer__links">
|
||||
<li><a href="/getting-started/" class="footer__link">Getting started</a></li>
|
||||
<li><a href="/migrate/" class="footer__link">Migration guides</a></li>
|
||||
{{if .Customer}}<li><a href="/client/" class="footer__link">My Docs</a></li>{{end}}
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p class="footer__col-title">Support</p>
|
||||
<ul class="footer__links">
|
||||
<li><a href="https://arcline.it/contact" class="footer__link">Open a ticket</a></li>
|
||||
<li><a href="https://arcline.it/faq" class="footer__link">FAQ</a></li>
|
||||
<li><a href="https://arcline.it/about" class="footer__link">About Arcline</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer__bottom">
|
||||
<p class="footer__copy">© {{.Year}} Arcline IT LLC. All rights reserved.</p>
|
||||
<nav class="footer__legal" aria-label="Legal links">
|
||||
<a href="https://arcline.it/tos">Terms of service</a>
|
||||
<a href="https://arcline.it/privacy">Privacy policy</a>
|
||||
<a href="https://arcline.it/aup">AUP</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
{{end}}
|
||||
|
||||
{{define "footer-simple"}}
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="footer__bottom">
|
||||
<p class="footer__copy">© {{.Year}} Arcline IT LLC. All rights reserved.</p>
|
||||
<nav class="footer__legal" aria-label="Legal links">
|
||||
<a href="https://arcline.it/tos">Terms of service</a>
|
||||
<a href="https://arcline.it/privacy">Privacy policy</a>
|
||||
<a href="https://arcline.it/aup">AUP</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
{{end}}
|
||||
94
templates/page.html
Normal file
94
templates/page.html
Normal file
@@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
<title>{{.Title}}</title>
|
||||
{{if .Description}}<meta name="description" content="{{.Description}}">{{end}}
|
||||
{{if .Canonical}}<link rel="canonical" href="{{.Canonical}}">{{end}}
|
||||
<meta name="docs-root" content="/">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="{{.Title}}">
|
||||
{{if .Description}}<meta property="og:description" content="{{.Description}}">{{end}}
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{template "nav" .}}
|
||||
|
||||
<main class="docs-main" id="main-content">
|
||||
|
||||
{{if .Breadcrumbs}}
|
||||
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||||
<a href="/">Docs</a>
|
||||
{{range .Breadcrumbs}}
|
||||
<span class="breadcrumb__sep">/</span>
|
||||
{{if .URL}}<a href="{{.URL}}">{{.Label}}</a>{{else}}<span>{{.Label}}</span>{{end}}
|
||||
{{end}}
|
||||
</nav>
|
||||
{{end}}
|
||||
|
||||
<article class="docs-article">
|
||||
{{if .Nav}}
|
||||
<nav class="docs-toc" aria-label="Table of contents">
|
||||
<details class="docs-toc__details" open>
|
||||
<summary class="docs-toc__summary">On this page</summary>
|
||||
<div class="docs-toc__links" id="docs-toc-links">
|
||||
<!-- Populated by JS from h2/h3 headings -->
|
||||
</div>
|
||||
</details>
|
||||
</nav>
|
||||
{{end}}
|
||||
|
||||
{{.Content}}
|
||||
</article>
|
||||
|
||||
{{if or .Prev .Next}}
|
||||
<nav class="docs-pager" aria-label="Next and previous pages">
|
||||
<div class="docs-pager__side">
|
||||
{{if .Prev}}
|
||||
<a href="{{.Prev.URL}}" class="docs-pager__link docs-pager__link--prev">
|
||||
<span class="docs-pager__dir">← Previous</span>
|
||||
<span class="docs-pager__title">{{.Prev.Title}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="docs-pager__side docs-pager__side--right">
|
||||
{{if .Next}}
|
||||
<a href="{{.Next.URL}}" class="docs-pager__link docs-pager__link--next">
|
||||
<span class="docs-pager__dir">Next →</span>
|
||||
<span class="docs-pager__title">{{.Next.Title}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
</main>
|
||||
|
||||
{{template "footer" .}}
|
||||
<script src="/js/search.js"></script>
|
||||
<script>
|
||||
(function() {
|
||||
// Inline table of contents — auto-generated from h2 and h3 headings.
|
||||
var toc = document.getElementById('docs-toc-links');
|
||||
if (!toc) return;
|
||||
var headings = document.querySelectorAll('.docs-article h2, .docs-article h3');
|
||||
if (headings.length < 2) { toc.parentElement.hidden = true; return; }
|
||||
var html = '<ul class="docs-toc__list">';
|
||||
var stack = ['ul'];
|
||||
var prevLevel = 2;
|
||||
headings.forEach(function(h) {
|
||||
var level = h.tagName === 'H2' ? 2 : 3;
|
||||
var id = h.id || '';
|
||||
if (!id) { id = h.textContent.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, ''); h.id = id; }
|
||||
if (level > prevLevel) { html += '<ul class="docs-toc__sublist">'; stack.push('ul'); }
|
||||
while (level < prevLevel && stack.length > 1) { html += '</' + stack.pop() + '>'; prevLevel--; }
|
||||
html += '<li class="docs-toc__item' + (level === 3 ? ' docs-toc__item--sub' : '') + '">' +
|
||||
'<a href="#' + id + '">' + h.textContent + '</a></li>';
|
||||
prevLevel = level;
|
||||
});
|
||||
while (stack.length > 1) { html += '</' + stack.pop() + '>'; }
|
||||
html += '</ul>';
|
||||
toc.innerHTML = html;
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user