Skip to content
Merged
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
42 changes: 42 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Set default behavior to automatically normalize line endings to LF
* text=auto eol=lf

# Explicitly declare text files you want to always be normalized and converted to LF on checkout
*.xml text eol=lf
*.mediawiki text eol=lf
*.tsv text eol=lf
*.md text eol=lf
*.rst text eol=lf
*.txt text eol=lf
*.py text eol=lf
*.sh text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.json text eol=lf
*.toml text eol=lf
*.svg text eol=lf
*.css text eol=lf
*.js text eol=lf
*.html text eol=lf

# Denote all files that are truly binary and should not be modified
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.pdf binary
*.zip binary
*.gz binary
*.tar binary
*.mp3 binary
*.mp4 binary
*.mov binary
*.avi binary
*.exe binary
*.dll binary
*.so binary
*.dylib binary
*.class binary
*.jar binary
*.war binary
150 changes: 150 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# hed-javascript Copilot instructions

> **Local environment:** If `.status/local-environment.md` exists in this repository, read it first.
> It contains machine-specific overrides (OS, shell, paths) that take precedence over this file.

This is a Node.js/JavaScript project managed with `npm`. Node.js >= 22.0.0 is required.
Always run `npm install` before building or testing. In CI contexts use `npm ci` instead.

When you create summaries of what you did — always put them in a `.status/` directory at the root of the repository.

Markdown headers in this repository use sentence case: capitalize only the first word (and proper nouns).

## Branch and PR policy

All changes must be submitted as pull requests targeting the `main` branch. Direct pushes to `main` are not permitted.

## Project overview

**hed-validator** (`hed-javascript`) is a JavaScript library for validating HED (Hierarchical Event Descriptor) strings, tags, and BIDS-compatible event files. It is published as the `hed-validator` npm package and supports both Node.js (CommonJS and ESM) and browser environments.

## Architecture overview

Source code is plain JavaScript (`.js`) in `src/`. TypeScript type declarations live in `types/index.d.ts`.

**Entry Point:**

- `index.js` (root): Re-exports the public API

**Source Modules** (`src/`):

- `bids/` — BIDS dataset and TSV/sidecar parsing and validation
- `datasetParser.js`, `tsvParser.js`, `schema.js`, `index.js`
- `types/` — BIDS-specific type helpers
- `validator/` — BIDS validation logic

- `parser/` — HED string parsing pipeline
- `tokenizer.js`, `splitter.js`, `parser.js`, `parseUtils.js`
- `parsedHedString.js`, `parsedHedTag.js`, `parsedHedGroup.js`, `parsedHedSubstring.js`, `parsedHedColumnSplice.js`
- `definitionManager.js`, `definitionChecker.js`, `reservedChecker.js`
- `tagConverter.js`, `eventManager.js`

- `schema/` — HED schema loading, parsing, and merging
- `loader.js`, `parser.js`, `schemaMerger.js`
- `config.js`, `containers.js`, `entries.js`, `specs.js`, `init.js`

- `issues/` — Issue codes and formatting
- `issues.js`, `data.js`

- `data/` — Bundled JSON configs and XML schema files

- `utils/` — General utilities
- `array.js`, `string.js`, `files.js`, `paths.js`, `hedStrings.js`, `memoizer.js`, `xml.js`

**Browser App** (`browser/`):

- A separate Vite/React app for browser-based HED validation. Has its own `package.json` and `vite.config.js`.

## Common commands

```powershell
npm install # Install dependencies (use npm ci in CI)
npm run build # Build dist/ with esbuild (CommonJS + ESM)
npm test # Run Jest tests in tests/
npm run testSpecs # Run spec tests in spec_tests/
npm run coverage # Run tests with coverage report
npm run lint # ESLint on src/
npm run build ; npm run test-types-local-windows # Type-check types/ (build required first)
npm run docs # Generate TypeDoc documentation
npm run clear_jest_cache # Clear Jest cache
```

**Running individual test files:**

```powershell
npx jest tests/otherTests/hed.spec.js
```

**Browser app (separate package):**

```powershell
cd browser ; npm install ; npm test # Run browser (Vitest) tests
cd browser ; npm run build # Build browser app
cd browser ; npm run preview # Serve browser app locally
```

## Testing structure

```
tests/
jsonTests/ # JSON-driven validation tests (spec files)
jsonTestData/ # Data files for JSON tests (.data.js)
otherTests/ # Additional spec files (bids, schema, issues, etc.)
otherTestData/ # Data files for other tests
testHelpers/ # Shared test utilities
bidsDemoData/ # Sample BIDS dataset used in integration tests
spec_tests/
jsonTests.spec.js # Runs the HED spec test suite
javascriptTests.json
browser/
vitest.config.js # Separate Vitest suite for browser components
```

