Skip to content
Closed
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
239 commits
Select commit Hold shift + click to select a range
41814df
perf: lift Set instantiation out of setNested loop (#51)
akutuva21 May 11, 2026
54a4ebb
🧪 Add error path tests for expectString (#52)
akutuva21 May 11, 2026
221944c
perf: Cache \`trim()\` string operation in loop (#53)
akutuva21 May 11, 2026
6d836ce
perf: Optimize string splitting in parseMetadataYaml
google-labs-jules[bot] May 16, 2026
1cfbdc4
refactor: extract ID generation logic in backfill-metadata.js
google-labs-jules[bot] May 16, 2026
c27051c
test: add parseScalar edge case tests in utils.test.js
google-labs-jules[bot] May 16, 2026
7c31b60
test: add unit tests for expectString function
google-labs-jules[bot] May 16, 2026
5645f69
test: add missing error path test for generate-gallery.js
google-labs-jules[bot] May 16, 2026
245387b
⚡ Optimize RegExp creation in apply-gallery-assignments.js loop
google-labs-jules[bot] May 16, 2026
5879cf2
fix: remove extraneous console.log in backfill-metadata.js dry-run
google-labs-jules[bot] May 21, 2026
01737f9
refactor: remove extraneous console log from apply-gallery-assignment…
google-labs-jules[bot] May 21, 2026
7cc6123
refactor(scripts): remove extraneous console.log in apply-gallery-ass…
google-labs-jules[bot] May 21, 2026
3783798
chore: remove extraneous console log from backfill-metadata.js
google-labs-jules[bot] May 21, 2026
fc3f117
🧹 remove extraneous console log from backfill-metadata.js
google-labs-jules[bot] May 21, 2026
65f5eaf
chore: remove extraneous console log from apply-gallery-assignments.js
google-labs-jules[bot] May 21, 2026
758c4c5
Refactor: Remove extraneous console log in backfill-metadata.js
google-labs-jules[bot] May 21, 2026
ddb07d4
chore(scripts): remove extraneous console.log in apply-gallery-assign…
google-labs-jules[bot] May 21, 2026
77c6fdf
🧹 Remove extraneous console log from generate-manifest.js
google-labs-jules[bot] May 21, 2026
19cf92d
Remove extraneous console logs from backfill-metadata.js
google-labs-jules[bot] May 21, 2026
0891222
Add tests for scripts/apply-gallery-assignments.js
google-labs-jules[bot] May 21, 2026
6c5f1ea
chore(scripts): remove extraneous console logs in backfill-metadata.js
google-labs-jules[bot] May 21, 2026
ef717c2
test(utils): add comprehensive edge case tests for parseScalar
google-labs-jules[bot] May 21, 2026
f2e67c2
refactor: remove extraneous console logs from backfill-metadata.js
google-labs-jules[bot] May 21, 2026
772fac5
refactor: extract helper functions from parseBngl to resolve long fun…
google-labs-jules[bot] May 21, 2026
b3e2f94
perf: optimize generate-gallery metadata scanning
google-labs-jules[bot] May 21, 2026
85f0709
chore: convert console.log to console.info in backfill-metadata.js su…
google-labs-jules[bot] May 21, 2026
61ac9ae
perf: optimize file reading with async listModelFiles
google-labs-jules[bot] May 21, 2026
90d3b6c
perf: use async file read for gallery categories
google-labs-jules[bot] May 21, 2026
06e706d
test(scripts): add unit tests for backfill-metadata.js
google-labs-jules[bot] May 21, 2026
966c455
Remove extraneous console.log in dry run
google-labs-jules[bot] May 21, 2026
b971283
perf: Optimize findBnglFiles with async I/O in backfill-metadata.js
google-labs-jules[bot] May 21, 2026
d169a43
perf: convert buildEntry to use async file reading
google-labs-jules[bot] May 21, 2026
0d1945a
feat: updated metadata files for published models and tutorials with …
akutuva21 May 28, 2026
1d48c90
test: add error path test for unreadable metadata.yaml in generate-ga…
akutuva21 May 28, 2026
a9d0bef
fix: Prevent prototype pollution in setNested using Object.create(nul…
akutuva21 May 28, 2026
de79eed
Refactor extractCategoryMappings to reduce code duplication (#101)
akutuva21 May 28, 2026
adcd458
Merge pull request #71 from akutuva21/fix-backfill-metadata-console-l…
akutuva21 May 28, 2026
d080f65
Merge pull request #72 from akutuva21/code-health/remove-console-log-…
akutuva21 May 28, 2026
c29971f
Merge pull request #73 from akutuva21/remove-extraneous-console-log-1…
akutuva21 May 28, 2026
17c4795
Merge pull request #74 from akutuva21/fix-extraneous-console-log-1610…
akutuva21 May 28, 2026
0031ba6
Merge pull request #75 from akutuva21/fix/remove-extraneous-log-41927…
akutuva21 May 28, 2026
9a9261b
Merge pull request #76 from akutuva21/chore/remove-extraneous-console…
akutuva21 May 28, 2026
e11cb5d
Merge pull request #77 from akutuva21/fix-extraneous-console-log-1033…
akutuva21 May 28, 2026
1dbb430
Merge pull request #79 from akutuva21/fix/remove-extraneous-console-l…
akutuva21 May 28, 2026
fd57155
Merge pull request #80 from akutuva21/fix/remove-extraneous-console-l…
akutuva21 May 28, 2026
03ae2be
Merge pull request #81 from akutuva21/fix-backfill-metadata-logging-6…
akutuva21 May 28, 2026
617dcb8
Merge pull request #88 from akutuva21/code-health/remove-extraneous-c…
akutuva21 May 28, 2026
5714395
Merge pull request #94 from akutuva21/fix-backfill-metadata-console-l…
akutuva21 May 28, 2026
43359e9
Merge remote-tracking branch 'origin/master' into chore/remove-extran…
akutuva21 May 28, 2026
7f8211f
Merge branch 'fix-extraneous-console-log-18040559875008328583'
akutuva21 May 28, 2026
7027e7e
Merge branch 'perf-generate-manifest-async-10366685079153124914'
akutuva21 May 28, 2026
26f1bee
Fix: use plain objects in setNested; make missing-README test async
akutuva21 May 28, 2026
02972bc
Make gallery unreadable test Windows-tolerant; re-add README and mult…
akutuva21 May 28, 2026
dfd6f52
tests(validate-metadata): await async validateMetadataFile calls to a…
akutuva21 May 28, 2026
0e209a3
Merge branch 'perf-backfill-metadata-async-2427477262316775781' into …
akutuva21 May 28, 2026
63d381e
generate-manifest: restore compatibility (default modelFiles, collect…
akutuva21 May 28, 2026
783d78e
tests(validate-metadata): await async validateMetadataFile in remaini…
akutuva21 May 28, 2026
1ee5eeb
manifest: avoid FS read when dir missing; utils: use plain objects fo…
akutuva21 May 28, 2026
6dcdfd1
manifest: variant id for collections; validate-metadata: add README +…
akutuva21 May 28, 2026
e8d2175
Merge branch 'add-backfill-metadata-tests-17002031079315346418' into …
akutuva21 May 28, 2026
810e3ba
Merge branch 'perf-async-gallery-categories-3086575105558555583' into…
akutuva21 May 28, 2026
a49564c
Merge branch 'perf/async-list-model-files-12232060558600452650' into …
akutuva21 May 28, 2026
195296b
Merge branch 'perf-async-gallery-generation-14319817925688091983' int…
akutuva21 May 28, 2026
56fc764
Merge branch 'testing-utils-parsescalar-15887917858828485261' into wi…
akutuva21 May 28, 2026
161c36d
Merge branch 'tests-apply-gallery-assignments-5921760678751512594' in…
akutuva21 May 28, 2026
59bfae7
Merge pull request #104 from akutuva21/wip/copilot-merge
akutuva21 May 28, 2026
70e3009
Merge branch 'master' of https://github.com/akutuva21/RuleHub
akutuva21 May 28, 2026
fa0e7be
test: add unit tests for updateMetadataFile
google-labs-jules[bot] May 16, 2026
e582d99
test: add comprehensive tests for formatYamlValue and fix null bug
google-labs-jules[bot] May 16, 2026
dad5832
⚡ Optimize parseMetadataYaml string splitting (#57)
akutuva21 May 28, 2026
0612c92
⚡ Optimize RegExp creation in apply-gallery-assignments.js (#67)
akutuva21 May 28, 2026
9c08650
🧹 refactor(scripts): resolve long function issue in parseBngl (#87)
akutuva21 May 28, 2026
8a41cc9
perf: use async readFile for gallery parsing
google-labs-jules[bot] May 21, 2026
f29ad17
🧹 Refactor ID generation in backfill-metadata.js (#58)
akutuva21 May 28, 2026
4e2d1d8
⚡ Optimize IO by using async readFile in generate-gallery.js (#82)
akutuva21 May 28, 2026
d5c1b1c
🧪 Add edge case tests for parseScalar in utils.test.js (#59)
akutuva21 May 28, 2026
9653083
test: add coverage for listModelFilesAsync in utils.js
google-labs-jules[bot] May 21, 2026
84105b7
🧪 test: add unit tests for expectString function (#60)
akutuva21 May 28, 2026
1edacff
🧪 Add tests for listModelFilesAsync (#78)
akutuva21 May 28, 2026
afbe2c0
Add unit tests for normalizeModelKey
google-labs-jules[bot] May 16, 2026
c78b52c
🧪 Add unit tests for normalizeModelKey (#66)
akutuva21 May 28, 2026
0763504
🧪 test: add missing error path test for generate-gallery.js (#64)
akutuva21 May 28, 2026
b6e8180
test: add test for JSON.parse error path in generate-gallery
google-labs-jules[bot] May 21, 2026
a1d0ba2
🧪 Add test for JSON.parse error path in generate-gallery.js (#95)
akutuva21 May 28, 2026
22774dc
test(scripts): Add unit tests for generate-gallery.js
google-labs-jules[bot] May 21, 2026
37b31e0
🧪 test: Add unit tests for generate-gallery.js (#86)
akutuva21 May 28, 2026
06bf822
🧪 test: Add tests for updateMetadataFile in apply-gallery-assignments…
akutuva21 May 28, 2026
d46dbc3
test: add unit tests for parseArgs in apply-gallery-assignments.js
google-labs-jules[bot] May 16, 2026
cb9a572
🧪 Add tests for parseArgs in apply-gallery-assignments.js (#63)
akutuva21 May 28, 2026
6e98af5
perf: make apply-gallery-assignments.js asynchronous
google-labs-jules[bot] May 16, 2026
7e5220f
⚡ Refactor apply-gallery-assignments.js to execute async I/O concurre…
akutuva21 May 28, 2026
e57e03a
perf(backfill): optimize molecule tag parsing with Set
google-labs-jules[bot] May 16, 2026
76743d0
⚡ Optimize molecule tag parsing with Set (#56)
akutuva21 May 28, 2026
7d65877
🧪 Add test coverage for formatYamlValue and fix null bug (#65)
akutuva21 May 28, 2026
de8cc16
perf: optimize backfill-metadata to read files concurrently
google-labs-jules[bot] May 21, 2026
3271e97
⚡ Optimize backfill-metadata.js file reading to be asynchronous and c…
akutuva21 May 28, 2026
6b8bc3a
test: add coverage for loadGalleryCategories unhandled fallback
google-labs-jules[bot] May 29, 2026
6d827aa
perf(scripts): make findAllMetadataFiles async
google-labs-jules[bot] May 29, 2026
9fd7ca4
🧪 Add tests and refactor normalize-published-ids.js
google-labs-jules[bot] May 29, 2026
fbb93f6
refactor: Replace blocking synchronous file read with async in genera…
google-labs-jules[bot] May 29, 2026
b37cea9
⚡ Use async I/O in normalize-published-ids.js
google-labs-jules[bot] May 29, 2026
676318b
perf(scripts): replace synchronous readdir with async promises
google-labs-jules[bot] May 29, 2026
c466f88
🧪 add tests for scripts/migration/curate-published-tags.js
google-labs-jules[bot] May 29, 2026
ca68bda
test: add unit tests for inferOrigin in backfill-metadata.js
google-labs-jules[bot] May 29, 2026
468523b
Fix hardcoded absolute path in normalize-published-ids.js
google-labs-jules[bot] May 29, 2026
f02c8ce
perf: optimize metadata validation directory traversal
google-labs-jules[bot] May 29, 2026
5357479
test: add missing tests for inferCategory in backfill-metadata.js
google-labs-jules[bot] May 29, 2026
a03f772
chore: add missing README.md files to fix CI
google-labs-jules[bot] May 29, 2026
4e375ce
🧪 Test `extractMetadataFromComments` in backfill-metadata.js
google-labs-jules[bot] May 29, 2026
993eabe
Fix path traversal vulnerability in directory processing
google-labs-jules[bot] May 29, 2026
dd3fc59
Re-submit loadGalleryCategories error fallback test
google-labs-jules[bot] May 29, 2026
2271876
test: add test suite for extract-gallery-from-constants.js
google-labs-jules[bot] May 29, 2026
504610b
fix: resolve CI validation failure by adding missing README.md files
google-labs-jules[bot] May 29, 2026
b96e96b
⚡ Fix CI Failure: migrate listMetadataFiles to async in validate-meta…
google-labs-jules[bot] May 29, 2026
c2dbc4b
🧪 test(migration): add test file for curate-published-tags.js
google-labs-jules[bot] May 29, 2026
84e110b
test: add unit tests for inferOrigin in backfill-metadata.js
google-labs-jules[bot] May 29, 2026
7f0ce36
perf: optimize metadata validation directory traversal
google-labs-jules[bot] May 29, 2026
e155f04
Fix hardcoded absolute path in normalize-published-ids.js
google-labs-jules[bot] May 29, 2026
d5fcc8c
test: add missing tests for inferCategory in backfill-metadata.js
google-labs-jules[bot] May 29, 2026
5e58cc1
🧪 Test `extractMetadataFromComments` in backfill-metadata.js
google-labs-jules[bot] May 29, 2026
dccd696
Re-submit loadGalleryCategories error fallback test
google-labs-jules[bot] May 29, 2026
0940a83
chore: regenerate manifests and gallery to fix CI
google-labs-jules[bot] May 29, 2026
c6a28fc
test: add test suite for extract-gallery-from-constants.js
google-labs-jules[bot] May 29, 2026
af3fef5
⚡ Fix CI Failure: migrate listMetadataFiles to async in validate-meta…
google-labs-jules[bot] May 29, 2026
3a11f88
fix: resolve CI manifest drift
google-labs-jules[bot] May 29, 2026
81d384a
test: add unit tests for inferOrigin in backfill-metadata.js
google-labs-jules[bot] May 29, 2026
0fb0ff6
fix: add missing README.md files to satisfy metadata validation
google-labs-jules[bot] May 29, 2026
08b4eb1
Fix CI failure by exempting legacy Published models from missing READ…
google-labs-jules[bot] May 29, 2026
df9b065
🧪 test: add coverage for extractMetadataFromComments
google-labs-jules[bot] May 29, 2026
0856daf
Re-submit loadGalleryCategories error fallback test
google-labs-jules[bot] May 29, 2026
3850e96
fix: update manifests to match current models and READMEs
google-labs-jules[bot] May 29, 2026
bde974c
fix: add missing README.md files in Published models to satisfy metad…
google-labs-jules[bot] May 30, 2026
8641961
⚡ Fix CI Failure: Add missing README.md files to satisfy validate-met…
google-labs-jules[bot] May 30, 2026
9a22e97
fix: regenerate manifest files to resolve CI check mismatch
google-labs-jules[bot] May 30, 2026
65c0fd2
Fix CI failure by exempting legacy Published models from missing READ…
google-labs-jules[bot] May 30, 2026
9002ce4
🧪 test: add coverage for extractMetadataFromComments
google-labs-jules[bot] May 30, 2026
460f0d3
fix: add missing README.md files and update generated artifacts
google-labs-jules[bot] May 30, 2026
b783c2a
🔒 Fix path traversal security vulnerability in directory processing
akutuva21 Jun 1, 2026
22cb14a
🔒 Security fix: Remove hardcoded path in normalize-published-ids.js
akutuva21 Jun 1, 2026
6a449ae
Merge PR #111: ⚡ Replace synchronous I/O with async I/O in normalize-…
akutuva21 Jun 1, 2026
77d45f5
⚡ Replace synchronous file read in async loop in generate-gallery.js
akutuva21 Jun 1, 2026
13eee29
Merge PR #109: 🧪 Add tests and refactor normalize-published-ids.js
akutuva21 Jun 1, 2026
113a088
🧪 Add test for loadGalleryCategories error fallback
akutuva21 Jun 1, 2026
1c9a23d
🧪 test(migration): add test file for curate-published-tags.js
akutuva21 Jun 1, 2026
02aa895
Merge PR #116: ⚡ Optimize validate-metadata.js directory traversal to…
akutuva21 Jun 1, 2026
3886e11
Merge PR #108: ⚡ perf: make apply-gallery-assignments file reading as…
akutuva21 Jun 1, 2026
343f1e2
Merge PR #112: ⚡ perf(scripts): convert curate-published-tags to use …
akutuva21 Jun 1, 2026
a68f71e
Merge remote-tracking branch 'origin/fix-infercategory-tests-18375894…
akutuva21 Jun 1, 2026
4b41014
Merge PR #114: 🧪 [test] add unit tests for inferOrigin
akutuva21 Jun 1, 2026
a34d34f
Merge PR #118: 🧪 test: add coverage for extractMetadataFromComments
akutuva21 Jun 1, 2026
344ad3e
Merge remote-tracking branch 'origin/add-tests-extract-gallery-131028…
akutuva21 Jun 1, 2026
9fb1ebc
Fix extractModelIds tests to match array return type
akutuva21 Jun 1, 2026
fdfe430
Fix tests to match async functions and dynamic paths after PR merges
akutuva21 Jun 1, 2026
f96de50
🧹 Remove redundant nested if in apply-gallery-assignments.js
google-labs-jules[bot] Jun 2, 2026
38c3222
Fix unused `updated` variable in apply-gallery-assignments.js
google-labs-jules[bot] Jun 2, 2026
8519c70
test: add missing tests for expectArray in validate-metadata.js
google-labs-jules[bot] Jun 2, 2026
298bd51
refactor: remove unused getIgnoreDirs function
google-labs-jules[bot] Jun 2, 2026
3ad8a39
Add unit tests for isCollectionEntry
google-labs-jules[bot] Jun 2, 2026
fb25b0b
test: add comprehensive tests for parseMetadataYaml
google-labs-jules[bot] Jun 2, 2026
a3258ed
test: add unit tests for formatYaml in backfill-metadata.js
google-labs-jules[bot] Jun 2, 2026
c4bd8cc
🔒 fix: prevent path traversal on input file read
google-labs-jules[bot] Jun 2, 2026
a3be13b
test(scripts): Add comprehensive tests for validateMetadataFile
google-labs-jules[bot] Jun 2, 2026
d5e9460
test: add tests for getIgnoreDirs in scripts/generate-manifest.js
google-labs-jules[bot] Jun 2, 2026
4ef0996
test: add tests for expectBoolean helper
google-labs-jules[bot] Jun 2, 2026
2455510
test: add unit tests for isIgnoredDir in generate-manifest
google-labs-jules[bot] Jun 2, 2026
729057f
🧪 Implement tests for extractMetadataFromComments
google-labs-jules[bot] Jun 2, 2026
f8bf84a
🧪 Add missing tests for expectEnum
google-labs-jules[bot] Jun 2, 2026
0bc2008
test: add coverage for backfill-metadata inferCategory edge cases
google-labs-jules[bot] Jun 2, 2026
5a8b383
test: Add unit tests for `generateId` in backfill-metadata.js
google-labs-jules[bot] Jun 2, 2026
0f6670a
test: fix inferOrigin test block nesting and expand coverage
google-labs-jules[bot] Jun 2, 2026
c6b4b59
test: add coverage for listModelFilesFiltered
google-labs-jules[bot] Jun 2, 2026
4adefcf
test: add unit tests for processModelLine parser function
google-labs-jules[bot] Jun 2, 2026
ee8424c
Add missing tests for processActionLine in backfill-metadata.js
google-labs-jules[bot] Jun 2, 2026
d8e05b8
🧹 [code health improvement] Remove unused function `isIgnoredDir`
google-labs-jules[bot] Jun 2, 2026
c4e2517
perf: refactor extractModelIds to use async fs.promises.readdir
google-labs-jules[bot] Jun 2, 2026
add7a96
Fix Path Traversal vulnerability in generate-manifest.js output flag
google-labs-jules[bot] Jun 2, 2026
da88845
test: add tests for findAllMetadataFiles in scripts/apply-gallery-ass…
google-labs-jules[bot] Jun 2, 2026
98408e2
fix(scripts): prevent RegExp injection in apply-gallery-assignments
google-labs-jules[bot] Jun 2, 2026
bcfe255
⚡ refactor(generate-manifest): optimize listMetadataFiles directory t…
google-labs-jules[bot] Jun 2, 2026
b718b8e
Merge pull request #146 from akutuva21/jules-async-listmetadatafiles-…
akutuva21 Jun 2, 2026
8cd74c0
Merge pull request #142 from akutuva21/perf-extract-model-ids-async-1…
akutuva21 Jun 2, 2026
d28af84
Merge pull request #137 from akutuva21/test-infer-origin-coverage-109…
akutuva21 Jun 2, 2026
32a2e95
Merge pull request #133 from akutuva21/test-extract-metadata-from-com…
akutuva21 Jun 2, 2026
9db99c6
Merge pull request #127 from akutuva21/test/formatYaml-45751091893259…
akutuva21 Jun 2, 2026
106f5d6
Merge pull request #145 from akutuva21/fix-apply-gallery-assignments-…
akutuva21 Jun 2, 2026
674785a
Merge pull request #138 from akutuva21/test-listModelFilesFiltered-14…
akutuva21 Jun 2, 2026
429e923
Merge pull request #131 from akutuva21/testing-improvement-expect-boo…
akutuva21 Jun 2, 2026
29a8d4c
Merge pull request #126 from akutuva21/testing-improvement-parse-meta…
akutuva21 Jun 2, 2026
ed5e2b9
Merge branch 'master' into test/findallmetadatafiles-coverage-1081223…
akutuva21 Jun 2, 2026
b57b6c5
Merge branch 'master' into fix/generate-manifest-path-traversal-15062…
akutuva21 Jun 2, 2026
d92bd13
Merge branch 'master' into remove-is-ignored-dir-13831833499686048603
akutuva21 Jun 2, 2026
35259ad
Merge branch 'master' into test-coverage-infercategory-11974916847795…
akutuva21 Jun 2, 2026
4ffb19a
Merge branch 'master' into fix/unused-variable-updated-81539892153346…
akutuva21 Jun 2, 2026
d4a6a18
Merge branch 'master' into fix-unused-getignore-dirs-1320372818373487…
akutuva21 Jun 2, 2026
4c3047a
Merge branch 'master' into code-health/remove-redundant-if-apply-gall…
akutuva21 Jun 2, 2026
12fb6aa
Merge pull request #144 from akutuva21/test/findallmetadatafiles-cove…
akutuva21 Jun 2, 2026
148d242
Merge pull request #122 from akutuva21/fix/unused-variable-updated-81…
akutuva21 Jun 2, 2026
113043e
Merge branch 'master' into fix/generate-manifest-path-traversal-15062…
akutuva21 Jun 2, 2026
fc923c3
Merge branch 'master' into remove-is-ignored-dir-13831833499686048603
akutuva21 Jun 2, 2026
43d8bd5
Merge branch 'master' into test-coverage-infercategory-11974916847795…
akutuva21 Jun 2, 2026
02f4f72
Merge branch 'master' into fix-unused-getignore-dirs-1320372818373487…
akutuva21 Jun 2, 2026
1aa9482
Merge branch 'master' into code-health/remove-redundant-if-apply-gall…
akutuva21 Jun 2, 2026
e9a1244
Merge pull request #141 from akutuva21/remove-is-ignored-dir-13831833…
akutuva21 Jun 2, 2026
88183e6
Merge pull request #121 from akutuva21/code-health/remove-redundant-i…
akutuva21 Jun 2, 2026
91d363d
Merge branch 'master' into fix/generate-manifest-path-traversal-15062…
akutuva21 Jun 2, 2026
7b669ad
Merge branch 'master' into test-coverage-infercategory-11974916847795…
akutuva21 Jun 2, 2026
1b5ce6d
Merge pull request #143 from akutuva21/fix/generate-manifest-path-tra…
akutuva21 Jun 2, 2026
71ccaeb
Merge branch 'master' into test-coverage-infercategory-11974916847795…
akutuva21 Jun 2, 2026
d0a945b
Merge pull request #135 from akutuva21/test-coverage-infercategory-11…
akutuva21 Jun 2, 2026
5b3c9a8
Merge master into PR #140 branch
Jun 2, 2026
5a16766
Merge pull request #140 from akutuva21/testing-improvement-processAct…
akutuva21 Jun 2, 2026
a2037e0
Merge master into PR #139 branch
Jun 2, 2026
20982f1
Merge latest master into PR #139
Jun 2, 2026
2bda9d0
Merge pull request #139 from akutuva21/test-process-model-line-165761…
akutuva21 Jun 2, 2026
ffff48d
Merge master into PR #136
Jun 2, 2026
f477764
Merge latest master into PR #136
Jun 2, 2026
39796a7
Merge pull request #136 from akutuva21/test/backfill-metadata-generat…
akutuva21 Jun 2, 2026
8e25c5e
Merge master into PR #134
Jun 2, 2026
d14e7a3
Merge pull request #134 from akutuva21/fix/expect-enum-tests-14705957…
akutuva21 Jun 2, 2026
ae46e56
Merge master into PR #130
Jun 2, 2026
bcd6ad7
Merge pull request #130 from akutuva21/testing-get-ignore-dirs-549341…
akutuva21 Jun 2, 2026
6814b85
Merge master into PR #129
Jun 2, 2026
24e3647
Merge pull request #129 from akutuva21/test-validate-metadata-4111691…
akutuva21 Jun 2, 2026
4aa0f00
Merge master into PR #125
Jun 2, 2026
a792aa7
Merge pull request #125 from akutuva21/test-iscollectionentry-1790141…
akutuva21 Jun 2, 2026
29cc8c9
Merge master into PR #124
Jun 2, 2026
e0abed4
Merge pull request #124 from akutuva21/fix-unused-getignore-dirs-1320…
akutuva21 Jun 2, 2026
f097fe2
Merge master into PR #123
Jun 2, 2026
cf13326
Merge pull request #123 from akutuva21/test-coverage-expectArray-1287…
akutuva21 Jun 2, 2026
ceb558f
Merge pull request #128 from akutuva21/fix-path-traversal-input-10377…
akutuva21 Jun 2, 2026
e6f7d77
Merge master into PR #132
Jun 2, 2026
cc85e1a
Merge pull request #132 from akutuva21/test-isignored-dir-18050093452…
akutuva21 Jun 2, 2026
9e293f0
Fix stale test files to match updated async APIs
akutuva21 Jun 3, 2026
4e1ee68
Fix CI error: define DEFAULT_IGNORE_DIRS and isIgnoredDir in generate…
akutuva21 Jun 3, 2026
7ecd47d
⚡ Optimize listModelFiles to use asynchronous I/O
akutuva21 Jun 8, 2026
b255844
⚡ Extract Regex from Gallery Assignment Loop
akutuva21 Jun 8, 2026
9f2f3b3
⚡ Replace synchronous file I/O with fs.promises
akutuva21 Jun 8, 2026
aa18c0c
🧪 Add edge case tests for normalizeModelKey
akutuva21 Jun 8, 2026
3c18cf3
⚡ Optimize gallery assignments by replacing synchronous I/O
akutuva21 Jun 8, 2026
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
15 changes: 11 additions & 4 deletions scripts/apply-gallery-assignments.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,17 @@ async function main(argv = process.argv.slice(2)) {
const assignments = JSON.parse(await fs.promises.readFile(input, 'utf8'));
console.log(`Loaded ${Object.keys(assignments).length} assignments`);

const compiledAssignments = Object.entries(assignments).map(([modelId, data]) => ({
modelId, data,
idPattern: new RegExp(`^id:\\s*["']?${modelId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}["']?\\s*$`, 'm')
}));
const compiledAssignments = [];
for (const [modelId, data] of Object.entries(assignments)) {
if (typeof modelId !== 'string' || modelId.length > 100) {
console.warn(`Skipping invalid modelId: ${modelId}`);
continue;
}
compiledAssignments.push({
modelId, data,
idPattern: new RegExp(`^id:\\s*["']?${modelId.replace(/[.*+?^${}()|[\]\\]/g, (match) => '\\' + match)}["']?\\s*$`, 'm')
});
}

