Migrating from Xporter — What Works and What Doesn't — Help
An honest map of how Xporter-style template syntax is handled when you upload a Word document into Word Template Mode. This is derived from the migration scanner Exportelier runs on every upload — the same classifications you see in the editor's compatibility report. For Exportelier's own grammar see
word-template-mode.md; for the full binding list seeword-template-token-reference.md.
i18n note: This page is EN-first. The German translation follows with the next localization pass — no code change is required to ship DE.
The honest promise
Exportelier is not "Xporter-compatible" and is not an Xporter replacement, and it does not run Xporter templates. What it does is help you migrate: when you upload a Word document, 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 example
#{for …}or${dateformat(…)}); nothing in an uploaded template is ever evaluated as code. - No vendor code is copied. The detection patterns and the alias suggestions are Exportelier-authored from publicly documented Xporter syntax shapes. Xporter's engine and templates are not embedded.
Every finding falls into one of four classes.
1. Supported as-is (no change needed)
If your template already uses Exportelier's canonical syntax, it just 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 (a copyable fix is offered)
Common Xporter syntax that has a safe, one-to-one Exportelier equivalent. The editor shows a warning and offers a copyable replacement token.
| Xporter construct | Exportelier equivalent | Notes |
|---|---|---|
${Key}, ${Summary}, ${Status}, … |
${issue.key}, ${issue.summary}, ${issue.status}, … |
Scalar field aliases (see the full list below). |
${Assignee.displayName} |
${issue.assignee.displayName} |
Known root alias + the rest of the path kept as-is. |
#{for comments} |
${#each comments as c} |
Loop opening → each-block opening. |
#{if(Assignee)} |
${#if issue.assignee} |
Simple truthiness conditional. |
#{else} |
${#else} |
Else marker. |
Recognized scalar field 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.
Important — conversion fixes the syntax, not the binding. A suggested rewrite uses the Exportelier shape, but the target path must still be a real binding (see
word-template-token-reference.md). Some aliases need a manual adjustment or they show anunknown-binding/wrong-binding-kindwarning:
- Not bindable in V1.1:
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(capitalD).- Kind mismatch:
Labelsis suggested as a scalar${issue.labels}, butissue.labelsis a collection — use${#each issue.labels as l}….- Issue links:
Linksis suggested aslinks, but the real binding isissue.issueLinks— use${#each issue.issueLinks as l}….
3. Unsupported but explainable (manual rewrite)
No clean one-to-one mapping, but there is a clear way to express the same intent. The editor explains the rewrite (and often suggests a starting point); it is a warning, not a blocker.
| Xporter construct | Why | What to do instead |
|---|---|---|
${Comments[0].Body} (indexed access) |
Paths have no bracket indexing. | Iterate the collection: ${#each comments as c}${c.body}${/each}. |
#{end} |
One generic terminator. | Use the matching close — ${/each} for a loop or ${/if} for a conditional. |
#{if(votes > 0)} (operators) |
Conditions test only truthiness (non-empty) of a single path — no operators or comparisons. | Restructure to test presence, e.g. ${#if issue.votes}. |
#{elseif(…)} |
There is no elseif. |
Nest conditionals: ${#if …}…${#else}${#if …}…${/if}${/if}. |
Any other #{…} directive |
Not recognized. | Replace with Exportelier ${…} syntax. |
Native grammar mistakes (unbalanced ${#each}/${/if}, bad path, unterminated ${) |
Caught by the parser. | Fix the token; the report shows the exact position. |
4. Unsafe / not supported (by design — never executed)
These are out of scope on purpose, because supporting them would turn the template into a scripting/expression engine — which Exportelier deliberately is not ("No Word-Macros. No XSL-FO. No Handlebars."; no Velocity/Groovy). 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 / filter calls |
Functions are never run. | Use the fixed formatter set, e.g. ${issue.created | date("yyyy-MM-dd")} (see word-template-mode.md). |
${jql("project = ABC")} / #{JQL: …} |
JQL is never run from a template. | Choose which issues to export via the export context (single issue, JQL search, board, sprint, release, backlog). |
| 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; export still proceeds, the value may render empty if a binding is unknown.
- error — unsafe/unsupported syntax, an unsafe path, or a parse error.
The compatibility report groups findings so you can work through them, and
auto-convertible findings come with a copyable replacement. Constructs that Word
preserves but does not fill (text boxes, footnotes, content controls, field codes,
comments/tracked changes) are reported separately as unsupported-location
warnings — the document keeps them, but tokens inside them are not filled. See the
limitations section of word-template-mode.md.