This commit is contained in:
David Taylor 2024-12-08 12:14:56 +00:00
parent b7e31cb380
commit 7acf16ebc8
No known key found for this signature in database
GPG Key ID: 46904C18B1D3F434
29 changed files with 8094 additions and 2523 deletions

View File

@ -4,9 +4,6 @@
"description": "Discourse's admin section",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"scripts": {
"build": "ember build",
"lint:hbs": "ember-template-lint .",
@ -16,7 +13,7 @@
"dependencies": {
"@babel/core": "^7.26.0",
"@ember/string": "^4.0.0",
"discourse-common": "workspace:1.0.0",
"discourse-common": "workspace:*",
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.3.0",
"ember-template-imports": "^4.2.0"
@ -46,8 +43,5 @@
"npm": "please-use-pnpm",
"yarn": "please-use-pnpm",
"pnpm": ">= 9"
},
"ember": {
"edition": "default"
}
}

View File

@ -4,22 +4,10 @@
"description": "Express.js middleware which injects ember-cli asset URLs into Discourse's HTML",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"ember-addon": {
"before": [
"broccoli-serve-files",
"proxy-server-middleware"
],
"after": [
"broccoli-watcher"
]
},
"devDependencies": {
"clean-base-url": "^1.0.0",
"express": "^4.21.1",
"glob": "^10.4.3",
"express": "^4.21.2",
"glob": "^10.4.5",
"html-entities": "^2.5.2",
"html-rewriter-wasm": "^0.4.1",
"node-fetch": "^3.3.2"

View File

@ -4,16 +4,13 @@
"description": "TODO",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"dependencies": {
"a11y-dialog": "8.1.1",
"ember-auto-import": "^2.10.0",
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.3.0",
"ember-template-imports": "^4.2.0",
"truth-helpers": "workspace:1.0.0"
"truth-helpers": "workspace:*"
},
"devDependencies": {
"@types/jquery": "^3.5.32",

View File

@ -1,4 +1,3 @@
import require from "require";
import { consolePrefix } from "discourse/lib/source-identifier";
import deprecated from "discourse-common/lib/deprecated";
import { getResolverOption } from "discourse-common/resolver";

View File

@ -4,9 +4,6 @@
"description": "Shared code between discourse apps",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"scripts": {
"build": "ember build",
"lint:hbs": "ember-template-lint .",
@ -14,15 +11,16 @@
"start": "ember serve"
},
"dependencies": {
"virtual-dom": "^2.1.1",
"@babel/core": "^7.26.0",
"@ember/string": "^4.0.0",
"discourse-i18n": "workspace:1.0.0",
"discourse-i18n": "workspace:*",
"ember-auto-import": "^2.10.0",
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.3.0",
"ember-resolver": "^13.1.0",
"handlebars": "^4.7.8",
"truth-helpers": "workspace:1.0.0"
"truth-helpers": "workspace:*"
},
"devDependencies": {
"@ember/optional-features": "^2.2.0",
@ -41,15 +39,14 @@
"ember-source": "~5.12.0",
"ember-source-channel-url": "^3.0.0",
"loader.js": "^4.7.0",
"webpack": "^5.97.1"
"webpack": "^5.97.1",
"@ember-decorators/component": "^6.1.1",
"@ember-decorators/object": "^6.1.1"
},
"engines": {
"node": ">= 18",
"npm": "please-use-pnpm",
"yarn": "please-use-pnpm",
"pnpm": ">= 9"
},
"ember": {
"edition": "default"
}
}

View File

@ -19,12 +19,12 @@
],
"dependencies": {
"@embroider/addon-shim": "^1.9.0",
"discourse-common": "workspace:1.0.0",
"discourse-i18n": "workspace:1.0.0",
"discourse-common": "workspace:*",
"discourse-i18n": "workspace:*",
"ember-auto-import": "^2.10.0",
"markdown-it": "14.0.0",
"pretty-text": "workspace:1.0.0",
"truth-helpers": "workspace:1.0.0",
"pretty-text": "workspace:*",
"truth-helpers": "workspace:*",
"xss": "^1.0.15"
},
"peerDependencies": {

View File

@ -4,14 +4,11 @@
"description": "An addon providing a broccoli tree for each Discourse plugin",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"dependencies": {
"@babel/core": "^7.26.0",
"deprecation-silencer": "workspace:1.0.0",
"discourse-hbr": "workspace:1.0.0",
"discourse-widget-hbs": "workspace:1.0.0",
"deprecation-silencer": "workspace:*",
"discourse-hbr": "workspace:*",
"discourse-widget-hbs": "workspace:*",
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.3.0",
"ember-template-imports": "^4.2.0",
@ -26,8 +23,5 @@
"npm": "please-use-pnpm",
"yarn": "please-use-pnpm",
"pnpm": ">= 9"
},
"ember": {
"edition": "default"
}
}

View File

