Added AuthorList, Author, AuthorSocial, SiteSocial, Image and Video structs

Added Page.Author(s) functions
Added schema, opengraph, twitter_cards, google_news metadata templates
Added "" template
This commit is contained in:
Derek Perkins 2014-12-09 11:33:55 -07:00 committed by spf13
parent fd33e5d202
commit 8f6f871f53
5 changed files with 233 additions and 2 deletions

49
hugolib/author.go Normal file
View file

@ -0,0 +1,49 @@
// Copyright © 2013 Steve Francia <spf@spf13.com>.
//
// Licensed under the Simple Public 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://opensource.org/licenses/Simple-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.
package hugolib
/*
* An author list is a list of all authors and their metadata
*/
type AuthorList map[string]Author
/*
* An author contains details about the author of a page
*/
type Author struct {
GivenName string
FamilyName string
DisplayName string
Thumbnail string
Image string
ShortBio string
LongBio string
Email string
Social AuthorSocial
}
// AuthorSocial is a place to put social details per author. These are the
// standard keys that themes will expect to have available, but can be
// expanded to any others on a per site basis
// - website
// - github
// - facebook
// - twitter
// - googleplus
// - pinterest
// - instagram
// - youtube
// - linkedin
// - skype
type AuthorSocial map[string]string

60
hugolib/media.go Normal file
View file

@ -0,0 +1,60 @@
// Copyright © 2013 Steve Francia <spf@spf13.com>.
//
// Licensed under the Simple Public 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://opensource.org/licenses/Simple-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.
package hugolib
// An image contains metadata for images + image sitemaps
// https://support.google.com/webmasters/answer/178636?hl=en
type Image struct {
// The URL of the image. In some cases, the image URL may not be on the
// same domain as your main site. This is fine, as long as both domains
// are verified in Webmaster Tools. If, for example, you use a
// content delivery network (CDN) to host your images, make sure that the
// hosting site is verified in Webmaster Tools OR that you submit your
// sitemap using robots.txt. In addition, make sure that your robots.txt
// file doesnt disallow the crawling of any content you want indexed.
URL string
Title string
Caption string
AltText string
// The geographic location of the image. For example,
// <image:geo_location>Limerick, Ireland</image:geo_location>.
GeoLocation string
// A URL to the license of the image.
License string
}
// An video contains metadata for videos + video sitemaps
// https://support.google.com/webmasters/answer/80471?hl=en
type Video struct {
ThumbnailLoc string
Title string
Description string
ContentLoc string
PlayerLoc string
Duration string
ExpirationDate string
Rating string
ViewCount string
PublicationDate string
FamilyFriendly string
Restriction string
GalleryLoc string
Price string
RequiresSubscription string
Uploader string
Live string
}

View file

