mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-11 21:26:44 +00:00
sys-front-inj-design now renders templates/css/app.css.j2 ahead of the role's stylesheet and templates/js/design.js.j2 ahead of its script. The branding URLs, the slot dimensions and the logo guard live there instead of being repeated per role: the guard that stood in 41 sheets is one condition in the composing template, and a sheet reads branding through --design-url-* / --design-slot-* custom properties. 29 stylesheets and 43 design scripts lose their Jinja and move to static files. Roles whose sheet carries app-specific URLs declare them as design_css_urls and read them as --design-url-app-*. The script prelude is prepended only when the role script references it, and it carries urls only while a logo is configured, so every role that needs neither is emitted byte for byte as before. Five checks keep the mechanism honest: a composed sheet may only read design custom properties that app.css.j2 declares for its role, a template may not carry Jinja expression text outside its delimiters, a design script may not quote its config object, and the injected-script parse check now covers the design channel. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
129 lines
4.9 KiB
JavaScript
129 lines
4.9 KiB
JavaScript
const js = require("@eslint/js");
|
|
const playwright = require("eslint-plugin-playwright");
|
|
const globals = require("globals");
|
|
|
|
module.exports = [
|
|
{
|
|
ignores: [
|
|
"node_modules/**",
|
|
"venv/**",
|
|
".venv/**",
|
|
"**/__pycache__/**",
|
|
"roles/web-app-bigbluebutton/files/javascript/ep_redis_publisher_index.js",
|
|
],
|
|
},
|
|
{
|
|
linterOptions: {
|
|
reportUnusedDisableDirectives: "warn",
|
|
},
|
|
},
|
|
js.configs.recommended,
|
|
{
|
|
// Repo-root config / build files are CommonJS Node modules.
|
|
files: ["*.js", "*.cjs"],
|
|
languageOptions: {
|
|
sourceType: "commonjs",
|
|
globals: { ...globals.node },
|
|
},
|
|
},
|
|
{
|
|
files: ["roles/**/files/**/*.js", "roles/**/templates/**/*.js"],
|
|
languageOptions: {
|
|
ecmaVersion: 2023,
|
|
sourceType: "commonjs",
|
|
globals: {
|
|
...globals.node,
|
|
// Specs and persona helpers run inside `page.evaluate(() => …)`
|
|
// callbacks where window/document/getComputedStyle/etc. are valid;
|
|
// adding the browser globals avoids a sea of `no-undef` false
|
|
// positives.
|
|
...globals.browser,
|
|
INFINITO_DESIGN: "readonly",
|
|
},
|
|
},
|
|
rules: {
|
|
"no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
|
"no-var": "error",
|
|
"eqeqeq": ["error", "always"],
|
|
"prefer-const": "error",
|
|
"prefer-template": "error",
|
|
"no-throw-literal": "error",
|
|
"no-self-compare": "error",
|
|
"default-case-last": "error",
|
|
// Defensive: forbid string-driven code execution shapes outright.
|
|
"no-eval": "error",
|
|
"no-implied-eval": "error",
|
|
"no-new-func": "error",
|
|
"no-script-url": "error",
|
|
// Empty `catch (e) {}` is the project's idiom for fire-and-forget
|
|
// best-effort actions (localStorage probes, optional cleanups, …);
|
|
// the catch protects the surrounding flow from incidental
|
|
// failures it can't act on.
|
|
"no-empty": ["error", { allowEmptyCatch: true }],
|
|
},
|
|
},
|
|
{
|
|
// SSO sidecar shims (oauth2-proxy header-auth / server patches) are
|
|
// authored as ES modules (import/export), not CommonJS.
|
|
files: ["roles/**/files/sso/**/*.js"],
|
|
languageOptions: {
|
|
sourceType: "module",
|
|
},
|
|
},
|
|
{
|
|
files: ["roles/web-svc-simpleicons/files/javascript/**/*.js"],
|
|
languageOptions: {
|
|
sourceType: "module",
|
|
},
|
|
},
|
|
{
|
|
files: [
|
|
"roles/**/files/playwright/**/*.js",
|
|
"roles/test-e2e-playwright/files/personas/**/*.js",
|
|
],
|
|
plugins: { playwright },
|
|
rules: {
|
|
...playwright.configs["flat/recommended"].rules,
|
|
// skipUnlessServiceEnabled() drives a real test.skip(...) on
|
|
// runtime-detected disabled services — that's the project's
|
|
// contract, not an oversight.
|
|
"playwright/no-skipped-test": "off",
|
|
// Persona helpers (runGuestFlow / runBiberFlow / runAdminFlow) branch
|
|
// on isVisible() / isServiceEnabled() before expect(); the conditional
|
|
// is the contract, not a bug.
|
|
"playwright/no-conditional-expect": "off",
|
|
"playwright/no-conditional-in-test": "off",
|
|
// Some specs use waitForTimeout deliberately for OIDC settle delays
|
|
// and federation propagation — banning it would force rewrites.
|
|
"playwright/no-wait-for-timeout": "off",
|
|
// The OIDC + post-redirect dance settles when the page is idle, not
|
|
// on a single load event. Several specs rely on
|
|
// waitForLoadState("networkidle") for that; banning it would force
|
|
// a coordinated rewrite of every flow. Tracked for a follow-up.
|
|
"playwright/no-networkidle": "off",
|
|
// Real lint signal, but the autofixer is not safe in every site we
|
|
// hit (it produced a broken diff in personas/utils/dashboard.js by
|
|
// dropping the `await getAttribute("href")` step and leaving a
|
|
// trailing-comma `toHaveAttribute("href", )` call). Keep off until
|
|
// a hand-migration pass; promote to "error" as those are reviewed.
|
|
"playwright/prefer-web-first-assertions": "off",
|
|
"playwright/no-wait-for-navigation": "error",
|
|
// An empty collection out of a catch reads downstream as "nothing to
|
|
// do": `JSON.parse` on a dotenv-quoted target list yields a string, the
|
|
// fallback made it `[]`, and every assertion iterating it passed while
|
|
// checking nothing. A catch returning "" or false or a populated object
|
|
// is not this class; reviewing all 26 such sites found each of them
|
|
// either recording the failure or answering a predicate.
|
|
"no-restricted-syntax": [
|
|
"error",
|
|
{
|
|
selector:
|
|
"CatchClause > BlockStatement > ReturnStatement > :matches(ArrayExpression[elements.length=0], ObjectExpression[properties.length=0])",
|
|
message:
|
|
"This catch returns an empty collection, which every caller reads as a legitimate 'nothing to do' and iterates zero times. Rethrow, or decode through a helper that throws on the shapes that cannot be right.",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
];
|