@ -4,9 +4,7 @@
"description": "Support for Discourse's inline `hbs` compiler for widgets",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"scripts": {
"build": "ember build",
"lint:hbs": "ember-template-lint .",
@ -43,8 +41,5 @@
"npm": "please-use-pnpm",
"yarn": "please-use-pnpm",
"pnpm": ">= 9"
},
"ember": {
"edition": "default"
}
}

View File

@ -1,6 +1,13 @@
import "./deprecation-workflow";
import "decorator-transforms/globals";
import "./loader";
import "./loader-shims";
import "./more-loader-shims";
// import compatModules from "@embroider/virtual/compat-modules";
// for (const [path, module] of Object.entries(compatModules)) {
// window.define(path, [], () => module);
// }
import "./global-compat";
import { registerDiscourseImplicitInjections } from "discourse/lib/implicit-injections";
@ -9,7 +16,7 @@ registerDiscourseImplicitInjections();
import Application from "@ember/application";
import { VERSION } from "@ember/version";
import require from "require";
// import require from "require";
import { normalizeEmberEventHandling } from "discourse/lib/ember-events";
import { withPluginApi } from "discourse/lib/plugin-api";
import { isTesting } from "discourse-common/config/environment";
@ -100,6 +107,7 @@ function loadInitializers(app) {
let discourseInstanceInitializers = [];
for (let moduleName of Object.keys(requirejs.entries)) {
console.log(moduleName);
if (moduleName.startsWith("discourse/") && !moduleName.endsWith("-test")) {
// In discourse core, initializers follow standard Ember conventions
if (moduleName.startsWith("discourse/initializers/")) {
@ -242,6 +250,9 @@ function printDebugInfo() {
}
export default Discourse;
import environment from "./config/environment";
const app = Discourse.create({ ...environment.APP });
app.start();
/**
* @typedef {import('ember-source/types')} EmberTypes

View File

@ -0,0 +1,5 @@
import loadConfigFromMeta from "@embroider/config-meta-loader";
console.log(loadConfigFromMeta("discourse"));
export default loadConfigFromMeta("discourse");

View File

@ -2,7 +2,7 @@ import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { hash } from "@ember/helper";
import { action } from "@ember/object";
import DMenu from "discourse/components/d-menu";
import DMenu from "float-kit/components/d-menu";
import DropdownMenu from "discourse/components/dropdown-menu";
import FKControlMenuContainer from "discourse/form-kit/components/fk/control/menu/container";
import FKControlMenuDivider from "discourse/form-kit/components/fk/control/menu/divider";

View File

@ -1,24 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<!--
👋 Greetings Discourse Developer. This html file is used by ember-cli/embroider to define our JS entrypoints,
but it is never actually used in development or production. Instead, we generate an `assets.json` file which
is ingested by Rails and used to generate the correct <script> tags.
When ember-cli is used as a proxy, we use the rails-generated HTML and replace urls in script/link tags
with the local ember-cli versions.
-->
<meta charset="utf-8">
<title>Discourse - Ember CLI</title>
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css" />
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/discourse.css" />
<script defer src="{{rootURL}}assets/vendor.js"></script>
<script defer src="{{rootURL}}assets/discourse.js"></script>
</head>
<body>
</body>
</html>

View File

@ -10,9 +10,7 @@ loaderShim("@ember-compat/tracked-built-ins", () =>
loaderShim("@popperjs/core", () => importSync("@popperjs/core"));
loaderShim("@floating-ui/dom", () => importSync("@floating-ui/dom"));
loaderShim("@uppy/aws-s3", () => importSync("@uppy/aws-s3"));
loaderShim("@uppy/aws-s3-multipart", () =>
importSync("@uppy/aws-s3-multipart")
);
loaderShim("@uppy/core", () => importSync("@uppy/core"));
loaderShim("@uppy/drop-target", () => importSync("@uppy/drop-target"));
loaderShim("@uppy/utils/lib/AbortController", () =>

View File

@ -0,0 +1,347 @@
function dict() {
var obj = Object.create(null);
obj['__'] = undefined;
delete obj['__'];
return obj;
}
// Save off the original values of these globals, so we can restore them if someone asks us to
// var oldGlobals = {
// loader: loader,
// define: define,
// requireModule: requireModule,
// require: require,
// requirejs: requirejs,
// };
window.requirejs =
window.require =
window.requireModule =
function (id) {
var pending = [];
var mod = findModule(id, '(require)', pending);
for (var i = pending.length - 1; i >= 0; i--) {
pending[i].exports();
}
return mod.module.exports;
};
window.loader = {
noConflict: function (aliases) {
// var oldName, newName;
// for (oldName in aliases) {
// if (aliases.hasOwnProperty(oldName)) {
// if (oldGlobals.hasOwnProperty(oldName)) {
// newName = aliases[oldName];
// global[newName] = global[oldName];
// global[oldName] = oldGlobals[oldName];
// }
// }
// }
},
// Option to enable or disable the generation of default exports
makeDefaultExport: true,
};
var registry = dict();
var seen = dict();
var uuid = 0;
function unsupportedModule(length) {
throw new Error(
'an unsupported module was defined, expected `define(id, deps, module)` instead got: `' +
length +
'` arguments to define`'
);
}
var defaultDeps = ['require', 'exports', 'module'];
function Module(id, deps, callback, alias) {
this.uuid = uuid++;
this.id = id;
this.deps = !deps.length && callback.length ? defaultDeps : deps;
this.module = { exports: {} };
this.callback = callback;
this.hasExportsAsDep = false;
this.isAlias = alias;
this.reified = new Array(deps.length);
/*
Each module normally passes through these states, in order:
new : initial state
pending : this module is scheduled to be executed
reifying : this module's dependencies are being executed
reified : this module's dependencies finished executing successfully
errored : this module's dependencies failed to execute
finalized : this module executed successfully
*/
this.state = 'new';
}
Module.prototype.makeDefaultExport = function () {
var exports = this.module.exports;
if (
exports !== null &&
(typeof exports === 'object' || typeof exports === 'function') &&
exports['default'] === undefined &&
Object.isExtensible(exports)
) {
exports['default'] = exports;
}
};
Module.prototype.exports = function () {
// if finalized, there is no work to do. If reifying, there is a
// circular dependency so we must return our (partial) exports.
if (this.state === 'finalized' || this.state === 'reifying') {
return this.module.exports;
}
if (window.loader.wrapModules) {
this.callback = window.loader.wrapModules(this.id, this.callback);
}
this.reify();
var result = this.callback.apply(this, this.reified);
this.reified.length = 0;
this.state = 'finalized';
if (!(this.hasExportsAsDep && result === undefined)) {
this.module.exports = result;
}
if (window.loader.makeDefaultExport) {
this.makeDefaultExport();
}
return this.module.exports;
};
Module.prototype.unsee = function () {
this.state = 'new';
this.module = { exports: {} };
};
Module.prototype.reify = function () {
if (this.state === 'reified') {
return;
}
this.state = 'reifying';
try {
this.reified = this._reify();
this.state = 'reified';
} finally {
if (this.state === 'reifying') {
this.state = 'errored';
}
}
};
Module.prototype._reify = function () {
var reified = this.reified.slice();
for (var i = 0; i < reified.length; i++) {
var mod = reified[i];
reified[i] = mod.exports ? mod.exports : mod.module.exports();
}
return reified;
};
Module.prototype.findDeps = function (pending) {
if (this.state !== 'new') {
return;
}
this.state = 'pending';
var deps = this.deps;
for (var i = 0; i < deps.length; i++) {
var dep = deps[i];
var entry = (this.reified[i] = { exports: undefined, module: undefined });
if (dep === 'exports') {
this.hasExportsAsDep = true;
entry.exports = this.module.exports;
} else if (dep === 'require') {
entry.exports = this.makeRequire();
} else if (dep === 'module') {
entry.exports = this.module;
} else {
entry.module = findModule(resolve(dep, this.id), this.id, pending);
}
}
};
Module.prototype.makeRequire = function () {
var id = this.id;
var r = function (dep) {
return window.require(resolve(dep, id));
};
r['default'] = r;
r.moduleId = id;
r.has = function (dep) {
return has(resolve(dep, id));
};
return r;
};
window.define = function (id, deps, callback) {
var module = registry[id];
// If a module for this id has already been defined and is in any state
// other than `new` (meaning it has been or is currently being required),
// then we return early to avoid redefinition.
if (module && module.state !== 'new') {
return;
}
if (arguments.length < 2) {
unsupportedModule(arguments.length);
}
if (!Array.isArray(deps)) {
callback = deps;
deps = [];
}
if (callback instanceof Alias) {
registry[id] = new Module(callback.id, deps, callback, true);
} else {
registry[id] = new Module(id, deps, callback, false);
}
};
window.define.exports = function (name, defaultExport) {
var module = registry[name];
// If a module for this name has already been defined and is in any state
// other than `new` (meaning it has been or is currently being required),
// then we return early to avoid redefinition.
if (module && module.state !== 'new') {
return;
}
module = new Module(name, [], noop, null);
module.module.exports = defaultExport;
module.state = 'finalized';
registry[name] = module;
return module;
};
function noop() {}
// we don't support all of AMD
// define.amd = {};
function Alias(id) {
this.id = id;
}
window.define.alias = function (id, target) {
if (arguments.length === 2) {
return window.define(target, new Alias(id));
}
return new Alias(id);
};
function missingModule(id, referrer) {
throw new Error(
'Could not find module `' + id + '` imported from `' + referrer + '`'
);
}
function findModule(id, referrer, pending) {
var mod = registry[id] || registry[id + '/index'];
while (mod && mod.isAlias) {
mod = registry[mod.id] || registry[mod.id + '/index'];
}
if (!mod) {
missingModule(id, referrer);
}
if (pending && mod.state !== 'pending' && mod.state !== 'finalized') {
mod.findDeps(pending);
pending.push(mod);
}
return mod;
}
function resolve(child, id) {
if (child.charAt(0) !== '.') {
return child;
}
var parts = child.split('/');
var nameParts = id.split('/');
var parentBase = nameParts.slice(0, -1);
for (var i = 0, l = parts.length; i < l; i++) {
var part = parts[i];
if (part === '..') {
if (parentBase.length === 0) {
throw new Error('Cannot access parent module of root');
}
parentBase.pop();
} else if (part === '.') {
continue;
} else {
parentBase.push(part);
}
}
return parentBase.join('/');
}
function has(id) {
return !!(registry[id] || registry[id + '/index']);
}
window.requirejs.entries = window.requirejs._eak_seen = registry;
window.requirejs.has = has;
window.requirejs.unsee = function (id) {
findModule(id, '(unsee)', false).unsee();
};
window.requirejs.clear = function () {
window.requirejs.entries = window.requirejs._eak_seen = registry = dict();
seen = dict();
};
// This code primes the JS engine for good performance by warming the
// JIT compiler for these functions.
// define('foo', function () {});
// define('foo/bar', [], function () {});
// define('foo/asdf', ['module', 'exports', 'require'], function (
// module,
// exports,
// require
// ) {
// if (require.has('foo/bar')) {
// require('foo/bar');
// }
// });
// define('foo/baz', [], define.alias('foo'));
// define('foo/quz', define.alias('foo'));
// define.alias('foo', 'foo/qux');
// define('foo/bar', [
// 'foo',
// './quz',
// './baz',
// './asdf',
// './bar',
// '../foo',
// ], function () {});
// define('foo/main', ['foo/bar'], function () {});
// define.exports('foo/exports', {});
// require('foo/exports');
// require('foo/main');
// require.unsee('foo/bar');
requirejs.clear();

View File

@ -0,0 +1,22 @@
import compatModules from "@embroider/virtual/compat-modules";
const seenNames = new Set();
for (const [path, module] of Object.entries(
import.meta.glob("./**/*.{gjs,js}", { eager: true })
)) {
const name = path.replace("./", "discourse/").replace(/\.g?js/, "");
seenNames.add(name);
window.define(name, [], () => module);
}
for (const [path, module] of Object.entries(
import.meta.glob("./**/*.hbs", { eager: true })
)) {
const name = path.replace("./", "discourse/").replace(/\.hbs/, "");
if (seenNames.has(name)) {
continue;
}
seenNames.add(name);
window.define(name, [], () => module);
}

View File

@ -0,0 +1,42 @@
const {
babelCompatSupport,
templateCompatSupport,
} = require('@embroider/compat/babel');
module.exports = {
plugins: [
[
'babel-plugin-ember-template-compilation',
{
compilerPath: 'ember-source/dist/ember-template-compiler.js',
enableLegacyModules: [
'ember-cli-htmlbars',
'ember-cli-htmlbars-inline-precompile',
'htmlbars-inline-precompile',
],
transforms: [...templateCompatSupport()],
},
],
[
'module:decorator-transforms',
{
runtime: {
import: require.resolve('decorator-transforms/runtime-esm'),
},
},
],
[
'@babel/plugin-transform-runtime',
{
absoluteRuntime: __dirname,
useESModules: true,
regenerator: false,
},
],
...babelCompatSupport(),
],
generatorOpts: {
compact: false,
},
};

View File

@ -1,253 +1,13 @@
"use strict";
const EmberApp = require("ember-cli/lib/broccoli/ember-app");
const path = require("path");
const mergeTrees = require("broccoli-merge-trees");
const concat = require("broccoli-concat");
const { createI18nTree } = require("./lib/translation-plugin");
const { parsePluginClientSettings } = require("./lib/site-settings-plugin");
const discourseScss = require("./lib/discourse-scss");
const generateScriptsTree = require("./lib/scripts");
const funnel = require("broccoli-funnel");
const DeprecationSilencer = require("deprecation-silencer");
const { compatBuild } = require("@embroider/compat");
const { Webpack } = require("@embroider/webpack");
const { StatsWriterPlugin } = require("webpack-stats-plugin");
const { RetryChunkLoadPlugin } = require("webpack-retry-chunk-load-plugin");
const withSideWatch = require("./lib/with-side-watch");
const RawHandlebarsCompiler = require("discourse-hbr/raw-handlebars-compiler");
const crypto = require("crypto");
const commonBabelConfig = require("./lib/common-babel-config");
const TerserPlugin = require("terser-webpack-plugin");
process.env.BROCCOLI_ENABLED_MEMOIZE = true;
const { maybeEmbroider } = require("@embroider/test-setup");
module.exports = function (defaults) {
const discourseRoot = path.resolve("../../../..");
const vendorJs = discourseRoot + "/vendor/assets/javascripts/";
let app = new EmberApp(defaults, {});
// Silence deprecations which we are aware of - see `lib/deprecation-silencer.js`
DeprecationSilencer.silence(console, "warn");
DeprecationSilencer.silence(defaults.project.ui, "writeWarnLine");
const isProduction = EmberApp.env().includes("production");
const app = new EmberApp(defaults, {
autoRun: false,
"ember-qunit": {
insertContentForTestBody: false,
},
sourcemaps: {
// There seems to be a bug with broccoli-concat when sourcemaps are disabled
// that causes the `app.import` statements below to fail in production mode.
// This forces the use of `fast-sourcemap-concat` which works in production.
enabled: true,
},
fingerprint: {
// Handled by Rails asset pipeline
enabled: false,
},
SRI: {
// We don't use SRI in Rails. Disable here to match:
enabled: false,
},
"ember-cli-deprecation-workflow": {
enabled: true,
},
"ember-cli-terser": {
enabled: isProduction,
exclude: ["**/highlightjs/*", "**/javascripts/*"],
},
...commonBabelConfig(),
vendorFiles: {
// Freedom patch - includes bug fix and async stack support
// https://github.com/discourse/backburner.js/commits/discourse-patches
backburner:
"node_modules/@discourse/backburner.js/dist/named-amd/backburner.js",
},
trees: {
app: RawHandlebarsCompiler(
withSideWatch("app", {
watching: ["../discourse-markdown-it", "../truth-helpers"],
})
),
},
return maybeEmbroider(app, {
staticComponents: false,
staticHelpers: false,
});
// WARNING: We should only import scripts here if they are not in NPM.
app.import(discourseRoot + "/app/assets/javascripts/polyfills.js");
app.import(
discourseRoot +
"/app/assets/javascripts/discourse/public/assets/scripts/module-shims.js"
);
const discoursePluginsTree = app.project
.findAddonByName("discourse-plugins")
.generatePluginsTree(app.tests);
const adminTree = app.project.findAddonByName("admin").treeForAddonBundle();
const testStylesheetTree = mergeTrees([
discourseScss(`${discourseRoot}/app/assets/stylesheets`, "qunit.scss"),
discourseScss(
`${discourseRoot}/app/assets/stylesheets`,
"qunit-custom.scss"
),
]);
app.project.liveReloadFilterPatterns = [/.*\.scss/];
const terserPlugin = app.project.findAddonByName("ember-cli-terser");
const applyTerser = (tree) => terserPlugin.postprocessTree("all", tree);
let extraPublicTrees = [
createI18nTree(discourseRoot, vendorJs),
parsePluginClientSettings(discourseRoot, vendorJs, app),
funnel(`${discourseRoot}/public/javascripts`, { destDir: "javascripts" }),
applyTerser(
concat(adminTree, {
inputFiles: ["**/*.js"],
outputFile: `assets/admin.js`,
})
),
applyTerser(generateScriptsTree(app)),
applyTerser(discoursePluginsTree),
testStylesheetTree,
];
const assetCachebuster = process.env["DISCOURSE_ASSET_URL_SALT"] || "";
const cachebusterHash = crypto
.createHash("md5")
.update(assetCachebuster)
.digest("hex")
.slice(0, 8);
const appTree = compatBuild(app, Webpack, {
staticEmberSource: true,
splitAtRoutes: ["wizard"],
staticAppPaths: ["static"],
packagerOptions: {
webpackConfig: {
devtool:
process.env.CHEAP_SOURCE_MAPS === "1"
? "cheap-source-map"
: "source-map",
output: {
publicPath: "auto",
filename: `assets/chunk.[chunkhash].${cachebusterHash}.js`,
chunkFilename: `assets/chunk.[chunkhash].${cachebusterHash}.js`,
},
optimization: {
minimize: isProduction,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.swcMinify,
terserOptions: {
compress: {
// Stop swc unwrapping 'unnecessary' IIFE wrappers which are added by Babel
// to workaround a bug in Safari 15 class fields.
inline: false,
reduce_funcs: false,
},
},
}),
],
},
cache: isProduction
? false
: {
type: "memory",
maxGenerations: 1,
},
entry: {
"assets/discourse.js/features/markdown-it.js": {
import: "./static/markdown-it",
dependOn: "assets/discourse.js",
runtime: false,
},
},
externals: [
function ({ request }, callback) {
if (
!request.includes("-embroider-implicit") &&
// TODO: delete special case for jquery when removing app.import() above
(request.startsWith("admin/") ||
request.startsWith("discourse/plugins/") ||
request.startsWith("discourse/theme-"))
) {
callback(null, request, "commonjs");
} else {
callback();
}
},
],
module: {
parser: {
javascript: {
exportsPresence: "error",
},
},
},
plugins: [
// The server use this output to map each asset to its chunks
new StatsWriterPlugin({
filename: "assets.json",
stats: {
all: false,
entrypoints: true,
},
transform({ entrypoints }) {
let names = Object.keys(entrypoints);
let output = {};
for (let name of names.sort()) {
let assets = entrypoints[name].assets.map(
(asset) => asset.name
);
let parent = names.find((parentName) =>
name.startsWith(parentName + "/")
);
if (parent) {
name = name.slice(parent.length + 1);
output[parent][name] = { assets };
} else {
output[name] = { assets };
}
}
return JSON.stringify(output, null, 2);
},
}),
new RetryChunkLoadPlugin({
retryDelay: 200,
maxRetries: 2,
chunks: ["assets/discourse.js"],
}),
],
},
},
skipBabel: [
{
package: "qunit",
},
{
package: "sinon",
},
{
package: "@json-editor/json-editor",
},
{
package: "ace-builds",
},
],
});
return mergeTrees([appTree, mergeTrees(extraPublicTrees)]);
};

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>AppTemplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{content-for "head"}}
<link integrity="" rel="stylesheet" href="/@embroider/virtual/vendor.css">
<link integrity="" rel="stylesheet" href="/assets/v2-app.css">
{{content-for "head-footer"}}
</head>
<body>
{{content-for "body"}}
<script src="/@embroider/virtual/vendor.js"></script>
<script type="module" src="/app/app.js"></script>
<div id="main"></div>
{{content-for "body-footer"}}
</body>
</html>

View File

@ -23,8 +23,8 @@
"@messageformat/runtime": "^3.0.1",
"ace-builds": "^1.36.5",
"decorator-transforms": "^2.3.0",
"discourse-hbr": "workspace:1.0.0",
"discourse-widget-hbs": "workspace:1.0.0",
"discourse-hbr": "workspace:*",
"discourse-widget-hbs": "workspace:*",
"ember-route-template": "^1.0.3",
"ember-tracked-storage-polyfill": "^1.0.0",
"handlebars": "^4.7.8",
@ -32,13 +32,13 @@
"immer": "^10.1.1",
"jspreadsheet-ce": "^4.15.0",
"morphlex": "^0.0.16",
"pretty-text": "workspace:1.0.0"
"pretty-text": "workspace:*"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@babel/standalone": "^7.26.4",
"@colors/colors": "^1.6.0",
"@discourse/backburner.js": "^2.7.1-0",
"@discourse/backburner.js": "2.7.1-0",
"@discourse/itsatrap": "^2.0.10",
"@ember-compat/tracked-built-ins": "^0.9.1",
"@ember/legacy-built-in-components": "^0.5.0",
@ -47,52 +47,54 @@
"@ember/string": "^4.0.0",
"@ember/test-helpers": "^4.0.4",
"@ember/test-waiters": "^3.1.0",
"@embroider/compat": "^3.7.0",
"@embroider/core": "^3.4.19",
"@embroider/macros": "^1.16.9",
"@embroider/router": "^2.1.8",
"@embroider/webpack": "^4.0.8",
"@embroider/compat": "3.7.1-unstable.35f48d4",
"@embroider/config-meta-loader": "0.0.1-unstable.35f48d4",
"@embroider/core": "3.4.20-unstable.35f48d4",
"@embroider/test-setup": "4.0.1-unstable.35f48d4",
"@embroider/vite": "0.2.2-unstable.35f48d4",
"@embroider/router": "2.1.9-unstable.b89b741",
"@floating-ui/dom": "^1.6.12",
"@glimmer/component": "^1.1.2",
"@glimmer/tracking": "^1.1.2",
"@popperjs/core": "^2.11.8",
"@rollup/plugin-babel": "^6.0.4",
"@swc/core": "^1.10.0",
"@types/jquery": "^3.5.32",
"@types/qunit": "^2.19.12",
"@types/rsvp": "^4.0.9",
"@uppy/aws-s3": "^4.1.0",
"@uppy/core": "^4.2.2",
"@uppy/aws-s3": "^4.1.3",
"@uppy/core": "^4.3.0",
"@uppy/drop-target": "3.0.1",
"@uppy/utils": "^6.0.3",
"@uppy/xhr-upload": "^4.2.1",
"@uppy/utils": "^6.0.5",
"@uppy/xhr-upload": "^4.2.3",
"a11y-dialog": "8.1.1",
"admin": "workspace:1.0.0",
"admin": "workspace:*",
"autosize": "^6.0.1",
"babel-import-util": "^3.0.0",
"babel-plugin-ember-template-compilation": "^2.3.0",
"bootstrap": "3.4.1",
"broccoli-asset-rev": "^3.0.0",
"custom-proxy": "workspace:1.0.0",
"custom-proxy": "workspace:*",
"deepmerge": "^4.3.1",
"deprecation-silencer": "workspace:1.0.0",
"dialog-holder": "workspace:1.0.0",
"discourse-common": "workspace:1.0.0",
"discourse-i18n": "workspace:1.0.0",
"discourse-markdown-it": "workspace:1.0.0",
"discourse-plugins": "workspace:1.0.0",
"deprecation-silencer": "workspace:*",
"dialog-holder": "workspace:*",
"discourse-common": "workspace:*",
"discourse-i18n": "workspace:*",
"discourse-markdown-it": "workspace:*",
"discourse-plugins": "workspace:*",
"ember-auto-import": "^2.10.0",
"ember-buffered-proxy": "^2.1.1",
"ember-cached-decorator-polyfill": "^1.0.2",
"ember-cli": "~6.0.1",
"ember-cli-app-version": "^7.0.0",
"ember-cli-babel": "^8.2.0",
"ember-cli-deprecation-workflow": "^3.0.2",
"ember-cli-htmlbars": "^6.3.0",
"ember-cli-inject-live-reload": "^2.1.0",
"ember-cli-progress-ci": "workspace:1.0.0",
"ember-cli-progress-ci": "workspace:*",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
"ember-decorators": "^6.1.1",
"@ember-decorators/component": "^6.1.1",
"@ember-decorators/object": "^6.1.1",
"ember-exam": "^9.0.0",
"ember-load-initializers": "^3.0.1",
"ember-modifier": "^4.2.0",
@ -101,7 +103,7 @@
"ember-source": "~5.12.0",
"ember-template-imports": "^4.2.0",
"ember-test-selectors": "^7.0.0",
"float-kit": "workspace:1.0.0",
"float-kit": "workspace:*",
"html-entities": "^2.5.2",
"imports-loader": "^5.0.0",
"jquery": "^3.7.1",
@ -111,17 +113,18 @@
"make-plural": "^7.4.0",
"message-bus-client": "^4.3.8",
"pretender": "^3.4.7",
"qunit": "^2.23.0",
"qunit": "^2.23.1",
"qunit-dom": "^3.4.0",
"sass": "^1.77.7",
"select-kit": "workspace:1.0.0",
"sass": "^1.82.0",
"select-kit": "workspace:*",
"sinon": "^19.0.2",
"source-map": "^0.7.4",
"terser": "^5.37.0",
"testem": "^3.15.2",
"truth-helpers": "workspace:1.0.0",
"truth-helpers": "workspace:*",
"util": "^0.12.5",
"virtual-dom": "^2.1.1",
"vite": "^5.4.11",
"webpack": "^5.97.1",
"webpack-retry-chunk-load-plugin": "^3.1.1",
"webpack-stats-plugin": "^1.1.3",
@ -135,5 +138,13 @@
},
"ember": {
"edition": "octane"
},
"ember-addon": {
"type": "app",
"version": 2
},
"exports": {
"./tests/*": "./tests/*",
"./*": "./app/*"
}
}

