Index: /main/trunk/greenstone3/web/interfaces/default/interfaceConfig.xml
===================================================================
--- /main/trunk/greenstone3/web/interfaces/default/interfaceConfig.xml	(revision 37089)
+++ /main/trunk/greenstone3/web/interfaces/default/interfaceConfig.xml	(revision 37090)
@@ -23,4 +23,5 @@
 		<action class="DocumentAction" name="d" xslt="pages/document.xsl">
 		  <subaction name="print" xslt="pages/document-print.xsl"/>
+		  <subaction name="iiif-manifest" xslt="pages/document-iiif-manifest.xsl"/>
 		</action>
 
Index: /main/trunk/greenstone3/web/interfaces/default/transform/pages/document-iiif-manifest.xsl
===================================================================
--- /main/trunk/greenstone3/web/interfaces/default/transform/pages/document-iiif-manifest.xsl	(revision 37090)
+++ /main/trunk/greenstone3/web/interfaces/default/transform/pages/document-iiif-manifest.xsl	(revision 37090)
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+	xmlns:java="http://xml.apache.org/xslt/java"
+	xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+	xmlns:gslib="http://www.greenstone.org/skinning"
+	xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat"
+	extension-element-prefixes="java util"
+	exclude-result-prefixes="java util gsf">
+
+  <!--
+      Key goal: generate a IIIF v2 compliant manifest file in JSON format based on the document
+  -->
+  
+  <!-- Similar in spirit to document.xsl (catering for 'simple' and complex document structures such as 'pages'),
+       but considerably tailored down to produce the raw IIIF-manifest JSON format:
+         (i)  focus on just the (potientailly hierachically nested) pages
+         (ii) so a bit like ed=1, but implied rather than needing to be set
+  -->
+
+  <!-- **** this only defines xsl-variables => change filename? -->
+  <xsl:include href="layouts/header-core.xsl"/>
+
+  <xsl:include href="pages/document-shared.xsl" />
+  <!-- **** this only defines xsl-variables => change filename? -->  
+  <xsl:include href="pages/document-core.xsl" />
+
+  
+  <xsl:output method="html" version="1.0" encoding="utf-8"/>
+  
+  <!--
+  <xsl:output method="text" version="1.0" encoding="utf-8" omit-xml-declaration="yes"/>
+  <xsl:strip-space elements="*"/>
+  -->
+
+  
+  <xsl:variable name="iiifPresentationRootIdentifier">http-greenstone://<xsl:value-of select="$site_name"/>/<xsl:value-of select="$collNameChecked"/>/<xsl:value-of select="$docID"/></xsl:variable>
+
+  <xsl:template match="/">
+      <html>
+	<body>
+	  <pre>
+	  <xsl:apply-templates select="/page/pageResponse/document" />
+	</pre>
+      </body>
+    </html>
+    
+  </xsl:template>
+
+  <xsl:template match="/page/pageResponse/document">
+    <!-- display the document -->
+    <xsl:choose>
+      <xsl:when test="@docType='simple'">
+	<xsl:call-template name="documentContent"/>
+      </xsl:when>	
+      <xsl:otherwise> <!-- kick off the recursive call for a more complex structured document-->
+	<xsl:call-template name="wrappedDocumentTopLevel"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  
+  <xsl:template name="wrappedDocumentTopLevel">
+
+    <!-- <xsl:call-template name="documentPre"/> -->
+    <xsl:call-template name="wrappedDocument"/> <!-- without ed=1, this template misses the binds in of documentPre and documentPost -->
+    <!-- <xsl:call-template name="documentPost"/> -->
+
+  </xsl:template>
+
+
+  <xsl:template name="wrappedDocument">
+
+    <xsl:call-template name="documentPre"/>
+      <xsl:for-each select="documentNode">
+	<xsl:call-template name="wrapDocumentNodes"/>
+      </xsl:for-each>
+    <xsl:call-template name="documentPost"/>					
+    
+  </xsl:template>	
+  
+  
+  <xsl:template name="iiif-other-content">
+    <xsl:param name="optSection"/>
+    
+    <xsl:variable name="baseURL">https:<xsl:value-of select="/page/pageRequest/@baseURL"/></xsl:variable> <!-- **** had to hardwire https: -->    
+    <!-- **** test for a gsf-option before include !!!! -->    
+  	      "otherContent": [{
+		    "@id": "<xsl:value-of select="$baseURL"/><xsl:value-of select="$library_name"/>/sites/<xsl:value-of select="$site_name"/>/collect/<xsl:value-of select="$collNameChecked"/>/index/assoc/<gsf:metadata name="assocfilepath" select="root"/>/openannotation-list<xsl:value-of select="$optSection"/>.json",
+                    "@type": "sc:AnnotationList"
+              }],
+  </xsl:template>
+  
+
+  <xsl:template name="iiif-canvas-image">
+    <xsl:param name="identifier"/>
+    <xsl:param name="docType"/>
+    
+    <xsl:variable name="iiifImageRootIdentifier">
+      <xsl:text>/gs-cantaloupe/iiif/2/</xsl:text><xsl:value-of select="$site_name"/>:<xsl:value-of select="$collNameChecked"/>:<xsl:value-of select="$identifier"/>
+    </xsl:variable>
+    
+    <!-- page/pageRequest[@baseURL]="//intermuse.sowemustthink.space/greenstone3/ -->
+    <!-- page/pageRequest[@fullURL]="//intermuse.sowemustthink.space/greenstone3/library?a=d.... -->
+
+    <!-- ***** need to work out domain name to use from raw XML message, say processing something from the above -->
+    
+    <xsl:variable name="document-location-origin">https://intermuse.sowemustthink.space</xsl:variable>
+
+    <xsl:variable name="section"><xsl:value-of select="position()" /></xsl:variable>
+    <xsl:variable name="optSection">
+      <xsl:choose>
+	<xsl:when test="$docType = 'simple'"></xsl:when><!-- i.e. empty -->
+	<xsl:otherwise><xsl:value-of select="position()" /></xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+
+    <xsl:variable name="chosenTitle">
+      <xsl:choose>
+	<xsl:when test="$docType = 'simple'">
+	  <xsl:call-template name="choose-title"/>
+	</xsl:when>
+	<xsl:otherwise>page <xsl:value-of select="$section"/></xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+    <!-- The following is useful for debugging, nested in 'pre' tags -->
+    <!--
+      docType   = <xsl:value-of select="$docType"/>
+      docID     = <xsl:value-of select="$docID"/>
+      position  = <xsl:value-of select="position()" />
+
+      identifer = <xsl:value-of select="$identifier"/>
+      section    = <xsl:value-of select="$section"/>
+      optSection = <xsl:value-of select="$optSection"/>
+
+      iiifPresRootIdentifier  = <xsl:value-of select="$iiifPresentationRootIdentifier" />
+      iiifImageRootIdentifier = <xsl:value-of select="$iiifImageRootIdentifier" />
+    -->
+    <!-- an array entry in 'canvases': { @content, @id, @type, label, width, height, images[{}], thumbnail {@id,@type} } -->
+      <!-- add a comma first, if it is not the first canvas element in the array -->
+      <xsl:if test="$section &gt; 1">
+	  ,
+      </xsl:if>
+	    {
+	      "@context": "http://iiif.io/api/presentation/2/context.json",
+	      "@id":      "<xsl:value-of select="$iiifPresentationRootIdentifier" />/canvas/<xsl:value-of select="$section"/>",
+	      "@type":    "sc:Canvas",
+	      "label":    "<xsl:value-of select="$chosenTitle"/>",
+	      <xsl:call-template name="iiif-other-content">
+		<xsl:with-param name="optSection"><xsl:value-of select="$optSection"/></xsl:with-param>
+	      </xsl:call-template>	    
+              &quot;width&quot;:  <gsf:metadata name="ImageWidth"/>,
+              &quot;height&quot;: <gsf:metadata name="ImageHeight"/>,
+	      
+	      "images": [{
+                "image": {
+	          "@context":   "http://iiif.io/api/image/2/context.json",
+	          "@type":      "oa:Annotation",
+		  "motivation": "sc:painting",
+		  "on":         "<xsl:value-of select="$iiifPresentationRootIdentifier" />/annotation/<xsl:value-of select="$section"/>",
+
+		  "resource": {
+		    "@id":     "<xsl:value-of select="$document-location-origin" /><xsl:value-of select="$iiifImageRootIdentifier" />/full/full/0/default.jpg",
+		    "@type":   "dctypes:Image",
+		    "format":  "image/jpeg",
+		    "width":   <gsf:metadata name="ImageWidth"/>,
+		    "hieght":  <gsf:metadata name="ImageHeight"/>,
+		    "service": {
+		      "@context": "http://iiif.io/api/image/2/context.json",
+		      "@id":      "<xsl:value-of select="$document-location-origin" /><xsl:value-of select="$iiifImageRootIdentifier" />",
+		      "profile":  "https://iiif.io/api/image/2/profiles/level2.json"
+		    }
+		  }
+		}
+	      }],
+	      "thumbnail": {
+	        "@id":   "<xsl:value-of select="$document-location-origin" /><xsl:value-of select="$iiifImageRootIdentifier" />/full/,150/0/default.jpg",
+		"@type": "dctypes:Image"
+	      }
+            }      
+    <!-- Another field to consider in the above JSON is: -->
+    <!--   "format": mime_type, // ???? or is it OK to always have this as image/jpeg and rely on IIIF Image Server coverting as/when needed??? -->
+  </xsl:template>
+
+
+  <xsl:template name="wrappedSectionPost">
+
+    <!-- add in IIIF Server link for section image -->
+    <xsl:variable name="nodeID" select="@nodeID"/>
+    <xsl:call-template name="iiif-canvas-image">
+      <xsl:with-param name="identifier" select="$nodeID" />
+      <xsl:with-param name="docType" select="@docType" />
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template name="sectionImage">
+    <!-- don't need this template to generate anything in the IIIF-Manifest JSON case -->
+  </xsl:template>
+
+  <xsl:template name="sectionContent">
+    <xsl:call-template name="wrappedSectionPost"/>
+  </xsl:template>
+
+  
+  <xsl:template name="documentPre">
+    <xsl:variable name="httpCollection">library/sites/<xsl:value-of select="$site_name"/>/collect/<xsl:value-of select="/page/pageResponse/collection/@name"/></xsl:variable>
+
+    <xsl:variable name="chosenTitle">
+      <xsl:choose>
+	<xsl:when test="@docType='simple'">
+	  <xsl:call-template name="choose-title"/>
+	</xsl:when>
+	<xsl:otherwise>
+	  <xsl:value-of disable-output-escaping="yes" select="/page/pageResponse/document/documentNode/metadataList/metadata[@name='Title']" />
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+    <!-- start of iiif_manifest: -->
+    {
+        "@context": "http://iiif.io/api/presentation/2/context.json",
+	"@type": "sc:Manifest",
+	"@id": "<xsl:value-of select="$iiifPresentationRootIdentifier"/>/manifest",
+	"label": "<xsl:value-of select="$chosenTitle"/>",
+	"attribution": "The Internet of Musical Events (InterMusE): Digital Scholarship, Community, and the Archiving of Performance",
+	"license": "https://**** To Be Determined ****",
+	"logo": "https://intermuse.datatodata.org/wp-content/uploads/sites/4/2021/03/cropped-cropped-cropped-1.png",
+        "metadata": [
+	  { "label": "creator", "value": ["aaa1","aaa2"] },
+	  { "label": "title", "value": ["chosen-title"] }
+	],
+	<!-- trival IIIF sequences => has one IIIF canvas in it -->
+	"sequences": [{
+	  "@context": "http://iiif.io/api/image/2/context.json",
+          "@id": "<xsl:value-of select="$iiifPresentationRootIdentifier"/>/sequence/normal",
+          "@type": "sc:Sequence",
+	  "canvases": [
+
+  </xsl:template>
+     
+  
+  <xsl:template name="documentContentSimpleIIIFImage">
+    <xsl:call-template name="iiif-canvas-image">
+      <xsl:with-param name="identifier" select="$docID" />
+      <xsl:with-param name="docType" select="@docType" />
+    </xsl:call-template>
+  </xsl:template>
+  
+  <xsl:template name="documentContent">
+    <!-- The way document.xsl templates are structured, only get to here is if @docType = 'simple' -->
+    <!-- A 'paged' (or 'hierarical') document goes throgh 'wrappedContent' -->
+    <xsl:call-template name="documentPre"/>
+    <xsl:call-template name="documentContentSimpleIIIFImage"/>
+    <xsl:call-template name="documentPost"/>
+  </xsl:template>
+
+  
+  <xsl:template name="wrapDocumentNodes">
+
+    <xsl:call-template name="sectionContent"/>
+    
+    <xsl:if test="documentNode">
+      <xsl:for-each select="documentNode">
+	<xsl:call-template name="wrapDocumentNodes"/>
+      </xsl:for-each>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template name="wrappedSectionImage">
+    <!-- don't need this template to generate anything in the IIIF-Manifest JSON case -->
+  </xsl:template>
+
+  
+  
+  <xsl:template name="documentPost">
+    <!-- end of iiif_manifest: -->
+    <!-- close of canvases, then close higher level blocks to complete the JSON file -->
+	  ]
+	}]	  
+    }    	
+    
+  </xsl:template>
+
+
+</xsl:stylesheet>
