mirror of
https://github.com/gohugoio/hugo.git
synced 2025-03-19 04:14:24 +00:00
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:
parent
fd33e5d202
commit
8f6f871f53
5 changed files with 233 additions and 2 deletions
49
hugolib/author.go
Normal file
49
hugolib/author.go
Normal 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
60
hugolib/media.go
Normal 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 doesn’t 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
|
||||||
|
}
|
|
@ -40,7 +40,8 @@ type Page struct {
|
||||||
Summary template.HTML
|
Summary template.HTML
|
||||||
Aliases []string
|
Aliases []string
|
||||||
Status string
|
Status string
|
||||||
Images []string
|
Images []Image
|
||||||
|
Videos []Video
|
||||||
TableOfContents template.HTML
|
TableOfContents template.HTML
|
||||||
Truncated bool
|
Truncated bool
|
||||||
Draft bool
|
Draft bool
|
||||||
|
@ -68,7 +69,6 @@ type Source struct {
|
||||||
Content []byte
|
Content []byte
|
||||||
source.File
|
source.File
|
||||||
}
|
}
|
||||||
|
|
||||||
type PageMeta struct {
|
type PageMeta struct {
|
||||||
WordCount int
|
WordCount int
|
||||||
FuzzyWordCount int
|
FuzzyWordCount int
|
||||||
|
@ -98,6 +98,32 @@ func (p *Page) IsPage() bool {
|
||||||
return true
|
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 {
|
func (p *Page) UniqueId() string {
|
||||||
return p.Source.UniqueId()
|
return p.Source.UniqueId()
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,8 @@ type targetList struct {
|
||||||
type SiteInfo struct {
|
type SiteInfo struct {
|
||||||
BaseUrl template.URL
|
BaseUrl template.URL
|
||||||
Taxonomies TaxonomyList
|
Taxonomies TaxonomyList
|
||||||
|
Authors AuthorList
|
||||||
|
Social SiteSocial
|
||||||
Indexes *TaxonomyList // legacy, should be identical to Taxonomies
|
Indexes *TaxonomyList // legacy, should be identical to Taxonomies
|
||||||
Sections Taxonomy
|
Sections Taxonomy
|
||||||
Pages *Pages
|
Pages *Pages
|
||||||
|
@ -105,6 +107,21 @@ type SiteInfo struct {
|
||||||
BuildDrafts bool
|
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{} {
|
func (s *SiteInfo) GetParam(key string) interface{} {
|
||||||
v := s.Params[strings.ToLower(key)]
|
v := s.Params[strings.ToLower(key)]
|
||||||
|
|
||||||
|
|
|
@ -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>
|
<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}}`)
|
<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 }}`)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue