Skip to content

Commit

Permalink
Metadata for HTML output
Browse files Browse the repository at this point in the history
From DocBook => HTML:

* <meta name="title">...</meta> =>
    <meta property="twitter:title" content="..."/>
    <meta property="og:title" content="..."/>

* <meta name="social-descr">...</meta> =>
    <meta property="twitter:description" content="..."/>
    <meta property="og:description" content="..."/>

* <meta name="category" content="Systems Management"/> =>
    <meta name="category" content="..."/>

* <meta name="maintainer" content="tux@example.com"/> =>
   <meta name="DC.creator" content="tux@example.com"/>

* Also try to match meta[@name='bugtracker']/d:phrase[@ROLE='editurl']

* Introduce include.html.dublincore parameter
  Used to add Dublin Core metadata for HTML
  • Loading branch information
tomschr committed May 8, 2023
1 parent 4a3cfd3 commit d7a1639
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 55 deletions.
87 changes: 32 additions & 55 deletions suse2022-ns/xhtml/docbook.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<xsl:include href="titlepage.templates.xsl"/>

<xsl:include href="tracker.meta.xsl"/>
<xsl:include href="meta.xsl"/>


<!-- Actual templates start here -->
Expand Down Expand Up @@ -178,6 +179,9 @@

<xsl:variable name="meta.description.base">
<xsl:choose>
<xsl:when test="d:info/d:meta[@name='description']">
<xsl:value-of select="normalize-space(d:info/d:meta[@name='description'][1])"/>
</xsl:when>
<xsl:when test="d:info/d:abstract or d:info/d:highlights">
<xsl:for-each select="(d:info[1]/d:abstract[1]|d:info[1]/d:highlights[1])[1]/*">
<xsl:value-of select="normalize-space(.)"/>
Expand Down Expand Up @@ -248,7 +252,6 @@
<xsl:with-param name="ellipsize.after" select="$socialmedia.title.length"/>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="socialmedia.preview">
<xsl:choose>
<!-- We ignore:
Expand All @@ -270,6 +273,7 @@
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="metanodes" select="$node/ancestor-or-self::*/d:info/d:meta"/>

<title><xsl:value-of select="$title"/></title>

Expand Down Expand Up @@ -311,6 +315,13 @@
<xsl:text>&#10;</xsl:text>
</xsl:if>

<xsl:if test="$include.html.dublincore">
<!-- For Dublin Core metadata -->
<link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" />
<link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" />
<xsl:text>&#10;</xsl:text>
</xsl:if>

<xsl:if test="$html.script != ''">
<xsl:call-template name="output.html.scripts">
<xsl:with-param name="scripts" select="normalize-space($html.script)"/>
Expand Down Expand Up @@ -347,58 +358,21 @@
<xsl:call-template name="create.bugtracker.information"/>

<xsl:apply-templates select="." mode="head.keywords.content"/>
<meta name="publisher" content="SUSE"/>

<xsl:if test="$canonical-url-base != ''">
<xsl:variable name="ischunk">
<xsl:call-template name="chunk"/>
</xsl:variable>
<xsl:variable name="filename">
<xsl:choose>
<xsl:when test="$ischunk = 1">
<xsl:apply-templates mode="chunk-filename" select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat($root.filename,$html.ext)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="canonical.url">
<xsl:value-of select="concat($canonical-url-base,'/',$filename)"/>
</xsl:variable>
<xsl:apply-templates select="($metanodes[@name='category'])[last()]" mode="meta"/>
<xsl:apply-templates select="($metanodes[@name='updated'])[last()]" mode="meta"/>
<xsl:apply-templates select="($metanodes[@name='maintainer'])[last()]" mode="meta"/>

<link rel="canonical" href="{$canonical.url}"/>
<xsl:text>&#10;</xsl:text>
<!-- These Open Graph and Twitter Cards properties need a canonical URL -->
<meta property="og:url" content="{$canonical.url}"/>
<xsl:text>&#10;</xsl:text>
<meta property="og:image" content="{concat($canonical-url-base,'/',$socialmedia.preview)}"/>
<xsl:text>&#10;</xsl:text>
<meta name="twitter:image" content="{concat($canonical-url-base,'/',$socialmedia.preview)}"/>
<xsl:text>&#10;</xsl:text>

<xsl:call-template name="meta-generator"/>
</xsl:if>

<!-- The following properties "work" without a canonical URL being defined
(but both the Open Graph and Twitter Cards implementations are incomplete
without the above tags, better than nothing though). -->
<meta property="og:title" content="{$socialmedia.title}"/>
<xsl:text>&#10;</xsl:text>
<meta property="og:description" content="{$socialmedia.description}"/>
<xsl:text>&#10;</xsl:text>
<meta property="og:type" content="{$opengraph.type}"/>
<xsl:text>&#10;</xsl:text>
<xsl:call-template name="social-media-opengraph">
<xsl:with-param name="socialmedia.title" select="$socialmedia.title"/>
<xsl:with-param name="socialmedia.description" select="$socialmedia.description"/>
</xsl:call-template>

<meta name="twitter:card" content="{$twittercards.type}"/>
<xsl:text>&#10;</xsl:text>
<meta name="twitter:title" content="{$socialmedia.title}"/>
<xsl:text>&#10;</xsl:text>
<meta name="twitter:description" content="{$socialmedia.description}"/>
<xsl:text>&#10;</xsl:text>
<xsl:if test="string-length($twittercards.twitter.account) &gt; 0">
<meta name="twitter:site" content="{$twittercards.twitter.account}"/>
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:call-template name="social-media-twitter">
<xsl:with-param name="socialmedia.title" select="$socialmedia.title"/>
<xsl:with-param name="socialmedia.description" select="$socialmedia.description"/>
</xsl:call-template>
</xsl:template>


Expand Down Expand Up @@ -582,11 +556,13 @@

<xsl:template name="give.feedback">
<xsl:if test="$generate.give.feedback = 1 or $force.generate.give.feedback = 1">
<xsl:variable name="meta-bugtracker" select="ancestor-or-self::*/d:info/d:meta[@name='bugtracker']/d:phrase[@role='editurl']"/>
<xsl:variable name="editurl" select="ancestor-or-self::*/d:info/dm:docmanager/dm:editurl[1]"/>
<xsl:variable name="xmlbase" select="ancestor-or-self::*[@xml:base][1]/@xml:base"/>
<xsl:variable name="url-candidate" select="($meta-bugtracker | $editurl)[last()]"/>

<xsl:variable name="valid-for-editurl">
<xsl:if test="($draft.mode = 'yes' or $show.edit.link = 1) and $editurl != '' and $xmlbase != ''">1</xsl:if>
<xsl:if test="($draft.mode = 'yes' or $show.edit.link = 1) and $url-candidate != '' and $xmlbase != ''">1</xsl:if>
</xsl:variable>

<xsl:if test="$valid-for-editurl = 1 or $force.generate.give.feedback = 1">
Expand All @@ -605,7 +581,7 @@
<!-- add here a "global" report bug -->
<xsl:if test="$valid-for-editurl = 1">
<li>
<a id="_feedback-editurl" href="{$editurl}{$xmlbase}" rel="nofollow" target="_blank">
<a id="_feedback-editurl" href="{$url-candidate}{$xmlbase}" rel="nofollow" target="_blank">
<xsl:call-template name="gentext">
<xsl:with-param name="key" select="'editsource'"/>
</xsl:call-template>
Expand All @@ -620,11 +596,13 @@

<xsl:template name="generate.sourcelink">
<xsl:param name="node" select="."/>
<xsl:variable name="meta-bugtracker" select="$node/ancestor-or-self::*/d:info/d:meta[@name='bugtracker']/d:phrase[@role='editurl']"/>
<xsl:variable name="editurl" select="$node/ancestor-or-self::*/d:info/dm:docmanager/dm:editurl[1]"/>
<xsl:variable name="xmlbase" select="$node/ancestor-or-self::*[@xml:base][1]/@xml:base"/>
<xsl:variable name="url-candidate" select="($meta-bugtracker | $editurl)[last()]"/>

<xsl:if test="($draft.mode = 'yes' or $show.edit.link = 1) and $editurl != '' and $xmlbase != ''">
<xsl:value-of select="concat($editurl, $xmlbase)"/>
<xsl:if test="($draft.mode = 'yes' or $show.edit.link = 1) and $url-candidate != '' and $xmlbase != ''">
<xsl:value-of select="concat($url-candidate, $xmlbase)"/>
</xsl:if>
</xsl:template>

Expand Down Expand Up @@ -818,7 +796,6 @@
<xsl:template name="user.head.content">
<xsl:param name="node" select="."/>


