eleventy-plugin-uncharted 1.0.0-beta.2 → 1.0.0-beta.3

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.
@@ -30,7 +30,8 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
30
30
  * @param {boolean|string} [options.downloadData] - Enable download links globally (individual charts can override)
31
31
  * @param {Object} [options.image] - Image generation options
32
32
  * @param {boolean} [options.image.enabled=false] - Enable PNG image generation
33
- * @param {string} [options.image.outputDir='/images/charts/'] - Output directory for images
33
+ * @param {string} [options.image.outputDir='/images/charts/'] - Output directory for images (URL path)
34
+ * @param {string} [options.image.cacheDir] - Source directory for cached images (enables caching when set)
34
35
  * @param {number} [options.image.width=800] - Default image width in pixels
35
36
  * @param {number} [options.image.height=400] - Default image height in pixels
36
37
  * @param {number} [options.image.scale=2] - Device scale factor (2 for retina)
@@ -69,7 +70,8 @@ export default function(eleventyConfig, options = {}) {
69
70
 
70
71
  // Image generation options
71
72
  const imageOptions = normalizeImageOptions(options.image);
72
- const skipImageGeneration = shouldSkipInDevMode(imageOptions);
73
+ const skipImageGeneration = shouldSkipInDevMode(imageOptions) ||
74
+ process.argv.includes('--skip-images');
73
75
 
74
76
  // Clear image URLs at start of each build
75
77
  clearImageUrls();
@@ -123,6 +125,15 @@ export default function(eleventyConfig, options = {}) {
123
125
  });
124
126
  }
125
127
 
128
+ // Image cache passthrough - copies cached images to output
129
+ if (imageOptions.cacheDir) {
130
+ const cacheDirClean = imageOptions.cacheDir.replace(/^\/|\/$/g, '');
131
+ const outputDirClean = imageOptions.outputDir.replace(/^\/|\/$/g, '');
132
+ eleventyConfig.addPassthroughCopy({
133
+ [cacheDirClean]: outputDirClean
134
+ });
135
+ }
136
+
126
137
  eleventyConfig.addShortcode('chart', function(chartId) {
127
138
  // Get resolved data directory (from Eleventy config or plugin options)
128
139
  const resolvedDataDir = getDataDir();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eleventy-plugin-uncharted",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.3",
4
4
  "description": "An Eleventy plugin that renders CSS-based charts from CSV data using shortcodes",
5
5
  "main": "eleventy.config.js",
6
6
  "type": "module",
@@ -15,6 +15,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
15
  * @typedef {Object} ImageOptions
16
16
  * @property {boolean} [enabled=false] - Enable image generation
17
17
  * @property {string} [outputDir='/images/charts/'] - Output directory for images (URL path)
18
+ * @property {string} [cacheDir=null] - Source directory for cached images (enables caching when set)
18
19
  * @property {number} [width=800] - Default image width
19
20
  * @property {number} [height=400] - Default image height
20
21
  * @property {number} [scale=2] - Device scale factor (2 for retina)
@@ -33,6 +34,7 @@ const imageUrls = new Map();
33
34
  const defaultOptions = {
34
35
  enabled: false,
35
36
  outputDir: '/images/charts/',
37
+ cacheDir: null,
36
38
  width: 800,
37
39
  height: 400,
38
40
  scale: 2,
@@ -83,6 +85,23 @@ export function getImageUrl(chartId, chartConfig, globalOptions) {
83
85
  return `${dir}${filename}.png`;
84
86
  }
85
87
 
88
+ /**
89
+ * Get the cache file path for a chart image.
90
+ * @param {string} chartId - Chart identifier
91
+ * @param {Object} chartConfig - Chart configuration
92
+ * @param {ImageOptions} globalOptions - Global image options
93
+ * @returns {string|null} Absolute cache path, or null if caching disabled
94
+ */
95
+ export function getCachePath(chartId, chartConfig, globalOptions) {
96
+ if (!globalOptions.cacheDir) return null;
97
+
98
+ const imageConfig = chartConfig.image || {};
99
+ const filename = imageConfig.filename || chartId;
100
+ const cacheDir = globalOptions.cacheDir.replace(/\/$/, '');
101
+
102
+ return path.resolve(process.cwd(), cacheDir, `${filename}.png`);
103
+ }
104
+
86
105
  /**
87
106
  * Store the image URL for a chart (for shortcode lookup).
88
107
  * @param {string} chartId
@@ -143,6 +162,7 @@ export function queueChartForImage(chartId, chartHtml, chartConfig, globalOption
143
162
 
144
163
  const outputPath = getImageOutputPath(chartId, chartConfig, globalOptions, outputDir);
145
164
  const url = getImageUrl(chartId, chartConfig, globalOptions);
165
+ const cachePath = getCachePath(chartId, chartConfig, globalOptions);
146
166
 
147
167
  // Store URL for shortcode lookup
148
168
  storeImageUrl(chartId, url);
@@ -152,7 +172,8 @@ export function queueChartForImage(chartId, chartHtml, chartConfig, globalOption
152
172
  id: chartId,
153
173
  html: chartHtml,
154
174
  config,
155
- outputPath
175
+ outputPath,
176
+ cachePath
156
177
  });
157
178
  }
158
179
 
@@ -171,7 +192,10 @@ export async function processQueue(options) {
171
192
  if (!available) {
172
193
  const count = getQueueSize();
173
194
  clearQueue();
174
- console.warn(`[uncharted] Puppeteer not installed. Skipped ${count} chart image(s).`);
195
+ // Suppress warning if cacheDir is set (cached images will be used via passthrough)
196
+ if (!options.cacheDir) {
197
+ console.warn(`[uncharted] Puppeteer not installed. Skipped ${count} chart image(s).`);
198
+ }
175
199
  return { success: [], failed: [], skipped: true };
176
200
  }
177
201
 
@@ -170,7 +170,8 @@ ${stylesheetLinks}
170
170
  * @param {Object} chart - Chart data
171
171
  * @param {string} chart.html - Chart HTML
172
172
  * @param {Object} chart.config - Image configuration
173
- * @param {string} chart.outputPath - Output file path
173
+ * @param {string} chart.outputPath - Output file path (_site)
174
+ * @param {string} [chart.cachePath] - Cache file path (source directory, if caching enabled)
174
175
  * @param {string} css - Chart CSS content
175
176
  * @param {Object} defaults - Default image options
176
177
  * @returns {Promise<void>}
@@ -183,6 +184,9 @@ async function renderChart(page, chart, css, defaults) {
183
184
  const background = config.background || '#ffffff';
184
185
  const stylesheets = config.stylesheets || defaults.stylesheets || [];
185
186
 
187
+ // Use cache path if provided, otherwise write directly to output
188
+ const writePath = chart.cachePath || chart.outputPath;
189
+
186
190
  // Set viewport
187
191
  await page.setViewport({
188
192
  width,
@@ -206,14 +210,14 @@ async function renderChart(page, chart, css, defaults) {
206
210
  }
207
211
 
208
212
  // Ensure output directory exists
209
- const outputDir = path.dirname(chart.outputPath);
213
+ const outputDir = path.dirname(writePath);
210
214
  if (!fs.existsSync(outputDir)) {
211
215
  fs.mkdirSync(outputDir, { recursive: true });
212
216
  }
213
217
 
214
218
  // Take screenshot
215
219
  await page.screenshot({
216
- path: chart.outputPath,
220
+ path: writePath,
217
221
  type: 'png',
218
222
  omitBackground: background === 'transparent'
219
223
  });