superbee 0.4.3-pre.2 → 0.4.3-pre.20

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.
@@ -30951,16 +30951,6 @@ function stringifyDoc(frontmatter2, body) {
30951
30951
  return stringifyWithData(frontmatter2, body);
30952
30952
  }
30953
30953
 
30954
- // ../core/src/meaningful-change-time.ts
30955
- function meaningfulChangeTimeField(frontmatter2) {
30956
- const generated = frontmatter2.generated;
30957
- if (generated !== null && typeof generated === "object" && !Array.isArray(generated) && generated.at !== void 0) return "generated.at";
30958
- return "timestamp";
30959
- }
30960
- function meaningfulChangeTimeValue(frontmatter2) {
30961
- return meaningfulChangeTimeField(frontmatter2) === "generated.at" ? frontmatter2.generated.at : frontmatter2.timestamp;
30962
- }
30963
-
30964
30954
  // ../core/src/errors.ts
30965
30955
  var InvalidInputError = class extends Error {
30966
30956
  constructor(message) {
@@ -30992,73 +30982,6 @@ var ConcurrentReplacementError = class extends Error {
30992
30982
  }
30993
30983
  };
30994
30984
 
30995
- // ../core/src/verification.ts
30996
- var TRUST_TIERS = Object.freeze([
30997
- "unverified",
30998
- "machine-confirmed",
30999
- "human-reviewed"
31000
- ]);
31001
- var ISO_INSTANT = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?(?:([Zz])|([+-])(\d{2})(?::?(\d{2}))?)$/;
31002
- function parseIsoInstant(raw, rounding = "truncate") {
31003
- const match = ISO_INSTANT.exec(raw);
31004
- if (!match) return null;
31005
- const [, y, mo, d, h, mi, sec = "0", frac = "0", zulu, sign, oh, om = "0"] = match;
31006
- const year = Number(y);
31007
- const month = Number(mo);
31008
- const day = Number(d);
31009
- const hour = Number(h);
31010
- const minute = Number(mi);
31011
- const second = Number(sec);
31012
- if (month < 1 || month > 12) return null;
31013
- const probe = /* @__PURE__ */ new Date(0);
31014
- probe.setUTCFullYear(year, month, 0);
31015
- if (day < 1 || day > probe.getUTCDate()) return null;
31016
- if (hour > 23 || minute > 59 || second > 59) return null;
31017
- let offsetMinutes = 0;
31018
- if (!zulu) {
31019
- const offsetHours = Number(oh);
31020
- const offsetMins = Number(om);
31021
- if (offsetHours > 23 || offsetMins > 59) return null;
31022
- offsetMinutes = (sign === "-" ? -1 : 1) * (offsetHours * 60 + offsetMins);
31023
- }
31024
- const millis = Number(frac.padEnd(3, "0").slice(0, 3));
31025
- const instant = /* @__PURE__ */ new Date(0);
31026
- instant.setUTCFullYear(year, month - 1, day);
31027
- instant.setUTCHours(hour, minute, second, millis);
31028
- const remainder = rounding === "ceil" && /[1-9]/.test(frac.slice(3)) ? 1 : 0;
31029
- return instant.getTime() - offsetMinutes * 6e4 + remainder;
31030
- }
31031
-
31032
- // ../core/src/freshness.ts
31033
- function parseTimestamp(ts, okfVersion) {
31034
- if (okfVersion === "0.2") return typeof ts === "string" ? parseIsoInstant(ts) : null;
31035
- if (ts instanceof Date) {
31036
- const ms2 = ts.getTime();
31037
- return Number.isNaN(ms2) ? null : ms2;
31038
- }
31039
- if (typeof ts === "number") {
31040
- return Number.isFinite(ts) ? ts : null;
31041
- }
31042
- if (typeof ts !== "string" || ts.trim() === "") return null;
31043
- const ms = Date.parse(ts);
31044
- return Number.isNaN(ms) ? null : ms;
31045
- }
31046
-
31047
- // ../core/src/okf-lifecycle.ts
31048
- var OKF_LIFECYCLE_STATUSES = Object.freeze(["draft", "stable", "deprecated"]);
31049
- function isOkfLifecycleStatus(value) {
31050
- return typeof value === "string" && OKF_LIFECYCLE_STATUSES.includes(value);
31051
- }
31052
-
31053
- // ../core/src/mutation-attribution.ts
31054
- var SUPERBEE_UPDATED_BY_FIELD = "superbee_updated_by";
31055
- function nonEmptyString(value) {
31056
- return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
31057
- }
31058
- function mutationActorFromFrontmatter(frontmatter2) {
31059
- return nonEmptyString(frontmatter2[SUPERBEE_UPDATED_BY_FIELD]) ?? nonEmptyString(frontmatter2.updated_by) ?? nonEmptyString(frontmatter2.actor);
31060
- }
31061
-
31062
30985
  // ../core/src/paths.ts
31063
30986
  var RESERVED_FILENAMES = ["index.md", "log.md"];
31064
30987
  function compareStorageKeys(a, b) {
@@ -31111,6 +31034,8 @@ function assertSafeConceptId(id) {
31111
31034
  );
31112
31035
  }
31113
31036
  }
