Xporter syntax: what works
An honest map of how Xporter-style template syntax is handled when you upload a Word document into Word Template Mode. This mirrors the migration scanner that runs on every upload — the same classifications you see in the editor's compatibility report.
The honest promise
Exportelier is not Xporter-compatible, is not an Xporter replacement, and does not run Xporter templates. What it does is help you migrate: on upload, the scanner recognizes common Xporter-style syntax and tells you, construct by construct, whether it already works, can be converted automatically, needs a manual rewrite, or is out of scope by design.
Two hard guarantees:
- Foreign syntax is only recognized, never executed. The scanner reads the shape of a construct —
#{for …},${dateformat(…)}— and nothing in an uploaded template is ever evaluated as code. - No vendor code is copied. The detection patterns and alias suggestions are Exportelier-authored from publicly documented syntax shapes.
Every finding falls into one of four classes.
1. Supported as-is
If your template already uses Exportelier's canonical syntax it simply works. These produce an informational note, not a warning.
| Construct | Example |
|---|---|
| Value token | ${issue.key} |
| Loop | ${#each issue.subtasks as sub}…${/each} |
| Conditional | ${#if issue.assignee}…${#else}…${/if} |
2. Auto-convertible
Common Xporter syntax with a safe one-to-one equivalent. The editor shows a warning and offers a copyable replacement.
| Xporter construct | Exportelier equivalent | Notes |
|---|---|---|
${Key}, ${Summary}, ${Status}, … | ${issue.key}, ${issue.summary}, ${issue.status}, … | Scalar field aliases. |
${Assignee.displayName} | ${issue.assignee.displayName} | Known root alias; the rest of the path is kept. |
#{for comments} | ${#each comments as c} | Loop opening. |
#{if(Assignee)} | ${#if issue.assignee} | Simple truthiness conditional. |
#{else} | ${#else} | Else marker. |
Recognized scalar aliases (16): Key, Summary, Description, Status, Priority, Resolution, Assignee, Reporter, Creator, Created, Updated, DueDate, IssueType, Type, Project, Labels.
Recognized collection aliases (5): Comments, Attachments, Subtasks, Links, Worklogs.
A suggested rewrite has the right shape, but the target must still be a real binding in the token reference. Some aliases need a manual adjustment:
- Not bindable:
Creator→issue.creator,Resolution→issue.resolution,Project→issue.project,IssueType/Type→issue.issuetype. None is a Tier-A binding. - Case mismatch:
DueDateis suggested asissue.duedate; the binding isissue.dueDate. - Kind mismatch:
Labelsis suggested as a scalar, butissue.labelsis a collection — use${#each issue.labels as l}…. - Issue links:
Linksis suggested aslinks, but the real binding isissue.issueLinks.
3. Unsupported but explainable
No clean one-to-one mapping, but a clear way to express the same intent. The editor explains the rewrite; it is a warning, not a blocker.
| Xporter construct | Why | What to do instead |
|---|---|---|
${Comments[0].Body} | Paths have no bracket indexing. | Iterate: ${#each comments as c}${c.body}${/each}. |
#{end} | One generic terminator. | Use the matching close — ${/each} or ${/if}. |
#{if(votes > 0)} | Conditions test only truthiness of a single path — no operators. | Test presence instead: ${#if issue.votes}. |
#{elseif(…)} | There is no elseif. | Nest conditionals. |
Any other #{…} directive | Not recognized. | Replace with ${…} syntax. |
Unbalanced ${#each}/${/if}, bad path, unterminated ${ | Caught by the parser. | Fix the token; the report shows the exact position. |
4. Unsafe or not supported
Out of scope on purpose — supporting these would turn the template into a scripting engine, which Exportelier deliberately is not. The editor shows an error and the construct is never executed.
| Xporter construct | Status | What to do instead |
|---|---|---|
${dateformat("yyyy-MM-dd")} and other function or filter calls | Functions are never run. | Use the fixed formatter set, e.g. ${issue.created | date("yyyy-MM-dd")}. |
${jql("project = ABC")} / #{JQL: …} | JQL is never run from a template. | Choose issues via the export context. |
| JavaScript, Groovy, Velocity, FreeMarker, JS filters | Not a scripting language. | Express the layout with tokens, loops, conditionals and formatters. |
set variables, break/continue, arithmetic, expressions | Not a scripting language. | Restructure into the supported constructs. |
What the validator does with these findings
At upload time each finding becomes a diagnostic with a severity:
- info — supported as-is, no action.
- warning — auto-convertible or explainable; the export still proceeds, though a value may render empty if a binding is unknown.
- error — unsafe or unsupported syntax, an unsafe path, or a parse error.
Constructs that Word preserves but does not fill — text boxes, footnotes, content controls, field codes, comments and tracked changes — are reported separately as unsupported-location warnings. The document keeps them, but tokens inside them are not filled.