"use strict"; const bent = require("bent"); const getJSON = bent("json"); const { encode } = require("html-entities"); const cleanBaseURL = require("clean-base-url"); const path = require("path"); const fs = require("fs"); const IGNORE_PATHS = [ /\/ember-cli-live-reload\.js$/, /\/session\/[^\/]+\/become$/, ]; function htmlTag(buffer, bootstrap) { let classList = ""; if (bootstrap.html_classes) { classList = ` class="${bootstrap.html_classes}"`; } buffer.push(``); } function head(buffer, bootstrap) { if (bootstrap.csrf_token) { buffer.push(``); buffer.push(``); } if (bootstrap.theme_ids) { buffer.push( `` ); } let setupData = ""; Object.keys(bootstrap.setup_data).forEach((sd) => { let val = bootstrap.setup_data[sd]; if (val) { if (Array.isArray(val)) { val = JSON.stringify(val); } else { val = val.toString(); } setupData += ` data-${sd.replace(/\_/g, "-")}="${encode(val)}"`; } }); buffer.push(``); (bootstrap.stylesheets || []).forEach((s) => { let attrs = []; if (s.media) { attrs.push(`media="${s.media}"`); } if (s.target) { attrs.push(`data-target="${s.target}"`); } if (s.theme_id) { attrs.push(`data-theme-id="${s.theme_id}"`); } let link = `\n`; buffer.push(link); }); bootstrap.plugin_js.forEach((src) => buffer.push(``) ); buffer.push(bootstrap.theme_html.translations); buffer.push(bootstrap.theme_html.js); buffer.push(bootstrap.theme_html.head_tag); buffer.push(bootstrap.html.before_head_close); } function localeScript(buffer, bootstrap) { buffer.push(``); } function beforeScriptLoad(buffer, bootstrap) { buffer.push(bootstrap.html.before_script_load); localeScript(buffer, bootstrap); (bootstrap.extra_locales || []).forEach((l) => buffer.push(``) ); } function body(buffer, bootstrap) { buffer.push(bootstrap.theme_html.header); buffer.push(bootstrap.html.header); } function bodyFooter(buffer, bootstrap) { buffer.push(bootstrap.theme_html.body_tag); buffer.push(bootstrap.html.before_body_close); } function hiddenLoginForm(buffer, bootstrap) { if (!bootstrap.preloaded.currentUser) { buffer.push(` `); } } function preloaded(buffer, bootstrap) { buffer.push( `` ); } const BUILDERS = { "html-tag": htmlTag, "before-script-load": beforeScriptLoad, head: head, body: body, "hidden-login-form": hiddenLoginForm, preloaded: preloaded, "body-footer": bodyFooter, "locale-script": localeScript, }; function replaceIn(bootstrap, template, id) { let buffer = []; BUILDERS[id](buffer, bootstrap); let contents = buffer.filter((b) => b && b.length > 0).join("\n"); return template.replace(``, contents); } function applyBootstrap(bootstrap, template) { Object.keys(BUILDERS).forEach((id) => { template = replaceIn(bootstrap, template, id); }); return template; } function decorateIndex(assetPath, baseUrl, headers) { // eslint-disable-next-line return new Promise((resolve, reject) => { fs.readFile( path.join(process.cwd(), "dist", assetPath), "utf8", (err, template) => { getJSON(`${baseUrl}/bootstrap.json`, null, headers) .then((json) => { resolve(applyBootstrap(json.bootstrap, template)); }) .catch(() => { reject(`Could not get ${baseUrl}/bootstrap.json`); }); } ); }); } module.exports = { name: require("./package").name, isDevelopingAddon() { return true; }, serverMiddleware(config) { let proxy = config.options.proxy; let app = config.app; let options = config.options; let watcher = options.watcher; let baseURL = options.rootURL === "" ? "/" : cleanBaseURL(options.rootURL || options.baseURL); app.use(async (req, res, next) => { try { const results = await watcher; if (this.shouldHandleRequest(req, options)) { let assetPath = req.path.slice(baseURL.length); let isFile = false; try { isFile = fs .statSync(path.join(results.directory, assetPath)) .isFile(); } catch (err) { /* ignore */ } if (!isFile) { assetPath = "index.html"; } if (assetPath.endsWith("index.html")) { let template; try { template = await decorateIndex(assetPath, proxy, req.headers); } catch (e) { template = `

Discourse Build Error

${e.toString()}

`; } return res.send(template); } } } finally { next(); } }); }, shouldHandleRequest(req, options) { let acceptHeaders = req.headers.accept || []; let hasHTMLHeader = acceptHeaders.indexOf("text/html") !== -1; if (req.method !== "GET") { return false; } if (!hasHTMLHeader) { return false; } if (IGNORE_PATHS.some((ip) => ip.test(req.path))) { return false; } let baseURL = options.rootURL === "" ? "/" : cleanBaseURL(options.rootURL || options.baseURL); let baseURLRegexp = new RegExp(`^${baseURL}`); return baseURLRegexp.test(req.path); }, };