Jest is configured via `jest.config.js` and `babel.config.js`. Note: `jest.config.js` has a
`transformIgnorePatterns` entry that allows `unicode-name` and `semver` to be transformed —
do not remove it or those imports will fail in tests.

## Key dependencies

- **fast-xml-parser** — XML schema parsing
- **lodash**, **semver**, **pluralize**, **unicode-name** — Utility support
- **esbuild** — Build tool (CommonJS + ESM output)
- **jest** / **babel-jest** — Testing
- **eslint** / **prettier** — Linting and formatting
- **typescript** / **typedoc** — Type declarations and docs generation
- **husky** — Git hooks (runs prettier on commit)

## File organization

- `src/` — JavaScript source code
- `tests/` — Jest test suite
- `spec_tests/` — HED spec-level tests
- `types/` — TypeScript type declarations (`index.d.ts`, `test.ts`)
- `browser/` — Vite/React browser demo app
- `dist/` — Compiled output, generated by `npm run build` (not committed)
- `scripts/` — Helper scripts for type testing
- `esbuild.mjs` — Build configuration
- `.status/` — Local summaries and environment notes (not published)

## CI checks (all must pass on PRs)

CI runs on every push/PR to `main`. Replicate these locally before opening a PR:

| Workflow | Command | Notes |
| --------------------- | --------------------------------------------------- | -------------------------------------------------- |
| `tests.yml` | `npm ci ; npm test` | Runs `tests/` suite on Node 22, lts/\*, latest |
| `tests.yml` | `npm ci ; npm run testSpecs` | Runs `spec_tests/` suite |
| `tests.yml` (browser) | `cd browser ; npm install ; npm test` | Separate Vitest browser suite |
| `test-types.yml` | `npm ci ; npm run build ; npm pack` then type-check | **Build required before type check** |
| `codeql.yml` | automatic | CodeQL security scan (JavaScript) |
| `codespell.yaml` | automatic | Spell check source files |
| `links.yml` | automatic | Lychee link checker (configured via `lychee.toml`) |

Comment on lines +139 to +142
**Type-check locally (without packing):**

```powershell
npm run build ; npm run test-types-local-windows # Windows
npm run build ; npm run test-types-local-unix # Linux/macOS
```

Publishing to npm happens automatically via `publish.yml` when a GitHub Release is created.
58 changes: 58 additions & 0 deletions .github/workflows/claude.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(
github.event_name == 'issue_comment' &&
contains(github.event.comment.body, '@claude') &&
(github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR')
) ||
(
github.event_name == 'pull_request_review_comment' &&
contains(github.event.comment.body, '@claude') &&
(github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR')
) ||
(
github.event_name == 'pull_request_review' &&
contains(github.event.review.body, '@claude') &&
(github.event.review.author_association == 'OWNER' ||
github.event.review.author_association == 'MEMBER' ||
github.event.review.author_association == 'COLLABORATOR')
) ||
(
github.event_name == 'issues' &&
(contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) &&
(github.event.issue.author_association == 'OWNER' ||
github.event.issue.author_association == 'MEMBER' ||
github.event.issue.author_association == 'COLLABORATOR')
)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ secrets.GITHUB_TOKEN }}
claude_args: '--allowedTools "Bash(gh issue comment:*),Bash(gh issue view:*),Bash(gh pr comment:*),Bash(gh pr view:*),Read,Glob,Grep"'
22 changes: 0 additions & 22 deletions .github/workflows/codespell.yaml

This file was deleted.

29 changes: 29 additions & 0 deletions .github/workflows/typos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: Typos

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
typos:
name: Check for spelling errors
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: '.typos.toml'

- name: Run typos
run: uvx 'typos>=1.29.0'
Comment on lines +1 to +29
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
coverage
node_modules
.directory
.github/copilot-instructions.md
.idea
dist/
.status/
/venv/
spec_tests/*.txt
spec_tests/temp*.json
spec_tests/temp.spec.js
tests/temp.spec.js
.vscode/

# Ignore local build output
/build/
Expand Down
32 changes: 32 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[files]
# Match the previous codespell skip behavior.
extend-exclude = [
"datasets",
".git",
"deprecated",
"*.pdf",
"*.svg",
"*.xml",
"*.mediawiki",
"*.omn",
".venv",
"docs/_build",
"docs/html",
"docs/source/_static",
"dist",
"build",
"node_modules",
"**/*.min.js",
"**/*.min.css",
"**/package-lock.json",
"**/*.lock",
]

[default.extend-words]
# Match previous codespell ignore-words-list behavior.
covert = "covert"
hed = "hed"
recuse = "recuse"
hertzs = "hertzs"
rouge = "rouge"
isnt = "isnt"
Loading