@jxsuite/compiler 0.25.5 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +202 -202
- package/package.json +4 -4
- package/src/site/image-cache.ts +61 -4
- package/src/site/image-transform.ts +2 -3
- package/src/site/site-build.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jxsuite/compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Jx static HTML compiler, island detector, and site builder",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@apidevtools/json-schema-ref-parser": "^15.3.5",
|
|
44
|
-
"@jxsuite/parser": "^0.
|
|
45
|
-
"@jxsuite/runtime": "^0.
|
|
46
|
-
"@jxsuite/schema": "^0.
|
|
44
|
+
"@jxsuite/parser": "^0.26.0",
|
|
45
|
+
"@jxsuite/runtime": "^0.26.0",
|
|
46
|
+
"@jxsuite/schema": "^0.26.0",
|
|
47
47
|
"remark-gfm": "^4.0.1",
|
|
48
48
|
"remark-stringify": "^11.0.0",
|
|
49
49
|
"sharp": "^0.34.5",
|
package/src/site/image-cache.ts
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
* Image-cache.js — Content-hash based cache for processed image variants.
|
|
3
3
|
*
|
|
4
4
|
* Stores a manifest of previously processed images so that unchanged sources can skip re-encoding
|
|
5
|
-
* on subsequent builds. Cache lives in
|
|
5
|
+
* on subsequent builds. Cache lives in the npm global cache directory under jxsuite-images/ so that
|
|
6
|
+
* CI environments (e.g. Cloudflare Pages) can persist it via their npm cache layer.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
9
|
-
import { resolve } from "node:path";
|
|
10
|
+
import { resolve, basename } from "node:path";
|
|
11
|
+
import { execSync } from "node:child_process";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
10
13
|
import { contentHash, configHash } from "./image-optimizer.ts";
|
|
11
14
|
|
|
12
15
|
import type { ImageManifest } from "./image-optimizer.ts";
|
|
@@ -23,6 +26,56 @@ export interface CacheManifest {
|
|
|
23
26
|
entries: Record<string, CacheEntry>; // Cached entries keyed by content+config hash
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
// ─── Cache directory resolution ──────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
let _npmCacheBase: string | null | undefined = undefined; // undefined = not yet resolved
|
|
32
|
+
|
|
33
|
+
/** Reset the memoized npm cache base so the next call re-evaluates. Tests only. */
|
|
34
|
+
export function _testResetNpmCacheBase() {
|
|
35
|
+
_npmCacheBase = undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Directly set the memoized npm cache base. Pass null to force the project-local fallback. Tests
|
|
40
|
+
* only.
|
|
41
|
+
*/
|
|
42
|
+
export function _testSetNpmCacheBase(value: string | null) {
|
|
43
|
+
_npmCacheBase = value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Return the image cache directory for a project.
|
|
48
|
+
*
|
|
49
|
+
* Prefers the npm global cache (`npm config get cache`) so CI environments that cache ~/.npm (e.g.
|
|
50
|
+
* Cloudflare Pages) automatically persist optimized images across builds. Falls back to
|
|
51
|
+
* .cache/images inside the project root when npm is unavailable.
|
|
52
|
+
*
|
|
53
|
+
* Result is memoized — `npm config get cache` is only spawned once per process.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} projectRoot
|
|
56
|
+
* @returns {string}
|
|
57
|
+
*/
|
|
58
|
+
export function getImageCacheDir(projectRoot: string): string {
|
|
59
|
+
if (_npmCacheBase === undefined) {
|
|
60
|
+
try {
|
|
61
|
+
const result = execSync("npm config get cache", {
|
|
62
|
+
encoding: "utf-8",
|
|
63
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
64
|
+
cwd: tmpdir(), // avoid ENOWORKSPACES when cwd is inside an npm workspace
|
|
65
|
+
}).trim();
|
|
66
|
+
_npmCacheBase = result && result !== "undefined" ? result : null;
|
|
67
|
+
} catch {
|
|
68
|
+
_npmCacheBase = null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (_npmCacheBase) {
|
|
72
|
+
return resolve(_npmCacheBase, "jxsuite-images", basename(projectRoot));
|
|
73
|
+
}
|
|
74
|
+
return resolve(projectRoot, ".cache/images");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ─── Cache key ───────────────────────────────────────────────────────────────
|
|
78
|
+
|
|
26
79
|
/**
|
|
27
80
|
* Build a cache key from source file content and config.
|
|
28
81
|
*
|
|
@@ -34,6 +87,8 @@ export function cacheKey(srcPath: string, config: ImageConfig) {
|
|
|
34
87
|
return `${contentHash(srcPath)}:${configHash(config)}`;
|
|
35
88
|
}
|
|
36
89
|
|
|
90
|
+
// ─── Load / save ─────────────────────────────────────────────────────────────
|
|
91
|
+
|
|
37
92
|
/**
|
|
38
93
|
* Load the cache manifest from disk, or return an empty one.
|
|
39
94
|
*
|
|
@@ -41,7 +96,7 @@ export function cacheKey(srcPath: string, config: ImageConfig) {
|
|
|
41
96
|
* @returns {CacheManifest}
|
|
42
97
|
*/
|
|
43
98
|
export function loadCache(projectRoot: string) {
|
|
44
|
-
const manifestPath = resolve(projectRoot, "
|
|
99
|
+
const manifestPath = resolve(getImageCacheDir(projectRoot), "manifest.json");
|
|
45
100
|
if (!existsSync(manifestPath)) {
|
|
46
101
|
return { version: 1, entries: {} };
|
|
47
102
|
}
|
|
@@ -59,11 +114,13 @@ export function loadCache(projectRoot: string) {
|
|
|
59
114
|
* @param {CacheManifest} cache
|
|
60
115
|
*/
|
|
61
116
|
export function saveCache(projectRoot: string, cache: CacheManifest) {
|
|
62
|
-
const cacheDir =
|
|
117
|
+
const cacheDir = getImageCacheDir(projectRoot);
|
|
63
118
|
mkdirSync(cacheDir, { recursive: true });
|
|
64
119
|
writeFileSync(resolve(cacheDir, "manifest.json"), JSON.stringify(cache, null, 2), "utf8");
|
|
65
120
|
}
|
|
66
121
|
|
|
122
|
+
// ─── Entry access ─────────────────────────────────────────────────────────────
|
|
123
|
+
|
|
67
124
|
/**
|
|
68
125
|
* Check if a cache entry exists and its output files are still present.
|
|
69
126
|
*
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { existsSync } from "node:fs";
|
|
10
10
|
import { resolve, extname, basename } from "node:path";
|
|
11
11
|
import { processImage, buildSrcset, contentHash, configHash } from "./image-optimizer.ts";
|
|
12
|
-
import { getCached, setCached } from "./image-cache.ts";
|
|
12
|
+
import { getCached, setCached, getImageCacheDir } from "./image-cache.ts";
|
|
13
13
|
|
|
14
14
|
import type { ImageConfig } from "./image-optimizer.ts";
|
|
15
15
|
import type { ImageManifest } from "./image-optimizer.ts";
|
|
@@ -44,8 +44,7 @@ async function resolveManifest(
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
if (!cached) console.log(` Optimizing ${basename(absoluteSrc)}...`);
|
|
47
|
-
const
|
|
48
|
-
const manifest = await processImage(absoluteSrc, cacheImgDir, config);
|
|
47
|
+
const manifest = await processImage(absoluteSrc, getImageCacheDir(projectRoot), config);
|
|
49
48
|
setCached(cache, key, src, manifest);
|
|
50
49
|
return manifest;
|
|
51
50
|
}
|
package/src/site/site-build.ts
CHANGED
|
@@ -44,7 +44,7 @@ import { loadContentTypes, loadContentConfig, resolveContentTypeRefs } from "./c
|
|
|
44
44
|
import { resolvePrototypes } from "./prototype-resolver.ts";
|
|
45
45
|
import { compileMarkdown } from "../targets/compile-markdown.ts";
|
|
46
46
|
import { transformImageNodes } from "./image-transform.ts";
|
|
47
|
-
import { loadCache, saveCache } from "./image-cache.ts";
|
|
47
|
+
import { loadCache, saveCache, getImageCacheDir } from "./image-cache.ts";
|
|
48
48
|
import type {
|
|
49
49
|
JxElement,
|
|
50
50
|
JxMutableNode,
|
|
@@ -257,7 +257,7 @@ export async function buildSite(
|
|
|
257
257
|
// ── 6b. Save image cache and copy variants to dist ──────────────────────
|
|
258
258
|
if (imageCache && projectConfig.images.optimize) {
|
|
259
259
|
saveCache(projectRoot, imageCache);
|
|
260
|
-
const cacheOptimizedDir = resolve(projectRoot, "
|
|
260
|
+
const cacheOptimizedDir = resolve(getImageCacheDir(projectRoot), "_optimized");
|
|
261
261
|
if (existsSync(cacheOptimizedDir)) {
|
|
262
262
|
const distOptimizedDir = resolve(outDir, "images/_optimized");
|
|
263
263
|
mkdirSync(distOptimizedDir, { recursive: true });
|