Browse Source

feat: add JSONLD schema for organizations

Forms part of the transition from Microdata to JSON-LD.

BREAKING CHANGES

Upgrades to your `params.toml` file are required:

- Address field has been split into semantic parts
- Latitude and longitude have moved under `coordinates` option
- Map settings have moved under `[map]` section
- Office hours can now be specified more simply, as a list
- Added optional `list_delimiter` option for formatting addresses

See #413
George Cushen 5 years ago
parent
commit
bd2e4ec418

+ 100 - 51
exampleSite/config/_default/params.toml

@@ -1,6 +1,10 @@
 # SITE SETUP
 # Documentation: https://sourcethemes.com/academic/
 
+############################
+## Theme
+############################
+
 # Choose a theme.
 #   Latest themes (may require updating): https://sourcethemes.com/academic/themes/
 #   Browse built-in themes in `themes/academic/data/themes/`
@@ -20,19 +24,36 @@ font = ""
 # Sizes: XS (extra small), S (small), M (medium), L (large - DEFAULT), XL (extra large)
 font_size = "L"
 
-# Description for social sharing and search engines. If undefined, superuser role is used in place.
-description = ""
+############################
+## Basic Info
+############################
 
-# Default image for social sharing and search engines. Place image in `static/img/` folder and specify image name here.
-sharing_image = ""
+# Website type
+#   Improve how search engines understand your site.
+#   For personal sites, choose "Person".
+#   For organizations and projects, choose from https://schema.org/Organization#subtypes
+#   E.g. Person, Organization, LocalBusiness, Project, EducationalOrganization
+site_type = "Person"
 
-# Twitter username (without @). Used when a visitor shares your site on Twitter.
-twitter = ""
+# Local business type (optional)
+# If you entered "LocalBusiness" above, choose the type of business from https://schema.org/LocalBusiness#subtypes
+local_business_type = ""
+
+# Organization name (optional)
+# Enter an organization or project name. Defaults to the site title from `config.toml`.
+org_name = ""
+
+# Description for social sharing and search engines. If undefined, superuser role is used in place.
+description = ""
 
 # Display a logo in navigation bar rather than title (optional).
 #   To enable, place an image in `static/img/` and reference its filename below. To disable, set the value to "".
 logo = ""
 
+############################
+## Site Features
+############################
+
 # Enable source code highlighting? true/false
 # Documentation: https://sourcethemes.com/academic/docs/writing-markdown-latex/#highlighting-options
 highlight = true
@@ -53,27 +74,34 @@ diagram = false
 privacy_pack = false
 
 # Enable visitors to edit pages?
-# `repo` defines the repository URL. `editable` defines which page types can be edited.
+#   `repo` defines the repository URL. `editable` defines which page types can be edited.
 edit_page = {repo_url = "https://github.com/gcushen/hugo-academic", repo_branch = "master", editable = {docs = true, page = false, post = false}}
 
-# Date and time format (refer to https://sourcethemes.com/academic/docs/customization/#date-format )
-#   Examples: "Mon, Jan 2, 2006" or "2006-01-02"
-date_format = "Jan 2, 2006"
-#   Examples: "3:04 pm" or "15:04"
-time_format = "3:04 PM"
-
 ############################
-## Contact Widget setup   ##
+## Contact details
+##
+## These details power the Contact widget (if enabled).
+## Additionally, for organizations, these details may be used to enrich search engine results.
 ############################
 
 # Enter contact details (optional). To hide a field, clear it to "".
 email = "test@example.org"
 phone = "888 888 88 88"
-address = "Building 1 Room 1, Stanford University, California, 90210, USA"
 
-# Office hours: use `<br>` to insert a line break, or set to "" to remove office hours
-office_hours = """Monday 10:00 to 13:00<br>
-                  Wednesday 09:00 to 10:00"""
+# Address
+# For country_code, use the 2-letter ISO code (see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 )
+address = {street = "450 Serra Mall", city = "Stanford", region = "CA", postcode = "94305", country = "United States", country_code = "US"}
+
+# Geographic coordinates
+# To get your coordinates, right-click on Google Maps and choose "What's here?". The coords will show up at the bottom.
+coordinates = {latitude = "37.4275", longitude = "-122.1697"}
+
+# Directions for visitors to locate you.
+directions = "Enter Building 1 and take the stairs to Office 200 on Floor 2"
+
+# Office hours
+# A list of your office hours. To remove, set to an empty list `[]`.
+office_hours = ["Monday 10:00 to 13:00", "Wednesday 09:00 to 10:00"]
 
 # Enter an optional link for booking appointments (e.g. calendly.com).
 appointment_url = "https://calendly.com"