View File

@ -0,0 +1,86 @@
import { defineConfig } from "vite";
import {
resolver,
hbs,
scripts,
templateTag,
optimizeDeps,
compatPrebuild,
assets,
contentFor,
} from "@embroider/vite";
import { babel } from "@rollup/plugin-babel";
const extensions = [
".mjs",
".gjs",
".js",
".mts",
".gts",
".ts",
".hbs",
".json",
];
export default defineConfig(({ mode }) => {
return {
resolve: {
extensions,
alias: [
{ find: "discourse-common", replacement: "/../discourse-common/addon" },
{ find: "pretty-text", replacement: "/../pretty-text/addon" },
{
find: "discourse-widget-hbs",
replacement: "/../discourse-widget-hbs/addon",
},
{ find: "select-kit", replacement: "/../select-kit/addon" },
{ find: "float-kit", replacement: "/../float-kit/addon" },
{ find: "discourse", replacement: "/app" },
// { find: "@ember-decorators", replacement: "ember-decorators" },
],
},
plugins: [
hbs(),
templateTag(),
scripts(),
resolver(),
compatPrebuild(),
assets(),
contentFor(),
babel({
babelHelpers: "runtime",
extensions,
}),
],
optimizeDeps: {
...optimizeDeps(),
include: ["virtual-dom"],
},
server: {
port: 4200,
},
build: {
manifest: true,
outDir: "dist",
rollupOptions: {
input: {
main: "index.html",
...(shouldBuildTests(mode)
? { tests: "tests/index.html" }
: undefined),
},
output: {
manualChunks(id, { getModuleInfo }) {
if (id.includes("node_modules")) {
return "vendor";
}
},
},
},
},
};
});
function shouldBuildTests(mode) {
return mode !== "production" || process.env.FORCE_BUILD_TESTS;
}

