M Makefile => Makefile +2 -2
@@ 6,8 6,8 @@ dst := _build/geohash-$(os)-$(cpu)-$(ver).cgi
final: build $(dst)
-lib/res.ml: res res/doap.rdf res/doap2html.xslt
- find res -name .DS_Store -delete
+lib/res.ml: res res/doap.rdf res/doap2html.xslt res/doap2html.css res/doap2html.js res/gpx2html.xslt res/gpx2html.css res/gpx2html.js
+ find $< -name .DS_Store -delete
# opam install ocp-ocamlres
ocp-ocamlres -format ocaml $< -o $@
M bin/cgi.ml => bin/cgi.ml +4 -0
@@ 64,7 64,11 @@ let handle oc req =
| "/about" -> dump_clob oc "text/xml" Res.doap_rdf
| "/LICENSE" -> dump_clob oc "text/plain" Res._LICENSE
| "/doap2html.xslt" -> dump_clob oc "text/xml" Res.doap2html_xslt
+ | "/doap2html.css" -> dump_clob oc "text/css; charset=utf-8" Res.doap2html_css
+ | "/doap2html.js" -> dump_clob oc "text/javascript; charset=utf-8" Res.doap2html_js
| "/gpx2html.xslt" -> dump_clob oc "text/xml" Res.gpx2html_xslt
+ | "/gpx2html.css" -> dump_clob oc "text/css; charset=utf-8" Res.gpx2html_css
+ | "/gpx2html.js" -> dump_clob oc "text/javascript; charset=utf-8" Res.gpx2html_js
| "" -> uri ^ "/" |> redirect oc
| "/" -> (
match req.query_string with
A res/doap2html.css => res/doap2html.css +38 -0
@@ 0,0 1,38 @@
+html {
+ font-family: sans-serif;
+ background: hsl(30, 50%, 93%);
+ color: hsl(30, 50%, 44%);
+}
+body {
+ margin: auto;
+ max-width: 43rem;
+}
+a, a:visited {
+ color: hsl(115, 50%, 35%);
+ text-decoration: none;
+}
+h1 > a, h2 > a {
+ font-size: 60%;
+ vertical-align: baseline;
+ position: relative;
+ top: -0.7em;
+}
+#sep {
+ text-align: center;
+}
+#poweredby {
+ font-size: 80%;
+ color: #888;
+ border-top: 2px solid darkgrey;
+ padding-top: 1ex;
+}
+p[lang="en"]::after { content: "🇬🇧"; }
+pre[lang="en"]::before { content: "🇬🇧"; }
+p[lang="fr"]::after { content: "🇫🇷"; }
+
+@media (prefers-color-scheme: dark) {
+ html {
+ background: hsl(30, 20%, 23%);
+ }
+}
+
A res/doap2html.js => res/doap2html.js +2 -0
@@ 0,0 1,2 @@
+document.getElementById('my-url').innerText = location.href;
+
M res/doap2html.xslt => res/doap2html.xslt +2 -45
@@ 51,47 51,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
- <style type="text/css">
-/*<![CDATA[*/
- html {
- font-family: sans-serif;
- background: hsl(30, 50%, 93%);
- color: hsl(30, 50%, 44%);
- }
- body {
- margin: auto;
- max-width: 43rem;
- }
- a, a:visited {
- color: hsl(115, 50%, 35%);
- text-decoration: none;
- }
- h1 > a, h2 > a {
- font-size: 60%;
- vertical-align: baseline;
- position: relative;
- top: -0.7em;
- }
- #sep {
- text-align: center;
- }
- #poweredby {
- font-size: 80%;
- color: #888;
- border-top: 2px solid darkgrey;
- padding-top: 1ex;
- }
- p[lang="en"]::after { content: "🇬🇧"; }
- pre[lang="en"]::before { content: "🇬🇧"; }
- p[lang="fr"]::after { content: "🇫🇷"; }
-
- @media (prefers-color-scheme: dark) {
- html {
- background: hsl(30, 20%, 23%);
- }
- }
- /*]]>*/
- </style>
+ <link href="./doap2html.css" rel="stylesheet" type="text/css"/>
<title><xsl:value-of select="doap:name"/> – DOAP</title>
</head>
@@ 193,10 153,7 @@
<p id="poweredby">RDF (<a href="https://en.wikipedia.org/wiki/DOAP">DOAP</a>): <tt>$ <a href=
"http://librdf.org/raptor/rapper.html">rapper</a> --guess --output turtle '<span id=
- "my-url">https://example.com/url-to-here</span>'</tt></p><script type="text/javascript">
-//<![CDATA[
- document.getElementById('my-url').innerText = location.href;
- //]]>
+ "my-url">https://example.com/url-to-here</span>'</tt></p><script src="./doap2html.js" type="text/javascript">
</script>
</body>
</html>
A res/gpx2html.css => res/gpx2html.css +40 -0
@@ 0,0 1,40 @@
+body {
+ background: #ddd;
+ margin: 0;
+}
+iframe {
+ background: #ddd;
+ border:0;
+ height:100%;
+ position:fixed; /* https://stackoverflow.com/a/2425694/349514 */
+ width:100%;
+}
+form {
+ left: 58px;
+ line-height: 4ex;
+ position: absolute;
+ top: 4px;
+ width: calc(100% - 59px);
+}
+input {
+ background: white;
+}
+small {
+ /* https://alligator.io/css/prevent-line-break/ */
+ background-color: hsla(0,0%,100%,0.75);
+ border: 2px solid #ccc;
+ overflow: hidden;
+ padding: 1.1ex;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+input,button {
+ font-family: monospace;
+ font-size: 10pt;
+ padding: 0.8ex 1.5ex;
+}
+input,button,small {
+ border-radius: 1ex;
+ margin: 1.2ex;
+}
+
A res/gpx2html.js => res/gpx2html.js +32 -0
@@ 0,0 1,32 @@
+/* MIT License https://github.com/joliss/js-string-escape/blob/master/index.js */
+function jsStringEscape(string) {
+ return ('' + string).replace(/["'\\\n\r\u2028\u2029]/g, function (character) {
+ // Escape all characters not included in SingleStringCharacters and
+ // DoubleStringCharacters on
+ // http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
+ switch (character) {
+ case '"':
+ case "'":
+ case '\\':
+ return '\\' + character
+ // Four possible LineTerminator characters need to be escaped:
+ case '\n':
+ return '\\n'
+ case '\r':
+ return '\\r'
+ case '\u2028':
+ return '\\u2028'
+ case '\u2029':
+ return '\\u2029'
+ }
+ })
+}
+
+document.onreadystatechange = function () {
+ var a = document.getElementById("bookmarklet");
+ a.href = a.href.replace("}('../'));", "}('"+jsStringEscape(window.location)+"/../'));");
+
+ // load iframe content once it's size is set - mitigate FOUC https://stackoverflow.com/a/57675785/349514
+ var f = document.getElementById('ifrm_map');
+ f.src = f.dataset.src;
+}
M res/gpx2html.xslt => res/gpx2html.xslt +4 -68
@@ 100,7 100,8 @@ function(bas)
<xsl:variable name="wpt" select="g:wpt[1]"/>
<body>
- <iframe src="https://www.openstreetmap.org/export/embed.html?bbox={$bbox/@minlon},{$bbox/@minlat},{$bbox/@maxlon},{$bbox/@maxlat}&marker={$wpt/@lat},{$wpt/@lon}"/>
+ <!-- defer until external (CSP!) css is ready -->
+ <iframe id="ifrm_map" data-src="https://www.openstreetmap.org/export/embed.html?bbox={$bbox/@minlon},{$bbox/@minlat},{$bbox/@maxlon},{$bbox/@maxlat}&marker={$wpt/@lat},{$wpt/@lon}"/>
<form action="." id="search_form" name="search_form">
<input name="q" placeholder="geo:lat,lon" size="24" value="geo:{$wpt/@lat},{$wpt/@lon}" autofocus="autofocus" />
@@ 125,33 126,7 @@ function(bas)
<xsl:text> </xsl:text>
<small>
<a id="bookmarklet" href="{$Geo2Rdf}"><xsl:value-of select="$globe"/> Geohash Bookmarklet</a>
- <script>
-/* MIT License https://github.com/joliss/js-string-escape/blob/master/index.js */
-function jsStringEscape(string) {
- return ('' + string).replace(/["'\\\n\r\u2028\u2029]/g, function (character) {
- // Escape all characters not included in SingleStringCharacters and
- // DoubleStringCharacters on
- // http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
- switch (character) {
- case '"':
- case "'":
- case '\\':
- return '\\' + character
- // Four possible LineTerminator characters need to be escaped:
- case '\n':
- return '\\n'
- case '\r':
- return '\\r'
- case '\u2028':
- return '\\u2028'
- case '\u2029':
- return '\\u2029'
- }
- })
-}
- var a = document.getElementById("bookmarklet");
- a.href = a.href.replace("}('../'));", "}('"+jsStringEscape(window.location)+"/../'));");
- </script>
+ <script defer="defer" src="./gpx2html.js"/>
</small>
</form>
</body>
@@ 168,46 143,7 @@ function jsStringEscape(string) {
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>#<xsl:value-of select="$globe"/> Geohash</title>
- <style type="text/css">
-/*<![CDATA[*/
- body {
- margin: 0;
- }
- iframe {
- border:0;
- height:100%;
- position:fixed; /* https://stackoverflow.com/a/2425694/349514 */
- width:100%;
- }
- form {
- left: 58px;
- line-height: 4ex;
- position: absolute;
- top: 4px;
- width: calc(100% - 59px);
- }
- input {
- background: white;
- }
- small {
- /* https://alligator.io/css/prevent-line-break/ */
- background-color: hsla(0,0%,100%,0.75);
- border: 2px solid #ccc;
- overflow: hidden;
- padding: 1.1ex;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- input,button {
- font-family: monospace;
- font-size: 10pt;
- padding: 0.8ex 1.5ex;
- }
- input,button,small {
- border-radius: 1ex;
- margin: 1.2ex;
- }
- /*]]>*/ </style>
+ <link href="./gpx2html.css" rel="stylesheet" type="text/css"/>
</head>
</xsl:template>
</xsl:stylesheet>