mirror of
https://github.com/discourse/discourse.git
synced 2026-08-09 21:45:25 +08:00
We were correctly un-colocating files in the root `templates/` directory, but the regex didn't allow for `discourse/template/...`. https://meta.discourse.org/t/398882
139 lines
4.1 KiB
JavaScript
Vendored
139 lines
4.1 KiB
JavaScript
Vendored
import { federatedExportNameFor } from "./federated-modules-helper";
|
|
|
|
const SUPPORTED_FILE_EXTENSIONS = [".js", ".js.es6", ".hbs", ".gjs"];
|
|
|
|
const IS_CONNECTOR_REGEX = /(^|\/)connectors\//;
|
|
|
|
export default {
|
|
"virtual:entrypoint": async (
|
|
moduleFilenames,
|
|
{ themeId },
|
|
{ basePath, context }
|
|
) => {
|
|
let output = `const compatModules = {};`;
|
|
|
|
if (themeId) {
|
|
output += cleanMultiline(`
|
|
import "virtual:init-settings";
|
|
`);
|
|
}
|
|
|
|
const moduleFilenamesSet = new Set(moduleFilenames);
|
|
const exportedModules = new Set();
|
|
|
|
let i = 1;
|
|
for (const moduleFilename of moduleFilenames) {
|
|
if (
|
|
!SUPPORTED_FILE_EXTENSIONS.some((ext) => moduleFilename.endsWith(ext))
|
|
) {
|
|
// Unsupported file type. Log a warning and skip
|
|
output += `console.warn("[THEME ${themeId}] Unsupported file type: ${moduleFilename}");\n`;
|
|
continue;
|
|
}
|
|
|
|
const filenameWithoutExtension = moduleFilename.replace(
|
|
/\.[^\.]+(\.es6)?$/,
|
|
""
|
|
);
|
|
|
|
let compatModuleName = filenameWithoutExtension;
|
|
|
|
if (moduleFilename.match(IS_CONNECTOR_REGEX)) {
|
|
const isTemplate = moduleFilename.endsWith(".hbs");
|
|
const isInTemplatesDirectory =
|
|
moduleFilename.match(/(^|\/)templates\//);
|
|
|
|
if (isTemplate && !isInTemplatesDirectory) {
|
|
compatModuleName = compatModuleName.replace(
|
|
IS_CONNECTOR_REGEX,
|
|
"$1templates/connectors/"
|
|
);
|
|
} else if (!isTemplate && isInTemplatesDirectory) {
|
|
compatModuleName = compatModuleName.replace(
|
|
/(^|\/)templates\//,
|
|
"$1"
|
|
);
|
|
}
|
|
}
|
|
|
|
const importPath = filenameWithoutExtension.match(IS_CONNECTOR_REGEX)
|
|
? moduleFilename
|
|
: filenameWithoutExtension;
|
|
|
|
if (exportedModules.has(importPath)) {
|
|
continue;
|
|
}
|
|
exportedModules.add(importPath);
|
|
|
|
output += `import * as Mod${i} from "./${importPath}";\n`;
|
|
output += `compatModules["${compatModuleName}"] = Mod${i};\n\n`;
|
|
|
|
const resolvedId = await context.resolve(
|
|
`./${importPath}`,
|
|
`${basePath}virtual:main`
|
|
);
|
|
const loadedModule = await context.load(resolvedId);
|
|
|
|
const reexportPairs = loadedModule.exports.map((exportedName) => {
|
|
return `${exportedName} as ${federatedExportNameFor(compatModuleName, exportedName)}`;
|
|
});
|
|
|
|
const isIndexModule =
|
|
compatModuleName.endsWith("/index") &&
|
|
!moduleFilenamesSet.has(moduleFilename.replace("/index", ""));
|
|
|
|
if (isIndexModule) {
|
|
loadedModule.exports.forEach((exportedName) => {
|
|
const federatedExportName = federatedExportNameFor(
|
|
compatModuleName.replace(/\/index$/, ""),
|
|
exportedName
|
|
);
|
|
reexportPairs.push(`${exportedName} as ${federatedExportName}`);
|
|
});
|
|
}
|
|
|
|
output += `export * as ${federatedExportNameFor(compatModuleName, "*")} from "./${importPath}";\n`;
|
|
output += `export {\n${reexportPairs.join(",\n")}\n} from "./${importPath}";\n`;
|
|
|
|
i += 1;
|
|
}
|
|
|
|
output += "export default compatModules;\n";
|
|
|
|
return output;
|
|
},
|
|
"virtual:init-settings": ({ themeId, settings }) => {
|
|
return (
|
|
`import { registerSettings } from "discourse/lib/theme-settings-store";\n\n` +
|
|
`registerSettings(${themeId}, ${JSON.stringify(settings, null, 2)});\n`
|
|
);
|
|
},
|
|
"virtual:theme": ({ themeId }) => {
|
|
return cleanMultiline(`
|
|
import { getObjectForTheme } from "discourse/lib/theme-settings-store";
|
|
|
|
export const settings = getObjectForTheme(${themeId});
|
|
|
|
export function themePrefix(key) {
|
|
return \`theme_translations.${themeId}.\${key}\`;
|
|
}
|
|
`);
|
|
},
|
|
};
|
|
|
|
function cleanMultiline(str) {
|
|
const lines = str.split("\n");
|
|
|
|
if (lines.at(0).trim() === "") {
|
|
lines.shift();
|
|
}
|
|
if (lines.at(-1).trim() === "") {
|
|
lines.pop();
|
|
}
|
|
|
|
const minLeadingWhitspace = Math.min(
|
|
...lines.filter(Boolean).map((line) => line.match(/^\s*/)[0].length)
|
|
);
|
|
|
|
return lines.map((line) => line.slice(minLeadingWhitspace)).join("\n") + "\n";
|
|
}
|