View File

@ -3,8 +3,6 @@
"version": "1.0.0",
"description": "Provides output during the ember-cli build process for CI environments",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
]
"license": "GPL-2.0-only"
}

View File

@ -4,9 +4,6 @@
"description": "Discourse's floating panels component.",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"scripts": {
"build": "ember build",
"lint:hbs": "ember-template-lint .",
@ -19,10 +16,12 @@
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.3.0",
"ember-template-imports": "^4.2.0",
"truth-helpers": "workspace:1.0.0"
"truth-helpers": "workspace:*"
},
"devDependencies": {
"ember-modifier": "^4.2.0",
"@ember/optional-features": "^2.2.0",
"@ember/render-modifiers": "^2.1.0",
"@embroider/test-setup": "^4.0.0",
"@glimmer/component": "^1.1.2",
"@types/jquery": "^3.5.32",
@ -39,15 +38,13 @@
"ember-source": "~5.12.0",
"ember-source-channel-url": "^3.0.0",
"loader.js": "^4.7.0",
"webpack": "^5.97.1"
"webpack": "^5.97.1",
"@floating-ui/dom": "^1.6.12"
},
"engines": {
"node": ">= 18",
"npm": "please-use-pnpm",
"yarn": "please-use-pnpm",
"pnpm": ">= 9"
},
"ember": {
"edition": "default"
}
}