<xsl:if test="$build.for.web = 1">
<script type="text/javascript">
<xsl:text disable-output-escaping="yes">
Expand Down
187 changes: 187 additions & 0 deletions suse2022-ns/xhtml/meta.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://docbook.org/ns/docbook"
xmlns:dm="urn:x-suse:ns:docmanager"
xmlns:exsl="http://exslt.org/common"
xmlns:date="http://exslt.org/dates-and-times"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="exsl date d dm">

<xsl:template match="d:meta[@name='productname']" mode="meta">
<xsl:variable name="productname" select="normalize-space(string(d:productname[1]))"/>
<xsl:value-of select="$productname"/>
</xsl:template>


<xsl:template match="d:meta[@name='productname']/d:productname[1]/@version" mode="meta">
<xsl:value-of select="."/>
</xsl:template>

<xsl:template match="d:meta[@name='maintainer']" mode="meta">
<xsl:variable name="content" select="normalize-space(@content)"/>

<xsl:choose>
<xsl:when test="$content">
<xsl:if test="$include.html.dublincore">
<meta name="DC.creator" content="{$content}" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="log.message">
<xsl:with-param name="level">warn</xsl:with-param>
<xsl:with-param name="context-desc">metadata</xsl:with-param>
<xsl:with-param name="message">
<xsl:value-of select="concat('In meta[@name=&quot;', @name, '&quot;]')"/>
<xsl:text> the @content attribute is empty!</xsl:text>
</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>


<xsl:template match="d:meta[@name='updated']" mode="meta">
<xsl:variable name="content" select="normalize-space(@content)"/>

<xsl:choose>
<xsl:when test="$content">
<xsl:if test="$include.html.dublincore">
<meta name="DCTERMS.modified" content="{$content}" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="log.message">
<xsl:with-param name="level">warn</xsl:with-param>
<xsl:with-param name="context-desc">metadata</xsl:with-param>
<xsl:with-param name="message">
<xsl:text>In meta[@name='updated'], the @content attribute is empty!</xsl:text>
</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="d:meta[@name='category']" mode="meta">
<xsl:variable name="content" select="normalize-space(@content)"/>

<xsl:choose>
<xsl:when test="$content">
<meta name="category" content="{$content}"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="log.message">
<xsl:with-param name="level">warn</xsl:with-param>
<xsl:with-param name="context-desc">metadata</xsl:with-param>
<xsl:with-param name="message">
<xsl:text>In meta[@name='category'], the @content attribute is empty!</xsl:text>
</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>


<xsl:template name="social-media-opengraph">
<xsl:param name="node" select="."/>
<xsl:param name="socialmedia.title"/>
<xsl:param name="socialmedia.description"/>
<xsl:param name="socialmedia.preview"/>
<xsl:param name="canonical-url-base"/>
<xsl:variable name="ischunk">
<xsl:call-template name="chunk"/>
</xsl:variable>
<xsl:variable name="filename">
<xsl:choose>
<xsl:when test="$ischunk = 1">
<xsl:apply-templates mode="chunk-filename" select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat($root.filename,$html.ext)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="canonical.url" select="concat($canonical-url-base,'/',$filename)"/>
<xsl:variable name="meta.nodes" select="$node/d:info/d:meta|$node/ancestor::*/d:info/d:meta"/>

<xsl:if test="$canonical-url-base != ''">
<!-- These Open Graph and Twitter Cards properties need a canonical URL -->
<link rel="canonical" href="{$canonical.url}"/>
<xsl:text>&#10;</xsl:text>
<!-- These Open Graph and Twitter Cards properties need a canonical URL -->
<meta property="og:url" content="{$canonical.url}"/>
<xsl:text>&#10;</xsl:text>
<meta property="og:image" content="{concat($canonical-url-base,'/',$socialmedia.preview)}"/>
<xsl:text>&#10;</xsl:text>
<xsl:call-template name="meta-generator"/>
</xsl:if>

<xsl:choose>
<xsl:when test="$meta.nodes[@name='title']">
<!-- <xsl:message>#############: <xsl:value-of select="normalize-space($meta.nodes[@name='title'][last()])"/></xsl:message>-->
<meta property="og:title" content="{normalize-space($meta.nodes[@name='title'][last()])}"/>
</xsl:when>
<xsl:otherwise>
<meta property="og:title" content="{$socialmedia.title}"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text>&#10;</xsl:text>

<xsl:choose>
<xsl:when test="$meta.nodes[@name='social-descr']">
<meta property="og:description" content="{normalize-space($meta.nodes[@name='social-descr'][last()])}" />
</xsl:when>
<xsl:otherwise>
<meta property="og:description" content="{$socialmedia.description}"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text>&#10;</xsl:text>

