diff --git a/lib/examples.mjs b/lib/examples.mjs
index 09aedcf..754e0ab 100644
--- a/lib/examples.mjs
+++ b/lib/examples.mjs
@@ -104,23 +104,29 @@ export function catalogueFiles() {
*
text the summary sentence (normal type)
*
text the search terms, then the docs links
*/
-const ROW = /^\|\s*(?:\*\*(?
[^*]+)\*\*\s*(?:—|--)\s*)?(?[^|<]*?)\s*(?(?:
(?:[^<]*<\/sub>|[^<]*))*)\s*\|\s*\[`(?[A-Z0-9_]+)`\]\((?[^)]+)\)\s*\|/;
+const ROW = /^\|\s*(?:\*\*(?[^*]+)\*\*\s*(?:—|--)\s*)?(?[^|<]*?)\s*(?(?:
(?:<[a-z]+>[^<]*<\/[a-z]+>|[^<]*))*)\s*\|\s*\[`(?[A-Z0-9_]+)`\]\((?[^)]+)\)\s*\|/;
-/** The blocks under a row title, in order, as `{ small, text }`. */
+/* The blocks under a row title, in order, as `{ tag, text }`.
+ *
+ * A block wrapped in a tag nobody here knows is kept as a block with that tag
+ * and then ignored by both readers below - which is the whole reason the row
+ * pattern accepts any tag rather than `` alone. Twice now a new KIND of
+ * block has made every row unmatchable over here, and that failure reads as
+ * "there are no samples for that" rather than as a parse error. */
function blocksOf(blocks) {
- return [...(blocks || '').matchAll(/
(?:([^<]*)<\/sub>|([^<]*))/g)]
+ return [...(blocks || '').matchAll(/
(?:<([a-z]+)>([^<]*)<\/[a-z]+>|([^<]*))/g)]
.map((m) => (m[1] !== undefined
- ? { small: true, text: m[1].trim() }
- : { small: false, text: (m[2] || '').trim() }))
+ ? { tag: m[1], text: (m[2] || '').trim() }
+ : { tag: '', text: (m[3] || '').trim() }))
.filter((b) => b.text);
}
-/** The sentence: the first block in NORMAL type. */
-const summaryOf = (blocks) => (blocksOf(blocks).find((b) => !b.small)?.text || '');
+/** The sentence: the first block in NORMAL type (no tag at all). */
+const summaryOf = (blocks) => (blocksOf(blocks).find((b) => !b.tag)?.text || '');
-/** The keywords: the first SMALL block that is not the `docs:` one. */
+/** The keywords: the first `` block that is not the `docs:` one. */
const keywordsOf = (blocks) =>
- (blocksOf(blocks).find((b) => b.small && !b.text.startsWith('docs:'))?.text || '');
+ (blocksOf(blocks).find((b) => b.tag === 'sub' && !b.text.startsWith('docs:'))?.text || '');
/** src/01 is the supported set; src/00 is experimental (97) or a test app (98). */
const areaOf = (repo, p) => {
diff --git a/test/unit.test.mjs b/test/unit.test.mjs
index be0fa92..62a2b93 100644
--- a/test/unit.test.mjs
+++ b/test/unit.test.mjs
@@ -429,6 +429,27 @@ test('a row without a summary still parses', () => {
assert.equal(e.keywords, 'f4 search help suggestion input');
});
+/* The row shape is maintained in three OTHER repositories, and a new kind of
+ * block has twice made every row unmatchable here. A block whose tag this
+ * parser has never seen must cost it nothing - the sample still has to be
+ * findable, because "no rows parsed" reads as "there are no samples for that"
+ * rather than as a parse error. */
+test('a row survives a block this parser has never seen', () => {
+ const md = [
+ '## Basics',
+ '',
+ '| Sample | Class |',
+ '|---|---|',
+ '| **Future** — Something
The sentence.
a block from a later generator
terms here | [`Z2UI5_CL_SMP_APP_999`](src/01/z2ui5_cl_smp_app_999.clas.abap) |',
+ ].join('\n');
+ const [e] = parseExamples(md);
+ assert.ok(e, 'the row with an unknown block was dropped');
+ assert.equal(e.cls, 'Z2UI5_CL_SMP_APP_999');
+ // and the two blocks this parser DOES read are still told apart correctly
+ assert.equal(e.summary, 'The sentence.');
+ assert.equal(e.keywords, 'terms here');
+});
+
test('every catalogue names its repository and its env var when it is missing', () => {
assert.deepEqual(CATALOGUES.map((c) => c.repo), ['samples', 'samples-controls', 'samples-stack']);
for (const c of CATALOGUES) {