From 4852f100a3191fd731ed2bc63d21516461725805 Mon Sep 17 00:00:00 2001 From: Ainsley Ellis <ainsleymae@proton.me> Date: Sat, 31 May 2025 07:16:12 -0400 Subject: [PATCH] Add XSLT for CVs --- assets/css/all.css | 122 ++++++++++++++++++++++++++ assets/css/print.css | 16 ++++ assets/css/screen.css | 8 ++ templates/cv.xsl | 132 +++++++++++++++++++++++++++++ templates/fragments/header.xml | 16 ++++ templates/fragments/objectives.xml | 14 +++ 6 files changed, 308 insertions(+) create mode 100755 assets/css/all.css create mode 100755 assets/css/print.css create mode 100755 assets/css/screen.css create mode 100644 templates/cv.xsl create mode 100644 templates/fragments/header.xml create mode 100644 templates/fragments/objectives.xml diff --git a/assets/css/all.css b/assets/css/all.css new file mode 100755 index 0000000..8bef177 --- /dev/null +++ b/assets/css/all.css @@ -0,0 +1,122 @@ +body { + margin: 0; +} + +h1, +h2, +h3, +h4 { + margin: 0; +} + +h1 { + text-align: center; +} + +h2 { + margin-block-end: 0.25em; + margin-bottom: 0.25em; + border-block-end: 0.0625em solid currentColor; + border-bottom: 0.0625em solid currentColor; + font-variant: small-caps; +} + +.headline { + margin-block-end: 1em; + margin-bottom: 1em; + text-align: center; +} + +address { + margin-block-end: 1em; + margin-bottom: 1em; + display: flex; + justify-content: space-between; + flex-wrap: wrap; + gap: 0.5em; +} + +address>ul { + margin: 0; + padding: 0; + display: inline-block; +} + +address> :last-child { + text-align: end; +} + +p { + margin: 0; +} + +hr { + width: 50%; +} + +main > section+section, +article+article { + margin-block-start: 1em; + margin-top: 1em; +} + +article>article { + margin-block-start: 0.5em; + margin-top: 0.5em; +} + +article header { +display: flex; +justify-content: space-between; +flex-wrap: wrap; +gap: 0.5em; +} + +article header p { + text-align: end; +} + +article > p { + margin-block-start: 0.25em; + margin-top: 0.25em; +} + +dl { + margin: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-inline-start: 2.5em; + margin-left: 2.5em; +} + +#skills h3 { +margin-block-start: 0.25em; +margin-top: 0.25em; +} + +#skills ul { + margin: 0; + padding: 0; + list-style-type: none; +} + +#skills li { + display: inline; +} + +#skills li::after { + content: ","; +} + +#skills li:last-child::after { + content: none; +} + +footer { +text-align: center; +} diff --git a/assets/css/print.css b/assets/css/print.css new file mode 100755 index 0000000..064ba1f --- /dev/null +++ b/assets/css/print.css @@ -0,0 +1,16 @@ +@page { + size: 8.5in 11in; + margin: 0.5in; + padding: 0; +} + +body { margin: 0; } + +article, +footer { + break-inside: avoid-page; +} + +a:visited { + color: blue; +} diff --git a/assets/css/screen.css b/assets/css/screen.css new file mode 100755 index 0000000..6d4905d --- /dev/null +++ b/assets/css/screen.css @@ -0,0 +1,8 @@ +body { + padding: 1em; +} + +main { + margin: 0 auto; + max-width: 50em; +} diff --git a/templates/cv.xsl b/templates/cv.xsl new file mode 100644 index 0000000..91a143b --- /dev/null +++ b/templates/cv.xsl @@ -0,0 +1,132 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes" standalone="yes" doctype-system="about:legacy-compat" /> + <xsl:param name="title" select="'Ainsley Ellis CV'"/> + <xsl:template name="company"> + <article> + <h3><xsl:value-of select="./name/text()"/></h3> + <xsl:for-each select="./role"> + <xsl:call-template name="role"/> + </xsl:for-each> + </article> + </xsl:template> + <xsl:template name="project"> + <article> + <header> + <h3><xsl:value-of select="./name/text()" /></h3> + <p> + <xsl:value-of select="./activity/text()" /> + </p> + </header> + <xsl:copy-of select="./description/node()" /> + </article> + </xsl:template> + <xsl:template name="institution"> + <article> + <h3><xsl:value-of select="./name/text()" /></h3> + <dl> + <xsl:for-each select="./degree"> + <dt><xsl:value-of select="./level/text()" /> in <xsl:value-of select="./concentration/text()" /></dt> + <xsl:for-each select="./distinction"> + <dd><xsl:value-of select="./text()" /></dd> + </xsl:for-each> + </xsl:for-each> + </dl> + </article> + </xsl:template> + <xsl:template name="skill-category"> + <section> + <h3><xsl:value-of select="./name/text()" /></h3> + <ul role="list"> + <xsl:for-each select="./item"> + <li><xsl:value-of select="./text()" /></li> + </xsl:for-each> + </ul> + </section> + </xsl:template> + <xsl:template name="role"> + <article> + <header> + <h4><xsl:value-of select="./title/text()" /></h4> + <p> + <time> + <xsl:attribute name="datetime"> + <xsl:value-of select="./duration/start[@datetime]" /> + </xsl:attribute> + <xsl:value-of select="./duration/start/text()" /> + </time> + to + <xsl:choose> + <xsl:when test="./duration/end"> + <time> + <xsl:attribute name="datetime"> + <xsl:value-of select="./duration/end[@datetime]" /> + </xsl:attribute> + <xsl:value-of select="./duration/end/text()" /> + </time> + </xsl:when> + <xsl:otherwise>Present</xsl:otherwise> + </xsl:choose> + </p> + </header> + <xsl:copy-of select="./description/node()" /> + </article> + </xsl:template> + <xsl:template match="/cv" data-xmlns="http://www.w3.org/1999/xhtml"> + <html lang="en" dir="ltr"> + <!-- The Yesterweb is dead, long live the Yesterweb! --> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta name="color-scheme" content="light dark" /> + <title><xsl:value-of select="$title"/></title> + <link rel="stylesheet" href="../assets/css/all.css" /> + <link rel="stylesheet" href="../assets/css/screen.css" media="screen" /> + <link rel="stylesheet" href="../assets/css/print.css" media="print" /> + </head> + <body> + <main> + <xsl:copy-of select="document('./fragments/header.xml')"/> + <!-- <xsl:copy-of select="/cv"/> --> + <section id="objective"> + <h2>Objective</h2> + <!-- select specific objective from xml file --> + <xsl:copy-of select="document('./fragments/objectives.xml')/objectives/objective[@name='web-development']/node()"/> + </section> + <section id="work-history"> + <h2>Work History</h2> + <xsl:for-each select="./work-history/company"> + <xsl:call-template name="company"/> + </xsl:for-each> + </section> + <section id="open-source-contributions"> + <h2>Open-source Contributions</h2> + <xsl:for-each select="./foss-contributions/project"> + <xsl:call-template name="project"/> + </xsl:for-each> + </section> + <section id="education"> + <h2>Education</h2> + <xsl:for-each select="./education/institution"> + <xsl:call-template name="institution"/> + </xsl:for-each> + </section> + <section id="skills"> + <h2>Skills</h2> + <xsl:for-each select="./skills/category"> + <xsl:call-template name="skill-category"/> + </xsl:for-each> + </section> + </main> + <hr/> + <xsl:if test="$hash"> + <footer> + <p> + <small>Built with XSLT (<a> + <xsl:attribute name="href">https://git.pub0.org/heyainsleymae/curriculum-vitae/src/commit/<xsl:value-of select="$hash" /></xsl:attribute>view commit</a>)</small></p> + </footer> + </xsl:if> + </body> + </html> + </xsl:template> +</xsl:stylesheet> diff --git a/templates/fragments/header.xml b/templates/fragments/header.xml new file mode 100644 index 0000000..c4f30d1 --- /dev/null +++ b/templates/fragments/header.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<header> + <h1>Ainsley Ellis</h1> + <p class="headline">Artist, Programmer, Digital Citizen</p> + <address> + <ul role="list"> + <li>Email: <a href="mailto:ainsleymae@proton.me">Ainsley Ellis <ainsleymae@proton.me></a> + </li> + <li>Website: <a href="https://ains.me">ains.me</a></li> + <li> + <code>heyainsleymae</code> on <a href="https://codeberg.org/heyainsleymae">Codeberg</a>, <a href="https://github.com/heyainsleymae">GitHub</a>, and <a href="https://npmjs.com/~heyainsleymae">npm</a> + </li> + </ul> + <p>America/New_York (NYC)<br />Remote or hybrid work, open to relocation</p> + </address> +</header> diff --git a/templates/fragments/objectives.xml b/templates/fragments/objectives.xml new file mode 100644 index 0000000..9dedf6b --- /dev/null +++ b/templates/fragments/objectives.xml @@ -0,0 +1,14 @@ +<objectives> + <objective name="web-development"> + <p> + I am an accomplished full-stack developer with a passion for + accessibility and open web standards. I have experience building large, scalable + projects from scratch, improving internal processes and + design systems, and mentoring junior engineers. I hold a + <b>Section 508 Trusted Tester</b> certification from the United + States Department of Homeland Security. I want to work with a + diverse team to build accessible products that entertain, + inform, or assist the public. + </p> + </objective> +</objectives>