"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"); // via https://stackoverflow.com/a/6248722/165668 function generateUID() { let firstPart = (Math.random() * 46656) | 0; // eslint-disable-line no-bitwise let secondPart = (Math.random() * 46656) | 0; // eslint-disable-line no-bitwise firstPart = ("000" + firstPart.toString(36)).slice(-3); secondPart = ("000" + secondPart.toString(36)).slice(-3); return firstPart + secondPart; } 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_id) { buffer.push( `` ); } if (bootstrap.theme_color) { 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}"`); } if (s.class) { attrs.push(`class="${s.class}"`); } let link = ``; 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, headers) { buffer.push(bootstrap.theme_html.body_tag); buffer.push(bootstrap.html.before_body_close); let v = generateUID(); buffer.push(` `); } 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, body, "hidden-login-form": hiddenLoginForm, preloaded, "body-footer": bodyFooter, "locale-script": localeScript, }; function replaceIn(bootstrap, template, id, headers) { let buffer = []; BUILDERS[id](buffer, bootstrap, headers); let contents = buffer.filter((b) => b && b.length > 0).join("\n"); return template.replace(`${e.toString()}
`);
}
}
}
module.exports = {
name: require("./package").name,
isDevelopingAddon() {
return true;
},
serverMiddleware(config) {
let proxy = config.options.proxy;
let app = config.app;
let options = config.options;
if (!proxy) {
// eslint-disable-next-line
console.error(`
Discourse can't be run without a \`--proxy\` setting, because it needs a Rails application
to serve API requests. For example:
yarn run ember serve --proxy "http://localhost:3000"\n`);
throw "--proxy argument is required";
}
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) {}
if (!isFile) {
assetPath = "index.html";
}
await handleRequest(assetPath, proxy, baseURL, req, res);
}
} finally {
if (!res.headersSent) {
return next();
}
}
});
},
shouldHandleRequest(req) {
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;
}
if (req.path.endsWith(".json")) {
return false;
}
let baseURLRegexp = new RegExp(`^/`);
return baseURLRegexp.test(req.path);
},
};