@@ -88,43 +116,32 @@ contact_links = [
   # {icon = "telegram", icon_pack = "fab", name = "Telegram Me", link = "https://telegram.me/@Telegram"},
   ]
 
-# Display a map.
-# To show your address on a map in the contact widget, you need to enter your latitude, longitude and choose
-# a map provider below.
-# To use Google Maps, set `map = 1` and enter your API key that can be obtained here:
-#   https://developers.google.com/maps/documentation/javascript/get-api-key
-# To use OpenStreetMap tiles, set `map = 2`.
-# To use OpenStreetMap on a high traffic site, set `map = 3` and enter your API key that can be obtained here:
-#   https://www.mapbox.com/studio/account/tokens
-# To get your coordinates, right-click on Google Maps and choose "What's here?". The coords will show up at the bottom.
-#
-# Map provider:
-#   0: No map
-#   1: Google Maps
-#   2: OpenStreetMap (Mapnik)
-#   3: OpenStreetMap (Mapbox)
-map = 2
-map_api_key = ""
-latitude = "37.4275"
-longitude = "-122.1697"
-zoom = 15
-
-# Address line delimiter
-# Popular separators are ", " (comma), "<br>" (new line), " " (space)
-address_delimiter = ", "
+############################
+## Social
+############################
+
+# Default image for social sharing and search engines. Place image in `static/img/` folder and specify image name here.
+sharing_image = ""
+
+# Twitter username (without @). Used when a visitor shares your site on Twitter.
+twitter = ""
 
 ############################
-## Plugins                ##
+## Regional Settings
 ############################
 
-# Load CSS and JS plugins
-#   E.g. To load `/assets/css/custom.css`, set `plugins_css = ["custom"]`.
-#   E.g. To load `/assets/js/custom.js`, set `plugins_js = ["custom"]`.
-plugins_css = []
-plugins_js  = []
+# Date and time format (refer to https://sourcethemes.com/academic/docs/customization/#date-format )
+#   Examples: "Mon, Jan 2, 2006" or "2006-01-02"
+date_format = "Jan 2, 2006"
+#   Examples: "3:04 pm" or "15:04"
+time_format = "3:04 PM"
+
+# List delimiter (separates parts of an address)
+# Popular separators are ", " (comma), "<br>" (new line), " " (space)
+list_delimiter = ", "
 
 ############################
-## Advanced options       ##
+## Advanced
 ############################
 
 # Get user avatars from Gravatar.com? (true/false)
@@ -143,6 +160,12 @@ docs_section_pager = true  # Display pager in Docs layout (e.g. tutorials)?
 # Enable in-built social sharing buttons? (true/false)
 sharing = true
 
+# Load CSS and JS plugins
+#   E.g. To load `/assets/css/custom.css`, set `plugins_css = ["custom"]`.
+#   E.g. To load `/assets/js/custom.js`, set `plugins_js = ["custom"]`.
+plugins_css = []
+plugins_js  = []
+
 # Configuration of publication pages.
 [publications]
   # Date format (refer to https://sourcethemes.com/academic/docs/customization/#date-format )
@@ -163,7 +186,9 @@ sharing = true
   publication_view = 2
   talk_view = 2
 
-# Comments.
+############################
+## Comments
+############################
 [comments]
   # Comment provider:
   #   0: Disabled
@@ -179,7 +204,9 @@ sharing = true
     shortname = ""  # Paste the shortname from your Disqus dashboard.
     show_count = true  # Show comment count in page header? (true/false)
 
-# Search.
+############################
+## Search
+############################
 [search]
   # Search provider:
   #   0: No search engine
@@ -194,3 +221,25 @@ sharing = true
     api_key = ""
     index_name = ""
     show_logo = false
