Forráskód Böngészése

Merge branch 'templates' of gogsadmin/prayer-generator into master

gogsadmin 8 hónapja
szülő
commit
540660c091
6 módosított fájl, 203 hozzáadás és 265 törlés
  1. 0 0
      requirements.txt
  2. 2 2
      rest/Dockerfile
  3. 34 98
      rest/pyapi.py
  4. 136 0
      rest/query-to-xml-xslt.xml
  5. 31 0
      rest/query-to-xml.tpl
  6. 0 165
      xml/pg_view_style.xsl

+ 0 - 0
rest/requirements.txt → requirements.txt


+ 2 - 2
rest/Dockerfile

@@ -2,5 +2,5 @@ FROM python:3-slim
 WORKDIR /usr/src/app
 COPY  requirements.txt ./
 RUN pip install --no-cache-dir -r requirements.txt
-COPY pyapi.py .
-CMD [ "python", "./pyapi.py" ]
+COPY rest rest
+CMD [ "python", "rest/pyapi.py" ]

+ 34 - 98
rest/pyapi.py

@@ -1,8 +1,9 @@
-# Copyright (c) Daniel Sheffield 2022
+# Copyright (c) Daniel Sheffield 2022 - 2024
 # All rights reserved.
-from bottle import route, request, run, template, response, abort
+from bottle import route, request, run, template, response, abort, static_file
 import psycopg
-from psycopg import Cursor, sql
+from psycopg import Cursor
+from psycopg.sql import SQL, Literal
 import os
 host = f"host={os.getenv('HOST')}"
 db = f"dbname={os.getenv('DB', 'pgdb')}"
@@ -11,104 +12,29 @@ password = f"password={os.getenv('PASSWORD','')}"
 if not password.split('=',1)[1]:
     password = ''
 conn: Cursor = psycopg.connect(f"{host} {db} {user} {password}")
-random_statement = """SELECT
-  query_to_xml('SELECT category, translation, reference, txt
-    FROM pg_random_view_default_if_null
-    JOIN pg_categories ON category = name
-    ORDER BY tableid ASC',
-  false, false, ''::text);"""
-specified_statement = sql.SQL("""SELECT query_to_xml($$SELECT category, translation, reference, txt
-  FROM getprayer(
-    {categories}::text[],
-    {translations}::text[],
-    {references}::text[]
-  ) ORDER BY ordinal ASC$$, false, false, ''::text);""")
-heading = """<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="https://shandan.one/xml/pg_view_style.xsl"?>
-"""
-random_schema = """
-<xsd:schema
-    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-
-<xsd:simpleType name="UDT.pgdb.pg_catalog.text">
-  <xsd:restriction base="xsd:string">
-  </xsd:restriction>
-</xsd:simpleType>
-
-<xsd:simpleType name="VARCHAR">
-  <xsd:restriction base="xsd:string">
-  </xsd:restriction>
-</xsd:simpleType>
-
-<xsd:complexType name="RowType.pgdb.public.pg_random_view_default_if_null">
-  <xsd:sequence>
-    <xsd:element name="category" type="UDT.pgdb.pg_catalog.text" minOccurs="0"></xsd:element>
-    <xsd:element name="translation" type="VARCHAR" minOccurs="0"></xsd:element>
-    <xsd:element name="reference" type="UDT.pgdb.pg_catalog.text" minOccurs="0"></xsd:element>
-    <xsd:element name="txt" type="VARCHAR" minOccurs="0"></xsd:element>
-  </xsd:sequence>
-</xsd:complexType>
-
-<xsd:complexType name="TableType.pgdb.public.pg_random_view_default_if_null">
-  <xsd:sequence>
-    <xsd:element name="row" type="RowType.pgdb.public.pg_random_view_default_if_null" minOccurs="0" maxOccurs="unbounded"/>
-  </xsd:sequence>
-</xsd:complexType>
-
-<xsd:element name="table" type="TableType.pgdb.public.pg_random_view_default_if_null"/>
-
-</xsd:schema>
-"""
-specified_heading = heading + """
-<xsd:element name="table" type="TableType.pgdb.public.pg_view"/>
-
-</xsd:schema>
-"""
-specified_schema = """
-<xsd:schema
-    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-
-<xsd:simpleType name="UDT.pgdb.pg_catalog.text">
-  <xsd:restriction base="xsd:string">
-  </xsd:restriction>
-</xsd:simpleType>
-
-<xsd:simpleType name="VARCHAR">
-  <xsd:restriction base="xsd:string">
-  </xsd:restriction>
-</xsd:simpleType>
-
-<xsd:complexType name="RowType.pgdb.public.pg_view">
-  <xsd:sequence>
-    <xsd:element name="category" type="UDT.pgdb.pg_catalog.text" minOccurs="0"></xsd:element>
-    <xsd:element name="translation" type="VARCHAR" minOccurs="0"></xsd:element>
-    <xsd:element name="reference" type="UDT.pgdb.pg_catalog.text" minOccurs="0"></xsd:element>
-    <xsd:element name="txt" type="VARCHAR" minOccurs="0"></xsd:element>
-  </xsd:sequence>
-</xsd:complexType>
-
-<xsd:complexType name="TableType.pgdb.public.pg_view">
-  <xsd:sequence>
-    <xsd:element name="row" type="RowType.pgdb.public.pg_view" minOccurs="0" maxOccurs="unbounded"/>
-  </xsd:sequence>
-</xsd:complexType>
-
-<xsd:element name="table" type="TableType.pgdb.public.pg_view"/>
-
-</xsd:schema>
-"""
-
 
 @route('/pyapi/random')
 def random():
     try:
         with conn.cursor() as cur:
