@karmaniverous/jeeves-watcher 0.9.5 → 0.9.6
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/config.schema.json +1 -1
- package/dist/cli/jeeves-watcher/index.js +73 -4
- package/dist/index.js +74 -5
- package/package.json +1 -1
package/config.schema.json
CHANGED
|
@@ -807,7 +807,7 @@
|
|
|
807
807
|
"items": {
|
|
808
808
|
"$ref": "#/definitions/__schema66"
|
|
809
809
|
},
|
|
810
|
-
"description": "Keys
|
|
810
|
+
"description": "Keys or glob patterns to include as YAML frontmatter. Supports picomatch globs (e.g. \"*\") and \"!\"-prefixed exclusion patterns (e.g. \"!_*\"). Explicit names preserve declaration order; glob-matched keys are sorted alphabetically."
|
|
811
811
|
},
|
|
812
812
|
"body": {
|
|
813
813
|
"type": "array",
|
|
@@ -1057,6 +1057,72 @@ function rebaseHeadings(markdown, baseHeading) {
|
|
|
1057
1057
|
return rebased.join('\n');
|
|
1058
1058
|
}
|
|
1059
1059
|
|
|
1060
|
+
/**
|
|
1061
|
+
* @module templates/resolveFrontmatterKeys
|
|
1062
|
+
* Resolves frontmatter key patterns (with glob/negation support) against
|
|
1063
|
+
* available context keys. Patterns prefixed with `!` are exclusions.
|
|
1064
|
+
* Supports picomatch glob syntax (e.g. `*`, `_*`, `chunk_*`).
|
|
1065
|
+
*/
|
|
1066
|
+
/**
|
|
1067
|
+
* Resolve frontmatter patterns against available keys.
|
|
1068
|
+
*
|
|
1069
|
+
* @param patterns - Array of key names or glob patterns. `!`-prefixed patterns exclude.
|
|
1070
|
+
* @param allKeys - All available keys from the rendering context.
|
|
1071
|
+
* @returns Ordered array of resolved keys: explicit names in declaration order,
|
|
1072
|
+
* then glob-matched names sorted alphabetically, minus exclusions.
|
|
1073
|
+
*/
|
|
1074
|
+
function resolveFrontmatterKeys(patterns, allKeys) {
|
|
1075
|
+
const includes = [];
|
|
1076
|
+
const excludePatterns = [];
|
|
1077
|
+
for (const p of patterns) {
|
|
1078
|
+
if (p.startsWith('!')) {
|
|
1079
|
+
excludePatterns.push(p.slice(1));
|
|
1080
|
+
}
|
|
1081
|
+
else {
|
|
1082
|
+
includes.push(p);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
const isExcluded = excludePatterns.length
|
|
1086
|
+
? picomatch(excludePatterns)
|
|
1087
|
+
: () => false;
|
|
1088
|
+
// Collect keys: explicit names first (in order), then glob-expanded (sorted).
|
|
1089
|
+
const result = [];
|
|
1090
|
+
const seen = new Set();
|
|
1091
|
+
// Pass 1: explicit (non-glob) names — preserved in declaration order.
|
|
1092
|
+
const explicitNames = [];
|
|
1093
|
+
const globPatterns = [];
|
|
1094
|
+
for (const p of includes) {
|
|
1095
|
+
if (isGlob(p)) {
|
|
1096
|
+
globPatterns.push(p);
|
|
1097
|
+
}
|
|
1098
|
+
else {
|
|
1099
|
+
explicitNames.push(p);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
for (const name of explicitNames) {
|
|
1103
|
+
if (!isExcluded(name) && allKeys.includes(name) && !seen.has(name)) {
|
|
1104
|
+
result.push(name);
|
|
1105
|
+
seen.add(name);
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
// Pass 2: glob patterns — matched keys sorted alphabetically.
|
|
1109
|
+
if (globPatterns.length) {
|
|
1110
|
+
const isIncluded = picomatch(globPatterns);
|
|
1111
|
+
const matched = allKeys.filter((k) => isIncluded(k)).sort();
|
|
1112
|
+
for (const key of matched) {
|
|
1113
|
+
if (!isExcluded(key) && !seen.has(key)) {
|
|
1114
|
+
result.push(key);
|
|
1115
|
+
seen.add(key);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
return result;
|
|
1120
|
+
}
|
|
1121
|
+
/** Check whether a pattern contains glob characters. */
|
|
1122
|
+
function isGlob(pattern) {
|
|
1123
|
+
return /[*?[\]{}]/.test(pattern);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1060
1126
|
/**
|
|
1061
1127
|
* @module templates/renderDoc
|
|
1062
1128
|
* Declarative renderer for YAML frontmatter + structured Markdown body.
|
|
@@ -1127,9 +1193,10 @@ function renderEach(hbs, section, value) {
|
|
|
1127
1193
|
*/
|
|
1128
1194
|
function renderDoc(context, config, hbs) {
|
|
1129
1195
|
const parts = [];
|
|
1130
|
-
// Frontmatter
|
|
1196
|
+
// Frontmatter — resolve patterns (globs, negations) against context keys.
|
|
1197
|
+
const resolvedKeys = resolveFrontmatterKeys(config.frontmatter, Object.keys(context));
|
|
1131
1198
|
const fmObj = {};
|
|
1132
|
-
for (const key of
|
|
1199
|
+
for (const key of resolvedKeys) {
|
|
1133
1200
|
const v = get(context, key);
|
|
1134
1201
|
if (v !== undefined) {
|
|
1135
1202
|
fmObj[key] = v;
|
|
@@ -1923,10 +1990,12 @@ const renderBodySectionSchema = z.object({
|
|
|
1923
1990
|
});
|
|
1924
1991
|
/** Render config: YAML frontmatter + ordered body sections. */
|
|
1925
1992
|
const renderConfigSchema = z.object({
|
|
1926
|
-
/** Keys to extract from context and include as YAML frontmatter. */
|
|
1993
|
+
/** Keys or glob patterns to extract from context and include as YAML frontmatter. */
|
|
1927
1994
|
frontmatter: z
|
|
1928
1995
|
.array(z.string().min(1))
|
|
1929
|
-
.describe('Keys
|
|
1996
|
+
.describe('Keys or glob patterns to include as YAML frontmatter. ' +
|
|
1997
|
+
'Supports picomatch globs (e.g. "*") and "!"-prefixed exclusion patterns (e.g. "!_*"). ' +
|
|
1998
|
+
'Explicit names preserve declaration order; glob-matched keys are sorted alphabetically.'),
|
|
1930
1999
|
/** Ordered markdown body sections. */
|
|
1931
2000
|
body: z
|
|
1932
2001
|
.array(renderBodySectionSchema)
|
package/dist/index.js
CHANGED
|
@@ -12,9 +12,9 @@ import { capitalize, title, camel, snake, dash, isEqual, get, parallel, omit } f
|
|
|
12
12
|
import rehypeParse from 'rehype-parse';
|
|
13
13
|
import { unified } from 'unified';
|
|
14
14
|
import yaml from 'js-yaml';
|
|
15
|
+
import picomatch from 'picomatch';
|
|
15
16
|
import Ajv from 'ajv';
|
|
16
17
|
import addFormats from 'ajv-formats';
|
|
17
|
-
import picomatch from 'picomatch';
|
|
18
18
|
import { readdir, stat, writeFile, rm, readFile, mkdir } from 'node:fs/promises';
|
|
19
19
|
import { z, ZodError } from 'zod';
|
|
20
20
|
import { JSONPath } from 'jsonpath-plus';
|
|
@@ -374,6 +374,72 @@ function rebaseHeadings(markdown, baseHeading) {
|
|
|
374
374
|
return rebased.join('\n');
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
+
/**
|
|
378
|
+
* @module templates/resolveFrontmatterKeys
|
|
379
|
+
* Resolves frontmatter key patterns (with glob/negation support) against
|
|
380
|
+
* available context keys. Patterns prefixed with `!` are exclusions.
|
|
381
|
+
* Supports picomatch glob syntax (e.g. `*`, `_*`, `chunk_*`).
|
|
382
|
+
*/
|
|
383
|
+
/**
|
|
384
|
+
* Resolve frontmatter patterns against available keys.
|
|
385
|
+
*
|
|
386
|
+
* @param patterns - Array of key names or glob patterns. `!`-prefixed patterns exclude.
|
|
387
|
+
* @param allKeys - All available keys from the rendering context.
|
|
388
|
+
* @returns Ordered array of resolved keys: explicit names in declaration order,
|
|
389
|
+
* then glob-matched names sorted alphabetically, minus exclusions.
|
|
390
|
+
*/
|
|
391
|
+
function resolveFrontmatterKeys(patterns, allKeys) {
|
|
392
|
+
const includes = [];
|
|
393
|
+
const excludePatterns = [];
|
|
394
|
+
for (const p of patterns) {
|
|
395
|
+
if (p.startsWith('!')) {
|
|
396
|
+
excludePatterns.push(p.slice(1));
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
includes.push(p);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const isExcluded = excludePatterns.length
|
|
403
|
+
? picomatch(excludePatterns)
|
|
404
|
+
: () => false;
|
|
405
|
+
// Collect keys: explicit names first (in order), then glob-expanded (sorted).
|
|
406
|
+
const result = [];
|
|
407
|
+
const seen = new Set();
|
|
408
|
+
// Pass 1: explicit (non-glob) names — preserved in declaration order.
|
|
409
|
+
const explicitNames = [];
|
|
410
|
+
const globPatterns = [];
|
|
411
|
+
for (const p of includes) {
|
|
412
|
+
if (isGlob(p)) {
|
|
413
|
+
globPatterns.push(p);
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
explicitNames.push(p);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
for (const name of explicitNames) {
|
|
420
|
+
if (!isExcluded(name) && allKeys.includes(name) && !seen.has(name)) {
|
|
421
|
+
result.push(name);
|
|
422
|
+
seen.add(name);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// Pass 2: glob patterns — matched keys sorted alphabetically.
|
|
426
|
+
if (globPatterns.length) {
|
|
427
|
+
const isIncluded = picomatch(globPatterns);
|
|
428
|
+
const matched = allKeys.filter((k) => isIncluded(k)).sort();
|
|
429
|
+
for (const key of matched) {
|
|
430
|
+
if (!isExcluded(key) && !seen.has(key)) {
|
|
431
|
+
result.push(key);
|
|
432
|
+
seen.add(key);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return result;
|
|
437
|
+
}
|
|
438
|
+
/** Check whether a pattern contains glob characters. */
|
|
439
|
+
function isGlob(pattern) {
|
|
440
|
+
return /[*?[\]{}]/.test(pattern);
|
|
441
|
+
}
|
|
442
|
+
|
|
377
443
|
/**
|
|
378
444
|
* @module templates/renderDoc
|
|
379
445
|
* Declarative renderer for YAML frontmatter + structured Markdown body.
|
|
@@ -444,9 +510,10 @@ function renderEach(hbs, section, value) {
|
|
|
444
510
|
*/
|
|
445
511
|
function renderDoc(context, config, hbs) {
|
|
446
512
|
const parts = [];
|
|
447
|
-
// Frontmatter
|
|
513
|
+
// Frontmatter — resolve patterns (globs, negations) against context keys.
|
|
514
|
+
const resolvedKeys = resolveFrontmatterKeys(config.frontmatter, Object.keys(context));
|
|
448
515
|
const fmObj = {};
|
|
449
|
-
for (const key of
|
|
516
|
+
for (const key of resolvedKeys) {
|
|
450
517
|
const v = get(context, key);
|
|
451
518
|
if (v !== undefined) {
|
|
452
519
|
fmObj[key] = v;
|
|
@@ -1609,10 +1676,12 @@ const renderBodySectionSchema = z.object({
|
|
|
1609
1676
|
});
|
|
1610
1677
|
/** Render config: YAML frontmatter + ordered body sections. */
|
|
1611
1678
|
const renderConfigSchema = z.object({
|
|
1612
|
-
/** Keys to extract from context and include as YAML frontmatter. */
|
|
1679
|
+
/** Keys or glob patterns to extract from context and include as YAML frontmatter. */
|
|
1613
1680
|
frontmatter: z
|
|
1614
1681
|
.array(z.string().min(1))
|
|
1615
|
-
.describe('Keys
|
|
1682
|
+
.describe('Keys or glob patterns to include as YAML frontmatter. ' +
|
|
1683
|
+
'Supports picomatch globs (e.g. "*") and "!"-prefixed exclusion patterns (e.g. "!_*"). ' +
|
|
1684
|
+
'Explicit names preserve declaration order; glob-matched keys are sorted alphabetically.'),
|
|
1616
1685
|
/** Ordered markdown body sections. */
|
|
1617
1686
|
body: z
|
|
1618
1687
|
.array(renderBodySectionSchema)
|
package/package.json
CHANGED