View File

@ -4,9 +4,6 @@
"description": "Discourse's text rendering utilities",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"scripts": {
"build": "ember build",
"lint:hbs": "ember-template-lint .",
@ -15,8 +12,8 @@
},
"dependencies": {
"@babel/core": "^7.26.0",
"discourse-common": "workspace:1.0.0",
"discourse-i18n": "workspace:1.0.0",
"discourse-common": "workspace:*",
"discourse-i18n": "workspace:*",
"ember-auto-import": "^2.10.0",
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.3.0",
@ -47,8 +44,5 @@
"npm": "please-use-pnpm",
"yarn": "please-use-pnpm",
"pnpm": ">= 9"
},
"ember": {
"edition": "default"
}
}

View File

@ -4,9 +4,6 @@
"description": "Discourse's select widget",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"scripts": {
"build": "ember build",
"lint:hbs": "ember-template-lint .",
@ -16,7 +13,7 @@
"dependencies": {
"@babel/core": "^7.26.0",
"@ember/string": "^4.0.0",
"discourse-i18n": "workspace:1.0.0",
"discourse-i18n": "workspace:*",
"ember-auto-import": "^2.10.0",
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.3.0",
@ -40,15 +37,19 @@
"ember-source": "~5.12.0",
"ember-source-channel-url": "^3.0.0",
"loader.js": "^4.7.0",
"webpack": "^5.97.1"
"webpack": "^5.97.1",
"@popperjs/core": "^2.11.8",
"@ember-decorators/component": "^6.1.1",
"@ember-decorators/object": "^6.1.1",
"ember-cached-decorator-polyfill": "^1.0.2",
"jquery": "^3.7.1"
},
"engines": {
"node": ">= 18",
"npm": "please-use-pnpm",
"yarn": "please-use-pnpm",
"pnpm": ">= 9"
},
"ember": {
"edition": "default"
}
}

