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 see word-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:

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 an unknown-binding / wrong-binding-kind warning:

  • Not bindable in V1.1: Creatorissue.creator, Resolutionissue.resolution, Projectissue.project, IssueType/Typeissue.issuetype. None is a Tier-A binding.
  • Case mismatch: DueDate is suggested as issue.duedate; the binding is issue.dueDate (capital D).
  • Kind mismatch: Labels is suggested as a scalar ${issue.labels}, but issue.labels is a collection — use ${#each issue.labels as l}….
  • Issue links: Links is suggested as links, but the real binding is issue.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:

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.