@rse/specbook 0.9.6 → 0.9.8

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.
Files changed (41) hide show
  1. package/README.md +65 -10
  2. package/dst/specbook-api.js +19 -18
  3. package/dst/specbook-cli.js +9 -6
  4. package/dst/specbook-cmd-describe.js +1 -3
  5. package/dst/specbook-cmd-export.js +24 -17
  6. package/dst/specbook-cmd-init.d.ts +1 -1
  7. package/dst/specbook-cmd-init.js +5 -4
  8. package/dst/specbook-cmd-lint.d.ts +0 -1
  9. package/dst/specbook-cmd-lint.js +29 -5
  10. package/dst/specbook-config.d.ts +1 -1
  11. package/dst/specbook-config.js +90 -71
  12. package/dst/specbook-diagnostic.js +4 -1
  13. package/dst/specbook-diagram.d.ts +8 -3
  14. package/dst/specbook-diagram.js +101 -105
  15. package/dst/specbook-export-ast.d.ts +1 -1
  16. package/dst/specbook-export-ast.js +1 -1
  17. package/dst/specbook-export-common.d.ts +2 -1
  18. package/dst/specbook-export-common.js +12 -14
  19. package/dst/specbook-export-html-search.js +10 -14
  20. package/dst/specbook-export-html.css +24 -29
  21. package/dst/specbook-export-html.js +101 -83
  22. package/dst/specbook-export-md.d.ts +1 -1
  23. package/dst/specbook-export-md.js +56 -23
  24. package/dst/specbook-export-pdf.d.ts +4 -2
  25. package/dst/specbook-export-pdf.js +48 -38
  26. package/dst/specbook-format-schema.js +6 -3
  27. package/dst/specbook-format.md +47 -20
  28. package/dst/specbook-link.d.ts +1 -0
  29. package/dst/specbook-link.js +7 -4
  30. package/dst/specbook-mcp.js +17 -10
  31. package/dst/specbook-parse-common.d.ts +2 -1
  32. package/dst/specbook-parse-common.js +2 -0
  33. package/dst/specbook-parse-semantic.d.ts +4 -2
  34. package/dst/specbook-parse-semantic.js +114 -43
  35. package/dst/specbook-parse-syntax.js +179 -137
  36. package/dst/specbook-parse-value.d.ts +1 -1
  37. package/dst/specbook-parse-value.js +9 -5
  38. package/dst/specbook-parse.d.ts +2 -5
  39. package/dst/specbook-parse.js +27 -34
  40. package/dst/specbook-verbose.js +2 -1
  41. package/package.json +1 -1
@@ -18,7 +18,7 @@
18
18
 
19
19
  /* shortest word still eligible for fuzzy matching: below it the
20
20
  edit distance would equate it with almost any short word */
21
- const FUZZY_MIN = 4
21
+ const fuzzyMin = 4
22
22
 
23
23
  /* the searchable units (paragraphs, list items, table rows, and
24
24
  headings), the corpus vocabulary, and the per-word cache of the
@@ -101,7 +101,7 @@
101
101
  if (result !== undefined)
102
102
  return result
103
103
  result = []
104
- if (word.length >= FUZZY_MIN)
104
+ if (word.length >= fuzzyMin)
105
105
  vocab.forEach((given) => {
106
106
  if (Math.abs(word.length - given.length) <= 1
107
107
  && (diceCoefficient(word, given) >= 0.50
@@ -115,19 +115,21 @@
115
115
  /* match a query word against a unit, as a literal substring or as
116
116
  a fuzzy variant, remembering the variants for the highlighting */
117
117
  const wordMatch = (word, unit, variants) => {
118
- if (unit.text.indexOf(word) >= 0)
118
+ if (unit.text.includes(word))
119
119
  return true
120
120
  const near = fuzzyWords(word).filter((v) => unit.words.has(v))
121
121
  near.forEach((v) => { variants.add(v) })
122
122
  return near.length > 0
123
123
  }
124
124
 
125
+ /* escape a text for its literal use inside a regular expression */
126
+ const escapeRegex = (s) =>
127
+ s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
128
+
125
129
  /* the alternation matching everything worth highlighting: the
126
130
  query words as plain substrings plus the fuzzy variants as
127
131
  whole words, longest alternative first, so a variant is never
128
132
  cut short by a query word nested inside it */
129
- const escapeRegex = (s) =>
130
- s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
131
133
  const buildRegex = (words, variants) => {
132
134
  const alts = words.map((w) => ({ len: w.length, src: escapeRegex(w) }))
133
135
  .concat(variants.map((v) => ({ len: v.length,
@@ -203,7 +205,7 @@
203
205
  units.forEach((unit) => { unit.keep = false })
204
206
  parts.forEach((part) => {
205
207
  let matched = units.filter((unit) =>
206
- part.every((word) => unit.text.indexOf(word) >= 0))
208
+ part.every((word) => unit.text.includes(word)))
207
209
  if (matched.length === 0)
208
210
  matched = units.filter((unit) =>
209
211
  part.every((word) => wordMatch(word, unit, variants)))
@@ -226,7 +228,7 @@
226
228
  const heading = section.firstElementChild
227
229
  if (heading !== null && /^H[1-6]$/.test(heading.tagName))
228
230
  heading.classList.add("search-keep")
229
- section = section.parentElement !== null ? section.parentElement.closest("section") : null
231
+ section = section.parentElement?.closest("section") ?? null
230
232
  }
231
233
  })
232
234
 
@@ -244,13 +246,7 @@
244
246
  })
245
247
 
246
248
  /* highlight every matched word within the kept units */
247
- const words = []
248
- parts.forEach((part) => {
249
- part.forEach((word) => {
250
- if (!words.includes(word))
251
- words.push(word)
252
- })
253
- })
249
+ const words = Array.from(new Set(parts.flat()))
254
250
  const regex = buildRegex(words, Array.from(variants))
255
251
  units.forEach((unit) => {
256
252
  if (unit.el.classList.contains("search-keep"))