-            xml = cur.execute(random_statement).fetchone()[0].splitlines()
+            inner = SQL("""
+SELECT category, translation, reference, txt
+FROM pg_random_view_default_if_null
+JOIN pg_categories ON category = name
+ORDER BY tableid ASC
+""")
+            xml = cur.execute(SQL("""
+SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text);
+""").format(q=inner.as_string(cur))).fetchone()[0]
     finally:
         conn.commit()
     response.content_type = 'application/xhtml+xml; charset=utf-8'
-    return f"{heading}{xml[0]}{random_schema}" + '\n'.join(xml[1:])
+    return template("rest/query-to-xml", title="Random Prayer Generator", xml=xml)
 
+@route('/pyapi/xslt')
+def table():
+    response.content_type = 'application/xhtml+xml; charset=utf-8'
+    return static_file("query-to-xml-xslt.xml", root="rest")
 
 @route('/pyapi/pg')
 def specified():
@@ -144,14 +70,24 @@ def specified():
 
     try:
         with conn.cursor() as cur:
-            xml = cur.execute(specified_statement.format(
-                categories=sql.Literal(categories),
-                translations=sql.Literal(translations),
-                references=sql.Literal(references)
-            )).fetchone()[0].splitlines()
+            inner = SQL("""
+SELECT category, translation, reference, txt
+    FROM getprayer(
+        {categories}::text[],
+        {translations}::text[],
+        {references}::text[]
+    ) ORDER BY ordinal ASC
+""").format(
+    categories=Literal(categories),
+    translations=Literal(translations),
+    references=Literal(references)
+)
+            xml = cur.execute(SQL("""
+SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text);
+""").format(q=Literal(inner.as_string(cur)))).fetchone()[0]
     finally:
         conn.commit()
     response.content_type = 'application/xhtml+xml; charset=utf-8'
-    return f"{heading}{xml[0]}{specified_schema}" + '\n'.join(xml[1:])
+    return template("rest/query-to-xml", title="Prayer Generator", xml=xml)
 
 run(host='0.0.0.0', port=11888)

+ 136 - 0
rest/query-to-xml-xslt.xml