View File

@ -12,8 +12,8 @@
"babel-plugin-ember-template-compilation": "^2.3.0",
"content-tag": "^3.0.0",
"decorator-transforms": "^2.3.0",
"discourse-common": "workspace:1.0.0",
"discourse-widget-hbs": "workspace:1.0.0",
"discourse-common": "workspace:*",
"discourse-widget-hbs": "workspace:*",
"ember-cli-htmlbars": "^6.3.0",
"ember-source": "~5.12.0",
"ember-this-fallback": "^0.4.0",

View File

@ -11,6 +11,7 @@
"exports": {
".": "./src/index.js",
"./*": "./src/*.js",
"./app/*": "./app/*.js",
"./addon-main.js": "./addon-main.cjs"
},
"files": [

View File

@ -6,7 +6,7 @@
"license": "GPL-2.0-only",
"devDependencies": {
"@babel/plugin-proposal-decorators": "^7.25.9",
"@discourse/lint-configs": "^2.2.1",
"@discourse/lint-configs": "^2.2.2",
"@discourse/moment-timezone-names-translations": "^1.0.0",
"@fortawesome/fontawesome-free": "6.6.0",
"@glint/core": "^1.5.0",
@ -22,9 +22,9 @@
"concurrently": "^9.1.0",
"ember-template-lint": "^6.0.0",
"esbuild": "^0.24.0",
"eslint": "^9.14.0",
"eslint": "^9.16.0",
"jsdoc": "^4.0.4",
"lefthook": "^1.8.5",
"lefthook": "^1.9.0",
"licensee": "^11.1.1",
"lint-to-the-future": "^2.5.1",
"lint-to-the-future-ember-template": "^2.0.0",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff