diff --git a/internal/check-embedded-rtl.mjs b/internal/check-embedded-rtl.mjs new file mode 100644 index 000000000..1fdfbec97 --- /dev/null +++ b/internal/check-embedded-rtl.mjs @@ -0,0 +1,152 @@ +#!/usr/bin/env node +/** + * check-embedded-rtl — an RTL locale must turn the PLUGIN right-to-left, and must NEVER + * turn the PARTNER'S PAGE right-to-left. + * + * TWO DEFECTS, one block (library/i18n/index.js, createAppI18n): + * 1. TIMING. It reflects RTL at CONSTRUCTION time from detectLocale(), which reads only the URL + * and . A locale arriving later through profile-config — the channel a HOST uses — + * never reaches it, so Arabic text renders inside a left-to-right layout. Measured: htmlDir + * null on every host-channel run, including leaves whose chrome was fully Arabic. + * 2. TARGET. It writes document.documentElement.dir. An EMBEDDED widget doing that flips the + * partner's WHOLE PAGE. The existing comment already worries about the host ("a WordPress RTL + * theme owns that decision") but only guards against CLEARING it, not against setting it. + * + * So direction belongs on the plugin's OWN element, driven by the locale ProfileLoader actually + * applies; stays only where the plugin owns the page (a standalone leaf). + * + * ⚠ THE HOST PAGE IS ON A DIFFERENT ORIGIN, deliberately: same-origin would let a bug pass that + * only bites a real partner. The tree is served on one port, the partner page on another. + * + * Usage: node internal/check-embedded-rtl.mjs [baseUrl] + */ +import { chromium } from 'playwright' +import { createServer } from 'node:http' +import { resolve, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' +import { servesThisTree } from './_serves-this-tree.mjs' + +const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..') +const BASE = process.argv[2] || process.env.BASE_URL || 'http://127.0.0.1:4173' +const HOST_PORT = Number(process.env.RTL_HOST_PORT || 47393) + +let reachable = false +try { const r = await fetch(`${BASE}/doxa-maps/manifest.json`, { signal: AbortSignal.timeout(4000) }); reachable = r.ok } catch { /* precondition */ } +if (!reachable) { console.log(`EMBEDDED-RTL: SKIP — nothing served at ${BASE}.`); process.exit(0) } +const treeCheck = await servesThisTree(BASE, ROOT) +if (!treeCheck.ok) { console.error(`EMBEDDED-RTL: NOT MEASURED — ${treeCheck.why}`); process.exit(2) } + +// A PARTNER PAGE on a foreign origin: its own is LTR and must stay that way. +const CASES = [ + { id: 'my-upg-100-list', tag: 'my-upg-100-list-map', profile: 'upg-100-mfe' }, + { id: 'my-upg-100-list', tag: 'my-upg-100-list-map', profile: 'poster-wall' }, +] +const TREE_PORT = Number(process.env.RTL_TREE_PORT || 47395) +const TREE = `http://127.0.0.1:${TREE_PORT}` +const hostHtml = (c) => ` +partner + +

Partner page

+ +