const SEARCH_ROOTS = ['Published', 'Examples', 'Tutorials'];
const metadataFileArrays = SEARCH_ROOTS.map(searchRoot =>
Expand Down
33 changes: 13 additions & 20 deletions scripts/backfill-metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,22 @@ async function findBnglFiles(dir, ignoreDirs = DEFAULT_IGNORE_DIRS) {
}

function extractMetadataFromComments(headerComments, metadata) {
if (headerComments.length === 0) return;

for (const comment of headerComments) {
const nameMatch = comment.match(/(?:model|name)[:\s]+(.+)/i);
if (nameMatch && !metadata.name) {
metadata.name = nameMatch[1].trim();
continue;
}

const doiMatch = comment.match(/(?:doi|DOI)[:\s]+(10\.\S+)/i);
if (doiMatch) {
metadata.doi = doiMatch[1].trim();
const match = comment.match(/^([a-zA-Z0-9_-]+):\s*(.*)$/);
if (match) {
const key = match[1];
const val = match[2].trim();
if (key === 'tags') {
val.split(',').forEach(tag => metadata.tags.add(tag.trim()));
} else if (key === 'description') {
if (!metadata.description) metadata.description = val;
} else if (key === 'name') {
metadata.name = val;
} else if (key === 'doi') {
metadata.doi = val;
}
}
}

const nonParamComments = headerComments.filter(c =>
!c.match(/^[a-zA-Z_]\w*\s+changed\s+to/i) &&
!c.match(/(?:model|name)[:\s]+(.+)/i) &&
!c.match(/(?:doi|DOI)[:\s]+(10\.\S+)/i)
);
if (nonParamComments.length > 0 && !metadata.description) {
metadata.description = nonParamComments[0];
}
}

function processActionLine(trimmed, metadata) {
Expand Down
192 changes: 123 additions & 69 deletions scripts/backfill-metadata.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const assert = require('node:assert');
const fs = require('fs');
const os = require('os');
const path = require('path');
const { parseBngl, generateMetadata, formatYamlValue, inferCategory, inferOrigin, extractMetadataFromComments } = require('./backfill-metadata.js');
const { parseBngl, generateMetadata, formatYaml, formatYamlValue, inferCategory, inferOrigin, extractMetadataFromComments } = require('./backfill-metadata.js');

test('backfill-metadata.js', async (t) => {
let tmpDir;
Expand All @@ -22,7 +22,7 @@ test('backfill-metadata.js', async (t) => {
const bnglContent = `
# name: Test Model
# doi: 10.1234/test
# This is a description of the model.
# description: This is a description of the model.
# Some other comment

begin model
Expand Down Expand Up @@ -245,6 +245,84 @@ end model
assert.strictEqual(inferCategory(path.join(cwd, 'unknown_model')), 'other');
assert.strictEqual(inferCategory(path.join(cwd, 'random', 'dir')), 'other');
});

await t.test('inferOrigin - infers origin based on path', async (st) => {
const cwd = process.cwd();

await st.test('infers published for Published directory', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Published', 'Model1')), 'published');
assert.strictEqual(inferOrigin(path.join(cwd, 'PUBLISHED', 'Model1')), 'published');
});

await st.test('infers ai-generated for Examples with AI prefix', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Examples', 'AI-Generated-Model')), 'ai-generated');
assert.strictEqual(inferOrigin(path.join(cwd, 'Examples', 'aigenerated-Model')), 'ai-generated');
assert.strictEqual(inferOrigin(path.join(cwd, 'EXAMPLES', 'ai-generated-Model')), 'ai-generated');
});

await st.test('infers ai-generated for Examples without AI prefix (fallback)', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Examples', 'Some-Model')), 'ai-generated');
});

await st.test('infers tutorial for Tutorials directory', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Tutorials', 'Basic')), 'tutorial');
assert.strictEqual(inferOrigin(path.join(cwd, 'TUTORIALS', 'Basic')), 'tutorial');
});

await st.test('infers contributed when path contains contributed', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'SomeDir', 'Contributed-Model')), 'contributed');
assert.strictEqual(inferOrigin(path.join(cwd, 'SomeDir', 'CONTRIBUTED-Model')), 'contributed');
});

await st.test('infers test-case for unknown paths', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Unknown', 'Dir')), 'test-case');
});
});
});

test('formatYaml', async (t) => {
await t.test('skips undefined and null values', async () => {
const obj = { a: 1, b: undefined, c: null, d: 'four' };
assert.strictEqual(formatYaml(obj), 'a: 1\nd: four\n');
});

await t.test('formats empty arrays', async () => {
const obj = { a: [] };
assert.strictEqual(formatYaml(obj), 'a: []\n');
assert.strictEqual(formatYaml(obj, 1), ' a: []\n');
});

await t.test('formats arrays of primitives', async () => {
const obj = { a: [1, 2, 3], b: ['one', 'two'], c: [true, false] };
const expected = 'a: [1, 2, 3]\nb: ["one", "two"]\nc: [true, false]\n';
assert.strictEqual(formatYaml(obj), expected);
});

await t.test('formats arrays of objects', async () => {
const obj = { a: [{ x: 1 }, { y: 2 }] };
const expected = 'a:\n - x: 1\n - y: 2\n';
assert.strictEqual(formatYaml(obj), expected);
const expectedIndented = ' a:\n - x: 1\n - y: 2\n';
assert.strictEqual(formatYaml(obj, 1), expectedIndented);
});

await t.test('formats mixed arrays', async () => {
const obj = { a: [1, { x: 1 }] };
const expected = 'a:\n - 1\n - x: 1\n';
assert.strictEqual(formatYaml(obj), expected);
});

await t.test('formats nested objects', async () => {
const obj = { a: { b: 1, c: { d: 2 } } };
const expected = 'a:\n b: 1\n c:\n d: 2\n';
assert.strictEqual(formatYaml(obj), expected);
});

await t.test('formats basic properties', async () => {
const obj = { a: 1, b: true, c: 'string' };
const expected = 'a: 1\nb: true\nc: string\n';
assert.strictEqual(formatYaml(obj), expected);
});
});

test('formatYamlValue', async (t) => {
Expand Down Expand Up @@ -286,99 +364,75 @@ test('formatYamlValue', async (t) => {
await t.test('handles null correctly', () => {
assert.strictEqual(formatYamlValue(null), 'null\n');
});

await t.test('inferOrigin - infers origin based on path', async (st) => {
const cwd = process.cwd();

await st.test('infers published for Published directory', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Published', 'Model1')), 'published');
});

await st.test('infers ai-generated for Examples with AI prefix', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Examples', 'AI-Generated-Model')), 'ai-generated');
assert.strictEqual(inferOrigin(path.join(cwd, 'Examples', 'aigenerated-Model')), 'ai-generated');
});

await st.test('infers ai-generated for Examples without AI prefix (fallback)', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Examples', 'Some-Model')), 'ai-generated');
});

await st.test('infers tutorial for Tutorials directory', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Tutorials', 'Basic')), 'tutorial');
});

await st.test('infers contributed when path contains contributed', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'SomeDir', 'Contributed-Model')), 'contributed');
});

await st.test('infers test-case for unknown paths', () => {
assert.strictEqual(inferOrigin(path.join(cwd, 'Unknown', 'Dir')), 'test-case');
});
});
});

test('extractMetadataFromComments', async (t) => {
await t.test('returns early if headerComments is empty', () => {
const metadata = { name: '', description: '', doi: '' };
await t.test('does nothing if headerComments is empty', () => {
const metadata = { name: '', description: '', doi: '', tags: new Set() };
extractMetadataFromComments([], metadata);
assert.deepStrictEqual(metadata, { name: '', description: '', doi: '' });
assert.deepStrictEqual(metadata, { name: '', description: '', doi: '', tags: new Set() });
});

await t.test('extracts model name from name: or model:', () => {
const metadata = { name: '' };
await t.test('extracts model name correctly and overwrites', () => {
const metadata = { name: 'Existing Name', description: '', doi: '', tags: new Set() };
extractMetadataFromComments(['name: Test Model Name'], metadata);
assert.strictEqual(metadata.name, 'Test Model Name');

const metadata2 = { name: '' };
extractMetadataFromComments(['model: Another Model'], metadata2);
assert.strictEqual(metadata2.name, 'Another Model');
});

await t.test('does not overwrite existing name', () => {
const metadata = { name: 'Existing Name' };
extractMetadataFromComments(['name: New Name'], metadata);
assert.strictEqual(metadata.name, 'Existing Name');
});

await t.test('extracts DOI correctly', () => {
const metadata = { doi: '' };
await t.test('extracts DOI correctly and overwrites', () => {
const metadata = { name: '', description: '', doi: 'old.doi', tags: new Set() };
extractMetadataFromComments(['doi: 10.1234/test.doi'], metadata);
assert.strictEqual(metadata.doi, '10.1234/test.doi');
});

const metadata2 = { doi: '' };
extractMetadataFromComments(['DOI: 10.5678/another.doi'], metadata2);
assert.strictEqual(metadata2.doi, '10.5678/another.doi');
await t.test('extracts description and does not overwrite existing description', () => {
const metadata = { name: '', description: 'Existing Description', doi: '', tags: new Set() };
extractMetadataFromComments(['description: New Description'], metadata);
assert.strictEqual(metadata.description, 'Existing Description');

const metadata2 = { name: '', description: '', doi: '', tags: new Set() };
extractMetadataFromComments(['description: First Description', 'description: Second Description'], metadata2);
assert.strictEqual(metadata2.description, 'First Description');
});

await t.test('extracts description from first non-parameter comment', () => {
const metadata = { description: '' };
const comments = [
'k1 changed to 2.0',
'This is the actual description',
'Some other comment'
];
extractMetadataFromComments(comments, metadata);
assert.strictEqual(metadata.description, 'This is the actual description');
await t.test('extracts tags correctly and trims them', () => {
const metadata = { name: '', description: '', doi: '', tags: new Set(['existing-tag']) };
extractMetadataFromComments(['tags: tag1, tag2 , tag3'], metadata);
assert.deepStrictEqual(metadata.tags, new Set(['existing-tag', 'tag1', 'tag2', 'tag3']));
});

await t.test('does not overwrite existing description', () => {
const metadata = { description: 'Existing Description' };
extractMetadataFromComments(['New Description'], metadata);
assert.strictEqual(metadata.description, 'Existing Description');
await t.test('ignores invalid or unhandled keys', () => {
const metadata = { name: 'Init', description: 'Init', doi: 'Init', tags: new Set() };
extractMetadataFromComments(['invalid-key: some value', 'unhandled: value'], metadata);
assert.strictEqual(metadata.name, 'Init');
assert.strictEqual(metadata.description, 'Init');
assert.strictEqual(metadata.doi, 'Init');
assert.deepStrictEqual(metadata.tags, new Set());
});

await t.test('ignores comments not matching regex', () => {
const metadata = { name: '', description: '', doi: '', tags: new Set() };
extractMetadataFromComments(['just some regular comment', 'no colon here', 'name : bad format'], metadata);
assert.strictEqual(metadata.name, '');
assert.strictEqual(metadata.description, '');
assert.strictEqual(metadata.doi, '');
assert.deepStrictEqual(metadata.tags, new Set());
});

await t.test('extracts everything together', () => {
const metadata = { name: '', description: '', doi: '' };
const metadata = { name: '', description: '', doi: '', tags: new Set() };
const comments = [
'model: Full Model',
'name: Full Model',
'doi: 10.9999/full',
'rate_constant changed to 5',
'A description of the full model',
'Another note'
'description: A description of the full model',
'tags: t1, t2',
'ignored: this is ignored',
'just some text'
];
extractMetadataFromComments(comments, metadata);
assert.strictEqual(metadata.name, 'Full Model');
assert.strictEqual(metadata.doi, '10.9999/full');
assert.strictEqual(metadata.description, 'A description of the full model');
assert.deepStrictEqual(metadata.tags, new Set(['t1', 't2']));
});
});
17 changes: 14 additions & 3 deletions scripts/generate-gallery.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,20 @@ function parseYamlSimple(content) {
return result;
}

function extractModelIds(metadataFile, metadata) {
async function extractModelIds(metadataFile, metadata) {
const modelDir = path.dirname(metadataFile);
const bnglFiles = fs.readdirSync(modelDir, { withFileTypes: true })
let entries;
try {
entries = await fs.promises.readdir(modelDir, { withFileTypes: true });
} catch (err) {
if (err.code === 'ENOENT') {
entries = [];
} else {
throw err;
}
}

const bnglFiles = entries
.filter(e => e.isFile() && e.name.endsWith('.bngl'))
.map(e => e.name)
.sort();
Expand Down Expand Up @@ -156,7 +167,7 @@ async function main(argv = process.argv.slice(2)) {
const content = await fs.promises.readFile(metadataFile, 'utf8');
const metadata = parseMetadataYaml(content);

const modelIds = extractModelIds(metadataFile, metadata);
const modelIds = await extractModelIds(metadataFile, metadata);
if (modelIds.length === 0) continue;

const tags = Array.isArray(metadata.tags) ? metadata.tags : [];
Expand Down
16 changes: 8 additions & 8 deletions scripts/generate-gallery.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,35 +235,35 @@ test('extractModelIds', async (t) => {
fs.rmSync(tmpDir, { recursive: true, force: true });
});

await t.test('returns metadata id if is collection', () => {
await t.test('returns metadata id if is collection', async () => {
const metadataPath = path.join(tmpDir, 'metadata.yaml');
fs.writeFileSync(metadataPath, '');
const result = extractModelIds(metadataPath, { id: 'coll_1', collection: true });
const result = await extractModelIds(metadataPath, { id: 'coll_1', collection: true });
assert.deepStrictEqual(result, ['coll_1']);
});

await t.test('returns metadata id if it exists and bngl files are present', () => {
await t.test('returns metadata id if it exists and bngl files are present', async () => {
const metadataPath = path.join(tmpDir, 'metadata.yaml');
fs.writeFileSync(metadataPath, '');
fs.writeFileSync(path.join(tmpDir, 'model.bngl'), '');

const result = extractModelIds(metadataPath, { id: 'meta_id' });
const result = await extractModelIds(metadataPath, { id: 'meta_id' });
assert.deepStrictEqual(result, ['meta_id']);
});

await t.test('returns filename of bngl if no metadata id is present', () => {
await t.test('returns filename of bngl if no metadata id is present', async () => {
const metadataPath = path.join(tmpDir, 'metadata.yaml');
fs.writeFileSync(metadataPath, '');
fs.writeFileSync(path.join(tmpDir, 'my_model.bngl'), '');

const result = extractModelIds(metadataPath, {});
const result = await extractModelIds(metadataPath, {});
assert.deepStrictEqual(result, ['my_model']);
});

await t.test('returns empty array if no bngl files are present (and not a collection)', () => {
await t.test('returns empty array if no bngl files are present (and not a collection)', async () => {
const metadataPath = path.join(tmpDir, 'metadata.yaml');
fs.writeFileSync(metadataPath, '');
const result = extractModelIds(metadataPath, { id: 'meta_id' });
const result = await extractModelIds(metadataPath, { id: 'meta_id' });
assert.deepStrictEqual(result, []);
});
});
Loading