Shipping this

This commit is contained in:
Neale Pickett 2019-11-09 11:00:00 -07:00
commit be5362136f
7 changed files with 297 additions and 0 deletions

26
.gcloudignore Normal file
View File

@ -0,0 +1,26 @@
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
fetch-static.sh
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
static/FeisWorxLogo2.gif
static/bg8.jpg
static/cards.jpg
static/favicon.ico
static/feisworx.css

22
README.md Normal file
View File

@ -0,0 +1,22 @@
This site adds a few simple tweaks to the feisworx web site,
in order to make it look better on a phone.
The iPhone doesn't allow browser plugins.
So I had to create a whole app just to drop in some JavaScript.
Hopefully one day feisworx integrates this and I can take my site down.
Testing
-------
First you should download static content,
so you're not hammering away at the feisworx site
for static resources.
./fetch-static.sh
Then you can test with
go run .

6
app.yaml Normal file
View File

@ -0,0 +1,6 @@
runtime: go113
handlers:
- url: /images
static_dir: static
- url: /share
static_dir: static

14
fetch-static.sh Executable file
View File

@ -0,0 +1,14 @@
#! /bin/sh
set -e
cd $(dirname $0)/static
while read url; do
wget -c $url
done <<EOD
https://www.feisworx.com/favicon.ico
https://www.feisworx.com/images/bg8.jpg
https://www.feisworx.com/images/cards.jpg
https://www.feisworx.com/images/FeisWorxLogo2.gif
https://www.feisworx.com/share/feisworx.css
EOD

70
main.go Normal file
View File

@ -0,0 +1,70 @@
package main
import (
"io/ioutil"
"net/http"
"regexp"
"log"
"os"
"strings"
"fmt"
)
func copyHeader(dst, src http.Header) {
for k, vv := range src {
for _, v := range vv {
dst.Add(k, v)
}
}
}
var HeadTag = regexp.MustCompile("<head>")
const NewHead = `<head>
<script src="/share/foneworx.js"></script>
`
func Handler(w http.ResponseWriter, r *http.Request) {
r.URL.Scheme = "https"
r.URL.Host = "www.feisworx.com"
r.Host = "www.feisworx.com"
resp, err := http.DefaultTransport.RoundTrip(r)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}
contentType := resp.Header.Get("Content-Type")
tamperBody := body
if strings.HasPrefix(contentType, "text/html") {
tamperBody = HeadTag.ReplaceAll(body, []byte(NewHead))
}
copyHeader(w.Header(), resp.Header)
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(tamperBody)))
w.WriteHeader(resp.StatusCode)
w.Write(tamperBody)
}
func main() {
http.HandleFunc("/", Handler)
http.Handle("/share/", http.StripPrefix("/share/", http.FileServer(http.Dir("static/"))))
http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir("static/"))))
port := os.Getenv("PORT")
if port == "" {
port = "8080"
log.Printf("Defaulting to port %s", port)
}
log.Printf("Listening on port %s", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

154
static/foneworx.js Normal file
View File

@ -0,0 +1,154 @@
// ==UserScript==
// @name PhoneWorx
// @namespace https://gist.githubusercontent.com/nealey/3af026cc34ddf502419aa16eee3a4caa/
// @version 0.4
// @description Subtly change Feisworks for narrow screens
// @author Neale Pickett <neale@woozle.org>
// @match http*://*.feisworx.com/*
// @match http*://feisworx.com/*
// @grant none
// ==/UserScript==
// jshint asi:true
// Most of what we're doing here is trying to make content flow.
// Quite a lot of pages are set up to do this pretty well already,
// they just need some hints removed.
var foneworxCss = `
body {
background: rgb(127,216,192);
background: linear-gradient(0deg, #1fc6f4 0%, #7fd8c0 100%);
}
#foneworx-contact p {
float: right;
padding: 0 1em;
font-size: small;
}
#foneworx-logo {
font-family: 'Uncial Antiqua', cursive;
font-size: 1.5em;
}
#foneworx-logo a:link {
text-decoration: none;
color: black;
}
@media (max-width: 768px) {
body {
margin: 0;
}
h1, h2, h3, p {
margin: 0.5em;
}
#foneworx-title h1 {
margin: 0em 0.5em;
}
body > table:nth-of-type(1) tr {
display: flex;
flex-wrap: wrap;
}
#foneworx-nav tr {
display: flex;
}
a.sel {
padding: 0.5em;
margin: 0.1em;
}
form > table:nth-of-type(1) tr {
display: flex;
flex-wrap: wrap;
}
form > table:nth-of-type(1) td {
display: block;
}
}
`
var foneworxNotice = `
<hr>
<p>
FoneWorx is an unofficial wrapper around FeisWorx.
We have reached out to the FeisWorx people
about integrating this functionality,
and remain hopeful that something like this can make it to the
official site.
</p>
<p>
If you have problems with FoneWorx,
try the <a href="https://www.feisworx.com/">FeisWorx Site</a>
instead.
</p>
<p>
<a href="mailto:neale@woozle.org">FoneWorx Contact</a>
|
<a href="https://github.com/nealey/foneworx">Source</a>
<p>
`
function foneworxTag(path, id) {
let e = document.querySelector(path)
if (e) {
e.id = id
}
}
function foneworxInit() {
let viewport = document.createElement("meta")
viewport.name = "viewport"
viewport.content = "width=device-width, initial-scale=1"
document.head.appendChild(viewport)
let fontlink = document.createElement("link")
fontlink.href="https://fonts.googleapis.com/css?family=Uncial+Antiqua&display=swap"
fontlink.rel="stylesheet"
document.head.appendChild(fontlink)
// Remove forced width on anything that forces it
for (let e of document.querySelectorAll("[width]")) {
e.width = undefined
}
// Tag some things to make CSS more readable
foneworxTag("body > table:first-child [align='left']", "foneworx-logo")
foneworxTag("body > table:first-child [align='center']", "foneworx-title")
foneworxTag("body > table:first-child [align='right']", "foneworx-contact")
foneworxTag("table[align='center']", "foneworx-nav")
// Do a lot of things to prevent people from pestering FeisWorx.
// If you are the FeisWorx people, I would love to
// give you whatever support you need to integrate this code,
// absolutely free of charge. neale@woozle.org
// Change out the logo so it's clear this isn't FeisWorx
let logo = document.querySelector("#foneworx-logo")
if (logo) {
logo.innerHTML = "<a href='/'>FoneWorx</a>"
}
// Tamper heavily with "contact us"
// so the feisworx people don't get a ton of mail
// about something they didn't make.
let contact = document.querySelector("#foneworx-contact")
if (contact) {
// Move it to the bottom
document.querySelector(".copyright").insertAdjacentElement("beforebegin", contact)
contact.innerHTML = foneworxNotice
}
let style = document.createElement("style")
style.textContent = foneworxCss
document.head.appendChild(style)
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", foneworxInit)
} else {
foneworxInit()
}