@ -40,7 +40,8 @@ type Page struct {
Summary template.HTML
Aliases []string
Status string
Images []string
Images []Image
Videos []Video
TableOfContents template.HTML
Truncated bool
Draft bool
@ -68,7 +69,6 @@ type Source struct {
Content []byte
source.File
}
type PageMeta struct {
WordCount int
FuzzyWordCount int
@ -98,6 +98,32 @@ func (p *Page) IsPage() bool {
return true
}
func (p *Page) Author() Author {
authors := p.Authors()
for _, author := range authors {
return author
}
return Author{}
}
func (p *Page) Authors() AuthorList {
authorKeys, ok := p.Params["authors"]
authors := authorKeys.([]string)
if !ok || len(authors) < 1 || len(p.Site.Authors) < 1 {
return AuthorList{}
}
al := make(AuthorList)
for _, author := range authors {
a, ok := p.Site.Authors[author]
if ok {
al[author] = a
}
}
return al
}
func (p *Page) UniqueId() string {
return p.Source.UniqueId()
}

View file

@ -88,6 +88,8 @@ type targetList struct {
type SiteInfo struct {
BaseUrl template.URL
Taxonomies TaxonomyList
Authors AuthorList
Social SiteSocial
Indexes *TaxonomyList // legacy, should be identical to Taxonomies
Sections Taxonomy
Pages *Pages
@ -105,6 +107,21 @@ type SiteInfo struct {
BuildDrafts bool
}
// SiteSocial is a place to put social details on a site level. These are the
// standard keys that themes will expect to have available, but can be
// expanded to any others on a per site basis
// github
// facebook
// facebook_admin
// twitter
// twitter_domain
// googleplus
// pinterest
// instagram
// youtube
// linkedin
type SiteSocial map[string]string
func (s *SiteInfo) GetParam(key string) interface{} {
v := s.Params[strings.ToLower(key)]

View file

@ -96,4 +96,83 @@ func (t *GoHtmlTemplate) EmbedTemplates() {
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>{{end}}`)
// Add SEO & Social metadata
t.AddInternalTemplate("_default", "opengraph.html", `<meta property="og:title" content="{{ .Title }}" />
<meta property="og:description" content="{{ if .Description }}{{ .Description }}{{ else }}{{if .IsPage}}{{ .Summary }}{{ end }}{{ end }}" />
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
<meta property="og:url" content="{{ .Permalink }}" />
{{ with .Params.images }}{{ range first 6 . }}
<meta property="og:image" content="{{ . }}" />
{{ end }}{{ end }}
<meta property="og:updated_time" content="{{ .Date }}"/>{{ with .Params.audio }}
<meta property="og:audio" content="{{ . }}" />{{ end }}{{ with .Params.locale }}
<meta property="og:locale" content="{{ . }}" />{{ end }}{{ with .Site.Params.title }}
<meta property="og:site_name" content="{{ . }}" />{{ end }}{{ with .Params.videos }}
{{ range .Params.videos }}
<meta property="og:video" content="{{ . }}" />
{{ end }}
<!-- If it is part of a series, link to related articles -->
{{ $permalink := .Permalink }}
{{ $siteSeries := .Site.Taxonomies.series }}{{ with .Params.series }}
{{ range $name := . }}
{{ $series := index $siteSeries $name }}
{{ range $page := first 6 $series.Pages }}
{{ if ne $page.Permalink $permalink }}<meta property="og:see_also" content="{{ $page.Permalink }}" />{{ end }}
{{ end }}
{{ end }}{{ end }}
{{ if .IsPage }}
{{ range .Site.Authors }}{{ with .Social.facebook }}
<meta property="article:author" content="https://www.facebook.com/{{ . }}" />{{ end }}{{ with .Site.Social.facebook }}
<meta property="article:publisher" content="https://www.facebook.com/{{ . }}" />{{ end }}
<meta property="article:published_time" content="{{ .PublishDate }}" />
<meta property="article:modified_time" content="{{ .Date }}" />
<meta property="article:section" content="{{ .Section }}" />
{{ with .Params.tags }}{{ range first 6 . }}
<meta property="article:tag" content="{{ . }}" />{{ end }}{{ end }}
{{ end }}
<!-- Facebook Page Admin ID for Domain Insights -->
{{ with .Site.Social.facebook_admin }}<meta property="fb:admins" content="{{ . }}" />{{ end }}`)
t.AddInternalTemplate("_default", "twitter_cards.html", `{{ if .IsPage }}
{{ with .Params.images }}
<!-- Twitter summary card with large image must be at least 280x150px -->
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:image:src" content="{{ index . 0 }}"/>
{{ else }}
<meta name="twitter:card" content="summary"/>
{{ end }}
<!-- Twitter Card data -->
<meta name="twitter:title" content="{{ .Title }}"/>
<meta name="twitter:description" content="{{ if .Description }}{{ .Description }}{{ else }}{{if .IsPage}}{{ .Summary }}{{ end }}{{ end }}"/>
{{ with .Site.Social.twitter }}<meta name="twitter:site" content="@{{ . }}"/>{{ end }}
{{ with .Site.Social.twitter_domain }}<meta name="twitter:domain" content="{{ . }}"/>{{ end }}
{{ range .Site.Authors }}
{{ with .twitter }}<meta name="twitter:creator" content="@{{ . }}"/>{{ end }}
{{ end }}{{ end }}`)
t.AddInternalTemplate("_default", "google_news.html", `{{ if .IsPage }}{{ with .Params.news_keywords }}
<meta name="news_keywords" content="{{ range $i, $kw := first 10 . }}{{ if $i }},{{ end }}{{ $kw }}{{ end }}" />
{{ end }}{{ end }}`)
t.AddInternalTemplate("_default", "schema.html", `{{ with .Site.Social.GooglePlus }}<link rel="publisher" href="{{ . }}"/>{{ end }}
<meta itemprop="name" content="{{ .Title }}">
<meta itemprop="description" content="{{ if .Description }}{{ .Description }}{{ else }}{{if .IsPage}}{{ .Summary }}{{ end }}{{ end }}">
{{if .IsPage}}
<meta itemprop="datePublished" content="{{ .PublishDate }}" />
<meta itemprop="dateModified" content="{{ .Date }}" />
<meta itemprop="wordCount" content="{{ .WordCount }}">
{{ with .Params.images }}{{ range first 6 . }}
<meta itemprop="image" content="{{ . }}">
{{ end }}{{ end }}
<!-- Output all taxonomies as schema.org keywords -->
<meta itemprop="keywords" content="{{ range $plural, $terms := .Site.Taxonomies }}{{ range $term, $val := $terms }}{{ printf "%s," $term }}{{ end }}{{ end }}" />
{{ end }}{{ end }}`)
}