Difference between revisions of "IG Publisher Documentation"
(→Paths) |
(Reorganised page to make it more logical and easier to follow, OK'd with GG) |
||
Line 1: | Line 1: | ||
= Summary = | = Summary = | ||
− | |||
− | |||
− | |||
− | |||
− | |||
The FHIR team provides an IG Publishing tool that takes the implementation guide resources and converts them to a set of 3 different types of files: | The FHIR team provides an IG Publishing tool that takes the implementation guide resources and converts them to a set of 3 different types of files: | ||
Line 11: | Line 6: | ||
* 6 standard zip files: definitions.[fmt].zip and examples.[fmt].zip - these are used by implementers for various purposes, so should be included in the final published version | * 6 standard zip files: definitions.[fmt].zip and examples.[fmt].zip - these are used by implementers for various purposes, so should be included in the final published version | ||
− | + | Building an IG is a 4 part process: | |
− | # | + | # [[#Installing|Installing the publisher]] |
− | # | + | # Defining the resources that underpin the Implementation Guide resources (Implementation Guide, Conformance Resources, Knowledge statements, examples) - using either [[#Using_Bundles|bundles]] or [[#Using_Spreadsheets|spreadsheets]] |
− | # | + | # Developing the structure and the narrative content that turns the resources into a useful implementation guide |
+ | # Running the publishing process that will publish it | ||
− | Alternatively, you may use the IG publisher to validate and render a set of Profiles, value sets etc without building a formal IG (see command line mode | + | Alternatively, you may use the IG publisher to validate and render a set of Profiles, value sets etc without building a formal IG (see [[#Validating_without_publishing|command line mode]]) |
= Examples = | = Examples = | ||
− | + | If you want an example of IG source, you can look in one of the following places: | |
− | * FHIR SVN repository, in \build\guides\* - any directory ending in 2 - a variety of styles of | + | * FHIR SVN repository, in \build\guides\* - any directory ending in 2 - a variety of styles of implementation guide. |
* Also, there's \build\tests\ig which is used for testing the tooling | * Also, there's \build\tests\ig which is used for testing the tooling | ||
+ | = Using FHIR IG Publisher = | ||
− | = | + | == Installing == |
− | + | # Get the publisher itself: this is a java jar called <code>org.hl7.fhir.igpublisher.jar</code>. You can get it from the downloads (e.g. [http://build.fhir.org/downloads.html http://build.fhir.org/downloads.html]) for the version of FHIR you are using (or, if you build locally, from your own publish directory). The jar includes everything from the spec that is required to generate the implementation guide. | |
− | + | # Get the publishers helper: you need to install Jekyll in order to publish the said implementation guide. See [http://jekyll-windows.juthilo.com/1-ruby-and-devkit/ Windows] and [http://jekyll.tips/jekyll-casts/install-jekyll-on-linux/ Linux] instructions. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Make sure you use the correct version of the IG publisher for your guide (check the versions in the log), since the IG publisher only supports the version of FHIR it's been made for. | |
− | + | The publisher can be run as a GUI application, or run from the command line. It can also can be hosted in a server - if you want to host it, talk to Grahame Grieve. | |
− | + | == Running in GUI mode == | |
− | + | '''Windows''': double-click on org.hl7.fhir.igpublisher.jar or right-click and select 'Open'. | |
− | + | '''Linux''': double-click on org.hl7.fhir.igpublisher.jar or right-click and select 'Open With Oracle Java 8 Runtime'. | |
− | |||
− | |||
− | |||
− | |||
− | + | You can also run it the command line: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
java -jar org.hl7.fhir.igpublisher.jar | java -jar org.hl7.fhir.igpublisher.jar | ||
Line 103: | Line 47: | ||
[[File:ig-builder.png]] | [[File:ig-builder.png]] | ||
− | To use it, 'Choose' an implementation guide control file, and click 'Execute'. The implementation guide will be built, and then the IG publisher will watch for changes until and do incremental rebuilds until you click 'Stop'. | + | To use it, 'Choose' an implementation guide control JSON file, and click 'Execute'. The implementation guide will be built, and then the IG publisher will watch for changes until and do incremental rebuilds until you click 'Stop'. |
− | == | + | == Ruinning in command line mode == |
To run in command line mode, run the IG Publisher like this: | To run in command line mode, run the IG Publisher like this: | ||
Line 112: | Line 56: | ||
parameters: | parameters: | ||
− | * -ig: a path or a url where the implementation guide control file is found | + | * -ig: a path or a url where the implementation guide JSON control file is found (see [[#Control_file|control file format documentation]]) |
− | * -tx: (optional) | + | * -tx: (optional) address to use for terminology server (default is http://fhir3.healthintersections.com.au - which is currently the only supported option) |
− | * -watch (optional): if this is present, the publisher will not terminate; instead, it will stay running, | + | * -watch (optional): if this is present, the publisher will not terminate; instead, it will stay running, and watch for changes to the IG or its contents and re-run when it sees changes. Note that changes the spec or to dependent implementation guides (see below) are not picked up during watch mode |
+ | |||
+ | Windows example: | ||
+ | |||
+ | [https://www.lifewire.com/how-to-open-command-prompt-2618089 Open the command prompt], then paste the following, with the paths adjusted for your computer: | ||
+ | java -jar "C:\Users\VadimPeretokin\Desktop\fhir-publisher\org.hl7.fhir.igpublisher.jar" -ig "C:\Users\VadimPeretokin\Desktop\fhir-git\tests\ig\test-ig.json" -watch | ||
+ | |||
+ | Linux: | ||
+ | Open the terminal (usually Ctrl+Alt+T), then paste the following, with the paths adjusted for your computer: | ||
+ | java -jar '/home/vadi/Programs/fhir-publisher/org.hl7.fhir.igpublisher.jar' -ig '/home/vadi/Programs/fhir-git/tests/ig/test-ig.json' -watch | ||
+ | |||
+ | === Validating without publishing === | ||
There is an alternative mode, where you run the IG publisher against a collection of conformance resources (profiles, logical models, value sets etc) without defining an implementation guide. This allows you to validate a set of profiles, and see what they look like. To run the IG publisher in this mode: | There is an alternative mode, where you run the IG publisher against a collection of conformance resources (profiles, logical models, value sets etc) without defining an implementation guide. This allows you to validate a set of profiles, and see what they look like. To run the IG publisher in this mode: | ||
Line 120: | Line 75: | ||
java -jar org.hl7.fhir.igpublisher.jar -source [source] -destination [dest] (-tx [url]) | java -jar org.hl7.fhir.igpublisher.jar -source [source] -destination [dest] (-tx [url]) | ||
− | Where source is a directory containing the conformance resources, destination is where to put the generated output (validation.html is the most important). In this case, the IG publisher uses | + | Where source is a directory containing the conformance resources, destination is where to put the generated output (validation.html is the most important). In this case, the IG publisher uses its own internal control file and renders a simple version of the output. |
== Operation of the IG Publisher == | == Operation of the IG Publisher == | ||
Line 130: | Line 85: | ||
* loads all the resources in the IG | * loads all the resources in the IG | ||
* processes code systems, value sets, structure definitions, structure maps | * processes code systems, value sets, structure definitions, structure maps | ||
− | * validates the all resources in the IG and produces an HTML file with any errors encountered | + | * validates the all resources in the IG and produces an HTML QA file with any errors encountered |
− | * for each resource in the IG, | + | * for each resource in the IG, generates a set of files - renderings of the artifact for possible inclusion in the published IG, plus the outputs defined above |
* generates summary output | * generates summary output | ||
− | * gets the tool (Jekyll) to generate the final output. The Jekyll source is in /pages | + | * gets the tool (Jekyll) to generate the final output. The Jekyll source is in /pages by default |
+ | |||
+ | If you'd like to use another website generation tool, discuss your tool of choice with Grahame Grieve. | ||
= Control file = | = Control file = | ||
Line 141: | Line 98: | ||
{ | { | ||
− | " | + | "source": "[ig]", // the name of the ImplementationGuide resource file to load |
− | "version" : "[optional - see below]", | + | "version" : "[optional - [[#Version|see below]]]", |
− | "paths" : { // see paths below | + | "paths" : { // [[#Paths|see paths]] below |
"resources" : "[resources]", | "resources" : "[resources]", | ||
"pages" : "[pages]", | "pages" : "[pages]", | ||
Line 157: | Line 114: | ||
"transform" : "[xslt file]" | "transform" : "[xslt file]" | ||
}, | }, | ||
− | "sct-edition" : "[uri - see below]", | + | "sct-edition" : "[uri - [[#Terminology_Options|see below]]]", |
"no-inactive-codes" : "true | false", | "no-inactive-codes" : "true | false", | ||
− | "gen-examples" : "true", // optional, see below ( | + | "gen-examples" : "true", // optional, see below ([[#Processing_Options|processing options]]) |
− | "do-transforms" : "true", // optional, see below ( | + | "do-transforms" : "true", // optional, see below ([[#Processing_Options|processing options]]) |
− | "canonicalBase": "[where this will be published - see above]", | + | "canonicalBase": "[where this will be published - [[#Canonical_URL|see above]]]", |
"dependencyList": [ | "dependencyList": [ | ||
// a list of other implementation guides that this guide depends on | // a list of other implementation guides that this guide depends on | ||
Line 167: | Line 124: | ||
// zero or more of this object: | // zero or more of this object: | ||
{ | { | ||
− | "name" : "[name of the IG, for logging, and | + | "name" : "[name of the IG, for logging, and Jekyll variable name for location]", |
"location" : "[http address where the IG lives]", | "location" : "[http address where the IG lives]", | ||
"source" : "[folder to get the definitions from if running ahead of publication at location (relative)]" | "source" : "[folder to get the definitions from if running ahead of publication at location (relative)]" | ||
Line 179: | Line 136: | ||
// Anything not mentioned defaults to true | // Anything not mentioned defaults to true | ||
"Any": { | "Any": { | ||
− | // fragment and template options - see below. example: | + | // fragment and template options - [[#Fragment_.26_Template_Options|see below]]. example: |
"xml" : false // don't produce xml example | "xml" : false // don't produce xml example | ||
− | "template-base" : "sometemplatefile.html" // | + | "template-base" : "sometemplatefile.html" // use this as the default template for all base pages if not overridden |
}, | }, | ||
"[Type]": { | "[Type]": { | ||
− | // fragment and template options - see below | + | // fragment and template options - [[#Fragment_.26_Template_Options|see below]] |
} | } | ||
}, | }, | ||
− | |||
"spreadsheets" : [ | "spreadsheets" : [ | ||
− | "[filename]" // see using spreadsheets | + | "[filename]" // see [[#Using_Spreadsheets|using spreadsheets]] |
], | ], | ||
"bundles" : [ | "bundles" : [ | ||
− | "[id]" // see using bundles below | + | "[id]" // see [[#Using_Bundles|using bundles below]] |
], | ], | ||
"resources": { | "resources": { | ||
Line 198: | Line 154: | ||
"source" : "[optional source file]", | "source" : "[optional source file]", | ||
"version" : "[optional version]", | "version" : "[optional version]", | ||
− | // template and fragment options - see below. E.g. | + | // template and fragment options - [[#Fragment_.26_Template_Options|see below]]. E.g. |
"base": "[overridden name for destination page for things referring to this resource]", | "base": "[overridden name for destination page for things referring to this resource]", | ||
"template-defns": "[template to use for resource definitions]", | "template-defns": "[template to use for resource definitions]", | ||
} | } | ||
− | } | + | }, |
+ | "tool" : "jekyll" // the tool used for the 3rd step of the build. See tooling below | ||
} | } | ||
Line 209: | Line 166: | ||
== Version == | == Version == | ||
− | The IG publisher knows how to publish | + | The IG publisher generally only knows how to publish for the FHIR version it's made, e.g. if the IG you want to publish is based on the FHIR version at http://hl7.org/fhir/20XXyyy, then you would download the publisher from http://hl7.org/fhir/20XXyyy/downloads.html, and use that. |
However there are a few special circumstances where you need to use one IG publisher to build files for a different version of the specification. If you need to do this - and you know that you meet one of these cases - then you can specify an alternative version using the "version" property in the json file. | However there are a few special circumstances where you need to use one IG publisher to build files for a different version of the specification. If you need to do this - and you know that you meet one of these cases - then you can specify an alternative version using the "version" property in the json file. | ||
Line 234: | Line 191: | ||
This is an HTTP page (http:// or file:// that points to the version of the specification on which this IG is based (use a version specific reference, not http://hl7.org/fhir itself, unless the IG is synced to the current build). It should also be the version on which the IG itself is based. | This is an HTTP page (http:// or file:// that points to the version of the specification on which this IG is based (use a version specific reference, not http://hl7.org/fhir itself, unless the IG is synced to the current build). It should also be the version on which the IG itself is based. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
=== Terminology Service Cache === | === Terminology Service Cache === | ||
Line 259: | Line 200: | ||
Choice 1 is not to specify this; the cache will be automatically created and maintained in the user's local directory. The problem with this is that all users have to delete and rebuild the cache manually (e.g. have to do it, and wait for the slow build). | Choice 1 is not to specify this; the cache will be automatically created and maintained in the user's local directory. The problem with this is that all users have to delete and rebuild the cache manually (e.g. have to do it, and wait for the slow build). | ||
− | Choice 2 is to put it in a subdirectory, and version control the content. This can be tiresome because everyone has to commit the files | + | Choice 2 is to put it in a subdirectory, and version control the content. This can be tiresome because everyone has to commit the files,but only one person needs to maintain the content. This is better for CI builds as well. |
=== Terminology Options === | === Terminology Options === | ||
Line 317: | Line 258: | ||
=== Fragment Codes === | === Fragment Codes === | ||
+ | There will be one each of these fragments for each resource type that is found: | ||
* xml: XML version of the resource (all resource types) | * xml: XML version of the resource (all resource types) | ||
* json: JSON version of the resource (all resource types) | * json: JSON version of the resource (all resource types) | ||
Line 335: | Line 277: | ||
* diff: Logical Table of the diff (Structure Definition) | * diff: Logical Table of the diff (Structure Definition) | ||
* snapshot: Logical Table of the snapshot (Structure Definition) | * snapshot: Logical Table of the snapshot (Structure Definition) | ||
− | * pseudo-xml: XML template for the snapshot (Structure Definition) | + | * pseudo-xml: XML template for the snapshot (Structure Definition); |
* pseudo-json: JSON template for the snapshot (Structure Definition) | * pseudo-json: JSON template for the snapshot (Structure Definition) | ||
* pseudo-ttl: Turtle template for the snapshot (Structure Definition) | * pseudo-ttl: Turtle template for the snapshot (Structure Definition) | ||
Line 352: | Line 294: | ||
* table-[type].xhtml | * table-[type].xhtml | ||
− | + | If there are any structure definitions of the right type, the publisher will also produce the following: | |
* table-profiles.xhtml & list-profiles.xhtml | * table-profiles.xhtml & list-profiles.xhtml | ||
* table-extensions.xhtml & list-extensions.xhtml | * table-extensions.xhtml & list-extensions.xhtml | ||
Line 374: | Line 316: | ||
These file names can be overridden on a per-resource instance basis by declaring an alternate name in the resource declaration. For example, | These file names can be overridden on a per-resource instance basis by declaring an alternate name in the resource declaration. For example, | ||
− | "StructureDefinition/123": { | + | |
− | + | "StructureDefinition/123": { | |
− | + | "base": "my123.html", | |
− | } | + | "defns": "my123-defs.html" |
+ | } | ||
When the template files are used, they are pre-processed and then copied to the correct place for the xml/json/ttl wrapper | When the template files are used, they are pre-processed and then copied to the correct place for the xml/json/ttl wrapper | ||
Line 426: | Line 369: | ||
] | ] | ||
− | The bundles property is an array of | + | The bundles property is an array of strings, where each entry is the id of a bundle. The bundle will be located using the standard resource location process, but once loaded, the bundle itself will be ignored, and the individual resources processed directly. Each resource in the bundle must have an entry in the resources section, and should be entered in the implementation guide. |
== Using Spreadsheets == | == Using Spreadsheets == | ||
Line 436: | Line 379: | ||
] | ] | ||
− | This is an array of | + | This is an array of strings, which each entry is the filename of the spreadsheet, relative to the control file. Each resource represented in the spreadsheet (profiles, value sets, search parameters) must have an entry in the resources section, and should be entered in the implementation guide. Note that the loading is order dependent - the author must ensure dependent profiles are listed and loaded after the ones they depend on. |
There's some differences between the spreadsheets used in the build directly, and the spreadsheets used by the IG Publisher, and these are changes that must be made manually: | There's some differences between the spreadsheets used in the build directly, and the spreadsheets used by the IG Publisher, and these are changes that must be made manually: | ||
Line 462: | Line 405: | ||
== Jekyll == | == Jekyll == | ||
− | Installation: | + | Installation: (see [http://jekyll-windows.juthilo.com/2-jekyll-gem/ Jekyll on Windows] for windows users) |
in config file: | in config file: | ||
Line 485: | Line 428: | ||
* genDate : date of generation (so date stamps in the pages can match those in the conformance resources) | * genDate : date of generation (so date stamps in the pages can match those in the conformance resources) | ||
− | + | Also, a file generated for the structure definitions. Each structure definition is listed by it's id, along with the following data for each id: | |
− | Also, a file generated for the structure definitions. Each structure definition is listed by it's id, along with the following data for each id | ||
− | |||
− | |||
* url : full canonical url for the structure | * url : full canonical url for the structure | ||
Line 505: | Line 445: | ||
* contextType : the type of context associated with an extension structure definition | * contextType : the type of context associated with an extension structure definition | ||
* contexts : an array of paths for each allowed context path for an extension | * contexts : an array of paths for each allowed context path for an extension | ||
+ | |||
+ | = Rules for Implementation Guides = | ||
+ | |||
+ | == Format Support == | ||
+ | |||
+ | The Implementation Guide supports 3 formats, as defined in the FHIR specification: | ||
+ | * XML | ||
+ | * JSON | ||
+ | * Turtle (RDF) | ||
+ | |||
+ | Note: in this documentation, [fmt] is one of 'xml', 'json', and 'ttl'. | ||
+ | |||
+ | By default, the IG publisher will produce all 3 of these formats. It is recommended to produce all 3, though specific formats can be turned off - but you must produce at least one. | ||
+ | |||
+ | == Layout == | ||
+ | |||
+ | The Implementation Guide author is free to lay out the content in what form they choose. However there are some rules about the arrangement of the implementation guide that must be followed: | ||
+ | |||
+ | * the home page should be 'index.html' (this is not a technical requirement, but is a human convenience) | ||
+ | * for each resource in the implementation guide, whether a conformance resource or an example, the IG Publisher will produce | ||
+ | ** [Type]-[id].html - the home page for the resource (note: you can rename this page using the [[#Control_file|control file]]) | ||
+ | ** [Type]-[id].[fmt] - the resource for the specified format (pretty printed) | ||
+ | ** !! [Type]-[id].canonical.[fmt] - the resource for the specified format in canonical format (not produced for ttl) (not currently produced) | ||
+ | ** redirects from /[Type]/[id] to one of the pages above (depending on request format) | ||
+ | ** [Type]-[id].[fmt].html - An HTML wrapper around the specified format, with a link to the native form | ||
+ | * the IG publisher will produce the files definitions.[fmt].zip. The community will expect that these are published along with the guide as these enable the conformance tooling to work with the guide. These should be referenced somewhere from the guide, but the tooling will just expect that they exist at [canonical]/definitions.[fmt].zip, irrespective of whether they are linked from the narrative | ||
+ | |||
+ | == URLs == | ||
+ | |||
+ | === Canonical URL === | ||
+ | |||
+ | The Implementation Guide must nominate a canonical URL, which we'll refer to as '''[canonical]'''. This canonical URL is used throughout all the resources (this is enforced by the publisher). The canonical URL should point to the current version of the IG that you're publishing, so if someone enters the canonical URL into their browser, they will get the IG home page (for example, http://example.com/fhir/mypatientprofile). | ||
+ | |||
+ | If possible, this should also be a FHIR server hosting resources - so a GET of [canonical]/[Type]/[id] should return a FHIR resource. For example, http://example.com/fhir/Patient/mysamplepatient would give you a sample Patient resource used throughout the specification. | ||
+ | |||
+ | === ImplementationGuide.url === | ||
+ | |||
+ | The [https://hl7-fhir.github.io/implementationguide-definitions.html#ImplementationGuide.url ImplementationGuide.url] element in your ImplementationGuide resource should be set to [canonical]/ImplementationGuide/[id], and that should redirect you to the base URL when entered into the browser - for example, entering ImplementationGuide.url of http://example.com/fhir/mypatientprofile/ImplementationGuide/mypatientprofile in the browser should take you to http://example.com/fhir/mypatientprofile. | ||
+ | |||
+ | == History == | ||
+ | |||
+ | Each Implementation Guide is also responsible for maintaining it's own published history. The standard way that this works for FHIR should be followed by the implementation guides: | ||
+ | * The current copy of the specification lives at [canonical] | ||
+ | * the published version history lives at [canonical]/directory.html (or similar name) and is manually maintained. It lists the current version, maybe the dev version location, and a history of past milestones | ||
+ | * the past milestones live at [canonical]/[id] where id is either a milestone name like "stu1" or a date (recommended format = YYYY) | ||
+ | * at least the home page of all the versions (current or historical) references the published version history in a prominent location | ||
+ | |||
+ | The IG publisher is only able to produce a single snapshot of the IG at a time - so in order to create your history, you'll need to manually move old versions to [canonical]/[id] and update the [canonical]/directory.html with a link to it. | ||
+ | |||
+ | == Styles == | ||
+ | |||
+ | All the generated fragments are generated assuming that the standard FHIR styles in fhir.css apply to the specified classes in the generated content. To keep the content valid, the simplest way is to include fhir.css in all your html pages as a style reference. But you don't have to do this; if you have some other styling system, you can make arrangements for the correct css definitions - which are deliberately very static - to be made available in some other form. You can even replace the styles completely and use your own. | ||
+ | |||
+ | Note, however this warning: The FHIR team does not provide support for replacing any CSS styles. In order to assist with this, for every generated fragment, there is a matching .html file created in the qa directory. The FHIR team will respond to any issue relating to incorrect display of the content of the qa html files. If the content does not appear correctly in the IG, but does appear correctly in the qa files, then this is assumed to be a problem with the IG styling, and not the problem of the IG Publisher authors. | ||
+ | |||
+ | == Implementation Guide Layouts == | ||
+ | |||
+ | Generally, there are 3 different approaches to organizing an implementation guide | ||
+ | * let the IG build generate an html file for each conformance resource (don't need to fill the instances out in the [[#Control_file|json control file]], just use the templates to make them look like you want). Write some introduction pages stringing them altogether | ||
+ | * hand write a page for each conformance resource, bringing in pieces of html into the pages, and choosing the page names for the resources (in the control file). And writing narrative to string all the pages together | ||
+ | * write a set of pages, and include the bits of html into the page where appropriate. Each conformance resource has a notional home somewhere in one of the pages (again, in the control file, using [page]#[fragment] | ||
+ | |||
+ | All 3 approaches are valid, with different advantages and disadvantages. You can mix'n'match all 3 approaches - it's driven by how you create the pages, and configure the IG output. The key thing is to have a very clear idea how the pages are strung together, and how the resource identification / page naming strategy works for your implementation guide. | ||
= Troubleshooting = | = Troubleshooting = |
Revision as of 03:55, 6 December 2016
Contents
Summary
The FHIR team provides an IG Publishing tool that takes the implementation guide resources and converts them to a set of 3 different types of files:
- generated resources ready for inclusion into the published guide (xml, json, ttl formats)
- a set of fragments ready to include in generated html files
- 6 standard zip files: definitions.[fmt].zip and examples.[fmt].zip - these are used by implementers for various purposes, so should be included in the final published version
Building an IG is a 4 part process:
- Installing the publisher
- Defining the resources that underpin the Implementation Guide resources (Implementation Guide, Conformance Resources, Knowledge statements, examples) - using either bundles or spreadsheets
- Developing the structure and the narrative content that turns the resources into a useful implementation guide
- Running the publishing process that will publish it
Alternatively, you may use the IG publisher to validate and render a set of Profiles, value sets etc without building a formal IG (see command line mode)
Examples
If you want an example of IG source, you can look in one of the following places:
- FHIR SVN repository, in \build\guides\* - any directory ending in 2 - a variety of styles of implementation guide.
- Also, there's \build\tests\ig which is used for testing the tooling
Using FHIR IG Publisher
Installing
- Get the publisher itself: this is a java jar called
org.hl7.fhir.igpublisher.jar
. You can get it from the downloads (e.g. http://build.fhir.org/downloads.html) for the version of FHIR you are using (or, if you build locally, from your own publish directory). The jar includes everything from the spec that is required to generate the implementation guide. - Get the publishers helper: you need to install Jekyll in order to publish the said implementation guide. See Windows and Linux instructions.
Make sure you use the correct version of the IG publisher for your guide (check the versions in the log), since the IG publisher only supports the version of FHIR it's been made for.
The publisher can be run as a GUI application, or run from the command line. It can also can be hosted in a server - if you want to host it, talk to Grahame Grieve.
Running in GUI mode
Windows: double-click on org.hl7.fhir.igpublisher.jar or right-click and select 'Open'.
Linux: double-click on org.hl7.fhir.igpublisher.jar or right-click and select 'Open With Oracle Java 8 Runtime'.
You can also run it the command line:
java -jar org.hl7.fhir.igpublisher.jar
Note that this doesn't work in OpenJDK - if you are using openJDK, your only option is to run it from the command prompt, as described below.
This is the IG builder:
To use it, 'Choose' an implementation guide control JSON file, and click 'Execute'. The implementation guide will be built, and then the IG publisher will watch for changes until and do incremental rebuilds until you click 'Stop'.
Ruinning in command line mode
To run in command line mode, run the IG Publisher like this:
java -jar org.hl7.fhir.igpublisher.jar -ig [source] (-tx [url]) (-watch)
parameters:
- -ig: a path or a url where the implementation guide JSON control file is found (see control file format documentation)
- -tx: (optional) address to use for terminology server (default is http://fhir3.healthintersections.com.au - which is currently the only supported option)
- -watch (optional): if this is present, the publisher will not terminate; instead, it will stay running, and watch for changes to the IG or its contents and re-run when it sees changes. Note that changes the spec or to dependent implementation guides (see below) are not picked up during watch mode
Windows example:
Open the command prompt, then paste the following, with the paths adjusted for your computer:
java -jar "C:\Users\VadimPeretokin\Desktop\fhir-publisher\org.hl7.fhir.igpublisher.jar" -ig "C:\Users\VadimPeretokin\Desktop\fhir-git\tests\ig\test-ig.json" -watch
Linux: Open the terminal (usually Ctrl+Alt+T), then paste the following, with the paths adjusted for your computer:
java -jar '/home/vadi/Programs/fhir-publisher/org.hl7.fhir.igpublisher.jar' -ig '/home/vadi/Programs/fhir-git/tests/ig/test-ig.json' -watch
Validating without publishing
There is an alternative mode, where you run the IG publisher against a collection of conformance resources (profiles, logical models, value sets etc) without defining an implementation guide. This allows you to validate a set of profiles, and see what they look like. To run the IG publisher in this mode:
java -jar org.hl7.fhir.igpublisher.jar -source [source] -destination [dest] (-tx [url])
Where source is a directory containing the conformance resources, destination is where to put the generated output (validation.html is the most important). In this case, the IG publisher uses its own internal control file and renders a simple version of the output.
Operation of the IG Publisher
once running, it:
- reads the control file
- reads the IG
- processes any spreadsheets, bundles, and logical models
- loads all the resources in the IG
- processes code systems, value sets, structure definitions, structure maps
- validates the all resources in the IG and produces an HTML QA file with any errors encountered
- for each resource in the IG, generates a set of files - renderings of the artifact for possible inclusion in the published IG, plus the outputs defined above
- generates summary output
- gets the tool (Jekyll) to generate the final output. The Jekyll source is in /pages by default
If you'd like to use another website generation tool, discuss your tool of choice with Grahame Grieve.
Control file
When the IG publisher is executed, it is pointed at a control file. This is a json file that contains all the information that the publisher needs to publish the implementation guide. It has this structure:
{ "source": "[ig]", // the name of the ImplementationGuide resource file to load "version" : "[optional - see below]", "paths" : { // see paths below "resources" : "[resources]", "pages" : "[pages]", "temp" : "[temp]", "output" : "[output]", "txCache" : "[txCache]", "qa" : "[qa]", "history" : "[history page]", "specification" : "[specification]" }, "pre-process" : { // optional section "folder" : "[folder]", "transform" : "[xslt file]" }, "sct-edition" : "[uri - see below]", "no-inactive-codes" : "true | false", "gen-examples" : "true", // optional, see below (processing options) "do-transforms" : "true", // optional, see below (processing options) "canonicalBase": "[where this will be published - see above]", "dependencyList": [ // a list of other implementation guides that this guide depends on // e.g. uses profiles, value sets, code systems etc // zero or more of this object: { "name" : "[name of the IG, for logging, and Jekyll variable name for location]", "location" : "[http address where the IG lives]", "source" : "[folder to get the definitions from if running ahead of publication at location (relative)]" } ] // Templates lists any additional templates beyond "base" and "format" that can be generated for one or more artifact types // The list of template names below are examples "extraTemplates": ["mapping", "foo", "bar"], "defaults": { // this object contains the default publishing policy for different types. // Anything not mentioned defaults to true "Any": { // fragment and template options - see below. example: "xml" : false // don't produce xml example "template-base" : "sometemplatefile.html" // use this as the default template for all base pages if not overridden }, "[Type]": { // fragment and template options - see below } }, "spreadsheets" : [ "[filename]" // see using spreadsheets ], "bundles" : [ "[id]" // see using bundles below ], "resources": { "[Type]/[id]": { "source" : "[optional source file]", "version" : "[optional version]", // template and fragment options - see below. E.g. "base": "[overridden name for destination page for things referring to this resource]", "template-defns": "[template to use for resource definitions]", } }, "tool" : "jekyll" // the tool used for the 3rd step of the build. See tooling below }
The control file must be maintained by the editor of the implementation guide.
Version
The IG publisher generally only knows how to publish for the FHIR version it's made, e.g. if the IG you want to publish is based on the FHIR version at http://hl7.org/fhir/20XXyyy, then you would download the publisher from http://hl7.org/fhir/20XXyyy/downloads.html, and use that.
However there are a few special circumstances where you need to use one IG publisher to build files for a different version of the specification. If you need to do this - and you know that you meet one of these cases - then you can specify an alternative version using the "version" property in the json file.
Valid Circumstances:
- the publisher for 1.6.0 (http://hl7.org/fhir/2016Sep) knows how to publish IGs for version 1.4.0 (http://hl7.org/fhir/2016May)
Paths
The IG publisher defines the following paths that can be configured in the control file:
- [resources]: the directory where all the input FHIR resources (usually conformance resources and examples)
- [pages]: the directory that contains all the jekyll source (not process, just passed to Jekyll for processing)
- [page-src]:
- [temp]: a scratch directory that is used for the temporary source for jekyll processing (do not use this directory for anything else)
- [output]: where the final output from the tool (the complete IG) will be placed
- [qa]: a folder where the validation output (validation.html) will be produced, along with a page for each fragment (for css style checking)
- [txCache]: where the terminology service cache goes. see below.
- [history page]: the page that lists the history of the implementation guide. This page is manually managed when the IG is published formally, so it is not produced (and cannot be produced) but is not listed as a broken link
All these folders are file paths that are relative to the control file. They are usually sub-folders, for version control/build convenience, but do not need to be. There is one more path:
- [specification]
This is an HTTP page (http:// or file:// that points to the version of the specification on which this IG is based (use a version specific reference, not http://hl7.org/fhir itself, unless the IG is synced to the current build). It should also be the version on which the IG itself is based.
Terminology Service Cache
There are 2 workable choices for this value : present, or in version control with the IG (e.g. a subdirectory, and store in version control)
Note that using the terminology server - unless you run a local copy - is slow. The build tool keeps a local terminology cache that speeds up the build process (e.g. from hours to seconds). But the cache is aggressive, and must be managed, since there's no arrangement to flush the cache when the terminology service updates its content.
Choice 1 is not to specify this; the cache will be automatically created and maintained in the user's local directory. The problem with this is that all users have to delete and rebuild the cache manually (e.g. have to do it, and wait for the slow build).
Choice 2 is to put it in a subdirectory, and version control the content. This can be tiresome because everyone has to commit the files,but only one person needs to maintain the content. This is better for CI builds as well.
Terminology Options
If you use SNOMED CT, you must specify a SNOMED CT Edition to use:
"sct-edition" : "http://snomed.info/sct/[module]",
where [module] comes from this list:
- International: 900000000000207008
- us: 731000124108
- AU: 32506021000036107
- Spanish: 449081005
- Danish: 554471000005108
- Dutch: 11000146104
- Swedish: 45991000052106
- UK: 999000041000000102
Note that you can only specify a version supported by the infrastructure (currently: International, US, AU). You can specify a version if you want (but it will fail if this is a different version to the infrastructure). You will have to delete the terminology cache if you change this value.
In addition to this, you can specify whether to include inactive codes or not:
"activeOnly" : "true",
By default, inactive codes are included
Pre-processing Pages
The IG publisher can pre-process pages. If you specify a pre-process option, then the IG publisher will copy the content from the pre-process directory, executing the specified transform on it as it copies the content. Directory structure will be preserved. Note: changes to the transform are not picked up when running in -watch mode.
The transform engine uses XSLT1 not XSLT2 (e.g. the standard java transform engine).
Processing Options
These are global flags that control FHIR specific pre-processing associated of profiles. All the flags default to false.
- gen-examples: whether to look for example data in the structure definitions (using the tool extension http://hl7.org/fhir/StructureDefinition/structuredefinition-example) and automatically generate additional resources containing the data provided
- do-transforms: for any structure maps, use them to transform the source content (StructureDefinitions and examples - usually logical models, see FHIR Logical Models and Mappings) to output Profiles and examples, and render these in the output
Fragment & Template Options
When deciding whether to produce a particular kind of fragment, the IG Publisher will look for a property of type boolean with the name given below. Similarly, when deciding to produce a particular type of web page, it will look for a template file (also described below).
In either case, it will look in the following places, in order:
- on the resource entry for the resource in question
- on the defaults entry for the resource type in question
- on the defaults entry for "ANY"
For fragment codes, if the IG tool doesn't find anything, it will produce the fragment. For templates, if no template is found, it will NOT produce an output page.
Fragment Codes
There will be one each of these fragments for each resource type that is found:
- xml: XML version of the resource (all resource types)
- json: JSON version of the resource (all resource types)
- ttl: Turtle version of the resource (all resource types)
- xml-html: html representation of XML version of the resource (all resource types)
- json-html: html representation of JSON version of the resource (all resource types)
- ttl-html: html representation of Turtle version of the resource (all resource types)
- html: narrative of resource as html
- summary: An html summary for the resource (all conformance resources)
- content: An HTML representation of the content in resource (code system, concept map, structure map)
- xref: A list of all the places where the resource is used (all conformance resources)
- cld: An HTML representation of the content in resource (value set)
- expansion: The expansion of the value set (Value set)
- shex: ShEx statement for the structure (Structure Definition)
- sch: schematron statement for the structure (Structure Definition)
- json-schema: JSON Schema statement for the structure (Structure Definition)
- header: Description of the identification of the structure (Structure Definition)
- diff: Logical Table of the diff (Structure Definition)
- snapshot: Logical Table of the snapshot (Structure Definition)
- pseudo-xml: XML template for the snapshot (Structure Definition);
- pseudo-json: JSON template for the snapshot (Structure Definition)
- pseudo-ttl: Turtle template for the snapshot (Structure Definition)
- uml: UML diagram for the structure (Structure Definition)
- tx: Terminology Notes for the structure (Structure Definition)
- inv: invariant summary for the structure (Structure Definition)
- dict: Detailed Element Definitions (Structure Definition)
- maps: Presentation of the mappings (Structure Definition)
- span: Presentation of all profiles a profile refers to (StructureDefinition where derivation = constraint)
- spanall: Presentation of all profiles & base resources a profile refers to (StructureDefinition where derivation = constraint)
- script: Script language rendition of a StructureMap (StructureMap)
- profiles: List of Profiles generated from a StructureMap (StructureMap)
In addition, the publisher produces the following set of fragments for listing all the content:
- list-[type].xhtml
- table-[type].xhtml
If there are any structure definitions of the right type, the publisher will also produce the following:
- table-profiles.xhtml & list-profiles.xhtml
- table-extensions.xhtml & list-extensions.xhtml
- table-logicals.xhtml & list-logicals.xhtml
Page templates
The IG tooling can automatically generate 0 or more HTML pages for each type of resource included in the IG. To generate files for resources, a template file must be declared that provides the base structure for what the resource file should look like. The template file will be a jekyll source file (e.g. html or markdown etc.) containing imports, variable references and other embedded control tags used by the static generation tool to produce the fully populated resource-specific pages.
The template can be declared in the default section for ANY or a specific type or for a specific artifact id. There are three standard templates available:
- template-base defines the base page that acts as the home page when references are encountered to that resource. Each resource should have one of these
- template-defns defines the base that provides the data dictionary with anchors for each data element in a structure definition. (In the future, this may be applicable to other resources too - let us know)
- template-fmt defines the page format for pretty-printed views of the JSON, XML and TTL representations of the resource.
The file names of these generated pages will default to the following:
- base: [ResourceType]-[id].html
- defns: [ResourceType]-[id]-definitions.html
- fmt: [ResourceType]-[id].[fmt].html where [fmt] is xml, json and ttl
In addition to these, additional template types can be declared (e.g. for mappings, lists of referenced elements, etc.) To provide support for additional template types, the name of each template type must be included in the extraTemplates list. This name is appended to "template-" to create the name of the template tag. (For example, "template-mapping", "template-foo" and "template-bar" in the example above.) The default file name is [ResourceType]-[id]-[templateName].html, for example [ResourceType]-[id]-mapping.html.
These file names can be overridden on a per-resource instance basis by declaring an alternate name in the resource declaration. For example,
"StructureDefinition/123": { "base": "my123.html", "defns": "my123-defs.html" }
When the template files are used, they are pre-processed and then copied to the correct place for the xml/json/ttl wrapper for each resource. When copied, the following strings will be replaced:
- {{[title]}} - a description of the content of the resource (typical use: <h2>{{[title]}}</h2>)
- {{[name]}} - the path for the source fragment to include (proper use: {% include {{[name]}}.xhtml %})
- {{[id]}} - the id of the resource
- [[[type]}} - the type of the resource
- [[[uid]}} - type-id (combination)
Loading Resources
Resources are loaded as follows:
- The IG resource is loaded (by literal filename)
- any spreadsheets are loaded (by literal filename) and converted to resources (for editor support, all the identities of the generated resources are noted in the validation output)
- any bundles are loaded (by Type/id)
- any resources referenced in the IG resource are loaded (by Type/Id)
Note: The IG resource must use sourceReference references by id. e.g.
<sourceReference> <reference value="ValueSet/my-value-set"/> </sourceReference>
A Type/Id reference is resolved to a to a local file by the control file, using the object /resources/"[Type]/[id]". If this object does not exist, the IG publication will fail. If this object exists, and has no "source" property, then the source property specifies the location of the file source relative to the IG file. If there is no "source" property, the IG publisher will look for [resources]/[Type]-[id].xml/json or [Type]-[id].xml/json (it's at editor discretion whether to store files using the simpler form, since this can cause conflicts between different resources with the same id (e.g. both Patient and Practitioner with the id of 'example')
By default, the version of the input resource is assumed to be the same version is the IG Publisher itself. However the IG publisher can also load resources from Forge. in order to load resources from forge, specify the version "1.0.1" for each forge resource. Note: this is only known to work reliably for StructureDefinition resources
Using Bundles
There's 2 different ways to use Bundles. The first way is examples of type Bundle. These are treated like any other resource. The second is where the bundle is a collection that contains a set of resources that need to be processed individually by the IG Publisher. To specify one of these bundles, use the "bundles" property:
"bundles" : [ "[id]" ]
The bundles property is an array of strings, where each entry is the id of a bundle. The bundle will be located using the standard resource location process, but once loaded, the bundle itself will be ignored, and the individual resources processed directly. Each resource in the bundle must have an entry in the resources section, and should be entered in the implementation guide.
Using Spreadsheets
For legacy reasons, it's possible to author profiles using spreadsheets. This approach is deprecated. To get the IG publisher to process a spreadsheet:
"spreadsheets" : [ "[filename]" ]
This is an array of strings, which each entry is the filename of the spreadsheet, relative to the control file. Each resource represented in the spreadsheet (profiles, value sets, search parameters) must have an entry in the resources section, and should be entered in the implementation guide. Note that the loading is order dependent - the author must ensure dependent profiles are listed and loaded after the ones they depend on.
There's some differences between the spreadsheets used in the build directly, and the spreadsheets used by the IG Publisher, and these are changes that must be made manually:
- Value Set references - use either
- ValueSet/xxx a reference to a value set defined in the IG, and registered directly in the implemnentation guide resource
- http(s)://... a reference to a value set from outside the IG, or in the IG
- valueset-xxx where:
- valueset-xxx is the name of a file found in the same directory as the spreadsheet
- The filename must not have .xml or .json on it, but a file with either .xml or .json appended to it must exist
- The file must be a ValueSet resource, with an id of xxx and the appropriate canonical URL
- Search Parameters
- You have to provide a fluent path expression directly ("Expression")
- you have to provide a description directly
- you have to specify the target types directly
- Types
- the build tool allows for the use of "SimpleQuantity" and other data type profiles (not that the build tool uses any other) as types, but they have to be invoked as profiles in the IG spreadsheets
- Note that IG publisher enforces the use of correct ids and canonical URLs against the base stated in the control file
Build Tools
Jekyll
Installation: (see Jekyll on Windows for windows users)
in config file:
"tool":"jekyll"
For Jekyll, some data files are also generated. The data from these is available when generating pages. e.g.
{ { site.data.fhir.version } }
inserts the version of the FHIR specification used by the build (without spaces between the {, which can't be done properly on this wiki). The following data is available:
- path : path to the main FHIR specification
- canonical : canonical path to this specification
- errorCount : number of errors in the build file (not including HTML validation errors)
- version : version of FHIR
- revision : revision of FHIR
- versionFull : version-revision
- totalFiles : total number of files found by the build
- processedFiles : number of files genrated by the build
- genDate : date of generation (so date stamps in the pages can match those in the conformance resources)
Also, a file generated for the structure definitions. Each structure definition is listed by it's id, along with the following data for each id:
- url : full canonical url for the structure
- name : the name given for it
- path : the path to it in the built html
- kind : the kind (complex data type, resource, logical model)
- type : the base type
- base : the url for structure definition from which it derives
- basename : the name of the structure definition from which it derives
- basepath : the url to the structure definition from which it derives
- status : the status (draft, active, retired)
- date : the date in the resource
- publisher : the stated publisher
- copyright : the stated copyright for the resource
- description : the description for the resource
- contextType : the type of context associated with an extension structure definition
- contexts : an array of paths for each allowed context path for an extension
Rules for Implementation Guides
Format Support
The Implementation Guide supports 3 formats, as defined in the FHIR specification:
- XML
- JSON
- Turtle (RDF)
Note: in this documentation, [fmt] is one of 'xml', 'json', and 'ttl'.
By default, the IG publisher will produce all 3 of these formats. It is recommended to produce all 3, though specific formats can be turned off - but you must produce at least one.
Layout
The Implementation Guide author is free to lay out the content in what form they choose. However there are some rules about the arrangement of the implementation guide that must be followed:
- the home page should be 'index.html' (this is not a technical requirement, but is a human convenience)
- for each resource in the implementation guide, whether a conformance resource or an example, the IG Publisher will produce
- [Type]-[id].html - the home page for the resource (note: you can rename this page using the control file)
- [Type]-[id].[fmt] - the resource for the specified format (pretty printed)
- !! [Type]-[id].canonical.[fmt] - the resource for the specified format in canonical format (not produced for ttl) (not currently produced)
- redirects from /[Type]/[id] to one of the pages above (depending on request format)
- [Type]-[id].[fmt].html - An HTML wrapper around the specified format, with a link to the native form
- the IG publisher will produce the files definitions.[fmt].zip. The community will expect that these are published along with the guide as these enable the conformance tooling to work with the guide. These should be referenced somewhere from the guide, but the tooling will just expect that they exist at [canonical]/definitions.[fmt].zip, irrespective of whether they are linked from the narrative
URLs
Canonical URL
The Implementation Guide must nominate a canonical URL, which we'll refer to as [canonical]. This canonical URL is used throughout all the resources (this is enforced by the publisher). The canonical URL should point to the current version of the IG that you're publishing, so if someone enters the canonical URL into their browser, they will get the IG home page (for example, http://example.com/fhir/mypatientprofile).
If possible, this should also be a FHIR server hosting resources - so a GET of [canonical]/[Type]/[id] should return a FHIR resource. For example, http://example.com/fhir/Patient/mysamplepatient would give you a sample Patient resource used throughout the specification.
ImplementationGuide.url
The ImplementationGuide.url element in your ImplementationGuide resource should be set to [canonical]/ImplementationGuide/[id], and that should redirect you to the base URL when entered into the browser - for example, entering ImplementationGuide.url of http://example.com/fhir/mypatientprofile/ImplementationGuide/mypatientprofile in the browser should take you to http://example.com/fhir/mypatientprofile.
History
Each Implementation Guide is also responsible for maintaining it's own published history. The standard way that this works for FHIR should be followed by the implementation guides:
- The current copy of the specification lives at [canonical]
- the published version history lives at [canonical]/directory.html (or similar name) and is manually maintained. It lists the current version, maybe the dev version location, and a history of past milestones
- the past milestones live at [canonical]/[id] where id is either a milestone name like "stu1" or a date (recommended format = YYYY)
- at least the home page of all the versions (current or historical) references the published version history in a prominent location
The IG publisher is only able to produce a single snapshot of the IG at a time - so in order to create your history, you'll need to manually move old versions to [canonical]/[id] and update the [canonical]/directory.html with a link to it.
Styles
All the generated fragments are generated assuming that the standard FHIR styles in fhir.css apply to the specified classes in the generated content. To keep the content valid, the simplest way is to include fhir.css in all your html pages as a style reference. But you don't have to do this; if you have some other styling system, you can make arrangements for the correct css definitions - which are deliberately very static - to be made available in some other form. You can even replace the styles completely and use your own.
Note, however this warning: The FHIR team does not provide support for replacing any CSS styles. In order to assist with this, for every generated fragment, there is a matching .html file created in the qa directory. The FHIR team will respond to any issue relating to incorrect display of the content of the qa html files. If the content does not appear correctly in the IG, but does appear correctly in the qa files, then this is assumed to be a problem with the IG styling, and not the problem of the IG Publisher authors.
Implementation Guide Layouts
Generally, there are 3 different approaches to organizing an implementation guide
- let the IG build generate an html file for each conformance resource (don't need to fill the instances out in the json control file, just use the templates to make them look like you want). Write some introduction pages stringing them altogether
- hand write a page for each conformance resource, bringing in pieces of html into the pages, and choosing the page names for the resources (in the control file). And writing narrative to string all the pages together
- write a set of pages, and include the bits of html into the page where appropriate. Each conformance resource has a notional home somewhere in one of the pages (again, in the control file, using [page]#[fragment]
All 3 approaches are valid, with different advantages and disadvantages. You can mix'n'match all 3 approaches - it's driven by how you create the pages, and configure the IG output. The key thing is to have a very clear idea how the pages are strung together, and how the resource identification / page naming strategy works for your implementation guide.
Troubleshooting
Notes about troubleshooting:
- before doing any trouble shooting, make sure you are running the latest IG publisher for the version of FHIR you are using
- if the Jekyll part of the build fails, it fails completely, and the old output is left in place
- if the build completes, and there's problems in the output, first, work through all the errors in the validation output before you ask for help
- Jekyll error "Permission denied @unlink_internal" - you have a file locked in the temp or output directory. Close any files in editors, and ensure you are only running one publisher
- If you're going to ask Grahame for help send the file fhir-ig-publishing.log in your temp directory to grahame@hl7.org along with a detailed description of what the problem is. (Alternatively, run the GUI version click, wait for the end ofthe run, and the click on the 'Debug Summary' button which puts the log on the clipboard so you can send pate it into your email)