Welcome! XSLTDebugX is an open-source browser-based XSLT 3.0 IDE maintained by the community. This guide covers code style, commit format, PR workflow, and bug reporting.
- Code of Conduct
- Before You Start
- Development Setup
- PR Checklist
- Code Style
- Commit Format
- PR Process
- Issue Reporting
- Maintenance
- License
We are committed to providing a welcoming and inclusive environment. Please be respectful in all interactions and follow the Contributor Covenant Code of Conduct.
- Search Issues — avoid duplicate work.
- Check .github/docs/reference/features.md — the feature may already exist.
- Open an issue for significant features or breaking changes; bug fixes and small docs improvements can go straight to a PR.
See .github/docs/DEVELOPMENT.md for full setup, local serving options, and DevTools debugging. See .github/docs/TESTING.md for the Playwright E2E guide.
Key commands:
npm install # Setup (once)
npm run serve # Local dev server on port 8000 (no build needed)
npm run test:e2e # Run all tests
npm run test:e2e:ui # Interactive UI mode
npm run test:e2e:debug # Debugger modeBefore submitting:
- No
var— uselet/const -
_prefix on private functions - Complex logic commented with why, not what
- Section dividers:
// ════════ Section Name ════════ - HTML IDs camelCase (
xmlEd,runBtn), CSS classes hyphenated (.pane-bar) - No new unprefixed globals — check
state.jsfirst -
console.logrestored, Monaco models disposed (no memory leaks) - Debounce timing unchanged (800ms validation)
- Manual browser test — no DevTools console errors
-
npm run test:e2epasses (Chromium — the only project enabled inplaywright.config.js/ CI) - Firefox manual smoke (optional) — Firefox/WebKit projects are commented out
- localStorage persistence works after refresh
// ✅ Good
const MAX_HISTORY_SIZE = 20;
function runTransform() { ... } // Public API — no prefix
function _parseErrorLine(err) { ... } // Private — underscore prefix
async function validateXmlWellFormedness(xml) { ... }
// ❌ Bad
var MAX = 20;
function run() { ... } // Not descriptive
function parseErrorLine(err) { ... } // Looks public but isn't// ✅ Good
// Debounce 800ms: large XSLT (>10KB) takes ~6-10ms to parse.
// Validating every keystroke = ~50/sec = CPU spike.
xsltDebounce = setTimeout(() => validateXslt(), 800);
// ❌ Bad
// Set timeout (states the obvious)
xsltDebounce = setTimeout(() => validateXslt(), 800);// ✅ Good
try {
const result = SaxonJS.transform({
stylesheetText: xslt,
sourceText: xml,
destination: 'serialized',
}, 'sync');
} catch (err) {
clog(`Transform failed: ${err.message}`, 'error');
return null;
}
// ❌ Bad — silent failure or raw console
try { ... } catch (err) { return null; }
console.error('Something went wrong');// ✅ Good — cleanup guaranteed even on error
async function runTransform() {
const originalLog = console.log;
try {
console.log = _captureLog;
// ...
} finally {
console.log = originalLog;
}
}
// ✅ Dispose Monaco models before reassigning
if (eds.xml) eds.xml.getModel()?.dispose();
eds.xml = monaco.editor.create(...);"Function name unclear" — Be specific: process(data) → validateXsltSyntax(xsltString)
"Add a comment explaining rationale" — The why isn't obvious; explain it.
"Missing cleanup" — Use try/finally so cleanup runs even on error.
"Add underscore prefix" — Function is internal but looks public.
"Breaks module load order" — A function is referenced before it's defined.
For examples authoring, see .github/docs/reference/examples-data.md.
Use conventional commits:
<type>(<scope>): <subject>
<body>
<footer>
Types: feat · fix · docs · refactor · perf · test · ci · chore
Scopes: transform · xpath · editor · validate · examples · ui · docs · tests
Subject rules: imperative mood (add not added), no period, ≤50 chars.
Body: explain why, not what. Wrap at 72 chars.
Footer: Fixes #123 or Refs #123.
feat(transform): Add CPI property simulation
- Rewrite cpi:setProperty calls to js:_cpiSetProperty
- Build property params from Properties panel
- Show output properties after transform
Fixes #89
fix(xpath): Handle empty nodeset results
Previous code assumed results array always present.
Now checks before rendering hints.
Refs #123
Bad commits:
Updated stuff # vague, no type
feat: fixed the thing # wrong mood, vague
Merge branch 'dev' # meaningless
Feature branches are cut from dev and PR back into dev. The dev → main PR is opened separately by maintainers when releasing.
git checkout dev
git pull origin dev
git checkout -b feat/your-feature # or fix/description — branched from dev
# ... make changes ...
npm run test:e2e # must pass
git push origin feat/your-feature
# Open PR with base = dev (NOT main)## Description
Brief explanation.
## Changes
- Change 1
- Change 2
## Testing
- [ ] Chrome + Firefox
- [ ] E2E tests pass
- [ ] No console errors
- [ ] localStorage persists after refresh
Fixes #123- Requires 1 maintainer approval
- All CI checks must pass
- Respond to feedback within a week
- Don't merge your own PRs
- After merge to
main, Cloudflare Pages auto-deploys toxsltdebugx.pages.dev
npm run test:e2e -- tests/e2e/workflows/failing.spec.js
# Fix, then:
git commit -m "fix: address review feedback"
git pushNeeds docs update? Update relevant files and note them in the PR description.
Needs tests? Add to tests/e2e/workflows/, run locally first.
Found a bug? Help us fix it.
## Description
What did you try to do? What happened instead?
## Steps to Reproduce
1. Open XSLTDebugX
2. Load the "Data Transformation" example
3. Click "Run XSLT"
4. Expected: Output appears in 100ms
5. Actual: Console shows "Saxon error: undefined variable..."
## Environment
- **Browser**: Chrome 120 (Windows 10)
- **OS**: Windows 10
- **Version**: As of 2026-03-27
## Affected Code
If you know which file/function, mention it:
- File: `js/xpath.js`
- Function: `_highlightXPath()`
## Additional Context
Attach screenshots, XSLT snippets, or XML samples if relevant.Before releasing:
- Bump version in README.md
- Update CHANGELOG.md
- Run
example-validatorskill to ensure all 61 examples pass - Test all examples in browser (click through each category)
- Create GitHub release with version tag
- Verify Cloudflare Pages deployment
Updating dependencies:
- Saxon-JS: Test all XPath and XSLT examples after updating
- Monaco Editor: Check release notes for breaking changes
- Cloudflare Workers: Update
wrangler.jsoncand test deployment
- Conventional Commits
- GitHub PR Docs
- .github/docs/ARCHITECTURE.md — constraints and patterns
- .github/docs/TESTING.md — test patterns
- .github/docs/TRANSFORM.md — CPI simulation deep dive
By contributing, you agree that your contributions will be licensed under the same license as the project (AGPL-3.0-or-later). See LICENSE for details.
- User features: See README.md
- Developer docs: See .github/docs/DEVELOPMENT.md
- API reference: See .github/docs/reference/
- Discussions: Open a GitHub Discussion
- Bug reports / Feature requests: Use GitHub Issues
Thank you for contributing to XSLTDebugX! 🙏