From 13d3d304afdbbef53c3b5425a77d97e1fc7bdf89 Mon Sep 17 00:00:00 2001 From: Eetu Rantanen Date: Fri, 10 Jul 2026 15:09:03 +0300 Subject: [PATCH 01/11] add dev-preview scaffolding and dependencies --- .gitignore | 1 + package.json | 3 +++ scripts/dev-preview/constants.js | 40 ++++++++++++++++++++++++++++++++ scripts/dev-preview/index.js | 2 ++ 4 files changed, 46 insertions(+) create mode 100644 scripts/dev-preview/constants.js create mode 100644 scripts/dev-preview/index.js diff --git a/.gitignore b/.gitignore index 4b5b6746381..b43392c4538 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.dev-preview /.idea/ /node_modules /lua/output diff --git a/package.json b/package.json index e0130280365..f4f4f9f5090 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,13 @@ "@playwright/test": "^1.61.1", "@stylistic/stylelint-plugin": "^2.1.2", "@typescript-eslint/eslint-plugin": "^8.56.1", + "chokidar": "^4.0.3", "eslint": "9.x.x", "eslint-config-wikimedia": "0.32.3", "eslint-plugin-jsdoc": "^62.6.0", "eslint-plugin-vue": "10.6.x", "globals": "^17.3.0", + "http-mitm-proxy": "^1.1.0", "jest": "^30.2.0", "jest-environment-jsdom": "^30.2.0", "jest-junit": "^16.0.0", @@ -33,6 +35,7 @@ ] }, "scripts": { + "dev": "node scripts/dev-preview/index.js", "lint": "npm run lint:js && npm run lint:scss", "lint:ci": "npm run lint:js && npm run lint:scss:ci", "lint:js": "eslint --fix", diff --git a/scripts/dev-preview/constants.js b/scripts/dev-preview/constants.js new file mode 100644 index 00000000000..cd478c7368f --- /dev/null +++ b/scripts/dev-preview/constants.js @@ -0,0 +1,40 @@ +const path = require( 'path' ); + +const repoRoot = path.resolve( __dirname, '..', '..' ); + +const DEV_DIR = path.join( repoRoot, '.dev-preview' ); + +module.exports = { + REPO_ROOT: repoRoot, + OUTPUT_CSS: path.join( repoRoot, 'lua', 'output', 'css', 'main.css' ), + OUTPUT_JS: path.join( repoRoot, 'lua', 'output', 'js', 'main.js' ), + DEV_DIR, + PROFILE_DIR: path.join( DEV_DIR, 'profile' ), + CA_DIR: path.join( DEV_DIR, 'ca' ), + DEFAULT_PORT: 8081, + WATCH_GLOBS: [ 'stylesheets/**/*.scss', 'javascript/**/*.js' ], + // First existing entry wins. LP_DEV_BROWSER env overrides all of this. + BROWSER_CANDIDATES: { + linux: [ + '/usr/bin/google-chrome', + '/usr/bin/google-chrome-stable', + '/usr/bin/chromium', + '/usr/bin/chromium-browser', + '/usr/bin/brave-browser', + '/opt/brave-bin/brave', + '/usr/bin/microsoft-edge' + ], + darwin: [ + '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', + '/Applications/Chromium.app/Contents/MacOS/Chromium', + '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser', + '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge' + ], + win32: [ + 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', + 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', + 'C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe', + 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe' + ] + } +}; diff --git a/scripts/dev-preview/index.js b/scripts/dev-preview/index.js new file mode 100644 index 00000000000..babae77d81a --- /dev/null +++ b/scripts/dev-preview/index.js @@ -0,0 +1,2 @@ +console.log( 'dev-preview: not yet implemented' ); +process.exit( 0 ); From 94852f9b1fa0612345663455e2b084908ef80223 Mon Sep 17 00:00:00 2001 From: Eetu Rantanen Date: Fri, 10 Jul 2026 15:11:19 +0300 Subject: [PATCH 02/11] add dev-preview request classifier --- scripts/dev-preview/classify.js | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 scripts/dev-preview/classify.js diff --git a/scripts/dev-preview/classify.js b/scripts/dev-preview/classify.js new file mode 100644 index 00000000000..736a8ffe4fa --- /dev/null +++ b/scripts/dev-preview/classify.js @@ -0,0 +1,42 @@ +// Classify a proxied request URL into the local asset we should serve, or +// 'passthrough' to forward it to the real server untouched. +function classifyRequest( rawUrl ) { + let parsed; + try { + parsed = new URL( rawUrl ); + } catch ( e ) { + return 'passthrough'; + } + + const host = parsed.hostname.toLowerCase(); + const isLiquipedia = host === 'liquipedia.net' || host.endsWith( '.liquipedia.net' ); + if ( !isLiquipedia || !parsed.pathname.endsWith( '/commons/load.php' ) ) { + return 'passthrough'; + } + + // The LakesideView skin needs runtime theme vars we cannot compile locally. + if ( ( parsed.searchParams.get( 'skin' ) || '' ) === 'lakesideview' ) { + return 'passthrough'; + } + + const only = parsed.searchParams.get( 'only' ); + if ( only === 'styles' ) { + return 'styles'; + } + if ( only === 'scripts' ) { + return 'scripts'; + } + return 'passthrough'; +} + +function contentTypeFor( kind ) { + if ( kind === 'styles' ) { + return 'text/css; charset=utf-8'; + } + if ( kind === 'scripts' ) { + return 'text/javascript; charset=utf-8'; + } + throw new Error( `No content type for kind: ${ kind }` ); +} + +module.exports = { classifyRequest, contentTypeFor }; From 904594a1c990d7f101fe054e5b1c8368a1453c00 Mon Sep 17 00:00:00 2001 From: Eetu Rantanen Date: Fri, 10 Jul 2026 15:13:37 +0300 Subject: [PATCH 03/11] add dev-preview pac generation --- scripts/dev-preview/pac.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 scripts/dev-preview/pac.js diff --git a/scripts/dev-preview/pac.js b/scripts/dev-preview/pac.js new file mode 100644 index 00000000000..af5bc0cec76 --- /dev/null +++ b/scripts/dev-preview/pac.js @@ -0,0 +1,19 @@ +// Route only *.liquipedia.net through the local proxy; everything else DIRECT +// so the contributor's normal browsing is untouched. +function buildPac( port ) { + return [ + 'function FindProxyForURL( url, host ) {', + '\tif ( dnsDomainIs( host, "liquipedia.net" ) || shExpMatch( host, "*.liquipedia.net" ) ) {', + `\t\treturn "PROXY 127.0.0.1:${ port }";`, + '\t}', + '\treturn "DIRECT";', + '}' + ].join( '\n' ); +} + +function pacDataUrl( port ) { + const encoded = encodeURIComponent( buildPac( port ) ); + return `data:application/x-ns-proxy-autoconfig,${ encoded }`; +} + +module.exports = { buildPac, pacDataUrl }; From 985eb22b3495e8d88860210f9b58db06e65e69a8 Mon Sep 17 00:00:00 2001 From: Eetu Rantanen Date: Fri, 10 Jul 2026 15:17:13 +0300 Subject: [PATCH 04/11] fix dev-preview pac domain match --- scripts/dev-preview/pac.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/dev-preview/pac.js b/scripts/dev-preview/pac.js index af5bc0cec76..93102c042b1 100644 --- a/scripts/dev-preview/pac.js +++ b/scripts/dev-preview/pac.js @@ -1,9 +1,12 @@ -// Route only *.liquipedia.net through the local proxy; everything else DIRECT -// so the contributor's normal browsing is untouched. function buildPac( port ) { + // Apex + subdomains only. shExpMatch( '*.liquipedia.net' ) needs a dot + // before the suffix, so it rejects lookalikes like notliquipedia.net; + // the explicit apex check covers the bare domain. (Do NOT use + // dnsDomainIs( host, 'liquipedia.net' ) — it is a plain suffix match and + // would route notliquipedia.net through the proxy.) return [ 'function FindProxyForURL( url, host ) {', - '\tif ( dnsDomainIs( host, "liquipedia.net" ) || shExpMatch( host, "*.liquipedia.net" ) ) {', + '\tif ( host === "liquipedia.net" || shExpMatch( host, "*.liquipedia.net" ) ) {', `\t\treturn "PROXY 127.0.0.1:${ port }";`, '\t}', '\treturn "DIRECT";', From f5072523fe597602ea87b9548fcb82f6b0c3ecbe Mon Sep 17 00:00:00 2001 From: Eetu Rantanen Date: Fri, 10 Jul 2026 15:19:09 +0300 Subject: [PATCH 05/11] add dev-preview browser detection and launch --- scripts/dev-preview/browser.js | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 scripts/dev-preview/browser.js diff --git a/scripts/dev-preview/browser.js b/scripts/dev-preview/browser.js new file mode 100644 index 00000000000..39dd9ff1f6b --- /dev/null +++ b/scripts/dev-preview/browser.js @@ -0,0 +1,38 @@ +const { spawn } = require( 'child_process' ); +const fs = require( 'fs' ); +const { BROWSER_CANDIDATES } = require( './constants.js' ); + +// Pure: pick the browser binary. LP_DEV_BROWSER wins; otherwise first existing +// candidate for the platform. Returns null if none found. +function detectBrowser( { env, platform, existsSync } ) { + const override = env.LP_DEV_BROWSER; + if ( override ) { + return existsSync( override ) ? override : null; + } + const candidates = BROWSER_CANDIDATES[ platform ] || []; + for ( const candidate of candidates ) { + if ( existsSync( candidate ) ) { + return candidate; + } + } + return null; +} + +// Thin shell: spawn the browser detached-but-tracked so we can kill it on teardown. +// --disable-quic is required: HTTP/3 bypasses the HTTP proxy entirely. +function launchBrowser( { browserPath, profileDir, pacUrl, url } ) { + const args = [ + `--user-data-dir=${ profileDir }`, + `--proxy-pac-url=${ pacUrl }`, + '--ignore-certificate-errors', + '--test-type', + '--disable-quic', + '--no-first-run', + '--no-default-browser-check', + '--new-window', + url + ]; + return spawn( browserPath, args, { stdio: 'ignore' } ); +} + +module.exports = { detectBrowser, launchBrowser, defaultExistsSync: fs.existsSync }; From d47087fb31c4e791f19be793e0a19f3d766ebc58 Mon Sep 17 00:00:00 2001 From: Eetu Rantanen Date: Fri, 10 Jul 2026 15:21:39 +0300 Subject: [PATCH 06/11] add dev-preview refresh client --- scripts/dev-preview/refresh-client.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 scripts/dev-preview/refresh-client.js diff --git a/scripts/dev-preview/refresh-client.js b/scripts/dev-preview/refresh-client.js new file mode 100644 index 00000000000..a69d0b9bd2d --- /dev/null +++ b/scripts/dev-preview/refresh-client.js @@ -0,0 +1,17 @@ +// Appended to the JS bundle we serve on only=scripts. No