Difference between revisions of "IG Publisher Documentation"
(Migrate Content to Confluence/Added Forward Link) |
|||
(31 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
− | = Summary = | + | Content on this page has been migrated to Confluence here: https://confluence.hl7.org/display/FHIR/IG+Publisher+Documentation |
+ | |||
+ | =Summary= | ||
The FHIR team provides an IG Publishing tool that takes the implementation guide content and converts it to a set of 3 different types of files: | The FHIR team provides an IG Publishing tool that takes the implementation guide content and converts it 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, which are then included into a published set of html files as directed by the author | + | *generated resources ready for inclusion into the published guide (xml, json, ttl formats) |
− | * Several different zip files: which are used by implementers for various purposes, so should be included in the final published version | + | *a set of fragments ready to include in generated html files, which are then included into a published set of html files as directed by the author |
+ | *Several different zip files: which are used by implementers for various purposes, so should be included in the final published version | ||
Building an IG is a 4 part process: | 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]] | + | #[[#Installing|Installing the publisher]] |
− | # Developing the structure and the narrative content that turns the resources into a useful implementation guide | + | #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]] |
− | # Running the publishing process that will publish it | + | #Developing the structure and the narrative content that turns the resources into a useful implementation guide |
+ | #Running the publishing process that will publish it | ||
The outcome of the publishing process is a set of HTML files that represent the implementation guide. These files can be posted to a web server. | The outcome of the publishing process is a set of HTML files that represent the implementation guide. These files can be posted to a web server. | ||
Line 16: | Line 20: | ||
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]]) | 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]]) | ||
− | == Publishing Implementation Guides == | + | If you wish to publish an IG through HL7 or the FHIR Foundation, you should also familiarize yourself with the [[FHIR Implementation Guide Publishing Requirements]]. |
+ | |||
+ | ==Publishing Implementation Guides== | ||
Typically, implementation guide publishing works like this: | Typically, implementation guide publishing works like this: | ||
− | * the master source for an implementation guide is in a public GitHub repository | + | |
− | * editors can run their own local build and share the set of files (full-ig.zip is automatically produced, for convenience) with anyone they want to | + | *the master source for an implementation guide is in a public GitHub repository |
− | * a CI build is published so everyone can see the output - see [[https://github.com/hl7-fhir/auto-ig-builder/blob/master/README.md Auto-IG-Publisher Documentation]] | + | *editors can run their own local build and share the set of files (full-ig.zip is automatically produced, for convenience) with anyone they want to |
− | * when formal milestones are achieved, the Implementation Guide is published to the canonical web site for the IG (typically, hl7.org, hl7.org.xx, or fhir.org, but need not be) (See [[Standard FHIR Publishing Layout Pattern]] for additional guidance) | + | *a CI build is published so everyone can see the output - see [[https://github.com/hl7-fhir/auto-ig-builder/blob/master/README.md Auto-IG-Publisher Documentation]] |
+ | *when formal milestones are achieved, the Implementation Guide is published to the canonical web site for the IG (typically, hl7.org, hl7.org.xx, or fhir.org, but need not be) (See [[Standard FHIR Publishing Layout Pattern]] for additional guidance) | ||
For IGs developed on the Simplifier.net infrastructure, see [todo as yet] for publishing details. Non-public Implementation guides can still use the IG build, but cannot use the CI Build infrastructure | For IGs developed on the Simplifier.net infrastructure, see [todo as yet] for publishing details. Non-public Implementation guides can still use the IG build, but cannot use the CI Build infrastructure | ||
− | = Examples = | + | =Examples= |
If you want an example of IG source, you can look in one of the following places: | If you want an example of IG source, you can look in one of the following places: | ||
− | * FHIR | + | *FHIR GitHub repository, in /guides/* - any directory ending in 2 - a variety of styles of implementation guide. |
− | * Also, there's | + | *Also, there's /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.publisher.jar</code>. You can get it from https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.publisher.jar. The jar includes everything from the spec that is required to generate the implementation guide. | |
− | # Get the publisher itself: this is a java jar called <code>org.hl7.fhir. | + | #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. |
− | # 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. | 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. | ||
Line 43: | Line 51: | ||
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. | 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. | ||
− | Alternatively, you can use the IG Publisher in web server mode. If you do this, you don't need any installed software. | + | Alternatively, you can use the IG Publisher in web server mode. If you do this, you don't need any installed software. |
− | == Using the IG Publisher Web Server == | + | ==Using the IG Publisher Web Server== |
The IG publisher lives at [[http://hapi.fhir.org/igweb]]. From there, you can upload a ip file containing the contents of the IG. After processing, you can download the output. | The IG publisher lives at [[http://hapi.fhir.org/igweb]]. From there, you can upload a ip file containing the contents of the IG. After processing, you can download the output. | ||
Line 53: | Line 61: | ||
You can also use the API to the IG web publisher directly. To do this, POST a zip containing the IG content to http://hapi.fhir.org/igweb/process (Content-Tyepe: application/zip), and after a period of seconds, a zip file containing the generated output will be returned. | You can also use the API to the IG web publisher directly. To do this, POST a zip containing the IG content to http://hapi.fhir.org/igweb/process (Content-Tyepe: application/zip), and after a period of seconds, a zip file containing the generated output will be returned. | ||
− | == Running in GUI mode == | + | ==Running in GUI mode== |
− | '''Windows''': double-click on org.hl7.fhir. | + | '''Windows''': double-click on org.hl7.fhir.publisher.jar or right-click and select 'Open'. |
− | '''Linux''': double-click on org.hl7.fhir. | + | '''Linux''': double-click on org.hl7.fhir.publisher.jar or right-click and select 'Open With Oracle Java 8 Runtime'. |
You can also run it the command line: | You can also run it the command line: | ||
− | java -jar org.hl7.fhir. | + | java -jar org.hl7.fhir.publisher.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. | 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. | ||
Line 71: | Line 79: | ||
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'. | 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'. | ||
− | == Running in command line mode == | + | ==Running 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: | ||
− | java -jar org.hl7.fhir. | + | java -jar org.hl7.fhir.publisher.jar -ig [source] (-tx [url]) (-packages [directory]) (-watch) |
parameters: | parameters: | ||
− | * -ig: a path or a url where the implementation guide JSON control file is found (see [[#Control_file|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) | + | *-ig: a path or a url where the implementation guide JSON control file is found (see [[#Control_file|control file format documentation]]) |
− | * -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 | + | *-tx: (optional) address to use for terminology server (default is http://fhir3.healthintersections.com.au - which is currently the only supported option) |
+ | *-packages: (optional) directory containing packages (tarball/gzips with implementation guide-associated artifacts with extension .tgz) to be used for packages to load without using package management infrastructure | ||
+ | *-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 | ||
Advanced parameters: | Advanced parameters: | ||
− | * -resetTx - clear out the txCache (see comments below about managing the freshness of the txCache) | + | |
− | * -resetTxErrors - delete any errors from the tcCache, but leave successful operations in the cache | + | *-resetTx - clear out the txCache (see comments below about managing the freshness of the txCache) |
+ | *-resetTxErrors - delete any errors from the tcCache, but leave successful operations in the cache | ||
Windows example: | 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: | [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. | + | java -jar "C:\Users\VadimPeretokin\Desktop\fhir-publisher\org.hl7.fhir.publisher.jar" -ig "C:\Users\VadimPeretokin\Desktop\fhir-git\tests\ig\test-ig.json" -watch |
Linux: | Linux: | ||
Open the terminal (usually Ctrl+Alt+T), then paste the following, with the paths adjusted for your computer: | 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. | + | java -jar '/home/vadi/Programs/fhir-publisher/org.hl7.fhir.publisher.jar' -ig '/home/vadi/Programs/fhir-git/tests/ig/test-ig.json' -watch |
− | === Validating without publishing === | + | ===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: | ||
− | java -jar org.hl7.fhir. | + | java -jar org.hl7.fhir.publisher.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. | 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== |
once running, it: | once running, it: | ||
− | * reads the control file | + | |
− | * reads the IG | + | *reads the control file |
− | * processes any spreadsheets, bundles, and logical models | + | *reads the IG |
− | * loads all the resources in the IG | + | *processes any spreadsheets, bundles, and logical models |
− | * processes code systems, value sets, structure definitions, structure maps | + | *loads all the resources in the IG |
− | * validates the all resources in the IG and produces an HTML QA file with any errors encountered | + | *processes code systems, value sets, structure definitions, structure maps |
− | * 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 | + | *validates the all resources in the IG and produces an HTML QA file with any errors encountered |
− | * generates summary output | + | *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 |
− | * gets the tool (Jekyll) to generate the final output. The Jekyll source is in /pages by default | + | *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. | If you'd like to use another website generation tool, discuss your tool of choice with Grahame Grieve. | ||
− | == IG Publisher Special Output files == | + | ==IG Publisher Special Output files== |
The IG Publisher produces (or may produce) several different zip files. The most significant is "validator.pack". This is a zip file that contains all the conformance & example resources, a version marker, and a json file that lists all the pages and urls in the ig itself. This file is used: | The IG Publisher produces (or may produce) several different zip files. The most significant is "validator.pack". This is a zip file that contains all the conformance & example resources, a version marker, and a json file that lists all the pages and urls in the ig itself. This file is used: | ||
− | * by the fhir validator - if you refer to the IG directly by it's canonical URL | + | *by the fhir validator - if you refer to the IG directly by it's canonical URL |
− | * by the IG publisher - if you declare that one IG depends on another | + | *by the IG publisher - if you declare that one IG depends on another |
− | * by a server - if you add the IG to a server load list | + | *by a server - if you add the IG to a server load list |
The IG publisher will generate definitions.[fmt].zip (unless instructed not to) - these may be useful for other tools that have format specific requirements, and must have json, xml., or ttl inputs. | The IG publisher will generate definitions.[fmt].zip (unless instructed not to) - these may be useful for other tools that have format specific requirements, and must have json, xml., or ttl inputs. | ||
Line 133: | Line 145: | ||
Finally the entire IG output is is provided as full-ig.zip. | Finally the entire IG output is is provided as full-ig.zip. | ||
− | = Control file = | + | =Control file= |
When the IG publisher is executed, it is pointed at a control file. This is a json file that contains all | When the IG publisher is executed, it is pointed at a control file. This is a json file that contains all | ||
Line 167: | Line 179: | ||
"languages" : [ // optional | "languages" : [ // optional | ||
"[language]" | "[language]" | ||
− | ] | + | ], |
"pre-process" : [{ // optional section [[#Pre-processing_Pages|see below]] | "pre-process" : [{ // optional section [[#Pre-processing_Pages|see below]] | ||
"folder" : "[folder]", | "folder" : "[folder]", | ||
Line 176: | Line 188: | ||
"no-inactive-codes" : true | false, // optional; default = false | "no-inactive-codes" : true | false, // optional; default = false | ||
"broken-links" : "warning | error", // optional; default to warning, but can be error (stops the build) | "broken-links" : "warning | error", // optional; default to warning, but can be error (stops the build) | ||
− | "gen-examples" : | + | "check-aggregation" : true, // Warning if aggregation not declared on differential elements of type Reference |
− | "do-transforms" : | + | "check-mustSupport" : true, // Warning if mustSupport not declared on elements appearing in differential |
+ | "append-slash-to-dependency-urls" : false, // true if the publisher should append / to dependency URLs in the jekyll data file (default false for legacy reasons) | ||
+ | "anyExtensionsAllowed" : false, // If false, raises an error if unrecognized encounters are encountered, otherwise only an 'information' message | ||
+ | "hintAboutNonMustSupport", : true //Info validation if elements appear in examples when not marked as mustSupport=true in one of the corresponding profiles | ||
+ | "gen-examples" : true, // optional, see below ([[#Processing_Options|processing options]]) | ||
+ | "do-transforms" : true, // optional, see below ([[#Processing_Options|processing options]]) | ||
"canonicalBase": "[where this will be published - [[#Canonical_URL|see above]]]. Mandatory", | "canonicalBase": "[where this will be published - [[#Canonical_URL|see above]]]. Mandatory", | ||
"dependencyList": [ // optional | "dependencyList": [ // optional | ||
Line 185: | Line 202: | ||
{ | { | ||
"name" : "[name of the IG, for logging, and Jekyll variable name for location]", | "name" : "[name of the IG, for logging, and Jekyll variable name for location]", | ||
− | "location" : "[http address where the IG lives]", | + | "package" : "[NPM package id of the IG]", |
− | "source" : "[folder to get the definitions from | + | "location" : "[http address where the IG lives (not needed if package is specified)]", |
+ | "version" : "[version, or 'current' or 'dev']", | ||
+ | "source" : "[optional folder to get the definitions from (relative). Should not be required]" | ||
} | } | ||
], | ], | ||
"extension-domains" : [ | "extension-domains" : [ | ||
"[url]" // list of domains from which undeclared extensions are allowed to come from | "[url]" // list of domains from which undeclared extensions are allowed to come from | ||
− | ] | + | ], |
// Templates lists any additional templates beyond "base" and "format" that can be generated for one or more artifact types | // 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 | // The list of template names below are examples | ||
Line 200: | Line 219: | ||
"Any": { | "Any": { | ||
// fragment and template options - [[#Fragment_.26_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" // use this as the default template for all base pages if not overridden | "template-base" : "sometemplatefile.html" // use this as the default template for all base pages if not overridden | ||
}, | }, | ||
Line 233: | Line 252: | ||
The control file must be maintained by the editor of the implementation guide. | The control file must be maintained by the editor of the implementation guide. | ||
− | == Version == | + | ==Version== |
The IG publisher lives in the current build (http://build.fhir.org), where it is maintained in an ongoing fashion. The IG publisher knows how to publish IGs for the following versions: | The IG publisher lives in the current build (http://build.fhir.org), where it is maintained in an ongoing fashion. The IG publisher knows how to publish IGs for the following versions: | ||
− | * 1.0.2: DSTU2 | + | *1.0.2: DSTU2 |
− | * 1.4.0: May 2016 draft release (supported for some stakeholders who use it, and make that possible) | + | *1.4.0: May 2016 draft release (supported for some stakeholders who use it, and make that possible) |
− | * 3.0. | + | *3.0.1: DSTU3 |
− | * | + | *current - the current build. |
The IG publisher may work with other versions (e.g. forks of R4 candidate versions) but this is not guaranteed. | The IG publisher may work with other versions (e.g. forks of R4 candidate versions) but this is not guaranteed. | ||
Line 248: | Line 267: | ||
"version" : "1.0.2" | "version" : "1.0.2" | ||
− | === Business Version === | + | ===Business Version=== |
You can impose a fixed business version on all the conformance resources using | You can impose a fixed business version on all the conformance resources using | ||
Line 257: | Line 276: | ||
This approach to profile versioning means that profiles do not need to have their cannonical URLs changed when substantive changes are made (nor do references to those profiles need to be updated). Instead, all profile references within an IG simply use a consistent canonical URL. When instances declare the profile in an instance, they combine the canonical URL with the profile/IG version as follows: | This approach to profile versioning means that profiles do not need to have their cannonical URLs changed when substantive changes are made (nor do references to those profiles need to be updated). Instead, all profile references within an IG simply use a consistent canonical URL. When instances declare the profile in an instance, they combine the canonical URL with the profile/IG version as follows: | ||
+ | |||
:[someurl]|[someVersion] | :[someurl]|[someVersion] | ||
Line 263: | Line 283: | ||
This tells the validator which version of the profile must be used when validating the instance. | This tells the validator which version of the profile must be used when validating the instance. | ||
− | + | ==License== | |
− | == License == | ||
The license parameter is required and is either: | The license parameter is required and is either: | ||
− | * An identifier from the [https://spdx.org/licenses/ SPDX License List] | + | *An identifier from the [https://spdx.org/licenses/ SPDX License List] |
− | * or literal string " | + | *or literal string "not-open-source" |
For example | For example | ||
Line 283: | Line 302: | ||
... | ... | ||
− | == Paths == | + | ==Paths== |
The IG publisher defines the following paths that can be configured in the control file: | The IG publisher defines the following paths that can be configured in the control file: | ||
− | * [resources]: the directory or set of directories where all the input FHIR resources are found (usually conformance resources and examples). Multiple directories can be used to allow source files to be grouped - e.g. separate folders for examples, vocabulary-related files and 'other' files. | + | *[resources]: the directory or set of directories where all the input FHIR resources are found (usually conformance resources and examples). Multiple directories can be used to allow source files to be grouped - e.g. separate folders for examples, vocabulary-related files and 'other' files. |
− | * [pages]: the directory or set of directories that contain the jekyll source (not process, just passed to Jekyll for processing). Multiple directories can be used if it makes implementation guide maintenance easier to separate certain files. (Also see pre-process.) | + | *[pages]: the directory or set of directories that contain the jekyll source (not process, just passed to Jekyll for processing). Multiple directories can be used if it makes implementation guide maintenance easier to separate certain files. (Also see pre-process.) |
− | * [temp]: a scratch directory that is used for the temporary source for jekyll processing (do not use this directory for anything else) | + | *[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 | + | *[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) | + | *[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. | + | *[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 | + | *[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 |
+ | *[liquid]: a folder that contains a set of liquid templates (see [[FHIR Liquid Profile]]) where the file name is [resource-type].liquid. When narrative is built for a resource, the nominated liquid template will be used rather than the default narrative generation | ||
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: | 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] | + | *[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. | + | 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. |
− | == DependencyList == | + | ==DependencyList== |
As stated above this is a list of other implementation guides that this guide depends on. For example building a profile upon a another profile or referencing another profile's structuredefinitions, value sets, code systems etc. | As stated above this is a list of other implementation guides that this guide depends on. For example building a profile upon a another profile or referencing another profile's structuredefinitions, value sets, code systems etc. | ||
Line 308: | Line 328: | ||
"dependencyList": [ | "dependencyList": [ | ||
− | + | { | |
− | |||
"name" : "uscore", | "name" : "uscore", | ||
"location" : "http://hl7.org/fhir/us/core", | "location" : "http://hl7.org/fhir/us/core", | ||
− | " | + | "version" : "1.1.0" |
− | } | + | }] |
− | + | The location is the canonical URL for the guide. The IG Publisher will resolve the canonical URL to a package id, add the specified guide to the [[FHIR Package cache]], and then use it. | |
+ | |||
+ | In addition to a published version of the IG, the following 2 special versions can be specified: | ||
+ | |||
+ | *current: Use the latest version of the IG as built by the IG auto-publisher (see above) - usually this is updated when a commit is pushed to github | ||
+ | *dev: use the latest local build of the IG. in the absence of a local build, this falls back to using the current version | ||
+ | |||
+ | If, for some reason, the dependent IG is not run on the auto-build platform, and the resolution from Canonical URL to package id is not known to the IG Publisher, you can specify your own package id: | ||
+ | |||
+ | { | ||
+ | "name" : "uscore", | ||
+ | "location" : "http://example.org/fhir/myig", | ||
+ | "package" : "example.fhir.myig", | ||
+ | "version" : "1.1.0", | ||
+ | } | ||
+ | |||
+ | Notes: | ||
+ | |||
+ | *never specify an alternative package id if one has already been used | ||
+ | *for IGs published through Hl7.org or fhir.org, package ids are assigned by the FHIR Product Director | ||
+ | *you can specify an alternative location for a specific version of a specific package through the [[FHIR Package cache]] localization mechanism | ||
In theory, all extensions that are referred to should be from Implementation Guides explicitly listed in the dependencyList. However, for a variety of reasons, that's not always possible. So particular domains that are explicitly allowed as unregistered extensions can be added using the allowed-domains list - an array of strings: | In theory, all extensions that are referred to should be from Implementation Guides explicitly listed in the dependencyList. However, for a variety of reasons, that's not always possible. So particular domains that are explicitly allowed as unregistered extensions can be added using the allowed-domains list - an array of strings: | ||
Line 323: | Line 362: | ||
] | ] | ||
− | === Terminology Service Cache === | + | ===Terminology Service Cache=== |
The IG Publisher uses a terminology server to support it's operations (presently, this is fhir3.healthintersections.com/au, but is planned to move to tx.fhir.org soon). In order to improve operational performance, the IG publisher caches the outcome of all interactions with the terminology server. This makes a substantial difference to the performance of the publication, but also means that there's a risk of the terminology content becoming stale. | The IG Publisher uses a terminology server to support it's operations (presently, this is fhir3.healthintersections.com/au, but is planned to move to tx.fhir.org soon). In order to improve operational performance, the IG publisher caches the outcome of all interactions with the terminology server. This makes a substantial difference to the performance of the publication, but also means that there's a risk of the terminology content becoming stale. | ||
Line 333: | Line 372: | ||
There are several ways to delete the terminology service cache: | There are several ways to delete the terminology service cache: | ||
− | * find the directory and manually delete content from it (e.g. all files). This is can be done safely at any time | + | *find the directory and manually delete content from it (e.g. all files). This is can be done safely at any time |
− | * run the IG Publisher with the parameter -resetTx - this clears the folder | + | *run the IG Publisher with the parameter -resetTx - this clears the folder |
− | * run the IG Publisher with the parameter -resetTxErrors - this clears the folder of any errors from the terminology server but keeps successful operations | + | *run the IG Publisher with the parameter -resetTxErrors - this clears the folder of any errors from the terminology server but keeps successful operations |
− | * the terminology cache will be flushed completely when the terminology server is upgraded | + | *the terminology cache will be flushed completely when the terminology server is upgraded |
− | === Terminology Options === | + | ===Terminology Options=== |
If you use SNOMED CT, you must specify a SNOMED CT Edition to use: | If you use SNOMED CT, you must specify a SNOMED CT Edition to use: | ||
Line 344: | Line 383: | ||
"sct-edition" : "http://snomed.info/sct/[module]", | "sct-edition" : "http://snomed.info/sct/[module]", | ||
− | where [module] comes from this list | + | where [module] comes from [[https://confluence.ihtsdotools.org/display/FHIR/Known+SNOMED+CT+Edition+Modules this list]] |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Note that you can only specify a version supported by the infrastructure (currently: International, US, AU, CA). You can specify a version if you want (but it will fail if this is a different version to the infrastructure). | Note that you can only specify a version supported by the infrastructure (currently: International, US, AU, CA). You can specify a version if you want (but it will fail if this is a different version to the infrastructure). | ||
Line 360: | Line 390: | ||
In addition to this, you can specify whether to include inactive codes or not: | In addition to this, you can specify whether to include inactive codes or not: | ||
− | "activeOnly" : | + | "activeOnly" : true, |
By default, inactive codes are included | By default, inactive codes are included | ||
− | == Pre-processing Pages == | + | ==Pre-processing Pages== |
The IG publisher can pre-process pages. If you specify a pre-process option, then the IG publisher will | 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 and will then do one or more of two things: | copy the content from the pre-process directory and will then do one or more of two things: | ||
− | * rather than putting it directly in the "pages" folder, will place it in the designated subfolder of pages. This allows pointing to a folder that contains content intended to map to _data, _includes or some other sub-folder without needing to create a directory hierarcy in the implementation guide's source files | + | |
− | * 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. | + | *rather than putting it directly in the "pages" folder, will place it in the designated subfolder of pages. This allows pointing to a folder that contains content intended to map to _data, _includes or some other sub-folder without needing to create a directory hierarcy in the implementation guide's source files |
+ | *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). | The transform engine uses XSLT1 not XSLT2 (e.g. the standard java transform engine). | ||
− | == Processing Options == | + | ==Processing Options== |
These are global flags that control FHIR specific pre-processing associated of profiles. All the flags default to false. | 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 | + | *'''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 | + | *'''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 == | + | ==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). | 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). | ||
Line 386: | Line 417: | ||
In either case, it will look in the following places, in order: | In either case, it will look in the following places, in order: | ||
− | * on the resource entry for the resource in question | + | *on the resource entry for the resource in question |
− | * on the defaults entry for the resource type in question | + | *on the defaults entry for the resource type in question |
− | * on the defaults entry for "ANY" | + | *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 | 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. | NOT produce an output page. | ||
− | === Fragment Codes === | + | ===Fragment Codes=== |
There will be one each of these fragments for each resource type that is found: | 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) | + | *xml: XML version of the resource (all resource types) |
− | * ttl: Turtle version of the resource (all resource types) | + | *json: JSON version of the resource (all resource types) |
− | * xml-html: html representation of XML version of the resource (all resource types) | + | *ttl: Turtle version of the resource (all resource types) |
− | * json-html: html representation of JSON version of the resource (all resource types) | + | *xml-html: html representation of XML version of the resource (all resource types) |
− | * ttl-html: html representation of Turtle version of the resource (all resource types) | + | *json-html: html representation of JSON version of the resource (all resource types) |
− | * html: narrative of resource as html | + | *ttl-html: html representation of Turtle version of the resource (all resource types) |
− | * summary: An html summary for the resource (all conformance resources) | + | *html: narrative of resource as html |
− | * content: An HTML representation of the content in resource (code system, concept map, structure map) | + | *summary: An html summary for the resource (all conformance resources) |
− | * xref: A list of all the places where the resource is used (all conformance resources) | + | *content: An HTML representation of the content in resource (code system, concept map, structure map) |
− | * cld: An HTML representation of the content in resource (value set) | + | *xref: A list of all the places where the resource is used (all conformance resources) |
− | * expansion: The expansion of the value set (Value set) | + | *cld: An HTML representation of the content in resource (value set) |
− | * shex: ShEx statement for the structure (Structure Definition) | + | *expansion: The expansion of the value set (Value set) |
− | * sch: schematron statement for the structure (Structure Definition) | + | *shex: ShEx statement for the structure (Structure Definition) |
− | * java: Java Class for the structure (Structure Definition) | + | *sch: schematron statement for the structure (Structure Definition) |
− | * json-schema: JSON Schema statement for the structure (Structure Definition) | + | *java: Java Class for the structure (Structure Definition) |
− | * header: Description of the identification of the structure (Structure Definition) | + | *json-schema: JSON Schema statement for the structure (Structure Definition) |
− | * diff: Logical Table of the diff (Structure Definition) | + | *header: Description of the identification of the structure (Structure Definition) |
− | * snapshot: Logical Table of the snapshot (Structure Definition) | + | *diff: Logical Table of the diff (Structure Definition) |
− | * pseudo-xml: XML template for the snapshot (Structure Definition); | + | *snapshot: Logical Table of the snapshot (Structure Definition) |
− | * pseudo-json: JSON template for the snapshot (Structure Definition) | + | *pseudo-xml: XML template for the snapshot (Structure Definition); |
− | * pseudo-ttl: Turtle template for the snapshot (Structure Definition) | + | *pseudo-json: JSON template for the snapshot (Structure Definition) |
− | * uml: UML diagram for the structure (Structure Definition) | + | *pseudo-ttl: Turtle template for the snapshot (Structure Definition) |
− | * tx: Terminology Notes for the structure (Structure Definition) | + | *uml: UML diagram for the structure (Structure Definition) |
− | * inv: invariant summary for the structure (Structure Definition) | + | *tx: Terminology Notes for the structure (Structure Definition) (all elements, snapshot) |
− | * dict: Detailed Element Definitions (Structure Definition) | + | *tx-must-support: Terminology Notes for the structure (Structure Definition) (must-support elements, snapshot) |
− | * dict-active: Detailed Element Definitions (Structure Definition), but only including elements with max cardinality > 0 | + | *tx-diff: Terminology Notes for the structure (Structure Definition) (all elements, differential) |
− | * maps: Presentation of the mappings (Structure Definition) | + | *tx-diff-must-support : Terminology Notes for the structure (Structure Definition) (must-support elements, differential) |
− | * span: Presentation of all profiles a profile refers to (StructureDefinition where derivation = constraint) | + | *inv: invariant summary for the structure (Structure Definition) |
− | * spanall: Presentation of all profiles & base resources a profile refers to (StructureDefinition where derivation = constraint) | + | *dict: Detailed Element Definitions (Structure Definition) |
− | * script: Script language rendition of a StructureMap (StructureMap) | + | *dict-active: Detailed Element Definitions (Structure Definition), but only including elements with max cardinality > 0 |
− | * profiles: List of Profiles generated from a StructureMap (StructureMap) | + | *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) | ||
+ | *maturity: Banner with resource maturity (all resources) | ||
+ | |||
+ | *for each list in the IG, the publisher can produce the following fragments: | ||
+ | **list-list - a list with descriptions | ||
+ | **list-list-simple: a list with no descriptions | ||
+ | **list-table-xx - a table, with 2 columns for name and description | ||
+ | **Note that for lists, 3 variants are produce, in the order of the list, and in alphabetical by type/id and name | ||
In addition, the publisher produces the following set of fragments for listing all the content: | In addition, the publisher produces the following set of fragments for listing all the content: | ||
− | * list-[type].xhtml | + | |
− | * table-[type].xhtml | + | *list-[type].xhtml |
+ | *list-simple-[type].xhtml | ||
+ | *table-[type].xhtml | ||
+ | |||
+ | These 3 are also produced with a -mm (e.g. list-[type]-mm.xhtml) that includes maturity levels for each resource, where it is known. (note that the maturity numbers are in an <a> tag with class="fmm", for styling purposes) | ||
If there are any structure definitions of the right type, the publisher will also produce the following: | If there are any structure definitions of the right type, the publisher will also produce the following: | ||
− | |||
− | |||
− | |||
− | === Page templates === | + | *table-profiles.xhtml & list-profiles.xhtml |
+ | *table-extensions.xhtml & list-extensions.xhtml | ||
+ | *table-logicals.xhtml & list-logicals.xhtml | ||
+ | |||
+ | Also, -mm variants (see above) are produced for these as well | ||
+ | |||
+ | ===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 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: | 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-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-fmt''' defines the page format for pretty-printed views of the JSON, XML and TTL representations of the resource. | + | *'''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: | The file names of these generated pages will default to the following: | ||
+ | |||
*base: [ResourceType]-[id].html | *base: [ResourceType]-[id].html | ||
*defns: [ResourceType]-[id]-definitions.html | *defns: [ResourceType]-[id]-definitions.html | ||
Line 464: | Line 515: | ||
for each resource. When copied, the following strings will be replaced: | 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>) | + | *<nowiki>{{[title]}}</nowiki> - a description of the content of the resource (typical use: <h2><nowiki>{{[title]}}</nowiki></h2>) |
− | * {{[name]}} - the path for the source fragment to include (proper use: {% include {{[name]}}.xhtml %}) | + | *<nowiki>{{[name]}}</nowiki> - the path for the source fragment to include (proper use: {% include <nowiki>{{[name]}}</nowiki>.xhtml %}) |
− | * {{[id]}} - the id of the resource | + | *<nowiki>{{[id]}}</nowiki> - the id of the resource |
− | * [[[type]}} - the type of the resource | + | *<nowiki>[[[type]}} - the type of the resource</nowiki> |
− | * [[[uid]}} - type-id (combination) | + | *<nowiki>[[[uid]}} - type-id (combination)</nowiki> |
− | == HTML Template == | + | ==HTML Template== |
In addition to the pages generated from artifacts, implementation guides will typically have non-generated HTML pages that provide navigation, background and other supporting information. In most IGs, these pages will follow a typical pattern in terms of header and footer, with only the "body" of the page changing. To allow this content to be edited in pure XHTML (with schema validation support), the IG publisher allows identifying a Jekyll template file that is to be used for some or all such files. The tool will look for HTML pages that are referenced in the implementation guide file but are not present in the pages folder. For each one found, it will look for a corresponding XML file and apply the templates specified with the html-template property. | In addition to the pages generated from artifacts, implementation guides will typically have non-generated HTML pages that provide navigation, background and other supporting information. In most IGs, these pages will follow a typical pattern in terms of header and footer, with only the "body" of the page changing. To allow this content to be edited in pure XHTML (with schema validation support), the IG publisher allows identifying a Jekyll template file that is to be used for some or all such files. The tool will look for HTML pages that are referenced in the implementation guide file but are not present in the pages folder. For each one found, it will look for a corresponding XML file and apply the templates specified with the html-template property. | ||
− | == Suppressed Warnings == | + | ==Suppressed Warnings== |
Warnings and information messages will occasionally be generated that are "known" and unavoidable based on the design of a particular implementation guide. When there are a large number of these, it can be difficult for someone reviewing the qa page to distinguish which warnings they need to pay attention to and which are new/important. This option allows the IG configuration file to identify a text file containing a list of warnings to suppress from the QA reports. Each line of the file should contain either the full text of the warning to suppress (as shown in qa.txt) or just the display message to suppress (if the message should be suppressed regardless of which file or location triggers the issue). This mechanism can suppress information messages, warning messages and errors related to broken links (e.g. if a link is created to a file produced during post-processing or that otherwise isn't resolvable during the IG publication process). | Warnings and information messages will occasionally be generated that are "known" and unavoidable based on the design of a particular implementation guide. When there are a large number of these, it can be difficult for someone reviewing the qa page to distinguish which warnings they need to pay attention to and which are new/important. This option allows the IG configuration file to identify a text file containing a list of warnings to suppress from the QA reports. Each line of the file should contain either the full text of the warning to suppress (as shown in qa.txt) or just the display message to suppress (if the message should be suppressed regardless of which file or location triggers the issue). This mechanism can suppress information messages, warning messages and errors related to broken links (e.g. if a link is created to a file produced during post-processing or that otherwise isn't resolvable during the IG publication process). | ||
Line 486: | Line 537: | ||
"suppressedWarningFile": "[path]mySuppressedWarnings.txt" | "suppressedWarningFile": "[path]mySuppressedWarnings.txt" | ||
− | == Loading Resources == | + | ==Loading Resources== |
Resources are loaded as follows: | 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) | + | *The IG resource is loaded (by literal filename) |
− | * any bundles are loaded (by Type/id) | + | *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 resources referenced in the IG resource are loaded (by Type/Id) | + | *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. | Note: The IG resource must use sourceReference references by id. e.g. | ||
Line 516: | Line 568: | ||
only known to work reliably for StructureDefinition resources | only known to work reliably for StructureDefinition resources | ||
− | == Using Bundles == | + | ==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: | 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: | ||
Line 526: | Line 578: | ||
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. | 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== |
For legacy reasons, it's possible to author profiles using spreadsheets. This approach is deprecated. To get the IG publisher to process a spreadsheet: | For legacy reasons, it's possible to author profiles using spreadsheets. This approach is deprecated. To get the IG publisher to process a spreadsheet: | ||
Line 538: | Line 590: | ||
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: | ||
− | * Value Set references - use either | + | *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 | + | **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 | + | **http(s)://... a reference to a value set from outside the IG, or in the IG |
− | ** valueset-xxx where: | + | **valueset-xxx where: |
− | *** valueset-xxx is the name of a file found in the same directory as the spreadsheet | + | ***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 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 | + | ***The file must be a ValueSet resource, with an id of xxx and the appropriate canonical URL |
− | * Search Parameters | + | *Search Parameters |
− | ** You have to provide a fluent path expression directly ("Expression") | + | **You have to provide a fluent path expression directly ("Expression") |
− | ** you have to provide a description directly | + | **you have to provide a description directly |
− | ** you have to specify the target types directly | + | **you have to specify the target types directly |
− | * Types | + | *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 | + | **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 |
− | ** You can specify ElementDefinition.type.versioning by appending a ~ then the versioning code to the type | + | **You can specify ElementDefinition.type.versioning by appending a ~ then the versioning code to the type |
− | * Note that IG publisher enforces the use of correct ids and canonical URLs against the base stated in the control file | + | *Note that IG publisher enforces the use of correct ids and canonical URLs against the base stated in the control file |
− | == Special URLs == | + | ==Special URLs== |
For MetadataResources - CodeSystem, ValueSet, etc (anything with a canonical URL) - the IG publisher expects that their Canonical URL is equal to [canonical]/[type]/[id] where [canonical is the IG canonical URL. The IG publisher will ensure that the IG itself is an valid FHIR implementation guide and responds correctly to requests for the resources by their canonical URL. | For MetadataResources - CodeSystem, ValueSet, etc (anything with a canonical URL) - the IG publisher expects that their Canonical URL is equal to [canonical]/[type]/[id] where [canonical is the IG canonical URL. The IG publisher will ensure that the IG itself is an valid FHIR implementation guide and responds correctly to requests for the resources by their canonical URL. | ||
Line 565: | Line 617: | ||
Notes: | Notes: | ||
− | * URLs have to be explicitly listed because it's too easy for an author to make a mistake and get the canonical URL wrong | + | *URLs have to be explicitly listed because it's too easy for an author to make a mistake and get the canonical URL wrong |
− | * one case for using this facility is where the IG includes a resource that is also published elsewhere. Author's should think hard before doing this - referring to a resource by it's canonical URL rather than copying into the IG is generally a much better approach in terms of ongoing maintenance. | + | *one case for using this facility is where the IG includes a resource that is also published elsewhere. Author's should think hard before doing this - referring to a resource by it's canonical URL rather than copying into the IG is generally a much better approach in terms of ongoing maintenance. |
− | == Jurisdiction == | + | ==Jurisdiction== |
The IG publisher can be configured to automatically fill out the Jurisdication on any Metadata Resources it encounters ([Resource].jurisdiction). Provide one or mode codes separated by commas, where the code is taken from http://build.fhir.org/valueset-jurisdiction.html (countries or regions only, no US states. System is not needed). Use code 001 for international specifications. | The IG publisher can be configured to automatically fill out the Jurisdication on any Metadata Resources it encounters ([Resource].jurisdiction). Provide one or mode codes separated by commas, where the code is taken from http://build.fhir.org/valueset-jurisdiction.html (countries or regions only, no US states. System is not needed). Use code 001 for international specifications. | ||
− | == NPM == | + | ==NPM== |
− | The publisher | + | The publisher produces an NPM package for ease of distribution. The property "npm-name" must have a value - see [[FHIR NPM Package Spec]] for details of how to populate this. This is required for all Implementation Guides. |
The IG publisher fills out a few mandatory elements in the package file from the information it has available. Authors can provide additional details beyond those generated by the IG publisher by providing a template which is loaded before the IG publisher writes out the details. The property "npm-template" is relative to the folder containing the configuration file | The IG publisher fills out a few mandatory elements in the package file from the information it has available. Authors can provide additional details beyond those generated by the IG publisher by providing a template which is loaded before the IG publisher writes out the details. The property "npm-template" is relative to the folder containing the configuration file | ||
− | = Language Support = | + | =Language Support= |
'''Note: this section is draft - the functionality described here is not yet implemented.''' | '''Note: this section is draft - the functionality described here is not yet implemented.''' | ||
Line 586: | Line 638: | ||
It's possible to publish Implementation Guides in other languages, or to publish them in multiple languages. Note, though, that there is always a single master language that the IG Publisher uses when publishing. | It's possible to publish Implementation Guides in other languages, or to publish them in multiple languages. Note, though, that there is always a single master language that the IG Publisher uses when publishing. | ||
− | == Specifying an Alternate Master Language == | + | ==Specifying an Alternate Master Language== |
To change the language from English, specify a language using the "language" property in the [[#Control file|json control]] file: | To change the language from English, specify a language using the "language" property in the [[#Control file|json control]] file: | ||
Line 596: | Line 648: | ||
When an alternative language is specified, the IG publisher changes how it works in the following ways: | When an alternative language is specified, the IG publisher changes how it works in the following ways: | ||
− | * When reading any text from a resource definition, the IG publisher will first look at any [[http://hl7.org/fhir/extension-translation.html translation extensions]] on the element for a matching language tag (full match including country first, then partial match). If there's no matching extension, it will just use the element value. This applies to any elements of type 'string' or 'markdown' | + | *When reading any text from a resource definition, the IG publisher will first look at any [[http://hl7.org/fhir/extension-translation.html translation extensions]] on the element for a matching language tag (full match including country first, then partial match). If there's no matching extension, it will just use the element value. This applies to any elements of type 'string' or 'markdown' |
− | * When looking up codes on the terminology server, the IG publisher will ask for the specified language. tx.fhir.org uses the same approach as immediately above in this case. Note: to get code system displays in additional languages defined on tx.fhir.org, talk to Grahame Grieve | + | *When looking up codes on the terminology server, the IG publisher will ask for the specified language. tx.fhir.org uses the same approach as immediately above in this case. Note: to get code system displays in additional languages defined on tx.fhir.org, talk to Grahame Grieve |
− | * Any text that is used by the IG publisher that is not in the specified language will be pass to an internal translation module that can translate the text to the target language. This is driven by a configuration file that has a list of mappings from language to language. The input file to configure this is languages.json in the same directory as the config file. There will be a file produced in the qa directory, also called languages.txt, which is the same file with any untranslated texts added (to help editors build the language file) | + | *Any text that is used by the IG publisher that is not in the specified language will be pass to an internal translation module that can translate the text to the target language. This is driven by a configuration file that has a list of mappings from language to language. The input file to configure this is languages.json in the same directory as the config file. There will be a file produced in the qa directory, also called languages.txt, which is the same file with any untranslated texts added (to help editors build the language file) |
− | * Any content in the pages is left untouched. | + | *Any content in the pages is left untouched. |
− | == Using multiple languages == | + | ==Using multiple languages== |
In addition, the IG publisher can produce fragments in multiple languages. To do this, specify additional languages using the language property; | In addition, the IG publisher can produce fragments in multiple languages. To do this, specify additional languages using the language property; | ||
Line 611: | Line 663: | ||
When you specify additional languages, for each output file that the IG publisher creates, it will also create additional fragments with same base file name, with -[lang] appended, in the specified language. This way, authors can build IGs in multiple languages. In this case, the language file will contain additional langauge codes but work as otherwise described above. | When you specify additional languages, for each output file that the IG publisher creates, it will also create additional fragments with same base file name, with -[lang] appended, in the specified language. This way, authors can build IGs in multiple languages. In this case, the language file will contain additional langauge codes but work as otherwise described above. | ||
− | == Sharing Language Translations Across IGs == | + | ==Sharing Language Translations Across IGs== |
Todo. Not sure about this yet | Todo. Not sure about this yet | ||
− | = Build Tools = | + | =Build Tools= |
− | == Jekyll == | + | ==Jekyll== |
Installation: https://jekyllrb.com/ (see [[http://jekyll-windows.juthilo.com/2-jekyll-gem/ Jekyll on Windows]] for windows users) | Installation: https://jekyllrb.com/ (see [[http://jekyll-windows.juthilo.com/2-jekyll-gem/ Jekyll on Windows]] for windows users) | ||
Line 632: | Line 684: | ||
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: | 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. For example this is some Jekyll liquid syntax to access the Resource type from an example instance using the type parameter from the list below. | 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. For example this is some Jekyll liquid syntax to access the Resource type from an example instance using the type parameter from the list below. | ||
− | include list-{{ site.data.structuredefinitions.{{[id]}}.type | slugify }}.xhtml | + | include list-<nowiki>{{site.data.structuredefinitions.{{[id]}}.type | slugify }}</nowiki>.xhtml |
− | * | + | *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 = | + | =Rules for Implementation Guides= |
− | == Format Support == | + | ==Format Support== |
The Implementation Guide supports 3 formats, as defined in the FHIR specification: | The Implementation Guide supports 3 formats, as defined in the FHIR specification: | ||
− | * XML | + | |
− | * JSON | + | *XML |
− | * Turtle (RDF) | + | *JSON |
+ | *Turtle (RDF) | ||
Note: in this documentation, [fmt] is one of 'xml', 'json', and 'ttl'. | Note: in this documentation, [fmt] is one of 'xml', 'json', and 'ttl'. | ||
Line 675: | Line 728: | ||
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. | 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 == | + | ==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 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) | + | *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 | + | *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].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].[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) | + | **!! [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) | + | **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 | + | **[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 | + | *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 == | + | ==URLs== |
− | === Canonical URL === | + | ===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). | 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). | ||
Line 696: | Line 749: | ||
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. | 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 === | + | ===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. | 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 == | + | ==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: | 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 current copy of the specification lives at [canonical] |
− | * the past milestones live at [canonical]/[id] where id is either a milestone name like "stu1" or a date (recommended format = YYYY) | + | *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 |
− | * at least the home page of all the versions (current or historical) references the published version history in a prominent location | + | *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. | 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 == | + | ==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. | 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. | ||
Line 716: | Line 770: | ||
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. | 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 == | + | ==Implementation Guide Layouts== |
Generally, there are 3 different approaches to organizing an implementation guide | 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 | + | *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 |
− | * 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] | + | *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. | 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. | ||
− | = Swagger = | + | =Swagger= |
'''Note: this section is draft - the functionality described here is not yet implemented.''' | '''Note: this section is draft - the functionality described here is not yet implemented.''' | ||
Line 738: | Line 793: | ||
The IG publisher will produce one set of swagger definitions for each entry in the list. | The IG publisher will produce one set of swagger definitions for each entry in the list. | ||
− | == Mode == | + | ==Mode== |
Whether to generate a single swagger file for all resources (single), or a file for each resource (split). | Whether to generate a single swagger file for all resources (single), or a file for each resource (split). | ||
− | == Capabilities == | + | ==Capabilities== |
The id of the capabilities statement to use as the base for generating the swagger file. | The id of the capabilities statement to use as the base for generating the swagger file. | ||
− | = Troubleshooting = | + | =Troubleshooting= |
Notes about 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 | + | #before doing any trouble shooting, make sure you are running the latest IG publisher for the version of FHIR you are using |
− | # Jekyll may not run if you have spaces your file path. Move to root directory, or eliminate spaces. | + | #Jekyll may not run if you have spaces your file path. Move to root directory, or eliminate spaces. |
− | # if the Jekyll part of the build fails, it fails completely, and the old output is left in place | + | #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 | + | #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 | + | #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) | + | #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) |
Before you ask about any terminology or dependency related issues, delete the content of your txCache directory, and run the IG publisher again | Before you ask about any terminology or dependency related issues, delete the content of your txCache directory, and run the IG publisher again | ||
− | == Logging == | + | ==Logging== |
The IG publisher performs 3 sorts of logging: | The IG publisher performs 3 sorts of logging: | ||
− | * basic progress logging to stdout (what you see) | + | *basic progress logging to stdout (what you see) |
− | * A full log to [tmp]/fhir-ig-publishing-tmp.log | + | *A full log to [tmp]/fhir-ig-publishing-tmp.log |
− | * in case of build failure, a debugging report to fhir-ig-publishing.log | + | *in case of build failure, a debugging report to fhir-ig-publishing.log |
You can change to amount of logging that goes to stdout using this option in the json file: | You can change to amount of logging that goes to stdout using this option in the json file: | ||
Line 773: | Line 828: | ||
where the options are any of these words: | where the options are any of these words: | ||
− | * '''init''': log extra details about the IG publisher initialization sequence | + | *'''init''': log extra details about the IG publisher initialization sequence |
− | * '''progress''': log extra details about the sequence of actions taken by the IG publisher | + | *'''progress''': log extra details about the sequence of actions taken by the IG publisher |
− | * '''context''': log each time a resource is added to the context (e.g. support validation) | + | *'''context''': log each time a resource is added to the context (e.g. support validation) |
− | * '''html''': log HTML link checking details | + | *'''html''': log HTML link checking details |
− | * '''tx''': detailed messages from the terminology sub-system | + | *'''tx''': detailed messages from the terminology sub-system |
This is particularly useful when debugging the auto-build when all you get is the stdout. | This is particularly useful when debugging the auto-build when all you get is the stdout. |
Latest revision as of 14:55, 29 October 2019
Content on this page has been migrated to Confluence here: https://confluence.hl7.org/display/FHIR/IG+Publisher+Documentation
Contents
- 1 Summary
- 2 Examples
- 3 Using FHIR IG Publisher
- 4 Control file
- 5 Language Support
- 6 Build Tools
- 7 Rules for Implementation Guides
- 8 Swagger
- 9 Troubleshooting
Summary
The FHIR team provides an IG Publishing tool that takes the implementation guide content and converts it 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, which are then included into a published set of html files as directed by the author
- Several different zip files: which 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
The outcome of the publishing process is a set of HTML files that represent the implementation guide. These files can be posted to a web server.
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)
If you wish to publish an IG through HL7 or the FHIR Foundation, you should also familiarize yourself with the FHIR Implementation Guide Publishing Requirements.
Publishing Implementation Guides
Typically, implementation guide publishing works like this:
- the master source for an implementation guide is in a public GitHub repository
- editors can run their own local build and share the set of files (full-ig.zip is automatically produced, for convenience) with anyone they want to
- a CI build is published so everyone can see the output - see [Auto-IG-Publisher Documentation]
- when formal milestones are achieved, the Implementation Guide is published to the canonical web site for the IG (typically, hl7.org, hl7.org.xx, or fhir.org, but need not be) (See Standard FHIR Publishing Layout Pattern for additional guidance)
For IGs developed on the Simplifier.net infrastructure, see [todo as yet] for publishing details. Non-public Implementation guides can still use the IG build, but cannot use the CI Build infrastructure
Examples
If you want an example of IG source, you can look in one of the following places:
- FHIR GitHub repository, in /guides/* - any directory ending in 2 - a variety of styles of implementation guide.
- Also, there's /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.publisher.jar
. You can get it from https://fhir.github.io/latest-ig-publisher/org.hl7.fhir.publisher.jar. 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.
Alternatively, you can use the IG Publisher in web server mode. If you do this, you don't need any installed software.
Using the IG Publisher Web Server
The IG publisher lives at [[1]]. From there, you can upload a ip file containing the contents of the IG. After processing, you can download the output.
Note that it's a little inconvenient to flip between modes (running locally vs using the web publisher) because the standard folder structures include /qa, /temp, and /output - you don't want to upload these - they can be very large (though the IG server will ignore them if you do). Also, the web publisher maintains it's own terminology server cache, and may give different results for expansions etc than if you are using your own txCache in the folder and not keeping it up to date.
You can also use the API to the IG web publisher directly. To do this, POST a zip containing the IG content to http://hapi.fhir.org/igweb/process (Content-Tyepe: application/zip), and after a period of seconds, a zip file containing the generated output will be returned.
Running in GUI mode
Windows: double-click on org.hl7.fhir.publisher.jar or right-click and select 'Open'.
Linux: double-click on org.hl7.fhir.publisher.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.publisher.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'.
Running in command line mode
To run in command line mode, run the IG Publisher like this:
java -jar org.hl7.fhir.publisher.jar -ig [source] (-tx [url]) (-packages [directory]) (-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)
- -packages: (optional) directory containing packages (tarball/gzips with implementation guide-associated artifacts with extension .tgz) to be used for packages to load without using package management infrastructure
- -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
Advanced parameters:
- -resetTx - clear out the txCache (see comments below about managing the freshness of the txCache)
- -resetTxErrors - delete any errors from the tcCache, but leave successful operations in the cache
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.publisher.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.publisher.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.publisher.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.
IG Publisher Special Output files
The IG Publisher produces (or may produce) several different zip files. The most significant is "validator.pack". This is a zip file that contains all the conformance & example resources, a version marker, and a json file that lists all the pages and urls in the ig itself. This file is used:
- by the fhir validator - if you refer to the IG directly by it's canonical URL
- by the IG publisher - if you declare that one IG depends on another
- by a server - if you add the IG to a server load list
The IG publisher will generate definitions.[fmt].zip (unless instructed not to) - these may be useful for other tools that have format specific requirements, and must have json, xml., or ttl inputs.
In addition, the IG publisher will generate examples.[fmt].zip (unless instructed not to) which contains all the IGs examples
Finally the entire IG output is is provided as full-ig.zip.
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. optional, default = ig.xml "version" : "[optional - see below]. default = current build", "fixed-business-version" : "[optional - see below]. default = none", "license" : [xxx]",// [required - see below]., "logging" : "[optional - "see below] default = none", "html-template" : "[optional - see below]. default = none", "suppressedWarningFile": "[optional - see below] default = none", "suppress-qa" : true | false, // suppress the generation of the QA folder content. default = don't suppress "paths" : { // see paths below. optional- defaults apply "resources" : [ // optional; default = "resources" "[resourcesFolder]" ], "pages" : [ // optional; default = "pages" "[pagesFolder]" ], "temp" : "[temp]", // optional; default = "temp" "output" : "[output]", // optional; default = "output" (and must be output for auto-build) "txCache" : "[txCache]", // optional; default = "no value - txCache not in version control (slower builds)" "qa" : "[qa]", // optional; default = "qc" "history" : "[history page]", // optional; default = no page marked as history page "specification" : "[specification]" // optional; default = "http://hl7.org/fhir" }, "npm-name" : "[node Package Name - see below]", "npm-template" : "[Optional npm package template file]", "jurisdiction" : "[code]", // see Jurisdiction below. optional "language" : "[language]", // see 'Language support' below. optional "languages" : [ // optional "[language]" ], "pre-process" : [{ // optional section see below "folder" : "[folder]", "transform" : "[xslt file (conditional)]", "relativePath" : "[relative path (conditional)]" }], "sct-edition" : "[uri - see below", // optional - defaults to SCT International "no-inactive-codes" : true | false, // optional; default = false "broken-links" : "warning | error", // optional; default to warning, but can be error (stops the build) "check-aggregation" : true, // Warning if aggregation not declared on differential elements of type Reference "check-mustSupport" : true, // Warning if mustSupport not declared on elements appearing in differential "append-slash-to-dependency-urls" : false, // true if the publisher should append / to dependency URLs in the jekyll data file (default false for legacy reasons) "anyExtensionsAllowed" : false, // If false, raises an error if unrecognized encounters are encountered, otherwise only an 'information' message "hintAboutNonMustSupport", : true //Info validation if elements appear in examples when not marked as mustSupport=true in one of the corresponding profiles "gen-examples" : true, // optional, see below (processing options) "do-transforms" : true, // optional, see below (processing options) "canonicalBase": "[where this will be published - see above]. Mandatory", "dependencyList": [ // optional // 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]", "package" : "[NPM package id of the IG]", "location" : "[http address where the IG lives (not needed if package is specified)]", "version" : "[version, or 'current' or 'dev']", "source" : "[optional folder to get the definitions from (relative). Should not be required]" } ], "extension-domains" : [ "[url]" // list of domains from which undeclared extensions are allowed to come from ], // 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]", } }, "special-urls" : [ // list of special URLs - see below ], "swagger" : [ // see swagger section below ], "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 lives in the current build (http://build.fhir.org), where it is maintained in an ongoing fashion. The IG publisher knows how to publish IGs for the following versions:
- 1.0.2: DSTU2
- 1.4.0: May 2016 draft release (supported for some stakeholders who use it, and make that possible)
- 3.0.1: DSTU3
- current - the current build.
The IG publisher may work with other versions (e.g. forks of R4 candidate versions) but this is not guaranteed.
If you are using a version other than the current build, you need to specify the version in the control file:
"version" : "1.0.2"
Business Version
You can impose a fixed business version on all the conformance resources using
"fixed-business-version" : "1.2"
If you use this, then the version element in the source for all the conformance resources in the IG must be either the same as the nominated business version, or empty.
This approach to profile versioning means that profiles do not need to have their cannonical URLs changed when substantive changes are made (nor do references to those profiles need to be updated). Instead, all profile references within an IG simply use a consistent canonical URL. When instances declare the profile in an instance, they combine the canonical URL with the profile/IG version as follows:
- [someurl]|[someVersion]
E.g. <profile value="http://example.org/fhir/StructureDefinition/someProfileId%7C1.2"/>
This tells the validator which version of the profile must be used when validating the instance.
License
The license parameter is required and is either:
- An identifier from the SPDX License List
- or literal string "not-open-source"
For example
This FHIR Specification is licensed under Creative Commons "No Rights Reserved" for which the identifier is CC0-1.0.
... "tool": "jekyll" "license": "CC0-1.0", "source": "ig.xml", "spreadsheets": [], "title": "IG-Test3", ...
Paths
The IG publisher defines the following paths that can be configured in the control file:
- [resources]: the directory or set of directories where all the input FHIR resources are found (usually conformance resources and examples). Multiple directories can be used to allow source files to be grouped - e.g. separate folders for examples, vocabulary-related files and 'other' files.
- [pages]: the directory or set of directories that contain the jekyll source (not process, just passed to Jekyll for processing). Multiple directories can be used if it makes implementation guide maintenance easier to separate certain files. (Also see pre-process.)
- [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
- [liquid]: a folder that contains a set of liquid templates (see FHIR Liquid Profile) where the file name is [resource-type].liquid. When narrative is built for a resource, the nominated liquid template will be used rather than the default narrative generation
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.
DependencyList
As stated above this is a list of other implementation guides that this guide depends on. For example building a profile upon a another profile or referencing another profile's structuredefinitions, value sets, code systems etc.
an example of this would be:
"dependencyList": [ { "name" : "uscore", "location" : "http://hl7.org/fhir/us/core", "version" : "1.1.0" }]
The location is the canonical URL for the guide. The IG Publisher will resolve the canonical URL to a package id, add the specified guide to the FHIR Package cache, and then use it.
In addition to a published version of the IG, the following 2 special versions can be specified:
- current: Use the latest version of the IG as built by the IG auto-publisher (see above) - usually this is updated when a commit is pushed to github
- dev: use the latest local build of the IG. in the absence of a local build, this falls back to using the current version
If, for some reason, the dependent IG is not run on the auto-build platform, and the resolution from Canonical URL to package id is not known to the IG Publisher, you can specify your own package id:
{ "name" : "uscore", "location" : "http://example.org/fhir/myig", "package" : "example.fhir.myig", "version" : "1.1.0", }
Notes:
- never specify an alternative package id if one has already been used
- for IGs published through Hl7.org or fhir.org, package ids are assigned by the FHIR Product Director
- you can specify an alternative location for a specific version of a specific package through the FHIR Package cache localization mechanism
In theory, all extensions that are referred to should be from Implementation Guides explicitly listed in the dependencyList. However, for a variety of reasons, that's not always possible. So particular domains that are explicitly allowed as unregistered extensions can be added using the allowed-domains list - an array of strings:
"allowed-domains" : [ "http://my.server.url" ]
Terminology Service Cache
The IG Publisher uses a terminology server to support it's operations (presently, this is fhir3.healthintersections.com/au, but is planned to move to tx.fhir.org soon). In order to improve operational performance, the IG publisher caches the outcome of all interactions with the terminology server. This makes a substantial difference to the performance of the publication, but also means that there's a risk of the terminology content becoming stale.
IG authors can choose to put the terminology cache into version control. This means that all builds (either by authors or by CI builds) get the same content, and reduces the load on the terminology server. Also, all authors get fully efficient publication. This also means that flushing the terminology cache is under the control of the editors process. It also means that editors have to commit the contents of the txCache when committing. Note that there is never any reason not to simply commit whatever changes have happened, and no user review is needed on this.
Note that the CI build does not maintain it's own persistent cache; if the terminology cache is not in version control, it will not have a terminology cache.
There are several ways to delete the terminology service cache:
- find the directory and manually delete content from it (e.g. all files). This is can be done safely at any time
- run the IG Publisher with the parameter -resetTx - this clears the folder
- run the IG Publisher with the parameter -resetTxErrors - this clears the folder of any errors from the terminology server but keeps successful operations
- the terminology cache will be flushed completely when the terminology server is upgraded
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]
Note that you can only specify a version supported by the infrastructure (currently: International, US, AU, CA). 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 and will then do one or more of two things:
- rather than putting it directly in the "pages" folder, will place it in the designated subfolder of pages. This allows pointing to a folder that contains content intended to map to _data, _includes or some other sub-folder without needing to create a directory hierarcy in the implementation guide's source files
- 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)
- java: Java Class 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) (all elements, snapshot)
- tx-must-support: Terminology Notes for the structure (Structure Definition) (must-support elements, snapshot)
- tx-diff: Terminology Notes for the structure (Structure Definition) (all elements, differential)
- tx-diff-must-support : Terminology Notes for the structure (Structure Definition) (must-support elements, differential)
- inv: invariant summary for the structure (Structure Definition)
- dict: Detailed Element Definitions (Structure Definition)
- dict-active: Detailed Element Definitions (Structure Definition), but only including elements with max cardinality > 0
- 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)
- maturity: Banner with resource maturity (all resources)
- for each list in the IG, the publisher can produce the following fragments:
- list-list - a list with descriptions
- list-list-simple: a list with no descriptions
- list-table-xx - a table, with 2 columns for name and description
- Note that for lists, 3 variants are produce, in the order of the list, and in alphabetical by type/id and name
In addition, the publisher produces the following set of fragments for listing all the content:
- list-[type].xhtml
- list-simple-[type].xhtml
- table-[type].xhtml
These 3 are also produced with a -mm (e.g. list-[type]-mm.xhtml) that includes maturity levels for each resource, where it is known. (note that the maturity numbers are in an <a> tag with class="fmm", for styling purposes)
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
Also, -mm variants (see above) are produced for these as well
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)
HTML Template
In addition to the pages generated from artifacts, implementation guides will typically have non-generated HTML pages that provide navigation, background and other supporting information. In most IGs, these pages will follow a typical pattern in terms of header and footer, with only the "body" of the page changing. To allow this content to be edited in pure XHTML (with schema validation support), the IG publisher allows identifying a Jekyll template file that is to be used for some or all such files. The tool will look for HTML pages that are referenced in the implementation guide file but are not present in the pages folder. For each one found, it will look for a corresponding XML file and apply the templates specified with the html-template property.
Suppressed Warnings
Warnings and information messages will occasionally be generated that are "known" and unavoidable based on the design of a particular implementation guide. When there are a large number of these, it can be difficult for someone reviewing the qa page to distinguish which warnings they need to pay attention to and which are new/important. This option allows the IG configuration file to identify a text file containing a list of warnings to suppress from the QA reports. Each line of the file should contain either the full text of the warning to suppress (as shown in qa.txt) or just the display message to suppress (if the message should be suppressed regardless of which file or location triggers the issue). This mechanism can suppress information messages, warning messages and errors related to broken links (e.g. if a link is created to a file produced during post-processing or that otherwise isn't resolvable during the IG publication process).
For example to suppress a couple of informational messages for any artifact and a error message related to a specific artifact in the QA report create a text file 'mySuppressedWarnings.txt' (or whatever name you like) which contains the following three lines:
Instance includes element that is not marked as 'mustSupport' and was validated against profiles declaring mustSupport=true Unable to check minimum required (1) due to lack of slicing validation Communication/rr-example-3: Communication.definition: Unable to resolve resource 'PlanDefinition/authoringagency-1'
and add the following line to the configuration file. :
"suppressedWarningFile": "[path]mySuppressedWarnings.txt"
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
- You can specify ElementDefinition.type.versioning by appending a ~ then the versioning code to the type
- Note that IG publisher enforces the use of correct ids and canonical URLs against the base stated in the control file
Special URLs
For MetadataResources - CodeSystem, ValueSet, etc (anything with a canonical URL) - the IG publisher expects that their Canonical URL is equal to [canonical]/[type]/[id] where [canonical is the IG canonical URL. The IG publisher will ensure that the IG itself is an valid FHIR implementation guide and responds correctly to requests for the resources by their canonical URL.
However in some cases, it's not possible or appropriate for a metadata resource to use the same canonical URL as where the IG is publishing it. In these cases, the URLs that are exempt from this rules need to listed explicitly in the special-urls property, which is array of strings that are the exempt URLs.
Notes:
- URLs have to be explicitly listed because it's too easy for an author to make a mistake and get the canonical URL wrong
- one case for using this facility is where the IG includes a resource that is also published elsewhere. Author's should think hard before doing this - referring to a resource by it's canonical URL rather than copying into the IG is generally a much better approach in terms of ongoing maintenance.
Jurisdiction
The IG publisher can be configured to automatically fill out the Jurisdication on any Metadata Resources it encounters ([Resource].jurisdiction). Provide one or mode codes separated by commas, where the code is taken from http://build.fhir.org/valueset-jurisdiction.html (countries or regions only, no US states. System is not needed). Use code 001 for international specifications.
NPM
The publisher produces an NPM package for ease of distribution. The property "npm-name" must have a value - see FHIR NPM Package Spec for details of how to populate this. This is required for all Implementation Guides.
The IG publisher fills out a few mandatory elements in the package file from the information it has available. Authors can provide additional details beyond those generated by the IG publisher by providing a template which is loaded before the IG publisher writes out the details. The property "npm-template" is relative to the folder containing the configuration file
Language Support
Note: this section is draft - the functionality described here is not yet implemented.
By default, the IG publisher is semi-language agnostic. Content from resources or pages is published in whatever language is expressed in the resources and the pages, but text injected by the IG publisher itself (some sprinkled text scattered through the include files) is in English. The intent of this mode is to support English language publishing.
It's possible to publish Implementation Guides in other languages, or to publish them in multiple languages. Note, though, that there is always a single master language that the IG Publisher uses when publishing.
Specifying an Alternate Master Language
To change the language from English, specify a language using the "language" property in the json control file:
"language" : "es-AR"
(The language tag is a standard xml:lang .e.g. BCP 47 tag. It must have a language, and may have a country (as shown above). Other sub-tags are not allowed)
When an alternative language is specified, the IG publisher changes how it works in the following ways:
- When reading any text from a resource definition, the IG publisher will first look at any [translation extensions] on the element for a matching language tag (full match including country first, then partial match). If there's no matching extension, it will just use the element value. This applies to any elements of type 'string' or 'markdown'
- When looking up codes on the terminology server, the IG publisher will ask for the specified language. tx.fhir.org uses the same approach as immediately above in this case. Note: to get code system displays in additional languages defined on tx.fhir.org, talk to Grahame Grieve
- Any text that is used by the IG publisher that is not in the specified language will be pass to an internal translation module that can translate the text to the target language. This is driven by a configuration file that has a list of mappings from language to language. The input file to configure this is languages.json in the same directory as the config file. There will be a file produced in the qa directory, also called languages.txt, which is the same file with any untranslated texts added (to help editors build the language file)
- Any content in the pages is left untouched.
Using multiple languages
In addition, the IG publisher can produce fragments in multiple languages. To do this, specify additional languages using the language property;
"languages" : [ "du", "es", "ru"]
Note that you must specify a primary language if you specify additional languages.
When you specify additional languages, for each output file that the IG publisher creates, it will also create additional fragments with same base file name, with -[lang] appended, in the specified language. This way, authors can build IGs in multiple languages. In this case, the language file will contain additional langauge codes but work as otherwise described above.
Sharing Language Translations Across IGs
Todo. Not sure about this yet
Build Tools
Jekyll
Installation: https://jekyllrb.com/ (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. For example this is some Jekyll liquid syntax to access the Resource type from an example instance using the type parameter from the list below.
include list-{{site.data.structuredefinitions.{{[id]}}.type | slugify }}.xhtml
- 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.
Swagger
Note: this section is draft - the functionality described here is not yet implemented.
The IG publisher can produce swagger definitions for the API defined by the implementation guide. The following object goes into the JSON control file (described above):
"swagger" : [{ "mode" : "single | split", "capabilities" : "[id]", }]
The IG publisher will produce one set of swagger definitions for each entry in the list.
Mode
Whether to generate a single swagger file for all resources (single), or a file for each resource (split).
Capabilities
The id of the capabilities statement to use as the base for generating the swagger file.
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
- Jekyll may not run if you have spaces your file path. Move to root directory, or eliminate spaces.
- 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)
Before you ask about any terminology or dependency related issues, delete the content of your txCache directory, and run the IG publisher again
Logging
The IG publisher performs 3 sorts of logging:
- basic progress logging to stdout (what you see)
- A full log to [tmp]/fhir-ig-publishing-tmp.log
- in case of build failure, a debugging report to fhir-ig-publishing.log
You can change to amount of logging that goes to stdout using this option in the json file:
"logging" : ["option1", "option2"]
where the options are any of these words:
- init: log extra details about the IG publisher initialization sequence
- progress: log extra details about the sequence of actions taken by the IG publisher
- context: log each time a resource is added to the context (e.g. support validation)
- html: log HTML link checking details
- tx: detailed messages from the terminology sub-system
This is particularly useful when debugging the auto-build when all you get is the stdout.