Skip to content

Commit 1c681bf

Browse files
authored
Dynamically register data/tables schemas (#57905)
1 parent 75b1694 commit 1c681bf

File tree

4 files changed

+65
-11
lines changed

4 files changed

+65
-11
lines changed

data/tables/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Data-driven tables
1+
# YAML-powered tables
22

33
## Overview
44

@@ -34,7 +34,7 @@ Every data-driven table needs **three files** that work together:
3434
|-----------|----------|---------|
3535
| **Data file** | `data/tables/` | Stores the table content in YAML format |
3636
| **Content file** | `content/` | Displays the table using Liquid templating |
37-
| **Schema file** | `src/data-directory/lib/data-schemas/` | Validates the YAML structure |
37+
| **Schema file** | `src/data-directory/lib/data-schemas/tables/` | Validates the YAML structure |
3838

3939
**Estimated time**: 30-60 minutes for a new table
4040

@@ -49,7 +49,7 @@ Create a new `.yml` file in `data/tables/` with a descriptive name.
4949
Create a YAML structure that will allow me to generate a table that looks like:
5050
[describe your table headers, rows, and columns OR attach an example]
5151
52-
See src/secret-scanning/data/public-docs.yml for an example.
52+
See data/tables/supported-code-languages.yml for an example.
5353
```
5454

5555
### Step 2: Create the content display
@@ -62,22 +62,22 @@ Create a Markdown table that is dynamically rendered using Liquid code.
6262
Pull data from data/tables/TABLE_NAME.yml.
6363
The table should look like: [describe your desired output OR attach an example]
6464
65-
See content/code-security/secret-scanning/introduction/supported-secret-scanning-patterns.md for an example.
65+
See content/get-started/learning-about-github/github-language-support.md for an example.
6666
Liquid docs: https://shopify.github.io/liquid
6767
```
6868

6969
**💡 Tip**: Iterate between Steps 1 and 2 until the table renders correctly.
7070

7171
### Step 3: Create the schema file
7272

73-
Create a `.ts` file in `src/data-directory/lib/data-schemas/` with the same name as your YAML file.
73+
Create a `.ts` file in `src/data-directory/lib/data-schemas/tables/` with the same name as your YAML file.
7474

7575
**Copilot prompt template:**
7676
```
7777
Create a TypeScript schema following prior art under data-schemas that enforces
7878
the structure of the data/TABLE_NAME.yml file.
7979
80-
See src/data-directory/lib/data-schemas/learning-tracks.ts for an example.
80+
See src/data-directory/lib/data-schemas/tables/supported-code-languages.ts for an example.
8181
```
8282

8383
## Testing and validation
Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,50 @@
1+
import fs from 'fs'
2+
import path from 'path'
3+
import { fileURLToPath } from 'url'
4+
5+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
6+
17
interface DataSchemas {
28
[key: string]: string
39
}
410

5-
const dataSchemas: DataSchemas = {
11+
// Auto-discover table schemas from data/tables/ directory
12+
function loadTableSchemas(): DataSchemas {
13+
const tablesDir = path.join(process.cwd(), 'data/tables')
14+
const schemasDir = path.join(__dirname, 'tables')
15+
const tableSchemas: DataSchemas = {}
16+
17+
if (fs.existsSync(tablesDir)) {
18+
const yamlFiles = fs.readdirSync(tablesDir).filter((file) => file.endsWith('.yml'))
19+
20+
for (const yamlFile of yamlFiles) {
21+
const name = path.basename(yamlFile, '.yml')
22+
const schemaPath = path.join(schemasDir, `${name}.ts`)
23+
24+
if (fs.existsSync(schemaPath)) {
25+
tableSchemas[`data/tables/${yamlFile}`] = `@/data-directory/lib/data-schemas/tables/${name}`
26+
}
27+
}
28+
}
29+
30+
return tableSchemas
31+
}
32+
33+
// Manual schema registrations for non-table data
34+
const manualSchemas: DataSchemas = {
635
'data/features': '@/data-directory/lib/data-schemas/features.js',
736
'data/variables': '@/data-directory/lib/data-schemas/variables',
837
'data/learning-tracks': '@/data-directory/lib/data-schemas/learning-tracks.js',
938
'data/release-notes': '@/data-directory/lib/data-schemas/release-notes.js',
1039
'data/code-languages.yml': '@/data-directory/lib/data-schemas/code-languages',
1140
'data/glossaries/candidates.yml': '@/data-directory/lib/data-schemas/glossaries-candidates.js',
1241
'data/glossaries/external.yml': '@/data-directory/lib/data-schemas/glossaries-external.js',
13-
'data/tables/supported-code-languages.yml':
14-
'@/data-directory/lib/data-schemas/supported-code-languages.js',
42+
}
43+
44+
// Combine manual registrations with auto-discovered table schemas
45+
const dataSchemas: DataSchemas = {
46+
...manualSchemas,
47+
...loadTableSchemas(),
1548
}
1649

1750
export default dataSchemas

src/data-directory/tests/data-schemas.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import yaml from 'js-yaml'
2-
import { readFileSync } from 'fs'
3-
import { extname, basename } from 'path'
2+
import { readFileSync, existsSync, readdirSync } from 'fs'
3+
import { extname, basename, join } from 'path'
44

55
import walk from 'walk-sync'
66
import { beforeAll, describe, expect, test } from 'vitest'
@@ -49,3 +49,24 @@ describe('single data files', () => {
4949
expect(isValid, formattedErrors).toBe(true)
5050
})
5151
})
52+
53+
describe('YAML-powered tables', () => {
54+
test('all table files have corresponding schemas', () => {
55+
const tablesDir = join(process.cwd(), 'data/tables')
56+
const schemasDir = join(__dirname, '../lib/data-schemas/tables')
57+
58+
if (existsSync(tablesDir)) {
59+
const yamlFiles = readdirSync(tablesDir).filter((file) => file.endsWith('.yml'))
60+
61+
for (const yamlFile of yamlFiles) {
62+
const name = basename(yamlFile, '.yml')
63+
const schemaPath = join(schemasDir, `${name}.ts`)
64+
expect(existsSync(schemaPath)).toBe(true)
65+
66+
// Also verify it's registered in the dataSchemas
67+
const dataKey = `data/tables/${yamlFile}`
68+
expect(dataSchemas[dataKey]).toBeDefined()
69+
}
70+
}
71+
})
72+
})

0 commit comments

Comments
 (0)