mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-07 08:54:42 +00:00
Give Markdown blocks one consistent gap, roomier on desktop, and a zoom-in cursor on images (#7298)
* fix(scripts): recover installs when a dependency patch changed patch-package cannot apply a patch over a package patched with an earlier version of it, and without --error-on-fail it exits 0 locally. Checkouts kept the stale patch silently: the Markdown code block spacing fix never reached them. The script now fails the install and removes that package so the next npm install reinstalls it clean with the current patch. A patch-package that cannot start fails the install without removing anything. * fix(app): give Markdown blocks one gap and roomier desktop spacing Every Markdown block is followed by one gap, density.blockGap: 12 on compact layouts and 16 wider. The library's element styles and the views stacked outside it (Mermaid segments on native, streaming head and tail) take the same token, so no block type carries its own margins. Desktop was too tight at 12. Markdown images show a zoom-in cursor on web, since tapping opens the lightbox.
This commit is contained in:
@@ -60,30 +60,37 @@ if (!existsSync("patches") || installedPackages.length === 0) {
|
||||
|
||||
const patchFiles = readdirSync("patches").filter((file) => file.endsWith(".patch"));
|
||||
|
||||
// Group patch files by the directory patch-package must run from.
|
||||
const patchFilesByCwd = new Map();
|
||||
for (const { patchPrefix, cwd = "." } of installedPackages) {
|
||||
const isWindows = process.platform === "win32";
|
||||
const cmd = isWindows ? "patch-package.cmd" : "patch-package";
|
||||
|
||||
let failed = false;
|
||||
for (const [index, { nodeModulesPath, patchPrefix, cwd = "." }] of installedPackages.entries()) {
|
||||
const files = patchFiles.filter((file) => file.startsWith(patchPrefix));
|
||||
if (files.length === 0) {
|
||||
continue;
|
||||
}
|
||||
const group = patchFilesByCwd.get(cwd) ?? [];
|
||||
group.push(...files);
|
||||
patchFilesByCwd.set(cwd, group);
|
||||
const outcome = applyPatches(cwd, files, index);
|
||||
if (outcome === "applied") {
|
||||
continue;
|
||||
}
|
||||
failed = true;
|
||||
if (outcome === "unavailable") {
|
||||
continue;
|
||||
}
|
||||
// patch-package cannot apply a patch that changed after an earlier version of it was
|
||||
// applied. Without the package, the next install fetches it clean and applies the patch.
|
||||
rmSync(nodeModulesPath, { recursive: true, force: true });
|
||||
console.error(
|
||||
`postinstall-patches: removed ${nodeModulesPath} because its patch did not apply. ` +
|
||||
"Run npm install again to reinstall it with the current patch. " +
|
||||
"If it fails again on the clean package, the patch is out of date and must be regenerated.",
|
||||
);
|
||||
}
|
||||
|
||||
if (patchFilesByCwd.size === 0) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const isWindows = process.platform === "win32";
|
||||
const cmd = isWindows ? "patch-package.cmd" : "patch-package";
|
||||
|
||||
let groupIndex = 0;
|
||||
for (const [cwd, files] of patchFilesByCwd) {
|
||||
groupIndex += 1;
|
||||
const tempPatchDir = join(".tmp", `postinstall-patches-${process.pid}-${groupIndex}`);
|
||||
process.exit(failed ? 1 : 0);
|
||||
|
||||
function applyPatches(cwd, files, index) {
|
||||
const tempPatchDir = join(".tmp", `postinstall-patches-${process.pid}-${index}`);
|
||||
mkdirSync(tempPatchDir, { recursive: true });
|
||||
for (const patchFile of files) {
|
||||
copyFileSync(join("patches", patchFile), join(tempPatchDir, patchFile));
|
||||
@@ -91,7 +98,7 @@ for (const [cwd, files] of patchFilesByCwd) {
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = spawnSync(cmd, ["--patch-dir", relative(cwd, tempPatchDir)], {
|
||||
result = spawnSync(cmd, ["--patch-dir", relative(cwd, tempPatchDir), "--error-on-fail"], {
|
||||
cwd,
|
||||
shell: isWindows,
|
||||
stdio: "inherit",
|
||||
@@ -103,10 +110,7 @@ for (const [cwd, files] of patchFilesByCwd) {
|
||||
|
||||
if (result.error) {
|
||||
console.error("postinstall-patches: patch-package failed to spawn:", result.error.message);
|
||||
return "unavailable";
|
||||
}
|
||||
if (result.status !== 0) {
|
||||
process.exit(result.status ?? 1);
|
||||
}
|
||||
return result.status === 0 ? "applied" : "rejected";
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { test } from "node:test";
|
||||
|
||||
const script = path.resolve("scripts", "postinstall-patches.mjs");
|
||||
const bin = path.resolve("node_modules", ".bin");
|
||||
const packageName = "react-native-draggable-flatlist";
|
||||
const patchFile = `${packageName}+4.0.3.patch`;
|
||||
|
||||
function createCheckout() {
|
||||
const root = mkdtempSync(path.join(tmpdir(), "postinstall-patches-"));
|
||||
writeFileSync(path.join(root, "package.json"), JSON.stringify({ name: "checkout" }));
|
||||
const packageDir = path.join(root, "node_modules", packageName);
|
||||
mkdirSync(packageDir, { recursive: true });
|
||||
writeFileSync(
|
||||
path.join(packageDir, "package.json"),
|
||||
JSON.stringify({ name: packageName, version: "4.0.3" }),
|
||||
);
|
||||
writeFileSync(path.join(packageDir, "index.js"), "export const value = 1;\n");
|
||||
mkdirSync(path.join(root, "patches"));
|
||||
return { root, packageDir };
|
||||
}
|
||||
|
||||
function writePatch(root, from, to) {
|
||||
const file = `node_modules/${packageName}/index.js`;
|
||||
writeFileSync(
|
||||
path.join(root, "patches", patchFile),
|
||||
[
|
||||
`diff --git a/${file} b/${file}`,
|
||||
`--- a/${file}`,
|
||||
`+++ b/${file}`,
|
||||
"@@ -1 +1 @@",
|
||||
`-export const value = ${from};`,
|
||||
`+export const value = ${to};`,
|
||||
"",
|
||||
].join("\n"),
|
||||
);
|
||||
}
|
||||
|
||||
function install(root, PATH = `${bin}${path.delimiter}${process.env.PATH}`) {
|
||||
return spawnSync(process.execPath, [script], {
|
||||
cwd: root,
|
||||
encoding: "utf8",
|
||||
env: { ...process.env, PATH },
|
||||
});
|
||||
}
|
||||
|
||||
test("a patch that changed since it was applied removes the package for a clean reinstall", () => {
|
||||
const { root, packageDir } = createCheckout();
|
||||
try {
|
||||
writePatch(root, 1, 2);
|
||||
assert.equal(install(root).status, 0);
|
||||
assert.equal(
|
||||
readFileSync(path.join(packageDir, "index.js"), "utf8"),
|
||||
"export const value = 2;\n",
|
||||
);
|
||||
|
||||
writePatch(root, 1, 3);
|
||||
const result = install(root);
|
||||
|
||||
assert.equal(result.status, 1);
|
||||
assert.match(result.stderr, /Run npm install again/);
|
||||
assert.equal(existsSync(packageDir), false);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("an already applied patch leaves the package in place", () => {
|
||||
const { root, packageDir } = createCheckout();
|
||||
try {
|
||||
writePatch(root, 1, 2);
|
||||
assert.equal(install(root).status, 0);
|
||||
assert.equal(install(root).status, 0);
|
||||
assert.equal(
|
||||
readFileSync(path.join(packageDir, "index.js"), "utf8"),
|
||||
"export const value = 2;\n",
|
||||
);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("a missing patch-package fails the install and leaves the package in place", () => {
|
||||
const { root, packageDir } = createCheckout();
|
||||
try {
|
||||
writePatch(root, 1, 2);
|
||||
const result = install(root, root);
|
||||
|
||||
assert.equal(result.status, 1);
|
||||
assert.match(result.stderr, /failed to spawn/);
|
||||
assert.equal(existsSync(packageDir), true);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user