31037
+ var FORMAT_AT_EDGE = new RegExp("^\\p{Cf}|\\p{Cf}$", "u");
31038
+ var FORMAT_INSIDE = new RegExp("(?![\\u200c\\u200d])\\p{Cf}", "u");
31114
31039
  function assertSafeBlobKey(key) {
31115
31040
  if (typeof key !== "string" || key.trim() === "") {
31116
31041
  throw new InvalidInputError("Blob key must be a non-empty string.");
@@ -31153,7 +31078,8 @@ function isExternalHref(href) {
31153
31078
  const h = href.trim();
31154
31079
  return /^[a-z][a-z0-9+.-]*:\/\//i.test(h) || h.startsWith("mailto:") || h.startsWith("#");
31155
31080
  }
31156
- function extractMarkdownLinks(body) {
31081
+ function extractMarkdownLinks(source, options = {}) {
31082
+ const body = options.skipCode ? maskMarkdownCode(source) : source;
31157
31083
  const out = [];
31158
31084
  let textOpen = -1;
31159
31085
  let afterClose;
@@ -31165,8 +31091,8 @@ function extractMarkdownLinks(body) {
31165
31091
  if (char === ")") {
31166
31092
  if (hrefRest.open === 0 || body[hrefRest.open - 1] !== "!") {
31167
31093
  out.push({
31168
- text: body.slice(hrefRest.open + 1, hrefRest.close),
31169
- href: body.slice(hrefRest.hrefStart, cursor)
31094
+ text: source.slice(hrefRest.open + 1, hrefRest.close),
31095
+ href: source.slice(hrefRest.hrefStart, cursor)
31170
31096
  });
31171
31097
  }
31172
31098
  textOpen = -1;
@@ -31197,6 +31123,150 @@ function extractMarkdownLinks(body) {
31197
31123
  }
31198
31124
  return out;
31199
31125
  }
31126
+ function leadingIndent(line, from, startColumn) {
31127
+ let columns = 0;
31128
+ let index2 = from;
31129
+ while (index2 < line.length) {
31130
+ const char = line[index2];
31131
+ if (char === " ") columns += 1;
31132
+ else if (char === " ") columns += 4 - (startColumn + columns) % 4;
31133
+ else break;
31134
+ index2++;
31135
+ }
31136
+ return { columns, chars: index2 - from };
31137
+ }
31138
+ var FENCE_OPEN = /^(`{3,}|~{3,})(.*)$/;
31139
+ var LIST_MARKER = /^([-+*]|\d{1,9}[.)])([ \t]+|$)/;
31140
+ var THEMATIC_BREAK = /^(?:(?:\*[ \t]*){3,}|(?:-[ \t]*){3,}|(?:_[ \t]*){3,})$/;
31141
+ var ATX_HEADING = /^#{1,6}(?:[ \t]|$)/;
31142
+ function maskMarkdownCode(body) {
31143
+ const out = body.split("");
31144
+ const blank = (from, to) => {
31145
+ for (let index2 = from; index2 < to; index2++) if (out[index2] !== "\n" && out[index2] !== "\r") out[index2] = " ";
31146
+ };
31147
+ const lists = [];
31148
+ let fence = null;
31149
+ let inParagraph = false;
31150
+ let segmentStart = -1;
31151
+ const closeSegment = (end) => {
31152
+ if (segmentStart >= 0) maskCodeSpans(body, segmentStart, end, blank);
31153
+ segmentStart = -1;
31154
+ };
31155
+ let lineStart = 0;
31156
+ while (lineStart <= body.length) {
31157
+ const newline = body.indexOf("\n", lineStart);
31158
+ const lineEnd = newline < 0 ? body.length : newline;
31159
+ const line = body.slice(lineStart, lineEnd);
31160
+ let contentAt = 0;
31161
+ let quotes = 0;
31162
+ for (let match = /^ {0,3}> ?/.exec(line); match; match = /^ {0,3}> ?/.exec(line.slice(contentAt))) {
31163
+ if (fence && quotes >= fence.quotes) break;
31164
+ contentAt += match[0].length;
31165
+ quotes++;
31166
+ }
31167
+ const { columns: indent2, chars } = leadingIndent(line, contentAt, contentAt);
31168
+ const rest = line.slice(contentAt + chars).replace(/\r$/, "");
31169
+ const isBlank = rest.trim() === "";
31170
+ if (fence && (quotes < fence.quotes || !isBlank && indent2 < fence.container)) fence = null;
31171
+ if (fence) {
31172
+ const close = indent2 - fence.container <= 3 ? FENCE_OPEN.exec(rest) : null;
31173
+ if (close && close[1][0] === fence.char && close[1].length >= fence.length && close[2].trim() === "") fence = null;
31174
+ blank(lineStart, lineEnd);
31175
+ } else if (isBlank) {
31176
+ closeSegment(lineStart);
31177
+ inParagraph = false;
31178
+ } else {
31179
+ if (!inParagraph) while (lists.length > 0 && lists[lists.length - 1] > indent2) lists.pop();
31180
+ let container = lists.length > 0 ? lists[lists.length - 1] : 0;
31181
+ let relative = indent2 - container;
31182
+ let text4 = rest;
31183
+ let textAt = lineStart + contentAt + chars;
31184
+ const marker = relative <= 3 && !THEMATIC_BREAK.test(text4) ? LIST_MARKER.exec(text4) : null;
31185
+ if (marker) {
31186
+ closeSegment(lineStart);
31187
+ const markerEnd = indent2 + marker[1].length;
31188
+ const spacing = leadingIndent(marker[2], 0, contentAt + markerEnd).columns;
31189
+ const wide = marker[2] === "" || spacing >= 5;
31190
+ lists.push(markerEnd + (wide ? 1 : spacing));
31191
+ container = lists[lists.length - 1];
31192
+ text4 = text4.slice(marker[1].length + (wide ? 0 : marker[2].length));
31193
+ textAt += marker[1].length + (wide ? 0 : marker[2].length);
31194
+ relative = wide ? Math.max(spacing - 1, 0) : 0;
31195
+ inParagraph = false;
31196
+ }
31197
+ const open = relative <= 3 ? FENCE_OPEN.exec(text4) : null;
31198
+ if (open && !(open[1][0] === "`" && open[2].includes("`"))) {
31199
+ closeSegment(lineStart);
31200
+ fence = { char: open[1][0], length: open[1].length, container, quotes };
31201
+ blank(textAt, lineEnd);
31202
+ inParagraph = false;
31203
+ } else if (!inParagraph && relative >= 4) {
31204
+ closeSegment(lineStart);
31205
+ blank(textAt, lineEnd);
31206
+ } else if (ATX_HEADING.test(text4) || THEMATIC_BREAK.test(text4)) {
31207
+ closeSegment(lineStart);
31208
+ maskCodeSpans(body, textAt, lineEnd, blank);
31209
+ inParagraph = false;
31210
+ } else {
31211
+ if (segmentStart < 0) segmentStart = textAt;
31212
+ inParagraph = text4.trim() !== "";
31213
+ }
31214
+ }
31215
+ if (newline < 0) break;
31216
+ lineStart = newline + 1;
31217
+ }
31218
+ closeSegment(body.length);
31219
+ return out.join("");
31220
+ }
31221
+ function maskCodeSpans(body, from, to, blank) {
31222
+ const runs = [];
31223
+ for (let index2 = from; index2 < to; ) {
31224
+ if (body[index2] !== "`") {
31225
+ index2++;
31226
+ continue;
31227
+ }
31228
+ let end = index2;
31229
+ while (end < to && body[end] === "`") end++;
31230
+ runs.push({ at: index2, length: end - index2 });
31231
+ index2 = end;
31232
+ }
31233
+ const byLength = /* @__PURE__ */ new Map();
31234
+ runs.forEach((run, position2) => {
31235
+ const list3 = byLength.get(run.length);
31236
+ if (list3) list3.push(position2);
31237
+ else byLength.set(run.length, [position2]);
31238
+ });
31239
+ const next = /* @__PURE__ */ new Map();
31240
+ const nextRun = (length, after) => {
31241
+ const list3 = byLength.get(length);
31242
+ if (!list3) return -1;
31243
+ let cursor = next.get(length) ?? 0;
31244
+ while (cursor < list3.length && list3[cursor] <= after) cursor++;
31245
+ next.set(length, cursor);
31246
+ return cursor < list3.length ? list3[cursor] : -1;
31247
+ };
31248
+ let escapeScan = from;
31249
+ let escaped = false;
31250
+ for (let position2 = 0; position2 < runs.length; position2++) {
31251
+ let { at, length } = runs[position2];
31252
+ for (; escapeScan < at; escapeScan++) escaped = body[escapeScan] === "\\" ? !escaped : false;
31253
+ if (escaped) {
31254
+ at += 1;
31255
+ length -= 1;
31256
+ escaped = false;
31257
+ if (length === 0) continue;
31258
+ const list3 = byLength.get(length);
31259
+ if (!list3) continue;
31260
+ }
31261
+ const closer = nextRun(length, position2);
31262
+ if (closer < 0) continue;
31263
+ const close = runs[closer];
31264
+ blank(at, close.at + close.length);
31265
+ position2 = closer;
31266
+ escapeScan = close.at + close.length;
31267
+ escaped = false;
31268
+ }
31269
+ }
31200
31270
  function resolveConceptId(fromId, href) {
31201
31271
  const target = (href.split("#")[0] ?? "").split("?")[0]?.trim() ?? "";
31202
31272
  if (target === "" || isExternalHref(target)) return null;
@@ -31230,6 +31300,102 @@ function parseLinksFromDoc(doc) {
31230
31300
  return links;
31231
31301
  }
31232
31302
 
31303
+ // ../core/src/version-transport.ts
31304
+ function isContentVersion(value) {
31305
+ return typeof value === "string" && /^sha256:[0-9a-f]{64}$/.test(value);
31306
+ }
31307
+ var VersionConflict = class extends Error {
31308
+ name = "VersionConflict";
31309
+ id;
31310
+ expected;
31311
+ actual;
31312
+ constructor(id, expected, actual) {
31313
+ super(
31314
+ `version conflict on '${id}': expected ${expected ?? "absent"}, found ${actual ?? "none"} (the document changed since you read it \u2014 re-read and retry)`
31315
+ );
31316
+ this.id = id;
31317
+ this.expected = expected;
31318
+ this.actual = actual;
31319
+ }
31320
+ };
31321
+
31322
+ // ../core/src/meaningful-change-time.ts
31323
+ function meaningfulChangeTimeField(frontmatter2) {
31324
+ const generated = frontmatter2.generated;
31325
+ if (generated !== null && typeof generated === "object" && !Array.isArray(generated) && generated.at !== void 0) return "generated.at";
31326
+ return "timestamp";
31327
+ }
31328
+ function meaningfulChangeTimeValue(frontmatter2) {
31329
+ return meaningfulChangeTimeField(frontmatter2) === "generated.at" ? frontmatter2.generated.at : frontmatter2.timestamp;
31330
+ }
31331
+
31332
+ // ../core/src/verification.ts
31333
+ var TRUST_TIERS = Object.freeze([
31334
+ "unverified",
31335
+ "machine-confirmed",
31336
+ "human-reviewed"
31337
+ ]);
31338
+ var ISO_INSTANT = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?(?:([Zz])|([+-])(\d{2})(?::?(\d{2}))?)$/;
31339
+ function parseIsoInstant(raw, rounding = "truncate") {
31340
+ const match = ISO_INSTANT.exec(raw);
31341
+ if (!match) return null;
31342
+ const [, y, mo, d, h, mi, sec = "0", frac = "0", zulu, sign, oh, om = "0"] = match;
31343
+ const year = Number(y);
31344
+ const month = Number(mo);
31345
+ const day = Number(d);
31346
+ const hour = Number(h);
31347
+ const minute = Number(mi);
31348
+ const second = Number(sec);
31349
+ if (month < 1 || month > 12) return null;
31350
+ const probe = /* @__PURE__ */ new Date(0);
31351
+ probe.setUTCFullYear(year, month, 0);
31352
+ if (day < 1 || day > probe.getUTCDate()) return null;
31353
+ if (hour > 23 || minute > 59 || second > 59) return null;
31354
+ let offsetMinutes = 0;
31355
+ if (!zulu) {
31356
+ const offsetHours = Number(oh);
31357
+ const offsetMins = Number(om);
31358
+ if (offsetHours > 23 || offsetMins > 59) return null;
31359
+ offsetMinutes = (sign === "-" ? -1 : 1) * (offsetHours * 60 + offsetMins);
31360
+ }
31361
+ const millis = Number(frac.padEnd(3, "0").slice(0, 3));
31362
+ const instant = /* @__PURE__ */ new Date(0);
31363
+ instant.setUTCFullYear(year, month - 1, day);
31364
+ instant.setUTCHours(hour, minute, second, millis);
31365
+ const remainder = rounding === "ceil" && /[1-9]/.test(frac.slice(3)) ? 1 : 0;
31366
+ return instant.getTime() - offsetMinutes * 6e4 + remainder;
31367
+ }
31368
+
31369
+ // ../core/src/freshness.ts
31370
+ function parseTimestamp(ts, okfVersion) {
31371
+ if (okfVersion === "0.2") return typeof ts === "string" ? parseIsoInstant(ts) : null;
31372
+ if (ts instanceof Date) {
31373
+ const ms2 = ts.getTime();
31374
+ return Number.isNaN(ms2) ? null : ms2;
31375
+ }
31376
+ if (typeof ts === "number") {
31377
+ return Number.isFinite(ts) ? ts : null;
31378
+ }
31379
+ if (typeof ts !== "string" || ts.trim() === "") return null;
31380
+ const ms = Date.parse(ts);
31381
+ return Number.isNaN(ms) ? null : ms;
31382
+ }
31383
+
31384
+ // ../core/src/okf-lifecycle.ts
31385
+ var OKF_LIFECYCLE_STATUSES = Object.freeze(["draft", "stable", "deprecated"]);
31386
+ function isOkfLifecycleStatus(value) {
31387
+ return typeof value === "string" && OKF_LIFECYCLE_STATUSES.includes(value);
31388
+ }
31389
+
31390
+ // ../core/src/mutation-attribution.ts
31391
+ var SUPERBEE_UPDATED_BY_FIELD = "superbee_updated_by";
31392
+ function nonEmptyString(value) {
31393
+ return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
31394
+ }
31395
+ function mutationActorFromFrontmatter(frontmatter2) {
31396
+ return nonEmptyString(frontmatter2[SUPERBEE_UPDATED_BY_FIELD]) ?? nonEmptyString(frontmatter2.updated_by) ?? nonEmptyString(frontmatter2.actor);
31397
+ }
31398
+
31233
31399
  // ../core/src/portable-frontmatter.ts
31234
31400
  var import_js_yaml2 = __toESM(require_js_yaml2(), 1);
31235
31401
  function parseLeadingFrontmatter(raw, context) {
@@ -31269,13 +31435,22 @@ function matchesFilter(doc, filter) {
31269
31435
  }
31270
31436
  return true;
31271
31437
  }
31272
- function matchesSourceIdentity(entry, identity) {
31273
- if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return false;
31438
+ function sourceIdentityOf(entry) {
31439
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return void 0;
31274
31440
  const row = entry;
31441
+ const identity = {};
31442
+ for (const key of ["resource", "id"]) {
31443
+ if (Object.hasOwn(row, key) && typeof row[key] === "string") identity[key] = row[key];
31444
+ }
31445
+ return identity;
31446
+ }
31447
+ function matchesSourceIdentity(entry, identity) {
31448
+ const own3 = sourceIdentityOf(entry);
31449
+ if (!own3) return false;
31275
31450
  for (const key of ["resource", "id"]) {
31276
31451
  const expected = identity[key];
31277
31452
  if (expected === void 0) continue;
31278
- if (!Object.hasOwn(row, key) || typeof row[key] !== "string" || row[key] !== expected) return false;
31453
+ if (own3[key] === void 0 || own3[key] !== expected) return false;
31279
31454
  }
31280
31455
  return true;
31281
31456
  }
@@ -32655,25 +32830,6 @@ function sha256HexOfUtf8(input) {
32655
32830
  return sha256HexOfBytes(encoder.encode(input));
32656
32831
  }
32657
32832
 
32658
- // ../core/src/version-transport.ts
32659
- function isContentVersion(value) {
32660
- return typeof value === "string" && /^sha256:[0-9a-f]{64}$/.test(value);
32661
- }
32662
- var VersionConflict = class extends Error {
32663
- name = "VersionConflict";
32664
- id;
32665
- expected;
32666
- actual;
32667
- constructor(id, expected, actual) {
32668
- super(
32669
- `version conflict on '${id}': expected ${expected ?? "absent"}, found ${actual ?? "none"} (the document changed since you read it \u2014 re-read and retry)`
32670
- );
32671
- this.id = id;
32672
- this.expected = expected;
32673
- this.actual = actual;
32674
- }
32675
- };
32676
-
32677
32833
  // ../core/src/versioning.ts
32678
32834
  function sha256Hex(input) {
32679
32835
  return sha256HexOfUtf8(input);
@@ -33028,6 +33184,23 @@ setDefaultBackendFactory((root) => new FilesystemBackend(root));
33028
33184
  // ../core/src/kinds.ts
33029
33185
  var CONVENTIONS_PREFIX = "conventions/";
33030
33186
  var CONVENTION_TYPE = "Convention";
33187
+ var KIND_FIELD_TYPES = [
33188
+ "date",
33189
+ "datetime",
33190
+ "https-url",
33191
+ "https-url-list",
33192
+ "integer",
33193
+ "number",
33194
+ "boolean",
33195
+ "slug",
33196
+ "string-list",
33197
+ "latitude",
33198
+ "longitude"
33199
+ ];
33200
+ var KIND_FIELD_TYPE_SET = new Set(KIND_FIELD_TYPES);
33201
+ function isKindFieldType(value) {
33202
+ return typeof value === "string" && KIND_FIELD_TYPE_SET.has(value);
33203
+ }
33031
33204
  function buildKindRegistry(docs, initialWarnings = [], options = {}) {
33032
33205
  const accepted = /* @__PURE__ */ new Map();
33033
33206
  const warnings = [...initialWarnings];
@@ -33179,7 +33352,8 @@ var VALID_FIELDS_KEYS = /* @__PURE__ */ new Set([
33179
33352
  "values",
33180
33353
  "value_descriptions",
33181
33354
  "terminal",
33182
- "descriptions"
33355
+ "descriptions",
33356
+ "types"
33183
33357
  ]);
33184
33358
  var MISPLACED_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["enum", "enums", "values", "constraints"]);
33185
33359
  var CLAIM_COORDINATE_KEYS = [
@@ -33219,7 +33393,7 @@ function parseConventionDoc(doc, options = {}) {
33219
33393
  if (!VALID_FIELDS_KEYS.has(key)) {
33220
33394
  warnings.push({
33221
33395
  code: "KIND_CONVENTION_UNKNOWN_FIELDS_KEY",
33222
- message: `kind convention '${doc.id}' declares an unrecognized key 'fields.${key}' (valid keys: fields.required, fields.optional, fields.values, fields.value_descriptions, fields.terminal, fields.descriptions); ignoring it.`,
33396
+ message: `kind convention '${doc.id}' declares an unrecognized key 'fields.${key}' (valid keys: fields.required, fields.optional, fields.values, fields.value_descriptions, fields.terminal, fields.descriptions, fields.types); ignoring it.`,
33223
33397
  field: `fields.${key}`,
33224
33398
  severity: "warning"
33225
33399
  });
@@ -33276,6 +33450,51 @@ function parseConventionDoc(doc, options = {}) {
33276
33450
  });
33277
33451
  }
33278
33452
  }
33453
+ const typesSource = fieldsRaw.types;
33454
+ const types = {};
33455
+ if (typesSource !== void 0) {
33456
+ if (!isPlainObject(typesSource)) {
33457
+ warnings.push({
33458
+ code: "KIND_CONVENTION_BAD_SHAPE",
33459
+ message: `kind convention '${doc.id}' has a non-map 'fields.types' (${describeShape(typesSource)}; expected a map of field name -> type); ignoring it.`,
33460
+ field: "fields.types",
33461
+ severity: "warning"
33462
+ });
33463
+ } else {
33464
+ for (const [field, declared] of Object.entries(typesSource)) {
33465
+ if (dropReserved(field, `fields.types.${field}`)) continue;
33466
+ if (!isKindFieldType(declared)) {
33467
+ warnings.push({
33468
+ code: "KIND_CONVENTION_UNKNOWN_FIELD_TYPE",
33469
+ message: `kind convention '${doc.id}' declares 'fields.types.${field}' as ${isScalar(declared) ? `'${String(declared)}'` : describeShape(declared)}, which is not a field type (valid types: ${KIND_FIELD_TYPES.join(", ")}); ignoring it.`,
33470
+ field: `fields.types.${field}`,
33471
+ severity: "warning"
33472
+ });
33473
+ continue;
33474
+ }
33475
+ if (!declaredFieldNames.has(field)) {
33476
+ warnings.push({
33477
+ code: "KIND_CONVENTION_UNDECLARED_TYPES_FIELD",
33478
+ message: `kind convention '${doc.id}' declares 'fields.types.${field}' but '${field}' is not in fields.required or fields.optional; ignoring it.`,
33479
+ field: `fields.types.${field}`,
33480
+ severity: "warning"
33481
+ });
33482
+ continue;
33483
+ }
33484
+ setOwn(types, field, declared);
33485
+ }
33486
+ }
33487
+ }
33488
+ for (const field of Object.keys(values)) {
33489
+ if (types[field] !== "https-url-list") continue;
33490
+ warnings.push({
33491
+ code: "KIND_CONVENTION_VALUES_TYPE_MISMATCH",
33492
+ message: `kind convention '${doc.id}' declares 'fields.values.${field}' on a field of type 'https-url-list', which cannot carry an enum; ignoring the values.`,
33493
+ field: `fields.values.${field}`,
33494
+ severity: "warning"
33495
+ });
33496
+ delete values[field];
33497
+ }
33279
33498
  const valueDescriptionsSource = fieldsRaw.value_descriptions;
33280
33499
  const valueDescriptions = {};
33281
33500
  if (valueDescriptionsSource !== void 0) {
@@ -33568,6 +33787,7 @@ function parseConventionDoc(doc, options = {}) {
33568
33787
  governs,
33569
33788
  fields: { required, optional, values, valueDescriptions, terminal, descriptions }
33570
33789
  };
33790
+ if (Object.keys(types).length > 0) kind2.fields.types = types;
33571
33791
  if (description !== void 0) kind2.description = description;
33572
33792
  if (path6 !== void 0) kind2.path = path6;
33573
33793
  if (links !== void 0) kind2.links = links;
@@ -42627,6 +42847,10 @@ function gfmFromMarkdown() {
42627
42847
 
42628
42848
  // ../markdown-renderer/src/index.tsx
42629
42849
  var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
42850
+ function renderableConceptId(fromId, raw) {
42851
+ if (/^okf:/i.test(raw.trim())) return null;
42852
+ return resolveConceptId(fromId, raw);
42853
+ }
42630
42854
  var MAX_BODY_CHARS = 262144;
42631
42855
  var MAX_NODES = 2e4;
42632
42856
  var MAX_DEPTH = 40;
@@ -42642,6 +42866,9 @@ function textOf(node2) {
42642
42866
  if (!Array.isArray(children)) return "";
42643
42867
  return children.map((child) => textOf(child)).join("");
42644
42868
  }
42869
+ function renderTextFallback(node2, index2) {
42870
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-markdown-fallback", children: textOf(node2) }, index2);
42871
+ }
42645
42872
  function isBlankInline(node2) {
42646
42873
  if (node2.type === "break") return true;
42647
42874
  if (node2.type === "text") return (node2.value ?? "").trim() === "";
@@ -42652,7 +42879,7 @@ function isBareLinkBlock(node2, fromId) {
42652
42879
  let sawLink = false;
42653
42880
  for (const child of node2.children) {
42654
42881
  if (isBlankInline(child)) continue;
42655
- if (child.type === "link" && resolveConceptId(fromId, child.url ?? "") !== null) {
42882
+ if (child.type === "link" && renderableConceptId(fromId, child.url ?? "") !== null) {
42656
42883
  sawLink = true;
42657
42884
  continue;
42658
42885
  }
@@ -42736,7 +42963,7 @@ function renderNode(node2, state, depth, index2) {
42736
42963
  state.count++;
42737
42964
  if (depth > MAX_DEPTH) {
42738
42965
  state.bounded = true;
42739
- return textOf(node2);
42966
+ return renderTextFallback(node2, index2);
42740
42967
  }
42741
42968
  switch (node2.type) {
42742
42969
  case "text":
@@ -42780,7 +43007,7 @@ function renderNode(node2, state, depth, index2) {
42780
43007
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}, index2);
42781
43008
  case "link": {
42782
43009
  const raw = node2.url ?? "";
42783
- const resolved = resolveConceptId(state.options.fromId, raw);
43010
+ const resolved = renderableConceptId(state.options.fromId, raw);
42784
43011
  const children = renderChildren(node2, state, depth);
42785
43012
  if (resolved === null) {
42786
43013
  const external = admitExternalLink(raw, state.options.externalLinkHosts);
@@ -42837,7 +43064,7 @@ function renderNode(node2, state, depth, index2) {
42837
43064
  case "html":
42838
43065
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-raw-html", children: node2.value }, index2);
42839
43066
  default:
42840
- return textOf(node2);
43067
+ return renderTextFallback(node2, index2);
42841
43068
  }
42842
43069
  }
42843
43070
  function renderEdgeList(links, state, index2) {
@@ -42849,14 +43076,14 @@ function renderEdgeList(links, state, index2) {
42849
43076
  break;
42850
43077
  }
42851
43078
  state.count++;
42852
- const to = resolveConceptId(fromId, links[i].url ?? "");
43079
+ const to = renderableConceptId(fromId, links[i].url ?? "");
42853
43080
  if (to === null) continue;
42854
43081
  const verb = textOf(links[i]).trim();
42855
43082
  const target = titleFor?.(to) ?? to;
42856
43083
  if (state.options.profile === "inert") {
42857
43084
  rows.push(
42858
43085
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "doc-edge-row", "data-aslite-doc-id": to, children: [
42859
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-edge-verb", children: verb }),
43086
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-edge-verb doc-markdown-fallback", children: verb }),
42860
43087
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-edge-arrow", "aria-hidden": "true", children: "\u2192" }),
42861
43088
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-edge-target", children: target })
42862
43089
  ] }, i)
@@ -42871,7 +43098,7 @@ function renderEdgeList(links, state, index2) {
42871
43098
  href: documentHref(to, state.options),
42872
43099
  onClick: (event) => navigateDoc(event, to, state.options),
42873
43100
  children: [
42874
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-edge-verb", children: verb }),
43101
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-edge-verb doc-markdown-fallback", children: verb }),
42875
43102
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-edge-arrow", "aria-hidden": "true", children: "\u2192" }),
42876
43103
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "doc-edge-target", children: target })
42877
43104
  ]