dsh-fonttune 0.3.6 → 0.4.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/lib/index.js CHANGED
@@ -273,6 +273,44 @@ export const Config = volatileWhenSupported(z.object({
273
273
  .description(
274
274
  "The interface follows the conversation: its family and weight take the conversation's values (off = the interface keeps its own)"
275
275
  ),
276
+ [shared.PANEL_ENABLED_FIELD]: z
277
+ .boolean()
278
+ .default(true)
279
+ .description(
280
+ "Master switch of the floating tune panel (off hides its dot everywhere)"
281
+ ),
282
+ [shared.PANEL_POS_FIELD]: z
283
+ .string()
284
+ .max(32)
285
+ .pattern(/^(\d{1,4},\d{1,4})?$/)
286
+ .default("")
287
+ .description(
288
+ "Last floating panel position as x,y in CSS pixels (empty = the default corner)"
289
+ ),
290
+ [shared.PANEL_CORNER_FIELD]: z
291
+ .string()
292
+ .max(2)
293
+ .pattern(/^(tl|tr|bl|br)?$/)
294
+ .default("")
295
+ .description(
296
+ "The corner the floating dot lives in, tl/tr/bl/br (empty = no corner chosen yet; the position is only its consequence)"
297
+ ),
298
+ [shared.PANEL_SIZE_FIELD]: z
299
+ .string()
300
+ .max(32)
301
+ .pattern(/^(\d{1,3},\d{1,3})?$/)
302
+ .default("")
303
+ .description(
304
+ "Last floating panel size as width,height in CSS pixels (empty = the default size)"
305
+ ),
306
+ [shared.SMOOTHING_FIELD]: z
307
+ .string()
308
+ .max(8)
309
+ .pattern(/^(auto|sharp|smooth)$/)
310
+ .default("auto")
311
+ .description(
312
+ "How the browser draws the strokes: auto = the system's own rendering, sharp = crisp subpixel, smooth = soft grayscale"
313
+ ),
276
314
  [PER_THEME_FIELD]: z
277
315
  .boolean()
278
316
  .default(false)
@@ -312,6 +350,22 @@ export const Config = volatileWhenSupported(z.object({
312
350
  */
313
351
  const VOLATILE_WRITE = Symbol.for("cosmokit.volatile.write");
314
352
 
353
+ /**
354
+ * Every key a parsed settings document may legitimately carry: the durable
355
+ * axes, the retired pair, the scale marker, the panel chrome, and the storage
356
+ * fields. Anything else is a leftover from a removed field (0.4.0 was never
357
+ * released, so no migration exists) and is read-skipped here — never stored
358
+ * back, never thrown on.
359
+ */
360
+ const KNOWN_CONFIG_KEYS = new Set(
361
+ shared.DURABLE_FIELDS.concat([
362
+ shared.PER_THEME_FIELD,
363
+ shared.DARK_VALUES_FIELD,
364
+ shared.PRESETS_FIELD,
365
+ shared.ACTIVE_PRESET_FIELD,
366
+ ])
367
+ );
368
+
315
369
  /**
316
370
  * Replace every volatile reference in a parsed config with its current value.
317
371
  *
@@ -322,13 +376,31 @@ const VOLATILE_WRITE = Symbol.for("cosmokit.volatile.write");
322
376
  * @returns {unknown} the same shape, references unwrapped.
323
377
  */
324
378
  export function plainConfigValue(value) {
379
+ return copyPlainConfig(value, true);
380
+ }
381
+
382
+ /**
383
+ * The recursive worker behind `plainConfigValue`.
384
+ *
385
+ * Only the top level is a config object, so only it is filtered: nested maps
386
+ * (none exist in the config today) pass through untouched. Schemastery keeps
387
+ * unknown keys instead of rejecting them, so without this filter a removed
388
+ * field lingering in an older document would be handed back as live data.
389
+ * @param {unknown} value - the node to copy.
390
+ * @param {boolean} top - true for the outermost call only.
391
+ * @returns {unknown} the copied node.
392
+ */
393
+ function copyPlainConfig(value, top) {
325
394
  if (value === null || typeof value !== "object") return value;
326
395
  if (VOLATILE_WRITE in value && typeof value.get === "function") {
327
- return plainConfigValue(value.get());
396
+ return copyPlainConfig(value.get(), top);
328
397
  }
329
- if (Array.isArray(value)) return value.map(plainConfigValue);
398
+ if (Array.isArray(value)) return value.map((entry) => copyPlainConfig(entry, false));
330
399
  const out = {};
331
- for (const [key, child] of Object.entries(value)) out[key] = plainConfigValue(child);
400
+ for (const [key, child] of Object.entries(value)) {
401
+ if (top && !KNOWN_CONFIG_KEYS.has(key)) continue;
402
+ out[key] = copyPlainConfig(child, false);
403
+ }
332
404
  return out;
333
405
  }
334
406