Fixed build:all output on Windows (#8089)

* Fixed handling for paths with windows separator during build

* Fixed icon index order on windows during build

* Updated icon search index

Removed obsolete icon search index
This commit is contained in:
Kamil Krzyśków
2025-03-14 20:19:21 +01:00
committed by GitHub
parent 0e75aef9ea
commit 091865798f
4 changed files with 89 additions and 12 deletions

File diff suppressed because one or more lines are too long

View File

@@ -22,6 +22,7 @@
import * as chokidar from "chokidar"
import * as fs from "fs/promises"
import * as path from "path"
import {
EMPTY,
Observable,
@@ -120,7 +121,7 @@ export function resolve(
/* Build overrides */
!process.argv.includes("--all")
? filter(file => !file.startsWith(".overrides/"))
? filter(file => !file.startsWith(`.overrides${path.sep}`))
: identity,
)
}

View File

@@ -27,6 +27,7 @@ import {
concat,
defer,
from,
identity,
map,
merge,
mergeMap,
@@ -112,6 +113,75 @@ function minsvg(data: string): string {
return result.data
}
/**
* Return a path with POSIX style separators
*
* The default function assumes UNIX system, so it just returns the path.
*
* @param p - string path
* @returns String path
*/
let assurePosixSep = function (p: string): string {
return p
};
/**
* Return a path with POSIX style separators
*
* The Windows variant of this function replaces the separator with regex.
*
* @param p - string path
* @returns String path
*/
function assurePosixSepWin(p: string): string {
return p.replace(winSepRegex, path.posix.sep)
};
const winSepRegex = new RegExp(`\\${path.win32.sep}`, "g");
if (path.sep === path.win32.sep) {
assurePosixSep = assurePosixSepWin;
}
/**
* Compare two path strings to decide on the order
*
* On Windows the default order of paths containing `_` from the resolve function
* is different than on macOS. This function restores the order to the usual.
* Implementation adapted based on https://t.ly/VJp78
*
* Note: The paths should have no extension like .svg, just the name. Otherwise
* it won't check the compare.startsWith(reference) properly.
*
* @param reference Left string to compare
* @param compare Right string to compare against
* @returns Number for the sort function to define the order
*/
function sortOrderForWindows(reference: string, compare: string): number {
reference = reference.toLowerCase();
compare = compare.toLowerCase();
const length = Math.min(reference.length, compare.length);
for (let i = 0; i < length; i++) {
const leftChar = reference[i];
const rightChar = compare[i];
if (leftChar !== rightChar)
return customAlphabet.indexOf(leftChar) - customAlphabet.indexOf(rightChar);
}
if (reference.length !== compare.length) {
if (compare.startsWith(reference) && compare[reference.length] === "-")
return 1;
return reference.length - compare.length;
}
return 0;
}
const customAlphabet: string = "_,-./0123456789abcdefghijklmnopqrstuvwxyz";
/* ----------------------------------------------------------------------------
* Tasks
* ------------------------------------------------------------------------- */
@@ -187,7 +257,7 @@ const sources$ = copyAll("**/*.py", {
const stylesheets$ = resolve("**/[!_]*.scss", { cwd: "src" })
.pipe(
mergeMap(file => zip(
of(ext(file, ".css").replace(/(overrides|templates)\//, "")),
of(ext(file, ".css").replace(new RegExp(`(overrides|templates)\\${path.sep}`), "")),
transformStyle({
from: `src/${file}`,
to: ext(`${base}/${file}`, ".css")
@@ -199,7 +269,7 @@ const stylesheets$ = resolve("**/[!_]*.scss", { cwd: "src" })
const javascripts$ = resolve("**/{custom,bundle,search}.ts", { cwd: "src" })
.pipe(
mergeMap(file => zip(
of(ext(file, ".js").replace(/(overrides|templates)\//, "")),
of(ext(file, ".js").replace(new RegExp(`(overrides|templates)\\${path.sep}`), "")),
transformScript({
from: `src/${file}`,
to: ext(`${base}/${file}`, ".js")
@@ -229,10 +299,10 @@ const manifest$ = merge(
.pipe(
scan((prev, mapping) => (
mapping.reduce((next, [key, value]) => (
next.set(key, value.replace(
new RegExp(`${base}\\/(overrides|templates)\\/`),
next.set(assurePosixSep(key), assurePosixSep(value.replace(
new RegExp(`${base}\\/(overrides|templates)\\${path.sep}`),
""
))
)))
), prev)
), new Map<string, string>()),
)
@@ -291,9 +361,15 @@ const icons$ = defer(() => resolve("**/*.svg", {
}))
.pipe(
reduce((index, file) => index.set(
file.replace(/\.svg$/, "").replace(/\//g, "-"),
file
), new Map<string, string>())
file.replace(/\.svg$/, "").replace(new RegExp(`\\${path.sep}`, "g"), "-"),
assurePosixSep(file)
), new Map<string, string>()),
// The icons are stored in the index file, and the output needs to be OS
// agnostic. Some icons contain the `_` character, which has different order
// in the glob output on Windows.
(path.sep === path.win32.sep) ? map(icons => new Map(
[...icons].sort((a, b) => sortOrderForWindows(a[0], b[0]))
)) : identity
)
/* Compute emoji mappings (based on Twemoji) */
@@ -372,7 +448,7 @@ const schema$ = merge(
"reference/icons-emojis/#search"
].join("/"),
"type": "string",
"enum": icons.map(icon => icon.replace(".svg", ""))
"enum": icons.map(icon => assurePosixSep(icon.replace(".svg", "")))
})),
switchMap(data => write(
"docs/schema/assets/icons.json",

View File

@@ -60,7 +60,8 @@ interface TransformOptions {
/**
* Base directory for source map resolution
*/
const root = new RegExp(`file://${path.resolve(".")}/`, "g")
const currentPath = path.resolve(".").replace(new RegExp(`\\${path.win32.sep}`, "g"), path.posix.sep)
const root = path.sep === path.posix.sep ? new RegExp(`file://${currentPath}/`, "g") : new RegExp(`file:///${currentPath}/`, "g")
/* ----------------------------------------------------------------------------
* Helper functions