Skip to content

Narrative generation fails when a liquid template puts {{...url}} inside an href attribute, because url elements now render as hyperlinks #1320

Description

@johngrimes

With publisher 2.2.8, every PlanDefinition in our IG that carries a relatedArtifact of type citation with an absolute url gets this in place of its narrative:

Exception generating Narrative: unexpected non-end of element null::a at line 136 column 55

The base template's PlanDefinition.liquid renders citations like this (https://github.com/HL7/ig-template-base/blob/master/liquid/PlanDefinition.liquid#L285):

<li>{{artifact.citation}}<br/><a href="{{artifact.url}}">{{artifact.url}}</a></li>

The liquid engine no longer substitutes the raw string for {{artifact.url}}. Non-string datatypes go through LiquidRenderer.renderForLiquid, which runs the standard datatype renderer, and DataRenderer.renderUri wraps any linkable absolute URL in its own anchor (x.ah(v).addText(v)). So the template output ends up with an anchor nested inside the attribute:

<a href="<a href="https://www.rcpa.edu.au/...">https://www.rcpa.edu.au/...</a>">...

When the publisher parses that back, XhtmlParser takes <a href= as the attribute value (ending at the second quote), reads https: as a junk attribute name, hits the //, and throws unexpected non-end of element from parseElement. The reported position is always line 136 column 55 regardless of the resource content, because the failing prefix <li><br/><a href="<a href="https is identical for every https citation URL.

To reproduce, build an IG with the base template containing any PlanDefinition along the lines of:

{
  "resourceType": "PlanDefinition",
  "id": "example",
  "status": "draft",
  "relatedArtifact": [
    {
      "type": "citation",
      "url": "https://example.org/some-guideline"
    }
  ]
}

The same pattern exists at PlanDefinition.liquid line 277 (documentation/justification artifacts), Library.liquid lines 282 and 290, and ActivityDefinition.liquid line 197, so Libraries and ActivityDefinitions with citation or documentation related artifacts should fail the same way.

I can see two ways to fix it, and I am happy to put up a PR for whichever is preferred:

  • have renderForLiquid return primitiveValue() for primitive types rather than running the datatype renderer, so {{...}} substitution of a url is attribute-safe again, or
  • change the templates to emit {{artifact.url}} bare and let the renderer do the linking, which makes the explicit anchors redundant.

Relevant code: LiquidEngine.liquify (org.hl7.fhir.r5.liquid.LiquidEngine, the renderForLiquid branch), LiquidRenderer.renderForLiquid (org.hl7.fhir.r5.renderers.LiquidRenderer), DataRenderer.renderUri, and the throw at XhtmlParser.parseElement.

Metadata

Metadata

Assignees

Labels

ApprovedChange has been reviewed and accepted and can now be applied to the templatesenhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

Status
To do

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions