Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions scripts/build-graph.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -239,20 +239,39 @@ export function parseGlossary(repoRoot) {
const content = readFileSync(glossaryPath, "utf-8");
const terms = [];
let currentCategory = "";
const lines = content.split("\n");
const termPattern =
/^\*\*(?:\[([^\]]+)\]\(([^)]+)\)|([^*]+))\*\*:\s*(.*)/;

for (const line of content.split("\n")) {
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const catMatch = line.match(/^### (.+)/);
if (catMatch) {
currentCategory = catMatch[1].trim();
continue;
}
const termMatch = line.match(
/^\*\*(?:\[([^\]]+)\]\(([^)]+)\)|([^*]+))\*\*:\s*(.*)/,
);
const termMatch = line.match(termPattern);
if (termMatch) {
let definition = termMatch[4].trim();

// GLOSSARY.md occasionally puts a term's definition on the next line.
// Only consume the immediate continuation line, and never swallow the
// next category or glossary term if the definition is actually missing.
if (!definition) {
const continuation = lines[i + 1]?.trim();
if (
continuation &&
!continuation.startsWith("### ") &&
!termPattern.test(continuation)
) {
definition = continuation;
i += 1;
}
}

const term = {
term: (termMatch[1] ?? termMatch[3]).trim(),
definition: termMatch[4].trim(),
definition,
category: currentCategory,
};
if (termMatch[2]) term.href = termMatch[2].trim();
Expand Down
2 changes: 1 addition & 1 deletion src/data/glossary.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
},
{
"term": "Data Availability Layer (DA Layer)",
"definition": "",
"definition": "A dedicated network or service that publishes and stores the data required for DA (for example, rollup or application data), separate from the main execution chain.",
"category": "Blockchain Architecture"
},
{
Expand Down
87 changes: 87 additions & 0 deletions tests/build-graph.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,93 @@ describe('classifyEdge', () => {
// ---------------------------------------------------------------------------

describe('parseGlossary', () => {
it('reads a definition from the immediate continuation line', () => {
const repoRoot = mkdtempSync(join(tmpdir(), 'ethsystems-glossary-'));
try {
writeFileSync(
join(repoRoot, 'GLOSSARY.md'),
`### Blockchain Architecture

**Data Availability Layer (DA Layer)**:
A dedicated network or service that publishes and stores the data required for DA.

**Sequencer**: Orders L2 transactions.
`,
);

const glossary = parseGlossary(repoRoot);

expect(glossary).toHaveLength(2);
expect(glossary[0]).toEqual({
term: 'Data Availability Layer (DA Layer)',
definition:
'A dedicated network or service that publishes and stores the data required for DA.',
category: 'Blockchain Architecture',
});
expect(glossary[1]).toEqual({
term: 'Sequencer',
definition: 'Orders L2 transactions.',
category: 'Blockchain Architecture',
});
} finally {
rmSync(repoRoot, { recursive: true, force: true });
}
});

it('does not consume the next term when a definition is missing', () => {
const repoRoot = mkdtempSync(join(tmpdir(), 'ethsystems-glossary-'));
try {
writeFileSync(
join(repoRoot, 'GLOSSARY.md'),
`### Blockchain Architecture

**Missing Definition**:
**Sequencer**: Orders L2 transactions.
`,
);

const glossary = parseGlossary(repoRoot);

expect(glossary).toHaveLength(2);
expect(glossary[0].definition).toBe('');
expect(glossary[1].definition).toBe('Orders L2 transactions.');
} finally {
rmSync(repoRoot, { recursive: true, force: true });
}
});

it('does not consume the next category when a definition is missing', () => {
const repoRoot = mkdtempSync(join(tmpdir(), 'ethsystems-glossary-'));
try {
writeFileSync(
join(repoRoot, 'GLOSSARY.md'),
`### Blockchain Architecture

**Missing Definition**:
### Next Category

**Sequencer**: Orders L2 transactions.
`,
);

const glossary = parseGlossary(repoRoot);

expect(glossary).toHaveLength(2);
expect(glossary[0]).toEqual({
term: 'Missing Definition',
definition: '',
category: 'Blockchain Architecture',
});
expect(glossary[1]).toEqual({
term: 'Sequencer',
definition: 'Orders L2 transactions.',
category: 'Next Category',
});
} finally {
rmSync(repoRoot, { recursive: true, force: true });
}
});

it('preserves linked term hrefs and definition markdown', () => {
const repoRoot = mkdtempSync(join(tmpdir(), 'ethsystems-glossary-'));
try {
Expand Down
Loading