mirror of
https://github.com/Wolvan/poll.horse.git
synced 2024-11-21 20:47:59 +01:00
Implement favicon and embbed icon
Thanks to Shydale for lending me their OC checkbox. She a cute.
This commit is contained in:
parent
8042cfb4ff
commit
f68ff6dbd2
11 changed files with 3715 additions and 75 deletions
|
@ -1,3 +1,4 @@
|
|||
dist/
|
||||
node_modules/
|
||||
utils/todo-finder.js
|
||||
utils/create-favicons.js
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -117,3 +117,6 @@ data/
|
|||
# Config files
|
||||
config*.js*
|
||||
!config.example.json
|
||||
|
||||
# Favicons that are being auto-generated
|
||||
frontend/favicons/
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<meta property="og:title" content="{{ TITLE }}" />
|
||||
<meta property="og:description" content="Simple, free and open source way to host polls for people to vote on. Create your own polls and share them with others!" />
|
||||
<meta property="og:url" content="{{ CANONICAL_HOST }}" />
|
||||
<meta property="og:image" content="" />
|
||||
<meta property="og:image" content="{{ HOST }}/static/img/icon.png" />
|
||||
<meta property="og:site_name" content="Poll.Horse" />
|
||||
<meta content="#FFD756" data-react-helmet="true" name="theme-color" />
|
||||
|
||||
|
@ -27,6 +27,9 @@
|
|||
const MAX_CHARACTER_LENGTH = "{{ MAX_CHARACTER_LENGTH }}";
|
||||
</script>
|
||||
<script nonce="{{ CORS_SCRIPT_NONCE }}" type="text/javascript" src="/static/js/index.js" defer="true" async="true"></script>
|
||||
<!-- FAVICON_MARKER -->
|
||||
|
||||
<!-- /FAVICON_MARKER -->
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<meta property="og:title" content="{{ TITLE }}" />
|
||||
<meta property="og:description" content="{{ POLL_META_DESCRIPTION }}" />
|
||||
<meta property="og:url" content="{{ CANONICAL_HOST }}" />
|
||||
<meta property="og:image" content="" />
|
||||
<meta property="og:image" content="{{ HOST }}/static/img/icon.png" />
|
||||
<meta property="og:site_name" content="Poll.Horse" />
|
||||
<meta content="#FFD756" data-react-helmet="true" name="theme-color" />
|
||||
|
||||
|
@ -36,6 +36,9 @@
|
|||
document.querySelectorAll(".poll-option .text").forEach(element => textFit(element, textFitOptions));
|
||||
});
|
||||
</script>
|
||||
<!-- FAVICON_MARKER -->
|
||||
|
||||
<!-- /FAVICON_MARKER -->
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<meta property="og:title" content="{{ TITLE }}" />
|
||||
<meta property="og:description" content="{{ POLL_META_DESCRIPTION }}" />
|
||||
<meta property="og:url" content="{{ CANONICAL_HOST }}" />
|
||||
<meta property="og:image" content="" />
|
||||
<meta property="og:image" content="{{ HOST }}/static/img/icon.png" />
|
||||
<meta property="og:site_name" content="Poll.Horse" />
|
||||
<meta content="#FFD756" data-react-helmet="true" name="theme-color" />
|
||||
|
||||
|
@ -30,6 +30,9 @@
|
|||
const POLL_ID = "{{ POLL_ID }}";
|
||||
</script>
|
||||
<script nonce="{{ CORS_SCRIPT_NONCE }}" type="text/javascript" src="/static/js/result.js" defer="true"></script>
|
||||
<!-- FAVICON_MARKER -->
|
||||
|
||||
<!-- /FAVICON_MARKER -->
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
|
|
BIN
frontend/static/img/icon.png
Normal file
BIN
frontend/static/img/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
3699
package-lock.json
generated
3699
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -8,7 +8,8 @@
|
|||
"find-todo": "node utils/todo-finder.js ./src && node utils/todo-finder.js ./frontend",
|
||||
"mocha": "mocha",
|
||||
"lint": "eslint .",
|
||||
"build": "rimraf ./dist && tsc",
|
||||
"build:favicons": "node utils/create-favicons",
|
||||
"build": "rimraf ./dist && npm run build:favicons && tsc",
|
||||
"test": "npm run lint && npm run find-todo && npm run mocha",
|
||||
"debug": "ts-node-dev --inspect --respawn --clear ./src/main.ts",
|
||||
"start:build": "npm test && npm run build && node ./dist/main.js",
|
||||
|
@ -46,6 +47,7 @@
|
|||
"@types/node": "^16.11.10",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
"@types/node-persist": "^3.1.2",
|
||||
"@types/serve-favicon": "^2.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"chai": "^4.3.4",
|
||||
|
@ -65,10 +67,12 @@
|
|||
"compression": "^1.7.4",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"express": "^4.17.2",
|
||||
"favicons": "^6.2.2",
|
||||
"fs-extra": "^10.0.0",
|
||||
"helmet": "^5.0.2",
|
||||
"mysql2": "^2.3.3",
|
||||
"node-fetch": "^2.6.6",
|
||||
"node-persist": "^3.1.0"
|
||||
"node-persist": "^3.1.0",
|
||||
"serve-favicon": "^2.5.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,7 +162,8 @@ export default function init(router: Router): void {
|
|||
"QR_CODE": `https://chart.googleapis.com/chart?cht=qr&chs=190x190&chld=L|1&chl=${ encodeURIComponent(`${ req.protocol }://${ req.headers.host }/${ id }`) }`,
|
||||
"CANONICAL_HOST": req.protocol + "://" + (req.headers.host || "") + "/" + id + "/r",
|
||||
"POLL_META_DESCRIPTION": xss(poll.title || "Simple, free and open source way to host polls for people to vote on. Create your own polls and share them with others!").substring(0, 150),
|
||||
"CORS_SCRIPT_NONCE": res.locals.cspNonce
|
||||
"CORS_SCRIPT_NONCE": res.locals.cspNonce,
|
||||
"HOST": req.protocol + "://" + (req.headers.host || "")
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
@ -202,7 +203,8 @@ export default function init(router: Router): void {
|
|||
"QR_CODE": `https://chart.googleapis.com/chart?cht=qr&chs=190x190&chld=L|1&chl=${ encodeURIComponent(`${ req.protocol }://${ req.headers.host }/${ id }`) }`,
|
||||
"CANONICAL_HOST": req.protocol + "://" + (req.headers.host || "") + "/" + id,
|
||||
"POLL_META_DESCRIPTION": xss(poll.title || "Simple, free and open source way to host polls for people to vote on. Create your own polls and share them with others!").substring(0, 150),
|
||||
"CORS_SCRIPT_NONCE": res.locals.cspNonce
|
||||
"CORS_SCRIPT_NONCE": res.locals.cspNonce,
|
||||
"HOST": req.protocol + "://" + (req.headers.host || "")
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
@ -237,7 +239,8 @@ export default function init(router: Router): void {
|
|||
"MAX_POLL_OPTIONS": MAX_POLL_OPTIONS,
|
||||
"MAX_CHARACTER_LENGTH": MAX_CHARACTER_LENGTH,
|
||||
"CANONICAL_HOST": req.protocol + "://" + (req.headers.host || ""),
|
||||
"CORS_SCRIPT_NONCE": res.locals.cspNonce
|
||||
"CORS_SCRIPT_NONCE": res.locals.cspNonce,
|
||||
"HOST": req.protocol + "://" + (req.headers.host || "")
|
||||
});
|
||||
});
|
||||
}
|
12
src/main.ts
12
src/main.ts
|
@ -11,6 +11,8 @@ import Storage from "./Storage";
|
|||
import MySQLStorage from "./MySQLStorage";
|
||||
import helmet from "helmet";
|
||||
import crypto from "crypto";
|
||||
import { statSync } from "fs";
|
||||
import serveFavicon from "serve-favicon";
|
||||
|
||||
async function main(): Promise<void> {
|
||||
await loadConfig([
|
||||
|
@ -31,6 +33,16 @@ async function main(): Promise<void> {
|
|||
const opts = program.opts();
|
||||
|
||||
const app = express();
|
||||
|
||||
try {
|
||||
if (statSync(resolve(__dirname, "../frontend/favicons")).isDirectory()) {
|
||||
app.use("/favicons", express.static(resolve(__dirname, "../frontend/favicons")));
|
||||
if (statSync(resolve(__dirname, "../frontend/favicons/favicon.ico")).isFile()) app.use(serveFavicon(resolve(__dirname, "../frontend/favicons/favicon.ico")));
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("FavIcons not available: ", error);
|
||||
}
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(compression());
|
||||
|
|
43
utils/create-favicons.js
Normal file
43
utils/create-favicons.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
const favicons = require("favicons");
|
||||
const resolve = require("path").resolve;
|
||||
const fs = require("fs-extra");
|
||||
|
||||
const start = new Date();
|
||||
favicons(resolve(__dirname, "../frontend/static/img/icon.png"), {
|
||||
path: "/favicons",
|
||||
appName: "Poll.Horse",
|
||||
appShortName: "poll_horse",
|
||||
appDescription: "Simple, free and open source way to host polls for people to vote on. Create your own polls and share them with others!",
|
||||
developerName: "Wolvan",
|
||||
developerURL: "https://github.com/wolvan",
|
||||
background: "#FFD756",
|
||||
theme_color: "#FFD756",
|
||||
version: require(resolve(__dirname, "../package.json")).version
|
||||
}, async (error, response) => {
|
||||
if (error) throw new error;
|
||||
await fs.remove(resolve(__dirname, "../frontend/favicons"));
|
||||
await fs.ensureDir(resolve(__dirname, "../frontend/favicons"));
|
||||
await Promise.all(response.images.map(({ name, contents }) => fs.writeFile(resolve(__dirname, "../frontend/favicons", name), contents)));
|
||||
await Promise.all(response.files.map(({ name, contents }) => fs.writeFile(resolve(__dirname, "../frontend/favicons", name), contents)));
|
||||
|
||||
try {
|
||||
if ((await fs.stat(resolve(__dirname, "../frontend/html"))).isDirectory()) {
|
||||
const files = await fs.readdir(resolve(__dirname, "../frontend/html"));
|
||||
await Promise.all(files.filter(file => file.match(/\.html?/i)).map(async file => {
|
||||
let content = await fs.readFile(resolve(__dirname, "../frontend/html", file), "utf8");
|
||||
content = content
|
||||
.replace(/<!-- FAVICON_MARKER -->[\s\S]*<!-- \/FAVICON_MARKER -->/i,
|
||||
`<!-- FAVICON_MARKER -->
|
||||
${response.html.join("\n ")}
|
||||
<!-- \/FAVICON_MARKER -->`);
|
||||
await fs.writeFile(resolve(__dirname, "../frontend/html", file), content);
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
console.log("Finished Favicon generation in", ((new Date() - start) / 1000).toFixed(2), "s");
|
||||
});
|
Loading…
Reference in a new issue