<meta property="og:type" content="{$opengraph.type}"/>
<xsl:text>&#10;</xsl:text>
</xsl:template>


<xsl:template name="social-media-twitter">
<xsl:param name="node" select="."/>
<xsl:param name="socialmedia.title"/>
<xsl:param name="socialmedia.description"/>
<xsl:param name="socialmedia.preview"/>
<xsl:param name="canonical-url-base"/>
<xsl:variable name="meta.nodes" select="$node/d:info/d:meta|$node/ancestor::*/d:info/d:meta"/>

<meta name="twitter:card" content="{$twittercards.type}"/>
<xsl:text>&#10;</xsl:text>

<xsl:if test="$canonical-url-base != ''">
<meta name="twitter:image" content="{concat($canonical-url-base,'/',$socialmedia.preview)}"/>
<xsl:text>&#10;</xsl:text>
</xsl:if>

<xsl:choose>
<xsl:when test="$meta.nodes[@name='title']">
<meta property="twitter:title" content="{normalize-space($meta.nodes[@name='title'][last()])}" />
</xsl:when>
<xsl:otherwise>
<meta name="twitter:title" content="{$socialmedia.title}"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text>&#10;</xsl:text>

<xsl:choose>
<xsl:when test="$meta.nodes[@name='social-descr']">
<meta name="twitter:description" content="{normalize-space($meta.nodes[@name='social-descr'][last()])}" />
</xsl:when>
<xsl:otherwise>
<meta name="twitter:description" content="{$socialmedia.description}"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text>&#10;</xsl:text>

<xsl:if test="string-length($twittercards.twitter.account) &gt; 0">
<meta name="twitter:site" content="{$twittercards.twitter.account}"/>
<xsl:text>&#10;</xsl:text>
</xsl:if>
</xsl:template>

</xsl:stylesheet>
3 changes: 3 additions & 0 deletions suse2022-ns/xhtml/param.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,9 @@ task before
<xsl:param name="title.icons" select="1"/>


<!-- Include HTML Dublin Core metadata? -->
<xsl:param name="include.html.dublincore" select="1"/>

<!-- Include header/footer via Server-Side Includes (SSI)? 0=no, 1=yes
-->
<xsl:param name="include.suse.header" select="0"/>
Expand Down
8 changes: 8 additions & 0 deletions suse2022-ns/xhtml/titlepage.templates.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@
In general, we want the long/official version, though. Dito for the
productnumber below. -->
<xsl:param name="prefer-abbreviation" select="0"/>
<xsl:variable name="meta.nodes" select="d:info/d:meta|ancestor::*/d:info/d:meta"/>

<!--
First we search for all productname[@role='abbrev'], starting in the nearest node followed
by its ancestors.
-->
<xsl:choose>
<xsl:when test="$meta.nodes[@name='bugtracker']/d:phrase[@name='productname'] and $prefer-abbreviation = 0">/
<xsl:apply-templates select="$meta.nodes[@name='bugtracker']/d:phrase[@name='productname'][last()]" mode="meta"/>
</xsl:when>
<xsl:when test="*/d:productname[@role='abbrev'] and $prefer-abbreviation = 1">
<xsl:apply-templates select="(*/d:productname[@role='abbrev'])[last()]"/>
</xsl:when>
Expand All @@ -53,10 +57,14 @@
<xsl:template name="product.number">
<!-- See comment in product.name... -->
<xsl:param name="prefer-abbreviation" select="0"/>
<xsl:variable name="meta.nodes" select="d:info/d:meta|ancestor::*/d:info/d:meta"/>

<!-- FIXME: This choose mechanism is a little wonky around inheritance and
abbreviation preference. May need a bit more think. -->
<xsl:choose>
<xsl:when test="$meta.nodes[@name='bugtracker']/d:phrase[@name='productnumber'] and $prefer-abbreviation = 0">
<xsl:apply-templates select="$meta.nodes[@name='bugtracker']/d:phrase[@name='productnumber'][last()]" mode="meta"/>
</xsl:when>
<xsl:when test="*/d:productnumber[@role='abbrev'] and $prefer-abbreviation = 1">
<xsl:apply-templates select="(*/d:productnumber[@role='abbrev'])[last()]"/>
</xsl:when>
Expand Down

0 comments on commit d7a1639

Please sign in to comment.