@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) Daniel Sheffield 2022
+All rights reserved.
+-->
+<xsl:stylesheet version="1.1"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  xmlns:xhtml="http://www.w3.org/1999/xhtml"
+>
+
+  <xsl:output method="xml"
+      doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+      doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"
+      indent="yes"/>
+
+  <!-- This is an identity template - it copies everything
+        that doesn't match another template -->
+  <xsl:template match="@* | node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@* | node()"/>
+    </xsl:copy>
+  </xsl:template>
+  <xsl:template match="processing-instruction()">
+  </xsl:template>
+
+  <xsl:template match="//xhtml:div[@id='xmldata']/*">
+
+    <xsl:variable name="schema" select="//xsd:schema"/>
+    <xsl:variable name="tabletypename"
+                  select="$schema/xsd:element[@name=name(current())]/@type"/>
+    <xsl:variable name="rowtypename"
+                  select="$schema/xsd:complexType[@name=$tabletypename]/xsd:sequence/xsd:element[@name='row']/@type"/>
+    
+    <div xmlns="http://www.w3.org/1999/xhtml"
+         style="background: darkgray; position: sticky; top: 0; margin: 0; padding: 0; width: 100%; z-index: 1; text-align: center;">
+      <form action="random">
+        <button type="submit" style="margin: 0.2em">Generate</button>
+        <span style="position: absolute; right: 0; padding: 0.4em">
+          <a>
+            <xsl:attribute name="href">./pg?<xsl:for-each select="xhtml:row">
+            <xsl:value-of select="xhtml:category"/>=<xsl:value-of select="translate(xhtml:reference,' ','')"/>+<xsl:value-of select="xhtml:translation"/>
+            <xsl:if test="position() != last()">&#038;</xsl:if>
+            </xsl:for-each>
+            </xsl:attribute>
+            Permalink
+          </a>
+        </span>
+	    </form>
+    </div>
+    <table xmlns="http://www.w3.org/1999/xhtml"
+           class="pure-table pure-table-bordered pure-table-striped">
+      <thead>
+        <tr style="text-transform: capitalize">
+        <xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename]/xsd:sequence/xsd:element/@name">
+            <xsl:variable name="elementtype"
+                          select="."/>
+            <xsl:choose>
+            <xsl:when test="$elementtype = 'txt'">
+              <th class="opt-all">Text</th>
+            </xsl:when>
+            <xsl:when test="$elementtype = 'category'">
+              <th class="opt-all">Section</th>
+            </xsl:when>
+            <xsl:when test="$elementtype = 'translation'">
+              <th class="opt-md opt-lg opt-xl opt-xxl">Reference</th>
+            </xsl:when>
+            <xsl:otherwise>
+            </xsl:otherwise>
+            </xsl:choose>
+        </xsl:for-each>
+        </tr>
+      </thead>
+      <tbody>
+        <xsl:for-each select="xhtml:row">
+          <tr>
+            <xsl:for-each select="*">
+              <xsl:variable name="elementtype"
+                            select="name(current())"/>
+              <xsl:choose>
+              <xsl:when test="$elementtype = 'txt'">
+                <td class="opt-all" style="text-align: justify"><xsl:value-of select="."/>&#160;<span class="engraved">
+                  <xsl:value-of select="../xhtml:translation"/>
+                  </span>
+                </td>
+              </xsl:when>
+              <xsl:when test="$elementtype = 'category'">
+                <xsl:choose>
+                  <xsl:when test="contains(.,'z_')">
+                    <td class="opt-all" rowspan="2" style="text-transform: capitalize;">Kingdom</td>
+                  </xsl:when>
+                  <xsl:when test="contains(.,'a_')"></xsl:when>
+                  <xsl:otherwise>
+                    <td class="opt-all" style="text-transform: capitalize;"><xsl:value-of select="."/></td>
+                  </xsl:otherwise>
+                </xsl:choose>
+              </xsl:when>
+              <xsl:when test="$elementtype = 'translation'">
+              </xsl:when>
+              <xsl:otherwise>
+                <td class="opt-md opt-lg opt-xl opt-xxl">
+                <xsl:value-of select="translate(translate(.,' ','&#160;'),'-','&#8209;')"/>
+                <br/>
+                <a>
+                  <xsl:attribute name="href">/license/<xsl:value-of select="preceding-sibling::xhtml:translation"/>.txt</xsl:attribute>
+                  <xsl:value-of select="preceding-sibling::xhtml:translation"/>
+                </a>
+                </td>
+              </xsl:otherwise>
+              </xsl:choose>
+            </xsl:for-each>
+          </tr>
+        </xsl:for-each>
+      </tbody>
+
+      <tfoot style="line-height: 1.4">
+        <tr>
+          <td colspan="3">
+            Copyright (c) Daniel Sheffield 2022. All right reserved.
+            <br/>
+            Powered by <a href="https://www.crosswire.org/jsword/">JSword</a> an implementation of <a href="https://www.crosswire.org/sword/index.jsp">The SWORD Project</a>'s SWORD API brought to you by the <a href="https://crosswire.org">The CrossWire Bible Society</a>.
+            <br/>
+            Quotes are taken from various translations as indicated. See
+            <xsl:for-each select="xhtml:row/xhtml:translation[not(.=preceding::*)]">
+            <a>
+            <xsl:attribute name="href">/license/<xsl:value-of select="."/>.txt</xsl:attribute>
+            <xsl:value-of select="."/>
+            </a>,
+            </xsl:for-each>
+            for the license and copyright information of each respective work.
+          </td>
+        </tr>
+      </tfoot>
+    </table>
+  </xsl:template>
+</xsl:stylesheet>

