| description | Complete feature inventory and API reference for XSLTDebugX. Use when implementing new features, understanding existing functionality, debugging feature interactions, checking if functionality already exists, planning architecture changes, or verifying feature coverage. | ||
|---|---|---|---|
| applyTo |
|
Complete catalog of all 200+ features across the codebase
Before implementing new functionality, check if it already exists below.
- Three editor instances:
eds.xml,eds.xslt,eds.out(state.js) - Two XML models:
xmlModelXslt,xmlModelXpathfor mode isolation (state.js) - Active model routing: Use
xpathEnabled ? xmlModelXpath : xmlModelXslt - Themes:
xdebugx(dark) andxdebugx-lightdefined inthemes.js(MONACO_THEME_DARK,MONACO_THEME_LIGHT) and registered byeditor.js - Theme toggle:
toggleTheme()inui.js
- validateXML(src) →
{ ok, line, col, message }(validate.js) - markErrorLine(editor, lineNumber, message, oldDecor) → red squiggle + glyph (
validate.js) - clearAllMarkers() → clears both XML models (
validate.js) - preflight(xmlSrc, xsltSrc) → pre-transform validation (
validate.js) - Debounce timers:
xsltDebounce,xmlDebounce(global)
- prettyXML(xml) → formatted XML string (
panes.js) - fmtEditor(which) → format button handler (
panes.js) - Context menu actions: Format, Minify, Comment/Uncomment (
editor.js)
- triggerUpload(pane) → triggers hidden file input (
files.js) - handleUpload(event, pane) → routes to active model based on
xpathEnabled(files.js) - downloadPane(pane, defaultName) → downloads editor content as file (
files.js) - setupDragDrop(editorWrapId, pane) → drag-and-drop handler (
files.js)
- toggleWordWrap(which) → per-editor state in
_wrapState(panes.js) - copyPane(which) → copies editor content to clipboard (
panes.js) - clearPane(which) → clears editor, both XML models for 'xml' (
panes.js)
- Copy XPath — Exact: Indexed XPath like
/Orders/Order[2]/Amount(editor.js) - Copy XPath — General: Pattern XPath like
/Orders/Order/Amount(editor.js) - Format XML/XSLT, Minify XML/XSLT, Comment/Uncomment Lines
- XSLT Snippets: Common patterns (for-each, choose-when, template, etc.) (
editor.js)
- setupAutoClose(editor) → manual XML tag auto-close (
editor.js) - _updateCursorStat(ed, label) → updates status bar with line/col/char count (
editor.js) - _getXmlLabel() → dynamic label: "XML Input" (XSLT mode) vs "XML Source" (XPath mode) (
editor.js)
- runXPath() → main entry point (
xpath.js) - Saxon-JS evaluation:
SaxonJS.XPath.evaluate(expr, xmlDoc, options) - Namespace bindings:
xs,fn,math,map,arrayauto-provided - _xpathNormalise(result) → flattens XDM sequence to JS array (
xpath.js)
- _highlightXPath(expr) → tokenizes and colors expression (
xpath.js) - Overlay div:
#xpathOverlaypositioned absolutely over textarea - Token colors: Functions (amber), attributes (lavender), strings (green), numbers (orange), operators (pink), variables (lavender), predicates (blue)
- _xpathHistory[] → last 20 expressions (
xpath.js) - _xpathHistoryKey:
'xdebugx-xpath-history' - _xpathHistoryPush(expr) → adds to history, dedupes, persists (
xpath.js) - _xpathHistoryNavigate(direction, input) → up/down navigation (
xpath.js) - _xpathHistoryCursor → current position in history (-1 = not browsing)
- _highlightMatchedNodes(items, xmlSrc) → amber line backgrounds (
xpath.js) - xpathDecorations → global decoration collection
- clearXPathHighlights() → clears decorations (
xpath.js) - _makeLineDecoration(line, hoverMsg) → creates glyph + hover (
xpath.js)
- getXPathAtCursor(editor) → returns
{ indexed, general }(xpath.js) - _buildXPathFromNode(el, indexed) → generates XPath (
xpath.js) - _getXPathDomNodeAtOffset(xmlSrc, offset) → finds element at cursor (
xpath.js) - _findNodeRange(xmlSrc, el, occurrenceIndex) → finds start/end offsets (
xpath.js) - _nthTagOpen(src, tag, n) → finds nth occurrence of tag (
xpath.js) - _offsetToLineCol(src, offset) → converts offset to line/col (
xpath.js)
- renderXPathHints(hints) → displays clickable chips (
xpath.js) - Chip rendering: Syntax-highlighted expressions
- Click handler: Populates input and auto-runs expression
- _showXPathResults(items, errorMsg, isError) → async with Monaco colorization (
xpath.js) - _xpathSerializeItem(item) → converts XDM item to display string (
xpath.js) - Match count → displayed in header panel
- Type labels: Node, Attribute, Text, Value
- clearXPathResults() → hides panel, clears decorations (
xpath.js) - restoreOutputSection() → re-expands output section (
xpath.js)
- toggleXPath() → trigger mode switch to XPath; calls
modeManager.setMode('XPATH')internally (xpath.js) - ModeManager class → Centralized mode switching, all UI sync happens inside
modeManager.setMode()(mode-manager.js) - modeManager.isXpath → getter property (use instead of checking
xpathEnableddirectly) - modeManager.setMode() → primary API for mode changes; updates models, UI, column states automatically
⚠️ DEPRECATED:xpathEnabledis ONLY a JSON key in saved-state — there is no live global. Read the mode viamodeManager.isXpath; never swap XML models manually — callmodeManager.setMode().
- copyXPathInput() → copies expression to clipboard (
xpath.js) - clearXPathInput() → clears expression, clears hints (
xpath.js) - copyXPathResults() → copies all results as plain text (
xpath.js) - _syncXPathInput(value) → syncs textarea value and overlay/height (
xpath.js)
- runTransform() → main entry point (
transform.js) - Saxon-JS 2.x: Bundled in
lib/SaxonJS2.js - saxonReady → global flag, must be true before transforms
- SaxonJS.transform() → called with
stylesheetText+sourceText - Performance timing → logs execution duration
- preflight(xmlSrc, xsltSrc) → validates both before Saxon runs (
validate.js) - Blocks on errors → returns false if validation fails
- Marker placement → highlights errors in editors with red squiggles
- XML detection: Starts with
<→ callsprettyXML() - JSON detection: Starts with
{or[→ validates withJSON.parse(), pretty-prints - Plain text fallback: CSV, fixed-length, EDI, etc. → shown as-is
- Monaco language mode:
setModelLanguage(eds.out.getModel(), lang) - Output badge: Updated to "XML", "JSON", or "TEXT"
- Download filename:
output.xml,output.json, oroutput.txt
- Spinner: Shown for minimum 300ms
- Status updates: "Validating…", "Running…", "Ready", "Transform failed"
- Error state: Red pill in status bar
- Success log: Shows execution time in ms
- kvData → global store:
{ headers: [], properties: [] }(state.js) - toggleKVPanel(panelId) → expand/collapse accordion (
transform.js) - addKVRow(type) → adds new header/property row (
transform.js) - deleteKVRow(type, id) → removes row (
transform.js) - updateKV(type, id, field, val) → edits name or value (
transform.js) - renderKV(type) → renders table with delete buttons (
transform.js) - renderOutputKV(headers, properties) → renders captured values (
transform.js) - Count badges → show number of entries in accordion headers
- rewriteCPICalls(xslt) → rewrites
cpi:namespace tojs:(transform.js) - ensureJsExcluded(xslt) → adds
exclude-result-prefixes="js"(transform.js) - JavaScript interceptors:
window.cpiSetHeader,window.cpiSetProperty - cpiCaptured → local object during transform:
{ headers: {}, properties: {} } - Full XPath evaluation: Supports
concat(),if-then-else,//element/path, variables - Output panels → captured values shown in Output Headers/Properties
- Reads: declare
<xsl:param name="X"/>— values come from Headers/Properties panels viabuildParamsXPath()(mirrors CPI runtime; nocpi:get*exists).
- buildParamsXPath() → injects $exchange + headers/properties (
transform.js) - Always injected → even if no headers/properties defined
- Dummy value → string
'exchange'(not a real object) - Usage constraint → only works as 1st argument to cpi:* functions
- console.log intercept → captures Saxon's stdout during transform
- _xslMessages[] → temporary array local to
runTransform(), flushed before completion log (transform.js) - Console display → logged as amber 'warn' type messages
- Execution order → fired in natural XSLT execution order
- Error detection → regex:
/^Terminated with (.+)$/i - Warning log → not treated as error (intentional halt)
- User-friendly → distinguishes from actual bugs
- parseSaxonErrorLine(msg) → extracts line from error message (
validate.js) - findXPathExpressionLine(saxonMsg, originalXslt, saxonReportedLine, cpiLineOffset) → maps to original XSLT (
validate.js) - Expression search → finds
{...}in error message - Multiple occurrence handling → uses closest match to Saxon line
- Limitation → ±5 line accuracy due to CPI rewriting
- hasCPI flag → detects
xmlns:cpiin XSLT source - Console logging → "CPI simulation enabled" message
- Captured count → logs "X headers captured · Y properties captured"
- Passthrough → input headers/properties merge to output if not overwritten
- isValidNCName(name) → validates param names (
transform.js) - NCName compliance → skips invalid names with console warning
- Map building →
{ exchange: 'exchange', HeaderName: 'value', ... } - stylesheetParams → passed to
SaxonJS.transform()
- CATEGORIES object → 6 categories with labels + accent colors (
examples-data.js) - renderExSidebar() → auto-generates category buttons with counts (
modal.js) - setExCat(cat) → filters grid by category (
modal.js) - 'all' category → shows all 61 examples
Categories:
transform— Data Transformation (8 examples)aggregation— Aggregation & Splitting (4 examples)format— Format Conversion (6 examples)advanced— XSLT 3.0 Advanced (6 examples)cpi— SAP CPI Patterns (18 examples)xpath— XPath Explorer (19 examples)
- EXAMPLES object → 61 examples keyed by ID (
examples-data.js) - Required fields:
label,icon(Lucide icon name, kebab-case string),desc,cat,xml,xslt - Optional fields:
headers,properties,xpathExpr,xpathHints - XPath examples → have
xpathExprinstead ofxslt - CPI examples → include
headers: [['name', 'value'], ...]arrays
- loadExample(key) → loads by key from EXAMPLES object (
modal.js) - Mode detection → switches XSLT↔XPath based on presence of
xpathExpr - Model swap → routes XML to
xmlModelXsltorxmlModelXpath - Content loading → populates XML, XSLT, KV panels
- Output clear → clears previous transform output
- XPath sync → loads expression + displays hints strip
- Modal auto-close → closes after successful load
- _lastExampleKey → global variable tracking current example
- renderExGrid() → builds card grid dynamically (
modal.js) - filterExamples() → search filter on label/desc/category (
modal.js) - Search input →
#exModalSearchwithoninput="filterExamples()" - Card layout → Icon, label, description, category tag
- Click handler →
onclick="loadExample('exampleKey')"
- openExModal() → shows examples library (
modal.js) - closeExModal() → hides modal (
modal.js) - handleModalBackdropClick(e) → click-to-close on backdrop (
modal.js) - Escape key → closes modal (global handler)
- buildSharePayload() → creates payload object (
share.js) - Payload fields:
xml(from xmlModelXslt),xslt,headers,properties - encodeShareData(data) → JSON → base64 → pako compress → base64 (
share.js) - generateShareUrl() → builds
#share/ENCODED_DATAURL (share.js)
- loadFromShareHash() → parses URL hash on page load (
share.js) - Hash detection → looks for
#share/... - _pendingShareData → deferred application after Monaco loads
- applyShareData(data) → populates editors + KV panels (
share.js) - Decompression → base64 decode → pako inflate → JSON parse
- Mode switch → always switches to XSLT mode
- KV restoration → rebuilds headers/properties from arrays
- Error handling → try/catch with console warning
- openShareModal() → generates URL and shows modal (
share.js) - closeShareModal() → hides modal (
share.js) - handleShareBackdropClick(e) → click-to-close (
share.js) - Share URL input → read-only, click-to-select
- _copyShareUrl(url, silent) → copies to clipboard with toast (
share.js)
- XSLT mode only → XPath expressions not included in share payload
- URL length limit → ~2000 chars browser limit, no warning shown
- Client-side only → never hits server, pure URL hash
- Recipients → always land in XSLT mode regardless of original mode
- scheduleSave() → debounced 800ms (
state.js) - saveState() → writes to localStorage (
state.js) - _saveTimer → debounce timer handle (
state.js) - _suppressNextSave → guards programmatic changes (
state.js) - Storage key:
'xdebugx-session-v1'
- xmlXslt → XSLT mode XML model content
- xmlXpath → XPath mode XML model content
- xslt → XSLT editor content
- headers → KV headers array
- properties → KV properties array
- xpathExpr → XPath expression
- xpathEnabled → mode flag (boolean)
- leftCollapsed → left column state (boolean)
- rightCollapsed → right column state (boolean)
- loadSavedState() → reads from localStorage (
state.js) - Backward compatibility → migrates old
'xml'key to'xmlXslt' - Session restoration →
editor.jsrestores full state - Model restoration → creates both XML models with saved content
- Mode restoration → swaps to correct XML model based on
xpathEnabled - KV restoration → rebuilds headers/properties panels
- Column state → restores collapsed states
- XPath state → restores expression + hints
- clearSavedState() → mode-aware reset (
state.js) - XSLT mode reset → identity transform + sample XML
- XPath mode reset → XPath navigation example
- localStorage clear → removes
'xdebugx-session-v1'key - History clear → wipes
_xpathHistory - KV clear → empties headers/properties
- Output clear → resets output editor language to XML
- Markers clear → removes validation errors
- Console preserved → logs "Session cleared" action
- Mode preserved → stays in current mode (XSLT or XPath)
- showSavedIndicator() → flashes "Saved" pill (
state.js) - _savedFadeTimer → 2-second fade timer (
state.js) - Opacity animation → CSS transition
- clog(msg, type) → main logging function (
state.js) - Types:
'info','warn','error','success' - Icons per type: ℹ️,
⚠️ , ❌, ✅ - escHtml(s) → XSS protection for log messages (
state.js) - Timestamp → HH:MM:SS format
- clearConsole() → clears all log lines (
state.js) - copyConsole() → copies all messages to clipboard (
ui.js) - consoleErrCount → global error counter
- updateConsoleErrBadge() → updates error count badge (
ui.js) - handleConsoleBarClick(e) → toggles panel expand/collapse (
ui.js) - setConsoleState(state) → 'expanded' | 'collapsed' | 'minimized' (
ui.js)
- setConsoleFilter(filter) → filters by 'all', 'info', 'warn', 'error' (
ui.js) - Active button highlight →
.activeclass toggle - CSS filtering → shows/hides by
.console-${type}class - Filter buttons → color-coded circle dots
- applyConsoleSearch(query) → keyword filter (
ui.js) - Case-insensitive → uses
toLowerCase() - Highlights matches → text contains search query
- Combined filtering → works with type filter
- toggleTheme() → switches light↔dark (
ui.js) - localStorage persistence →
'xdebugx-theme'key - Body class →
'light'or none (dark default) - Monaco theme →
'xdebugx-light'or'xdebugx' - Button emoji → ☀️ sun (light mode) / 🌙 moon (dark mode)
- Smooth transition → CSS transitions on theme switch
- openHelpModal() → shows help modal (
ui.js) - closeHelpModal() → hides modal (
ui.js) - handleHelpBackdropClick(e) → click-to-close on backdrop (
ui.js) - switchHelpTab(tab) → switches between 'features' and 'shortcuts' tabs (
ui.js) - Tab content → features list, keyboard shortcuts table
- toggleSideCol(side) → toggles 'left' or 'right' column (
ui.js) - Collapse buttons → arrow icons in pane bars
- Tab handles → clickable when collapsed (
.col-tab) - Editor layout → calls
eds.xml.layout()after expand/collapse - Mode-aware → XPath mode can hide center (XSLT) column
- setStatus(txt, state) → updates status pill (
state.js) - States:
'ok','err','busy' - Color coding → green, red, blue
- Icon per state → ✓, ✗, spinner
- Cursor stats → line, column, character count
- Dynamic label → "XML Input" vs "XML Source" based on mode
- Backdrop click-to-close → all modals support this
- Escape key → closes any open modal (global listener)
- Centered layout → CSS Flexbox centering
- Close button → ✕ icon in top-right
- Z-index stacking → proper layering with
.ex-modal-backdrop
- KV panels → Headers, Properties, Output Headers, Output Properties
- Chevron icon → rotates on expand/collapse (CSS transform)
- Badge counts → shows number of entries in accordion header
- Add buttons →
+icon, usesevent.stopPropagation() - Delete buttons → per-row
×icon with hover highlight
- User loads XML + XSLT (manual entry, file upload, or example)
- Press Run XSLT button or
Ctrl+Enter preflight()validates XML and XSLT well-formedness- If CPI namespace detected (
xmlns:cpi),rewriteCPICalls()rewrites tojs: ensureJsExcluded()addsexclude-result-prefixes="js"buildParamsXPath()injects$exchange+ headers/properties as params- Saxon-JS runs
SaxonJS.transform() - Output language detected (XML/JSON/plain text)
- Output pretty-printed if XML or JSON
- CPI-captured values shown in Output Headers/Properties panels
xsl:messagelines logged to console as warnings- Success/error status displayed in status bar
- User clicks ƒx XPath mode button or switches via example
- XML editor swaps to
xmlModelXpathmodel - UI updates (hides XSLT column, shows XQuery bar, moves console)
- User types XPath expression (live syntax coloring applied)
- Press Run XPath button or
Enterkey - XML validated for well-formedness
- Saxon-JS evaluates
SaxonJS.XPath.evaluate() - Results normalized to flat array
- Items serialized and syntax-colored via Monaco
- XPath Results panel shown with match count
- Matched nodes highlighted in amber in XML editor
- Output section minimized automatically
- Expression added to history (max 20)
- User clicks Examples button in header
- Modal opens with category sidebar + grid layout
- User selects category or uses search filter
- User clicks example card
loadExample()detects mode (XSLT vs XPath based onxpathExpr)- If mode switch needed,
modeManager.setMode('XPATH')is called (or viatoggleXPath()thin wrapper) - XML editor model swapped to match new mode
- Content loaded to editors (XML, XSLT or XPath expression)
- Headers/Properties populated (if XSLT example)
- XPath expression + hints loaded (if XPath example)
- Modal closes automatically
- User can immediately run transform/evaluation
- User clicks Share button in header
buildSharePayload()collects current state- Data compressed (pako) and base64-encoded
- URL generated with
#share/ENCODED_DATAhash - Modal shows URL in read-only input field
- User clicks Copy URL button
- URL copied to clipboard
- Success toast notification shown
- Recipient opens URL in browser
loadFromShareHash()parses hash on page load- State restored after Monaco loads (via
_pendingShareData) - Always lands in XSLT mode regardless of original mode
- Page loads, Monaco loader script runs
loadSavedState()reads from localStorage- Both XML models created with saved content (xmlXslt, xmlXpath)
- Editors initialized with saved XSLT content
xpathEnabledflag restored from saved session- XML editor model swapped to match restored mode
- KV panels populated with saved headers/properties
- Column collapse states applied
- XPath expression restored to input
- If share hash present in URL, overrides saved state
state.js → mode-manager.js → validate.js → panes.js → transform.js →
examples-data.js → modal.js → files.js → ui.js → share.js → xpath.js → editor.js
- eds →
{ xml, xslt, out }Monaco editor instances - xmlModelXslt → XML model for XSLT mode
- xmlModelXpath → XML model for XPath mode
- saxonReady → boolean flag for Saxon-JS readiness
- modeManager →
ModeManagerinstance; mode is read viamodeManager.isXpath(thexpathEnabledflag is a JSON-key only, not a live global) - kvData →
{ headers: [], properties: [] } - kvIdSeq → auto-increment ID for KV rows
- EXAMPLES → object with 61 examples
- CATEGORIES → object with 6 category definitions
- consoleErrCount → global error counter
- _suppressNextSave → skip next scheduleSave() call
- _suppressNextXmlChange → skip next XML content-change handler
- _suppressNextValidation → skip next validation debounce
- clog() → called from all modules
- scheduleSave() → called on editor changes, file operations
- validateXML() → called from validate, transform, xpath
- preflight() → called before transform
- clearAllMarkers() → called from state, modal, validate
- prettyXML() → called from panes, transform, xpath, editor
- toggleXPath() → thin wrapper; calls
modeManager.setMode('XPATH')from modal (example loading), editor (keyboard) - modeManager.setMode() → centralized mode switching; called from modal, editor, share, xpath
- _syncXPathInput() → called from state, modal, editor
- _updateCursorStat() → called from modal, editor, xpath
- renderXPathHints() → called from state, modal, xpath
- clearXPathHighlights() → called from editor, xpath
- clearXPathResults() → called from state, xpath, modal
- restoreOutputSection() → called from transform
- Check if Monaco API supports it natively
- Add global state variable if needed (prefix with
_if private) - Implement in appropriate module (editor.js for Monaco, panes.js for actions)
- Call
scheduleSave()if state should persist - Update
saveState()/loadSavedState()if new persistent field
- Add to
rewriteCPICalls()regex patterns - Create JavaScript interceptor function
- Intercept in transform before Saxon runs
- Return value to XSLT via Saxon's
js:extension - Test with CPI simulation example
- Document in help modal if user-facing
- Add entry to
EXAMPLESobject inexamples-data.js - Use existing category or add to
CATEGORIESif new - Follow example structure:
{ label, icon, desc, cat, xml, xslt } - For XPath examples: include
xpathExprfield - For CPI examples: include
headersandpropertiesarrays - Test via Examples modal
- Add to
preflight()invalidate.jsfor blocking errors - Add to debounced validation for live feedback
- Use
markErrorLine()for visual markers - Use
clog()for console messages - Return
falsefrompreflight()to block transform
- Global namespace → no module system, all functions are global
- Load order matters → modules depend on previous modules being loaded
- Model swap events → synthetic content-change events require suppression flags
- Saxon async readiness → must check
saxonReadybefore XSLT/XPath operations
- $exchange not a real object → dummy string, only works as 1st arg to cpi:*
- Error line mapping → ±5 line accuracy due to XSLT rewriting
- No dynamic namespace registration → CPI namespace must be declared in XSLT
- XSLT mode only → XPath expressions and mode not shared
- URL length limit → ~2000 chars browser limit, no user warning
- Client-side only → never hits server, pure URL hash
- localStorage limit → ~5-10MB per domain
- Clipboard API → falls back to
execCommandfor file:// protocol - Monaco CDN → requires internet connection (no offline mode)
- Test in both XSLT and XPath modes
- Verify session persistence (save → reload → verify state)
- Test with CPI examples (headers/properties simulation)
- Verify validation works (XML + XSLT errors marked)
- Test example loading (mode switching)
- Test share URL (encode → decode → verify state)
- Test in light and dark themes
- Test file upload/download
- Test drag-and-drop
- Test context menu actions
- Verify console logging (info/warn/error/success)
- Test column collapse/expand
- Test keyboard shortcuts (Ctrl+Enter)
- Test with large files (performance)
- Test error scenarios (invalid XML, XSLT errors)
| Function | File | Purpose |
|---|---|---|
runTransform() |
transform.js | Main XSLT transform entry |
runXPath() |
xpath.js | Main XPath eval entry |
toggleXPath() |
xpath.js | Mode switch XSLT↔XPath |
loadExample(key) |
modal.js | Load example by key |
validateXML(src) |
validate.js | XML validation |
preflight(xml, xslt) |
validate.js | Pre-transform check |
prettyXML(xml) |
panes.js | XML formatter |
clog(msg, type) |
state.js | Console logger |
saveState() |
state.js | Save to localStorage |
loadSavedState() |
state.js | Load from localStorage |
clearSavedState() |
state.js | Clear localStorage |
buildSharePayload() |
share.js | Build share data |
applyShareData(data) |
share.js | Apply share data |
For detailed implementation examples, see individual module files.
For CPI simulation details, see .github/docs/TRANSFORM.md.
For example structure, see .github/docs/reference/examples-data.md.