+
+############################
+## Maps
+############################
+[map]
+  # To show your address on a map in the Contact widget, enter your latitude and longitude (above)
+  # and choose a map provider below.
+  #
+  # To use Google Maps, set `engine` to 1 and enter your API key that can be obtained here:
+  #   https://developers.google.com/maps/documentation/javascript/get-api-key
+  # To use OpenStreetMap tiles, set `engine` to 2.
+  # To use OpenStreetMap on a high traffic site, set `engine` to 3 and enter your API key that can be obtained here:
+  #   https://www.mapbox.com/studio/account/tokens
+  #
+  # Map provider:
+  #   0: No map
+  #   1: Google Maps
+  #   2: OpenStreetMap (Mapnik)
+  #   3: OpenStreetMap (Mapbox)
+  engine = 2
+  api_key = ""
+  zoom = 15

+ 9 - 0
layouts/index.html

@@ -5,6 +5,15 @@
   {{ errorf "Please complete the installation of Academic by following the steps at https://sourcethemes.com/academic/docs/install/" }}
 {{ end }}
 
+{{/* Deprecation warnings */}}
+
+{{/* v4.5: Address changed from string to map. */}}
+{{ if isset site.Params "address" }}
+{{ if eq (reflect.IsMap site.Params.address) false }}
+  {{ errorf "Please upgrade the `address` field in `config/_default/params.toml`. Refer to all of the Breaking Changes in v4.5 at https://sourcethemes.com/academic/updates/v4.5.0/" }}
+{{ end }}
+{{ end }}
+
 {{/* Generate homepage. */}}
 {{ partial "widget_page.html" . }}
 

+ 29 - 0
layouts/partials/jsonld/business.html

@@ -0,0 +1,29 @@
+<script type="application/ld+json">
+{
+  "@context": "https://schema.org",
+  "@type": {{site.Params.local_business_type | default site.Params.site_type}},
+  "@id": {{site.BaseURL}},
+  "name": {{site.Params.org_name | default site.Title}},
+  {{with site.Params.logo}}"logo": {{printf "img/%s" . | absURL}},{{end}}
+  {{with site.Params.sharing_image}}"image": {{printf "img/%s" . | absURL}},{{end}}
+  {{ if (eq site.Params.site_type "LocalBusiness") | and site.Params.coordinates }}
+  "geo": {
+    "@type": "GeoCoordinates",
+    "latitude": {{site.Params.coordinates.latitude}},
+    "longitude": {{site.Params.coordinates.longitude}}
+  },
+  {{end}}
+  {{ with site.Params.address }}
+  "address": {
+    "@type": "PostalAddress",
+    "streetAddress": {{ .street | default "" }},
+    "addressLocality": {{ .city | default "" }},
+    "addressRegion": {{ .region | default "" }},
+    "postalCode": {{ .postcode | default "" }},
+    "addressCountry": {{ .country_code | default .country | default "" }}
+  },
+  {{end}}
+  {{ with site.Params.phone }}"telephone": {{.}},{{end}}
+  "url": {{site.BaseURL}}
+}
+</script>

+ 6 - 1
layouts/partials/jsonld/main.html

@@ -1,13 +1,18 @@
 {{ $page := .page }}
 {{ $summary := .summary }}
+{{ $site_type := site.Params.site_type | default "Person" }}
 
 {{- if $page.IsHome -}}
 
   {{ partial "jsonld/website.html" $page }}
 
+  {{ if ne $site_type "Person" }}
+    {{ partial "jsonld/business.html" $page }}
+  {{ end }}
+
 {{- else if $page.IsPage -}}
 
-  {{ if or (eq $page.Type "post") (eq $page.Type "publication") }}
+  {{ if (eq $page.Type "post") | or (eq $page.Type "publication") | or (eq $page.Type "project") }}
     {{ partial "jsonld/article.html" (dict "page" $page "summary" $summary) }}
   {{ end }}
 

+ 1 - 1
layouts/partials/site_head.html

@@ -83,7 +83,7 @@
       {{ end }}
     {{ end }}
 