+ 31 - 0
rest/query-to-xml.tpl

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) Daniel Sheffield 2022
+All rights reserved.
+-->
+<?xml-stylesheet type="text/xsl" href="/pyapi/xslt"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+  <title>{{title}}</title>
+	<meta name="description" content="Generate a template prayer following the form of the model prayer outlined in Matthew 6:9‑13 and Luke 11:2‑4"/>
+	<meta name="keywords" content="Bible, Prayer, Generator, SWORD"/>
+	<meta name="author" content="Daniel Sheffield"/>
+	<meta name="viewport" content="width=device-width, initial-scale=1"/>
+	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/purecss@2.1.0/build/pure-min.css" integrity="sha384-yHIFVG6ClnONEA5yB5DJXfW2/KC173DIQrYoZMEtBvGzmf0PKiGyNEqe9N6BNDBH" crossorigin="anonymous"/>
+	<link rel="stylesheet" href="https://shandan.one/css/grids-responsive-min.css"/>
+	<link rel="stylesheet" href="https://shandan.one/css/responsive-visibility-collapse.css"/>
+    <style>
+span.engraved {
+    color: #A8A8A8;
+    font-size: 0.8em;
+    text-shadow: 0px 0.1em 0px rgba(168,168,168,.1), 0px -0.1em 0px rgba(0,0,0,.7);
+    float: right;
+}
+  </style>
+  </head>
+  <body>
+    <div id="xmldata" style="position: relative; max-width: 68em; min-width: min(100%, 68em); left: 50%; transform: translate(max(-50%, -34em),0)">
+{{!xml}}
+    </div>
+  </body>
+</html>

+ 0 - 165
xml/pg_view_style.xsl

