Spaces:
Running
Running
| const handlebars = require("handlebars"); | |
| const fs = require("fs"); | |
| const path = require("path"); | |
| const url = require("url"); | |
| const accept_language_parser = require("accept-language-parser"); | |
| const client_config = require("./client_configuration"); | |
| /** | |
| * Associations from language to translation dictionnaries | |
| * @const | |
| * @type {object} | |
| */ | |
| const TRANSLATIONS = JSON.parse( | |
| fs.readFileSync(path.join(__dirname, "translations.json")), | |
| ); | |
| const languages = Object.keys(TRANSLATIONS); | |
| handlebars.registerHelper({ | |
| json: JSON.stringify.bind(JSON), | |
| }); | |
| function findBaseUrl(req) { | |
| var proto = | |
| req.headers["X-Forwarded-Proto"] || | |
| (req.connection.encrypted ? "https" : "http"); | |
| var host = req.headers["X-Forwarded-Host"] || req.headers.host; | |
| return proto + "://" + host; | |
| } | |
| class Template { | |
| constructor(path) { | |
| const contents = fs.readFileSync(path, { encoding: "utf8" }); | |
| this.template = handlebars.compile(contents); | |
| } | |
| parameters(parsedUrl, request, isModerator) { | |
| const accept_language_str = | |
| parsedUrl.query.lang || request.headers["accept-language"]; | |
| const accept_languages = accept_language_parser.parse(accept_language_str); | |
| const opts = { loose: true }; | |
| let language = | |
| accept_language_parser.pick(languages, accept_languages, opts) || "en"; | |
| // The loose matcher returns the first language that partially matches, so we need to | |
| // check if the preferred language is supported to return it | |
| if (accept_languages.length > 0) { | |
| const preferred_language = | |
| accept_languages[0].code + "-" + accept_languages[0].region; | |
| if (languages.includes(preferred_language)) { | |
| language = preferred_language; | |
| } | |
| } | |
| const translations = TRANSLATIONS[language] || {}; | |
| const configuration = client_config || {}; | |
| const prefix = request.url.split("/boards/")[0].substr(1); | |
| const baseUrl = findBaseUrl(request) + (prefix ? prefix + "/" : ""); | |
| const moderator = isModerator; | |
| return { | |
| baseUrl, | |
| languages, | |
| language, | |
| translations, | |
| configuration, | |
| moderator, | |
| }; | |
| } | |
| serve(request, response, isModerator) { | |
| const parsedUrl = url.parse(request.url, true); | |
| const parameters = this.parameters(parsedUrl, request, isModerator); | |
| var body = this.template(parameters); | |
| var headers = { | |
| "Content-Length": Buffer.byteLength(body), | |
| "Content-Type": "text/html", | |
| "Cache-Control": "public, max-age=3600", | |
| }; | |
| if (!parsedUrl.query.lang) { | |
| headers["Vary"] = "Accept-Language"; | |
| } | |
| response.writeHead(200, headers); | |
| response.end(body); | |
| } | |
| } | |
| class BoardTemplate extends Template { | |
| parameters(parsedUrl, request, isModerator) { | |
| const params = super.parameters(parsedUrl, request, isModerator); | |
| const parts = parsedUrl.pathname.split("boards/", 2); | |
| const boardUriComponent = parts[1]; | |
| params["boardUriComponent"] = boardUriComponent; | |
| params["board"] = decodeURIComponent(boardUriComponent); | |
| params["hideMenu"] = parsedUrl.query.hideMenu == "true" || false; | |
| return params; | |
| } | |
| } | |
| module.exports = { Template, BoardTemplate }; | |