-    {{ if or (eq site.Params.map 2) (eq site.Params.map 3) }}
+    {{ if or (eq site.Params.map.engine 2) (eq site.Params.map.engine 3) }}
     {{ printf "<link rel=\"stylesheet\" href=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\">" (printf $css.leaflet.url $css.leaflet.version) $css.leaflet.sri | safeHTML }}
     {{ end }}
 

+ 3 - 3
layouts/partials/site_js.html

@@ -35,12 +35,12 @@
     {{ end }}
 
     {{/* Maps JS. */}}
-    {{ if eq site.Params.map 1 }}
-      <script async defer src="https://maps.googleapis.com/maps/api/js?key={{ site.Params.map_api_key }}"></script>
+    {{ if eq site.Params.map.engine 1 }}
+      <script async defer src="https://maps.googleapis.com/maps/api/js?key={{ site.Params.map.api_key }}"></script>
       {{ if ($scr.Get "use_cdn") }}
       {{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.gmaps.url $js.gmaps.version) $js.gmaps.sri | safeHTML }}
       {{ end }}
-    {{ else if and (or (eq site.Params.map 2) (eq site.Params.map 3)) ($scr.Get "use_cdn") }}
+    {{ else if and (or (eq site.Params.map.engine 2) (eq site.Params.map.engine 3)) ($scr.Get "use_cdn") }}
       {{ printf "<script src=\"%s\" integrity=\"%s\" crossorigin=\"anonymous\"></script>" (printf $js.leaflet.url $js.leaflet.version) $js.leaflet.sri | safeHTML }}
     {{ end }}
 

+ 45 - 23
layouts/partials/widgets/contact.html

@@ -1,6 +1,7 @@
 {{ $ := .root }}
 {{ $page := .page }}
 {{ $autolink := default true $page.Params.autolink }}
+{{ $data := site.Params }}
 
 <!-- Contact widget -->
 <div class="row contact-widget">
@@ -17,10 +18,10 @@
     {{ if eq $page.Params.email_form 1 }}
       {{ $post_action = "netlify" }}
     {{ else }}
-      {{ if not site.Params.email }}
-        {{ errorf "Please set an email address for the contact form using the `email` parameter in `config.toml`. Otherwise, set `email_form = 0` to disable the contact form." }}
+      {{ if not $data.email }}
+        {{ errorf "Please set an email address for the contact form using the `email` parameter in `params.toml`. Otherwise, set `email_form = 0` to disable the contact form." }}
       {{ end }}
-      {{ $post_action = printf "action=\"https://formspree.io/%s\"" site.Params.email }}
+      {{ $post_action = printf "action=\"https://formspree.io/%s\"" $data.email }}
     {{end}}
 
     <div class="mb-3">
@@ -42,41 +43,62 @@
     </div>
     {{end}}
 
-    <ul class="fa-ul" itemscope>
+    <ul class="fa-ul">
 
-      {{ if and site.Params.email (not $page.Params.email_form) }}
+      {{ if and $data.email (not $page.Params.email_form) }}
       <li>
         <i class="fa-li fas fa-envelope fa-2x" aria-hidden="true"></i>
-        <span id="person-email" itemprop="email">
-        {{- if $autolink }}<a href="mailto:{{ site.Params.email }}">{{ site.Params.email }}</a>{{ else }}{{ site.Params.email }}{{ end -}}
+        <span id="person-email">
+        {{- if $autolink }}<a href="mailto:{{ $data.email }}">{{ $data.email }}</a>{{ else }}{{ $data.email }}{{ end -}}
         </span>
       </li>
       {{ end }}
 
-      {{ with site.Params.phone }}
+      {{ with $data.phone }}
       <li>
         <i class="fa-li fas fa-phone fa-2x" aria-hidden="true"></i>
-        <span id="person-telephone" itemprop="telephone">
+        <span id="person-telephone">
         {{- if $autolink }}<a href="tel:{{ . }}">{{ . }}</a>{{ else }}{{ . }}{{ end -}}
         </span>
       </li>
       {{ end }}
 