@@ -1,165 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (c) Daniel Sheffield 2022
-All rights reserved.
--->
-<xsl:stylesheet version="1.0"
-    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-    xmlns="http://www.w3.org/1999/xhtml"
->
-
-  <xsl:output method="xml"
-      doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
-      doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"
-      indent="yes"/>
-
-  <xsl:template match="/*">
-    <xsl:variable name="schema" select="//xsd:schema"/>
-    <xsl:variable name="tabletypename"
-                  select="$schema/xsd:element[@name=name(current())]/@type"/>
-    <xsl:variable name="rowtypename"
-                  select="$schema/xsd:complexType[@name=$tabletypename]/xsd:sequence/xsd:element[@name='row']/@type"/>
-
-    <html>
-      <head>
-        <title>
-        <xsl:choose>
-          <xsl:when test="$tabletypename = 'TableType.pgdb.public.pg_random_view_default_if_null'">
-          Random Prayer Generator
-          </xsl:when>
-          <xsl:when test="$tabletypename = 'TableType.pgdb.public.pg_view'">
-          Prayer Generator
-          </xsl:when>
-          <xsl:otherwise>
-          <xsl:value-of select="$tabletypename"/>
-          </xsl:otherwise>
-        </xsl:choose>
-        </title>
-        <meta>
-        <xsl:attribute name="name">title</xsl:attribute>
-        <xsl:attribute name="content">
-        <xsl:choose>
-          <xsl:when test="$tabletypename = 'TableType.pgdb.public.pg_random_view_default_if_null'">Random Prayer Generator</xsl:when>
-          <xsl:when test="$tabletypename = 'TableType.pgdb.public.pg_view'">Prayer Generator</xsl:when>
-          <xsl:otherwise>
-          <xsl:value-of select="$tabletypename"/>
-          </xsl:otherwise>
-        </xsl:choose>
-        </xsl:attribute>
-        </meta>
-	<meta name="description" content="Generate a template prayer following the form of the model prayer outlined in Matthew 6:9‑13 and Luke 11:2‑4"/>
-	<meta name="keywords" content="Bible, Prayer, Generator, SWORD"/>
-	<meta name="author" content="Daniel Sheffield"/>
-	<meta name="viewport" content="width=device-width, initial-scale=1"/>
-	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/purecss@2.1.0/build/pure-min.css" integrity="sha384-yHIFVG6ClnONEA5yB5DJXfW2/KC173DIQrYoZMEtBvGzmf0PKiGyNEqe9N6BNDBH" crossorigin="anonymous"/>
-	<link rel="stylesheet" href="https://shandan.one/css/grids-responsive-min.css"/>
-	<link rel="stylesheet" href="https://shandan.one/css/responsive-visibility-collapse.css"/>
-        <style>
-span.engraved {
-    color: #A8A8A8;
-    font-size: 0.8em;
-    text-shadow: 0px 0.1em 0px rgba(168,168,168,.1), 0px -0.1em 0px rgba(0,0,0,.7);
-    float: right;
-}
-	</style>
-      </head>
-      <body>
-        <div style="background: darkgray; position: sticky; top: 0; margin: 0; padding: 0; width: 100%; z-index: 1; text-align: center;">
-        <form action="random">
-          <button type="submit" style="margin: 0.2em">Generate</button>
-          <span style="position: absolute; right: 0; padding: 0.4em">
-          <a>
-          <xsl:attribute name="href">./pg?<xsl:for-each select="//row"><xsl:value-of select="category"/>=<xsl:value-of select="translate(reference,' ','')"/>+<xsl:value-of select="translation"/><xsl:if test="position() != last()">&#038;</xsl:if></xsl:for-each></xsl:attribute>
-          Permalink
-          </a>
-          </span>
-	</form>
-        </div>
-        <div style="position: relative; max-width: 68em; min-width: min(100%, 68em); left: 50%; transform: translate(max(-50%, -34em),0)">
-        <table class="pure-table pure-table-bordered pure-table-striped">
-          <tr style="text-transform: capitalize">
-            <xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename]/xsd:sequence/xsd:element/@name">
-                <xsl:variable name="elementtype"
-                              select="."/>
-                <xsl:choose>
-                <xsl:when test="$elementtype = 'txt'">
-              <th class="opt-all">Text</th>
-                </xsl:when>
-                <xsl:when test="$elementtype = 'category'">
-              <th class="opt-all">Section</th>
-                </xsl:when>
-                <xsl:when test="$elementtype = 'translation'">
-              <th class="opt-md opt-lg opt-xl opt-xxl">Reference</th>
-                </xsl:when>
-                <xsl:otherwise>
-                </xsl:otherwise>
-                </xsl:choose>
-            </xsl:for-each>
-          </tr>
-
-          <xsl:for-each select="row">
-            <tr>
-              <xsl:for-each select="*">
-                <xsl:variable name="elementtype"
-                              select="name(current())"/>
-                <xsl:choose>
-                <xsl:when test="$elementtype = 'txt'">
-                <td class="opt-all" style="text-align: justify"><xsl:value-of select="."/>&#160;<span class="engraved">
-                <xsl:value-of select="../translation"/>
-                </span>
-                </td>
-                </xsl:when>
-                <xsl:when test="$elementtype = 'category'">
-                  <xsl:choose>
-                  <xsl:when test="contains(.,'z_')">
-                  <td class="opt-all" rowspan="2" style="text-transform: capitalize;">Kingdom</td>
-                  </xsl:when>
-                  <xsl:when test="contains(.,'a_')">
-                  </xsl:when>
-		  <xsl:otherwise>
-                  <td class="opt-all" style="text-transform: capitalize;"><xsl:value-of select="."/></td>
-                  </xsl:otherwise>
-                  </xsl:choose>
-                </xsl:when>
-                <xsl:when test="$elementtype = 'translation'">
-                </xsl:when>
-                <xsl:otherwise>
-                  <td class="opt-md opt-lg opt-xl opt-xxl">
-                  <xsl:value-of select="translate(translate(.,' ','&#160;'),'-','&#8209;')"/>
-                  <br/>
-                  <a>
-                  <xsl:attribute name="href">/license/<xsl:value-of select="preceding-sibling::translation"/>.txt</xsl:attribute>
-                  <xsl:value-of select="preceding-sibling::translation"/>
-                  </a>
-                  </td>
-                </xsl:otherwise>
-                </xsl:choose>
-              </xsl:for-each>
-            </tr>
-          </xsl:for-each>
-        <tfoot style="line-height: 1.4">
-        <tr>
-          <td colspan="3">
-          Copyright (c) Daniel Sheffield 2022. All right reserved.
-          <br/>
-          Powered <a href="https://www.crosswire.org/jsword/">JSword</a> an implementation of <a href="https://www.crosswire.org/sword/index.jsp">The SWORD Project</a>'s SWORD API brought to you by the <a href="https://crosswire.org">The CrossWire Bible Society</a>.
-          <br/>
-          Quotes are taken from various translations as indicated. See 
-          <xsl:for-each select="//row/translation[not(.=preceding::*)]">
-          <a>
-          <xsl:attribute name="href">/license/<xsl:value-of select="."/>.txt</xsl:attribute>
-          <xsl:value-of select="."/>
-          </a>,
-          </xsl:for-each>
-          for the license and copyright information of each respective work.
-          </td>
-        </tr>
-        </tfoot>
-        </table>
-        </div>
-      </body>
-    </html>
-  </xsl:template>
-
-</xsl:stylesheet>