summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2021-11-14 17:53:31 +0100
committerTor Andersson <tor@ccxvii.net>2021-11-14 17:53:31 +0100
commitb9d5983b17adbd238fdb8a41d926dacf53730675 (patch)
tree994df12beb4a91d9255aea656050ddc9afda0688
parentbf9b4ddafe5d11e510760f6af4479e29da6987ba (diff)
downloadserver-b9d5983b17adbd238fdb8a41d926dacf53730675.tar.gz
Inline style sheet in EJS template to prevent FOUC.
-rw-r--r--public/fonts/fonts.css103
-rw-r--r--public/style.css74
-rw-r--r--server.js9
-rw-r--r--views/header.ejs6
4 files changed, 43 insertions, 149 deletions
diff --git a/public/fonts/fonts.css b/public/fonts/fonts.css
index 641373e..2dfe776 100644
--- a/public/fonts/fonts.css
+++ b/public/fonts/fonts.css
@@ -1,88 +1,15 @@
-@font-face {
- font-family: 'Circled Numbers';
- src: url('CircledNumbers.woff2') format('woff2');
- unicode-range: U+2460-2465, U+2776-277B;
-}
-
-@font-face {
- font-family: 'Dingbats';
- src: url('Dingbats.woff2') format('woff2');
- unicode-range: U+2701-27FF;
-}
-
-@font-face {
- font-family: 'Noto Emoji';
- src: url('NotoEmoji.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Sans';
- src: url('SourceSans3-Regular.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Sans';
- font-style: italic;
- src: url('SourceSans3-It.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Sans';
- font-weight: bold;
- src: url('SourceSans3-Semibold.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Sans';
- font-weight: bold;
- font-style: italic;
- src: url('SourceSans3-SemiboldIt.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Serif';
- src: url('SourceSerif4-Regular.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Serif';
- font-style: italic;
- src: url('SourceSerif4-It.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Serif';
- font-weight: bold;
- src: url('SourceSerif4-Semibold.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Serif';
- font-weight: bold;
- font-style: italic;
- src: url('SourceSerif4-SemiboldIt.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Serif SmText';
- src: url('SourceSerif4SmText-Regular.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Serif SmText';
- font-style: italic;
- src: url('SourceSerif4SmText-It.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Serif SmText';
- font-weight: bold;
- src: url('SourceSerif4SmText-Semibold.woff2') format('woff2');
-}
-
-@font-face {
- font-family: 'Source Serif SmText';
- font-weight: bold;
- font-style: italic;
- src: url('SourceSerif4SmText-SemiboldIt.woff2') format('woff2');
-}
+@font-face{font-family:'Circled Numbers';src:url('/fonts/CircledNumbers.woff2')format('woff2');unicode-range:U+2460-2465, U+2776-277B}
+@font-face{font-family:'Dingbats';src:url('/fonts/Dingbats.woff2')format('woff2');unicode-range:U+2701-27FF}
+@font-face{font-family:'Noto Emoji';src:url('/fonts/NotoEmoji.woff2')format('woff2')}
+@font-face{font-family:'Source Sans';src:url('/fonts/SourceSans3-Regular.woff2')format('woff2')}
+@font-face{font-family:'Source Sans';font-style:italic;src:url('/fonts/SourceSans3-It.woff2')format('woff2')}
+@font-face{font-family:'Source Sans';font-weight:bold;src:url('/fonts/SourceSans3-Semibold.woff2')format('woff2')}
+@font-face{font-family:'Source Sans';font-weight:bold;font-style:italic;src:url('/fonts/SourceSans3-SemiboldIt.woff2')format('woff2')}
+@font-face{font-family:'Source Serif';src:url('/fonts/SourceSerif4-Regular.woff2')format('woff2')}
+@font-face{font-family:'Source Serif';font-style:italic;src:url('/fonts/SourceSerif4-It.woff2')format('woff2')}
+@font-face{font-family:'Source Serif';font-weight:bold;src:url('/fonts/SourceSerif4-Semibold.woff2')format('woff2')}
+@font-face{font-family:'Source Serif';font-weight:bold;font-style:italic;src:url('/fonts/SourceSerif4-SemiboldIt.woff2')format('woff2')}
+@font-face{font-family:'Source Serif SmText';src:url('/fonts/SourceSerif4SmText-Regular.woff2')format('woff2')}
+@font-face{font-family:'Source Serif SmText';font-style:italic;src:url('/fonts/SourceSerif4SmText-It.woff2')format('woff2')}
+@font-face{font-family:'Source Serif SmText';font-weight:bold;src:url('/fonts/SourceSerif4SmText-Semibold.woff2')format('woff2')}
+@font-face{font-family:'Source Serif SmText';font-weight:bold;font-style:italic;src:url('/fonts/SourceSerif4SmText-SemiboldIt.woff2')format('woff2')}
diff --git a/public/style.css b/public/style.css
index f72cdb7..76d6ff2 100644
--- a/public/style.css
+++ b/public/style.css
@@ -1,21 +1,9 @@
-button, select {
- font-family: "Source Sans", "Verdana", "Dingbats", "Noto Emoji", sans-serif;
- font-size: 16px;
-}
-html, input, textarea {
- font-family: "Source Serif", "Georgia", "Dingbats", "Noto Emoji", serif;
- font-size: 16px;
-}
+html, input, textarea { font-family: "Source Serif", "Georgia", "Dingbats", "Noto Emoji", serif; font-size: 16px; }
+button, select { font-family: "Source Sans", "Verdana", "Dingbats", "Noto Emoji", sans-serif; font-size: 16px; }
html, body { margin: 0; }
h1 { margin-left: -2px; }
h2 { margin-left: -1px; }
-.header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- border-bottom: 2px solid brown;
- padding-right: 1em;
-}
+.header { display: flex; align-items: center; justify-content: space-between; border-bottom: 2px solid brown; padding-right: 1em; }
.header img { display: block; margin: 4px 0 -2px 2px; }
.header span { margin: 0 1em; }
.header a { color: black; }
@@ -24,29 +12,25 @@ h2 { margin-left: -1px; }
.main hr { max-width: 50rem; margin-right: auto; margin-left: 0; }
.main hr { border: none; border-top: 2px dotted brown; }
.main hr + p { font-style: italic; }
+img.logo { float: left; margin: 0 20px 5px 0; box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.5); height: 200px; }
+img.avatar { float: left; margin: 0 20px 5px 0; box-shadow: 2px 2px 4px 0px rgba(0,0,0,.5); width: 80px; height: 80px; }
.is_active { background-color: lemonchiffon; }
.error { color: brown; font-style: italic; white-space: pre-wrap; }
.warning { color: brown; }
.warning::before { content: "\26a0"; }
-img.logo {
- float: left;
- margin: 0 20px 5px 0;
- box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.5);
- height: 200px;
-}
-img.avatar {
- float: left;
- margin: 0 20px 5px 0;
- box-shadow: 2px 2px 4px 0px rgba(0,0,0,.5);
- width: 80px; height: 80px;
-}
-
+form { display: inline; }
+label { user-select: none; }
+input[type="text"], input[type="password"], textarea { padding: 5px; }
+select { padding-right: 20px; }
+button, input, select { font-size: 1rem; margin: 5px 0; }
+button, select { margin: 5px 10px 5px 0; padding: 1px 10px; background-color: gainsboro; vertical-align: top; }
+button:disabled { color: gray; border: 2px solid gainsboro; outline: 1px solid gray; }
+button:enabled, select { border: 2px outset white; outline: 1px solid black; }
+button:enabled:active:hover, select:active { border: 2px inset white; padding: 2px 9px 0px 11px; }
table { border-collapse: collapse; }
-tfoot td { background-color: gainsboro; }
+tfoot { background-color: gainsboro; }
th { text-align: left; background-color: gainsboro; }
-th, td { border: 1px solid black; }
-th, td { padding: 3px 1ex; }
-
+th, td { border: 1px solid black; padding: 3px 1ex; }
table.game { min-width: min(50rem,100%); }
table.game .title { white-space: nowrap; }
table.game .scenario { white-space: nowrap; }
@@ -54,7 +38,6 @@ table.game .role { white-space: nowrap; }
table.game .time { white-space: nowrap; }
table.game td a { text-decoration: none; color: black; }
table.game td.command a { text-decoration: underline; color: blue; }
-
table.post { min-width: min(50rem,100%); }
table.post .author { white-space: nowrap; width: 10rem; }
table.post .time { white-space: nowrap; text-align: right; width: 5rem; }
@@ -63,28 +46,3 @@ table.post .unread { background-color: lightyellow; }
table.post .body { white-space: pre-wrap; padding: 10px 10px; }
table.post th a { text-decoration: none; color: black; }
table.post td:not(.body):not(.edit) a { text-decoration: none; color: black; }
-
-label { user-select: none; }
-button, input, select { font-size: 1rem; margin: 5px 0; }
-input[type="text"], input[type="password"], textarea { padding: 5px; }
-select { padding-right: 20px; }
-form { display: inline; }
-button, select {
- margin: 5px 10px 5px 0;
- padding: 1px 10px;
- background-color: gainsboro;
- vertical-align: top;
-}
-button:disabled {
- color: gray;
- border: 2px solid gainsboro;
- outline: 1px solid gray;
-}
-button:enabled, select {
- border: 2px outset white;
- outline: 1px solid black;
-}
-button:enabled:active:hover, select:active {
- border: 2px inset white;
- padding: 2px 9px 0px 11px;
-}
diff --git a/server.js b/server.js
index 470eba9..a6c8394 100644
--- a/server.js
+++ b/server.js
@@ -87,7 +87,14 @@ io.use(passport_socket.authorize({
store: session_store,
}));
-app.use(express.static('public'));
+const is_immutable = /\.(svg|png|jpg|jpeg|woff2)$/;
+
+function setHeaders(res, path) {
+ if (is_immutable.test(path))
+ res.set("Cache-Control", "public, max-age=86400, immutable");
+}
+
+app.use(express.static('public', { setHeaders: setHeaders }));
/*
* MISC FUNCTIONS
diff --git a/views/header.ejs b/views/header.ejs
index 337290a..c8337fc 100644
--- a/views/header.ejs
+++ b/views/header.ejs
@@ -4,9 +4,11 @@
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">
<% if (typeof refresh !== 'undefined' && refresh > 0) { %><meta http-equiv="refresh" content="<%= refresh %>"><% } %>
<link rel="icon" href="/favicon.svg">
-<link rel="stylesheet" href="/fonts/fonts.css">
-<link rel="stylesheet" href="/style.css">
<title><%= title %></title>
+<style>
+<%- include('../public/fonts/fonts.css') _%>
+<%- include('../public/style.css') _%>
+</style>
</head>
<body>
<div class="header">