@descent-vtt/spec-graph 0.18.0 → 0.19.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/extract.js CHANGED
@@ -351,11 +351,12 @@ const NEGATION = /(?:^|[^\p{L}\p{N}-])(?:no|not|no-one|nobody|none|never|neither
351
351
  * by" are read, and "not only blocked by" and "nothing but blocked by",
352
352
  * which state the relation, are not. Only a space stands between, so a
353
353
  * mark keeps the word to itself: the option `"never" blocked by` states the
354
- * relation, as "Not in this release: deferred to" does. A comma is blanked
355
- * before this is read, as it was, so "If not, blocked by" is cancelled: a
356
- * miss, kept so that a comma moves no phrase's reach. A contraction is a
357
- * negation, `isn't` and `doesn’t`, and so is `cannot`. Tested against the
358
- * text just before the phrase, which ends with the space before it.
354
+ * relation, as "Not in this release: deferred to" does. A comma does too,
355
+ * and ends the clause the word belongs to: "If not, blocked by" and "both
356
+ * or neither, because" state the relation, where with the comma blanked
357
+ * they were cancelled (ADR-0006, 2026-10-19). A contraction is a negation,
358
+ * `isn't` and `doesn’t`, and so is `cannot`. Tested against the text just
359
+ * before the phrase, which ends with the space or the comma before it.
359
360
  */
360
361
  const NEGATED_BEFORE = /(?:^|[^\p{L}\p{N}-])(?:no|not|no one|no-one|nobody|none|never|neither|nor|nothing|without|cannot|\p{L}+n['’]t)(?: (?:be|been|being|is|are|was|were|yet|longer|ever|even|currently|actually|really|necessarily|always))* $/u;
361
362
  /**
@@ -1276,7 +1277,7 @@ function ownerOf(items, offset) {
1276
1277
  * neutral citation.
1277
1278
  */
1278
1279
  export function classifyReference(text, start, end, section) {
1279
- const before = sentenceBefore(text, start);
1280
+ const { words: before, commas } = sentenceBefore(text, start);
1280
1281
  // Left to right, so the last match within the window is the nearest one - and
1281
1282
  // the nearest governing phrase is the one that governs. `matchAll`, not a
1282
1283
  // loop over `exec`: an empty match leaves `lastIndex` where it began, and
@@ -1292,10 +1293,11 @@ export function classifyReference(text, start, end, section) {
1292
1293
  continue;
1293
1294
  // What sits between the phrase and the reference has to be connective. A
1294
1295
  // negation in there reverses the claim the phrase would otherwise make,
1295
- // and so does one just before the phrase.
1296
+ // and so does one just before the phrase, where no comma ends its clause
1297
+ // first.
1296
1298
  if (NEGATION.test(before.slice(end)))
1297
1299
  continue;
1298
- if (NEGATED_BEFORE.test(before.slice(0, m.index)))
1300
+ if (NEGATED_BEFORE.test(commas.slice(0, m.index)))
1299
1301
  continue;
1300
1302
  // Always found: the pattern was compiled from this table's own keys, and a
1301
1303
  // lower-cased search matches them only as written. The check is for types.
@@ -1358,17 +1360,26 @@ const STATEMENT_BREAK = /[.?!;]\s|[。?!;]|\n\s*\n|\n\s*[-*+>#]|\|/g;
1358
1360
  * names a word, and `isn't` is one word. Kept, each counts toward the
1359
1361
  * distance a phrase reaches where it stands beside a space, as a curly one
1360
1362
  * did (ADR-0006, 2026-10-18).
1363
+ *
1364
+ * The same text is given a second time with each run of spaces that held a
1365
+ * comma written as the comma: one character either way, so the two line up
1366
+ * and a comma counts toward no phrase's reach, and a negation before a
1367
+ * phrase is read from the second, where a comma keeps the two apart
1368
+ * (ADR-0006, 2026-10-19).
1361
1369
  */
1362
1370
  function sentenceBefore(text, start) {
1363
1371
  const window = text.slice(Math.max(0, start - 160), start);
1364
1372
  let cut = 0;
1365
1373
  for (const m of window.matchAll(STATEMENT_BREAK))
1366
1374
  cut = m.index + m[0].length;
1367
- return window
1375
+ const statement = window
1368
1376
  .slice(cut)
1369
1377
  .toLowerCase()
1370
- .replace(/[`*_~()\[\],]/g, ' ')
1371
- .replace(/\s+/g, ' ');
1378
+ .replace(/[`*_~()\[\]]/g, ' ');
1379
+ return {
1380
+ words: statement.replace(/[\s,]+/g, ' '),
1381
+ commas: statement.replace(/[\s,]+/g, (run) => (run.includes(',') ? ',' : ' ')),
1382
+ };
1372
1383
  }
1373
1384
  /**
1374
1385
  * The statement after a reference, to the first stop, the stops of a sentence