# Wizly — Magic xpa Web Client Post‑Processor
Wizly automatically post‑processes HTML generated by Magic xpa Web Client.
Using powerful, configurable regex rules, it fixes structural and quality
issues and lets you switch to other UI frameworks if you prefer. Transformations
run right after generation when you trigger Wizly, or automatically for new files
when autoTransformOnCreate is enabled; you don’t need to manually edit the
generated HTML, which saves time and yields consistent, maintainable output.
Wizly is a VS Code extension that uses a project configuration file.
You can export .vswizly.js and keep it in version control so the
whole team applies the same rules.
✨ Features
- Regex‑based HTML post‑processing
- Shared project config via
.vswizly.js (version‑controlled)
- Auto‑transform on file creation (
autoTransformOnCreate)
- Optional info toast (
autoTransformToast)
- Transform tag to avoid re‑processing
- Commands: Transform current file, Transform uncommitted files, Export settings / templates / advanced rules
- Status bar showing active rule count with quick access to the config file
- Works with another editor: keep VS Code open with
autoTransformOnCreate: true; new .html files in the workspace transform automatically.
- Compatibility: Requires
VS Code 1.109.0+
Bundled Default Rules
The bundled default rules adjust Magic‑generated HTML in several ways to improve structure, framework compatibility, and maintainability:
- Rebuild the base to use a
<form> instead of a <div>
- Replace non‑input
<label> elements with <span> (Magic puts default text in <label>, which is not per HTML guidelines)
- Remove
<div> elements that break Material Design components
- Remove wrapper
<div> elements around form controls
- Remove
mat-card wrapper for subforms
- Change
<div> with inline flex row styling to Bootstrap classes
- Replace
visibility inline style with Bootstrap d-none classes (note: display: none does not preserve element height, visibility: hidden does)
Tables:
- Change
mat-table (flex layout) to native HTML <table> to support better column behavior and row/col‑span capabilities
- Remove classes
container_border and table_row from the table
- Use
formgroup on <tr> instead of in each <td> (needs extra testing)
🚀 Usage
Shortcuts
Use Ctrl+Shift+P (Windows/Linux) or Cmd+Shift+P (macOS) to open the command palette and type "Wizly".
Commands
Wizly: Transform Current File — transform the active file
Wizly: Transform All Uncommitted Files — transform files changed in Git
Wizly: Export Settings — writes a starter .vswizly.js at the workspace root (fails if the file already exists)
Wizly: Export Templates — exports the built-in EJS templates so you can customise them per project
Wizly: Export Advanced Rules — exports the built-in regex rules as a starting point for custom rules
Creating Custom Rules
Edit the project config file directly to tailor transformations for your codebase.
Use a versioned .vswizly.js at the workspace root to share rules across your team. Changes are automatically reloaded. If the file is missing, Wizly uses built‑in defaults.
- Run
Wizly: Export Default Rules to .vswizly.js
- Open the file in the project root
- Add, modify, or disable rules as needed
- Save — changes are picked up automatically
See docs/rules.md for advanced rule fields, rationale, and tips. For full before/after samples, see examples/.
⚙️ Configuration
VS Code Settings
The following settings can be configured in VS Code (settings.json or the Settings UI under Wizly):
| Setting |
Default |
Description |
wizly.autoTransformOnCreate |
false |
Automatically transform new .html files on creation |
wizly.autoTransformToast |
true |
Show a notification after an automatic transform |
wizly.transformTag.enable |
true |
Insert a "Changed by Wizly" comment at the top of transformed files |
wizly.transformTag.dateFormat |
"YYYY-MM-DD" |
Date format used in the transform tag |
wizly.transformTag.timeFormat |
"HH:mm" |
Time format used in the transform tag |
wizly.transformTag.template |
"Changed by Wizly on {date} at {time}" |
Template for the transform tag comment |
wizly.zoomIcon |
"search" |
Material icon name used for zoom buttons (e.g. "search", "more_horiz", "open_in_new") |
wizly.removeEmptyLinesAfterPrettier |
false |
Strip empty lines introduced by Prettier between block elements |
wizly.smartTabMatcher |
false |
Extract tab_content divs and place their content inside mat-tab elements (required for Angular Material tab animations) |
wizly.smartLabelMatcher.enabled |
false |
Enable smart label matching |
wizly.smartLabelMatcher.labelPrefix |
"L_" |
Prefix(es) for label magic attributes — string or array of strings |
wizly.smartLabelMatcher.controlPrefix |
["V_", "P_"] |
Prefix(es) for control magic attributes — string or array of strings |
wizly.customSmartMatchers |
[] |
Optional user-defined extractors using regex named capture groups (must include magic), with optional matchOn mapping and remove |
Prettier Integration
Wizly uses Prettier to format HTML after applying regex rules.
- Bundled Prettier: the extension ships its own Prettier package, so users don’t need to install anything.
- Prefer workspace Prettier: if your project has
prettier installed, Wizly will prefer that workspace version.
- Respect workspace config: Wizly reads your Prettier configuration (
.prettierrc, prettier.config.*, or package.json prettier field) via resolveConfig and applies it. Team settings take precedence over the defaults.
- VS Code Prettier extension: the separate “Prettier” editor extension is not required for Wizly. Wizly uses its own Prettier module, but still follows your project configuration.
Known Limitations
- Tested with Magic xpa 4.12.1. Other versions may produce different HTML output that requires rule adjustments.
- Designed for the Material Design rendering engine only. It does not work with SmartUX.
- Regex is not well‑suited for deeply nested or recursive HTML structures. Prefer narrow, targeted patterns and consider splitting complex transforms into multiple rules.
Rules execute in order (top to bottom). Later rules run on the output of earlier rules, so order matters. Place broader patterns first and more specific ones after to get the desired result.
Add a tag at the top of transformed files to avoid re‑processing and provide an audit trail. Placeholders {date} and {time} are supported; see the configuration example above.
Smart Label Matcher
When wizly.smartLabelMatcher.enabled is true, the extension automatically moves standalone <label> elements into the corresponding <mat-form-field> as a <mat-label>.
How it works:
- Looks for
<label> elements with [magic] attributes that start with labelPrefix (default L_, can also be an array)
- Checks if there is a corresponding control element with a
[magic] attribute starting with one of the controlPrefix values (default ["V_", "P_"])
- If a matching control is found, the standalone label is removed
- The label content is wrapped in
<mat-label> and inserted before the control element
Custom Smart Matchers
wizly.customSmartMatchers lets you define additional optional extractors. Each matcher:
- Runs before the main rule processing
- Extracts all regex named capture groups into a stored record
- Requires a named capture group
magic
- Can optionally remove the matched block (
remove: true)
- Can optionally map
magic via matchOn (prefix/suffix) to attach the match to a control magic ID
Example (zoom button capture, default disabled):
{
name: "smartZoomMatcher",
enabled: false,
filePattern: "*.html",
regex: /(?<button><button\b[^>]*?(?:magic|\[magic\])="(?<magic>mgc\.[^"]+)"[^>]*>)(?<content>[\s\S]*?)<\/button>/gm,
remove: true,
matchOn: {
matchPrefix: "Z_",
controlPrefix: ["V_", "P_"],
controlSuffix: ""
}
}
Notes
matchPrefix and matchSuffix can be used together. If you provide both, both must match.
- By default, the control check is exact. For example,
V_Combo does not match V_ComboBox.
- If you want to allow extra suffix text in the control magic (e.g.
V_ComboBox should match V_Combo), set controlSuffix: "*".
Example:
<!-- Before transformation -->
<label [magic]="mgc.L_firstName">First Name</label>
<mat-form-field>
<input [magic]="mgc.V_firstName" />
</mat-form-field>
<!-- After transformation -->
<mat-form-field>
<mat-label>First Name</mat-label>
<input [magic]="mgc.V_firstName" />
</mat-form-field>
🎯 Example
See examples/ for full before/after sample.
ℹ️ How Replace Works
See docs/rules.md for details on the EOF marker, named groups, and regex flags.
🛠️ Development
Development Requirements
Note: End users installing the extension do not need Node.js. Runtime compatibility is governed by engines.vscode in package.json (currently ^1.109.0).
📚 Documentation
📝 Changelog
See CHANGELOG.md for the full release history.
🤝 Contributing
Feedback and ideas are welcome via Issues: https://github.com/SybrenVanZon/wizly-plugin/issues
Credits
- Built for Magic xpa Web Client workflows.
- Author: Sybren van Zon — Magic xpa & Angular · Wizly author & maintainer.
Disclaimer
This extension is not affiliated with or endorsed by Magic xpa or Magic Software Enterprises. All trademarks are the property of their respective owners.
📄 License
MIT License — see LICENSE file for details.