mirror of https://github.com/writeas/writefreely
parent
8f08de02b8
commit
af872127c6
@ -0,0 +1,24 @@ |
|||||||
|
{{define "head"}}<title>About {{.SiteName}}</title> |
||||||
|
{{end}} |
||||||
|
{{define "content"}}<div class="content-container" style="margin-top: 2em;"> |
||||||
|
<div class="content-container"> |
||||||
|
<div class="marketing-section"> |
||||||
|
<div class="clearfix blurbs"> |
||||||
|
<div class="third big"> |
||||||
|
<h3>Simple and focused</h3> |
||||||
|
<p>Write.as isn't a platform for building <em>any</em> kind of blog or website. It's meant to help you get your thoughts down—and published—fast.</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="third big"> |
||||||
|
<h3>Distraction-free</h3> |
||||||
|
<p>Our editor lets you write and publish — that's it. And we separated the <a href="https://read.write.as">reading</a> experience so there's no stream or feed or "likes" or "follows" to steal your focus.</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="third big"> |
||||||
|
<h3>Never lose your progress</h3> |
||||||
|
<p>Your writing automatically saves as you type. It'll always be waiting, even if you don't "save" before leaving.</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{end}} |
@ -0,0 +1,117 @@ |
|||||||
|
{{define "head"}} |
||||||
|
<title>{{.SiteName}}</title> |
||||||
|
|
||||||
|
<style type="text/css"> |
||||||
|
h2 { |
||||||
|
font-weight: normal; |
||||||
|
} |
||||||
|
#pricing.content-container div.form-container #payment-form { |
||||||
|
display: block !important; |
||||||
|
} |
||||||
|
#pricing #signup-form table { |
||||||
|
max-width: inherit !important; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
#pricing #payment-form table { |
||||||
|
margin-top: 0 !important; |
||||||
|
max-width: inherit !important; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
tr.subscription { |
||||||
|
border-spacing: 0; |
||||||
|
} |
||||||
|
#pricing.content-container tr.subscription button { |
||||||
|
margin-top: 0 !important; |
||||||
|
margin-bottom: 0 !important; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
#pricing tr.subscription td { |
||||||
|
padding: 0 0.5em; |
||||||
|
} |
||||||
|
#pricing table.billing > tbody > tr > td:first-child { |
||||||
|
vertical-align: middle !important; |
||||||
|
} |
||||||
|
.billing-section { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
.billing-section.bill-me { |
||||||
|
display: table-row; |
||||||
|
} |
||||||
|
#btn-create { |
||||||
|
color: white !important; |
||||||
|
} |
||||||
|
#total-price { |
||||||
|
padding-left: 0.5em; |
||||||
|
} |
||||||
|
#alias-site.demo { |
||||||
|
color: #999; |
||||||
|
} |
||||||
|
#alias-site { |
||||||
|
text-align: left; |
||||||
|
margin: 0.5em 0; |
||||||
|
} |
||||||
|
</style> |
||||||
|
{{end}} |
||||||
|
{{define "content"}} |
||||||
|
<div id="pricing" class="content-container wide-form"> |
||||||
|
|
||||||
|
<div class="row"> |
||||||
|
<div style="text-align:left"> |
||||||
|
<h1 style="margin-top:0;max-width:8em;">{{if .Federation}}Start your blog in the fediverse{{else}}Start your minimalist blog{{end}}</h1> |
||||||
|
<p><a href="#more">Learn more...</a></p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div> |
||||||
|
{{if .Flashes}}<ul class="errors"> |
||||||
|
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}} |
||||||
|
</ul>{{end}} |
||||||
|
|
||||||
|
<div id="billing"> |
||||||
|
<form action="/auth/signup" method="POST" id="signup-form"> |
||||||
|
<dl class="billing"> |
||||||
|
<label> |
||||||
|
<dt>Username</dt> |
||||||
|
<dd> |
||||||
|
<input type="text" id="alias" name="alias" style="width: 100%; box-sizing: border-box;" tabindex="1" autofocus /> |
||||||
|
<p id="alias-site" class="demo">@<strong>your-username</strong>@{{.FriendlyHost}}</p> |
||||||
|
</dd> |
||||||
|
</label> |
||||||
|
<label> |
||||||
|
<dt>Password</dt> |
||||||
|
<dd><input type="password" id="password" name="pass" autocomplete="new-password" placeholder="" tabindex="2" style="width: 100%; box-sizing: border-box;" /></dd> |
||||||
|
</label> |
||||||
|
<label> |
||||||
|
<dt>Email (optional)</dt> |
||||||
|
<dd><input type="email" name="email" id="email" style="letter-spacing: 1px; width: 100%; box-sizing: border-box;" placeholder="me@example.com" tabindex="3" /></dd> |
||||||
|
</label> |
||||||
|
<dt> |
||||||
|
<button id="btn-create" type="submit" style="margin-top: 0">Create blog</button> |
||||||
|
</dt> |
||||||
|
</dl> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{{if .Federation}} |
||||||
|
<a name="more"></a><hr style="margin: 1em auto 3em;" /> |
||||||
|
{{end}} |
||||||
|
</div> |
||||||
|
|
||||||
|
{{ if .Federation }} |
||||||
|
<div class="content-container snug"> |
||||||
|
|
||||||
|
<h2>Join the Fediverse</h2> |
||||||
|
<p>The fediverse is a large network of platforms that all speak a common language. Imagine if you could reply to Instagram posts from Twitter, or interact with your favorite Medium blogs from Facebook — federated alternatives like <a href="https://pixelfed.org/" target="pixel">PixelFed</a>, <a href="https://joinmastodon.org/" target="masto">Mastodon</a>, and Write Freely enable you to do these types of things.</p> |
||||||
|
|
||||||
|
<div style="text-align:center"> |
||||||
|
<iframe style="width: 560px; height: 315px; max-width: 100%;" sandbox="allow-same-origin allow-scripts" src="https://video.writeas.org/videos/embed/cc55e615-d204-417c-9575-7b57674cc6f3" frameborder="0" allowfullscreen></iframe> |
||||||
|
</div> |
||||||
|
|
||||||
|
<h2>Write More Socially</h2> |
||||||
|
<p>Write Freely can communicate with other federated platforms like Mastodon, so people can follow your blogs, bookmark their favorite posts, and boost them to their followers. Sign up above to create a blog and join the fediverse.</p> |
||||||
|
|
||||||
|
</div> |
||||||
|
{{ end }} |
||||||
|
|
||||||
|
{{end}} |
@ -0,0 +1,30 @@ |
|||||||
|
{{define "head"}}<title>Log in — {{.SiteName}}</title> |
||||||
|
<meta name="description" content="Log in to access your blogs, published posts, and linked accounts."> |
||||||
|
<meta itemprop="description" content="Log in to access your blogs, published posts, and linked accounts."> |
||||||
|
<style>input{margin-bottom:0.5em;}</style> |
||||||
|
{{end}} |
||||||
|
{{define "content"}} |
||||||
|
<div class="tight content-container"> |
||||||
|
<h1>Log in to {{.SiteName}}</h1> |
||||||
|
|
||||||
|
{{if .Flashes}}<ul class="errors"> |
||||||
|
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}} |
||||||
|
</ul>{{end}} |
||||||
|
|
||||||
|
<form action="/auth/login" method="post" style="text-align: center;margin-top:1em;" onsubmit="disableSubmit()"> |
||||||
|
<input type="text" name="alias" placeholder="Username" value="{{.Username}}" {{if not .Username}}autofocus{{end}} /><br /> |
||||||
|
<input type="password" name="pass" placeholder="Password" {{if .Username}}autofocus{{end}} /><br /> |
||||||
|
{{if .To}}<input type="hidden" name="to" value="{{.To}}" />{{end}} |
||||||
|
<input type="submit" id="btn-login" value="Login" /> |
||||||
|
</form> |
||||||
|
|
||||||
|
<p style="text-align:center;font-size:0.9em;margin:3em auto;max-width:26em;">{{if .Message}}{{.Message}}{{else}}<em>No account yet?</em> <a href="/new/blog">Sign up</a> to start a blog.{{end}}</p> |
||||||
|
|
||||||
|
<script type="text/javascript"> |
||||||
|
function disableSubmit() { |
||||||
|
var $btn = document.getElementById("btn-login"); |
||||||
|
$btn.value = "Logging in..."; |
||||||
|
$btn.disabled = true; |
||||||
|
} |
||||||
|
</script> |
||||||
|
{{end}} |
@ -0,0 +1,7 @@ |
|||||||
|
{{define "head"}}<title>{{.SiteName}} Privacy Policy</title> |
||||||
|
{{end}} |
||||||
|
{{define "content"}}<div class="content-container snug"> |
||||||
|
<h2>Privacy Policy</h2> |
||||||
|
<p class="intro">We protect your privacy! Like, for real.</p> |
||||||
|
</div> |
||||||
|
{{end}} |
@ -0,0 +1,55 @@ |
|||||||
|
{{define "base"}}<!DOCTYPE HTML> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
{{ template "head" . }} |
||||||
|
<link rel="stylesheet" type="text/css" href="{{.Host}}/css/{{.Theme}}.css" /> |
||||||
|
<link rel="shortcut icon" href="{{.Host}}/favicon.ico" /> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
|
||||||
|
<meta name="application-name" content="{{.SiteName}}"> |
||||||
|
<meta name="application-url" content="{{.Host}}"> |
||||||
|
<meta property="og:site_name" content="{{.SiteName}}" /> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="overlay"></div> |
||||||
|
<header> |
||||||
|
<h2><a href="/">{{.SiteName}}</a></h2> |
||||||
|
{{if .HeaderNav}} |
||||||
|
<nav id="user-nav"> |
||||||
|
<nav class="tabs"> |
||||||
|
<a href="/about"{{if eq .Path "/about"}} class="selected"{{end}}>About</a> |
||||||
|
<a href="/login"{{if eq .Path "/login"}} class="selected"{{end}}>Log in</a> |
||||||
|
</nav> |
||||||
|
</nav> |
||||||
|
{{end}} |
||||||
|
</header> |
||||||
|
|
||||||
|
<div id="official-writing"> |
||||||
|
{{ template "content" . }} |
||||||
|
</div> |
||||||
|
|
||||||
|
{{ template "footer" . }} |
||||||
|
|
||||||
|
{{if not .JSDisabled}} |
||||||
|
<script type="text/javascript"> |
||||||
|
{{if .WebFonts}} |
||||||
|
try { // Google Fonts |
||||||
|
WebFontConfig = { |
||||||
|
custom: { families: [ 'Lora:400,700:latin', 'Open+Sans:400,700:latin' ], urls: [ '/css/fonts.css' ] } |
||||||
|
}; |
||||||
|
(function() { |
||||||
|
var wf = document.createElement('script'); |
||||||
|
wf.src = '/js/webfont.js'; |
||||||
|
wf.type = 'text/javascript'; |
||||||
|
wf.async = 'true'; |
||||||
|
var s = document.getElementsByTagName('script')[0]; |
||||||
|
s.parentNode.insertBefore(wf, s); |
||||||
|
})(); |
||||||
|
} catch (e) { /* ¯\_(ツ)_/¯ */ } |
||||||
|
{{end}} |
||||||
|
</script> |
||||||
|
{{else}} |
||||||
|
{{if .WebFonts}}<link href="{{.Host}}/css/fonts.css" rel="stylesheet" type="text/css" />{{end}} |
||||||
|
{{end}} |
||||||
|
</body> |
||||||
|
</html>{{end}} |
@ -0,0 +1,135 @@ |
|||||||
|
{{define "post"}}<!DOCTYPE HTML> |
||||||
|
<html {{if .Language.Valid}}lang="{{.Language.String}}"{{end}} dir="{{.Direction}}"> |
||||||
|
<head prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#"> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>{{.PlainDisplayTitle}} — {{.Collection.DisplayTitle}}</title> |
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/write.css" /> |
||||||
|
<link rel="shortcut icon" href="/favicon.ico" /> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
<link rel="canonical" href="{{.CanonicalURL}}" /> |
||||||
|
<meta name="generator" content="Write Freely"> |
||||||
|
<meta name="title" content="{{.PlainDisplayTitle}} — {{if .Collection.Title}}{{.Collection.Title}}{{else}}{{.Collection.Alias}}{{end}}"> |
||||||
|
<meta name="description" content="{{.Summary}}"> |
||||||
|
{{if gt .Views 1}}<meta name="twitter:label1" value="Views"> |
||||||
|
<meta name="twitter:data1" value="{{largeNumFmt .Views}}">{{end}} |
||||||
|
<meta name="author" content="{{.Collection.Title}}" /> |
||||||
|
<meta itemprop="description" content="{{.Summary}}"> |
||||||
|
<meta itemprop="datePublished" content="{{.CreatedDate}}" /> |
||||||
|
<meta name="twitter:card" content="summary"> |
||||||
|
<meta name="twitter:description" content="{{.Summary}}"> |
||||||
|
<meta name="twitter:title" content="{{.PlainDisplayTitle}} — {{if .Collection.Title}}{{.Collection.Title}}{{else}}{{.Collection.Alias}}{{end}}"> |
||||||
|
{{if gt (len .Images) 0}}<meta name="twitter:image" content="{{index .Images 0}}">{{else}}<meta name="twitter:image" content="https://write.as/img/w-sq-light.png">{{end}} |
||||||
|
<meta property="og:title" content="{{.PlainDisplayTitle}}" /> |
||||||
|
<meta property="og:description" content="{{.Summary}}" /> |
||||||
|
<meta property="og:site_name" content="{{.Collection.DisplayTitle}}" /> |
||||||
|
<meta property="og:type" content="article" /> |
||||||
|
<meta property="og:url" content="{{.CanonicalURL}}" /> |
||||||
|
<meta property="og:updated_time" content="{{.Created8601}}" /> |
||||||
|
{{range .Images}}<meta property="og:image" content="{{.}}" />{{else}}<meta property="og:image" content="https://write.as/img/w-sq-light.png">{{end}} |
||||||
|
<meta property="article:published_time" content="{{.Created8601}}"> |
||||||
|
{{if .Collection.StyleSheet}}<style type="text/css">{{.Collection.StyleSheetDisplay}}</style>{{end}} |
||||||
|
{{if .Collection.RenderMathJax}} |
||||||
|
<script type="text/x-mathjax-config"> |
||||||
|
MathJax.Hub.Config({ |
||||||
|
extensions: ["tex2jax.js"], |
||||||
|
jax: ["input/TeX", "output/HTML-CSS"], |
||||||
|
tex2jax: { |
||||||
|
inlineMath: [ ['$','$'], ["\\(","\\)"] ], |
||||||
|
displayMath: [ ['$$','$$'], ["\\[","\\]"] ], |
||||||
|
processEscapes: true |
||||||
|
}, |
||||||
|
"HTML-CSS": { fonts: ["TeX"] } |
||||||
|
}); |
||||||
|
</script> |
||||||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML" async></script>{{end}} |
||||||
|
|
||||||
|
</head> |
||||||
|
<body id="post"> |
||||||
|
|
||||||
|
<div id="overlay"></div> |
||||||
|
|
||||||
|
<header> |
||||||
|
<h1 dir="{{.Direction}}" id="blog-title"><a rel="author" href="{{if .IsTopLevel}}/{{else}}/{{.Collection.Alias}}/{{end}}" class="h-card p-author">{{.Collection.DisplayTitle}}</a></h1> |
||||||
|
<nav> |
||||||
|
{{if .PinnedPosts}} |
||||||
|
{{range .PinnedPosts}}<a class="pinned{{if eq .Slug.String $.Slug.String}} selected{{end}}" href="{{if $.IsOwner}}/{{$.Collection.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.PlainDisplayTitle}}</a>{{end}} |
||||||
|
{{end}} |
||||||
|
{{ if .IsOwner }}<span class="views" dir="ltr"><strong>{{largeNumFmt .Views}}</strong> {{pluralize "view" "views" .Views}}</span> |
||||||
|
<a class="xtra-feature" href="/{{.Collection.Alias}}/{{.Slug.String}}/edit" dir="{{.Direction}}">Edit</a> |
||||||
|
{{if .IsPinned}}<a class="xtra-feature unpin" href="/{{.Collection.Alias}}/{{.Slug.String}}/unpin" dir="{{.Direction}}" onclick="unpinPost(event, '{{.ID}}')">Unpin</a>{{end}} |
||||||
|
{{ end }} |
||||||
|
</nav> |
||||||
|
</header> |
||||||
|
|
||||||
|
<article id="post-body" class="{{.Font}} h-entry">{{if .IsScheduled}}<p class="badge">Scheduled</p>{{end}}{{if .Title.String}}<h2 id="title" class="p-name">{{.FormattedDisplayTitle}}</h2>{{end}}<div class="e-content">{{.HTMLContent}}</div></article> |
||||||
|
|
||||||
|
{{ if .Collection.ShowFooterBranding }} |
||||||
|
<footer dir="ltr"><hr><nav><p style="font-size: 0.9em">{{localhtml "published with write.as" .Language.String}}</p></nav></footer> |
||||||
|
{{ end }} |
||||||
|
</body> |
||||||
|
|
||||||
|
{{if .Collection.CanShowScript}} |
||||||
|
{{range .Collection.ExternalScripts}}<script type="text/javascript" src="{{.}}" async></script>{{end}} |
||||||
|
{{if .Collection.Script}}<script type="text/javascript">{{.Collection.ScriptDisplay}}</script>{{end}} |
||||||
|
{{end}} |
||||||
|
<script type="text/javascript"> |
||||||
|
|
||||||
|
var pinning = false; |
||||||
|
function unpinPost(e, postID) { |
||||||
|
e.preventDefault(); |
||||||
|
if (pinning) { |
||||||
|
return; |
||||||
|
} |
||||||
|
pinning = true; |
||||||
|
|
||||||
|
var $header = document.getElementsByTagName('header')[0]; |
||||||
|
var callback = function() { |
||||||
|
// Hide current page |
||||||
|
var $pinnedNavLink = $header.getElementsByTagName('nav')[0].querySelector('.pinned.selected'); |
||||||
|
$pinnedNavLink.style.display = 'none'; |
||||||
|
try { _paq.push(['trackEvent', 'Post', 'unpin', 'post']); } catch(e) {} |
||||||
|
}; |
||||||
|
|
||||||
|
var $pinBtn = $header.getElementsByClassName('unpin')[0]; |
||||||
|
$pinBtn.innerHTML = '...'; |
||||||
|
|
||||||
|
var http = new XMLHttpRequest(); |
||||||
|
var url = "/api/collections/{{.Collection.Alias}}/unpin"; |
||||||
|
var params = [ { "id": postID } ]; |
||||||
|
http.open("POST", url, true); |
||||||
|
http.setRequestHeader("Content-type", "application/json"); |
||||||
|
http.onreadystatechange = function() { |
||||||
|
if (http.readyState == 4) { |
||||||
|
pinning = false; |
||||||
|
if (http.status == 200) { |
||||||
|
callback(); |
||||||
|
$pinBtn.style.display = 'none'; |
||||||
|
$pinBtn.innerHTML = 'Pin'; |
||||||
|
} else if (http.status == 409) { |
||||||
|
$pinBtn.innerHTML = 'Unpin'; |
||||||
|
} else { |
||||||
|
$pinBtn.innerHTML = 'Unpin'; |
||||||
|
alert("Failed to unpin." + (http.status>=500?" Please try again.":"")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
http.send(JSON.stringify(params)); |
||||||
|
}; |
||||||
|
|
||||||
|
try { // Fonts |
||||||
|
WebFontConfig = { |
||||||
|
custom: { families: [ 'Lora:400,700:latin', 'Open+Sans:400,700:latin' ], urls: [ '/css/fonts.css' ] } |
||||||
|
}; |
||||||
|
(function() { |
||||||
|
var wf = document.createElement('script'); |
||||||
|
wf.src = '/js/webfont.js'; |
||||||
|
wf.type = 'text/javascript'; |
||||||
|
wf.async = 'true'; |
||||||
|
var s = document.getElementsByTagName('script')[0]; |
||||||
|
s.parentNode.insertBefore(wf, s); |
||||||
|
})(); |
||||||
|
} catch (e) { /* ¯\_(ツ)_/¯ */ } |
||||||
|
</script> |
||||||
|
</html>{{end}} |
@ -0,0 +1,198 @@ |
|||||||
|
{{define "collection-tags"}}<!DOCTYPE HTML> |
||||||
|
<html> |
||||||
|
<head prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#"> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>{{.Tag}} — {{.Collection.DisplayTitle}}</title> |
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="{{if .IsCustomDomain}}https://files.writeas.org{{end}}/css/write.css" /> |
||||||
|
<link rel="shortcut icon" href="{{ if .Collection.ShowFooterBranding }}{{if .IsCustomDomain}}https://files.writeas.org{{end}}/favicon.ico{{ else }}/none.ico{{ end }}" /> |
||||||
|
{{if not .Collection.IsPrivate}}<link rel="alternate" type="application/rss+xml" title="{{.Tag}} posts on {{.DisplayTitle}}" href="{{.CanonicalURL}}tag:{{.Tag}}/feed/" />{{end}} |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
<link rel="canonical" href="{{.CanonicalURL}}tag:{{.Tag | tolower}}" /> |
||||||
|
<meta name="generator" content="Write.as"> |
||||||
|
<meta name="title" content="{{.Tag}} — {{.Collection.DisplayTitle}}"> |
||||||
|
<meta name="description" content="{{.Tag}} posts on {{.Collection.DisplayTitle}}"> |
||||||
|
<meta name="application-name" content="Write.as"> |
||||||
|
<meta name="application-url" content="https://write.as"> |
||||||
|
{{if gt .Views 1}}<meta name="twitter:label1" value="Views"> |
||||||
|
<meta name="twitter:data1" value="{{largeNumFmt .Views}}">{{end}} |
||||||
|
<meta itemprop="name" content="{{.Collection.DisplayTitle}}"> |
||||||
|
<meta itemprop="description" content="{{.Tag}} posts on {{.Collection.DisplayTitle}}"> |
||||||
|
<meta name="twitter:card" content="summary"> |
||||||
|
<meta name="twitter:site" content="@writeas__"> |
||||||
|
<meta name="twitter:description" content="{{.Tag}} posts on {{.Collection.DisplayTitle}}"> |
||||||
|
<meta name="twitter:title" content="{{.Tag}} — {{.Collection.DisplayTitle}}"> |
||||||
|
<meta property="og:title" content="{{.Tag}} — {{.Collection.DisplayTitle}}" /> |
||||||
|
<meta property="og:site_name" content="{{.DisplayTitle}}" /> |
||||||
|
<meta property="og:type" content="article" /> |
||||||
|
<meta property="og:url" content="{{.CanonicalURL}}tag:{{.Tag}}" /> |
||||||
|
{{if .Collection.StyleSheet}}<style type="text/css">{{.Collection.StyleSheetDisplay}}</style>{{end}} |
||||||
|
{{if .Collection.RenderMathJax}} |
||||||
|
<script type="text/x-mathjax-config"> |
||||||
|
MathJax.Hub.Config({ |
||||||
|
extensions: ["tex2jax.js"], |
||||||
|
jax: ["input/TeX", "output/HTML-CSS"], |
||||||
|
tex2jax: { |
||||||
|
inlineMath: [ ['$','$'], ["\\(","\\)"] ], |
||||||
|
displayMath: [ ['$$','$$'], ["\\[","\\]"] ], |
||||||
|
processEscapes: true |
||||||
|
}, |
||||||
|
"HTML-CSS": { fonts: ["TeX"] } |
||||||
|
}); |
||||||
|
</script> |
||||||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML" async></script>{{end}} |
||||||
|
|
||||||
|
</head> |
||||||
|
<body id="subpage"> |
||||||
|
|
||||||
|
<div id="overlay"></div> |
||||||
|
|
||||||
|
<header> |
||||||
|
<h1 dir="{{.Direction}}" id="blog-title"><a href="{{if .IsTopLevel}}/{{else}}/{{.Collection.Alias}}/{{end}}" class="h-card p-author">{{.Collection.DisplayTitle}}</a></h1> |
||||||
|
<nav> |
||||||
|
{{if .PinnedPosts}} |
||||||
|
{{range .PinnedPosts}}<a class="pinned" href="{{if $.IsOwner}}/{{$.Collection.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.DisplayTitle}}</a>{{end}} |
||||||
|
{{end}} |
||||||
|
</nav> |
||||||
|
</header> |
||||||
|
|
||||||
|
{{if .Posts}}<section id="wrapper" itemscope itemtype="http://schema.org/Blog">{{else}}<div id="wrapper">{{end}} |
||||||
|
<h1>{{.Tag}}</h1> |
||||||
|
{{template "posts" .}} |
||||||
|
{{if .Posts}}</section>{{else}}</div>{{end}} |
||||||
|
|
||||||
|
{{ if .Collection.ShowFooterBranding }} |
||||||
|
<footer dir="ltr"> |
||||||
|
<hr> |
||||||
|
<nav> |
||||||
|
<p style="font-size: 0.9em"><a class="home pubd" href="/">{{.SiteName}}</a> · powered by <a style="margin-left:0" href="https://writefreely.org">write freely</a></p> |
||||||
|
</nav> |
||||||
|
</footer> |
||||||
|
{{ end }} |
||||||
|
</body> |
||||||
|
|
||||||
|
{{if .CanShowScript}} |
||||||
|
{{range .ExternalScripts}}<script type="text/javascript" src="{{.}}" async></script>{{end}} |
||||||
|
{{if .Collection.Script}}<script type="text/javascript">{{.ScriptDisplay}}</script>{{end}} |
||||||
|
{{end}} |
||||||
|
{{if .IsOwner}} |
||||||
|
<script src="/js/h.js"></script> |
||||||
|
<script src="/js/postactions.js"></script> |
||||||
|
{{end}} |
||||||
|
<script type="text/javascript"> |
||||||
|
{{if .IsOwner}} |
||||||
|
var deleting = false; |
||||||
|
function delPost(e, id, owned) { |
||||||
|
e.preventDefault(); |
||||||
|
if (deleting) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: UNDO! |
||||||
|
if (window.confirm('Are you sure you want to delete this post?')) { |
||||||
|
// AJAX |
||||||
|
deletePost(id, "", function() { |
||||||
|
// Remove post from list |
||||||
|
var $postEl = document.getElementById('post-' + id); |
||||||
|
$postEl.parentNode.removeChild($postEl); |
||||||
|
// TODO: add next post from this collection at the bottom |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var deletePost = function(postID, token, callback) { |
||||||
|
deleting = true; |
||||||
|
|
||||||
|
var $delBtn = document.getElementById('post-' + postID).getElementsByClassName('delete action')[0]; |
||||||
|
$delBtn.innerHTML = '...'; |
||||||
|
|
||||||
|
var http = new XMLHttpRequest(); |
||||||
|
var url = "/api/posts/" + postID; |
||||||
|
http.open("DELETE", url, true); |
||||||
|
http.onreadystatechange = function() { |
||||||
|
if (http.readyState == 4) { |
||||||
|
deleting = false; |
||||||
|
if (http.status == 204) { |
||||||
|
callback(); |
||||||
|
} else if (http.status == 409) { |
||||||
|
$delBtn.innerHTML = 'delete'; |
||||||
|
alert("Post is synced to another account. Delete the post from that account instead."); |
||||||
|
// TODO: show "remove" button instead of "delete" now |
||||||
|
// Persist that state. |
||||||
|
// Have it remove the post locally only. |
||||||
|
} else { |
||||||
|
$delBtn.innerHTML = 'delete'; |
||||||
|
alert("Failed to delete." + (http.status>=500?" Please try again.":"")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
http.send(); |
||||||
|
}; |
||||||
|
|
||||||
|
var pinning = false; |
||||||
|
function pinPost(e, postID, slug, title) { |
||||||
|
e.preventDefault(); |
||||||
|
if (pinning) { |
||||||
|
return; |
||||||
|
} |
||||||
|
pinning = true; |
||||||
|
|
||||||
|
var callback = function() { |
||||||
|
// Visibly remove post from collection |
||||||
|
var $postEl = document.getElementById('post-' + postID); |
||||||
|
$postEl.parentNode.removeChild($postEl); |
||||||
|
var $header = document.getElementsByTagName('header')[0]; |
||||||
|
var $pinnedNavs = $header.getElementsByTagName('nav'); |
||||||
|
// Add link to nav |
||||||
|
var link = '<a class="pinned" href="/{{.Alias}}/'+slug+'">'+title+'</a>'; |
||||||
|
if ($pinnedNavs.length == 0) { |
||||||
|
$header.insertAdjacentHTML("beforeend", '<nav>'+link+'</nav>'); |
||||||
|
} else { |
||||||
|
$pinnedNavs[0].insertAdjacentHTML("beforeend", link); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var $pinBtn = document.getElementById('post-' + postID).getElementsByClassName('pin action')[0]; |
||||||
|
$pinBtn.innerHTML = '...'; |
||||||
|
|
||||||
|
var http = new XMLHttpRequest(); |
||||||
|
var url = "/api/collections/{{.Alias}}/pin"; |
||||||
|
var params = [ { "id": postID } ]; |
||||||
|
http.open("POST", url, true); |
||||||
|
http.setRequestHeader("Content-type", "application/json"); |
||||||
|
http.onreadystatechange = function() { |
||||||
|
if (http.readyState == 4) { |
||||||
|
pinning = false; |
||||||
|
if (http.status == 200) { |
||||||
|
callback(); |
||||||
|
} else if (http.status == 409) { |
||||||
|
$pinBtn.innerHTML = 'pin'; |
||||||
|
alert("Post is synced to another account. Delete the post from that account instead."); |
||||||
|
// TODO: show "remove" button instead of "delete" now |
||||||
|
// Persist that state. |
||||||
|
// Have it remove the post locally only. |
||||||
|
} else { |
||||||
|
$pinBtn.innerHTML = 'pin'; |
||||||
|
alert("Failed to pin." + (http.status>=500?" Please try again.":"")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
http.send(JSON.stringify(params)); |
||||||
|
}; |
||||||
|
{{end}} |
||||||
|
try { // Fonts |
||||||
|
WebFontConfig = { |
||||||
|
custom: { families: [ 'Lora:400,700:latin', 'Open+Sans:400,700:latin' ], urls: [ '{{if .IsCustomDomain}}https://files.writeas.org{{end}}/css/fonts.css' ] } |
||||||
|
}; |
||||||
|
(function() { |
||||||
|
var wf = document.createElement('script'); |
||||||
|
wf.src = '{{if .IsCustomDomain}}https://files.writeas.org{{end}}/js/webfont.js'; |
||||||
|
wf.type = 'text/javascript'; |
||||||
|
wf.async = 'true'; |
||||||
|
var s = document.getElementsByTagName('script')[0]; |
||||||
|
s.parentNode.insertBefore(wf, s); |
||||||
|
})(); |
||||||
|
} catch (e) { /* ¯\_(ツ)_/¯ */ } |
||||||
|
</script> |
||||||
|
</html>{{end}} |
@ -0,0 +1,225 @@ |
|||||||
|
{{define "collection"}}<!DOCTYPE HTML> |
||||||
|
<html {{if .Language}}lang="{{.Language}}"{{end}} dir="{{.Direction}}"> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>{{.DisplayTitle}}{{if not .SingleUser}} — {{.SiteName}}{{end}}</title> |
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/write.css" /> |
||||||
|
<link rel="shortcut icon" href="/favicon.ico" /> |
||||||
|
<link rel="canonical" href="{{.CanonicalURL}}"> |
||||||
|
{{if gt .CurrentPage 1}}<link rel="prev" href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">{{end}} |
||||||
|
{{if lt .CurrentPage .TotalPages}}<link rel="next" href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">{{end}} |
||||||
|
{{if not .IsPrivate}}<link rel="alternate" type="application/rss+xml" title="{{.DisplayTitle}} » Feed" href="{{.CanonicalURL}}feed/" />{{end}} |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
|
||||||
|
<meta name="generator" content="Write Freely"> |
||||||
|
<meta name="description" content="{{.Description}}"> |
||||||
|
<meta itemprop="name" content="{{.DisplayTitle}}"> |
||||||
|
<meta itemprop="description" content="{{.Description}}"> |
||||||
|
<meta name="twitter:card" content="summary"> |
||||||
|
<meta name="twitter:title" content="{{.DisplayTitle}}"> |
||||||
|
<meta name="twitter:description" content="{{.Description}}"> |
||||||
|
<meta property="og:title" content="{{.DisplayTitle}}" /> |
||||||
|
<meta property="og:site_name" content="{{.DisplayTitle}}" /> |
||||||
|
<meta property="og:type" content="article" /> |
||||||
|
<meta property="og:url" content="{{.CanonicalURL}}" /> |
||||||
|
<meta property="og:description" content="{{.Description}}" /> |
||||||
|
{{if .StyleSheet}}<style type="text/css">{{.StyleSheetDisplay}}</style>{{end}} |
||||||
|
{{if .RenderMathJax}} |
||||||
|
<script type="text/x-mathjax-config"> |
||||||
|
MathJax.Hub.Config({ |
||||||
|
extensions: ["tex2jax.js"], |
||||||
|
jax: ["input/TeX", "output/HTML-CSS"], |
||||||
|
tex2jax: { |
||||||
|
inlineMath: [ ['$','$'], ["\\(","\\)"] ], |
||||||
|
displayMath: [ ['$$','$$'], ["\\[","\\]"] ], |
||||||
|
processEscapes: true |
||||||
|
}, |
||||||
|
"HTML-CSS": { fonts: ["TeX"] } |
||||||
|
}); |
||||||
|
</script> |
||||||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML" async></script>{{end}} |
||||||
|
|
||||||
|
</head> |
||||||
|
<body id="collection" itemscope itemtype="http://schema.org/WebPage"> |
||||||
|
{{if .IsOwner}}<nav id="manage"><ul> |
||||||
|
<li><a onclick="void(0)">☰ Menu</a> |
||||||
|
<ul> |
||||||
|
<li><a href="/#{{.Alias}}" class="write">{{.SiteName}}</a></li> |
||||||
|
<li><a href="/me/c/{{.Alias}}">Customize</a></li> |
||||||
|
<li><a href="/me/c/{{.Alias}}/stats">Stats</a></li> |
||||||
|
<li class="separator"><hr /></li> |
||||||
|
<li><a href="/me/c/"><img class="ic-18dp" src="/img/ic_blogs_dark@2x.png" /> View Blogs</a></li> |
||||||
|
<li><a href="/me/posts/"><img class="ic-18dp" src="/img/ic_list_dark@2x.png" /> View Drafts</a></li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
</ul></nav>{{end}} |
||||||
|
|
||||||
|
<header> |
||||||
|
<h1 dir="{{.Direction}}" id="blog-title">{{if .Posts}}{{else}}<span class="writeas-prefix"><a href="/">write.as</a></span> {{end}}<a href="/{{if .IsTopLevel}}{{else}}{{.Prefix}}{{.Alias}}/{{end}}" class="h-card p-author u-url" rel="me author">{{.DisplayTitle}}</a></h1> |
||||||
|
{{if .Description}}<p class="description p-note">{{.Description}}</p>{{end}} |
||||||
|
{{/*if not .Public/*}} |
||||||
|
<!--p class="meta-note"><span>Private collection</span>. Only you can see this page.</p--> |
||||||
|
{{/*end*/}} |
||||||
|
{{if .PinnedPosts}}<nav> |
||||||
|
{{range .PinnedPosts}}<a class="pinned" href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.PlainDisplayTitle}}</a>{{end}}</nav> |
||||||
|
{{end}} |
||||||
|
</header> |
||||||
|
|
||||||
|
{{if .Posts}}<section id="wrapper" itemscope itemtype="http://schema.org/Blog">{{else}}<div id="wrapper">{{end}} |
||||||
|
|
||||||
|
{{if .IsWelcome}} |
||||||
|
<div id="welcome"> |
||||||
|
<h2>Welcome, <strong>{{.Username}}</strong>!</h2> |
||||||
|
<p>This is your new blog.</p> |
||||||
|
<p><a class="simple-cta" href="/#{{.Alias}}">Start writing</a>, or <a class="simple-cta" href="/me/c/{{.Alias}}">customize</a> your blog.</p> |
||||||
|
<p>Check out our <a class="simple-cta" href="https://guides.write.as/writing/?pk_campaign=welcome">writing guide</a> to see what else you can do, and <a class="simple-cta" href="/contact">get in touch</a> anytime with questions or feedback.</p> |
||||||
|
</div> |
||||||
|
{{end}} |
||||||
|
|
||||||
|
{{template "posts" .}} |
||||||
|
|
||||||
|
{{if gt .TotalPages 1}}<nav id="paging" class="content-container clearfix"> |
||||||
|
{{if or (and .Format.Ascending (lt .CurrentPage .TotalPages)) (isRTL .Direction)}} |
||||||
|
{{if gt .CurrentPage 1}}<a href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">⇠ {{if and .Format.Ascending (lt .CurrentPage .TotalPages)}}Previous{{else}}Newer{{end}}</a>{{end}} |
||||||
|
{{if lt .CurrentPage .TotalPages}}<a style="float:right;" href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">{{if and .Format.Ascending (lt .CurrentPage .TotalPages)}}Next{{else}}Older{{end}} ⇢</a>{{end}} |
||||||
|
{{else}} |
||||||
|
{{if lt .CurrentPage .TotalPages}}<a href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">⇠ Older</a>{{end}} |
||||||
|
{{if gt .CurrentPage 1}}<a style="float:right;" href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">Newer ⇢</a>{{end}} |
||||||
|
{{end}} |
||||||
|
</nav>{{end}} |
||||||
|
|
||||||
|
{{if .Posts}}</section>{{else}}</div>{{end}} |
||||||
|
|
||||||
|
{{if .ShowFooterBranding }} |
||||||
|
<footer> |
||||||
|
<hr /> |
||||||
|
<nav dir="ltr"> |
||||||
|
<a class="home pubd" href="/">{{.SiteName}}</a> · powered by <a style="margin-left:0" href="https://writefreely.org">write freely</a> |
||||||
|
</nav> |
||||||
|
</footer> |
||||||
|
{{ end }} |
||||||
|
</body> |
||||||
|
|
||||||
|
{{if .CanShowScript}} |
||||||
|
{{range .ExternalScripts}}<script type="text/javascript" src="{{.}}" async></script>{{end}} |
||||||
|
{{if .Script}}<script type="text/javascript">{{.ScriptDisplay}}</script>{{end}} |
||||||
|
{{end}} |
||||||
|
<script src="/js/h.js"></script> |
||||||
|
<script src="/js/postactions.js"></script> |
||||||
|
<script type="text/javascript"> |
||||||
|
var deleting = false; |
||||||
|
function delPost(e, id, owned) { |
||||||
|
e.preventDefault(); |
||||||
|
if (deleting) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: UNDO! |
||||||
|
if (window.confirm('Are you sure you want to delete this post?')) { |
||||||
|
// AJAX |
||||||
|
deletePost(id, "", function() { |
||||||
|
// Remove post from list |
||||||
|
var $postEl = document.getElementById('post-' + id); |
||||||
|
$postEl.parentNode.removeChild($postEl); |
||||||
|
// TODO: add next post from this collection at the bottom |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var deletePost = function(postID, token, callback) { |
||||||
|
deleting = true; |
||||||
|
|
||||||
|
var $delBtn = document.getElementById('post-' + postID).getElementsByClassName('delete action')[0]; |
||||||
|
$delBtn.innerHTML = '...'; |
||||||
|
|
||||||
|
var http = new XMLHttpRequest(); |
||||||
|
var url = "/api/posts/" + postID; |
||||||
|
http.open("DELETE", url, true); |
||||||
|
http.onreadystatechange = function() { |
||||||
|
if (http.readyState == 4) { |
||||||
|
deleting = false; |
||||||
|
if (http.status == 204) { |
||||||
|
callback(); |
||||||
|
} else if (http.status == 409) { |
||||||
|
$delBtn.innerHTML = 'delete'; |
||||||
|
alert("Post is synced to another account. Delete the post from that account instead."); |
||||||
|
// TODO: show "remove" button instead of "delete" now |
||||||
|
// Persist that state. |
||||||
|
// Have it remove the post locally only. |
||||||
|
} else { |
||||||
|
$delBtn.innerHTML = 'delete'; |
||||||
|
alert("Failed to delete." + (http.status>=500?" Please try again.":"")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
http.send(); |
||||||
|
}; |
||||||
|
|
||||||
|
var pinning = false; |
||||||
|
function pinPost(e, postID, slug, title) { |
||||||
|
e.preventDefault(); |
||||||
|
if (pinning) { |
||||||
|
return; |
||||||
|
} |
||||||
|
pinning = true; |
||||||
|
|
||||||
|
var callback = function() { |
||||||
|
// Visibly remove post from collection |
||||||
|
var $postEl = document.getElementById('post-' + postID); |
||||||
|
$postEl.parentNode.removeChild($postEl); |
||||||
|
var $header = document.getElementsByTagName('header')[0]; |
||||||
|
var $pinnedNavs = $header.getElementsByTagName('nav'); |
||||||
|
// Add link to nav |
||||||
|
var link = '<a class="pinned" href="/{{.Alias}}/'+slug+'">'+title+'</a>'; |
||||||
|
if ($pinnedNavs.length == 0) { |
||||||
|
$header.insertAdjacentHTML("beforeend", '<nav>'+link+'</nav>'); |
||||||
|
} else { |
||||||
|
$pinnedNavs[0].insertAdjacentHTML("beforeend", link); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var $pinBtn = document.getElementById('post-' + postID).getElementsByClassName('pin action')[0]; |
||||||
|
$pinBtn.innerHTML = '...'; |
||||||
|
|
||||||
|
var http = new XMLHttpRequest(); |
||||||
|
var url = "/api/collections/{{.Alias}}/pin"; |
||||||
|
var params = [ { "id": postID } ]; |
||||||
|
http.open("POST", url, true); |
||||||
|
http.setRequestHeader("Content-type", "application/json"); |
||||||
|
http.onreadystatechange = function() { |
||||||
|
if (http.readyState == 4) { |
||||||
|
pinning = false; |
||||||
|
if (http.status == 200) { |
||||||
|
callback(); |
||||||
|
} else if (http.status == 409) { |
||||||
|
$pinBtn.innerHTML = 'pin'; |
||||||
|
alert("Post is synced to another account. Delete the post from that account instead."); |
||||||
|
// TODO: show "remove" button instead of "delete" now |
||||||
|
// Persist that state. |
||||||
|
// Have it remove the post locally only. |
||||||
|
} else { |
||||||
|
$pinBtn.innerHTML = 'pin'; |
||||||
|
alert("Failed to pin." + (http.status>=500?" Please try again.":"")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
http.send(JSON.stringify(params)); |
||||||
|
}; |
||||||
|
|
||||||
|
try { |
||||||
|
WebFontConfig = { |
||||||
|
custom: { families: [ 'Lora:400,700:latin', 'Open+Sans:400,700:latin' ], urls: [ '/css/fonts.css' ] } |
||||||
|
}; |
||||||
|
(function() { |
||||||
|
var wf = document.createElement('script'); |
||||||
|
wf.src = '/js/webfont.js'; |
||||||
|
wf.type = 'text/javascript'; |
||||||
|
wf.async = 'true'; |
||||||
|
var s = document.getElementsByTagName('script')[0]; |
||||||
|
s.parentNode.insertBefore(wf, s); |
||||||
|
})(); |
||||||
|
} catch (e) {} |
||||||
|
</script> |
||||||
|
</html>{{end}} |
@ -0,0 +1,25 @@ |
|||||||
|
{{define "footer"}} |
||||||
|
<footer class="contain-me"> |
||||||
|
<hr /> |
||||||
|
<div class="marketing-section"> |
||||||
|
<div class="clearfix blurbs"> |
||||||
|
<div class="half"> |
||||||
|
<h3><a class="home" href="/">{{.SiteName}}</a></h3> |
||||||
|
<ul> |
||||||
|
<li><a href="/about">about</a></li> |
||||||
|
<li><a href="/privacy">privacy</a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div class="half"> |
||||||
|
<h3><a href="https://writefreely.org">write freely</a></h3> |
||||||
|
<ul> |
||||||
|
<li><a href="https://writefreely.org/apps">apps</a></li> |
||||||
|
<li><a href="https://developers.write.as/" title="Build on Write Freely with our open developer API.">developers</a></li> |
||||||
|
<li><a href="https://github.com/writeas/writefreely">source code</a></li> |
||||||
|
<li style="margin-top:0.8em">{{.Version}}</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</footer> |
||||||
|
{{end}} |
@ -0,0 +1,53 @@ |
|||||||
|
{{ define "posts" }} |
||||||
|
{{ range $el := .Posts }}<article id="post-{{.ID}}" class="{{.Font}} h-entry" itemscope itemtype="http://schema.org/BlogPosting"> |
||||||
|
{{if .IsScheduled}}<p class="badge">Scheduled</p>{{end}} |
||||||
|
{{if .Title.String}}<h2 class="post-title" itemprop="name" class="p-name">{{if .HasTitleLink}}{{.HTMLTitle}} <a class="user hidden action" href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}">view</a>{{else}}<a href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}" itemprop="url" class="u-url">{{.HTMLTitle}}</a>{{end}} |
||||||
|
{{if $.IsOwner}} |
||||||
|
<a class="user hidden action" href="/{{$.Alias}}/{{.Slug.String}}/edit">edit</a> |
||||||
|
{{if $.CanPin}}<a class="user hidden pin action" href="/{{$.Alias}}/{{.Slug.String}}/pin" onclick="pinPost(event, '{{.ID}}', '{{.Slug.String}}', '{{.PlainDisplayTitle}}')">pin</a>{{end}} |
||||||
|
<a class="user hidden delete action" onclick="delPost(event, '{{.ID}}')" href="/{{$.Alias}}/{{.Slug.String}}/delete">delete</a> |
||||||
|
{{if gt (len $.Collections) 1}}<div class="user hidden action flat-select"> |
||||||
|
<select id="move-{{.ID}}" onchange="postActions.multiMove(this, '{{.ID}}')" title="Move this post to another blog"> |
||||||
|
<option style="display:none"></option> |
||||||
|
<option value="|anonymous|" style="font-style:italic">Draft</option> |
||||||
|
{{range $.Collections}}{{if ne .Alias $.Alias}}<option value="{{.Alias}}">{{.DisplayTitle}}</option>{{end}}{{end}} |
||||||
|
</select> |
||||||
|
<label for="move-{{.ID}}">move to...</label> |
||||||
|
<img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /> |
||||||
|
</div>{{else}} |
||||||
|
{{range $.Collections}} |
||||||
|
<a class="user hidden action" href="/{{$el.ID}}" title="Change to a draft" onclick="postActions.move(this, '{{$el.ID}}', '|anonymous|');return false">change to <em>draft</em></a> |
||||||
|
{{end}} |
||||||
|
{{end}} |
||||||
|
{{end}} |
||||||
|
</h2> |
||||||
|
{{if $.Format.ShowDates}}<time class="dt-published" datetime="{{.Created}}" pubdate itemprop="datePublished" content="{{.Created}}">{{if not .Title.String}}<a href="{{$.CanonicalURL}}{{.Slug.String}}" itemprop="url">{{end}}{{.DisplayDate}}{{if not .Title.String}}</a>{{end}}</time>{{end}} |
||||||
|
{{else}} |
||||||
|
<h2 class="post-title" itemprop="name"> |
||||||
|
{{if $.Format.ShowDates}}<time class="dt-published" datetime="{{.Created}}" pubdate itemprop="datePublished" content="{{.Created}}"><a href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}" itemprop="url" class="u-url">{{.DisplayDate}}</a></time>{{end}} |
||||||
|
{{if $.IsOwner}} |
||||||
|
{{if not $.Format.ShowDates}}<a class="user hidden action" href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}">view</a>{{end}} |
||||||
|
<a class="user hidden action" href="/{{$.Alias}}/{{.Slug.String}}/edit">edit</a> |
||||||
|
{{if $.CanPin}}<a class="user hidden pin action" href="/{{$.Alias}}/{{.Slug.String}}/pin" onclick="pinPost(event, '{{.ID}}', '{{.Slug.String}}', '{{.PlainDisplayTitle}}')">pin</a>{{end}} |
||||||
|
<a class="user hidden delete action" onclick="delPost(event, '{{.ID}}')" href="/{{$.Alias}}/{{.Slug.String}}/delete">delete</a> |
||||||
|
{{if gt (len $.Collections) 1}}<div class="user hidden action flat-select"> |
||||||
|
<select id="move-{{.ID}}" onchange="postActions.multiMove(this, '{{.ID}}')" title="Move this post to another blog"> |
||||||
|
<option style="display:none"></option> |
||||||
|
<option value="|anonymous|" style="font-style:italic">Draft</option> |
||||||
|
{{range $.Collections}}{{if ne .Alias $.Alias}}<option value="{{.Alias}}">{{.DisplayTitle}}</option>{{end}}{{end}} |
||||||
|
</select> |
||||||
|
<label for="move-{{.ID}}">move to...</label> |
||||||
|
<img class="ic-18dp" src="/img/ic_down_arrow_dark@2x.png" /> |
||||||
|
</div>{{else}} |
||||||
|
{{range $.Collections}} |
||||||
|
<a class="user hidden action" href="/{{$el.ID}}" title="Change to a draft" onclick="postActions.move(this, '{{$el.ID}}', '|anonymous|');return false">change to <em>draft</em></a> |
||||||
|
{{end}} |
||||||
|
{{end}} |
||||||
|
{{end}} |
||||||
|
</h2> |
||||||
|
{{end}} |
||||||
|
|
||||||
|
{{if .Excerpt}}<div {{if .Language}}lang="{{.Language.String}}"{{end}} dir="{{.Direction}}" class="book p-summary">{{if and (and (not $.IsOwner) (not $.Format.ShowDates)) (not .Title.String)}}<a class="hidden action" href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}">view</a>{{end}}{{.Excerpt}}</div> |
||||||
|
|
||||||
|
<a class="read-more" href="{{$.CanonicalURL}}{{.Slug.String}}">{{localstr "Read more..." .Language.String}}</a>{{else}}<div {{if .Language}}lang="{{.Language.String}}"{{end}} dir="{{.Direction}}" class="book e-content">{{if and (and (not $.IsOwner) (not $.Format.ShowDates)) (not .Title.String)}}<a class="hidden action" href="{{if $.IsOwner}}/{{$.Alias}}/{{.Slug.String}}{{else}}{{$.CanonicalURL}}{{.Slug.String}}{{end}}">view</a>{{end}}{{.HTMLContent}}</div>{{end}}</article>{{ end }} |
||||||
|
{{ end }} |
@ -0,0 +1,75 @@ |
|||||||
|
{{define "password-collection"}}<!DOCTYPE HTML> |
||||||
|
<html {{if .Language}}lang="{{.Language}}"{{end}} dir="{{.Direction}}"> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>{{.DisplayTitle}}{{if not .SingleUser}} — {{.SiteName}}{{end}}</title> |
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/write.css" /> |
||||||
|
<link rel="shortcut icon" href="/favicon.ico" /> |
||||||
|
<link rel="canonical" href="{{.CanonicalURL}}"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
|
||||||
|
<meta name="description" content="{{.Description}}"> |
||||||
|
<meta itemprop="name" content="{{.DisplayTitle}}"> |
||||||
|
<meta itemprop="description" content="{{.Description}}"> |
||||||
|
<meta name="twitter:card" content="summary"> |
||||||
|
<meta name="twitter:title" content="{{.DisplayTitle}}"> |
||||||
|
<meta name="twitter:description" content="{{.Description}}"> |
||||||
|
<meta property="og:title" content="{{.DisplayTitle}}" /> |
||||||
|
<meta property="og:site_name" content="{{.DisplayTitle}}" /> |
||||||
|
<meta property="og:type" content="article" /> |
||||||
|
<meta property="og:url" content="{{.CanonicalURL}}" /> |
||||||
|
<meta property="og:description" content="{{.Description}}" /> |
||||||
|
{{if .StyleSheet}}<style type="text/css">{{.StyleSheetDisplay}}</style>{{end}} |
||||||
|
|
||||||
|
</head> |
||||||
|
<body id="collection" itemscope itemtype="http://schema.org/WebPage"> |
||||||
|
<header> |
||||||
|
<h1 dir="{{.Direction}}" id="blog-title"><a href="/{{.Alias}}/" class="h-card p-author u-url" rel="me author">{{.DisplayTitle}}</a></h1> |
||||||
|
</header> |
||||||
|
|
||||||
|
<div id="wrapper"> |
||||||
|
|
||||||
|
<div class="access"> |
||||||
|
<form method="post" action="/api/auth/read"> |
||||||
|
{{if .Flashes}}<ul class="errors"> |
||||||
|
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}} |
||||||
|
</ul>{{else}} |
||||||
|
<h2>This blog requires a password.</h2> |
||||||
|
{{end}} |
||||||
|
<input type="hidden" name="alias" value="{{.Alias}}" /> |
||||||
|
<input type="hidden" name="to" value="{{.Next}}" /> |
||||||
|
<input type="password" autocomplete="new-password" name="password" tabindex="1" autofocus /> |
||||||
|
<p><input type="submit" value="Enter" /></p> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<footer> |
||||||
|
<hr /> |
||||||
|
<nav dir="ltr"> |
||||||
|
<a class="home pubd" href="/">{{.SiteName}}</a> · powered by <a style="margin-left:0" href="https://writefreely.org">write freely</a> |
||||||
|
</nav> |
||||||
|
</footer> |
||||||
|
</body> |
||||||
|
|
||||||
|
{{if and .Script .CanShowScript}}<script type="text/javascript">{{.ScriptDisplay}}</script>{{end}} |
||||||
|
<script src="/js/h.js"></script> |
||||||
|
<script src="/js/postactions.js"></script> |
||||||
|
<script type="text/javascript"> |
||||||
|
try { |
||||||
|
WebFontConfig = { |
||||||
|
custom: { families: [ 'Lora:400,700:latin', 'Open+Sans:400,700:latin' ], urls: [ '/css/fonts.css' ] } |
||||||
|
}; |
||||||
|
(function() { |
||||||
|
var wf = document.createElement('script'); |
||||||
|
wf.src = '/js/webfont.js'; |
||||||
|
wf.type = 'text/javascript'; |
||||||
|
wf.async = 'true'; |
||||||
|
var s = document.getElementsByTagName('script')[0]; |
||||||
|
s.parentNode.insertBefore(wf, s); |
||||||
|
})(); |
||||||
|
} catch (e) {} |
||||||
|
</script> |
||||||
|
</html>{{end}} |
@ -0,0 +1,97 @@ |
|||||||
|
{{define "post"}}<!DOCTYPE HTML> |
||||||
|
<html {{if .Language}}lang="{{.Language}}"{{end}} dir="{{.Direction}}"> |
||||||
|
<head prefix="og: http://ogp.me/ns#"> |
||||||
|
<meta charset="utf-8"> |
||||||
|
|
||||||
|
<title>{{if .Title}}{{.Title}}{{else}}{{.GenTitle}}{{end}} — {{.SiteName}}</title> |
||||||
|
|
||||||
|
{{if .IsCode}} |
||||||
|
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/mono-blue.min.css"> |
||||||
|
{{end}} |
||||||
|
<link rel="stylesheet" type="text/css" href="/css/write.css" /> |
||||||
|
<link rel="shortcut icon" href="/favicon.ico" /> |
||||||
|
<link rel="canonical" href="{{.Host}}/{{.ID}}" /> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
|
||||||
|
<meta name="generator" content="{{.SiteName}}"> |
||||||
|
<meta name="title" content="{{if .Title}}{{.Title}}{{else}}{{.GenTitle}}{{end}}"> |
||||||
|
<meta name="description" content="{{.Description}}"> |
||||||
|
<meta itemprop="name" content="{{.SiteName}}"> |
||||||
|
<meta itemprop="description" content="{{.Description}}"> |
||||||
|
<meta name="twitter:card" content="summary"> |
||||||
|
<meta name="twitter:title" content="{{if .Title}}{{.Title}}{{else}}{{.GenTitle}}{{end}}"> |
||||||
|
<meta name="twitter:description" content="{{.Description}}"> |
||||||
|
{{if gt .Views 1}}<meta name="twitter:label1" value="Views"> |
||||||
|
<meta name="twitter:data1" value="{{largeNumFmt .Views}}">{{end}} |
||||||
|
<meta name="twitter:image" content="https://write.as/img/w-sq-light.png"> |
||||||
|
<meta property="og:title" content="{{if .Title}}{{.Title}}{{else}}{{.GenTitle}}{{end}}" /> |
||||||
|
<meta property="og:site_name" content="{{.SiteName}}" /> |
||||||
|
<meta property="og:type" content="article" /> |
||||||
|
<meta property="og:url" content="https://write.as/{{.ID}}" /> |
||||||
|
<meta property="og:description" content="{{.Description}}" /> |
||||||
|
<meta property="og:image" content="https://write.as/img/w-sq-light.png"> |
||||||
|
{{if .Author}}<meta property="article:author" content="https://{{.Author}}" />{{end}} |
||||||
|
|
||||||
|
</head> |
||||||
|
<body id="post"> |
||||||
|
|
||||||
|
<header> |
||||||
|
<h1 dir="{{.Direction}}"><a href="/">{{.SiteName}}</a></h1> |
||||||
|
<nav> |
||||||
|
<span class="views{{if not .IsOwner}} owner-visible{{end}}" dir="ltr"><strong>{{largeNumFmt .Views}}</strong> {{pluralize "view" "views" .Views}}</span> |
||||||
|
{{if .IsCode}}<a href="/{{.ID}}.txt" rel="noindex" dir="{{.Direction}}">View raw</a>{{end}} |
||||||
|
{{ if .Username }} |
||||||
|
{{if .IsOwner}} |
||||||
|
<a href="/{{.ID}}/edit" dir="{{.Direction}}">Edit</a> |
||||||
|
{{end}} |
||||||
|
<a class="xtra-feature dash-nav" href="/me/posts/" dir="{{.Direction}}">Drafts</a> |
||||||
|
{{ end }} |
||||||
|
</nav> |
||||||
|
</header> |
||||||
|
|
||||||
|
<article class="{{.Font}} h-entry">{{if .Title}}<h2 id="title" class="p-name">{{.Title}}</h2>{{end}}{{ if .IsPlainText }}<p id="post-body" class="e-content">{{.Content}}</p>{{ else }}<div id="post-body" class="e-content">{{.HTMLContent}}</div>{{ end }}</article> |
||||||
|
|
||||||
|
<footer dir="ltr"><hr><nav><p style="font-size: 0.9em">{{localhtml "published with write.as" .Language}}</p></nav></footer> |
||||||
|
</body> |
||||||
|
|
||||||
|
{{if .IsCode}} |
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script> |
||||||
|
<script> |
||||||
|
hljs.highlightBlock(document.getElementById('post-body')); |
||||||
|
</script> |
||||||
|
{{else}} |
||||||
|
<script src="/js/h.js"></script> |
||||||
|
{{if .IsPlainText}}<script src="/js/twitter-text.min.js"></script>{{end}} |
||||||
|
{{end}} |
||||||
|
<script type="text/javascript"> |
||||||
|
try { |
||||||
|
WebFontConfig = { |
||||||
|
custom: { families: [ 'Lora:400,700:latin'{{if eq .Font "sans"}}, 'Open+Sans:400,700:latin'{{end}} ], urls: [ '/css/fonts.css' ] } |
||||||
|
}; |
||||||
|
(function() { |
||||||
|
var wf = document.createElement('script'); |
||||||
|
wf.src = '/js/webfont.js'; |
||||||
|
wf.type = 'text/javascript'; |
||||||
|
wf.async = 'true'; |
||||||
|
var s = document.getElementsByTagName('script')[0]; |
||||||
|
s.parentNode.insertBefore(wf, s); |
||||||
|
})(); |
||||||
|
} catch (e) { /* ¯\_(ツ)_/¯ */ } |
||||||
|
|
||||||
|
var posts = localStorage.getItem('posts'); |
||||||
|
if (posts != null) { |
||||||
|
posts = JSON.parse(posts); |
||||||
|
var $nav = document.getElementsByTagName('nav')[0]; |
||||||
|
for (var i=0; i<posts.length; i++) { |
||||||
|
if (posts[i].id == "{{.ID}}") { |
||||||
|
$nav.innerHTML = $nav.innerHTML + '<a class="xtra-feature" href="/edit/{{.ID}}" dir="{{.Direction}}">Edit</a>'; |
||||||
|
var $ownerVis = document.querySelectorAll('.owner-visible'); |
||||||
|
for (var i=0; i<$ownerVis.length; i++) { |
||||||
|
$ownerVis[i].classList.remove('owner-visible'); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
</html>{{end}} |
Loading…
Reference in new issue