-      {{ with site.Params.address }}
+      {{ $addr_formatted := "" }}{{/* Scoping for maps. */}}
+      {{ if $data.address }}
+        {{ $addr := slice }}
+        {{with $data.address.street}}{{$addr = $addr | append .}}{{end}}
+        {{with $data.address.city}}{{$addr = $addr | append .}}{{end}}
+        {{with $data.address.region}}{{$addr = $addr | append .}}{{end}}
+        {{with $data.address.postcode}}{{$addr = $addr | append .}}{{end}}
+        {{with $data.address.country}}{{$addr = $addr | append .}}{{end}}
+        {{ $addr_formatted = delimit $addr (site.Params.list_delimiter | default ", ") }}
+        <li>
+          <i class="fa-li fas fa-map-marker fa-2x" aria-hidden="true"></i>
+          <span id="person-address">{{ $addr_formatted }}</span>
+        </li>
+      {{ end }}
+
+      {{ with $data.directions }}
       <li>
-        <i class="fa-li fas fa-map-marker fa-2x" aria-hidden="true"></i>
-        <span id="person-address" itemprop="address">{{ . | markdownify | emojify }}</span>
+        <i class="fa-li fas fa-compass fa-2x" aria-hidden="true"></i>
+        <span>{{ . | markdownify | emojify }}</span>
       </li>
       {{ end }}
 
-      {{ with site.Params.office_hours }}
+      {{ with $data.office_hours }}
       <li>
         <i class="fa-li fas fa-clock fa-2x" aria-hidden="true"></i>
-        <span>{{ . | markdownify | emojify }}</span>
+        <span>
+          {{- if not (reflect.IsSlice .)}}{{/* Support legacy string format. */}}
+            {{- . | markdownify | emojify -}}
+          {{else}}
+            {{- delimit . "<br>" | markdownify | emojify -}}
+          {{end -}}
+        </span>
       </li>
       {{ end }}
 
-      {{ with site.Params.appointment_url }}
+      {{ with $data.appointment_url }}
       <li>
         <i class="fa-li fas fa-calendar-check fa-2x" aria-hidden="true"></i>
         <a href="{{ . }}" target="_blank" rel="noopener">{{ i18n "book_appointment" | default "Book an appointment" }}</a>
@@ -84,7 +106,7 @@
       {{ end }}
 
       {{/* Contact links. */}}
-      {{ range site.Params.contact_links }}
+      {{ range $data.contact_links }}
       {{ $pack := or .icon_pack "fas" }}
       {{ $pack_prefix := $pack }}
       {{ if in (slice "fab" "fas" "far" "fal") $pack }}
@@ -106,14 +128,14 @@
 
     </ul>
 
-    {{ if site.Params.map }}
+    {{ if and site.Params.map.engine $data.coordinates.latitude }}
     <div class="d-none">
-      <input id="map-provider" value="{{ site.Params.map }}">
-      <input id="map-lat" value="{{ site.Params.latitude }}">
-      <input id="map-lng" value="{{ site.Params.longitude }}">
-      <input id="map-dir" value="{{ site.Params.address }}">
-      <input id="map-zoom" value="{{ site.Params.zoom | default "15" }}">
-      <input id="map-api-key" value="{{ site.Params.map_api_key }}">
+      <input id="map-provider" value="{{ site.Params.map.engine }}">
+      <input id="map-lat" value="{{ $data.coordinates.latitude }}">
+      <input id="map-lng" value="{{ $data.coordinates.longitude }}">
+      <input id="map-dir" value="{{ $addr_formatted }}">
+      <input id="map-zoom" value="{{ site.Params.map.zoom | default "15" }}">
+      <input id="map-api-key" value="{{ site.Params.map.api_key }}">
     </div>
     <div id="map"></div>
     {{ end }}

+ 1 - 1
layouts/talk/single.html

@@ -57,7 +57,7 @@
             {{with .Params.address.region}}{{$addr = $addr | append .}}{{end}}
             {{with .Params.address.postcode}}{{$addr = $addr | append .}}{{end}}
             {{with .Params.address.country}}{{$addr = $addr | append .}}{{end}}
-            {{ $addr_formatted := delimit $addr (site.Params.address_delimiter | default ", ") }}
+            {{ $addr_formatted := delimit $addr (site.Params.list_delimiter | default ", ") }}
             <div class="col-md-3"></div>
             <div class="col-12 col-md-9">{{$addr_formatted}}</div>
           {{end}}